~drizzle-trunk/drizzle/development

« back to all changes in this revision

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

  • Committer: Mark Atwood
  • Date: 2011-12-20 02:32:53 UTC
  • mfrom: (2469.1.1 drizzle-build)
  • Revision ID: me@mark.atwood.name-20111220023253-bvu0kr14kwsdvz7g
mergeĀ lp:~brianaker/drizzle/deprecate-pbms

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
 
 * 2009-10-27
22
 
 *
23
 
 * System backup info table for repository backups.
24
 
 */
25
 
#ifdef DRIZZLED
26
 
#include <config.h>
27
 
#include <drizzled/common.h>
28
 
#include <drizzled/session.h>
29
 
#include <drizzled/sql_lex.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
 
#include "cslib/CSPath.h"
45
 
#include "cslib/CSDirectory.h"
46
 
 
47
 
#include "ha_pbms.h"
48
 
//#include <plugin.h>
49
 
 
50
 
#include "mysql_ms.h"
51
 
#include "database_ms.h"
52
 
#include "open_table_ms.h"
53
 
#include "discover_ms.h"
54
 
#include "systab_util_ms.h"
55
 
#include "backup_ms.h"
56
 
 
57
 
#include "systab_backup_ms.h"
58
 
 
59
 
 
60
 
DT_FIELD_INFO pbms_backup_info[]=
61
 
{
62
 
        {"Id",                          NOVAL,  NULL, MYSQL_TYPE_LONG,          NULL,                   NOT_NULL_FLAG,  "The backup reference ID"},
63
 
        {"Database_Name",       64,             NULL, MYSQL_TYPE_VARCHAR,       &UTF8_CHARSET,  NOT_NULL_FLAG,  "The database name"},
64
 
        {"Database_Id",         NOVAL,  NULL, MYSQL_TYPE_LONG,          NULL,                   0,      "The database ID"},
65
 
        {"Started",                     32,             NULL, MYSQL_TYPE_VARCHAR,       &UTF8_CHARSET,  0,      "The start time"},
66
 
        {"Completed",           32,             NULL, MYSQL_TYPE_VARCHAR,       &UTF8_CHARSET,  0,      "The completion time"},
67
 
        {"IsRunning",           3,              NULL, MYSQL_TYPE_VARCHAR,       &UTF8_CHARSET,  0,      "Is the backup still running"},
68
 
        {"IsDump",                      3,              NULL, MYSQL_TYPE_VARCHAR,       &UTF8_CHARSET,  0,      "Is the backup the result of a dump"},
69
 
        {"Location",            1024,   NULL, MYSQL_TYPE_VARCHAR,       &UTF8_CHARSET,  0,      "The backup location"},
70
 
        {"Cloud_Ref",           NOVAL,  NULL, MYSQL_TYPE_LONG,          NULL,                   0,      "The S3 cloud reference number refering to the pbms.pbms_cloud table."},
71
 
        {"Cloud_Backup_No",     NOVAL,  NULL, MYSQL_TYPE_LONG,          NULL,                   0,      "The cloud backup number"},
72
 
        {NULL,NOVAL, NULL, MYSQL_TYPE_STRING,NULL, 0, NULL}
73
 
};
74
 
 
75
 
DT_KEY_INFO pbms_backup_keys[]=
76
 
{
77
 
        {"pbms_backup_pk", PRI_KEY_FLAG, {"Id", NULL}},
78
 
        {NULL, 0, {NULL}}
79
 
};
80
 
 
81
 
#define MIN_BACKUP_TABLE_FILE_SIZE 4
82
 
 
83
 
 
84
 
//----------------------------
85
 
void MSBackupTable::startUp()
86
 
{
87
 
        MSBackupInfo::startUp();
88
 
}
89
 
 
90
 
//----------------------------
91
 
void MSBackupTable::shutDown()
92
 
{
93
 
        MSBackupInfo::shutDown();
94
 
}
95
 
 
96
 
//----------------------------
97
 
void MSBackupTable::loadTable(MSDatabase *db)
98
 
{
99
 
 
100
 
        enter_();
101
 
        
102
 
        push_(db);
103
 
        lock_(MSBackupInfo::gBackupInfo);
104
 
        
105
 
        if (MSBackupInfo::gMaxInfoRef == 0) {
106
 
                CSPath  *path;
107
 
                path = getSysFile(getPBMSPath(RETAIN(db->myDatabasePath)), BACKUP_TABLE_NAME, MIN_BACKUP_TABLE_FILE_SIZE);
108
 
                push_(path);
109
 
 
110
 
                if (path->exists()) {
111
 
                        CSFile          *file;
112
 
                        SysTabRec       *backupData;
113
 
                        const char      *name, *location;
114
 
                        uint32_t                info_id, db_id, start, end, cloud_ref, cloud_backup_no;
115
 
                        bool            isDump;
116
 
                        MSBackupInfo    *info;
117
 
                        size_t          size;
118
 
                        
119
 
                        new_(backupData, SysTabRec("pbms", BACKUP_TABLE_NAME".dat", BACKUP_TABLE_NAME));
120
 
                        push_(backupData);
121
 
 
122
 
                        file = path->openFile(CSFile::READONLY);
123
 
                        push_(file);
124
 
                        size = file->getEOF();
125
 
                        backupData->setLength(size);
126
 
                        file->read(backupData->getBuffer(0), 0, size, size);
127
 
                        release_(file);
128
 
                        
129
 
                        backupData->firstRecord();
130
 
                        MSBackupInfo::gMaxInfoRef = backupData->getInt4Field();
131
 
                        
132
 
                        if (! backupData->isValidRecord()) 
133
 
                                MSBackupInfo::gMaxInfoRef = 1;
134
 
                        
135
 
                        while (backupData->nextRecord()) {
136
 
                                info_id = backupData->getInt4Field();
137
 
                                name = backupData->getStringField();
138
 
                                db_id = backupData->getInt4Field();
139
 
                                start = backupData->getInt4Field();
140
 
                                end = backupData->getInt4Field();
141
 
                                isDump = backupData->getInt1Field();
142
 
                                location = backupData->getStringField();
143
 
                                cloud_ref = backupData->getInt4Field();
144
 
                                cloud_backup_no = backupData->getInt4Field();
145
 
                                
146
 
                                if (backupData->isValidRecord()) {
147
 
                                        if (info_id > MSBackupInfo::gMaxInfoRef) {
148
 
                                                char msg[80];
149
 
                                                snprintf(msg, 80, "backup info id (%"PRIu32") larger than expected (%"PRIu32")\n", info_id, MSBackupInfo::gMaxInfoRef);
150
 
                                                CSL.log(self, CSLog::Warning, "pbms "BACKUP_TABLE_NAME".dat :possible damaged file or record. ");
151
 
                                                CSL.log(self, CSLog::Warning, msg);
152
 
                                                MSBackupInfo::gMaxInfoRef = info_id +1;
153
 
                                        }
154
 
                                        if ( MSBackupInfo::gBackupInfo->get(info_id)) {
155
 
                                                char msg[80];
156
 
                                                snprintf(msg, 80, "Duplicate Backup info id (%"PRIu32") being ignored\n", info_id);
157
 
                                                CSL.log(self, CSLog::Warning, "pbms "BACKUP_TABLE_NAME".dat :possible damaged file or record. ");
158
 
                                                CSL.log(self, CSLog::Warning, msg);
159
 
                                        } else {
160
 
                                                new_(info, MSBackupInfo(info_id, name, db_id, start, end, isDump, location, cloud_ref, cloud_backup_no));
161
 
                                                MSBackupInfo::gBackupInfo->set(info_id, info);
162
 
                                        }
163
 
                                }
164
 
                        }
165
 
                        release_(backupData); backupData = NULL;
166
 
                        
167
 
                } else
168
 
                        MSBackupInfo::gMaxInfoRef = 1;
169
 
                
170
 
                release_(path);
171
 
                
172
 
        }
173
 
        unlock_(MSBackupInfo::gBackupInfo);
174
 
 
175
 
        release_(db);
176
 
 
177
 
        exit_();
178
 
}
179
 
 
180
 
void MSBackupTable::saveTable(MSDatabase *db)
181
 
{
182
 
        SysTabRec               *backupData;
183
 
        MSBackupInfo            *info;
184
 
        enter_();
185
 
        
186
 
        push_(db);
187
 
        
188
 
        new_(backupData, SysTabRec("pbms", BACKUP_TABLE_NAME".dat", BACKUP_TABLE_NAME));
189
 
        push_(backupData);
190
 
        
191
 
        // Build the table records
192
 
        backupData->clear();
193
 
        lock_(MSBackupInfo::gBackupInfo);
194
 
        
195
 
        backupData->beginRecord();      
196
 
        backupData->setInt4Field(MSBackupInfo::gMaxInfoRef);
197
 
        backupData->endRecord();        
198
 
        for  (int i = 0;(info = (MSBackupInfo*) MSBackupInfo::gBackupInfo->itemAt(i)); i++) { // info is not referenced.
199
 
                
200
 
                backupData->beginRecord();      
201
 
                backupData->setInt4Field(info->getBackupRefId());
202
 
                
203
 
                backupData->setStringField(info->getName());
204
 
                backupData->setInt4Field(info->getDatabaseId());
205
 
                backupData->setInt4Field(info->getStart());
206
 
                backupData->setInt4Field(info->getEnd());
207
 
                backupData->setInt1Field(info->isDump());
208
 
                backupData->setStringField(info->getLocation());
209
 
                backupData->setInt4Field(info->getcloudRef());
210
 
                backupData->setInt4Field(info->getcloudBackupNo());
211
 
                backupData->endRecord();                        
212
 
        }
213
 
        unlock_(MSBackupInfo::gBackupInfo);
214
 
 
215
 
        restoreTable(RETAIN(db), backupData->getBuffer(0), backupData->length(), false);
216
 
        
217
 
        release_(backupData);
218
 
        release_(db);
219
 
        exit_();
220
 
}
221
 
 
222
 
 
223
 
MSBackupTable::MSBackupTable(MSSystemTableShare *share, TABLE *table):
224
 
MSOpenSystemTable(share, table),
225
 
iBackupIndex(0)
226
 
{
227
 
}
228
 
 
229
 
MSBackupTable::~MSBackupTable()
230
 
{
231
 
        //unuse();
232
 
}
233
 
 
234
 
void MSBackupTable::use()
235
 
{
236
 
        MSBackupInfo::gBackupInfo->lock();
237
 
}
238
 
 
239
 
void MSBackupTable::unuse()
240
 
{
241
 
        MSBackupInfo::gBackupInfo->unlock();
242
 
        
243
 
}
244
 
 
245
 
 
246
 
void MSBackupTable::seqScanInit()
247
 
{
248
 
        iBackupIndex = 0;
249
 
}
250
 
 
251
 
bool MSBackupTable::seqScanNext(char *buf)
252
 
{
253
 
        TABLE           *table = mySQLTable;
254
 
        Field           *curr_field;
255
 
        byte            *save;
256
 
        MY_BITMAP       *save_write_set;
257
 
        MSBackupInfo    *info;
258
 
        CSTime          *timeVal;
259
 
        const char      *val;
260
 
        
261
 
        enter_();
262
 
        
263
 
        info = (MSBackupInfo    *) MSBackupInfo::gBackupInfo->itemAt(iBackupIndex++); // Object is not referenced.
264
 
        if (!info)
265
 
                return_(false);
266
 
        
267
 
        save_write_set = table->write_set;
268
 
        table->write_set = NULL;
269
 
 
270
 
        new_(timeVal, CSTime());
271
 
        push_(timeVal);
272
 
#ifdef DRIZZLED
273
 
        memset(buf, 0xFF, table->getNullBytes());
274
 
#else
275
 
        memset(buf, 0xFF, table->s->null_bytes);
276
 
#endif
277
 
        for (Field **field=GET_TABLE_FIELDS(table) ; *field ; field++) {
278
 
                curr_field = *field;
279
 
                save = curr_field->ptr;
280
 
#if MYSQL_VERSION_ID < 50114
281
 
                curr_field->ptr = (byte *) buf + curr_field->offset();
282
 
#else
283
 
#ifdef DRIZZLED
284
 
                curr_field->ptr = (byte *) buf + curr_field->offset(curr_field->getTable()->getInsertRecord());
285
 
#else
286
 
                curr_field->ptr = (byte *) buf + curr_field->offset(curr_field->table->record[0]);
287
 
#endif
288
 
#endif
289
 
                switch (curr_field->field_name[0]) {
290
 
                        case 'I':
291
 
                                if (curr_field->field_name[1] == 'd') {
292
 
                                        ASSERT(strcmp(curr_field->field_name, "Id") == 0);
293
 
                                        curr_field->store(info->getBackupRefId(), true);
294
 
                                        setNotNullInRecord(curr_field, buf);
295
 
                                } else if (curr_field->field_name[2] == 'D') {
296
 
                                        ASSERT(strcmp(curr_field->field_name, "IsDump") == 0);
297
 
                                        val = (info->isDump())? "Yes": "No";
298
 
                                        curr_field->store(val, strlen(val), &UTF8_CHARSET);
299
 
                                        setNotNullInRecord(curr_field, buf);
300
 
                                } else {
301
 
                                        ASSERT(strcmp(curr_field->field_name, "IsRunning") == 0);
302
 
                                        val = (info->isBackupRunning())? "Yes": "No";
303
 
                                        curr_field->store(val, strlen(val), &UTF8_CHARSET);
304
 
                                        setNotNullInRecord(curr_field, buf);
305
 
                                } 
306
 
                                break;
307
 
 
308
 
                        case 'D':
309
 
                                if (curr_field->field_name[9] == 'I') {
310
 
                                        ASSERT(strcmp(curr_field->field_name, "Database_Id") == 0);
311
 
                                        curr_field->store(info->getDatabaseId(), true);
312
 
                                        setNotNullInRecord(curr_field, buf);
313
 
                                } else {
314
 
                                        ASSERT(strcmp(curr_field->field_name, "Database_Name") == 0);
315
 
                                        val = info->getName();
316
 
                                        curr_field->store(val, strlen(val), &UTF8_CHARSET);
317
 
                                        setNotNullInRecord(curr_field, buf);
318
 
                                }
319
 
                                
320
 
                                break;
321
 
 
322
 
                        case 'S': 
323
 
                                ASSERT(strcmp(curr_field->field_name, "Started") == 0);
324
 
                                if (info->getStart()) {
325
 
                                        timeVal->setUTC1970(info->getStart(), 0);
326
 
                                        val = timeVal->getCString();
327
 
                                        curr_field->store(val, strlen(val), &UTF8_CHARSET);
328
 
                                        setNotNullInRecord(curr_field, buf);
329
 
                                }
330
 
                                break;
331
 
 
332
 
                        case 'L':
333
 
                                ASSERT(strcmp(curr_field->field_name, "Location") == 0);
334
 
                                val = info->getLocation();
335
 
                                if (val) {
336
 
                                        curr_field->store(val, strlen(val), &UTF8_CHARSET);
337
 
                                        setNotNullInRecord(curr_field, buf);
338
 
                                }
339
 
                                break;
340
 
 
341
 
                        case 'C': 
342
 
                                if (curr_field->field_name[1] == 'o') {
343
 
                                        ASSERT(strcmp(curr_field->field_name, "Completed") == 0);
344
 
                                        if (info->getEnd()) {
345
 
                                                timeVal->setUTC1970(info->getEnd(), 0);
346
 
                                                val = timeVal->getCString();
347
 
                                                curr_field->store(val, strlen(val), &UTF8_CHARSET);
348
 
                                                setNotNullInRecord(curr_field, buf);
349
 
                                        }
350
 
                                } else if (curr_field->field_name[6] == 'R') {
351
 
                                        ASSERT(strcmp(curr_field->field_name, "Cloud_Ref") == 0);
352
 
                                        curr_field->store(info->getcloudRef(), true);
353
 
                                        setNotNullInRecord(curr_field, buf);
354
 
                                } else if (curr_field->field_name[6] == 'B') {
355
 
                                        ASSERT(strcmp(curr_field->field_name, "Cloud_Backup_No") == 0);
356
 
                                        curr_field->store(info->getcloudBackupNo(), true);
357
 
                                        setNotNullInRecord(curr_field, buf);
358
 
                                } else {
359
 
                                        ASSERT(false);
360
 
                                        break;
361
 
                                }
362
 
                                break;
363
 
                                
364
 
                        default:
365
 
                                ASSERT(false);
366
 
                }
367
 
                curr_field->ptr = save;
368
 
        }
369
 
 
370
 
        release_(timeVal);
371
 
        table->write_set = save_write_set;
372
 
        
373
 
        return_(true);
374
 
}
375
 
 
376
 
void MSBackupTable::seqScanPos(unsigned char *pos)
377
 
{
378
 
        int32_t index = iBackupIndex -1;
379
 
        if (index < 0)
380
 
                index = 0; // This is probably an error condition.
381
 
                
382
 
        mi_int4store(pos, index);
383
 
}
384
 
 
385
 
void MSBackupTable::seqScanRead(unsigned char *pos, char *buf)
386
 
{
387
 
        iBackupIndex = mi_uint4korr(pos);
388
 
        seqScanNext(buf);
389
 
}
390
 
 
391
 
void MSBackupTable::updateRow(char *old_data, char *new_data) 
392
 
{
393
 
        uint32_t n_id, db_id, cloud_ref, cloud_backup_no, n_indx;
394
 
        uint32_t o_id, o_db_id, o_cloud_ref, o_cloud_backup_no, o_indx;
395
 
        String name, start, end, isRunning, isDump, location;
396
 
        String o_name, o_start, o_end, o_isRunning, o_isDump, o_location;
397
 
        MSBackupInfo *info, *old_info;
398
 
 
399
 
        enter_();
400
 
        
401
 
        getFieldValue(new_data, 0, &n_id);
402
 
        getFieldValue(new_data, 1, &name);
403
 
        getFieldValue(new_data, 2, &db_id);
404
 
        getFieldValue(new_data, 3, &start);
405
 
        getFieldValue(new_data, 4, &end);
406
 
        getFieldValue(new_data, 5, &isRunning);
407
 
        getFieldValue(new_data, 6, &isDump);
408
 
        getFieldValue(new_data, 7, &location);
409
 
        getFieldValue(new_data, 8, &cloud_ref);
410
 
        getFieldValue(new_data, 9, &cloud_backup_no);
411
 
 
412
 
        getFieldValue(old_data, 0, &o_id);
413
 
        getFieldValue(old_data, 1, &o_name);
414
 
        getFieldValue(old_data, 2, &o_db_id);
415
 
        getFieldValue(old_data, 3, &o_start);
416
 
        getFieldValue(old_data, 4, &o_end);
417
 
        getFieldValue(old_data, 5, &o_isRunning);
418
 
        getFieldValue(old_data, 6, &o_isDump);
419
 
        getFieldValue(old_data, 7, &o_location);
420
 
        getFieldValue(old_data, 8, &o_cloud_ref);
421
 
        getFieldValue(old_data, 9, &o_cloud_backup_no);
422
 
 
423
 
        // The only fields that are allowed to be updated are 'Location' and 'Cloud_Ref'.
424
 
        // It makes no scence to update any of the other fields.
425
 
        if (n_id != o_id )
426
 
                CSException::throwException(CS_CONTEXT, HA_ERR_TABLE_READONLY, "Attempt to update read only field (Id) in the "BACKUP_TABLE_NAME" table.");
427
 
        
428
 
        if (strcmp(name.c_ptr(), o_name.c_ptr()) == 0 )
429
 
                CSException::throwException(CS_CONTEXT, HA_ERR_TABLE_READONLY, "Attempt to update read only field (Database_Name) in the "BACKUP_TABLE_NAME" table.");
430
 
        
431
 
        if (db_id != o_db_id )
432
 
                CSException::throwException(CS_CONTEXT, HA_ERR_TABLE_READONLY, "Attempt to update read only field (Database_Id) in the "BACKUP_TABLE_NAME" table.");
433
 
        
434
 
        if (strcmp(start.c_ptr(), o_start.c_ptr()) == 0 )
435
 
                CSException::throwException(CS_CONTEXT, HA_ERR_TABLE_READONLY, "Attempt to update read only field (Started) in the "BACKUP_TABLE_NAME" table.");
436
 
        
437
 
        if (strcmp(end.c_ptr(), o_end.c_ptr()) == 0 )
438
 
                CSException::throwException(CS_CONTEXT, HA_ERR_TABLE_READONLY, "Attempt to update read only field (Completed) in the "BACKUP_TABLE_NAME" table.");
439
 
        
440
 
        if (strcmp(isRunning.c_ptr(), o_isRunning.c_ptr()) == 0 )
441
 
                CSException::throwException(CS_CONTEXT, HA_ERR_TABLE_READONLY, "Attempt to update read only field (isRunning) in the "BACKUP_TABLE_NAME" table.");
442
 
        
443
 
        if (strcmp(isDump.c_ptr(), o_isDump.c_ptr()) == 0 )
444
 
                CSException::throwException(CS_CONTEXT, HA_ERR_TABLE_READONLY, "Attempt to update read only field (IsDump) in the "BACKUP_TABLE_NAME" table.");
445
 
        
446
 
        if (cloud_backup_no != o_cloud_backup_no )
447
 
                CSException::throwException(CS_CONTEXT, HA_ERR_TABLE_READONLY, "Attempt to update read only field (Cloud_Backup_No) in the "BACKUP_TABLE_NAME" table.");
448
 
 
449
 
        old_info = (MSBackupInfo*)  MSBackupInfo::gBackupInfo->get(o_id); // A non referenced object.
450
 
        
451
 
        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));
452
 
        push_(info);
453
 
        
454
 
        o_indx = MSBackupInfo::gBackupInfo->getIndex(o_id);
455
 
 
456
 
        MSBackupInfo::gBackupInfo->remove(o_id);
457
 
        pop_(info);
458
 
        MSBackupInfo::gBackupInfo->set(n_id, info);
459
 
        
460
 
        // Adjust the current position in the array if required.
461
 
        n_indx = MSBackupInfo::gBackupInfo->getIndex(n_id);
462
 
        if (o_indx < n_indx )
463
 
                iBackupIndex--;
464
 
 
465
 
        saveTable(RETAIN(myShare->mySysDatabase));
466
 
 
467
 
        exit_();
468
 
}
469
 
 
470
 
class InsertRowCleanUp : public CSRefObject {
471
 
        bool do_cleanup;
472
 
        CSThread *myself;
473
 
        
474
 
        uint32_t ref_id;
475
 
 
476
 
        public:
477
 
        
478
 
        InsertRowCleanUp(CSThread *self): CSRefObject(),
479
 
                do_cleanup(true), myself(self){}
480
 
                
481
 
        ~InsertRowCleanUp() 
482
 
        {
483
 
                if (do_cleanup) {
484
 
                        myself->logException();
485
 
                        if (ref_id)
486
 
                                MSBackupInfo::gBackupInfo->remove(ref_id);
487
 
 
488
 
                }
489
 
        }
490
 
        
491
 
        void setCleanUp(uint32_t id)
492
 
        {
493
 
                ref_id = id;
494
 
        }
495
 
        
496
 
        void cancelCleanUp()
497
 
        {
498
 
                do_cleanup = false;
499
 
        }
500
 
        
501
 
};
502
 
 
503
 
void MSBackupTable::insertRow(char *data) 
504
 
{
505
 
        uint32_t ref_id = 0, db_id, cloud_ref, cloud_backup_no;
506
 
        String name, start, end, isRunning, isDump, location;
507
 
        MSBackupInfo *info = NULL;
508
 
        const char *db_name;
509
 
        InsertRowCleanUp *cleanup;
510
 
 
511
 
        enter_();
512
 
 
513
 
        new_(cleanup, InsertRowCleanUp(self));
514
 
        push_(cleanup);
515
 
        
516
 
        getFieldValue(data, 0, &ref_id);
517
 
                
518
 
        // The id must be unique.
519
 
        if (ref_id && MSBackupInfo::gBackupInfo->get(ref_id)) {
520
 
                CSException::throwException(CS_CONTEXT, MS_ERR_DUPLICATE, "Attempt to insert a row with a duplicate key in the "BACKUP_TABLE_NAME" table.");
521
 
        }
522
 
        
523
 
        // The 'Database_Id', 'Start', 'Completion' and "IsDump" fields are ignored.
524
 
        // I still need to get the fields though to advance the field position pointer.
525
 
        getFieldValue(data, 1, &name);
526
 
        getFieldValue(data, 2, &db_id);
527
 
        getFieldValue(data, 3, &start);
528
 
        getFieldValue(data, 4, &end);
529
 
        getFieldValue(data, 5, &isRunning);
530
 
        getFieldValue(data, 6, &isDump);
531
 
        getFieldValue(data, 7, &location);
532
 
        getFieldValue(data, 8, &cloud_ref);
533
 
        getFieldValue(data, 9, &cloud_backup_no);
534
 
        
535
 
        if (ref_id == 0)
536
 
                ref_id = MSBackupInfo::gMaxInfoRef++;
537
 
        else if (ref_id >= MSBackupInfo::gMaxInfoRef)
538
 
                MSBackupInfo::gMaxInfoRef = ref_id +1;
539
 
        
540
 
        db_name = name.c_ptr();
541
 
        db_id = MSDatabase::getDatabaseID(db_name, false);
542
 
        
543
 
        cleanup->setCleanUp(ref_id);
544
 
        new_(info, MSBackupInfo(ref_id, db_name, db_id, 0, 0, false, location.c_ptr(), cloud_ref, cloud_backup_no));
545
 
        MSBackupInfo::gBackupInfo->set(ref_id, info);
546
 
        
547
 
        // There is no need to call this now, startBackup() will call it
548
 
        // after the backup is started.
549
 
        // saveTable(RETAIN(myShare->mySysDatabase)); 
550
 
        info->startBackup(RETAIN(myShare->mySysDatabase));
551
 
 
552
 
        cleanup->cancelCleanUp();
553
 
        release_(cleanup);
554
 
        
555
 
        exit_();
556
 
}
557
 
 
558
 
void MSBackupTable::deleteRow(char *data) 
559
 
{
560
 
        uint32_t ref_id, indx;
561
 
 
562
 
        enter_();
563
 
        
564
 
        getFieldValue(data, 0, &ref_id);
565
 
        
566
 
        // Adjust the current position in the array if required.
567
 
        indx = MSBackupInfo::gBackupInfo->getIndex(ref_id);
568
 
        if (indx <= iBackupIndex)
569
 
                iBackupIndex--;
570
 
        
571
 
        MSBackupInfo::gBackupInfo->remove(ref_id);
572
 
        saveTable(RETAIN(myShare->mySysDatabase));
573
 
        exit_();
574
 
}
575
 
 
576
 
void MSBackupTable::transferTable(MSDatabase *to_db, MSDatabase *from_db)
577
 
{
578
 
        CSPath  *path;
579
 
        enter_();
580
 
        
581
 
        push_(from_db);
582
 
        push_(to_db);
583
 
        
584
 
        path = CSPath::newPath(getPBMSPath(RETAIN(from_db->myDatabasePath)), BACKUP_TABLE_NAME".dat");
585
 
        push_(path);
586
 
        if (path->exists()) {
587
 
                CSPath  *bu_path;
588
 
                bu_path = CSPath::newPath(getPBMSPath(RETAIN(to_db->myDatabasePath)), BACKUP_TABLE_NAME".dat");
589
 
                path->copyTo(bu_path, true);
590
 
        }
591
 
        
592
 
        release_(path);
593
 
        release_(to_db);
594
 
        release_(from_db);
595
 
        
596
 
        exit_();
597
 
}
598
 
 
599
 
CSStringBuffer *MSBackupTable::dumpTable(MSDatabase *db)
600
 
{
601
 
 
602
 
        CSPath                  *path;
603
 
        CSStringBuffer  *dump;
604
 
 
605
 
        enter_();
606
 
        
607
 
        push_(db);
608
 
        path = getSysFile(getPBMSPath(RETAIN(db->myDatabasePath)), BACKUP_TABLE_NAME, MIN_BACKUP_TABLE_FILE_SIZE);
609
 
        release_(db);
610
 
        
611
 
        push_(path);
612
 
        new_(dump, CSStringBuffer(20));
613
 
        push_(dump);
614
 
 
615
 
        if (path->exists()) {
616
 
                CSFile  *file;
617
 
                size_t  size;
618
 
                
619
 
                file = path->openFile(CSFile::READONLY);
620
 
                push_(file);
621
 
                
622
 
                size = file->getEOF();
623
 
                dump->setLength(size);
624
 
                file->read(dump->getBuffer(0), 0, size, size);
625
 
                release_(file);
626
 
        }
627
 
        
628
 
        pop_(dump);
629
 
        release_(path);
630
 
        return_(dump);
631
 
}
632
 
 
633
 
void MSBackupTable::restoreTable(MSDatabase *db, const char *data, size_t size, bool reload)
634
 
{
635
 
        CSPath  *path;
636
 
        CSFile  *file;
637
 
 
638
 
        enter_();
639
 
        
640
 
        push_(db);
641
 
        path = getSysFile(getPBMSPath(RETAIN(db->myDatabasePath)), BACKUP_TABLE_NAME, MIN_BACKUP_TABLE_FILE_SIZE);
642
 
        push_(path);
643
 
        
644
 
        file = path->openFile(CSFile::CREATE | CSFile::TRUNCATE);
645
 
        push_(file);
646
 
        
647
 
        file->write(data, 0, size);
648
 
        file->close();
649
 
        release_(file);
650
 
        
651
 
        release_(path);
652
 
        
653
 
        pop_(db);
654
 
        if (reload)
655
 
                loadTable(db);
656
 
        else
657
 
                db->release();
658
 
                
659
 
        exit_();
660
 
}
661
 
 
662
 
// The cloud info table is only removed from the pbms database
663
 
// if there are no more databases.
664
 
void MSBackupTable::removeTable(CSString *db_path)
665
 
{
666
 
        CSPath  *path;
667
 
        char pbms_path[PATH_MAX];
668
 
        
669
 
        enter_();
670
 
        
671
 
        push_(db_path); 
672
 
        cs_strcpy(PATH_MAX, pbms_path, db_path->getCString());
673
 
        release_(db_path);
674
 
        
675
 
        if (strcmp(cs_last_name_of_path(pbms_path), "pbms")  != 0)
676
 
                exit_();
677
 
                
678
 
        cs_remove_last_name_of_path(pbms_path);
679
 
 
680
 
        path = getSysFile(CSString::newString(pbms_path), BACKUP_TABLE_NAME, MIN_BACKUP_TABLE_FILE_SIZE);
681
 
        push_(path);
682
 
        
683
 
        if (path->exists())
684
 
                path->removeFile();
685
 
        release_(path);
686
 
        
687
 
        exit_();
688
 
}
689