~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to plugin/pbms/src/systab_variable_ms.cc

  • Committer: Brian Aker
  • Date: 2011-12-13 03:21:35 UTC
  • mto: This revision was merged to the branch mainline in revision 2475.
  • Revision ID: brian@tangent.org-20111213032135-8dta0336wn38uok9
Rmove PBMS (deprecated)

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/* Copyright (C) 2009 PrimeBase Technologies GmbH, Germany
2
 
 *
3
 
 * PrimeBase Media Stream for MySQL
4
 
 *
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.
9
 
 *
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.
14
 
 *
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
18
 
 *
19
 
 * Barry Leslie
20
 
 *
21
 
 * System variables table.
22
 
 *
23
 
 */
24
 
#ifdef DRIZZLED
25
 
#include <config.h>
26
 
#include <drizzled/common.h>
27
 
#include <drizzled/session.h>
28
 
#include <drizzled/sql_lex.h>
29
 
#include <drizzled/field/blob.h>
30
 
#endif
31
 
 
32
 
#include "cslib/CSConfig.h"
33
 
#include <inttypes.h>
34
 
 
35
 
#include <sys/types.h>
36
 
#include <sys/stat.h>
37
 
#include <stdlib.h>
38
 
#include <time.h>
39
 
 
40
 
//#include "mysql_priv.h"
41
 
#include "cslib/CSGlobal.h"
42
 
#include "cslib/CSStrUtil.h"
43
 
#include "cslib/CSLog.h"
44
 
 
45
 
#include "ha_pbms.h"
46
 
//#include <plugin.h>
47
 
 
48
 
#include "mysql_ms.h"
49
 
#include "repository_ms.h"
50
 
#include "database_ms.h"
51
 
#include "compactor_ms.h"
52
 
#include "open_table_ms.h"
53
 
#include "discover_ms.h"
54
 
 
55
 
 
56
 
 
57
 
#include "systab_variable_ms.h"
58
 
 
59
 
#define MS_REPOSITORY_STORAGE_TYPE      "REPOSITORY"
60
 
#define MS_CLOUD_STORAGE_TYPE           "CLOUD"
61
 
 
62
 
DT_FIELD_INFO pbms_variable_info[]=
63
 
{
64
 
        {"Id",                  NOVAL,  NULL, MYSQL_TYPE_LONG,          NULL,                                                   NOT_NULL_FLAG,  "The variable ID"},
65
 
        {"Name",                32,             NULL, MYSQL_TYPE_VARCHAR,       &UTF8_CHARSET,  NOT_NULL_FLAG,  "PBMS variable name"},
66
 
        {"Value",       1024,   NULL, MYSQL_TYPE_VARCHAR,       &UTF8_CHARSET,  0,      "PBMS variable value."},
67
 
        {"Description", 124,    NULL, MYSQL_TYPE_VARCHAR,       &UTF8_CHARSET,  NOT_NULL_FLAG,  "PBMS variable description."},
68
 
        {NULL,NOVAL, NULL, MYSQL_TYPE_STRING,NULL, 0, NULL}
69
 
};
70
 
 
71
 
DT_KEY_INFO pbms_variable_keys[]=
72
 
{
73
 
        {"pbms_variable_pk", PRI_KEY_FLAG, {"Id", NULL}},
74
 
        {NULL, 0, {NULL}}
75
 
};
76
 
 
77
 
typedef const char *(*PBMSVarGetFunc)(MSDatabase *db, const char *dflt_value);
78
 
typedef const char *(*PBMSVarCheckFunc)(char *value, bool *ok);
79
 
typedef void (*PBMSVarActionFunc)(MSDatabase *db, const char *value);
80
 
 
81
 
typedef struct {
82
 
        bool hidden;                    // true if the value is not to be displayed
83
 
        const char *name;
84
 
        const char *value;
85
 
        const char *info;
86
 
        bool save;                      // true if the value is to be saved to disk on update
87
 
        PBMSVarGetFunc get;
88
 
        PBMSVarCheckFunc check;
89
 
        PBMSVarActionFunc action;
90
 
} PBMSVariableRec, *PBMSVariablePtr;
91
 
 
92
 
CSLock MSVariableTable::gVarLock;
93
 
 
94
 
//---------------------------
95
 
static char *cleanupVariable(char *value, int *len)
96
 
{
97
 
        char *ptr;
98
 
        
99
 
        while (*value && isspace(*value)) value++;
100
 
        ptr = value + strlen(value) -1;
101
 
        while ((ptr > value) && isspace(*ptr)) ptr--;
102
 
        ptr++;
103
 
        *ptr = 0;
104
 
        
105
 
        ptr = value;
106
 
        while (*ptr) {
107
 
                *ptr = toupper(*ptr);
108
 
                ptr++;
109
 
        }
110
 
        
111
 
        *len = ptr - value;
112
 
        return value;
113
 
}
114
 
 
115
 
//---------------------------
116
 
static const char *get_DumpRestore(MSDatabase *db, const char *)
117
 
{
118
 
        const char *value;
119
 
        enter_();
120
 
        push_(db);
121
 
        if (db->isRecovering())
122
 
                value = "TRUE";
123
 
        else
124
 
                value = "FALSE";
125
 
        release_(db);
126
 
        return_(value);
127
 
}
128
 
 
129
 
//---------------------------
130
 
static const char *readOnlyCheck(char *, bool *ok)
131
 
{
132
 
        *ok = false;
133
 
        return "Value is Read Only.";
134
 
}
135
 
//---------------------------
136
 
static const char *boolCheck(char *value, bool *ok)
137
 
{
138
 
        const char *val = "Invalid boolean variable, try 'true' or 'false'";
139
 
        int len;
140
 
        
141
 
        value = cleanupVariable(value, &len);
142
 
        
143
 
        *ok = false;
144
 
        switch (*value) {
145
 
                case '0':
146
 
                        if (len == 1) {
147
 
                                *ok = true;
148
 
                                val = "FALSE";
149
 
                        }
150
 
                        break;
151
 
                        
152
 
                case '1':
153
 
                        if (len == 1) {
154
 
                                *ok = true;
155
 
                                val = "TRUE";
156
 
                        }
157
 
                        break;
158
 
                        
159
 
                case 'T':
160
 
                        if (!strcmp(value, "TRUE")) {
161
 
                                *ok = true;
162
 
                                val = "TRUE";
163
 
                        }
164
 
                        break;
165
 
                        
166
 
                case 'F':
167
 
                        if (!strcmp(value, "FALSE")) {
168
 
                                *ok = true;
169
 
                                val = "FALSE";
170
 
                        }
171
 
                        break;
172
 
                        
173
 
                                
174
 
        }
175
 
        
176
 
        return val;
177
 
}
178
 
 
179
 
//---------------------------
180
 
static const char *storageTypeCheck(char *value, bool *ok)
181
 
{
182
 
        const char *val = "Invalid storage type, try '"MS_REPOSITORY_STORAGE_TYPE"' or '"MS_CLOUD_STORAGE_TYPE"'";
183
 
        int len;
184
 
        
185
 
        value = cleanupVariable(value, &len);
186
 
        *ok = false;
187
 
        
188
 
        if (!strcmp(value, MS_REPOSITORY_STORAGE_TYPE)) {
189
 
                *ok = true;
190
 
                val = MS_REPOSITORY_STORAGE_TYPE;
191
 
        } else if (!strcmp(value, MS_CLOUD_STORAGE_TYPE)) {
192
 
                *ok = true;
193
 
                val = MS_CLOUD_STORAGE_TYPE;
194
 
        }
195
 
        
196
 
        return val;
197
 
}
198
 
 
199
 
//---------------------------
200
 
static void set_DumpRestore(MSDatabase *db, const char *value)
201
 
{
202
 
        enter_();
203
 
        push_(db);
204
 
        db->setRecovering((strcmp(value, "TRUE") == 0));
205
 
        release_(db);
206
 
        exit_();
207
 
}
208
 
 
209
 
//---------------------------
210
 
static void set_StorageType(MSDatabase *db, const char *value)
211
 
{
212
 
        enter_();
213
 
        push_(db);
214
 
 
215
 
        if (!strcmp(value, MS_REPOSITORY_STORAGE_TYPE))
216
 
                db->myBlobType = MS_STANDARD_STORAGE;
217
 
        else if (!strcmp(value, MS_CLOUD_STORAGE_TYPE))
218
 
                db->myBlobType = MS_CLOUD_STORAGE;
219
 
 
220
 
        release_(db);
221
 
        exit_();
222
 
}
223
 
 
224
 
//---------------------------
225
 
static const char *get_StorageType(MSDatabase *db, const char *)
226
 
{
227
 
        const char *value = "Unknown";
228
 
        enter_();
229
 
        push_(db);
230
 
 
231
 
        if (db->myBlobType == MS_STANDARD_STORAGE)
232
 
                value = MS_REPOSITORY_STORAGE_TYPE;
233
 
        else if (db->myBlobType == MS_CLOUD_STORAGE)
234
 
                value = MS_CLOUD_STORAGE_TYPE;
235
 
 
236
 
        release_(db);
237
 
        return_(value);
238
 
}
239
 
 
240
 
//---------------------------
241
 
static const char *get_S3CloudRefNo(MSDatabase *db, const char *)
242
 
{
243
 
        static char value[20];
244
 
        uint32_t        num;
245
 
        enter_();
246
 
        push_(db);
247
 
        
248
 
        num = db->myBlobCloud->cl_getDefaultCloudRef();
249
 
        snprintf(value, 20, "%"PRIu32"", num);
250
 
        
251
 
        release_(db);
252
 
        return_(value);
253
 
}
254
 
 
255
 
//---------------------------
256
 
static void set_S3CloudRefNo(MSDatabase *db, const char *value)
257
 
{
258
 
        enter_();
259
 
        push_(db);
260
 
        
261
 
        db->myBlobCloud->cl_setDefaultCloudRef(atol(value));
262
 
        
263
 
        release_(db);
264
 
        exit_();
265
 
}
266
 
 
267
 
//---------------------------
268
 
static void set_BackupNo(MSDatabase *db, const char *value)
269
 
{
270
 
        enter_();
271
 
        push_(db);
272
 
        
273
 
        db->myBlobCloud->cl_setRecoveryNumber(value);
274
 
        
275
 
        release_(db);
276
 
        exit_();
277
 
}
278
 
 
279
 
//---------------------------
280
 
static const char *get_BackupNo(MSDatabase *db, const char *)
281
 
{
282
 
        const char *value;
283
 
        enter_();
284
 
        push_(db);
285
 
        
286
 
        value = db->myBlobCloud->cl_getRecoveryNumber();
287
 
        
288
 
        release_(db);
289
 
        return_(value);
290
 
}
291
 
 
292
 
static PBMSVariableRec variables[] = {
293
 
        {false, "Storage-Type", MS_REPOSITORY_STORAGE_TYPE, "How the BLOB data is to be stored.", true, get_StorageType, storageTypeCheck, set_StorageType},
294
 
        {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},
295
 
        {false, RESTORE_DUMP_VAR, "FALSE", "Indicate if the database is being restored from a dump file.", false, get_DumpRestore, boolCheck, set_DumpRestore},
296
 
        // Hidden variables should be placed at the end.
297
 
        {true, BACKUP_NUMBER_VAR, NULL, "The backup number for cloud blob data after a drag and drop restore.", true, get_BackupNo, readOnlyCheck, set_BackupNo}
298
 
};
299
 
 
300
 
static const uint32_t num_variables = 4;
301
 
 
302
 
//---------------------------
303
 
//----------------------------
304
 
#define PBMS_VARIABLES_FILE     "pbms_variables"
305
 
static  CSPath *getSysVarFile(CSString *db_path)
306
 
{
307
 
        CSPath                  *path;
308
 
 
309
 
        enter_();
310
 
        
311
 
        push_(db_path);
312
 
 
313
 
        path = CSPath::newPath(RETAIN(db_path), PBMS_VARIABLES_FILE".dat");
314
 
        push_(path);
315
 
        if (!path->exists()) {
316
 
                CSPath *tmp_path;
317
 
 
318
 
                tmp_path = CSPath::newPath(RETAIN(db_path), PBMS_VARIABLES_FILE".tmp");
319
 
                push_(tmp_path);
320
 
                if (tmp_path->exists())
321
 
                        tmp_path->rename(PBMS_VARIABLES_FILE".dat");
322
 
                release_(tmp_path);
323
 
        }
324
 
        
325
 
        
326
 
        pop_(path);
327
 
        release_(db_path);
328
 
        return_(path);
329
 
}
330
 
 
331
 
class LoadTableCleanUp : public CSRefObject {
332
 
        bool do_cleanup;
333
 
        CSThread *myself;
334
 
        
335
 
        uint32_t ref_id;
336
 
 
337
 
        public:
338
 
        
339
 
        LoadTableCleanUp(): CSRefObject(),
340
 
                do_cleanup(false), myself(NULL){}
341
 
                
342
 
        ~LoadTableCleanUp() 
343
 
        {
344
 
                if (do_cleanup) {
345
 
                        CSL.log(myself, CSLog::Protocol, "\nRestore failed!\n");
346
 
                        CSL.flush();
347
 
                        myself->logException();
348
 
                }
349
 
        }
350
 
        
351
 
        void setCleanUp(CSThread *self)
352
 
        {
353
 
                myself = self;
354
 
                do_cleanup = true;
355
 
        }
356
 
        
357
 
        void cancelCleanUp()
358
 
        {
359
 
                do_cleanup = false;
360
 
        }
361
 
        
362
 
};
363
 
 
364
 
void MSVariableTable::loadTable(MSDatabase *db)
365
 
{
366
 
        CSPath  *path;
367
 
 
368
 
        enter_();
369
 
        
370
 
        push_(db);
371
 
        path = getSysVarFile(RETAIN(db->myDatabasePath));
372
 
        push_(path);
373
 
 
374
 
        if (path->exists()) {
375
 
                CSFile                  *file;
376
 
                CSStringBuffer  *string;
377
 
                size_t                  size = 0, pos =0;
378
 
                char                    *name, *value;
379
 
                
380
 
                new_(string, CSStringBuffer(20));
381
 
                push_(string);
382
 
 
383
 
                file = path->openFile(CSFile::READONLY);
384
 
                push_(file);
385
 
                size = file->getEOF();
386
 
                string->setLength(size);
387
 
                file->read(string->getBuffer(0), 0, size, size);
388
 
                release_(file);
389
 
                                
390
 
                while (pos < size) {
391
 
                        name = string->getBuffer(pos);
392
 
                        pos += strlen(name) +1;
393
 
                        if (pos >= size)
394
 
                                break;
395
 
                                
396
 
                        value = string->getBuffer(pos);
397
 
                        pos += strlen(value) +1;
398
 
                        if (pos > size)
399
 
                                break;
400
 
                        
401
 
                        for (uint32_t i =0; i < num_variables; i++) {
402
 
                                if (variables[i].save && variables[i].action && !strcmp(name, variables[i].name)) {
403
 
                                        variables[i].action(RETAIN(db), value);
404
 
                                }
405
 
                        }
406
 
                        
407
 
                }
408
 
                
409
 
                release_(string);
410
 
 
411
 
        } else { // Set the default values
412
 
                for (uint32_t i =0; i < num_variables; i++) {
413
 
                        if (variables[i].value && variables[i].action) {
414
 
                                variables[i].action(RETAIN(db), variables[i].value);
415
 
                        }
416
 
                }
417
 
        }
418
 
        
419
 
 
420
 
        release_(path);
421
 
        
422
 
        // Check to see if there is cloud storage and if the database is not
423
 
        // currently recovering, then try to restore the BLOBs. 
424
 
        if ((db->myBlobType == MS_CLOUD_STORAGE) && db->myBlobCloud->cl_mustRecoverBlobs() && !db->isRecovering()) {
425
 
                CSL.log(self, CSLog::Protocol, "Restoring Cloud BLOBs for database: ");
426
 
                CSL.log(self, CSLog::Protocol, db->myDatabaseName->getCString());
427
 
                CSL.log(self, CSLog::Protocol, " ...");
428
 
                CSL.flush();
429
 
                LoadTableCleanUp *cleanup;
430
 
                
431
 
                new_(cleanup, LoadTableCleanUp());
432
 
                push_(cleanup);
433
 
                cleanup->setCleanUp(self);
434
 
                
435
 
                db->myBlobCloud->cl_restoreDB();
436
 
                
437
 
                cleanup->cancelCleanUp();
438
 
                release_(cleanup);
439
 
 
440
 
                CSL.log(self, CSLog::Protocol, "\nRestore done.\n");
441
 
                CSL.flush();
442
 
                set_BackupNo(RETAIN(db), "0");
443
 
                saveTable(RETAIN(db));
444
 
        }
445
 
        
446
 
        release_(db);
447
 
 
448
 
        exit_();
449
 
}
450
 
 
451
 
void MSVariableTable::saveTable(MSDatabase *db)
452
 
{
453
 
        CSPath                  *path;
454
 
        CSPath                  *old_path;
455
 
        CSFile                  *file;
456
 
        const char              *value;
457
 
        size_t                  offset = 0, len;
458
 
        char                    null_char = 0;
459
 
        enter_();
460
 
        
461
 
        push_(db);
462
 
        path = CSPath::newPath(RETAIN(db->myDatabasePath), PBMS_VARIABLES_FILE".tmp");
463
 
        push_(path);
464
 
        file = path->openFile(CSFile::CREATE | CSFile::TRUNCATE);
465
 
        push_(file);
466
 
        
467
 
        for (uint32_t i = 0; i < num_variables; i++) {
468
 
                if (! variables[i].save) continue;
469
 
                
470
 
                len = strlen(variables[i].name)+1;
471
 
                file->write(variables[i].name, offset, len);
472
 
                offset += len;
473
 
 
474
 
                value = variables[i].get(RETAIN(db), variables[i].value);
475
 
                if (value) {
476
 
                        len = strlen(value)+1;
477
 
                        file->write(value, offset, len);
478
 
                        offset += len;
479
 
                } else {
480
 
                        file->write(&null_char, offset, 1);
481
 
                        offset++;
482
 
                }               
483
 
        }
484
 
        file->close();
485
 
        release_(file);
486
 
 
487
 
        old_path = CSPath::newPath(RETAIN(db->myDatabasePath), PBMS_VARIABLES_FILE".dat");
488
 
        push_(old_path);
489
 
        if (old_path->exists())
490
 
                old_path->remove();
491
 
        path->rename(PBMS_VARIABLES_FILE".dat");
492
 
        release_(old_path);
493
 
 
494
 
        release_(path);
495
 
        release_(db);
496
 
        exit_();
497
 
}
498
 
 
499
 
 
500
 
MSVariableTable::MSVariableTable(MSSystemTableShare *share, TABLE *table):
501
 
MSOpenSystemTable(share, table),
502
 
iVariableIndex(0)
503
 
{
504
 
}
505
 
 
506
 
MSVariableTable::~MSVariableTable()
507
 
{
508
 
        //unuse();
509
 
}
510
 
 
511
 
void MSVariableTable::use()
512
 
{
513
 
        gVarLock.lock();
514
 
}
515
 
 
516
 
void MSVariableTable::unuse()
517
 
{
518
 
        gVarLock.unlock();      
519
 
}
520
 
 
521
 
 
522
 
void MSVariableTable::seqScanInit()
523
 
{
524
 
        iVariableIndex = 0;
525
 
}
526
 
 
527
 
bool MSVariableTable::seqScanNext(char *buf)
528
 
{
529
 
        TABLE           *table = mySQLTable;
530
 
        Field           *curr_field;
531
 
        byte            *save;
532
 
        MY_BITMAP       *save_write_set;
533
 
        PBMSVariablePtr var;
534
 
        
535
 
        enter_();
536
 
        
537
 
        do {
538
 
                if (iVariableIndex >= num_variables)
539
 
                        return_(false);
540
 
                var = &(variables[iVariableIndex++]);
541
 
        
542
 
        } while (var->hidden); 
543
 
        
544
 
        save_write_set = table->write_set;
545
 
        table->write_set = NULL;
546
 
 
547
 
#ifdef DRIZZLED
548
 
        memset(buf, 0xFF, table->getNullBytes());
549
 
#else
550
 
        memset(buf, 0xFF, table->s->null_bytes);
551
 
#endif
552
 
        for (Field **field=GET_TABLE_FIELDS(table) ; *field ; field++) {
553
 
                curr_field = *field;
554
 
                save = curr_field->ptr;
555
 
#if MYSQL_VERSION_ID < 50114
556
 
                curr_field->ptr = (byte *) buf + curr_field->offset();
557
 
#else
558
 
#ifdef DRIZZLED
559
 
                curr_field->ptr = (byte *) buf + curr_field->offset(curr_field->getTable()->getInsertRecord());
560
 
#else
561
 
                curr_field->ptr = (byte *) buf + curr_field->offset(curr_field->table->record[0]);
562
 
#endif
563
 
#endif
564
 
                switch (curr_field->field_name[0]) {
565
 
                        case 'I':
566
 
                                ASSERT(strcmp(curr_field->field_name, "Id") == 0);
567
 
                                curr_field->store(iVariableIndex, true);
568
 
                                setNotNullInRecord(curr_field, buf);
569
 
                                break;
570
 
 
571
 
                        case 'N':
572
 
                                ASSERT(strcmp(curr_field->field_name, "Name") == 0);
573
 
                                        curr_field->store(var->name, strlen(var->name), &UTF8_CHARSET);
574
 
                                        setNotNullInRecord(curr_field, buf);
575
 
                                break;
576
 
 
577
 
                        case 'V': {
578
 
                                ASSERT(strcmp(curr_field->field_name, "Value") == 0);
579
 
                                        const char *value;
580
 
                                        value = var->get(RETAIN(myShare->mySysDatabase), var->value);
581
 
                                        if (value) {
582
 
                                                curr_field->store(value, strlen(value), &UTF8_CHARSET);
583
 
                                                setNotNullInRecord(curr_field, buf);
584
 
                                        }
585
 
                                }
586
 
                                break;
587
 
 
588
 
                        case 'D':
589
 
                                ASSERT(strcmp(curr_field->field_name, "Description") == 0);
590
 
                                        curr_field->store(var->info, strlen(var->info), &UTF8_CHARSET);
591
 
                                        setNotNullInRecord(curr_field, buf);
592
 
                                break;
593
 
 
594
 
                }
595
 
                curr_field->ptr = save;
596
 
        }
597
 
 
598
 
        table->write_set = save_write_set;
599
 
        return_(true);
600
 
}
601
 
 
602
 
void MSVariableTable::seqScanPos(unsigned char *pos)
603
 
{
604
 
        int32_t index = iVariableIndex -1;
605
 
        if (index < 0)
606
 
                index = 0; // This is probably an error condition.
607
 
                
608
 
        mi_int4store(pos, index);
609
 
}
610
 
 
611
 
void MSVariableTable::seqScanRead(unsigned char *pos, char *buf)
612
 
{
613
 
        iVariableIndex = mi_uint4korr(pos);
614
 
        seqScanNext(buf);
615
 
}
616
 
 
617
 
void MSVariableTable::updateRow(char *old_data, char *new_data) 
618
 
{
619
 
        uint32_t n_id, o_id;
620
 
        String n_var_name, n_var_value; 
621
 
        String o_var_name;      
622
 
        const char *clean_value;
623
 
 
624
 
        enter_();
625
 
        
626
 
        getFieldValue(old_data, 0, &o_id);
627
 
        getFieldValue(old_data, 1, &o_var_name);
628
 
        
629
 
        getFieldValue(new_data, 0, &n_id);
630
 
        getFieldValue(new_data, 1, &n_var_name);
631
 
        getFieldValue(new_data, 2, &n_var_value);
632
 
        
633
 
        // The command names must match.
634
 
        if ((n_id != o_id) || UTF8_CHARSET.strcasecmp(o_var_name.c_str(), n_var_name.c_str()))
635
 
                CSException::throwException(CS_CONTEXT, HA_ERR_TABLE_READONLY, "Attempt to update read only fields in the "VARIABLES_TABLE_NAME" table.");
636
 
                
637
 
        n_id--;
638
 
        if (n_id >  num_variables) // Should never happen
639
 
                CSException::throwException(CS_CONTEXT, HA_ERR_KEY_NOT_FOUND, "Invalid id");
640
 
        
641
 
        CSStringBuffer *value;  
642
 
        new_(value, CSStringBuffer(0));
643
 
        push_(value);
644
 
        value->append(n_var_value.c_ptr(), n_var_value.length());
645
 
        
646
 
        // check the input value converting it to a standard format where aplicable:
647
 
        if (variables[n_id].check) {
648
 
                bool ok = false;
649
 
                clean_value = variables[n_id].check(value->getCString(), &ok);
650
 
                if (!ok)
651
 
                        CSException::throwException(CS_CONTEXT, HA_ERR_GENERIC, clean_value);
652
 
        } else
653
 
                clean_value = value->getCString();
654
 
                
655
 
        // Execute the action associated with the variable.
656
 
        if (variables[n_id].action) {
657
 
                variables[n_id].action(RETAIN(myShare->mySysDatabase), clean_value);
658
 
        }
659
 
        
660
 
        release_(value);
661
 
        
662
 
        if (variables[n_id].save) {
663
 
                saveTable(RETAIN(myShare->mySysDatabase));
664
 
        }
665
 
        
666
 
        exit_();
667
 
}
668
 
 
669
 
void MSVariableTable::transferTable(MSDatabase *to_db, MSDatabase *from_db)
670
 
{
671
 
        CSPath  *path;
672
 
        enter_();
673
 
        
674
 
        push_(from_db);
675
 
        push_(to_db);
676
 
        
677
 
        path = CSPath::newPath(RETAIN(from_db->myDatabasePath), PBMS_VARIABLES_FILE".dat");
678
 
        push_(path);
679
 
        if (path->exists()) {
680
 
                CSPath  *bu_path;
681
 
                bu_path = CSPath::newPath(RETAIN(to_db->myDatabasePath), PBMS_VARIABLES_FILE".dat");
682
 
                path->copyTo(bu_path, true);
683
 
        }
684
 
        
685
 
        release_(path);
686
 
        release_(to_db);
687
 
        release_(from_db);
688
 
        
689
 
        exit_();
690
 
}
691
 
 
692
 
void MSVariableTable::setVariable(MSDatabase *db, const char *name, const char *value)
693
 
{
694
 
        enter_();
695
 
        
696
 
        push_(db);
697
 
        
698
 
        for (uint32_t i =0; db && i < num_variables; i++) {
699
 
                if (variables[i].action && !strcmp(name, variables[i].name)) {
700
 
                        variables[i].action(RETAIN(db), value);
701
 
                        if (variables[i].save) {
702
 
                                pop_(db);
703
 
                                saveTable(db);
704
 
                        } else
705
 
                                release_(db);
706
 
                        db = NULL;
707
 
                }
708
 
        }
709
 
 
710
 
        if (db) {
711
 
                release_(db);
712
 
                CSException::throwException(CS_CONTEXT, HA_ERR_KEY_NOT_FOUND, name);
713
 
        }
714
 
        exit_();
715
 
}
716
 
 
717
 
CSStringBuffer *MSVariableTable::dumpTable(MSDatabase *db)
718
 
{
719
 
 
720
 
        CSPath                  *path;
721
 
        CSStringBuffer  *dump;
722
 
 
723
 
        enter_();
724
 
        
725
 
        push_(db);
726
 
        path = getSysVarFile(RETAIN(db->myDatabasePath));
727
 
        release_(db);
728
 
        
729
 
        push_(path);
730
 
        new_(dump, CSStringBuffer(20));
731
 
        push_(dump);
732
 
 
733
 
        if (path->exists()) {
734
 
                CSFile  *file;
735
 
                size_t  size;
736
 
                
737
 
                file = path->openFile(CSFile::READONLY);
738
 
                push_(file);
739
 
                
740
 
                size = file->getEOF();
741
 
                dump->setLength(size);
742
 
                file->read(dump->getBuffer(0), 0, size, size);
743
 
                release_(file);
744
 
        }
745
 
        
746
 
        pop_(dump);
747
 
        release_(path);
748
 
        return_(dump);
749
 
}
750
 
 
751
 
void MSVariableTable::restoreTable(MSDatabase *db, const char *data, size_t size, bool reload)
752
 
{
753
 
        CSPath  *path;
754
 
        CSFile  *file;
755
 
 
756
 
        enter_();
757
 
        
758
 
        push_(db);
759
 
        path = getSysVarFile(RETAIN(db->myDatabasePath));
760
 
        push_(path);
761
 
        
762
 
        file = path->openFile(CSFile::CREATE | CSFile::TRUNCATE);
763
 
        push_(file);
764
 
        
765
 
        file->write(data, 0, size);
766
 
        file->close();
767
 
        release_(file);
768
 
        
769
 
        release_(path);
770
 
        
771
 
        pop_(db);
772
 
        if (reload)
773
 
                loadTable(db);
774
 
        else
775
 
                db->release();
776
 
        exit_();
777
 
}
778
 
 
779
 
void MSVariableTable::removeTable(CSString *db_path)
780
 
{
781
 
        CSPath  *path;
782
 
        enter_();
783
 
        
784
 
        path = getSysVarFile(db_path);
785
 
        push_(path);
786
 
        
787
 
        path->removeFile();
788
 
        release_(path);
789
 
        exit_();
790
 
}
791