~drizzle-trunk/drizzle/development

« back to all changes in this revision

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

  • Committer: Brian Aker
  • Date: 2011-12-13 03:21:35 UTC
  • mto: This revision was merged to the branch mainline in revision 2475.
  • Revision ID: brian@tangent.org-20111213032135-8dta0336wn38uok9
Rmove PBMS (deprecated)

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/* Copyright (C) 2008 PrimeBase Technologies GmbH, Germany
2
 
 *
3
 
 * PrimeBase Media Stream for MySQL
4
 
 *
5
 
 * This program is free software; you can redistribute it and/or modify
6
 
 * it under the terms of the GNU General Public License as published by
7
 
 * the Free Software Foundation; either version 2 of the License, or
8
 
 * (at your option) any later version.
9
 
 *
10
 
 * This program is distributed in the hope that it will be useful,
11
 
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12
 
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13
 
 * GNU General Public License for more details.
14
 
 *
15
 
 * You should have received a copy of the GNU General Public License
16
 
 * along with this program; if not, write to the Free Software
17
 
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
18
 
 *
19
 
 * Original author: Paul McCullagh
20
 
 * Continued development: Barry Leslie
21
 
 *
22
 
 * 2007-07-18
23
 
 *
24
 
 * H&G2JCtL
25
 
 *
26
 
 * System tables.
27
 
 *
28
 
 */
29
 
 
30
 
#ifdef DRIZZLED
31
 
#include <config.h>
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>
37
 
 
38
 
#include <drizzled/message/table.pb.h>
39
 
#include <drizzled/charset.h>
40
 
#include <drizzled/table_proto.h>
41
 
#endif
42
 
 
43
 
 
44
 
#include "cslib/CSConfig.h"
45
 
#include <inttypes.h>
46
 
 
47
 
#include <sys/types.h>
48
 
#include <sys/stat.h>
49
 
#include <stdlib.h>
50
 
#include <time.h>
51
 
 
52
 
//#include "mysql_priv.h"
53
 
//#include <plugin.h>
54
 
 
55
 
#include "cslib/CSGlobal.h"
56
 
#include "cslib/CSStrUtil.h"
57
 
#include "ha_pbms.h"
58
 
 
59
 
#include "mysql_ms.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
68
 
#include "alias_ms.h"
69
 
#endif
70
 
#include "cloud_ms.h"
71
 
#include "transaction_ms.h"
72
 
 
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"
78
 
#ifndef DRIZZLED
79
 
#include "systab_enabled_ms.h"
80
 
#endif
81
 
#include "discover_ms.h"
82
 
#include "parameters_ms.h"
83
 
 
84
 
///* Note: mysql_priv.h messes with new, which caused a crash. */
85
 
//#ifdef new
86
 
//#undef new
87
 
//#endif
88
 
 
89
 
/* Definitions for PBMS table discovery: */
90
 
//--------------------------------
91
 
static DT_FIELD_INFO pbms_repository_info[]=
92
 
{
93
 
#ifdef HAVE_ALIAS_SUPPORT
94
 
        {"Blob_alias",                  BLOB_ALIAS_LENGTH, NULL, MYSQL_TYPE_VARCHAR,            &my_charset_utf8_bin,   0,                                                              "The BLOB alias"},
95
 
#endif
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}
107
 
};
108
 
 
109
 
#ifdef PBMS_HAS_KEYS
110
 
static DT_KEY_INFO pbms_repository_keys[]=
111
 
{
112
 
        {"pbms_repository_pk", PRI_KEY_FLAG, {"Repository_id", "Repo_blob_offset", NULL}},
113
 
        {NULL, 0, {NULL}}
114
 
};
115
 
#endif
116
 
 
117
 
static DT_FIELD_INFO pbms_metadata_info[]=
118
 
{
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}
124
 
};
125
 
 
126
 
#ifdef PBMS_HAS_KEYS
127
 
static DT_KEY_INFO pbms_metadata_keys[]=
128
 
{
129
 
        {"pbms_metadata_pk", PRI_KEY_FLAG, {"Repository_id", "Repo_blob_offset", NULL}},
130
 
        {NULL, 0, {NULL}}
131
 
};
132
 
#endif
133
 
 
134
 
 
135
 
#ifdef HAVE_ALIAS_SUPPORT
136
 
static DT_FIELD_INFO pbms_alias_info[]=
137
 
{
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}
142
 
};
143
 
 
144
 
static DT_KEY_INFO pbms_alias_keys[]=
145
 
{
146
 
        {"pbms_alias_pk", PRI_KEY_FLAG, {"Repository_id", "Repo_blob_offset", NULL}},
147
 
        {NULL, 0, {NULL}}
148
 
};
149
 
#endif
150
 
 
151
 
static DT_FIELD_INFO pbms_blobs_info[]=
152
 
{
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}
157
 
};
158
 
 
159
 
#ifdef PBMS_HAS_KEYS
160
 
static DT_KEY_INFO pbms_blobs_keys[]=
161
 
{
162
 
        {"pbms_blobs_pk", PRI_KEY_FLAG, {"Repository_id", "Repo_blob_offset", NULL}},
163
 
        {NULL, 0, {NULL}}
164
 
};
165
 
#endif
166
 
 
167
 
static DT_FIELD_INFO pbms_reference_info[]=
168
 
{
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}
181
 
};
182
 
 
183
 
#ifdef PBMS_HAS_KEYS
184
 
static DT_KEY_INFO pbms_reference_keys[]=
185
 
{
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}},
188
 
        {NULL, 0, {NULL}}
189
 
};
190
 
#endif
191
 
 
192
 
 
193
 
typedef enum {  SYS_REP = 0, 
194
 
                                SYS_REF, 
195
 
                                SYS_BLOB, 
196
 
                                SYS_DUMP, 
197
 
                                SYS_META, 
198
 
                                SYS_HTTP, 
199
 
#ifdef HAVE_ALIAS_SUPPORT
200
 
                                SYS_ALIAS, 
201
 
#endif
202
 
                                SYS_VARIABLE, 
203
 
                                SYS_CLOUD, 
204
 
                                SYS_BACKUP, 
205
 
#ifndef DRIZZLED
206
 
                                SYS_ENABLED, 
207
 
#endif
208
 
                                SYS_UNKNOWN} SysTableType;
209
 
                                
210
 
static const char *sysTableNames[] = {
211
 
        "pbms_repository",
212
 
        "pbms_reference",
213
 
        "pbms_blob",
214
 
        "pbms_dump",
215
 
        "pbms_metadata",
216
 
        METADATA_HEADER_NAME,
217
 
#ifdef HAVE_ALIAS_SUPPORT
218
 
        "pbms_alias",
219
 
#endif
220
 
        VARIABLES_TABLE_NAME,
221
 
        CLOUD_TABLE_NAME,
222
 
        BACKUP_TABLE_NAME,
223
 
#ifndef DRIZZLED
224
 
        ENABLED_TABLE_NAME,
225
 
#endif
226
 
        NULL
227
 
};
228
 
 
229
 
static INTERRNAL_TABLE_INFO pbms_internal_tables[]=
230
 
{
231
 
#ifdef PBMS_HAS_KEYS
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},
240
 
#endif
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},
244
 
#ifndef DRIZZLED
245
 
        { true, sysTableNames[SYS_ENABLED], pbms_enabled_info, pbms_enabled_keys},
246
 
#endif
247
 
#else
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},
256
 
#endif
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},
260
 
#ifndef DRIZZLED
261
 
        { true, sysTableNames[SYS_ENABLED], pbms_enabled_info, NULL},
262
 
#endif
263
 
#endif
264
 
 
265
 
        { false, NULL, NULL, NULL}
266
 
        
267
 
};
268
 
 
269
 
//--------------------------
270
 
static SysTableType pbms_systable_type(const char *table)
271
 
{
272
 
        int i = 0;
273
 
        
274
 
        while ((i < SYS_UNKNOWN) && strcasecmp(table, sysTableNames[i])) i++;
275
 
        
276
 
        return((SysTableType) i );
277
 
}
278
 
 
279
 
//--------------------------
280
 
bool PBMSSystemTables::isSystemTable(bool isPBMS, const char *table)
281
 
{
282
 
        SysTableType i;
283
 
        
284
 
        i = pbms_systable_type(table);
285
 
 
286
 
        if (i == SYS_UNKNOWN)
287
 
                return false;
288
 
                
289
 
        return (pbms_internal_tables[i].is_pbms == isPBMS);
290
 
}
291
 
 
292
 
//--------------------------
293
 
#ifdef DRIZZLED
294
 
using namespace std;
295
 
using namespace drizzled;
296
 
#undef TABLE
297
 
#undef Field
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)
299
 
{
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;
304
 
 
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);
309
 
        
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);
313
 
        
314
 
        while (info->field_name) {      
315
 
                field= table.add_field();
316
 
                
317
 
                field->set_name(info->field_name);
318
 
                if (info->comment)
319
 
                        field->set_comment(info->comment);
320
 
                        
321
 
                field_constraints= field->mutable_constraints();
322
 
                if (info->field_flags & NOT_NULL_FLAG)
323
 
                        field_constraints->set_is_notnull(true);
324
 
                
325
 
                if (info->field_flags & UNSIGNED_FLAG)
326
 
                        field_constraints->set_is_unsigned(true);
327
 
                else
328
 
                        field_constraints->set_is_unsigned(false);
329
 
 
330
 
                switch (info->field_type) {
331
 
                        case DRIZZLE_TYPE_VARCHAR:
332
 
                                string_field_options = field->mutable_string_options();
333
 
                                
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);
339
 
                                }
340
 
                                break;
341
 
                                
342
 
                        case DRIZZLE_TYPE_LONG:
343
 
                                field->set_type(message::Table::Field::INTEGER);
344
 
                                break;
345
 
                                
346
 
                        case DRIZZLE_TYPE_DOUBLE:
347
 
                                field->set_type(message::Table::Field::DOUBLE);
348
 
                                break;
349
 
                                
350
 
                        case DRIZZLE_TYPE_LONGLONG:
351
 
                                field->set_type(message::Table::Field::BIGINT);
352
 
                                break;
353
 
                                
354
 
                        case DRIZZLE_TYPE_TIMESTAMP:
355
 
                                field->set_type(message::Table::Field::EPOCH);
356
 
                                break;
357
 
                                
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);
364
 
                                }
365
 
                                break;
366
 
                                
367
 
                        default:
368
 
                                assert(0); 
369
 
                }
370
 
                info++;
371
 
        }
372
 
        
373
 
                        
374
 
        if (keys) {
375
 
                while (keys->key_name) {
376
 
                        // To be done later. (maybe)
377
 
                        keys++;
378
 
                }
379
 
        }
380
 
 
381
 
        return 0;
382
 
}
383
 
#define TABLE                                                           drizzled::Table
384
 
#define Field                                                           drizzled::Field
385
 
 
386
 
int PBMSSystemTables::getSystemTableInfo(const char *name, drizzled::message::Table &table)
387
 
{
388
 
        int err = 1, i = 0;
389
 
                        
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);
393
 
                        break;
394
 
                }
395
 
                i++;
396
 
        }
397
 
        
398
 
        return err;
399
 
}
400
 
 
401
 
void PBMSSystemTables::getSystemTableNames(bool isPBMS, std::set<std::string> &set_of_names)
402
 
{
403
 
        int i = 0;
404
 
                        
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);
408
 
                }
409
 
                i++;
410
 
        }
411
 
        
412
 
}
413
 
 
414
 
#else // DRIZZLED
415
 
//--------------------------
416
 
static bool pbms_database_follder_exists( const char *db)
417
 
{
418
 
        struct stat stat_info;  
419
 
        char path[PATH_MAX];
420
 
        
421
 
        if (!db)
422
 
                return false;
423
 
                
424
 
        cs_strcpy(PATH_MAX, path, ms_my_get_mysql_home_path());
425
 
        cs_add_name_to_path(PATH_MAX, path, db);
426
 
        
427
 
        if (stat(path, &stat_info) == 0)
428
 
                return(stat_info.st_mode & S_IFDIR);
429
 
                
430
 
        return false;
431
 
}
432
 
 
433
 
int pbms_discover_system_tables(handlerton *hton, THD* thd, const char *db, const char *name, uchar **frmblob, size_t *frmlen)
434
 
{
435
 
        int err = 1, i = 0;
436
 
        bool is_pbms = false;
437
 
 
438
 
        // Check that the database exists!
439
 
        if (!pbms_database_follder_exists(db))
440
 
                return err;
441
 
                
442
 
        is_pbms = (strcmp(db, "pbms") == 0);
443
 
                
444
 
        
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);
448
 
                        break;
449
 
                }
450
 
                i++;
451
 
        }
452
 
        
453
 
        return err;
454
 
}
455
 
#endif // DRIZZLED
456
 
 
457
 
// Transfer any physical PBMS ststem tables to another database.
458
 
void PBMSSystemTables::transferSystemTables(MSDatabase *dst_db, MSDatabase *src_db)
459
 
{
460
 
        enter_();
461
 
        push_(dst_db);
462
 
        push_(src_db);
463
 
        
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));
468
 
        
469
 
        release_(src_db);
470
 
        release_(dst_db);
471
 
        exit_();
472
 
}
473
 
 
474
 
//----------------
475
 
void PBMSSystemTables::removeSystemTables(CSString *db_path)
476
 
{
477
 
        enter_();
478
 
        push_(db_path);
479
 
        
480
 
        MSHTTPHeaderTable::removeTable(RETAIN(db_path));
481
 
        MSVariableTable::removeTable(RETAIN(db_path));
482
 
        MSCloudTable::removeTable(RETAIN(db_path));
483
 
        MSBackupTable::removeTable(RETAIN(db_path));
484
 
        
485
 
        release_(db_path);
486
 
        exit_();
487
 
}
488
 
 
489
 
//----------------
490
 
bool PBMSSystemTables::try_loadSystemTables(CSThread *self, int i, MSDatabase *db)
491
 
{
492
 
        volatile bool rtc = true;
493
 
        try_(a) {
494
 
                switch (i) {
495
 
                        case 0:
496
 
                                MSHTTPHeaderTable::loadTable(RETAIN(db));
497
 
                                break;
498
 
                        case 1:
499
 
                                MSCloudTable::loadTable(RETAIN(db));
500
 
                                break;
501
 
                        case 2:
502
 
                                MSBackupTable::loadTable(RETAIN(db));
503
 
                                break;
504
 
                        case 3:
505
 
                                // Variable must be loaded after cloud and backup info
506
 
                                // incase BLOB recovery is required.
507
 
                                MSVariableTable::loadTable(RETAIN(db)); 
508
 
                                break;
509
 
                                
510
 
                        default:
511
 
                                ASSERT(false);
512
 
                }
513
 
                rtc = false;
514
 
        }
515
 
        catch_(a);
516
 
        cont_(a);
517
 
        return rtc;
518
 
}
519
 
//----------------
520
 
void PBMSSystemTables::loadSystemTables(MSDatabase *db)
521
 
{
522
 
        enter_();
523
 
        push_(db);
524
 
        
525
 
        for ( int i = 0; i < 4; i++) {
526
 
                if (try_loadSystemTables(self, i, db))
527
 
                        self->logException();                   
528
 
        }
529
 
        
530
 
        release_(db);
531
 
        exit_();
532
 
}
533
 
 
534
 
//----------------
535
 
// Dump all the system tables into one buffer.
536
 
typedef struct {
537
 
        CSDiskValue4 size_4;
538
 
        CSDiskValue1 tab_id_1;
539
 
        CSDiskValue4 tab_version_4;
540
 
} DumpHeaderRec, *DumpHeaderPtr;
541
 
 
542
 
typedef union {
543
 
                char *rec_chars;
544
 
                const char *rec_cchars;
545
 
                DumpHeaderPtr dumpHeader;
546
 
} DumpDiskData;
547
 
 
548
 
CSStringBuffer *PBMSSystemTables::dumpSystemTables(MSDatabase *db)
549
 
{
550
 
        CSStringBuffer *sysDump, *tabDump = NULL;
551
 
        uint32_t size, pos, tab_version;
552
 
        uint8_t tab_id = 0;
553
 
        DumpDiskData    d;
554
 
 
555
 
        enter_();
556
 
        push_(db);
557
 
        new_(sysDump, CSStringBuffer());
558
 
        push_(sysDump);
559
 
        pos = 0;
560
 
        
561
 
        for ( int i = 0; i < 4; i++) {
562
 
                switch (i) {
563
 
                        case 0:
564
 
                                tabDump = MSHTTPHeaderTable::dumpTable(RETAIN(db));
565
 
                                tab_id = MSHTTPHeaderTable::tableID;
566
 
                                tab_version = MSHTTPHeaderTable::tableVersion;
567
 
                                break;
568
 
                        case 1:
569
 
                                tabDump = MSCloudTable::dumpTable(RETAIN(db));
570
 
                                tab_id = MSCloudTable::tableID;
571
 
                                tab_version = MSCloudTable::tableVersion;
572
 
                                break;
573
 
                        case 2:
574
 
                                tabDump = MSBackupTable::dumpTable(RETAIN(db));
575
 
                                tab_id = MSBackupTable::tableID;
576
 
                                tab_version = MSBackupTable::tableVersion;
577
 
                                break;
578
 
                        case 3:
579
 
                                tabDump = MSVariableTable::dumpTable(RETAIN(db)); // Dump the variables table last.
580
 
                                tab_id = MSVariableTable::tableID;
581
 
                                tab_version = MSVariableTable::tableVersion;
582
 
                                break;
583
 
                                
584
 
                        default:
585
 
                                ASSERT(false);
586
 
                }
587
 
                
588
 
                push_(tabDump);
589
 
                size = tabDump->length();
590
 
                
591
 
                // Grow the buffer for the header
592
 
                sysDump->setLength(pos + sizeof(DumpHeaderRec));
593
 
                
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);        
599
 
        
600
 
                sysDump->append(tabDump->getBuffer(0), size);
601
 
                pos += size + sizeof(DumpHeaderRec);
602
 
                release_(tabDump);
603
 
        }
604
 
        
605
 
        
606
 
        pop_(sysDump);
607
 
        release_(db);
608
 
        return_(sysDump);
609
 
}
610
 
 
611
 
//----------------
612
 
void PBMSSystemTables::restoreSystemTables(MSDatabase *db, const char *data, size_t size)
613
 
{
614
 
        uint32_t tab_size, tab_version;
615
 
        uint8_t tab_id;
616
 
        DumpDiskData    d;
617
 
 
618
 
        enter_();
619
 
        push_(db);
620
 
        
621
 
        while  ( size >= sizeof(DumpHeaderRec)) {
622
 
                d.rec_cchars = data;
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);
628
 
                
629
 
                if (size < tab_size) {
630
 
                        CSException::throwException(CS_CONTEXT, CS_ERR_GENERIC_ERROR, "PBMS system table restore data truncated.");
631
 
                }
632
 
                
633
 
                switch (tab_id) {
634
 
                        case MSHTTPHeaderTable::tableID:
635
 
                                if (MSHTTPHeaderTable::tableVersion == tab_version)
636
 
                                        MSHTTPHeaderTable::restoreTable(RETAIN(db), data, tab_size);
637
 
                                else
638
 
                                        CSException::logException(CS_CONTEXT, MS_ERR_SYSTAB_VERSION, "Restore "METADATA_HEADER_NAME" failed, incompatible table version" );
639
 
                                break;
640
 
                        case MSCloudTable::tableID:
641
 
                                if (MSCloudTable::tableVersion == tab_version)
642
 
                                        MSCloudTable::restoreTable(RETAIN(db), data, tab_size);
643
 
                                else
644
 
                                        CSException::logException(CS_CONTEXT, MS_ERR_SYSTAB_VERSION, "Restore "CLOUD_TABLE_NAME" failed, incompatible table version" );
645
 
                                break;
646
 
                        case MSBackupTable::tableID:
647
 
                                if (MSBackupTable::tableVersion == tab_version)
648
 
                                        MSBackupTable::restoreTable(RETAIN(db), data, tab_size);
649
 
                                else
650
 
                                        CSException::logException(CS_CONTEXT, MS_ERR_SYSTAB_VERSION, "Restore "BACKUP_TABLE_NAME" failed, incompatible table version" );
651
 
                                break;                          
652
 
                        case MSVariableTable::tableID:
653
 
                                if (MSVariableTable::tableVersion == tab_version)
654
 
                                        MSVariableTable::restoreTable(RETAIN(db), data, tab_size);
655
 
                                else
656
 
                                        CSException::logException(CS_CONTEXT, MS_ERR_SYSTAB_VERSION, "Restore "VARIABLES_TABLE_NAME" failed, incompatible table version" );
657
 
                                break;
658
 
                        default:
659
 
                                ASSERT(false);
660
 
                }
661
 
                 data += tab_size;
662
 
                 size -= tab_size;
663
 
        }
664
 
        
665
 
        if (size) {
666
 
                CSException::logException(CS_CONTEXT, CS_ERR_GENERIC_ERROR, "PBMS trailing garbage in system table restore data being ignored.");
667
 
        }
668
 
                
669
 
        release_(db);
670
 
        exit_();
671
 
}
672
 
 
673
 
/*
674
 
 * -------------------------------------------------------------------------
675
 
 * MYSQL UTILITIES
676
 
 */
677
 
 
678
 
void MSOpenSystemTable::setNotNullInRecord(Field *field, char *record)
679
 
{
680
 
#ifdef DRIZZLED
681
 
        if (field->null_ptr)
682
 
                record[(uint) (field->null_ptr - (uchar *) field->getTable()->getInsertRecord())] &= (uchar) ~field->null_bit;
683
 
#else
684
 
        if (field->null_ptr)
685
 
                record[(uint) (field->null_ptr - (uchar *) field->table->record[0])] &= (uchar) ~field->null_bit;
686
 
#endif
687
 
}
688
 
 
689
 
/*
690
 
 * -------------------------------------------------------------------------
691
 
 * OPEN SYSTEM TABLES
692
 
 */
693
 
 
694
 
MSOpenSystemTable::MSOpenSystemTable(MSSystemTableShare *share, TABLE *table):
695
 
CSRefObject()
696
 
{
697
 
        myShare = share;
698
 
        mySQLTable = table;
699
 
}
700
 
 
701
 
MSOpenSystemTable::~MSOpenSystemTable()
702
 
{
703
 
        MSSystemTableShare::releaseSystemTable(this);
704
 
}
705
 
 
706
 
 
707
 
/*
708
 
 * -------------------------------------------------------------------------
709
 
 * REPOSITORY TABLE
710
 
 */
711
 
 
712
 
MSRepositoryTable::MSRepositoryTable(MSSystemTableShare *share, TABLE *table):
713
 
MSOpenSystemTable(share, table),
714
 
iCompactor(NULL),
715
 
iRepoFile(NULL),
716
 
iBlobBuffer(NULL)
717
 
{
718
 
}
719
 
 
720
 
//-----------------------
721
 
MSRepositoryTable::~MSRepositoryTable()
722
 
{
723
 
        unuse();
724
 
        
725
 
        if (iBlobBuffer)
726
 
                iBlobBuffer->release();
727
 
}
728
 
 
729
 
//-----------------------
730
 
void MSRepositoryTable::use()
731
 
{
732
 
        MSDatabase *db;
733
 
        enter_();
734
 
 
735
 
        if (!iBlobBuffer)
736
 
                new_(iBlobBuffer, CSStringBuffer(20));
737
 
                
738
 
        db = myShare->mySysDatabase;
739
 
        if ((iCompactor = db->getCompactorThread())) {
740
 
                if (iCompactor->isMe(self))
741
 
                        iCompactor = NULL;
742
 
                else {
743
 
                        iCompactor->retain();
744
 
                        iCompactor->suspend();
745
 
                }
746
 
        }
747
 
        exit_();
748
 
}
749
 
 
750
 
//-----------------------
751
 
void MSRepositoryTable::unuse()
752
 
{
753
 
        if (iCompactor) {
754
 
                iCompactor->resume();
755
 
                iCompactor->release();
756
 
                iCompactor = NULL;
757
 
        }
758
 
        if (iRepoFile) {
759
 
                iRepoFile->release();
760
 
                iRepoFile = NULL;
761
 
        }
762
 
        if (iBlobBuffer)
763
 
                iBlobBuffer->clear();
764
 
}
765
 
 
766
 
 
767
 
//-----------------------
768
 
void MSRepositoryTable::seqScanInit()
769
 
{
770
 
        enter_();
771
 
        
772
 
        // Flush all committed transactions to the repository file.
773
 
        MSTransactionManager::flush();
774
 
 
775
 
        iRepoIndex = 0;
776
 
        iRepoOffset = 0;
777
 
                
778
 
        exit_();
779
 
}
780
 
 
781
 
//-----------------------
782
 
bool MSRepositoryTable::resetScan(bool positioned, uint32_t repo_index)
783
 
{
784
 
        if (positioned) {
785
 
                if (iRepoFile && (repo_index != iRepoIndex)) {
786
 
                        iRepoFile->release();
787
 
                        iRepoFile = NULL;
788
 
                }
789
 
                
790
 
                iRepoIndex = repo_index;
791
 
        }
792
 
        if (iRepoFile) 
793
 
                return true;
794
 
                
795
 
        enter_();
796
 
        MSRepository    *repo = NULL;
797
 
        CSSyncVector    *repo_list = myShare->mySysDatabase->getRepositoryList();
798
 
 
799
 
        lock_(repo_list);
800
 
        for (; iRepoIndex<repo_list->size(); iRepoIndex++) {
801
 
                if ((repo = (MSRepository *) repo_list->get(iRepoIndex))) {
802
 
                        iRepoFile = repo->openRepoFile();
803
 
                        break;
804
 
                }
805
 
        }
806
 
        unlock_(repo_list);
807
 
        
808
 
        if (!iRepoFile)
809
 
                return_(false);
810
 
        iRepoFileSize = repo->getRepoFileSize();
811
 
        if ((!iRepoOffset) || !positioned) 
812
 
                iRepoOffset = repo->getRepoHeadSize();
813
 
                
814
 
        iRepoCurrentOffset = iRepoOffset;
815
 
                
816
 
        return_(true);
817
 
}
818
 
 
819
 
//-----------------------
820
 
bool MSRepositoryTable::seqScanNext(char *buf)
821
 
{
822
 
 
823
 
        enter_();
824
 
        iRepoCurrentOffset = iRepoOffset;
825
 
        
826
 
        if (returnSubRecord(buf))
827
 
                goto exit;
828
 
 
829
 
        restart:
830
 
        if ((!iRepoFile) && !MSRepositoryTable::resetScan(false))
831
 
                return false;
832
 
 
833
 
        while (iRepoOffset < iRepoFileSize) {
834
 
                if (returnRecord(buf))
835
 
                        goto exit;
836
 
        }
837
 
 
838
 
        if (iRepoFile) {
839
 
                iRepoFile->release();
840
 
                iRepoFile = NULL;
841
 
                iRepoOffset = 0;
842
 
        }
843
 
        iRepoIndex++;
844
 
        goto restart;
845
 
 
846
 
        exit:
847
 
        return_(true);
848
 
}
849
 
 
850
 
//-----------------------
851
 
int     MSRepositoryTable::getRefLen()
852
 
{
853
 
        return sizeof(iRepoIndex) + sizeof(iRepoOffset);
854
 
}
855
 
 
856
 
 
857
 
//-----------------------
858
 
void MSRepositoryTable::seqScanPos(unsigned char *pos)
859
 
{
860
 
        mi_int4store(pos, iRepoIndex); pos +=4;
861
 
        mi_int8store(pos, iRepoCurrentOffset);
862
 
}
863
 
 
864
 
//-----------------------
865
 
void MSRepositoryTable::seqScanRead(uint32_t repo, uint64_t offset, char *buf)
866
 
{
867
 
        iRepoOffset = offset;
868
 
 
869
 
        if (!resetScan(true, repo))
870
 
                return;
871
 
                
872
 
        seqScanNext(buf);
873
 
}
874
 
 
875
 
//-----------------------
876
 
void MSRepositoryTable::seqScanRead(unsigned char *pos, char *buf)
877
 
{
878
 
        seqScanRead(mi_uint4korr( pos), mi_uint8korr(pos +4), buf);
879
 
}
880
 
 
881
 
//-----------------------
882
 
bool MSRepositoryTable::returnRecord(char *buf)
883
 
{
884
 
        CSMutex                 *lock;
885
 
        MSBlobHeadRec   blob;
886
 
        uint16_t                        head_size;
887
 
        uint64_t                        blob_size;
888
 
        int                             ref_count;
889
 
        size_t                  ref_size;
890
 
        uint8_t                 status;
891
 
 
892
 
        enter_();
893
 
        retry_read:
894
 
        lock = iRepoFile->myRepo->getRepoLock(iRepoOffset);
895
 
        lock_(lock);
896
 
        if (iRepoFile->read(&blob, iRepoOffset, sizeof(MSBlobHeadRec), 0) < sizeof(MSBlobHeadRec)) {
897
 
                unlock_(lock);
898
 
                iRepoOffset = iRepoFileSize;
899
 
                return_(false);
900
 
        }
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! */
910
 
                unlock_(lock);
911
 
                iRepoOffset++;
912
 
                goto retry_read;
913
 
        }
914
 
 
915
 
        if (IN_USE_BLOB_STATUS(status)) {
916
 
                unlock_(lock);
917
 
                if (!returnRow(&blob, buf)) {
918
 
                        /* This record may not have had any data of interest. */
919
 
                        iRepoOffset++;
920
 
                        goto retry_read;
921
 
                }
922
 
                iRepoOffset += head_size + blob_size;
923
 
                return_(true);
924
 
        }
925
 
        unlock_(lock);
926
 
        iRepoOffset += head_size + blob_size;
927
 
        return_(false);
928
 
}
929
 
 
930
 
//-----------------------
931
 
bool MSRepositoryTable::returnSubRecord(char *)
932
 
{
933
 
        return false;
934
 
}
935
 
 
936
 
//-----------------------
937
 
bool MSRepositoryTable::returnRow(MSBlobHeadPtr blob, char *buf)
938
 
{
939
 
        TABLE           *table = mySQLTable;
940
 
        uint8_t         storage_type;
941
 
        uint32_t                access_count;
942
 
        uint32_t                last_access;
943
 
        uint32_t                last_ref;
944
 
        uint32_t                creation_time;
945
 
        uint32_t                access_code;
946
 
        uint16_t                head_size;
947
 
        uint16_t                alias_offset;
948
 
        uint64_t                blob_size;
949
 
        Field           *curr_field;
950
 
        byte            *save;
951
 
        MY_BITMAP       *save_write_set;
952
 
 
953
 
        (void)alias_offset;
954
 
        
955
 
        enter_();
956
 
 
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);
966
 
 
967
 
        /* ASSERT_COLUMN_MARKED_FOR_WRITE is failing when
968
 
         * I use store()!??
969
 
         * But I want to use it! :(
970
 
         */
971
 
        save_write_set = table->write_set;
972
 
        table->write_set = NULL;
973
 
 
974
 
#ifdef DRIZZLED
975
 
        memset(buf, 0xFF, table->getNullBytes());
976
 
#else
977
 
        memset(buf, 0xFF, table->s->null_bytes);
978
 
#endif
979
 
        for (Field **field=GET_TABLE_FIELDS(table) ; *field ; field++) {
980
 
                curr_field = *field;
981
 
                save = curr_field->ptr;
982
 
#if MYSQL_VERSION_ID < 50114
983
 
                curr_field->ptr = (byte *) buf + curr_field->offset();
984
 
#else
985
 
#ifdef DRIZZLED
986
 
                curr_field->ptr = (byte *) buf + curr_field->offset(curr_field->getTable()->getInsertRecord());
987
 
#else
988
 
                curr_field->ptr = (byte *) buf + curr_field->offset(curr_field->table->record[0]);
989
 
#endif
990
 
#endif
991
 
                switch (curr_field->field_name[0]) {
992
 
                        case 'A':
993
 
                                switch (curr_field->field_name[9]) {
994
 
                                        case 'd':
995
 
                                                ASSERT(strcmp(curr_field->field_name, "Access_code") == 0);
996
 
                                                curr_field->store(access_code, true);
997
 
                                                setNotNullInRecord(curr_field, buf);
998
 
                                                break;
999
 
                                        case 'u':
1000
 
                                                ASSERT(strcmp(curr_field->field_name, "Access_count") == 0);
1001
 
                                                curr_field->store(access_count, true);
1002
 
                                                setNotNullInRecord(curr_field, buf);
1003
 
                                                break;
1004
 
                                }
1005
 
                                break;
1006
 
                        case 'R':
1007
 
                                switch (curr_field->field_name[6]) {
1008
 
                                        case 't':
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);
1013
 
                                                break;
1014
 
                                        case 'l':
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);
1019
 
                                                break;
1020
 
                                }
1021
 
                                break;
1022
 
                        case 'B':
1023
 
                                switch (curr_field->field_name[5]) {
1024
 
                                        case 's':
1025
 
                                                // Blob_size         BIGINT
1026
 
                                                ASSERT(strcmp(curr_field->field_name, "Blob_size") == 0);
1027
 
                                                curr_field->store(blob_size, true);
1028
 
                                                setNotNullInRecord(curr_field, buf);
1029
 
                                                break;
1030
 
                                        case 'a':
1031
 
                                                // Blob_alias         
1032
 
                                                ASSERT(strcmp(curr_field->field_name, "Blob_alias") == 0);
1033
 
#ifdef HAVE_ALIAS_SUPPORT
1034
 
                                                if (alias_offset) {
1035
 
                                                        char blob_alias[BLOB_ALIAS_LENGTH +1];
1036
 
                                                        CSMutex *lock;
1037
 
                                                        uint64_t rsize;
1038
 
                                                        
1039
 
                                                        lock = iRepoFile->myRepo->getRepoLock(iRepoOffset);
1040
 
                                                        lock_(lock);
1041
 
                                                        rsize = iRepoFile->read(blob_alias, iRepoOffset + alias_offset, BLOB_ALIAS_LENGTH, 0);
1042
 
                                                        unlock_(lock);
1043
 
                                                        blob_alias[rsize] = 0;
1044
 
                                                        curr_field->store(blob_alias, strlen(blob_alias), &my_charset_utf8_general_ci);
1045
 
                                                        setNotNullInRecord(curr_field, buf);
1046
 
                                                } else {
1047
 
                                                        curr_field->store((uint64_t) 0, true);
1048
 
                                                }
1049
 
#else
1050
 
                                                curr_field->store((uint64_t) 0, true);
1051
 
#endif
1052
 
                                                
1053
 
                                                break;
1054
 
                                }
1055
 
 
1056
 
                                break;
1057
 
                        case 'M': // MD5_Checksum
1058
 
                                if (storage_type == MS_STANDARD_STORAGE) {
1059
 
                                        char checksum[sizeof(Md5Digest) *2 +1];
1060
 
                                        
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);
1065
 
                                        
1066
 
                                } else
1067
 
                                        curr_field->store((uint64_t) 0, true);
1068
 
                        
1069
 
                                break;
1070
 
                        case 'H':
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);
1075
 
                                break;
1076
 
                        case 'C':
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);
1081
 
                                break;
1082
 
                        case 'L':
1083
 
                                switch (curr_field->field_name[5]) {
1084
 
                                        case 'r':
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);
1089
 
                                                break;
1090
 
                                        case 'a':
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);
1095
 
                                                break;
1096
 
                                }
1097
 
                                break;
1098
 
                }
1099
 
                curr_field->ptr = save;
1100
 
        }
1101
 
 
1102
 
        table->write_set = save_write_set;
1103
 
        return_(true);
1104
 
}
1105
 
 
1106
 
/*
1107
 
 * -------------------------------------------------------------------------
1108
 
 * BLOB DATA TABLE
1109
 
 */
1110
 
//-----------------------
1111
 
MSBlobDataTable::MSBlobDataTable(MSSystemTableShare *share, TABLE *table):MSRepositoryTable(share, table)
1112
 
{
1113
 
}
1114
 
 
1115
 
//-----------------------
1116
 
MSBlobDataTable::~MSBlobDataTable()
1117
 
{       
1118
 
}
1119
 
 
1120
 
//-----------------------
1121
 
bool MSBlobDataTable::returnRow(MSBlobHeadPtr blob, char *buf)
1122
 
{
1123
 
        TABLE           *table = mySQLTable;
1124
 
        uint8_t         blob_type;
1125
 
        uint16_t                head_size;
1126
 
        uint64_t                blob_size;
1127
 
        uint32          len;
1128
 
        Field           *curr_field;
1129
 
        byte            *save;
1130
 
        MY_BITMAP       *save_write_set;
1131
 
 
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);
1135
 
 
1136
 
        /* ASSERT_COLUMN_MARKED_FOR_WRITE is failing when
1137
 
         * I use store()!??
1138
 
         * But I want to use it! :(
1139
 
         */
1140
 
        save_write_set = table->write_set;
1141
 
        table->write_set = NULL;
1142
 
 
1143
 
#ifdef DRIZZLED
1144
 
        memset(buf, 0xFF, table->getNullBytes());
1145
 
#else
1146
 
        memset(buf, 0xFF, table->s->null_bytes);
1147
 
#endif
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();
1153
 
#else
1154
 
#ifdef DRIZZLED
1155
 
                curr_field->ptr = (byte *) buf + curr_field->offset(curr_field->getTable()->getInsertRecord());
1156
 
#else
1157
 
                curr_field->ptr = (byte *) buf + curr_field->offset(curr_field->table->record[0]);
1158
 
#endif
1159
 
#endif
1160
 
                switch (curr_field->field_name[0]) {
1161
 
                        case 'R':
1162
 
                                switch (curr_field->field_name[6]) {
1163
 
                                        case 't':
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);
1168
 
                                                break;
1169
 
                                        case 'l':
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);
1174
 
                                                break;
1175
 
                                }
1176
 
                                break;
1177
 
                        case 'B':
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);
1184
 
                                        } else {
1185
 
                                                CloudDB *blobCloud = myShare->mySysDatabase->myBlobCloud;
1186
 
                                                CloudKeyRec key;
1187
 
                                                ASSERT(blobCloud != NULL);
1188
 
                                                
1189
 
                                                MSRepoFile::getBlobKey(blob, &key);
1190
 
                                                
1191
 
                                                len = blobCloud->cl_getData(&key, iBlobBuffer->getBuffer(0), blob_size);
1192
 
                                        }
1193
 
                                        ((Field_blob *) curr_field)->set_ptr(len, (byte *) iBlobBuffer->getBuffer(0));
1194
 
                                        setNotNullInRecord(curr_field, buf);
1195
 
                                }
1196
 
                                break;
1197
 
                }
1198
 
                curr_field->ptr = save;
1199
 
        }
1200
 
 
1201
 
        table->write_set = save_write_set;
1202
 
        return true;
1203
 
}
1204
 
 
1205
 
#ifdef HAVE_ALIAS_SUPPORT
1206
 
/*
1207
 
 * -------------------------------------------------------------------------
1208
 
 * Alias DATA TABLE
1209
 
 */
1210
 
bool MSBlobAliasTable::returnRow(MSBlobHeadPtr blob, char *buf)
1211
 
{
1212
 
        TABLE           *table = mySQLTable;
1213
 
        Field           *curr_field;
1214
 
        byte            *save;
1215
 
        MY_BITMAP       *save_write_set;
1216
 
        uint16_t                alias_offset; 
1217
 
        char            blob_alias[BLOB_ALIAS_LENGTH +1];
1218
 
        CSMutex         *lock;
1219
 
        uint64_t                rsize;
1220
 
        enter_();
1221
 
        
1222
 
        alias_offset = CS_GET_DISK_2(blob->rb_alias_offset_2);
1223
 
 
1224
 
        if (!alias_offset)
1225
 
                return_(false);
1226
 
 
1227
 
        lock = iRepoFile->myRepo->getRepoLock(iRepoOffset);
1228
 
        lock_(lock);
1229
 
        rsize = iRepoFile->read(blob_alias, iRepoOffset + alias_offset, BLOB_ALIAS_LENGTH, 0);
1230
 
        unlock_(lock);
1231
 
        blob_alias[rsize] = 0;
1232
 
        
1233
 
        /* ASSERT_COLUMN_MARKED_FOR_WRITE is failing when
1234
 
         * I use store()!??
1235
 
         * But I want to use it! :(
1236
 
         */
1237
 
        save_write_set = table->write_set;
1238
 
        table->write_set = NULL;
1239
 
 
1240
 
#ifdef DRIZZLED
1241
 
        memset(buf, 0xFF, table->getNullBytes());
1242
 
#else
1243
 
        memset(buf, 0xFF, table->s->null_bytes);
1244
 
#endif
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();
1250
 
#else
1251
 
#ifdef DRIZZLED
1252
 
                curr_field->ptr = (byte *) buf + curr_field->offset(curr_field->getTable()->getInsertRecord());
1253
 
#else
1254
 
                curr_field->ptr = (byte *) buf + curr_field->offset(curr_field->table->record[0]);
1255
 
#endif
1256
 
#endif
1257
 
                switch (curr_field->field_name[0]) {
1258
 
                        case 'R':
1259
 
                                switch (curr_field->field_name[6]) {
1260
 
                                        case 't':
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);
1265
 
                                                break;
1266
 
                                        case 'l':
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);
1271
 
                                                break;
1272
 
                                }
1273
 
                                break;
1274
 
                        case 'B':
1275
 
                                // Blob_alias         
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);
1279
 
                                
1280
 
                                break;
1281
 
                }
1282
 
                curr_field->ptr = save;
1283
 
        }
1284
 
 
1285
 
        table->write_set = save_write_set;
1286
 
        return_(true);
1287
 
}
1288
 
 
1289
 
#endif
1290
 
 
1291
 
/*
1292
 
 * -------------------------------------------------------------------------
1293
 
 * REFERENCE TABLE
1294
 
 */
1295
 
 
1296
 
MSReferenceTable::MSReferenceTable(MSSystemTableShare *share, TABLE *table):
1297
 
MSRepositoryTable(share, table),
1298
 
iRefDataList(NULL), 
1299
 
iRefDataSize(0), 
1300
 
iRefDataUsed(0),
1301
 
iRefDataPos(0),
1302
 
iRefOpenTable(NULL),
1303
 
iRefTempLog(NULL)
1304
 
{
1305
 
}
1306
 
 
1307
 
MSReferenceTable::~MSReferenceTable()
1308
 
{
1309
 
        if (iRefDataList)
1310
 
                cs_free(iRefDataList);
1311
 
        if (iRefOpenTable)
1312
 
                iRefOpenTable->returnToPool();
1313
 
        if (iRefTempLog)
1314
 
                iRefTempLog->release();
1315
 
}
1316
 
 
1317
 
void MSReferenceTable::unuse()
1318
 
{
1319
 
        MSRepositoryTable::unuse();
1320
 
        if (iRefDataList) {
1321
 
                cs_free(iRefDataList);
1322
 
                iRefDataList = NULL;
1323
 
        }
1324
 
        iRefDataSize = 0;
1325
 
        if (iRefOpenTable) {
1326
 
                iRefOpenTable->returnToPool();
1327
 
                iRefOpenTable = NULL;
1328
 
        }
1329
 
        if (iRefTempLog) {
1330
 
                iRefTempLog->release();
1331
 
                iRefTempLog = NULL;
1332
 
        }
1333
 
}
1334
 
 
1335
 
 
1336
 
void MSReferenceTable::seqScanInit()
1337
 
{
1338
 
        MSRepositoryTable::seqScanInit();
1339
 
        iRefDataUsed = 0;
1340
 
        iRefDataPos = 0;
1341
 
}
1342
 
 
1343
 
int     MSReferenceTable::getRefLen()
1344
 
{
1345
 
        return sizeof(iRefDataUsed) + sizeof(iRefDataPos) + sizeof(iRefCurrentIndex) + sizeof(iRefCurrentOffset);
1346
 
}
1347
 
 
1348
 
void MSReferenceTable::seqScanPos(unsigned char *pos)
1349
 
{
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);
1354
 
}
1355
 
 
1356
 
void MSReferenceTable::seqScanRead(unsigned char *pos, char *buf)
1357
 
{
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);
1363
 
}
1364
 
 
1365
 
bool MSReferenceTable::seqScanNext(char *buf)
1366
 
{
1367
 
        iRefCurrentDataPos = iRefDataPos;
1368
 
        iRefCurrentDataUsed = iRefDataUsed;
1369
 
        
1370
 
        // Reset the position
1371
 
        return MSRepositoryTable::seqScanNext(buf);
1372
 
}
1373
 
// select * from pbms_reference order by blob_size DESC;
1374
 
// select * from pbms_reference order by Table_name DESC;
1375
 
 
1376
 
bool MSReferenceTable::resetScan(bool positioned, uint32_t repo_index)
1377
 
{
1378
 
        CSMutex                         *lock;
1379
 
        MSBlobHeadRec           blob;
1380
 
        uint16_t                        head_size;
1381
 
        uint64_t                        blob_size;
1382
 
        MSRepoPointersRec       ptr;
1383
 
        size_t                          ref_size;
1384
 
        uint32_t                        tab_index;
1385
 
        uint32_t                        ref_count;
1386
 
        uint8_t                         status;
1387
 
 
1388
 
        enter_();
1389
 
        
1390
 
        if (!MSRepositoryTable::resetScan(positioned, repo_index))
1391
 
                return_(false);
1392
 
        
1393
 
        retry_read:
1394
 
        lock = iRepoFile->myRepo->getRepoLock(iRepoOffset);
1395
 
        lock_(lock);
1396
 
        if (iRepoFile->read(&blob, iRepoOffset, sizeof(MSBlobHeadRec), 0) < sizeof(MSBlobHeadRec)) {
1397
 
                unlock_(lock);
1398
 
                iRepoOffset = iRepoFileSize;
1399
 
                return_(false);
1400
 
        }
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! */
1410
 
                unlock_(lock);
1411
 
                iRepoOffset++;
1412
 
                goto retry_read;
1413
 
        }
1414
 
 
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) {
1418
 
                        unlock_(lock);
1419
 
                        iRepoOffset = iRepoFileSize;
1420
 
                        return_(false);
1421
 
                }
1422
 
                unlock_(lock);
1423
 
 
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;
1428
 
 
1429
 
                if (ref_count > iRefDataSize) {
1430
 
                        cs_realloc((void **) &iRefDataList, sizeof(MSRefDataRec) * ref_count);
1431
 
                        iRefDataSize = ref_count;
1432
 
                }
1433
 
                
1434
 
                if (!positioned) 
1435
 
                        iRefDataPos = 0;
1436
 
 
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);
1444
 
 
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:
1450
 
                                        break;
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
1455
 
                                        break;
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)) {
1459
 
                                                tab_index--;
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);
1462
 
                                        }
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);
1471
 
                                        }
1472
 
                                        break;
1473
 
                                default:
1474
 
                                        MSRepoTableRefPtr       tab_ref;
1475
 
 
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);
1479
 
        
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));
1484
 
 
1485
 
                                                iRefDataList[tab_index].rd_ref_count++;
1486
 
                                        }
1487
 
                                        else {
1488
 
                                                /* Can't be true. Assume this is garbage! */
1489
 
                                                unlock_(lock);
1490
 
                                                iRepoOffset++;
1491
 
                                                goto retry_read;
1492
 
                                        }
1493
 
                                        break;
1494
 
                        }
1495
 
                        ptr.rp_chars += ref_size;
1496
 
                }
1497
 
 
1498
 
                iRepoOffset += head_size + blob_size;
1499
 
 
1500
 
                return_(true);
1501
 
        }
1502
 
        unlock_(lock);
1503
 
        iRepoOffset += head_size + blob_size;
1504
 
        return_(false);
1505
 
}
1506
 
 
1507
 
bool MSReferenceTable::returnRecord(char *buf)
1508
 
{
1509
 
        if (!resetScan(false))
1510
 
                return false;
1511
 
                
1512
 
        return(returnSubRecord(buf));
1513
 
}
1514
 
 
1515
 
bool MSReferenceTable::returnSubRecord(char *buf)
1516
 
{
1517
 
        uint32_t i;
1518
 
        
1519
 
        while (iRefDataPos < iRefDataUsed) {
1520
 
                i = iRefDataPos++;
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);
1526
 
                                        return true;
1527
 
                                }
1528
 
                        }
1529
 
                        else {
1530
 
                                /* This is an engine reference */
1531
 
                                returnRow(&iRefDataList[i], buf);
1532
 
                                return true;
1533
 
                        }
1534
 
                }
1535
 
        }
1536
 
 
1537
 
        return false;
1538
 
}
1539
 
 
1540
 
void MSReferenceTable::returnRow(MSRefDataPtr ref_data, char *buf)
1541
 
{
1542
 
        TABLE                   *table = mySQLTable;
1543
 
        Field                   *curr_field;
1544
 
        byte                    *save;
1545
 
        MY_BITMAP               *save_write_set;
1546
 
        MY_BITMAP               *save_read_set;
1547
 
        bool                    have_times = false;
1548
 
        time_t                  delete_time;
1549
 
        int32_t                 countdown = 0;
1550
 
 
1551
 
        if (iRefOpenTable) {
1552
 
                if (iRefOpenTable->getDBTable()->myTableID != ref_data->rd_tab_id) {
1553
 
                        iRefOpenTable->returnToPool();
1554
 
                        iRefOpenTable = NULL;
1555
 
                }
1556
 
        }
1557
 
 
1558
 
        if (!iRefOpenTable && ref_data->rd_tab_id != 0xFFFFFFFF)
1559
 
                iRefOpenTable = MSTableList::getOpenTableByID(myShare->mySysDatabase->myDatabaseID, ref_data->rd_tab_id);
1560
 
 
1561
 
        if (ref_data->rd_temp_log_id) {
1562
 
                if (iRefTempLog) {
1563
 
                        if (iRefTempLog->myTempLogID != ref_data->rd_temp_log_id) {
1564
 
                                iRefTempLog->release();
1565
 
                                iRefTempLog = NULL;
1566
 
                        }
1567
 
                }
1568
 
                if (!iRefTempLog)
1569
 
                        iRefTempLog = myShare->mySysDatabase->openTempLogFile(ref_data->rd_temp_log_id, NULL, NULL);
1570
 
 
1571
 
                if (iRefTempLog) {
1572
 
                        MSTempLogItemRec        log_item;
1573
 
 
1574
 
                        if (iRefTempLog->read(&log_item, ref_data->rd_temp_log_offset, sizeof(MSTempLogItemRec), 0) == sizeof(MSTempLogItemRec)) {
1575
 
                                have_times = true;
1576
 
                                delete_time = CS_GET_DISK_4(log_item.ti_time_4);
1577
 
                                countdown = (int32_t) (delete_time + PBMSParameters::getTempBlobTimeout()) - (int32_t) time(NULL);
1578
 
                        }
1579
 
                }
1580
 
        }
1581
 
 
1582
 
        if (ref_data->rd_col_index != INVALID_INDEX) {
1583
 
                if (iRefOpenTable) {
1584
 
                        if (iRefOpenTable->getDBTable()->isToDelete()) {
1585
 
                                have_times = true;
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);
1589
 
                        }
1590
 
                }
1591
 
                else
1592
 
                        ref_data->rd_col_index = INVALID_INDEX;
1593
 
        }
1594
 
 
1595
 
        save_write_set = table->write_set;
1596
 
        save_read_set = table->read_set;
1597
 
        table->write_set = NULL;
1598
 
        table->read_set = NULL;
1599
 
 
1600
 
#ifdef DRIZZLED
1601
 
        memset(buf, 0xFF, table->getNullBytes());
1602
 
#else
1603
 
        memset(buf, 0xFF, table->s->null_bytes);
1604
 
#endif
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();
1610
 
#else
1611
 
#ifdef DRIZZLED
1612
 
                curr_field->ptr = (byte *) buf + curr_field->offset(curr_field->getTable()->getInsertRecord());
1613
 
#else
1614
 
                curr_field->ptr = (byte *) buf + curr_field->offset(curr_field->table->record[0]);
1615
 
#endif
1616
 
#endif
1617
 
                switch (curr_field->field_name[0]) {
1618
 
                        case 'B':
1619
 
                                switch (curr_field->field_name[5]) {
1620
 
                                        case 'i':
1621
 
                                                // Blob_id           BIGINT,
1622
 
                                                ASSERT(strcmp(curr_field->field_name, "Blob_id") == 0);
1623
 
                                                if (ref_data->rd_tab_id == 0xFFFFFFFF)
1624
 
                                                        curr_field->store(0, true);
1625
 
                                                else {
1626
 
                                                        curr_field->store(ref_data->rd_blob_id, true);
1627
 
                                                        setNotNullInRecord(curr_field, buf);
1628
 
                                                }
1629
 
                                                break;
1630
 
                                        case 'u':
1631
 
                                                // Blob_url          VARCHAR(120),
1632
 
                                                PBMSBlobURLRec blob_url;
1633
 
 
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);
1639
 
                                                }
1640
 
                                                break;
1641
 
                                        case 's':
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);
1646
 
                                                break;
1647
 
                                }
1648
 
                                break;
1649
 
                        case 'C':
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);
1655
 
                                }
1656
 
                                break;
1657
 
                        case 'D':
1658
 
                                // Deletion_time     TIMESTAMP,
1659
 
                                ASSERT(strcmp(curr_field->field_name, "Deletion_time") == 0);
1660
 
                                if (have_times) {
1661
 
                                        curr_field->store(ms_my_1970_to_mysql_time(delete_time), true);
1662
 
                                        setNotNullInRecord(curr_field, buf);
1663
 
                                }
1664
 
                                break;
1665
 
                        case 'R':
1666
 
                                switch (curr_field->field_name[5]) {
1667
 
                                        case 'i':
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);
1672
 
                                                break;
1673
 
                                        case 'b':
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);
1678
 
                                                break;
1679
 
                                        case 'e':
1680
 
                                                // Remove_in INT
1681
 
                                                ASSERT(strcmp(curr_field->field_name, "Remove_in") == 0);
1682
 
                                                if (have_times) {
1683
 
                                                        curr_field->store(countdown, false);
1684
 
                                                        setNotNullInRecord(curr_field, buf);
1685
 
                                                }
1686
 
                                                break;
1687
 
                                }
1688
 
                                break;
1689
 
                        case 'T':
1690
 
                                switch (curr_field->field_name[9]) {
1691
 
                                        case 'e':
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);
1698
 
                                                        }
1699
 
                                                        else {
1700
 
                                                                char buffer[MS_TABLE_NAME_SIZE];
1701
 
                                                                
1702
 
                                                                snprintf(buffer, MS_TABLE_NAME_SIZE, "Table #%"PRIu32"", ref_data->rd_tab_id);
1703
 
                                                                curr_field->store(buffer, strlen(buffer), &UTF8_CHARSET);
1704
 
                                                        }
1705
 
                                                        setNotNullInRecord(curr_field, buf);
1706
 
                                                }
1707
 
                                                break;
1708
 
                                        case 'i':
1709
 
                                                // Temp_log_id       INT,
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);
1714
 
                                                }
1715
 
                                                break;
1716
 
                                        case 'o':
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);
1722
 
                                                }
1723
 
                                                break;
1724
 
                                }
1725
 
                                break;
1726
 
                }
1727
 
                curr_field->ptr = save;
1728
 
        }
1729
 
 
1730
 
        table->write_set = save_write_set;
1731
 
        table->read_set = save_read_set;
1732
 
}
1733
 
 
1734
 
/*
1735
 
 * -------------------------------------------------------------------------
1736
 
 * META DATA TABLE
1737
 
 */
1738
 
MSMetaDataTable::MSMetaDataTable(MSSystemTableShare *share, TABLE *table):
1739
 
MSRepositoryTable(share, table),
1740
 
iMetData(NULL), 
1741
 
iMetCurrentBlobRepo(0),
1742
 
iMetCurrentBlobOffset(0),
1743
 
iMetCurrentDataPos(0),
1744
 
iMetCurrentDataSize(0),
1745
 
iMetDataPos(0),
1746
 
iMetDataSize(0), 
1747
 
iMetBlobRepo(0),
1748
 
iMetBlobOffset(0),
1749
 
iMetStateSaved(false)
1750
 
{
1751
 
}
1752
 
 
1753
 
MSMetaDataTable::~MSMetaDataTable()
1754
 
{
1755
 
        if (iMetData) {
1756
 
                iMetData->release();
1757
 
                iMetData = NULL;
1758
 
        }
1759
 
}
1760
 
 
1761
 
MSMetaDataTable *MSMetaDataTable::newMSMetaDataTable(MSDatabase *db)
1762
 
{
1763
 
        char path[PATH_MAX];
1764
 
        
1765
 
        cs_strcpy(PATH_MAX, path, db->myDatabasePath->getCString());
1766
 
        db->release();
1767
 
        cs_add_dir_char(PATH_MAX, path);
1768
 
        cs_strcat(PATH_MAX, path, sysTableNames[SYS_META]);
1769
 
        
1770
 
        return  (MSMetaDataTable*) MSSystemTableShare::openSystemTable(path, NULL);
1771
 
}
1772
 
 
1773
 
void MSMetaDataTable::use()
1774
 
{
1775
 
        MSRepositoryTable::use();
1776
 
        new_(iMetData, CSStringBuffer(80));
1777
 
        iMetDataSize = 0;
1778
 
}
1779
 
 
1780
 
void MSMetaDataTable::unuse()
1781
 
{
1782
 
        MSRepositoryTable::unuse();
1783
 
        if (iMetData) {
1784
 
                iMetData->release();
1785
 
                iMetData = NULL;
1786
 
        }
1787
 
        iMetDataSize = 0;
1788
 
}
1789
 
 
1790
 
 
1791
 
void MSMetaDataTable::seqScanInit()
1792
 
{
1793
 
        MSRepositoryTable::seqScanInit();
1794
 
        iMetDataSize = 0;
1795
 
        iMetDataPos = 0;
1796
 
        iMetBlobRepo = 0;
1797
 
        iMetBlobOffset = 0;
1798
 
        iMetStateSaved = false;
1799
 
}
1800
 
 
1801
 
void MSMetaDataTable::seqScanReset()
1802
 
{
1803
 
        seqScanPos(iMetState);
1804
 
        seqScanInit();
1805
 
        iMetStateSaved = true;
1806
 
}
1807
 
 
1808
 
int     MSMetaDataTable::getRefLen()
1809
 
{
1810
 
        return sizeof(iMetCurrentDataPos) + sizeof(iMetCurrentDataSize) + sizeof(iMetCurrentBlobRepo) + sizeof(iMetCurrentBlobOffset);
1811
 
}
1812
 
 
1813
 
void MSMetaDataTable::seqScanPos(unsigned char *pos)
1814
 
{
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);
1819
 
}
1820
 
 
1821
 
void MSMetaDataTable::seqScanRead(unsigned char *pos, char *buf)
1822
 
{
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);
1829
 
}
1830
 
 
1831
 
bool MSMetaDataTable::seqScanNext(char *buf)
1832
 
{
1833
 
        if (iMetStateSaved) {
1834
 
                bool have_data;
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);
1843
 
        }
1844
 
        
1845
 
        iMetCurrentDataPos = iMetDataPos;
1846
 
        iMetCurrentDataSize = iMetDataSize;
1847
 
        
1848
 
        return MSRepositoryTable::seqScanNext(buf);
1849
 
}
1850
 
 
1851
 
bool MSMetaDataTable::resetScan(bool positioned, bool *have_data, uint32_t repo_index)
1852
 
{
1853
 
        CSMutex                         *lock;
1854
 
        MSBlobHeadRec           blob;
1855
 
        uint16_t                                head_size;
1856
 
        uint64_t                                blob_size;
1857
 
        size_t                          mdata_size, mdata_offset;
1858
 
        uint8_t                         status;
1859
 
 
1860
 
        enter_();
1861
 
        
1862
 
        *have_data = false;
1863
 
        if (!MSRepositoryTable::resetScan(positioned, repo_index))
1864
 
                return_(false);
1865
 
        
1866
 
        retry_read:
1867
 
        lock = iRepoFile->myRepo->getRepoLock(iRepoOffset);
1868
 
        lock_(lock);
1869
 
        if (iRepoFile->read(&blob, iRepoOffset, sizeof(MSBlobHeadRec), 0) < sizeof(MSBlobHeadRec)) {
1870
 
                unlock_(lock);
1871
 
                iRepoOffset = iRepoFileSize;
1872
 
                return_(false);
1873
 
        }
1874
 
        
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);
1879
 
        
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! */
1883
 
                unlock_(lock);
1884
 
                iRepoOffset++;
1885
 
                goto retry_read;
1886
 
        }
1887
 
 
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) {
1891
 
                        unlock_(lock);
1892
 
                        iRepoOffset = iRepoFileSize;
1893
 
                        return_(false);
1894
 
                }
1895
 
 
1896
 
                iMetBlobRepo = iRepoFile->myRepo->getRepoID();
1897
 
                iMetBlobOffset = iRepoOffset;
1898
 
 
1899
 
                if (!positioned) 
1900
 
                        iMetDataPos = 0;
1901
 
 
1902
 
                iMetDataSize = mdata_size;
1903
 
                
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;
1910
 
                
1911
 
                *have_data = true;
1912
 
        }
1913
 
        unlock_(lock);
1914
 
        iRepoOffset += head_size + blob_size;
1915
 
        return_(true);
1916
 
}
1917
 
 
1918
 
bool MSMetaDataTable::returnRecord(char *buf)
1919
 
{
1920
 
        bool have_data = false;
1921
 
 
1922
 
        if (resetScan(false, &have_data) && have_data)
1923
 
                return(returnSubRecord(buf));
1924
 
                
1925
 
        return false;
1926
 
}
1927
 
 
1928
 
bool MSMetaDataTable::nextRecord(char **name, char **value)
1929
 
{
1930
 
        if (iMetDataPos < iMetDataSize) {
1931
 
                char *data = iMetData->getBuffer(iMetDataPos);
1932
 
                
1933
 
                *name = data;
1934
 
                data += strlen(*name) +1;
1935
 
                *value = data;
1936
 
                data += strlen(*value) +1;
1937
 
                
1938
 
                iMetDataPos += data - *name;
1939
 
                ASSERT(iMetDataPos <= iMetDataSize);
1940
 
                
1941
 
                return true;            
1942
 
        }
1943
 
 
1944
 
        return false;
1945
 
        
1946
 
}
1947
 
 
1948
 
bool MSMetaDataTable::returnSubRecord(char *buf)
1949
 
{
1950
 
        char *name, *value;
1951
 
        
1952
 
        if (nextRecord(&name, &value)) {
1953
 
                returnRow(name, value, buf);            
1954
 
                return true;            
1955
 
        }
1956
 
 
1957
 
        return false;
1958
 
}
1959
 
 
1960
 
void MSMetaDataTable::returnRow(char *name, char *value, char *buf)
1961
 
{
1962
 
        TABLE           *table = mySQLTable;
1963
 
        Field           *curr_field;
1964
 
        byte            *save;
1965
 
        MY_BITMAP       *save_write_set;
1966
 
 
1967
 
        save_write_set = table->write_set;
1968
 
        table->write_set = NULL;
1969
 
 
1970
 
#ifdef DRIZZLED
1971
 
        memset(buf, 0xFF, table->getNullBytes());
1972
 
#else
1973
 
        memset(buf, 0xFF, table->s->null_bytes);
1974
 
#endif
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();
1980
 
#else
1981
 
#ifdef DRIZZLED
1982
 
                curr_field->ptr = (byte *) buf + curr_field->offset(curr_field->getTable()->getInsertRecord());
1983
 
#else
1984
 
                curr_field->ptr = (byte *) buf + curr_field->offset(curr_field->table->record[0]);
1985
 
#endif
1986
 
#endif
1987
 
                switch (curr_field->field_name[0]) {
1988
 
                        case 'R':
1989
 
                                switch (curr_field->field_name[6]) {
1990
 
                                        case 't':
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);
1995
 
                                                break;
1996
 
                                        case 'l':
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);
2001
 
                                                break;
2002
 
                                }
2003
 
                                break;
2004
 
                        case 'N':
2005
 
                                // Name        
2006
 
                                ASSERT(strcmp(curr_field->field_name, "Name") == 0);
2007
 
                                curr_field->store(name, strlen(name), &UTF8_CHARSET);
2008
 
                                setNotNullInRecord(curr_field, buf);
2009
 
                                break;
2010
 
                        case 'V':
2011
 
                                // Value        
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);
2015
 
                                break;
2016
 
                }
2017
 
                curr_field->ptr = save;
2018
 
        }
2019
 
 
2020
 
        table->write_set = save_write_set;
2021
 
}
2022
 
 
2023
 
 
2024
 
#ifdef HAVE_ALIAS_SUPPORT
2025
 
bool MSMetaDataTable::matchAlias(uint32_t repo_id, uint64_t offset, const char *alias)
2026
 
{
2027
 
        bool matched = false, have_data = false;
2028
 
        enter_();
2029
 
        
2030
 
        if (resetScan(true, &have_data, repo_id) && have_data) {
2031
 
                const char *blob_alias;
2032
 
                MetaData md(iMetData->getBuffer(0), iMetDataSize);
2033
 
                
2034
 
                blob_alias = md.findAlias();
2035
 
                matched = (blob_alias && !UTF8_CHARSET.strcasecmp(blob_alias, alias));
2036
 
        }
2037
 
        
2038
 
        return_(matched);
2039
 
}
2040
 
#endif
2041
 
 
2042
 
void MSMetaDataTable::insertRow(char *buf)
2043
 
{
2044
 
        uint32_t repo_index;
2045
 
        String meta_name, meta_value;   
2046
 
        uint16_t data_len;
2047
 
        uint64_t repo_offset;
2048
 
        char *data;             
2049
 
        bool have_data, reset_alias = false;
2050
 
        
2051
 
        enter_();
2052
 
        
2053
 
        // Metadata inserts are ignored during reovery.
2054
 
        // They will be restored from the dump table.
2055
 
        if (myShare->mySysDatabase->isRecovering())
2056
 
                exit_();
2057
 
                
2058
 
        seqScanReset();
2059
 
 
2060
 
        getFieldValue(buf, 0, &repo_index);
2061
 
        getFieldValue(buf, 1, &repo_offset);
2062
 
        getFieldValue(buf, 2, &meta_name);
2063
 
        getFieldValue(buf, 3, &meta_value);
2064
 
        
2065
 
        if (!repo_index)
2066
 
                CSException::throwException(CS_CONTEXT, HA_ERR_CANNOT_ADD_FOREIGN, "Invalid Repository_id");
2067
 
                
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");
2071
 
        
2072
 
        const char *alias = NULL, *tag = meta_name.c_str();
2073
 
        
2074
 
        if (iMetDataSize) {
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.");
2079
 
                        
2080
 
#ifdef HAVE_ALIAS_SUPPORT
2081
 
                alias = md.findAlias();
2082
 
#endif
2083
 
        }
2084
 
        
2085
 
        // Create the meta data record.
2086
 
#ifdef HAVE_ALIAS_SUPPORT
2087
 
        if (alias)
2088
 
                data = iMetData->getBuffer(0); // This is to be able to test if the alias pointer needs to be reset.
2089
 
        else
2090
 
#endif
2091
 
                data = NULL;
2092
 
                
2093
 
        iMetData->setLength(iMetDataSize + meta_name.length() + meta_value.length()  + 2);
2094
 
        
2095
 
#ifdef HAVE_ALIAS_SUPPORT
2096
 
        if (alias && (data != iMetData->getBuffer(0))) // The buffer moved, adjust the alias.
2097
 
                alias += (iMetData->getBuffer(0) - data);
2098
 
#endif
2099
 
        
2100
 
        data = iMetData->getBuffer(0);
2101
 
        data_len = iMetDataSize;
2102
 
        
2103
 
#ifdef HAVE_ALIAS_SUPPORT
2104
 
        if ((!alias) && !UTF8_CHARSET.strcasecmp(MS_ALIAS_TAG, tag)) {
2105
 
                reset_alias = true;
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.
2108
 
        } else 
2109
 
#endif
2110
 
                memcpy(data + data_len, meta_name.data(), meta_name.length());
2111
 
                
2112
 
        data_len += meta_name.length();
2113
 
        data[data_len] = 0;
2114
 
        data_len++;
2115
 
 
2116
 
        memcpy(data + data_len, meta_value.data(), meta_value.length());
2117
 
        data_len += meta_value.length();
2118
 
        data[data_len] = 0;
2119
 
        data_len++;
2120
 
        
2121
 
        // Update the blob header with the new meta data.
2122
 
        MSOpenTable     *otab = MSOpenTable::newOpenTable(NULL);
2123
 
        push_(otab);
2124
 
        iRepoFile->setBlobMetaData(otab, repo_offset, data, data_len, reset_alias, alias);
2125
 
        release_(otab);
2126
 
                
2127
 
        exit_();
2128
 
}
2129
 
/*
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;
2135
 
 
2136
 
delete from pbms_mata_data where value = "xx";
2137
 
select * from pbms_mata_data;
2138
 
 
2139
 
update pbms_mata_data set value = "!!" where name = "ATAG 3";
2140
 
update pbms_mata_data set Repo_blob_offset = 383 where value = "!!";
2141
 
 
2142
 
delete from pbms_mata_data where Repo_blob_offset = 921;
2143
 
*/
2144
 
//insert into pbms_mata_data values(1, 921, "blob_ALIAs", "My_alias");
2145
 
//select * from pbms_mata_data;
2146
 
//select * from pbms_repository;
2147
 
 
2148
 
 
2149
 
void MSMetaDataTable::deleteRow(char *buf)
2150
 
{
2151
 
        uint32_t repo_index;
2152
 
        String meta_name, meta_value;   
2153
 
        uint16_t record_size;
2154
 
        uint64_t repo_offset;
2155
 
        char *data;
2156
 
        bool have_data, reset_alias = false;
2157
 
        
2158
 
        enter_();
2159
 
        
2160
 
        seqScanReset();
2161
 
 
2162
 
        getFieldValue(buf, 0, &repo_index);
2163
 
        getFieldValue(buf, 1, &repo_offset);
2164
 
        getFieldValue(buf, 2, &meta_name);
2165
 
        getFieldValue(buf, 3, &meta_value);
2166
 
 
2167
 
        if (!repo_index)
2168
 
                CSException::throwException(CS_CONTEXT, HA_ERR_CANNOT_ADD_FOREIGN, "Invalid Repository_id");
2169
 
                
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");
2173
 
        
2174
 
        const char *alias = NULL, *value = NULL, *tag = meta_name.c_str();
2175
 
        char *location;
2176
 
        
2177
 
        // Check to see name exists.
2178
 
        MetaData md;
2179
 
 
2180
 
        md.use_data(iMetData->getBuffer(0), iMetDataSize);
2181
 
        if (iMetDataSize) 
2182
 
                value = md.findName(tag);
2183
 
        
2184
 
        if (value == NULL)
2185
 
                CSException::throwException(CS_CONTEXT, HA_ERR_KEY_NOT_FOUND, "Meta data tag dosn't exists.");
2186
 
                        
2187
 
#ifdef HAVE_ALIAS_SUPPORT
2188
 
        alias = md.findAlias();
2189
 
        
2190
 
        if (alias == value) {
2191
 
                reset_alias = true;
2192
 
                alias = NULL;
2193
 
        }
2194
 
#endif
2195
 
        
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
2202
 
 
2203
 
#ifdef HAVE_ALIAS_SUPPORT
2204
 
        // Get the alias again incase it moved.
2205
 
        if (alias)
2206
 
                alias = md.findAlias();
2207
 
#endif
2208
 
        
2209
 
        // Update the blob header with the new meta data.
2210
 
        MSOpenTable     *otab = MSOpenTable::newOpenTable(NULL);
2211
 
        push_(otab);
2212
 
        iRepoFile->setBlobMetaData(otab, repo_offset, data, iMetDataSize, reset_alias, alias);
2213
 
        release_(otab);
2214
 
 
2215
 
        exit_();
2216
 
}
2217
 
 
2218
 
class UpdateRowCleanUp : public CSRefObject {
2219
 
        bool do_cleanup;
2220
 
        MSMetaDataTable *tab;
2221
 
        char *row_data;
2222
 
        
2223
 
        uint32_t ref_id;
2224
 
 
2225
 
        public:
2226
 
        
2227
 
        UpdateRowCleanUp(): CSRefObject(),
2228
 
                do_cleanup(false), tab(NULL), row_data(NULL){}
2229
 
                
2230
 
        ~UpdateRowCleanUp() 
2231
 
        {
2232
 
                if (do_cleanup) {
2233
 
                        tab->deleteRow(row_data);
2234
 
                }
2235
 
        }
2236
 
        
2237
 
        void setCleanUp(MSMetaDataTable *table, char *data)
2238
 
        {
2239
 
                row_data = data;
2240
 
                tab = table;
2241
 
                do_cleanup = true;
2242
 
        }
2243
 
        
2244
 
        void cancelCleanUp()
2245
 
        {
2246
 
                do_cleanup = false;
2247
 
        }
2248
 
        
2249
 
};
2250
 
 
2251
 
void MSMetaDataTable::updateRow(char *old_data, char *new_data)
2252
 
{
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;
2258
 
        char *data;     
2259
 
        bool have_data, reset_alias = false;
2260
 
        
2261
 
        enter_();
2262
 
        
2263
 
        seqScanReset();
2264
 
 
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);
2269
 
 
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);
2274
 
 
2275
 
        if ((!o_repo_index) || (!n_repo_index))
2276
 
                CSException::throwException(CS_CONTEXT, HA_ERR_CANNOT_ADD_FOREIGN, "Invalid Repository_id");
2277
 
        
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());
2282
 
                push_(cleanup);
2283
 
 
2284
 
                insertRow(new_data);
2285
 
                
2286
 
                cleanup->setCleanUp(this, new_data);
2287
 
                
2288
 
                deleteRow(old_data);
2289
 
                
2290
 
                cleanup->cancelCleanUp();
2291
 
                release_(cleanup);
2292
 
                
2293
 
                exit_();
2294
 
        }
2295
 
        
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");
2299
 
        
2300
 
        char *location;
2301
 
        const char *value, *alias = NULL, *n_tag = n_meta_name.c_str(), *o_tag = o_meta_name.c_str();
2302
 
        
2303
 
        if (!UTF8_CHARSET.strcasecmp(o_tag, n_tag))
2304
 
                n_tag = NULL;
2305
 
                
2306
 
        MetaData md;
2307
 
 
2308
 
        md.use_data(iMetData->getBuffer(0), iMetDataSize);
2309
 
        
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.");
2312
 
                        
2313
 
        if (n_tag && (md.findName(n_tag) != NULL))
2314
 
                CSException::throwException(CS_CONTEXT, HA_ERR_FOUND_DUPP_KEY, "Meta data tag already exists.");
2315
 
                
2316
 
#ifdef HAVE_ALIAS_SUPPORT
2317
 
        alias = md.findAlias();
2318
 
 
2319
 
        if (alias == value) {
2320
 
                reset_alias = true;
2321
 
                alias = NULL; // The alias is being deleted.
2322
 
        }
2323
 
#endif
2324
 
        
2325
 
        if (!n_tag)
2326
 
                n_tag = o_tag;
2327
 
                
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
2334
 
        
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);
2337
 
        
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.
2341
 
        if (alias)
2342
 
                alias = md.findAlias();
2343
 
#endif
2344
 
        
2345
 
        data = iMetData->getBuffer(0);
2346
 
                
2347
 
#ifdef HAVE_ALIAS_SUPPORT
2348
 
        if ((!alias) && !UTF8_CHARSET.strcasecmp(MS_ALIAS_TAG, n_tag)) {
2349
 
                reset_alias = true;
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.
2352
 
        } else 
2353
 
#endif
2354
 
                memcpy(data + iMetDataSize, n_meta_name.data(), n_meta_name.length());
2355
 
                
2356
 
        iMetDataSize += n_meta_name.length();
2357
 
        data[iMetDataSize] = 0;
2358
 
        iMetDataSize++;
2359
 
 
2360
 
        memcpy(data + iMetDataSize, n_meta_value.data(), n_meta_value.length());
2361
 
        iMetDataSize += n_meta_value.length();
2362
 
        data[iMetDataSize] = 0;
2363
 
        iMetDataSize++;
2364
 
        
2365
 
        
2366
 
        // Update the blob header with the new meta data.
2367
 
        MSOpenTable     *otab = MSOpenTable::newOpenTable(NULL);
2368
 
        push_(otab);
2369
 
        iRepoFile->setBlobMetaData(otab, n_repo_offset, data, iMetDataSize, reset_alias, alias);
2370
 
        release_(otab);
2371
 
                
2372
 
        exit_();
2373
 
}
2374
 
 
2375
 
/*
2376
 
 * -------------------------------------------------------------------------
2377
 
 * SYSTEM TABLE SHARES
2378
 
 */
2379
 
 
2380
 
CSSyncSortedList *MSSystemTableShare::gSystemTableList;
2381
 
 
2382
 
MSSystemTableShare::MSSystemTableShare():
2383
 
CSRefObject(),
2384
 
myTablePath(NULL),
2385
 
mySysDatabase(NULL),
2386
 
iOpenCount(0)
2387
 
{
2388
 
        thr_lock_init(&myThrLock);
2389
 
}
2390
 
 
2391
 
MSSystemTableShare::~MSSystemTableShare()
2392
 
{
2393
 
#ifndef DRIZZLED
2394
 
        thr_lock_delete(&myThrLock);
2395
 
#endif
2396
 
        if (myTablePath) {
2397
 
                myTablePath->release();
2398
 
                myTablePath = NULL;
2399
 
        }
2400
 
        if (mySysDatabase) {
2401
 
                mySysDatabase->release();
2402
 
                mySysDatabase = NULL;
2403
 
        }
2404
 
}
2405
 
 
2406
 
CSObject *MSSystemTableShare::getKey()
2407
 
{
2408
 
        return (CSObject *) myTablePath;
2409
 
}
2410
 
 
2411
 
int MSSystemTableShare::compareKey(CSObject *key)
2412
 
{
2413
 
        return myTablePath->compare((CSString *) key);
2414
 
}
2415
 
 
2416
 
void MSSystemTableShare::startUp()
2417
 
{
2418
 
        new_(gSystemTableList, CSSyncSortedList);
2419
 
}
2420
 
 
2421
 
void MSSystemTableShare::shutDown()
2422
 
{
2423
 
        if (gSystemTableList) {
2424
 
                gSystemTableList->release();
2425
 
                gSystemTableList = NULL;
2426
 
        }
2427
 
}
2428
 
 
2429
 
MSOpenSystemTable *MSSystemTableShare::openSystemTable(const char *table_path, TABLE *table)
2430
 
{
2431
 
        CSString                        *table_url;
2432
 
        MSSystemTableShare      *share;
2433
 
        MSOpenSystemTable       *otab = NULL;
2434
 
        SysTableType            table_type;
2435
 
 
2436
 
        enter_();
2437
 
        
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");
2441
 
        
2442
 
        table_path = cs_last_name_of_path(table_path, 2);
2443
 
        table_url = CSString::newString(table_path);
2444
 
        push_(table_url);
2445
 
 
2446
 
        lock_(gSystemTableList);
2447
 
        if (!(share = (MSSystemTableShare *) gSystemTableList->find(table_url))) {
2448
 
                share = MSSystemTableShare::newTableShare(RETAIN(table_url));
2449
 
                gSystemTableList->add(share);
2450
 
        }
2451
 
        
2452
 
        switch (table_type) {
2453
 
                case SYS_REP:
2454
 
                        new_(otab, MSRepositoryTable(share, table));
2455
 
                        break;
2456
 
                case SYS_REF:
2457
 
                        new_(otab, MSReferenceTable(share, table));
2458
 
                        break;
2459
 
                case SYS_BLOB:
2460
 
                        new_(otab, MSBlobDataTable(share, table));
2461
 
                        break;
2462
 
                case SYS_DUMP:
2463
 
                        new_(otab, MSDumpTable(share, table));
2464
 
                        break;
2465
 
                case SYS_META:
2466
 
                        new_(otab, MSMetaDataTable(share, table));
2467
 
                        break;
2468
 
                case SYS_HTTP:
2469
 
                        new_(otab, MSHTTPHeaderTable(share, table));
2470
 
                        break;
2471
 
#ifdef HAVE_ALIAS_SUPPORT
2472
 
                case SYS_ALIAS:
2473
 
                        new_(otab, MSBlobAliasTable(share, table));
2474
 
                        break;
2475
 
#endif
2476
 
                case SYS_VARIABLE:
2477
 
                        new_(otab, MSVariableTable(share, table));
2478
 
                        break;
2479
 
                case SYS_CLOUD:
2480
 
                        new_(otab, MSCloudTable(share, table));
2481
 
                        break;
2482
 
                case SYS_BACKUP:
2483
 
                        new_(otab, MSBackupTable(share, table));
2484
 
                        break;
2485
 
#ifndef DRIZZLED
2486
 
                case SYS_ENABLED:
2487
 
                        new_(otab, MSEnabledTable(share, table));
2488
 
                        break;
2489
 
#endif
2490
 
                case SYS_UNKNOWN:
2491
 
                        break;
2492
 
        }
2493
 
        
2494
 
        share->iOpenCount++;
2495
 
        unlock_(gSystemTableList);
2496
 
 
2497
 
        release_(table_url);
2498
 
        return_(otab);
2499
 
}
2500
 
 
2501
 
void MSSystemTableShare::removeDatabaseSystemTables(MSDatabase *doomed_db)
2502
 
{
2503
 
        MSSystemTableShare      *share;
2504
 
        uint32_t i= 0;
2505
 
        enter_();
2506
 
        
2507
 
        push_(doomed_db);
2508
 
        lock_(gSystemTableList);
2509
 
        while ((share = (MSSystemTableShare *) gSystemTableList->itemAt(i))) {
2510
 
                if (share->mySysDatabase == doomed_db) {
2511
 
                        gSystemTableList->remove(share->myTablePath);
2512
 
                } else
2513
 
                        i++;
2514
 
        }
2515
 
        
2516
 
        unlock_(gSystemTableList);
2517
 
        release_(doomed_db);
2518
 
        exit_();
2519
 
}
2520
 
 
2521
 
void MSSystemTableShare::releaseSystemTable(MSOpenSystemTable *tab)
2522
 
{
2523
 
        enter_();
2524
 
        lock_(gSystemTableList);
2525
 
        tab->myShare->iOpenCount--;
2526
 
        if (!tab->myShare->iOpenCount) {
2527
 
                gSystemTableList->remove(tab->myShare->myTablePath);
2528
 
        }
2529
 
        unlock_(gSystemTableList);
2530
 
        exit_();
2531
 
}
2532
 
 
2533
 
MSSystemTableShare *MSSystemTableShare::newTableShare(CSString *table_path)
2534
 
{
2535
 
        MSSystemTableShare *tab;
2536
 
 
2537
 
        enter_();
2538
 
        if (!(tab = new MSSystemTableShare())) {
2539
 
                table_path->release();
2540
 
                CSException::throwOSError(CS_CONTEXT, ENOMEM);
2541
 
        }
2542
 
        push_(tab);
2543
 
        tab->myTablePath = table_path;
2544
 
        tab->mySysDatabase = MSDatabase::getDatabase(table_path->left("/", -1), true);
2545
 
        pop_(tab);
2546
 
        return_(tab);
2547
 
}
2548
 
 
2549
 
void PBMSSystemTables::systemTablesStartUp()
2550
 
{
2551
 
        MSCloudTable::startUp();
2552
 
        MSBackupTable::startUp();
2553
 
}
2554
 
 
2555
 
void PBMSSystemTables::systemTableShutDown()
2556
 
{
2557
 
        MSBackupTable::shutDown();
2558
 
        MSCloudTable::shutDown();
2559
 
}
2560