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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 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.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", NOVAL, NULL, MYSQL_TYPE_LONG, NULL, NOT_NULL_FLAG, "The repository file number"},
97
{"Repo_blob_offset", NOVAL, NULL, MYSQL_TYPE_LONGLONG, NULL, NOT_NULL_FLAG, "The offset of the BLOB in the repository file"},
98
{"Blob_size", NOVAL, 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", NOVAL, NULL, MYSQL_TYPE_SHORT, NULL, NOT_NULL_FLAG | UNSIGNED_FLAG, "The size of the BLOB header - proceeds the BLOB data"},
101
{"Access_code", NOVAL, 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", NOVAL, NULL, MYSQL_TYPE_TIMESTAMP, NULL, NOT_NULL_FLAG, "The time the BLOB was created"},
103
{"Last_ref_time", NOVAL, NULL, MYSQL_TYPE_TIMESTAMP, NULL, 0, "The last time the BLOB was referenced"},
104
{"Last_access_time", NOVAL, NULL, MYSQL_TYPE_TIMESTAMP, NULL, 0, "The last time the BLOB was accessed (read)"},
105
{"Access_count", NOVAL, NULL, MYSQL_TYPE_LONG, NULL, NOT_NULL_FLAG, "The count of the number of times the BLOB has been read"},
106
{NULL,NOVAL, 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", NOVAL, NULL, MYSQL_TYPE_LONG, NULL, NOT_NULL_FLAG, "The repository file number"},
120
{"Repo_blob_offset", NOVAL, 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, NOVAL, 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", NOVAL, NULL, MYSQL_TYPE_LONG, NULL, NOT_NULL_FLAG, "The repository file number"},
139
{"Repo_blob_offset", NOVAL, 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,NOVAL, 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", NOVAL, NULL, MYSQL_TYPE_LONG, NULL, NOT_NULL_FLAG, "The repository file number"},
154
{"Repo_blob_offset", NOVAL, NULL, MYSQL_TYPE_LONGLONG, NULL, NOT_NULL_FLAG, "The offset of the BLOB in the repository file"},
155
{"Blob_data", NOVAL, NULL, MYSQL_TYPE_LONG_BLOB, &my_charset_bin, NOT_NULL_FLAG, "The data of this BLOB"},
156
{NULL,NOVAL, 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", NOVAL, NULL, MYSQL_TYPE_LONG, NULL, 0, "The column ordinal of the referencing field"},
171
{"Blob_id", NOVAL, 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", NOVAL, NULL, MYSQL_TYPE_LONG, NULL, NOT_NULL_FLAG, "The repository file number of the BLOB"},
174
{"Repo_blob_offset",NOVAL, NULL, MYSQL_TYPE_LONGLONG, NULL, NOT_NULL_FLAG, "The offset in the repository file"},
175
{"Blob_size", NOVAL, NULL, MYSQL_TYPE_LONGLONG, NULL, NOT_NULL_FLAG, "The size of the BLOB in bytes"},
176
{"Deletion_time", NOVAL, NULL, MYSQL_TYPE_TIMESTAMP, NULL, 0, "The time the BLOB was deleted"},
177
{"Remove_in", NOVAL, NULL, MYSQL_TYPE_LONG, NULL, 0, "The number of seconds before the reference/BLOB is removed perminently"},
178
{"Temp_log_id", NOVAL, NULL, MYSQL_TYPE_LONG, NULL, 0, "Temporary log number of the referencing deletion entry"},
179
{"Temp_log_offset", NOVAL, NULL, MYSQL_TYPE_LONGLONG, NULL, 0, "Temporary log offset of the referencing deletion entry"},
180
{NULL,NOVAL, 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_notnull(true);
325
if (info->field_flags & UNSIGNED_FLAG)
326
field_constraints->set_is_unsigned(true);
328
field_constraints->set_is_unsigned(false);
330
switch (info->field_type) {
331
case DRIZZLE_TYPE_VARCHAR:
332
string_field_options = field->mutable_string_options();
334
field->set_type(message::Table::Field::VARCHAR);
335
string_field_options->set_length(info->field_length);
336
if (info->field_charset) {
337
string_field_options->set_collation(info->field_charset->name);
338
string_field_options->set_collation_id(info->field_charset->number);
342
case DRIZZLE_TYPE_LONG:
343
field->set_type(message::Table::Field::INTEGER);
346
case DRIZZLE_TYPE_DOUBLE:
347
field->set_type(message::Table::Field::DOUBLE);
350
case DRIZZLE_TYPE_LONGLONG:
351
field->set_type(message::Table::Field::BIGINT);
354
case DRIZZLE_TYPE_TIMESTAMP:
355
field->set_type(message::Table::Field::EPOCH);
358
case DRIZZLE_TYPE_BLOB:
359
field->set_type(message::Table::Field::BLOB);
360
if (info->field_charset) {
361
string_field_options = field->mutable_string_options();
362
string_field_options->set_collation(info->field_charset->name);
363
string_field_options->set_collation_id(info->field_charset->number);
375
while (keys->key_name) {
376
// To be done later. (maybe)
383
#define TABLE drizzled::Table
384
#define Field drizzled::Field
386
int PBMSSystemTables::getSystemTableInfo(const char *name, drizzled::message::Table &table)
390
while (pbms_internal_tables[i].name) {
391
if (strcasecmp(name, pbms_internal_tables[i].name) == 0){
392
err = pbms_create_proto_table("PBMS", name, pbms_internal_tables[i].info, pbms_internal_tables[i].keys, table);
401
void PBMSSystemTables::getSystemTableNames(bool isPBMS, std::set<std::string> &set_of_names)
405
while (pbms_internal_tables[i].name) {
406
if ( isPBMS == pbms_internal_tables[i].is_pbms){
407
set_of_names.insert(pbms_internal_tables[i].name);
415
//--------------------------
416
static bool pbms_database_follder_exists( const char *db)
418
struct stat stat_info;
424
cs_strcpy(PATH_MAX, path, ms_my_get_mysql_home_path());
425
cs_add_name_to_path(PATH_MAX, path, db);
427
if (stat(path, &stat_info) == 0)
428
return(stat_info.st_mode & S_IFDIR);
433
int pbms_discover_system_tables(handlerton *hton, THD* thd, const char *db, const char *name, uchar **frmblob, size_t *frmlen)
436
bool is_pbms = false;
438
// Check that the database exists!
439
if (!pbms_database_follder_exists(db))
442
is_pbms = (strcmp(db, "pbms") == 0);
445
while (pbms_internal_tables[i].name) {
446
if ((!strcasecmp(name, pbms_internal_tables[i].name)) && ( is_pbms == pbms_internal_tables[i].is_pbms)){
447
err = ms_create_table_frm(hton, thd, db, name, pbms_internal_tables[i].info, pbms_internal_tables[i].keys, frmblob, frmlen);
457
// Transfer any physical PBMS ststem tables to another database.
458
void PBMSSystemTables::transferSystemTables(MSDatabase *dst_db, MSDatabase *src_db)
464
MSHTTPHeaderTable::transferTable(RETAIN(dst_db), RETAIN(src_db));
465
MSVariableTable::transferTable(RETAIN(dst_db), RETAIN(src_db));
466
MSCloudTable::transferTable(RETAIN(dst_db), RETAIN(src_db));
467
MSBackupTable::transferTable(RETAIN(dst_db), RETAIN(src_db));
475
void PBMSSystemTables::removeSystemTables(CSString *db_path)
480
MSHTTPHeaderTable::removeTable(RETAIN(db_path));
481
MSVariableTable::removeTable(RETAIN(db_path));
482
MSCloudTable::removeTable(RETAIN(db_path));
483
MSBackupTable::removeTable(RETAIN(db_path));
490
bool PBMSSystemTables::try_loadSystemTables(CSThread *self, int i, MSDatabase *db)
492
volatile bool rtc = true;
496
MSHTTPHeaderTable::loadTable(RETAIN(db));
499
MSCloudTable::loadTable(RETAIN(db));
502
MSBackupTable::loadTable(RETAIN(db));
505
// Variable must be loaded after cloud and backup info
506
// incase BLOB recovery is required.
507
MSVariableTable::loadTable(RETAIN(db));
520
void PBMSSystemTables::loadSystemTables(MSDatabase *db)
525
for ( int i = 0; i < 4; i++) {
526
if (try_loadSystemTables(self, i, db))
527
self->logException();
535
// Dump all the system tables into one buffer.
538
CSDiskValue1 tab_id_1;
539
CSDiskValue4 tab_version_4;
540
} DumpHeaderRec, *DumpHeaderPtr;
544
const char *rec_cchars;
545
DumpHeaderPtr dumpHeader;
548
CSStringBuffer *PBMSSystemTables::dumpSystemTables(MSDatabase *db)
550
CSStringBuffer *sysDump, *tabDump = NULL;
551
uint32_t size, pos, tab_version;
557
new_(sysDump, CSStringBuffer());
561
for ( int i = 0; i < 4; i++) {
564
tabDump = MSHTTPHeaderTable::dumpTable(RETAIN(db));
565
tab_id = MSHTTPHeaderTable::tableID;
566
tab_version = MSHTTPHeaderTable::tableVersion;
569
tabDump = MSCloudTable::dumpTable(RETAIN(db));
570
tab_id = MSCloudTable::tableID;
571
tab_version = MSCloudTable::tableVersion;
574
tabDump = MSBackupTable::dumpTable(RETAIN(db));
575
tab_id = MSBackupTable::tableID;
576
tab_version = MSBackupTable::tableVersion;
579
tabDump = MSVariableTable::dumpTable(RETAIN(db)); // Dump the variables table last.
580
tab_id = MSVariableTable::tableID;
581
tab_version = MSVariableTable::tableVersion;
589
size = tabDump->length();
591
// Grow the buffer for the header
592
sysDump->setLength(pos + sizeof(DumpHeaderRec));
594
// Add the dump header
595
d.rec_chars = sysDump->getBuffer(pos);
596
CS_SET_DISK_4(d.dumpHeader->size_4, size);;
597
CS_SET_DISK_1(d.dumpHeader->tab_id_1, tab_id);
598
CS_SET_DISK_4(d.dumpHeader->tab_version_4, tab_version);
600
sysDump->append(tabDump->getBuffer(0), size);
601
pos += size + sizeof(DumpHeaderRec);
612
void PBMSSystemTables::restoreSystemTables(MSDatabase *db, const char *data, size_t size)
614
uint32_t tab_size, tab_version;
621
while ( size >= sizeof(DumpHeaderRec)) {
623
tab_size = CS_GET_DISK_4(d.dumpHeader->size_4);
624
tab_id = CS_GET_DISK_1(d.dumpHeader->tab_id_1);
625
tab_version = CS_GET_DISK_4(d.dumpHeader->tab_version_4);
626
data += sizeof(DumpHeaderRec);
627
size -= sizeof(DumpHeaderRec);
629
if (size < tab_size) {
630
CSException::throwException(CS_CONTEXT, CS_ERR_GENERIC_ERROR, "PBMS system table restore data truncated.");
634
case MSHTTPHeaderTable::tableID:
635
if (MSHTTPHeaderTable::tableVersion == tab_version)
636
MSHTTPHeaderTable::restoreTable(RETAIN(db), data, tab_size);
638
CSException::logException(CS_CONTEXT, MS_ERR_SYSTAB_VERSION, "Restore "METADATA_HEADER_NAME" failed, incompatible table version" );
640
case MSCloudTable::tableID:
641
if (MSCloudTable::tableVersion == tab_version)
642
MSCloudTable::restoreTable(RETAIN(db), data, tab_size);
644
CSException::logException(CS_CONTEXT, MS_ERR_SYSTAB_VERSION, "Restore "CLOUD_TABLE_NAME" failed, incompatible table version" );
646
case MSBackupTable::tableID:
647
if (MSBackupTable::tableVersion == tab_version)
648
MSBackupTable::restoreTable(RETAIN(db), data, tab_size);
650
CSException::logException(CS_CONTEXT, MS_ERR_SYSTAB_VERSION, "Restore "BACKUP_TABLE_NAME" failed, incompatible table version" );
652
case MSVariableTable::tableID:
653
if (MSVariableTable::tableVersion == tab_version)
654
MSVariableTable::restoreTable(RETAIN(db), data, tab_size);
656
CSException::logException(CS_CONTEXT, MS_ERR_SYSTAB_VERSION, "Restore "VARIABLES_TABLE_NAME" failed, incompatible table version" );
666
CSException::logException(CS_CONTEXT, CS_ERR_GENERIC_ERROR, "PBMS trailing garbage in system table restore data being ignored.");
674
* -------------------------------------------------------------------------
678
void MSOpenSystemTable::setNotNullInRecord(Field *field, char *record)
682
record[(uint) (field->null_ptr - (uchar *) field->getTable()->getInsertRecord())] &= (uchar) ~field->null_bit;
685
record[(uint) (field->null_ptr - (uchar *) field->table->record[0])] &= (uchar) ~field->null_bit;
690
* -------------------------------------------------------------------------
694
MSOpenSystemTable::MSOpenSystemTable(MSSystemTableShare *share, TABLE *table):
701
MSOpenSystemTable::~MSOpenSystemTable()
703
MSSystemTableShare::releaseSystemTable(this);
708
* -------------------------------------------------------------------------
712
MSRepositoryTable::MSRepositoryTable(MSSystemTableShare *share, TABLE *table):
713
MSOpenSystemTable(share, table),
720
//-----------------------
721
MSRepositoryTable::~MSRepositoryTable()
726
iBlobBuffer->release();
729
//-----------------------
730
void MSRepositoryTable::use()
736
new_(iBlobBuffer, CSStringBuffer(20));
738
db = myShare->mySysDatabase;
739
if ((iCompactor = db->getCompactorThread())) {
740
if (iCompactor->isMe(self))
743
iCompactor->retain();
744
iCompactor->suspend();
750
//-----------------------
751
void MSRepositoryTable::unuse()
754
iCompactor->resume();
755
iCompactor->release();
759
iRepoFile->release();
763
iBlobBuffer->clear();
767
//-----------------------
768
void MSRepositoryTable::seqScanInit()
772
// Flush all committed transactions to the repository file.
773
MSTransactionManager::flush();
781
//-----------------------
782
bool MSRepositoryTable::resetScan(bool positioned, uint32_t repo_index)
785
if (iRepoFile && (repo_index != iRepoIndex)) {
786
iRepoFile->release();
790
iRepoIndex = repo_index;
796
MSRepository *repo = NULL;
797
CSSyncVector *repo_list = myShare->mySysDatabase->getRepositoryList();
800
for (; iRepoIndex<repo_list->size(); iRepoIndex++) {
801
if ((repo = (MSRepository *) repo_list->get(iRepoIndex))) {
802
iRepoFile = repo->openRepoFile();
810
iRepoFileSize = repo->getRepoFileSize();
811
if ((!iRepoOffset) || !positioned)
812
iRepoOffset = repo->getRepoHeadSize();
814
iRepoCurrentOffset = iRepoOffset;
819
//-----------------------
820
bool MSRepositoryTable::seqScanNext(char *buf)
824
iRepoCurrentOffset = iRepoOffset;
826
if (returnSubRecord(buf))
830
if ((!iRepoFile) && !MSRepositoryTable::resetScan(false))
833
while (iRepoOffset < iRepoFileSize) {
834
if (returnRecord(buf))
839
iRepoFile->release();
850
//-----------------------
851
int MSRepositoryTable::getRefLen()
853
return sizeof(iRepoIndex) + sizeof(iRepoOffset);
857
//-----------------------
858
void MSRepositoryTable::seqScanPos(unsigned char *pos)
860
mi_int4store(pos, iRepoIndex); pos +=4;
861
mi_int8store(pos, iRepoCurrentOffset);
864
//-----------------------
865
void MSRepositoryTable::seqScanRead(uint32_t repo, uint64_t offset, char *buf)
867
iRepoOffset = offset;
869
if (!resetScan(true, repo))
875
//-----------------------
876
void MSRepositoryTable::seqScanRead(unsigned char *pos, char *buf)
878
seqScanRead(mi_uint4korr( pos), mi_uint8korr(pos +4), buf);
881
//-----------------------
882
bool MSRepositoryTable::returnRecord(char *buf)
894
lock = iRepoFile->myRepo->getRepoLock(iRepoOffset);
896
if (iRepoFile->read(&blob, iRepoOffset, sizeof(MSBlobHeadRec), 0) < sizeof(MSBlobHeadRec)) {
898
iRepoOffset = iRepoFileSize;
901
head_size = CS_GET_DISK_2(blob.rb_head_size_2);
902
blob_size = CS_GET_DISK_6(blob.rb_blob_repo_size_6);
903
ref_size = CS_GET_DISK_1(blob.rb_ref_size_1);
904
ref_count = CS_GET_DISK_2(blob.rb_ref_count_2);
905
status = CS_GET_DISK_1(blob.rb_status_1);
906
if (ref_count <= 0 || ref_size == 0 ||
907
head_size < iRepoFile->myRepo->getRepoBlobHeadSize() + ref_count * ref_size ||
908
!VALID_BLOB_STATUS(status)) {
909
/* Can't be true. Assume this is garbage! */
915
if (IN_USE_BLOB_STATUS(status)) {
917
if (!returnRow(&blob, buf)) {
918
/* This record may not have had any data of interest. */
922
iRepoOffset += head_size + blob_size;
926
iRepoOffset += head_size + blob_size;
930
//-----------------------
931
bool MSRepositoryTable::returnSubRecord(char *)
936
//-----------------------
937
bool MSRepositoryTable::returnRow(MSBlobHeadPtr blob, char *buf)
939
TABLE *table = mySQLTable;
940
uint8_t storage_type;
941
uint32_t access_count;
942
uint32_t last_access;
944
uint32_t creation_time;
945
uint32_t access_code;
947
uint16_t alias_offset;
951
MY_BITMAP *save_write_set;
957
storage_type = CS_GET_DISK_1(blob->rb_storage_type_1);
958
last_access = CS_GET_DISK_4(blob->rb_last_access_4);
959
access_count = CS_GET_DISK_4(blob->rb_access_count_4);
960
last_ref = CS_GET_DISK_4(blob->rb_last_ref_4);
961
creation_time = CS_GET_DISK_4(blob->rb_create_time_4);
962
head_size = CS_GET_DISK_2(blob->rb_head_size_2);
963
blob_size = CS_GET_DISK_6(blob->rb_blob_repo_size_6);
964
access_code = CS_GET_DISK_4(blob->rb_auth_code_4);
965
alias_offset = CS_GET_DISK_2(blob->rb_alias_offset_2);
967
/* ASSERT_COLUMN_MARKED_FOR_WRITE is failing when
969
* But I want to use it! :(
971
save_write_set = table->write_set;
972
table->write_set = NULL;
975
memset(buf, 0xFF, table->getNullBytes());
977
memset(buf, 0xFF, table->s->null_bytes);
979
for (Field **field=GET_TABLE_FIELDS(table) ; *field ; field++) {
981
save = curr_field->ptr;
982
#if MYSQL_VERSION_ID < 50114
983
curr_field->ptr = (byte *) buf + curr_field->offset();
986
curr_field->ptr = (byte *) buf + curr_field->offset(curr_field->getTable()->getInsertRecord());
988
curr_field->ptr = (byte *) buf + curr_field->offset(curr_field->table->record[0]);
991
switch (curr_field->field_name[0]) {
993
switch (curr_field->field_name[9]) {
995
ASSERT(strcmp(curr_field->field_name, "Access_code") == 0);
996
curr_field->store(access_code, true);
997
setNotNullInRecord(curr_field, buf);
1000
ASSERT(strcmp(curr_field->field_name, "Access_count") == 0);
1001
curr_field->store(access_count, true);
1002
setNotNullInRecord(curr_field, buf);
1007
switch (curr_field->field_name[6]) {
1009
// Repository_id INT
1010
ASSERT(strcmp(curr_field->field_name, "Repository_id") == 0);
1011
curr_field->store(iRepoFile->myRepo->getRepoID(), true);
1012
setNotNullInRecord(curr_field, buf);
1015
// Repo_blob_offset BIGINT
1016
ASSERT(strcmp(curr_field->field_name, "Repo_blob_offset") == 0);
1017
curr_field->store(iRepoOffset, true);
1018
setNotNullInRecord(curr_field, buf);
1023
switch (curr_field->field_name[5]) {
1026
ASSERT(strcmp(curr_field->field_name, "Blob_size") == 0);
1027
curr_field->store(blob_size, true);
1028
setNotNullInRecord(curr_field, buf);
1032
ASSERT(strcmp(curr_field->field_name, "Blob_alias") == 0);
1033
#ifdef HAVE_ALIAS_SUPPORT
1035
char blob_alias[BLOB_ALIAS_LENGTH +1];
1039
lock = iRepoFile->myRepo->getRepoLock(iRepoOffset);
1041
rsize = iRepoFile->read(blob_alias, iRepoOffset + alias_offset, BLOB_ALIAS_LENGTH, 0);
1043
blob_alias[rsize] = 0;
1044
curr_field->store(blob_alias, strlen(blob_alias), &my_charset_utf8_general_ci);
1045
setNotNullInRecord(curr_field, buf);
1047
curr_field->store((uint64_t) 0, true);
1050
curr_field->store((uint64_t) 0, true);
1057
case 'M': // MD5_Checksum
1058
if (storage_type == MS_STANDARD_STORAGE) {
1059
char checksum[sizeof(Md5Digest) *2 +1];
1061
ASSERT(strcmp(curr_field->field_name, "MD5_Checksum") == 0);
1062
cs_bin_to_hex(sizeof(Md5Digest) *2 +1, checksum, sizeof(Md5Digest), &(blob->rb_blob_checksum_md5d));
1063
curr_field->store(checksum, sizeof(Md5Digest) *2, system_charset_info);
1064
setNotNullInRecord(curr_field, buf);
1067
curr_field->store((uint64_t) 0, true);
1071
// Head_size SMALLINT UNSIGNED
1072
ASSERT(strcmp(curr_field->field_name, "Head_size") == 0);
1073
curr_field->store(head_size, true);
1074
setNotNullInRecord(curr_field, buf);
1077
// Creation_time TIMESTAMP
1078
ASSERT(strcmp(curr_field->field_name, "Creation_time") == 0);
1079
curr_field->store(ms_my_1970_to_mysql_time(creation_time), true);
1080
setNotNullInRecord(curr_field, buf);
1083
switch (curr_field->field_name[5]) {
1085
// Last_ref_time TIMESTAMP
1086
ASSERT(strcmp(curr_field->field_name, "Last_ref_time") == 0);
1087
curr_field->store(ms_my_1970_to_mysql_time(last_ref), true);
1088
setNotNullInRecord(curr_field, buf);
1091
// Last_access_time TIMESTAMP
1092
ASSERT(strcmp(curr_field->field_name, "Last_access_time") == 0);
1093
curr_field->store(ms_my_1970_to_mysql_time(last_access), true);
1094
setNotNullInRecord(curr_field, buf);
1099
curr_field->ptr = save;
1102
table->write_set = save_write_set;
1107
* -------------------------------------------------------------------------
1110
//-----------------------
1111
MSBlobDataTable::MSBlobDataTable(MSSystemTableShare *share, TABLE *table):MSRepositoryTable(share, table)
1115
//-----------------------
1116
MSBlobDataTable::~MSBlobDataTable()
1120
//-----------------------
1121
bool MSBlobDataTable::returnRow(MSBlobHeadPtr blob, char *buf)
1123
TABLE *table = mySQLTable;
1130
MY_BITMAP *save_write_set;
1132
head_size = CS_GET_DISK_2(blob->rb_head_size_2);
1133
blob_size = CS_GET_DISK_6(blob->rb_blob_repo_size_6);
1134
blob_type = CS_GET_DISK_1(blob->rb_storage_type_1);
1136
/* ASSERT_COLUMN_MARKED_FOR_WRITE is failing when
1138
* But I want to use it! :(
1140
save_write_set = table->write_set;
1141
table->write_set = NULL;
1144
memset(buf, 0xFF, table->getNullBytes());
1146
memset(buf, 0xFF, table->s->null_bytes);
1148
for (Field **field=GET_TABLE_FIELDS(table) ; *field ; field++) {
1149
curr_field = *field;
1150
save = curr_field->ptr;
1151
#if MYSQL_VERSION_ID < 50114
1152
curr_field->ptr = (byte *) buf + curr_field->offset();
1155
curr_field->ptr = (byte *) buf + curr_field->offset(curr_field->getTable()->getInsertRecord());
1157
curr_field->ptr = (byte *) buf + curr_field->offset(curr_field->table->record[0]);
1160
switch (curr_field->field_name[0]) {
1162
switch (curr_field->field_name[6]) {
1164
// Repository_id INT
1165
ASSERT(strcmp(curr_field->field_name, "Repository_id") == 0);
1166
curr_field->store(iRepoFile->myRepo->getRepoID(), true);
1167
setNotNullInRecord(curr_field, buf);
1170
// Repo_blob_offset BIGINT
1171
ASSERT(strcmp(curr_field->field_name, "Repo_blob_offset") == 0);
1172
curr_field->store(iRepoOffset, true);
1173
setNotNullInRecord(curr_field, buf);
1178
// Blob_data LONGBLOB
1179
ASSERT(strcmp(curr_field->field_name, "Blob_data") == 0);
1180
if (blob_size <= 0xFFFFFFF) {
1181
iBlobBuffer->setLength((uint32_t) blob_size);
1182
if (BLOB_IN_REPOSITORY(blob_type)) {
1183
len = iRepoFile->read(iBlobBuffer->getBuffer(0), iRepoOffset + head_size, (size_t) blob_size, 0);
1185
CloudDB *blobCloud = myShare->mySysDatabase->myBlobCloud;
1187
ASSERT(blobCloud != NULL);
1189
MSRepoFile::getBlobKey(blob, &key);
1191
len = blobCloud->cl_getData(&key, iBlobBuffer->getBuffer(0), blob_size);
1193
((Field_blob *) curr_field)->set_ptr(len, (byte *) iBlobBuffer->getBuffer(0));
1194
setNotNullInRecord(curr_field, buf);
1198
curr_field->ptr = save;
1201
table->write_set = save_write_set;
1205
#ifdef HAVE_ALIAS_SUPPORT
1207
* -------------------------------------------------------------------------
1210
bool MSBlobAliasTable::returnRow(MSBlobHeadPtr blob, char *buf)
1212
TABLE *table = mySQLTable;
1215
MY_BITMAP *save_write_set;
1216
uint16_t alias_offset;
1217
char blob_alias[BLOB_ALIAS_LENGTH +1];
1222
alias_offset = CS_GET_DISK_2(blob->rb_alias_offset_2);
1227
lock = iRepoFile->myRepo->getRepoLock(iRepoOffset);
1229
rsize = iRepoFile->read(blob_alias, iRepoOffset + alias_offset, BLOB_ALIAS_LENGTH, 0);
1231
blob_alias[rsize] = 0;
1233
/* ASSERT_COLUMN_MARKED_FOR_WRITE is failing when
1235
* But I want to use it! :(
1237
save_write_set = table->write_set;
1238
table->write_set = NULL;
1241
memset(buf, 0xFF, table->getNullBytes());
1243
memset(buf, 0xFF, table->s->null_bytes);
1245
for (Field **field=GET_TABLE_FIELDS(table) ; *field ; field++) {
1246
curr_field = *field;
1247
save = curr_field->ptr;
1248
#if MYSQL_VERSION_ID < 50114
1249
curr_field->ptr = (byte *) buf + curr_field->offset();
1252
curr_field->ptr = (byte *) buf + curr_field->offset(curr_field->getTable()->getInsertRecord());
1254
curr_field->ptr = (byte *) buf + curr_field->offset(curr_field->table->record[0]);
1257
switch (curr_field->field_name[0]) {
1259
switch (curr_field->field_name[6]) {
1261
// Repository_id INT
1262
ASSERT(strcmp(curr_field->field_name, "Repository_id") == 0);
1263
curr_field->store(iRepoFile->myRepo->getRepoID(), true);
1264
setNotNullInRecord(curr_field, buf);
1267
// Repo_blob_offset BIGINT
1268
ASSERT(strcmp(curr_field->field_name, "Repo_blob_offset") == 0);
1269
curr_field->store(iRepoOffset, true);
1270
setNotNullInRecord(curr_field, buf);
1276
ASSERT(strcmp(curr_field->field_name, "Blob_alias") == 0);
1277
curr_field->store(blob_alias, strlen(blob_alias), &UTF8_CHARSET);
1278
setNotNullInRecord(curr_field, buf);
1282
curr_field->ptr = save;
1285
table->write_set = save_write_set;
1292
* -------------------------------------------------------------------------
1296
MSReferenceTable::MSReferenceTable(MSSystemTableShare *share, TABLE *table):
1297
MSRepositoryTable(share, table),
1302
iRefOpenTable(NULL),
1307
MSReferenceTable::~MSReferenceTable()
1310
cs_free(iRefDataList);
1312
iRefOpenTable->returnToPool();
1314
iRefTempLog->release();
1317
void MSReferenceTable::unuse()
1319
MSRepositoryTable::unuse();
1321
cs_free(iRefDataList);
1322
iRefDataList = NULL;
1325
if (iRefOpenTable) {
1326
iRefOpenTable->returnToPool();
1327
iRefOpenTable = NULL;
1330
iRefTempLog->release();
1336
void MSReferenceTable::seqScanInit()
1338
MSRepositoryTable::seqScanInit();
1343
int MSReferenceTable::getRefLen()
1345
return sizeof(iRefDataUsed) + sizeof(iRefDataPos) + sizeof(iRefCurrentIndex) + sizeof(iRefCurrentOffset);
1348
void MSReferenceTable::seqScanPos(unsigned char *pos)
1350
mi_int4store(pos, iRefCurrentDataPos); pos +=4;
1351
mi_int4store(pos, iRefCurrentDataUsed);pos +=4;
1352
mi_int4store(pos, iRefCurrentIndex); pos +=4;
1353
mi_int8store(pos, iRefCurrentOffset);
1356
void MSReferenceTable::seqScanRead(unsigned char *pos, char *buf)
1358
iRefDataPos = mi_uint4korr( pos); pos +=4;
1359
iRefDataUsed = mi_uint4korr(pos); pos +=4;
1360
iRefBlobRepo = mi_uint4korr(pos); pos +=4;
1361
iRefBlobOffset = mi_uint8korr(pos);
1362
MSRepositoryTable::seqScanRead(iRefBlobRepo, iRefBlobOffset, buf);
1365
bool MSReferenceTable::seqScanNext(char *buf)
1367
iRefCurrentDataPos = iRefDataPos;
1368
iRefCurrentDataUsed = iRefDataUsed;
1370
// Reset the position
1371
return MSRepositoryTable::seqScanNext(buf);
1373
// select * from pbms_reference order by blob_size DESC;
1374
// select * from pbms_reference order by Table_name DESC;
1376
bool MSReferenceTable::resetScan(bool positioned, uint32_t repo_index)
1382
MSRepoPointersRec ptr;
1390
if (!MSRepositoryTable::resetScan(positioned, repo_index))
1394
lock = iRepoFile->myRepo->getRepoLock(iRepoOffset);
1396
if (iRepoFile->read(&blob, iRepoOffset, sizeof(MSBlobHeadRec), 0) < sizeof(MSBlobHeadRec)) {
1398
iRepoOffset = iRepoFileSize;
1401
head_size = CS_GET_DISK_2(blob.rb_head_size_2);
1402
blob_size = CS_GET_DISK_6(blob.rb_blob_repo_size_6);
1403
ref_size = CS_GET_DISK_1(blob.rb_ref_size_1);
1404
ref_count = CS_GET_DISK_2(blob.rb_ref_count_2);
1405
status = CS_GET_DISK_1(blob.rb_status_1);
1406
if (ref_count <= 0 || ref_size == 0 ||
1407
head_size < iRepoFile->myRepo->getRepoBlobHeadSize() + ref_count * ref_size ||
1408
!VALID_BLOB_STATUS(status)) {
1409
/* Can't be true. Assume this is garbage! */
1415
if (IN_USE_BLOB_STATUS(status)) {
1416
iBlobBuffer->setLength((uint32_t) head_size);
1417
if (iRepoFile->read(iBlobBuffer->getBuffer(0), iRepoOffset, head_size, 0) < head_size) {
1419
iRepoOffset = iRepoFileSize;
1424
iRefAuthCode = CS_GET_DISK_4(blob.rb_auth_code_4);
1425
iRefBlobSize = CS_GET_DISK_6(blob.rb_blob_data_size_6);;
1426
iRefBlobRepo = iRepoFile->myRepo->getRepoID();
1427
iRefBlobOffset = iRepoOffset;
1429
if (ref_count > iRefDataSize) {
1430
cs_realloc((void **) &iRefDataList, sizeof(MSRefDataRec) * ref_count);
1431
iRefDataSize = ref_count;
1437
// When ever the data position is reset the current location information
1438
// must also be reset so that it is consisent with the data position.
1439
iRefCurrentDataPos = iRefDataPos;
1440
iRefCurrentOffset = iRepoOffset;
1441
iRefCurrentIndex = iRepoIndex;
1442
iRefCurrentDataUsed = iRefDataUsed = ref_count;
1443
memset(iRefDataList, 0, sizeof(MSRefDataRec) * ref_count);
1445
uint32_t h = iRepoFile->myRepo->getRepoBlobHeadSize();
1446
ptr.rp_chars = iBlobBuffer->getBuffer(0) + h;
1447
for (uint32_t i=0; i<ref_count; i++) {
1448
switch (CS_GET_DISK_2(ptr.rp_ref->rr_type_2)) {
1449
case MS_BLOB_FREE_REF:
1451
case MS_BLOB_TABLE_REF: // The blob is intended for a file but has not been inserted yet.
1452
iRefDataList[i].rd_tab_id = CS_GET_DISK_4(ptr.rp_tab_ref->tr_table_id_4);
1453
iRefDataList[i].rd_blob_id = CS_GET_DISK_6(ptr.rp_tab_ref->tr_blob_id_6);
1454
iRefDataList[i].rd_col_index = INVALID_INDEX; // Means not used
1456
case MS_BLOB_DELETE_REF:
1457
tab_index = CS_GET_DISK_2(ptr.rp_temp_ref->tp_del_ref_2);
1458
if (tab_index && (tab_index <= ref_count)) {
1460
iRefDataList[tab_index].rd_temp_log_id = CS_GET_DISK_4(ptr.rp_temp_ref->tp_log_id_4);
1461
iRefDataList[tab_index].rd_temp_log_offset = CS_GET_DISK_4(ptr.rp_temp_ref->tp_offset_4);
1463
else if (tab_index == INVALID_INDEX) {
1464
/* The is a reference from the temporary log only!! */
1465
iRefDataList[i].rd_tab_id = 0xFFFFFFFF; // Indicates no table
1466
iRefDataList[i].rd_blob_id = iRepoOffset;
1467
iRefDataList[i].rd_blob_ref_id = CS_GET_DISK_4(ptr.rp_temp_ref->tp_log_id_4);;
1468
iRefDataList[i].rd_col_index = INVALID_INDEX; // Means not used
1469
iRefDataList[i].rd_temp_log_id = CS_GET_DISK_4(ptr.rp_temp_ref->tp_log_id_4);
1470
iRefDataList[i].rd_temp_log_offset = CS_GET_DISK_4(ptr.rp_temp_ref->tp_offset_4);
1474
MSRepoTableRefPtr tab_ref;
1476
tab_index = CS_GET_DISK_2(ptr.rp_blob_ref->er_table_2)-1;
1477
if (tab_index < ref_count) {
1478
tab_ref = (MSRepoTableRefPtr) (iBlobBuffer->getBuffer(0) + iRepoFile->myRepo->getRepoBlobHeadSize() + tab_index * ref_size);
1480
iRefDataList[i].rd_tab_id = CS_GET_DISK_4(tab_ref->tr_table_id_4);
1481
iRefDataList[i].rd_blob_id = CS_GET_DISK_6(tab_ref->tr_blob_id_6);
1482
iRefDataList[i].rd_col_index = CS_GET_DISK_2(ptr.rp_blob_ref->er_col_index_2);
1483
iRefDataList[i].rd_blob_ref_id = COMMIT_MASK(CS_GET_DISK_8(ptr.rp_blob_ref->er_blob_ref_id_8));
1485
iRefDataList[tab_index].rd_ref_count++;
1488
/* Can't be true. Assume this is garbage! */
1495
ptr.rp_chars += ref_size;
1498
iRepoOffset += head_size + blob_size;
1503
iRepoOffset += head_size + blob_size;
1507
bool MSReferenceTable::returnRecord(char *buf)
1509
if (!resetScan(false))
1512
return(returnSubRecord(buf));
1515
bool MSReferenceTable::returnSubRecord(char *buf)
1519
while (iRefDataPos < iRefDataUsed) {
1521
if (iRefDataList[i].rd_tab_id) {
1522
if (iRefDataList[i].rd_col_index == INVALID_INDEX) {
1523
/* This is a table reference */
1524
if (!iRefDataList[i].rd_ref_count || iRefDataList[i].rd_temp_log_id) {
1525
returnRow(&iRefDataList[i], buf);
1530
/* This is an engine reference */
1531
returnRow(&iRefDataList[i], buf);
1540
void MSReferenceTable::returnRow(MSRefDataPtr ref_data, char *buf)
1542
TABLE *table = mySQLTable;
1545
MY_BITMAP *save_write_set;
1546
MY_BITMAP *save_read_set;
1547
bool have_times = false;
1549
int32_t countdown = 0;
1551
if (iRefOpenTable) {
1552
if (iRefOpenTable->getDBTable()->myTableID != ref_data->rd_tab_id) {
1553
iRefOpenTable->returnToPool();
1554
iRefOpenTable = NULL;
1558
if (!iRefOpenTable && ref_data->rd_tab_id != 0xFFFFFFFF)
1559
iRefOpenTable = MSTableList::getOpenTableByID(myShare->mySysDatabase->myDatabaseID, ref_data->rd_tab_id);
1561
if (ref_data->rd_temp_log_id) {
1563
if (iRefTempLog->myTempLogID != ref_data->rd_temp_log_id) {
1564
iRefTempLog->release();
1569
iRefTempLog = myShare->mySysDatabase->openTempLogFile(ref_data->rd_temp_log_id, NULL, NULL);
1572
MSTempLogItemRec log_item;
1574
if (iRefTempLog->read(&log_item, ref_data->rd_temp_log_offset, sizeof(MSTempLogItemRec), 0) == sizeof(MSTempLogItemRec)) {
1576
delete_time = CS_GET_DISK_4(log_item.ti_time_4);
1577
countdown = (int32_t) (delete_time + PBMSParameters::getTempBlobTimeout()) - (int32_t) time(NULL);
1582
if (ref_data->rd_col_index != INVALID_INDEX) {
1583
if (iRefOpenTable) {
1584
if (iRefOpenTable->getDBTable()->isToDelete()) {
1586
iRefOpenTable->getDBTable()->getDeleteInfo(&ref_data->rd_temp_log_id, &ref_data->rd_temp_log_offset, &delete_time);
1587
ref_data->rd_col_index = INVALID_INDEX;
1588
countdown = (int32_t) (delete_time + PBMSParameters::getTempBlobTimeout()) - (int32_t) time(NULL);
1592
ref_data->rd_col_index = INVALID_INDEX;
1595
save_write_set = table->write_set;
1596
save_read_set = table->read_set;
1597
table->write_set = NULL;
1598
table->read_set = NULL;
1601
memset(buf, 0xFF, table->getNullBytes());
1603
memset(buf, 0xFF, table->s->null_bytes);
1605
for (Field **field=GET_TABLE_FIELDS(table) ; *field ; field++) {
1606
curr_field = *field;
1607
save = curr_field->ptr;
1608
#if MYSQL_VERSION_ID < 50114
1609
curr_field->ptr = (byte *) buf + curr_field->offset();
1612
curr_field->ptr = (byte *) buf + curr_field->offset(curr_field->getTable()->getInsertRecord());
1614
curr_field->ptr = (byte *) buf + curr_field->offset(curr_field->table->record[0]);
1617
switch (curr_field->field_name[0]) {
1619
switch (curr_field->field_name[5]) {
1622
ASSERT(strcmp(curr_field->field_name, "Blob_id") == 0);
1623
if (ref_data->rd_tab_id == 0xFFFFFFFF)
1624
curr_field->store(0, true);
1626
curr_field->store(ref_data->rd_blob_id, true);
1627
setNotNullInRecord(curr_field, buf);
1631
// Blob_url VARCHAR(120),
1632
PBMSBlobURLRec blob_url;
1634
ASSERT(strcmp(curr_field->field_name, "Blob_url") == 0);
1635
if (ref_data->rd_tab_id != 0xFFFFFFFF) {
1636
iRefOpenTable->formatBlobURL(&blob_url, ref_data->rd_blob_id, iRefAuthCode, iRefBlobSize, ref_data->rd_blob_ref_id);
1637
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.
1638
setNotNullInRecord(curr_field, buf);
1642
// Blob_size BIGINT,
1643
ASSERT(strcmp(curr_field->field_name, "Blob_size") == 0);
1644
curr_field->store(iRefBlobSize, true);
1645
setNotNullInRecord(curr_field, buf);
1650
// Column_ordinal INT,
1651
ASSERT(strcmp(curr_field->field_name, "Column_ordinal") == 0);
1652
if (ref_data->rd_col_index != INVALID_INDEX) {
1653
curr_field->store(ref_data->rd_col_index +1, true);
1654
setNotNullInRecord(curr_field, buf);
1658
// Deletion_time TIMESTAMP,
1659
ASSERT(strcmp(curr_field->field_name, "Deletion_time") == 0);
1661
curr_field->store(ms_my_1970_to_mysql_time(delete_time), true);
1662
setNotNullInRecord(curr_field, buf);
1666
switch (curr_field->field_name[5]) {
1668
// Repository_id INT,
1669
ASSERT(strcmp(curr_field->field_name, "Repository_id") == 0);
1670
curr_field->store(iRefBlobRepo, true);
1671
setNotNullInRecord(curr_field, buf);
1674
// Repo_blob_offset BIGINT,
1675
ASSERT(strcmp(curr_field->field_name, "Repo_blob_offset") == 0);
1676
curr_field->store(iRefBlobOffset, true);
1677
setNotNullInRecord(curr_field, buf);
1681
ASSERT(strcmp(curr_field->field_name, "Remove_in") == 0);
1683
curr_field->store(countdown, false);
1684
setNotNullInRecord(curr_field, buf);
1690
switch (curr_field->field_name[9]) {
1692
// Table_name CHAR(64),
1693
ASSERT(strcmp(curr_field->field_name, "Table_name") == 0);
1694
if (ref_data->rd_tab_id != 0xFFFFFFFF) {
1695
if (iRefOpenTable) {
1696
CSString *table_name = iRefOpenTable->getDBTable()->getTableName();
1697
curr_field->store(table_name->getCString(), table_name->length(), &UTF8_CHARSET);
1700
char buffer[MS_TABLE_NAME_SIZE];
1702
snprintf(buffer, MS_TABLE_NAME_SIZE, "Table #%"PRIu32"", ref_data->rd_tab_id);
1703
curr_field->store(buffer, strlen(buffer), &UTF8_CHARSET);
1705
setNotNullInRecord(curr_field, buf);
1710
ASSERT(strcmp(curr_field->field_name, "Temp_log_id") == 0);
1711
if (ref_data->rd_temp_log_id) {
1712
curr_field->store(ref_data->rd_temp_log_id, true);
1713
setNotNullInRecord(curr_field, buf);
1717
// Temp_log_offset BIGINT
1718
ASSERT(strcmp(curr_field->field_name, "Temp_log_offset") == 0);
1719
if (ref_data->rd_temp_log_id) {
1720
curr_field->store(ref_data->rd_temp_log_offset, true);
1721
setNotNullInRecord(curr_field, buf);
1727
curr_field->ptr = save;
1730
table->write_set = save_write_set;
1731
table->read_set = save_read_set;
1735
* -------------------------------------------------------------------------
1738
MSMetaDataTable::MSMetaDataTable(MSSystemTableShare *share, TABLE *table):
1739
MSRepositoryTable(share, table),
1741
iMetCurrentBlobRepo(0),
1742
iMetCurrentBlobOffset(0),
1743
iMetCurrentDataPos(0),
1744
iMetCurrentDataSize(0),
1749
iMetStateSaved(false)
1753
MSMetaDataTable::~MSMetaDataTable()
1756
iMetData->release();
1761
MSMetaDataTable *MSMetaDataTable::newMSMetaDataTable(MSDatabase *db)
1763
char path[PATH_MAX];
1765
cs_strcpy(PATH_MAX, path, db->myDatabasePath->getCString());
1767
cs_add_dir_char(PATH_MAX, path);
1768
cs_strcat(PATH_MAX, path, sysTableNames[SYS_META]);
1770
return (MSMetaDataTable*) MSSystemTableShare::openSystemTable(path, NULL);
1773
void MSMetaDataTable::use()
1775
MSRepositoryTable::use();
1776
new_(iMetData, CSStringBuffer(80));
1780
void MSMetaDataTable::unuse()
1782
MSRepositoryTable::unuse();
1784
iMetData->release();
1791
void MSMetaDataTable::seqScanInit()
1793
MSRepositoryTable::seqScanInit();
1798
iMetStateSaved = false;
1801
void MSMetaDataTable::seqScanReset()
1803
seqScanPos(iMetState);
1805
iMetStateSaved = true;
1808
int MSMetaDataTable::getRefLen()
1810
return sizeof(iMetCurrentDataPos) + sizeof(iMetCurrentDataSize) + sizeof(iMetCurrentBlobRepo) + sizeof(iMetCurrentBlobOffset);
1813
void MSMetaDataTable::seqScanPos(unsigned char *pos)
1815
mi_int4store(pos, iMetCurrentDataPos); pos +=4;
1816
mi_int4store(pos, iMetCurrentDataSize);pos +=4;
1817
mi_int4store(pos, iMetCurrentBlobRepo); pos +=4;
1818
mi_int8store(pos, iMetCurrentBlobOffset);
1821
void MSMetaDataTable::seqScanRead(unsigned char *pos, char *buf)
1823
iMetStateSaved = false;
1824
iMetDataPos = mi_uint4korr( pos); pos +=4;
1825
iMetDataSize = mi_uint4korr(pos); pos +=4;
1826
iMetBlobRepo = mi_uint4korr(pos); pos +=4;
1827
iMetBlobOffset = mi_uint8korr(pos);
1828
MSRepositoryTable::seqScanRead(iMetBlobRepo, iMetBlobOffset, buf);
1831
bool MSMetaDataTable::seqScanNext(char *buf)
1833
if (iMetStateSaved) {
1835
uint8_t *pos = iMetState;
1836
iMetDataPos = mi_uint4korr( pos); pos +=4;
1837
// Do not reset the meta data size.
1838
/*iMetDataSize = mi_uint4korr(pos); */pos +=4;
1839
iMetBlobRepo = mi_uint4korr(pos); pos +=4;
1840
iMetBlobOffset = mi_uint8korr(pos);
1841
iMetStateSaved = false;
1842
resetScan(true, &have_data, iMetBlobRepo);
1845
iMetCurrentDataPos = iMetDataPos;
1846
iMetCurrentDataSize = iMetDataSize;
1848
return MSRepositoryTable::seqScanNext(buf);
1851
bool MSMetaDataTable::resetScan(bool positioned, bool *have_data, uint32_t repo_index)
1857
size_t mdata_size, mdata_offset;
1863
if (!MSRepositoryTable::resetScan(positioned, repo_index))
1867
lock = iRepoFile->myRepo->getRepoLock(iRepoOffset);
1869
if (iRepoFile->read(&blob, iRepoOffset, sizeof(MSBlobHeadRec), 0) < sizeof(MSBlobHeadRec)) {
1871
iRepoOffset = iRepoFileSize;
1875
head_size = CS_GET_DISK_2(blob.rb_head_size_2);
1876
blob_size = CS_GET_DISK_6(blob.rb_blob_repo_size_6);
1877
mdata_size = CS_GET_DISK_2(blob.rb_mdata_size_2);
1878
mdata_offset = CS_GET_DISK_2(blob.rb_mdata_offset_2);
1880
status = CS_GET_DISK_1(blob.rb_status_1);
1881
if ((head_size < (mdata_offset + mdata_size)) || !VALID_BLOB_STATUS(status)) {
1882
/* Can't be true. Assume this is garbage! */
1888
if (mdata_size && IN_USE_BLOB_STATUS(status)) {
1889
iMetData->setLength((uint32_t) mdata_size);
1890
if (iRepoFile->read(iMetData->getBuffer(0), iRepoOffset + mdata_offset, mdata_size, 0) < mdata_size) {
1892
iRepoOffset = iRepoFileSize;
1896
iMetBlobRepo = iRepoFile->myRepo->getRepoID();
1897
iMetBlobOffset = iRepoOffset;
1902
iMetDataSize = mdata_size;
1904
// When ever the data position is reset the current location information
1905
// must also be reset to that it is consisent with the data position.
1906
iMetCurrentBlobOffset = iRepoOffset;
1907
iMetCurrentBlobRepo = iRepoIndex;
1908
iMetCurrentDataPos = iMetDataPos;
1909
iMetCurrentDataSize = iMetDataSize;
1914
iRepoOffset += head_size + blob_size;
1918
bool MSMetaDataTable::returnRecord(char *buf)
1920
bool have_data = false;
1922
if (resetScan(false, &have_data) && have_data)
1923
return(returnSubRecord(buf));
1928
bool MSMetaDataTable::nextRecord(char **name, char **value)
1930
if (iMetDataPos < iMetDataSize) {
1931
char *data = iMetData->getBuffer(iMetDataPos);
1934
data += strlen(*name) +1;
1936
data += strlen(*value) +1;
1938
iMetDataPos += data - *name;
1939
ASSERT(iMetDataPos <= iMetDataSize);
1948
bool MSMetaDataTable::returnSubRecord(char *buf)
1952
if (nextRecord(&name, &value)) {
1953
returnRow(name, value, buf);
1960
void MSMetaDataTable::returnRow(char *name, char *value, char *buf)
1962
TABLE *table = mySQLTable;
1965
MY_BITMAP *save_write_set;
1967
save_write_set = table->write_set;
1968
table->write_set = NULL;
1971
memset(buf, 0xFF, table->getNullBytes());
1973
memset(buf, 0xFF, table->s->null_bytes);
1975
for (Field **field=GET_TABLE_FIELDS(table) ; *field ; field++) {
1976
curr_field = *field;
1977
save = curr_field->ptr;
1978
#if MYSQL_VERSION_ID < 50114
1979
curr_field->ptr = (byte *) buf + curr_field->offset();
1982
curr_field->ptr = (byte *) buf + curr_field->offset(curr_field->getTable()->getInsertRecord());
1984
curr_field->ptr = (byte *) buf + curr_field->offset(curr_field->table->record[0]);
1987
switch (curr_field->field_name[0]) {
1989
switch (curr_field->field_name[6]) {
1991
// Repository_id INT
1992
ASSERT(strcmp(curr_field->field_name, "Repository_id") == 0);
1993
curr_field->store(iRepoFile->myRepo->getRepoID(), true);
1994
setNotNullInRecord(curr_field, buf);
1997
// Repo_blob_offset BIGINT
1998
ASSERT(strcmp(curr_field->field_name, "Repo_blob_offset") == 0);
1999
curr_field->store(iMetCurrentBlobOffset, true);
2000
setNotNullInRecord(curr_field, buf);
2006
ASSERT(strcmp(curr_field->field_name, "Name") == 0);
2007
curr_field->store(name, strlen(name), &UTF8_CHARSET);
2008
setNotNullInRecord(curr_field, buf);
2012
ASSERT(strcmp(curr_field->field_name, "Value") == 0);
2013
curr_field->store(value, strlen(value), &my_charset_utf8_bin);
2014
setNotNullInRecord(curr_field, buf);
2017
curr_field->ptr = save;
2020
table->write_set = save_write_set;
2024
#ifdef HAVE_ALIAS_SUPPORT
2025
bool MSMetaDataTable::matchAlias(uint32_t repo_id, uint64_t offset, const char *alias)
2027
bool matched = false, have_data = false;
2030
if (resetScan(true, &have_data, repo_id) && have_data) {
2031
const char *blob_alias;
2032
MetaData md(iMetData->getBuffer(0), iMetDataSize);
2034
blob_alias = md.findAlias();
2035
matched = (blob_alias && !UTF8_CHARSET.strcasecmp(blob_alias, alias));
2042
void MSMetaDataTable::insertRow(char *buf)
2044
uint32_t repo_index;
2045
String meta_name, meta_value;
2047
uint64_t repo_offset;
2049
bool have_data, reset_alias = false;
2053
// Metadata inserts are ignored during reovery.
2054
// They will be restored from the dump table.
2055
if (myShare->mySysDatabase->isRecovering())
2060
getFieldValue(buf, 0, &repo_index);
2061
getFieldValue(buf, 1, &repo_offset);
2062
getFieldValue(buf, 2, &meta_name);
2063
getFieldValue(buf, 3, &meta_value);
2066
CSException::throwException(CS_CONTEXT, HA_ERR_CANNOT_ADD_FOREIGN, "Invalid Repository_id");
2068
iRepoOffset = repo_offset;
2069
if (!resetScan(true, &have_data, repo_index -1))
2070
CSException::throwException(CS_CONTEXT, HA_ERR_CANNOT_ADD_FOREIGN, "Invalid Repository_id or Repo_blob_offset");
2072
const char *alias = NULL, *tag = meta_name.c_str();
2075
MetaData md(iMetData->getBuffer(0), iMetDataSize);
2076
// Check to see it this is a duplicate name.
2077
if (md.findName(tag))
2078
CSException::throwException(CS_CONTEXT, HA_ERR_FOUND_DUPP_KEY, "Meta data tag already exists.");
2080
#ifdef HAVE_ALIAS_SUPPORT
2081
alias = md.findAlias();
2085
// Create the meta data record.
2086
#ifdef HAVE_ALIAS_SUPPORT
2088
data = iMetData->getBuffer(0); // This is to be able to test if the alias pointer needs to be reset.
2093
iMetData->setLength(iMetDataSize + meta_name.length() + meta_value.length() + 2);
2095
#ifdef HAVE_ALIAS_SUPPORT
2096
if (alias && (data != iMetData->getBuffer(0))) // The buffer moved, adjust the alias.
2097
alias += (iMetData->getBuffer(0) - data);
2100
data = iMetData->getBuffer(0);
2101
data_len = iMetDataSize;
2103
#ifdef HAVE_ALIAS_SUPPORT
2104
if ((!alias) && !UTF8_CHARSET.strcasecmp(MS_ALIAS_TAG, tag)) {
2106
memcpy(data + data_len, MS_ALIAS_TAG, meta_name->length()); // Use my alias tag so we do not need to wory about case.
2107
alias = data + data_len + meta_name->length() + 1; // Set the alias to the value location.
2110
memcpy(data + data_len, meta_name.data(), meta_name.length());
2112
data_len += meta_name.length();
2116
memcpy(data + data_len, meta_value.data(), meta_value.length());
2117
data_len += meta_value.length();
2121
// Update the blob header with the new meta data.
2122
MSOpenTable *otab = MSOpenTable::newOpenTable(NULL);
2124
iRepoFile->setBlobMetaData(otab, repo_offset, data, data_len, reset_alias, alias);
2130
insert into pbms_mata_data values(1, 921, "ATAG 3", "xx");
2131
insert into pbms_mata_data values(1, 921, "ATAG 1", "A VALUE 1");
2132
insert into pbms_mata_data values(1, 921, "ATAG 2", "xx");
2133
insert into pbms_mata_data values(1, 383, "ATAG 2", "xx");
2134
select * from pbms_mata_data;
2136
delete from pbms_mata_data where value = "xx";
2137
select * from pbms_mata_data;
2139
update pbms_mata_data set value = "!!" where name = "ATAG 3";
2140
update pbms_mata_data set Repo_blob_offset = 383 where value = "!!";
2142
delete from pbms_mata_data where Repo_blob_offset = 921;
2144
//insert into pbms_mata_data values(1, 921, "blob_ALIAs", "My_alias");
2145
//select * from pbms_mata_data;
2146
//select * from pbms_repository;
2149
void MSMetaDataTable::deleteRow(char *buf)
2151
uint32_t repo_index;
2152
String meta_name, meta_value;
2153
uint16_t record_size;
2154
uint64_t repo_offset;
2156
bool have_data, reset_alias = false;
2162
getFieldValue(buf, 0, &repo_index);
2163
getFieldValue(buf, 1, &repo_offset);
2164
getFieldValue(buf, 2, &meta_name);
2165
getFieldValue(buf, 3, &meta_value);
2168
CSException::throwException(CS_CONTEXT, HA_ERR_CANNOT_ADD_FOREIGN, "Invalid Repository_id");
2170
iRepoOffset = repo_offset;
2171
if (!resetScan(true, &have_data, repo_index -1))
2172
CSException::throwException(CS_CONTEXT, HA_ERR_CANNOT_ADD_FOREIGN, "Invalid Repository_id or Repo_blob_offset");
2174
const char *alias = NULL, *value = NULL, *tag = meta_name.c_str();
2177
// Check to see name exists.
2180
md.use_data(iMetData->getBuffer(0), iMetDataSize);
2182
value = md.findName(tag);
2185
CSException::throwException(CS_CONTEXT, HA_ERR_KEY_NOT_FOUND, "Meta data tag dosn't exists.");
2187
#ifdef HAVE_ALIAS_SUPPORT
2188
alias = md.findAlias();
2190
if (alias == value) {
2196
// Create the meta data record.
2197
data = md.getBuffer();
2198
location = md.findNamePosition(tag);
2199
record_size = MetaData::recSize(location);
2200
iMetDataSize -= record_size;
2201
memmove(location, location + record_size, iMetDataSize - (location - data)); // Shift the meta data down
2203
#ifdef HAVE_ALIAS_SUPPORT
2204
// Get the alias again incase it moved.
2206
alias = md.findAlias();
2209
// Update the blob header with the new meta data.
2210
MSOpenTable *otab = MSOpenTable::newOpenTable(NULL);
2212
iRepoFile->setBlobMetaData(otab, repo_offset, data, iMetDataSize, reset_alias, alias);
2218
class UpdateRowCleanUp : public CSRefObject {
2220
MSMetaDataTable *tab;
2227
UpdateRowCleanUp(): CSRefObject(),
2228
do_cleanup(false), tab(NULL), row_data(NULL){}
2233
tab->deleteRow(row_data);
2237
void setCleanUp(MSMetaDataTable *table, char *data)
2244
void cancelCleanUp()
2251
void MSMetaDataTable::updateRow(char *old_data, char *new_data)
2253
uint32_t o_repo_index, n_repo_index;
2254
String n_meta_name, n_meta_value;
2255
String o_meta_name, o_meta_value;
2256
uint16_t record_size;
2257
uint64_t o_repo_offset, n_repo_offset;
2259
bool have_data, reset_alias = false;
2265
getFieldValue(new_data, 0, &n_repo_index);
2266
getFieldValue(new_data, 1, &n_repo_offset);
2267
getFieldValue(new_data, 2, &n_meta_name);
2268
getFieldValue(new_data, 3, &n_meta_value);
2270
getFieldValue(old_data, 0, &o_repo_index);
2271
getFieldValue(old_data, 1, &o_repo_offset);
2272
getFieldValue(old_data, 2, &o_meta_name);
2273
getFieldValue(old_data, 3, &o_meta_value);
2275
if ((!o_repo_index) || (!n_repo_index))
2276
CSException::throwException(CS_CONTEXT, HA_ERR_CANNOT_ADD_FOREIGN, "Invalid Repository_id");
2278
// If the meta data is not for the same BLOB then we do an insert and delete.
2279
if ((n_repo_index != o_repo_index) || (n_repo_offset != o_repo_offset)) {
2280
UpdateRowCleanUp *cleanup;
2281
new_(cleanup, UpdateRowCleanUp());
2284
insertRow(new_data);
2286
cleanup->setCleanUp(this, new_data);
2288
deleteRow(old_data);
2290
cleanup->cancelCleanUp();
2296
iRepoOffset = n_repo_offset;
2297
if (!resetScan(true, &have_data, n_repo_index -1))
2298
CSException::throwException(CS_CONTEXT, HA_ERR_CANNOT_ADD_FOREIGN, "Invalid Repository_id or Repo_blob_offset");
2301
const char *value, *alias = NULL, *n_tag = n_meta_name.c_str(), *o_tag = o_meta_name.c_str();
2303
if (!UTF8_CHARSET.strcasecmp(o_tag, n_tag))
2308
md.use_data(iMetData->getBuffer(0), iMetDataSize);
2310
if ((!iMetDataSize) || ((value = md.findName(o_tag)) == NULL))
2311
CSException::throwException(CS_CONTEXT, HA_ERR_KEY_NOT_FOUND, "Meta data tag dosn't exists.");
2313
if (n_tag && (md.findName(n_tag) != NULL))
2314
CSException::throwException(CS_CONTEXT, HA_ERR_FOUND_DUPP_KEY, "Meta data tag already exists.");
2316
#ifdef HAVE_ALIAS_SUPPORT
2317
alias = md.findAlias();
2319
if (alias == value) {
2321
alias = NULL; // The alias is being deleted.
2328
// Create the meta data record.
2329
data = md.getBuffer();
2330
location = md.findNamePosition(o_tag);
2331
record_size = MetaData::recSize(location);
2332
iMetDataSize -= record_size;
2333
memmove(location, location + record_size, iMetDataSize - (location - data)); // Shift the meta data down
2335
// Add the updated meta data to the end of the block.
2336
iMetData->setLength(iMetDataSize + n_meta_name.length() + n_meta_value.length() + 2);
2338
md.use_data(iMetData->getBuffer(0), iMetDataSize); // Reset this incase the buffer moved.
2339
#ifdef HAVE_ALIAS_SUPPORT
2340
// Get the alias again incase it moved.
2342
alias = md.findAlias();
2345
data = iMetData->getBuffer(0);
2347
#ifdef HAVE_ALIAS_SUPPORT
2348
if ((!alias) && !UTF8_CHARSET.strcasecmp(MS_ALIAS_TAG, n_tag)) {
2350
memcpy(data + iMetDataSize, MS_ALIAS_TAG, n_meta_name.length()); // Use my alias tag so we do not need to wory about case.
2351
alias = data + iMetDataSize + n_meta_name.length() + 1; // Set the alias to the value location.
2354
memcpy(data + iMetDataSize, n_meta_name.data(), n_meta_name.length());
2356
iMetDataSize += n_meta_name.length();
2357
data[iMetDataSize] = 0;
2360
memcpy(data + iMetDataSize, n_meta_value.data(), n_meta_value.length());
2361
iMetDataSize += n_meta_value.length();
2362
data[iMetDataSize] = 0;
2366
// Update the blob header with the new meta data.
2367
MSOpenTable *otab = MSOpenTable::newOpenTable(NULL);
2369
iRepoFile->setBlobMetaData(otab, n_repo_offset, data, iMetDataSize, reset_alias, alias);
2376
* -------------------------------------------------------------------------
2377
* SYSTEM TABLE SHARES
2380
CSSyncSortedList *MSSystemTableShare::gSystemTableList;
2382
MSSystemTableShare::MSSystemTableShare():
2385
mySysDatabase(NULL),
2388
thr_lock_init(&myThrLock);
2391
MSSystemTableShare::~MSSystemTableShare()
2394
thr_lock_delete(&myThrLock);
2397
myTablePath->release();
2400
if (mySysDatabase) {
2401
mySysDatabase->release();
2402
mySysDatabase = NULL;
2406
CSObject *MSSystemTableShare::getKey()
2408
return (CSObject *) myTablePath;
2411
int MSSystemTableShare::compareKey(CSObject *key)
2413
return myTablePath->compare((CSString *) key);
2416
void MSSystemTableShare::startUp()
2418
new_(gSystemTableList, CSSyncSortedList);
2421
void MSSystemTableShare::shutDown()
2423
if (gSystemTableList) {
2424
gSystemTableList->release();
2425
gSystemTableList = NULL;
2429
MSOpenSystemTable *MSSystemTableShare::openSystemTable(const char *table_path, TABLE *table)
2431
CSString *table_url;
2432
MSSystemTableShare *share;
2433
MSOpenSystemTable *otab = NULL;
2434
SysTableType table_type;
2438
table_type = pbms_systable_type(cs_last_name_of_path(table_path));
2439
if (table_type == SYS_UNKNOWN)
2440
CSException::throwException(CS_CONTEXT, MS_ERR_UNKNOWN_TABLE, "Table not found");
2442
table_path = cs_last_name_of_path(table_path, 2);
2443
table_url = CSString::newString(table_path);
2446
lock_(gSystemTableList);
2447
if (!(share = (MSSystemTableShare *) gSystemTableList->find(table_url))) {
2448
share = MSSystemTableShare::newTableShare(RETAIN(table_url));
2449
gSystemTableList->add(share);
2452
switch (table_type) {
2454
new_(otab, MSRepositoryTable(share, table));
2457
new_(otab, MSReferenceTable(share, table));
2460
new_(otab, MSBlobDataTable(share, table));
2463
new_(otab, MSDumpTable(share, table));
2466
new_(otab, MSMetaDataTable(share, table));
2469
new_(otab, MSHTTPHeaderTable(share, table));
2471
#ifdef HAVE_ALIAS_SUPPORT
2473
new_(otab, MSBlobAliasTable(share, table));
2477
new_(otab, MSVariableTable(share, table));
2480
new_(otab, MSCloudTable(share, table));
2483
new_(otab, MSBackupTable(share, table));
2487
new_(otab, MSEnabledTable(share, table));
2494
share->iOpenCount++;
2495
unlock_(gSystemTableList);
2497
release_(table_url);
2501
void MSSystemTableShare::removeDatabaseSystemTables(MSDatabase *doomed_db)
2503
MSSystemTableShare *share;
2508
lock_(gSystemTableList);
2509
while ((share = (MSSystemTableShare *) gSystemTableList->itemAt(i))) {
2510
if (share->mySysDatabase == doomed_db) {
2511
gSystemTableList->remove(share->myTablePath);
2516
unlock_(gSystemTableList);
2517
release_(doomed_db);
2521
void MSSystemTableShare::releaseSystemTable(MSOpenSystemTable *tab)
2524
lock_(gSystemTableList);
2525
tab->myShare->iOpenCount--;
2526
if (!tab->myShare->iOpenCount) {
2527
gSystemTableList->remove(tab->myShare->myTablePath);
2529
unlock_(gSystemTableList);
2533
MSSystemTableShare *MSSystemTableShare::newTableShare(CSString *table_path)
2535
MSSystemTableShare *tab;
2538
if (!(tab = new MSSystemTableShare())) {
2539
table_path->release();
2540
CSException::throwOSError(CS_CONTEXT, ENOMEM);
2543
tab->myTablePath = table_path;
2544
tab->mySysDatabase = MSDatabase::getDatabase(table_path->left("/", -1), true);
2549
void PBMSSystemTables::systemTablesStartUp()
2551
MSCloudTable::startUp();
2552
MSBackupTable::startUp();
2555
void PBMSSystemTables::systemTableShutDown()
2557
MSBackupTable::shutDown();
2558
MSCloudTable::shutDown();