~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to storage/csv/ha_tina.cc

  • Committer: Jay Pipes
  • Date: 2008-07-17 17:54:00 UTC
  • mto: This revision was merged to the branch mainline in revision 182.
  • Revision ID: jay@mysql.com-20080717175400-xm2aazihjra8mdzq
Removal of DBUG from libdrizzle/ - Round 2

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);
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,
 
100
static uchar* tina_get_key(TINA_SHARE *share, size_t *length,
95
101
                          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
168
    share->crashed= false;
162
170
    share->update_file_opened= false;
163
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);
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) ||
 
263
  if ((meta_buffer[0] != (uchar)TINA_CHECK_HEADER) ||
254
264
      ((bool)(*ptr)== true))
255
 
    return(HA_ERR_CRASHED_ON_USAGE);
 
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,
330
345
  if ((share->tina_write_filedes=
331
346
        my_open(share->data_file_name, O_RDWR|O_APPEND, MYF(0))) == -1)
332
347
  {
 
348
    DBUG_PRINT("info", ("Could not open tina file writes"));
333
349
    share->crashed= true;
334
 
    return(1);
 
350
    DBUG_RETURN(1);
335
351
  }
336
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){
364
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
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
 
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);
1106
1164
}
1107
1165
 
1108
1166
/*
1115
1173
  if (closest_hole == chain_ptr) /* no more chains */
1116
1174
    *end_pos= file_buff->end();
1117
1175
  else
1118
 
    *end_pos= std::min(file_buff->end(),
1119
 
                       closest_hole->begin);
 
1176
    *end_pos= min(file_buff->end(),
 
1177
                  closest_hole->begin);
1120
1178
  return (closest_hole != chain_ptr) && (*end_pos == closest_hole->begin);
1121
1179
}
1122
1180
 
1131
1189
{
1132
1190
  char updated_fname[FN_REFLEN];
1133
1191
  off_t file_buffer_start= 0;
 
1192
  DBUG_ENTER("ha_tina::rnd_end");
1134
1193
 
1135
1194
  free_root(&blobroot, MYF(0));
1136
1195
  records_is_known= 1;
1156
1215
 
1157
1216
    /* create the file to write updated table if it wasn't yet created */
1158
1217
    if (open_update_temp_file_if_needed())
1159
 
      return(-1);
 
1218
      DBUG_RETURN(-1);
1160
1219
 
1161
1220
    /* write the file with updated info */
1162
1221
    while ((file_buffer_start != -1))     // while not end of file
1168
1227
      if (write_length)
1169
1228
      {
1170
1229
        if (my_write(update_temp_file, 
1171
 
                     (unsigned char*) (file_buff->ptr() +
 
1230
                     (uchar*) (file_buff->ptr() +
1172
1231
                               (write_begin - file_buff->start())),
1173
1232
                     write_length, MYF_RW))
1174
1233
          goto error;
1192
1251
 
1193
1252
    if (my_sync(update_temp_file, MYF(MY_WME)) ||
1194
1253
        my_close(update_temp_file, MYF(0)))
1195
 
      return(-1);
 
1254
      DBUG_RETURN(-1);
1196
1255
 
1197
1256
    share->update_file_opened= false;
1198
1257
 
1199
1258
    if (share->tina_write_opened)
1200
1259
    {
1201
1260
      if (my_close(share->tina_write_filedes, MYF(0)))
1202
 
        return(-1);
 
1261
        DBUG_RETURN(-1);
1203
1262
      /*
1204
1263
        Mark that the writer fd is closed, so that init_tina_writer()
1205
1264
        will reopen it later.
1215
1274
        my_rename(fn_format(updated_fname, share->table_name, "", CSN_EXT,
1216
1275
                            MY_REPLACE_EXT | MY_UNPACK_FILENAME),
1217
1276
                  share->data_file_name, MYF(0)))
1218
 
      return(-1);
 
1277
      DBUG_RETURN(-1);
1219
1278
 
1220
1279
    /* Open the file again */
1221
1280
    if (((data_file= my_open(share->data_file_name, O_RDONLY, MYF(0))) == -1))
1222
 
      return(-1);
 
1281
      DBUG_RETURN(-1);
1223
1282
    /*
1224
1283
      As we reopened the data file, increase share->data_file_version 
1225
1284
      in order to force other threads waiting on a table lock and  
1243
1302
    local_saved_data_file_length= temp_file_length;
1244
1303
  }
1245
1304
 
1246
 
  return(0);
 
1305
  DBUG_RETURN(0);
1247
1306
error:
1248
1307
  my_close(update_temp_file, MYF(0));
1249
1308
  share->update_file_opened= false;
1250
 
  return(-1);
 
1309
  DBUG_RETURN(-1);
1251
1310
}
1252
1311
 
1253
1312
 
1270
1329
*/
1271
1330
 
1272
1331
int ha_tina::repair(THD* thd,
1273
 
                    HA_CHECK_OPT* check_opt __attribute__((unused)))
 
1332
                    HA_CHECK_OPT* check_opt __attribute__((__unused__)))
1274
1333
{
1275
1334
  char repaired_fname[FN_REFLEN];
1276
 
  unsigned char *buf;
 
1335
  uchar *buf;
1277
1336
  File repair_file;
1278
1337
  int rc;
1279
1338
  ha_rows rows_repaired= 0;
1280
1339
  off_t write_begin= 0, write_end;
 
1340
  DBUG_ENTER("ha_tina::repair");
1281
1341
 
1282
1342
  /* empty file */
1283
1343
  if (!share->saved_data_file_length)
1288
1348
 
1289
1349
  /* Don't assert in field::val() functions */
1290
1350
  table->use_all_columns();
1291
 
  if (!(buf= (unsigned char*) my_malloc(table->s->reclength, MYF(MY_WME))))
1292
 
    return(HA_ERR_OUT_OF_MEM);
 
1351
  if (!(buf= (uchar*) my_malloc(table->s->reclength, MYF(MY_WME))))
 
1352
    DBUG_RETURN(HA_ERR_OUT_OF_MEM);
1293
1353
 
1294
1354
  /* position buffer to the start of the file */
1295
1355
  if (init_data_file())
1296
 
    return(HA_ERR_CRASHED_ON_REPAIR);
 
1356
    DBUG_RETURN(HA_ERR_CRASHED_ON_REPAIR);
1297
1357
 
1298
1358
  /*
1299
1359
    Local_saved_data_file_length is initialized during the lock phase.
1316
1376
 
1317
1377
  free_root(&blobroot, MYF(0));
1318
1378
 
1319
 
  free((char*)buf);
 
1379
  my_free((char*)buf, MYF(0));
1320
1380
 
1321
1381
  if (rc == HA_ERR_END_OF_FILE)
1322
1382
  {
1337
1397
                                        "", CSN_EXT,
1338
1398
                                        MY_REPLACE_EXT|MY_UNPACK_FILENAME),
1339
1399
                           0, O_RDWR | O_TRUNC,MYF(MY_WME))) < 0)
1340
 
    return(HA_ERR_CRASHED_ON_REPAIR);
 
1400
    DBUG_RETURN(HA_ERR_CRASHED_ON_REPAIR);
1341
1401
 
1342
1402
  file_buff->init_buff(data_file);
1343
1403
 
1348
1408
  /* write repaired file */
1349
1409
  while (1)
1350
1410
  {
1351
 
    write_end= std::min(file_buff->end(), current_position);
 
1411
    write_end= min(file_buff->end(), current_position);
1352
1412
    if ((write_end - write_begin) &&
1353
 
        (my_write(repair_file, (unsigned char*)file_buff->ptr(),
 
1413
        (my_write(repair_file, (uchar*)file_buff->ptr(),
1354
1414
                  write_end - write_begin, MYF_RW)))
1355
 
      return(-1);
 
1415
      DBUG_RETURN(-1);
1356
1416
 
1357
1417
    write_begin= write_end;
1358
1418
    if (write_end== current_position)
1369
1429
  */
1370
1430
  if (my_close(data_file,MYF(0)) || my_close(repair_file, MYF(0)) ||
1371
1431
      my_rename(repaired_fname, share->data_file_name, MYF(0)))
1372
 
    return(-1);
 
1432
    DBUG_RETURN(-1);
1373
1433
 
1374
1434
  /* Open the file again, it should now be repaired */
1375
1435
  if ((data_file= my_open(share->data_file_name, O_RDWR|O_APPEND,
1376
1436
                          MYF(0))) == -1)
1377
 
     return(-1);
 
1437
     DBUG_RETURN(-1);
1378
1438
 
1379
1439
  /* Set new file size. The file size will be updated by ::update_status() */
1380
1440
  local_saved_data_file_length= (size_t) current_position;
1381
1441
 
1382
1442
end:
1383
1443
  share->crashed= false;
1384
 
  return(HA_ADMIN_OK);
 
1444
  DBUG_RETURN(HA_ADMIN_OK);
1385
1445
}
1386
1446
 
1387
1447
/*
1391
1451
int ha_tina::delete_all_rows()
1392
1452
{
1393
1453
  int rc;
 
1454
  DBUG_ENTER("ha_tina::delete_all_rows");
1394
1455
 
1395
1456
  if (!records_is_known)
1396
 
    return(my_errno=HA_ERR_WRONG_COMMAND);
 
1457
    DBUG_RETURN(my_errno=HA_ERR_WRONG_COMMAND);
1397
1458
 
1398
1459
  if (!share->tina_write_opened)
1399
1460
    if (init_tina_writer())
1400
 
      return(-1);
 
1461
      DBUG_RETURN(-1);
1401
1462
 
1402
1463
  /* Truncate the file to zero size */
1403
1464
  rc= ftruncate(share->tina_write_filedes, 0);
1408
1469
  share->rows_recorded= 0;
1409
1470
  pthread_mutex_unlock(&share->mutex);
1410
1471
  local_saved_data_file_length= 0;
1411
 
  return(rc);
 
1472
  DBUG_RETURN(rc);
1412
1473
}
1413
1474
 
1414
1475
/*
1415
1476
  Called by the database to lock the table. Keep in mind that this
1416
1477
  is an internal lock.
1417
1478
*/
1418
 
THR_LOCK_DATA **ha_tina::store_lock(THD *thd __attribute__((unused)),
 
1479
THR_LOCK_DATA **ha_tina::store_lock(THD *thd __attribute__((__unused__)),
1419
1480
                                    THR_LOCK_DATA **to,
1420
1481
                                    enum thr_lock_type lock_type)
1421
1482
{
1430
1491
  this (the database will call ::open() if it needs to).
1431
1492
*/
1432
1493
 
1433
 
int ha_tina::create(const char *name, Table *table_arg,
1434
 
                    HA_CREATE_INFO *create_info __attribute__((unused)))
 
1494
int ha_tina::create(const char *name, TABLE *table_arg,
 
1495
                    HA_CREATE_INFO *create_info __attribute__((__unused__)))
1435
1496
{
1436
1497
  char name_buff[FN_REFLEN];
1437
1498
  File create_file;
 
1499
  DBUG_ENTER("ha_tina::create");
1438
1500
 
1439
1501
  /*
1440
1502
    check columns
1444
1506
    if ((*field)->real_maybe_null())
1445
1507
    {
1446
1508
      my_error(ER_CHECK_NOT_IMPLEMENTED, MYF(0), "nullable columns");
1447
 
      return(HA_ERR_UNSUPPORTED);
 
1509
      DBUG_RETURN(HA_ERR_UNSUPPORTED);
1448
1510
    }
1449
1511
  }
1450
1512
  
1452
1514
  if ((create_file= my_create(fn_format(name_buff, name, "", CSM_EXT,
1453
1515
                                        MY_REPLACE_EXT|MY_UNPACK_FILENAME), 0,
1454
1516
                              O_RDWR | O_TRUNC,MYF(MY_WME))) < 0)
1455
 
    return(-1);
 
1517
    DBUG_RETURN(-1);
1456
1518
 
1457
1519
  write_meta_file(create_file, 0, false);
1458
1520
  my_close(create_file, MYF(0));
1460
1522
  if ((create_file= my_create(fn_format(name_buff, name, "", CSV_EXT,
1461
1523
                                        MY_REPLACE_EXT|MY_UNPACK_FILENAME),0,
1462
1524
                              O_RDWR | O_TRUNC,MYF(MY_WME))) < 0)
1463
 
    return(-1);
 
1525
    DBUG_RETURN(-1);
1464
1526
 
1465
1527
  my_close(create_file, MYF(0));
1466
1528
 
1467
 
  return(0);
 
1529
  DBUG_RETURN(0);
1468
1530
}
1469
1531
 
1470
1532
int ha_tina::check(THD* thd,
1471
 
                   HA_CHECK_OPT* check_opt __attribute__((unused)))
 
1533
                   HA_CHECK_OPT* check_opt __attribute__((__unused__)))
1472
1534
{
1473
1535
  int rc= 0;
1474
 
  unsigned char *buf;
 
1536
  uchar *buf;
1475
1537
  const char *old_proc_info;
1476
1538
  ha_rows count= share->rows_recorded;
 
1539
  DBUG_ENTER("ha_tina::check");
1477
1540
 
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);
 
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);
1482
1544
 
1483
1545
  /* position buffer to the start of the file */
1484
1546
   if (init_data_file())
1485
 
     return(HA_ERR_CRASHED);
 
1547
     DBUG_RETURN(HA_ERR_CRASHED);
1486
1548
 
1487
1549
  /*
1488
1550
    Local_saved_data_file_length is initialized during the lock phase.
1505
1567
  
1506
1568
  free_root(&blobroot, MYF(0));
1507
1569
 
1508
 
  free((char*)buf);
1509
 
  set_thd_proc_info(thd, old_proc_info);
 
1570
  my_free((char*)buf, MYF(0));
 
1571
  thd_proc_info(thd, old_proc_info);
1510
1572
 
1511
1573
  if ((rc != HA_ERR_END_OF_FILE) || count)
1512
1574
  {
1513
1575
    share->crashed= true;
1514
 
    return(HA_ADMIN_CORRUPT);
 
1576
    DBUG_RETURN(HA_ADMIN_CORRUPT);
1515
1577
  }
1516
1578
  else
1517
 
    return(HA_ADMIN_OK);
 
1579
    DBUG_RETURN(HA_ADMIN_OK);
1518
1580
}
1519
1581
 
1520
1582
 
1521
 
bool ha_tina::check_if_incompatible_data(HA_CREATE_INFO *info __attribute__((unused)),
1522
 
                                         uint32_t table_changes __attribute__((unused)))
 
1583
bool ha_tina::check_if_incompatible_data(HA_CREATE_INFO *info __attribute__((__unused__)),
 
1584
                                         uint table_changes __attribute__((__unused__)))
1523
1585
{
1524
1586
  return COMPATIBLE_DATA_YES;
1525
1587
}
1526
1588
 
 
1589
struct st_mysql_storage_engine csv_storage_engine=
 
1590
{ MYSQL_HANDLERTON_INTERFACE_VERSION };
 
1591
 
1527
1592
mysql_declare_plugin(csv)
1528
1593
{
1529
 
  DRIZZLE_STORAGE_ENGINE_PLUGIN,
 
1594
  MYSQL_STORAGE_ENGINE_PLUGIN,
 
1595
  &csv_storage_engine,
1530
1596
  "CSV",
1531
 
  "1.0",
1532
1597
  "Brian Aker, MySQL AB",
1533
1598
  "CSV storage engine",
1534
1599
  PLUGIN_LICENSE_GPL,
1535
1600
  tina_init_func, /* Plugin Init */
1536
1601
  tina_done_func, /* Plugin Deinit */
 
1602
  0x0100 /* 1.0 */,
1537
1603
  NULL,                       /* status variables                */
1538
1604
  NULL,                       /* system variables                */
1539
1605
  NULL                        /* config options                  */