~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to storage/archive/ha_archive.cc

  • Committer: Brian Aker
  • Date: 2008-07-14 22:18:37 UTC
  • mfrom: (77.1.96 codestyle)
  • Revision ID: brian@tangent.org-20080714221837-oceoshx7fjkla9u3
Merge from Monty

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/mysql_priv.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 
115
118
                     uchar **frmblob, 
116
119
                     size_t *frmlen);
117
120
 
118
 
static my_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.
153
156
    void *
154
157
 
155
158
  RETURN
156
 
    false       OK
157
 
    true        Error
 
159
    FALSE       OK
 
160
    TRUE        Error
158
161
*/
159
162
 
160
163
int archive_db_init(void *p)
161
164
{
 
165
  DBUG_ENTER("archive_db_init");
162
166
  handlerton *archive_hton;
163
167
 
164
168
  archive_hton= (handlerton *)p;
180
184
  }
181
185
  else
182
186
  {
183
 
    return(false);
 
187
    DBUG_RETURN(FALSE);
184
188
  }
185
189
error:
186
 
  return(true);
 
190
  DBUG_RETURN(TRUE);
187
191
}
188
192
 
189
193
/*
194
198
    void
195
199
 
196
200
  RETURN
197
 
    false       OK
 
201
    FALSE       OK
198
202
*/
199
203
 
200
 
int archive_db_done(void *p __attribute__((unused)))
 
204
int archive_db_done(void *p __attribute__((__unused__)))
201
205
{
202
206
  hash_free(&archive_open_tables);
203
207
  VOID(pthread_mutex_destroy(&archive_mutex));
214
218
 
215
219
  /* The size of the offset value we will use for position() */
216
220
  ref_length= sizeof(my_off_t);
217
 
  archive_reader_open= false;
 
221
  archive_reader_open= FALSE;
218
222
}
219
223
 
220
 
int archive_discover(handlerton *hton __attribute__((unused)),
221
 
                     THD* thd __attribute__((unused)),
 
224
int archive_discover(handlerton *hton __attribute__((__unused__)),
 
225
                     THD* thd __attribute__((__unused__)),
222
226
                     const char *db,
223
227
                     const char *name,
224
228
                     uchar **frmblob,
225
229
                     size_t *frmlen)
226
230
{
 
231
  DBUG_ENTER("archive_discover");
 
232
  DBUG_PRINT("archive_discover", ("db: %s, name: %s", db, name)); 
227
233
  azio_stream frm_stream;
228
234
  char az_file[FN_REFLEN];
229
235
  char *frm_ptr;
237
243
  if (!(azopen(&frm_stream, az_file, O_RDONLY|O_BINARY, AZ_METHOD_BLOCK)))
238
244
  {
239
245
    if (errno == EROFS || errno == EACCES)
240
 
      return(my_errno= errno);
241
 
    return(HA_ERR_CRASHED_ON_USAGE);
 
246
      DBUG_RETURN(my_errno= errno);
 
247
    DBUG_RETURN(HA_ERR_CRASHED_ON_USAGE);
242
248
  }
243
249
 
244
250
  if (frm_stream.frm_length == 0)
251
257
  *frmlen= frm_stream.frm_length;
252
258
  *frmblob= (uchar*) frm_ptr;
253
259
 
254
 
  return(0);
 
260
  DBUG_RETURN(0);
255
261
err:
256
262
  my_errno= 0;
257
 
  return(1);
 
263
  DBUG_RETURN(1);
258
264
}
259
265
 
260
266
/*
262
268
*/
263
269
int ha_archive::read_data_header(azio_stream *file_to_read)
264
270
{
 
271
  DBUG_ENTER("ha_archive::read_data_header");
 
272
 
265
273
  if (azread_init(file_to_read) == -1)
266
 
    return(HA_ERR_CRASHED_ON_USAGE);
 
274
    DBUG_RETURN(HA_ERR_CRASHED_ON_USAGE);
267
275
 
268
276
  if (file_to_read->version >= 3)
269
 
    return(0);
 
277
    DBUG_RETURN(0);
270
278
 
271
 
  return(1);
 
279
  DBUG_RETURN(1);
272
280
}
273
281
 
274
282
 
282
290
ARCHIVE_SHARE *ha_archive::get_share(const char *table_name, int *rc)
283
291
{
284
292
  uint length;
 
293
  DBUG_ENTER("ha_archive::get_share");
285
294
 
286
295
  pthread_mutex_lock(&archive_mutex);
287
296
  length=(uint) strlen(table_name);
300
309
    {
301
310
      pthread_mutex_unlock(&archive_mutex);
302
311
      *rc= HA_ERR_OUT_OF_MEM;
303
 
      return(NULL);
 
312
      DBUG_RETURN(NULL);
304
313
    }
305
314
 
306
315
    share->use_count= 0;
307
316
    share->table_name_length= length;
308
317
    share->table_name= tmp_name;
309
 
    share->crashed= false;
310
 
    share->archive_write_open= false;
 
318
    share->crashed= FALSE;
 
319
    share->archive_write_open= FALSE;
311
320
    fn_format(share->data_file_name, table_name, "",
312
321
              ARZ, MY_REPLACE_EXT | MY_UNPACK_FILENAME);
313
322
    strmov(share->table_name, table_name);
 
323
    DBUG_PRINT("ha_archive", ("Data File %s", 
 
324
                        share->data_file_name));
314
325
    /*
315
326
      We will use this lock for rows.
316
327
    */
329
340
      free(share);
330
341
      pthread_mutex_unlock(&archive_mutex);
331
342
      *rc= HA_ERR_CRASHED_ON_REPAIR;
332
 
      return(NULL);
 
343
      DBUG_RETURN(NULL);
333
344
    }
334
345
    stats.auto_increment_value= archive_tmp.auto_increment + 1;
335
346
    share->rows_recorded= (ha_rows)archive_tmp.rows;
345
356
    thr_lock_init(&share->lock);
346
357
  }
347
358
  share->use_count++;
 
359
  DBUG_PRINT("ha_archive", ("archive table %.*s has %d open handles now", 
 
360
                      share->table_name_length, share->table_name,
 
361
                      share->use_count));
348
362
  if (share->crashed)
349
363
    *rc= HA_ERR_CRASHED_ON_USAGE;
350
364
  pthread_mutex_unlock(&archive_mutex);
351
365
 
352
 
  return(share);
 
366
  DBUG_RETURN(share);
353
367
}
354
368
 
355
369
 
360
374
int ha_archive::free_share()
361
375
{
362
376
  int rc= 0;
 
377
  DBUG_ENTER("ha_archive::free_share");
 
378
  DBUG_PRINT("ha_archive",
 
379
             ("archive table %.*s has %d open handles on entrance", 
 
380
              share->table_name_length, share->table_name,
 
381
              share->use_count));
363
382
 
364
383
  pthread_mutex_lock(&archive_mutex);
365
384
  if (!--share->use_count)
374
393
      Since we will close the data down after this, we go on and count
375
394
      the flush on close;
376
395
    */
377
 
    if (share->archive_write_open == true)
 
396
    if (share->archive_write_open == TRUE)
378
397
    {
379
398
      if (azclose(&(share->archive_write)))
380
399
        rc= 1;
383
402
  }
384
403
  pthread_mutex_unlock(&archive_mutex);
385
404
 
386
 
  return(rc);
 
405
  DBUG_RETURN(rc);
387
406
}
388
407
 
389
408
int ha_archive::init_archive_writer()
390
409
{
 
410
  DBUG_ENTER("ha_archive::init_archive_writer");
391
411
  /* 
392
412
    It is expensive to open and close the data files and since you can't have
393
413
    a gzip file that can be both read and written we keep a writer open
396
416
  if (!(azopen(&(share->archive_write), share->data_file_name, 
397
417
               O_RDWR|O_BINARY, AZ_METHOD_BLOCK)))
398
418
  {
399
 
    share->crashed= true;
400
 
    return(1);
 
419
    DBUG_PRINT("ha_archive", ("Could not open archive write file"));
 
420
    share->crashed= TRUE;
 
421
    DBUG_RETURN(1);
401
422
  }
402
 
  share->archive_write_open= true;
 
423
  share->archive_write_open= TRUE;
403
424
 
404
 
  return(0);
 
425
  DBUG_RETURN(0);
405
426
}
406
427
 
407
428
 
410
431
*/
411
432
int ha_archive::init_archive_reader()
412
433
{
 
434
  DBUG_ENTER("ha_archive::init_archive_reader");
413
435
  /* 
414
436
    It is expensive to open and close the data files and since you can't have
415
437
    a gzip file that can be both read and written we keep a writer open
416
438
    that is shared amoung all open tables.
417
439
  */
418
 
  if (archive_reader_open == false)
 
440
  if (archive_reader_open == FALSE)
419
441
  {
420
442
    az_method method;
421
443
 
422
444
    switch (archive_use_aio)
423
445
    {
424
 
    case false:
 
446
    case FALSE:
425
447
      method= AZ_METHOD_BLOCK;
426
448
      break;
427
 
    case true:
 
449
    case TRUE:
428
450
      method= AZ_METHOD_AIO;
429
451
      break;
430
452
    default:
433
455
    if (!(azopen(&archive, share->data_file_name, O_RDONLY|O_BINARY, 
434
456
                 method)))
435
457
    {
436
 
      share->crashed= true;
437
 
      return(1);
 
458
      DBUG_PRINT("ha_archive", ("Could not open archive read file"));
 
459
      share->crashed= TRUE;
 
460
      DBUG_RETURN(1);
438
461
    }
439
 
    archive_reader_open= true;
 
462
    archive_reader_open= TRUE;
440
463
  }
441
464
 
442
 
  return(0);
 
465
  DBUG_RETURN(0);
443
466
}
444
467
 
445
468
 
464
487
  We open the file we will read from.
465
488
*/
466
489
int ha_archive::open(const char *name,
467
 
                     int mode __attribute__((unused)),
 
490
                     int mode __attribute__((__unused__)),
468
491
                     uint open_options)
469
492
{
470
493
  int rc= 0;
 
494
  DBUG_ENTER("ha_archive::open");
 
495
 
 
496
  DBUG_PRINT("ha_archive", ("archive table was opened for crash: %s", 
 
497
                      (open_options & HA_OPEN_FOR_REPAIR) ? "yes" : "no"));
471
498
  share= get_share(name, &rc);
472
499
 
473
500
  if (rc == HA_ERR_CRASHED_ON_USAGE && !(open_options & HA_OPEN_FOR_REPAIR))
474
501
  {
475
502
    /* purecov: begin inspected */
476
503
    free_share();
477
 
    return(rc);
 
504
    DBUG_RETURN(rc);
478
505
    /* purecov: end */    
479
506
  }
480
507
  else if (rc == HA_ERR_OUT_OF_MEM)
481
508
  {
482
 
    return(rc);
 
509
    DBUG_RETURN(rc);
483
510
  }
484
511
 
485
 
  assert(share);
 
512
  DBUG_ASSERT(share);
486
513
 
487
514
  record_buffer= create_record_buffer(table->s->reclength + 
488
515
                                      ARCHIVE_ROW_HEADER_SIZE);
490
517
  if (!record_buffer)
491
518
  {
492
519
    free_share();
493
 
    return(HA_ERR_OUT_OF_MEM);
 
520
    DBUG_RETURN(HA_ERR_OUT_OF_MEM);
494
521
  }
495
522
 
496
523
  thr_lock_data_init(&share->lock, &lock, NULL);
497
524
 
 
525
  DBUG_PRINT("ha_archive", ("archive table was crashed %s", 
 
526
                      rc == HA_ERR_CRASHED_ON_USAGE ? "yes" : "no"));
498
527
  if (rc == HA_ERR_CRASHED_ON_USAGE && open_options & HA_OPEN_FOR_REPAIR)
499
528
  {
500
 
    return(0);
 
529
    DBUG_RETURN(0);
501
530
  }
502
531
  else
503
 
    return(rc);
 
532
    DBUG_RETURN(rc);
504
533
}
505
534
 
506
535
 
524
553
int ha_archive::close(void)
525
554
{
526
555
  int rc= 0;
 
556
  DBUG_ENTER("ha_archive::close");
527
557
 
528
558
  destroy_record_buffer(record_buffer);
529
559
 
530
560
  /* First close stream */
531
 
  if (archive_reader_open == true)
 
561
  if (archive_reader_open == TRUE)
532
562
  {
533
563
    if (azclose(&archive))
534
564
      rc= 1;
536
566
  /* then also close share */
537
567
  rc|= free_share();
538
568
 
539
 
  return(rc);
 
569
  DBUG_RETURN(rc);
540
570
}
541
571
 
542
572
 
560
590
  struct stat file_stat;
561
591
  uchar *frm_ptr;
562
592
 
 
593
  DBUG_ENTER("ha_archive::create");
 
594
 
563
595
  stats.auto_increment_value= create_info->auto_increment_value;
564
596
 
565
597
  for (uint key= 0; key < table_arg->s->keys; key++)
575
607
      if (!(field->flags & AUTO_INCREMENT_FLAG))
576
608
      {
577
609
        error= -1;
 
610
        DBUG_PRINT("ha_archive", ("Index error in creating archive table"));
578
611
        goto error;
579
612
      }
580
613
    }
585
618
  */
586
619
  if (create_info->data_file_name && create_info->data_file_name[0] != '#')
587
620
  {
 
621
    DBUG_PRINT("ha_archive", ("archive will create stream file %s", 
 
622
                        create_info->data_file_name));
 
623
                        
588
624
    fn_format(name_buff, create_info->data_file_name, "", ARZ,
589
625
              MY_REPLACE_EXT | MY_UNPACK_FILENAME);
590
626
    fn_format(linkname, name, "", ARZ,
653
689
  else
654
690
    my_errno= 0;
655
691
 
656
 
  return(0);
 
692
  DBUG_PRINT("ha_archive", ("Creating File %s", name_buff));
 
693
  DBUG_PRINT("ha_archive", ("Creating Link %s", linkname));
 
694
 
 
695
 
 
696
  DBUG_RETURN(0);
657
697
 
658
698
error2:
659
699
  delete_table(name);
660
700
error:
661
701
  /* Return error number, if we got one */
662
 
  return(error ? error : -1);
 
702
  DBUG_RETURN(error ? error : -1);
663
703
}
664
704
 
665
705
/*
669
709
{
670
710
  my_off_t written;
671
711
  unsigned int r_pack_length;
 
712
  DBUG_ENTER("ha_archive::real_write_row");
672
713
 
673
714
  /* We pack the row for writing */
674
715
  r_pack_length= pack_row(buf);
676
717
  written= azwrite_row(writer, record_buffer->buffer, r_pack_length);
677
718
  if (written != r_pack_length)
678
719
  {
679
 
    return(-1);
 
720
    DBUG_PRINT("ha_archive", ("Wrote %d bytes expected %d", 
 
721
                                              (uint32) written, 
 
722
                                              (uint32)r_pack_length));
 
723
    DBUG_RETURN(-1);
680
724
  }
681
725
 
682
726
  if (!delayed_insert || !bulk_insert)
683
 
    share->dirty= true;
 
727
    share->dirty= TRUE;
684
728
 
685
 
  return(0);
 
729
  DBUG_RETURN(0);
686
730
}
687
731
 
688
732
 
691
735
  the bytes required for the length in the header.
692
736
*/
693
737
 
694
 
uint32_t ha_archive::max_row_length(const uchar *buf __attribute__((unused)))
 
738
uint32 ha_archive::max_row_length(const uchar *buf __attribute__((__unused__)))
695
739
{
696
 
  uint32_t length= (uint32_t)(table->s->reclength + table->s->fields*2);
 
740
  uint32 length= (uint32)(table->s->reclength + table->s->fields*2);
697
741
  length+= ARCHIVE_ROW_HEADER_SIZE;
698
742
 
699
743
  uint *ptr, *end;
712
756
{
713
757
  uchar *ptr;
714
758
 
 
759
  DBUG_ENTER("ha_archive::pack_row");
 
760
 
 
761
 
715
762
  if (fix_rec_buff(max_row_length(record)))
716
 
    return(HA_ERR_OUT_OF_MEM); /* purecov: inspected */
 
763
    DBUG_RETURN(HA_ERR_OUT_OF_MEM); /* purecov: inspected */
717
764
 
718
765
  /* Copy null bits */
719
766
  memcpy(record_buffer->buffer, record, table->s->null_bytes);
725
772
      ptr= (*field)->pack(ptr, record + (*field)->offset(record));
726
773
  }
727
774
 
728
 
  return((unsigned int) (ptr - record_buffer->buffer));
 
775
  DBUG_PRINT("ha_archive",("Pack row length %u", (unsigned int)
 
776
                           (ptr - record_buffer->buffer - 
 
777
                             ARCHIVE_ROW_HEADER_SIZE)));
 
778
 
 
779
  DBUG_RETURN((unsigned int) (ptr - record_buffer->buffer));
729
780
}
730
781
 
731
782
 
744
795
  uchar *read_buf= NULL;
745
796
  uint64_t temp_auto;
746
797
  uchar *record=  table->record[0];
 
798
  DBUG_ENTER("ha_archive::write_row");
747
799
 
748
800
  if (share->crashed)
749
 
    return(HA_ERR_CRASHED_ON_USAGE);
 
801
    DBUG_RETURN(HA_ERR_CRASHED_ON_USAGE);
750
802
 
751
803
  ha_statistic_increment(&SSV::ha_write_count);
752
804
  if (table->timestamp_field_type & TIMESTAMP_AUTO_SET_ON_INSERT)
753
805
    table->timestamp_field->set_time();
754
806
  pthread_mutex_lock(&share->mutex);
755
807
 
756
 
  if (share->archive_write_open == false)
 
808
  if (share->archive_write_open == FALSE)
757
809
    if (init_archive_writer())
758
 
      return(HA_ERR_CRASHED_ON_USAGE);
 
810
      DBUG_RETURN(HA_ERR_CRASHED_ON_USAGE);
759
811
 
760
812
 
761
813
  if (table->next_number_field && record == table->record[0])
838
890
  if (read_buf)
839
891
    my_free((uchar*) read_buf, MYF(0));
840
892
 
841
 
  return(rc);
 
893
  DBUG_RETURN(rc);
842
894
}
843
895
 
844
896
 
845
 
void ha_archive::get_auto_increment(uint64_t offset __attribute__((unused)),
846
 
                                    uint64_t increment __attribute__((unused)),
847
 
                                    uint64_t nb_desired_values __attribute__((unused)),
848
 
                                    uint64_t *first_value __attribute__((unused)),
849
 
                                    uint64_t *nb_reserved_values __attribute__((unused)))
 
897
void ha_archive::get_auto_increment(uint64_t offset __attribute__((__unused__)),
 
898
                                    uint64_t increment __attribute__((__unused__)),
 
899
                                    uint64_t nb_desired_values __attribute__((__unused__)),
 
900
                                    uint64_t *first_value __attribute__((__unused__)),
 
901
                                    uint64_t *nb_reserved_values __attribute__((__unused__)))
850
902
{
851
 
  *nb_reserved_values= UINT64_MAX;
 
903
  *nb_reserved_values= ULONGLONG_MAX;
852
904
  *first_value= share->archive_write.auto_increment + 1;
853
905
}
854
906
 
855
907
/* Initialized at each key walk (called multiple times unlike rnd_init()) */
856
 
int ha_archive::index_init(uint keynr, bool sorted __attribute__((unused)))
 
908
int ha_archive::index_init(uint keynr, bool sorted __attribute__((__unused__)))
857
909
{
 
910
  DBUG_ENTER("ha_archive::index_init");
858
911
  active_index= keynr;
859
 
  return(0);
 
912
  DBUG_RETURN(0);
860
913
}
861
914
 
862
915
 
868
921
                             uint key_len, enum ha_rkey_function find_flag)
869
922
{
870
923
  int rc;
 
924
  DBUG_ENTER("ha_archive::index_read");
871
925
  rc= index_read_idx(buf, active_index, key, key_len, find_flag);
872
 
  return(rc);
 
926
  DBUG_RETURN(rc);
873
927
}
874
928
 
875
929
 
876
930
int ha_archive::index_read_idx(uchar *buf, uint index, const uchar *key,
877
931
                               uint key_len,
878
 
                               enum ha_rkey_function find_flag __attribute__((unused)))
 
932
                               enum ha_rkey_function find_flag __attribute__((__unused__)))
879
933
{
880
934
  int rc;
881
935
  bool found= 0;
884
938
  current_key= key;
885
939
  current_key_len= key_len;
886
940
 
887
 
  rc= rnd_init(true);
 
941
 
 
942
  DBUG_ENTER("ha_archive::index_read_idx");
 
943
 
 
944
  rc= rnd_init(TRUE);
888
945
 
889
946
  if (rc)
890
947
    goto error;
899
956
  }
900
957
 
901
958
  if (found)
902
 
    return(0);
 
959
    DBUG_RETURN(0);
903
960
 
904
961
error:
905
 
  return(rc ? rc : HA_ERR_END_OF_FILE);
 
962
  DBUG_RETURN(rc ? rc : HA_ERR_END_OF_FILE);
906
963
}
907
964
 
908
965
 
910
967
911
968
  bool found= 0;
912
969
 
 
970
  DBUG_ENTER("ha_archive::index_next");
 
971
 
913
972
  while (!(get_row(&archive, buf)))
914
973
  {
915
974
    if (!memcmp(current_key, buf+current_k_offset, current_key_len))
919
978
    }
920
979
  }
921
980
 
922
 
  return(found ? 0 : HA_ERR_END_OF_FILE); 
 
981
  DBUG_RETURN(found ? 0 : HA_ERR_END_OF_FILE); 
923
982
}
924
983
 
925
984
/*
930
989
 
931
990
int ha_archive::rnd_init(bool scan)
932
991
{
 
992
  DBUG_ENTER("ha_archive::rnd_init");
 
993
  
933
994
  if (share->crashed)
934
 
      return(HA_ERR_CRASHED_ON_USAGE);
 
995
      DBUG_RETURN(HA_ERR_CRASHED_ON_USAGE);
935
996
 
936
997
  init_archive_reader();
937
998
 
938
999
  /* We rewind the file so that we can read from the beginning if scan */
939
1000
  if (scan)
940
1001
  {
 
1002
    DBUG_PRINT("info", ("archive will retrieve %llu rows", 
 
1003
                        (uint64_t) scan_rows));
 
1004
 
941
1005
    if (read_data_header(&archive))
942
 
      return(HA_ERR_CRASHED_ON_USAGE);
 
1006
      DBUG_RETURN(HA_ERR_CRASHED_ON_USAGE);
943
1007
  }
944
1008
 
945
 
  return(0);
 
1009
  DBUG_RETURN(0);
946
1010
}
947
1011
 
948
1012
 
953
1017
int ha_archive::get_row(azio_stream *file_to_read, uchar *buf)
954
1018
{
955
1019
  int rc;
956
 
 
 
1020
  DBUG_ENTER("ha_archive::get_row");
 
1021
  DBUG_PRINT("ha_archive", ("Picking version for get_row() %d -> %d", 
 
1022
                            (uchar)file_to_read->version, 
 
1023
                            ARCHIVE_VERSION));
957
1024
  if (file_to_read->version == ARCHIVE_VERSION)
958
1025
    rc= get_row_version3(file_to_read, buf);
959
1026
  else
960
1027
    rc= -1;
961
1028
 
962
 
  return(rc);
 
1029
  DBUG_PRINT("ha_archive", ("Return %d\n", rc));
 
1030
 
 
1031
  DBUG_RETURN(rc);
963
1032
}
964
1033
 
965
1034
/* Reallocate buffer if needed */
966
1035
bool ha_archive::fix_rec_buff(unsigned int length)
967
1036
{
968
 
  assert(record_buffer->buffer);
 
1037
  DBUG_ENTER("ha_archive::fix_rec_buff");
 
1038
  DBUG_PRINT("ha_archive", ("Fixing %u for %u", 
 
1039
                            length, record_buffer->length));
 
1040
  DBUG_ASSERT(record_buffer->buffer);
969
1041
 
970
1042
  if (length > record_buffer->length)
971
1043
  {
973
1045
    if (!(newptr=(uchar*) my_realloc((uchar*) record_buffer->buffer, 
974
1046
                                    length,
975
1047
                                    MYF(MY_ALLOW_ZERO_PTR))))
976
 
      return(1);
 
1048
      DBUG_RETURN(1);
977
1049
    record_buffer->buffer= newptr;
978
1050
    record_buffer->length= length;
979
1051
  }
980
1052
 
981
 
  assert(length <= record_buffer->length);
 
1053
  DBUG_ASSERT(length <= record_buffer->length);
982
1054
 
983
 
  return(0);
 
1055
  DBUG_RETURN(0);
984
1056
}
985
1057
 
986
1058
int ha_archive::unpack_row(azio_stream *file_to_read, uchar *record)
987
1059
{
 
1060
  DBUG_ENTER("ha_archive::unpack_row");
 
1061
 
988
1062
  unsigned int read;
989
1063
  int error;
990
1064
  const uchar *ptr;
994
1068
 
995
1069
  if (error || read == 0)
996
1070
  {
997
 
    return(-1);
 
1071
    DBUG_RETURN(-1);
998
1072
  }
999
1073
 
1000
1074
  /* Copy null bits */
1007
1081
      ptr= (*field)->unpack(record + (*field)->offset(table->record[0]), ptr);
1008
1082
    }
1009
1083
  }
1010
 
  return(0);
 
1084
  DBUG_RETURN(0);
1011
1085
}
1012
1086
 
1013
1087
 
1014
1088
int ha_archive::get_row_version3(azio_stream *file_to_read, uchar *buf)
1015
1089
{
 
1090
  DBUG_ENTER("ha_archive::get_row_version3");
 
1091
 
1016
1092
  int returnable= unpack_row(file_to_read, buf);
1017
1093
 
1018
 
  return(returnable);
 
1094
  DBUG_RETURN(returnable);
1019
1095
}
1020
1096
 
1021
1097
 
1027
1103
int ha_archive::rnd_next(uchar *buf)
1028
1104
{
1029
1105
  int rc;
 
1106
  DBUG_ENTER("ha_archive::rnd_next");
1030
1107
 
1031
1108
  if (share->crashed)
1032
 
      return(HA_ERR_CRASHED_ON_USAGE);
 
1109
      DBUG_RETURN(HA_ERR_CRASHED_ON_USAGE);
1033
1110
 
1034
1111
  if (!scan_rows)
1035
 
    return(HA_ERR_END_OF_FILE);
 
1112
    DBUG_RETURN(HA_ERR_END_OF_FILE);
1036
1113
  scan_rows--;
1037
1114
 
1038
1115
  ha_statistic_increment(&SSV::ha_read_rnd_next_count);
1041
1118
 
1042
1119
  table->status=rc ? STATUS_NOT_FOUND: 0;
1043
1120
 
1044
 
  return(rc);
 
1121
  DBUG_RETURN(rc);
1045
1122
}
1046
1123
 
1047
1124
 
1051
1128
  needed.
1052
1129
*/
1053
1130
 
1054
 
void ha_archive::position(const uchar *record __attribute__((unused)))
 
1131
void ha_archive::position(const uchar *record __attribute__((__unused__)))
1055
1132
{
 
1133
  DBUG_ENTER("ha_archive::position");
1056
1134
  my_store_ptr(ref, ref_length, current_position);
1057
 
  return;
 
1135
  DBUG_VOID_RETURN;
1058
1136
}
1059
1137
 
1060
1138
 
1067
1145
 
1068
1146
int ha_archive::rnd_pos(uchar * buf, uchar *pos)
1069
1147
{
 
1148
  DBUG_ENTER("ha_archive::rnd_pos");
1070
1149
  ha_statistic_increment(&SSV::ha_read_rnd_next_count);
1071
1150
  current_position= (my_off_t)my_get_ptr(pos, ref_length);
1072
1151
  if (azseek(&archive, (size_t)current_position, SEEK_SET) == (size_t)(-1L))
1073
 
    return(HA_ERR_CRASHED_ON_USAGE);
1074
 
  return(get_row(&archive, buf));
 
1152
    DBUG_RETURN(HA_ERR_CRASHED_ON_USAGE);
 
1153
  DBUG_RETURN(get_row(&archive, buf));
1075
1154
}
1076
1155
 
1077
1156
/*
1081
1160
*/
1082
1161
int ha_archive::repair(THD* thd, HA_CHECK_OPT* check_opt)
1083
1162
{
 
1163
  DBUG_ENTER("ha_archive::repair");
1084
1164
  check_opt->flags= T_EXTEND;
1085
1165
  int rc= optimize(thd, check_opt);
1086
1166
 
1087
1167
  if (rc)
1088
 
    return(HA_ERR_CRASHED_ON_REPAIR);
 
1168
    DBUG_RETURN(HA_ERR_CRASHED_ON_REPAIR);
1089
1169
 
1090
 
  share->crashed= false;
1091
 
  return(0);
 
1170
  share->crashed= FALSE;
 
1171
  DBUG_RETURN(0);
1092
1172
}
1093
1173
 
1094
1174
/*
1095
1175
  The table can become fragmented if data was inserted, read, and then
1096
1176
  inserted again. What we do is open up the file and recompress it completely. 
1097
1177
*/
1098
 
int ha_archive::optimize(THD* thd __attribute__((unused)),
1099
 
                         HA_CHECK_OPT* check_opt __attribute__((unused)))
 
1178
int ha_archive::optimize(THD* thd __attribute__((__unused__)),
 
1179
                         HA_CHECK_OPT* check_opt __attribute__((__unused__)))
1100
1180
{
 
1181
  DBUG_ENTER("ha_archive::optimize");
1101
1182
  int rc= 0;
1102
1183
  azio_stream writer;
1103
1184
  char writer_filename[FN_REFLEN];
1108
1189
  if (share->archive_write_open)
1109
1190
  {
1110
1191
    azclose(&(share->archive_write));
1111
 
    share->archive_write_open= false;
 
1192
    share->archive_write_open= FALSE;
1112
1193
  }
1113
1194
 
1114
1195
  /* Lets create a file to contain the new data */
1116
1197
            MY_REPLACE_EXT | MY_UNPACK_FILENAME);
1117
1198
 
1118
1199
  if (!(azopen(&writer, writer_filename, O_CREAT|O_RDWR|O_BINARY, AZ_METHOD_BLOCK)))
1119
 
    return(HA_ERR_CRASHED_ON_USAGE); 
 
1200
    DBUG_RETURN(HA_ERR_CRASHED_ON_USAGE); 
1120
1201
 
1121
1202
  /* 
1122
1203
    An extended rebuild is a lot more effort. We open up each row and re-record it. 
1127
1208
  */
1128
1209
  if (1)
1129
1210
  {
 
1211
    DBUG_PRINT("ha_archive", ("archive extended rebuild"));
 
1212
 
1130
1213
    /*
1131
1214
      Now we will rewind the archive file so that we are positioned at the 
1132
1215
      start of the file.
1176
1259
      share->rows_recorded= (ha_rows)writer.rows;
1177
1260
    }
1178
1261
 
 
1262
    DBUG_PRINT("info", ("recovered %llu archive rows", 
 
1263
                        (uint64_t)share->rows_recorded));
 
1264
 
 
1265
    DBUG_PRINT("ha_archive", ("recovered %llu archive rows", 
 
1266
                        (uint64_t)share->rows_recorded));
 
1267
 
1179
1268
    if (rc && rc != HA_ERR_END_OF_FILE)
1180
1269
    {
1181
1270
      goto error;
1183
1272
  } 
1184
1273
 
1185
1274
  azclose(&writer);
1186
 
  share->dirty= false;
 
1275
  share->dirty= FALSE;
1187
1276
  
1188
1277
  azclose(&archive);
1189
1278
 
1191
1280
  rc = my_rename(writer_filename,share->data_file_name,MYF(0));
1192
1281
 
1193
1282
 
1194
 
  return(rc);
 
1283
  DBUG_RETURN(rc);
1195
1284
error:
 
1285
  DBUG_PRINT("ha_archive", ("Failed to recover, error was %d", rc));
1196
1286
  azclose(&writer);
1197
1287
 
1198
 
  return(rc); 
 
1288
  DBUG_RETURN(rc); 
1199
1289
}
1200
1290
 
1201
1291
/* 
1206
1296
                                       enum thr_lock_type lock_type)
1207
1297
{
1208
1298
  if (lock_type == TL_WRITE_DELAYED)
1209
 
    delayed_insert= true;
 
1299
    delayed_insert= TRUE;
1210
1300
  else
1211
 
    delayed_insert= false;
 
1301
    delayed_insert= FALSE;
1212
1302
 
1213
1303
  if (lock_type != TL_IGNORE && lock.type == TL_UNLOCK) 
1214
1304
  {
1245
1335
 
1246
1336
void ha_archive::update_create_info(HA_CREATE_INFO *create_info)
1247
1337
{
 
1338
  DBUG_ENTER("ha_archive::update_create_info");
 
1339
 
1248
1340
  ha_archive::info(HA_STATUS_AUTO);
1249
1341
  if (!(create_info->used_fields & HA_CREATE_USED_AUTO))
1250
1342
  {
1254
1346
  if (!(my_readlink(share->real_path, share->data_file_name, MYF(0))))
1255
1347
    create_info->data_file_name= share->real_path;
1256
1348
 
1257
 
  return;
 
1349
  DBUG_VOID_RETURN;
1258
1350
}
1259
1351
 
1260
1352
 
1263
1355
*/
1264
1356
int ha_archive::info(uint flag)
1265
1357
{
 
1358
  DBUG_ENTER("ha_archive::info");
 
1359
 
1266
1360
  /* 
1267
1361
    If dirty, we lock, and then reset/flush the data.
1268
1362
    I found that just calling azflush() doesn't always work.
1269
1363
  */
1270
1364
  pthread_mutex_lock(&share->mutex);
1271
 
  if (share->dirty == true)
 
1365
  if (share->dirty == TRUE)
1272
1366
  {
 
1367
    DBUG_PRINT("ha_archive", ("archive flushing out rows for scan"));
1273
1368
    azflush(&(share->archive_write), Z_SYNC_FLUSH);
1274
1369
    share->rows_recorded= share->archive_write.rows;
1275
 
    share->dirty= false;
 
1370
    share->dirty= FALSE;
1276
1371
    if (share->version < global_version)
1277
1372
    {
1278
1373
      share->version_rows= share->rows_recorded;
1291
1386
  scan_rows= stats.records;
1292
1387
  stats.deleted= 0;
1293
1388
 
 
1389
  DBUG_PRINT("ha_archive", ("Stats rows is %d\n", (int)stats.records));
1294
1390
  /* Costs quite a bit more to get all information */
1295
1391
  if (flag & HA_STATUS_TIME)
1296
1392
  {
1316
1412
    stats.auto_increment_value= archive.auto_increment + 1;
1317
1413
  }
1318
1414
 
1319
 
  return(0);
 
1415
  DBUG_RETURN(0);
1320
1416
}
1321
1417
 
1322
1418
 
1328
1424
*/
1329
1425
void ha_archive::start_bulk_insert(ha_rows rows)
1330
1426
{
 
1427
  DBUG_ENTER("ha_archive::start_bulk_insert");
1331
1428
  if (!rows || rows >= ARCHIVE_MIN_ROWS_TO_USE_BULK_INSERT)
1332
 
    bulk_insert= true;
1333
 
  return;
 
1429
    bulk_insert= TRUE;
 
1430
  DBUG_VOID_RETURN;
1334
1431
}
1335
1432
 
1336
1433
 
1340
1437
*/
1341
1438
int ha_archive::end_bulk_insert()
1342
1439
{
1343
 
  bulk_insert= false;
1344
 
  share->dirty= true;
1345
 
  return(0);
 
1440
  DBUG_ENTER("ha_archive::end_bulk_insert");
 
1441
  bulk_insert= FALSE;
 
1442
  share->dirty= TRUE;
 
1443
  DBUG_RETURN(0);
1346
1444
}
1347
1445
 
1348
1446
/*
1352
1450
*/
1353
1451
int ha_archive::delete_all_rows()
1354
1452
{
1355
 
  return(HA_ERR_WRONG_COMMAND);
 
1453
  DBUG_ENTER("ha_archive::delete_all_rows");
 
1454
  DBUG_RETURN(HA_ERR_WRONG_COMMAND);
1356
1455
}
1357
1456
 
1358
1457
/*
1360
1459
*/
1361
1460
bool ha_archive::is_crashed() const 
1362
1461
{
1363
 
  return(share->crashed); 
 
1462
  DBUG_ENTER("ha_archive::is_crashed");
 
1463
  DBUG_RETURN(share->crashed); 
1364
1464
}
1365
1465
 
1366
1466
/*
1368
1468
*/
1369
1469
 
1370
1470
int ha_archive::check(THD* thd,
1371
 
                      HA_CHECK_OPT* check_opt __attribute__((unused)))
 
1471
                      HA_CHECK_OPT* check_opt __attribute__((__unused__)))
1372
1472
{
1373
1473
  int rc= 0;
1374
1474
  const char *old_proc_info;
1375
1475
  uint64_t x;
 
1476
  DBUG_ENTER("ha_archive::check");
1376
1477
 
1377
1478
  old_proc_info= thd_proc_info(thd, "Checking table");
1378
1479
  /* Flush any waiting data */
1399
1500
 
1400
1501
  if ((rc && rc != HA_ERR_END_OF_FILE))  
1401
1502
  {
1402
 
    share->crashed= false;
1403
 
    return(HA_ADMIN_CORRUPT);
 
1503
    share->crashed= FALSE;
 
1504
    DBUG_RETURN(HA_ADMIN_CORRUPT);
1404
1505
  }
1405
1506
  else
1406
1507
  {
1407
 
    return(HA_ADMIN_OK);
 
1508
    DBUG_RETURN(HA_ADMIN_OK);
1408
1509
  }
1409
1510
}
1410
1511
 
1414
1515
bool ha_archive::check_and_repair(THD *thd) 
1415
1516
{
1416
1517
  HA_CHECK_OPT check_opt;
 
1518
  DBUG_ENTER("ha_archive::check_and_repair");
1417
1519
 
1418
1520
  check_opt.init();
1419
1521
 
1420
 
  return(repair(thd, &check_opt));
 
1522
  DBUG_RETURN(repair(thd, &check_opt));
1421
1523
}
1422
1524
 
1423
1525
archive_record_buffer *ha_archive::create_record_buffer(unsigned int length) 
1424
1526
{
 
1527
  DBUG_ENTER("ha_archive::create_record_buffer");
1425
1528
  archive_record_buffer *r;
1426
1529
  if (!(r= 
1427
1530
        (archive_record_buffer*) my_malloc(sizeof(archive_record_buffer),
1428
1531
                                           MYF(MY_WME))))
1429
1532
  {
1430
 
    return(NULL); /* purecov: inspected */
 
1533
    DBUG_RETURN(NULL); /* purecov: inspected */
1431
1534
  }
1432
1535
  r->length= (int)length;
1433
1536
 
1435
1538
                                    MYF(MY_WME))))
1436
1539
  {
1437
1540
    my_free((char*) r, MYF(MY_ALLOW_ZERO_PTR));
1438
 
    return(NULL); /* purecov: inspected */
 
1541
    DBUG_RETURN(NULL); /* purecov: inspected */
1439
1542
  }
1440
1543
 
1441
 
  return(r);
 
1544
  DBUG_RETURN(r);
1442
1545
}
1443
1546
 
1444
1547
void ha_archive::destroy_record_buffer(archive_record_buffer *r) 
1445
1548
{
 
1549
  DBUG_ENTER("ha_archive::destroy_record_buffer");
1446
1550
  my_free((char*) r->buffer, MYF(MY_ALLOW_ZERO_PTR));
1447
1551
  my_free((char*) r, MYF(MY_ALLOW_ZERO_PTR));
1448
 
  return;
 
1552
  DBUG_VOID_RETURN;
1449
1553
}
1450
1554
 
1451
1555
static MYSQL_SYSVAR_BOOL(aio, archive_use_aio,
1452
1556
  PLUGIN_VAR_NOCMDOPT,
1453
1557
  "Whether or not to use asynchronous IO.",
1454
 
  NULL, NULL, true);
 
1558
  NULL, NULL, TRUE);
1455
1559
 
1456
1560
static struct st_mysql_sys_var* archive_system_variables[]= {
1457
1561
  MYSQL_SYSVAR(aio),
1458
1562
  NULL
1459
1563
};
1460
1564
 
 
1565
struct st_mysql_storage_engine archive_storage_engine=
 
1566
{ MYSQL_HANDLERTON_INTERFACE_VERSION };
 
1567
 
1461
1568
mysql_declare_plugin(archive)
1462
1569
{
1463
1570
  MYSQL_STORAGE_ENGINE_PLUGIN,
 
1571
  &archive_storage_engine,
1464
1572
  "ARCHIVE",
1465
 
  "3.5",
1466
1573
  "Brian Aker, MySQL AB",
1467
1574
  "Archive storage engine",
1468
1575
  PLUGIN_LICENSE_GPL,
1469
1576
  archive_db_init, /* Plugin Init */
1470
1577
  archive_db_done, /* Plugin Deinit */
 
1578
  0x0350 /* 3.0 */,
1471
1579
  NULL,                       /* status variables                */
1472
1580
  archive_system_variables,   /* system variables                */
1473
1581
  NULL                        /* config options                  */