~drizzle-trunk/drizzle/development

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