~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to storage/archive/ha_archive.cc

  • Committer: Padraig O'Sullivan
  • Date: 2009-03-21 20:26:28 UTC
  • mto: (960.2.5 mordred)
  • mto: This revision was merged to the branch mainline in revision 961.
  • Revision ID: osullivan.padraig@gmail.com-20090321202628-nh6qsi825m4d4av6
Removing the queues.[h,cc] files from the mysys directory. The only place
where they are needed now is in the MyISAM storage engine. Thus, I moved the
files there and updated the files in the MyISAM storage engine
appropriately.

Show diffs side-by-side

added added

removed removed

Lines of Context:
13
13
  along with this program; if not, write to the Free Software
14
14
  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA */
15
15
 
16
 
#ifdef USE_PRAGMA_IMPLEMENTATION
17
 
#pragma implementation        // gcc: Class implementation
18
 
#endif
19
16
 
20
 
#include <drizzled/common_includes.h>
 
17
#include <drizzled/server_includes.h>
 
18
#include <drizzled/field.h>
 
19
#include <drizzled/field/blob.h>
 
20
#include <drizzled/field/timestamp.h>
21
21
#include <storage/myisam/myisam.h>
 
22
#include <drizzled/table.h>
 
23
#include <drizzled/session.h>
 
24
#include <stdio.h>
22
25
 
23
 
#include "ha_archive.h"
 
26
#include <storage/archive/ha_archive.h>
24
27
 
25
28
/*
26
 
  First, if you want to understand storage engines you should look at 
27
 
  ha_example.cc and ha_example.h. 
 
29
  First, if you want to understand storage engines you should look at
 
30
  ha_example.cc and ha_example.h.
28
31
 
29
32
  This example was written as a test case for a customer who needed
30
33
  a storage engine without indexes that could compress data very well.
31
34
  So, welcome to a completely compressed storage engine. This storage
32
 
  engine only does inserts. No replace, deletes, or updates. All reads are 
 
35
  engine only does inserts. No replace, deletes, or updates. All reads are
33
36
  complete table scans. Compression is done through a combination of packing
34
37
  and making use of the zlib library
35
 
  
 
38
 
36
39
  We keep a file pointer open for each instance of ha_archive for each read
37
40
  but for writes we keep one open file handle just for that. We flush it
38
41
  only if we have a read occur. azip handles compressing lots of records
42
45
  the same time since we would want to flush).
43
46
 
44
47
  A "meta" file is kept alongside the data file. This file serves two purpose.
45
 
  The first purpose is to track the number of rows in the table. The second 
46
 
  purpose is to determine if the table was closed properly or not. When the 
47
 
  meta file is first opened it is marked as dirty. It is opened when the table 
48
 
  itself is opened for writing. When the table is closed the new count for rows 
49
 
  is written to the meta file and the file is marked as clean. If the meta file 
50
 
  is opened and it is marked as dirty, it is assumed that a crash occured. At 
 
48
  The first purpose is to track the number of rows in the table. The second
 
49
  purpose is to determine if the table was closed properly or not. When the
 
50
  meta file is first opened it is marked as dirty. It is opened when the table
 
51
  itself is opened for writing. When the table is closed the new count for rows
 
52
  is written to the meta file and the file is marked as clean. If the meta file
 
53
  is opened and it is marked as dirty, it is assumed that a crash occured. At
51
54
  this point an error occurs and the user is told to rebuild the file.
52
55
  A rebuild scans the rows and rewrites the meta file. If corruption is found
53
56
  in the data file then the meta file is not repaired.
54
57
 
55
58
  At some point a recovery method for such a drastic case needs to be divised.
56
59
 
57
 
  Locks are row level, and you will get a consistant read. 
 
60
  Locks are row level, and you will get a consistant read.
58
61
 
59
62
  For performance as far as table scans go it is quite fast. I don't have
60
63
  good numbers but locally it has out performed both Innodb and MyISAM. For
61
64
  Innodb the question will be if the table can be fit into the buffer
62
65
  pool. For MyISAM its a question of how much the file system caches the
63
66
  MyISAM file. With enough free memory MyISAM is faster. Its only when the OS
64
 
  doesn't have enough memory to cache entire table that archive turns out 
65
 
  to be any faster. 
 
67
  doesn't have enough memory to cache entire table that archive turns out
 
68
  to be any faster.
66
69
 
67
70
  Examples between MyISAM (packed) and Archive.
68
71
 
98
101
/* The file extension */
99
102
#define ARZ ".ARZ"               // The data file
100
103
#define ARN ".ARN"               // Files used during an optimize call
101
 
#define ARM ".ARM"               // Meta file (deprecated)
102
104
 
103
 
/*
104
 
  unsigned char + unsigned char
105
 
*/
106
 
#define DATA_BUFFER_SIZE 2       // Size of the data used in the data file
107
 
#define ARCHIVE_CHECK_HEADER 254 // The number we use to determine corruption
108
105
 
109
106
/* Static declarations for handerton */
110
 
static handler *archive_create_handler(handlerton *hton, 
111
 
                                       TABLE_SHARE *table, 
 
107
static handler *archive_create_handler(handlerton *hton,
 
108
                                       TABLE_SHARE *table,
112
109
                                       MEM_ROOT *mem_root);
113
 
int archive_discover(handlerton *hton, THD* thd, const char *db, 
114
 
                     const char *name,
115
 
                     unsigned char **frmblob, 
116
 
                     size_t *frmlen);
117
110
 
118
111
static bool archive_use_aio= false;
119
112
 
128
121
#define ARCHIVE_ROW_HEADER_SIZE 4
129
122
 
130
123
static handler *archive_create_handler(handlerton *hton,
131
 
                                       TABLE_SHARE *table, 
 
124
                                       TABLE_SHARE *table,
132
125
                                       MEM_ROOT *mem_root)
133
126
{
134
127
  return new (mem_root) ha_archive(hton, table);
137
130
/*
138
131
  Used for hash table that tracks open tables.
139
132
*/
140
 
static unsigned char* archive_get_key(ARCHIVE_SHARE *share, size_t *length,
141
 
                             bool not_used __attribute__((unused)))
 
133
static unsigned char* archive_get_key(ARCHIVE_SHARE *share, size_t *length, bool)
142
134
{
143
135
  *length=share->table_name_length;
144
136
  return (unsigned char*) share->table_name;
165
157
  archive_hton->state= SHOW_OPTION_YES;
166
158
  archive_hton->create= archive_create_handler;
167
159
  archive_hton->flags= HTON_NO_FLAGS;
168
 
  archive_hton->discover= archive_discover;
169
160
 
170
161
  /* When the engine starts up set the first version */
171
162
  global_version= 1;
196
187
    false       OK
197
188
*/
198
189
 
199
 
int archive_db_done(void *p __attribute__((unused)))
 
190
int archive_db_done(void *)
200
191
{
201
192
  hash_free(&archive_open_tables);
202
193
  pthread_mutex_destroy(&archive_mutex);
216
207
  archive_reader_open= false;
217
208
}
218
209
 
219
 
int archive_discover(handlerton *hton __attribute__((unused)),
220
 
                     THD* thd __attribute__((unused)),
221
 
                     const char *db,
222
 
                     const char *name,
223
 
                     unsigned char **frmblob,
224
 
                     size_t *frmlen)
225
 
{
226
 
  azio_stream frm_stream;
227
 
  char az_file[FN_REFLEN];
228
 
  char *frm_ptr;
229
 
  struct stat file_stat; 
230
 
 
231
 
  fn_format(az_file, name, db, ARZ, MY_REPLACE_EXT | MY_UNPACK_FILENAME);
232
 
 
233
 
  if (stat(az_file, &file_stat))
234
 
    goto err;
235
 
 
236
 
  if (!(azopen(&frm_stream, az_file, O_RDONLY|O_BINARY, AZ_METHOD_BLOCK)))
237
 
  {
238
 
    if (errno == EROFS || errno == EACCES)
239
 
      return(my_errno= errno);
240
 
    return(HA_ERR_CRASHED_ON_USAGE);
241
 
  }
242
 
 
243
 
  if (frm_stream.frm_length == 0)
244
 
    goto err;
245
 
 
246
 
  frm_ptr= (char *)my_malloc(sizeof(char) * frm_stream.frm_length, MYF(0));
247
 
  azread_frm(&frm_stream, frm_ptr);
248
 
  azclose(&frm_stream);
249
 
 
250
 
  *frmlen= frm_stream.frm_length;
251
 
  *frmblob= (unsigned char*) frm_ptr;
252
 
 
253
 
  return(0);
254
 
err:
255
 
  my_errno= 0;
256
 
  return(1);
257
 
}
258
 
 
259
210
/*
260
211
  This method reads the header of a datafile and returns whether or not it was successful.
261
212
*/
272
223
 
273
224
 
274
225
/*
275
 
  We create the shared memory space that we will use for the open table. 
 
226
  We create the shared memory space that we will use for the open table.
276
227
  No matter what we try to get or create a share. This is so that a repair
277
 
  table operation can occur. 
 
228
  table operation can occur.
278
229
 
279
230
  See ha_example.cc for a longer description.
280
231
*/
295
246
    if (!my_multi_malloc(MYF(MY_WME | MY_ZEROFILL),
296
247
                          &share, sizeof(*share),
297
248
                          &tmp_name, length+1,
298
 
                          NULL)) 
 
249
                          NULL))
299
250
    {
300
251
      pthread_mutex_unlock(&archive_mutex);
301
252
      *rc= HA_ERR_OUT_OF_MEM;
309
260
    share->archive_write_open= false;
310
261
    fn_format(share->data_file_name, table_name, "",
311
262
              ARZ, MY_REPLACE_EXT | MY_UNPACK_FILENAME);
312
 
    my_stpcpy(share->table_name, table_name);
 
263
    strcpy(share->table_name, table_name);
313
264
    /*
314
265
      We will use this lock for rows.
315
266
    */
316
267
    pthread_mutex_init(&share->mutex,MY_MUTEX_INIT_FAST);
317
 
    
 
268
 
318
269
    /*
319
270
      We read the meta file, but do not mark it dirty. Since we are not
320
271
      doing a write we won't mark it dirty (and we won't open it for
321
272
      anything but reading... open it for write and we will generate null
322
273
      compression writes).
323
274
    */
324
 
    if (!(azopen(&archive_tmp, share->data_file_name, O_RDONLY|O_BINARY,
 
275
    if (!(azopen(&archive_tmp, share->data_file_name, O_RDONLY,
325
276
                 AZ_METHOD_BLOCK)))
326
277
    {
327
278
      pthread_mutex_destroy(&share->mutex);
352
303
}
353
304
 
354
305
 
355
 
/* 
 
306
/*
356
307
  Free the share.
357
308
  See ha_example.cc for a description.
358
309
*/
366
317
    hash_delete(&archive_open_tables, (unsigned char*) share);
367
318
    thr_lock_delete(&share->lock);
368
319
    pthread_mutex_destroy(&share->mutex);
369
 
    /* 
 
320
    /*
370
321
      We need to make sure we don't reset the crashed state.
371
322
      If we open a crashed file, wee need to close it as crashed unless
372
323
      it has been repaired.
387
338
 
388
339
int ha_archive::init_archive_writer()
389
340
{
390
 
  /* 
 
341
  /*
391
342
    It is expensive to open and close the data files and since you can't have
392
343
    a gzip file that can be both read and written we keep a writer open
393
344
    that is shared amoung all open tables.
394
345
  */
395
 
  if (!(azopen(&(share->archive_write), share->data_file_name, 
396
 
               O_RDWR|O_BINARY, AZ_METHOD_BLOCK)))
 
346
  if (!(azopen(&(share->archive_write), share->data_file_name,
 
347
               O_RDWR, AZ_METHOD_BLOCK)))
397
348
  {
398
349
    share->crashed= true;
399
350
    return(1);
404
355
}
405
356
 
406
357
 
407
 
/* 
 
358
/*
408
359
  No locks are required because it is associated with just one handler instance
409
360
*/
410
361
int ha_archive::init_archive_reader()
411
362
{
412
 
  /* 
 
363
  /*
413
364
    It is expensive to open and close the data files and since you can't have
414
365
    a gzip file that can be both read and written we keep a writer open
415
366
    that is shared amoung all open tables.
429
380
    default:
430
381
      method= AZ_METHOD_BLOCK;
431
382
    }
432
 
    if (!(azopen(&archive, share->data_file_name, O_RDONLY|O_BINARY, 
 
383
    if (!(azopen(&archive, share->data_file_name, O_RDONLY,
433
384
                 method)))
434
385
    {
435
386
      share->crashed= true;
456
407
}
457
408
 
458
409
 
459
 
/* 
 
410
/*
460
411
  When opening a file we:
461
412
  Create/get our shared structure.
462
413
  Init out lock.
463
414
  We open the file we will read from.
464
415
*/
465
 
int ha_archive::open(const char *name,
466
 
                     int mode __attribute__((unused)),
467
 
                     uint32_t open_options)
 
416
int ha_archive::open(const char *name, int, uint32_t open_options)
468
417
{
469
418
  int rc= 0;
470
419
  share= get_share(name, &rc);
474
423
    /* purecov: begin inspected */
475
424
    free_share();
476
425
    return(rc);
477
 
    /* purecov: end */    
 
426
    /* purecov: end */
478
427
  }
479
428
  else if (rc == HA_ERR_OUT_OF_MEM)
480
429
  {
483
432
 
484
433
  assert(share);
485
434
 
486
 
  record_buffer= create_record_buffer(table->s->reclength + 
 
435
  record_buffer= create_record_buffer(table->s->reclength +
487
436
                                      ARCHIVE_ROW_HEADER_SIZE);
488
437
 
489
438
  if (!record_buffer)
508
457
 
509
458
  SYNOPSIS
510
459
    close();
511
 
  
 
460
 
512
461
  IMPLEMENTATION:
513
462
 
514
463
  We first close this storage engines file handle to the archive and
540
489
 
541
490
 
542
491
/*
543
 
  We create our data file here. The format is pretty simple. 
 
492
  We create our data file here. The format is pretty simple.
544
493
  You can read about the format of the data file above.
545
 
  Unlike other storage engines we do not "pack" our data. Since we 
546
 
  are about to do a general compression, packing would just be a waste of 
547
 
  CPU time. If the table has blobs they are written after the row in the order 
 
494
  Unlike other storage engines we do not "pack" our data. Since we
 
495
  are about to do a general compression, packing would just be a waste of
 
496
  CPU time. If the table has blobs they are written after the row in the order
548
497
  of creation.
549
498
*/
550
499
 
553
502
{
554
503
  char name_buff[FN_REFLEN];
555
504
  char linkname[FN_REFLEN];
556
 
  int error;
 
505
  int error= 0;
557
506
  azio_stream create_stream;            /* Archive file we are working with */
558
 
  File frm_file;                   /* File handler for readers */
 
507
  FILE *frm_file;                   /* File handler for readers */
559
508
  struct stat file_stat;
560
509
  unsigned char *frm_ptr;
 
510
  int r;
561
511
 
562
512
  stats.auto_increment_value= create_info->auto_increment_value;
563
513
 
579
529
    }
580
530
  }
581
531
 
582
 
  /* 
 
532
  /*
583
533
    We reuse name_buff since it is available.
584
534
  */
585
535
  if (create_info->data_file_name && create_info->data_file_name[0] != '#')
600
550
    There is a chance that the file was "discovered". In this case
601
551
    just use whatever file is there.
602
552
  */
603
 
  if (!stat(name_buff, &file_stat))
604
 
  {
605
 
    my_errno= 0;
606
 
    if (!(azopen(&create_stream, name_buff, O_CREAT|O_RDWR|O_BINARY,
607
 
                 AZ_METHOD_BLOCK)))
608
 
    {
609
 
      error= errno;
610
 
      goto error2;
611
 
    }
612
 
 
613
 
    if (linkname[0])
614
 
      my_symlink(name_buff, linkname, MYF(0));
615
 
    fn_format(name_buff, name, "", ".frm",
616
 
              MY_REPLACE_EXT | MY_UNPACK_FILENAME);
617
 
 
618
 
    /*
619
 
      Here is where we open up the frm and pass it to archive to store 
620
 
    */
621
 
    if ((frm_file= my_open(name_buff, O_RDONLY, MYF(0))) > 0)
622
 
    {
623
 
      if (fstat(frm_file, &file_stat))
624
 
      {
625
 
        frm_ptr= (unsigned char *)my_malloc(sizeof(unsigned char) * file_stat.st_size, MYF(0));
626
 
        if (frm_ptr)
627
 
        {
628
 
          my_read(frm_file, frm_ptr, file_stat.st_size, MYF(0));
629
 
          azwrite_frm(&create_stream, (char *)frm_ptr, file_stat.st_size);
630
 
          free((unsigned char*)frm_ptr);
631
 
        }
632
 
      }
633
 
      my_close(frm_file, MYF(0));
634
 
    }
635
 
 
636
 
    if (create_info->comment.str)
637
 
      azwrite_comment(&create_stream, create_info->comment.str, 
638
 
                      (unsigned int)create_info->comment.length);
639
 
 
640
 
    /* 
641
 
      Yes you need to do this, because the starting value 
642
 
      for the autoincrement may not be zero.
643
 
    */
644
 
    create_stream.auto_increment= stats.auto_increment_value ?
645
 
                                    stats.auto_increment_value - 1 : 0;
646
 
    if (azclose(&create_stream))
647
 
    {
648
 
      error= errno;
649
 
      goto error2;
650
 
    }
651
 
  }
652
 
  else
653
 
    my_errno= 0;
 
553
  r= stat(name_buff, &file_stat);
 
554
  if (r == -1 && errno!=ENOENT)
 
555
  {
 
556
    return errno;
 
557
  }
 
558
  if (!r)
 
559
    return HA_ERR_TABLE_EXIST;
 
560
 
 
561
  my_errno= 0;
 
562
  if (!(azopen(&create_stream, name_buff, O_CREAT|O_RDWR,
 
563
               AZ_METHOD_BLOCK)))
 
564
  {
 
565
    error= errno;
 
566
    goto error2;
 
567
  }
 
568
 
 
569
  if (linkname[0])
 
570
    my_symlink(name_buff, linkname, MYF(0));
 
571
  fn_format(name_buff, name, "", ".frm",
 
572
            MY_REPLACE_EXT | MY_UNPACK_FILENAME);
 
573
 
 
574
  /*
 
575
    Here is where we open up the frm and pass it to archive to store
 
576
  */
 
577
  if ((frm_file= fopen(name_buff, "r")) > 0)
 
578
  {
 
579
    if (fstat(fileno(frm_file), &file_stat))
 
580
    {
 
581
      if ((uint64_t)file_stat.st_size > SIZE_MAX)
 
582
      {
 
583
        error= ENOMEM;
 
584
        goto error2;
 
585
      }
 
586
      frm_ptr= (unsigned char *)malloc((size_t)file_stat.st_size);
 
587
      if (frm_ptr)
 
588
      {
 
589
        size_t length_io;
 
590
        length_io= read(fileno(frm_file), frm_ptr, (size_t)file_stat.st_size);
 
591
 
 
592
        if (length_io != (size_t)file_stat.st_size)
 
593
        {
 
594
          free(frm_ptr);
 
595
          goto error2;
 
596
        }
 
597
 
 
598
        length_io= azwrite_frm(&create_stream, (char *)frm_ptr, (size_t)file_stat.st_size);
 
599
 
 
600
        if (length_io != (size_t)file_stat.st_size)
 
601
        {
 
602
          free(frm_ptr);
 
603
          goto error2;
 
604
        }
 
605
 
 
606
        free(frm_ptr);
 
607
      }
 
608
    }
 
609
    fclose(frm_file);
 
610
  }
 
611
 
 
612
  if (create_info->comment.str)
 
613
  {
 
614
    size_t write_length;
 
615
 
 
616
    write_length= azwrite_comment(&create_stream, create_info->comment.str,
 
617
                                  (unsigned int)create_info->comment.length);
 
618
 
 
619
    if (write_length == (size_t)create_info->comment.length)
 
620
      goto error2;
 
621
  }
 
622
 
 
623
  /*
 
624
    Yes you need to do this, because the starting value
 
625
    for the autoincrement may not be zero.
 
626
  */
 
627
  create_stream.auto_increment= stats.auto_increment_value ?
 
628
    stats.auto_increment_value - 1 : 0;
 
629
  if (azclose(&create_stream))
 
630
  {
 
631
    error= errno;
 
632
    goto error2;
 
633
  }
654
634
 
655
635
  return(0);
656
636
 
666
646
*/
667
647
int ha_archive::real_write_row(unsigned char *buf, azio_stream *writer)
668
648
{
669
 
  my_off_t written;
 
649
  off_t written;
670
650
  unsigned int r_pack_length;
671
651
 
672
652
  /* We pack the row for writing */
685
665
}
686
666
 
687
667
 
688
 
/* 
 
668
/*
689
669
  Calculate max length needed for row. This includes
690
670
  the bytes required for the length in the header.
691
671
*/
692
672
 
693
 
uint32_t ha_archive::max_row_length(const unsigned char *buf __attribute__((unused)))
 
673
uint32_t ha_archive::max_row_length(const unsigned char *)
694
674
{
695
675
  uint32_t length= (uint32_t)(table->getRecordLength() + table->sizeFields()*2);
696
676
  length+= ARCHIVE_ROW_HEADER_SIZE;
728
708
}
729
709
 
730
710
 
731
 
/* 
 
711
/*
732
712
  Look at ha_archive::open() for an explanation of the row format.
733
713
  Here we just write out the row.
734
714
 
735
715
  Wondering about start_bulk_insert()? We don't implement it for
736
716
  archive since it optimizes for lots of writes. The only save
737
 
  for implementing start_bulk_insert() is that we could skip 
 
717
  for implementing start_bulk_insert() is that we could skip
738
718
  setting dirty to true each time.
739
719
*/
740
720
int ha_archive::write_row(unsigned char *buf)
748
728
    return(HA_ERR_CRASHED_ON_USAGE);
749
729
 
750
730
  ha_statistic_increment(&SSV::ha_write_count);
751
 
  if (table->timestamp_field_type & TIMESTAMP_AUTO_SET_ON_INSERT)
752
 
    table->timestamp_field->set_time();
753
731
  pthread_mutex_lock(&share->mutex);
754
732
 
755
733
  if (share->archive_write_open == false)
767
745
      We don't support decremening auto_increment. They make the performance
768
746
      just cry.
769
747
    */
770
 
    if (temp_auto <= share->archive_write.auto_increment && 
 
748
    if (temp_auto <= share->archive_write.auto_increment &&
771
749
        mkey->flags & HA_NOSAME)
772
750
    {
773
751
      rc= HA_ERR_FOUND_DUPP_KEY;
775
753
    }
776
754
#ifdef DEAD_CODE
777
755
    /*
778
 
      Bad news, this will cause a search for the unique value which is very 
779
 
      expensive since we will have to do a table scan which will lock up 
780
 
      all other writers during this period. This could perhaps be optimized 
 
756
      Bad news, this will cause a search for the unique value which is very
 
757
      expensive since we will have to do a table scan which will lock up
 
758
      all other writers during this period. This could perhaps be optimized
781
759
      in the future.
782
760
    */
783
761
    {
784
 
      /* 
 
762
      /*
785
763
        First we create a buffer that we can use for reading rows, and can pass
786
764
        to get_row().
787
765
      */
788
 
      if (!(read_buf= (unsigned char*) my_malloc(table->s->reclength, MYF(MY_WME))))
 
766
      if (!(read_buf= (unsigned char*) malloc(table->s->reclength)))
789
767
      {
790
768
        rc= HA_ERR_OUT_OF_MEM;
791
769
        goto error;
792
770
      }
793
 
       /* 
 
771
       /*
794
772
         All of the buffer must be written out or we won't see all of the
795
 
         data 
 
773
         data
796
774
       */
797
775
      azflush(&(share->archive_write), Z_SYNC_FLUSH);
798
776
      /*
841
819
}
842
820
 
843
821
 
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)))
 
822
void ha_archive::get_auto_increment(uint64_t, uint64_t, uint64_t,
 
823
                                    uint64_t *first_value, uint64_t *nb_reserved_values)
849
824
{
850
825
  *nb_reserved_values= UINT64_MAX;
851
826
  *first_value= share->archive_write.auto_increment + 1;
852
827
}
853
828
 
854
829
/* Initialized at each key walk (called multiple times unlike rnd_init()) */
855
 
int ha_archive::index_init(uint32_t keynr, bool sorted __attribute__((unused)))
 
830
int ha_archive::index_init(uint32_t keynr, bool)
856
831
{
857
832
  active_index= keynr;
858
833
  return(0);
873
848
 
874
849
 
875
850
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)))
 
851
                               uint32_t key_len, enum ha_rkey_function)
878
852
{
879
853
  int rc;
880
854
  bool found= 0;
905
879
}
906
880
 
907
881
 
908
 
int ha_archive::index_next(unsigned char * buf) 
909
 
 
882
int ha_archive::index_next(unsigned char * buf)
 
883
{
910
884
  bool found= 0;
911
885
 
912
886
  while (!(get_row(&archive, buf)))
918
892
    }
919
893
  }
920
894
 
921
 
  return(found ? 0 : HA_ERR_END_OF_FILE); 
 
895
  return(found ? 0 : HA_ERR_END_OF_FILE);
922
896
}
923
897
 
924
898
/*
946
920
 
947
921
 
948
922
/*
949
 
  This is the method that is used to read a row. It assumes that the row is 
 
923
  This is the method that is used to read a row. It assumes that the row is
950
924
  positioned where you want it.
951
925
*/
952
926
int ha_archive::get_row(azio_stream *file_to_read, unsigned char *buf)
969
943
  if (length > record_buffer->length)
970
944
  {
971
945
    unsigned char *newptr;
972
 
    if (!(newptr=(unsigned char*) my_realloc((unsigned char*) record_buffer->buffer, 
973
 
                                    length,
974
 
                                    MYF(MY_ALLOW_ZERO_PTR))))
 
946
    if (!(newptr= (unsigned char *)realloc(record_buffer->buffer, length)))
975
947
      return(1);
976
948
    record_buffer->buffer= newptr;
977
949
    record_buffer->length= length;
1018
990
}
1019
991
 
1020
992
 
1021
 
/* 
 
993
/*
1022
994
  Called during ORDER BY. Its position is either from being called sequentially
1023
995
  or by having had ha_archive::rnd_pos() called before it is called.
1024
996
*/
1050
1022
  needed.
1051
1023
*/
1052
1024
 
1053
 
void ha_archive::position(const unsigned char *record __attribute__((unused)))
 
1025
void ha_archive::position(const unsigned char *)
1054
1026
{
1055
1027
  my_store_ptr(ref, ref_length, current_position);
1056
1028
  return;
1074
1046
}
1075
1047
 
1076
1048
/*
1077
 
  This method repairs the meta file. It does this by walking the datafile and 
 
1049
  This method repairs the meta file. It does this by walking the datafile and
1078
1050
  rewriting the meta file. Currently it does this by calling optimize with
1079
1051
  the extended flag.
1080
1052
*/
1081
 
int ha_archive::repair(THD* thd, HA_CHECK_OPT* check_opt)
 
1053
int ha_archive::repair(Session* session, HA_CHECK_OPT* check_opt)
1082
1054
{
1083
1055
  check_opt->flags= T_EXTEND;
1084
 
  int rc= optimize(thd, check_opt);
 
1056
  int rc= optimize(session, check_opt);
1085
1057
 
1086
1058
  if (rc)
1087
1059
    return(HA_ERR_CRASHED_ON_REPAIR);
1092
1064
 
1093
1065
/*
1094
1066
  The table can become fragmented if data was inserted, read, and then
1095
 
  inserted again. What we do is open up the file and recompress it completely. 
 
1067
  inserted again. What we do is open up the file and recompress it completely.
1096
1068
*/
1097
 
int ha_archive::optimize(THD* thd __attribute__((unused)),
1098
 
                         HA_CHECK_OPT* check_opt __attribute__((unused)))
 
1069
int ha_archive::optimize(Session *, HA_CHECK_OPT *)
1099
1070
{
1100
1071
  int rc= 0;
1101
1072
  azio_stream writer;
1111
1082
  }
1112
1083
 
1113
1084
  /* Lets create a file to contain the new data */
1114
 
  fn_format(writer_filename, share->table_name, "", ARN, 
 
1085
  fn_format(writer_filename, share->table_name, "", ARN,
1115
1086
            MY_REPLACE_EXT | MY_UNPACK_FILENAME);
1116
1087
 
1117
 
  if (!(azopen(&writer, writer_filename, O_CREAT|O_RDWR|O_BINARY, AZ_METHOD_BLOCK)))
1118
 
    return(HA_ERR_CRASHED_ON_USAGE); 
 
1088
  if (!(azopen(&writer, writer_filename, O_CREAT|O_RDWR, AZ_METHOD_BLOCK)))
 
1089
    return(HA_ERR_CRASHED_ON_USAGE);
1119
1090
 
1120
 
  /* 
1121
 
    An extended rebuild is a lot more effort. We open up each row and re-record it. 
1122
 
    Any dead rows are removed (aka rows that may have been partially recorded). 
 
1091
  /*
 
1092
    An extended rebuild is a lot more effort. We open up each row and re-record it.
 
1093
    Any dead rows are removed (aka rows that may have been partially recorded).
1123
1094
 
1124
1095
    As of Archive format 3, this is the only type that is performed, before this
1125
1096
    version it was just done on T_EXTEND
1127
1098
  if (1)
1128
1099
  {
1129
1100
    /*
1130
 
      Now we will rewind the archive file so that we are positioned at the 
 
1101
      Now we will rewind the archive file so that we are positioned at the
1131
1102
      start of the file.
1132
1103
    */
1133
1104
    azflush(&archive, Z_SYNC_FLUSH);
1134
1105
    rc= read_data_header(&archive);
1135
1106
 
1136
 
    /* 
 
1107
    /*
1137
1108
      On success of writing out the new header, we now fetch each row and
1138
 
      insert it into the new archive file. 
 
1109
      insert it into the new archive file.
1139
1110
    */
1140
1111
    if (!rc)
1141
1112
    {
1177
1148
    {
1178
1149
      goto error;
1179
1150
    }
1180
 
  } 
 
1151
  }
1181
1152
 
1182
1153
  azclose(&writer);
1183
1154
  share->dirty= false;
1184
 
  
 
1155
 
1185
1156
  azclose(&archive);
1186
1157
 
1187
1158
  // make the file we just wrote be our data file
1192
1163
error:
1193
1164
  azclose(&writer);
1194
1165
 
1195
 
  return(rc); 
 
1166
  return(rc);
1196
1167
}
1197
1168
 
1198
 
/* 
 
1169
/*
1199
1170
  Below is an example of how to setup row level locking.
1200
1171
*/
1201
 
THR_LOCK_DATA **ha_archive::store_lock(THD *thd,
 
1172
THR_LOCK_DATA **ha_archive::store_lock(Session *session,
1202
1173
                                       THR_LOCK_DATA **to,
1203
1174
                                       enum thr_lock_type lock_type)
1204
1175
{
1207
1178
  else
1208
1179
    delayed_insert= false;
1209
1180
 
1210
 
  if (lock_type != TL_IGNORE && lock.type == TL_UNLOCK) 
 
1181
  if (lock_type != TL_IGNORE && lock.type == TL_UNLOCK)
1211
1182
  {
1212
 
    /* 
 
1183
    /*
1213
1184
      Here is where we get into the guts of a row level lock.
1214
 
      If TL_UNLOCK is set 
 
1185
      If TL_UNLOCK is set
1215
1186
      If we are not doing a LOCK Table or DISCARD/IMPORT
1216
 
      TABLESPACE, then allow multiple writers 
 
1187
      TABLESPACE, then allow multiple writers
1217
1188
    */
1218
1189
 
1219
1190
    if ((lock_type >= TL_WRITE_CONCURRENT_INSERT &&
1220
 
         lock_type <= TL_WRITE) && !thd_in_lock_tables(thd)
1221
 
        && !thd_tablespace_op(thd))
 
1191
         lock_type <= TL_WRITE) && !session_in_lock_tables(session)
 
1192
        && !session_tablespace_op(session))
1222
1193
      lock_type = TL_WRITE_ALLOW_WRITE;
1223
1194
 
1224
 
    /* 
 
1195
    /*
1225
1196
      In queries of type INSERT INTO t1 SELECT ... FROM t2 ...
1226
1197
      MySQL would use the lock TL_READ_NO_INSERT on t2, and that
1227
1198
      would conflict with TL_WRITE_ALLOW_WRITE, blocking all inserts
1228
1199
      to t2. Convert the lock to a normal read lock to allow
1229
 
      concurrent inserts to t2. 
 
1200
      concurrent inserts to t2.
1230
1201
    */
1231
1202
 
1232
 
    if (lock_type == TL_READ_NO_INSERT && !thd_in_lock_tables(thd)) 
 
1203
    if (lock_type == TL_READ_NO_INSERT && !session_in_lock_tables(session))
1233
1204
      lock_type = TL_READ;
1234
1205
 
1235
1206
    lock.type=lock_type;
1260
1231
*/
1261
1232
int ha_archive::info(uint32_t flag)
1262
1233
{
1263
 
  /* 
 
1234
  /*
1264
1235
    If dirty, we lock, and then reset/flush the data.
1265
1236
    I found that just calling azflush() doesn't always work.
1266
1237
  */
1278
1249
 
1279
1250
  }
1280
1251
 
1281
 
  /* 
 
1252
  /*
1282
1253
    This should be an accurate number now, though bulk and delayed inserts can
1283
1254
    cause the number to be inaccurate.
1284
1255
  */
1331
1302
}
1332
1303
 
1333
1304
 
1334
 
/* 
 
1305
/*
1335
1306
  Other side of start_bulk_insert, is end_bulk_insert. Here we turn off the bulk insert
1336
1307
  flag, and set the share dirty so that the next select will call sync for us.
1337
1308
*/
1344
1315
 
1345
1316
/*
1346
1317
  We cancel a truncate command. The only way to delete an archive table is to drop it.
1347
 
  This is done for security reasons. In a later version we will enable this by 
 
1318
  This is done for security reasons. In a later version we will enable this by
1348
1319
  allowing the user to select a different row format.
1349
1320
*/
1350
1321
int ha_archive::delete_all_rows()
1355
1326
/*
1356
1327
  We just return state if asked.
1357
1328
*/
1358
 
bool ha_archive::is_crashed() const 
 
1329
bool ha_archive::is_crashed() const
1359
1330
{
1360
 
  return(share->crashed); 
 
1331
  return(share->crashed);
1361
1332
}
1362
1333
 
1363
1334
/*
1364
1335
  Simple scan of the tables to make sure everything is ok.
1365
1336
*/
1366
1337
 
1367
 
int ha_archive::check(THD* thd,
1368
 
                      HA_CHECK_OPT* check_opt __attribute__((unused)))
 
1338
int ha_archive::check(Session* session, HA_CHECK_OPT *)
1369
1339
{
1370
1340
  int rc= 0;
1371
1341
  const char *old_proc_info;
1372
1342
  uint64_t x;
1373
1343
 
1374
 
  old_proc_info= thd_proc_info(thd, "Checking table");
 
1344
  old_proc_info= get_session_proc_info(session);
 
1345
  set_session_proc_info(session, "Checking table");
1375
1346
  /* Flush any waiting data */
1376
1347
  pthread_mutex_lock(&share->mutex);
1377
1348
  azflush(&(share->archive_write), Z_SYNC_FLUSH);
1378
1349
  pthread_mutex_unlock(&share->mutex);
1379
1350
 
1380
1351
  /*
1381
 
    Now we will rewind the archive file so that we are positioned at the 
 
1352
    Now we will rewind the archive file so that we are positioned at the
1382
1353
    start of the file.
1383
1354
  */
1384
1355
  init_archive_reader();
1392
1363
      break;
1393
1364
  }
1394
1365
 
1395
 
  thd_proc_info(thd, old_proc_info);
 
1366
  set_session_proc_info(session, old_proc_info);
1396
1367
 
1397
 
  if ((rc && rc != HA_ERR_END_OF_FILE))  
 
1368
  if ((rc && rc != HA_ERR_END_OF_FILE))
1398
1369
  {
1399
1370
    share->crashed= false;
1400
1371
    return(HA_ADMIN_CORRUPT);
1408
1379
/*
1409
1380
  Check and repair the table if needed.
1410
1381
*/
1411
 
bool ha_archive::check_and_repair(THD *thd) 
 
1382
bool ha_archive::check_and_repair(Session *session)
1412
1383
{
1413
1384
  HA_CHECK_OPT check_opt;
1414
1385
 
1415
1386
  check_opt.init();
1416
1387
 
1417
 
  return(repair(thd, &check_opt));
 
1388
  return(repair(session, &check_opt));
1418
1389
}
1419
1390
 
1420
 
archive_record_buffer *ha_archive::create_record_buffer(unsigned int length) 
 
1391
archive_record_buffer *ha_archive::create_record_buffer(unsigned int length)
1421
1392
{
1422
1393
  archive_record_buffer *r;
1423
 
  if (!(r= 
1424
 
        (archive_record_buffer*) my_malloc(sizeof(archive_record_buffer),
1425
 
                                           MYF(MY_WME))))
 
1394
  if (!(r= (archive_record_buffer*) malloc(sizeof(archive_record_buffer))))
1426
1395
  {
1427
1396
    return(NULL); /* purecov: inspected */
1428
1397
  }
1429
1398
  r->length= (int)length;
1430
1399
 
1431
 
  if (!(r->buffer= (unsigned char*) my_malloc(r->length,
1432
 
                                    MYF(MY_WME))))
 
1400
  if (!(r->buffer= (unsigned char*) malloc(r->length)))
1433
1401
  {
1434
1402
    free((char*) r);
1435
1403
    return(NULL); /* purecov: inspected */
1438
1406
  return(r);
1439
1407
}
1440
1408
 
1441
 
void ha_archive::destroy_record_buffer(archive_record_buffer *r) 
 
1409
void ha_archive::destroy_record_buffer(archive_record_buffer *r)
1442
1410
{
1443
1411
  free((char*) r->buffer);
1444
1412
  free((char*) r);
1455
1423
  NULL
1456
1424
};
1457
1425
 
1458
 
mysql_declare_plugin(archive)
 
1426
drizzle_declare_plugin(archive)
1459
1427
{
1460
1428
  DRIZZLE_STORAGE_ENGINE_PLUGIN,
1461
1429
  "ARCHIVE",
1469
1437
  archive_system_variables,   /* system variables                */
1470
1438
  NULL                        /* config options                  */
1471
1439
}
1472
 
mysql_declare_plugin_end;
 
1440
drizzle_declare_plugin_end;
1473
1441