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 __attribute__((__unused__)))
118
125
hash_free(&tina_open_tables);
119
126
pthread_mutex_destroy(&tina_mutex);
126
133
Simple lock controls.
128
135
static TINA_SHARE *get_share(const char *table_name,
129
Table *table __attribute__((unused)))
136
TABLE *table __attribute__((__unused__)))
131
138
TINA_SHARE *share;
132
139
char meta_file_name[FN_REFLEN];
133
140
struct stat file_stat;
137
144
pthread_mutex_lock(&tina_mutex);
138
145
length=(uint) strlen(table_name);
142
149
initialize its members.
144
151
if (!(share=(TINA_SHARE*) hash_search(&tina_open_tables,
145
(unsigned char*) table_name,
148
155
if (!my_multi_malloc(MYF(MY_WME | MY_ZEROFILL),
149
156
&share, sizeof(*share),
150
157
&tmp_name, length+1,
153
160
pthread_mutex_unlock(&tina_mutex);
157
164
share->use_count= 0;
165
share->is_log_table= FALSE;
158
166
share->table_name_length= length;
159
167
share->table_name= tmp_name;
160
share->crashed= false;
168
share->crashed= FALSE;
161
169
share->rows_recorded= 0;
162
share->update_file_opened= false;
163
share->tina_write_opened= false;
170
share->update_file_opened= FALSE;
171
share->tina_write_opened= FALSE;
164
172
share->data_file_version= 0;
165
my_stpcpy(share->table_name, table_name);
173
strmov(share->table_name, table_name);
166
174
fn_format(share->data_file_name, table_name, "", CSV_EXT,
167
175
MY_REPLACE_EXT|MY_UNPACK_FILENAME);
168
176
fn_format(meta_file_name, table_name, "", CSM_EXT,
173
181
share->saved_data_file_length= file_stat.st_size;
175
if (my_hash_insert(&tina_open_tables, (unsigned char*) share))
183
if (my_hash_insert(&tina_open_tables, (uchar*) share))
177
185
thr_lock_init(&share->lock);
178
186
pthread_mutex_init(&share->mutex,MY_MUTEX_INIT_FAST);
186
194
if ((share->meta_file= my_open(meta_file_name,
187
195
O_RDWR|O_CREAT, MYF(0))) == -1)
188
share->crashed= true;
196
share->crashed= TRUE;
191
199
If the meta file will not open we assume it is crashed and
194
202
if (read_meta_file(share->meta_file, &share->rows_recorded))
195
share->crashed= true;
203
share->crashed= TRUE;
197
205
share->use_count++;
198
206
pthread_mutex_unlock(&tina_mutex);
229
237
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)
239
uchar meta_buffer[META_BUFFER_SIZE];
240
uchar *ptr= meta_buffer;
242
DBUG_ENTER("ha_tina::read_meta_file");
244
VOID(my_seek(meta_file, 0, MY_SEEK_SET, MYF(0)));
245
if (my_read(meta_file, (uchar*)meta_buffer, META_BUFFER_SIZE, 0)
236
246
!= META_BUFFER_SIZE)
237
return(HA_ERR_CRASHED_ON_USAGE);
247
DBUG_RETURN(HA_ERR_CRASHED_ON_USAGE);
240
250
Parse out the meta data, we ignore version at the moment
243
ptr+= sizeof(unsigned char)*2; // Move past header
253
ptr+= sizeof(uchar)*2; // Move past header
244
254
*rows= (ha_rows)uint8korr(ptr);
245
255
ptr+= sizeof(uint64_t); // Move past rows
250
260
ptr+= 3*sizeof(uint64_t);
252
262
/* 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);
263
if ((meta_buffer[0] != (uchar)TINA_CHECK_HEADER) ||
264
((bool)(*ptr)== TRUE))
265
DBUG_RETURN(HA_ERR_CRASHED_ON_USAGE);
257
267
my_sync(meta_file, MYF(MY_WME));
282
292
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);
294
uchar meta_buffer[META_BUFFER_SIZE];
295
uchar *ptr= meta_buffer;
297
DBUG_ENTER("ha_tina::write_meta_file");
299
*ptr= (uchar)TINA_CHECK_HEADER;
301
*ptr= (uchar)TINA_VERSION;
291
303
int8store(ptr, (uint64_t)rows);
292
304
ptr+= sizeof(uint64_t);
293
305
memset(ptr, 0, 3*sizeof(uint64_t));
296
308
We'll need them later.
298
310
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)
313
VOID(my_seek(meta_file, 0, MY_SEEK_SET, MYF(0)));
314
if (my_write(meta_file, (uchar *)meta_buffer, META_BUFFER_SIZE, 0)
303
315
!= META_BUFFER_SIZE)
306
318
my_sync(meta_file, MYF(MY_WME));
311
323
bool ha_tina::check_and_repair(THD *thd)
313
325
HA_CHECK_OPT check_opt;
326
DBUG_ENTER("ha_tina::check_and_repair");
315
328
check_opt.init();
317
return(repair(thd, &check_opt));
330
DBUG_RETURN(repair(thd, &check_opt));
321
334
int ha_tina::init_tina_writer()
336
DBUG_ENTER("ha_tina::init_tina_writer");
324
339
Mark the file as crashed. We will set the flag back when we close
325
340
the file. In the case of the crash it will remain marked crashed,
326
341
which enforce recovery.
328
(void)write_meta_file(share->meta_file, share->rows_recorded, true);
343
(void)write_meta_file(share->meta_file, share->rows_recorded, TRUE);
330
345
if ((share->tina_write_filedes=
331
346
my_open(share->data_file_name, O_RDWR|O_APPEND, MYF(0))) == -1)
333
share->crashed= true;
348
DBUG_PRINT("info", ("Could not open tina file writes"));
349
share->crashed= TRUE;
336
share->tina_write_opened= true;
352
share->tina_write_opened= TRUE;
342
358
bool ha_tina::is_crashed() const
344
return(share->crashed);
360
DBUG_ENTER("ha_tina::is_crashed");
361
DBUG_RETURN(share->crashed);
350
367
static int free_share(TINA_SHARE *share)
369
DBUG_ENTER("ha_tina::free_share");
352
370
pthread_mutex_lock(&tina_mutex);
353
371
int result_code= 0;
354
372
if (!--share->use_count){
355
373
/* Write the meta file. Mark it as crashed if needed. */
356
374
(void)write_meta_file(share->meta_file, share->rows_recorded,
357
share->crashed ? true :false);
375
share->crashed ? TRUE :FALSE);
358
376
if (my_close(share->meta_file, MYF(0)))
360
378
if (share->tina_write_opened)
362
380
if (my_close(share->tina_write_filedes, MYF(0)))
364
share->tina_write_opened= false;
382
share->tina_write_opened= FALSE;
367
hash_delete(&tina_open_tables, (unsigned char*) share);
385
hash_delete(&tina_open_tables, (uchar*) share);
368
386
thr_lock_delete(&share->lock);
369
387
pthread_mutex_destroy(&share->mutex);
370
free((unsigned char*) share);
388
my_free((uchar*) share, MYF(0));
372
390
pthread_mutex_unlock(&tina_mutex);
392
DBUG_RETURN(result_code);
442
460
Encode a buffer into the quoted format.
445
int ha_tina::encode_quote(unsigned char *buf __attribute__((unused)))
463
int ha_tina::encode_quote(uchar *buf __attribute__((__unused__)))
447
465
char attribute_buffer[1024];
448
466
String attribute(attribute_buffer, sizeof(attribute_buffer),
449
467
&my_charset_bin);
469
my_bitmap_map *org_bitmap= dbug_tmp_use_all_columns(table, table->read_set);
451
470
buffer.length(0);
453
472
for (Field **field=table->field ; *field ; field++)
523
542
//buffer.replace(buffer.length(), 0, "\n", 1);
544
dbug_tmp_restore_column_map(table->read_set, org_bitmap);
525
545
return (buffer.length());
544
564
if (chain_alloced)
546
566
/* Must cast since my_malloc unlike malloc doesn't have a void ptr */
547
if ((chain= (tina_set *) my_realloc((unsigned char*)chain,
567
if ((chain= (tina_set *) my_realloc((uchar*)chain,
548
568
chain_size, MYF(MY_WME))) == NULL)
573
int ha_tina::find_current_row(unsigned char *buf)
593
int ha_tina::find_current_row(uchar *buf)
575
595
off_t end_offset, curr_offset= current_position;
597
my_bitmap_map *org_bitmap;
600
DBUG_ENTER("ha_tina::find_current_row");
580
602
free_root(&blobroot, MYF(MY_MARK_BLOCKS_FREE));
587
609
find_eoln_buff(file_buff, current_position,
588
610
local_saved_data_file_length, &eoln_len)) == 0)
589
return(HA_ERR_END_OF_FILE);
611
DBUG_RETURN(HA_ERR_END_OF_FILE);
591
613
/* We must read all columns in case a table is opened for update */
592
614
read_all= !bitmap_is_clear_all(table->write_set);
615
/* Avoid asserts in ::store() for columns that are not going to be updated */
616
org_bitmap= dbug_tmp_use_all_columns(table, table->write_set);
593
617
error= HA_ERR_CRASHED_ON_USAGE;
595
619
memset(buf, 0, table->s->null_bytes);
667
691
if ((*field)->flags & BLOB_FLAG)
669
693
Field_blob *blob= *(Field_blob**) field;
670
unsigned char *src, *tgt;
671
uint32_t length, packlength;
695
uint length, packlength;
673
697
packlength= blob->pack_length_no_ptr();
674
698
length= blob->get_length(blob->ptr);
675
memcpy(&src, blob->ptr + packlength, sizeof(char*));
699
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*));
702
tgt= (uchar*) alloc_root(&blobroot, length);
703
bmove(tgt, src, length);
704
memcpy_fixed(blob->ptr + packlength, &tgt, sizeof(char*));
713
738
void tina_get_status(void* param,
714
int concurrent_insert __attribute__((unused)))
739
int concurrent_insert __attribute__((__unused__)))
716
741
ha_tina *tina= (ha_tina*) param;
717
742
tina->get_status();
744
769
void ha_tina::get_status()
771
if (share->is_log_table)
774
We have to use mutex to follow pthreads memory visibility
775
rules for share->saved_data_file_length
777
pthread_mutex_lock(&share->mutex);
778
local_saved_data_file_length= share->saved_data_file_length;
779
pthread_mutex_unlock(&share->mutex);
746
782
local_saved_data_file_length= share->saved_data_file_length;
764
800
For log tables concurrent insert works different. The reason is that
765
801
log tables are always opened and locked. And as they do not unlock
766
802
tables, the file length after writes should be updated in a different
803
way. For this purpose we need is_log_table flag. When this flag is set
804
we call update_status() explicitly after each row write.
770
807
void ha_tina::update_status()
779
816
this will not be called for every request. Any sort of positions
780
817
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)
819
int ha_tina::open(const char *name, int mode __attribute__((__unused__)),
822
DBUG_ENTER("ha_tina::open");
785
824
if (!(share= get_share(name, table)))
786
return(HA_ERR_OUT_OF_MEM);
825
DBUG_RETURN(HA_ERR_OUT_OF_MEM);
788
827
if (share->crashed && !(open_options & HA_OPEN_FOR_REPAIR))
790
829
free_share(share);
791
return(HA_ERR_CRASHED_ON_USAGE);
830
DBUG_RETURN(HA_ERR_CRASHED_ON_USAGE);
794
833
local_data_file_version= share->data_file_version;
795
834
if ((data_file= my_open(share->data_file_name, O_RDONLY, MYF(0))) == -1)
799
838
Init locking. Pass handler object to the locking routines,
818
857
int ha_tina::close(void)
860
DBUG_ENTER("ha_tina::close");
821
861
rc= my_close(data_file, MYF(0));
822
return(free_share(share) || rc);
862
DBUG_RETURN(free_share(share) || rc);
827
867
of the file and appends the data. In an error case it really should
828
868
just truncate to the original position (this is not done yet).
830
int ha_tina::write_row(unsigned char * buf)
870
int ha_tina::write_row(uchar * buf)
873
DBUG_ENTER("ha_tina::write_row");
834
875
if (share->crashed)
835
return(HA_ERR_CRASHED_ON_USAGE);
876
DBUG_RETURN(HA_ERR_CRASHED_ON_USAGE);
837
878
ha_statistic_increment(&SSV::ha_write_count);
844
885
if (!share->tina_write_opened)
845
886
if (init_tina_writer())
848
889
/* use pwrite, as concurrent reader could have changed the position */
849
if (my_write(share->tina_write_filedes, (unsigned char*)buffer.ptr(), size,
890
if (my_write(share->tina_write_filedes, (uchar*)buffer.ptr(), size,
850
891
MYF(MY_WME | MY_NABP)))
853
894
/* update local copy of the max position to see our own changes */
854
895
local_saved_data_file_length+= size;
876
919
MY_REPLACE_EXT | MY_UNPACK_FILENAME),
877
920
0, O_RDWR | O_TRUNC, MYF(MY_WME))) < 0)
879
share->update_file_opened= true;
922
share->update_file_opened= TRUE;
880
923
temp_file_length= 0;
890
933
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)
936
int ha_tina::update_row(const uchar * old_data __attribute__((__unused__)),
941
DBUG_ENTER("ha_tina::update_row");
899
943
ha_statistic_increment(&SSV::ha_update_count);
916
960
if (open_update_temp_file_if_needed())
919
if (my_write(update_temp_file, (unsigned char*)buffer.ptr(), size,
963
if (my_write(update_temp_file, (uchar*)buffer.ptr(), size,
920
964
MYF(MY_WME | MY_NABP)))
922
966
temp_file_length+= size;
969
/* UPDATE should never happen on the log tables */
970
DBUG_ASSERT(!share->is_log_table);
973
DBUG_PRINT("info",("rc = %d", rc));
936
984
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)))
987
int ha_tina::delete_row(const uchar * buf __attribute__((__unused__)))
989
DBUG_ENTER("ha_tina::delete_row");
941
990
ha_statistic_increment(&SSV::ha_delete_count);
943
992
if (chain_append())
947
996
/* Update shared info */
948
assert(share->rows_recorded);
997
DBUG_ASSERT(share->rows_recorded);
949
998
pthread_mutex_lock(&share->mutex);
950
999
share->rows_recorded--;
951
1000
pthread_mutex_unlock(&share->mutex);
1002
/* DELETE should never happen on the log table */
1003
DBUG_ASSERT(!share->is_log_table);
1015
int ha_tina::rnd_init(bool scan __attribute__((unused)))
1067
int ha_tina::rnd_init(bool scan __attribute__((__unused__)))
1069
DBUG_ENTER("ha_tina::rnd_init");
1017
1071
/* set buffer to the beginning of the file */
1018
1072
if (share->crashed || init_data_file())
1019
return(HA_ERR_CRASHED_ON_USAGE);
1073
DBUG_RETURN(HA_ERR_CRASHED_ON_USAGE);
1021
1075
current_position= next_position= 0;
1022
1076
stats.records= 0;
1042
1096
NULL and "". This is ok since this table handler is for spreadsheets and
1043
1097
they don't know about them either :)
1045
int ha_tina::rnd_next(unsigned char *buf)
1099
int ha_tina::rnd_next(uchar *buf)
1102
DBUG_ENTER("ha_tina::rnd_next");
1049
1104
if (share->crashed)
1050
return(HA_ERR_CRASHED_ON_USAGE);
1105
DBUG_RETURN(HA_ERR_CRASHED_ON_USAGE);
1052
1107
ha_statistic_increment(&SSV::ha_read_rnd_next_count);
1056
1111
/* don't scan an empty file */
1057
1112
if (!local_saved_data_file_length)
1058
return(HA_ERR_END_OF_FILE);
1113
DBUG_RETURN(HA_ERR_END_OF_FILE);
1060
1115
if ((rc= find_current_row(buf)))
1063
1118
stats.records++;
1073
1128
its just a position. Look at the bdb code if you want to see a case
1074
1129
where something other then a number is stored.
1076
void ha_tina::position(const unsigned char *record __attribute__((unused)))
1131
void ha_tina::position(const uchar *record __attribute__((__unused__)))
1133
DBUG_ENTER("ha_tina::position");
1078
1134
my_store_ptr(ref, ref_length, current_position);
1085
1141
my_get_ptr() retrieves the data for you.
1088
int ha_tina::rnd_pos(unsigned char * buf, unsigned char *pos)
1144
int ha_tina::rnd_pos(uchar * buf, uchar *pos)
1146
DBUG_ENTER("ha_tina::rnd_pos");
1090
1147
ha_statistic_increment(&SSV::ha_read_rnd_count);
1091
1148
current_position= (off_t)my_get_ptr(pos,ref_length);
1092
return(find_current_row(buf));
1149
DBUG_RETURN(find_current_row(buf));
1097
1154
Currently this table handler doesn't implement most of the fields
1098
1155
really needed. SHOW also makes use of this data
1100
int ha_tina::info(uint32_t flag __attribute__((unused)))
1157
int ha_tina::info(uint flag __attribute__((__unused__)))
1159
DBUG_ENTER("ha_tina::info");
1102
1160
/* This is a lie, but you don't want the optimizer to see zero or 1 */
1103
1161
if (!records_is_known && stats.records < 2)
1104
1162
stats.records= 2;
1167
Grab bag of flags that are sent to the able handler every so often.
1168
HA_EXTRA_RESET and HA_EXTRA_RESET_STATE are the most frequently called.
1169
You are not required to implement any of these.
1171
int ha_tina::extra(enum ha_extra_function operation)
1173
DBUG_ENTER("ha_tina::extra");
1174
if (operation == HA_EXTRA_MARK_AS_LOG_TABLE)
1176
pthread_mutex_lock(&share->mutex);
1177
share->is_log_table= TRUE;
1178
pthread_mutex_unlock(&share->mutex);
1115
1190
if (closest_hole == chain_ptr) /* no more chains */
1116
1191
*end_pos= file_buff->end();
1118
*end_pos= std::min(file_buff->end(),
1119
closest_hole->begin);
1193
*end_pos= min(file_buff->end(),
1194
closest_hole->begin);
1120
1195
return (closest_hole != chain_ptr) && (*end_pos == closest_hole->begin);
1132
1207
char updated_fname[FN_REFLEN];
1133
1208
off_t file_buffer_start= 0;
1209
DBUG_ENTER("ha_tina::rnd_end");
1135
1211
free_root(&blobroot, MYF(0));
1136
1212
records_is_known= 1;
1157
1233
/* create the file to write updated table if it wasn't yet created */
1158
1234
if (open_update_temp_file_if_needed())
1161
1237
/* write the file with updated info */
1162
1238
while ((file_buffer_start != -1)) // while not end of file
1168
1244
if (write_length)
1170
1246
if (my_write(update_temp_file,
1171
(unsigned char*) (file_buff->ptr() +
1247
(uchar*) (file_buff->ptr() +
1172
1248
(write_begin - file_buff->start())),
1173
1249
write_length, MYF_RW))
1193
1269
if (my_sync(update_temp_file, MYF(MY_WME)) ||
1194
1270
my_close(update_temp_file, MYF(0)))
1197
share->update_file_opened= false;
1273
share->update_file_opened= FALSE;
1199
1275
if (share->tina_write_opened)
1201
1277
if (my_close(share->tina_write_filedes, MYF(0)))
1204
1280
Mark that the writer fd is closed, so that init_tina_writer()
1205
1281
will reopen it later.
1207
share->tina_write_opened= false;
1283
share->tina_write_opened= FALSE;
1215
1291
my_rename(fn_format(updated_fname, share->table_name, "", CSN_EXT,
1216
1292
MY_REPLACE_EXT | MY_UNPACK_FILENAME),
1217
1293
share->data_file_name, MYF(0)))
1220
1296
/* Open the file again */
1221
1297
if (((data_file= my_open(share->data_file_name, O_RDONLY, MYF(0))) == -1))
1224
1300
As we reopened the data file, increase share->data_file_version
1225
1301
in order to force other threads waiting on a table lock and
1235
1311
closed, so nothing worrying will happen to it in case of a crash.
1236
1312
Here we record this fact to the meta-file.
1238
(void)write_meta_file(share->meta_file, share->rows_recorded, false);
1314
(void)write_meta_file(share->meta_file, share->rows_recorded, FALSE);
1240
1316
Update local_saved_data_file_length with the real length of the
1243
1319
local_saved_data_file_length= temp_file_length;
1248
1324
my_close(update_temp_file, MYF(0));
1249
share->update_file_opened= false;
1325
share->update_file_opened= FALSE;
1272
1348
int ha_tina::repair(THD* thd,
1273
HA_CHECK_OPT* check_opt __attribute__((unused)))
1349
HA_CHECK_OPT* check_opt __attribute__((__unused__)))
1275
1351
char repaired_fname[FN_REFLEN];
1277
1353
File repair_file;
1279
1355
ha_rows rows_repaired= 0;
1280
1356
off_t write_begin= 0, write_end;
1357
DBUG_ENTER("ha_tina::repair");
1282
1359
/* empty file */
1283
1360
if (!share->saved_data_file_length)
1289
1366
/* Don't assert in field::val() functions */
1290
1367
table->use_all_columns();
1291
if (!(buf= (unsigned char*) my_malloc(table->s->reclength, MYF(MY_WME))))
1292
return(HA_ERR_OUT_OF_MEM);
1368
if (!(buf= (uchar*) my_malloc(table->s->reclength, MYF(MY_WME))))
1369
DBUG_RETURN(HA_ERR_OUT_OF_MEM);
1294
1371
/* position buffer to the start of the file */
1295
1372
if (init_data_file())
1296
return(HA_ERR_CRASHED_ON_REPAIR);
1373
DBUG_RETURN(HA_ERR_CRASHED_ON_REPAIR);
1299
1376
Local_saved_data_file_length is initialized during the lock phase.
1338
1415
MY_REPLACE_EXT|MY_UNPACK_FILENAME),
1339
1416
0, O_RDWR | O_TRUNC,MYF(MY_WME))) < 0)
1340
return(HA_ERR_CRASHED_ON_REPAIR);
1417
DBUG_RETURN(HA_ERR_CRASHED_ON_REPAIR);
1342
1419
file_buff->init_buff(data_file);
1348
1425
/* write repaired file */
1351
write_end= std::min(file_buff->end(), current_position);
1428
write_end= min(file_buff->end(), current_position);
1352
1429
if ((write_end - write_begin) &&
1353
(my_write(repair_file, (unsigned char*)file_buff->ptr(),
1430
(my_write(repair_file, (uchar*)file_buff->ptr(),
1354
1431
write_end - write_begin, MYF_RW)))
1357
1434
write_begin= write_end;
1358
1435
if (write_end== current_position)
1370
1447
if (my_close(data_file,MYF(0)) || my_close(repair_file, MYF(0)) ||
1371
1448
my_rename(repaired_fname, share->data_file_name, MYF(0)))
1374
1451
/* Open the file again, it should now be repaired */
1375
1452
if ((data_file= my_open(share->data_file_name, O_RDWR|O_APPEND,
1376
1453
MYF(0))) == -1)
1379
1456
/* Set new file size. The file size will be updated by ::update_status() */
1380
1457
local_saved_data_file_length= (size_t) current_position;
1383
share->crashed= false;
1384
return(HA_ADMIN_OK);
1460
share->crashed= FALSE;
1461
DBUG_RETURN(HA_ADMIN_OK);
1391
1468
int ha_tina::delete_all_rows()
1471
DBUG_ENTER("ha_tina::delete_all_rows");
1395
1473
if (!records_is_known)
1396
return(my_errno=HA_ERR_WRONG_COMMAND);
1474
DBUG_RETURN(my_errno=HA_ERR_WRONG_COMMAND);
1398
1476
if (!share->tina_write_opened)
1399
1477
if (init_tina_writer())
1402
1480
/* Truncate the file to zero size */
1403
1481
rc= ftruncate(share->tina_write_filedes, 0);
1408
1486
share->rows_recorded= 0;
1409
1487
pthread_mutex_unlock(&share->mutex);
1410
1488
local_saved_data_file_length= 0;
1415
1493
Called by the database to lock the table. Keep in mind that this
1416
1494
is an internal lock.
1418
THR_LOCK_DATA **ha_tina::store_lock(THD *thd __attribute__((unused)),
1496
THR_LOCK_DATA **ha_tina::store_lock(THD *thd __attribute__((__unused__)),
1419
1497
THR_LOCK_DATA **to,
1420
1498
enum thr_lock_type lock_type)
1430
1508
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)))
1511
int ha_tina::create(const char *name, TABLE *table_arg,
1512
HA_CREATE_INFO *create_info __attribute__((__unused__)))
1436
1514
char name_buff[FN_REFLEN];
1437
1515
File create_file;
1516
DBUG_ENTER("ha_tina::create");
1444
1523
if ((*field)->real_maybe_null())
1446
1525
my_error(ER_CHECK_NOT_IMPLEMENTED, MYF(0), "nullable columns");
1447
return(HA_ERR_UNSUPPORTED);
1526
DBUG_RETURN(HA_ERR_UNSUPPORTED);
1452
1531
if ((create_file= my_create(fn_format(name_buff, name, "", CSM_EXT,
1453
1532
MY_REPLACE_EXT|MY_UNPACK_FILENAME), 0,
1454
1533
O_RDWR | O_TRUNC,MYF(MY_WME))) < 0)
1457
write_meta_file(create_file, 0, false);
1536
write_meta_file(create_file, 0, FALSE);
1458
1537
my_close(create_file, MYF(0));
1460
1539
if ((create_file= my_create(fn_format(name_buff, name, "", CSV_EXT,
1461
1540
MY_REPLACE_EXT|MY_UNPACK_FILENAME),0,
1462
1541
O_RDWR | O_TRUNC,MYF(MY_WME))) < 0)
1465
1544
my_close(create_file, MYF(0));
1470
1549
int ha_tina::check(THD* thd,
1471
HA_CHECK_OPT* check_opt __attribute__((unused)))
1550
HA_CHECK_OPT* check_opt __attribute__((__unused__)))
1475
1554
const char *old_proc_info;
1476
1555
ha_rows count= share->rows_recorded;
1556
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);
1558
old_proc_info= thd_proc_info(thd, "Checking table");
1559
if (!(buf= (uchar*) my_malloc(table->s->reclength, MYF(MY_WME))))
1560
DBUG_RETURN(HA_ERR_OUT_OF_MEM);
1483
1562
/* position buffer to the start of the file */
1484
1563
if (init_data_file())
1485
return(HA_ERR_CRASHED);
1564
DBUG_RETURN(HA_ERR_CRASHED);
1488
1567
Local_saved_data_file_length is initialized during the lock phase.
1506
1585
free_root(&blobroot, MYF(0));
1509
set_thd_proc_info(thd, old_proc_info);
1587
my_free((char*)buf, MYF(0));
1588
thd_proc_info(thd, old_proc_info);
1511
1590
if ((rc != HA_ERR_END_OF_FILE) || count)
1513
share->crashed= true;
1514
return(HA_ADMIN_CORRUPT);
1592
share->crashed= TRUE;
1593
DBUG_RETURN(HA_ADMIN_CORRUPT);
1517
return(HA_ADMIN_OK);
1596
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)))
1600
bool ha_tina::check_if_incompatible_data(HA_CREATE_INFO *info __attribute__((__unused__)),
1601
uint table_changes __attribute__((__unused__)))
1524
1603
return COMPATIBLE_DATA_YES;
1606
struct st_mysql_storage_engine csv_storage_engine=
1607
{ MYSQL_HANDLERTON_INTERFACE_VERSION };
1527
1609
mysql_declare_plugin(csv)
1529
DRIZZLE_STORAGE_ENGINE_PLUGIN,
1611
MYSQL_STORAGE_ENGINE_PLUGIN,
1612
&csv_storage_engine,
1532
1614
"Brian Aker, MySQL AB",
1533
1615
"CSV storage engine",
1534
1616
PLUGIN_LICENSE_GPL,
1535
1617
tina_init_func, /* Plugin Init */
1536
1618
tina_done_func, /* Plugin Deinit */
1537
1620
NULL, /* status variables */
1538
1621
NULL, /* system variables */
1539
1622
NULL /* config options */