00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025 #ifdef DRIZZLED
00026 #include <config.h>
00027 #include <drizzled/common.h>
00028 #include <drizzled/session.h>
00029 #endif
00030
00031 #include "cslib/CSConfig.h"
00032 #include <inttypes.h>
00033
00034 #include <sys/types.h>
00035 #include <sys/stat.h>
00036 #include <stdlib.h>
00037 #include <time.h>
00038
00039
00040 #include "cslib/CSGlobal.h"
00041 #include "cslib/CSStrUtil.h"
00042 #include "cslib/CSLog.h"
00043 #include "cslib/CSPath.h"
00044 #include "cslib/CSDirectory.h"
00045
00046 #include "ha_pbms.h"
00047
00048
00049 #include "mysql_ms.h"
00050 #include "database_ms.h"
00051 #include "open_table_ms.h"
00052 #include "discover_ms.h"
00053 #include "systab_util_ms.h"
00054 #include "backup_ms.h"
00055
00056 #include "systab_backup_ms.h"
00057
00058
00059 DT_FIELD_INFO pbms_backup_info[]=
00060 {
00061 {"Id", NOVAL, NULL, MYSQL_TYPE_LONG, NULL, NOT_NULL_FLAG, "The backup reference ID"},
00062 {"Database_Name", 64, NULL, MYSQL_TYPE_VARCHAR, &UTF8_CHARSET, NOT_NULL_FLAG, "The database name"},
00063 {"Database_Id", NOVAL, NULL, MYSQL_TYPE_LONG, NULL, 0, "The database ID"},
00064 {"Started", 32, NULL, MYSQL_TYPE_VARCHAR, &UTF8_CHARSET, 0, "The start time"},
00065 {"Completed", 32, NULL, MYSQL_TYPE_VARCHAR, &UTF8_CHARSET, 0, "The completion time"},
00066 {"IsRunning", 3, NULL, MYSQL_TYPE_VARCHAR, &UTF8_CHARSET, 0, "Is the backup still running"},
00067 {"IsDump", 3, NULL, MYSQL_TYPE_VARCHAR, &UTF8_CHARSET, 0, "Is the backup the result of a dump"},
00068 {"Location", 1024, NULL, MYSQL_TYPE_VARCHAR, &UTF8_CHARSET, 0, "The backup location"},
00069 {"Cloud_Ref", NOVAL, NULL, MYSQL_TYPE_LONG, NULL, 0, "The S3 cloud reference number refering to the pbms.pbms_cloud table."},
00070 {"Cloud_Backup_No", NOVAL, NULL, MYSQL_TYPE_LONG, NULL, 0, "The cloud backup number"},
00071 {NULL,NOVAL, NULL, MYSQL_TYPE_STRING,NULL, 0, NULL}
00072 };
00073
00074 DT_KEY_INFO pbms_backup_keys[]=
00075 {
00076 {"pbms_backup_pk", PRI_KEY_FLAG, {"Id", NULL}},
00077 {NULL, 0, {NULL}}
00078 };
00079
00080 #define MIN_BACKUP_TABLE_FILE_SIZE 4
00081
00082
00083
00084 void MSBackupTable::startUp()
00085 {
00086 MSBackupInfo::startUp();
00087 }
00088
00089
00090 void MSBackupTable::shutDown()
00091 {
00092 MSBackupInfo::shutDown();
00093 }
00094
00095
00096 void MSBackupTable::loadTable(MSDatabase *db)
00097 {
00098
00099 enter_();
00100
00101 push_(db);
00102 lock_(MSBackupInfo::gBackupInfo);
00103
00104 if (MSBackupInfo::gMaxInfoRef == 0) {
00105 CSPath *path;
00106 path = getSysFile(getPBMSPath(RETAIN(db->myDatabasePath)), BACKUP_TABLE_NAME, MIN_BACKUP_TABLE_FILE_SIZE);
00107 push_(path);
00108
00109 if (path->exists()) {
00110 CSFile *file;
00111 SysTabRec *backupData;
00112 const char *name, *location;
00113 uint32_t info_id, db_id, start, end, cloud_ref, cloud_backup_no;
00114 bool isDump;
00115 MSBackupInfo *info;
00116 size_t size;
00117
00118 new_(backupData, SysTabRec("pbms", BACKUP_TABLE_NAME".dat", BACKUP_TABLE_NAME));
00119 push_(backupData);
00120
00121 file = path->openFile(CSFile::READONLY);
00122 push_(file);
00123 size = file->getEOF();
00124 backupData->setLength(size);
00125 file->read(backupData->getBuffer(0), 0, size, size);
00126 release_(file);
00127
00128 backupData->firstRecord();
00129 MSBackupInfo::gMaxInfoRef = backupData->getInt4Field();
00130
00131 if (! backupData->isValidRecord())
00132 MSBackupInfo::gMaxInfoRef = 1;
00133
00134 while (backupData->nextRecord()) {
00135 info_id = backupData->getInt4Field();
00136 name = backupData->getStringField();
00137 db_id = backupData->getInt4Field();
00138 start = backupData->getInt4Field();
00139 end = backupData->getInt4Field();
00140 isDump = backupData->getInt1Field();
00141 location = backupData->getStringField();
00142 cloud_ref = backupData->getInt4Field();
00143 cloud_backup_no = backupData->getInt4Field();
00144
00145 if (backupData->isValidRecord()) {
00146 if (info_id > MSBackupInfo::gMaxInfoRef) {
00147 char msg[80];
00148 snprintf(msg, 80, "backup info id (%"PRIu32") larger than expected (%"PRIu32")\n", info_id, MSBackupInfo::gMaxInfoRef);
00149 CSL.log(self, CSLog::Warning, "pbms "BACKUP_TABLE_NAME".dat :possible damaged file or record. ");
00150 CSL.log(self, CSLog::Warning, msg);
00151 MSBackupInfo::gMaxInfoRef = info_id +1;
00152 }
00153 if ( MSBackupInfo::gBackupInfo->get(info_id)) {
00154 char msg[80];
00155 snprintf(msg, 80, "Duplicate Backup info id (%"PRIu32") being ignored\n", info_id);
00156 CSL.log(self, CSLog::Warning, "pbms "BACKUP_TABLE_NAME".dat :possible damaged file or record. ");
00157 CSL.log(self, CSLog::Warning, msg);
00158 } else {
00159 new_(info, MSBackupInfo(info_id, name, db_id, start, end, isDump, location, cloud_ref, cloud_backup_no));
00160 MSBackupInfo::gBackupInfo->set(info_id, info);
00161 }
00162 }
00163 }
00164 release_(backupData); backupData = NULL;
00165
00166 } else
00167 MSBackupInfo::gMaxInfoRef = 1;
00168
00169 release_(path);
00170
00171 }
00172 unlock_(MSBackupInfo::gBackupInfo);
00173
00174 release_(db);
00175
00176 exit_();
00177 }
00178
00179 void MSBackupTable::saveTable(MSDatabase *db)
00180 {
00181 SysTabRec *backupData;
00182 MSBackupInfo *info;
00183 enter_();
00184
00185 push_(db);
00186
00187 new_(backupData, SysTabRec("pbms", BACKUP_TABLE_NAME".dat", BACKUP_TABLE_NAME));
00188 push_(backupData);
00189
00190
00191 backupData->clear();
00192 lock_(MSBackupInfo::gBackupInfo);
00193
00194 backupData->beginRecord();
00195 backupData->setInt4Field(MSBackupInfo::gMaxInfoRef);
00196 backupData->endRecord();
00197 for (int i = 0;(info = (MSBackupInfo*) MSBackupInfo::gBackupInfo->itemAt(i)); i++) {
00198
00199 backupData->beginRecord();
00200 backupData->setInt4Field(info->getBackupRefId());
00201
00202 backupData->setStringField(info->getName());
00203 backupData->setInt4Field(info->getDatabaseId());
00204 backupData->setInt4Field(info->getStart());
00205 backupData->setInt4Field(info->getEnd());
00206 backupData->setInt1Field(info->isDump());
00207 backupData->setStringField(info->getLocation());
00208 backupData->setInt4Field(info->getcloudRef());
00209 backupData->setInt4Field(info->getcloudBackupNo());
00210 backupData->endRecord();
00211 }
00212 unlock_(MSBackupInfo::gBackupInfo);
00213
00214 restoreTable(RETAIN(db), backupData->getBuffer(0), backupData->length(), false);
00215
00216 release_(backupData);
00217 release_(db);
00218 exit_();
00219 }
00220
00221
00222 MSBackupTable::MSBackupTable(MSSystemTableShare *share, TABLE *table):
00223 MSOpenSystemTable(share, table),
00224 iBackupIndex(0)
00225 {
00226 }
00227
00228 MSBackupTable::~MSBackupTable()
00229 {
00230
00231 }
00232
00233 void MSBackupTable::use()
00234 {
00235 MSBackupInfo::gBackupInfo->lock();
00236 }
00237
00238 void MSBackupTable::unuse()
00239 {
00240 MSBackupInfo::gBackupInfo->unlock();
00241
00242 }
00243
00244
00245 void MSBackupTable::seqScanInit()
00246 {
00247 iBackupIndex = 0;
00248 }
00249
00250 bool MSBackupTable::seqScanNext(char *buf)
00251 {
00252 TABLE *table = mySQLTable;
00253 Field *curr_field;
00254 byte *save;
00255 MY_BITMAP *save_write_set;
00256 MSBackupInfo *info;
00257 CSTime *timeVal;
00258 const char *val;
00259
00260 enter_();
00261
00262 info = (MSBackupInfo *) MSBackupInfo::gBackupInfo->itemAt(iBackupIndex++);
00263 if (!info)
00264 return_(false);
00265
00266 save_write_set = table->write_set;
00267 table->write_set = NULL;
00268
00269 new_(timeVal, CSTime());
00270 push_(timeVal);
00271 #ifdef DRIZZLED
00272 memset(buf, 0xFF, table->getNullBytes());
00273 #else
00274 memset(buf, 0xFF, table->s->null_bytes);
00275 #endif
00276 for (Field **field=GET_TABLE_FIELDS(table) ; *field ; field++) {
00277 curr_field = *field;
00278 save = curr_field->ptr;
00279 #if MYSQL_VERSION_ID < 50114
00280 curr_field->ptr = (byte *) buf + curr_field->offset();
00281 #else
00282 #ifdef DRIZZLED
00283 curr_field->ptr = (byte *) buf + curr_field->offset(curr_field->getTable()->getInsertRecord());
00284 #else
00285 curr_field->ptr = (byte *) buf + curr_field->offset(curr_field->table->record[0]);
00286 #endif
00287 #endif
00288 switch (curr_field->field_name[0]) {
00289 case 'I':
00290 if (curr_field->field_name[1] == 'd') {
00291 ASSERT(strcmp(curr_field->field_name, "Id") == 0);
00292 curr_field->store(info->getBackupRefId(), true);
00293 setNotNullInRecord(curr_field, buf);
00294 } else if (curr_field->field_name[2] == 'D') {
00295 ASSERT(strcmp(curr_field->field_name, "IsDump") == 0);
00296 val = (info->isDump())? "Yes": "No";
00297 curr_field->store(val, strlen(val), &UTF8_CHARSET);
00298 setNotNullInRecord(curr_field, buf);
00299 } else {
00300 ASSERT(strcmp(curr_field->field_name, "IsRunning") == 0);
00301 val = (info->isBackupRunning())? "Yes": "No";
00302 curr_field->store(val, strlen(val), &UTF8_CHARSET);
00303 setNotNullInRecord(curr_field, buf);
00304 }
00305 break;
00306
00307 case 'D':
00308 if (curr_field->field_name[9] == 'I') {
00309 ASSERT(strcmp(curr_field->field_name, "Database_Id") == 0);
00310 curr_field->store(info->getDatabaseId(), true);
00311 setNotNullInRecord(curr_field, buf);
00312 } else {
00313 ASSERT(strcmp(curr_field->field_name, "Database_Name") == 0);
00314 val = info->getName();
00315 curr_field->store(val, strlen(val), &UTF8_CHARSET);
00316 setNotNullInRecord(curr_field, buf);
00317 }
00318
00319 break;
00320
00321 case 'S':
00322 ASSERT(strcmp(curr_field->field_name, "Started") == 0);
00323 if (info->getStart()) {
00324 timeVal->setUTC1970(info->getStart(), 0);
00325 val = timeVal->getCString();
00326 curr_field->store(val, strlen(val), &UTF8_CHARSET);
00327 setNotNullInRecord(curr_field, buf);
00328 }
00329 break;
00330
00331 case 'L':
00332 ASSERT(strcmp(curr_field->field_name, "Location") == 0);
00333 val = info->getLocation();
00334 if (val) {
00335 curr_field->store(val, strlen(val), &UTF8_CHARSET);
00336 setNotNullInRecord(curr_field, buf);
00337 }
00338 break;
00339
00340 case 'C':
00341 if (curr_field->field_name[1] == 'o') {
00342 ASSERT(strcmp(curr_field->field_name, "Completed") == 0);
00343 if (info->getEnd()) {
00344 timeVal->setUTC1970(info->getEnd(), 0);
00345 val = timeVal->getCString();
00346 curr_field->store(val, strlen(val), &UTF8_CHARSET);
00347 setNotNullInRecord(curr_field, buf);
00348 }
00349 } else if (curr_field->field_name[6] == 'R') {
00350 ASSERT(strcmp(curr_field->field_name, "Cloud_Ref") == 0);
00351 curr_field->store(info->getcloudRef(), true);
00352 setNotNullInRecord(curr_field, buf);
00353 } else if (curr_field->field_name[6] == 'B') {
00354 ASSERT(strcmp(curr_field->field_name, "Cloud_Backup_No") == 0);
00355 curr_field->store(info->getcloudBackupNo(), true);
00356 setNotNullInRecord(curr_field, buf);
00357 } else {
00358 ASSERT(false);
00359 break;
00360 }
00361 break;
00362
00363 default:
00364 ASSERT(false);
00365 }
00366 curr_field->ptr = save;
00367 }
00368
00369 release_(timeVal);
00370 table->write_set = save_write_set;
00371
00372 return_(true);
00373 }
00374
00375 void MSBackupTable::seqScanPos(unsigned char *pos)
00376 {
00377 int32_t index = iBackupIndex -1;
00378 if (index < 0)
00379 index = 0;
00380
00381 mi_int4store(pos, index);
00382 }
00383
00384 void MSBackupTable::seqScanRead(unsigned char *pos, char *buf)
00385 {
00386 iBackupIndex = mi_uint4korr(pos);
00387 seqScanNext(buf);
00388 }
00389
00390 void MSBackupTable::updateRow(char *old_data, char *new_data)
00391 {
00392 uint32_t n_id, db_id, cloud_ref, cloud_backup_no, n_indx;
00393 uint32_t o_id, o_db_id, o_cloud_ref, o_cloud_backup_no, o_indx;
00394 String name, start, end, isRunning, isDump, location;
00395 String o_name, o_start, o_end, o_isRunning, o_isDump, o_location;
00396 MSBackupInfo *info, *old_info;
00397
00398 enter_();
00399
00400 getFieldValue(new_data, 0, &n_id);
00401 getFieldValue(new_data, 1, &name);
00402 getFieldValue(new_data, 2, &db_id);
00403 getFieldValue(new_data, 3, &start);
00404 getFieldValue(new_data, 4, &end);
00405 getFieldValue(new_data, 5, &isRunning);
00406 getFieldValue(new_data, 6, &isDump);
00407 getFieldValue(new_data, 7, &location);
00408 getFieldValue(new_data, 8, &cloud_ref);
00409 getFieldValue(new_data, 9, &cloud_backup_no);
00410
00411 getFieldValue(old_data, 0, &o_id);
00412 getFieldValue(old_data, 1, &o_name);
00413 getFieldValue(old_data, 2, &o_db_id);
00414 getFieldValue(old_data, 3, &o_start);
00415 getFieldValue(old_data, 4, &o_end);
00416 getFieldValue(old_data, 5, &o_isRunning);
00417 getFieldValue(old_data, 6, &o_isDump);
00418 getFieldValue(old_data, 7, &o_location);
00419 getFieldValue(old_data, 8, &o_cloud_ref);
00420 getFieldValue(old_data, 9, &o_cloud_backup_no);
00421
00422
00423
00424 if (n_id != o_id )
00425 CSException::throwException(CS_CONTEXT, HA_ERR_TABLE_READONLY, "Attempt to update read only field (Id) in the "BACKUP_TABLE_NAME" table.");
00426
00427 if (strcmp(name.c_ptr(), o_name.c_ptr()) == 0 )
00428 CSException::throwException(CS_CONTEXT, HA_ERR_TABLE_READONLY, "Attempt to update read only field (Database_Name) in the "BACKUP_TABLE_NAME" table.");
00429
00430 if (db_id != o_db_id )
00431 CSException::throwException(CS_CONTEXT, HA_ERR_TABLE_READONLY, "Attempt to update read only field (Database_Id) in the "BACKUP_TABLE_NAME" table.");
00432
00433 if (strcmp(start.c_ptr(), o_start.c_ptr()) == 0 )
00434 CSException::throwException(CS_CONTEXT, HA_ERR_TABLE_READONLY, "Attempt to update read only field (Started) in the "BACKUP_TABLE_NAME" table.");
00435
00436 if (strcmp(end.c_ptr(), o_end.c_ptr()) == 0 )
00437 CSException::throwException(CS_CONTEXT, HA_ERR_TABLE_READONLY, "Attempt to update read only field (Completed) in the "BACKUP_TABLE_NAME" table.");
00438
00439 if (strcmp(isRunning.c_ptr(), o_isRunning.c_ptr()) == 0 )
00440 CSException::throwException(CS_CONTEXT, HA_ERR_TABLE_READONLY, "Attempt to update read only field (isRunning) in the "BACKUP_TABLE_NAME" table.");
00441
00442 if (strcmp(isDump.c_ptr(), o_isDump.c_ptr()) == 0 )
00443 CSException::throwException(CS_CONTEXT, HA_ERR_TABLE_READONLY, "Attempt to update read only field (IsDump) in the "BACKUP_TABLE_NAME" table.");
00444
00445 if (cloud_backup_no != o_cloud_backup_no )
00446 CSException::throwException(CS_CONTEXT, HA_ERR_TABLE_READONLY, "Attempt to update read only field (Cloud_Backup_No) in the "BACKUP_TABLE_NAME" table.");
00447
00448 old_info = (MSBackupInfo*) MSBackupInfo::gBackupInfo->get(o_id);
00449
00450 new_(info, MSBackupInfo(n_id, old_info->getName(), db_id, old_info->getStart(), old_info->getEnd(), old_info->isDump(), location.c_ptr(), cloud_ref, cloud_backup_no));
00451 push_(info);
00452
00453 o_indx = MSBackupInfo::gBackupInfo->getIndex(o_id);
00454
00455 MSBackupInfo::gBackupInfo->remove(o_id);
00456 pop_(info);
00457 MSBackupInfo::gBackupInfo->set(n_id, info);
00458
00459
00460 n_indx = MSBackupInfo::gBackupInfo->getIndex(n_id);
00461 if (o_indx < n_indx )
00462 iBackupIndex--;
00463
00464 saveTable(RETAIN(myShare->mySysDatabase));
00465
00466 exit_();
00467 }
00468
00469 class InsertRowCleanUp : public CSRefObject {
00470 bool do_cleanup;
00471 CSThread *myself;
00472
00473 uint32_t ref_id;
00474
00475 public:
00476
00477 InsertRowCleanUp(CSThread *self): CSRefObject(),
00478 do_cleanup(true), myself(self){}
00479
00480 ~InsertRowCleanUp()
00481 {
00482 if (do_cleanup) {
00483 myself->logException();
00484 if (ref_id)
00485 MSBackupInfo::gBackupInfo->remove(ref_id);
00486
00487 }
00488 }
00489
00490 void setCleanUp(uint32_t id)
00491 {
00492 ref_id = id;
00493 }
00494
00495 void cancelCleanUp()
00496 {
00497 do_cleanup = false;
00498 }
00499
00500 };
00501
00502 void MSBackupTable::insertRow(char *data)
00503 {
00504 uint32_t ref_id = 0, db_id, cloud_ref, cloud_backup_no;
00505 String name, start, end, isRunning, isDump, location;
00506 MSBackupInfo *info = NULL;
00507 const char *db_name;
00508 InsertRowCleanUp *cleanup;
00509
00510 enter_();
00511
00512 new_(cleanup, InsertRowCleanUp(self));
00513 push_(cleanup);
00514
00515 getFieldValue(data, 0, &ref_id);
00516
00517
00518 if (ref_id && MSBackupInfo::gBackupInfo->get(ref_id)) {
00519 CSException::throwException(CS_CONTEXT, MS_ERR_DUPLICATE, "Attempt to insert a row with a duplicate key in the "BACKUP_TABLE_NAME" table.");
00520 }
00521
00522
00523
00524 getFieldValue(data, 1, &name);
00525 getFieldValue(data, 2, &db_id);
00526 getFieldValue(data, 3, &start);
00527 getFieldValue(data, 4, &end);
00528 getFieldValue(data, 5, &isRunning);
00529 getFieldValue(data, 6, &isDump);
00530 getFieldValue(data, 7, &location);
00531 getFieldValue(data, 8, &cloud_ref);
00532 getFieldValue(data, 9, &cloud_backup_no);
00533
00534 if (ref_id == 0)
00535 ref_id = MSBackupInfo::gMaxInfoRef++;
00536 else if (ref_id >= MSBackupInfo::gMaxInfoRef)
00537 MSBackupInfo::gMaxInfoRef = ref_id +1;
00538
00539 db_name = name.c_ptr();
00540 db_id = MSDatabase::getDatabaseID(db_name, false);
00541
00542 cleanup->setCleanUp(ref_id);
00543 new_(info, MSBackupInfo(ref_id, db_name, db_id, 0, 0, false, location.c_ptr(), cloud_ref, cloud_backup_no));
00544 MSBackupInfo::gBackupInfo->set(ref_id, info);
00545
00546
00547
00548
00549 info->startBackup(RETAIN(myShare->mySysDatabase));
00550
00551 cleanup->cancelCleanUp();
00552 release_(cleanup);
00553
00554 exit_();
00555 }
00556
00557 void MSBackupTable::deleteRow(char *data)
00558 {
00559 uint32_t ref_id, indx;
00560
00561 enter_();
00562
00563 getFieldValue(data, 0, &ref_id);
00564
00565
00566 indx = MSBackupInfo::gBackupInfo->getIndex(ref_id);
00567 if (indx <= iBackupIndex)
00568 iBackupIndex--;
00569
00570 MSBackupInfo::gBackupInfo->remove(ref_id);
00571 saveTable(RETAIN(myShare->mySysDatabase));
00572 exit_();
00573 }
00574
00575 void MSBackupTable::transferTable(MSDatabase *to_db, MSDatabase *from_db)
00576 {
00577 CSPath *path;
00578 enter_();
00579
00580 push_(from_db);
00581 push_(to_db);
00582
00583 path = CSPath::newPath(getPBMSPath(RETAIN(from_db->myDatabasePath)), BACKUP_TABLE_NAME".dat");
00584 push_(path);
00585 if (path->exists()) {
00586 CSPath *bu_path;
00587 bu_path = CSPath::newPath(getPBMSPath(RETAIN(to_db->myDatabasePath)), BACKUP_TABLE_NAME".dat");
00588 path->copyTo(bu_path, true);
00589 }
00590
00591 release_(path);
00592 release_(to_db);
00593 release_(from_db);
00594
00595 exit_();
00596 }
00597
00598 CSStringBuffer *MSBackupTable::dumpTable(MSDatabase *db)
00599 {
00600
00601 CSPath *path;
00602 CSStringBuffer *dump;
00603
00604 enter_();
00605
00606 push_(db);
00607 path = getSysFile(getPBMSPath(RETAIN(db->myDatabasePath)), BACKUP_TABLE_NAME, MIN_BACKUP_TABLE_FILE_SIZE);
00608 release_(db);
00609
00610 push_(path);
00611 new_(dump, CSStringBuffer(20));
00612 push_(dump);
00613
00614 if (path->exists()) {
00615 CSFile *file;
00616 size_t size;
00617
00618 file = path->openFile(CSFile::READONLY);
00619 push_(file);
00620
00621 size = file->getEOF();
00622 dump->setLength(size);
00623 file->read(dump->getBuffer(0), 0, size, size);
00624 release_(file);
00625 }
00626
00627 pop_(dump);
00628 release_(path);
00629 return_(dump);
00630 }
00631
00632 void MSBackupTable::restoreTable(MSDatabase *db, const char *data, size_t size, bool reload)
00633 {
00634 CSPath *path;
00635 CSFile *file;
00636
00637 enter_();
00638
00639 push_(db);
00640 path = getSysFile(getPBMSPath(RETAIN(db->myDatabasePath)), BACKUP_TABLE_NAME, MIN_BACKUP_TABLE_FILE_SIZE);
00641 push_(path);
00642
00643 file = path->openFile(CSFile::CREATE | CSFile::TRUNCATE);
00644 push_(file);
00645
00646 file->write(data, 0, size);
00647 file->close();
00648 release_(file);
00649
00650 release_(path);
00651
00652 pop_(db);
00653 if (reload)
00654 loadTable(db);
00655 else
00656 db->release();
00657
00658 exit_();
00659 }
00660
00661
00662
00663 void MSBackupTable::removeTable(CSString *db_path)
00664 {
00665 CSPath *path;
00666 char pbms_path[PATH_MAX];
00667
00668 enter_();
00669
00670 push_(db_path);
00671 cs_strcpy(PATH_MAX, pbms_path, db_path->getCString());
00672 release_(db_path);
00673
00674 if (strcmp(cs_last_name_of_path(pbms_path), "pbms") != 0)
00675 exit_();
00676
00677 cs_remove_last_name_of_path(pbms_path);
00678
00679 path = getSysFile(CSString::newString(pbms_path), BACKUP_TABLE_NAME, MIN_BACKUP_TABLE_FILE_SIZE);
00680 push_(path);
00681
00682 if (path->exists())
00683 path->removeFile();
00684 release_(path);
00685
00686 exit_();
00687 }
00688