~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to storage/csv/ha_tina.cc

Removed DBUG symbols and fixed TRUE/FALSE

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 __attribute__((__unused__)))
117
124
{
118
125
  hash_free(&tina_open_tables);
119
126
  pthread_mutex_destroy(&tina_mutex);
126
133
  Simple lock controls.
127
134
*/
128
135
static TINA_SHARE *get_share(const char *table_name,
129
 
                             Table *table __attribute__((unused)))
 
136
                             TABLE *table __attribute__((__unused__)))
130
137
{
131
138
  TINA_SHARE *share;
132
139
  char meta_file_name[FN_REFLEN];
133
140
  struct stat file_stat;
134
141
  char *tmp_name;
135
 
  uint32_t length;
 
142
  uint length;
136
143
 
137
144
  pthread_mutex_lock(&tina_mutex);
138
145
  length=(uint) strlen(table_name);
142
149
    initialize its members.
143
150
  */
144
151
  if (!(share=(TINA_SHARE*) hash_search(&tina_open_tables,
145
 
                                        (unsigned char*) table_name,
 
152
                                        (uchar*) table_name,
146
153
                                       length)))
147
154
  {
148
155
    if (!my_multi_malloc(MYF(MY_WME | MY_ZEROFILL),
149
156
                         &share, sizeof(*share),
150
157
                         &tmp_name, length+1,
151
 
                         NULL))
 
158
                         NullS))
152
159
    {
153
160
      pthread_mutex_unlock(&tina_mutex);
154
161
      return NULL;
155
162
    }
156
163
 
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,
172
180
      goto error;
173
181
    share->saved_data_file_length= file_stat.st_size;
174
182
 
175
 
    if (my_hash_insert(&tina_open_tables, (unsigned char*) share))
 
183
    if (my_hash_insert(&tina_open_tables, (uchar*) share))
176
184
      goto error;
177
185
    thr_lock_init(&share->lock);
178
186
    pthread_mutex_init(&share->mutex,MY_MUTEX_INIT_FAST);
185
193
    */
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;
189
197
 
190
198
    /*
191
199
      If the meta file will not open we assume it is crashed and
192
200
      mark it as such.
193
201
    */
194
202
    if (read_meta_file(share->meta_file, &share->rows_recorded))
195
 
      share->crashed= true;
 
203
      share->crashed= TRUE;
196
204
  }
197
205
  share->use_count++;
198
206
  pthread_mutex_unlock(&tina_mutex);
201
209
 
202
210
error:
203
211
  pthread_mutex_unlock(&tina_mutex);
204
 
  free((unsigned char*) share);
 
212
  my_free((uchar*) share, MYF(0));
205
213
 
206
214
  return NULL;
207
215
}
228
236
 
229
237
static int read_meta_file(File meta_file, ha_rows *rows)
230
238
{
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)
 
239
  uchar meta_buffer[META_BUFFER_SIZE];
 
240
  uchar *ptr= meta_buffer;
 
241
 
 
242
  DBUG_ENTER("ha_tina::read_meta_file");
 
243
 
 
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);
238
248
 
239
249
  /*
240
250
    Parse out the meta data, we ignore version at the moment
241
251
  */
242
252
 
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
246
256
  /*
250
260
  ptr+= 3*sizeof(uint64_t);
251
261
 
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);
256
266
 
257
267
  my_sync(meta_file, MYF(MY_WME));
258
268
 
259
 
  return(0);
 
269
  DBUG_RETURN(0);
260
270
}
261
271
 
262
272
 
281
291
 
282
292
static int write_meta_file(File meta_file, ha_rows rows, bool dirty)
283
293
{
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);
 
294
  uchar meta_buffer[META_BUFFER_SIZE];
 
295
  uchar *ptr= meta_buffer;
 
296
 
 
297
  DBUG_ENTER("ha_tina::write_meta_file");
 
298
 
 
299
  *ptr= (uchar)TINA_CHECK_HEADER;
 
300
  ptr+= sizeof(uchar);
 
301
  *ptr= (uchar)TINA_VERSION;
 
302
  ptr+= sizeof(uchar);
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.
297
309
  */
298
310
  ptr+= 3*sizeof(uint64_t);
299
 
  *ptr= (unsigned char)dirty;
 
311
  *ptr= (uchar)dirty;
300
312
 
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)
304
 
    return(-1);
 
316
    DBUG_RETURN(-1);
305
317
 
306
318
  my_sync(meta_file, MYF(MY_WME));
307
319
 
308
 
  return(0);
 
320
  DBUG_RETURN(0);
309
321
}
310
322
 
311
323
bool ha_tina::check_and_repair(THD *thd)
312
324
{
313
325
  HA_CHECK_OPT check_opt;
 
326
  DBUG_ENTER("ha_tina::check_and_repair");
314
327
 
315
328
  check_opt.init();
316
329
 
317
 
  return(repair(thd, &check_opt));
 
330
  DBUG_RETURN(repair(thd, &check_opt));
318
331
}
319
332
 
320
333
 
321
334
int ha_tina::init_tina_writer()
322
335
{
 
336
  DBUG_ENTER("ha_tina::init_tina_writer");
 
337
 
323
338
  /*
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.
327
342
  */
328
 
  (void)write_meta_file(share->meta_file, share->rows_recorded, true);
 
343
  (void)write_meta_file(share->meta_file, share->rows_recorded, TRUE);
329
344
 
330
345
  if ((share->tina_write_filedes=
331
346
        my_open(share->data_file_name, O_RDWR|O_APPEND, MYF(0))) == -1)
332
347
  {
333
 
    share->crashed= true;
334
 
    return(1);
 
348
    DBUG_PRINT("info", ("Could not open tina file writes"));
 
349
    share->crashed= TRUE;
 
350
    DBUG_RETURN(1);
335
351
  }
336
 
  share->tina_write_opened= true;
 
352
  share->tina_write_opened= TRUE;
337
353
 
338
 
  return(0);
 
354
  DBUG_RETURN(0);
339
355
}
340
356
 
341
357
 
342
358
bool ha_tina::is_crashed() const
343
359
{
344
 
  return(share->crashed);
 
360
  DBUG_ENTER("ha_tina::is_crashed");
 
361
  DBUG_RETURN(share->crashed);
345
362
}
346
363
 
347
364
/*
349
366
*/
350
367
static int free_share(TINA_SHARE *share)
351
368
{
 
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)))
359
377
      result_code= 1;
360
378
    if (share->tina_write_opened)
361
379
    {
362
380
      if (my_close(share->tina_write_filedes, MYF(0)))
363
381
        result_code= 1;
364
 
      share->tina_write_opened= false;
 
382
      share->tina_write_opened= FALSE;
365
383
    }
366
384
 
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));
371
389
  }
372
390
  pthread_mutex_unlock(&tina_mutex);
373
391
 
374
 
  return(result_code);
 
392
  DBUG_RETURN(result_code);
375
393
}
376
394
 
377
395
 
442
460
  Encode a buffer into the quoted format.
443
461
*/
444
462
 
445
 
int ha_tina::encode_quote(unsigned char *buf __attribute__((unused)))
 
463
int ha_tina::encode_quote(uchar *buf __attribute__((__unused__)))
446
464
{
447
465
  char attribute_buffer[1024];
448
466
  String attribute(attribute_buffer, sizeof(attribute_buffer),
449
467
                   &my_charset_bin);
450
468
 
 
469
  my_bitmap_map *org_bitmap= dbug_tmp_use_all_columns(table, table->read_set);
451
470
  buffer.length(0);
452
471
 
453
472
  for (Field **field=table->field ; *field ; field++)
522
541
 
523
542
  //buffer.replace(buffer.length(), 0, "\n", 1);
524
543
 
 
544
  dbug_tmp_restore_column_map(table->read_set, org_bitmap);
525
545
  return (buffer.length());
526
546
}
527
547
 
544
564
      if (chain_alloced)
545
565
      {
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)
549
569
          return -1;
550
570
      }
570
590
/*
571
591
  Scans for a row.
572
592
*/
573
 
int ha_tina::find_current_row(unsigned char *buf)
 
593
int ha_tina::find_current_row(uchar *buf)
574
594
{
575
595
  off_t end_offset, curr_offset= current_position;
576
596
  int eoln_len;
 
597
  my_bitmap_map *org_bitmap;
577
598
  int error;
578
599
  bool read_all;
 
600
  DBUG_ENTER("ha_tina::find_current_row");
579
601
 
580
602
  free_root(&blobroot, MYF(MY_MARK_BLOCKS_FREE));
581
603
 
586
608
  if ((end_offset=
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);
590
612
 
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;
594
618
 
595
619
  memset(buf, 0, table->s->null_bytes);
667
691
      if ((*field)->flags & BLOB_FLAG)
668
692
      {
669
693
        Field_blob *blob= *(Field_blob**) field;
670
 
        unsigned char *src, *tgt;
671
 
        uint32_t length, packlength;
 
694
        uchar *src, *tgt;
 
695
        uint length, packlength;
672
696
        
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*));
676
700
        if (src)
677
701
        {
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*));
681
705
        }
682
706
      }
683
707
    }
686
710
  error= 0;
687
711
 
688
712
err:
 
713
  dbug_tmp_restore_column_map(table->write_set, org_bitmap);
689
714
 
690
 
  return(error);
 
715
  DBUG_RETURN(error);
691
716
}
692
717
 
693
718
/*
697
722
static const char *ha_tina_exts[] = {
698
723
  CSV_EXT,
699
724
  CSM_EXT,
700
 
  NULL
 
725
  NullS
701
726
};
702
727
 
703
728
const char **ha_tina::bas_ext() const
711
736
*/
712
737
 
713
738
void tina_get_status(void* param,
714
 
                     int concurrent_insert __attribute__((unused)))
 
739
                     int concurrent_insert __attribute__((__unused__)))
715
740
{
716
741
  ha_tina *tina= (ha_tina*) param;
717
742
  tina->get_status();
724
749
}
725
750
 
726
751
/* this should exist and return 0 for concurrent insert to work */
727
 
bool tina_check_status(void* param __attribute__((unused)))
 
752
my_bool tina_check_status(void* param __attribute__((__unused__)))
728
753
{
729
754
  return 0;
730
755
}
743
768
 
744
769
void ha_tina::get_status()
745
770
{
 
771
  if (share->is_log_table)
 
772
  {
 
773
    /*
 
774
      We have to use mutex to follow pthreads memory visibility
 
775
      rules for share->saved_data_file_length
 
776
    */
 
777
    pthread_mutex_lock(&share->mutex);
 
778
    local_saved_data_file_length= share->saved_data_file_length;
 
779
    pthread_mutex_unlock(&share->mutex);
 
780
    return;
 
781
  }
746
782
  local_saved_data_file_length= share->saved_data_file_length;
747
783
}
748
784
 
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
767
 
    way. 
 
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.
768
805
*/
769
806
 
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.
781
818
*/
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__)),
 
820
                  uint open_options)
784
821
{
 
822
  DBUG_ENTER("ha_tina::open");
 
823
 
785
824
  if (!(share= get_share(name, table)))
786
 
    return(HA_ERR_OUT_OF_MEM);
 
825
    DBUG_RETURN(HA_ERR_OUT_OF_MEM);
787
826
 
788
827
  if (share->crashed && !(open_options & HA_OPEN_FOR_REPAIR))
789
828
  {
790
829
    free_share(share);
791
 
    return(HA_ERR_CRASHED_ON_USAGE);
 
830
    DBUG_RETURN(HA_ERR_CRASHED_ON_USAGE);
792
831
  }
793
832
 
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)
796
 
    return(0);
 
835
    DBUG_RETURN(0);
797
836
 
798
837
  /*
799
838
    Init locking. Pass handler object to the locking routines,
807
846
  share->lock.update_status= tina_update_status;
808
847
  share->lock.check_status= tina_check_status;
809
848
 
810
 
  return(0);
 
849
  DBUG_RETURN(0);
811
850
}
812
851
 
813
852
 
818
857
int ha_tina::close(void)
819
858
{
820
859
  int rc= 0;
 
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);
823
863
}
824
864
 
825
865
/*
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).
829
869
*/
830
 
int ha_tina::write_row(unsigned char * buf)
 
870
int ha_tina::write_row(uchar * buf)
831
871
{
832
872
  int size;
 
873
  DBUG_ENTER("ha_tina::write_row");
833
874
 
834
875
  if (share->crashed)
835
 
      return(HA_ERR_CRASHED_ON_USAGE);
 
876
      DBUG_RETURN(HA_ERR_CRASHED_ON_USAGE);
836
877
 
837
878
  ha_statistic_increment(&SSV::ha_write_count);
838
879
 
843
884
 
844
885
  if (!share->tina_write_opened)
845
886
    if (init_tina_writer())
846
 
      return(-1);
 
887
      DBUG_RETURN(-1);
847
888
 
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)))
851
 
    return(-1);
 
892
    DBUG_RETURN(-1);
852
893
 
853
894
  /* update local copy of the max position to see our own changes */
854
895
  local_saved_data_file_length+= size;
857
898
  pthread_mutex_lock(&share->mutex);
858
899
  share->rows_recorded++;
859
900
  /* update status for the log tables */
 
901
  if (share->is_log_table)
 
902
    update_status();
860
903
  pthread_mutex_unlock(&share->mutex);
861
904
 
862
905
  stats.records++;
863
 
  return(0);
 
906
  DBUG_RETURN(0);
864
907
}
865
908
 
866
909
 
876
919
                               MY_REPLACE_EXT | MY_UNPACK_FILENAME),
877
920
                     0, O_RDWR | O_TRUNC, MYF(MY_WME))) < 0)
878
921
      return 1;
879
 
    share->update_file_opened= true;
 
922
    share->update_file_opened= TRUE;
880
923
    temp_file_length= 0;
881
924
  }
882
925
  return 0;
890
933
  This will be called in a table scan right before the previous ::rnd_next()
891
934
  call.
892
935
*/
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__)),
 
937
                        uchar * new_data)
895
938
{
896
939
  int size;
897
940
  int rc= -1;
 
941
  DBUG_ENTER("ha_tina::update_row");
898
942
 
899
943
  ha_statistic_increment(&SSV::ha_update_count);
900
944
 
916
960
  if (open_update_temp_file_if_needed())
917
961
    goto err;
918
962
 
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)))
921
965
    goto err;
922
966
  temp_file_length+= size;
923
967
  rc= 0;
924
968
 
 
969
  /* UPDATE should never happen on the log tables */
 
970
  DBUG_ASSERT(!share->is_log_table);
 
971
 
925
972
err:
926
 
  return(rc);
 
973
  DBUG_PRINT("info",("rc = %d", rc));
 
974
  DBUG_RETURN(rc);
927
975
}
928
976
 
929
977
 
936
984
  The table will then be deleted/positioned based on the ORDER (so RANDOM,
937
985
  DESC, ASC).
938
986
*/
939
 
int ha_tina::delete_row(const unsigned char * buf __attribute__((unused)))
 
987
int ha_tina::delete_row(const uchar * buf __attribute__((__unused__)))
940
988
{
 
989
  DBUG_ENTER("ha_tina::delete_row");
941
990
  ha_statistic_increment(&SSV::ha_delete_count);
942
991
 
943
992
  if (chain_append())
944
 
    return(-1);
 
993
    DBUG_RETURN(-1);
945
994
 
946
995
  stats.records--;
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);
952
1001
 
953
 
  return(0);
 
1002
  /* DELETE should never happen on the log table */
 
1003
  DBUG_ASSERT(!share->is_log_table);
 
1004
 
 
1005
  DBUG_RETURN(0);
954
1006
}
955
1007
 
956
1008
 
1012
1064
 
1013
1065
*/
1014
1066
 
1015
 
int ha_tina::rnd_init(bool scan __attribute__((unused)))
 
1067
int ha_tina::rnd_init(bool scan __attribute__((__unused__)))
1016
1068
{
 
1069
  DBUG_ENTER("ha_tina::rnd_init");
 
1070
 
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);
1020
1074
 
1021
1075
  current_position= next_position= 0;
1022
1076
  stats.records= 0;
1025
1079
 
1026
1080
  init_alloc_root(&blobroot, BLOB_MEMROOT_ALLOC_SIZE, 0);
1027
1081
 
1028
 
  return(0);
 
1082
  DBUG_RETURN(0);
1029
1083
}
1030
1084
 
1031
1085
/*
1042
1096
  NULL and "". This is ok since this table handler is for spreadsheets and
1043
1097
  they don't know about them either :)
1044
1098
*/
1045
 
int ha_tina::rnd_next(unsigned char *buf)
 
1099
int ha_tina::rnd_next(uchar *buf)
1046
1100
{
1047
1101
  int rc;
 
1102
  DBUG_ENTER("ha_tina::rnd_next");
1048
1103
 
1049
1104
  if (share->crashed)
1050
 
      return(HA_ERR_CRASHED_ON_USAGE);
 
1105
      DBUG_RETURN(HA_ERR_CRASHED_ON_USAGE);
1051
1106
 
1052
1107
  ha_statistic_increment(&SSV::ha_read_rnd_next_count);
1053
1108
 
1055
1110
 
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);
1059
1114
 
1060
1115
  if ((rc= find_current_row(buf)))
1061
 
    return(rc);
 
1116
    DBUG_RETURN(rc);
1062
1117
 
1063
1118
  stats.records++;
1064
 
  return(0);
 
1119
  DBUG_RETURN(0);
1065
1120
}
1066
1121
 
1067
1122
/*
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.
1075
1130
*/
1076
 
void ha_tina::position(const unsigned char *record __attribute__((unused)))
 
1131
void ha_tina::position(const uchar *record __attribute__((__unused__)))
1077
1132
{
 
1133
  DBUG_ENTER("ha_tina::position");
1078
1134
  my_store_ptr(ref, ref_length, current_position);
1079
 
  return;
 
1135
  DBUG_VOID_RETURN;
1080
1136
}
1081
1137
 
1082
1138
 
1085
1141
  my_get_ptr() retrieves the data for you.
1086
1142
*/
1087
1143
 
1088
 
int ha_tina::rnd_pos(unsigned char * buf, unsigned char *pos)
 
1144
int ha_tina::rnd_pos(uchar * buf, uchar *pos)
1089
1145
{
 
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));
1093
1150
}
1094
1151
 
1095
1152
/*
1097
1154
  Currently this table handler doesn't implement most of the fields
1098
1155
  really needed. SHOW also makes use of this data
1099
1156
*/
1100
 
int ha_tina::info(uint32_t flag __attribute__((unused)))
 
1157
int ha_tina::info(uint flag __attribute__((__unused__)))
1101
1158
{
 
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;
1105
 
  return(0);
 
1163
  DBUG_RETURN(0);
 
1164
}
 
1165
 
 
1166
/*
 
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.
 
1170
*/
 
1171
int ha_tina::extra(enum ha_extra_function operation)
 
1172
{
 
1173
  DBUG_ENTER("ha_tina::extra");
 
1174
 if (operation == HA_EXTRA_MARK_AS_LOG_TABLE)
 
1175
 {
 
1176
   pthread_mutex_lock(&share->mutex);
 
1177
   share->is_log_table= TRUE;
 
1178
   pthread_mutex_unlock(&share->mutex);
 
1179
 }
 
1180
  DBUG_RETURN(0);
1106
1181
}
1107
1182
 
1108
1183
/*
1115
1190
  if (closest_hole == chain_ptr) /* no more chains */
1116
1191
    *end_pos= file_buff->end();
1117
1192
  else
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);
1121
1196
}
1122
1197
 
1131
1206
{
1132
1207
  char updated_fname[FN_REFLEN];
1133
1208
  off_t file_buffer_start= 0;
 
1209
  DBUG_ENTER("ha_tina::rnd_end");
1134
1210
 
1135
1211
  free_root(&blobroot, MYF(0));
1136
1212
  records_is_known= 1;
1156
1232
 
1157
1233
    /* create the file to write updated table if it wasn't yet created */
1158
1234
    if (open_update_temp_file_if_needed())
1159
 
      return(-1);
 
1235
      DBUG_RETURN(-1);
1160
1236
 
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)
1169
1245
      {
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))
1174
1250
          goto error;
1192
1268
 
1193
1269
    if (my_sync(update_temp_file, MYF(MY_WME)) ||
1194
1270
        my_close(update_temp_file, MYF(0)))
1195
 
      return(-1);
 
1271
      DBUG_RETURN(-1);
1196
1272
 
1197
 
    share->update_file_opened= false;
 
1273
    share->update_file_opened= FALSE;
1198
1274
 
1199
1275
    if (share->tina_write_opened)
1200
1276
    {
1201
1277
      if (my_close(share->tina_write_filedes, MYF(0)))
1202
 
        return(-1);
 
1278
        DBUG_RETURN(-1);
1203
1279
      /*
1204
1280
        Mark that the writer fd is closed, so that init_tina_writer()
1205
1281
        will reopen it later.
1206
1282
      */
1207
 
      share->tina_write_opened= false;
 
1283
      share->tina_write_opened= FALSE;
1208
1284
    }
1209
1285
 
1210
1286
    /*
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)))
1218
 
      return(-1);
 
1294
      DBUG_RETURN(-1);
1219
1295
 
1220
1296
    /* Open the file again */
1221
1297
    if (((data_file= my_open(share->data_file_name, O_RDONLY, MYF(0))) == -1))
1222
 
      return(-1);
 
1298
      DBUG_RETURN(-1);
1223
1299
    /*
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.
1237
1313
    */
1238
 
    (void)write_meta_file(share->meta_file, share->rows_recorded, false);
 
1314
    (void)write_meta_file(share->meta_file, share->rows_recorded, FALSE);
1239
1315
    /* 
1240
1316
      Update local_saved_data_file_length with the real length of the 
1241
1317
      data file.
1243
1319
    local_saved_data_file_length= temp_file_length;
1244
1320
  }
1245
1321
 
1246
 
  return(0);
 
1322
  DBUG_RETURN(0);
1247
1323
error:
1248
1324
  my_close(update_temp_file, MYF(0));
1249
 
  share->update_file_opened= false;
1250
 
  return(-1);
 
1325
  share->update_file_opened= FALSE;
 
1326
  DBUG_RETURN(-1);
1251
1327
}
1252
1328
 
1253
1329
 
1270
1346
*/
1271
1347
 
1272
1348
int ha_tina::repair(THD* thd,
1273
 
                    HA_CHECK_OPT* check_opt __attribute__((unused)))
 
1349
                    HA_CHECK_OPT* check_opt __attribute__((__unused__)))
1274
1350
{
1275
1351
  char repaired_fname[FN_REFLEN];
1276
 
  unsigned char *buf;
 
1352
  uchar *buf;
1277
1353
  File repair_file;
1278
1354
  int rc;
1279
1355
  ha_rows rows_repaired= 0;
1280
1356
  off_t write_begin= 0, write_end;
 
1357
  DBUG_ENTER("ha_tina::repair");
1281
1358
 
1282
1359
  /* empty file */
1283
1360
  if (!share->saved_data_file_length)
1288
1365
 
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);
1293
1370
 
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);
1297
1374
 
1298
1375
  /*
1299
1376
    Local_saved_data_file_length is initialized during the lock phase.
1316
1393
 
1317
1394
  free_root(&blobroot, MYF(0));
1318
1395
 
1319
 
  free((char*)buf);
 
1396
  my_free((char*)buf, MYF(0));
1320
1397
 
1321
1398
  if (rc == HA_ERR_END_OF_FILE)
1322
1399
  {
1337
1414
                                        "", CSN_EXT,
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);
1341
1418
 
1342
1419
  file_buff->init_buff(data_file);
1343
1420
 
1348
1425
  /* write repaired file */
1349
1426
  while (1)
1350
1427
  {
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)))
1355
 
      return(-1);
 
1432
      DBUG_RETURN(-1);
1356
1433
 
1357
1434
    write_begin= write_end;
1358
1435
    if (write_end== current_position)
1369
1446
  */
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)))
1372
 
    return(-1);
 
1449
    DBUG_RETURN(-1);
1373
1450
 
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)
1377
 
     return(-1);
 
1454
     DBUG_RETURN(-1);
1378
1455
 
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;
1381
1458
 
1382
1459
end:
1383
 
  share->crashed= false;
1384
 
  return(HA_ADMIN_OK);
 
1460
  share->crashed= FALSE;
 
1461
  DBUG_RETURN(HA_ADMIN_OK);
1385
1462
}
1386
1463
 
1387
1464
/*
1391
1468
int ha_tina::delete_all_rows()
1392
1469
{
1393
1470
  int rc;
 
1471
  DBUG_ENTER("ha_tina::delete_all_rows");
1394
1472
 
1395
1473
  if (!records_is_known)
1396
 
    return(my_errno=HA_ERR_WRONG_COMMAND);
 
1474
    DBUG_RETURN(my_errno=HA_ERR_WRONG_COMMAND);
1397
1475
 
1398
1476
  if (!share->tina_write_opened)
1399
1477
    if (init_tina_writer())
1400
 
      return(-1);
 
1478
      DBUG_RETURN(-1);
1401
1479
 
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;
1411
 
  return(rc);
 
1489
  DBUG_RETURN(rc);
1412
1490
}
1413
1491
 
1414
1492
/*
1415
1493
  Called by the database to lock the table. Keep in mind that this
1416
1494
  is an internal lock.
1417
1495
*/
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)
1421
1499
{
1430
1508
  this (the database will call ::open() if it needs to).
1431
1509
*/
1432
1510
 
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__)))
1435
1513
{
1436
1514
  char name_buff[FN_REFLEN];
1437
1515
  File create_file;
 
1516
  DBUG_ENTER("ha_tina::create");
1438
1517
 
1439
1518
  /*
1440
1519
    check columns
1444
1523
    if ((*field)->real_maybe_null())
1445
1524
    {
1446
1525
      my_error(ER_CHECK_NOT_IMPLEMENTED, MYF(0), "nullable columns");
1447
 
      return(HA_ERR_UNSUPPORTED);
 
1526
      DBUG_RETURN(HA_ERR_UNSUPPORTED);
1448
1527
    }
1449
1528
  }
1450
1529
  
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)
1455
 
    return(-1);
 
1534
    DBUG_RETURN(-1);
1456
1535
 
1457
 
  write_meta_file(create_file, 0, false);
 
1536
  write_meta_file(create_file, 0, FALSE);
1458
1537
  my_close(create_file, MYF(0));
1459
1538
 
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)
1463
 
    return(-1);
 
1542
    DBUG_RETURN(-1);
1464
1543
 
1465
1544
  my_close(create_file, MYF(0));
1466
1545
 
1467
 
  return(0);
 
1546
  DBUG_RETURN(0);
1468
1547
}
1469
1548
 
1470
1549
int ha_tina::check(THD* thd,
1471
 
                   HA_CHECK_OPT* check_opt __attribute__((unused)))
 
1550
                   HA_CHECK_OPT* check_opt __attribute__((__unused__)))
1472
1551
{
1473
1552
  int rc= 0;
1474
 
  unsigned char *buf;
 
1553
  uchar *buf;
1475
1554
  const char *old_proc_info;
1476
1555
  ha_rows count= share->rows_recorded;
 
1556
  DBUG_ENTER("ha_tina::check");
1477
1557
 
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);
1482
1561
 
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);
1486
1565
 
1487
1566
  /*
1488
1567
    Local_saved_data_file_length is initialized during the lock phase.
1505
1584
  
1506
1585
  free_root(&blobroot, MYF(0));
1507
1586
 
1508
 
  free((char*)buf);
1509
 
  set_thd_proc_info(thd, old_proc_info);
 
1587
  my_free((char*)buf, MYF(0));
 
1588
  thd_proc_info(thd, old_proc_info);
1510
1589
 
1511
1590
  if ((rc != HA_ERR_END_OF_FILE) || count)
1512
1591
  {
1513
 
    share->crashed= true;
1514
 
    return(HA_ADMIN_CORRUPT);
 
1592
    share->crashed= TRUE;
 
1593
    DBUG_RETURN(HA_ADMIN_CORRUPT);
1515
1594
  }
1516
1595
  else
1517
 
    return(HA_ADMIN_OK);
 
1596
    DBUG_RETURN(HA_ADMIN_OK);
1518
1597
}
1519
1598
 
1520
1599
 
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__)))
1523
1602
{
1524
1603
  return COMPATIBLE_DATA_YES;
1525
1604
}
1526
1605
 
 
1606
struct st_mysql_storage_engine csv_storage_engine=
 
1607
{ MYSQL_HANDLERTON_INTERFACE_VERSION };
 
1608
 
1527
1609
mysql_declare_plugin(csv)
1528
1610
{
1529
 
  DRIZZLE_STORAGE_ENGINE_PLUGIN,
 
1611
  MYSQL_STORAGE_ENGINE_PLUGIN,
 
1612
  &csv_storage_engine,
1530
1613
  "CSV",
1531
 
  "1.0",
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 */
 
1619
  0x0100 /* 1.0 */,
1537
1620
  NULL,                       /* status variables                */
1538
1621
  NULL,                       /* system variables                */
1539
1622
  NULL                        /* config options                  */