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 <drizzled/error.h>
48
#include <drizzled/table.h>
49
#include <drizzled/session.h>
44
51
#include "ha_tina.h"
57
static const string engine_name("CSV");
48
60
unsigned char + unsigned char + uint64_t + uint64_t + uint64_t + uint64_t + unsigned char
70
82
/* Stuff for shares */
71
83
pthread_mutex_t tina_mutex;
72
84
static HASH tina_open_tables;
73
static handler *tina_create_handler(handlerton *hton,
78
86
/*****************************************************************************
91
99
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)))
102
static unsigned char* tina_get_key(TINA_SHARE *share, size_t *length, bool)
97
104
*length=share->table_name_length;
98
105
return (unsigned char*) share->table_name;
101
static int tina_init_func(void *p)
103
handlerton *tina_hton;
105
tina_hton= (handlerton *)p;
108
class Tina : public StorageEngine
111
Tina(const string& name_arg)
112
: StorageEngine(name_arg, HTON_CAN_RECREATE | HTON_SUPPORT_LOG_TABLES |
113
HTON_NO_PARTITION) {}
114
virtual handler *create(TableShare *table,
117
return new (mem_root) ha_tina(this, table);
121
static Tina *tina_engine= NULL;
123
static int tina_init_func(PluginRegistry ®istry)
126
tina_engine= new Tina(engine_name);
127
registry.add(tina_engine);
106
129
pthread_mutex_init(&tina_mutex,MY_MUTEX_INIT_FAST);
107
130
(void) hash_init(&tina_open_tables,system_charset_info,32,0,0,
108
131
(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)))
135
static int tina_done_func(PluginRegistry ®istry)
137
registry.remove(tina_engine);
118
140
hash_free(&tina_open_tables);
119
141
pthread_mutex_destroy(&tina_mutex);
126
148
Simple lock controls.
128
static TINA_SHARE *get_share(const char *table_name,
129
Table *table __attribute__((unused)))
150
static TINA_SHARE *get_share(const char *table_name, Table *)
131
152
TINA_SHARE *share;
132
153
char meta_file_name[FN_REFLEN];
162
183
share->update_file_opened= false;
163
184
share->tina_write_opened= false;
164
185
share->data_file_version= 0;
165
my_stpcpy(share->table_name, table_name);
186
strcpy(share->table_name, table_name);
166
187
fn_format(share->data_file_name, table_name, "", CSV_EXT,
167
188
MY_REPLACE_EXT|MY_UNPACK_FILENAME);
168
189
fn_format(meta_file_name, table_name, "", CSM_EXT,
231
252
unsigned char meta_buffer[META_BUFFER_SIZE];
232
253
unsigned char *ptr= meta_buffer;
234
my_seek(meta_file, 0, MY_SEEK_SET, MYF(0));
255
lseek(meta_file, 0, SEEK_SET);
235
256
if (my_read(meta_file, (unsigned char*)meta_buffer, META_BUFFER_SIZE, 0)
236
257
!= META_BUFFER_SIZE)
237
258
return(HA_ERR_CRASHED_ON_USAGE);
298
319
ptr+= 3*sizeof(uint64_t);
299
320
*ptr= (unsigned char)dirty;
301
my_seek(meta_file, 0, MY_SEEK_SET, MYF(0));
322
lseek(meta_file, 0, SEEK_SET);
302
323
if (my_write(meta_file, (unsigned char *)meta_buffer, META_BUFFER_SIZE, 0)
303
324
!= META_BUFFER_SIZE)
311
bool ha_tina::check_and_repair(THD *thd)
332
bool ha_tina::check_and_repair(Session *session)
313
334
HA_CHECK_OPT check_opt;
315
336
check_opt.init();
317
return(repair(thd, &check_opt));
338
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),
438
ha_tina::ha_tina(StorageEngine *engine_arg, TableShare *table_arg)
439
:handler(engine_arg, table_arg),
427
441
These definitions are found in handler.h
428
442
They are not probably completely right.
442
456
Encode a buffer into the quoted format.
445
int ha_tina::encode_quote(unsigned char *buf __attribute__((unused)))
459
int ha_tina::encode_quote(unsigned char *)
447
461
char attribute_buffer[1024];
448
462
String attribute(attribute_buffer, sizeof(attribute_buffer),
543
557
chain_size += DEFAULT_CHAIN_LENGTH;
544
558
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)
560
if ((chain= (tina_set *) realloc(chain, chain_size)) == NULL)
553
tina_set *ptr= (tina_set *) my_malloc(chain_size * sizeof(tina_set),
565
tina_set *ptr= (tina_set *) malloc(chain_size * sizeof(tina_set));
555
568
memcpy(ptr, chain, DEFAULT_CHAIN_LENGTH * sizeof(tina_set));
588
601
local_saved_data_file_length, &eoln_len)) == 0)
589
602
return(HA_ERR_END_OF_FILE);
591
/* We must read all columns in case a table is opened for update */
592
read_all= !bitmap_is_clear_all(table->write_set);
593
604
error= HA_ERR_CRASHED_ON_USAGE;
595
606
memset(buf, 0, table->s->null_bytes);
608
/* We need to first check to see if this is a write (rewrite this to something sane that knows if we are doing an update) */
609
for (Field **field=table->field ; *field ; field++)
611
if ((*field)->isWriteSet())
597
618
for (Field **field=table->field ; *field ; field++)
601
622
buffer.length(0);
602
623
if (curr_offset >= end_offset)
662
if (read_all || bitmap_is_set(table->read_set, (*field)->field_index))
683
if (read_all || (*field)->isReadSet())
664
685
if ((*field)->store(buffer.ptr(), buffer.length(), buffer.charset(),
665
686
CHECK_FIELD_WARN))
669
690
Field_blob *blob= *(Field_blob**) field;
670
691
unsigned char *src, *tgt;
671
692
uint32_t length, packlength;
673
694
packlength= blob->pack_length_no_ptr();
674
695
length= blob->get_length(blob->ptr);
675
696
memcpy(&src, blob->ptr + packlength, sizeof(char*));
678
699
tgt= (unsigned char*) alloc_root(&blobroot, length);
679
memcpy(tgt, src, length);
700
memmove(tgt, src, length);
680
701
memcpy(blob->ptr + packlength, &tgt, sizeof(char*));
710
731
for CSV engine. For more details see mysys/thr_lock.c
713
void tina_get_status(void* param,
714
int concurrent_insert __attribute__((unused)))
734
void tina_get_status(void* param, int)
716
736
ha_tina *tina= (ha_tina*) param;
717
737
tina->get_status();
764
784
For log tables concurrent insert works different. The reason is that
765
785
log tables are always opened and locked. And as they do not unlock
766
786
tables, the file length after writes should be updated in a different
770
790
void ha_tina::update_status()
779
799
this will not be called for every request. Any sort of positions
780
800
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)
802
int ha_tina::open(const char *name, int, uint32_t open_options)
785
804
if (!(share= get_share(name, table)))
786
return(HA_ERR_OUT_OF_MEM);
788
807
if (share->crashed && !(open_options & HA_OPEN_FOR_REPAIR))
890
906
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)
909
int ha_tina::update_row(const unsigned char *, unsigned char * new_data)
904
919
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.
922
During update we mark each updating record as deleted
923
(see the chain_append()) then write new one to the temporary data file.
909
924
At the end of the sequence in the rnd_end() we append all non-marked
910
925
records from the data file to the temporary data file then rename it.
911
926
The temp_file_length is used to calculate new data file length.
936
951
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)))
954
int ha_tina::delete_row(const unsigned char *)
941
956
ha_statistic_increment(&SSV::ha_delete_count);
958
973
@brief Initialize the data file.
960
975
@details Compare the local version of the data file with the shared one.
961
976
If they differ, there are some changes behind and we have to reopen
962
977
the data file to make the changes visible.
963
Call @c file_buff->init_buff() at the end to read the beginning of the
978
Call @c file_buff->init_buff() at the end to read the beginning of the
964
979
data file into buffer.
967
982
@retval 1 There was an error.
1073
1088
its just a position. Look at the bdb code if you want to see a case
1074
1089
where something other then a number is stored.
1076
void ha_tina::position(const unsigned char *record __attribute__((unused)))
1091
void ha_tina::position(const unsigned char *)
1078
1093
my_store_ptr(ref, ref_length, current_position);
1097
1112
Currently this table handler doesn't implement most of the fields
1098
1113
really needed. SHOW also makes use of this data
1100
int ha_tina::info(uint32_t flag __attribute__((unused)))
1115
int ha_tina::info(uint32_t)
1102
1117
/* This is a lie, but you don't want the optimizer to see zero or 1 */
1103
if (!records_is_known && stats.records < 2)
1118
if (!records_is_known && stats.records < 2)
1104
1119
stats.records= 2;
1164
1179
bool in_hole= get_write_pos(&write_end, ptr);
1165
1180
off_t write_length= write_end - write_begin;
1181
if ((uint64_t)write_length > SIZE_MAX)
1167
1186
/* if there is something to write, write it */
1168
1187
if (write_length)
1170
if (my_write(update_temp_file,
1189
if (my_write(update_temp_file,
1171
1190
(unsigned char*) (file_buff->ptr() +
1172
1191
(write_begin - file_buff->start())),
1173
write_length, MYF_RW))
1192
(size_t)write_length, MYF_RW))
1175
1194
temp_file_length+= write_length;
1221
1240
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
1243
As we reopened the data file, increase share->data_file_version
1244
in order to force other threads waiting on a table lock and
1226
1245
have already opened the table to reopen the data file.
1227
1246
That makes the latest changes become visible to them.
1228
Update local_data_file_version as no need to reopen it in the
1247
Update local_data_file_version as no need to reopen it in the
1229
1248
current thread.
1231
1250
share->data_file_version++;
1236
1255
Here we record this fact to the meta-file.
1238
1257
(void)write_meta_file(share->meta_file, share->rows_recorded, false);
1240
Update local_saved_data_file_length with the real length of the
1259
Update local_saved_data_file_length with the real length of the
1243
1262
local_saved_data_file_length= temp_file_length;
1269
1288
rows (after the first bad one) as well.
1272
int ha_tina::repair(THD* thd,
1273
HA_CHECK_OPT* check_opt __attribute__((unused)))
1291
int ha_tina::repair(Session* session, HA_CHECK_OPT *)
1275
1293
char repaired_fname[FN_REFLEN];
1276
1294
unsigned char *buf;
1289
1307
/* Don't assert in field::val() functions */
1290
1308
table->use_all_columns();
1291
if (!(buf= (unsigned char*) my_malloc(table->s->reclength, MYF(MY_WME))))
1309
if (!(buf= (unsigned char*) malloc(table->s->reclength)))
1292
1310
return(HA_ERR_OUT_OF_MEM);
1294
1312
/* position buffer to the start of the file */
1309
1327
/* Read the file row-by-row. If everything is ok, repair is not needed. */
1310
1328
while (!(rc= find_current_row(buf)))
1312
thd_inc_row_count(thd);
1330
session_inc_row_count(session);
1313
1331
rows_repaired++;
1314
1332
current_position= next_position;
1351
1369
write_end= std::min(file_buff->end(), current_position);
1352
if ((write_end - write_begin) &&
1371
off_t write_length= write_end - write_begin;
1372
if ((uint64_t)write_length > SIZE_MAX)
1376
if ((write_length) &&
1353
1377
(my_write(repair_file, (unsigned char*)file_buff->ptr(),
1354
write_end - write_begin, MYF_RW)))
1378
(size_t)write_length, MYF_RW)))
1357
1381
write_begin= write_end;
1415
1439
Called by the database to lock the table. Keep in mind that this
1416
1440
is an internal lock.
1418
THR_LOCK_DATA **ha_tina::store_lock(THD *thd __attribute__((unused)),
1442
THR_LOCK_DATA **ha_tina::store_lock(Session *,
1419
1443
THR_LOCK_DATA **to,
1420
1444
enum thr_lock_type lock_type)
1429
1453
Create a table. You do not want to leave the table open after a call to
1430
1454
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)))
1457
int ha_tina::create(const char *name, Table *table_arg, HA_CREATE_INFO *)
1436
1459
char name_buff[FN_REFLEN];
1437
1460
File create_file;
1447
1470
return(HA_ERR_UNSUPPORTED);
1452
1475
if ((create_file= my_create(fn_format(name_buff, name, "", CSM_EXT,
1453
1476
MY_REPLACE_EXT|MY_UNPACK_FILENAME), 0,
1470
int ha_tina::check(THD* thd,
1471
HA_CHECK_OPT* check_opt __attribute__((unused)))
1493
int ha_tina::check(Session* session, HA_CHECK_OPT *)
1474
1496
unsigned char *buf;
1475
1497
const char *old_proc_info;
1476
1498
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))))
1500
old_proc_info= get_session_proc_info(session);
1501
set_session_proc_info(session, "Checking table");
1502
if (!(buf= (unsigned char*) malloc(table->s->reclength)))
1480
1503
return(HA_ERR_OUT_OF_MEM);
1482
1505
/* position buffer to the start of the file */
1497
1520
/* Read the file row-by-row. If everything is ok, repair is not needed. */
1498
1521
while (!(rc= find_current_row(buf)))
1500
thd_inc_row_count(thd);
1523
session_inc_row_count(session);
1502
1525
current_position= next_position;
1505
1528
free_root(&blobroot, MYF(0));
1507
1530
free((char*)buf);
1508
thd_proc_info(thd, old_proc_info);
1531
set_session_proc_info(session, old_proc_info);
1510
1533
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)))
1523
return COMPATIBLE_DATA_YES;
1526
mysql_declare_plugin(csv)
1528
DRIZZLE_STORAGE_ENGINE_PLUGIN,
1543
drizzle_declare_plugin(csv)
1531
1547
"Brian Aker, MySQL AB",
1537
1553
NULL, /* system variables */
1538
1554
NULL /* config options */
1540
mysql_declare_plugin_end;
1556
drizzle_declare_plugin_end;