1
/* Copyright (C) 2006 MySQL AB
3
This program is free software; you can redistribute it and/or modify
4
it under the terms of the GNU General Public License as published by
5
the Free Software Foundation; version 2 of the License.
7
This program is distributed in the hope that it will be useful,
8
but WITHOUT ANY WARRANTY; without even the implied warranty of
9
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10
GNU General Public License for more details.
12
You should have received a copy of the GNU General Public License
13
along with this program; if not, write to the Free Software
14
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
22
#include "mysql_priv.h"
23
#include "ha_falcon.h"
24
#include "StorageConnection.h"
25
#include "StorageTable.h"
26
#include "StorageTableShare.h"
27
#include "StorageHandler.h"
29
#include "InfoTable.h"
30
//#include "TimeTest.h"
32
#define I64FORMAT "%I64d"
34
#define I64FORMAT "%lld"
37
#include "ScaledBinary.h"
43
#define MIN(a,b) ((a <= b) ? (a) : (b))
44
#define MAX(a,b) ((a >= b) ? (a) : (b))
47
static const uint LOAD_AUTOCOMMIT_RECORDS = 10000;
48
static const char falcon_hton_name[] = "Falcon";
50
static const char *falcon_extensions[] = {
57
static StorageHandler *storageHandler;
59
unsigned long long falcon_record_memory_max;
60
int falcon_record_scavenge_threshold;
61
int falcon_record_scavenge_floor;
62
unsigned long long falcon_initial_allocation;
63
uint falcon_allocation_extent;
64
my_bool falcon_disable_fsync;
65
unsigned long long falcon_page_cache_size;
66
uint falcon_page_size;
67
uint falcon_serial_log_buffers;
68
char* falcon_serial_log_dir;
69
char* falcon_checkpoint_schedule;
70
char* falcon_scavenge_schedule;
71
int falcon_debug_mask;
72
my_bool falcon_debug_server;
73
FILE *falcon_log_file;
74
uint falcon_index_chill_threshold;
75
uint falcon_record_chill_threshold;
76
uint falcon_tablespace_mode;
77
uint falcon_max_transaction_backlog;
80
static struct st_mysql_show_var falconStatus[]=
82
//{"static", (char*)"just a static text", SHOW_CHAR},
83
//{"called", (char*)&number_of_calls, SHOW_LONG},
87
extern THD* current_thd;
89
static handler *falcon_create_handler(handlerton *hton,
90
TABLE_SHARE *table, MEM_ROOT *mem_root)
92
return new (mem_root) StorageInterface(hton, table);
95
handlerton *falcon_hton;
97
void openFalconLogFile(const char *file)
100
fclose(falcon_log_file);
101
falcon_log_file = fopen(file, "a");
104
void closeFalconLogFile()
108
fclose(falcon_log_file);
109
falcon_log_file = NULL;
113
void flushFalconLogFile()
116
fflush(falcon_log_file);
119
int StorageInterface::falcon_init(void *p)
121
DBUG_ENTER("falcon_init");
122
falcon_hton = (handlerton *)p;
125
storageHandler = getFalconStorageHandler(sizeof(THR_LOCK));
127
falcon_hton->state = SHOW_OPTION_YES;
128
falcon_hton->db_type = DB_TYPE_FALCON;
129
falcon_hton->savepoint_offset = sizeof(void*);
130
falcon_hton->close_connection = StorageInterface::closeConnection;
131
falcon_hton->savepoint_set = StorageInterface::savepointSet;
132
falcon_hton->savepoint_rollback = StorageInterface::savepointRollback;
133
falcon_hton->savepoint_release = StorageInterface::savepointRelease;
134
falcon_hton->commit = StorageInterface::commit;
135
falcon_hton->rollback = StorageInterface::rollback;
136
falcon_hton->create = falcon_create_handler;
137
falcon_hton->drop_database = StorageInterface::dropDatabase;
138
falcon_hton->panic = StorageInterface::panic;
139
falcon_hton->alter_table_flags = StorageInterface::alter_table_flags;
142
falcon_hton->prepare = StorageInterface::prepare;
145
falcon_hton->commit_by_xid = StorageInterface::commit_by_xid;
146
falcon_hton->rollback_by_xid = StorageInterface::rollback_by_xid;
148
falcon_hton->alter_tablespace = StorageInterface::alter_tablespace;
149
//falcon_hton->show_status = StorageInterface::show_status;
150
falcon_hton->flags = HTON_NO_FLAGS;
152
storageHandler->addNfsLogger(-1, StorageInterface::logger, NULL);
154
if (falcon_debug_server)
155
storageHandler->startNfsServer();
158
//timeTest.testScaled(16, 2, 100000);
160
//pluginHandler = new NfsPluginHandler;
166
int StorageInterface::falcon_deinit(void *p)
168
storageHandler->shutdownHandler();
173
int falcon_strnxfrm (void *cs,
174
const char *dst, uint dstlen,
175
const char *src, uint srclen)
177
CHARSET_INFO *charset = (CHARSET_INFO*) cs;
179
return charset->coll->strnxfrm(charset, (uchar *) dst, dstlen, MAX_INDEX_KEY_LENGTH,
180
(uchar *) src, srclen, 0);
183
char falcon_get_pad_char (void *cs)
185
return (char) ((CHARSET_INFO*) cs)->pad_char;
188
int falcon_cs_is_binary (void *cs)
190
return (0 == strcmp(((CHARSET_INFO*) cs)->name, "binary"));
191
// return ((((CHARSET_INFO*) cs)->state & MY_CS_BINSORT) == MY_CS_BINSORT);
194
unsigned int falcon_get_mbmaxlen (void *cs)
196
return ((CHARSET_INFO*) cs)->mbmaxlen;
199
char falcon_get_min_sort_char (void *cs)
201
return (char) ((CHARSET_INFO*) cs)->min_sort_char;
204
// Return the actual number of characters in the string
205
// Note, this is not the number of characters with collatable weight.
207
uint falcon_strnchrlen(void *cs, const char *s, uint l)
209
CHARSET_INFO *charset = (CHARSET_INFO*) cs;
211
if (charset->mbmaxlen == 1)
215
uchar *ch = (uchar *) s;
220
int len = charset->cset->mbcharlen(charset, *ch);
222
break; // invalid character.
231
// Determine how many bytes are required to store the output of cs->coll->strnxfrm()
232
// cs is how the source string is formatted.
233
// srcLen is the number of bytes in the source string.
234
// partialKey is the max key buffer size if not zero.
235
// bufSize is the ultimate maximum destSize.
236
// If the string is multibyte, strnxfrmlen expects srcLen to be
237
// the maximum number of characters this can be. Falcon wants to send
238
// a number that represents the actual number of characters in the string
239
// so that the call to cs->coll->strnxfrm() will not pad.
241
uint falcon_strnxfrmlen(void *cs, const char *s, uint srcLen,
242
int partialKey, int bufSize)
244
CHARSET_INFO *charset = (CHARSET_INFO*) cs;
245
uint chrLen = falcon_strnchrlen(cs, s, srcLen);
246
int maxChrLen = partialKey ? min(chrLen, partialKey / charset->mbmaxlen) : chrLen;
248
return min(charset->coll->strnxfrmlen(charset, maxChrLen * charset->mbmaxlen), (uint) bufSize);
251
// Return the number of bytes used in s to hold a certain number of characters.
252
// This partialKey is a byte length with charset->mbmaxlen figured in.
253
// In other words, it is the number of characters times mbmaxlen.
255
uint falcon_strntrunc(void *cs, int partialKey, const char *s, uint l)
257
CHARSET_INFO *charset = (CHARSET_INFO*) cs;
259
if ((charset->mbmaxlen == 1) || (partialKey == 0))
260
return min((uint) partialKey, l);
262
int charLimit = partialKey / charset->mbmaxlen;
263
uchar *ch = (uchar *) s;
266
while ((ch < end) && charLimit)
268
int len = charset->cset->mbcharlen(charset, *ch);
270
break; // invalid character.
276
return ch - (uchar *) s;
279
int falcon_strnncoll(void *cs, const char *s1, uint l1, const char *s2, uint l2, char flag)
281
CHARSET_INFO *charset = (CHARSET_INFO*) cs;
283
return charset->coll->strnncoll(charset, (uchar *) s1, l1, (uchar *) s2, l2, flag);
286
int falcon_strnncollsp(void *cs, const char *s1, uint l1, const char *s2, uint l2, char flag)
288
CHARSET_INFO *charset = (CHARSET_INFO*) cs;
290
return charset->coll->strnncollsp(charset, (uchar *) s1, l1, (uchar *) s2, l2, flag);
293
int (*strnncoll)(struct charset_info_st *, const uchar *, uint, const uchar *, uint, my_bool);
298
static const char THIS_FILE[]=__FILE__;
303
typedef decimal_digit_t dec1;
304
typedef longlong dec2;
306
#define DIG_PER_DEC1 9
307
#define DIG_MASK 100000000
308
#define DIG_BASE 1000000000
309
#define DIG_MAX (DIG_BASE-1)
310
#define DIG_BASE2 ((dec2)DIG_BASE * (dec2)DIG_BASE)
311
#define ROUND_UP(X) (((X)+DIG_PER_DEC1-1)/DIG_PER_DEC1)
314
//////////////////////////////////////////////////////////////////////
315
// Construction/Destruction
316
//////////////////////////////////////////////////////////////////////
318
StorageInterface::StorageInterface(handlerton *hton, st_table_share *table_arg)
319
: handler(hton, table_arg)
321
ref_length = sizeof(lastRecord);
322
stats.records = 1000;
323
stats.data_file_length = 10000;
325
lockForUpdate = false;
327
storageConnection = NULL;
338
recordLength = table_arg->reclength;
344
StorageInterface::~StorageInterface(void)
349
for (StorageBlob *blob; (blob = freeBlobs); )
351
freeBlobs = blob->next;
357
storageTable->deleteStorageTable();
361
if (storageConnection)
363
storageConnection->release();
364
storageConnection = NULL;
370
int StorageInterface::rnd_init(bool scan)
372
DBUG_ENTER("StorageInterface::rnd_init");
380
int StorageInterface::open(const char *name, int mode, uint test_if_locked)
382
DBUG_ENTER("StorageInterface::open");
385
mySqlThread = current_thd;
389
storageShare = storageHandler->findTable(name);
390
storageConnection = storageHandler->getStorageConnection(storageShare, mySqlThread, mySqlThread->thread_id, OpenDatabase, falcon_tablespace_mode);
392
if (!storageConnection)
393
DBUG_RETURN(HA_ERR_NO_CONNECTION);
395
*((StorageConnection**) thd_ha_data(mySqlThread, falcon_hton)) = storageConnection;
396
storageConnection->addRef();
397
storageTable = storageConnection->getStorageTable(storageShare);
399
if (!storageShare->initialized)
401
storageShare->lock(true);
403
if (!storageShare->initialized)
405
thr_lock_init((THR_LOCK *)storageShare->impure);
406
storageShare->setTablePath(name, tempTable);
407
storageShare->initialized = true;
410
// Register any collations used
412
uint fieldCount = (table) ? table->s->fields : 0;
414
for (uint n = 0; n < fieldCount; ++n)
416
Field *field = table->field[n];
417
CHARSET_INFO *charset = field->charset();
420
storageShare->registerCollation(charset->name, charset);
423
storageShare->unlock();
427
int ret = storageTable->open();
430
DBUG_RETURN(error(ret));
432
thr_lock_data_init((THR_LOCK *)storageShare->impure, &lockData, NULL);
436
DBUG_RETURN(error(ret));
442
StorageConnection* StorageInterface::getStorageConnection(THD* thd)
444
return *(StorageConnection**) thd_ha_data(thd, falcon_hton);
447
int StorageInterface::close(void)
449
DBUG_ENTER("StorageInterface::close");
453
int StorageInterface::rnd_next(uchar *buf)
455
DBUG_ENTER("StorageInterface::rnd_next");
456
ha_statistic_increment(&SSV::ha_read_rnd_next_count);
461
lastRecord = storageTable->next(nextRecord, lockForUpdate);
465
if (lastRecord == StorageErrorRecordNotFound)
468
table->status = STATUS_NOT_FOUND;
469
DBUG_RETURN(HA_ERR_END_OF_FILE);
472
DBUG_RETURN(error(lastRecord));
478
nextRecord = lastRecord + 1;
484
void StorageInterface::unlock_row(void)
486
storageTable->unlockRow();
489
int StorageInterface::rnd_pos(uchar *buf, uchar *pos)
492
DBUG_ENTER("StorageInterface::rnd_pos");
493
ha_statistic_increment(&SSV::ha_read_rnd_next_count);
495
memcpy(&recordNumber, pos, sizeof(recordNumber));
500
int ret = storageTable->fetch(recordNumber, lockForUpdate);
504
table->status = STATUS_NOT_FOUND;
505
DBUG_RETURN(error(ret));
508
lastRecord = recordNumber;
515
void StorageInterface::position(const uchar *record)
517
DBUG_ENTER("StorageInterface::position");
518
memcpy(ref, &lastRecord, sizeof(lastRecord));
522
int StorageInterface::info(uint what)
524
DBUG_ENTER("StorageInterface::info");
527
if (what & HA_STATUS_VARIABLE)
531
if (what & HA_STATUS_AUTO)
532
stats.auto_increment_value = storageShare->getSequenceValue(0);
534
if (what & HA_STATUS_ERRKEY)
535
errkey = indexErrorId;
541
void StorageInterface::getDemographics(void)
543
DBUG_ENTER("StorageInterface::getDemographics");
545
stats.records = (ha_rows) storageShare->estimateCardinality();
546
// Temporary fix for Bug#28686. (HK) 2007-05-26.
550
stats.block_size = 4096;
552
for (uint n = 0; n < table->s->keys; ++n)
554
KEY *key = table->s->key_info + n;
555
StorageIndexDesc *desc = storageShare->getIndex(n);
559
ha_rows n = 1 << desc->numberSegments;
561
for (uint segment = 0; segment < key->key_parts; ++segment, n >>= 1)
563
ha_rows recordsPerSegment = (ha_rows) desc->segmentRecordCounts[segment];
564
key->rec_per_key[segment] = MAX(recordsPerSegment, n);
572
int StorageInterface::optimize(THD* thd, HA_CHECK_OPT* check_opt)
574
DBUG_ENTER("StorageInterface::optimize");
576
int ret = storageTable->optimize();
579
DBUG_RETURN(error(ret));
584
uint8 StorageInterface::table_cache_type(void)
586
return HA_CACHE_TBL_TRANSACT;
589
const char *StorageInterface::table_type(void) const
591
DBUG_ENTER("StorageInterface::table_type");
592
DBUG_RETURN(falcon_hton_name);
596
const char **StorageInterface::bas_ext(void) const
598
DBUG_ENTER("StorageInterface::bas_ext");
599
DBUG_RETURN(falcon_extensions);
603
ulonglong StorageInterface::table_flags(void) const
605
DBUG_ENTER("StorageInterface::table_flags");
606
DBUG_RETURN(HA_REC_NOT_IN_SEQ | HA_NULL_IN_KEY | HA_AUTO_PART_KEY |
607
HA_PARTIAL_COLUMN_READ | HA_CAN_GEOMETRY);
611
ulong StorageInterface::index_flags(uint idx, uint part, bool all_parts) const
613
DBUG_ENTER("StorageInterface::index_flags");
614
DBUG_RETURN(HA_READ_RANGE | HA_KEY_SCAN_NOT_ROR);
618
int StorageInterface::create(const char *mySqlName, TABLE *form,
619
HA_CREATE_INFO *info)
621
DBUG_ENTER("StorageInterface::create");
622
tempTable = (info->options & HA_LEX_CREATE_TMP_TABLE) ? true : false;
623
OpenOption openOption = (tempTable) ? OpenTemporaryDatabase : OpenOrCreateDatabase;
627
storageTable->deleteStorageTable();
632
mySqlThread = current_thd;
634
storageShare = storageHandler->createTable(mySqlName, info->tablespace, tempTable);
637
DBUG_RETURN(HA_ERR_TABLE_EXIST);
639
storageConnection = storageHandler->getStorageConnection(storageShare, mySqlThread, mySqlThread->thread_id, openOption, falcon_tablespace_mode);
640
*((StorageConnection**) thd_ha_data(mySqlThread, falcon_hton)) = storageConnection;
642
if (!storageConnection)
643
DBUG_RETURN(HA_ERR_NO_CONNECTION);
645
storageTable = storageConnection->getStorageTable(storageShare);
646
storageTable->localTable = this;
649
int64 incrementValue = 0;
652
const char *tableName = storageTable->getName();
653
const char *schemaName = storageTable->getSchemaName();
654
gen.gen("create table \"%s\".\"%s\" (\n", schemaName, tableName);
655
const char *sep = "";
656
char nameBuffer[129];
658
for (n = 0; n < form->s->fields; ++n)
660
Field *field = form->field[n];
661
CHARSET_INFO *charset = field->charset();
664
storageShare->registerCollation(charset->name, charset);
666
storageShare->cleanupFieldName(field->field_name, nameBuffer,
668
gen.gen("%s \"%s\" ", sep, nameBuffer);
669
int ret = genType(field, &gen);
674
if (!field->maybe_null())
675
gen.gen(" not null");
680
if (form->found_next_number_field) // && form->s->next_number_key_offset == 0)
682
incrementValue = info->auto_increment_value;
684
if (incrementValue == 0)
688
if (form->s->primary_key < form->s->keys)
690
KEY *key = form->key_info + form->s->primary_key;
691
gen.gen(",\n primary key ");
692
genKeyFields(key, &gen);
696
const char *tableSpace = NULL;
698
if (falcon_tablespace_mode == (uint)TABLESPACE_INTERNAL)
701
tableSpace = TEMPORARY_TABLESPACE;
702
else if (info->tablespace)
703
tableSpace = info->tablespace;
705
tableSpace = DEFAULT_TABLESPACE;
709
gen.gen(" tablespace %s", tableSpace);
711
DBUG_PRINT("info",("incrementValue = " I64FORMAT, (long long int)incrementValue));
713
if ((ret = storageTable->create(gen.getString(), incrementValue)))
714
DBUG_RETURN(error(ret));
716
for (n = 0; n < form->s->keys; ++n)
717
if (n != form->s->primary_key)
718
if ((ret = createIndex(schemaName, tableName, form->key_info + n, n)))
720
storageTable->deleteTable();
722
DBUG_RETURN(error(ret));
728
int StorageInterface::add_index(TABLE* table_arg, KEY* key_info, uint num_of_keys)
730
DBUG_ENTER("StorageInterface::add_index");
731
int ret = createIndex(storageTable->getSchemaName(), storageTable->getName(), key_info, table_arg->s->keys);
736
int StorageInterface::createIndex(const char *schemaName, const char *tableName,
737
KEY *key, int indexNumber)
740
const char *unique = (key->flags & HA_NOSAME) ? "unique " : "";
741
gen.gen("create %sindex \"%s$%d\" on %s.\"%s\" ", unique, tableName,
742
indexNumber, schemaName, tableName);
743
genKeyFields(key, &gen);
744
const char *sql = gen.getString();
746
return storageTable->share->createIndex(storageConnection, key->name, sql);
750
uint StorageInterface::alter_table_flags(uint flags)
752
if (flags & ALTER_DROP_PARTITION)
755
return HA_ONLINE_ADD_INDEX | HA_ONLINE_ADD_UNIQUE_INDEX;
759
bool StorageInterface::check_if_incompatible_data(HA_CREATE_INFO* create_info, uint table_changes)
761
if (true || create_info->auto_increment_value != 0)
762
return COMPATIBLE_DATA_NO;
764
return COMPATIBLE_DATA_YES;
767
THR_LOCK_DATA **StorageInterface::store_lock(THD *thd, THR_LOCK_DATA **to,
768
enum thr_lock_type lock_type)
770
DBUG_ENTER("StorageInterface::store_lock");
771
//lockForUpdate = (lock_type == TL_WRITE && thd->lex->sql_command == SQLCOM_SELECT);
772
lockForUpdate = (lock_type == TL_WRITE);
774
if (lock_type != TL_IGNORE && lockData.type == TL_UNLOCK)
777
Here is where we get into the guts of a row level lock.
779
If we are not doing a LOCK TABLE or DISCARD/IMPORT
780
TABLESPACE, then allow multiple writers
783
if ( (lock_type >= TL_WRITE_CONCURRENT_INSERT && lock_type <= TL_WRITE) &&
784
!thd_in_lock_tables(thd))
785
lock_type = TL_WRITE_ALLOW_WRITE;
788
In queries of type INSERT INTO t1 SELECT ... FROM t2 ...
789
MySQL would use the lock TL_READ_NO_INSERT on t2, and that
790
would conflict with TL_WRITE_ALLOW_WRITE, blocking all inserts
791
to t2. Convert the lock to a normal read lock to allow
792
concurrent inserts to t2.
795
#ifdef XXX_TALK_TO_SERGEI
796
if (lock_type == TL_READ_NO_INSERT && !thd_in_lock_tables(thd))
801
lockData.type = lock_type;
809
int StorageInterface::delete_table(const char *tableName)
811
DBUG_ENTER("StorageInterface::delete_table");
814
mySqlThread = current_thd;
817
storageShare = storageHandler->findTable(tableName);
819
if (!storageConnection)
820
if ( !(storageConnection = storageHandler->getStorageConnection(storageShare, mySqlThread, mySqlThread->thread_id, OpenDatabase, falcon_tablespace_mode)) )
824
storageTable = storageConnection->getStorageTable(storageShare);
828
storageShare->lock(true);
830
if (storageShare->initialized)
832
thr_lock_delete((THR_LOCK*) storageShare->impure);
833
storageShare->initialized = false;
834
//DBUG_ASSERT(false);
837
storageShare->unlock();
840
int res = storageTable->deleteTable();
841
storageTable->deleteStorageTable();
844
if (res == StorageErrorTableNotFound)
847
DBUG_RETURN(error(res));
850
uint StorageInterface::max_supported_keys(void) const
852
DBUG_ENTER("StorageInterface::max_supported_keys");
853
DBUG_RETURN(MAX_KEY);
857
int StorageInterface::write_row(uchar *buff)
859
DBUG_ENTER("StorageInterface::write_row");
860
ha_statistic_increment(&SSV::ha_write_count);
862
/* If we have a timestamp column, update it to the current time */
864
if (table->timestamp_field_type & TIMESTAMP_AUTO_SET_ON_INSERT)
865
table->timestamp_field->set_time();
868
If we have an auto_increment column and we are writing a changed row
869
or a new row, then update the auto_increment value in the record.
872
if (table->next_number_field && buff == table->record[0])
874
update_auto_increment();
877
If the new value is less than the current highest value, it will be
878
ignored by setSequenceValue().
881
int code = storageShare->setSequenceValue(table->next_number_field->val_int());
884
DBUG_RETURN(error(code));
887
encodeRecord(buff, false);
888
lastRecord = storageTable->insert();
892
int code = lastRecord >> StoreErrorIndexShift;
893
indexErrorId = (lastRecord & StoreErrorIndexMask) - 1;
895
DBUG_RETURN(error(code));
898
if (++insertCount > LOAD_AUTOCOMMIT_RECORDS)
899
switch (thd_sql_command(mySqlThread))
902
case SQLCOM_ALTER_TABLE:
903
storageHandler->commit(mySqlThread);
904
storageConnection->startTransaction(thd_tx_isolation(mySqlThread));
905
storageConnection->markVerb();
917
int StorageInterface::update_row(const uchar* oldData, uchar* newData)
919
DBUG_ENTER("StorageInterface::update_row");
920
DBUG_ASSERT (lastRecord >= 0);
922
ha_statistic_increment(&SSV::ha_update_count);
924
/* If we have a timestamp column, update it to the current time */
926
if (table->timestamp_field_type & TIMESTAMP_AUTO_SET_ON_UPDATE)
927
table->timestamp_field->set_time();
929
/* If we have an auto_increment column, update the sequence value. */
931
Field *autoInc = table->found_next_number_field;
933
if ((autoInc) && bitmap_is_set(table->read_set, autoInc->field_index))
935
int code = storageShare->setSequenceValue(autoInc->val_int());
938
DBUG_RETURN(error(code));
941
encodeRecord(newData, true);
943
int ret = storageTable->updateRow(lastRecord);
947
int code = ret >> StoreErrorIndexShift;
948
indexErrorId = (ret & StoreErrorIndexMask) - 1;
949
DBUG_RETURN(error(code));
956
int StorageInterface::delete_row(const uchar* buf)
958
DBUG_ENTER("StorageInterface::delete_row");
959
DBUG_ASSERT (lastRecord >= 0);
960
ha_statistic_increment(&SSV::ha_delete_count);
965
int ret = storageTable->deleteRow(lastRecord);
968
DBUG_RETURN(error(ret));
976
int StorageInterface::commit(handlerton *hton, THD* thd, bool all)
978
DBUG_ENTER("StorageInterface::commit");
979
StorageConnection *storageConnection = getStorageConnection(thd);
981
if (all || !thd_test_options(thd, OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN))
983
if (storageConnection)
984
storageConnection->commit();
986
storageHandler->commit(thd);
990
if (storageConnection)
991
storageConnection->releaseVerb();
993
storageHandler->releaseVerb(thd);
999
int StorageInterface::prepare(handlerton* hton, THD* thd, bool all)
1001
DBUG_ENTER("StorageInterface::prepare");
1003
if (all || !thd_test_options(thd, OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN))
1004
storageHandler->prepare(thd, sizeof(thd->transaction.xid), (const unsigned char*) &thd->transaction.xid);
1007
StorageConnection *storageConnection = getStorageConnection(thd);
1009
if (storageConnection)
1010
storageConnection->releaseVerb();
1012
storageHandler->releaseVerb(thd);
1018
int StorageInterface::rollback(handlerton *hton, THD *thd, bool all)
1020
DBUG_ENTER("StorageInterface::rollback");
1021
StorageConnection *storageConnection = getStorageConnection(thd);
1023
if (all || !thd_test_options(thd, OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN))
1025
if (storageConnection)
1026
storageConnection->rollback();
1028
storageHandler->rollback(thd);
1032
if (storageConnection)
1033
storageConnection->rollbackVerb();
1035
storageHandler->rollbackVerb(thd);
1041
int StorageInterface::commit_by_xid(handlerton* hton, XID* xid)
1043
DBUG_ENTER("StorageInterface::commit_by_xid");
1044
int ret = storageHandler->commitByXID(sizeof(XID), (const unsigned char*) xid);
1048
int StorageInterface::rollback_by_xid(handlerton* hton, XID* xid)
1050
DBUG_ENTER("StorageInterface::rollback_by_xid");
1051
int ret = storageHandler->rollbackByXID(sizeof(XID), (const unsigned char*) xid);
1055
const COND* StorageInterface::cond_push(const COND* cond)
1057
#ifdef COND_PUSH_ENABLED
1058
DBUG_ENTER("StorageInterface::cond_push");
1060
String str(buff,(uint32) sizeof(buff), system_charset_info);
1062
Item *cond_ptr= (COND *)cond;
1063
cond_ptr->print(&str);
1065
DBUG_PRINT("StorageInterface::cond_push", ("%s", str.ptr()));
1068
return handler::cond_push(cond);
1072
void StorageInterface::startTransaction(void)
1074
threadSwitch(table->in_use);
1076
if (!storageConnection->transactionActive)
1078
storageConnection->startTransaction(thd_tx_isolation(mySqlThread));
1079
trans_register_ha(mySqlThread, true, falcon_hton);
1082
switch (thd_tx_isolation(mySqlThread))
1084
case ISO_READ_UNCOMMITTED:
1085
error(StorageWarningReadUncommitted);
1088
case ISO_SERIALIZABLE:
1089
error(StorageWarningSerializable);
1095
int StorageInterface::savepointSet(handlerton *hton, THD *thd, void *savePoint)
1097
return storageHandler->savepointSet(thd, savePoint);
1101
int StorageInterface::savepointRollback(handlerton *hton, THD *thd, void *savePoint)
1103
return storageHandler->savepointRollback(thd, savePoint);
1107
int StorageInterface::savepointRelease(handlerton *hton, THD *thd, void *savePoint)
1109
return storageHandler->savepointRelease(thd, savePoint);
1113
int StorageInterface::index_read(uchar *buf, const uchar *keyBytes, uint key_len,
1114
enum ha_rkey_function find_flag)
1116
DBUG_ENTER("StorageInterface::index_read");
1118
ha_statistic_increment(&SSV::ha_read_key_count);
1120
// XXX This needs to be revisited
1123
case HA_READ_KEY_EXACT:
1124
which = UpperBound | LowerBound;
1127
case HA_READ_KEY_OR_NEXT:
1128
storageTable->setPartialKey();
1132
case HA_READ_AFTER_KEY: // ???
1133
if (!storageTable->isKeyNull((const unsigned char*) keyBytes, key_len))
1138
case HA_READ_BEFORE_KEY: // ???
1139
case HA_READ_PREFIX_LAST_OR_PREV: // ???
1140
case HA_READ_PREFIX_LAST: // ???
1141
case HA_READ_PREFIX:
1142
case HA_READ_KEY_OR_PREV:
1144
DBUG_RETURN(HA_ERR_UNSUPPORTED);
1147
const unsigned char *key = (const unsigned char*) keyBytes;
1150
if ((ret = storageTable->setIndexBound(key, key_len, which)))
1151
DBUG_RETURN(error(ret));
1153
if ((ret = storageTable->indexScan()))
1154
DBUG_RETURN(error(ret));
1160
int ret = index_next(buf);
1165
int comparison = storageTable->compareKey(key, key_len);
1167
if ((which & LowerBound) && comparison < 0)
1170
if ((which & UpperBound) && comparison > 0)
1178
int StorageInterface::index_init(uint idx, bool sorted)
1180
DBUG_ENTER("StorageInterface::index_init");
1183
haveStartKey = false;
1186
if (!storageTable->setIndex(idx))
1189
StorageIndexDesc indexDesc;
1190
getKeyDesc(table->key_info + idx, &indexDesc);
1192
if (idx == table->s->primary_key)
1193
indexDesc.primaryKey = true;
1195
int ret = storageTable->setIndex(table->s->keys, idx, &indexDesc);
1198
DBUG_RETURN(error(ret));
1204
int StorageInterface::index_end(void)
1206
DBUG_ENTER("StorageInterface::index_end");
1207
storageTable->indexEnd();
1211
ha_rows StorageInterface::records_in_range(uint indexId, key_range *lower,
1214
DBUG_ENTER("StorageInterface::records_in_range");
1217
DBUG_RETURN(handler::records_in_range(indexId, lower, upper));
1220
ha_rows cardinality = (ha_rows) storageShare->estimateCardinality();
1223
DBUG_RETURN(MAX(cardinality, 2));
1225
StorageIndexDesc *index = storageShare->getIndex(indexId);
1228
DBUG_RETURN(MAX(cardinality, 2));
1230
int numberSegments = 0;
1232
for (int map = lower->keypart_map; map; map >>= 1)
1235
if (index->unique && numberSegments == index->numberSegments)
1238
ha_rows segmentRecords = (ha_rows) index->segmentRecordCounts[numberSegments - 1];
1239
ha_rows guestimate = cardinality;
1241
if (lower->flag == HA_READ_KEY_EXACT)
1244
guestimate = segmentRecords;
1246
for (int n = 0; n < numberSegments; ++n)
1252
DBUG_RETURN(MAX(guestimate, 2));
1256
void StorageInterface::getKeyDesc(KEY *keyInfo, StorageIndexDesc *indexInfo)
1258
int numberKeys = keyInfo->key_parts;
1259
indexInfo->numberSegments = numberKeys;
1260
indexInfo->name = keyInfo->name;
1261
indexInfo->unique = (keyInfo->flags & HA_NOSAME);
1262
indexInfo->primaryKey = false;
1264
for (int n = 0; n < numberKeys; ++n)
1266
StorageSegment *segment = indexInfo->segments + n;
1267
KEY_PART_INFO *part = keyInfo->key_part + n;
1268
segment->offset = part->offset;
1269
segment->length = part->length;
1270
segment->type = part->field->key_type();
1271
segment->nullBit = part->null_bit;
1272
segment->isUnsigned = (part->field->flags & ENUM_FLAG) ?
1273
true : ((Field_num*) part->field)->unsigned_flag;
1275
switch (segment->type)
1277
case HA_KEYTYPE_TEXT:
1278
case HA_KEYTYPE_VARTEXT1:
1279
case HA_KEYTYPE_VARTEXT2:
1280
case HA_KEYTYPE_VARBINARY1:
1281
case HA_KEYTYPE_VARBINARY2:
1282
segment->mysql_charset = part->field->charset();
1286
segment->mysql_charset = NULL;
1292
int StorageInterface::rename_table(const char *from, const char *to)
1294
DBUG_ENTER("StorageInterface::rename_table");
1295
//tempTable = storageHandler->isTempTable(from) > 0;
1296
table = 0; // XXX hack?
1297
int ret = open(from, 0, 0);
1302
DBUG_RETURN(storageShare->renameTable(storageConnection, to));
1306
double StorageInterface::read_time(uint index, uint ranges, ha_rows rows)
1308
DBUG_ENTER("StorageInterface::read_time");
1309
DBUG_RETURN(rows2double(rows / 3));
1313
int StorageInterface::read_range_first(const key_range *start_key,
1314
const key_range *end_key,
1315
bool eq_range_arg, bool sorted)
1317
DBUG_ENTER("StorageInterface::read_range_first");
1318
storageTable->clearIndexBounds();
1319
haveStartKey = false;
1322
if (start_key && !storageTable->isKeyNull((const unsigned char*) start_key->key, start_key->length))
1324
haveStartKey = true;
1325
startKey = *start_key;
1327
if (start_key->flag == HA_READ_KEY_OR_NEXT)
1328
storageTable->setPartialKey();
1329
else if (start_key->flag == HA_READ_AFTER_KEY)
1330
storageTable->setReadAfterKey();
1332
int ret = storageTable->setIndexBound((const unsigned char*) start_key->key,
1333
start_key->length, LowerBound);
1340
if (end_key->flag == HA_READ_BEFORE_KEY)
1341
storageTable->setReadBeforeKey();
1343
int ret = storageTable->setIndexBound((const unsigned char*) end_key->key,
1344
end_key->length, UpperBound);
1349
storageTable->indexScan();
1352
eq_range = eq_range_arg;
1359
end_range = &save_end_range;
1360
save_end_range = *end_key;
1361
key_compare_result_on_equal = ((end_key->flag == HA_READ_BEFORE_KEY) ? 1 :
1362
(end_key->flag == HA_READ_AFTER_KEY) ? -1 :
1366
range_key_part = table->key_info[active_index].key_part;
1370
int result = index_next(table->record[0]);
1374
if (result == HA_ERR_KEY_NOT_FOUND)
1375
result = HA_ERR_END_OF_FILE;
1377
table->status = result;
1378
DBUG_RETURN(result);
1386
int StorageInterface::index_next(uchar *buf)
1388
DBUG_ENTER("StorageInterface::index_next");
1389
ha_statistic_increment(&SSV::ha_read_next_count);
1396
lastRecord = storageTable->nextIndexed(nextRecord, lockForUpdate);
1400
if (lastRecord == StorageErrorRecordNotFound)
1403
table->status = STATUS_NOT_FOUND;
1404
DBUG_RETURN(HA_ERR_END_OF_FILE);
1407
DBUG_RETURN(error(lastRecord));
1410
nextRecord = lastRecord + 1;
1414
int n = storageTable->compareKey((const unsigned char*) startKey.key, startKey.length);
1416
if (n < 0 || (n == 0 && startKey.flag == HA_READ_AFTER_KEY))
1418
storageTable->unlockRow();
1425
int n = storageTable->compareKey((const unsigned char*) endKey.key, endKey.length);
1427
if (n > 0 || (n == 0 && endKey.flag == HA_READ_BEFORE_KEY))
1429
storageTable->unlockRow();
1442
int StorageInterface::index_next_same(uchar *buf, const uchar *key, uint key_len)
1444
DBUG_ENTER("StorageInterface::index_next_same");
1445
ha_statistic_increment(&SSV::ha_read_next_count);
1449
int ret = index_next(buf);
1454
int comparison = storageTable->compareKey((const unsigned char*) key, key_len);
1456
if (comparison == 0)
1462
double StorageInterface::scan_time(void)
1464
DBUG_ENTER("StorageInterface::scan_time");
1465
DBUG_RETURN(stats.records * 1000);
1468
bool StorageInterface::threadSwitch(THD* newThread)
1470
if (newThread == mySqlThread)
1473
if (storageConnection)
1475
if (!storageConnection->mySqlThread && !mySqlThread)
1477
storageConnection->setMySqlThread(newThread);
1478
mySqlThread = newThread;
1483
storageConnection->release();
1486
storageConnection = storageHandler->getStorageConnection(storageShare, newThread, newThread->thread_id, OpenDatabase, falcon_tablespace_mode);
1489
storageTable->setConnection(storageConnection);
1491
storageTable = storageConnection->getStorageTable(storageShare);
1493
mySqlThread = newThread;
1499
int StorageInterface::threadSwitchError(void)
1505
int StorageInterface::error(int storageError)
1507
DBUG_ENTER("StorageInterface::error");
1509
if (storageError == 0)
1511
DBUG_PRINT("info", ("returning 0"));
1515
switch (storageError)
1517
case StorageErrorDupKey:
1518
DBUG_PRINT("info", ("StorageErrorDupKey"));
1519
DBUG_RETURN(HA_ERR_FOUND_DUPP_KEY);
1521
case StorageErrorDeadlock:
1522
DBUG_PRINT("info", ("StorageErrorDeadlock"));
1523
DBUG_RETURN(HA_ERR_LOCK_DEADLOCK);
1524
//DBUG_RETURN(200 - storageError);
1526
case StorageErrorRecordNotFound:
1527
DBUG_PRINT("info", ("StorageErrorRecordNotFound"));
1528
DBUG_RETURN(HA_ERR_KEY_NOT_FOUND);
1530
case StorageErrorTableNotFound:
1531
DBUG_PRINT("info", ("StorageErrorTableNotFound"));
1532
DBUG_RETURN(HA_ERR_NO_SUCH_TABLE);
1534
case StorageErrorNoIndex:
1535
DBUG_PRINT("info", ("StorageErrorNoIndex"));
1536
DBUG_RETURN(HA_ERR_WRONG_INDEX);
1538
case StorageErrorBadKey:
1539
DBUG_PRINT("info", ("StorageErrorBadKey"));
1540
DBUG_RETURN(HA_ERR_WRONG_INDEX);
1542
case StorageErrorIndexOverflow:
1543
DBUG_PRINT("info", ("StorageErrorIndexOverflow"));
1544
DBUG_RETURN(HA_WRONG_CREATE_OPTION); // HA_ERR_TOO_LONG_KEY does not exist
1546
case StorageErrorTableExits:
1547
DBUG_PRINT("info", ("StorageErrorTableExits"));
1548
DBUG_RETURN(HA_ERR_TABLE_EXIST);
1550
case StorageErrorUpdateConflict:
1551
DBUG_PRINT("info", ("StorageErrorUpdateConflict"));
1552
DBUG_RETURN(HA_ERR_RECORD_CHANGED);
1554
case StorageErrorUncommittedUpdates:
1555
DBUG_PRINT("info", ("StorageErrorUncommittedUpdates"));
1556
DBUG_RETURN(HA_ERR_TABLE_EXIST);
1558
case StorageErrorUncommittedRecords:
1559
DBUG_PRINT("info", ("StorageErrorUncommittedRecords"));
1560
DBUG_RETURN(200 - storageError);
1562
case StorageErrorNoSequence:
1563
DBUG_PRINT("info", ("StorageErrorNoSequence"));
1565
if (storageConnection)
1566
storageConnection->setErrorText("no sequenced defined for autoincrement operation");
1568
DBUG_RETURN(200 - storageError);
1570
case StorageErrorTruncation:
1571
DBUG_PRINT("info", ("StorageErrorTruncation"));
1572
DBUG_RETURN(HA_ERR_TO_BIG_ROW);
1574
case StorageWarningSerializable:
1575
push_warning_printf(current_thd, MYSQL_ERROR::WARN_LEVEL_WARN,
1576
ER_CANT_CHANGE_TX_ISOLATION,
1577
"Falcon does not support SERIALIZABLE ISOLATION, using REPEATABLE READ instead.");
1580
case StorageWarningReadUncommitted:
1581
push_warning_printf(current_thd, MYSQL_ERROR::WARN_LEVEL_WARN,
1582
ER_CANT_CHANGE_TX_ISOLATION,
1583
"Falcon does not support READ UNCOMMITTED ISOLATION, using REPEATABLE READ instead.");
1586
case StorageErrorOutOfMemory:
1587
DBUG_PRINT("info", ("StorageErrorOutOfMemory"));
1588
DBUG_RETURN(HA_ERR_OUT_OF_MEM);
1590
case StorageErrorOutOfRecordMemory:
1591
DBUG_PRINT("info", ("StorageErrorOutOfRecordMemory"));
1592
DBUG_RETURN(200 - storageError);
1595
DBUG_PRINT("info", ("Unknown Falcon Error"));
1596
DBUG_RETURN(200 - storageError);
1599
DBUG_RETURN(storageError);
1602
int StorageInterface::start_stmt(THD *thd, thr_lock_type lock_type)
1604
DBUG_ENTER("StorageInterface::start_stmt");
1607
if (storageConnection->markVerb())
1608
trans_register_ha(thd, FALSE, falcon_hton);
1614
int StorageInterface::external_lock(THD *thd, int lock_type)
1616
DBUG_ENTER("StorageInterface::external_lock");
1619
if (lock_type == F_UNLCK)
1621
storageConnection->setCurrentStatement(NULL);
1623
if (!thd_test_options(thd, OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN))
1624
storageConnection->endImplicitTransaction();
1626
storageConnection->releaseVerb();
1630
storageTable->clearRecord();
1631
storageTable->clearBitmap();
1632
storageTable->clearAlter();
1637
if (storageConnection && thd->query)
1638
storageConnection->setCurrentStatement(thd->query);
1642
switch (thd_sql_command(thd))
1644
case SQLCOM_ALTER_TABLE:
1645
case SQLCOM_DROP_INDEX:
1646
case SQLCOM_CREATE_INDEX:
1648
int ret = storageTable->alterCheck();
1651
DBUG_RETURN(error(ret));
1659
if (thd_test_options(thd, OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN))
1661
if (storageConnection->startTransaction(thd_tx_isolation(thd)))
1662
trans_register_ha(thd, true, falcon_hton);
1664
if (storageConnection->markVerb())
1665
trans_register_ha(thd, false, falcon_hton);
1669
if (storageConnection->startImplicitTransaction(thd_tx_isolation(thd)))
1670
trans_register_ha(thd, false, falcon_hton);
1673
switch (thd_tx_isolation(mySqlThread))
1675
case ISO_READ_UNCOMMITTED:
1676
error(StorageWarningReadUncommitted);
1679
case ISO_SERIALIZABLE:
1680
error(StorageWarningSerializable);
1689
void StorageInterface::get_auto_increment(ulonglong offset, ulonglong increment,
1690
ulonglong nb_desired_values,
1691
ulonglong *first_value,
1692
ulonglong *nb_reserved_values)
1694
DBUG_ENTER("StorageInterface::get_auto_increment");
1695
*first_value = storageShare->getSequenceValue(1);
1696
*nb_reserved_values = 1;
1701
int StorageInterface::reset_auto_increment(ulonglong value)
1703
return handler::reset_auto_increment(value);
1706
const char *StorageInterface::index_type(uint key_number)
1708
DBUG_ENTER("StorageInterface::index_type");
1709
DBUG_RETURN("BTREE");
1712
void StorageInterface::dropDatabase(handlerton *hton, char *path)
1714
DBUG_ENTER("StorageInterface::dropDatabase");
1715
storageHandler->dropDatabase(path);
1721
void StorageInterface::freeActiveBlobs(void)
1723
for (StorageBlob *blob; (blob = activeBlobs); )
1725
activeBlobs = blob->next;
1726
storageTable->freeBlob(blob);
1727
blob->next = freeBlobs;
1733
void StorageInterface::shutdown(handlerton *htons)
1735
storageHandler->shutdownHandler();
1739
int StorageInterface::panic(handlerton* hton, ha_panic_function flag)
1741
storageHandler->shutdownHandler();
1747
int StorageInterface::closeConnection(handlerton *hton, THD *thd)
1749
DBUG_ENTER("NfsStorageEngine::closeConnection");
1750
storageHandler->closeConnections(thd);
1751
*thd_ha_data(thd, hton) = NULL;
1757
int StorageInterface::alter_tablespace(handlerton* hton, THD* thd, st_alter_tablespace* ts_info)
1759
DBUG_ENTER("NfsStorageEngine::alter_tablespace");
1763
CREATE TABLESPACE tablespace
1765
USE LOGFILE GROUP logfile_group
1766
[EXTENT_SIZE [=] extent_size]
1767
INITIAL_SIZE [=] initial_size
1771
switch (ts_info->ts_cmd_type)
1773
case CREATE_TABLESPACE:
1774
ret = storageHandler->createTablespace(ts_info->tablespace_name, ts_info->data_file_name, falcon_tablespace_mode);
1777
case DROP_TABLESPACE:
1778
ret = storageHandler->deleteTablespace(ts_info->tablespace_name);
1782
DBUG_RETURN(HA_ADMIN_NOT_IMPLEMENTED);
1788
uint StorageInterface::max_supported_key_length(void) const
1790
// Assume 4K page unless proven otherwise.
1791
if (storageConnection)
1792
return storageConnection->getMaxKeyLength();
1794
return MAX_INDEX_KEY_LENGTH_4K; // Default value.
1798
uint StorageInterface::max_supported_key_part_length(void) const
1800
// Assume 4K page unless proven otherwise.
1801
if (storageConnection)
1802
return storageConnection->getMaxKeyLength();
1804
return MAX_INDEX_KEY_LENGTH_4K; // Default for future sizes.
1808
void StorageInterface::logger(int mask, const char* text, void* arg)
1810
if (mask & falcon_debug_mask)
1812
printf ("%s", text);
1814
if (falcon_log_file)
1815
fprintf(falcon_log_file, "%s", text);
1820
int StorageInterface::setIndexes(void)
1822
if (!table || storageShare->haveIndexes())
1825
storageShare->lock(true);
1827
if (!storageShare->haveIndexes())
1829
StorageIndexDesc indexDesc;
1831
for (uint n = 0; n < table->s->keys; ++n)
1833
getKeyDesc(table->key_info + n, &indexDesc);
1835
if (n == table->s->primary_key)
1836
indexDesc.primaryKey = true;
1838
int ret = storageTable->setIndex(table->s->keys, n, &indexDesc);
1844
storageShare->unlock();
1849
int StorageInterface::genType(Field* field, CmdGen* gen)
1852
const char *arg = NULL;
1855
switch (field->real_type())
1857
case MYSQL_TYPE_DECIMAL:
1858
case MYSQL_TYPE_TINY:
1859
case MYSQL_TYPE_SHORT:
1860
case MYSQL_TYPE_BIT:
1864
case MYSQL_TYPE_INT24:
1865
case MYSQL_TYPE_LONG:
1866
case MYSQL_TYPE_YEAR:
1870
case MYSQL_TYPE_FLOAT:
1874
case MYSQL_TYPE_DOUBLE:
1878
case MYSQL_TYPE_TIMESTAMP:
1882
case MYSQL_TYPE_SET:
1883
case MYSQL_TYPE_LONGLONG:
1888
Falcon's date and time types don't handle invalid dates like MySQL's do,
1889
so we just use an int for storage
1892
case MYSQL_TYPE_DATE:
1893
case MYSQL_TYPE_TIME:
1894
case MYSQL_TYPE_ENUM:
1895
case MYSQL_TYPE_NEWDATE:
1899
case MYSQL_TYPE_DATETIME:
1903
case MYSQL_TYPE_VARCHAR:
1904
case MYSQL_TYPE_VAR_STRING:
1905
case MYSQL_TYPE_STRING:
1907
CHARSET_INFO *charset = field->charset();
1911
arg = charset->name;
1912
type = "varchar (%d) collation %s";
1915
type = "varchar (%d)";
1917
length = field->field_length;
1921
case MYSQL_TYPE_TINY_BLOB:
1922
case MYSQL_TYPE_LONG_BLOB:
1923
case MYSQL_TYPE_BLOB:
1924
case MYSQL_TYPE_MEDIUM_BLOB:
1925
case MYSQL_TYPE_GEOMETRY:
1926
if (field->field_length < 256)
1927
type = "varchar (256)";
1932
case MYSQL_TYPE_NEWDECIMAL:
1934
Field_new_decimal *newDecimal = (Field_new_decimal*) field;
1937
if (newDecimal->precision > 18 && newDecimal->dec > 9)
1939
errorText = "columns with greater than 18 digits precision and greater than 9 digits of fraction are not supported";
1941
return HA_ERR_UNSUPPORTED;
1945
gen->gen("numeric (%d,%d)", newDecimal->precision, newDecimal->dec);
1951
errorText = "unsupported Falcon data type";
1953
return HA_ERR_UNSUPPORTED;
1956
gen->gen(type, length, arg);
1962
void StorageInterface::genKeyFields(KEY* key, CmdGen* gen)
1964
const char *sep = "(";
1965
char nameBuffer[129];
1967
for (uint n = 0; n < key->key_parts; ++n)
1969
KEY_PART_INFO *part = key->key_part + n;
1970
Field *field = part->field;
1971
storageShare->cleanupFieldName(field->field_name, nameBuffer,
1972
sizeof(nameBuffer));
1974
if (part->key_part_flag & HA_PART_KEY_SEG)
1975
gen->gen("%s\"%s\"(%d)", sep, nameBuffer, part->length);
1977
gen->gen("%s\"%s\"", sep, nameBuffer);
1986
void StorageInterface::encodeRecord(uchar *buf, bool updateFlag)
1988
storageTable->preInsert();
1989
my_ptrdiff_t ptrDiff = buf - table->record[0];
1990
my_bitmap_map *old_map = dbug_tmp_use_all_columns(table, table->read_set);
1992
for (uint n = 0; n < table->s->fields; ++n)
1994
Field *field = table->field[n];
1997
field->move_field_offset(ptrDiff);
1999
if (updateFlag && !bitmap_is_set(table->write_set, field->field_index))
2001
const unsigned char *p = storageTable->getEncoding(n);
2002
storageTable->dataStream.encodeEncoding(p);
2004
else if (field->is_null())
2005
storageTable->dataStream.encodeNull();
2007
switch (field->real_type())
2009
case MYSQL_TYPE_TINY:
2010
case MYSQL_TYPE_SHORT:
2011
case MYSQL_TYPE_INT24:
2012
case MYSQL_TYPE_LONG:
2013
case MYSQL_TYPE_LONGLONG:
2014
case MYSQL_TYPE_YEAR:
2015
case MYSQL_TYPE_DECIMAL:
2016
case MYSQL_TYPE_ENUM:
2017
case MYSQL_TYPE_SET:
2018
case MYSQL_TYPE_BIT:
2019
storageTable->dataStream.encodeInt64(field->val_int());
2022
case MYSQL_TYPE_NEWDECIMAL:
2024
int precision = ((Field_new_decimal *)field)->precision;
2025
int scale = ((Field_new_decimal *)field)->dec;
2029
int64 value = ScaledBinary::getInt64FromBinaryDecimal((const char *) field->ptr,
2032
storageTable->dataStream.encodeInt64(value, scale);
2037
ScaledBinary::getBigIntFromBinaryDecimal((const char*) field->ptr, precision, scale, &bigInt);
2039
// Handle value as int64 if possible. Even if the number fits
2040
// an int64, it can only be scaled within 18 digits or less.
2042
if (bigInt.fitsInInt64() && scale < 19)
2044
int64 value = bigInt.getInt();
2045
storageTable->dataStream.encodeInt64(value, scale);
2048
storageTable->dataStream.encodeBigInt(&bigInt);
2053
case MYSQL_TYPE_DOUBLE:
2054
case MYSQL_TYPE_FLOAT:
2055
storageTable->dataStream.encodeDouble(field->val_real());
2058
case MYSQL_TYPE_TIMESTAMP:
2061
int64 value = ((Field_timestamp*) field)->get_timestamp(&nullValue);
2062
storageTable->dataStream.encodeDate(value * 1000);
2066
case MYSQL_TYPE_DATE:
2067
storageTable->dataStream.encodeInt64(field->val_int());
2070
case MYSQL_TYPE_NEWDATE:
2071
//storageTable->dataStream.encodeInt64(field->val_int());
2072
storageTable->dataStream.encodeInt64(uint3korr(field->ptr));
2075
case MYSQL_TYPE_TIME:
2076
storageTable->dataStream.encodeInt64(field->val_int());
2079
case MYSQL_TYPE_DATETIME:
2080
storageTable->dataStream.encodeInt64(field->val_int());
2083
case MYSQL_TYPE_VARCHAR:
2084
case MYSQL_TYPE_VAR_STRING:
2085
case MYSQL_TYPE_STRING:
2089
field->val_str(&buffer, &string);
2090
storageTable->dataStream.encodeOpaque(string.length(), string.ptr());
2094
case MYSQL_TYPE_TINY_BLOB:
2096
Field_blob *blob = (Field_blob*) field;
2097
uint length = blob->get_length();
2099
blob->get_ptr(&ptr);
2100
storageTable->dataStream.encodeOpaque(length, (const char*) ptr);
2104
case MYSQL_TYPE_LONG_BLOB:
2105
case MYSQL_TYPE_BLOB:
2106
case MYSQL_TYPE_MEDIUM_BLOB:
2107
case MYSQL_TYPE_GEOMETRY:
2109
Field_blob *blob = (Field_blob*) field;
2110
uint length = blob->get_length();
2112
blob->get_ptr(&ptr);
2113
StorageBlob *storageBlob;
2116
for (storageBlob = activeBlobs; storageBlob; storageBlob = storageBlob->next)
2117
if (storageBlob->data == (uchar*) ptr)
2119
blobId = storageBlob->blobId;
2125
StorageBlob storageBlob;
2126
storageBlob.length = length;
2127
storageBlob.data = (uchar *)ptr;
2128
blobId = storageTable->storeBlob(&storageBlob);
2129
blob->set_ptr(storageBlob.length, storageBlob.data);
2132
storageTable->dataStream.encodeBinaryBlob(blobId);
2137
storageTable->dataStream.encodeOpaque(field->field_length, (const char*) field->ptr);
2141
field->move_field_offset(-ptrDiff);
2144
dbug_tmp_restore_column_map(table->read_set, old_map);
2147
void StorageInterface::decodeRecord(uchar *buf)
2149
EncodedDataStream *dataStream = &storageTable->dataStream;
2150
my_ptrdiff_t ptrDiff = buf - table->record[0];
2151
my_bitmap_map *old_map = dbug_tmp_use_all_columns(table, table->write_set);
2152
DBUG_ENTER("StorageInterface::decodeRecord");
2154
for (uint n = 0; n < table->s->fields; ++n)
2156
Field *field = table->field[n];
2157
dataStream->decode();
2160
field->move_field_offset(ptrDiff);
2162
// @todo (HK) Affects Bug#28158: Falcon unique key violation gives wrong error message
2163
// @todo (KL) Affects Bug#26827: Falcon: column is null after update of a different column
2164
// both of these bugs need to be fixed in the server, not here.
2165
// This call to set_null is correct. When they are fixed, we can delete these comments.
2167
if (dataStream->type == edsTypeNull || !bitmap_is_set(table->read_set, field->field_index))
2171
field->set_notnull();
2173
switch (field->real_type())
2175
case MYSQL_TYPE_TINY:
2176
case MYSQL_TYPE_SHORT:
2177
case MYSQL_TYPE_INT24:
2178
case MYSQL_TYPE_LONG:
2179
case MYSQL_TYPE_LONGLONG:
2180
case MYSQL_TYPE_YEAR:
2181
case MYSQL_TYPE_DECIMAL:
2182
case MYSQL_TYPE_ENUM:
2183
case MYSQL_TYPE_SET:
2184
case MYSQL_TYPE_BIT:
2185
field->store(dataStream->getInt64(),
2186
((Field_num*)field)->unsigned_flag);
2189
case MYSQL_TYPE_NEWDECIMAL:
2191
int precision = ((Field_new_decimal*) field)->precision;
2192
int scale = ((Field_new_decimal*) field)->dec;
2194
if (dataStream->type == edsTypeBigInt)
2195
ScaledBinary::putBigInt(&dataStream->bigInt, (char*) field->ptr, precision, scale);
2198
int64 value = dataStream->getInt64(scale);
2199
ScaledBinary::putBinaryDecimal(value, (char*) field->ptr, precision, scale);
2204
case MYSQL_TYPE_DOUBLE:
2205
case MYSQL_TYPE_FLOAT:
2206
field->store(dataStream->value.dbl);
2209
case MYSQL_TYPE_TIMESTAMP:
2211
int value = (int) (dataStream->value.integer64 / 1000);
2212
longstore(field->ptr, value);
2216
case MYSQL_TYPE_DATE:
2217
field->store(dataStream->getInt64(), false);
2220
case MYSQL_TYPE_NEWDATE:
2221
//field->store(dataStream->getInt64(), false);
2222
int3store(field->ptr, dataStream->getInt32());
2225
case MYSQL_TYPE_TIME:
2226
field->store(dataStream->getInt64(), false);
2229
case MYSQL_TYPE_DATETIME:
2230
field->store(dataStream->getInt64(), false);
2233
case MYSQL_TYPE_VARCHAR:
2234
case MYSQL_TYPE_VAR_STRING:
2235
case MYSQL_TYPE_STRING:
2236
field->store((const char*) dataStream->value.string.data,
2237
dataStream->value.string.length, field->charset());
2240
case MYSQL_TYPE_TINY_BLOB:
2242
Field_blob *blob = (Field_blob*) field;
2243
blob->set_ptr(dataStream->value.string.length,
2244
(uchar*) dataStream->value.string.data);
2248
case MYSQL_TYPE_LONG_BLOB:
2249
case MYSQL_TYPE_BLOB:
2250
case MYSQL_TYPE_MEDIUM_BLOB:
2251
case MYSQL_TYPE_GEOMETRY:
2253
Field_blob *blob = (Field_blob*) field;
2254
StorageBlob *storageBlob = freeBlobs;
2257
freeBlobs = storageBlob->next;
2259
storageBlob = new StorageBlob;
2261
storageBlob->next = activeBlobs;
2262
activeBlobs = storageBlob;
2263
storageBlob->blobId = dataStream->value.blobId;
2264
storageTable->getBlob(storageBlob->blobId, storageBlob);
2265
blob->set_ptr(storageBlob->length, (uchar*) storageBlob->data);
2271
uint l = dataStream->value.string.length;
2273
if (field->field_length < l)
2274
l = field->field_length;
2276
memcpy(field->ptr, dataStream->value.string.data, l);
2282
field->move_field_offset(-ptrDiff);
2284
dbug_tmp_restore_column_map(table->write_set, old_map);
2290
int StorageInterface::extra(ha_extra_function operation)
2292
DBUG_ENTER("StorageInterface::extra");
2296
bool StorageInterface::get_error_message(int error, String *buf)
2298
if (storageConnection)
2300
const char *text = storageConnection->getLastErrorString();
2301
buf->set(text, strlen(text), system_charset_info);
2304
buf->set(errorText, strlen(errorText), system_charset_info);
2309
void StorageInterface::unlockTable(void)
2313
storageShare->unlock();
2314
tableLocked = false;
2318
//*****************************************************************************
2322
//*****************************************************************************
2323
NfsPluginHandler::NfsPluginHandler()
2325
storageConnection = NULL;
2326
storageTable = NULL;
2329
NfsPluginHandler::~NfsPluginHandler()
2333
//*****************************************************************************
2335
// System Memory Usage
2337
//*****************************************************************************
2338
int NfsPluginHandler::call_fillSystemMemoryDetailTable(THD *thd, TABLE_LIST *tables, COND *cond)
2340
InfoTableImpl infoTable(thd, tables, system_charset_info);
2343
storageHandler->getMemoryDetailInfo(&infoTable);
2345
return infoTable.error;
2349
ST_FIELD_INFO memoryDetailFieldInfo[]=
2351
{"FILE", 120, MYSQL_TYPE_STRING, 0, 0, "File", SKIP_OPEN_TABLE},
2352
{"LINE", 4, MYSQL_TYPE_LONG, 0, 0, "Line", SKIP_OPEN_TABLE},
2353
{"OBJECTS_IN_USE", 4, MYSQL_TYPE_LONG, 0, 0, "Objects in Use", SKIP_OPEN_TABLE},
2354
{"SPACE_IN_USE", 4, MYSQL_TYPE_LONG, 0, 0, "Space in Use", SKIP_OPEN_TABLE},
2355
{"OBJECTS_DELETED", 4, MYSQL_TYPE_LONG, 0, 0, "Objects Deleted", SKIP_OPEN_TABLE},
2356
{"SPACE_DELETED", 4, MYSQL_TYPE_LONG, 0, 0, "Space Deleted", SKIP_OPEN_TABLE},
2357
{0, 0, MYSQL_TYPE_STRING, 0, 0, 0, SKIP_OPEN_TABLE}
2360
int NfsPluginHandler::initSystemMemoryDetail(void *p)
2362
DBUG_ENTER("initSystemMemoryDetail");
2363
ST_SCHEMA_TABLE *schema = (ST_SCHEMA_TABLE*) p;
2364
schema->fields_info = memoryDetailFieldInfo;
2365
schema->fill_table = NfsPluginHandler::call_fillSystemMemoryDetailTable;
2369
int NfsPluginHandler::deinitSystemMemoryDetail(void *p)
2371
DBUG_ENTER("deinitSystemMemoryDetail");
2375
//*****************************************************************************
2377
// System memory usage summary
2379
//*****************************************************************************
2381
int NfsPluginHandler::call_fillSystemMemorySummaryTable(THD *thd, TABLE_LIST *tables, COND *cond)
2383
//return(pluginHandler->fillSystemMemorySummaryTable(thd, tables, cond));
2384
InfoTableImpl infoTable(thd, tables, system_charset_info);
2387
storageHandler->getMemorySummaryInfo(&infoTable);
2389
return infoTable.error;
2392
ST_FIELD_INFO memorySummaryFieldInfo[]=
2394
{"TOTAL_SPACE", 4, MYSQL_TYPE_LONGLONG, 0, 0, "Total Space", SKIP_OPEN_TABLE},
2395
{"FREE_SPACE", 4, MYSQL_TYPE_LONGLONG, 0, 0, "Free Space", SKIP_OPEN_TABLE},
2396
{"FREE_SEGMENTS", 4, MYSQL_TYPE_LONG, 0, 0, "Free Segments", SKIP_OPEN_TABLE},
2397
{"BIG_HUNKS", 4, MYSQL_TYPE_LONG, 0, 0, "Big Hunks", SKIP_OPEN_TABLE},
2398
{"SMALL_HUNKS", 4, MYSQL_TYPE_LONG, 0, 0, "Small Hunks", SKIP_OPEN_TABLE},
2399
{"UNIQUE_SIZES", 4, MYSQL_TYPE_LONG, 0, 0, "Unique Sizes", SKIP_OPEN_TABLE},
2400
{0, 0, MYSQL_TYPE_STRING, 0, 0, 0, SKIP_OPEN_TABLE}
2403
int NfsPluginHandler::initSystemMemorySummary(void *p)
2405
DBUG_ENTER("initSystemMemorySummary");
2406
ST_SCHEMA_TABLE *schema = (ST_SCHEMA_TABLE *)p;
2407
schema->fields_info = memorySummaryFieldInfo;
2408
schema->fill_table = NfsPluginHandler::call_fillSystemMemorySummaryTable;
2413
int NfsPluginHandler::deinitSystemMemorySummary(void *p)
2415
DBUG_ENTER("deinitSystemMemorySummary");
2419
//*****************************************************************************
2421
// Record cache usage detail
2423
//*****************************************************************************
2425
int NfsPluginHandler::call_fillRecordCacheDetailTable(THD *thd, TABLE_LIST *tables, COND *cond)
2427
InfoTableImpl infoTable(thd, tables, system_charset_info);
2430
storageHandler->getRecordCacheDetailInfo(&infoTable);
2432
return infoTable.error;
2435
ST_FIELD_INFO recordDetailFieldInfo[]=
2437
{"FILE", 120, MYSQL_TYPE_STRING, 0, 0, "File", SKIP_OPEN_TABLE},
2438
{"LINE", 4, MYSQL_TYPE_LONG, 0, 0, "Line", SKIP_OPEN_TABLE},
2439
{"OBJECTS_IN_USE", 4, MYSQL_TYPE_LONG, 0, 0, "Objects in Use", SKIP_OPEN_TABLE},
2440
{"SPACE_IN_USE", 4, MYSQL_TYPE_LONG, 0, 0, "Space in Use", SKIP_OPEN_TABLE},
2441
{"OBJECTS_DELETED", 4, MYSQL_TYPE_LONG, 0, 0, "Objects Deleted", SKIP_OPEN_TABLE},
2442
{"SPACE_DELETED", 4, MYSQL_TYPE_LONG, 0, 0, "Space Deleted", SKIP_OPEN_TABLE},
2443
{0, 0, MYSQL_TYPE_STRING, 0, 0, 0, SKIP_OPEN_TABLE}
2446
int NfsPluginHandler::initRecordCacheDetail(void *p)
2448
DBUG_ENTER("initRecordCacheDetail");
2449
ST_SCHEMA_TABLE *schema = (ST_SCHEMA_TABLE *)p;
2450
schema->fields_info = recordDetailFieldInfo;
2451
schema->fill_table = NfsPluginHandler::call_fillRecordCacheDetailTable;
2456
int NfsPluginHandler::deinitRecordCacheDetail(void *p)
2458
DBUG_ENTER("deinitRecordCacheDetail");
2462
//*****************************************************************************
2464
// Record cache usage summary
2466
//*****************************************************************************
2468
int NfsPluginHandler::call_fillRecordCacheSummaryTable(THD *thd, TABLE_LIST *tables, COND *cond)
2470
InfoTableImpl infoTable(thd, tables, system_charset_info);
2473
storageHandler->getRecordCacheSummaryInfo(&infoTable);
2475
return infoTable.error;
2478
ST_FIELD_INFO recordSummaryFieldInfo[]=
2480
{"TOTAL_SPACE", 4, MYSQL_TYPE_LONGLONG, 0, 0, "Total Space", SKIP_OPEN_TABLE},
2481
{"FREE_SPACE", 4, MYSQL_TYPE_LONGLONG, 0, 0, "Free Space", SKIP_OPEN_TABLE},
2482
{"FREE_SEGMENTS", 4, MYSQL_TYPE_LONG, 0, 0, "Free Segments", SKIP_OPEN_TABLE},
2483
{"BIG_HUNKS", 4, MYSQL_TYPE_LONG, 0, 0, "Big Hunks", SKIP_OPEN_TABLE},
2484
{"SMALL_HUNKS", 4, MYSQL_TYPE_LONG, 0, 0, "Small Hunks", SKIP_OPEN_TABLE},
2485
{"UNIQUE_SIZES", 4, MYSQL_TYPE_LONG, 0, 0, "Unique Sizes", SKIP_OPEN_TABLE},
2486
{0, 0, MYSQL_TYPE_STRING, 0, 0, 0, SKIP_OPEN_TABLE}
2489
int NfsPluginHandler::initRecordCacheSummary(void *p)
2491
DBUG_ENTER("initRecordCacheSummary");
2492
ST_SCHEMA_TABLE *schema = (ST_SCHEMA_TABLE *)p;
2493
schema->fields_info = recordSummaryFieldInfo;
2494
schema->fill_table = NfsPluginHandler::call_fillRecordCacheSummaryTable;
2499
int NfsPluginHandler::deinitRecordCacheSummary(void *p)
2501
DBUG_ENTER("deinitRecordCacheSummary");
2505
//*****************************************************************************
2509
//*****************************************************************************
2511
int NfsPluginHandler::call_fillDatabaseIOTable(THD *thd, TABLE_LIST *tables, COND *cond)
2513
InfoTableImpl infoTable(thd, tables, system_charset_info);
2516
storageHandler->getIOInfo(&infoTable);
2518
return infoTable.error;
2521
ST_FIELD_INFO databaseIOFieldInfo[]=
2523
{"DATABASE", 120, MYSQL_TYPE_STRING, 0, 0, "Database", SKIP_OPEN_TABLE},
2524
{"PAGE_SIZE", 4, MYSQL_TYPE_LONG, 0, 0, "Page Size", SKIP_OPEN_TABLE},
2525
{"BUFFERS", 4, MYSQL_TYPE_LONG, 0, 0, "Buffers", SKIP_OPEN_TABLE},
2526
{"PHYSICAL_READS", 4, MYSQL_TYPE_LONG, 0, 0, "Physical Reads", SKIP_OPEN_TABLE},
2527
{"WRITES", 4, MYSQL_TYPE_LONG, 0, 0, "Writes", SKIP_OPEN_TABLE},
2528
{"LOGICAL_READS", 4, MYSQL_TYPE_LONG, 0, 0, "Logical Reads", SKIP_OPEN_TABLE},
2529
{"FAKES", 4, MYSQL_TYPE_LONG, 0, 0, "Fakes", SKIP_OPEN_TABLE},
2530
{0, 0, MYSQL_TYPE_STRING, 0, 0, 0, SKIP_OPEN_TABLE}
2533
int NfsPluginHandler::initDatabaseIO(void *p)
2535
DBUG_ENTER("initDatabaseIO");
2536
ST_SCHEMA_TABLE *schema = (ST_SCHEMA_TABLE *)p;
2537
schema->fields_info = databaseIOFieldInfo;
2538
schema->fill_table = NfsPluginHandler::call_fillDatabaseIOTable;
2543
int NfsPluginHandler::deinitDatabaseIO(void *p)
2545
DBUG_ENTER("deinitDatabaseIO");
2549
int NfsPluginHandler::callTablesInfo(THD *thd, TABLE_LIST *tables, COND *cond)
2551
InfoTableImpl infoTable(thd, tables, system_charset_info);
2554
storageHandler->getTablesInfo(&infoTable);
2556
return infoTable.error;
2560
ST_FIELD_INFO tablesFieldInfo[]=
2562
{"SCHEMA_NAME", 127, MYSQL_TYPE_STRING, 0, 0, "Schema Name", SKIP_OPEN_TABLE},
2563
{"TABLE_NAME", 127, MYSQL_TYPE_STRING, 0, 0, "Table Name", SKIP_OPEN_TABLE},
2564
{"TABLESPACE", 127, MYSQL_TYPE_STRING, 0, 0, "Tablespace", SKIP_OPEN_TABLE},
2565
{0, 0, MYSQL_TYPE_STRING, 0, 0, 0, SKIP_OPEN_TABLE}
2568
int NfsPluginHandler::initTablesInfo(void *p)
2570
DBUG_ENTER("initTablesInfo");
2571
ST_SCHEMA_TABLE *schema = (ST_SCHEMA_TABLE *)p;
2572
schema->fields_info = tablesFieldInfo;
2573
schema->fill_table = NfsPluginHandler::callTablesInfo;
2578
int NfsPluginHandler::deinitTablesInfo(void *p)
2580
DBUG_ENTER("initTables");
2584
//*****************************************************************************
2586
// Transaction Information
2588
//*****************************************************************************
2590
int NfsPluginHandler::callTransactionInfo(THD *thd, TABLE_LIST *tables, COND *cond)
2592
InfoTableImpl infoTable(thd, tables, system_charset_info);
2595
storageHandler->getTransactionInfo(&infoTable);
2597
return infoTable.error;
2600
ST_FIELD_INFO transactionInfoFieldInfo[]=
2602
{"DATABASE", 120, MYSQL_TYPE_STRING, 0, 0, "Database", SKIP_OPEN_TABLE},
2603
{"THREAD_ID", 4, MYSQL_TYPE_LONG, 0, 0, "Thread Id", SKIP_OPEN_TABLE},
2604
{"ID", 4, MYSQL_TYPE_LONG, 0, 0, "Id", SKIP_OPEN_TABLE},
2605
{"STATE", 10, MYSQL_TYPE_STRING, 0, 0, "State", SKIP_OPEN_TABLE},
2606
{"UPDATES", 4, MYSQL_TYPE_LONG, 0, 0, "Has Updates", SKIP_OPEN_TABLE},
2607
{"PENDING", 4, MYSQL_TYPE_LONG, 0, 0, "Write Pending", SKIP_OPEN_TABLE},
2608
{"DEP", 4, MYSQL_TYPE_LONG, 0, 0, "Dependencies", SKIP_OPEN_TABLE},
2609
{"OLDEST", 4, MYSQL_TYPE_LONG, 0, 0, "Oldest Active", SKIP_OPEN_TABLE},
2610
{"RECORDS", 4, MYSQL_TYPE_LONG, 0, 0, "Has Records", SKIP_OPEN_TABLE},
2611
{"WAITING_FOR", 4, MYSQL_TYPE_LONG, 0, 0, "Waiting For", SKIP_OPEN_TABLE},
2612
{"STATEMENT", 120, MYSQL_TYPE_STRING, 0, 0, "Statement", SKIP_OPEN_TABLE},
2613
{0, 0, MYSQL_TYPE_STRING, 0, 0, 0, SKIP_OPEN_TABLE}
2616
int NfsPluginHandler::initTransactionInfo(void *p)
2618
DBUG_ENTER("initTransactionInfo");
2619
ST_SCHEMA_TABLE *schema = (ST_SCHEMA_TABLE *)p;
2620
schema->fields_info = transactionInfoFieldInfo;
2621
schema->fill_table = NfsPluginHandler::callTransactionInfo;
2626
int NfsPluginHandler::deinitTransactionInfo(void *p)
2628
DBUG_ENTER("deinitTransactionInfo");
2632
//*****************************************************************************
2634
// Transaction Summary Information
2636
//*****************************************************************************
2638
int NfsPluginHandler::callTransactionSummaryInfo(THD *thd, TABLE_LIST *tables, COND *cond)
2640
InfoTableImpl infoTable(thd, tables, system_charset_info);
2643
storageHandler->getTransactionSummaryInfo(&infoTable);
2645
return infoTable.error;
2648
ST_FIELD_INFO transactionInfoFieldSummaryInfo[]=
2650
{"DATABASE", 120, MYSQL_TYPE_STRING, 0, 0, "Database", SKIP_OPEN_TABLE},
2651
{"COMMITTED", 4, MYSQL_TYPE_LONG, 0, 0, "Committed Transaction.", SKIP_OPEN_TABLE},
2652
{"ROLLED_BACK", 4, MYSQL_TYPE_LONG, 0, 0, "Transactions Rolled Back.", SKIP_OPEN_TABLE},
2653
{"ACTIVE", 4, MYSQL_TYPE_LONG, 0, 0, "Active Transactions", SKIP_OPEN_TABLE},
2654
{"PENDING_COMMIT", 4, MYSQL_TYPE_LONG, 0, 0, "Transaction Pending Commit", SKIP_OPEN_TABLE},
2655
{"PENDING_COMPLETION",4, MYSQL_TYPE_LONG, 0, 0, "Transaction Pending Completion", SKIP_OPEN_TABLE},
2656
{0, 0, MYSQL_TYPE_STRING, 0, 0, 0, SKIP_OPEN_TABLE}
2659
int NfsPluginHandler::initTransactionSummaryInfo(void *p)
2661
DBUG_ENTER("initTransactionSummaryInfo");
2662
ST_SCHEMA_TABLE *schema = (ST_SCHEMA_TABLE *)p;
2663
schema->fields_info = transactionInfoFieldSummaryInfo;
2664
schema->fill_table = NfsPluginHandler::callTransactionSummaryInfo;
2669
int NfsPluginHandler::deinitTransactionSummaryInfo(void *p)
2671
DBUG_ENTER("deinitTransactionInfo");
2676
//*****************************************************************************
2678
// SerialLog Information
2680
//*****************************************************************************
2682
int NfsPluginHandler::callSerialLogInfo(THD *thd, TABLE_LIST *tables, COND *cond)
2684
InfoTableImpl infoTable(thd, tables, system_charset_info);
2687
storageHandler->getSerialLogInfo(&infoTable);
2689
return infoTable.error;
2692
ST_FIELD_INFO serialSerialLogFieldInfo[]=
2694
{"DATABASE", 120, MYSQL_TYPE_STRING, 0, 0, "Database", SKIP_OPEN_TABLE},
2695
{"TRANSACTIONS", 4, MYSQL_TYPE_LONG, 0, 0, "Transactions", SKIP_OPEN_TABLE},
2696
{"BLOCKS", 8, MYSQL_TYPE_LONGLONG, 0, 0, "Blocks", SKIP_OPEN_TABLE},
2697
{"WINDOWS", 4, MYSQL_TYPE_LONG, 0, 0, "Windows", SKIP_OPEN_TABLE},
2698
{"BUFFERS", 4, MYSQL_TYPE_LONG, 0, 0, "Buffers", SKIP_OPEN_TABLE},
2699
{0, 0, MYSQL_TYPE_STRING, 0, 0, 0, SKIP_OPEN_TABLE}
2702
int NfsPluginHandler::initSerialLogInfo(void *p)
2704
DBUG_ENTER("initSerialLogInfoInfo");
2705
ST_SCHEMA_TABLE *schema = (ST_SCHEMA_TABLE *)p;
2706
schema->fields_info = serialSerialLogFieldInfo;
2707
schema->fill_table = NfsPluginHandler::callSerialLogInfo;
2712
int NfsPluginHandler::deinitSerialLogInfo(void *p)
2714
DBUG_ENTER("deinitSerialLogInfo");
2719
//*****************************************************************************
2723
//*****************************************************************************
2725
int NfsPluginHandler::callSyncInfo(THD *thd, TABLE_LIST *tables, COND *cond)
2727
InfoTableImpl infoTable(thd, tables, system_charset_info);
2730
storageHandler->getSyncInfo(&infoTable);
2732
return infoTable.error;
2735
ST_FIELD_INFO syncInfoFieldInfo[]=
2737
{"CALLER", 120, MYSQL_TYPE_STRING, 0, 0, "Caller", SKIP_OPEN_TABLE},
2738
{"SHARED", 4, MYSQL_TYPE_LONG, 0, 0, "Shared", SKIP_OPEN_TABLE},
2739
{"EXCLUSIVE", 4, MYSQL_TYPE_LONG, 0, 0, "Exclusive", SKIP_OPEN_TABLE},
2740
{"WAITS", 4, MYSQL_TYPE_LONG, 0, 0, "Waits", SKIP_OPEN_TABLE},
2741
{"QUEUE_LENGTH", 4, MYSQL_TYPE_LONG, 0, 0, "Queue Length", SKIP_OPEN_TABLE},
2742
{0, 0, MYSQL_TYPE_STRING, 0, 0, 0, SKIP_OPEN_TABLE}
2745
int NfsPluginHandler::initSyncInfo(void *p)
2747
DBUG_ENTER("initSyncInfo");
2748
ST_SCHEMA_TABLE *schema = (ST_SCHEMA_TABLE *)p;
2749
schema->fields_info = syncInfoFieldInfo;
2750
schema->fill_table = NfsPluginHandler::callSyncInfo;
2755
int NfsPluginHandler::deinitSyncInfo(void *p)
2757
DBUG_ENTER("deinitSyncInfo");
2761
static void updateIndexChillThreshold(MYSQL_THD thd,
2762
struct st_mysql_sys_var *var,
2763
void *var_ptr, void *save)
2765
// TBD; Apply this setting to all configurations associated with 'thd'.
2766
//uint newFalconIndexChillThreshold = *((uint *) save);
2769
static void updateRecordChillThreshold(MYSQL_THD thd,
2770
struct st_mysql_sys_var *var,
2771
void *var_ptr, void *save)
2773
// TBD; Apply this setting to all configurations associated with 'thd'.
2774
//uint newFalconRecordChillThreshold = *((uint *) save);
2778
void StorageInterface::updateFsyncDisable(MYSQL_THD thd, struct st_mysql_sys_var* variable, void *var_ptr, void *save)
2780
falcon_disable_fsync = *(my_bool*) save;
2783
storageHandler->setSyncDisable(falcon_disable_fsync);
2786
void StorageInterface::updateRecordMemoryMax(MYSQL_THD thd, struct st_mysql_sys_var* variable, void* var_ptr, void* save)
2788
falcon_record_memory_max = *(unsigned long long*) save;
2791
storageHandler->setRecordMemoryMax(falcon_record_memory_max);
2794
void StorageInterface::updateRecordScavengeThreshold(MYSQL_THD thd, struct st_mysql_sys_var* variable, void* var_ptr, void* save)
2796
falcon_record_scavenge_threshold = *(int*) save;
2799
storageHandler->setRecordScavengeThreshold(falcon_record_scavenge_threshold);
2802
void StorageInterface::updateRecordScavengeFloor(MYSQL_THD thd, struct st_mysql_sys_var* variable, void* var_ptr, void* save)
2804
falcon_record_scavenge_floor = *(int*) save;
2807
storageHandler->setRecordScavengeFloor(falcon_record_scavenge_floor);
2811
static MYSQL_SYSVAR_BOOL(debug_server, falcon_debug_server,
2812
PLUGIN_VAR_NOCMDARG | PLUGIN_VAR_READONLY,
2813
"Enable Falcon debug code.",
2816
static MYSQL_SYSVAR_BOOL(disable_fsync, falcon_disable_fsync,
2817
PLUGIN_VAR_NOCMDARG, // | PLUGIN_VAR_READONLY,
2818
"Disable periodic fsync().",
2819
NULL, StorageInterface::updateFsyncDisable, FALSE);
2821
static MYSQL_SYSVAR_STR(serial_log_dir, falcon_serial_log_dir,
2822
PLUGIN_VAR_RQCMDARG| PLUGIN_VAR_READONLY | PLUGIN_VAR_MEMALLOC,
2823
"Falcon serial log file directory.",
2826
static MYSQL_SYSVAR_STR(checkpoint_schedule, falcon_checkpoint_schedule,
2827
PLUGIN_VAR_RQCMDARG| PLUGIN_VAR_READONLY | PLUGIN_VAR_MEMALLOC,
2828
"Falcon checkpoint schedule.",
2829
NULL, NULL, "7 * * * * *");
2831
static MYSQL_SYSVAR_STR(scavenge_schedule, falcon_scavenge_schedule,
2832
PLUGIN_VAR_RQCMDARG| PLUGIN_VAR_READONLY | PLUGIN_VAR_MEMALLOC,
2833
"Falcon record scavenge schedule.",
2834
NULL, NULL, "15,45 * * * * *");
2836
static MYSQL_SYSVAR_INT(debug_mask, falcon_debug_mask,
2837
PLUGIN_VAR_RQCMDARG,
2838
"Falcon message type mask for logged messages.",
2839
NULL, NULL, 0, 0, INT_MAX, 0);
2841
static MYSQL_SYSVAR_ULONGLONG(record_memory_max, falcon_record_memory_max,
2842
PLUGIN_VAR_RQCMDARG, // | PLUGIN_VAR_READONLY,
2843
"The maximum size of the record memory cache.",
2844
NULL, StorageInterface::updateRecordMemoryMax, LL(250)<<20, 0, (ulonglong) ~0, LL(1)<<20);
2846
static MYSQL_SYSVAR_INT(record_scavenge_threshold, falcon_record_scavenge_threshold,
2847
PLUGIN_VAR_OPCMDARG, // | PLUGIN_VAR_READONLY,
2848
"The percentage of falcon_record_memory_max that will cause the scavenger thread to start scavenging records from the record cache.",
2849
NULL, StorageInterface::updateRecordScavengeThreshold, 67, 10, 100, 1);
2851
static MYSQL_SYSVAR_INT(record_scavenge_floor, falcon_record_scavenge_floor,
2852
PLUGIN_VAR_OPCMDARG, // | PLUGIN_VAR_READONLY,
2853
"A percentage of falcon_record_memory_threshold that defines the amount of record data that will remain in the record cache after a scavenge run.",
2854
NULL, StorageInterface::updateRecordScavengeFloor, 50, 10, 90, 1);
2856
static MYSQL_SYSVAR_ULONGLONG(initial_allocation, falcon_initial_allocation,
2857
PLUGIN_VAR_RQCMDARG, // | PLUGIN_VAR_READONLY,
2858
"Initial allocation (in bytes) of falcon user tablespace.",
2859
NULL, NULL, 0, 0, LL(4000000000), LL(1)<<20);
2862
static MYSQL_SYSVAR_UINT(allocation_extent, falcon_allocation_extent,
2863
PLUGIN_VAR_OPCMDARG | PLUGIN_VAR_READONLY,
2864
"The percentage of the current size of falcon_user.fts to use as the size of the next extension to the file.",
2865
NULL, NULL, 10, 0, 100, 1);
2868
static MYSQL_SYSVAR_ULONGLONG(page_cache_size, falcon_page_cache_size,
2869
PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_READONLY,
2870
"The amount of memory to be used for the database page cache.",
2871
NULL, NULL, LL(4)<<20, LL(2)<<20, (ulonglong) ~0, LL(1)<<20);
2873
static MYSQL_SYSVAR_UINT(page_size, falcon_page_size,
2874
PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_READONLY,
2875
"The page size used when creating a Falcon tablespace.",
2876
NULL, NULL, 4096, 1024, 32768, 1024);
2878
static MYSQL_SYSVAR_UINT(serial_log_buffers, falcon_serial_log_buffers,
2879
PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_READONLY,
2880
"The number of buffers allocated for Falcon serial log.",
2881
NULL, NULL, 10, 10, 32768, 10);
2883
static MYSQL_SYSVAR_UINT(index_chill_threshold, falcon_index_chill_threshold,
2884
PLUGIN_VAR_RQCMDARG,
2885
"Mbytes of pending index data that is 'frozen' to the Falcon serial log.",
2886
NULL, &updateIndexChillThreshold, 4, 1, 1024, 1);
2889
static MYSQL_SYSVAR_UINT(tablespace_mode, falcon_tablespace_mode,
2890
PLUGIN_VAR_RQCMDARG,
2891
"tablespace mapping mode.",
2892
NULL, NULL, 0, 0, 3, 1);
2895
static MYSQL_SYSVAR_UINT(record_chill_threshold, falcon_record_chill_threshold,
2896
PLUGIN_VAR_RQCMDARG,
2897
"Mbytes of pending record data that is 'frozen' to the Falcon serial log.",
2898
NULL, &updateRecordChillThreshold, 5, 1, 1024, 1);
2900
static MYSQL_SYSVAR_UINT(max_transaction_backlog, falcon_max_transaction_backlog,
2901
PLUGIN_VAR_RQCMDARG,
2902
"Maximum number of backlogged transactions.",
2903
NULL, NULL, 150, 1, 1000000, 1);
2905
static struct st_mysql_sys_var* falconVariables[]= {
2906
MYSQL_SYSVAR(debug_server),
2907
MYSQL_SYSVAR(disable_fsync),
2908
MYSQL_SYSVAR(serial_log_dir),
2909
MYSQL_SYSVAR(checkpoint_schedule),
2910
MYSQL_SYSVAR(scavenge_schedule),
2911
MYSQL_SYSVAR(debug_mask),
2912
MYSQL_SYSVAR(record_memory_max),
2913
MYSQL_SYSVAR(record_scavenge_floor),
2914
MYSQL_SYSVAR(record_scavenge_threshold),
2915
MYSQL_SYSVAR(initial_allocation),
2916
//MYSQL_SYSVAR(allocation_extent),
2917
MYSQL_SYSVAR(page_cache_size),
2918
MYSQL_SYSVAR(page_size),
2919
MYSQL_SYSVAR(serial_log_buffers),
2920
MYSQL_SYSVAR(index_chill_threshold),
2921
MYSQL_SYSVAR(record_chill_threshold),
2922
MYSQL_SYSVAR(max_transaction_backlog),
2923
//MYSQL_SYSVAR(tablespace_mode),
2927
static st_mysql_storage_engine falcon_storage_engine = { MYSQL_HANDLERTON_INTERFACE_VERSION};
2928
static st_mysql_information_schema falcon_system_memory_detail = { MYSQL_INFORMATION_SCHEMA_INTERFACE_VERSION};
2929
static st_mysql_information_schema falcon_system_memory_summary = { MYSQL_INFORMATION_SCHEMA_INTERFACE_VERSION};
2930
static st_mysql_information_schema falcon_record_cache_detail = { MYSQL_INFORMATION_SCHEMA_INTERFACE_VERSION};
2931
static st_mysql_information_schema falcon_record_cache_summary = { MYSQL_INFORMATION_SCHEMA_INTERFACE_VERSION};
2932
static st_mysql_information_schema falcon_database_io = { MYSQL_INFORMATION_SCHEMA_INTERFACE_VERSION};
2933
static st_mysql_information_schema falcon_transaction_info = { MYSQL_INFORMATION_SCHEMA_INTERFACE_VERSION};
2934
static st_mysql_information_schema falcon_transaction_summary_info= { MYSQL_INFORMATION_SCHEMA_INTERFACE_VERSION};
2935
static st_mysql_information_schema falcon_sync_info = { MYSQL_INFORMATION_SCHEMA_INTERFACE_VERSION};
2936
static st_mysql_information_schema falcon_serial_log_info = { MYSQL_INFORMATION_SCHEMA_INTERFACE_VERSION};
2937
static st_mysql_information_schema falcon_tables = { MYSQL_INFORMATION_SCHEMA_INTERFACE_VERSION};
2939
mysql_declare_plugin(falcon)
2941
MYSQL_STORAGE_ENGINE_PLUGIN,
2942
&falcon_storage_engine,
2945
"Falcon storage engine",
2947
StorageInterface::falcon_init, /* plugin init */
2948
StorageInterface::falcon_deinit, /* plugin deinit */
2950
falconStatus, /* status variables */
2951
falconVariables, /* system variables */
2952
NULL /* config options */
2956
MYSQL_INFORMATION_SCHEMA_PLUGIN,
2957
&falcon_system_memory_detail,
2958
"FALCON_SYSTEM_MEMORY_DETAIL",
2960
"Falcon System Memory Detail.",
2962
NfsPluginHandler::initSystemMemoryDetail, /* plugin init */
2963
NfsPluginHandler::deinitSystemMemoryDetail, /* plugin deinit */
2965
NULL, /* status variables */
2966
NULL, /* system variables */
2967
NULL /* config options */
2971
MYSQL_INFORMATION_SCHEMA_PLUGIN,
2972
&falcon_system_memory_summary,
2973
"FALCON_SYSTEM_MEMORY_SUMMARY",
2975
"Falcon System Memory Summary.",
2977
NfsPluginHandler::initSystemMemorySummary, /* plugin init */
2978
NfsPluginHandler::deinitSystemMemorySummary,/* plugin deinit */
2980
NULL, /* status variables */
2981
NULL, /* system variables */
2982
NULL /* config options */
2986
MYSQL_INFORMATION_SCHEMA_PLUGIN,
2987
&falcon_record_cache_detail,
2988
"FALCON_RECORD_CACHE_DETAIL",
2990
"Falcon Record Cache Detail.",
2992
NfsPluginHandler::initRecordCacheDetail, /* plugin init */
2993
NfsPluginHandler::deinitRecordCacheDetail, /* plugin deinit */
2995
NULL, /* status variables */
2996
NULL, /* system variables */
2997
NULL /* config options */
3001
MYSQL_INFORMATION_SCHEMA_PLUGIN,
3002
&falcon_record_cache_summary,
3003
"FALCON_RECORD_CACHE_SUMMARY",
3005
"Falcon Record Cache Summary.",
3007
NfsPluginHandler::initRecordCacheSummary, /* plugin init */
3008
NfsPluginHandler::deinitRecordCacheSummary, /* plugin deinit */
3010
NULL, /* status variables */
3011
NULL, /* system variables */
3012
NULL /* config options */
3016
MYSQL_INFORMATION_SCHEMA_PLUGIN,
3017
&falcon_transaction_info,
3018
"FALCON_TRANSACTIONS",
3020
"Falcon Transactions.",
3022
NfsPluginHandler::initTransactionInfo, /* plugin init */
3023
NfsPluginHandler::deinitTransactionInfo, /* plugin deinit */
3025
NULL, /* status variables */
3026
NULL, /* system variables */
3027
NULL /* config options */
3031
MYSQL_INFORMATION_SCHEMA_PLUGIN,
3032
&falcon_transaction_summary_info,
3033
"FALCON_TRANSACTION_SUMMARY",
3035
"Falcon Transaction Summary.",
3037
NfsPluginHandler::initTransactionSummaryInfo, /* plugin init */
3038
NfsPluginHandler::deinitTransactionSummaryInfo, /* plugin deinit */
3040
NULL, /* status variables */
3041
NULL, /* system variables */
3042
NULL /* config options */
3046
MYSQL_INFORMATION_SCHEMA_PLUGIN,
3048
"FALCON_SYNCOBJECTS",
3050
"Falcon SyncObjects.",
3052
NfsPluginHandler::initSyncInfo, /* plugin init */
3053
NfsPluginHandler::deinitSyncInfo, /* plugin deinit */
3055
NULL, /* status variables */
3056
NULL, /* system variables */
3057
NULL /* config options */
3061
MYSQL_INFORMATION_SCHEMA_PLUGIN,
3062
&falcon_serial_log_info,
3063
"FALCON_SERIAL_LOG",
3065
"Falcon Serial Log.",
3067
NfsPluginHandler::initSerialLogInfo, /* plugin init */
3068
NfsPluginHandler::deinitSerialLogInfo, /* plugin deinit */
3070
NULL, /* status variables */
3071
NULL, /* system variables */
3072
NULL /* config options */
3076
MYSQL_INFORMATION_SCHEMA_PLUGIN,
3077
&falcon_database_io,
3078
"FALCON_DATABASE_IO",
3080
"Falcon Database IO.",
3082
NfsPluginHandler::initDatabaseIO, /* plugin init */
3083
NfsPluginHandler::deinitDatabaseIO, /* plugin deinit */
3085
NULL, /* status variables */
3086
NULL, /* system variables */
3087
NULL /* config options */
3091
MYSQL_INFORMATION_SCHEMA_PLUGIN,
3097
NfsPluginHandler::initTablesInfo, /* plugin init */
3098
NfsPluginHandler::deinitTablesInfo, /* plugin deinit */
3100
NULL, /* status variables */
3101
NULL, /* system variables */
3102
NULL /* config options */
3105
mysql_declare_plugin_end;