~drizzle-trunk/drizzle/development

« back to all changes in this revision

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

  • Committer: Monty Taylor
  • Date: 2010-07-06 00:44:32 UTC
  • mfrom: (1643.1.13 build)
  • Revision ID: mordred@inaugust.com-20100706004432-843uftc92rc2497l
Merged in PBMS, translation updates, a few build fixes and a few bug fixes.

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