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;
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);
101
120
static int tina_init_func(void *p)
103
handlerton *tina_hton;
105
tina_hton= (handlerton *)p;
122
StorageEngine **engine= static_cast<StorageEngine **>(p);
124
Tina *tina_engine= new Tina(engine_name);
106
126
pthread_mutex_init(&tina_mutex,MY_MUTEX_INIT_FAST);
107
127
(void) hash_init(&tina_open_tables,system_charset_info,32,0,0,
108
128
(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 |
129
*engine= tina_engine;
116
static int tina_done_func(void *p __attribute__((unused)))
133
static int tina_done_func(void *p)
135
Tina *tina_engine= static_cast<Tina *>(p);
118
138
hash_free(&tina_open_tables);
119
139
pthread_mutex_destroy(&tina_mutex);
126
146
Simple lock controls.
128
static TINA_SHARE *get_share(const char *table_name,
129
Table *table __attribute__((unused)))
148
static TINA_SHARE *get_share(const char *table_name, Table *)
131
150
TINA_SHARE *share;
132
151
char meta_file_name[FN_REFLEN];
162
181
share->update_file_opened= false;
163
182
share->tina_write_opened= false;
164
183
share->data_file_version= 0;
165
my_stpcpy(share->table_name, table_name);
184
strcpy(share->table_name, table_name);
166
185
fn_format(share->data_file_name, table_name, "", CSV_EXT,
167
186
MY_REPLACE_EXT|MY_UNPACK_FILENAME);
168
187
fn_format(meta_file_name, table_name, "", CSM_EXT,
231
250
unsigned char meta_buffer[META_BUFFER_SIZE];
232
251
unsigned char *ptr= meta_buffer;
234
my_seek(meta_file, 0, MY_SEEK_SET, MYF(0));
253
lseek(meta_file, 0, SEEK_SET);
235
254
if (my_read(meta_file, (unsigned char*)meta_buffer, META_BUFFER_SIZE, 0)
236
255
!= META_BUFFER_SIZE)
237
256
return(HA_ERR_CRASHED_ON_USAGE);
298
317
ptr+= 3*sizeof(uint64_t);
299
318
*ptr= (unsigned char)dirty;
301
my_seek(meta_file, 0, MY_SEEK_SET, MYF(0));
320
lseek(meta_file, 0, SEEK_SET);
302
321
if (my_write(meta_file, (unsigned char *)meta_buffer, META_BUFFER_SIZE, 0)
303
322
!= META_BUFFER_SIZE)
311
bool ha_tina::check_and_repair(THD *thd)
330
bool ha_tina::check_and_repair(Session *session)
313
332
HA_CHECK_OPT check_opt;
315
334
check_opt.init();
317
return(repair(thd, &check_opt));
336
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),
436
ha_tina::ha_tina(StorageEngine *engine_arg, TABLE_SHARE *table_arg)
437
:handler(engine_arg, table_arg),
427
439
These definitions are found in handler.h
428
440
They are not probably completely right.
442
454
Encode a buffer into the quoted format.
445
int ha_tina::encode_quote(unsigned char *buf __attribute__((unused)))
457
int ha_tina::encode_quote(unsigned char *)
447
459
char attribute_buffer[1024];
448
460
String attribute(attribute_buffer, sizeof(attribute_buffer),
543
555
chain_size += DEFAULT_CHAIN_LENGTH;
544
556
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)
558
if ((chain= (tina_set *) realloc(chain, chain_size)) == NULL)
553
tina_set *ptr= (tina_set *) my_malloc(chain_size * sizeof(tina_set),
563
tina_set *ptr= (tina_set *) malloc(chain_size * sizeof(tina_set));
555
566
memcpy(ptr, chain, DEFAULT_CHAIN_LENGTH * sizeof(tina_set));
669
680
Field_blob *blob= *(Field_blob**) field;
670
681
unsigned char *src, *tgt;
671
682
uint32_t length, packlength;
673
684
packlength= blob->pack_length_no_ptr();
674
685
length= blob->get_length(blob->ptr);
675
686
memcpy(&src, blob->ptr + packlength, sizeof(char*));
678
689
tgt= (unsigned char*) alloc_root(&blobroot, length);
679
memcpy(tgt, src, length);
690
memmove(tgt, src, length);
680
691
memcpy(blob->ptr + packlength, &tgt, sizeof(char*));
710
721
for CSV engine. For more details see mysys/thr_lock.c
713
void tina_get_status(void* param,
714
int concurrent_insert __attribute__((unused)))
724
void tina_get_status(void* param, int)
716
726
ha_tina *tina= (ha_tina*) param;
717
727
tina->get_status();
764
774
For log tables concurrent insert works different. The reason is that
765
775
log tables are always opened and locked. And as they do not unlock
766
776
tables, the file length after writes should be updated in a different
770
780
void ha_tina::update_status()
779
789
this will not be called for every request. Any sort of positions
780
790
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)
792
int ha_tina::open(const char *name, int, uint32_t open_options)
785
794
if (!(share= get_share(name, table)))
786
return(HA_ERR_OUT_OF_MEM);
788
797
if (share->crashed && !(open_options & HA_OPEN_FOR_REPAIR))
890
896
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)
899
int ha_tina::update_row(const unsigned char *, unsigned char * new_data)
904
909
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.
912
During update we mark each updating record as deleted
913
(see the chain_append()) then write new one to the temporary data file.
909
914
At the end of the sequence in the rnd_end() we append all non-marked
910
915
records from the data file to the temporary data file then rename it.
911
916
The temp_file_length is used to calculate new data file length.
936
941
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)))
944
int ha_tina::delete_row(const unsigned char *)
941
946
ha_statistic_increment(&SSV::ha_delete_count);
958
963
@brief Initialize the data file.
960
965
@details Compare the local version of the data file with the shared one.
961
966
If they differ, there are some changes behind and we have to reopen
962
967
the data file to make the changes visible.
963
Call @c file_buff->init_buff() at the end to read the beginning of the
968
Call @c file_buff->init_buff() at the end to read the beginning of the
964
969
data file into buffer.
967
972
@retval 1 There was an error.
1073
1078
its just a position. Look at the bdb code if you want to see a case
1074
1079
where something other then a number is stored.
1076
void ha_tina::position(const unsigned char *record __attribute__((unused)))
1081
void ha_tina::position(const unsigned char *)
1078
1083
my_store_ptr(ref, ref_length, current_position);
1097
1102
Currently this table handler doesn't implement most of the fields
1098
1103
really needed. SHOW also makes use of this data
1100
int ha_tina::info(uint32_t flag __attribute__((unused)))
1105
int ha_tina::info(uint32_t)
1102
1107
/* This is a lie, but you don't want the optimizer to see zero or 1 */
1103
if (!records_is_known && stats.records < 2)
1108
if (!records_is_known && stats.records < 2)
1104
1109
stats.records= 2;
1164
1169
bool in_hole= get_write_pos(&write_end, ptr);
1165
1170
off_t write_length= write_end - write_begin;
1171
if ((uint64_t)write_length > SIZE_MAX)
1167
1176
/* if there is something to write, write it */
1168
1177
if (write_length)
1170
if (my_write(update_temp_file,
1179
if (my_write(update_temp_file,
1171
1180
(unsigned char*) (file_buff->ptr() +
1172
1181
(write_begin - file_buff->start())),
1173
write_length, MYF_RW))
1182
(size_t)write_length, MYF_RW))
1175
1184
temp_file_length+= write_length;
1221
1230
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
1233
As we reopened the data file, increase share->data_file_version
1234
in order to force other threads waiting on a table lock and
1226
1235
have already opened the table to reopen the data file.
1227
1236
That makes the latest changes become visible to them.
1228
Update local_data_file_version as no need to reopen it in the
1237
Update local_data_file_version as no need to reopen it in the
1229
1238
current thread.
1231
1240
share->data_file_version++;
1236
1245
Here we record this fact to the meta-file.
1238
1247
(void)write_meta_file(share->meta_file, share->rows_recorded, false);
1240
Update local_saved_data_file_length with the real length of the
1249
Update local_saved_data_file_length with the real length of the
1243
1252
local_saved_data_file_length= temp_file_length;
1269
1278
rows (after the first bad one) as well.
1272
int ha_tina::repair(THD* thd,
1273
HA_CHECK_OPT* check_opt __attribute__((unused)))
1281
int ha_tina::repair(Session* session, HA_CHECK_OPT *)
1275
1283
char repaired_fname[FN_REFLEN];
1276
1284
unsigned char *buf;
1289
1297
/* Don't assert in field::val() functions */
1290
1298
table->use_all_columns();
1291
if (!(buf= (unsigned char*) my_malloc(table->s->reclength, MYF(MY_WME))))
1299
if (!(buf= (unsigned char*) malloc(table->s->reclength)))
1292
1300
return(HA_ERR_OUT_OF_MEM);
1294
1302
/* position buffer to the start of the file */
1309
1317
/* Read the file row-by-row. If everything is ok, repair is not needed. */
1310
1318
while (!(rc= find_current_row(buf)))
1312
thd_inc_row_count(thd);
1320
session_inc_row_count(session);
1313
1321
rows_repaired++;
1314
1322
current_position= next_position;
1351
1359
write_end= std::min(file_buff->end(), current_position);
1352
if ((write_end - write_begin) &&
1361
off_t write_length= write_end - write_begin;
1362
if ((uint64_t)write_length > SIZE_MAX)
1366
if ((write_length) &&
1353
1367
(my_write(repair_file, (unsigned char*)file_buff->ptr(),
1354
write_end - write_begin, MYF_RW)))
1368
(size_t)write_length, MYF_RW)))
1357
1371
write_begin= write_end;
1415
1429
Called by the database to lock the table. Keep in mind that this
1416
1430
is an internal lock.
1418
THR_LOCK_DATA **ha_tina::store_lock(THD *thd __attribute__((unused)),
1432
THR_LOCK_DATA **ha_tina::store_lock(Session *,
1419
1433
THR_LOCK_DATA **to,
1420
1434
enum thr_lock_type lock_type)
1429
1443
Create a table. You do not want to leave the table open after a call to
1430
1444
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)))
1447
int ha_tina::create(const char *name, Table *table_arg, HA_CREATE_INFO *)
1436
1449
char name_buff[FN_REFLEN];
1437
1450
File create_file;
1447
1460
return(HA_ERR_UNSUPPORTED);
1452
1465
if ((create_file= my_create(fn_format(name_buff, name, "", CSM_EXT,
1453
1466
MY_REPLACE_EXT|MY_UNPACK_FILENAME), 0,
1470
int ha_tina::check(THD* thd,
1471
HA_CHECK_OPT* check_opt __attribute__((unused)))
1483
int ha_tina::check(Session* session, HA_CHECK_OPT *)
1474
1486
unsigned char *buf;
1475
1487
const char *old_proc_info;
1476
1488
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))))
1490
old_proc_info= get_session_proc_info(session);
1491
set_session_proc_info(session, "Checking table");
1492
if (!(buf= (unsigned char*) malloc(table->s->reclength)))
1480
1493
return(HA_ERR_OUT_OF_MEM);
1482
1495
/* position buffer to the start of the file */
1497
1510
/* Read the file row-by-row. If everything is ok, repair is not needed. */
1498
1511
while (!(rc= find_current_row(buf)))
1500
thd_inc_row_count(thd);
1513
session_inc_row_count(session);
1502
1515
current_position= next_position;
1505
1518
free_root(&blobroot, MYF(0));
1507
1520
free((char*)buf);
1508
thd_proc_info(thd, old_proc_info);
1521
set_session_proc_info(session, old_proc_info);
1510
1523
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)))
1533
bool ha_tina::check_if_incompatible_data(HA_CREATE_INFO *, uint32_t)
1523
1535
return COMPATIBLE_DATA_YES;
1526
mysql_declare_plugin(csv)
1538
drizzle_declare_plugin(csv)
1528
1540
DRIZZLE_STORAGE_ENGINE_PLUGIN,
1537
1549
NULL, /* system variables */
1538
1550
NULL /* config options */
1540
mysql_declare_plugin_end;
1552
drizzle_declare_plugin_end;