~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to storage/csv/ha_tina.cc

Removed SCCS references.

Show diffs side-by-side

added added

removed removed

Lines of Context:
40
40
 
41
41
 -Brian
42
42
*/
43
 
#include <drizzled/common_includes.h>
 
43
 
 
44
#ifdef USE_PRAGMA_IMPLEMENTATION
 
45
#pragma implementation        // gcc: Class implementation
 
46
#endif
 
47
 
 
48
#include "mysql_priv.h"
 
49
#include <mysql/plugin.h>
44
50
#include "ha_tina.h"
45
51
 
46
52
 
47
53
/*
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
49
55
*/
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
54
60
 
58
64
#define CSM_EXT ".CSM"               // Meta file
59
65
 
60
66
 
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);
65
71
 
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);
69
75
 
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 ) );
92
98
}
93
99
 
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)))
96
102
{
97
103
  *length=share->table_name_length;
98
 
  return (unsigned char*) share->table_name;
 
104
  return (uchar*) share->table_name;
99
105
}
100
106
 
101
107
static int tina_init_func(void *p)
103
109
  handlerton *tina_hton;
104
110
 
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);
113
120
  return 0;
114
121
}
115
122
 
116
 
static int tina_done_func(void *p __attribute__((unused)))
 
123
static int tina_done_func(void *p)
117
124
{
118
125
  hash_free(&tina_open_tables);
119
126
  pthread_mutex_destroy(&tina_mutex);
125
132
/*
126
133
  Simple lock controls.
127
134
*/
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)
130
136
{
131
137
  TINA_SHARE *share;
132
138
  char meta_file_name[FN_REFLEN];
133
139
  struct stat file_stat;
134
140
  char *tmp_name;
135
 
  uint32_t length;
 
141
  uint length;
136
142
 
137
143
  pthread_mutex_lock(&tina_mutex);
138
144
  length=(uint) strlen(table_name);
142
148
    initialize its members.
143
149
  */
144
150
  if (!(share=(TINA_SHARE*) hash_search(&tina_open_tables,
145
 
                                        (unsigned char*) table_name,
 
151
                                        (uchar*) table_name,
146
152
                                       length)))
147
153
  {
148
154
    if (!my_multi_malloc(MYF(MY_WME | MY_ZEROFILL),
149
155
                         &share, sizeof(*share),
150
156
                         &tmp_name, length+1,
151
 
                         NULL))
 
157
                         NullS))
152
158
    {
153
159
      pthread_mutex_unlock(&tina_mutex);
154
160
      return NULL;
155
161
    }
156
162
 
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,
172
179
      goto error;
173
180
    share->saved_data_file_length= file_stat.st_size;
174
181
 
175
 
    if (my_hash_insert(&tina_open_tables, (unsigned char*) share))
 
182
    if (my_hash_insert(&tina_open_tables, (uchar*) share))
176
183
      goto error;
177
184
    thr_lock_init(&share->lock);
178
185
    pthread_mutex_init(&share->mutex,MY_MUTEX_INIT_FAST);
185
192
    */
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;
189
196
 
190
197
    /*
191
198
      If the meta file will not open we assume it is crashed and
192
199
      mark it as such.
193
200
    */
194
201
    if (read_meta_file(share->meta_file, &share->rows_recorded))
195
 
      share->crashed= true;
 
202
      share->crashed= TRUE;
196
203
  }
197
204
  share->use_count++;
198
205
  pthread_mutex_unlock(&tina_mutex);
201
208
 
202
209
error:
203
210
  pthread_mutex_unlock(&tina_mutex);
204
 
  free((unsigned char*) share);
 
211
  my_free((uchar*) share, MYF(0));
205
212
 
206
213
  return NULL;
207
214
}
228
235
 
229
236
static int read_meta_file(File meta_file, ha_rows *rows)
230
237
{
231
 
  unsigned char meta_buffer[META_BUFFER_SIZE];
232
 
  unsigned char *ptr= meta_buffer;
233
 
 
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;
 
240
 
 
241
  DBUG_ENTER("ha_tina::read_meta_file");
 
242
 
 
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);
238
247
 
239
248
  /*
240
249
    Parse out the meta data, we ignore version at the moment
241
250
  */
242
251
 
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
246
255
  /*
250
259
  ptr+= 3*sizeof(uint64_t);
251
260
 
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);
256
265
 
257
266
  my_sync(meta_file, MYF(MY_WME));
258
267
 
259
 
  return(0);
 
268
  DBUG_RETURN(0);
260
269
}
261
270
 
262
271
 
281
290
 
282
291
static int write_meta_file(File meta_file, ha_rows rows, bool dirty)
283
292
{
284
 
  unsigned char meta_buffer[META_BUFFER_SIZE];
285
 
  unsigned char *ptr= meta_buffer;
286
 
 
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;
 
295
 
 
296
  DBUG_ENTER("ha_tina::write_meta_file");
 
297
 
 
298
  *ptr= (uchar)TINA_CHECK_HEADER;
 
299
  ptr+= sizeof(uchar);
 
300
  *ptr= (uchar)TINA_VERSION;
 
301
  ptr+= sizeof(uchar);
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.
297
308
  */
298
309
  ptr+= 3*sizeof(uint64_t);
299
 
  *ptr= (unsigned char)dirty;
 
310
  *ptr= (uchar)dirty;
300
311
 
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)
304
 
    return(-1);
 
315
    DBUG_RETURN(-1);
305
316
 
306
317
  my_sync(meta_file, MYF(MY_WME));
307
318
 
308
 
  return(0);
 
319
  DBUG_RETURN(0);
309
320
}
310
321
 
311
322
bool ha_tina::check_and_repair(THD *thd)
312
323
{
313
324
  HA_CHECK_OPT check_opt;
 
325
  DBUG_ENTER("ha_tina::check_and_repair");
314
326
 
315
327
  check_opt.init();
316
328
 
317
 
  return(repair(thd, &check_opt));
 
329
  DBUG_RETURN(repair(thd, &check_opt));
318
330
}
319
331
 
320
332
 
321
333
int ha_tina::init_tina_writer()
322
334
{
 
335
  DBUG_ENTER("ha_tina::init_tina_writer");
 
336
 
323
337
  /*
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.
327
341
  */
328
 
  (void)write_meta_file(share->meta_file, share->rows_recorded, true);
 
342
  (void)write_meta_file(share->meta_file, share->rows_recorded, TRUE);
329
343
 
330
344
  if ((share->tina_write_filedes=
331
345
        my_open(share->data_file_name, O_RDWR|O_APPEND, MYF(0))) == -1)
332
346
  {
333
 
    share->crashed= true;
334
 
    return(1);
 
347
    DBUG_PRINT("info", ("Could not open tina file writes"));
 
348
    share->crashed= TRUE;
 
349
    DBUG_RETURN(1);
335
350
  }
336
 
  share->tina_write_opened= true;
 
351
  share->tina_write_opened= TRUE;
337
352
 
338
 
  return(0);
 
353
  DBUG_RETURN(0);
339
354
}
340
355
 
341
356
 
342
357
bool ha_tina::is_crashed() const
343
358
{
344
 
  return(share->crashed);
 
359
  DBUG_ENTER("ha_tina::is_crashed");
 
360
  DBUG_RETURN(share->crashed);
345
361
}
346
362
 
347
363
/*
349
365
*/
350
366
static int free_share(TINA_SHARE *share)
351
367
{
 
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)))
359
376
      result_code= 1;
360
377
    if (share->tina_write_opened)
361
378
    {
362
379
      if (my_close(share->tina_write_filedes, MYF(0)))
363
380
        result_code= 1;
364
 
      share->tina_write_opened= false;
 
381
      share->tina_write_opened= FALSE;
365
382
    }
366
383
 
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));
371
388
  }
372
389
  pthread_mutex_unlock(&tina_mutex);
373
390
 
374
 
  return(result_code);
 
391
  DBUG_RETURN(result_code);
375
392
}
376
393
 
377
394
 
442
459
  Encode a buffer into the quoted format.
443
460
*/
444
461
 
445
 
int ha_tina::encode_quote(unsigned char *buf __attribute__((unused)))
 
462
int ha_tina::encode_quote(uchar *buf)
446
463
{
447
464
  char attribute_buffer[1024];
448
465
  String attribute(attribute_buffer, sizeof(attribute_buffer),
449
466
                   &my_charset_bin);
450
467
 
 
468
  my_bitmap_map *org_bitmap= dbug_tmp_use_all_columns(table, table->read_set);
451
469
  buffer.length(0);
452
470
 
453
471
  for (Field **field=table->field ; *field ; field++)
522
540
 
523
541
  //buffer.replace(buffer.length(), 0, "\n", 1);
524
542
 
 
543
  dbug_tmp_restore_column_map(table->read_set, org_bitmap);
525
544
  return (buffer.length());
526
545
}
527
546
 
544
563
      if (chain_alloced)
545
564
      {
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)
549
568
          return -1;
550
569
      }
570
589
/*
571
590
  Scans for a row.
572
591
*/
573
 
int ha_tina::find_current_row(unsigned char *buf)
 
592
int ha_tina::find_current_row(uchar *buf)
574
593
{
575
594
  off_t end_offset, curr_offset= current_position;
576
595
  int eoln_len;
 
596
  my_bitmap_map *org_bitmap;
577
597
  int error;
578
598
  bool read_all;
 
599
  DBUG_ENTER("ha_tina::find_current_row");
579
600
 
580
601
  free_root(&blobroot, MYF(MY_MARK_BLOCKS_FREE));
581
602
 
586
607
  if ((end_offset=
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);
590
611
 
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;
594
617
 
595
618
  memset(buf, 0, table->s->null_bytes);
667
690
      if ((*field)->flags & BLOB_FLAG)
668
691
      {
669
692
        Field_blob *blob= *(Field_blob**) field;
670
 
        unsigned char *src, *tgt;
671
 
        uint32_t length, packlength;
 
693
        uchar *src, *tgt;
 
694
        uint length, packlength;
672
695
        
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*));
676
699
        if (src)
677
700
        {
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*));
681
704
        }
682
705
      }
683
706
    }
686
709
  error= 0;
687
710
 
688
711
err:
 
712
  dbug_tmp_restore_column_map(table->write_set, org_bitmap);
689
713
 
690
 
  return(error);
 
714
  DBUG_RETURN(error);
691
715
}
692
716
 
693
717
/*
697
721
static const char *ha_tina_exts[] = {
698
722
  CSV_EXT,
699
723
  CSM_EXT,
700
 
  NULL
 
724
  NullS
701
725
};
702
726
 
703
727
const char **ha_tina::bas_ext() const
710
734
  for CSV engine. For more details see mysys/thr_lock.c
711
735
*/
712
736
 
713
 
void tina_get_status(void* param,
714
 
                     int concurrent_insert __attribute__((unused)))
 
737
void tina_get_status(void* param, int concurrent_insert)
715
738
{
716
739
  ha_tina *tina= (ha_tina*) param;
717
740
  tina->get_status();
724
747
}
725
748
 
726
749
/* this should exist and return 0 for concurrent insert to work */
727
 
bool tina_check_status(void* param __attribute__((unused)))
 
750
my_bool tina_check_status(void* param)
728
751
{
729
752
  return 0;
730
753
}
743
766
 
744
767
void ha_tina::get_status()
745
768
{
 
769
  if (share->is_log_table)
 
770
  {
 
771
    /*
 
772
      We have to use mutex to follow pthreads memory visibility
 
773
      rules for share->saved_data_file_length
 
774
    */
 
775
    pthread_mutex_lock(&share->mutex);
 
776
    local_saved_data_file_length= share->saved_data_file_length;
 
777
    pthread_mutex_unlock(&share->mutex);
 
778
    return;
 
779
  }
746
780
  local_saved_data_file_length= share->saved_data_file_length;
747
781
}
748
782
 
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
767
 
    way. 
 
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.
768
803
*/
769
804
 
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.
781
816
*/
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)
784
818
{
 
819
  DBUG_ENTER("ha_tina::open");
 
820
 
785
821
  if (!(share= get_share(name, table)))
786
 
    return(HA_ERR_OUT_OF_MEM);
 
822
    DBUG_RETURN(HA_ERR_OUT_OF_MEM);
787
823
 
788
824
  if (share->crashed && !(open_options & HA_OPEN_FOR_REPAIR))
789
825
  {
790
826
    free_share(share);
791
 
    return(HA_ERR_CRASHED_ON_USAGE);
 
827
    DBUG_RETURN(HA_ERR_CRASHED_ON_USAGE);
792
828
  }
793
829
 
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)
796
 
    return(0);
 
832
    DBUG_RETURN(0);
797
833
 
798
834
  /*
799
835
    Init locking. Pass handler object to the locking routines,
807
843
  share->lock.update_status= tina_update_status;
808
844
  share->lock.check_status= tina_check_status;
809
845
 
810
 
  return(0);
 
846
  DBUG_RETURN(0);
811
847
}
812
848
 
813
849
 
818
854
int ha_tina::close(void)
819
855
{
820
856
  int rc= 0;
 
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);
823
860
}
824
861
 
825
862
/*
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).
829
866
*/
830
 
int ha_tina::write_row(unsigned char * buf)
 
867
int ha_tina::write_row(uchar * buf)
831
868
{
832
869
  int size;
 
870
  DBUG_ENTER("ha_tina::write_row");
833
871
 
834
872
  if (share->crashed)
835
 
      return(HA_ERR_CRASHED_ON_USAGE);
 
873
      DBUG_RETURN(HA_ERR_CRASHED_ON_USAGE);
836
874
 
837
875
  ha_statistic_increment(&SSV::ha_write_count);
838
876
 
843
881
 
844
882
  if (!share->tina_write_opened)
845
883
    if (init_tina_writer())
846
 
      return(-1);
 
884
      DBUG_RETURN(-1);
847
885
 
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)))
851
 
    return(-1);
 
889
    DBUG_RETURN(-1);
852
890
 
853
891
  /* update local copy of the max position to see our own changes */
854
892
  local_saved_data_file_length+= size;
857
895
  pthread_mutex_lock(&share->mutex);
858
896
  share->rows_recorded++;
859
897
  /* update status for the log tables */
 
898
  if (share->is_log_table)
 
899
    update_status();
860
900
  pthread_mutex_unlock(&share->mutex);
861
901
 
862
902
  stats.records++;
863
 
  return(0);
 
903
  DBUG_RETURN(0);
864
904
}
865
905
 
866
906
 
876
916
                               MY_REPLACE_EXT | MY_UNPACK_FILENAME),
877
917
                     0, O_RDWR | O_TRUNC, MYF(MY_WME))) < 0)
878
918
      return 1;
879
 
    share->update_file_opened= true;
 
919
    share->update_file_opened= TRUE;
880
920
    temp_file_length= 0;
881
921
  }
882
922
  return 0;
890
930
  This will be called in a table scan right before the previous ::rnd_next()
891
931
  call.
892
932
*/
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)
895
934
{
896
935
  int size;
897
936
  int rc= -1;
 
937
  DBUG_ENTER("ha_tina::update_row");
898
938
 
899
939
  ha_statistic_increment(&SSV::ha_update_count);
900
940
 
916
956
  if (open_update_temp_file_if_needed())
917
957
    goto err;
918
958
 
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)))
921
961
    goto err;
922
962
  temp_file_length+= size;
923
963
  rc= 0;
924
964
 
 
965
  /* UPDATE should never happen on the log tables */
 
966
  DBUG_ASSERT(!share->is_log_table);
 
967
 
925
968
err:
926
 
  return(rc);
 
969
  DBUG_PRINT("info",("rc = %d", rc));
 
970
  DBUG_RETURN(rc);
927
971
}
928
972
 
929
973
 
936
980
  The table will then be deleted/positioned based on the ORDER (so RANDOM,
937
981
  DESC, ASC).
938
982
*/
939
 
int ha_tina::delete_row(const unsigned char * buf __attribute__((unused)))
 
983
int ha_tina::delete_row(const uchar * buf)
940
984
{
 
985
  DBUG_ENTER("ha_tina::delete_row");
941
986
  ha_statistic_increment(&SSV::ha_delete_count);
942
987
 
943
988
  if (chain_append())
944
 
    return(-1);
 
989
    DBUG_RETURN(-1);
945
990
 
946
991
  stats.records--;
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);
952
997
 
953
 
  return(0);
 
998
  /* DELETE should never happen on the log table */
 
999
  DBUG_ASSERT(!share->is_log_table);
 
1000
 
 
1001
  DBUG_RETURN(0);
954
1002
}
955
1003
 
956
1004
 
1012
1060
 
1013
1061
*/
1014
1062
 
1015
 
int ha_tina::rnd_init(bool scan __attribute__((unused)))
 
1063
int ha_tina::rnd_init(bool scan)
1016
1064
{
 
1065
  DBUG_ENTER("ha_tina::rnd_init");
 
1066
 
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);
1020
1070
 
1021
1071
  current_position= next_position= 0;
1022
1072
  stats.records= 0;
1025
1075
 
1026
1076
  init_alloc_root(&blobroot, BLOB_MEMROOT_ALLOC_SIZE, 0);
1027
1077
 
1028
 
  return(0);
 
1078
  DBUG_RETURN(0);
1029
1079
}
1030
1080
 
1031
1081
/*
1042
1092
  NULL and "". This is ok since this table handler is for spreadsheets and
1043
1093
  they don't know about them either :)
1044
1094
*/
1045
 
int ha_tina::rnd_next(unsigned char *buf)
 
1095
int ha_tina::rnd_next(uchar *buf)
1046
1096
{
1047
1097
  int rc;
 
1098
  DBUG_ENTER("ha_tina::rnd_next");
1048
1099
 
1049
1100
  if (share->crashed)
1050
 
      return(HA_ERR_CRASHED_ON_USAGE);
 
1101
      DBUG_RETURN(HA_ERR_CRASHED_ON_USAGE);
1051
1102
 
1052
1103
  ha_statistic_increment(&SSV::ha_read_rnd_next_count);
1053
1104
 
1055
1106
 
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);
1059
1110
 
1060
1111
  if ((rc= find_current_row(buf)))
1061
 
    return(rc);
 
1112
    DBUG_RETURN(rc);
1062
1113
 
1063
1114
  stats.records++;
1064
 
  return(0);
 
1115
  DBUG_RETURN(0);
1065
1116
}
1066
1117
 
1067
1118
/*
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.
1075
1126
*/
1076
 
void ha_tina::position(const unsigned char *record __attribute__((unused)))
 
1127
void ha_tina::position(const uchar *record)
1077
1128
{
 
1129
  DBUG_ENTER("ha_tina::position");
1078
1130
  my_store_ptr(ref, ref_length, current_position);
1079
 
  return;
 
1131
  DBUG_VOID_RETURN;
1080
1132
}
1081
1133
 
1082
1134
 
1085
1137
  my_get_ptr() retrieves the data for you.
1086
1138
*/
1087
1139
 
1088
 
int ha_tina::rnd_pos(unsigned char * buf, unsigned char *pos)
 
1140
int ha_tina::rnd_pos(uchar * buf, uchar *pos)
1089
1141
{
 
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));
1093
1146
}
1094
1147
 
1095
1148
/*
1097
1150
  Currently this table handler doesn't implement most of the fields
1098
1151
  really needed. SHOW also makes use of this data
1099
1152
*/
1100
 
int ha_tina::info(uint32_t flag __attribute__((unused)))
 
1153
int ha_tina::info(uint flag)
1101
1154
{
 
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;
1105
 
  return(0);
 
1159
  DBUG_RETURN(0);
 
1160
}
 
1161
 
 
1162
/*
 
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.
 
1166
*/
 
1167
int ha_tina::extra(enum ha_extra_function operation)
 
1168
{
 
1169
  DBUG_ENTER("ha_tina::extra");
 
1170
 if (operation == HA_EXTRA_MARK_AS_LOG_TABLE)
 
1171
 {
 
1172
   pthread_mutex_lock(&share->mutex);
 
1173
   share->is_log_table= TRUE;
 
1174
   pthread_mutex_unlock(&share->mutex);
 
1175
 }
 
1176
  DBUG_RETURN(0);
1106
1177
}
1107
1178
 
1108
1179
/*
1115
1186
  if (closest_hole == chain_ptr) /* no more chains */
1116
1187
    *end_pos= file_buff->end();
1117
1188
  else
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);
1121
1192
}
1122
1193
 
1131
1202
{
1132
1203
  char updated_fname[FN_REFLEN];
1133
1204
  off_t file_buffer_start= 0;
 
1205
  DBUG_ENTER("ha_tina::rnd_end");
1134
1206
 
1135
1207
  free_root(&blobroot, MYF(0));
1136
1208
  records_is_known= 1;
1156
1228
 
1157
1229
    /* create the file to write updated table if it wasn't yet created */
1158
1230
    if (open_update_temp_file_if_needed())
1159
 
      return(-1);
 
1231
      DBUG_RETURN(-1);
1160
1232
 
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)
1169
1241
      {
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))
1174
1246
          goto error;
1192
1264
 
1193
1265
    if (my_sync(update_temp_file, MYF(MY_WME)) ||
1194
1266
        my_close(update_temp_file, MYF(0)))
1195
 
      return(-1);
 
1267
      DBUG_RETURN(-1);
1196
1268
 
1197
 
    share->update_file_opened= false;
 
1269
    share->update_file_opened= FALSE;
1198
1270
 
1199
1271
    if (share->tina_write_opened)
1200
1272
    {
1201
1273
      if (my_close(share->tina_write_filedes, MYF(0)))
1202
 
        return(-1);
 
1274
        DBUG_RETURN(-1);
1203
1275
      /*
1204
1276
        Mark that the writer fd is closed, so that init_tina_writer()
1205
1277
        will reopen it later.
1206
1278
      */
1207
 
      share->tina_write_opened= false;
 
1279
      share->tina_write_opened= FALSE;
1208
1280
    }
1209
1281
 
1210
1282
    /*
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)))
1218
 
      return(-1);
 
1290
      DBUG_RETURN(-1);
1219
1291
 
1220
1292
    /* Open the file again */
1221
1293
    if (((data_file= my_open(share->data_file_name, O_RDONLY, MYF(0))) == -1))
1222
 
      return(-1);
 
1294
      DBUG_RETURN(-1);
1223
1295
    /*
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.
1237
1309
    */
1238
 
    (void)write_meta_file(share->meta_file, share->rows_recorded, false);
 
1310
    (void)write_meta_file(share->meta_file, share->rows_recorded, FALSE);
1239
1311
    /* 
1240
1312
      Update local_saved_data_file_length with the real length of the 
1241
1313
      data file.
1243
1315
    local_saved_data_file_length= temp_file_length;
1244
1316
  }
1245
1317
 
1246
 
  return(0);
 
1318
  DBUG_RETURN(0);
1247
1319
error:
1248
1320
  my_close(update_temp_file, MYF(0));
1249
 
  share->update_file_opened= false;
1250
 
  return(-1);
 
1321
  share->update_file_opened= FALSE;
 
1322
  DBUG_RETURN(-1);
1251
1323
}
1252
1324
 
1253
1325
 
1269
1341
         rows (after the first bad one) as well.
1270
1342
*/
1271
1343
 
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)
1274
1345
{
1275
1346
  char repaired_fname[FN_REFLEN];
1276
 
  unsigned char *buf;
 
1347
  uchar *buf;
1277
1348
  File repair_file;
1278
1349
  int rc;
1279
1350
  ha_rows rows_repaired= 0;
1280
1351
  off_t write_begin= 0, write_end;
 
1352
  DBUG_ENTER("ha_tina::repair");
1281
1353
 
1282
1354
  /* empty file */
1283
1355
  if (!share->saved_data_file_length)
1288
1360
 
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);
1293
1365
 
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);
1297
1369
 
1298
1370
  /*
1299
1371
    Local_saved_data_file_length is initialized during the lock phase.
1316
1388
 
1317
1389
  free_root(&blobroot, MYF(0));
1318
1390
 
1319
 
  free((char*)buf);
 
1391
  my_free((char*)buf, MYF(0));
1320
1392
 
1321
1393
  if (rc == HA_ERR_END_OF_FILE)
1322
1394
  {
1337
1409
                                        "", CSN_EXT,
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);
1341
1413
 
1342
1414
  file_buff->init_buff(data_file);
1343
1415
 
1348
1420
  /* write repaired file */
1349
1421
  while (1)
1350
1422
  {
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)))
1355
 
      return(-1);
 
1427
      DBUG_RETURN(-1);
1356
1428
 
1357
1429
    write_begin= write_end;
1358
1430
    if (write_end== current_position)
1369
1441
  */
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)))
1372
 
    return(-1);
 
1444
    DBUG_RETURN(-1);
1373
1445
 
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)
1377
 
     return(-1);
 
1449
     DBUG_RETURN(-1);
1378
1450
 
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;
1381
1453
 
1382
1454
end:
1383
 
  share->crashed= false;
1384
 
  return(HA_ADMIN_OK);
 
1455
  share->crashed= FALSE;
 
1456
  DBUG_RETURN(HA_ADMIN_OK);
1385
1457
}
1386
1458
 
1387
1459
/*
1391
1463
int ha_tina::delete_all_rows()
1392
1464
{
1393
1465
  int rc;
 
1466
  DBUG_ENTER("ha_tina::delete_all_rows");
1394
1467
 
1395
1468
  if (!records_is_known)
1396
 
    return(my_errno=HA_ERR_WRONG_COMMAND);
 
1469
    DBUG_RETURN(my_errno=HA_ERR_WRONG_COMMAND);
1397
1470
 
1398
1471
  if (!share->tina_write_opened)
1399
1472
    if (init_tina_writer())
1400
 
      return(-1);
 
1473
      DBUG_RETURN(-1);
1401
1474
 
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));
1404
1477
 
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;
1411
 
  return(rc);
 
1484
  DBUG_RETURN(rc);
1412
1485
}
1413
1486
 
1414
1487
/*
1415
1488
  Called by the database to lock the table. Keep in mind that this
1416
1489
  is an internal lock.
1417
1490
*/
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)
1421
1494
{
1430
1503
  this (the database will call ::open() if it needs to).
1431
1504
*/
1432
1505
 
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)
1435
1508
{
1436
1509
  char name_buff[FN_REFLEN];
1437
1510
  File create_file;
 
1511
  DBUG_ENTER("ha_tina::create");
1438
1512
 
1439
1513
  /*
1440
1514
    check columns
1444
1518
    if ((*field)->real_maybe_null())
1445
1519
    {
1446
1520
      my_error(ER_CHECK_NOT_IMPLEMENTED, MYF(0), "nullable columns");
1447
 
      return(HA_ERR_UNSUPPORTED);
 
1521
      DBUG_RETURN(HA_ERR_UNSUPPORTED);
1448
1522
    }
1449
1523
  }
1450
1524
  
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)
1455
 
    return(-1);
 
1529
    DBUG_RETURN(-1);
1456
1530
 
1457
 
  write_meta_file(create_file, 0, false);
 
1531
  write_meta_file(create_file, 0, FALSE);
1458
1532
  my_close(create_file, MYF(0));
1459
1533
 
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)
1463
 
    return(-1);
 
1537
    DBUG_RETURN(-1);
1464
1538
 
1465
1539
  my_close(create_file, MYF(0));
1466
1540
 
1467
 
  return(0);
 
1541
  DBUG_RETURN(0);
1468
1542
}
1469
1543
 
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)
1472
1545
{
1473
1546
  int rc= 0;
1474
 
  unsigned char *buf;
 
1547
  uchar *buf;
1475
1548
  const char *old_proc_info;
1476
1549
  ha_rows count= share->rows_recorded;
 
1550
  DBUG_ENTER("ha_tina::check");
1477
1551
 
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);
1482
1555
 
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);
1486
1559
 
1487
1560
  /*
1488
1561
    Local_saved_data_file_length is initialized during the lock phase.
1505
1578
  
1506
1579
  free_root(&blobroot, MYF(0));
1507
1580
 
1508
 
  free((char*)buf);
1509
 
  set_thd_proc_info(thd, old_proc_info);
 
1581
  my_free((char*)buf, MYF(0));
 
1582
  thd_proc_info(thd, old_proc_info);
1510
1583
 
1511
1584
  if ((rc != HA_ERR_END_OF_FILE) || count)
1512
1585
  {
1513
 
    share->crashed= true;
1514
 
    return(HA_ADMIN_CORRUPT);
 
1586
    share->crashed= TRUE;
 
1587
    DBUG_RETURN(HA_ADMIN_CORRUPT);
1515
1588
  }
1516
1589
  else
1517
 
    return(HA_ADMIN_OK);
 
1590
    DBUG_RETURN(HA_ADMIN_OK);
1518
1591
}
1519
1592
 
1520
1593
 
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,
 
1595
                                           uint table_changes)
1523
1596
{
1524
1597
  return COMPATIBLE_DATA_YES;
1525
1598
}
1526
1599
 
 
1600
struct st_mysql_storage_engine csv_storage_engine=
 
1601
{ MYSQL_HANDLERTON_INTERFACE_VERSION };
 
1602
 
1527
1603
mysql_declare_plugin(csv)
1528
1604
{
1529
 
  DRIZZLE_STORAGE_ENGINE_PLUGIN,
 
1605
  MYSQL_STORAGE_ENGINE_PLUGIN,
 
1606
  &csv_storage_engine,
1530
1607
  "CSV",
1531
 
  "1.0",
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 */
 
1613
  0x0100 /* 1.0 */,
1537
1614
  NULL,                       /* status variables                */
1538
1615
  NULL,                       /* system variables                */
1539
1616
  NULL                        /* config options                  */