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
#ifdef USE_PRAGMA_IMPLEMENTATION
45
#pragma implementation // gcc: Class implementation
48
#include "mysql_priv.h"
49
#include <mysql/plugin.h>
51
50
#include "ha_tina.h"
57
static const string engine_name("CSV");
60
unsigned char + unsigned char + uint64_t + uint64_t + uint64_t + uint64_t + unsigned char
54
uchar + uchar + uint64_t + uint64_t + uint64_t + uint64_t + uchar
62
#define META_BUFFER_SIZE sizeof(unsigned char) + sizeof(unsigned char) + sizeof(uint64_t) \
63
+ sizeof(uint64_t) + sizeof(uint64_t) + sizeof(uint64_t) + sizeof(unsigned char)
56
#define META_BUFFER_SIZE sizeof(uchar) + sizeof(uchar) + sizeof(uint64_t) \
57
+ sizeof(uint64_t) + sizeof(uint64_t) + sizeof(uint64_t) + sizeof(uchar)
64
58
#define TINA_CHECK_HEADER 254 // The number we use to determine corruption
65
59
#define BLOB_MEMROOT_ALLOC_SIZE 8192
70
64
#define CSM_EXT ".CSM" // Meta file
73
static TINA_SHARE *get_share(const char *table_name, Table *table);
67
static TINA_SHARE *get_share(const char *table_name, TABLE *table);
74
68
static int free_share(TINA_SHARE *share);
75
69
static int read_meta_file(File meta_file, ha_rows *rows);
76
70
static int write_meta_file(File meta_file, ha_rows rows, bool dirty);
78
72
extern "C" void tina_get_status(void* param, int concurrent_insert);
79
73
extern "C" void tina_update_status(void* param);
80
extern "C" bool tina_check_status(void* param);
74
extern "C" my_bool tina_check_status(void* param);
82
76
/* Stuff for shares */
83
77
pthread_mutex_t tina_mutex;
84
78
static HASH tina_open_tables;
79
static handler *tina_create_handler(handlerton *hton,
86
84
/*****************************************************************************
99
97
return ( a->begin > b->begin ? 1 : ( a->begin < b->begin ? -1 : 0 ) );
102
static unsigned char* tina_get_key(TINA_SHARE *share, size_t *length, bool)
100
static uchar* tina_get_key(TINA_SHARE *share, size_t *length,
101
my_bool not_used __attribute__((unused)))
104
103
*length=share->table_name_length;
105
return (unsigned char*) share->table_name;
104
return (uchar*) share->table_name;
110
If frm_error() is called in table.cc this is called to find out what file
111
extensions exist for this handler.
113
static const char *ha_tina_exts[] = {
119
class Tina : public StorageEngine
122
Tina(const string& name_arg)
123
: StorageEngine(name_arg, HTON_CAN_RECREATE | HTON_TEMPORARY_ONLY) {}
124
virtual handler *create(TableShare *table,
127
return new (mem_root) ha_tina(this, table);
130
const char **bas_ext() const {
134
int createTableImpl(Session *, const char *table_name, Table *table_arg,
139
static Tina *tina_engine= NULL;
141
static int tina_init_func(PluginRegistry ®istry)
144
tina_engine= new Tina(engine_name);
145
registry.add(tina_engine);
147
pthread_mutex_init(&tina_mutex,MY_MUTEX_INIT_FAST);
107
static int tina_init_func(void *p)
109
handlerton *tina_hton;
111
tina_hton= (handlerton *)p;
112
VOID(pthread_mutex_init(&tina_mutex,MY_MUTEX_INIT_FAST));
148
113
(void) hash_init(&tina_open_tables,system_charset_info,32,0,0,
149
114
(hash_get_key) tina_get_key,0,0);
115
tina_hton->state= SHOW_OPTION_YES;
116
tina_hton->db_type= DB_TYPE_CSV_DB;
117
tina_hton->create= tina_create_handler;
118
tina_hton->flags= (HTON_CAN_RECREATE | HTON_SUPPORT_LOG_TABLES |
153
static int tina_done_func(PluginRegistry ®istry)
123
static int tina_done_func(void *p)
155
registry.remove(tina_engine);
158
125
hash_free(&tina_open_tables);
159
126
pthread_mutex_destroy(&tina_mutex);
166
133
Simple lock controls.
168
static TINA_SHARE *get_share(const char *table_name, Table *)
135
static TINA_SHARE *get_share(const char *table_name, TABLE *table)
170
137
TINA_SHARE *share;
171
138
char meta_file_name[FN_REFLEN];
172
struct stat file_stat;
139
MY_STAT file_stat; /* Stat information for the data file */
176
143
pthread_mutex_lock(&tina_mutex);
177
144
length=(uint) strlen(table_name);
181
148
initialize its members.
183
150
if (!(share=(TINA_SHARE*) hash_search(&tina_open_tables,
184
(unsigned char*) table_name,
187
154
if (!my_multi_malloc(MYF(MY_WME | MY_ZEROFILL),
188
155
&share, sizeof(*share),
189
156
&tmp_name, length+1,
192
159
pthread_mutex_unlock(&tina_mutex);
196
163
share->use_count= 0;
164
share->is_log_table= FALSE;
197
165
share->table_name_length= length;
198
166
share->table_name= tmp_name;
199
share->crashed= false;
167
share->crashed= FALSE;
200
168
share->rows_recorded= 0;
201
share->update_file_opened= false;
202
share->tina_write_opened= false;
169
share->update_file_opened= FALSE;
170
share->tina_write_opened= FALSE;
203
171
share->data_file_version= 0;
204
strcpy(share->table_name, table_name);
172
strmov(share->table_name, table_name);
205
173
fn_format(share->data_file_name, table_name, "", CSV_EXT,
206
174
MY_REPLACE_EXT|MY_UNPACK_FILENAME);
207
175
fn_format(meta_file_name, table_name, "", CSM_EXT,
208
176
MY_REPLACE_EXT|MY_UNPACK_FILENAME);
210
if (stat(share->data_file_name, &file_stat))
178
if (my_stat(share->data_file_name, &file_stat, MYF(MY_WME)) == NULL)
212
180
share->saved_data_file_length= file_stat.st_size;
214
if (my_hash_insert(&tina_open_tables, (unsigned char*) share))
182
if (my_hash_insert(&tina_open_tables, (uchar*) share))
216
184
thr_lock_init(&share->lock);
217
185
pthread_mutex_init(&share->mutex,MY_MUTEX_INIT_FAST);
225
193
if ((share->meta_file= my_open(meta_file_name,
226
194
O_RDWR|O_CREAT, MYF(0))) == -1)
227
share->crashed= true;
195
share->crashed= TRUE;
230
198
If the meta file will not open we assume it is crashed and
233
201
if (read_meta_file(share->meta_file, &share->rows_recorded))
234
share->crashed= true;
202
share->crashed= TRUE;
236
204
share->use_count++;
237
205
pthread_mutex_unlock(&tina_mutex);
268
236
static int read_meta_file(File meta_file, ha_rows *rows)
270
unsigned char meta_buffer[META_BUFFER_SIZE];
271
unsigned char *ptr= meta_buffer;
273
lseek(meta_file, 0, SEEK_SET);
274
if (my_read(meta_file, (unsigned char*)meta_buffer, META_BUFFER_SIZE, 0)
238
uchar meta_buffer[META_BUFFER_SIZE];
239
uchar *ptr= meta_buffer;
241
DBUG_ENTER("ha_tina::read_meta_file");
243
VOID(my_seek(meta_file, 0, MY_SEEK_SET, MYF(0)));
244
if (my_read(meta_file, (uchar*)meta_buffer, META_BUFFER_SIZE, 0)
275
245
!= META_BUFFER_SIZE)
276
return(HA_ERR_CRASHED_ON_USAGE);
246
DBUG_RETURN(HA_ERR_CRASHED_ON_USAGE);
279
249
Parse out the meta data, we ignore version at the moment
282
ptr+= sizeof(unsigned char)*2; // Move past header
252
ptr+= sizeof(uchar)*2; // Move past header
283
253
*rows= (ha_rows)uint8korr(ptr);
284
254
ptr+= sizeof(uint64_t); // Move past rows
289
259
ptr+= 3*sizeof(uint64_t);
291
261
/* check crashed bit and magic number */
292
if ((meta_buffer[0] != (unsigned char)TINA_CHECK_HEADER) ||
293
((bool)(*ptr)== true))
294
return(HA_ERR_CRASHED_ON_USAGE);
262
if ((meta_buffer[0] != (uchar)TINA_CHECK_HEADER) ||
263
((bool)(*ptr)== TRUE))
264
DBUG_RETURN(HA_ERR_CRASHED_ON_USAGE);
296
266
my_sync(meta_file, MYF(MY_WME));
321
291
static int write_meta_file(File meta_file, ha_rows rows, bool dirty)
323
unsigned char meta_buffer[META_BUFFER_SIZE];
324
unsigned char *ptr= meta_buffer;
326
*ptr= (unsigned char)TINA_CHECK_HEADER;
327
ptr+= sizeof(unsigned char);
328
*ptr= (unsigned char)TINA_VERSION;
329
ptr+= sizeof(unsigned char);
293
uchar meta_buffer[META_BUFFER_SIZE];
294
uchar *ptr= meta_buffer;
296
DBUG_ENTER("ha_tina::write_meta_file");
298
*ptr= (uchar)TINA_CHECK_HEADER;
300
*ptr= (uchar)TINA_VERSION;
330
302
int8store(ptr, (uint64_t)rows);
331
303
ptr+= sizeof(uint64_t);
332
304
memset(ptr, 0, 3*sizeof(uint64_t));
335
307
We'll need them later.
337
309
ptr+= 3*sizeof(uint64_t);
338
*ptr= (unsigned char)dirty;
340
lseek(meta_file, 0, SEEK_SET);
341
if (my_write(meta_file, (unsigned char *)meta_buffer, META_BUFFER_SIZE, 0)
312
VOID(my_seek(meta_file, 0, MY_SEEK_SET, MYF(0)));
313
if (my_write(meta_file, (uchar *)meta_buffer, META_BUFFER_SIZE, 0)
342
314
!= META_BUFFER_SIZE)
345
317
my_sync(meta_file, MYF(MY_WME));
350
bool ha_tina::check_and_repair(Session *session)
322
bool ha_tina::check_and_repair(THD *thd)
352
324
HA_CHECK_OPT check_opt;
325
DBUG_ENTER("ha_tina::check_and_repair");
354
327
check_opt.init();
356
return(repair(session, &check_opt));
329
DBUG_RETURN(repair(thd, &check_opt));
360
333
int ha_tina::init_tina_writer()
335
DBUG_ENTER("ha_tina::init_tina_writer");
363
338
Mark the file as crashed. We will set the flag back when we close
364
339
the file. In the case of the crash it will remain marked crashed,
365
340
which enforce recovery.
367
(void)write_meta_file(share->meta_file, share->rows_recorded, true);
342
(void)write_meta_file(share->meta_file, share->rows_recorded, TRUE);
369
344
if ((share->tina_write_filedes=
370
345
my_open(share->data_file_name, O_RDWR|O_APPEND, MYF(0))) == -1)
372
share->crashed= true;
347
DBUG_PRINT("info", ("Could not open tina file writes"));
348
share->crashed= TRUE;
375
share->tina_write_opened= true;
351
share->tina_write_opened= TRUE;
381
357
bool ha_tina::is_crashed() const
383
return(share->crashed);
359
DBUG_ENTER("ha_tina::is_crashed");
360
DBUG_RETURN(share->crashed);
389
366
static int free_share(TINA_SHARE *share)
368
DBUG_ENTER("ha_tina::free_share");
391
369
pthread_mutex_lock(&tina_mutex);
392
370
int result_code= 0;
393
371
if (!--share->use_count){
394
372
/* Write the meta file. Mark it as crashed if needed. */
395
373
(void)write_meta_file(share->meta_file, share->rows_recorded,
396
share->crashed ? true :false);
374
share->crashed ? TRUE :FALSE);
397
375
if (my_close(share->meta_file, MYF(0)))
399
377
if (share->tina_write_opened)
401
379
if (my_close(share->tina_write_filedes, MYF(0)))
403
share->tina_write_opened= false;
381
share->tina_write_opened= FALSE;
406
hash_delete(&tina_open_tables, (unsigned char*) share);
384
hash_delete(&tina_open_tables, (uchar*) share);
407
385
thr_lock_delete(&share->lock);
408
386
pthread_mutex_destroy(&share->mutex);
409
free((unsigned char*) share);
387
my_free((uchar*) share, MYF(0));
411
389
pthread_mutex_unlock(&tina_mutex);
391
DBUG_RETURN(result_code);
456
ha_tina::ha_tina(StorageEngine *engine_arg, TableShare *table_arg)
457
:handler(engine_arg, table_arg),
433
static handler *tina_create_handler(handlerton *hton,
437
return new (mem_root) ha_tina(hton, table);
441
ha_tina::ha_tina(handlerton *hton, TABLE_SHARE *table_arg)
442
:handler(hton, table_arg),
459
444
These definitions are found in handler.h
460
445
They are not probably completely right.
474
459
Encode a buffer into the quoted format.
477
int ha_tina::encode_quote(unsigned char *)
462
int ha_tina::encode_quote(uchar *buf)
479
464
char attribute_buffer[1024];
480
465
String attribute(attribute_buffer, sizeof(attribute_buffer),
481
466
&my_charset_bin);
468
my_bitmap_map *org_bitmap= dbug_tmp_use_all_columns(table, table->read_set);
483
469
buffer.length(0);
485
471
for (Field **field=table->field ; *field ; field++)
575
562
chain_size += DEFAULT_CHAIN_LENGTH;
576
563
if (chain_alloced)
578
if ((chain= (tina_set *) realloc(chain, chain_size)) == NULL)
565
/* Must cast since my_malloc unlike malloc doesn't have a void ptr */
566
if ((chain= (tina_set *) my_realloc((uchar*)chain,
567
chain_size, MYF(MY_WME))) == NULL)
583
tina_set *ptr= (tina_set *) malloc(chain_size * sizeof(tina_set));
572
tina_set *ptr= (tina_set *) my_malloc(chain_size * sizeof(tina_set),
586
574
memcpy(ptr, chain, DEFAULT_CHAIN_LENGTH * sizeof(tina_set));
604
int ha_tina::find_current_row(unsigned char *buf)
592
int ha_tina::find_current_row(uchar *buf)
606
594
off_t end_offset, curr_offset= current_position;
596
my_bitmap_map *org_bitmap;
609
bool read_all= false;
599
DBUG_ENTER("ha_tina::find_current_row");
611
601
free_root(&blobroot, MYF(MY_MARK_BLOCKS_FREE));
618
608
find_eoln_buff(file_buff, current_position,
619
609
local_saved_data_file_length, &eoln_len)) == 0)
620
return(HA_ERR_END_OF_FILE);
610
DBUG_RETURN(HA_ERR_END_OF_FILE);
612
/* We must read all columns in case a table is opened for update */
613
read_all= !bitmap_is_clear_all(table->write_set);
614
/* Avoid asserts in ::store() for columns that are not going to be updated */
615
org_bitmap= dbug_tmp_use_all_columns(table, table->write_set);
622
616
error= HA_ERR_CRASHED_ON_USAGE;
624
618
memset(buf, 0, table->s->null_bytes);
626
/* 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) */
627
for (Field **field=table->field ; *field ; field++)
629
if ((*field)->isWriteSet())
636
620
for (Field **field=table->field ; *field ; field++)
640
624
buffer.length(0);
641
625
if (curr_offset >= end_offset)
706
690
if ((*field)->flags & BLOB_FLAG)
708
692
Field_blob *blob= *(Field_blob**) field;
709
unsigned char *src, *tgt;
710
uint32_t length, packlength;
694
uint length, packlength;
712
696
packlength= blob->pack_length_no_ptr();
713
697
length= blob->get_length(blob->ptr);
714
memcpy(&src, blob->ptr + packlength, sizeof(char*));
698
memcpy_fixed(&src, blob->ptr + packlength, sizeof(char*));
717
tgt= (unsigned char*) alloc_root(&blobroot, length);
718
memmove(tgt, src, length);
719
memcpy(blob->ptr + packlength, &tgt, sizeof(char*));
701
tgt= (uchar*) alloc_root(&blobroot, length);
702
bmove(tgt, src, length);
703
memcpy_fixed(blob->ptr + packlength, &tgt, sizeof(char*));
767
767
void ha_tina::get_status()
769
if (share->is_log_table)
772
We have to use mutex to follow pthreads memory visibility
773
rules for share->saved_data_file_length
775
pthread_mutex_lock(&share->mutex);
776
local_saved_data_file_length= share->saved_data_file_length;
777
pthread_mutex_unlock(&share->mutex);
769
780
local_saved_data_file_length= share->saved_data_file_length;
787
798
For log tables concurrent insert works different. The reason is that
788
799
log tables are always opened and locked. And as they do not unlock
789
800
tables, the file length after writes should be updated in a different
801
way. For this purpose we need is_log_table flag. When this flag is set
802
we call update_status() explicitly after each row write.
793
805
void ha_tina::update_status()
802
814
this will not be called for every request. Any sort of positions
803
815
that need to be reset should be kept in the ::extra() call.
805
int ha_tina::open(const char *name, int, uint32_t open_options)
817
int ha_tina::open(const char *name, int mode, uint open_options)
819
DBUG_ENTER("ha_tina::open");
807
821
if (!(share= get_share(name, table)))
822
DBUG_RETURN(HA_ERR_OUT_OF_MEM);
810
824
if (share->crashed && !(open_options & HA_OPEN_FOR_REPAIR))
812
826
free_share(share);
813
return(HA_ERR_CRASHED_ON_USAGE);
827
DBUG_RETURN(HA_ERR_CRASHED_ON_USAGE);
816
830
local_data_file_version= share->data_file_version;
817
831
if ((data_file= my_open(share->data_file_name, O_RDONLY, MYF(0))) == -1)
821
835
Init locking. Pass handler object to the locking routines,
849
864
of the file and appends the data. In an error case it really should
850
865
just truncate to the original position (this is not done yet).
852
int ha_tina::write_row(unsigned char * buf)
867
int ha_tina::write_row(uchar * buf)
870
DBUG_ENTER("ha_tina::write_row");
856
872
if (share->crashed)
857
return(HA_ERR_CRASHED_ON_USAGE);
873
DBUG_RETURN(HA_ERR_CRASHED_ON_USAGE);
859
875
ha_statistic_increment(&SSV::ha_write_count);
877
if (table->timestamp_field_type & TIMESTAMP_AUTO_SET_ON_INSERT)
878
table->timestamp_field->set_time();
861
880
size= encode_quote(buf);
863
882
if (!share->tina_write_opened)
864
883
if (init_tina_writer())
867
886
/* use pwrite, as concurrent reader could have changed the position */
868
if (my_write(share->tina_write_filedes, (unsigned char*)buffer.ptr(), size,
887
if (my_write(share->tina_write_filedes, (uchar*)buffer.ptr(), size,
869
888
MYF(MY_WME | MY_NABP)))
872
891
/* update local copy of the max position to see our own changes */
873
892
local_saved_data_file_length+= size;
909
930
This will be called in a table scan right before the previous ::rnd_next()
912
int ha_tina::update_row(const unsigned char *, unsigned char * new_data)
933
int ha_tina::update_row(const uchar * old_data, uchar * new_data)
937
DBUG_ENTER("ha_tina::update_row");
917
939
ha_statistic_increment(&SSV::ha_update_count);
922
944
size= encode_quote(new_data);
925
During update we mark each updating record as deleted
926
(see the chain_append()) then write new one to the temporary data file.
947
During update we mark each updating record as deleted
948
(see the chain_append()) then write new one to the temporary data file.
927
949
At the end of the sequence in the rnd_end() we append all non-marked
928
950
records from the data file to the temporary data file then rename it.
929
951
The temp_file_length is used to calculate new data file length.
934
956
if (open_update_temp_file_if_needed())
937
if (my_write(update_temp_file, (unsigned char*)buffer.ptr(), size,
959
if (my_write(update_temp_file, (uchar*)buffer.ptr(), size,
938
960
MYF(MY_WME | MY_NABP)))
940
962
temp_file_length+= size;
965
/* UPDATE should never happen on the log tables */
966
DBUG_ASSERT(!share->is_log_table);
969
DBUG_PRINT("info",("rc = %d", rc));
954
980
The table will then be deleted/positioned based on the ORDER (so RANDOM,
957
int ha_tina::delete_row(const unsigned char *)
983
int ha_tina::delete_row(const uchar * buf)
985
DBUG_ENTER("ha_tina::delete_row");
959
986
ha_statistic_increment(&SSV::ha_delete_count);
961
988
if (chain_append())
965
992
/* Update shared info */
966
assert(share->rows_recorded);
993
DBUG_ASSERT(share->rows_recorded);
967
994
pthread_mutex_lock(&share->mutex);
968
995
share->rows_recorded--;
969
996
pthread_mutex_unlock(&share->mutex);
998
/* DELETE should never happen on the log table */
999
DBUG_ASSERT(!share->is_log_table);
976
1006
@brief Initialize the data file.
978
1008
@details Compare the local version of the data file with the shared one.
979
1009
If they differ, there are some changes behind and we have to reopen
980
1010
the data file to make the changes visible.
981
Call @c file_buff->init_buff() at the end to read the beginning of the
1011
Call @c file_buff->init_buff() at the end to read the beginning of the
982
1012
data file into buffer.
985
1015
@retval 1 There was an error.
1033
int ha_tina::rnd_init(bool)
1063
int ha_tina::rnd_init(bool scan)
1065
DBUG_ENTER("ha_tina::rnd_init");
1035
1067
/* set buffer to the beginning of the file */
1036
1068
if (share->crashed || init_data_file())
1037
return(HA_ERR_CRASHED_ON_USAGE);
1069
DBUG_RETURN(HA_ERR_CRASHED_ON_USAGE);
1039
1071
current_position= next_position= 0;
1040
1072
stats.records= 0;
1060
1092
NULL and "". This is ok since this table handler is for spreadsheets and
1061
1093
they don't know about them either :)
1063
int ha_tina::rnd_next(unsigned char *buf)
1095
int ha_tina::rnd_next(uchar *buf)
1098
DBUG_ENTER("ha_tina::rnd_next");
1067
1100
if (share->crashed)
1068
return(HA_ERR_CRASHED_ON_USAGE);
1101
DBUG_RETURN(HA_ERR_CRASHED_ON_USAGE);
1070
1103
ha_statistic_increment(&SSV::ha_read_rnd_next_count);
1091
1124
its just a position. Look at the bdb code if you want to see a case
1092
1125
where something other then a number is stored.
1094
void ha_tina::position(const unsigned char *)
1127
void ha_tina::position(const uchar *record)
1129
DBUG_ENTER("ha_tina::position");
1096
1130
my_store_ptr(ref, ref_length, current_position);
1103
1137
my_get_ptr() retrieves the data for you.
1106
int ha_tina::rnd_pos(unsigned char * buf, unsigned char *pos)
1140
int ha_tina::rnd_pos(uchar * buf, uchar *pos)
1142
DBUG_ENTER("ha_tina::rnd_pos");
1108
1143
ha_statistic_increment(&SSV::ha_read_rnd_count);
1109
1144
current_position= (off_t)my_get_ptr(pos,ref_length);
1110
return(find_current_row(buf));
1145
DBUG_RETURN(find_current_row(buf));
1115
1150
Currently this table handler doesn't implement most of the fields
1116
1151
really needed. SHOW also makes use of this data
1118
int ha_tina::info(uint32_t)
1153
int ha_tina::info(uint flag)
1155
DBUG_ENTER("ha_tina::info");
1120
1156
/* This is a lie, but you don't want the optimizer to see zero or 1 */
1121
if (!records_is_known && stats.records < 2)
1157
if (!records_is_known && stats.records < 2)
1122
1158
stats.records= 2;
1163
Grab bag of flags that are sent to the able handler every so often.
1164
HA_EXTRA_RESET and HA_EXTRA_RESET_STATE are the most frequently called.
1165
You are not required to implement any of these.
1167
int ha_tina::extra(enum ha_extra_function operation)
1169
DBUG_ENTER("ha_tina::extra");
1170
if (operation == HA_EXTRA_MARK_AS_LOG_TABLE)
1172
pthread_mutex_lock(&share->mutex);
1173
share->is_log_table= TRUE;
1174
pthread_mutex_unlock(&share->mutex);
1133
1186
if (closest_hole == chain_ptr) /* no more chains */
1134
1187
*end_pos= file_buff->end();
1136
*end_pos= std::min(file_buff->end(),
1137
closest_hole->begin);
1189
*end_pos= min(file_buff->end(),
1190
closest_hole->begin);
1138
1191
return (closest_hole != chain_ptr) && (*end_pos == closest_hole->begin);
1175
1229
/* create the file to write updated table if it wasn't yet created */
1176
1230
if (open_update_temp_file_if_needed())
1179
1233
/* write the file with updated info */
1180
1234
while ((file_buffer_start != -1)) // while not end of file
1182
1236
bool in_hole= get_write_pos(&write_end, ptr);
1183
1237
off_t write_length= write_end - write_begin;
1184
if ((uint64_t)write_length > SIZE_MAX)
1189
1239
/* if there is something to write, write it */
1190
1240
if (write_length)
1192
if (my_write(update_temp_file,
1193
(unsigned char*) (file_buff->ptr() +
1242
if (my_write(update_temp_file,
1243
(uchar*) (file_buff->ptr() +
1194
1244
(write_begin - file_buff->start())),
1195
(size_t)write_length, MYF_RW))
1245
write_length, MYF_RW))
1197
1247
temp_file_length+= write_length;
1215
1265
if (my_sync(update_temp_file, MYF(MY_WME)) ||
1216
1266
my_close(update_temp_file, MYF(0)))
1219
share->update_file_opened= false;
1269
share->update_file_opened= FALSE;
1221
1271
if (share->tina_write_opened)
1223
1273
if (my_close(share->tina_write_filedes, MYF(0)))
1226
1276
Mark that the writer fd is closed, so that init_tina_writer()
1227
1277
will reopen it later.
1229
share->tina_write_opened= false;
1279
share->tina_write_opened= FALSE;
1237
1287
my_rename(fn_format(updated_fname, share->table_name, "", CSN_EXT,
1238
1288
MY_REPLACE_EXT | MY_UNPACK_FILENAME),
1239
1289
share->data_file_name, MYF(0)))
1242
1292
/* Open the file again */
1243
1293
if (((data_file= my_open(share->data_file_name, O_RDONLY, MYF(0))) == -1))
1246
As we reopened the data file, increase share->data_file_version
1247
in order to force other threads waiting on a table lock and
1296
As we reopened the data file, increase share->data_file_version
1297
in order to force other threads waiting on a table lock and
1248
1298
have already opened the table to reopen the data file.
1249
1299
That makes the latest changes become visible to them.
1250
Update local_data_file_version as no need to reopen it in the
1300
Update local_data_file_version as no need to reopen it in the
1251
1301
current thread.
1253
1303
share->data_file_version++;
1257
1307
closed, so nothing worrying will happen to it in case of a crash.
1258
1308
Here we record this fact to the meta-file.
1260
(void)write_meta_file(share->meta_file, share->rows_recorded, false);
1262
Update local_saved_data_file_length with the real length of the
1310
(void)write_meta_file(share->meta_file, share->rows_recorded, FALSE);
1312
Update local_saved_data_file_length with the real length of the
1265
1315
local_saved_data_file_length= temp_file_length;
1270
1320
my_close(update_temp_file, MYF(0));
1271
share->update_file_opened= false;
1321
share->update_file_opened= FALSE;
1291
1341
rows (after the first bad one) as well.
1294
int ha_tina::repair(Session* session, HA_CHECK_OPT *)
1344
int ha_tina::repair(THD* thd, HA_CHECK_OPT* check_opt)
1296
1346
char repaired_fname[FN_REFLEN];
1298
1348
File repair_file;
1300
1350
ha_rows rows_repaired= 0;
1301
1351
off_t write_begin= 0, write_end;
1352
DBUG_ENTER("ha_tina::repair");
1303
1354
/* empty file */
1304
1355
if (!share->saved_data_file_length)
1310
1361
/* Don't assert in field::val() functions */
1311
1362
table->use_all_columns();
1312
if (!(buf= (unsigned char*) malloc(table->s->reclength)))
1313
return(HA_ERR_OUT_OF_MEM);
1363
if (!(buf= (uchar*) my_malloc(table->s->reclength, MYF(MY_WME))))
1364
DBUG_RETURN(HA_ERR_OUT_OF_MEM);
1315
1366
/* position buffer to the start of the file */
1316
1367
if (init_data_file())
1317
return(HA_ERR_CRASHED_ON_REPAIR);
1368
DBUG_RETURN(HA_ERR_CRASHED_ON_REPAIR);
1320
1371
Local_saved_data_file_length is initialized during the lock phase.
1330
1381
/* Read the file row-by-row. If everything is ok, repair is not needed. */
1331
1382
while (!(rc= find_current_row(buf)))
1333
session_inc_row_count(session);
1384
thd_inc_row_count(thd);
1334
1385
rows_repaired++;
1335
1386
current_position= next_position;
1338
1389
free_root(&blobroot, MYF(0));
1391
my_free((char*)buf, MYF(0));
1342
1393
if (rc == HA_ERR_END_OF_FILE)
1359
1410
MY_REPLACE_EXT|MY_UNPACK_FILENAME),
1360
1411
0, O_RDWR | O_TRUNC,MYF(MY_WME))) < 0)
1361
return(HA_ERR_CRASHED_ON_REPAIR);
1412
DBUG_RETURN(HA_ERR_CRASHED_ON_REPAIR);
1363
1414
file_buff->init_buff(data_file);
1369
1420
/* write repaired file */
1372
write_end= std::min(file_buff->end(), current_position);
1374
off_t write_length= write_end - write_begin;
1375
if ((uint64_t)write_length > SIZE_MAX)
1379
if ((write_length) &&
1380
(my_write(repair_file, (unsigned char*)file_buff->ptr(),
1381
(size_t)write_length, MYF_RW)))
1423
write_end= min(file_buff->end(), current_position);
1424
if ((write_end - write_begin) &&
1425
(my_write(repair_file, (uchar*)file_buff->ptr(),
1426
write_end - write_begin, MYF_RW)))
1384
1429
write_begin= write_end;
1385
1430
if (write_end== current_position)
1397
1442
if (my_close(data_file,MYF(0)) || my_close(repair_file, MYF(0)) ||
1398
1443
my_rename(repaired_fname, share->data_file_name, MYF(0)))
1401
1446
/* Open the file again, it should now be repaired */
1402
1447
if ((data_file= my_open(share->data_file_name, O_RDWR|O_APPEND,
1403
1448
MYF(0))) == -1)
1406
1451
/* Set new file size. The file size will be updated by ::update_status() */
1407
1452
local_saved_data_file_length= (size_t) current_position;
1410
share->crashed= false;
1411
return(HA_ADMIN_OK);
1455
share->crashed= FALSE;
1456
DBUG_RETURN(HA_ADMIN_OK);
1418
1463
int ha_tina::delete_all_rows()
1466
DBUG_ENTER("ha_tina::delete_all_rows");
1422
1468
if (!records_is_known)
1423
return(my_errno=HA_ERR_WRONG_COMMAND);
1469
DBUG_RETURN(my_errno=HA_ERR_WRONG_COMMAND);
1425
1471
if (!share->tina_write_opened)
1426
1472
if (init_tina_writer())
1429
1475
/* Truncate the file to zero size */
1430
rc= ftruncate(share->tina_write_filedes, 0);
1476
rc= my_chsize(share->tina_write_filedes, 0, 0, MYF(MY_WME));
1432
1478
stats.records=0;
1433
1479
/* Update shared info */
1435
1481
share->rows_recorded= 0;
1436
1482
pthread_mutex_unlock(&share->mutex);
1437
1483
local_saved_data_file_length= 0;
1442
1488
Called by the database to lock the table. Keep in mind that this
1443
1489
is an internal lock.
1445
THR_LOCK_DATA **ha_tina::store_lock(Session *,
1491
THR_LOCK_DATA **ha_tina::store_lock(THD *thd,
1446
1492
THR_LOCK_DATA **to,
1447
1493
enum thr_lock_type lock_type)
1456
1502
Create a table. You do not want to leave the table open after a call to
1457
1503
this (the database will call ::open() if it needs to).
1460
int Tina::createTableImpl(Session *, const char *table_name, Table *table_arg,
1506
int ha_tina::create(const char *name, TABLE *table_arg,
1507
HA_CREATE_INFO *create_info)
1463
1509
char name_buff[FN_REFLEN];
1464
1510
File create_file;
1511
DBUG_ENTER("ha_tina::create");
1471
1518
if ((*field)->real_maybe_null())
1473
1520
my_error(ER_CHECK_NOT_IMPLEMENTED, MYF(0), "nullable columns");
1474
return(HA_ERR_UNSUPPORTED);
1521
DBUG_RETURN(HA_ERR_UNSUPPORTED);
1479
if ((create_file= my_create(fn_format(name_buff, table_name, "", CSM_EXT,
1526
if ((create_file= my_create(fn_format(name_buff, name, "", CSM_EXT,
1480
1527
MY_REPLACE_EXT|MY_UNPACK_FILENAME), 0,
1481
1528
O_RDWR | O_TRUNC,MYF(MY_WME))) < 0)
1484
write_meta_file(create_file, 0, false);
1531
write_meta_file(create_file, 0, FALSE);
1485
1532
my_close(create_file, MYF(0));
1487
if ((create_file= my_create(fn_format(name_buff, table_name, "", CSV_EXT,
1534
if ((create_file= my_create(fn_format(name_buff, name, "", CSV_EXT,
1488
1535
MY_REPLACE_EXT|MY_UNPACK_FILENAME),0,
1489
1536
O_RDWR | O_TRUNC,MYF(MY_WME))) < 0)
1492
1539
my_close(create_file, MYF(0));
1497
int ha_tina::check(Session* session, HA_CHECK_OPT *)
1544
int ha_tina::check(THD* thd, HA_CHECK_OPT* check_opt)
1501
1548
const char *old_proc_info;
1502
1549
ha_rows count= share->rows_recorded;
1550
DBUG_ENTER("ha_tina::check");
1504
old_proc_info= get_session_proc_info(session);
1505
set_session_proc_info(session, "Checking table");
1506
if (!(buf= (unsigned char*) malloc(table->s->reclength)))
1507
return(HA_ERR_OUT_OF_MEM);
1552
old_proc_info= thd_proc_info(thd, "Checking table");
1553
if (!(buf= (uchar*) my_malloc(table->s->reclength, MYF(MY_WME))))
1554
DBUG_RETURN(HA_ERR_OUT_OF_MEM);
1509
1556
/* position buffer to the start of the file */
1510
1557
if (init_data_file())
1511
return(HA_ERR_CRASHED);
1558
DBUG_RETURN(HA_ERR_CRASHED);
1514
1561
Local_saved_data_file_length is initialized during the lock phase.
1524
1571
/* Read the file row-by-row. If everything is ok, repair is not needed. */
1525
1572
while (!(rc= find_current_row(buf)))
1527
session_inc_row_count(session);
1574
thd_inc_row_count(thd);
1529
1576
current_position= next_position;
1532
1579
free_root(&blobroot, MYF(0));
1535
set_session_proc_info(session, old_proc_info);
1581
my_free((char*)buf, MYF(0));
1582
thd_proc_info(thd, old_proc_info);
1537
1584
if ((rc != HA_ERR_END_OF_FILE) || count)
1539
share->crashed= true;
1540
return(HA_ADMIN_CORRUPT);
1586
share->crashed= TRUE;
1587
DBUG_RETURN(HA_ADMIN_CORRUPT);
1543
return(HA_ADMIN_OK);
1547
drizzle_declare_plugin(csv)
1590
DBUG_RETURN(HA_ADMIN_OK);
1594
bool ha_tina::check_if_incompatible_data(HA_CREATE_INFO *info,
1597
return COMPATIBLE_DATA_YES;
1600
struct st_mysql_storage_engine csv_storage_engine=
1601
{ MYSQL_HANDLERTON_INTERFACE_VERSION };
1603
mysql_declare_plugin(csv)
1605
MYSQL_STORAGE_ENGINE_PLUGIN,
1606
&csv_storage_engine,
1551
1608
"Brian Aker, MySQL AB",
1552
1609
"CSV storage engine",
1553
1610
PLUGIN_LICENSE_GPL,
1554
1611
tina_init_func, /* Plugin Init */
1555
1612
tina_done_func, /* Plugin Deinit */
1556
1614
NULL, /* status variables */
1557
1615
NULL, /* system variables */
1558
1616
NULL /* config options */
1560
drizzle_declare_plugin_end;
1618
mysql_declare_plugin_end;