~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to storage/csv/ha_tina.cc

  • Committer: Brian Aker
  • Date: 2008-08-12 03:12:57 UTC
  • Revision ID: brian@tangent.org-20080812031257-ln3uk87y1r22byeg
First pass of new sql_db.cc work

Show diffs side-by-side

added added

removed removed

Lines of Context:
45
45
 
46
46
 
47
47
/*
48
 
  unsigned char + unsigned char + uint64_t + uint64_t + uint64_t + uint64_t + unsigned char
 
48
  uchar + uchar + uint64_t + uint64_t + uint64_t + uint64_t + uchar
49
49
*/
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)
 
50
#define META_BUFFER_SIZE sizeof(uchar) + sizeof(uchar) + sizeof(uint64_t) \
 
51
  + sizeof(uint64_t) + sizeof(uint64_t) + sizeof(uint64_t) + sizeof(uchar)
52
52
#define TINA_CHECK_HEADER 254 // The number we use to determine corruption
53
53
#define BLOB_MEMROOT_ALLOC_SIZE 8192
54
54
 
58
58
#define CSM_EXT ".CSM"               // Meta file
59
59
 
60
60
 
61
 
static TINA_SHARE *get_share(const char *table_name, Table *table);
 
61
static TINA_SHARE *get_share(const char *table_name, TABLE *table);
62
62
static int free_share(TINA_SHARE *share);
63
63
static int read_meta_file(File meta_file, ha_rows *rows);
64
64
static int write_meta_file(File meta_file, ha_rows rows, bool dirty);
91
91
  return ( a->begin > b->begin ? 1 : ( a->begin < b->begin ? -1 : 0 ) );
92
92
}
93
93
 
94
 
static unsigned char* tina_get_key(TINA_SHARE *share, size_t *length,
 
94
static uchar* tina_get_key(TINA_SHARE *share, size_t *length,
95
95
                          bool not_used __attribute__((unused)))
96
96
{
97
97
  *length=share->table_name_length;
98
 
  return (unsigned char*) share->table_name;
 
98
  return (uchar*) share->table_name;
99
99
}
100
100
 
101
101
static int tina_init_func(void *p)
103
103
  handlerton *tina_hton;
104
104
 
105
105
  tina_hton= (handlerton *)p;
106
 
  pthread_mutex_init(&tina_mutex,MY_MUTEX_INIT_FAST);
 
106
  VOID(pthread_mutex_init(&tina_mutex,MY_MUTEX_INIT_FAST));
107
107
  (void) hash_init(&tina_open_tables,system_charset_info,32,0,0,
108
108
                   (hash_get_key) tina_get_key,0,0);
109
109
  tina_hton->state= SHOW_OPTION_YES;
 
110
  tina_hton->db_type= DB_TYPE_CSV_DB;
110
111
  tina_hton->create= tina_create_handler;
111
112
  tina_hton->flags= (HTON_CAN_RECREATE | HTON_SUPPORT_LOG_TABLES | 
112
113
                     HTON_NO_PARTITION);
126
127
  Simple lock controls.
127
128
*/
128
129
static TINA_SHARE *get_share(const char *table_name,
129
 
                             Table *table __attribute__((unused)))
 
130
                             TABLE *table __attribute__((unused)))
130
131
{
131
132
  TINA_SHARE *share;
132
133
  char meta_file_name[FN_REFLEN];
133
134
  struct stat file_stat;
134
135
  char *tmp_name;
135
 
  uint32_t length;
 
136
  uint length;
136
137
 
137
138
  pthread_mutex_lock(&tina_mutex);
138
139
  length=(uint) strlen(table_name);
142
143
    initialize its members.
143
144
  */
144
145
  if (!(share=(TINA_SHARE*) hash_search(&tina_open_tables,
145
 
                                        (unsigned char*) table_name,
 
146
                                        (uchar*) table_name,
146
147
                                       length)))
147
148
  {
148
149
    if (!my_multi_malloc(MYF(MY_WME | MY_ZEROFILL),
149
150
                         &share, sizeof(*share),
150
151
                         &tmp_name, length+1,
151
 
                         NULL))
 
152
                         NullS))
152
153
    {
153
154
      pthread_mutex_unlock(&tina_mutex);
154
155
      return NULL;
162
163
    share->update_file_opened= false;
163
164
    share->tina_write_opened= false;
164
165
    share->data_file_version= 0;
165
 
    my_stpcpy(share->table_name, table_name);
 
166
    stpcpy(share->table_name, table_name);
166
167
    fn_format(share->data_file_name, table_name, "", CSV_EXT,
167
168
              MY_REPLACE_EXT|MY_UNPACK_FILENAME);
168
169
    fn_format(meta_file_name, table_name, "", CSM_EXT,
172
173
      goto error;
173
174
    share->saved_data_file_length= file_stat.st_size;
174
175
 
175
 
    if (my_hash_insert(&tina_open_tables, (unsigned char*) share))
 
176
    if (my_hash_insert(&tina_open_tables, (uchar*) share))
176
177
      goto error;
177
178
    thr_lock_init(&share->lock);
178
179
    pthread_mutex_init(&share->mutex,MY_MUTEX_INIT_FAST);
201
202
 
202
203
error:
203
204
  pthread_mutex_unlock(&tina_mutex);
204
 
  free((unsigned char*) share);
 
205
  my_free((uchar*) share, MYF(0));
205
206
 
206
207
  return NULL;
207
208
}
228
229
 
229
230
static int read_meta_file(File meta_file, ha_rows *rows)
230
231
{
231
 
  unsigned char meta_buffer[META_BUFFER_SIZE];
232
 
  unsigned char *ptr= meta_buffer;
 
232
  uchar meta_buffer[META_BUFFER_SIZE];
 
233
  uchar *ptr= meta_buffer;
233
234
 
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)
 
235
  VOID(my_seek(meta_file, 0, MY_SEEK_SET, MYF(0)));
 
236
  if (my_read(meta_file, (uchar*)meta_buffer, META_BUFFER_SIZE, 0)
236
237
      != META_BUFFER_SIZE)
237
238
    return(HA_ERR_CRASHED_ON_USAGE);
238
239
 
240
241
    Parse out the meta data, we ignore version at the moment
241
242
  */
242
243
 
243
 
  ptr+= sizeof(unsigned char)*2; // Move past header
 
244
  ptr+= sizeof(uchar)*2; // Move past header
244
245
  *rows= (ha_rows)uint8korr(ptr);
245
246
  ptr+= sizeof(uint64_t); // Move past rows
246
247
  /*
250
251
  ptr+= 3*sizeof(uint64_t);
251
252
 
252
253
  /* check crashed bit and magic number */
253
 
  if ((meta_buffer[0] != (unsigned char)TINA_CHECK_HEADER) ||
 
254
  if ((meta_buffer[0] != (uchar)TINA_CHECK_HEADER) ||
254
255
      ((bool)(*ptr)== true))
255
256
    return(HA_ERR_CRASHED_ON_USAGE);
256
257
 
281
282
 
282
283
static int write_meta_file(File meta_file, ha_rows rows, bool dirty)
283
284
{
284
 
  unsigned char meta_buffer[META_BUFFER_SIZE];
285
 
  unsigned char *ptr= meta_buffer;
 
285
  uchar meta_buffer[META_BUFFER_SIZE];
 
286
  uchar *ptr= meta_buffer;
286
287
 
287
 
  *ptr= (unsigned char)TINA_CHECK_HEADER;
288
 
  ptr+= sizeof(unsigned char);
289
 
  *ptr= (unsigned char)TINA_VERSION;
290
 
  ptr+= sizeof(unsigned char);
 
288
  *ptr= (uchar)TINA_CHECK_HEADER;
 
289
  ptr+= sizeof(uchar);
 
290
  *ptr= (uchar)TINA_VERSION;
 
291
  ptr+= sizeof(uchar);
291
292
  int8store(ptr, (uint64_t)rows);
292
293
  ptr+= sizeof(uint64_t);
293
294
  memset(ptr, 0, 3*sizeof(uint64_t));
296
297
     We'll need them later.
297
298
  */
298
299
  ptr+= 3*sizeof(uint64_t);
299
 
  *ptr= (unsigned char)dirty;
 
300
  *ptr= (uchar)dirty;
300
301
 
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)
 
302
  VOID(my_seek(meta_file, 0, MY_SEEK_SET, MYF(0)));
 
303
  if (my_write(meta_file, (uchar *)meta_buffer, META_BUFFER_SIZE, 0)
303
304
      != META_BUFFER_SIZE)
304
305
    return(-1);
305
306
 
364
365
      share->tina_write_opened= false;
365
366
    }
366
367
 
367
 
    hash_delete(&tina_open_tables, (unsigned char*) share);
 
368
    hash_delete(&tina_open_tables, (uchar*) share);
368
369
    thr_lock_delete(&share->lock);
369
370
    pthread_mutex_destroy(&share->mutex);
370
 
    free((unsigned char*) share);
 
371
    my_free((uchar*) share, MYF(0));
371
372
  }
372
373
  pthread_mutex_unlock(&tina_mutex);
373
374
 
442
443
  Encode a buffer into the quoted format.
443
444
*/
444
445
 
445
 
int ha_tina::encode_quote(unsigned char *buf __attribute__((unused)))
 
446
int ha_tina::encode_quote(uchar *buf __attribute__((unused)))
446
447
{
447
448
  char attribute_buffer[1024];
448
449
  String attribute(attribute_buffer, sizeof(attribute_buffer),
449
450
                   &my_charset_bin);
450
451
 
 
452
  my_bitmap_map *org_bitmap= dbug_tmp_use_all_columns(table, table->read_set);
451
453
  buffer.length(0);
452
454
 
453
455
  for (Field **field=table->field ; *field ; field++)
522
524
 
523
525
  //buffer.replace(buffer.length(), 0, "\n", 1);
524
526
 
 
527
  dbug_tmp_restore_column_map(table->read_set, org_bitmap);
525
528
  return (buffer.length());
526
529
}
527
530
 
544
547
      if (chain_alloced)
545
548
      {
546
549
        /* Must cast since my_malloc unlike malloc doesn't have a void ptr */
547
 
        if ((chain= (tina_set *) my_realloc((unsigned char*)chain,
 
550
        if ((chain= (tina_set *) my_realloc((uchar*)chain,
548
551
                                            chain_size, MYF(MY_WME))) == NULL)
549
552
          return -1;
550
553
      }
570
573
/*
571
574
  Scans for a row.
572
575
*/
573
 
int ha_tina::find_current_row(unsigned char *buf)
 
576
int ha_tina::find_current_row(uchar *buf)
574
577
{
575
578
  off_t end_offset, curr_offset= current_position;
576
579
  int eoln_len;
 
580
  my_bitmap_map *org_bitmap;
577
581
  int error;
578
582
  bool read_all;
579
583
 
590
594
 
591
595
  /* We must read all columns in case a table is opened for update */
592
596
  read_all= !bitmap_is_clear_all(table->write_set);
 
597
  /* Avoid asserts in ::store() for columns that are not going to be updated */
 
598
  org_bitmap= dbug_tmp_use_all_columns(table, table->write_set);
593
599
  error= HA_ERR_CRASHED_ON_USAGE;
594
600
 
595
601
  memset(buf, 0, table->s->null_bytes);
667
673
      if ((*field)->flags & BLOB_FLAG)
668
674
      {
669
675
        Field_blob *blob= *(Field_blob**) field;
670
 
        unsigned char *src, *tgt;
671
 
        uint32_t length, packlength;
 
676
        uchar *src, *tgt;
 
677
        uint length, packlength;
672
678
        
673
679
        packlength= blob->pack_length_no_ptr();
674
680
        length= blob->get_length(blob->ptr);
675
681
        memcpy(&src, blob->ptr + packlength, sizeof(char*));
676
682
        if (src)
677
683
        {
678
 
          tgt= (unsigned char*) alloc_root(&blobroot, length);
 
684
          tgt= (uchar*) alloc_root(&blobroot, length);
679
685
          memcpy(tgt, src, length);
680
686
          memcpy(blob->ptr + packlength, &tgt, sizeof(char*));
681
687
        }
686
692
  error= 0;
687
693
 
688
694
err:
 
695
  dbug_tmp_restore_column_map(table->write_set, org_bitmap);
689
696
 
690
697
  return(error);
691
698
}
697
704
static const char *ha_tina_exts[] = {
698
705
  CSV_EXT,
699
706
  CSM_EXT,
700
 
  NULL
 
707
  NullS
701
708
};
702
709
 
703
710
const char **ha_tina::bas_ext() const
780
787
  that need to be reset should be kept in the ::extra() call.
781
788
*/
782
789
int ha_tina::open(const char *name, int mode __attribute__((unused)),
783
 
                  uint32_t open_options)
 
790
                  uint open_options)
784
791
{
785
792
  if (!(share= get_share(name, table)))
786
793
    return(HA_ERR_OUT_OF_MEM);
827
834
  of the file and appends the data. In an error case it really should
828
835
  just truncate to the original position (this is not done yet).
829
836
*/
830
 
int ha_tina::write_row(unsigned char * buf)
 
837
int ha_tina::write_row(uchar * buf)
831
838
{
832
839
  int size;
833
840
 
846
853
      return(-1);
847
854
 
848
855
   /* use pwrite, as concurrent reader could have changed the position */
849
 
  if (my_write(share->tina_write_filedes, (unsigned char*)buffer.ptr(), size,
 
856
  if (my_write(share->tina_write_filedes, (uchar*)buffer.ptr(), size,
850
857
               MYF(MY_WME | MY_NABP)))
851
858
    return(-1);
852
859
 
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 uchar * old_data __attribute__((unused)),
 
901
                        uchar * new_data)
895
902
{
896
903
  int size;
897
904
  int rc= -1;
916
923
  if (open_update_temp_file_if_needed())
917
924
    goto err;
918
925
 
919
 
  if (my_write(update_temp_file, (unsigned char*)buffer.ptr(), size,
 
926
  if (my_write(update_temp_file, (uchar*)buffer.ptr(), size,
920
927
               MYF(MY_WME | MY_NABP)))
921
928
    goto err;
922
929
  temp_file_length+= size;
936
943
  The table will then be deleted/positioned based on the ORDER (so RANDOM,
937
944
  DESC, ASC).
938
945
*/
939
 
int ha_tina::delete_row(const unsigned char * buf __attribute__((unused)))
 
946
int ha_tina::delete_row(const uchar * buf __attribute__((unused)))
940
947
{
941
948
  ha_statistic_increment(&SSV::ha_delete_count);
942
949
 
1042
1049
  NULL and "". This is ok since this table handler is for spreadsheets and
1043
1050
  they don't know about them either :)
1044
1051
*/
1045
 
int ha_tina::rnd_next(unsigned char *buf)
 
1052
int ha_tina::rnd_next(uchar *buf)
1046
1053
{
1047
1054
  int rc;
1048
1055
 
1073
1080
  its just a position. Look at the bdb code if you want to see a case
1074
1081
  where something other then a number is stored.
1075
1082
*/
1076
 
void ha_tina::position(const unsigned char *record __attribute__((unused)))
 
1083
void ha_tina::position(const uchar *record __attribute__((unused)))
1077
1084
{
1078
1085
  my_store_ptr(ref, ref_length, current_position);
1079
1086
  return;
1085
1092
  my_get_ptr() retrieves the data for you.
1086
1093
*/
1087
1094
 
1088
 
int ha_tina::rnd_pos(unsigned char * buf, unsigned char *pos)
 
1095
int ha_tina::rnd_pos(uchar * buf, uchar *pos)
1089
1096
{
1090
1097
  ha_statistic_increment(&SSV::ha_read_rnd_count);
1091
1098
  current_position= (off_t)my_get_ptr(pos,ref_length);
1097
1104
  Currently this table handler doesn't implement most of the fields
1098
1105
  really needed. SHOW also makes use of this data
1099
1106
*/
1100
 
int ha_tina::info(uint32_t flag __attribute__((unused)))
 
1107
int ha_tina::info(uint flag __attribute__((unused)))
1101
1108
{
1102
1109
  /* This is a lie, but you don't want the optimizer to see zero or 1 */
1103
1110
  if (!records_is_known && stats.records < 2) 
1115
1122
  if (closest_hole == chain_ptr) /* no more chains */
1116
1123
    *end_pos= file_buff->end();
1117
1124
  else
1118
 
    *end_pos= std::min(file_buff->end(),
1119
 
                       closest_hole->begin);
 
1125
    *end_pos= min(file_buff->end(),
 
1126
                  closest_hole->begin);
1120
1127
  return (closest_hole != chain_ptr) && (*end_pos == closest_hole->begin);
1121
1128
}
1122
1129
 
1168
1175
      if (write_length)
1169
1176
      {
1170
1177
        if (my_write(update_temp_file, 
1171
 
                     (unsigned char*) (file_buff->ptr() +
 
1178
                     (uchar*) (file_buff->ptr() +
1172
1179
                               (write_begin - file_buff->start())),
1173
1180
                     write_length, MYF_RW))
1174
1181
          goto error;
1273
1280
                    HA_CHECK_OPT* check_opt __attribute__((unused)))
1274
1281
{
1275
1282
  char repaired_fname[FN_REFLEN];
1276
 
  unsigned char *buf;
 
1283
  uchar *buf;
1277
1284
  File repair_file;
1278
1285
  int rc;
1279
1286
  ha_rows rows_repaired= 0;
1288
1295
 
1289
1296
  /* Don't assert in field::val() functions */
1290
1297
  table->use_all_columns();
1291
 
  if (!(buf= (unsigned char*) my_malloc(table->s->reclength, MYF(MY_WME))))
 
1298
  if (!(buf= (uchar*) my_malloc(table->s->reclength, MYF(MY_WME))))
1292
1299
    return(HA_ERR_OUT_OF_MEM);
1293
1300
 
1294
1301
  /* position buffer to the start of the file */
1316
1323
 
1317
1324
  free_root(&blobroot, MYF(0));
1318
1325
 
1319
 
  free((char*)buf);
 
1326
  my_free((char*)buf, MYF(0));
1320
1327
 
1321
1328
  if (rc == HA_ERR_END_OF_FILE)
1322
1329
  {
1348
1355
  /* write repaired file */
1349
1356
  while (1)
1350
1357
  {
1351
 
    write_end= std::min(file_buff->end(), current_position);
 
1358
    write_end= min(file_buff->end(), current_position);
1352
1359
    if ((write_end - write_begin) &&
1353
 
        (my_write(repair_file, (unsigned char*)file_buff->ptr(),
 
1360
        (my_write(repair_file, (uchar*)file_buff->ptr(),
1354
1361
                  write_end - write_begin, MYF_RW)))
1355
1362
      return(-1);
1356
1363
 
1430
1437
  this (the database will call ::open() if it needs to).
1431
1438
*/
1432
1439
 
1433
 
int ha_tina::create(const char *name, Table *table_arg,
 
1440
int ha_tina::create(const char *name, TABLE *table_arg,
1434
1441
                    HA_CREATE_INFO *create_info __attribute__((unused)))
1435
1442
{
1436
1443
  char name_buff[FN_REFLEN];
1471
1478
                   HA_CHECK_OPT* check_opt __attribute__((unused)))
1472
1479
{
1473
1480
  int rc= 0;
1474
 
  unsigned char *buf;
 
1481
  uchar *buf;
1475
1482
  const char *old_proc_info;
1476
1483
  ha_rows count= share->rows_recorded;
1477
1484
 
1478
1485
  old_proc_info= thd_proc_info(thd, "Checking table");
1479
 
  if (!(buf= (unsigned char*) my_malloc(table->s->reclength, MYF(MY_WME))))
 
1486
  if (!(buf= (uchar*) my_malloc(table->s->reclength, MYF(MY_WME))))
1480
1487
    return(HA_ERR_OUT_OF_MEM);
1481
1488
 
1482
1489
  /* position buffer to the start of the file */
1504
1511
  
1505
1512
  free_root(&blobroot, MYF(0));
1506
1513
 
1507
 
  free((char*)buf);
 
1514
  my_free((char*)buf, MYF(0));
1508
1515
  thd_proc_info(thd, old_proc_info);
1509
1516
 
1510
1517
  if ((rc != HA_ERR_END_OF_FILE) || count)
1518
1525
 
1519
1526
 
1520
1527
bool ha_tina::check_if_incompatible_data(HA_CREATE_INFO *info __attribute__((unused)),
1521
 
                                         uint32_t table_changes __attribute__((unused)))
 
1528
                                         uint table_changes __attribute__((unused)))
1522
1529
{
1523
1530
  return COMPATIBLE_DATA_YES;
1524
1531
}
1525
1532
 
1526
1533
mysql_declare_plugin(csv)
1527
1534
{
1528
 
  DRIZZLE_STORAGE_ENGINE_PLUGIN,
 
1535
  MYSQL_STORAGE_ENGINE_PLUGIN,
1529
1536
  "CSV",
1530
1537
  "1.0",
1531
1538
  "Brian Aker, MySQL AB",