1
/* Copyright (C) 2009 PrimeBase Technologies GmbH, Germany
3
* PrimeBase Media Stream for MySQL
5
* This program is free software; you can redistribute it and/or modify
6
* it under the terms of the GNU General Public License as published by
7
* the Free Software Foundation; either version 2 of the License, or
8
* (at your option) any later version.
10
* This program is distributed in the hope that it will be useful,
11
* but WITHOUT ANY WARRANTY; without even the implied warranty of
12
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13
* GNU General Public License for more details.
15
* You should have received a copy of the GNU General Public License
16
* along with this program; if not, write to the Free Software
17
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
19
* Created by Barry Leslie on 3/20/09.
25
#include <drizzled/common.h>
26
#include <drizzled/session.h>
27
#include <drizzled/table.h>
28
#include <drizzled/message/table.pb.h>
29
#include <drizzled/charset.h>
30
#include <drizzled/table_proto.h>
31
#include <drizzled/session.h>
32
#include <drizzled/field.h>
35
#include "cslib/CSConfig.h"
41
#include "cslib/CSGlobal.h"
42
#include "cslib/CSThread.h"
43
#include "cslib/CSLog.h"
44
#include "cslib/CSPath.h"
45
#include "cslib/CSFile.h"
46
#include "cslib/CSString.h"
47
#include "cslib/CSStrUtil.h"
48
#include "cslib/CSStorage.h"
49
#include "cslib/CSEncode.h"
50
#include "cslib/CSS3Protocol.h"
52
#include "backup_ms.h"
55
CSSyncSparseArray *MSCloudInfo::gCloudInfo;
56
uint32_t MSCloudInfo::gMaxInfoRef;
58
uint32_t CloudDB::gKeyIndex;
59
CSMutex CloudDB::gCloudKeyLock;
61
//==============================
62
MSCloudInfo::MSCloudInfo(uint32_t id,
64
const char *bucket_arg,
65
const char *publicKey,
66
const char *privateKey
72
new_(s3Prot, CSS3Protocol());
73
s3Prot->s3_setServer(server);
74
s3Prot->s3_setPublicKey(publicKey);
75
s3Prot->s3_setPrivateKey(privateKey);
77
bucket = CSString::newString(bucket_arg);
80
//-------------------------------
81
MSCloudInfo::~MSCloudInfo()
90
//-------------------------------
91
const char *MSCloudInfo::getServer()
93
return s3Prot->s3_getServer();
96
//-------------------------------
97
const char *MSCloudInfo::getBucket()
99
return bucket->getCString();
102
//-------------------------------
103
const char *MSCloudInfo::getPublicKey()
105
return s3Prot->s3_getPublicKey();
108
//-------------------------------
109
const char *MSCloudInfo::getPrivateKey()
111
return s3Prot->s3_getPrivateKey();
114
//-------------------------------
115
CSString *MSCloudInfo::getSignature(const char *key, const char *content_type, uint32_t *s3AuthorizationTime)
117
return s3Prot->s3_getAuthorization(bucket->getCString(), key, content_type, s3AuthorizationTime);
120
//-------------------------------
121
CSString *MSCloudInfo::getDataURL(const char *key, int keep_alive)
123
return s3Prot->s3_getDataURL(bucket->getCString(), key, keep_alive);
126
//-------------------------------
127
void MSCloudInfo::send(CSInputStream *input, const char *key, off64_t size)
130
headers = s3Prot->s3_send(input, bucket->getCString(), key, size);
134
//-------------------------------
135
CSVector *MSCloudInfo::list(const char *key_prefix, uint32_t max)
137
return s3Prot->s3_list(bucket->getCString(), key_prefix, max);
140
//-------------------------------
141
void MSCloudInfo::receive(CSOutputStream *output, const char *key)
146
headers = s3Prot->s3_receive(output, bucket->getCString(), key, &found);
152
new_(err, CSStringBuffer());
154
err->append("S3 object not found: ");
155
err->append(getServer());
157
err->append(bucket->getCString());
161
CSException::throwException(CS_CONTEXT, CS_ERR_GENERIC_ERROR, err->getCString());
167
//-------------------------------
168
void MSCloudInfo::cDelete(const char *key)
170
s3Prot->s3_delete(bucket->getCString(), key);
173
//-------------------------------
174
void MSCloudInfo::copy(MSCloudInfo *dst_cloud, const char *dst_key, const char *src_key)
179
s3Prot->s3_copy(dst_cloud->getServer() ,dst_cloud->bucket->getCString(), dst_key, bucket->getCString(), src_key);
185
//==============================
186
CloudDB::CloudDB(uint32_t db_id):
188
keep_alive(5 * 60),// default URL keep alive in seconds.
198
new_(clObjectKey, CSStringBuffer());
199
clObjectKey->setLength(base_key_size);
204
//-------------------------------
209
backupInfo->release();
212
backupCloud->release();
215
clObjectKey->release();
218
//-------------------------------
219
MSBackupInfo *CloudDB::cl_getBackupInfo()
222
backupInfo->retain();
227
//-------------------------------
228
void CloudDB::cl_clearBackupInfo(){ backupInfo->release(); backupInfo = NULL;}
230
//-------------------------------
231
void CloudDB::cl_createDB()
236
//-------------------------------
238
void CloudDB::cl_restoreDB()
240
CSVector *list = NULL;
241
CSString *key = NULL;
242
CloudObjectKey *src_objectKey = NULL, *dst_objectKey = NULL;
243
CloudKeyRec cloudKey;
244
uint32_t src_cloudRef, dst_cloudRef = 0;
245
MSBackupInfo *backup_info = NULL;
246
MSCloudInfo *src_cloud = NULL, *dst_cloud = NULL;
249
if (!blob_recovery_no)
250
exit_(); // nothing to do.
252
backup_info = MSBackupInfo::getBackupInfo(blob_recovery_no);
255
src_cloudRef = backup_info->getcloudRef();
256
src_cloud = MSCloudInfo::getCloudInfo(src_cloudRef);
259
new_(dst_objectKey, CloudObjectKey(blob_db_id));
260
push_(dst_objectKey);
262
// Get the key for the backup BLOB
263
new_(src_objectKey, CloudObjectKey(blob_db_id));
264
push_(src_objectKey);
265
src_objectKey->setObjectKey(NULL, backup_info->getcloudBackupNo(), backup_info->getDatabaseId());
267
// Get a list of all the BLOBs that were backed up.
268
list = src_cloud->list(src_objectKey->getCString());
269
release_(src_objectKey);
273
// Go through the list copying the keys.
274
dst_cloudRef = src_cloudRef;
275
dst_cloud = src_cloud;
278
push_ref_(dst_cloud); // Push a reference to dst_cloud so that what ever it references will be released.
280
while ((key = (CSString*)(list->take(0))) ) {
283
// The source key name must be parsed to get its
284
// destination cloud reference. The destination for
285
// the BLOBs may not all be in the same cloud.
286
CloudObjectKey::parseObjectKey(key->getCString(), &cloudKey);
288
// Reset the destination cloud if required.
289
if (cloudKey.cloud_ref != dst_cloudRef) {
291
dst_cloud->release();
294
dst_cloudRef = cloudKey.cloud_ref;
295
dst_cloud = MSCloudInfo::getCloudInfo(dst_cloudRef);
298
// Copy the BLOB to the recovered database.
299
dst_objectKey->setObjectKey(&cloudKey);
300
src_cloud->copy(RETAIN(dst_cloud), dst_objectKey->getCString(), key->getCString());
307
blob_recovery_no = 0;
309
release_(dst_objectKey);
311
release_(backup_info);
315
//-------------------------------
316
uint32_t CloudDB::cl_getNextBackupNumber(uint32_t cloud_ref)
318
CloudObjectKey *objectKey;
320
uint32_t backup_no = 0, size = 1;
321
MSCloudInfo *s3Cloud;
324
s3Cloud = MSCloudInfo::getCloudInfo((cloud_ref)?cloud_ref:dfltCloudRefId);
327
new_(objectKey, CloudObjectKey(blob_db_id));
330
// Find the next available backup number
333
objectKey->setObjectKey(NULL, backup_no); // use the key prefix with the backup number for listing.
334
list = s3Cloud->list(objectKey->getCString(), 1);
345
//-------------------------------
346
void CloudDB::cl_backupBLOB(CloudKeyPtr key)
348
CloudObjectKey *src_objectKey, *dst_objectKey;
349
uint32_t cloudRef, backupNo;
350
MSCloudInfo *src_cloud = NULL, *dst_cloud = NULL;
355
if ((cloudRef = backupInfo->getcloudRef()) == 0) {
356
backupInfo->setcloudRef(dfltCloudRefId);
357
cloudRef = dfltCloudRefId;
360
if ((backupNo = backupInfo->getcloudBackupNo()) == 0) {
361
backupNo = cl_getNextBackupNumber(cloudRef);
362
backupInfo->setcloudBackupNo(backupNo);
365
// Set the source object's key
366
new_(src_objectKey, CloudObjectKey(blob_db_id));
367
push_(src_objectKey);
368
src_objectKey->setObjectKey(key);
370
// Set the destination object's key
371
new_(dst_objectKey, CloudObjectKey(blob_db_id));
372
push_(dst_objectKey);
373
dst_objectKey->setObjectKey(key, backupNo);
375
// Get the source cloud
376
src_cloud = MSCloudInfo::getCloudInfo((key->cloud_ref)?key->cloud_ref:dfltCloudRefId);
379
// Copy the object to the destination cloud
380
dst_cloud = MSCloudInfo::getCloudInfo(cloudRef);
381
src_cloud->copy(dst_cloud, dst_objectKey->getCString(), src_objectKey->getCString());
384
release_(dst_objectKey);
385
release_(src_objectKey);
389
//-------------------------------
390
void CloudDB::cl_restoreBLOB(CloudKeyPtr key, uint32_t backup_db_id)
392
CloudObjectKey *src_objectKey, *dst_objectKey;
393
uint32_t cloudRef, backupNo;
394
MSCloudInfo *src_cloud = NULL, *dst_cloud = NULL;
399
if ((cloudRef = backupInfo->getcloudRef()) == 0) {
400
backupInfo->setcloudRef(dfltCloudRefId);
401
cloudRef = dfltCloudRefId;
404
if ((backupNo = backupInfo->getcloudBackupNo()) == 0) {
405
backupNo = cl_getNextBackupNumber(cloudRef);
406
backupInfo->setcloudBackupNo(backupNo);
409
// Set the source object's key
410
new_(src_objectKey, CloudObjectKey(backup_db_id));
411
push_(src_objectKey);
412
src_objectKey->setObjectKey(key, backupNo);
414
// Set the destination object's key
415
new_(dst_objectKey, CloudObjectKey(blob_db_id));
416
push_(dst_objectKey);
417
dst_objectKey->setObjectKey(key);
419
// Get the source cloud
420
src_cloud = MSCloudInfo::getCloudInfo(cloudRef);
423
// Copy the object to the destination cloud
424
dst_cloud = MSCloudInfo::getCloudInfo((key->cloud_ref)?key->cloud_ref:dfltCloudRefId);
425
src_cloud->copy(dst_cloud, dst_objectKey->getCString(), src_objectKey->getCString());
428
release_(dst_objectKey);
429
release_(src_objectKey);
433
//-------------------------------
434
// Drop database deletes all objects with the database key prefix
435
void CloudDB::cl_dropDB()
439
CloudObjectKey *objectKey;
440
MSCloudInfo *s3Cloud = NULL;
445
new_(objectKey, CloudObjectKey(blob_db_id));
448
lock_(MSCloudInfo::gCloudInfo);
452
if (backupInfo && (backup_no = backupInfo->getcloudBackupNo())) {
453
objectKey->setObjectKey(NULL, backup_no); // use the key prefix for the backup for listing.
454
if ((s3Cloud = MSCloudInfo::getCloudInfo(backupInfo->getcloudRef())))
458
objectKey->setObjectKey(); // use the key prefix for listing.
460
s3Cloud = (MSCloudInfo*)MSCloudInfo::gCloudInfo->itemAt(i++); // <-- unreferenced object
463
key_str = objectKey->getCString();
465
// For non backup BLOBs all known clouds must be searched
466
// for possible BLOBs and deleted. The BLOBs belonging to a backup
467
// will ever only be in one cloud storage location.
469
list = s3Cloud->list(key_str);
472
// Go through the list deleting the keys.
473
while ((key = (CSString*)(list->take(0))) ) {
475
s3Cloud->cDelete(key->getCString());
481
release_(s3Cloud); // Only the backup s3Cloud needs to be released.
484
s3Cloud = (MSCloudInfo*)MSCloudInfo::gCloudInfo->itemAt(i++);// <-- unreferenced object
487
unlock_(MSCloudInfo::gCloudInfo);
492
//-------------------------------
493
void CloudDB::cl_putData(CloudKeyPtr key, CSInputStream *stream, off64_t size)
495
CloudObjectKey *objectKey;
496
MSCloudInfo *s3Cloud;
502
new_(objectKey, CloudObjectKey(blob_db_id));
505
objectKey->setObjectKey(key);
507
s3Cloud = MSCloudInfo::getCloudInfo((key->cloud_ref)?key->cloud_ref:dfltCloudRefId);
509
s3Cloud->send(RETAIN(stream), objectKey->getCString(), size);
518
//-------------------------------
519
off64_t CloudDB::cl_getData(CloudKeyPtr key, char *buffer, off64_t size)
521
CloudObjectKey *objectKey;
522
CSStaticMemoryOutputStream *output;
523
MSCloudInfo *s3Cloud;
526
new_(objectKey, CloudObjectKey(blob_db_id));
529
s3Cloud = MSCloudInfo::getCloudInfo(key->cloud_ref);
532
new_(output, CSStaticMemoryOutputStream((u_char *)buffer, size));
535
objectKey->setObjectKey(key);
537
s3Cloud->receive(RETAIN(output), objectKey->getCString());
538
size = output->getSize();
546
//-------------------------------
547
void CloudDB::cl_deleteData(CloudKeyPtr key)
549
MSCloudInfo *s3Cloud;
550
CloudObjectKey *objectKey;
553
new_(objectKey, CloudObjectKey(blob_db_id));
556
s3Cloud = MSCloudInfo::getCloudInfo(key->cloud_ref);
559
objectKey->setObjectKey(key);
561
s3Cloud->cDelete(objectKey->getCString());
569
//-------------------------------
570
CSString *CloudDB::cl_getDataURL(CloudKeyPtr key)
572
CloudObjectKey *objectKey;
574
MSCloudInfo *s3Cloud;
577
new_(objectKey, CloudObjectKey(blob_db_id));
580
objectKey->setObjectKey(key);
582
s3Cloud = MSCloudInfo::getCloudInfo(key->cloud_ref);
585
url = s3Cloud->getDataURL(objectKey->getCString(), keep_alive);
593
//-------------------------------
594
CSString *CloudDB::cl_getSignature(CloudKeyPtr key, CSString *content_type_arg, uint32_t *s3AuthorizationTime)
597
CloudObjectKey *objectKey;
598
const char *content_type = NULL;
599
MSCloudInfo *s3Cloud;
602
new_(objectKey, CloudObjectKey(blob_db_id));
605
if (content_type_arg) {
606
push_(content_type_arg);
607
content_type = content_type_arg->getCString();
610
objectKey->setObjectKey(key);
611
s3Cloud = MSCloudInfo::getCloudInfo(key->cloud_ref);
614
signature = s3Cloud->getSignature(objectKey->getCString(), content_type, s3AuthorizationTime);
616
if (content_type_arg)
617
release_(content_type_arg);
625
//==============================