~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to storage/archive/ha_archive.cc

  • Committer: Monty Taylor
  • Date: 2008-08-09 02:24:34 UTC
  • mto: (266.1.8 codestyle)
  • mto: This revision was merged to the branch mainline in revision 279.
  • Revision ID: monty@inaugust.com-20080809022434-97na8pnugghskxip
Removed mystringslt conv lib and replaced it with a noinst lib.

Show diffs side-by-side

added added

removed removed

Lines of Context:
101
101
#define ARM ".ARM"               // Meta file (deprecated)
102
102
 
103
103
/*
104
 
  unsigned char + unsigned char
 
104
  uchar + uchar
105
105
*/
106
106
#define DATA_BUFFER_SIZE 2       // Size of the data used in the data file
107
107
#define ARCHIVE_CHECK_HEADER 254 // The number we use to determine corruption
112
112
                                       MEM_ROOT *mem_root);
113
113
int archive_discover(handlerton *hton, THD* thd, const char *db, 
114
114
                     const char *name,
115
 
                     unsigned char **frmblob, 
 
115
                     uchar **frmblob, 
116
116
                     size_t *frmlen);
117
117
 
118
 
static bool archive_use_aio= false;
 
118
static my_bool archive_use_aio= false;
119
119
 
120
120
/*
121
121
  Number of rows that will force a bulk insert.
137
137
/*
138
138
  Used for hash table that tracks open tables.
139
139
*/
140
 
static unsigned char* archive_get_key(ARCHIVE_SHARE *share, size_t *length,
141
 
                             bool not_used __attribute__((unused)))
 
140
static uchar* archive_get_key(ARCHIVE_SHARE *share, size_t *length,
 
141
                             my_bool not_used __attribute__((unused)))
142
142
{
143
143
  *length=share->table_name_length;
144
 
  return (unsigned char*) share->table_name;
 
144
  return (uchar*) share->table_name;
145
145
}
146
146
 
147
147
 
163
163
 
164
164
  archive_hton= (handlerton *)p;
165
165
  archive_hton->state= SHOW_OPTION_YES;
 
166
  archive_hton->db_type= DB_TYPE_ARCHIVE_DB;
166
167
  archive_hton->create= archive_create_handler;
167
168
  archive_hton->flags= HTON_NO_FLAGS;
168
169
  archive_hton->discover= archive_discover;
175
176
  if (hash_init(&archive_open_tables, system_charset_info, 32, 0, 0,
176
177
                (hash_get_key) archive_get_key, 0, 0))
177
178
  {
178
 
    pthread_mutex_destroy(&archive_mutex);
 
179
    VOID(pthread_mutex_destroy(&archive_mutex));
179
180
  }
180
181
  else
181
182
  {
199
200
int archive_db_done(void *p __attribute__((unused)))
200
201
{
201
202
  hash_free(&archive_open_tables);
202
 
  pthread_mutex_destroy(&archive_mutex);
 
203
  VOID(pthread_mutex_destroy(&archive_mutex));
203
204
 
204
205
  return 0;
205
206
}
220
221
                     THD* thd __attribute__((unused)),
221
222
                     const char *db,
222
223
                     const char *name,
223
 
                     unsigned char **frmblob,
 
224
                     uchar **frmblob,
224
225
                     size_t *frmlen)
225
226
{
226
227
  azio_stream frm_stream;
248
249
  azclose(&frm_stream);
249
250
 
250
251
  *frmlen= frm_stream.frm_length;
251
 
  *frmblob= (unsigned char*) frm_ptr;
 
252
  *frmblob= (uchar*) frm_ptr;
252
253
 
253
254
  return(0);
254
255
err:
280
281
*/
281
282
ARCHIVE_SHARE *ha_archive::get_share(const char *table_name, int *rc)
282
283
{
283
 
  uint32_t length;
 
284
  uint length;
284
285
 
285
286
  pthread_mutex_lock(&archive_mutex);
286
287
  length=(uint) strlen(table_name);
287
288
 
288
289
  if (!(share=(ARCHIVE_SHARE*) hash_search(&archive_open_tables,
289
 
                                           (unsigned char*) table_name,
 
290
                                           (uchar*) table_name,
290
291
                                           length)))
291
292
  {
292
293
    char *tmp_name;
295
296
    if (!my_multi_malloc(MYF(MY_WME | MY_ZEROFILL),
296
297
                          &share, sizeof(*share),
297
298
                          &tmp_name, length+1,
298
 
                          NULL)) 
 
299
                          NullS)) 
299
300
    {
300
301
      pthread_mutex_unlock(&archive_mutex);
301
302
      *rc= HA_ERR_OUT_OF_MEM;
309
310
    share->archive_write_open= false;
310
311
    fn_format(share->data_file_name, table_name, "",
311
312
              ARZ, MY_REPLACE_EXT | MY_UNPACK_FILENAME);
312
 
    my_stpcpy(share->table_name, table_name);
 
313
    strmov(share->table_name, table_name);
313
314
    /*
314
315
      We will use this lock for rows.
315
316
    */
316
 
    pthread_mutex_init(&share->mutex,MY_MUTEX_INIT_FAST);
 
317
    VOID(pthread_mutex_init(&share->mutex,MY_MUTEX_INIT_FAST));
317
318
    
318
319
    /*
319
320
      We read the meta file, but do not mark it dirty. Since we are not
324
325
    if (!(azopen(&archive_tmp, share->data_file_name, O_RDONLY|O_BINARY,
325
326
                 AZ_METHOD_BLOCK)))
326
327
    {
327
 
      pthread_mutex_destroy(&share->mutex);
 
328
      VOID(pthread_mutex_destroy(&share->mutex));
328
329
      free(share);
329
330
      pthread_mutex_unlock(&archive_mutex);
330
331
      *rc= HA_ERR_CRASHED_ON_REPAIR;
340
341
    }
341
342
    azclose(&archive_tmp);
342
343
 
343
 
    my_hash_insert(&archive_open_tables, (unsigned char*) share);
 
344
    VOID(my_hash_insert(&archive_open_tables, (uchar*) share));
344
345
    thr_lock_init(&share->lock);
345
346
  }
346
347
  share->use_count++;
363
364
  pthread_mutex_lock(&archive_mutex);
364
365
  if (!--share->use_count)
365
366
  {
366
 
    hash_delete(&archive_open_tables, (unsigned char*) share);
 
367
    hash_delete(&archive_open_tables, (uchar*) share);
367
368
    thr_lock_delete(&share->lock);
368
 
    pthread_mutex_destroy(&share->mutex);
 
369
    VOID(pthread_mutex_destroy(&share->mutex));
369
370
    /* 
370
371
      We need to make sure we don't reset the crashed state.
371
372
      If we open a crashed file, wee need to close it as crashed unless
378
379
      if (azclose(&(share->archive_write)))
379
380
        rc= 1;
380
381
    }
381
 
    free((unsigned char*) share);
 
382
    my_free((uchar*) share, MYF(0));
382
383
  }
383
384
  pthread_mutex_unlock(&archive_mutex);
384
385
 
447
448
*/
448
449
static const char *ha_archive_exts[] = {
449
450
  ARZ,
450
 
  NULL
 
451
  NullS
451
452
};
452
453
 
453
454
const char **ha_archive::bas_ext() const
464
465
*/
465
466
int ha_archive::open(const char *name,
466
467
                     int mode __attribute__((unused)),
467
 
                     uint32_t open_options)
 
468
                     uint open_options)
468
469
{
469
470
  int rc= 0;
470
471
  share= get_share(name, &rc);
548
549
  of creation.
549
550
*/
550
551
 
551
 
int ha_archive::create(const char *name, Table *table_arg,
 
552
int ha_archive::create(const char *name, TABLE *table_arg,
552
553
                       HA_CREATE_INFO *create_info)
553
554
{
554
555
  char name_buff[FN_REFLEN];
557
558
  azio_stream create_stream;            /* Archive file we are working with */
558
559
  File frm_file;                   /* File handler for readers */
559
560
  struct stat file_stat;
560
 
  unsigned char *frm_ptr;
 
561
  uchar *frm_ptr;
561
562
 
562
563
  stats.auto_increment_value= create_info->auto_increment_value;
563
564
 
564
 
  for (uint32_t key= 0; key < table_arg->sizeKeys(); key++)
 
565
  for (uint key= 0; key < table_arg->s->keys; key++)
565
566
  {
566
567
    KEY *pos= table_arg->key_info+key;
567
568
    KEY_PART_INFO *key_part=     pos->key_part;
622
623
    {
623
624
      if (fstat(frm_file, &file_stat))
624
625
      {
625
 
        frm_ptr= (unsigned char *)my_malloc(sizeof(unsigned char) * file_stat.st_size, MYF(0));
 
626
        frm_ptr= (uchar *)my_malloc(sizeof(uchar) * file_stat.st_size, MYF(0));
626
627
        if (frm_ptr)
627
628
        {
628
629
          my_read(frm_file, frm_ptr, file_stat.st_size, MYF(0));
629
630
          azwrite_frm(&create_stream, (char *)frm_ptr, file_stat.st_size);
630
 
          free((unsigned char*)frm_ptr);
 
631
          my_free((uchar*)frm_ptr, MYF(0));
631
632
        }
632
633
      }
633
634
      my_close(frm_file, MYF(0));
664
665
/*
665
666
  This is where the actual row is written out.
666
667
*/
667
 
int ha_archive::real_write_row(unsigned char *buf, azio_stream *writer)
 
668
int ha_archive::real_write_row(uchar *buf, azio_stream *writer)
668
669
{
669
670
  my_off_t written;
670
671
  unsigned int r_pack_length;
690
691
  the bytes required for the length in the header.
691
692
*/
692
693
 
693
 
uint32_t ha_archive::max_row_length(const unsigned char *buf __attribute__((unused)))
 
694
uint32_t ha_archive::max_row_length(const uchar *buf __attribute__((unused)))
694
695
{
695
 
  uint32_t length= (uint32_t)(table->getRecordLength() + table->sizeFields()*2);
 
696
  uint32_t length= (uint32_t)(table->s->reclength + table->s->fields*2);
696
697
  length+= ARCHIVE_ROW_HEADER_SIZE;
697
698
 
698
 
  uint32_t *ptr, *end;
699
 
  for (ptr= table->getBlobField(), end=ptr + table->sizeBlobFields();
 
699
  uint *ptr, *end;
 
700
  for (ptr= table->s->blob_field, end=ptr + table->s->blob_fields ;
700
701
       ptr != end ;
701
702
       ptr++)
702
703
  {
707
708
}
708
709
 
709
710
 
710
 
unsigned int ha_archive::pack_row(unsigned char *record)
 
711
unsigned int ha_archive::pack_row(uchar *record)
711
712
{
712
 
  unsigned char *ptr;
 
713
  uchar *ptr;
713
714
 
714
715
  if (fix_rec_buff(max_row_length(record)))
715
716
    return(HA_ERR_OUT_OF_MEM); /* purecov: inspected */
737
738
  for implementing start_bulk_insert() is that we could skip 
738
739
  setting dirty to true each time.
739
740
*/
740
 
int ha_archive::write_row(unsigned char *buf)
 
741
int ha_archive::write_row(uchar *buf)
741
742
{
742
743
  int rc;
743
 
  unsigned char *read_buf= NULL;
 
744
  uchar *read_buf= NULL;
744
745
  uint64_t temp_auto;
745
 
  unsigned char *record=  table->record[0];
 
746
  uchar *record=  table->record[0];
746
747
 
747
748
  if (share->crashed)
748
749
    return(HA_ERR_CRASHED_ON_USAGE);
785
786
        First we create a buffer that we can use for reading rows, and can pass
786
787
        to get_row().
787
788
      */
788
 
      if (!(read_buf= (unsigned char*) my_malloc(table->s->reclength, MYF(MY_WME))))
 
789
      if (!(read_buf= (uchar*) my_malloc(table->s->reclength, MYF(MY_WME))))
789
790
      {
790
791
        rc= HA_ERR_OUT_OF_MEM;
791
792
        goto error;
835
836
error:
836
837
  pthread_mutex_unlock(&share->mutex);
837
838
  if (read_buf)
838
 
    free((unsigned char*) read_buf);
 
839
    my_free((uchar*) read_buf, MYF(0));
839
840
 
840
841
  return(rc);
841
842
}
852
853
}
853
854
 
854
855
/* Initialized at each key walk (called multiple times unlike rnd_init()) */
855
 
int ha_archive::index_init(uint32_t keynr, bool sorted __attribute__((unused)))
 
856
int ha_archive::index_init(uint keynr, bool sorted __attribute__((unused)))
856
857
{
857
858
  active_index= keynr;
858
859
  return(0);
863
864
  No indexes, so if we get a request for an index search since we tell
864
865
  the optimizer that we have unique indexes, we scan
865
866
*/
866
 
int ha_archive::index_read(unsigned char *buf, const unsigned char *key,
867
 
                             uint32_t key_len, enum ha_rkey_function find_flag)
 
867
int ha_archive::index_read(uchar *buf, const uchar *key,
 
868
                             uint key_len, enum ha_rkey_function find_flag)
868
869
{
869
870
  int rc;
870
871
  rc= index_read_idx(buf, active_index, key, key_len, find_flag);
872
873
}
873
874
 
874
875
 
875
 
int ha_archive::index_read_idx(unsigned char *buf, uint32_t index, const unsigned char *key,
876
 
                               uint32_t key_len,
 
876
int ha_archive::index_read_idx(uchar *buf, uint index, const uchar *key,
 
877
                               uint key_len,
877
878
                               enum ha_rkey_function find_flag __attribute__((unused)))
878
879
{
879
880
  int rc;
905
906
}
906
907
 
907
908
 
908
 
int ha_archive::index_next(unsigned char * buf) 
 
909
int ha_archive::index_next(uchar * buf) 
909
910
910
911
  bool found= 0;
911
912
 
949
950
  This is the method that is used to read a row. It assumes that the row is 
950
951
  positioned where you want it.
951
952
*/
952
 
int ha_archive::get_row(azio_stream *file_to_read, unsigned char *buf)
 
953
int ha_archive::get_row(azio_stream *file_to_read, uchar *buf)
953
954
{
954
955
  int rc;
955
956
 
968
969
 
969
970
  if (length > record_buffer->length)
970
971
  {
971
 
    unsigned char *newptr;
972
 
    if (!(newptr=(unsigned char*) my_realloc((unsigned char*) record_buffer->buffer, 
 
972
    uchar *newptr;
 
973
    if (!(newptr=(uchar*) my_realloc((uchar*) record_buffer->buffer, 
973
974
                                    length,
974
975
                                    MYF(MY_ALLOW_ZERO_PTR))))
975
976
      return(1);
982
983
  return(0);
983
984
}
984
985
 
985
 
int ha_archive::unpack_row(azio_stream *file_to_read, unsigned char *record)
 
986
int ha_archive::unpack_row(azio_stream *file_to_read, uchar *record)
986
987
{
987
988
  unsigned int read;
988
989
  int error;
989
 
  const unsigned char *ptr;
 
990
  const uchar *ptr;
990
991
 
991
992
  read= azread_row(file_to_read, &error);
992
 
  ptr= (const unsigned char *)file_to_read->row_ptr;
 
993
  ptr= (const uchar *)file_to_read->row_ptr;
993
994
 
994
995
  if (error || read == 0)
995
996
  {
997
998
  }
998
999
 
999
1000
  /* Copy null bits */
1000
 
  memcpy(record, ptr, table->getNullBytes());
1001
 
  ptr+= table->getNullBytes();
 
1001
  memcpy(record, ptr, table->s->null_bytes);
 
1002
  ptr+= table->s->null_bytes;
1002
1003
  for (Field **field=table->field ; *field ; field++)
1003
1004
  {
1004
1005
    if (!((*field)->is_null()))
1010
1011
}
1011
1012
 
1012
1013
 
1013
 
int ha_archive::get_row_version3(azio_stream *file_to_read, unsigned char *buf)
 
1014
int ha_archive::get_row_version3(azio_stream *file_to_read, uchar *buf)
1014
1015
{
1015
1016
  int returnable= unpack_row(file_to_read, buf);
1016
1017
 
1023
1024
  or by having had ha_archive::rnd_pos() called before it is called.
1024
1025
*/
1025
1026
 
1026
 
int ha_archive::rnd_next(unsigned char *buf)
 
1027
int ha_archive::rnd_next(uchar *buf)
1027
1028
{
1028
1029
  int rc;
1029
1030
 
1050
1051
  needed.
1051
1052
*/
1052
1053
 
1053
 
void ha_archive::position(const unsigned char *record __attribute__((unused)))
 
1054
void ha_archive::position(const uchar *record __attribute__((unused)))
1054
1055
{
1055
1056
  my_store_ptr(ref, ref_length, current_position);
1056
1057
  return;
1064
1065
  correctly ordered row.
1065
1066
*/
1066
1067
 
1067
 
int ha_archive::rnd_pos(unsigned char * buf, unsigned char *pos)
 
1068
int ha_archive::rnd_pos(uchar * buf, uchar *pos)
1068
1069
{
1069
1070
  ha_statistic_increment(&SSV::ha_read_rnd_next_count);
1070
1071
  current_position= (my_off_t)my_get_ptr(pos, ref_length);
1144
1145
      share->rows_recorded= 0;
1145
1146
      stats.auto_increment_value= 1;
1146
1147
      share->archive_write.auto_increment= 0;
 
1148
      my_bitmap_map *org_bitmap= dbug_tmp_use_all_columns(table, table->read_set);
1147
1149
 
1148
1150
      rows_restored= archive.rows;
1149
1151
 
1170
1172
              (share->archive_write.auto_increment= auto_value) + 1;
1171
1173
        }
1172
1174
      }
 
1175
      dbug_tmp_restore_column_map(table->read_set, org_bitmap);
1173
1176
      share->rows_recorded= (ha_rows)writer.rows;
1174
1177
    }
1175
1178
 
1212
1215
    /* 
1213
1216
      Here is where we get into the guts of a row level lock.
1214
1217
      If TL_UNLOCK is set 
1215
 
      If we are not doing a LOCK Table or DISCARD/IMPORT
 
1218
      If we are not doing a LOCK TABLE or DISCARD/IMPORT
1216
1219
      TABLESPACE, then allow multiple writers 
1217
1220
    */
1218
1221
 
1258
1261
/*
1259
1262
  Hints for optimizer, see ha_tina for more information
1260
1263
*/
1261
 
int ha_archive::info(uint32_t flag)
 
1264
int ha_archive::info(uint flag)
1262
1265
{
1263
1266
  /* 
1264
1267
    If dirty, we lock, and then reset/flush the data.
1293
1296
  {
1294
1297
    struct stat file_stat;  // Stat information for the data file
1295
1298
 
1296
 
    stat(share->data_file_name, &file_stat);
 
1299
    VOID(stat(share->data_file_name, &file_stat));
1297
1300
 
1298
 
    stats.mean_rec_length= table->getRecordLength()+ buffer.alloced_length();
 
1301
    stats.mean_rec_length= table->s->reclength + buffer.alloced_length();
1299
1302
    stats.data_file_length= file_stat.st_size;
1300
1303
    stats.create_time= file_stat.st_ctime;
1301
1304
    stats.update_time= file_stat.st_mtime;
1428
1431
  }
1429
1432
  r->length= (int)length;
1430
1433
 
1431
 
  if (!(r->buffer= (unsigned char*) my_malloc(r->length,
 
1434
  if (!(r->buffer= (uchar*) my_malloc(r->length,
1432
1435
                                    MYF(MY_WME))))
1433
1436
  {
1434
 
    free((char*) r);
 
1437
    my_free((char*) r, MYF(MY_ALLOW_ZERO_PTR));
1435
1438
    return(NULL); /* purecov: inspected */
1436
1439
  }
1437
1440
 
1440
1443
 
1441
1444
void ha_archive::destroy_record_buffer(archive_record_buffer *r) 
1442
1445
{
1443
 
  free((char*) r->buffer);
1444
 
  free((char*) r);
 
1446
  my_free((char*) r->buffer, MYF(MY_ALLOW_ZERO_PTR));
 
1447
  my_free((char*) r, MYF(MY_ALLOW_ZERO_PTR));
1445
1448
  return;
1446
1449
}
1447
1450
 
1448
 
static DRIZZLE_SYSVAR_BOOL(aio, archive_use_aio,
 
1451
static MYSQL_SYSVAR_BOOL(aio, archive_use_aio,
1449
1452
  PLUGIN_VAR_NOCMDOPT,
1450
1453
  "Whether or not to use asynchronous IO.",
1451
1454
  NULL, NULL, true);
1452
1455
 
1453
1456
static struct st_mysql_sys_var* archive_system_variables[]= {
1454
 
  DRIZZLE_SYSVAR(aio),
 
1457
  MYSQL_SYSVAR(aio),
1455
1458
  NULL
1456
1459
};
1457
1460
 
1458
1461
mysql_declare_plugin(archive)
1459
1462
{
1460
 
  DRIZZLE_STORAGE_ENGINE_PLUGIN,
 
1463
  MYSQL_STORAGE_ENGINE_PLUGIN,
1461
1464
  "ARCHIVE",
1462
1465
  "3.5",
1463
1466
  "Brian Aker, MySQL AB",