~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to storage/csv/ha_tina.cc

  • Committer: Monty Taylor
  • Date: 2008-10-16 06:32:30 UTC
  • mto: (511.1.5 codestyle)
  • mto: This revision was merged to the branch mainline in revision 521.
  • Revision ID: monty@inaugust.com-20081016063230-4brxsra0qsmsg84q
Added -Wunused-macros.

Show diffs side-by-side

added added

removed removed

Lines of Context:
40
40
 
41
41
 -Brian
42
42
*/
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>
 
43
#include <drizzled/common_includes.h>
50
44
#include "ha_tina.h"
51
45
 
52
46
 
53
47
/*
54
 
  uchar + uchar + uint64_t + uint64_t + uint64_t + uint64_t + uchar
 
48
  unsigned char + unsigned char + uint64_t + uint64_t + uint64_t + uint64_t + unsigned char
55
49
*/
56
 
#define META_BUFFER_SIZE sizeof(uchar) + sizeof(uchar) + sizeof(uint64_t) \
57
 
  + sizeof(uint64_t) + sizeof(uint64_t) + sizeof(uint64_t) + sizeof(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)
58
52
#define TINA_CHECK_HEADER 254 // The number we use to determine corruption
59
53
#define BLOB_MEMROOT_ALLOC_SIZE 8192
60
54
 
64
58
#define CSM_EXT ".CSM"               // Meta file
65
59
 
66
60
 
67
 
static TINA_SHARE *get_share(const char *table_name, TABLE *table);
 
61
static TINA_SHARE *get_share(const char *table_name, Table *table);
68
62
static int free_share(TINA_SHARE *share);
69
63
static int read_meta_file(File meta_file, ha_rows *rows);
70
64
static int write_meta_file(File meta_file, ha_rows rows, bool dirty);
97
91
  return ( a->begin > b->begin ? 1 : ( a->begin < b->begin ? -1 : 0 ) );
98
92
}
99
93
 
100
 
static uchar* tina_get_key(TINA_SHARE *share, size_t *length,
 
94
static unsigned char* tina_get_key(TINA_SHARE *share, size_t *length,
101
95
                          bool not_used __attribute__((unused)))
102
96
{
103
97
  *length=share->table_name_length;
104
 
  return (uchar*) share->table_name;
 
98
  return (unsigned char*) share->table_name;
105
99
}
106
100
 
107
101
static int tina_init_func(void *p)
109
103
  handlerton *tina_hton;
110
104
 
111
105
  tina_hton= (handlerton *)p;
112
 
  VOID(pthread_mutex_init(&tina_mutex,MY_MUTEX_INIT_FAST));
 
106
  pthread_mutex_init(&tina_mutex,MY_MUTEX_INIT_FAST);
113
107
  (void) hash_init(&tina_open_tables,system_charset_info,32,0,0,
114
108
                   (hash_get_key) tina_get_key,0,0);
115
109
  tina_hton->state= SHOW_OPTION_YES;
116
 
  tina_hton->db_type= DB_TYPE_CSV_DB;
117
110
  tina_hton->create= tina_create_handler;
118
111
  tina_hton->flags= (HTON_CAN_RECREATE | HTON_SUPPORT_LOG_TABLES | 
119
112
                     HTON_NO_PARTITION);
120
113
  return 0;
121
114
}
122
115
 
123
 
static int tina_done_func(void *p __attribute__((__unused__)))
 
116
static int tina_done_func(void *p __attribute__((unused)))
124
117
{
125
118
  hash_free(&tina_open_tables);
126
119
  pthread_mutex_destroy(&tina_mutex);
133
126
  Simple lock controls.
134
127
*/
135
128
static TINA_SHARE *get_share(const char *table_name,
136
 
                             TABLE *table __attribute__((__unused__)))
 
129
                             Table *table __attribute__((unused)))
137
130
{
138
131
  TINA_SHARE *share;
139
132
  char meta_file_name[FN_REFLEN];
140
133
  struct stat file_stat;
141
134
  char *tmp_name;
142
 
  uint length;
 
135
  uint32_t length;
143
136
 
144
137
  pthread_mutex_lock(&tina_mutex);
145
138
  length=(uint) strlen(table_name);
149
142
    initialize its members.
150
143
  */
151
144
  if (!(share=(TINA_SHARE*) hash_search(&tina_open_tables,
152
 
                                        (uchar*) table_name,
 
145
                                        (unsigned char*) table_name,
153
146
                                       length)))
154
147
  {
155
148
    if (!my_multi_malloc(MYF(MY_WME | MY_ZEROFILL),
156
149
                         &share, sizeof(*share),
157
150
                         &tmp_name, length+1,
158
 
                         NullS))
 
151
                         NULL))
159
152
    {
160
153
      pthread_mutex_unlock(&tina_mutex);
161
154
      return NULL;
162
155
    }
163
156
 
164
157
    share->use_count= 0;
165
 
    share->is_log_table= false;
166
158
    share->table_name_length= length;
167
159
    share->table_name= tmp_name;
168
160
    share->crashed= false;
170
162
    share->update_file_opened= false;
171
163
    share->tina_write_opened= false;
172
164
    share->data_file_version= 0;
173
 
    strmov(share->table_name, table_name);
 
165
    my_stpcpy(share->table_name, table_name);
174
166
    fn_format(share->data_file_name, table_name, "", CSV_EXT,
175
167
              MY_REPLACE_EXT|MY_UNPACK_FILENAME);
176
168
    fn_format(meta_file_name, table_name, "", CSM_EXT,
180
172
      goto error;
181
173
    share->saved_data_file_length= file_stat.st_size;
182
174
 
183
 
    if (my_hash_insert(&tina_open_tables, (uchar*) share))
 
175
    if (my_hash_insert(&tina_open_tables, (unsigned char*) share))
184
176
      goto error;
185
177
    thr_lock_init(&share->lock);
186
178
    pthread_mutex_init(&share->mutex,MY_MUTEX_INIT_FAST);
209
201
 
210
202
error:
211
203
  pthread_mutex_unlock(&tina_mutex);
212
 
  my_free((uchar*) share, MYF(0));
 
204
  free((unsigned char*) share);
213
205
 
214
206
  return NULL;
215
207
}
236
228
 
237
229
static int read_meta_file(File meta_file, ha_rows *rows)
238
230
{
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)
 
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)
246
236
      != META_BUFFER_SIZE)
247
 
    DBUG_RETURN(HA_ERR_CRASHED_ON_USAGE);
 
237
    return(HA_ERR_CRASHED_ON_USAGE);
248
238
 
249
239
  /*
250
240
    Parse out the meta data, we ignore version at the moment
251
241
  */
252
242
 
253
 
  ptr+= sizeof(uchar)*2; // Move past header
 
243
  ptr+= sizeof(unsigned char)*2; // Move past header
254
244
  *rows= (ha_rows)uint8korr(ptr);
255
245
  ptr+= sizeof(uint64_t); // Move past rows
256
246
  /*
260
250
  ptr+= 3*sizeof(uint64_t);
261
251
 
262
252
  /* check crashed bit and magic number */
263
 
  if ((meta_buffer[0] != (uchar)TINA_CHECK_HEADER) ||
 
253
  if ((meta_buffer[0] != (unsigned char)TINA_CHECK_HEADER) ||
264
254
      ((bool)(*ptr)== true))
265
 
    DBUG_RETURN(HA_ERR_CRASHED_ON_USAGE);
 
255
    return(HA_ERR_CRASHED_ON_USAGE);
266
256
 
267
257
  my_sync(meta_file, MYF(MY_WME));
268
258
 
269
 
  DBUG_RETURN(0);
 
259
  return(0);
270
260
}
271
261
 
272
262
 
291
281
 
292
282
static int write_meta_file(File meta_file, ha_rows rows, bool dirty)
293
283
{
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);
 
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);
303
291
  int8store(ptr, (uint64_t)rows);
304
292
  ptr+= sizeof(uint64_t);
305
293
  memset(ptr, 0, 3*sizeof(uint64_t));
308
296
     We'll need them later.
309
297
  */
310
298
  ptr+= 3*sizeof(uint64_t);
311
 
  *ptr= (uchar)dirty;
 
299
  *ptr= (unsigned char)dirty;
312
300
 
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)
 
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)
315
303
      != META_BUFFER_SIZE)
316
 
    DBUG_RETURN(-1);
 
304
    return(-1);
317
305
 
318
306
  my_sync(meta_file, MYF(MY_WME));
319
307
 
320
 
  DBUG_RETURN(0);
 
308
  return(0);
321
309
}
322
310
 
323
311
bool ha_tina::check_and_repair(THD *thd)
324
312
{
325
313
  HA_CHECK_OPT check_opt;
326
 
  DBUG_ENTER("ha_tina::check_and_repair");
327
314
 
328
315
  check_opt.init();
329
316
 
330
 
  DBUG_RETURN(repair(thd, &check_opt));
 
317
  return(repair(thd, &check_opt));
331
318
}
332
319
 
333
320
 
334
321
int ha_tina::init_tina_writer()
335
322
{
336
 
  DBUG_ENTER("ha_tina::init_tina_writer");
337
 
 
338
323
  /*
339
324
    Mark the file as crashed. We will set the flag back when we close
340
325
    the file. In the case of the crash it will remain marked crashed,
345
330
  if ((share->tina_write_filedes=
346
331
        my_open(share->data_file_name, O_RDWR|O_APPEND, MYF(0))) == -1)
347
332
  {
348
 
    DBUG_PRINT("info", ("Could not open tina file writes"));
349
333
    share->crashed= true;
350
 
    DBUG_RETURN(1);
 
334
    return(1);
351
335
  }
352
336
  share->tina_write_opened= true;
353
337
 
354
 
  DBUG_RETURN(0);
 
338
  return(0);
355
339
}
356
340
 
357
341
 
358
342
bool ha_tina::is_crashed() const
359
343
{
360
 
  DBUG_ENTER("ha_tina::is_crashed");
361
 
  DBUG_RETURN(share->crashed);
 
344
  return(share->crashed);
362
345
}
363
346
 
364
347
/*
366
349
*/
367
350
static int free_share(TINA_SHARE *share)
368
351
{
369
 
  DBUG_ENTER("ha_tina::free_share");
370
352
  pthread_mutex_lock(&tina_mutex);
371
353
  int result_code= 0;
372
354
  if (!--share->use_count){
382
364
      share->tina_write_opened= false;
383
365
    }
384
366
 
385
 
    hash_delete(&tina_open_tables, (uchar*) share);
 
367
    hash_delete(&tina_open_tables, (unsigned char*) share);
386
368
    thr_lock_delete(&share->lock);
387
369
    pthread_mutex_destroy(&share->mutex);
388
 
    my_free((uchar*) share, MYF(0));
 
370
    free((unsigned char*) share);
389
371
  }
390
372
  pthread_mutex_unlock(&tina_mutex);
391
373
 
392
 
  DBUG_RETURN(result_code);
 
374
  return(result_code);
393
375
}
394
376
 
395
377
 
460
442
  Encode a buffer into the quoted format.
461
443
*/
462
444
 
463
 
int ha_tina::encode_quote(uchar *buf __attribute__((__unused__)))
 
445
int ha_tina::encode_quote(unsigned char *buf __attribute__((unused)))
464
446
{
465
447
  char attribute_buffer[1024];
466
448
  String attribute(attribute_buffer, sizeof(attribute_buffer),
467
449
                   &my_charset_bin);
468
450
 
469
 
  my_bitmap_map *org_bitmap= dbug_tmp_use_all_columns(table, table->read_set);
470
451
  buffer.length(0);
471
452
 
472
453
  for (Field **field=table->field ; *field ; field++)
541
522
 
542
523
  //buffer.replace(buffer.length(), 0, "\n", 1);
543
524
 
544
 
  dbug_tmp_restore_column_map(table->read_set, org_bitmap);
545
525
  return (buffer.length());
546
526
}
547
527
 
564
544
      if (chain_alloced)
565
545
      {
566
546
        /* Must cast since my_malloc unlike malloc doesn't have a void ptr */
567
 
        if ((chain= (tina_set *) my_realloc((uchar*)chain,
 
547
        if ((chain= (tina_set *) my_realloc((unsigned char*)chain,
568
548
                                            chain_size, MYF(MY_WME))) == NULL)
569
549
          return -1;
570
550
      }
590
570
/*
591
571
  Scans for a row.
592
572
*/
593
 
int ha_tina::find_current_row(uchar *buf)
 
573
int ha_tina::find_current_row(unsigned char *buf)
594
574
{
595
575
  off_t end_offset, curr_offset= current_position;
596
576
  int eoln_len;
597
 
  my_bitmap_map *org_bitmap;
598
577
  int error;
599
578
  bool read_all;
600
 
  DBUG_ENTER("ha_tina::find_current_row");
601
579
 
602
580
  free_root(&blobroot, MYF(MY_MARK_BLOCKS_FREE));
603
581
 
608
586
  if ((end_offset=
609
587
        find_eoln_buff(file_buff, current_position,
610
588
                       local_saved_data_file_length, &eoln_len)) == 0)
611
 
    DBUG_RETURN(HA_ERR_END_OF_FILE);
 
589
    return(HA_ERR_END_OF_FILE);
612
590
 
613
591
  /* We must read all columns in case a table is opened for update */
614
592
  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);
617
593
  error= HA_ERR_CRASHED_ON_USAGE;
618
594
 
619
595
  memset(buf, 0, table->s->null_bytes);
691
667
      if ((*field)->flags & BLOB_FLAG)
692
668
      {
693
669
        Field_blob *blob= *(Field_blob**) field;
694
 
        uchar *src, *tgt;
695
 
        uint length, packlength;
 
670
        unsigned char *src, *tgt;
 
671
        uint32_t length, packlength;
696
672
        
697
673
        packlength= blob->pack_length_no_ptr();
698
674
        length= blob->get_length(blob->ptr);
699
 
        memcpy_fixed(&src, blob->ptr + packlength, sizeof(char*));
 
675
        memcpy(&src, blob->ptr + packlength, sizeof(char*));
700
676
        if (src)
701
677
        {
702
 
          tgt= (uchar*) alloc_root(&blobroot, length);
703
 
          bmove(tgt, src, length);
704
 
          memcpy_fixed(blob->ptr + packlength, &tgt, sizeof(char*));
 
678
          tgt= (unsigned char*) alloc_root(&blobroot, length);
 
679
          memcpy(tgt, src, length);
 
680
          memcpy(blob->ptr + packlength, &tgt, sizeof(char*));
705
681
        }
706
682
      }
707
683
    }
710
686
  error= 0;
711
687
 
712
688
err:
713
 
  dbug_tmp_restore_column_map(table->write_set, org_bitmap);
714
689
 
715
 
  DBUG_RETURN(error);
 
690
  return(error);
716
691
}
717
692
 
718
693
/*
722
697
static const char *ha_tina_exts[] = {
723
698
  CSV_EXT,
724
699
  CSM_EXT,
725
 
  NullS
 
700
  NULL
726
701
};
727
702
 
728
703
const char **ha_tina::bas_ext() const
736
711
*/
737
712
 
738
713
void tina_get_status(void* param,
739
 
                     int concurrent_insert __attribute__((__unused__)))
 
714
                     int concurrent_insert __attribute__((unused)))
740
715
{
741
716
  ha_tina *tina= (ha_tina*) param;
742
717
  tina->get_status();
749
724
}
750
725
 
751
726
/* this should exist and return 0 for concurrent insert to work */
752
 
bool tina_check_status(void* param __attribute__((__unused__)))
 
727
bool tina_check_status(void* param __attribute__((unused)))
753
728
{
754
729
  return 0;
755
730
}
768
743
 
769
744
void ha_tina::get_status()
770
745
{
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
 
  }
782
746
  local_saved_data_file_length= share->saved_data_file_length;
783
747
}
784
748
 
800
764
    For log tables concurrent insert works different. The reason is that
801
765
    log tables are always opened and locked. And as they do not unlock
802
766
    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.
 
767
    way. 
805
768
*/
806
769
 
807
770
void ha_tina::update_status()
816
779
  this will not be called for every request. Any sort of positions
817
780
  that need to be reset should be kept in the ::extra() call.
818
781
*/
819
 
int ha_tina::open(const char *name, int mode __attribute__((__unused__)),
820
 
                  uint open_options)
 
782
int ha_tina::open(const char *name, int mode __attribute__((unused)),
 
783
                  uint32_t open_options)
821
784
{
822
 
  DBUG_ENTER("ha_tina::open");
823
 
 
824
785
  if (!(share= get_share(name, table)))
825
 
    DBUG_RETURN(HA_ERR_OUT_OF_MEM);
 
786
    return(HA_ERR_OUT_OF_MEM);
826
787
 
827
788
  if (share->crashed && !(open_options & HA_OPEN_FOR_REPAIR))
828
789
  {
829
790
    free_share(share);
830
 
    DBUG_RETURN(HA_ERR_CRASHED_ON_USAGE);
 
791
    return(HA_ERR_CRASHED_ON_USAGE);
831
792
  }
832
793
 
833
794
  local_data_file_version= share->data_file_version;
834
795
  if ((data_file= my_open(share->data_file_name, O_RDONLY, MYF(0))) == -1)
835
 
    DBUG_RETURN(0);
 
796
    return(0);
836
797
 
837
798
  /*
838
799
    Init locking. Pass handler object to the locking routines,
846
807
  share->lock.update_status= tina_update_status;
847
808
  share->lock.check_status= tina_check_status;
848
809
 
849
 
  DBUG_RETURN(0);
 
810
  return(0);
850
811
}
851
812
 
852
813
 
857
818
int ha_tina::close(void)
858
819
{
859
820
  int rc= 0;
860
 
  DBUG_ENTER("ha_tina::close");
861
821
  rc= my_close(data_file, MYF(0));
862
 
  DBUG_RETURN(free_share(share) || rc);
 
822
  return(free_share(share) || rc);
863
823
}
864
824
 
865
825
/*
867
827
  of the file and appends the data. In an error case it really should
868
828
  just truncate to the original position (this is not done yet).
869
829
*/
870
 
int ha_tina::write_row(uchar * buf)
 
830
int ha_tina::write_row(unsigned char * buf)
871
831
{
872
832
  int size;
873
 
  DBUG_ENTER("ha_tina::write_row");
874
833
 
875
834
  if (share->crashed)
876
 
      DBUG_RETURN(HA_ERR_CRASHED_ON_USAGE);
 
835
      return(HA_ERR_CRASHED_ON_USAGE);
877
836
 
878
837
  ha_statistic_increment(&SSV::ha_write_count);
879
838
 
884
843
 
885
844
  if (!share->tina_write_opened)
886
845
    if (init_tina_writer())
887
 
      DBUG_RETURN(-1);
 
846
      return(-1);
888
847
 
889
848
   /* use pwrite, as concurrent reader could have changed the position */
890
 
  if (my_write(share->tina_write_filedes, (uchar*)buffer.ptr(), size,
 
849
  if (my_write(share->tina_write_filedes, (unsigned char*)buffer.ptr(), size,
891
850
               MYF(MY_WME | MY_NABP)))
892
 
    DBUG_RETURN(-1);
 
851
    return(-1);
893
852
 
894
853
  /* update local copy of the max position to see our own changes */
895
854
  local_saved_data_file_length+= size;
898
857
  pthread_mutex_lock(&share->mutex);
899
858
  share->rows_recorded++;
900
859
  /* update status for the log tables */
901
 
  if (share->is_log_table)
902
 
    update_status();
903
860
  pthread_mutex_unlock(&share->mutex);
904
861
 
905
862
  stats.records++;
906
 
  DBUG_RETURN(0);
 
863
  return(0);
907
864
}
908
865
 
909
866
 
933
890
  This will be called in a table scan right before the previous ::rnd_next()
934
891
  call.
935
892
*/
936
 
int ha_tina::update_row(const uchar * old_data __attribute__((__unused__)),
937
 
                        uchar * new_data)
 
893
int ha_tina::update_row(const unsigned char * old_data __attribute__((unused)),
 
894
                        unsigned char * new_data)
938
895
{
939
896
  int size;
940
897
  int rc= -1;
941
 
  DBUG_ENTER("ha_tina::update_row");
942
898
 
943
899
  ha_statistic_increment(&SSV::ha_update_count);
944
900
 
960
916
  if (open_update_temp_file_if_needed())
961
917
    goto err;
962
918
 
963
 
  if (my_write(update_temp_file, (uchar*)buffer.ptr(), size,
 
919
  if (my_write(update_temp_file, (unsigned char*)buffer.ptr(), size,
964
920
               MYF(MY_WME | MY_NABP)))
965
921
    goto err;
966
922
  temp_file_length+= size;
967
923
  rc= 0;
968
924
 
969
 
  /* UPDATE should never happen on the log tables */
970
 
  DBUG_ASSERT(!share->is_log_table);
971
 
 
972
925
err:
973
 
  DBUG_PRINT("info",("rc = %d", rc));
974
 
  DBUG_RETURN(rc);
 
926
  return(rc);
975
927
}
976
928
 
977
929
 
984
936
  The table will then be deleted/positioned based on the ORDER (so RANDOM,
985
937
  DESC, ASC).
986
938
*/
987
 
int ha_tina::delete_row(const uchar * buf __attribute__((__unused__)))
 
939
int ha_tina::delete_row(const unsigned char * buf __attribute__((unused)))
988
940
{
989
 
  DBUG_ENTER("ha_tina::delete_row");
990
941
  ha_statistic_increment(&SSV::ha_delete_count);
991
942
 
992
943
  if (chain_append())
993
 
    DBUG_RETURN(-1);
 
944
    return(-1);
994
945
 
995
946
  stats.records--;
996
947
  /* Update shared info */
997
 
  DBUG_ASSERT(share->rows_recorded);
 
948
  assert(share->rows_recorded);
998
949
  pthread_mutex_lock(&share->mutex);
999
950
  share->rows_recorded--;
1000
951
  pthread_mutex_unlock(&share->mutex);
1001
952
 
1002
 
  /* DELETE should never happen on the log table */
1003
 
  DBUG_ASSERT(!share->is_log_table);
1004
 
 
1005
 
  DBUG_RETURN(0);
 
953
  return(0);
1006
954
}
1007
955
 
1008
956
 
1064
1012
 
1065
1013
*/
1066
1014
 
1067
 
int ha_tina::rnd_init(bool scan __attribute__((__unused__)))
 
1015
int ha_tina::rnd_init(bool scan __attribute__((unused)))
1068
1016
{
1069
 
  DBUG_ENTER("ha_tina::rnd_init");
1070
 
 
1071
1017
  /* set buffer to the beginning of the file */
1072
1018
  if (share->crashed || init_data_file())
1073
 
    DBUG_RETURN(HA_ERR_CRASHED_ON_USAGE);
 
1019
    return(HA_ERR_CRASHED_ON_USAGE);
1074
1020
 
1075
1021
  current_position= next_position= 0;
1076
1022
  stats.records= 0;
1079
1025
 
1080
1026
  init_alloc_root(&blobroot, BLOB_MEMROOT_ALLOC_SIZE, 0);
1081
1027
 
1082
 
  DBUG_RETURN(0);
 
1028
  return(0);
1083
1029
}
1084
1030
 
1085
1031
/*
1096
1042
  NULL and "". This is ok since this table handler is for spreadsheets and
1097
1043
  they don't know about them either :)
1098
1044
*/
1099
 
int ha_tina::rnd_next(uchar *buf)
 
1045
int ha_tina::rnd_next(unsigned char *buf)
1100
1046
{
1101
1047
  int rc;
1102
 
  DBUG_ENTER("ha_tina::rnd_next");
1103
1048
 
1104
1049
  if (share->crashed)
1105
 
      DBUG_RETURN(HA_ERR_CRASHED_ON_USAGE);
 
1050
      return(HA_ERR_CRASHED_ON_USAGE);
1106
1051
 
1107
1052
  ha_statistic_increment(&SSV::ha_read_rnd_next_count);
1108
1053
 
1110
1055
 
1111
1056
  /* don't scan an empty file */
1112
1057
  if (!local_saved_data_file_length)
1113
 
    DBUG_RETURN(HA_ERR_END_OF_FILE);
 
1058
    return(HA_ERR_END_OF_FILE);
1114
1059
 
1115
1060
  if ((rc= find_current_row(buf)))
1116
 
    DBUG_RETURN(rc);
 
1061
    return(rc);
1117
1062
 
1118
1063
  stats.records++;
1119
 
  DBUG_RETURN(0);
 
1064
  return(0);
1120
1065
}
1121
1066
 
1122
1067
/*
1128
1073
  its just a position. Look at the bdb code if you want to see a case
1129
1074
  where something other then a number is stored.
1130
1075
*/
1131
 
void ha_tina::position(const uchar *record __attribute__((__unused__)))
 
1076
void ha_tina::position(const unsigned char *record __attribute__((unused)))
1132
1077
{
1133
 
  DBUG_ENTER("ha_tina::position");
1134
1078
  my_store_ptr(ref, ref_length, current_position);
1135
 
  DBUG_VOID_RETURN;
 
1079
  return;
1136
1080
}
1137
1081
 
1138
1082
 
1141
1085
  my_get_ptr() retrieves the data for you.
1142
1086
*/
1143
1087
 
1144
 
int ha_tina::rnd_pos(uchar * buf, uchar *pos)
 
1088
int ha_tina::rnd_pos(unsigned char * buf, unsigned char *pos)
1145
1089
{
1146
 
  DBUG_ENTER("ha_tina::rnd_pos");
1147
1090
  ha_statistic_increment(&SSV::ha_read_rnd_count);
1148
1091
  current_position= (off_t)my_get_ptr(pos,ref_length);
1149
 
  DBUG_RETURN(find_current_row(buf));
 
1092
  return(find_current_row(buf));
1150
1093
}
1151
1094
 
1152
1095
/*
1154
1097
  Currently this table handler doesn't implement most of the fields
1155
1098
  really needed. SHOW also makes use of this data
1156
1099
*/
1157
 
int ha_tina::info(uint flag __attribute__((__unused__)))
 
1100
int ha_tina::info(uint32_t flag __attribute__((unused)))
1158
1101
{
1159
 
  DBUG_ENTER("ha_tina::info");
1160
1102
  /* This is a lie, but you don't want the optimizer to see zero or 1 */
1161
1103
  if (!records_is_known && stats.records < 2) 
1162
1104
    stats.records= 2;
1163
 
  DBUG_RETURN(0);
 
1105
  return(0);
1164
1106
}
1165
1107
 
1166
1108
/*
1173
1115
  if (closest_hole == chain_ptr) /* no more chains */
1174
1116
    *end_pos= file_buff->end();
1175
1117
  else
1176
 
    *end_pos= min(file_buff->end(),
1177
 
                  closest_hole->begin);
 
1118
    *end_pos= std::min(file_buff->end(),
 
1119
                       closest_hole->begin);
1178
1120
  return (closest_hole != chain_ptr) && (*end_pos == closest_hole->begin);
1179
1121
}
1180
1122
 
1189
1131
{
1190
1132
  char updated_fname[FN_REFLEN];
1191
1133
  off_t file_buffer_start= 0;
1192
 
  DBUG_ENTER("ha_tina::rnd_end");
1193
1134
 
1194
1135
  free_root(&blobroot, MYF(0));
1195
1136
  records_is_known= 1;
1215
1156
 
1216
1157
    /* create the file to write updated table if it wasn't yet created */
1217
1158
    if (open_update_temp_file_if_needed())
1218
 
      DBUG_RETURN(-1);
 
1159
      return(-1);
1219
1160
 
1220
1161
    /* write the file with updated info */
1221
1162
    while ((file_buffer_start != -1))     // while not end of file
1227
1168
      if (write_length)
1228
1169
      {
1229
1170
        if (my_write(update_temp_file, 
1230
 
                     (uchar*) (file_buff->ptr() +
 
1171
                     (unsigned char*) (file_buff->ptr() +
1231
1172
                               (write_begin - file_buff->start())),
1232
1173
                     write_length, MYF_RW))
1233
1174
          goto error;
1251
1192
 
1252
1193
    if (my_sync(update_temp_file, MYF(MY_WME)) ||
1253
1194
        my_close(update_temp_file, MYF(0)))
1254
 
      DBUG_RETURN(-1);
 
1195
      return(-1);
1255
1196
 
1256
1197
    share->update_file_opened= false;
1257
1198
 
1258
1199
    if (share->tina_write_opened)
1259
1200
    {
1260
1201
      if (my_close(share->tina_write_filedes, MYF(0)))
1261
 
        DBUG_RETURN(-1);
 
1202
        return(-1);
1262
1203
      /*
1263
1204
        Mark that the writer fd is closed, so that init_tina_writer()
1264
1205
        will reopen it later.
1274
1215
        my_rename(fn_format(updated_fname, share->table_name, "", CSN_EXT,
1275
1216
                            MY_REPLACE_EXT | MY_UNPACK_FILENAME),
1276
1217
                  share->data_file_name, MYF(0)))
1277
 
      DBUG_RETURN(-1);
 
1218
      return(-1);
1278
1219
 
1279
1220
    /* Open the file again */
1280
1221
    if (((data_file= my_open(share->data_file_name, O_RDONLY, MYF(0))) == -1))
1281
 
      DBUG_RETURN(-1);
 
1222
      return(-1);
1282
1223
    /*
1283
1224
      As we reopened the data file, increase share->data_file_version 
1284
1225
      in order to force other threads waiting on a table lock and  
1302
1243
    local_saved_data_file_length= temp_file_length;
1303
1244
  }
1304
1245
 
1305
 
  DBUG_RETURN(0);
 
1246
  return(0);
1306
1247
error:
1307
1248
  my_close(update_temp_file, MYF(0));
1308
1249
  share->update_file_opened= false;
1309
 
  DBUG_RETURN(-1);
 
1250
  return(-1);
1310
1251
}
1311
1252
 
1312
1253
 
1329
1270
*/
1330
1271
 
1331
1272
int ha_tina::repair(THD* thd,
1332
 
                    HA_CHECK_OPT* check_opt __attribute__((__unused__)))
 
1273
                    HA_CHECK_OPT* check_opt __attribute__((unused)))
1333
1274
{
1334
1275
  char repaired_fname[FN_REFLEN];
1335
 
  uchar *buf;
 
1276
  unsigned char *buf;
1336
1277
  File repair_file;
1337
1278
  int rc;
1338
1279
  ha_rows rows_repaired= 0;
1339
1280
  off_t write_begin= 0, write_end;
1340
 
  DBUG_ENTER("ha_tina::repair");
1341
1281
 
1342
1282
  /* empty file */
1343
1283
  if (!share->saved_data_file_length)
1348
1288
 
1349
1289
  /* Don't assert in field::val() functions */
1350
1290
  table->use_all_columns();
1351
 
  if (!(buf= (uchar*) my_malloc(table->s->reclength, MYF(MY_WME))))
1352
 
    DBUG_RETURN(HA_ERR_OUT_OF_MEM);
 
1291
  if (!(buf= (unsigned char*) my_malloc(table->s->reclength, MYF(MY_WME))))
 
1292
    return(HA_ERR_OUT_OF_MEM);
1353
1293
 
1354
1294
  /* position buffer to the start of the file */
1355
1295
  if (init_data_file())
1356
 
    DBUG_RETURN(HA_ERR_CRASHED_ON_REPAIR);
 
1296
    return(HA_ERR_CRASHED_ON_REPAIR);
1357
1297
 
1358
1298
  /*
1359
1299
    Local_saved_data_file_length is initialized during the lock phase.
1376
1316
 
1377
1317
  free_root(&blobroot, MYF(0));
1378
1318
 
1379
 
  my_free((char*)buf, MYF(0));
 
1319
  free((char*)buf);
1380
1320
 
1381
1321
  if (rc == HA_ERR_END_OF_FILE)
1382
1322
  {
1397
1337
                                        "", CSN_EXT,
1398
1338
                                        MY_REPLACE_EXT|MY_UNPACK_FILENAME),
1399
1339
                           0, O_RDWR | O_TRUNC,MYF(MY_WME))) < 0)
1400
 
    DBUG_RETURN(HA_ERR_CRASHED_ON_REPAIR);
 
1340
    return(HA_ERR_CRASHED_ON_REPAIR);
1401
1341
 
1402
1342
  file_buff->init_buff(data_file);
1403
1343
 
1408
1348
  /* write repaired file */
1409
1349
  while (1)
1410
1350
  {
1411
 
    write_end= min(file_buff->end(), current_position);
 
1351
    write_end= std::min(file_buff->end(), current_position);
1412
1352
    if ((write_end - write_begin) &&
1413
 
        (my_write(repair_file, (uchar*)file_buff->ptr(),
 
1353
        (my_write(repair_file, (unsigned char*)file_buff->ptr(),
1414
1354
                  write_end - write_begin, MYF_RW)))
1415
 
      DBUG_RETURN(-1);
 
1355
      return(-1);
1416
1356
 
1417
1357
    write_begin= write_end;
1418
1358
    if (write_end== current_position)
1429
1369
  */
1430
1370
  if (my_close(data_file,MYF(0)) || my_close(repair_file, MYF(0)) ||
1431
1371
      my_rename(repaired_fname, share->data_file_name, MYF(0)))
1432
 
    DBUG_RETURN(-1);
 
1372
    return(-1);
1433
1373
 
1434
1374
  /* Open the file again, it should now be repaired */
1435
1375
  if ((data_file= my_open(share->data_file_name, O_RDWR|O_APPEND,
1436
1376
                          MYF(0))) == -1)
1437
 
     DBUG_RETURN(-1);
 
1377
     return(-1);
1438
1378
 
1439
1379
  /* Set new file size. The file size will be updated by ::update_status() */
1440
1380
  local_saved_data_file_length= (size_t) current_position;
1441
1381
 
1442
1382
end:
1443
1383
  share->crashed= false;
1444
 
  DBUG_RETURN(HA_ADMIN_OK);
 
1384
  return(HA_ADMIN_OK);
1445
1385
}
1446
1386
 
1447
1387
/*
1451
1391
int ha_tina::delete_all_rows()
1452
1392
{
1453
1393
  int rc;
1454
 
  DBUG_ENTER("ha_tina::delete_all_rows");
1455
1394
 
1456
1395
  if (!records_is_known)
1457
 
    DBUG_RETURN(my_errno=HA_ERR_WRONG_COMMAND);
 
1396
    return(my_errno=HA_ERR_WRONG_COMMAND);
1458
1397
 
1459
1398
  if (!share->tina_write_opened)
1460
1399
    if (init_tina_writer())
1461
 
      DBUG_RETURN(-1);
 
1400
      return(-1);
1462
1401
 
1463
1402
  /* Truncate the file to zero size */
1464
1403
  rc= ftruncate(share->tina_write_filedes, 0);
1469
1408
  share->rows_recorded= 0;
1470
1409
  pthread_mutex_unlock(&share->mutex);
1471
1410
  local_saved_data_file_length= 0;
1472
 
  DBUG_RETURN(rc);
 
1411
  return(rc);
1473
1412
}
1474
1413
 
1475
1414
/*
1476
1415
  Called by the database to lock the table. Keep in mind that this
1477
1416
  is an internal lock.
1478
1417
*/
1479
 
THR_LOCK_DATA **ha_tina::store_lock(THD *thd __attribute__((__unused__)),
 
1418
THR_LOCK_DATA **ha_tina::store_lock(THD *thd __attribute__((unused)),
1480
1419
                                    THR_LOCK_DATA **to,
1481
1420
                                    enum thr_lock_type lock_type)
1482
1421
{
1491
1430
  this (the database will call ::open() if it needs to).
1492
1431
*/
1493
1432
 
1494
 
int ha_tina::create(const char *name, TABLE *table_arg,
1495
 
                    HA_CREATE_INFO *create_info __attribute__((__unused__)))
 
1433
int ha_tina::create(const char *name, Table *table_arg,
 
1434
                    HA_CREATE_INFO *create_info __attribute__((unused)))
1496
1435
{
1497
1436
  char name_buff[FN_REFLEN];
1498
1437
  File create_file;
1499
 
  DBUG_ENTER("ha_tina::create");
1500
1438
 
1501
1439
  /*
1502
1440
    check columns
1506
1444
    if ((*field)->real_maybe_null())
1507
1445
    {
1508
1446
      my_error(ER_CHECK_NOT_IMPLEMENTED, MYF(0), "nullable columns");
1509
 
      DBUG_RETURN(HA_ERR_UNSUPPORTED);
 
1447
      return(HA_ERR_UNSUPPORTED);
1510
1448
    }
1511
1449
  }
1512
1450
  
1514
1452
  if ((create_file= my_create(fn_format(name_buff, name, "", CSM_EXT,
1515
1453
                                        MY_REPLACE_EXT|MY_UNPACK_FILENAME), 0,
1516
1454
                              O_RDWR | O_TRUNC,MYF(MY_WME))) < 0)
1517
 
    DBUG_RETURN(-1);
 
1455
    return(-1);
1518
1456
 
1519
1457
  write_meta_file(create_file, 0, false);
1520
1458
  my_close(create_file, MYF(0));
1522
1460
  if ((create_file= my_create(fn_format(name_buff, name, "", CSV_EXT,
1523
1461
                                        MY_REPLACE_EXT|MY_UNPACK_FILENAME),0,
1524
1462
                              O_RDWR | O_TRUNC,MYF(MY_WME))) < 0)
1525
 
    DBUG_RETURN(-1);
 
1463
    return(-1);
1526
1464
 
1527
1465
  my_close(create_file, MYF(0));
1528
1466
 
1529
 
  DBUG_RETURN(0);
 
1467
  return(0);
1530
1468
}
1531
1469
 
1532
1470
int ha_tina::check(THD* thd,
1533
 
                   HA_CHECK_OPT* check_opt __attribute__((__unused__)))
 
1471
                   HA_CHECK_OPT* check_opt __attribute__((unused)))
1534
1472
{
1535
1473
  int rc= 0;
1536
 
  uchar *buf;
 
1474
  unsigned char *buf;
1537
1475
  const char *old_proc_info;
1538
1476
  ha_rows count= share->rows_recorded;
1539
 
  DBUG_ENTER("ha_tina::check");
1540
1477
 
1541
 
  old_proc_info= thd_proc_info(thd, "Checking table");
1542
 
  if (!(buf= (uchar*) my_malloc(table->s->reclength, MYF(MY_WME))))
1543
 
    DBUG_RETURN(HA_ERR_OUT_OF_MEM);
 
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);
1544
1482
 
1545
1483
  /* position buffer to the start of the file */
1546
1484
   if (init_data_file())
1547
 
     DBUG_RETURN(HA_ERR_CRASHED);
 
1485
     return(HA_ERR_CRASHED);
1548
1486
 
1549
1487
  /*
1550
1488
    Local_saved_data_file_length is initialized during the lock phase.
1567
1505
  
1568
1506
  free_root(&blobroot, MYF(0));
1569
1507
 
1570
 
  my_free((char*)buf, MYF(0));
1571
 
  thd_proc_info(thd, old_proc_info);
 
1508
  free((char*)buf);
 
1509
  set_thd_proc_info(thd, old_proc_info);
1572
1510
 
1573
1511
  if ((rc != HA_ERR_END_OF_FILE) || count)
1574
1512
  {
1575
1513
    share->crashed= true;
1576
 
    DBUG_RETURN(HA_ADMIN_CORRUPT);
 
1514
    return(HA_ADMIN_CORRUPT);
1577
1515
  }
1578
1516
  else
1579
 
    DBUG_RETURN(HA_ADMIN_OK);
 
1517
    return(HA_ADMIN_OK);
1580
1518
}
1581
1519
 
1582
1520
 
1583
 
bool ha_tina::check_if_incompatible_data(HA_CREATE_INFO *info __attribute__((__unused__)),
1584
 
                                         uint table_changes __attribute__((__unused__)))
 
1521
bool ha_tina::check_if_incompatible_data(HA_CREATE_INFO *info __attribute__((unused)),
 
1522
                                         uint32_t table_changes __attribute__((unused)))
1585
1523
{
1586
1524
  return COMPATIBLE_DATA_YES;
1587
1525
}
1588
1526
 
1589
 
struct st_mysql_storage_engine csv_storage_engine=
1590
 
{ MYSQL_HANDLERTON_INTERFACE_VERSION };
1591
 
 
1592
1527
mysql_declare_plugin(csv)
1593
1528
{
1594
 
  MYSQL_STORAGE_ENGINE_PLUGIN,
1595
 
  &csv_storage_engine,
 
1529
  DRIZZLE_STORAGE_ENGINE_PLUGIN,
1596
1530
  "CSV",
 
1531
  "1.0",
1597
1532
  "Brian Aker, MySQL AB",
1598
1533
  "CSV storage engine",
1599
1534
  PLUGIN_LICENSE_GPL,
1600
1535
  tina_init_func, /* Plugin Init */
1601
1536
  tina_done_func, /* Plugin Deinit */
1602
 
  0x0100 /* 1.0 */,
1603
1537
  NULL,                       /* status variables                */
1604
1538
  NULL,                       /* system variables                */
1605
1539
  NULL                        /* config options                  */