~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to plugin/pbms/src/table_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) 2008 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
 * Original author: Paul McCullagh
 
20
 * Continued development: Barry Leslie
 
21
 *
 
22
 * 2007-05-25
 
23
 *
 
24
 * H&G2JCtL
 
25
 *
 
26
 * Contains the information about a table.
 
27
 *
 
28
 */
 
29
 
 
30
#include "cslib/CSConfig.h"
 
31
 
 
32
#include <stdlib.h>
 
33
#include <stddef.h>
 
34
 
 
35
#include "cslib/CSGlobal.h"
 
36
#include "cslib/CSLog.h"
 
37
#include "cslib/CSPath.h"
 
38
#include "cslib/CSStrUtil.h"
 
39
 
 
40
#include "database_ms.h"
 
41
#include "open_table_ms.h"
 
42
 
 
43
MSTable::MSTable():
 
44
CSSharedRefObject(),
 
45
myTableName(NULL),
 
46
myTableID(0),
 
47
myDatabase(NULL),
 
48
iTableFileSize(0),
 
49
iTableHeadSize(0),
 
50
iFreeList(0),
 
51
iToDelete(0),
 
52
iTabDeleteTime(0),
 
53
iTabTempLogID(0),
 
54
iTabTempLogOffset(0)
 
55
{
 
56
}
 
57
 
 
58
MSTable::~MSTable()
 
59
{
 
60
        if (myTableName)
 
61
                myTableName->release();
 
62
}
 
63
 
 
64
#define MS_DELETE_MARK          "#DEL#"
 
65
#define MS_DELETE_MARK_LEN      5
 
66
 
 
67
CSPath *MSTable::getTableFile(const char *table_name, bool to_delete)
 
68
{
 
69
        char file_name[MS_TABLE_NAME_SIZE + 50];
 
70
 
 
71
        if ((table_name && to_delete) || iToDelete) {
 
72
                cs_strcpy(MS_TABLE_NAME_SIZE + 50, file_name, "bs-logs");
 
73
                // Make sure it exists
 
74
                cs_add_dir_char(MS_TABLE_NAME_SIZE + 50, file_name);
 
75
        }
 
76
        else
 
77
                *file_name = 0;
 
78
        if (table_name)
 
79
                cs_strcat(MS_TABLE_NAME_SIZE + 50, file_name, table_name);
 
80
        else {
 
81
                cs_strcat(MS_TABLE_NAME_SIZE + 50, file_name, myTableName->getCString());
 
82
                if (iToDelete) {
 
83
                        char *str = file_name + strlen(file_name) - MS_DELETE_MARK_LEN;
 
84
                        
 
85
                        while (str > file_name) {
 
86
                                if (strncmp(str, MS_DELETE_MARK, MS_DELETE_MARK_LEN) == 0) {
 
87
                                        *str = 0;
 
88
                                        break;
 
89
                                }
 
90
                                str--;
 
91
                        }
 
92
                }
 
93
        }
 
94
        cs_strcat(MS_TABLE_NAME_SIZE + 50, file_name, "-");
 
95
        cs_strcat(MS_TABLE_NAME_SIZE + 50, file_name, myTableID);
 
96
        cs_strcat(MS_TABLE_NAME_SIZE + 50, file_name, ".bst");
 
97
 
 
98
        return CSPath::newPath(RETAIN(myDatabase->myDatabasePath), file_name);
 
99
}
 
100
 
 
101
CSPath *MSTable::getTableFile()
 
102
{
 
103
        return getTableFile(NULL, false);
 
104
}
 
105
 
 
106
CSFile *MSTable::openTableFile()
 
107
{
 
108
        CSPath  *path;
 
109
        CSFile  *fh;
 
110
 
 
111
        enter_();
 
112
        path = getTableFile();
 
113
        push_(path);
 
114
        fh = iTableFileSize ? path->openFile(CSFile::DEFAULT) : path->openFile(CSFile::CREATE);
 
115
        push_(fh);
 
116
        if (!iTableHeadSize) {
 
117
                MSTableHeadRec tab_head;
 
118
 
 
119
                lock_(this);
 
120
                /* Check again after locking: */
 
121
                if (!iTableHeadSize) {
 
122
                        size_t rem;
 
123
 
 
124
                        if (fh->read(&tab_head, 0, offsetof(MSTableHeadRec, th_reserved_4), 0) < offsetof(MSTableHeadRec, th_reserved_4)) {
 
125
                                CS_SET_DISK_4(tab_head.th_magic_4, MS_TABLE_FILE_MAGIC);
 
126
                                CS_SET_DISK_2(tab_head.th_version_2, MS_TABLE_FILE_VERSION);
 
127
                                CS_SET_DISK_2(tab_head.th_head_size_2, MS_TABLE_FILE_HEAD_SIZE);
 
128
                                CS_SET_DISK_8(tab_head.th_free_list_8, 0);
 
129
                                CS_SET_DISK_4(tab_head.th_del_time_4, 0);
 
130
                                CS_SET_DISK_4(tab_head.th_temp_log_id_4, 0);
 
131
                                CS_SET_DISK_4(tab_head.th_temp_log_offset_4, 0);
 
132
                                CS_SET_DISK_4(tab_head.th_reserved_4, 0);
 
133
                                fh->write(&tab_head, 0, sizeof(MSTableHeadRec));
 
134
                        }
 
135
                        
 
136
                        /* Check the file header: */
 
137
                        if (CS_GET_DISK_4(tab_head.th_magic_4) != MS_TABLE_FILE_MAGIC)
 
138
                                CSException::throwFileError(CS_CONTEXT, path->getString(), CS_ERR_BAD_HEADER_MAGIC);
 
139
                        if (CS_GET_DISK_2(tab_head.th_version_2) > MS_TABLE_FILE_VERSION)
 
140
                                CSException::throwFileError(CS_CONTEXT, path->getString(), CS_ERR_VERSION_TOO_NEW);
 
141
 
 
142
                        /* Load the header details: */
 
143
                        iFreeList = CS_GET_DISK_8(tab_head.th_free_list_8);
 
144
                        iTableHeadSize = CS_GET_DISK_2(tab_head.th_head_size_2);
 
145
                        iTabDeleteTime = CS_GET_DISK_4(tab_head.th_del_time_4);
 
146
                        iTabTempLogID = CS_GET_DISK_4(tab_head.th_temp_log_id_4);
 
147
                        iTabTempLogOffset = CS_GET_DISK_4(tab_head.th_temp_log_offset_4);
 
148
 
 
149
                        /* Round file size up to a header boundary: */
 
150
                        if (iTableFileSize < iTableHeadSize)
 
151
                                iTableFileSize = iTableHeadSize;
 
152
                        if ((rem = (iTableFileSize - iTableHeadSize) % sizeof(MSTableBlobRec)))
 
153
                                iTableFileSize += sizeof(MSTableBlobRec) - rem;
 
154
                }
 
155
                unlock_(this);
 
156
        }
 
157
        pop_(fh);
 
158
        release_(path);
 
159
        return_(fh);
 
160
}
 
161
 
 
162
void MSTable::prepareToDelete()
 
163
{
 
164
        MSOpenTable     *otab;
 
165
        uint32_t                delete_time = 0;
 
166
 
 
167
        enter_();
 
168
        iToDelete = true;
 
169
        otab = MSOpenTable::newOpenTable(NULL);
 
170
        push_(otab);
 
171
        otab->myTableFile = openTableFile();
 
172
        if (iTabTempLogID) {
 
173
                MSTempLogFile           *log;
 
174
                MSTempLogItemRec        log_item;
 
175
 
 
176
                log = myDatabase->openTempLogFile(iTabTempLogID, NULL, NULL);
 
177
                if (log) {
 
178
                        push_(log);
 
179
                        if (log->read(&log_item, iTabTempLogOffset, sizeof(MSTempLogItemRec), 0) == sizeof(MSTempLogItemRec)) {
 
180
                                delete_time = CS_GET_DISK_4(log_item.ti_time_4);
 
181
                                if (delete_time != iTabDeleteTime)
 
182
                                        delete_time = 0;
 
183
                        }
 
184
                        release_(log);
 
185
                }
 
186
        }
 
187
 
 
188
        if (!delete_time) {
 
189
                MSTableHeadRec tab_head;
 
190
 
 
191
                myDatabase->queueForDeletion(otab, MS_TL_TABLE_REF, myTableID, 0, 0, &iTabTempLogID, &iTabTempLogOffset, &iTabDeleteTime);
 
192
                CS_SET_DISK_4(tab_head.th_del_time_4, iTabDeleteTime);
 
193
                CS_SET_DISK_4(tab_head.th_temp_log_id_4, iTabTempLogID);
 
194
                CS_SET_DISK_4(tab_head.th_temp_log_offset_4, iTabTempLogOffset);
 
195
                otab->myTableFile->write(&tab_head.th_del_time_4, offsetof(MSTableHeadRec, th_del_time_4), 12);
 
196
        }
 
197
 
 
198
        release_(otab);
 
199
        exit_();
 
200
}
 
201
 
 
202
uint64_t MSTable::findBlobHandle(MSOpenTable *otab, uint32_t repo_id, uint64_t file_offset, uint64_t size, uint16_t head_size, uint32_t auth_code)
 
203
{
 
204
        uint64_t                        blob_id = 0;
 
205
        off64_t                 offset = iTableHeadSize;
 
206
        MSTableBlobRec  blob;
 
207
        enter_();
 
208
        lock_(this);
 
209
 
 
210
        while (offset < iTableFileSize && !blob_id) {
 
211
                otab->myTableFile->read(&blob, offset, sizeof(MSTableBlobRec), sizeof(MSTableBlobRec));
 
212
                 if (   (CS_GET_DISK_1(blob.tb_status_1) == 1) &&
 
213
                                (CS_GET_DISK_3(blob.tb_repo_id_3) == repo_id) &&
 
214
                                (CS_GET_DISK_6(blob.tb_offset_6) == file_offset) &&
 
215
                                (CS_GET_DISK_6(blob.tb_size_6) == size) &&
 
216
                                (CS_GET_DISK_2(blob.tb_header_size_2) == head_size) &&
 
217
                                (CS_GET_DISK_4(blob.tb_auth_code_4) == auth_code)       ) {
 
218
                                
 
219
                        blob_id = offset;
 
220
                }
 
221
                offset += sizeof(MSTableBlobRec);
 
222
        }
 
223
        unlock_(this);
 
224
        return_(blob_id);
 
225
}
 
226
 
 
227
uint64_t MSTable::createBlobHandle(MSOpenTable *otab, uint32_t repo_id, uint64_t file_offset, uint64_t size, uint16_t head_size, uint32_t auth_code)
 
228
{
 
229
        uint64_t                        blob_id;
 
230
        MSTableBlobRec  blob;
 
231
 
 
232
        enter_();
 
233
        lock_(this);
 
234
        if (iFreeList) {
 
235
                MSTableFreeBlobRec      freeb;
 
236
                MSTableHeadRec          tab_head;
 
237
 
 
238
                blob_id = iFreeList;
 
239
                otab->myTableFile->read(&freeb, iFreeList, sizeof(MSTableFreeBlobRec), sizeof(MSTableFreeBlobRec));
 
240
                iFreeList = CS_GET_DISK_6(freeb.tf_next_6);
 
241
                CS_SET_DISK_8(tab_head.th_free_list_8, iFreeList);
 
242
                otab->myTableFile->write(&tab_head.th_free_list_8, offsetof(MSTableHeadRec, th_free_list_8), 8);
 
243
        }
 
244
        else {
 
245
                blob_id = iTableFileSize;
 
246
                iTableFileSize += sizeof(MSTableBlobRec);
 
247
        }
 
248
        unlock_(this);
 
249
 
 
250
        CS_SET_DISK_1(blob.tb_status_1, 1);
 
251
        CS_SET_DISK_3(blob.tb_repo_id_3, repo_id);
 
252
        CS_SET_DISK_6(blob.tb_offset_6, file_offset);
 
253
        CS_SET_DISK_6(blob.tb_size_6, size);
 
254
        CS_SET_DISK_2(blob.tb_header_size_2, head_size);
 
255
        CS_SET_DISK_4(blob.tb_auth_code_4, auth_code);
 
256
        otab->myTableFile->write(&blob, blob_id, sizeof(MSTableBlobRec));
 
257
 
 
258
        return_(blob_id);
 
259
}
 
260
 
 
261
void MSTable::setBlobHandle(MSOpenTable *otab, uint64_t blob_id, uint32_t repo_id, uint64_t file_offset, uint64_t size, uint16_t head_size, uint32_t auth_code)
 
262
{
 
263
        MSTableBlobRec  blob;
 
264
 
 
265
        if (!otab->myTableFile && !otab->isNotATable)
 
266
                otab->myTableFile = openTableFile();
 
267
                
 
268
        CS_SET_DISK_1(blob.tb_status_1, 1);
 
269
        CS_SET_DISK_3(blob.tb_repo_id_3, repo_id);
 
270
        CS_SET_DISK_6(blob.tb_offset_6, file_offset);
 
271
        CS_SET_DISK_6(blob.tb_size_6, size);
 
272
        CS_SET_DISK_2(blob.tb_header_size_2, head_size);
 
273
        CS_SET_DISK_4(blob.tb_auth_code_4, auth_code);
 
274
        otab->myTableFile->write(&blob, blob_id, sizeof(MSTableBlobRec));
 
275
}
 
276
 
 
277
void MSTable::updateBlobHandle(MSOpenTable *otab, uint64_t blob_id, uint32_t repo_id, uint64_t offset, uint16_t head_size)
 
278
{
 
279
        MSTableBlobRec  blob;
 
280
 
 
281
        if (!otab->myTableFile && !otab->isNotATable)
 
282
                otab->myTableFile = openTableFile();
 
283
                
 
284
        CS_SET_DISK_3(blob.tb_repo_id_3, repo_id);
 
285
        CS_SET_DISK_6(blob.tb_offset_6, offset);
 
286
        if (head_size) {
 
287
                CS_SET_DISK_2(blob.tb_header_size_2, head_size);
 
288
                otab->myTableFile->write(&blob.tb_repo_id_3, blob_id + offsetof(MSTableBlobRec, tb_repo_id_3), 11);
 
289
        }
 
290
        else
 
291
                otab->myTableFile->write(&blob.tb_repo_id_3, blob_id + offsetof(MSTableBlobRec, tb_repo_id_3), 9);
 
292
}
 
293
 
 
294
bool MSTable::readBlobHandle(MSOpenTable *otab, uint64_t blob_id, uint32_t *auth_code,
 
295
        uint32_t *repo_id, uint64_t *offset, uint64_t *data_size, uint16_t *head_size, bool throw_error)
 
296
{
 
297
        MSTableBlobRec  blob;
 
298
        uint32_t                        ac;
 
299
 
 
300
        if (!otab->myTableFile && !otab->isNotATable)
 
301
                otab->myTableFile = openTableFile();
 
302
 
 
303
        otab->myTableFile->read(&blob, blob_id, sizeof(MSTableBlobRec), sizeof(MSTableBlobRec));
 
304
        if (!(*repo_id = CS_GET_DISK_3(blob.tb_repo_id_3))) {
 
305
                if (throw_error)
 
306
                        CSException::throwException(CS_CONTEXT, MS_ERR_NOT_FOUND, "BLOB has already been freed");
 
307
                return false;
 
308
        }
 
309
        *offset = CS_GET_DISK_6(blob.tb_offset_6);
 
310
        *data_size = CS_GET_DISK_6(blob.tb_size_6);
 
311
        *head_size = CS_GET_DISK_2(blob.tb_header_size_2);
 
312
        ac = CS_GET_DISK_4(blob.tb_auth_code_4);
 
313
        if (!*auth_code)
 
314
                *auth_code = ac;
 
315
        else if (*auth_code != ac) {
 
316
                if (throw_error)
 
317
                        CSException::throwException(CS_CONTEXT, MS_ERR_AUTH_FAILED, "Invalid BLOB identifier");
 
318
                return false;
 
319
        }
 
320
        return true;
 
321
}
 
322
 
 
323
void MSTable::freeBlobHandle(MSOpenTable *otab, uint64_t blob_id, uint32_t repo_id, uint64_t file_offset, uint32_t auth_code)
 
324
{
 
325
        MSTableBlobRec          blob;
 
326
        MSTableFreeBlobPtr      fblob = (MSTableFreeBlobPtr) &blob;
 
327
        MSTableHeadRec          tab_head;
 
328
 
 
329
        enter_();
 
330
        otab->openForReading();
 
331
        otab->myTableFile->read(&blob, blob_id, sizeof(MSTableBlobRec), sizeof(MSTableBlobRec));
 
332
        if (CS_GET_DISK_1(blob.tb_status_1) == 1 &&
 
333
                CS_GET_DISK_3(blob.tb_repo_id_3) == repo_id &&
 
334
                CS_GET_DISK_6(blob.tb_offset_6) == file_offset &&
 
335
                CS_GET_DISK_4(blob.tb_auth_code_4) == auth_code) {
 
336
                lock_(this);
 
337
                memset(&blob, 0, sizeof(MSTableBlobRec));
 
338
                CS_SET_DISK_6(fblob->tf_next_6, iFreeList);
 
339
                iFreeList = blob_id;
 
340
                CS_SET_DISK_8(tab_head.th_free_list_8, iFreeList);
 
341
                otab->myTableFile->write(&blob, blob_id, sizeof(MSTableBlobRec));
 
342
                otab->myTableFile->write(&tab_head.th_free_list_8, offsetof(MSTableHeadRec, th_free_list_8), 8);
 
343
                unlock_(this);
 
344
        }
 
345
        exit_();
 
346
}
 
347
 
 
348
CSObject *MSTable::getKey()
 
349
{
 
350
        return (CSObject *) myTableName;
 
351
}
 
352
 
 
353
int MSTable::compareKey(CSObject *key)
 
354
{
 
355
        return myTableName->compare((CSString *) key);
 
356
}
 
357
 
 
358
uint32_t MSTable::hashKey()
 
359
{
 
360
        return myTableName->hashKey();
 
361
}
 
362
 
 
363
CSString *MSTable::getTableName()
 
364
{
 
365
        return myTableName;
 
366
}
 
367
 
 
368
void MSTable::getDeleteInfo(uint32_t *log, uint32_t *offs, time_t *tim)
 
369
{
 
370
        if (!iTableHeadSize) {
 
371
                CSFile *fh;
 
372
 
 
373
                fh = openTableFile();
 
374
                fh->release();
 
375
        }
 
376
 
 
377
        *log = iTabTempLogID;
 
378
        *offs = iTabTempLogOffset;
 
379
        *tim = iTabDeleteTime; 
 
380
}
 
381
 
 
382
MSTable *MSTable::newTable(uint32_t tab_id, CSString *tab_name, MSDatabase *db, off64_t file_size, bool to_delete)
 
383
{
 
384
        MSTable *tab;
 
385
 
 
386
        if (!(tab = new MSTable())) {
 
387
                tab_name->release();
 
388
                CSException::throwOSError(CS_CONTEXT, ENOMEM);
 
389
        }
 
390
        if (to_delete) {
 
391
                /* Create a new table name: */
 
392
                char name_buffer[MS_TABLE_NAME_SIZE + 40];
 
393
                
 
394
                cs_strcpy(MS_TABLE_NAME_SIZE + 40, name_buffer, tab_name->getCString());
 
395
                cs_strcat(MS_TABLE_NAME_SIZE + 40, name_buffer, MS_DELETE_MARK);
 
396
                cs_strcat(MS_TABLE_NAME_SIZE + 40, name_buffer, tab_id);
 
397
                tab_name->release();
 
398
                tab_name = CSString::newString(name_buffer);
 
399
        }
 
400
 
 
401
        tab->myTableID = tab_id;
 
402
        tab->myTableName = tab_name;
 
403
        tab->myDatabase = db;
 
404
        tab->iTableFileSize = file_size;
 
405
        tab->iToDelete = to_delete;
 
406
        return tab;
 
407
}
 
408
 
 
409
MSTable *MSTable::newTable(uint32_t tab_id, const char *name, MSDatabase *db, off64_t file_size, bool to_delete)
 
410
{
 
411
        return newTable(tab_id, CSString::newString(name), db, file_size, to_delete);
 
412
}
 
413
 
 
414