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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19
* Created by Barry Leslie on 3/20/09.
35
#include "CSStrUtil.h"
36
#include "CSStorage.h"
38
#include "CSS3Protocol.h"
40
#include "backup_ms.h"
43
CSSyncSparseArray *MSCloudInfo::gCloudInfo;
44
uint32_t MSCloudInfo::gMaxInfoRef;
46
uint32_t CloudDB::gKeyIndex;
47
CSMutex CloudDB::gCloudKeyLock;
49
//==============================
50
MSCloudInfo::MSCloudInfo(uint32_t id,
52
const char *bucket_arg,
53
const char *publicKey,
54
const char *privateKey
60
new_(s3Prot, CSS3Protocol());
61
s3Prot->s3_setServer(server);
62
s3Prot->s3_setPublicKey(publicKey);
63
s3Prot->s3_setPrivateKey(privateKey);
65
bucket = CSString::newString(bucket_arg);
68
//-------------------------------
69
MSCloudInfo::~MSCloudInfo()
78
//-------------------------------
79
const char *MSCloudInfo::getServer()
81
return s3Prot->s3_getServer();
84
//-------------------------------
85
const char *MSCloudInfo::getBucket()
87
return bucket->getCString();
90
//-------------------------------
91
const char *MSCloudInfo::getPublicKey()
93
return s3Prot->s3_getPublicKey();
96
//-------------------------------
97
const char *MSCloudInfo::getPrivateKey()
99
return s3Prot->s3_getPrivateKey();
102
//-------------------------------
103
CSString *MSCloudInfo::getSignature(const char *key, const char *content_type, uint32_t *s3AuthorizationTime)
105
return s3Prot->s3_getAuthorization(bucket->getCString(), key, content_type, s3AuthorizationTime);
108
//-------------------------------
109
CSString *MSCloudInfo::getDataURL(const char *key, int keep_alive)
111
return s3Prot->s3_getDataURL(bucket->getCString(), key, keep_alive);
114
//-------------------------------
115
void MSCloudInfo::send(CSInputStream *input, const char *key, off_t size)
118
headers = s3Prot->s3_send(input, bucket->getCString(), key, size);
122
//-------------------------------
123
CSVector *MSCloudInfo::list(const char *key_prefix, uint32_t max)
125
return s3Prot->s3_list(bucket->getCString(), key_prefix, max);
128
//-------------------------------
129
void MSCloudInfo::receive(CSOutputStream *output, const char *key)
134
headers = s3Prot->s3_receive(output, bucket->getCString(), key, &found);
140
new_(err, CSStringBuffer());
142
err->append("S3 object not found: ");
143
err->append(getServer());
145
err->append(bucket->getCString());
149
CSException::throwException(CS_CONTEXT, CS_ERR_GENERIC_ERROR, err->getCString());
155
//-------------------------------
156
void MSCloudInfo::cDelete(const char *key)
158
s3Prot->s3_delete(bucket->getCString(), key);
161
//-------------------------------
162
void MSCloudInfo::copy(MSCloudInfo *dst_cloud, const char *dst_key, const char *src_key)
167
s3Prot->s3_copy(dst_cloud->getServer() ,dst_cloud->bucket->getCString(), dst_key, bucket->getCString(), src_key);
173
//==============================
174
CloudDB::CloudDB(uint32_t db_id):
185
keep_alive = (5 * 60); // default URL keep alive in seconds.
186
new_(clObjectKey, CSStringBuffer());
187
clObjectKey->setLength(base_key_size);
192
//-------------------------------
197
backupInfo->release();
200
backupCloud->release();
203
clObjectKey->release();
206
//-------------------------------
207
MSBackupInfo *CloudDB::cl_getBackupInfo()
210
backupInfo->retain();
215
//-------------------------------
216
void CloudDB::cl_clearBackupInfo(){ backupInfo->release(); backupInfo = NULL;}
218
//-------------------------------
219
void CloudDB::cl_createDB()
224
//-------------------------------
226
void CloudDB::cl_restoreDB()
230
CloudObjectKey *src_objectKey, *dst_objectKey;
231
CloudKeyRec cloudKey;
232
uint32_t src_cloudRef, dst_cloudRef = 0;
233
MSBackupInfo *backup_info;
234
MSCloudInfo *src_cloud, *dst_cloud;
237
if (!blob_recovery_no)
238
exit_(); // nothing to do.
240
backup_info = MSBackupInfo::getBackupInfo(blob_recovery_no);
243
src_cloudRef = backup_info->getcloudRef();
244
src_cloud = MSCloudInfo::getCloudInfo(src_cloudRef);
247
new_(dst_objectKey, CloudObjectKey(blob_db_id));
248
push_(dst_objectKey);
250
// Get the key for the backup BLOB
251
new_(src_objectKey, CloudObjectKey(blob_db_id));
252
push_(src_objectKey);
253
src_objectKey->setObjectKey(NULL, backup_info->getcloudBackupNo(), backup_info->getDatabaseId());
255
// Get a list of all the BLOBs that were backed up.
256
list = src_cloud->list(src_objectKey->getCString());
257
release_(src_objectKey);
260
// Go through the list copying the keys.
262
dst_cloudRef = src_cloudRef;
263
dst_cloud = src_cloud;
266
while ((key = (CSString*)(list->take(0))) ) {
269
// The source key name must be parsed to get its
270
// destination cloud reference. The destination for
271
// the BLOBs may not all be in the same cloud.
272
CloudObjectKey::parseObjectKey(key->getCString(), &cloudKey);
274
// Reset the destination cloud if required.
275
if (cloudKey.cloud_ref != dst_cloudRef) {
277
dst_cloud->release();
280
dst_cloudRef = cloudKey.cloud_ref;
281
dst_cloud = MSCloudInfo::getCloudInfo(dst_cloudRef);
284
// Copy the BLOB to the recovered database.
285
dst_objectKey->setObjectKey(&cloudKey);
286
src_cloud->copy(RETAIN(dst_cloud), dst_objectKey->getCString(), key->getCString());
294
dst_cloud->release();
298
blob_recovery_no = 0;
300
release_(dst_objectKey);
302
release_(backup_info);
306
//-------------------------------
307
uint32_t CloudDB::cl_getNextBackupNumber(uint32_t cloud_ref)
309
CloudObjectKey *objectKey;
311
uint32_t backup_no = 0, size = 1;
312
MSCloudInfo *s3Cloud;
315
s3Cloud = MSCloudInfo::getCloudInfo((cloud_ref)?cloud_ref:dfltCloudRefId);
318
new_(objectKey, CloudObjectKey(blob_db_id));
321
// Find the next available backup number
324
objectKey->setObjectKey(NULL, backup_no); // use the key prefix with the backup number for listing.
325
list = s3Cloud->list(objectKey->getCString(), 1);
336
//-------------------------------
337
void CloudDB::cl_backupBLOB(CloudKeyPtr key)
339
CloudObjectKey *src_objectKey, *dst_objectKey;
340
uint32_t cloudRef, backupNo;
341
MSCloudInfo *src_cloud, *dst_cloud;
346
if ((cloudRef = backupInfo->getcloudRef()) == 0) {
347
backupInfo->setcloudRef(dfltCloudRefId);
348
cloudRef = dfltCloudRefId;
351
if ((backupNo = backupInfo->getcloudBackupNo()) == 0) {
352
backupNo = cl_getNextBackupNumber(cloudRef);
353
backupInfo->setcloudBackupNo(backupNo);
356
// Set the source object's key
357
new_(src_objectKey, CloudObjectKey(blob_db_id));
358
push_(src_objectKey);
359
src_objectKey->setObjectKey(key);
361
// Set the destination object's key
362
new_(dst_objectKey, CloudObjectKey(blob_db_id));
363
push_(dst_objectKey);
364
dst_objectKey->setObjectKey(key, backupNo);
366
// Get the source cloud
367
src_cloud = MSCloudInfo::getCloudInfo((key->cloud_ref)?key->cloud_ref:dfltCloudRefId);
370
// Copy the object to the destination cloud
371
dst_cloud = MSCloudInfo::getCloudInfo(cloudRef);
372
src_cloud->copy(dst_cloud, dst_objectKey->getCString(), src_objectKey->getCString());
375
release_(dst_objectKey);
376
release_(src_objectKey);
380
//-------------------------------
381
void CloudDB::cl_restoreBLOB(CloudKeyPtr key, uint32_t backup_db_id)
383
CloudObjectKey *src_objectKey, *dst_objectKey;
384
uint32_t cloudRef, backupNo;
385
MSCloudInfo *src_cloud, *dst_cloud;
390
if ((cloudRef = backupInfo->getcloudRef()) == 0) {
391
backupInfo->setcloudRef(dfltCloudRefId);
392
cloudRef = dfltCloudRefId;
395
if ((backupNo = backupInfo->getcloudBackupNo()) == 0) {
396
backupNo = cl_getNextBackupNumber(cloudRef);
397
backupInfo->setcloudBackupNo(backupNo);
400
// Set the source object's key
401
new_(src_objectKey, CloudObjectKey(backup_db_id));
402
push_(src_objectKey);
403
src_objectKey->setObjectKey(key, backupNo);
405
// Set the destination object's key
406
new_(dst_objectKey, CloudObjectKey(blob_db_id));
407
push_(dst_objectKey);
408
dst_objectKey->setObjectKey(key);
410
// Get the source cloud
411
src_cloud = MSCloudInfo::getCloudInfo(cloudRef);
414
// Copy the object to the destination cloud
415
dst_cloud = MSCloudInfo::getCloudInfo((key->cloud_ref)?key->cloud_ref:dfltCloudRefId);
416
src_cloud->copy(dst_cloud, dst_objectKey->getCString(), src_objectKey->getCString());
419
release_(dst_objectKey);
420
release_(src_objectKey);
424
//-------------------------------
425
// Drop database deletes all objects with the database key prefix
426
void CloudDB::cl_dropDB()
430
CloudObjectKey *objectKey;
431
MSCloudInfo *s3Cloud = NULL;
436
new_(objectKey, CloudObjectKey(blob_db_id));
439
lock_(MSCloudInfo::gCloudInfo);
443
if (backupInfo && (backup_no = backupInfo->getcloudBackupNo())) {
444
objectKey->setObjectKey(NULL, backup_no); // use the key prefix for the backup for listing.
445
if ((s3Cloud = MSCloudInfo::getCloudInfo(backupInfo->getcloudRef())))
449
objectKey->setObjectKey(); // use the key prefix for listing.
451
s3Cloud = (MSCloudInfo*)MSCloudInfo::gCloudInfo->itemAt(i++); // <-- unreferenced object
454
key_str = objectKey->getCString();
456
// For non backup BLOBs all known clouds must be searched
457
// for possible BLOBs and deleted. The BLOBs belonging to a backup
458
// will ever only be in one cloud storage location.
460
list = s3Cloud->list(key_str);
463
// Go through the list deleting the keys.
464
while ((key = (CSString*)(list->take(0))) ) {
466
s3Cloud->cDelete(key->getCString());
472
release_(s3Cloud); // Only the backup s3Cloud needs to be released.
475
s3Cloud = (MSCloudInfo*)MSCloudInfo::gCloudInfo->itemAt(i++);// <-- unreferenced object
479
unlock_(MSCloudInfo::gCloudInfo);
484
//-------------------------------
485
void CloudDB::cl_putData(CloudKeyPtr key, CSInputStream *stream, off_t size)
487
CloudObjectKey *objectKey;
488
MSCloudInfo *s3Cloud;
494
new_(objectKey, CloudObjectKey(blob_db_id));
497
objectKey->setObjectKey(key);
499
s3Cloud = MSCloudInfo::getCloudInfo((key->cloud_ref)?key->cloud_ref:dfltCloudRefId);
501
s3Cloud->send(RETAIN(stream), objectKey->getCString(), size);
510
//-------------------------------
511
off_t CloudDB::cl_getData(CloudKeyPtr key, char *buffer, off_t size)
513
CloudObjectKey *objectKey;
514
CSStaticMemoryOutputStream *output;
515
MSCloudInfo *s3Cloud;
518
new_(objectKey, CloudObjectKey(blob_db_id));
521
s3Cloud = MSCloudInfo::getCloudInfo(key->cloud_ref);
524
new_(output, CSStaticMemoryOutputStream((u_char *)buffer, size));
527
objectKey->setObjectKey(key);
529
s3Cloud->receive(RETAIN(output), objectKey->getCString());
530
size = output->getSize();
538
//-------------------------------
539
void CloudDB::cl_deleteData(CloudKeyPtr key)
541
MSCloudInfo *s3Cloud;
542
CloudObjectKey *objectKey;
545
new_(objectKey, CloudObjectKey(blob_db_id));
548
s3Cloud = MSCloudInfo::getCloudInfo(key->cloud_ref);
551
objectKey->setObjectKey(key);
553
s3Cloud->cDelete(objectKey->getCString());
561
//-------------------------------
562
CSString *CloudDB::cl_getDataURL(CloudKeyPtr key)
564
CloudObjectKey *objectKey;
566
MSCloudInfo *s3Cloud;
569
new_(objectKey, CloudObjectKey(blob_db_id));
572
objectKey->setObjectKey(key);
574
s3Cloud = MSCloudInfo::getCloudInfo(key->cloud_ref);
577
url = s3Cloud->getDataURL(objectKey->getCString(), keep_alive);
585
//-------------------------------
586
CSString *CloudDB::cl_getSignature(CloudKeyPtr key, CSString *content_type_arg, uint32_t *s3AuthorizationTime)
589
CloudObjectKey *objectKey;
590
const char *content_type = NULL;
591
MSCloudInfo *s3Cloud;
594
new_(objectKey, CloudObjectKey(blob_db_id));
597
if (content_type_arg) {
598
push_(content_type_arg);
599
content_type = content_type_arg->getCString();
602
objectKey->setObjectKey(key);
603
s3Cloud = MSCloudInfo::getCloudInfo(key->cloud_ref);
606
signature = s3Cloud->getSignature(objectKey->getCString(), content_type, s3AuthorizationTime);
608
if (content_type_arg)
609
release_(content_type_arg);
617
//==============================