43
#include <drizzled/common_includes.h>
43
#include <drizzled/server_includes.h>
44
#include <drizzled/field.h>
45
#include <drizzled/field/blob.h>
46
#include <drizzled/field/timestamp.h>
47
#include <storage/csv/ha_tina.h>
48
#include <drizzled/error.h>
49
#include <drizzled/table.h>
50
#include <drizzled/session.h>
56
static const string engine_name("CSV");
48
59
unsigned char + unsigned char + uint64_t + uint64_t + uint64_t + uint64_t + unsigned char
70
81
/* Stuff for shares */
71
82
pthread_mutex_t tina_mutex;
72
83
static HASH tina_open_tables;
73
static handler *tina_create_handler(handlerton *hton,
78
85
/*****************************************************************************
91
98
return ( a->begin > b->begin ? 1 : ( a->begin < b->begin ? -1 : 0 ) );
94
static unsigned char* tina_get_key(TINA_SHARE *share, size_t *length,
95
bool not_used __attribute__((unused)))
101
static unsigned char* tina_get_key(TINA_SHARE *share, size_t *length, bool)
97
103
*length=share->table_name_length;
98
104
return (unsigned char*) share->table_name;
101
static int tina_init_func(void *p)
103
handlerton *tina_hton;
105
tina_hton= (handlerton *)p;
107
class Tina : public StorageEngine
110
Tina(const string& name_arg)
111
: StorageEngine(name_arg, HTON_CAN_RECREATE | HTON_SUPPORT_LOG_TABLES |
112
HTON_NO_PARTITION) {}
113
virtual handler *create(TABLE_SHARE *table,
116
return new (mem_root) ha_tina(this, table);
120
static Tina *tina_engine= NULL;
122
static int tina_init_func(PluginRegistry ®istry)
125
tina_engine= new Tina(engine_name);
126
registry.add(tina_engine);
106
128
pthread_mutex_init(&tina_mutex,MY_MUTEX_INIT_FAST);
107
129
(void) hash_init(&tina_open_tables,system_charset_info,32,0,0,
108
130
(hash_get_key) tina_get_key,0,0);
109
tina_hton->state= SHOW_OPTION_YES;
110
tina_hton->create= tina_create_handler;
111
tina_hton->flags= (HTON_CAN_RECREATE | HTON_SUPPORT_LOG_TABLES |
116
static int tina_done_func(void *p __attribute__((unused)))
134
static int tina_done_func(PluginRegistry ®istry)
136
registry.remove(tina_engine);
118
139
hash_free(&tina_open_tables);
119
140
pthread_mutex_destroy(&tina_mutex);
126
147
Simple lock controls.
128
static TINA_SHARE *get_share(const char *table_name,
129
Table *table __attribute__((unused)))
149
static TINA_SHARE *get_share(const char *table_name, Table *)
131
151
TINA_SHARE *share;
132
152
char meta_file_name[FN_REFLEN];
162
182
share->update_file_opened= false;
163
183
share->tina_write_opened= false;
164
184
share->data_file_version= 0;
165
my_stpcpy(share->table_name, table_name);
185
strcpy(share->table_name, table_name);
166
186
fn_format(share->data_file_name, table_name, "", CSV_EXT,
167
187
MY_REPLACE_EXT|MY_UNPACK_FILENAME);
168
188
fn_format(meta_file_name, table_name, "", CSM_EXT,
231
251
unsigned char meta_buffer[META_BUFFER_SIZE];
232
252
unsigned char *ptr= meta_buffer;
234
my_seek(meta_file, 0, MY_SEEK_SET, MYF(0));
254
lseek(meta_file, 0, SEEK_SET);
235
255
if (my_read(meta_file, (unsigned char*)meta_buffer, META_BUFFER_SIZE, 0)
236
256
!= META_BUFFER_SIZE)
237
257
return(HA_ERR_CRASHED_ON_USAGE);
298
318
ptr+= 3*sizeof(uint64_t);
299
319
*ptr= (unsigned char)dirty;
301
my_seek(meta_file, 0, MY_SEEK_SET, MYF(0));
321
lseek(meta_file, 0, SEEK_SET);
302
322
if (my_write(meta_file, (unsigned char *)meta_buffer, META_BUFFER_SIZE, 0)
303
323
!= META_BUFFER_SIZE)
311
bool ha_tina::check_and_repair(THD *thd)
331
bool ha_tina::check_and_repair(Session *session)
313
333
HA_CHECK_OPT check_opt;
315
335
check_opt.init();
317
return(repair(thd, &check_opt));
337
return(repair(session, &check_opt));
416
static handler *tina_create_handler(handlerton *hton,
420
return new (mem_root) ha_tina(hton, table);
424
ha_tina::ha_tina(handlerton *hton, TABLE_SHARE *table_arg)
425
:handler(hton, table_arg),
437
ha_tina::ha_tina(StorageEngine *engine_arg, TABLE_SHARE *table_arg)
438
:handler(engine_arg, table_arg),
427
440
These definitions are found in handler.h
428
441
They are not probably completely right.
442
455
Encode a buffer into the quoted format.
445
int ha_tina::encode_quote(unsigned char *buf __attribute__((unused)))
458
int ha_tina::encode_quote(unsigned char *)
447
460
char attribute_buffer[1024];
448
461
String attribute(attribute_buffer, sizeof(attribute_buffer),
543
556
chain_size += DEFAULT_CHAIN_LENGTH;
544
557
if (chain_alloced)
546
/* Must cast since my_malloc unlike malloc doesn't have a void ptr */
547
if ((chain= (tina_set *) my_realloc((unsigned char*)chain,
548
chain_size, MYF(MY_WME))) == NULL)
559
if ((chain= (tina_set *) realloc(chain, chain_size)) == NULL)
553
tina_set *ptr= (tina_set *) my_malloc(chain_size * sizeof(tina_set),
564
tina_set *ptr= (tina_set *) malloc(chain_size * sizeof(tina_set));
555
567
memcpy(ptr, chain, DEFAULT_CHAIN_LENGTH * sizeof(tina_set));
589
601
return(HA_ERR_END_OF_FILE);
591
603
/* We must read all columns in case a table is opened for update */
592
read_all= !bitmap_is_clear_all(table->write_set);
604
read_all= !table->write_set->none();
593
605
error= HA_ERR_CRASHED_ON_USAGE;
595
607
memset(buf, 0, table->s->null_bytes);
662
if (read_all || bitmap_is_set(table->read_set, (*field)->field_index))
674
if (read_all || table->read_set->test((*field)->field_index))
664
676
if ((*field)->store(buffer.ptr(), buffer.length(), buffer.charset(),
665
677
CHECK_FIELD_WARN))
669
681
Field_blob *blob= *(Field_blob**) field;
670
682
unsigned char *src, *tgt;
671
683
uint32_t length, packlength;
673
685
packlength= blob->pack_length_no_ptr();
674
686
length= blob->get_length(blob->ptr);
675
687
memcpy(&src, blob->ptr + packlength, sizeof(char*));
678
690
tgt= (unsigned char*) alloc_root(&blobroot, length);
679
memcpy(tgt, src, length);
691
memmove(tgt, src, length);
680
692
memcpy(blob->ptr + packlength, &tgt, sizeof(char*));
710
722
for CSV engine. For more details see mysys/thr_lock.c
713
void tina_get_status(void* param,
714
int concurrent_insert __attribute__((unused)))
725
void tina_get_status(void* param, int)
716
727
ha_tina *tina= (ha_tina*) param;
717
728
tina->get_status();
764
775
For log tables concurrent insert works different. The reason is that
765
776
log tables are always opened and locked. And as they do not unlock
766
777
tables, the file length after writes should be updated in a different
770
781
void ha_tina::update_status()
779
790
this will not be called for every request. Any sort of positions
780
791
that need to be reset should be kept in the ::extra() call.
782
int ha_tina::open(const char *name, int mode __attribute__((unused)),
783
uint32_t open_options)
793
int ha_tina::open(const char *name, int, uint32_t open_options)
785
795
if (!(share= get_share(name, table)))
786
return(HA_ERR_OUT_OF_MEM);
788
798
if (share->crashed && !(open_options & HA_OPEN_FOR_REPAIR))
890
897
This will be called in a table scan right before the previous ::rnd_next()
893
int ha_tina::update_row(const unsigned char * old_data __attribute__((unused)),
894
unsigned char * new_data)
900
int ha_tina::update_row(const unsigned char *, unsigned char * new_data)
904
910
size= encode_quote(new_data);
907
During update we mark each updating record as deleted
908
(see the chain_append()) then write new one to the temporary data file.
913
During update we mark each updating record as deleted
914
(see the chain_append()) then write new one to the temporary data file.
909
915
At the end of the sequence in the rnd_end() we append all non-marked
910
916
records from the data file to the temporary data file then rename it.
911
917
The temp_file_length is used to calculate new data file length.
936
942
The table will then be deleted/positioned based on the ORDER (so RANDOM,
939
int ha_tina::delete_row(const unsigned char * buf __attribute__((unused)))
945
int ha_tina::delete_row(const unsigned char *)
941
947
ha_statistic_increment(&SSV::ha_delete_count);
958
964
@brief Initialize the data file.
960
966
@details Compare the local version of the data file with the shared one.
961
967
If they differ, there are some changes behind and we have to reopen
962
968
the data file to make the changes visible.
963
Call @c file_buff->init_buff() at the end to read the beginning of the
969
Call @c file_buff->init_buff() at the end to read the beginning of the
964
970
data file into buffer.
967
973
@retval 1 There was an error.
1073
1079
its just a position. Look at the bdb code if you want to see a case
1074
1080
where something other then a number is stored.
1076
void ha_tina::position(const unsigned char *record __attribute__((unused)))
1082
void ha_tina::position(const unsigned char *)
1078
1084
my_store_ptr(ref, ref_length, current_position);
1097
1103
Currently this table handler doesn't implement most of the fields
1098
1104
really needed. SHOW also makes use of this data
1100
int ha_tina::info(uint32_t flag __attribute__((unused)))
1106
int ha_tina::info(uint32_t)
1102
1108
/* This is a lie, but you don't want the optimizer to see zero or 1 */
1103
if (!records_is_known && stats.records < 2)
1109
if (!records_is_known && stats.records < 2)
1104
1110
stats.records= 2;
1164
1170
bool in_hole= get_write_pos(&write_end, ptr);
1165
1171
off_t write_length= write_end - write_begin;
1172
if ((uint64_t)write_length > SIZE_MAX)
1167
1177
/* if there is something to write, write it */
1168
1178
if (write_length)
1170
if (my_write(update_temp_file,
1180
if (my_write(update_temp_file,
1171
1181
(unsigned char*) (file_buff->ptr() +
1172
1182
(write_begin - file_buff->start())),
1173
write_length, MYF_RW))
1183
(size_t)write_length, MYF_RW))
1175
1185
temp_file_length+= write_length;
1221
1231
if (((data_file= my_open(share->data_file_name, O_RDONLY, MYF(0))) == -1))
1224
As we reopened the data file, increase share->data_file_version
1225
in order to force other threads waiting on a table lock and
1234
As we reopened the data file, increase share->data_file_version
1235
in order to force other threads waiting on a table lock and
1226
1236
have already opened the table to reopen the data file.
1227
1237
That makes the latest changes become visible to them.
1228
Update local_data_file_version as no need to reopen it in the
1238
Update local_data_file_version as no need to reopen it in the
1229
1239
current thread.
1231
1241
share->data_file_version++;
1236
1246
Here we record this fact to the meta-file.
1238
1248
(void)write_meta_file(share->meta_file, share->rows_recorded, false);
1240
Update local_saved_data_file_length with the real length of the
1250
Update local_saved_data_file_length with the real length of the
1243
1253
local_saved_data_file_length= temp_file_length;
1269
1279
rows (after the first bad one) as well.
1272
int ha_tina::repair(THD* thd,
1273
HA_CHECK_OPT* check_opt __attribute__((unused)))
1282
int ha_tina::repair(Session* session, HA_CHECK_OPT *)
1275
1284
char repaired_fname[FN_REFLEN];
1276
1285
unsigned char *buf;
1289
1298
/* Don't assert in field::val() functions */
1290
1299
table->use_all_columns();
1291
if (!(buf= (unsigned char*) my_malloc(table->s->reclength, MYF(MY_WME))))
1300
if (!(buf= (unsigned char*) malloc(table->s->reclength)))
1292
1301
return(HA_ERR_OUT_OF_MEM);
1294
1303
/* position buffer to the start of the file */
1309
1318
/* Read the file row-by-row. If everything is ok, repair is not needed. */
1310
1319
while (!(rc= find_current_row(buf)))
1312
thd_inc_row_count(thd);
1321
session_inc_row_count(session);
1313
1322
rows_repaired++;
1314
1323
current_position= next_position;
1351
1360
write_end= std::min(file_buff->end(), current_position);
1352
if ((write_end - write_begin) &&
1362
off_t write_length= write_end - write_begin;
1363
if ((uint64_t)write_length > SIZE_MAX)
1367
if ((write_length) &&
1353
1368
(my_write(repair_file, (unsigned char*)file_buff->ptr(),
1354
write_end - write_begin, MYF_RW)))
1369
(size_t)write_length, MYF_RW)))
1357
1372
write_begin= write_end;
1415
1430
Called by the database to lock the table. Keep in mind that this
1416
1431
is an internal lock.
1418
THR_LOCK_DATA **ha_tina::store_lock(THD *thd __attribute__((unused)),
1433
THR_LOCK_DATA **ha_tina::store_lock(Session *,
1419
1434
THR_LOCK_DATA **to,
1420
1435
enum thr_lock_type lock_type)
1429
1444
Create a table. You do not want to leave the table open after a call to
1430
1445
this (the database will call ::open() if it needs to).
1433
int ha_tina::create(const char *name, Table *table_arg,
1434
HA_CREATE_INFO *create_info __attribute__((unused)))
1448
int ha_tina::create(const char *name, Table *table_arg, HA_CREATE_INFO *)
1436
1450
char name_buff[FN_REFLEN];
1437
1451
File create_file;
1447
1461
return(HA_ERR_UNSUPPORTED);
1452
1466
if ((create_file= my_create(fn_format(name_buff, name, "", CSM_EXT,
1453
1467
MY_REPLACE_EXT|MY_UNPACK_FILENAME), 0,
1470
int ha_tina::check(THD* thd,
1471
HA_CHECK_OPT* check_opt __attribute__((unused)))
1484
int ha_tina::check(Session* session, HA_CHECK_OPT *)
1474
1487
unsigned char *buf;
1475
1488
const char *old_proc_info;
1476
1489
ha_rows count= share->rows_recorded;
1478
old_proc_info= thd_proc_info(thd, "Checking table");
1479
if (!(buf= (unsigned char*) my_malloc(table->s->reclength, MYF(MY_WME))))
1491
old_proc_info= get_session_proc_info(session);
1492
set_session_proc_info(session, "Checking table");
1493
if (!(buf= (unsigned char*) malloc(table->s->reclength)))
1480
1494
return(HA_ERR_OUT_OF_MEM);
1482
1496
/* position buffer to the start of the file */
1497
1511
/* Read the file row-by-row. If everything is ok, repair is not needed. */
1498
1512
while (!(rc= find_current_row(buf)))
1500
thd_inc_row_count(thd);
1514
session_inc_row_count(session);
1502
1516
current_position= next_position;
1505
1519
free_root(&blobroot, MYF(0));
1507
1521
free((char*)buf);
1508
thd_proc_info(thd, old_proc_info);
1522
set_session_proc_info(session, old_proc_info);
1510
1524
if ((rc != HA_ERR_END_OF_FILE) || count)
1520
bool ha_tina::check_if_incompatible_data(HA_CREATE_INFO *info __attribute__((unused)),
1521
uint32_t table_changes __attribute__((unused)))
1534
bool ha_tina::check_if_incompatible_data(HA_CREATE_INFO *, uint32_t)
1523
1536
return COMPATIBLE_DATA_YES;
1526
mysql_declare_plugin(csv)
1539
drizzle_declare_plugin(csv)
1528
DRIZZLE_STORAGE_ENGINE_PLUGIN,
1531
1543
"Brian Aker, MySQL AB",
1537
1549
NULL, /* system variables */
1538
1550
NULL /* config options */
1540
mysql_declare_plugin_end;
1552
drizzle_declare_plugin_end;