~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to storage/csv/ha_tina.cc

Moved the last of the libdrizzleclient calls into Protocol.

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