Drizzled Public API Documentation

systab_variable_ms.cc
00001 /* Copyright (C) 2009 PrimeBase Technologies GmbH, Germany
00002  *
00003  * PrimeBase Media Stream for MySQL
00004  *
00005  * This program is free software; you can redistribute it and/or modify
00006  * it under the terms of the GNU General Public License as published by
00007  * the Free Software Foundation; either version 2 of the License, or
00008  * (at your option) any later version.
00009  *
00010  * This program is distributed in the hope that it will be useful,
00011  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00012  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00013  * GNU General Public License for more details.
00014  *
00015  * You should have received a copy of the GNU General Public License
00016  * along with this program; if not, write to the Free Software
00017  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
00018  *
00019  * Barry Leslie
00020  *
00021  * System variables table.
00022  *
00023  */
00024 #ifdef DRIZZLED
00025 #include <config.h>
00026 #include <drizzled/common.h>
00027 #include <drizzled/session.h>
00028 #include <drizzled/field/blob.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 //#include "mysql_priv.h"
00040 #include "cslib/CSGlobal.h"
00041 #include "cslib/CSStrUtil.h"
00042 #include "cslib/CSLog.h"
00043 
00044 #include "ha_pbms.h"
00045 //#include <plugin.h>
00046 
00047 #include "mysql_ms.h"
00048 #include "repository_ms.h"
00049 #include "database_ms.h"
00050 #include "compactor_ms.h"
00051 #include "open_table_ms.h"
00052 #include "discover_ms.h"
00053 
00054 
00055 
00056 #include "systab_variable_ms.h"
00057 
00058 #define MS_REPOSITORY_STORAGE_TYPE  "REPOSITORY"
00059 #define MS_CLOUD_STORAGE_TYPE   "CLOUD"
00060 
00061 DT_FIELD_INFO pbms_variable_info[]=
00062 {
00063   {"Id",      NOVAL,  NULL, MYSQL_TYPE_LONG,    NULL,             NOT_NULL_FLAG,  "The variable ID"},
00064   {"Name",    32,   NULL, MYSQL_TYPE_VARCHAR, &UTF8_CHARSET,  NOT_NULL_FLAG,  "PBMS variable name"},
00065   {"Value", 1024, NULL, MYSQL_TYPE_VARCHAR, &UTF8_CHARSET,  0,  "PBMS variable value."},
00066   {"Description", 124,  NULL, MYSQL_TYPE_VARCHAR, &UTF8_CHARSET,  NOT_NULL_FLAG,  "PBMS variable description."},
00067   {NULL,NOVAL, NULL, MYSQL_TYPE_STRING,NULL, 0, NULL}
00068 };
00069 
00070 DT_KEY_INFO pbms_variable_keys[]=
00071 {
00072   {"pbms_variable_pk", PRI_KEY_FLAG, {"Id", NULL}},
00073   {NULL, 0, {NULL}}
00074 };
00075 
00076 typedef const char *(*PBMSVarGetFunc)(MSDatabase *db, const char *dflt_value);
00077 typedef const char *(*PBMSVarCheckFunc)(char *value, bool *ok);
00078 typedef void (*PBMSVarActionFunc)(MSDatabase *db, const char *value);
00079 
00080 typedef struct {
00081   bool hidden;      // true if the value is not to be displayed
00082   const char *name;
00083   const char *value;
00084   const char *info;
00085   bool save;      // true if the value is to be saved to disk on update
00086   PBMSVarGetFunc get;
00087   PBMSVarCheckFunc check;
00088   PBMSVarActionFunc action;
00089 } PBMSVariableRec, *PBMSVariablePtr;
00090 
00091 CSLock MSVariableTable::gVarLock;
00092 
00093 //---------------------------
00094 static char *cleanupVariable(char *value, int *len)
00095 {
00096   char *ptr;
00097   
00098   while (*value && isspace(*value)) value++;
00099   ptr = value + strlen(value) -1;
00100   while ((ptr > value) && isspace(*ptr)) ptr--;
00101   ptr++;
00102   *ptr = 0;
00103   
00104   ptr = value;
00105   while (*ptr) {
00106     *ptr = toupper(*ptr);
00107     ptr++;
00108   }
00109   
00110   *len = ptr - value;
00111   return value;
00112 }
00113 
00114 //---------------------------
00115 static const char *get_DumpRestore(MSDatabase *db, const char *)
00116 {
00117   const char *value;
00118   enter_();
00119   push_(db);
00120   if (db->isRecovering())
00121     value = "TRUE";
00122   else
00123     value = "FALSE";
00124   release_(db);
00125   return_(value);
00126 }
00127 
00128 //---------------------------
00129 static const char *readOnlyCheck(char *, bool *ok)
00130 {
00131   *ok = false;
00132   return "Value is Read Only.";
00133 }
00134 //---------------------------
00135 static const char *boolCheck(char *value, bool *ok)
00136 {
00137   const char *val = "Invalid boolean variable, try 'true' or 'false'";
00138   int len;
00139   
00140   value = cleanupVariable(value, &len);
00141   
00142   *ok = false;
00143   switch (*value) {
00144     case '0':
00145       if (len == 1) {
00146         *ok = true;
00147         val = "FALSE";
00148       }
00149       break;
00150       
00151     case '1':
00152       if (len == 1) {
00153         *ok = true;
00154         val = "TRUE";
00155       }
00156       break;
00157       
00158     case 'T':
00159       if (!strcmp(value, "TRUE")) {
00160         *ok = true;
00161         val = "TRUE";
00162       }
00163       break;
00164       
00165     case 'F':
00166       if (!strcmp(value, "FALSE")) {
00167         *ok = true;
00168         val = "FALSE";
00169       }
00170       break;
00171       
00172         
00173   }
00174   
00175   return val;
00176 }
00177 
00178 //---------------------------
00179 static const char *storageTypeCheck(char *value, bool *ok)
00180 {
00181   const char *val = "Invalid storage type, try '"MS_REPOSITORY_STORAGE_TYPE"' or '"MS_CLOUD_STORAGE_TYPE"'";
00182   int len;
00183   
00184   value = cleanupVariable(value, &len);
00185   *ok = false;
00186   
00187   if (!strcmp(value, MS_REPOSITORY_STORAGE_TYPE)) {
00188     *ok = true;
00189     val = MS_REPOSITORY_STORAGE_TYPE;
00190   } else if (!strcmp(value, MS_CLOUD_STORAGE_TYPE)) {
00191     *ok = true;
00192     val = MS_CLOUD_STORAGE_TYPE;
00193   }
00194   
00195   return val;
00196 }
00197 
00198 //---------------------------
00199 static void set_DumpRestore(MSDatabase *db, const char *value)
00200 {
00201   enter_();
00202   push_(db);
00203   db->setRecovering((strcmp(value, "TRUE") == 0));
00204   release_(db);
00205   exit_();
00206 }
00207 
00208 //---------------------------
00209 static void set_StorageType(MSDatabase *db, const char *value)
00210 {
00211   enter_();
00212   push_(db);
00213 
00214   if (!strcmp(value, MS_REPOSITORY_STORAGE_TYPE))
00215     db->myBlobType = MS_STANDARD_STORAGE;
00216   else if (!strcmp(value, MS_CLOUD_STORAGE_TYPE))
00217     db->myBlobType = MS_CLOUD_STORAGE;
00218 
00219   release_(db);
00220   exit_();
00221 }
00222 
00223 //---------------------------
00224 static const char *get_StorageType(MSDatabase *db, const char *)
00225 {
00226   const char *value = "Unknown";
00227   enter_();
00228   push_(db);
00229 
00230   if (db->myBlobType == MS_STANDARD_STORAGE)
00231     value = MS_REPOSITORY_STORAGE_TYPE;
00232   else if (db->myBlobType == MS_CLOUD_STORAGE)
00233     value = MS_CLOUD_STORAGE_TYPE;
00234 
00235   release_(db);
00236   return_(value);
00237 }
00238 
00239 //---------------------------
00240 static const char *get_S3CloudRefNo(MSDatabase *db, const char *)
00241 {
00242   static char value[20];
00243   uint32_t  num;
00244   enter_();
00245   push_(db);
00246   
00247   num = db->myBlobCloud->cl_getDefaultCloudRef();
00248   snprintf(value, 20, "%"PRIu32"", num);
00249   
00250   release_(db);
00251   return_(value);
00252 }
00253 
00254 //---------------------------
00255 static void set_S3CloudRefNo(MSDatabase *db, const char *value)
00256 {
00257   enter_();
00258   push_(db);
00259   
00260   db->myBlobCloud->cl_setDefaultCloudRef(atol(value));
00261   
00262   release_(db);
00263   exit_();
00264 }
00265 
00266 //---------------------------
00267 static void set_BackupNo(MSDatabase *db, const char *value)
00268 {
00269   enter_();
00270   push_(db);
00271   
00272   db->myBlobCloud->cl_setRecoveryNumber(value);
00273   
00274   release_(db);
00275   exit_();
00276 }
00277 
00278 //---------------------------
00279 static const char *get_BackupNo(MSDatabase *db, const char *)
00280 {
00281   const char *value;
00282   enter_();
00283   push_(db);
00284   
00285   value = db->myBlobCloud->cl_getRecoveryNumber();
00286   
00287   release_(db);
00288   return_(value);
00289 }
00290 
00291 static PBMSVariableRec variables[] = {
00292   {false, "Storage-Type", MS_REPOSITORY_STORAGE_TYPE, "How the BLOB data is to be stored.", true, get_StorageType, storageTypeCheck, set_StorageType},
00293   {false, "S3-Cloud-Ref", NULL, "The S3 cloud reference id from the pbms.pbms_cloud table used for new BLOB storage.", true, get_S3CloudRefNo, NULL, set_S3CloudRefNo},
00294   {false, RESTORE_DUMP_VAR, "FALSE", "Indicate if the database is being restored from a dump file.", false, get_DumpRestore, boolCheck, set_DumpRestore},
00295   // Hidden variables should be placed at the end.
00296   {true, BACKUP_NUMBER_VAR, NULL, "The backup number for cloud blob data after a drag and drop restore.", true, get_BackupNo, readOnlyCheck, set_BackupNo}
00297 };
00298 
00299 static const uint32_t num_variables = 4;
00300 
00301 //---------------------------
00302 //----------------------------
00303 #define PBMS_VARIABLES_FILE "pbms_variables"
00304 static  CSPath *getSysVarFile(CSString *db_path)
00305 {
00306   CSPath      *path;
00307 
00308   enter_();
00309   
00310   push_(db_path);
00311 
00312   path = CSPath::newPath(RETAIN(db_path), PBMS_VARIABLES_FILE".dat");
00313   push_(path);
00314   if (!path->exists()) {
00315     CSPath *tmp_path;
00316 
00317     tmp_path = CSPath::newPath(RETAIN(db_path), PBMS_VARIABLES_FILE".tmp");
00318     push_(tmp_path);
00319     if (tmp_path->exists())
00320       tmp_path->rename(PBMS_VARIABLES_FILE".dat");
00321     release_(tmp_path);
00322   }
00323   
00324   
00325   pop_(path);
00326   release_(db_path);
00327   return_(path);
00328 }
00329 
00330 class LoadTableCleanUp : public CSRefObject {
00331   bool do_cleanup;
00332   CSThread *myself;
00333   
00334   uint32_t ref_id;
00335 
00336   public:
00337   
00338   LoadTableCleanUp(): CSRefObject(),
00339     do_cleanup(false), myself(NULL){}
00340     
00341   ~LoadTableCleanUp() 
00342   {
00343     if (do_cleanup) {
00344       CSL.log(myself, CSLog::Protocol, "\nRestore failed!\n");
00345       CSL.flush();
00346       myself->logException();
00347     }
00348   }
00349   
00350   void setCleanUp(CSThread *self)
00351   {
00352     myself = self;
00353     do_cleanup = true;
00354   }
00355   
00356   void cancelCleanUp()
00357   {
00358     do_cleanup = false;
00359   }
00360   
00361 };
00362 
00363 void MSVariableTable::loadTable(MSDatabase *db)
00364 {
00365   CSPath  *path;
00366 
00367   enter_();
00368   
00369   push_(db);
00370   path = getSysVarFile(RETAIN(db->myDatabasePath));
00371   push_(path);
00372 
00373   if (path->exists()) {
00374     CSFile      *file;
00375     CSStringBuffer  *string;
00376     size_t      size = 0, pos =0;
00377     char      *name, *value;
00378     
00379     new_(string, CSStringBuffer(20));
00380     push_(string);
00381 
00382     file = path->openFile(CSFile::READONLY);
00383     push_(file);
00384     size = file->getEOF();
00385     string->setLength(size);
00386     file->read(string->getBuffer(0), 0, size, size);
00387     release_(file);
00388         
00389     while (pos < size) {
00390       name = string->getBuffer(pos);
00391       pos += strlen(name) +1;
00392       if (pos >= size)
00393         break;
00394         
00395       value = string->getBuffer(pos);
00396       pos += strlen(value) +1;
00397       if (pos > size)
00398         break;
00399       
00400       for (uint32_t i =0; i < num_variables; i++) {
00401         if (variables[i].save && variables[i].action && !strcmp(name, variables[i].name)) {
00402           variables[i].action(RETAIN(db), value);
00403         }
00404       }
00405       
00406     }
00407     
00408     release_(string);
00409 
00410   } else { // Set the default values
00411     for (uint32_t i =0; i < num_variables; i++) {
00412       if (variables[i].value && variables[i].action) {
00413         variables[i].action(RETAIN(db), variables[i].value);
00414       }
00415     }
00416   }
00417   
00418 
00419   release_(path);
00420   
00421   // Check to see if there is cloud storage and if the database is not
00422   // currently recovering, then try to restore the BLOBs. 
00423   if ((db->myBlobType == MS_CLOUD_STORAGE) && db->myBlobCloud->cl_mustRecoverBlobs() && !db->isRecovering()) {
00424     CSL.log(self, CSLog::Protocol, "Restoring Cloud BLOBs for database: ");
00425     CSL.log(self, CSLog::Protocol, db->myDatabaseName->getCString());
00426     CSL.log(self, CSLog::Protocol, " ...");
00427     CSL.flush();
00428     LoadTableCleanUp *cleanup;
00429     
00430     new_(cleanup, LoadTableCleanUp());
00431     push_(cleanup);
00432     cleanup->setCleanUp(self);
00433     
00434     db->myBlobCloud->cl_restoreDB();
00435     
00436     cleanup->cancelCleanUp();
00437     release_(cleanup);
00438 
00439     CSL.log(self, CSLog::Protocol, "\nRestore done.\n");
00440     CSL.flush();
00441     set_BackupNo(RETAIN(db), "0");
00442     saveTable(RETAIN(db));
00443   }
00444   
00445   release_(db);
00446 
00447   exit_();
00448 }
00449 
00450 void MSVariableTable::saveTable(MSDatabase *db)
00451 {
00452   CSPath      *path;
00453   CSPath      *old_path;
00454   CSFile      *file;
00455   const char    *value;
00456   size_t      offset = 0, len;
00457   char      null_char = 0;
00458   enter_();
00459   
00460   push_(db);
00461   path = CSPath::newPath(RETAIN(db->myDatabasePath), PBMS_VARIABLES_FILE".tmp");
00462   push_(path);
00463   file = path->openFile(CSFile::CREATE | CSFile::TRUNCATE);
00464   push_(file);
00465   
00466   for (uint32_t i = 0; i < num_variables; i++) {
00467     if (! variables[i].save) continue;
00468     
00469     len = strlen(variables[i].name)+1;
00470     file->write(variables[i].name, offset, len);
00471     offset += len;
00472 
00473     value = variables[i].get(RETAIN(db), variables[i].value);
00474     if (value) {
00475       len = strlen(value)+1;
00476       file->write(value, offset, len);
00477       offset += len;
00478     } else {
00479       file->write(&null_char, offset, 1);
00480       offset++;
00481     }   
00482   }
00483   file->close();
00484   release_(file);
00485 
00486   old_path = CSPath::newPath(RETAIN(db->myDatabasePath), PBMS_VARIABLES_FILE".dat");
00487   push_(old_path);
00488   if (old_path->exists())
00489     old_path->remove();
00490   path->rename(PBMS_VARIABLES_FILE".dat");
00491   release_(old_path);
00492 
00493   release_(path);
00494   release_(db);
00495   exit_();
00496 }
00497 
00498 
00499 MSVariableTable::MSVariableTable(MSSystemTableShare *share, TABLE *table):
00500 MSOpenSystemTable(share, table),
00501 iVariableIndex(0)
00502 {
00503 }
00504 
00505 MSVariableTable::~MSVariableTable()
00506 {
00507   //unuse();
00508 }
00509 
00510 void MSVariableTable::use()
00511 {
00512   gVarLock.lock();
00513 }
00514 
00515 void MSVariableTable::unuse()
00516 {
00517   gVarLock.unlock();  
00518 }
00519 
00520 
00521 void MSVariableTable::seqScanInit()
00522 {
00523   iVariableIndex = 0;
00524 }
00525 
00526 bool MSVariableTable::seqScanNext(char *buf)
00527 {
00528   TABLE   *table = mySQLTable;
00529   Field   *curr_field;
00530   byte    *save;
00531   MY_BITMAP *save_write_set;
00532   PBMSVariablePtr var;
00533   
00534   enter_();
00535   
00536   do {
00537     if (iVariableIndex >= num_variables)
00538       return_(false);
00539     var = &(variables[iVariableIndex++]);
00540   
00541   } while (var->hidden); 
00542   
00543   save_write_set = table->write_set;
00544   table->write_set = NULL;
00545 
00546 #ifdef DRIZZLED
00547   memset(buf, 0xFF, table->getNullBytes());
00548 #else
00549   memset(buf, 0xFF, table->s->null_bytes);
00550 #endif
00551   for (Field **field=GET_TABLE_FIELDS(table) ; *field ; field++) {
00552     curr_field = *field;
00553     save = curr_field->ptr;
00554 #if MYSQL_VERSION_ID < 50114
00555     curr_field->ptr = (byte *) buf + curr_field->offset();
00556 #else
00557 #ifdef DRIZZLED
00558     curr_field->ptr = (byte *) buf + curr_field->offset(curr_field->getTable()->getInsertRecord());
00559 #else
00560     curr_field->ptr = (byte *) buf + curr_field->offset(curr_field->table->record[0]);
00561 #endif
00562 #endif
00563     switch (curr_field->field_name[0]) {
00564       case 'I':
00565         ASSERT(strcmp(curr_field->field_name, "Id") == 0);
00566         curr_field->store(iVariableIndex, true);
00567         setNotNullInRecord(curr_field, buf);
00568         break;
00569 
00570       case 'N':
00571         ASSERT(strcmp(curr_field->field_name, "Name") == 0);
00572           curr_field->store(var->name, strlen(var->name), &UTF8_CHARSET);
00573           setNotNullInRecord(curr_field, buf);
00574         break;
00575 
00576       case 'V': {
00577         ASSERT(strcmp(curr_field->field_name, "Value") == 0);
00578           const char *value;
00579           value = var->get(RETAIN(myShare->mySysDatabase), var->value);
00580           if (value) {
00581             curr_field->store(value, strlen(value), &UTF8_CHARSET);
00582             setNotNullInRecord(curr_field, buf);
00583           }
00584         }
00585         break;
00586 
00587       case 'D':
00588         ASSERT(strcmp(curr_field->field_name, "Description") == 0);
00589           curr_field->store(var->info, strlen(var->info), &UTF8_CHARSET);
00590           setNotNullInRecord(curr_field, buf);
00591         break;
00592 
00593     }
00594     curr_field->ptr = save;
00595   }
00596 
00597   table->write_set = save_write_set;
00598   return_(true);
00599 }
00600 
00601 void MSVariableTable::seqScanPos(unsigned char *pos)
00602 {
00603   int32_t index = iVariableIndex -1;
00604   if (index < 0)
00605     index = 0; // This is probably an error condition.
00606     
00607   mi_int4store(pos, index);
00608 }
00609 
00610 void MSVariableTable::seqScanRead(unsigned char *pos, char *buf)
00611 {
00612   iVariableIndex = mi_uint4korr(pos);
00613   seqScanNext(buf);
00614 }
00615 
00616 void MSVariableTable::updateRow(char *old_data, char *new_data) 
00617 {
00618   uint32_t n_id, o_id;
00619   String n_var_name, n_var_value; 
00620   String o_var_name;  
00621   const char *clean_value;
00622 
00623   enter_();
00624   
00625   getFieldValue(old_data, 0, &o_id);
00626   getFieldValue(old_data, 1, &o_var_name);
00627   
00628   getFieldValue(new_data, 0, &n_id);
00629   getFieldValue(new_data, 1, &n_var_name);
00630   getFieldValue(new_data, 2, &n_var_value);
00631   
00632   // The command names must match.
00633   if ((n_id != o_id) || my_strcasecmp(&UTF8_CHARSET, o_var_name.c_ptr_safe(), n_var_name.c_ptr_safe()))
00634     CSException::throwException(CS_CONTEXT, HA_ERR_TABLE_READONLY, "Attempt to update read only fields in the "VARIABLES_TABLE_NAME" table.");
00635     
00636   n_id--;
00637   if (n_id >  num_variables) // Should never happen
00638     CSException::throwException(CS_CONTEXT, HA_ERR_KEY_NOT_FOUND, "Invalid id");
00639   
00640   CSStringBuffer *value;  
00641   new_(value, CSStringBuffer(0));
00642   push_(value);
00643   value->append(n_var_value.c_ptr(), n_var_value.length());
00644   
00645   // check the input value converting it to a standard format where aplicable:
00646   if (variables[n_id].check) {
00647     bool ok = false;
00648     clean_value = variables[n_id].check(value->getCString(), &ok);
00649     if (!ok)
00650       CSException::throwException(CS_CONTEXT, HA_ERR_GENERIC, clean_value);
00651   } else
00652     clean_value = value->getCString();
00653     
00654   // Execute the action associated with the variable.
00655   if (variables[n_id].action) {
00656     variables[n_id].action(RETAIN(myShare->mySysDatabase), clean_value);
00657   }
00658   
00659   release_(value);
00660   
00661   if (variables[n_id].save) {
00662     saveTable(RETAIN(myShare->mySysDatabase));
00663   }
00664   
00665   exit_();
00666 }
00667 
00668 void MSVariableTable::transferTable(MSDatabase *to_db, MSDatabase *from_db)
00669 {
00670   CSPath  *path;
00671   enter_();
00672   
00673   push_(from_db);
00674   push_(to_db);
00675   
00676   path = CSPath::newPath(RETAIN(from_db->myDatabasePath), PBMS_VARIABLES_FILE".dat");
00677   push_(path);
00678   if (path->exists()) {
00679     CSPath  *bu_path;
00680     bu_path = CSPath::newPath(RETAIN(to_db->myDatabasePath), PBMS_VARIABLES_FILE".dat");
00681     path->copyTo(bu_path, true);
00682   }
00683   
00684   release_(path);
00685   release_(to_db);
00686   release_(from_db);
00687   
00688   exit_();
00689 }
00690 
00691 void MSVariableTable::setVariable(MSDatabase *db, const char *name, const char *value)
00692 {
00693   enter_();
00694   
00695   push_(db);
00696   
00697   for (uint32_t i =0; db && i < num_variables; i++) {
00698     if (variables[i].action && !strcmp(name, variables[i].name)) {
00699       variables[i].action(RETAIN(db), value);
00700       if (variables[i].save) {
00701         pop_(db);
00702         saveTable(db);
00703       } else
00704         release_(db);
00705       db = NULL;
00706     }
00707   }
00708 
00709   if (db) {
00710     release_(db);
00711     CSException::throwException(CS_CONTEXT, HA_ERR_KEY_NOT_FOUND, name);
00712   }
00713   exit_();
00714 }
00715 
00716 CSStringBuffer *MSVariableTable::dumpTable(MSDatabase *db)
00717 {
00718 
00719   CSPath      *path;
00720   CSStringBuffer  *dump;
00721 
00722   enter_();
00723   
00724   push_(db);
00725   path = getSysVarFile(RETAIN(db->myDatabasePath));
00726   release_(db);
00727   
00728   push_(path);
00729   new_(dump, CSStringBuffer(20));
00730   push_(dump);
00731 
00732   if (path->exists()) {
00733     CSFile  *file;
00734     size_t  size;
00735     
00736     file = path->openFile(CSFile::READONLY);
00737     push_(file);
00738     
00739     size = file->getEOF();
00740     dump->setLength(size);
00741     file->read(dump->getBuffer(0), 0, size, size);
00742     release_(file);
00743   }
00744   
00745   pop_(dump);
00746   release_(path);
00747   return_(dump);
00748 }
00749 
00750 void MSVariableTable::restoreTable(MSDatabase *db, const char *data, size_t size, bool reload)
00751 {
00752   CSPath  *path;
00753   CSFile  *file;
00754 
00755   enter_();
00756   
00757   push_(db);
00758   path = getSysVarFile(RETAIN(db->myDatabasePath));
00759   push_(path);
00760   
00761   file = path->openFile(CSFile::CREATE | CSFile::TRUNCATE);
00762   push_(file);
00763   
00764   file->write(data, 0, size);
00765   file->close();
00766   release_(file);
00767   
00768   release_(path);
00769   
00770   pop_(db);
00771   if (reload)
00772     loadTable(db);
00773   else
00774     db->release();
00775   exit_();
00776 }
00777 
00778 void MSVariableTable::removeTable(CSString *db_path)
00779 {
00780   CSPath  *path;
00781   enter_();
00782   
00783   path = getSysVarFile(db_path);
00784   push_(path);
00785   
00786   path->removeFile();
00787   release_(path);
00788   exit_();
00789 }
00790