1
/* Copyright (c) 2008 PrimeBase Technologies GmbH, Germany
3
* PrimeBase Media Stream for MySQL
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.
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.
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
19
* Original author: Paul McCullagh
20
* Continued development: Barry Leslie
32
#include <drizzled/common.h>
33
#include <drizzled/session.h>
34
#include <drizzled/table.h>
35
#include <drizzled/field.h>
36
#include <drizzled/field/blob.h>
38
#include <drizzled/message/table.pb.h>
39
#include "drizzled/charset_info.h"
40
#include <drizzled/table_proto.h>
44
#include "cslib/CSConfig.h"
47
#include <sys/types.h>
52
//#include "mysql_priv.h"
55
#include "cslib/CSGlobal.h"
56
#include "cslib/CSStrUtil.h"
60
#include "engine_ms.h"
61
#include "system_table_ms.h"
62
#include "repository_ms.h"
63
#include "database_ms.h"
64
#include "compactor_ms.h"
65
#include "open_table_ms.h"
66
#include "metadata_ms.h"
67
#ifdef HAVE_ALIAS_SUPPORT
71
#include "transaction_ms.h"
73
#include "systab_httpheader_ms.h"
74
#include "systab_dump_ms.h"
75
#include "systab_variable_ms.h"
76
#include "systab_cloud_ms.h"
77
#include "systab_backup_ms.h"
79
#include "systab_enabled_ms.h"
81
#include "discover_ms.h"
82
#include "parameters_ms.h"
84
///* Note: mysql_priv.h messes with new, which caused a crash. */
89
/* Definitions for PBMS table discovery: */
90
//--------------------------------
91
static DT_FIELD_INFO pbms_repository_info[]=
93
#ifdef HAVE_ALIAS_SUPPORT
94
{"Blob_alias", BLOB_ALIAS_LENGTH, NULL, MYSQL_TYPE_VARCHAR, &my_charset_utf8_bin, 0, "The BLOB alias"},
96
{"Repository_id", NULL, NULL, MYSQL_TYPE_LONG, NULL, NOT_NULL_FLAG, "The repository file number"},
97
{"Repo_blob_offset", NULL, NULL, MYSQL_TYPE_LONGLONG, NULL, NOT_NULL_FLAG, "The offset of the BLOB in the repository file"},
98
{"Blob_size", NULL, NULL, MYSQL_TYPE_LONGLONG, NULL, NOT_NULL_FLAG, "The size of the BLOB in bytes"},
99
{"MD5_Checksum", 32, NULL, MYSQL_TYPE_VARCHAR, system_charset_info, 0, "The MD5 Digest of the BLOB data."},
100
{"Head_size", NULL, NULL, MYSQL_TYPE_SHORT, NULL, NOT_NULL_FLAG | UNSIGNED_FLAG, "The size of the BLOB header - proceeds the BLOB data"},
101
{"Access_code", NULL, NULL, MYSQL_TYPE_LONG, NULL, NOT_NULL_FLAG, "The 4-byte authorisation code required to access the BLOB - part of the BLOB URL"},
102
{"Creation_time", NULL, NULL, MYSQL_TYPE_TIMESTAMP, NULL, NOT_NULL_FLAG, "The time the BLOB was created"},
103
{"Last_ref_time", NULL, NULL, MYSQL_TYPE_TIMESTAMP, NULL, 0, "The last time the BLOB was referenced"},
104
{"Last_access_time", NULL, NULL, MYSQL_TYPE_TIMESTAMP, NULL, 0, "The last time the BLOB was accessed (read)"},
105
{"Access_count", NULL, NULL, MYSQL_TYPE_LONG, NULL, NOT_NULL_FLAG, "The count of the number of times the BLOB has been read"},
106
{NULL,NULL, NULL, MYSQL_TYPE_STRING,NULL, 0, NULL}
110
static DT_KEY_INFO pbms_repository_keys[]=
112
{"pbms_repository_pk", PRI_KEY_FLAG, {"Repository_id", "Repo_blob_offset", NULL}},
117
static DT_FIELD_INFO pbms_metadata_info[]=
119
{"Repository_id", NULL, NULL, MYSQL_TYPE_LONG, NULL, NOT_NULL_FLAG, "The repository file number"},
120
{"Repo_blob_offset", NULL, NULL, MYSQL_TYPE_LONGLONG, NULL, NOT_NULL_FLAG, "The offset of the BLOB in the repository file"},
121
{"Name", MS_META_NAME_SIZE, NULL, MYSQL_TYPE_VARCHAR, &UTF8_CHARSET, NOT_NULL_FLAG, "Metadata name"},
122
{"Value", MS_META_VALUE_SIZE, NULL, MYSQL_TYPE_VARCHAR, &UTF8_CHARSET, NOT_NULL_FLAG, "Metadata value"},
123
{NULL, NULL, NULL, MYSQL_TYPE_STRING, NULL, 0, NULL}
127
static DT_KEY_INFO pbms_metadata_keys[]=
129
{"pbms_metadata_pk", PRI_KEY_FLAG, {"Repository_id", "Repo_blob_offset", NULL}},
135
#ifdef HAVE_ALIAS_SUPPORT
136
static DT_FIELD_INFO pbms_alias_info[]=
138
{"Repository_id", NULL, NULL, MYSQL_TYPE_LONG, NULL, NOT_NULL_FLAG, "The repository file number"},
139
{"Repo_blob_offset", NULL, NULL, MYSQL_TYPE_LONGLONG, NULL, NOT_NULL_FLAG, "The offset of the BLOB in the repository file"},
140
{"Blob_alias", BLOB_ALIAS_LENGTH, NULL, MYSQL_TYPE_VARCHAR, &my_charset_utf8_bin, NOT_NULL_FLAG, "The BLOB alias"},
141
{NULL,NULL, NULL, MYSQL_TYPE_STRING,NULL, 0, NULL}
144
static DT_KEY_INFO pbms_alias_keys[]=
146
{"pbms_alias_pk", PRI_KEY_FLAG, {"Repository_id", "Repo_blob_offset", NULL}},
151
static DT_FIELD_INFO pbms_blobs_info[]=
153
{"Repository_id", NULL, NULL, MYSQL_TYPE_LONG, NULL, NOT_NULL_FLAG, "The repository file number"},
154
{"Repo_blob_offset", NULL, NULL, MYSQL_TYPE_LONGLONG, NULL, NOT_NULL_FLAG, "The offset of the BLOB in the repository file"},
155
{"Blob_data", NULL, NULL, MYSQL_TYPE_LONG_BLOB, &my_charset_bin, NOT_NULL_FLAG, "The data of this BLOB"},
156
{NULL,NULL, NULL, MYSQL_TYPE_STRING,NULL, 0, NULL}
160
static DT_KEY_INFO pbms_blobs_keys[]=
162
{"pbms_blobs_pk", PRI_KEY_FLAG, {"Repository_id", "Repo_blob_offset", NULL}},
167
static DT_FIELD_INFO pbms_reference_info[]=
169
{"Table_name", MS_TABLE_NAME_SIZE, NULL, MYSQL_TYPE_STRING, system_charset_info, 0, "The name of the referencing table"},
170
{"Column_ordinal", NULL, NULL, MYSQL_TYPE_LONG, NULL, 0, "The column ordinal of the referencing field"},
171
{"Blob_id", NULL, NULL, MYSQL_TYPE_LONGLONG, NULL, NOT_NULL_FLAG, "The BLOB reference number - part of the BLOB URL"},
172
{"Blob_url", PBMS_BLOB_URL_SIZE, NULL, MYSQL_TYPE_VARCHAR, system_charset_info, 0, "The BLOB URL for HTTP GET access"},
173
{"Repository_id", NULL, NULL, MYSQL_TYPE_LONG, NULL, NOT_NULL_FLAG, "The repository file number of the BLOB"},
174
{"Repo_blob_offset",NULL, NULL, MYSQL_TYPE_LONGLONG, NULL, NOT_NULL_FLAG, "The offset in the repository file"},
175
{"Blob_size", NULL, NULL, MYSQL_TYPE_LONGLONG, NULL, NOT_NULL_FLAG, "The size of the BLOB in bytes"},
176
{"Deletion_time", NULL, NULL, MYSQL_TYPE_TIMESTAMP, NULL, 0, "The time the BLOB was deleted"},
177
{"Remove_in", NULL, NULL, MYSQL_TYPE_LONG, NULL, 0, "The number of seconds before the reference/BLOB is removed perminently"},
178
{"Temp_log_id", NULL, NULL, MYSQL_TYPE_LONG, NULL, 0, "Temporary log number of the referencing deletion entry"},
179
{"Temp_log_offset", NULL, NULL, MYSQL_TYPE_LONGLONG, NULL, 0, "Temporary log offset of the referencing deletion entry"},
180
{NULL,NULL, NULL, MYSQL_TYPE_STRING,NULL, 0, NULL}
184
static DT_KEY_INFO pbms_reference_keys[]=
186
{"pbms_reference_pk", PRI_KEY_FLAG, {"Table_name", "Blob_id", NULL}},
187
{"pbms_reference_k", MULTIPLE_KEY_FLAG, {"Repository_id", "Repo_blob_offset", NULL}},
193
typedef enum { SYS_REP = 0,
199
#ifdef HAVE_ALIAS_SUPPORT
208
SYS_UNKNOWN} SysTableType;
210
static const char *sysTableNames[] = {
216
METADATA_HEADER_NAME,
217
#ifdef HAVE_ALIAS_SUPPORT
220
VARIABLES_TABLE_NAME,
229
static INTERRNAL_TABLE_INFO pbms_internal_tables[]=
232
{ false, sysTableNames[SYS_REP],pbms_repository_info, pbms_repository_keys},
233
{ false, sysTableNames[SYS_REF], pbms_reference_info, pbms_reference_keys},
234
{ false, sysTableNames[SYS_BLOB], pbms_blobs_info, pbms_blobs_keys},
235
{ false, sysTableNames[SYS_DUMP], pbms_dump_info, pbms_dump_keys},
236
{ false, sysTableNames[SYS_META], pbms_metadata_info, pbms_metadata_keys},
237
{ false, sysTableNames[SYS_HTTP], pbms_metadata_headers_info, pbms_metadata_headers_keys},
238
#ifdef HAVE_ALIAS_SUPPORT
239
{ false, sysTableNames[SYS_ALIAS], pbms_alias_info, pbms_alias_keys},
241
{ false, sysTableNames[SYS_VARIABLE], pbms_variable_info, pbms_variable_keys},
242
{ true, sysTableNames[SYS_CLOUD], pbms_cloud_info, pbms_cloud_keys},
243
{ true, sysTableNames[SYS_BACKUP], pbms_backup_info, pbms_backup_keys},
245
{ true, sysTableNames[SYS_ENABLED], pbms_enabled_info, pbms_enabled_keys},
248
{ false, sysTableNames[SYS_REP], pbms_repository_info, NULL},
249
{ false, sysTableNames[SYS_REF], pbms_reference_info, NULL},
250
{ false, sysTableNames[SYS_BLOB], pbms_blobs_info, NULL},
251
{ false, sysTableNames[SYS_DUMP], pbms_dump_info, NULL},
252
{ false, sysTableNames[SYS_META], pbms_metadata_info, NULL},
253
{ false, sysTableNames[SYS_HTTP], pbms_metadata_headers_info, NULL},
254
#ifdef HAVE_ALIAS_SUPPORT
255
{ false, sysTableNames[SYS_ALIAS], pbms_alias_info, NULL},
257
{ false, sysTableNames[SYS_VARIABLE], pbms_variable_info, NULL},
258
{ true, sysTableNames[SYS_CLOUD], pbms_cloud_info, NULL},
259
{ true, sysTableNames[SYS_BACKUP], pbms_backup_info, NULL},
261
{ true, sysTableNames[SYS_ENABLED], pbms_enabled_info, NULL},
265
{ false, NULL, NULL, NULL}
269
//--------------------------
270
static SysTableType pbms_systable_type(const char *table)
274
while ((i < SYS_UNKNOWN) && strcasecmp(table, sysTableNames[i])) i++;
276
return((SysTableType) i );
279
//--------------------------
280
bool PBMSSystemTables::isSystemTable(bool isPBMS, const char *table)
284
i = pbms_systable_type(table);
286
if (i == SYS_UNKNOWN)
289
return (pbms_internal_tables[i].is_pbms == isPBMS);
292
//--------------------------
295
using namespace drizzled;
298
static int pbms_create_proto_table(const char *engine_name, const char *name, DT_FIELD_INFO *info, DT_KEY_INFO *keys, drizzled::message::Table &table)
300
message::Table::Field *field;
301
message::Table::Field::FieldConstraints *field_constraints;
302
message::Table::Field::StringFieldOptions *string_field_options;
303
message::Table::TableOptions *table_options;
305
table.set_name(name);
306
table.set_name(name);
307
table.set_type(message::Table::STANDARD);
308
table.mutable_engine()->set_name(engine_name);
310
table_options = table.mutable_options();
311
table_options->set_collation_id(my_charset_utf8_bin.number);
312
table_options->set_collation(my_charset_utf8_bin.name);
314
while (info->field_name) {
315
field= table.add_field();
317
field->set_name(info->field_name);
319
field->set_comment(info->comment);
321
field_constraints= field->mutable_constraints();
322
if (info->field_flags & NOT_NULL_FLAG)
323
field_constraints->set_is_nullable(false);
325
field_constraints->set_is_nullable(true);
327
if (info->field_flags & UNSIGNED_FLAG)
328
field_constraints->set_is_unsigned(true);
330
field_constraints->set_is_unsigned(false);
332
switch (info->field_type) {
333
case DRIZZLE_TYPE_VARCHAR:
334
string_field_options = field->mutable_string_options();
336
field->set_type(message::Table::Field::VARCHAR);
337
string_field_options->set_length(info->field_length);
338
if (info->field_charset) {
339
string_field_options->set_collation(info->field_charset->name);
340
string_field_options->set_collation_id(info->field_charset->number);
344
case DRIZZLE_TYPE_LONG:
345
field->set_type(message::Table::Field::INTEGER);
348
case DRIZZLE_TYPE_DOUBLE:
349
field->set_type(message::Table::Field::DOUBLE);
352
case DRIZZLE_TYPE_LONGLONG:
353
field->set_type(message::Table::Field::BIGINT);
356
case DRIZZLE_TYPE_TIMESTAMP:
357
field->set_type(message::Table::Field::TIMESTAMP);
360
case DRIZZLE_TYPE_BLOB:
361
field->set_type(message::Table::Field::BLOB);
362
if (info->field_charset) {
363
string_field_options = field->mutable_string_options();
364
string_field_options->set_collation(info->field_charset->name);
365
string_field_options->set_collation_id(info->field_charset->number);
377
while (keys->key_name) {
378
// To be done later. (maybe)
385
#define TABLE drizzled::Table
386
#define Field drizzled::Field
388
int PBMSSystemTables::getSystemTableInfo(const char *name, drizzled::message::Table &table)
392
while (pbms_internal_tables[i].name) {
393
if (strcasecmp(name, pbms_internal_tables[i].name) == 0){
394
err = pbms_create_proto_table("PBMS", name, pbms_internal_tables[i].info, pbms_internal_tables[i].keys, table);
403
void PBMSSystemTables::getSystemTableNames(bool isPBMS, std::set<std::string> &set_of_names)
407
while (pbms_internal_tables[i].name) {
408
if ( isPBMS == pbms_internal_tables[i].is_pbms){
409
set_of_names.insert(pbms_internal_tables[i].name);
417
//--------------------------
418
static bool pbms_database_follder_exists( const char *db)
420
struct stat stat_info;
426
cs_strcpy(PATH_MAX, path, ms_my_get_mysql_home_path());
427
cs_add_name_to_path(PATH_MAX, path, db);
429
if (stat(path, &stat_info) == 0)
430
return(stat_info.st_mode & S_IFDIR);
435
int pbms_discover_system_tables(handlerton *hton, THD* thd, const char *db, const char *name, uchar **frmblob, size_t *frmlen)
438
bool is_pbms = false;
440
// Check that the database exists!
441
if (!pbms_database_follder_exists(db))
444
is_pbms = (strcmp(db, "pbms") == 0);
447
while (pbms_internal_tables[i].name) {
448
if ((!strcasecmp(name, pbms_internal_tables[i].name)) && ( is_pbms == pbms_internal_tables[i].is_pbms)){
449
err = ms_create_table_frm(hton, thd, db, name, pbms_internal_tables[i].info, pbms_internal_tables[i].keys, frmblob, frmlen);
459
// Transfer any physical PBMS ststem tables to another database.
460
void PBMSSystemTables::transferSystemTables(MSDatabase *dst_db, MSDatabase *src_db)
466
MSHTTPHeaderTable::transferTable(RETAIN(dst_db), RETAIN(src_db));
467
MSVariableTable::transferTable(RETAIN(dst_db), RETAIN(src_db));
468
MSCloudTable::transferTable(RETAIN(dst_db), RETAIN(src_db));
469
MSBackupTable::transferTable(RETAIN(dst_db), RETAIN(src_db));
477
void PBMSSystemTables::removeSystemTables(CSString *db_path)
482
MSHTTPHeaderTable::removeTable(RETAIN(db_path));
483
MSVariableTable::removeTable(RETAIN(db_path));
484
MSCloudTable::removeTable(RETAIN(db_path));
485
MSBackupTable::removeTable(RETAIN(db_path));
492
void PBMSSystemTables::loadSystemTables(MSDatabase *db)
497
for ( int i = 0; i < 4; i++) {
501
MSHTTPHeaderTable::loadTable(RETAIN(db));
504
MSCloudTable::loadTable(RETAIN(db));
507
MSBackupTable::loadTable(RETAIN(db));
510
// Variable must be loaded after cloud and backup info
511
// incase BLOB recovery is required.
512
MSVariableTable::loadTable(RETAIN(db));
520
self->logException();
530
// Dump all the system tables into one buffer.
533
CSDiskValue1 tab_id_1;
534
CSDiskValue4 tab_version_4;
535
} DumpHeaderRec, *DumpHeaderPtr;
539
const char *rec_cchars;
540
DumpHeaderPtr dumpHeader;
543
CSStringBuffer *PBMSSystemTables::dumpSystemTables(MSDatabase *db)
545
CSStringBuffer *sysDump, *tabDump;
546
uint32_t size, pos, tab_version;
552
new_(sysDump, CSStringBuffer());
556
for ( int i = 0; i < 4; i++) {
559
tabDump = MSHTTPHeaderTable::dumpTable(RETAIN(db));
560
tab_id = MSHTTPHeaderTable::tableID;
561
tab_version = MSHTTPHeaderTable::tableVersion;
564
tabDump = MSCloudTable::dumpTable(RETAIN(db));
565
tab_id = MSCloudTable::tableID;
566
tab_version = MSCloudTable::tableVersion;
569
tabDump = MSBackupTable::dumpTable(RETAIN(db));
570
tab_id = MSBackupTable::tableID;
571
tab_version = MSBackupTable::tableVersion;
574
tabDump = MSVariableTable::dumpTable(RETAIN(db)); // Dump the variables table last.
575
tab_id = MSVariableTable::tableID;
576
tab_version = MSVariableTable::tableVersion;
584
size = tabDump->length();
586
// Grow the buffer for the header
587
sysDump->setLength(pos + sizeof(DumpHeaderRec));
589
// Add the dump header
590
d.rec_chars = sysDump->getBuffer(pos);
591
CS_SET_DISK_4(d.dumpHeader->size_4, size);;
592
CS_SET_DISK_1(d.dumpHeader->tab_id_1, tab_id);
593
CS_SET_DISK_4(d.dumpHeader->tab_version_4, tab_version);
595
sysDump->append(tabDump->getBuffer(0), size);
596
pos += size + sizeof(DumpHeaderRec);
607
void PBMSSystemTables::restoreSystemTables(MSDatabase *db, const char *data, size_t size)
609
uint32_t tab_size, tab_version;
616
while ( size >= sizeof(DumpHeaderRec)) {
618
tab_size = CS_GET_DISK_4(d.dumpHeader->size_4);
619
tab_id = CS_GET_DISK_1(d.dumpHeader->tab_id_1);
620
tab_version = CS_GET_DISK_4(d.dumpHeader->tab_version_4);
621
data += sizeof(DumpHeaderRec);
622
size -= sizeof(DumpHeaderRec);
624
if (size < tab_size) {
625
CSException::throwException(CS_CONTEXT, CS_ERR_GENERIC_ERROR, "PBMS system table restore data truncated.");
629
case MSHTTPHeaderTable::tableID:
630
if (MSHTTPHeaderTable::tableVersion == tab_version)
631
MSHTTPHeaderTable::restoreTable(RETAIN(db), data, tab_size);
633
CSException::logException(CS_CONTEXT, MS_ERR_SYSTAB_VERSION, "Restore "METADATA_HEADER_NAME" failed, incompatable table version" );
635
case MSCloudTable::tableID:
636
if (MSCloudTable::tableVersion == tab_version)
637
MSCloudTable::restoreTable(RETAIN(db), data, tab_size);
639
CSException::logException(CS_CONTEXT, MS_ERR_SYSTAB_VERSION, "Restore "CLOUD_TABLE_NAME" failed, incompatable table version" );
641
case MSBackupTable::tableID:
642
if (MSBackupTable::tableVersion == tab_version)
643
MSBackupTable::restoreTable(RETAIN(db), data, tab_size);
645
CSException::logException(CS_CONTEXT, MS_ERR_SYSTAB_VERSION, "Restore "BACKUP_TABLE_NAME" failed, incompatable table version" );
647
case MSVariableTable::tableID:
648
if (MSVariableTable::tableVersion == tab_version)
649
MSVariableTable::restoreTable(RETAIN(db), data, tab_size);
651
CSException::logException(CS_CONTEXT, MS_ERR_SYSTAB_VERSION, "Restore "VARIABLES_TABLE_NAME" failed, incompatable table version" );
661
CSException::logException(CS_CONTEXT, CS_ERR_GENERIC_ERROR, "PBMS trailing garbage in system table restore data being ignored.");
669
* -------------------------------------------------------------------------
673
void MSOpenSystemTable::setNotNullInRecord(Field *field, char *record)
676
record[(uint) (field->null_ptr - (uchar *) field->table->record[0])] &= (uchar) ~field->null_bit;
680
* -------------------------------------------------------------------------
684
MSOpenSystemTable::MSOpenSystemTable(MSSystemTableShare *share, TABLE *table):
691
MSOpenSystemTable::~MSOpenSystemTable()
693
MSSystemTableShare::releaseSystemTable(this);
698
* -------------------------------------------------------------------------
702
MSRepositoryTable::MSRepositoryTable(MSSystemTableShare *share, TABLE *table):
703
MSOpenSystemTable(share, table),
710
//-----------------------
711
MSRepositoryTable::~MSRepositoryTable()
716
iBlobBuffer->release();
719
//-----------------------
720
void MSRepositoryTable::use()
724
//-----------------------
725
void MSRepositoryTable::unuse()
728
iCompactor->resume();
729
iCompactor->release();
733
iRepoFile->release();
737
iBlobBuffer->clear();
741
//-----------------------
742
void MSRepositoryTable::seqScanInit()
748
// Flush all committed transactions to the repository file.
749
MSTransactionManager::flush();
754
new_(iBlobBuffer, CSStringBuffer(20));
755
db = myShare->mySysDatabase;
756
if ((iCompactor = db->getCompactorThread())) {
757
if (iCompactor->isMe(self))
760
iCompactor->retain();
761
iCompactor->suspend();
768
//-----------------------
769
bool MSRepositoryTable::resetScan(bool positioned, uint32_t repo_index)
772
if (iRepoFile && (repo_index != iRepoIndex)) {
773
iRepoFile->release();
777
iRepoIndex = repo_index;
783
MSRepository *repo = NULL;
784
CSSyncVector *repo_list = myShare->mySysDatabase->getRepositoryList();
787
for (; iRepoIndex<repo_list->size(); iRepoIndex++) {
788
if ((repo = (MSRepository *) repo_list->get(iRepoIndex))) {
789
iRepoFile = repo->openRepoFile();
797
iRepoFileSize = repo->getRepoFileSize();
798
if ((!iRepoOffset) || !positioned)
799
iRepoOffset = repo->getRepoHeadSize();
801
iRepoCurrentOffset = iRepoOffset;
806
//-----------------------
807
bool MSRepositoryTable::seqScanNext(char *buf)
811
iRepoCurrentOffset = iRepoOffset;
813
if (returnSubRecord(buf))
817
if ((!iRepoFile) && !MSRepositoryTable::resetScan(false))
820
while (iRepoOffset < iRepoFileSize) {
821
if (returnRecord(buf))
826
iRepoFile->release();
837
//-----------------------
838
int MSRepositoryTable::getRefLen()
840
return sizeof(iRepoIndex) + sizeof(iRepoOffset);
844
//-----------------------
845
void MSRepositoryTable::seqScanPos(uint8_t *pos)
847
mi_int4store(pos, iRepoIndex); pos +=4;
848
mi_int8store(pos, iRepoCurrentOffset);
851
//-----------------------
852
void MSRepositoryTable::seqScanRead(uint32_t repo, uint64_t offset, char *buf)
854
iRepoOffset = offset;
856
if (!resetScan(true, repo))
862
//-----------------------
863
void MSRepositoryTable::seqScanRead(uint8_t *pos, char *buf)
865
seqScanRead(mi_uint4korr( pos), mi_uint8korr(pos +4), buf);
868
//-----------------------
869
bool MSRepositoryTable::returnRecord(char *buf)
881
lock = iRepoFile->myRepo->getRepoLock(iRepoOffset);
883
if (iRepoFile->read(&blob, iRepoOffset, sizeof(MSBlobHeadRec), 0) < sizeof(MSBlobHeadRec)) {
885
iRepoOffset = iRepoFileSize;
888
head_size = CS_GET_DISK_2(blob.rb_head_size_2);
889
blob_size = CS_GET_DISK_6(blob.rb_blob_repo_size_6);
890
ref_size = CS_GET_DISK_1(blob.rb_ref_size_1);
891
ref_count = CS_GET_DISK_2(blob.rb_ref_count_2);
892
status = CS_GET_DISK_1(blob.rb_status_1);
893
if (ref_count <= 0 || ref_size == 0 ||
894
head_size < iRepoFile->myRepo->getRepoBlobHeadSize() + ref_count * ref_size ||
895
!VALID_BLOB_STATUS(status)) {
896
/* Can't be true. Assume this is garbage! */
902
if (IN_USE_BLOB_STATUS(status)) {
904
if (!returnRow(&blob, buf)) {
905
/* This record may not have had any data of interest. */
909
iRepoOffset += head_size + blob_size;
913
iRepoOffset += head_size + blob_size;
917
//-----------------------
918
bool MSRepositoryTable::returnSubRecord(char *)
923
//-----------------------
924
bool MSRepositoryTable::returnRow(MSBlobHeadPtr blob, char *buf)
926
TABLE *table = mySQLTable;
927
uint8_t storage_type;
928
uint32_t access_count;
929
uint32_t last_access;
931
uint32_t creation_time;
932
uint32_t access_code;
934
uint16_t alias_offset;
938
MY_BITMAP *save_write_set;
942
storage_type = CS_GET_DISK_1(blob->rb_storage_type_1);
943
last_access = CS_GET_DISK_4(blob->rb_last_access_4);
944
access_count = CS_GET_DISK_4(blob->rb_access_count_4);
945
last_ref = CS_GET_DISK_4(blob->rb_last_ref_4);
946
creation_time = CS_GET_DISK_4(blob->rb_create_time_4);
947
head_size = CS_GET_DISK_2(blob->rb_head_size_2);
948
blob_size = CS_GET_DISK_6(blob->rb_blob_repo_size_6);
949
access_code = CS_GET_DISK_4(blob->rb_auth_code_4);
950
alias_offset = CS_GET_DISK_2(blob->rb_alias_offset_2);
952
/* ASSERT_COLUMN_MARKED_FOR_WRITE is failing when
954
* But I want to use it! :(
956
save_write_set = table->write_set;
957
table->write_set = NULL;
959
memset(buf, 0xFF, table->s->null_bytes);
960
for (Field **field=GET_TABLE_FIELDS(table) ; *field ; field++) {
963
save = curr_field->ptr;
964
#if MYSQL_VERSION_ID < 50114
965
curr_field->ptr = (byte *) buf + curr_field->offset();
967
curr_field->ptr = (byte *) buf + curr_field->offset(curr_field->table->record[0]);
969
switch (curr_field->field_name[0]) {
971
switch (curr_field->field_name[9]) {
973
ASSERT(strcmp(curr_field->field_name, "Access_code") == 0);
974
curr_field->store(access_code, true);
975
setNotNullInRecord(curr_field, buf);
978
ASSERT(strcmp(curr_field->field_name, "Access_count") == 0);
979
curr_field->store(access_count, true);
980
setNotNullInRecord(curr_field, buf);
985
switch (curr_field->field_name[6]) {
988
ASSERT(strcmp(curr_field->field_name, "Repository_id") == 0);
989
curr_field->store(iRepoFile->myRepo->getRepoID(), true);
990
setNotNullInRecord(curr_field, buf);
993
// Repo_blob_offset BIGINT
994
ASSERT(strcmp(curr_field->field_name, "Repo_blob_offset") == 0);
995
curr_field->store(iRepoOffset, true);
996
setNotNullInRecord(curr_field, buf);
1001
switch (curr_field->field_name[5]) {
1004
ASSERT(strcmp(curr_field->field_name, "Blob_size") == 0);
1005
curr_field->store(blob_size, true);
1006
setNotNullInRecord(curr_field, buf);
1010
ASSERT(strcmp(curr_field->field_name, "Blob_alias") == 0);
1011
#ifdef HAVE_ALIAS_SUPPORT
1013
char blob_alias[BLOB_ALIAS_LENGTH +1];
1017
lock = iRepoFile->myRepo->getRepoLock(iRepoOffset);
1019
rsize = iRepoFile->read(blob_alias, iRepoOffset + alias_offset, BLOB_ALIAS_LENGTH, 0);
1021
blob_alias[rsize] = 0;
1022
curr_field->store(blob_alias, strlen(blob_alias), &my_charset_utf8_general_ci);
1023
setNotNullInRecord(curr_field, buf);
1025
curr_field->store((uint64_t) 0, true);
1028
curr_field->store((uint64_t) 0, true);
1035
case 'M': // MD5_Checksum
1036
if (storage_type == MS_STANDARD_STORAGE) {
1037
char checksum[sizeof(Md5Digest) *2];
1039
ASSERT(strcmp(curr_field->field_name, "MD5_Checksum") == 0);
1040
cs_bin_to_hex(sizeof(Md5Digest) *2, checksum, sizeof(Md5Digest), &(blob->rb_blob_checksum_md5d));
1041
curr_field->store(checksum, sizeof(Md5Digest) *2, system_charset_info);
1042
setNotNullInRecord(curr_field, buf);
1045
curr_field->store((uint64_t) 0, true);
1049
// Head_size SMALLINT UNSIGNED
1050
ASSERT(strcmp(curr_field->field_name, "Head_size") == 0);
1051
curr_field->store(head_size, true);
1052
setNotNullInRecord(curr_field, buf);
1055
// Creation_time TIMESTAMP
1056
ASSERT(strcmp(curr_field->field_name, "Creation_time") == 0);
1057
curr_field->store(ms_my_1970_to_mysql_time(creation_time), true);
1058
setNotNullInRecord(curr_field, buf);
1061
switch (curr_field->field_name[5]) {
1063
// Last_ref_time TIMESTAMP
1064
ASSERT(strcmp(curr_field->field_name, "Last_ref_time") == 0);
1065
curr_field->store(ms_my_1970_to_mysql_time(last_ref), true);
1066
setNotNullInRecord(curr_field, buf);
1069
// Last_access_time TIMESTAMP
1070
ASSERT(strcmp(curr_field->field_name, "Last_access_time") == 0);
1071
curr_field->store(ms_my_1970_to_mysql_time(last_access), true);
1072
setNotNullInRecord(curr_field, buf);
1077
curr_field->ptr = save;
1080
table->write_set = save_write_set;
1085
* -------------------------------------------------------------------------
1088
//-----------------------
1089
MSBlobDataTable::MSBlobDataTable(MSSystemTableShare *share, TABLE *table):MSRepositoryTable(share, table)
1093
//-----------------------
1094
MSBlobDataTable::~MSBlobDataTable()
1098
//-----------------------
1099
bool MSBlobDataTable::returnRow(MSBlobHeadPtr blob, char *buf)
1101
TABLE *table = mySQLTable;
1108
MY_BITMAP *save_write_set;
1110
head_size = CS_GET_DISK_2(blob->rb_head_size_2);
1111
blob_size = CS_GET_DISK_6(blob->rb_blob_repo_size_6);
1112
blob_type = CS_GET_DISK_1(blob->rb_storage_type_1);
1114
/* ASSERT_COLUMN_MARKED_FOR_WRITE is failing when
1116
* But I want to use it! :(
1118
save_write_set = table->write_set;
1119
table->write_set = NULL;
1121
memset(buf, 0xFF, table->s->null_bytes);
1122
for (Field **field=GET_TABLE_FIELDS(table) ; *field ; field++) {
1123
curr_field = *field;
1125
save = curr_field->ptr;
1126
#if MYSQL_VERSION_ID < 50114
1127
curr_field->ptr = (byte *) buf + curr_field->offset();
1129
curr_field->ptr = (byte *) buf + curr_field->offset(curr_field->table->record[0]);
1131
switch (curr_field->field_name[0]) {
1133
switch (curr_field->field_name[6]) {
1135
// Repository_id INT
1136
ASSERT(strcmp(curr_field->field_name, "Repository_id") == 0);
1137
curr_field->store(iRepoFile->myRepo->getRepoID(), true);
1138
setNotNullInRecord(curr_field, buf);
1141
// Repo_blob_offset BIGINT
1142
ASSERT(strcmp(curr_field->field_name, "Repo_blob_offset") == 0);
1143
curr_field->store(iRepoOffset, true);
1144
setNotNullInRecord(curr_field, buf);
1149
// Blob_data LONGBLOB
1150
ASSERT(strcmp(curr_field->field_name, "Blob_data") == 0);
1151
if (blob_size <= 0xFFFFFFF) {
1152
iBlobBuffer->setLength((uint32_t) blob_size);
1153
if (BLOB_IN_REPOSITORY(blob_type)) {
1154
len = iRepoFile->read(iBlobBuffer->getBuffer(0), iRepoOffset + head_size, (size_t) blob_size, 0);
1156
CloudDB *blobCloud = myShare->mySysDatabase->myBlobCloud;
1158
ASSERT(blobCloud != NULL);
1160
MSRepoFile::getBlobKey(blob, &key);
1162
len = blobCloud->cl_getData(&key, iBlobBuffer->getBuffer(0), blob_size);
1164
((Field_blob *) curr_field)->set_ptr(len, (byte *) iBlobBuffer->getBuffer(0));
1165
setNotNullInRecord(curr_field, buf);
1169
curr_field->ptr = save;
1172
table->write_set = save_write_set;
1176
#ifdef HAVE_ALIAS_SUPPORT
1178
* -------------------------------------------------------------------------
1181
bool MSBlobAliasTable::returnRow(MSBlobHeadPtr blob, char *buf)
1183
TABLE *table = mySQLTable;
1186
MY_BITMAP *save_write_set;
1187
uint16_t alias_offset;
1188
char blob_alias[BLOB_ALIAS_LENGTH +1];
1193
alias_offset = CS_GET_DISK_2(blob->rb_alias_offset_2);
1198
lock = iRepoFile->myRepo->getRepoLock(iRepoOffset);
1200
rsize = iRepoFile->read(blob_alias, iRepoOffset + alias_offset, BLOB_ALIAS_LENGTH, 0);
1202
blob_alias[rsize] = 0;
1204
/* ASSERT_COLUMN_MARKED_FOR_WRITE is failing when
1206
* But I want to use it! :(
1208
save_write_set = table->write_set;
1209
table->write_set = NULL;
1211
memset(buf, 0xFF, table->s->null_bytes);
1212
for (Field **field=GET_TABLE_FIELDS(table) ; *field ; field++) {
1213
curr_field = *field;
1215
save = curr_field->ptr;
1216
#if MYSQL_VERSION_ID < 50114
1217
curr_field->ptr = (byte *) buf + curr_field->offset();
1219
curr_field->ptr = (byte *) buf + curr_field->offset(curr_field->table->record[0]);
1221
switch (curr_field->field_name[0]) {
1223
switch (curr_field->field_name[6]) {
1225
// Repository_id INT
1226
ASSERT(strcmp(curr_field->field_name, "Repository_id") == 0);
1227
curr_field->store(iRepoFile->myRepo->getRepoID(), true);
1228
setNotNullInRecord(curr_field, buf);
1231
// Repo_blob_offset BIGINT
1232
ASSERT(strcmp(curr_field->field_name, "Repo_blob_offset") == 0);
1233
curr_field->store(iRepoOffset, true);
1234
setNotNullInRecord(curr_field, buf);
1240
ASSERT(strcmp(curr_field->field_name, "Blob_alias") == 0);
1241
curr_field->store(blob_alias, strlen(blob_alias), &UTF8_CHARSET);
1242
setNotNullInRecord(curr_field, buf);
1246
curr_field->ptr = save;
1249
table->write_set = save_write_set;
1256
* -------------------------------------------------------------------------
1260
MSReferenceTable::MSReferenceTable(MSSystemTableShare *share, TABLE *table):
1261
MSRepositoryTable(share, table),
1266
iRefOpenTable(NULL),
1271
MSReferenceTable::~MSReferenceTable()
1274
cs_free(iRefDataList);
1276
iRefOpenTable->returnToPool();
1278
iRefTempLog->release();
1281
void MSReferenceTable::unuse()
1283
MSRepositoryTable::unuse();
1285
cs_free(iRefDataList);
1286
iRefDataList = NULL;
1289
if (iRefOpenTable) {
1290
iRefOpenTable->returnToPool();
1291
iRefOpenTable = NULL;
1294
iRefTempLog->release();
1300
void MSReferenceTable::seqScanInit()
1302
MSRepositoryTable::seqScanInit();
1307
int MSReferenceTable::getRefLen()
1309
return sizeof(iRefDataUsed) + sizeof(iRefDataPos) + sizeof(iRefCurrentIndex) + sizeof(iRefCurrentOffset);
1312
void MSReferenceTable::seqScanPos(uint8_t *pos)
1314
mi_int4store(pos, iRefCurrentDataPos); pos +=4;
1315
mi_int4store(pos, iRefCurrentDataUsed);pos +=4;
1316
mi_int4store(pos, iRefCurrentIndex); pos +=4;
1317
mi_int8store(pos, iRefCurrentOffset);
1320
void MSReferenceTable::seqScanRead(uint8_t *pos, char *buf)
1322
iRefDataPos = mi_uint4korr( pos); pos +=4;
1323
iRefDataUsed = mi_uint4korr(pos); pos +=4;
1324
iRefBlobRepo = mi_uint4korr(pos); pos +=4;
1325
iRefBlobOffset = mi_uint8korr(pos);
1326
MSRepositoryTable::seqScanRead(iRefBlobRepo, iRefBlobOffset, buf);
1329
bool MSReferenceTable::seqScanNext(char *buf)
1331
iRefCurrentDataPos = iRefDataPos;
1332
iRefCurrentDataUsed = iRefDataUsed;
1334
// Reset the position
1335
return MSRepositoryTable::seqScanNext(buf);
1337
// select * from pbms_reference order by blob_size DESC;
1338
// select * from pbms_reference order by Table_name DESC;
1340
bool MSReferenceTable::resetScan(bool positioned, uint32_t repo_index)
1346
MSRepoPointersRec ptr;
1354
if (!MSRepositoryTable::resetScan(positioned, repo_index))
1358
lock = iRepoFile->myRepo->getRepoLock(iRepoOffset);
1360
if (iRepoFile->read(&blob, iRepoOffset, sizeof(MSBlobHeadRec), 0) < sizeof(MSBlobHeadRec)) {
1362
iRepoOffset = iRepoFileSize;
1365
head_size = CS_GET_DISK_2(blob.rb_head_size_2);
1366
blob_size = CS_GET_DISK_6(blob.rb_blob_repo_size_6);
1367
ref_size = CS_GET_DISK_1(blob.rb_ref_size_1);
1368
ref_count = CS_GET_DISK_2(blob.rb_ref_count_2);
1369
status = CS_GET_DISK_1(blob.rb_status_1);
1370
if (ref_count <= 0 || ref_size == 0 ||
1371
head_size < iRepoFile->myRepo->getRepoBlobHeadSize() + ref_count * ref_size ||
1372
!VALID_BLOB_STATUS(status)) {
1373
/* Can't be true. Assume this is garbage! */
1379
if (IN_USE_BLOB_STATUS(status)) {
1380
iBlobBuffer->setLength((uint32_t) head_size);
1381
if (iRepoFile->read(iBlobBuffer->getBuffer(0), iRepoOffset, head_size, 0) < head_size) {
1383
iRepoOffset = iRepoFileSize;
1388
iRefAuthCode = CS_GET_DISK_4(blob.rb_auth_code_4);
1389
iRefBlobSize = CS_GET_DISK_6(blob.rb_blob_data_size_6);;
1390
iRefBlobRepo = iRepoFile->myRepo->getRepoID();
1391
iRefBlobOffset = iRepoOffset;
1393
if (ref_count > iRefDataSize) {
1394
cs_realloc((void **) &iRefDataList, sizeof(MSRefDataRec) * ref_count);
1395
iRefDataSize = ref_count;
1401
// When ever the data position is reset the current location information
1402
// must also be reset so that it is consisent with the data position.
1403
iRefCurrentDataPos = iRefDataPos;
1404
iRefCurrentOffset = iRepoOffset;
1405
iRefCurrentIndex = iRepoIndex;
1406
iRefCurrentDataUsed = iRefDataUsed = ref_count;
1407
memset(iRefDataList, 0, sizeof(MSRefDataRec) * ref_count);
1409
uint32_t h = iRepoFile->myRepo->getRepoBlobHeadSize();
1410
ptr.rp_chars = iBlobBuffer->getBuffer(0) + h;
1411
for (uint32_t i=0; i<ref_count; i++) {
1412
switch (CS_GET_DISK_2(ptr.rp_ref->rr_type_2)) {
1413
case MS_BLOB_FREE_REF:
1415
case MS_BLOB_TABLE_REF: // The blob is intended for a file but has not been inserted yet.
1416
iRefDataList[i].rd_tab_id = CS_GET_DISK_4(ptr.rp_tab_ref->tr_table_id_4);
1417
iRefDataList[i].rd_blob_id = CS_GET_DISK_6(ptr.rp_tab_ref->tr_blob_id_6);
1418
iRefDataList[i].rd_col_index = INVALID_INDEX; // Means not used
1420
case MS_BLOB_DELETE_REF:
1421
tab_index = CS_GET_DISK_2(ptr.rp_temp_ref->tp_del_ref_2);
1422
if (tab_index && (tab_index <= ref_count)) {
1424
iRefDataList[tab_index].rd_temp_log_id = CS_GET_DISK_4(ptr.rp_temp_ref->tp_log_id_4);
1425
iRefDataList[tab_index].rd_temp_log_offset = CS_GET_DISK_4(ptr.rp_temp_ref->tp_offset_4);
1427
else if (tab_index == INVALID_INDEX) {
1428
/* The is a reference from the temporary log only!! */
1429
iRefDataList[i].rd_tab_id = 0xFFFFFFFF; // Indicates no table
1430
iRefDataList[i].rd_blob_id = iRepoOffset;
1431
iRefDataList[i].rd_blob_ref_id = CS_GET_DISK_4(ptr.rp_temp_ref->tp_log_id_4);;
1432
iRefDataList[i].rd_col_index = INVALID_INDEX; // Means not used
1433
iRefDataList[i].rd_temp_log_id = CS_GET_DISK_4(ptr.rp_temp_ref->tp_log_id_4);
1434
iRefDataList[i].rd_temp_log_offset = CS_GET_DISK_4(ptr.rp_temp_ref->tp_offset_4);
1438
MSRepoTableRefPtr tab_ref;
1440
tab_index = CS_GET_DISK_2(ptr.rp_blob_ref->er_table_2)-1;
1441
if (tab_index < ref_count) {
1442
tab_ref = (MSRepoTableRefPtr) (iBlobBuffer->getBuffer(0) + iRepoFile->myRepo->getRepoBlobHeadSize() + tab_index * ref_size);
1444
iRefDataList[i].rd_tab_id = CS_GET_DISK_4(tab_ref->tr_table_id_4);
1445
iRefDataList[i].rd_blob_id = CS_GET_DISK_6(tab_ref->tr_blob_id_6);
1446
iRefDataList[i].rd_col_index = CS_GET_DISK_2(ptr.rp_blob_ref->er_col_index_2);
1447
iRefDataList[i].rd_blob_ref_id = COMMIT_MASK(CS_GET_DISK_8(ptr.rp_blob_ref->er_blob_ref_id_8));
1449
iRefDataList[tab_index].rd_ref_count++;
1452
/* Can't be true. Assume this is garbage! */
1459
ptr.rp_chars += ref_size;
1462
iRepoOffset += head_size + blob_size;
1467
iRepoOffset += head_size + blob_size;
1471
bool MSReferenceTable::returnRecord(char *buf)
1473
if (!resetScan(false))
1476
return(returnSubRecord(buf));
1479
bool MSReferenceTable::returnSubRecord(char *buf)
1483
while (iRefDataPos < iRefDataUsed) {
1485
if (iRefDataList[i].rd_tab_id) {
1486
if (iRefDataList[i].rd_col_index == INVALID_INDEX) {
1487
/* This is a table reference */
1488
if (!iRefDataList[i].rd_ref_count || iRefDataList[i].rd_temp_log_id) {
1489
returnRow(&iRefDataList[i], buf);
1494
/* This is an engine reference */
1495
returnRow(&iRefDataList[i], buf);
1504
void MSReferenceTable::returnRow(MSRefDataPtr ref_data, char *buf)
1506
TABLE *table = mySQLTable;
1509
MY_BITMAP *save_write_set;
1510
MY_BITMAP *save_read_set;
1511
bool have_times = false;
1513
int32_t countdown = 0;
1515
if (iRefOpenTable) {
1516
if (iRefOpenTable->getDBTable()->myTableID != ref_data->rd_tab_id) {
1517
iRefOpenTable->returnToPool();
1518
iRefOpenTable = NULL;
1522
if (!iRefOpenTable && ref_data->rd_tab_id != 0xFFFFFFFF)
1523
iRefOpenTable = MSTableList::getOpenTableByID(myShare->mySysDatabase->myDatabaseID, ref_data->rd_tab_id);
1525
if (ref_data->rd_temp_log_id) {
1527
if (iRefTempLog->myTempLogID != ref_data->rd_temp_log_id) {
1528
iRefTempLog->release();
1533
iRefTempLog = myShare->mySysDatabase->openTempLogFile(ref_data->rd_temp_log_id, NULL, NULL);
1536
MSTempLogItemRec log_item;
1538
if (iRefTempLog->read(&log_item, ref_data->rd_temp_log_offset, sizeof(MSTempLogItemRec), 0) == sizeof(MSTempLogItemRec)) {
1540
delete_time = CS_GET_DISK_4(log_item.ti_time_4);
1541
countdown = (int32_t) (delete_time + PBMSParameters::getTempBlobTimeout()) - (int32_t) time(NULL);
1546
if (ref_data->rd_col_index != INVALID_INDEX) {
1547
if (iRefOpenTable) {
1548
if (iRefOpenTable->getDBTable()->isToDelete()) {
1550
iRefOpenTable->getDBTable()->getDeleteInfo(&ref_data->rd_temp_log_id, &ref_data->rd_temp_log_offset, &delete_time);
1551
ref_data->rd_col_index = INVALID_INDEX;
1552
countdown = (int32_t) (delete_time + PBMSParameters::getTempBlobTimeout()) - (int32_t) time(NULL);
1556
ref_data->rd_col_index = INVALID_INDEX;
1559
save_write_set = table->write_set;
1560
save_read_set = table->read_set;
1561
table->write_set = NULL;
1562
table->read_set = NULL;
1564
memset(buf, 0xFF, table->s->null_bytes);
1565
for (Field **field=GET_TABLE_FIELDS(table) ; *field ; field++) {
1566
curr_field = *field;
1568
save = curr_field->ptr;
1569
#if MYSQL_VERSION_ID < 50114
1570
curr_field->ptr = (byte *) buf + curr_field->offset();
1572
curr_field->ptr = (byte *) buf + curr_field->offset(curr_field->table->record[0]);
1574
switch (curr_field->field_name[0]) {
1576
switch (curr_field->field_name[5]) {
1579
ASSERT(strcmp(curr_field->field_name, "Blob_id") == 0);
1580
if (ref_data->rd_tab_id == 0xFFFFFFFF)
1581
curr_field->store(0, true);
1583
curr_field->store(ref_data->rd_blob_id, true);
1584
setNotNullInRecord(curr_field, buf);
1588
// Blob_url VARCHAR(120),
1589
PBMSBlobURLRec blob_url;
1591
ASSERT(strcmp(curr_field->field_name, "Blob_url") == 0);
1592
if (ref_data->rd_tab_id != 0xFFFFFFFF) {
1593
iRefOpenTable->formatBlobURL(&blob_url, ref_data->rd_blob_id, iRefAuthCode, iRefBlobSize, ref_data->rd_blob_ref_id);
1594
curr_field->store(blob_url.bu_data, strlen(blob_url.bu_data) +1, &UTF8_CHARSET); // Include the null char in the url. This is the way it is stored in user tables.
1595
setNotNullInRecord(curr_field, buf);
1599
// Blob_size BIGINT,
1600
ASSERT(strcmp(curr_field->field_name, "Blob_size") == 0);
1601
curr_field->store(iRefBlobSize, true);
1602
setNotNullInRecord(curr_field, buf);
1607
// Column_ordinal INT,
1608
ASSERT(strcmp(curr_field->field_name, "Column_ordinal") == 0);
1609
if (ref_data->rd_col_index != INVALID_INDEX) {
1610
curr_field->store(ref_data->rd_col_index +1, true);
1611
setNotNullInRecord(curr_field, buf);
1615
// Deletion_time TIMESTAMP,
1616
ASSERT(strcmp(curr_field->field_name, "Deletion_time") == 0);
1618
curr_field->store(ms_my_1970_to_mysql_time(delete_time), true);
1619
setNotNullInRecord(curr_field, buf);
1623
switch (curr_field->field_name[5]) {
1625
// Repository_id INT,
1626
ASSERT(strcmp(curr_field->field_name, "Repository_id") == 0);
1627
curr_field->store(iRefBlobRepo, true);
1628
setNotNullInRecord(curr_field, buf);
1631
// Repo_blob_offset BIGINT,
1632
ASSERT(strcmp(curr_field->field_name, "Repo_blob_offset") == 0);
1633
curr_field->store(iRefBlobOffset, true);
1634
setNotNullInRecord(curr_field, buf);
1638
ASSERT(strcmp(curr_field->field_name, "Remove_in") == 0);
1640
curr_field->store(countdown, false);
1641
setNotNullInRecord(curr_field, buf);
1647
switch (curr_field->field_name[9]) {
1649
// Table_name CHAR(64),
1650
ASSERT(strcmp(curr_field->field_name, "Table_name") == 0);
1651
if (ref_data->rd_tab_id != 0xFFFFFFFF) {
1652
if (iRefOpenTable) {
1653
CSString *table_name = iRefOpenTable->getDBTable()->getTableName();
1654
curr_field->store(table_name->getCString(), table_name->length(), &UTF8_CHARSET);
1657
char buffer[MS_TABLE_NAME_SIZE];
1659
snprintf(buffer, MS_TABLE_NAME_SIZE, "Table #%"PRIu32"", ref_data->rd_tab_id);
1660
curr_field->store(buffer, strlen(buffer), &UTF8_CHARSET);
1662
setNotNullInRecord(curr_field, buf);
1667
ASSERT(strcmp(curr_field->field_name, "Temp_log_id") == 0);
1668
if (ref_data->rd_temp_log_id) {
1669
curr_field->store(ref_data->rd_temp_log_id, true);
1670
setNotNullInRecord(curr_field, buf);
1674
// Temp_log_offset BIGINT
1675
ASSERT(strcmp(curr_field->field_name, "Temp_log_offset") == 0);
1676
if (ref_data->rd_temp_log_id) {
1677
curr_field->store(ref_data->rd_temp_log_offset, true);
1678
setNotNullInRecord(curr_field, buf);
1684
curr_field->ptr = save;
1687
table->write_set = save_write_set;
1688
table->read_set = save_read_set;
1692
* -------------------------------------------------------------------------
1695
MSMetaDataTable::MSMetaDataTable(MSSystemTableShare *share, TABLE *table):
1696
MSRepositoryTable(share, table),
1698
iMetCurrentBlobRepo(0),
1699
iMetCurrentBlobOffset(0),
1700
iMetCurrentDataPos(0),
1701
iMetCurrentDataSize(0),
1706
iMetStateSaved(false)
1710
MSMetaDataTable::~MSMetaDataTable()
1713
iMetData->release();
1718
MSMetaDataTable *MSMetaDataTable::newMSMetaDataTable(MSDatabase *db)
1720
char path[PATH_MAX];
1722
cs_strcpy(PATH_MAX, path, db->myDatabasePath->getCString());
1724
cs_add_dir_char(PATH_MAX, path);
1725
cs_strcat(PATH_MAX, path, sysTableNames[SYS_META]);
1727
return (MSMetaDataTable*) MSSystemTableShare::openSystemTable(path, NULL);
1730
void MSMetaDataTable::unuse()
1732
MSRepositoryTable::unuse();
1734
iMetData->release();
1741
void MSMetaDataTable::seqScanInit()
1743
MSRepositoryTable::seqScanInit();
1748
new_(iMetData, CSStringBuffer(80));
1749
iMetStateSaved = false;
1752
void MSMetaDataTable::seqScanReset()
1754
seqScanPos(iMetState);
1756
iMetStateSaved = true;
1759
int MSMetaDataTable::getRefLen()
1761
return sizeof(iMetCurrentDataPos) + sizeof(iMetCurrentDataSize) + sizeof(iMetCurrentBlobRepo) + sizeof(iMetCurrentBlobOffset);
1764
void MSMetaDataTable::seqScanPos(uint8_t *pos)
1766
mi_int4store(pos, iMetCurrentDataPos); pos +=4;
1767
mi_int4store(pos, iMetCurrentDataSize);pos +=4;
1768
mi_int4store(pos, iMetCurrentBlobRepo); pos +=4;
1769
mi_int8store(pos, iMetCurrentBlobOffset);
1772
void MSMetaDataTable::seqScanRead(uint8_t *pos, char *buf)
1774
iMetStateSaved = false;
1775
iMetDataPos = mi_uint4korr( pos); pos +=4;
1776
iMetDataSize = mi_uint4korr(pos); pos +=4;
1777
iMetBlobRepo = mi_uint4korr(pos); pos +=4;
1778
iMetBlobOffset = mi_uint8korr(pos);
1779
MSRepositoryTable::seqScanRead(iMetBlobRepo, iMetBlobOffset, buf);
1782
bool MSMetaDataTable::seqScanNext(char *buf)
1784
if (iMetStateSaved) {
1786
uint8_t *pos = iMetState;
1787
iMetDataPos = mi_uint4korr( pos); pos +=4;
1788
// Do not reset the meta data size.
1789
/*iMetDataSize = mi_uint4korr(pos); */pos +=4;
1790
iMetBlobRepo = mi_uint4korr(pos); pos +=4;
1791
iMetBlobOffset = mi_uint8korr(pos);
1792
iMetStateSaved = false;
1793
resetScan(true, &have_data, iMetBlobRepo);
1796
iMetCurrentDataPos = iMetDataPos;
1797
iMetCurrentDataSize = iMetDataSize;
1799
return MSRepositoryTable::seqScanNext(buf);
1802
bool MSMetaDataTable::resetScan(bool positioned, bool *have_data, uint32_t repo_index)
1808
size_t mdata_size, mdata_offset;
1814
if (!MSRepositoryTable::resetScan(positioned, repo_index))
1818
lock = iRepoFile->myRepo->getRepoLock(iRepoOffset);
1820
if (iRepoFile->read(&blob, iRepoOffset, sizeof(MSBlobHeadRec), 0) < sizeof(MSBlobHeadRec)) {
1822
iRepoOffset = iRepoFileSize;
1826
head_size = CS_GET_DISK_2(blob.rb_head_size_2);
1827
blob_size = CS_GET_DISK_6(blob.rb_blob_repo_size_6);
1828
mdata_size = CS_GET_DISK_2(blob.rb_mdata_size_2);
1829
mdata_offset = CS_GET_DISK_2(blob.rb_mdata_offset_2);
1831
status = CS_GET_DISK_1(blob.rb_status_1);
1832
if ((head_size < (mdata_offset + mdata_size)) || !VALID_BLOB_STATUS(status)) {
1833
/* Can't be true. Assume this is garbage! */
1839
if (mdata_size && IN_USE_BLOB_STATUS(status)) {
1840
iMetData->setLength((uint32_t) mdata_size);
1841
if (iRepoFile->read(iMetData->getBuffer(0), iRepoOffset + mdata_offset, mdata_size, 0) < mdata_size) {
1843
iRepoOffset = iRepoFileSize;
1847
iMetBlobRepo = iRepoFile->myRepo->getRepoID();
1848
iMetBlobOffset = iRepoOffset;
1853
iMetDataSize = mdata_size;
1855
// When ever the data position is reset the current location information
1856
// must also be reset to that it is consisent with the data position.
1857
iMetCurrentBlobOffset = iRepoOffset;
1858
iMetCurrentBlobRepo = iRepoIndex;
1859
iMetCurrentDataPos = iMetDataPos;
1860
iMetCurrentDataSize = iMetDataSize;
1865
iRepoOffset += head_size + blob_size;
1869
bool MSMetaDataTable::returnRecord(char *buf)
1871
bool have_data = false;
1873
if (resetScan(false, &have_data) && have_data)
1874
return(returnSubRecord(buf));
1879
bool MSMetaDataTable::nextRecord(char **name, char **value)
1881
if (iMetDataPos < iMetDataSize) {
1882
char *data = iMetData->getBuffer(iMetDataPos);
1885
data += strlen(*name) +1;
1887
data += strlen(*value) +1;
1889
iMetDataPos += data - *name;
1890
ASSERT(iMetDataPos <= iMetDataSize);
1899
bool MSMetaDataTable::returnSubRecord(char *buf)
1903
if (nextRecord(&name, &value)) {
1904
returnRow(name, value, buf);
1911
void MSMetaDataTable::returnRow(char *name, char *value, char *buf)
1913
TABLE *table = mySQLTable;
1916
MY_BITMAP *save_write_set;
1918
save_write_set = table->write_set;
1919
table->write_set = NULL;
1921
memset(buf, 0xFF, table->s->null_bytes);
1922
for (Field **field=GET_TABLE_FIELDS(table) ; *field ; field++) {
1923
curr_field = *field;
1925
save = curr_field->ptr;
1926
#if MYSQL_VERSION_ID < 50114
1927
curr_field->ptr = (byte *) buf + curr_field->offset();
1929
curr_field->ptr = (byte *) buf + curr_field->offset(curr_field->table->record[0]);
1931
switch (curr_field->field_name[0]) {
1933
switch (curr_field->field_name[6]) {
1935
// Repository_id INT
1936
ASSERT(strcmp(curr_field->field_name, "Repository_id") == 0);
1937
curr_field->store(iRepoFile->myRepo->getRepoID(), true);
1938
setNotNullInRecord(curr_field, buf);
1941
// Repo_blob_offset BIGINT
1942
ASSERT(strcmp(curr_field->field_name, "Repo_blob_offset") == 0);
1943
curr_field->store(iMetCurrentBlobOffset, true);
1944
setNotNullInRecord(curr_field, buf);
1950
ASSERT(strcmp(curr_field->field_name, "Name") == 0);
1951
curr_field->store(name, strlen(name), &UTF8_CHARSET);
1952
setNotNullInRecord(curr_field, buf);
1956
ASSERT(strcmp(curr_field->field_name, "Value") == 0);
1957
curr_field->store(value, strlen(value), &my_charset_utf8_bin);
1958
setNotNullInRecord(curr_field, buf);
1961
curr_field->ptr = save;
1964
table->write_set = save_write_set;
1968
#ifdef HAVE_ALIAS_SUPPORT
1969
bool MSMetaDataTable::matchAlias(uint32_t repo_id, uint64_t offset, const char *alias)
1971
bool matched = false, have_data = false;
1974
if (resetScan(true, &have_data, repo_id) && have_data) {
1975
const char *blob_alias;
1976
MetaData md(iMetData->getBuffer(0), iMetDataSize);
1978
blob_alias = md.findAlias();
1979
matched = (blob_alias && !my_strcasecmp(&UTF8_CHARSET, blob_alias, alias));
1986
void MSMetaDataTable::insertRow(char *buf)
1988
uint32_t repo_index;
1989
String meta_name, meta_value;
1991
uint64_t repo_offset;
1993
bool have_data, reset_alias = false;
1997
// Metadata inserts are ignored during reovery.
1998
// They will be restored from the dump table.
1999
if (myShare->mySysDatabase->isRecovering())
2004
getFieldValue(buf, 0, &repo_index);
2005
getFieldValue(buf, 1, &repo_offset);
2006
getFieldValue(buf, 2, &meta_name);
2007
getFieldValue(buf, 3, &meta_value);
2010
CSException::throwException(CS_CONTEXT, HA_ERR_CANNOT_ADD_FOREIGN, "Invalid Repository_id");
2012
iRepoOffset = repo_offset;
2013
if (!resetScan(true, &have_data, repo_index -1))
2014
CSException::throwException(CS_CONTEXT, HA_ERR_CANNOT_ADD_FOREIGN, "Invalid Repository_id or Repo_blob_offset");
2016
const char *alias = NULL, *tag = meta_name.c_ptr_safe();
2019
MetaData md(iMetData->getBuffer(0), iMetDataSize);
2020
// Check to see it this is a duplicate name.
2021
if (md.findName(tag))
2022
CSException::throwException(CS_CONTEXT, HA_ERR_FOUND_DUPP_KEY, "Meta data tag already exists.");
2024
#ifdef HAVE_ALIAS_SUPPORT
2025
alias = md.findAlias();
2029
// Create the meta data record.
2030
#ifdef HAVE_ALIAS_SUPPORT
2032
data = iMetData->getBuffer(0); // This is to be able to test if the alias pointer needs to be reset.
2037
iMetData->setLength(iMetDataSize + meta_name.length() + meta_value.length() + 2);
2039
#ifdef HAVE_ALIAS_SUPPORT
2040
if (alias && (data != iMetData->getBuffer(0))) // The buffer moved, adjust the alias.
2041
alias += (iMetData->getBuffer(0) - data);
2044
data = iMetData->getBuffer(0);
2045
data_len = iMetDataSize;
2047
#ifdef HAVE_ALIAS_SUPPORT
2048
if ((!alias) && !my_strcasecmp(&UTF8_CHARSET, MS_ALIAS_TAG, tag)) {
2050
memcpy(data + data_len, MS_ALIAS_TAG, meta_name->length()); // Use my alias tag so we do not need to wory about case.
2051
alias = data + data_len + meta_name->length() + 1; // Set the alias to the value location.
2054
memcpy(data + data_len, meta_name.c_ptr_quick(), meta_name.length());
2056
data_len += meta_name.length();
2060
memcpy(data + data_len, meta_value.c_ptr_quick(), meta_value.length());
2061
data_len += meta_value.length();
2065
// Update the blob header with the new meta data.
2066
MSOpenTable *otab = MSOpenTable::newOpenTable(NULL);
2068
iRepoFile->setBlobMetaData(otab, repo_offset, data, data_len, reset_alias, alias);
2074
insert into pbms_mata_data values(1, 921, "ATAG 3", "xx");
2075
insert into pbms_mata_data values(1, 921, "ATAG 1", "A VALUE 1");
2076
insert into pbms_mata_data values(1, 921, "ATAG 2", "xx");
2077
insert into pbms_mata_data values(1, 383, "ATAG 2", "xx");
2078
select * from pbms_mata_data;
2080
delete from pbms_mata_data where value = "xx";
2081
select * from pbms_mata_data;
2083
update pbms_mata_data set value = "!!" where name = "ATAG 3";
2084
update pbms_mata_data set Repo_blob_offset = 383 where value = "!!";
2086
delete from pbms_mata_data where Repo_blob_offset = 921;
2088
//insert into pbms_mata_data values(1, 921, "blob_ALIAs", "My_alias");
2089
//select * from pbms_mata_data;
2090
//select * from pbms_repository;
2093
void MSMetaDataTable::deleteRow(char *buf)
2095
uint32_t repo_index;
2096
String meta_name, meta_value;
2097
uint16_t record_size;
2098
uint64_t repo_offset;
2100
bool have_data, reset_alias = false;
2106
getFieldValue(buf, 0, &repo_index);
2107
getFieldValue(buf, 1, &repo_offset);
2108
getFieldValue(buf, 2, &meta_name);
2109
getFieldValue(buf, 3, &meta_value);
2112
CSException::throwException(CS_CONTEXT, HA_ERR_CANNOT_ADD_FOREIGN, "Invalid Repository_id");
2114
iRepoOffset = repo_offset;
2115
if (!resetScan(true, &have_data, repo_index -1))
2116
CSException::throwException(CS_CONTEXT, HA_ERR_CANNOT_ADD_FOREIGN, "Invalid Repository_id or Repo_blob_offset");
2118
const char *alias = NULL, *value = NULL, *tag = meta_name.c_ptr_safe();
2121
// Check to see name exists.
2124
md.use_data(iMetData->getBuffer(0), iMetDataSize);
2126
value = md.findName(tag);
2129
CSException::throwException(CS_CONTEXT, HA_ERR_KEY_NOT_FOUND, "Meta data tag dosn't exists.");
2131
#ifdef HAVE_ALIAS_SUPPORT
2132
alias = md.findAlias();
2134
if (alias == value) {
2140
// Create the meta data record.
2141
data = md.getBuffer();
2142
location = md.findNamePosition(tag);
2143
record_size = MetaData::recSize(location);
2144
iMetDataSize -= record_size;
2145
memmove(location, location + record_size, iMetDataSize - (location - data)); // Shift the meta data down
2147
#ifdef HAVE_ALIAS_SUPPORT
2148
// Get the alias again incase it moved.
2150
alias = md.findAlias();
2153
// Update the blob header with the new meta data.
2154
MSOpenTable *otab = MSOpenTable::newOpenTable(NULL);
2156
iRepoFile->setBlobMetaData(otab, repo_offset, data, iMetDataSize, reset_alias, alias);
2162
void MSMetaDataTable::updateRow(char *old_data, char *new_data)
2164
uint32_t o_repo_index, n_repo_index;
2165
String n_meta_name, n_meta_value;
2166
String o_meta_name, o_meta_value;
2167
uint16_t record_size;
2168
uint64_t o_repo_offset, n_repo_offset;
2170
bool have_data, reset_alias = false;
2176
getFieldValue(new_data, 0, &n_repo_index);
2177
getFieldValue(new_data, 1, &n_repo_offset);
2178
getFieldValue(new_data, 2, &n_meta_name);
2179
getFieldValue(new_data, 3, &n_meta_value);
2181
getFieldValue(old_data, 0, &o_repo_index);
2182
getFieldValue(old_data, 1, &o_repo_offset);
2183
getFieldValue(old_data, 2, &o_meta_name);
2184
getFieldValue(old_data, 3, &o_meta_value);
2186
if ((!o_repo_index) || (!n_repo_index))
2187
CSException::throwException(CS_CONTEXT, HA_ERR_CANNOT_ADD_FOREIGN, "Invalid Repository_id");
2189
// If the meta data is not for the same BLOB then we do an insert and delete.
2190
if ((n_repo_index != o_repo_index) || (n_repo_offset != o_repo_offset)) {
2191
insertRow(new_data);
2193
deleteRow(old_data);
2196
deleteRow(new_data);
2203
iRepoOffset = n_repo_offset;
2204
if (!resetScan(true, &have_data, n_repo_index -1))
2205
CSException::throwException(CS_CONTEXT, HA_ERR_CANNOT_ADD_FOREIGN, "Invalid Repository_id or Repo_blob_offset");
2208
const char *value, *alias = NULL, *n_tag = n_meta_name.c_ptr_safe(), *o_tag = o_meta_name.c_ptr_safe();
2210
if (!my_strcasecmp(&UTF8_CHARSET, o_tag, n_tag))
2215
md.use_data(iMetData->getBuffer(0), iMetDataSize);
2217
if ((!iMetDataSize) || ((value = md.findName(o_tag)) == NULL))
2218
CSException::throwException(CS_CONTEXT, HA_ERR_KEY_NOT_FOUND, "Meta data tag dosn't exists.");
2220
if (n_tag && (md.findName(n_tag) != NULL))
2221
CSException::throwException(CS_CONTEXT, HA_ERR_FOUND_DUPP_KEY, "Meta data tag already exists.");
2223
#ifdef HAVE_ALIAS_SUPPORT
2224
alias = md.findAlias();
2226
if (alias == value) {
2228
alias = NULL; // The alias is being deleted.
2235
// Create the meta data record.
2236
data = md.getBuffer();
2237
location = md.findNamePosition(o_tag);
2238
record_size = MetaData::recSize(location);
2239
iMetDataSize -= record_size;
2240
memmove(location, location + record_size, iMetDataSize - (location - data)); // Shift the meta data down
2242
// Add the updated meta data to the end of the block.
2243
iMetData->setLength(iMetDataSize + n_meta_name.length() + n_meta_value.length() + 2);
2245
md.use_data(iMetData->getBuffer(0), iMetDataSize); // Reset this incase the buffer moved.
2246
#ifdef HAVE_ALIAS_SUPPORT
2247
// Get the alias again incase it moved.
2249
alias = md.findAlias();
2252
data = iMetData->getBuffer(0);
2254
#ifdef HAVE_ALIAS_SUPPORT
2255
if ((!alias) && !my_strcasecmp(&UTF8_CHARSET, MS_ALIAS_TAG, n_tag)) {
2257
memcpy(data + iMetDataSize, MS_ALIAS_TAG, n_meta_name.length()); // Use my alias tag so we do not need to wory about case.
2258
alias = data + iMetDataSize + n_meta_name.length() + 1; // Set the alias to the value location.
2261
memcpy(data + iMetDataSize, n_meta_name.c_ptr_quick(), n_meta_name.length());
2263
iMetDataSize += n_meta_name.length();
2264
data[iMetDataSize] = 0;
2267
memcpy(data + iMetDataSize, n_meta_value.c_ptr_quick(), n_meta_value.length());
2268
iMetDataSize += n_meta_value.length();
2269
data[iMetDataSize] = 0;
2273
// Update the blob header with the new meta data.
2274
MSOpenTable *otab = MSOpenTable::newOpenTable(NULL);
2276
iRepoFile->setBlobMetaData(otab, n_repo_offset, data, iMetDataSize, reset_alias, alias);
2283
* -------------------------------------------------------------------------
2284
* SYSTEM TABLE SHARES
2287
CSSyncSortedList *MSSystemTableShare::gSystemTableList;
2289
MSSystemTableShare::MSSystemTableShare():
2292
mySysDatabase(NULL),
2295
thr_lock_init(&myThrLock);
2298
MSSystemTableShare::~MSSystemTableShare()
2300
thr_lock_delete(&myThrLock);
2302
myTablePath->release();
2305
if (mySysDatabase) {
2306
mySysDatabase->release();
2307
mySysDatabase = NULL;
2311
CSObject *MSSystemTableShare::getKey()
2313
return (CSObject *) myTablePath;
2316
int MSSystemTableShare::compareKey(CSObject *key)
2318
return myTablePath->compare((CSString *) key);
2321
void MSSystemTableShare::startUp()
2323
new_(gSystemTableList, CSSyncSortedList);
2326
void MSSystemTableShare::shutDown()
2328
if (gSystemTableList) {
2329
gSystemTableList->release();
2330
gSystemTableList = NULL;
2334
MSOpenSystemTable *MSSystemTableShare::openSystemTable(const char *table_path, TABLE *table)
2336
CSString *table_url;
2337
MSSystemTableShare *share;
2338
MSOpenSystemTable *otab = NULL;
2339
SysTableType table_type;
2343
table_type = pbms_systable_type(cs_last_name_of_path(table_path));
2344
if (table_type == SYS_UNKNOWN)
2345
CSException::throwException(CS_CONTEXT, MS_ERR_UNKNOWN_TABLE, "Table not found");
2347
table_path = cs_last_name_of_path(table_path, 2);
2348
table_url = CSString::newString(table_path);
2351
lock_(gSystemTableList);
2352
if (!(share = (MSSystemTableShare *) gSystemTableList->find(table_url))) {
2353
share = MSSystemTableShare::newTableShare(RETAIN(table_url));
2354
gSystemTableList->add(share);
2357
switch (table_type) {
2359
new_(otab, MSRepositoryTable(share, table));
2362
new_(otab, MSReferenceTable(share, table));
2365
new_(otab, MSBlobDataTable(share, table));
2368
new_(otab, MSDumpTable(share, table));
2371
new_(otab, MSMetaDataTable(share, table));
2374
new_(otab, MSHTTPHeaderTable(share, table));
2376
#ifdef HAVE_ALIAS_SUPPORT
2378
new_(otab, MSBlobAliasTable(share, table));
2382
new_(otab, MSVariableTable(share, table));
2385
new_(otab, MSCloudTable(share, table));
2388
new_(otab, MSBackupTable(share, table));
2392
new_(otab, MSEnabledTable(share, table));
2399
share->iOpenCount++;
2400
unlock_(gSystemTableList);
2402
release_(table_url);
2406
void MSSystemTableShare::removeDatabaseSystemTables(MSDatabase *doomed_db)
2408
MSSystemTableShare *share;
2413
lock_(gSystemTableList);
2414
while ((share = (MSSystemTableShare *) gSystemTableList->itemAt(i))) {
2415
if (share->mySysDatabase == doomed_db) {
2416
gSystemTableList->remove(share->myTablePath);
2421
unlock_(gSystemTableList);
2422
release_(doomed_db);
2426
void MSSystemTableShare::releaseSystemTable(MSOpenSystemTable *tab)
2429
lock_(gSystemTableList);
2430
tab->myShare->iOpenCount--;
2431
if (!tab->myShare->iOpenCount) {
2432
gSystemTableList->remove(tab->myShare->myTablePath);
2434
unlock_(gSystemTableList);
2438
MSSystemTableShare *MSSystemTableShare::newTableShare(CSString *table_path)
2440
MSSystemTableShare *tab;
2443
if (!(tab = new MSSystemTableShare())) {
2444
table_path->release();
2445
CSException::throwOSError(CS_CONTEXT, ENOMEM);
2448
tab->myTablePath = table_path;
2449
tab->mySysDatabase = MSDatabase::getDatabase(table_path->left("/", -1), true);
2454
void PBMSSystemTables::systemTablesStartUp()
2456
MSCloudTable::startUp();
2457
MSBackupTable::startUp();
2460
void PBMSSystemTables::systemTableShutDown()
2462
MSBackupTable::shutDown();
2463
MSCloudTable::shutDown();