~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to storage/archive/ha_archive.cc

  • Committer: Jay Pipes
  • Date: 2008-07-17 19:43:08 UTC
  • mto: This revision was merged to the branch mainline in revision 182.
  • Revision ID: jay@mysql.com-20080717194308-l9i4ti57gikm2qbv
Phase 1 removal of DBUG in mysys

Show diffs side-by-side

added added

removed removed

Lines of Context:
17
17
#pragma implementation        // gcc: Class implementation
18
18
#endif
19
19
 
20
 
#include <drizzled/common_includes.h>
21
 
#include <storage/myisam/myisam.h>
 
20
#include "mysql_priv.h"
 
21
#include <myisam.h>
22
22
 
23
23
#include "ha_archive.h"
 
24
#include <my_dir.h>
 
25
 
 
26
#include <mysql/plugin.h>
24
27
 
25
28
/*
26
29
  First, if you want to understand storage engines you should look at 
101
104
#define ARM ".ARM"               // Meta file (deprecated)
102
105
 
103
106
/*
104
 
  unsigned char + unsigned char
 
107
  uchar + uchar
105
108
*/
106
109
#define DATA_BUFFER_SIZE 2       // Size of the data used in the data file
107
110
#define ARCHIVE_CHECK_HEADER 254 // The number we use to determine corruption
112
115
                                       MEM_ROOT *mem_root);
113
116
int archive_discover(handlerton *hton, THD* thd, const char *db, 
114
117
                     const char *name,
115
 
                     unsigned char **frmblob, 
 
118
                     uchar **frmblob, 
116
119
                     size_t *frmlen);
117
120
 
118
 
static bool archive_use_aio= false;
 
121
static my_bool archive_use_aio= false;
119
122
 
120
123
/*
121
124
  Number of rows that will force a bulk insert.
137
140
/*
138
141
  Used for hash table that tracks open tables.
139
142
*/
140
 
static unsigned char* archive_get_key(ARCHIVE_SHARE *share, size_t *length,
141
 
                             bool not_used __attribute__((unused)))
 
143
static uchar* archive_get_key(ARCHIVE_SHARE *share, size_t *length,
 
144
                             my_bool not_used __attribute__((unused)))
142
145
{
143
146
  *length=share->table_name_length;
144
 
  return (unsigned char*) share->table_name;
 
147
  return (uchar*) share->table_name;
145
148
}
146
149
 
147
150
 
163
166
 
164
167
  archive_hton= (handlerton *)p;
165
168
  archive_hton->state= SHOW_OPTION_YES;
 
169
  archive_hton->db_type= DB_TYPE_ARCHIVE_DB;
166
170
  archive_hton->create= archive_create_handler;
167
171
  archive_hton->flags= HTON_NO_FLAGS;
168
172
  archive_hton->discover= archive_discover;
175
179
  if (hash_init(&archive_open_tables, system_charset_info, 32, 0, 0,
176
180
                (hash_get_key) archive_get_key, 0, 0))
177
181
  {
178
 
    pthread_mutex_destroy(&archive_mutex);
 
182
    VOID(pthread_mutex_destroy(&archive_mutex));
179
183
  }
180
184
  else
181
185
  {
196
200
    false       OK
197
201
*/
198
202
 
199
 
int archive_db_done(void *p __attribute__((unused)))
 
203
int archive_db_done(void *p __attribute__((__unused__)))
200
204
{
201
205
  hash_free(&archive_open_tables);
202
 
  pthread_mutex_destroy(&archive_mutex);
 
206
  VOID(pthread_mutex_destroy(&archive_mutex));
203
207
 
204
208
  return 0;
205
209
}
216
220
  archive_reader_open= false;
217
221
}
218
222
 
219
 
int archive_discover(handlerton *hton __attribute__((unused)),
220
 
                     THD* thd __attribute__((unused)),
 
223
int archive_discover(handlerton *hton __attribute__((__unused__)),
 
224
                     THD* thd __attribute__((__unused__)),
221
225
                     const char *db,
222
226
                     const char *name,
223
 
                     unsigned char **frmblob,
 
227
                     uchar **frmblob,
224
228
                     size_t *frmlen)
225
229
{
226
230
  azio_stream frm_stream;
248
252
  azclose(&frm_stream);
249
253
 
250
254
  *frmlen= frm_stream.frm_length;
251
 
  *frmblob= (unsigned char*) frm_ptr;
 
255
  *frmblob= (uchar*) frm_ptr;
252
256
 
253
257
  return(0);
254
258
err:
280
284
*/
281
285
ARCHIVE_SHARE *ha_archive::get_share(const char *table_name, int *rc)
282
286
{
283
 
  uint32_t length;
 
287
  uint length;
284
288
 
285
289
  pthread_mutex_lock(&archive_mutex);
286
290
  length=(uint) strlen(table_name);
287
291
 
288
292
  if (!(share=(ARCHIVE_SHARE*) hash_search(&archive_open_tables,
289
 
                                           (unsigned char*) table_name,
 
293
                                           (uchar*) table_name,
290
294
                                           length)))
291
295
  {
292
296
    char *tmp_name;
295
299
    if (!my_multi_malloc(MYF(MY_WME | MY_ZEROFILL),
296
300
                          &share, sizeof(*share),
297
301
                          &tmp_name, length+1,
298
 
                          NULL)) 
 
302
                          NullS)) 
299
303
    {
300
304
      pthread_mutex_unlock(&archive_mutex);
301
305
      *rc= HA_ERR_OUT_OF_MEM;
309
313
    share->archive_write_open= false;
310
314
    fn_format(share->data_file_name, table_name, "",
311
315
              ARZ, MY_REPLACE_EXT | MY_UNPACK_FILENAME);
312
 
    my_stpcpy(share->table_name, table_name);
 
316
    strmov(share->table_name, table_name);
313
317
    /*
314
318
      We will use this lock for rows.
315
319
    */
316
 
    pthread_mutex_init(&share->mutex,MY_MUTEX_INIT_FAST);
 
320
    VOID(pthread_mutex_init(&share->mutex,MY_MUTEX_INIT_FAST));
317
321
    
318
322
    /*
319
323
      We read the meta file, but do not mark it dirty. Since we are not
324
328
    if (!(azopen(&archive_tmp, share->data_file_name, O_RDONLY|O_BINARY,
325
329
                 AZ_METHOD_BLOCK)))
326
330
    {
327
 
      pthread_mutex_destroy(&share->mutex);
 
331
      VOID(pthread_mutex_destroy(&share->mutex));
328
332
      free(share);
329
333
      pthread_mutex_unlock(&archive_mutex);
330
334
      *rc= HA_ERR_CRASHED_ON_REPAIR;
340
344
    }
341
345
    azclose(&archive_tmp);
342
346
 
343
 
    my_hash_insert(&archive_open_tables, (unsigned char*) share);
 
347
    VOID(my_hash_insert(&archive_open_tables, (uchar*) share));
344
348
    thr_lock_init(&share->lock);
345
349
  }
346
350
  share->use_count++;
363
367
  pthread_mutex_lock(&archive_mutex);
364
368
  if (!--share->use_count)
365
369
  {
366
 
    hash_delete(&archive_open_tables, (unsigned char*) share);
 
370
    hash_delete(&archive_open_tables, (uchar*) share);
367
371
    thr_lock_delete(&share->lock);
368
 
    pthread_mutex_destroy(&share->mutex);
 
372
    VOID(pthread_mutex_destroy(&share->mutex));
369
373
    /* 
370
374
      We need to make sure we don't reset the crashed state.
371
375
      If we open a crashed file, wee need to close it as crashed unless
378
382
      if (azclose(&(share->archive_write)))
379
383
        rc= 1;
380
384
    }
381
 
    free((unsigned char*) share);
 
385
    my_free((uchar*) share, MYF(0));
382
386
  }
383
387
  pthread_mutex_unlock(&archive_mutex);
384
388
 
447
451
*/
448
452
static const char *ha_archive_exts[] = {
449
453
  ARZ,
450
 
  NULL
 
454
  NullS
451
455
};
452
456
 
453
457
const char **ha_archive::bas_ext() const
463
467
  We open the file we will read from.
464
468
*/
465
469
int ha_archive::open(const char *name,
466
 
                     int mode __attribute__((unused)),
467
 
                     uint32_t open_options)
 
470
                     int mode __attribute__((__unused__)),
 
471
                     uint open_options)
468
472
{
469
473
  int rc= 0;
470
474
  share= get_share(name, &rc);
548
552
  of creation.
549
553
*/
550
554
 
551
 
int ha_archive::create(const char *name, Table *table_arg,
 
555
int ha_archive::create(const char *name, TABLE *table_arg,
552
556
                       HA_CREATE_INFO *create_info)
553
557
{
554
558
  char name_buff[FN_REFLEN];
557
561
  azio_stream create_stream;            /* Archive file we are working with */
558
562
  File frm_file;                   /* File handler for readers */
559
563
  struct stat file_stat;
560
 
  unsigned char *frm_ptr;
 
564
  uchar *frm_ptr;
561
565
 
562
566
  stats.auto_increment_value= create_info->auto_increment_value;
563
567
 
564
 
  for (uint32_t key= 0; key < table_arg->sizeKeys(); key++)
 
568
  for (uint key= 0; key < table_arg->s->keys; key++)
565
569
  {
566
570
    KEY *pos= table_arg->key_info+key;
567
571
    KEY_PART_INFO *key_part=     pos->key_part;
622
626
    {
623
627
      if (fstat(frm_file, &file_stat))
624
628
      {
625
 
        frm_ptr= (unsigned char *)my_malloc(sizeof(unsigned char) * file_stat.st_size, MYF(0));
 
629
        frm_ptr= (uchar *)my_malloc(sizeof(uchar) * file_stat.st_size, MYF(0));
626
630
        if (frm_ptr)
627
631
        {
628
632
          my_read(frm_file, frm_ptr, file_stat.st_size, MYF(0));
629
633
          azwrite_frm(&create_stream, (char *)frm_ptr, file_stat.st_size);
630
 
          free((unsigned char*)frm_ptr);
 
634
          my_free((uchar*)frm_ptr, MYF(0));
631
635
        }
632
636
      }
633
637
      my_close(frm_file, MYF(0));
664
668
/*
665
669
  This is where the actual row is written out.
666
670
*/
667
 
int ha_archive::real_write_row(unsigned char *buf, azio_stream *writer)
 
671
int ha_archive::real_write_row(uchar *buf, azio_stream *writer)
668
672
{
669
673
  my_off_t written;
670
674
  unsigned int r_pack_length;
690
694
  the bytes required for the length in the header.
691
695
*/
692
696
 
693
 
uint32_t ha_archive::max_row_length(const unsigned char *buf __attribute__((unused)))
 
697
uint32 ha_archive::max_row_length(const uchar *buf __attribute__((__unused__)))
694
698
{
695
 
  uint32_t length= (uint32_t)(table->getRecordLength() + table->sizeFields()*2);
 
699
  uint32 length= (uint32)(table->s->reclength + table->s->fields*2);
696
700
  length+= ARCHIVE_ROW_HEADER_SIZE;
697
701
 
698
 
  uint32_t *ptr, *end;
699
 
  for (ptr= table->getBlobField(), end=ptr + table->sizeBlobFields();
 
702
  uint *ptr, *end;
 
703
  for (ptr= table->s->blob_field, end=ptr + table->s->blob_fields ;
700
704
       ptr != end ;
701
705
       ptr++)
702
706
  {
707
711
}
708
712
 
709
713
 
710
 
unsigned int ha_archive::pack_row(unsigned char *record)
 
714
unsigned int ha_archive::pack_row(uchar *record)
711
715
{
712
 
  unsigned char *ptr;
 
716
  uchar *ptr;
713
717
 
714
718
  if (fix_rec_buff(max_row_length(record)))
715
719
    return(HA_ERR_OUT_OF_MEM); /* purecov: inspected */
737
741
  for implementing start_bulk_insert() is that we could skip 
738
742
  setting dirty to true each time.
739
743
*/
740
 
int ha_archive::write_row(unsigned char *buf)
 
744
int ha_archive::write_row(uchar *buf)
741
745
{
742
746
  int rc;
743
 
  unsigned char *read_buf= NULL;
 
747
  uchar *read_buf= NULL;
744
748
  uint64_t temp_auto;
745
 
  unsigned char *record=  table->record[0];
 
749
  uchar *record=  table->record[0];
746
750
 
747
751
  if (share->crashed)
748
752
    return(HA_ERR_CRASHED_ON_USAGE);
785
789
        First we create a buffer that we can use for reading rows, and can pass
786
790
        to get_row().
787
791
      */
788
 
      if (!(read_buf= (unsigned char*) my_malloc(table->s->reclength, MYF(MY_WME))))
 
792
      if (!(read_buf= (uchar*) my_malloc(table->s->reclength, MYF(MY_WME))))
789
793
      {
790
794
        rc= HA_ERR_OUT_OF_MEM;
791
795
        goto error;
835
839
error:
836
840
  pthread_mutex_unlock(&share->mutex);
837
841
  if (read_buf)
838
 
    free((unsigned char*) read_buf);
 
842
    my_free((uchar*) read_buf, MYF(0));
839
843
 
840
844
  return(rc);
841
845
}
842
846
 
843
847
 
844
 
void ha_archive::get_auto_increment(uint64_t offset __attribute__((unused)),
845
 
                                    uint64_t increment __attribute__((unused)),
846
 
                                    uint64_t nb_desired_values __attribute__((unused)),
847
 
                                    uint64_t *first_value __attribute__((unused)),
848
 
                                    uint64_t *nb_reserved_values __attribute__((unused)))
 
848
void ha_archive::get_auto_increment(uint64_t offset __attribute__((__unused__)),
 
849
                                    uint64_t increment __attribute__((__unused__)),
 
850
                                    uint64_t nb_desired_values __attribute__((__unused__)),
 
851
                                    uint64_t *first_value __attribute__((__unused__)),
 
852
                                    uint64_t *nb_reserved_values __attribute__((__unused__)))
849
853
{
850
854
  *nb_reserved_values= UINT64_MAX;
851
855
  *first_value= share->archive_write.auto_increment + 1;
852
856
}
853
857
 
854
858
/* Initialized at each key walk (called multiple times unlike rnd_init()) */
855
 
int ha_archive::index_init(uint32_t keynr, bool sorted __attribute__((unused)))
 
859
int ha_archive::index_init(uint keynr, bool sorted __attribute__((__unused__)))
856
860
{
857
861
  active_index= keynr;
858
862
  return(0);
863
867
  No indexes, so if we get a request for an index search since we tell
864
868
  the optimizer that we have unique indexes, we scan
865
869
*/
866
 
int ha_archive::index_read(unsigned char *buf, const unsigned char *key,
867
 
                             uint32_t key_len, enum ha_rkey_function find_flag)
 
870
int ha_archive::index_read(uchar *buf, const uchar *key,
 
871
                             uint key_len, enum ha_rkey_function find_flag)
868
872
{
869
873
  int rc;
870
874
  rc= index_read_idx(buf, active_index, key, key_len, find_flag);
872
876
}
873
877
 
874
878
 
875
 
int ha_archive::index_read_idx(unsigned char *buf, uint32_t index, const unsigned char *key,
876
 
                               uint32_t key_len,
877
 
                               enum ha_rkey_function find_flag __attribute__((unused)))
 
879
int ha_archive::index_read_idx(uchar *buf, uint index, const uchar *key,
 
880
                               uint key_len,
 
881
                               enum ha_rkey_function find_flag __attribute__((__unused__)))
878
882
{
879
883
  int rc;
880
884
  bool found= 0;
905
909
}
906
910
 
907
911
 
908
 
int ha_archive::index_next(unsigned char * buf) 
 
912
int ha_archive::index_next(uchar * buf) 
909
913
910
914
  bool found= 0;
911
915
 
949
953
  This is the method that is used to read a row. It assumes that the row is 
950
954
  positioned where you want it.
951
955
*/
952
 
int ha_archive::get_row(azio_stream *file_to_read, unsigned char *buf)
 
956
int ha_archive::get_row(azio_stream *file_to_read, uchar *buf)
953
957
{
954
958
  int rc;
955
959
 
968
972
 
969
973
  if (length > record_buffer->length)
970
974
  {
971
 
    unsigned char *newptr;
972
 
    if (!(newptr=(unsigned char*) my_realloc((unsigned char*) record_buffer->buffer, 
 
975
    uchar *newptr;
 
976
    if (!(newptr=(uchar*) my_realloc((uchar*) record_buffer->buffer, 
973
977
                                    length,
974
978
                                    MYF(MY_ALLOW_ZERO_PTR))))
975
979
      return(1);
982
986
  return(0);
983
987
}
984
988
 
985
 
int ha_archive::unpack_row(azio_stream *file_to_read, unsigned char *record)
 
989
int ha_archive::unpack_row(azio_stream *file_to_read, uchar *record)
986
990
{
987
991
  unsigned int read;
988
992
  int error;
989
 
  const unsigned char *ptr;
 
993
  const uchar *ptr;
990
994
 
991
995
  read= azread_row(file_to_read, &error);
992
 
  ptr= (const unsigned char *)file_to_read->row_ptr;
 
996
  ptr= (const uchar *)file_to_read->row_ptr;
993
997
 
994
998
  if (error || read == 0)
995
999
  {
997
1001
  }
998
1002
 
999
1003
  /* Copy null bits */
1000
 
  memcpy(record, ptr, table->getNullBytes());
1001
 
  ptr+= table->getNullBytes();
 
1004
  memcpy(record, ptr, table->s->null_bytes);
 
1005
  ptr+= table->s->null_bytes;
1002
1006
  for (Field **field=table->field ; *field ; field++)
1003
1007
  {
1004
1008
    if (!((*field)->is_null()))
1010
1014
}
1011
1015
 
1012
1016
 
1013
 
int ha_archive::get_row_version3(azio_stream *file_to_read, unsigned char *buf)
 
1017
int ha_archive::get_row_version3(azio_stream *file_to_read, uchar *buf)
1014
1018
{
1015
1019
  int returnable= unpack_row(file_to_read, buf);
1016
1020
 
1023
1027
  or by having had ha_archive::rnd_pos() called before it is called.
1024
1028
*/
1025
1029
 
1026
 
int ha_archive::rnd_next(unsigned char *buf)
 
1030
int ha_archive::rnd_next(uchar *buf)
1027
1031
{
1028
1032
  int rc;
1029
1033
 
1050
1054
  needed.
1051
1055
*/
1052
1056
 
1053
 
void ha_archive::position(const unsigned char *record __attribute__((unused)))
 
1057
void ha_archive::position(const uchar *record __attribute__((__unused__)))
1054
1058
{
1055
1059
  my_store_ptr(ref, ref_length, current_position);
1056
1060
  return;
1064
1068
  correctly ordered row.
1065
1069
*/
1066
1070
 
1067
 
int ha_archive::rnd_pos(unsigned char * buf, unsigned char *pos)
 
1071
int ha_archive::rnd_pos(uchar * buf, uchar *pos)
1068
1072
{
1069
1073
  ha_statistic_increment(&SSV::ha_read_rnd_next_count);
1070
1074
  current_position= (my_off_t)my_get_ptr(pos, ref_length);
1094
1098
  The table can become fragmented if data was inserted, read, and then
1095
1099
  inserted again. What we do is open up the file and recompress it completely. 
1096
1100
*/
1097
 
int ha_archive::optimize(THD* thd __attribute__((unused)),
1098
 
                         HA_CHECK_OPT* check_opt __attribute__((unused)))
 
1101
int ha_archive::optimize(THD* thd __attribute__((__unused__)),
 
1102
                         HA_CHECK_OPT* check_opt __attribute__((__unused__)))
1099
1103
{
1100
1104
  int rc= 0;
1101
1105
  azio_stream writer;
1144
1148
      share->rows_recorded= 0;
1145
1149
      stats.auto_increment_value= 1;
1146
1150
      share->archive_write.auto_increment= 0;
 
1151
      my_bitmap_map *org_bitmap= dbug_tmp_use_all_columns(table, table->read_set);
1147
1152
 
1148
1153
      rows_restored= archive.rows;
1149
1154
 
1170
1175
              (share->archive_write.auto_increment= auto_value) + 1;
1171
1176
        }
1172
1177
      }
 
1178
      dbug_tmp_restore_column_map(table->read_set, org_bitmap);
1173
1179
      share->rows_recorded= (ha_rows)writer.rows;
1174
1180
    }
1175
1181
 
1212
1218
    /* 
1213
1219
      Here is where we get into the guts of a row level lock.
1214
1220
      If TL_UNLOCK is set 
1215
 
      If we are not doing a LOCK Table or DISCARD/IMPORT
 
1221
      If we are not doing a LOCK TABLE or DISCARD/IMPORT
1216
1222
      TABLESPACE, then allow multiple writers 
1217
1223
    */
1218
1224
 
1258
1264
/*
1259
1265
  Hints for optimizer, see ha_tina for more information
1260
1266
*/
1261
 
int ha_archive::info(uint32_t flag)
 
1267
int ha_archive::info(uint flag)
1262
1268
{
1263
1269
  /* 
1264
1270
    If dirty, we lock, and then reset/flush the data.
1293
1299
  {
1294
1300
    struct stat file_stat;  // Stat information for the data file
1295
1301
 
1296
 
    stat(share->data_file_name, &file_stat);
 
1302
    VOID(stat(share->data_file_name, &file_stat));
1297
1303
 
1298
 
    stats.mean_rec_length= table->getRecordLength()+ buffer.alloced_length();
 
1304
    stats.mean_rec_length= table->s->reclength + buffer.alloced_length();
1299
1305
    stats.data_file_length= file_stat.st_size;
1300
1306
    stats.create_time= file_stat.st_ctime;
1301
1307
    stats.update_time= file_stat.st_mtime;
1365
1371
*/
1366
1372
 
1367
1373
int ha_archive::check(THD* thd,
1368
 
                      HA_CHECK_OPT* check_opt __attribute__((unused)))
 
1374
                      HA_CHECK_OPT* check_opt __attribute__((__unused__)))
1369
1375
{
1370
1376
  int rc= 0;
1371
1377
  const char *old_proc_info;
1428
1434
  }
1429
1435
  r->length= (int)length;
1430
1436
 
1431
 
  if (!(r->buffer= (unsigned char*) my_malloc(r->length,
 
1437
  if (!(r->buffer= (uchar*) my_malloc(r->length,
1432
1438
                                    MYF(MY_WME))))
1433
1439
  {
1434
 
    free((char*) r);
 
1440
    my_free((char*) r, MYF(MY_ALLOW_ZERO_PTR));
1435
1441
    return(NULL); /* purecov: inspected */
1436
1442
  }
1437
1443
 
1440
1446
 
1441
1447
void ha_archive::destroy_record_buffer(archive_record_buffer *r) 
1442
1448
{
1443
 
  free((char*) r->buffer);
1444
 
  free((char*) r);
 
1449
  my_free((char*) r->buffer, MYF(MY_ALLOW_ZERO_PTR));
 
1450
  my_free((char*) r, MYF(MY_ALLOW_ZERO_PTR));
1445
1451
  return;
1446
1452
}
1447
1453
 
1448
 
static DRIZZLE_SYSVAR_BOOL(aio, archive_use_aio,
 
1454
static MYSQL_SYSVAR_BOOL(aio, archive_use_aio,
1449
1455
  PLUGIN_VAR_NOCMDOPT,
1450
1456
  "Whether or not to use asynchronous IO.",
1451
1457
  NULL, NULL, true);
1452
1458
 
1453
1459
static struct st_mysql_sys_var* archive_system_variables[]= {
1454
 
  DRIZZLE_SYSVAR(aio),
 
1460
  MYSQL_SYSVAR(aio),
1455
1461
  NULL
1456
1462
};
1457
1463
 
 
1464
struct st_mysql_storage_engine archive_storage_engine=
 
1465
{ MYSQL_HANDLERTON_INTERFACE_VERSION };
 
1466
 
1458
1467
mysql_declare_plugin(archive)
1459
1468
{
1460
 
  DRIZZLE_STORAGE_ENGINE_PLUGIN,
 
1469
  MYSQL_STORAGE_ENGINE_PLUGIN,
 
1470
  &archive_storage_engine,
1461
1471
  "ARCHIVE",
1462
 
  "3.5",
1463
1472
  "Brian Aker, MySQL AB",
1464
1473
  "Archive storage engine",
1465
1474
  PLUGIN_LICENSE_GPL,
1466
1475
  archive_db_init, /* Plugin Init */
1467
1476
  archive_db_done, /* Plugin Deinit */
 
1477
  0x0350 /* 3.0 */,
1468
1478
  NULL,                       /* status variables                */
1469
1479
  archive_system_variables,   /* system variables                */
1470
1480
  NULL                        /* config options                  */