~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to storage/csv/ha_tina.cc

Removing global errbuff and cleaning up two remaining instances that referenced it.

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>
44
 
#include "ha_tina.h"
45
 
 
 
43
#include <drizzled/server_includes.h>
 
44
#include <drizzled/field.h>
 
45
#include <drizzled/field/blob.h>
 
46
#include <drizzled/field/timestamp.h>
 
47
#include <storage/csv/ha_tina.h>
 
48
#include <drizzled/error.h>
 
49
#include <drizzled/table.h>
 
50
#include <drizzled/session.h>
 
51
 
 
52
#include <string>
 
53
 
 
54
using namespace std;
 
55
 
 
56
static const string engine_name("CSV");
46
57
 
47
58
/*
48
59
  unsigned char + unsigned char + uint64_t + uint64_t + uint64_t + uint64_t + unsigned char
70
81
/* Stuff for shares */
71
82
pthread_mutex_t tina_mutex;
72
83
static HASH tina_open_tables;
73
 
static handler *tina_create_handler(handlerton *hton,
74
 
                                    TABLE_SHARE *table, 
75
 
                                    MEM_ROOT *mem_root);
76
 
 
77
84
 
78
85
/*****************************************************************************
79
86
 ** TINA tables
91
98
  return ( a->begin > b->begin ? 1 : ( a->begin < b->begin ? -1 : 0 ) );
92
99
}
93
100
 
94
 
static unsigned char* tina_get_key(TINA_SHARE *share, size_t *length,
95
 
                          bool not_used __attribute__((unused)))
 
101
static unsigned char* tina_get_key(TINA_SHARE *share, size_t *length, bool)
96
102
{
97
103
  *length=share->table_name_length;
98
104
  return (unsigned char*) share->table_name;
99
105
}
100
106
 
101
 
static int tina_init_func(void *p)
102
 
{
103
 
  handlerton *tina_hton;
104
 
 
105
 
  tina_hton= (handlerton *)p;
 
107
class Tina : public StorageEngine
 
108
{
 
109
public:
 
110
  Tina(const string& name_arg)
 
111
   : StorageEngine(name_arg, HTON_CAN_RECREATE | HTON_SUPPORT_LOG_TABLES |
 
112
                             HTON_NO_PARTITION) {}
 
113
  virtual handler *create(TABLE_SHARE *table,
 
114
                          MEM_ROOT *mem_root)
 
115
  {
 
116
    return new (mem_root) ha_tina(this, table);
 
117
  }
 
118
};
 
119
 
 
120
static Tina *tina_engine= NULL;
 
121
 
 
122
static int tina_init_func(PluginRegistry &registry)
 
123
{
 
124
 
 
125
  tina_engine= new Tina(engine_name);
 
126
  registry.add(tina_engine);
 
127
 
106
128
  pthread_mutex_init(&tina_mutex,MY_MUTEX_INIT_FAST);
107
129
  (void) hash_init(&tina_open_tables,system_charset_info,32,0,0,
108
130
                   (hash_get_key) tina_get_key,0,0);
109
 
  tina_hton->state= SHOW_OPTION_YES;
110
 
  tina_hton->create= tina_create_handler;
111
 
  tina_hton->flags= (HTON_CAN_RECREATE | HTON_SUPPORT_LOG_TABLES | 
112
 
                     HTON_NO_PARTITION);
113
131
  return 0;
114
132
}
115
133
 
116
 
static int tina_done_func(void *p __attribute__((unused)))
 
134
static int tina_done_func(PluginRegistry &registry)
117
135
{
 
136
  registry.remove(tina_engine);
 
137
  delete tina_engine;
 
138
 
118
139
  hash_free(&tina_open_tables);
119
140
  pthread_mutex_destroy(&tina_mutex);
120
141
 
125
146
/*
126
147
  Simple lock controls.
127
148
*/
128
 
static TINA_SHARE *get_share(const char *table_name,
129
 
                             Table *table __attribute__((unused)))
 
149
static TINA_SHARE *get_share(const char *table_name, Table *)
130
150
{
131
151
  TINA_SHARE *share;
132
152
  char meta_file_name[FN_REFLEN];
162
182
    share->update_file_opened= false;
163
183
    share->tina_write_opened= false;
164
184
    share->data_file_version= 0;
165
 
    my_stpcpy(share->table_name, table_name);
 
185
    strcpy(share->table_name, table_name);
166
186
    fn_format(share->data_file_name, table_name, "", CSV_EXT,
167
187
              MY_REPLACE_EXT|MY_UNPACK_FILENAME);
168
188
    fn_format(meta_file_name, table_name, "", CSM_EXT,
231
251
  unsigned char meta_buffer[META_BUFFER_SIZE];
232
252
  unsigned char *ptr= meta_buffer;
233
253
 
234
 
  my_seek(meta_file, 0, MY_SEEK_SET, MYF(0));
 
254
  lseek(meta_file, 0, SEEK_SET);
235
255
  if (my_read(meta_file, (unsigned char*)meta_buffer, META_BUFFER_SIZE, 0)
236
256
      != META_BUFFER_SIZE)
237
257
    return(HA_ERR_CRASHED_ON_USAGE);
298
318
  ptr+= 3*sizeof(uint64_t);
299
319
  *ptr= (unsigned char)dirty;
300
320
 
301
 
  my_seek(meta_file, 0, MY_SEEK_SET, MYF(0));
 
321
  lseek(meta_file, 0, SEEK_SET);
302
322
  if (my_write(meta_file, (unsigned char *)meta_buffer, META_BUFFER_SIZE, 0)
303
323
      != META_BUFFER_SIZE)
304
324
    return(-1);
308
328
  return(0);
309
329
}
310
330
 
311
 
bool ha_tina::check_and_repair(THD *thd)
 
331
bool ha_tina::check_and_repair(Session *session)
312
332
{
313
333
  HA_CHECK_OPT check_opt;
314
334
 
315
335
  check_opt.init();
316
336
 
317
 
  return(repair(thd, &check_opt));
 
337
  return(repair(session, &check_opt));
318
338
}
319
339
 
320
340
 
413
433
}
414
434
 
415
435
 
416
 
static handler *tina_create_handler(handlerton *hton,
417
 
                                    TABLE_SHARE *table, 
418
 
                                    MEM_ROOT *mem_root)
419
 
{
420
 
  return new (mem_root) ha_tina(hton, table);
421
 
}
422
 
 
423
 
 
424
 
ha_tina::ha_tina(handlerton *hton, TABLE_SHARE *table_arg)
425
 
  :handler(hton, table_arg),
 
436
 
 
437
ha_tina::ha_tina(StorageEngine *engine_arg, TABLE_SHARE *table_arg)
 
438
  :handler(engine_arg, table_arg),
426
439
  /*
427
440
    These definitions are found in handler.h
428
441
    They are not probably completely right.
442
455
  Encode a buffer into the quoted format.
443
456
*/
444
457
 
445
 
int ha_tina::encode_quote(unsigned char *buf __attribute__((unused)))
 
458
int ha_tina::encode_quote(unsigned char *)
446
459
{
447
460
  char attribute_buffer[1024];
448
461
  String attribute(attribute_buffer, sizeof(attribute_buffer),
455
468
    const char *ptr;
456
469
    const char *end_ptr;
457
470
    const bool was_null= (*field)->is_null();
458
 
    
 
471
 
459
472
    /*
460
473
      assistance for backwards compatibility in production builds.
461
474
      note: this will not work for ENUM columns.
467
480
    }
468
481
 
469
482
    (*field)->val_str(&attribute,&attribute);
470
 
    
 
483
 
471
484
    if (was_null)
472
485
      (*field)->set_null();
473
486
 
478
491
 
479
492
      buffer.append('"');
480
493
 
481
 
      while (ptr < end_ptr) 
 
494
      while (ptr < end_ptr)
482
495
      {
483
496
        if (*ptr == '"')
484
497
        {
543
556
      chain_size += DEFAULT_CHAIN_LENGTH;
544
557
      if (chain_alloced)
545
558
      {
546
 
        /* Must cast since my_malloc unlike malloc doesn't have a void ptr */
547
 
        if ((chain= (tina_set *) my_realloc((unsigned char*)chain,
548
 
                                            chain_size, MYF(MY_WME))) == NULL)
 
559
        if ((chain= (tina_set *) realloc(chain, chain_size)) == NULL)
549
560
          return -1;
550
561
      }
551
562
      else
552
563
      {
553
 
        tina_set *ptr= (tina_set *) my_malloc(chain_size * sizeof(tina_set),
554
 
                                              MYF(MY_WME));
 
564
        tina_set *ptr= (tina_set *) malloc(chain_size * sizeof(tina_set));
 
565
        if (ptr == NULL)
 
566
          return -1;
555
567
        memcpy(ptr, chain, DEFAULT_CHAIN_LENGTH * sizeof(tina_set));
556
568
        chain= ptr;
557
569
        chain_alloced++;
589
601
    return(HA_ERR_END_OF_FILE);
590
602
 
591
603
  /* We must read all columns in case a table is opened for update */
592
 
  read_all= !bitmap_is_clear_all(table->write_set);
 
604
  read_all= !table->write_set->none();
593
605
  error= HA_ERR_CRASHED_ON_USAGE;
594
606
 
595
607
  memset(buf, 0, table->s->null_bytes);
597
609
  for (Field **field=table->field ; *field ; field++)
598
610
  {
599
611
    char curr_char;
600
 
    
 
612
 
601
613
    buffer.length(0);
602
614
    if (curr_offset >= end_offset)
603
615
      goto err;
645
657
        }
646
658
      }
647
659
    }
648
 
    else 
 
660
    else
649
661
    {
650
662
      for(; curr_offset < end_offset; curr_offset++)
651
663
      {
659
671
      }
660
672
    }
661
673
 
662
 
    if (read_all || bitmap_is_set(table->read_set, (*field)->field_index))
 
674
    if (read_all || table->read_set->test((*field)->field_index))
663
675
    {
664
676
      if ((*field)->store(buffer.ptr(), buffer.length(), buffer.charset(),
665
677
                          CHECK_FIELD_WARN))
669
681
        Field_blob *blob= *(Field_blob**) field;
670
682
        unsigned char *src, *tgt;
671
683
        uint32_t length, packlength;
672
 
        
 
684
 
673
685
        packlength= blob->pack_length_no_ptr();
674
686
        length= blob->get_length(blob->ptr);
675
687
        memcpy(&src, blob->ptr + packlength, sizeof(char*));
676
688
        if (src)
677
689
        {
678
690
          tgt= (unsigned char*) alloc_root(&blobroot, length);
679
 
          memcpy(tgt, src, length);
 
691
          memmove(tgt, src, length);
680
692
          memcpy(blob->ptr + packlength, &tgt, sizeof(char*));
681
693
        }
682
694
      }
710
722
  for CSV engine. For more details see mysys/thr_lock.c
711
723
*/
712
724
 
713
 
void tina_get_status(void* param,
714
 
                     int concurrent_insert __attribute__((unused)))
 
725
void tina_get_status(void* param, int)
715
726
{
716
727
  ha_tina *tina= (ha_tina*) param;
717
728
  tina->get_status();
724
735
}
725
736
 
726
737
/* this should exist and return 0 for concurrent insert to work */
727
 
bool tina_check_status(void* param __attribute__((unused)))
 
738
bool tina_check_status(void *)
728
739
{
729
740
  return 0;
730
741
}
764
775
    For log tables concurrent insert works different. The reason is that
765
776
    log tables are always opened and locked. And as they do not unlock
766
777
    tables, the file length after writes should be updated in a different
767
 
    way. 
 
778
    way.
768
779
*/
769
780
 
770
781
void ha_tina::update_status()
779
790
  this will not be called for every request. Any sort of positions
780
791
  that need to be reset should be kept in the ::extra() call.
781
792
*/
782
 
int ha_tina::open(const char *name, int mode __attribute__((unused)),
783
 
                  uint32_t open_options)
 
793
int ha_tina::open(const char *name, int, uint32_t open_options)
784
794
{
785
795
  if (!(share= get_share(name, table)))
786
 
    return(HA_ERR_OUT_OF_MEM);
 
796
    return(ENOENT);
787
797
 
788
798
  if (share->crashed && !(open_options & HA_OPEN_FOR_REPAIR))
789
799
  {
836
846
 
837
847
  ha_statistic_increment(&SSV::ha_write_count);
838
848
 
839
 
  if (table->timestamp_field_type & TIMESTAMP_AUTO_SET_ON_INSERT)
840
 
    table->timestamp_field->set_time();
841
 
 
842
849
  size= encode_quote(buf);
843
850
 
844
851
  if (!share->tina_write_opened)
890
897
  This will be called in a table scan right before the previous ::rnd_next()
891
898
  call.
892
899
*/
893
 
int ha_tina::update_row(const unsigned char * old_data __attribute__((unused)),
894
 
                        unsigned char * new_data)
 
900
int ha_tina::update_row(const unsigned char *, unsigned char * new_data)
895
901
{
896
902
  int size;
897
903
  int rc= -1;
904
910
  size= encode_quote(new_data);
905
911
 
906
912
  /*
907
 
    During update we mark each updating record as deleted 
908
 
    (see the chain_append()) then write new one to the temporary data file. 
 
913
    During update we mark each updating record as deleted
 
914
    (see the chain_append()) then write new one to the temporary data file.
909
915
    At the end of the sequence in the rnd_end() we append all non-marked
910
916
    records from the data file to the temporary data file then rename it.
911
917
    The temp_file_length is used to calculate new data file length.
936
942
  The table will then be deleted/positioned based on the ORDER (so RANDOM,
937
943
  DESC, ASC).
938
944
*/
939
 
int ha_tina::delete_row(const unsigned char * buf __attribute__((unused)))
 
945
int ha_tina::delete_row(const unsigned char *)
940
946
{
941
947
  ha_statistic_increment(&SSV::ha_delete_count);
942
948
 
956
962
 
957
963
/**
958
964
  @brief Initialize the data file.
959
 
  
 
965
 
960
966
  @details Compare the local version of the data file with the shared one.
961
967
  If they differ, there are some changes behind and we have to reopen
962
968
  the data file to make the changes visible.
963
 
  Call @c file_buff->init_buff() at the end to read the beginning of the 
 
969
  Call @c file_buff->init_buff() at the end to read the beginning of the
964
970
  data file into buffer.
965
 
  
 
971
 
966
972
  @retval  0  OK.
967
973
  @retval  1  There was an error.
968
974
*/
1012
1018
 
1013
1019
*/
1014
1020
 
1015
 
int ha_tina::rnd_init(bool scan __attribute__((unused)))
 
1021
int ha_tina::rnd_init(bool)
1016
1022
{
1017
1023
  /* set buffer to the beginning of the file */
1018
1024
  if (share->crashed || init_data_file())
1073
1079
  its just a position. Look at the bdb code if you want to see a case
1074
1080
  where something other then a number is stored.
1075
1081
*/
1076
 
void ha_tina::position(const unsigned char *record __attribute__((unused)))
 
1082
void ha_tina::position(const unsigned char *)
1077
1083
{
1078
1084
  my_store_ptr(ref, ref_length, current_position);
1079
1085
  return;
1097
1103
  Currently this table handler doesn't implement most of the fields
1098
1104
  really needed. SHOW also makes use of this data
1099
1105
*/
1100
 
int ha_tina::info(uint32_t flag __attribute__((unused)))
 
1106
int ha_tina::info(uint32_t)
1101
1107
{
1102
1108
  /* This is a lie, but you don't want the optimizer to see zero or 1 */
1103
 
  if (!records_is_known && stats.records < 2) 
 
1109
  if (!records_is_known && stats.records < 2)
1104
1110
    stats.records= 2;
1105
1111
  return(0);
1106
1112
}
1163
1169
    {
1164
1170
      bool in_hole= get_write_pos(&write_end, ptr);
1165
1171
      off_t write_length= write_end - write_begin;
 
1172
      if ((uint64_t)write_length > SIZE_MAX)
 
1173
      {
 
1174
        goto error;
 
1175
      }
1166
1176
 
1167
1177
      /* if there is something to write, write it */
1168
1178
      if (write_length)
1169
1179
      {
1170
 
        if (my_write(update_temp_file, 
 
1180
        if (my_write(update_temp_file,
1171
1181
                     (unsigned char*) (file_buff->ptr() +
1172
1182
                               (write_begin - file_buff->start())),
1173
 
                     write_length, MYF_RW))
 
1183
                     (size_t)write_length, MYF_RW))
1174
1184
          goto error;
1175
1185
        temp_file_length+= write_length;
1176
1186
      }
1221
1231
    if (((data_file= my_open(share->data_file_name, O_RDONLY, MYF(0))) == -1))
1222
1232
      return(-1);
1223
1233
    /*
1224
 
      As we reopened the data file, increase share->data_file_version 
1225
 
      in order to force other threads waiting on a table lock and  
 
1234
      As we reopened the data file, increase share->data_file_version
 
1235
      in order to force other threads waiting on a table lock and
1226
1236
      have already opened the table to reopen the data file.
1227
1237
      That makes the latest changes become visible to them.
1228
 
      Update local_data_file_version as no need to reopen it in the 
 
1238
      Update local_data_file_version as no need to reopen it in the
1229
1239
      current thread.
1230
1240
    */
1231
1241
    share->data_file_version++;
1236
1246
      Here we record this fact to the meta-file.
1237
1247
    */
1238
1248
    (void)write_meta_file(share->meta_file, share->rows_recorded, false);
1239
 
    /* 
1240
 
      Update local_saved_data_file_length with the real length of the 
 
1249
    /*
 
1250
      Update local_saved_data_file_length with the real length of the
1241
1251
      data file.
1242
1252
    */
1243
1253
    local_saved_data_file_length= temp_file_length;
1256
1266
 
1257
1267
  SYNOPSIS
1258
1268
    repair()
1259
 
    thd         The thread, performing repair
 
1269
    session         The thread, performing repair
1260
1270
    check_opt   The options for repair. We do not use it currently.
1261
1271
 
1262
1272
  DESCRIPTION
1269
1279
         rows (after the first bad one) as well.
1270
1280
*/
1271
1281
 
1272
 
int ha_tina::repair(THD* thd,
1273
 
                    HA_CHECK_OPT* check_opt __attribute__((unused)))
 
1282
int ha_tina::repair(Session* session, HA_CHECK_OPT *)
1274
1283
{
1275
1284
  char repaired_fname[FN_REFLEN];
1276
1285
  unsigned char *buf;
1288
1297
 
1289
1298
  /* Don't assert in field::val() functions */
1290
1299
  table->use_all_columns();
1291
 
  if (!(buf= (unsigned char*) my_malloc(table->s->reclength, MYF(MY_WME))))
 
1300
  if (!(buf= (unsigned char*) malloc(table->s->reclength)))
1292
1301
    return(HA_ERR_OUT_OF_MEM);
1293
1302
 
1294
1303
  /* position buffer to the start of the file */
1309
1318
  /* Read the file row-by-row. If everything is ok, repair is not needed. */
1310
1319
  while (!(rc= find_current_row(buf)))
1311
1320
  {
1312
 
    thd_inc_row_count(thd);
 
1321
    session_inc_row_count(session);
1313
1322
    rows_repaired++;
1314
1323
    current_position= next_position;
1315
1324
  }
1349
1358
  while (1)
1350
1359
  {
1351
1360
    write_end= std::min(file_buff->end(), current_position);
1352
 
    if ((write_end - write_begin) &&
 
1361
 
 
1362
    off_t write_length= write_end - write_begin;
 
1363
    if ((uint64_t)write_length > SIZE_MAX)
 
1364
    {
 
1365
      return -1;
 
1366
    }
 
1367
    if ((write_length) &&
1353
1368
        (my_write(repair_file, (unsigned char*)file_buff->ptr(),
1354
 
                  write_end - write_begin, MYF_RW)))
 
1369
                  (size_t)write_length, MYF_RW)))
1355
1370
      return(-1);
1356
1371
 
1357
1372
    write_begin= write_end;
1415
1430
  Called by the database to lock the table. Keep in mind that this
1416
1431
  is an internal lock.
1417
1432
*/
1418
 
THR_LOCK_DATA **ha_tina::store_lock(THD *thd __attribute__((unused)),
 
1433
THR_LOCK_DATA **ha_tina::store_lock(Session *,
1419
1434
                                    THR_LOCK_DATA **to,
1420
1435
                                    enum thr_lock_type lock_type)
1421
1436
{
1425
1440
  return to;
1426
1441
}
1427
1442
 
1428
 
/* 
 
1443
/*
1429
1444
  Create a table. You do not want to leave the table open after a call to
1430
1445
  this (the database will call ::open() if it needs to).
1431
1446
*/
1432
1447
 
1433
 
int ha_tina::create(const char *name, Table *table_arg,
1434
 
                    HA_CREATE_INFO *create_info __attribute__((unused)))
 
1448
int ha_tina::create(const char *name, Table *table_arg, HA_CREATE_INFO *)
1435
1449
{
1436
1450
  char name_buff[FN_REFLEN];
1437
1451
  File create_file;
1447
1461
      return(HA_ERR_UNSUPPORTED);
1448
1462
    }
1449
1463
  }
1450
 
  
 
1464
 
1451
1465
 
1452
1466
  if ((create_file= my_create(fn_format(name_buff, name, "", CSM_EXT,
1453
1467
                                        MY_REPLACE_EXT|MY_UNPACK_FILENAME), 0,
1467
1481
  return(0);
1468
1482
}
1469
1483
 
1470
 
int ha_tina::check(THD* thd,
1471
 
                   HA_CHECK_OPT* check_opt __attribute__((unused)))
 
1484
int ha_tina::check(Session* session, HA_CHECK_OPT *)
1472
1485
{
1473
1486
  int rc= 0;
1474
1487
  unsigned char *buf;
1475
1488
  const char *old_proc_info;
1476
1489
  ha_rows count= share->rows_recorded;
1477
1490
 
1478
 
  old_proc_info= thd_proc_info(thd, "Checking table");
1479
 
  if (!(buf= (unsigned char*) my_malloc(table->s->reclength, MYF(MY_WME))))
 
1491
  old_proc_info= get_session_proc_info(session);
 
1492
  set_session_proc_info(session, "Checking table");
 
1493
  if (!(buf= (unsigned char*) malloc(table->s->reclength)))
1480
1494
    return(HA_ERR_OUT_OF_MEM);
1481
1495
 
1482
1496
  /* position buffer to the start of the file */
1497
1511
  /* Read the file row-by-row. If everything is ok, repair is not needed. */
1498
1512
  while (!(rc= find_current_row(buf)))
1499
1513
  {
1500
 
    thd_inc_row_count(thd);
 
1514
    session_inc_row_count(session);
1501
1515
    count--;
1502
1516
    current_position= next_position;
1503
1517
  }
1504
 
  
 
1518
 
1505
1519
  free_root(&blobroot, MYF(0));
1506
1520
 
1507
1521
  free((char*)buf);
1508
 
  thd_proc_info(thd, old_proc_info);
 
1522
  set_session_proc_info(session, old_proc_info);
1509
1523
 
1510
1524
  if ((rc != HA_ERR_END_OF_FILE) || count)
1511
1525
  {
1517
1531
}
1518
1532
 
1519
1533
 
1520
 
bool ha_tina::check_if_incompatible_data(HA_CREATE_INFO *info __attribute__((unused)),
1521
 
                                         uint32_t table_changes __attribute__((unused)))
 
1534
bool ha_tina::check_if_incompatible_data(HA_CREATE_INFO *, uint32_t)
1522
1535
{
1523
1536
  return COMPATIBLE_DATA_YES;
1524
1537
}
1525
1538
 
1526
 
mysql_declare_plugin(csv)
 
1539
drizzle_declare_plugin(csv)
1527
1540
{
1528
 
  DRIZZLE_STORAGE_ENGINE_PLUGIN,
1529
1541
  "CSV",
1530
1542
  "1.0",
1531
1543
  "Brian Aker, MySQL AB",
1537
1549
  NULL,                       /* system variables                */
1538
1550
  NULL                        /* config options                  */
1539
1551
}
1540
 
mysql_declare_plugin_end;
 
1552
drizzle_declare_plugin_end;
1541
1553