43
#include <drizzled/common_includes.h>
44
#ifdef USE_PRAGMA_IMPLEMENTATION
45
#pragma implementation // gcc: Class implementation
48
#include "mysql_priv.h"
49
#include <mysql/plugin.h>
44
50
#include "ha_tina.h"
48
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
50
#define META_BUFFER_SIZE sizeof(unsigned char) + sizeof(unsigned char) + sizeof(uint64_t) \
51
+ 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)
52
58
#define TINA_CHECK_HEADER 254 // The number we use to determine corruption
53
59
#define BLOB_MEMROOT_ALLOC_SIZE 8192
58
64
#define CSM_EXT ".CSM" // Meta file
61
static TINA_SHARE *get_share(const char *table_name, Table *table);
67
static TINA_SHARE *get_share(const char *table_name, TABLE *table);
62
68
static int free_share(TINA_SHARE *share);
63
69
static int read_meta_file(File meta_file, ha_rows *rows);
64
70
static int write_meta_file(File meta_file, ha_rows rows, bool dirty);
66
72
extern "C" void tina_get_status(void* param, int concurrent_insert);
67
73
extern "C" void tina_update_status(void* param);
68
extern "C" bool tina_check_status(void* param);
74
extern "C" my_bool tina_check_status(void* param);
70
76
/* Stuff for shares */
71
77
pthread_mutex_t tina_mutex;
91
97
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)))
100
static uchar* tina_get_key(TINA_SHARE *share, size_t *length,
101
my_bool not_used __attribute__((unused)))
97
103
*length=share->table_name_length;
98
return (unsigned char*) share->table_name;
104
return (uchar*) share->table_name;
101
107
static int tina_init_func(void *p)
103
109
handlerton *tina_hton;
105
111
tina_hton= (handlerton *)p;
106
pthread_mutex_init(&tina_mutex,MY_MUTEX_INIT_FAST);
112
VOID(pthread_mutex_init(&tina_mutex,MY_MUTEX_INIT_FAST));
107
113
(void) hash_init(&tina_open_tables,system_charset_info,32,0,0,
108
114
(hash_get_key) tina_get_key,0,0);
109
115
tina_hton->state= SHOW_OPTION_YES;
116
tina_hton->db_type= DB_TYPE_CSV_DB;
110
117
tina_hton->create= tina_create_handler;
111
118
tina_hton->flags= (HTON_CAN_RECREATE | HTON_SUPPORT_LOG_TABLES |
112
119
HTON_NO_PARTITION);
116
static int tina_done_func(void *p __attribute__((unused)))
123
static int tina_done_func(void *p)
118
125
hash_free(&tina_open_tables);
119
126
pthread_mutex_destroy(&tina_mutex);
126
133
Simple lock controls.
128
static TINA_SHARE *get_share(const char *table_name,
129
Table *table __attribute__((unused)))
135
static TINA_SHARE *get_share(const char *table_name, TABLE *table)
131
137
TINA_SHARE *share;
132
138
char meta_file_name[FN_REFLEN];
133
139
struct stat file_stat;
137
143
pthread_mutex_lock(&tina_mutex);
138
144
length=(uint) strlen(table_name);
142
148
initialize its members.
144
150
if (!(share=(TINA_SHARE*) hash_search(&tina_open_tables,
145
(unsigned char*) table_name,
148
154
if (!my_multi_malloc(MYF(MY_WME | MY_ZEROFILL),
149
155
&share, sizeof(*share),
150
156
&tmp_name, length+1,
153
159
pthread_mutex_unlock(&tina_mutex);
157
163
share->use_count= 0;
164
share->is_log_table= FALSE;
158
165
share->table_name_length= length;
159
166
share->table_name= tmp_name;
160
share->crashed= false;
167
share->crashed= FALSE;
161
168
share->rows_recorded= 0;
162
share->update_file_opened= false;
163
share->tina_write_opened= false;
169
share->update_file_opened= FALSE;
170
share->tina_write_opened= FALSE;
164
171
share->data_file_version= 0;
165
my_stpcpy(share->table_name, table_name);
172
strmov(share->table_name, table_name);
166
173
fn_format(share->data_file_name, table_name, "", CSV_EXT,
167
174
MY_REPLACE_EXT|MY_UNPACK_FILENAME);
168
175
fn_format(meta_file_name, table_name, "", CSM_EXT,
173
180
share->saved_data_file_length= file_stat.st_size;
175
if (my_hash_insert(&tina_open_tables, (unsigned char*) share))
182
if (my_hash_insert(&tina_open_tables, (uchar*) share))
177
184
thr_lock_init(&share->lock);
178
185
pthread_mutex_init(&share->mutex,MY_MUTEX_INIT_FAST);
186
193
if ((share->meta_file= my_open(meta_file_name,
187
194
O_RDWR|O_CREAT, MYF(0))) == -1)
188
share->crashed= true;
195
share->crashed= TRUE;
191
198
If the meta file will not open we assume it is crashed and
194
201
if (read_meta_file(share->meta_file, &share->rows_recorded))
195
share->crashed= true;
202
share->crashed= TRUE;
197
204
share->use_count++;
198
205
pthread_mutex_unlock(&tina_mutex);
229
236
static int read_meta_file(File meta_file, ha_rows *rows)
231
unsigned char meta_buffer[META_BUFFER_SIZE];
232
unsigned char *ptr= meta_buffer;
234
my_seek(meta_file, 0, MY_SEEK_SET, MYF(0));
235
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)
236
245
!= META_BUFFER_SIZE)
237
return(HA_ERR_CRASHED_ON_USAGE);
246
DBUG_RETURN(HA_ERR_CRASHED_ON_USAGE);
240
249
Parse out the meta data, we ignore version at the moment
243
ptr+= sizeof(unsigned char)*2; // Move past header
252
ptr+= sizeof(uchar)*2; // Move past header
244
253
*rows= (ha_rows)uint8korr(ptr);
245
254
ptr+= sizeof(uint64_t); // Move past rows
250
259
ptr+= 3*sizeof(uint64_t);
252
261
/* check crashed bit and magic number */
253
if ((meta_buffer[0] != (unsigned char)TINA_CHECK_HEADER) ||
254
((bool)(*ptr)== true))
255
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);
257
266
my_sync(meta_file, MYF(MY_WME));
282
291
static int write_meta_file(File meta_file, ha_rows rows, bool dirty)
284
unsigned char meta_buffer[META_BUFFER_SIZE];
285
unsigned char *ptr= meta_buffer;
287
*ptr= (unsigned char)TINA_CHECK_HEADER;
288
ptr+= sizeof(unsigned char);
289
*ptr= (unsigned char)TINA_VERSION;
290
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;
291
302
int8store(ptr, (uint64_t)rows);
292
303
ptr+= sizeof(uint64_t);
293
304
memset(ptr, 0, 3*sizeof(uint64_t));
296
307
We'll need them later.
298
309
ptr+= 3*sizeof(uint64_t);
299
*ptr= (unsigned char)dirty;
301
my_seek(meta_file, 0, MY_SEEK_SET, MYF(0));
302
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)
303
314
!= META_BUFFER_SIZE)
306
317
my_sync(meta_file, MYF(MY_WME));
311
322
bool ha_tina::check_and_repair(THD *thd)
313
324
HA_CHECK_OPT check_opt;
325
DBUG_ENTER("ha_tina::check_and_repair");
315
327
check_opt.init();
317
return(repair(thd, &check_opt));
329
DBUG_RETURN(repair(thd, &check_opt));
321
333
int ha_tina::init_tina_writer()
335
DBUG_ENTER("ha_tina::init_tina_writer");
324
338
Mark the file as crashed. We will set the flag back when we close
325
339
the file. In the case of the crash it will remain marked crashed,
326
340
which enforce recovery.
328
(void)write_meta_file(share->meta_file, share->rows_recorded, true);
342
(void)write_meta_file(share->meta_file, share->rows_recorded, TRUE);
330
344
if ((share->tina_write_filedes=
331
345
my_open(share->data_file_name, O_RDWR|O_APPEND, MYF(0))) == -1)
333
share->crashed= true;
347
DBUG_PRINT("info", ("Could not open tina file writes"));
348
share->crashed= TRUE;
336
share->tina_write_opened= true;
351
share->tina_write_opened= TRUE;
342
357
bool ha_tina::is_crashed() const
344
return(share->crashed);
359
DBUG_ENTER("ha_tina::is_crashed");
360
DBUG_RETURN(share->crashed);
350
366
static int free_share(TINA_SHARE *share)
368
DBUG_ENTER("ha_tina::free_share");
352
369
pthread_mutex_lock(&tina_mutex);
353
370
int result_code= 0;
354
371
if (!--share->use_count){
355
372
/* Write the meta file. Mark it as crashed if needed. */
356
373
(void)write_meta_file(share->meta_file, share->rows_recorded,
357
share->crashed ? true :false);
374
share->crashed ? TRUE :FALSE);
358
375
if (my_close(share->meta_file, MYF(0)))
360
377
if (share->tina_write_opened)
362
379
if (my_close(share->tina_write_filedes, MYF(0)))
364
share->tina_write_opened= false;
381
share->tina_write_opened= FALSE;
367
hash_delete(&tina_open_tables, (unsigned char*) share);
384
hash_delete(&tina_open_tables, (uchar*) share);
368
385
thr_lock_delete(&share->lock);
369
386
pthread_mutex_destroy(&share->mutex);
370
free((unsigned char*) share);
387
my_free((uchar*) share, MYF(0));
372
389
pthread_mutex_unlock(&tina_mutex);
391
DBUG_RETURN(result_code);
442
459
Encode a buffer into the quoted format.
445
int ha_tina::encode_quote(unsigned char *buf __attribute__((unused)))
462
int ha_tina::encode_quote(uchar *buf)
447
464
char attribute_buffer[1024];
448
465
String attribute(attribute_buffer, sizeof(attribute_buffer),
449
466
&my_charset_bin);
468
my_bitmap_map *org_bitmap= dbug_tmp_use_all_columns(table, table->read_set);
451
469
buffer.length(0);
453
471
for (Field **field=table->field ; *field ; field++)
523
541
//buffer.replace(buffer.length(), 0, "\n", 1);
543
dbug_tmp_restore_column_map(table->read_set, org_bitmap);
525
544
return (buffer.length());
544
563
if (chain_alloced)
546
565
/* Must cast since my_malloc unlike malloc doesn't have a void ptr */
547
if ((chain= (tina_set *) my_realloc((unsigned char*)chain,
566
if ((chain= (tina_set *) my_realloc((uchar*)chain,
548
567
chain_size, MYF(MY_WME))) == NULL)
573
int ha_tina::find_current_row(unsigned char *buf)
592
int ha_tina::find_current_row(uchar *buf)
575
594
off_t end_offset, curr_offset= current_position;
596
my_bitmap_map *org_bitmap;
599
DBUG_ENTER("ha_tina::find_current_row");
580
601
free_root(&blobroot, MYF(MY_MARK_BLOCKS_FREE));
587
608
find_eoln_buff(file_buff, current_position,
588
609
local_saved_data_file_length, &eoln_len)) == 0)
589
return(HA_ERR_END_OF_FILE);
610
DBUG_RETURN(HA_ERR_END_OF_FILE);
591
612
/* We must read all columns in case a table is opened for update */
592
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);
593
616
error= HA_ERR_CRASHED_ON_USAGE;
595
618
memset(buf, 0, table->s->null_bytes);
667
690
if ((*field)->flags & BLOB_FLAG)
669
692
Field_blob *blob= *(Field_blob**) field;
670
unsigned char *src, *tgt;
671
uint32_t length, packlength;
694
uint length, packlength;
673
696
packlength= blob->pack_length_no_ptr();
674
697
length= blob->get_length(blob->ptr);
675
memcpy(&src, blob->ptr + packlength, sizeof(char*));
698
memcpy_fixed(&src, blob->ptr + packlength, sizeof(char*));
678
tgt= (unsigned char*) alloc_root(&blobroot, length);
679
memcpy(tgt, src, length);
680
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*));
710
734
for CSV engine. For more details see mysys/thr_lock.c
713
void tina_get_status(void* param,
714
int concurrent_insert __attribute__((unused)))
737
void tina_get_status(void* param, int concurrent_insert)
716
739
ha_tina *tina= (ha_tina*) param;
717
740
tina->get_status();
744
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);
746
780
local_saved_data_file_length= share->saved_data_file_length;
764
798
For log tables concurrent insert works different. The reason is that
765
799
log tables are always opened and locked. And as they do not unlock
766
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.
770
805
void ha_tina::update_status()
779
814
this will not be called for every request. Any sort of positions
780
815
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)
817
int ha_tina::open(const char *name, int mode, uint open_options)
819
DBUG_ENTER("ha_tina::open");
785
821
if (!(share= get_share(name, table)))
786
return(HA_ERR_OUT_OF_MEM);
822
DBUG_RETURN(HA_ERR_OUT_OF_MEM);
788
824
if (share->crashed && !(open_options & HA_OPEN_FOR_REPAIR))
790
826
free_share(share);
791
return(HA_ERR_CRASHED_ON_USAGE);
827
DBUG_RETURN(HA_ERR_CRASHED_ON_USAGE);
794
830
local_data_file_version= share->data_file_version;
795
831
if ((data_file= my_open(share->data_file_name, O_RDONLY, MYF(0))) == -1)
799
835
Init locking. Pass handler object to the locking routines,
818
854
int ha_tina::close(void)
857
DBUG_ENTER("ha_tina::close");
821
858
rc= my_close(data_file, MYF(0));
822
return(free_share(share) || rc);
859
DBUG_RETURN(free_share(share) || rc);
827
864
of the file and appends the data. In an error case it really should
828
865
just truncate to the original position (this is not done yet).
830
int ha_tina::write_row(unsigned char * buf)
867
int ha_tina::write_row(uchar * buf)
870
DBUG_ENTER("ha_tina::write_row");
834
872
if (share->crashed)
835
return(HA_ERR_CRASHED_ON_USAGE);
873
DBUG_RETURN(HA_ERR_CRASHED_ON_USAGE);
837
875
ha_statistic_increment(&SSV::ha_write_count);
844
882
if (!share->tina_write_opened)
845
883
if (init_tina_writer())
848
886
/* use pwrite, as concurrent reader could have changed the position */
849
if (my_write(share->tina_write_filedes, (unsigned char*)buffer.ptr(), size,
887
if (my_write(share->tina_write_filedes, (uchar*)buffer.ptr(), size,
850
888
MYF(MY_WME | MY_NABP)))
853
891
/* update local copy of the max position to see our own changes */
854
892
local_saved_data_file_length+= size;
876
916
MY_REPLACE_EXT | MY_UNPACK_FILENAME),
877
917
0, O_RDWR | O_TRUNC, MYF(MY_WME))) < 0)
879
share->update_file_opened= true;
919
share->update_file_opened= TRUE;
880
920
temp_file_length= 0;
890
930
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)
933
int ha_tina::update_row(const uchar * old_data, uchar * new_data)
937
DBUG_ENTER("ha_tina::update_row");
899
939
ha_statistic_increment(&SSV::ha_update_count);
916
956
if (open_update_temp_file_if_needed())
919
if (my_write(update_temp_file, (unsigned char*)buffer.ptr(), size,
959
if (my_write(update_temp_file, (uchar*)buffer.ptr(), size,
920
960
MYF(MY_WME | MY_NABP)))
922
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));
936
980
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)))
983
int ha_tina::delete_row(const uchar * buf)
985
DBUG_ENTER("ha_tina::delete_row");
941
986
ha_statistic_increment(&SSV::ha_delete_count);
943
988
if (chain_append())
947
992
/* Update shared info */
948
assert(share->rows_recorded);
993
DBUG_ASSERT(share->rows_recorded);
949
994
pthread_mutex_lock(&share->mutex);
950
995
share->rows_recorded--;
951
996
pthread_mutex_unlock(&share->mutex);
998
/* DELETE should never happen on the log table */
999
DBUG_ASSERT(!share->is_log_table);
1015
int ha_tina::rnd_init(bool scan __attribute__((unused)))
1063
int ha_tina::rnd_init(bool scan)
1065
DBUG_ENTER("ha_tina::rnd_init");
1017
1067
/* set buffer to the beginning of the file */
1018
1068
if (share->crashed || init_data_file())
1019
return(HA_ERR_CRASHED_ON_USAGE);
1069
DBUG_RETURN(HA_ERR_CRASHED_ON_USAGE);
1021
1071
current_position= next_position= 0;
1022
1072
stats.records= 0;
1042
1092
NULL and "". This is ok since this table handler is for spreadsheets and
1043
1093
they don't know about them either :)
1045
int ha_tina::rnd_next(unsigned char *buf)
1095
int ha_tina::rnd_next(uchar *buf)
1098
DBUG_ENTER("ha_tina::rnd_next");
1049
1100
if (share->crashed)
1050
return(HA_ERR_CRASHED_ON_USAGE);
1101
DBUG_RETURN(HA_ERR_CRASHED_ON_USAGE);
1052
1103
ha_statistic_increment(&SSV::ha_read_rnd_next_count);
1056
1107
/* don't scan an empty file */
1057
1108
if (!local_saved_data_file_length)
1058
return(HA_ERR_END_OF_FILE);
1109
DBUG_RETURN(HA_ERR_END_OF_FILE);
1060
1111
if ((rc= find_current_row(buf)))
1063
1114
stats.records++;
1073
1124
its just a position. Look at the bdb code if you want to see a case
1074
1125
where something other then a number is stored.
1076
void ha_tina::position(const unsigned char *record __attribute__((unused)))
1127
void ha_tina::position(const uchar *record)
1129
DBUG_ENTER("ha_tina::position");
1078
1130
my_store_ptr(ref, ref_length, current_position);
1085
1137
my_get_ptr() retrieves the data for you.
1088
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");
1090
1143
ha_statistic_increment(&SSV::ha_read_rnd_count);
1091
1144
current_position= (off_t)my_get_ptr(pos,ref_length);
1092
return(find_current_row(buf));
1145
DBUG_RETURN(find_current_row(buf));
1097
1150
Currently this table handler doesn't implement most of the fields
1098
1151
really needed. SHOW also makes use of this data
1100
int ha_tina::info(uint32_t flag __attribute__((unused)))
1153
int ha_tina::info(uint flag)
1155
DBUG_ENTER("ha_tina::info");
1102
1156
/* This is a lie, but you don't want the optimizer to see zero or 1 */
1103
1157
if (!records_is_known && stats.records < 2)
1104
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);
1115
1186
if (closest_hole == chain_ptr) /* no more chains */
1116
1187
*end_pos= file_buff->end();
1118
*end_pos= std::min(file_buff->end(),
1119
closest_hole->begin);
1189
*end_pos= min(file_buff->end(),
1190
closest_hole->begin);
1120
1191
return (closest_hole != chain_ptr) && (*end_pos == closest_hole->begin);
1132
1203
char updated_fname[FN_REFLEN];
1133
1204
off_t file_buffer_start= 0;
1205
DBUG_ENTER("ha_tina::rnd_end");
1135
1207
free_root(&blobroot, MYF(0));
1136
1208
records_is_known= 1;
1157
1229
/* create the file to write updated table if it wasn't yet created */
1158
1230
if (open_update_temp_file_if_needed())
1161
1233
/* write the file with updated info */
1162
1234
while ((file_buffer_start != -1)) // while not end of file
1168
1240
if (write_length)
1170
1242
if (my_write(update_temp_file,
1171
(unsigned char*) (file_buff->ptr() +
1243
(uchar*) (file_buff->ptr() +
1172
1244
(write_begin - file_buff->start())),
1173
1245
write_length, MYF_RW))
1193
1265
if (my_sync(update_temp_file, MYF(MY_WME)) ||
1194
1266
my_close(update_temp_file, MYF(0)))
1197
share->update_file_opened= false;
1269
share->update_file_opened= FALSE;
1199
1271
if (share->tina_write_opened)
1201
1273
if (my_close(share->tina_write_filedes, MYF(0)))
1204
1276
Mark that the writer fd is closed, so that init_tina_writer()
1205
1277
will reopen it later.
1207
share->tina_write_opened= false;
1279
share->tina_write_opened= FALSE;
1215
1287
my_rename(fn_format(updated_fname, share->table_name, "", CSN_EXT,
1216
1288
MY_REPLACE_EXT | MY_UNPACK_FILENAME),
1217
1289
share->data_file_name, MYF(0)))
1220
1292
/* Open the file again */
1221
1293
if (((data_file= my_open(share->data_file_name, O_RDONLY, MYF(0))) == -1))
1224
1296
As we reopened the data file, increase share->data_file_version
1225
1297
in order to force other threads waiting on a table lock and
1235
1307
closed, so nothing worrying will happen to it in case of a crash.
1236
1308
Here we record this fact to the meta-file.
1238
(void)write_meta_file(share->meta_file, share->rows_recorded, false);
1310
(void)write_meta_file(share->meta_file, share->rows_recorded, FALSE);
1240
1312
Update local_saved_data_file_length with the real length of the
1243
1315
local_saved_data_file_length= temp_file_length;
1248
1320
my_close(update_temp_file, MYF(0));
1249
share->update_file_opened= false;
1321
share->update_file_opened= FALSE;
1269
1341
rows (after the first bad one) as well.
1272
int ha_tina::repair(THD* thd,
1273
HA_CHECK_OPT* check_opt __attribute__((unused)))
1344
int ha_tina::repair(THD* thd, HA_CHECK_OPT* check_opt)
1275
1346
char repaired_fname[FN_REFLEN];
1277
1348
File repair_file;
1279
1350
ha_rows rows_repaired= 0;
1280
1351
off_t write_begin= 0, write_end;
1352
DBUG_ENTER("ha_tina::repair");
1282
1354
/* empty file */
1283
1355
if (!share->saved_data_file_length)
1289
1361
/* Don't assert in field::val() functions */
1290
1362
table->use_all_columns();
1291
if (!(buf= (unsigned char*) my_malloc(table->s->reclength, MYF(MY_WME))))
1292
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);
1294
1366
/* position buffer to the start of the file */
1295
1367
if (init_data_file())
1296
return(HA_ERR_CRASHED_ON_REPAIR);
1368
DBUG_RETURN(HA_ERR_CRASHED_ON_REPAIR);
1299
1371
Local_saved_data_file_length is initialized during the lock phase.
1338
1410
MY_REPLACE_EXT|MY_UNPACK_FILENAME),
1339
1411
0, O_RDWR | O_TRUNC,MYF(MY_WME))) < 0)
1340
return(HA_ERR_CRASHED_ON_REPAIR);
1412
DBUG_RETURN(HA_ERR_CRASHED_ON_REPAIR);
1342
1414
file_buff->init_buff(data_file);
1348
1420
/* write repaired file */
1351
write_end= std::min(file_buff->end(), current_position);
1423
write_end= min(file_buff->end(), current_position);
1352
1424
if ((write_end - write_begin) &&
1353
(my_write(repair_file, (unsigned char*)file_buff->ptr(),
1425
(my_write(repair_file, (uchar*)file_buff->ptr(),
1354
1426
write_end - write_begin, MYF_RW)))
1357
1429
write_begin= write_end;
1358
1430
if (write_end== current_position)
1370
1442
if (my_close(data_file,MYF(0)) || my_close(repair_file, MYF(0)) ||
1371
1443
my_rename(repaired_fname, share->data_file_name, MYF(0)))
1374
1446
/* Open the file again, it should now be repaired */
1375
1447
if ((data_file= my_open(share->data_file_name, O_RDWR|O_APPEND,
1376
1448
MYF(0))) == -1)
1379
1451
/* Set new file size. The file size will be updated by ::update_status() */
1380
1452
local_saved_data_file_length= (size_t) current_position;
1383
share->crashed= false;
1384
return(HA_ADMIN_OK);
1455
share->crashed= FALSE;
1456
DBUG_RETURN(HA_ADMIN_OK);
1391
1463
int ha_tina::delete_all_rows()
1466
DBUG_ENTER("ha_tina::delete_all_rows");
1395
1468
if (!records_is_known)
1396
return(my_errno=HA_ERR_WRONG_COMMAND);
1469
DBUG_RETURN(my_errno=HA_ERR_WRONG_COMMAND);
1398
1471
if (!share->tina_write_opened)
1399
1472
if (init_tina_writer())
1402
1475
/* Truncate the file to zero size */
1403
rc= ftruncate(share->tina_write_filedes, 0);
1476
rc= my_chsize(share->tina_write_filedes, 0, 0, MYF(MY_WME));
1405
1478
stats.records=0;
1406
1479
/* Update shared info */
1408
1481
share->rows_recorded= 0;
1409
1482
pthread_mutex_unlock(&share->mutex);
1410
1483
local_saved_data_file_length= 0;
1415
1488
Called by the database to lock the table. Keep in mind that this
1416
1489
is an internal lock.
1418
THR_LOCK_DATA **ha_tina::store_lock(THD *thd __attribute__((unused)),
1491
THR_LOCK_DATA **ha_tina::store_lock(THD *thd,
1419
1492
THR_LOCK_DATA **to,
1420
1493
enum thr_lock_type lock_type)
1430
1503
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)))
1506
int ha_tina::create(const char *name, TABLE *table_arg,
1507
HA_CREATE_INFO *create_info)
1436
1509
char name_buff[FN_REFLEN];
1437
1510
File create_file;
1511
DBUG_ENTER("ha_tina::create");
1444
1518
if ((*field)->real_maybe_null())
1446
1520
my_error(ER_CHECK_NOT_IMPLEMENTED, MYF(0), "nullable columns");
1447
return(HA_ERR_UNSUPPORTED);
1521
DBUG_RETURN(HA_ERR_UNSUPPORTED);
1452
1526
if ((create_file= my_create(fn_format(name_buff, name, "", CSM_EXT,
1453
1527
MY_REPLACE_EXT|MY_UNPACK_FILENAME), 0,
1454
1528
O_RDWR | O_TRUNC,MYF(MY_WME))) < 0)
1457
write_meta_file(create_file, 0, false);
1531
write_meta_file(create_file, 0, FALSE);
1458
1532
my_close(create_file, MYF(0));
1460
1534
if ((create_file= my_create(fn_format(name_buff, name, "", CSV_EXT,
1461
1535
MY_REPLACE_EXT|MY_UNPACK_FILENAME),0,
1462
1536
O_RDWR | O_TRUNC,MYF(MY_WME))) < 0)
1465
1539
my_close(create_file, MYF(0));
1470
int ha_tina::check(THD* thd,
1471
HA_CHECK_OPT* check_opt __attribute__((unused)))
1544
int ha_tina::check(THD* thd, HA_CHECK_OPT* check_opt)
1475
1548
const char *old_proc_info;
1476
1549
ha_rows count= share->rows_recorded;
1550
DBUG_ENTER("ha_tina::check");
1478
old_proc_info= get_thd_proc_info(thd);
1479
set_thd_proc_info(thd, "Checking table");
1480
if (!(buf= (unsigned char*) my_malloc(table->s->reclength, MYF(MY_WME))))
1481
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);
1483
1556
/* position buffer to the start of the file */
1484
1557
if (init_data_file())
1485
return(HA_ERR_CRASHED);
1558
DBUG_RETURN(HA_ERR_CRASHED);
1488
1561
Local_saved_data_file_length is initialized during the lock phase.
1506
1579
free_root(&blobroot, MYF(0));
1509
set_thd_proc_info(thd, old_proc_info);
1581
my_free((char*)buf, MYF(0));
1582
thd_proc_info(thd, old_proc_info);
1511
1584
if ((rc != HA_ERR_END_OF_FILE) || count)
1513
share->crashed= true;
1514
return(HA_ADMIN_CORRUPT);
1586
share->crashed= TRUE;
1587
DBUG_RETURN(HA_ADMIN_CORRUPT);
1517
return(HA_ADMIN_OK);
1590
DBUG_RETURN(HA_ADMIN_OK);
1521
bool ha_tina::check_if_incompatible_data(HA_CREATE_INFO *info __attribute__((unused)),
1522
uint32_t table_changes __attribute__((unused)))
1594
bool ha_tina::check_if_incompatible_data(HA_CREATE_INFO *info,
1524
1597
return COMPATIBLE_DATA_YES;
1600
struct st_mysql_storage_engine csv_storage_engine=
1601
{ MYSQL_HANDLERTON_INTERFACE_VERSION };
1527
1603
mysql_declare_plugin(csv)
1529
DRIZZLE_STORAGE_ENGINE_PLUGIN,
1605
MYSQL_STORAGE_ENGINE_PLUGIN,
1606
&csv_storage_engine,
1532
1608
"Brian Aker, MySQL AB",
1533
1609
"CSV storage engine",
1534
1610
PLUGIN_LICENSE_GPL,
1535
1611
tina_init_func, /* Plugin Init */
1536
1612
tina_done_func, /* Plugin Deinit */
1537
1614
NULL, /* status variables */
1538
1615
NULL, /* system variables */
1539
1616
NULL /* config options */