~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to storage/archive/ha_archive.cc

  • Committer: Monty Taylor
  • Date: 2008-09-15 17:24:04 UTC
  • Revision ID: monty@inaugust.com-20080915172404-ygh6hiyu0q7qpa9x
Removed strndup calls.

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
16
19
 
17
20
#include <drizzled/common_includes.h>
18
21
#include <storage/myisam/myisam.h>
95
98
/* The file extension */
96
99
#define ARZ ".ARZ"               // The data file
97
100
#define ARN ".ARN"               // Files used during an optimize call
 
101
#define ARM ".ARM"               // Meta file (deprecated)
98
102
 
 
103
/*
 
104
  uchar + uchar
 
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
99
108
 
100
109
/* Static declarations for handerton */
101
110
static handler *archive_create_handler(handlerton *hton, 
102
111
                                       TABLE_SHARE *table, 
103
112
                                       MEM_ROOT *mem_root);
104
 
int archive_discover(handlerton *hton, Session* session, const char *db, 
 
113
int archive_discover(handlerton *hton, THD* thd, const char *db, 
105
114
                     const char *name,
106
 
                     unsigned char **frmblob, 
 
115
                     uchar **frmblob, 
107
116
                     size_t *frmlen);
108
117
 
109
118
static bool archive_use_aio= false;
128
137
/*
129
138
  Used for hash table that tracks open tables.
130
139
*/
131
 
static unsigned char* archive_get_key(ARCHIVE_SHARE *share, size_t *length,
 
140
static uchar* archive_get_key(ARCHIVE_SHARE *share, size_t *length,
132
141
                             bool not_used __attribute__((unused)))
133
142
{
134
143
  *length=share->table_name_length;
135
 
  return (unsigned char*) share->table_name;
 
144
  return (uchar*) share->table_name;
136
145
}
137
146
 
138
147
 
154
163
 
155
164
  archive_hton= (handlerton *)p;
156
165
  archive_hton->state= SHOW_OPTION_YES;
 
166
  archive_hton->db_type= DB_TYPE_ARCHIVE_DB;
157
167
  archive_hton->create= archive_create_handler;
158
168
  archive_hton->flags= HTON_NO_FLAGS;
159
169
  archive_hton->discover= archive_discover;
166
176
  if (hash_init(&archive_open_tables, system_charset_info, 32, 0, 0,
167
177
                (hash_get_key) archive_get_key, 0, 0))
168
178
  {
169
 
    pthread_mutex_destroy(&archive_mutex);
 
179
    VOID(pthread_mutex_destroy(&archive_mutex));
170
180
  }
171
181
  else
172
182
  {
190
200
int archive_db_done(void *p __attribute__((unused)))
191
201
{
192
202
  hash_free(&archive_open_tables);
193
 
  pthread_mutex_destroy(&archive_mutex);
 
203
  VOID(pthread_mutex_destroy(&archive_mutex));
194
204
 
195
205
  return 0;
196
206
}
208
218
}
209
219
 
210
220
int archive_discover(handlerton *hton __attribute__((unused)),
211
 
                     Session* session __attribute__((unused)),
 
221
                     THD* thd __attribute__((unused)),
212
222
                     const char *db,
213
223
                     const char *name,
214
 
                     unsigned char **frmblob,
 
224
                     uchar **frmblob,
215
225
                     size_t *frmlen)
216
226
{
217
227
  azio_stream frm_stream;
224
234
  if (stat(az_file, &file_stat))
225
235
    goto err;
226
236
 
227
 
  if (!(azopen(&frm_stream, az_file, O_RDONLY, AZ_METHOD_BLOCK)))
 
237
  if (!(azopen(&frm_stream, az_file, O_RDONLY|O_BINARY, AZ_METHOD_BLOCK)))
228
238
  {
229
239
    if (errno == EROFS || errno == EACCES)
230
240
      return(my_errno= errno);
239
249
  azclose(&frm_stream);
240
250
 
241
251
  *frmlen= frm_stream.frm_length;
242
 
  *frmblob= (unsigned char*) frm_ptr;
 
252
  *frmblob= (uchar*) frm_ptr;
243
253
 
244
254
  return(0);
245
255
err:
271
281
*/
272
282
ARCHIVE_SHARE *ha_archive::get_share(const char *table_name, int *rc)
273
283
{
274
 
  uint32_t length;
 
284
  uint length;
275
285
 
276
286
  pthread_mutex_lock(&archive_mutex);
277
287
  length=(uint) strlen(table_name);
278
288
 
279
289
  if (!(share=(ARCHIVE_SHARE*) hash_search(&archive_open_tables,
280
 
                                           (unsigned char*) table_name,
 
290
                                           (uchar*) table_name,
281
291
                                           length)))
282
292
  {
283
293
    char *tmp_name;
286
296
    if (!my_multi_malloc(MYF(MY_WME | MY_ZEROFILL),
287
297
                          &share, sizeof(*share),
288
298
                          &tmp_name, length+1,
289
 
                          NULL)) 
 
299
                          NullS)) 
290
300
    {
291
301
      pthread_mutex_unlock(&archive_mutex);
292
302
      *rc= HA_ERR_OUT_OF_MEM;
300
310
    share->archive_write_open= false;
301
311
    fn_format(share->data_file_name, table_name, "",
302
312
              ARZ, MY_REPLACE_EXT | MY_UNPACK_FILENAME);
303
 
    my_stpcpy(share->table_name, table_name);
 
313
    stpcpy(share->table_name, table_name);
304
314
    /*
305
315
      We will use this lock for rows.
306
316
    */
307
 
    pthread_mutex_init(&share->mutex,MY_MUTEX_INIT_FAST);
 
317
    VOID(pthread_mutex_init(&share->mutex,MY_MUTEX_INIT_FAST));
308
318
    
309
319
    /*
310
320
      We read the meta file, but do not mark it dirty. Since we are not
312
322
      anything but reading... open it for write and we will generate null
313
323
      compression writes).
314
324
    */
315
 
    if (!(azopen(&archive_tmp, share->data_file_name, O_RDONLY,
 
325
    if (!(azopen(&archive_tmp, share->data_file_name, O_RDONLY|O_BINARY,
316
326
                 AZ_METHOD_BLOCK)))
317
327
    {
318
 
      pthread_mutex_destroy(&share->mutex);
 
328
      VOID(pthread_mutex_destroy(&share->mutex));
319
329
      free(share);
320
330
      pthread_mutex_unlock(&archive_mutex);
321
331
      *rc= HA_ERR_CRASHED_ON_REPAIR;
331
341
    }
332
342
    azclose(&archive_tmp);
333
343
 
334
 
    my_hash_insert(&archive_open_tables, (unsigned char*) share);
 
344
    VOID(my_hash_insert(&archive_open_tables, (uchar*) share));
335
345
    thr_lock_init(&share->lock);
336
346
  }
337
347
  share->use_count++;
354
364
  pthread_mutex_lock(&archive_mutex);
355
365
  if (!--share->use_count)
356
366
  {
357
 
    hash_delete(&archive_open_tables, (unsigned char*) share);
 
367
    hash_delete(&archive_open_tables, (uchar*) share);
358
368
    thr_lock_delete(&share->lock);
359
 
    pthread_mutex_destroy(&share->mutex);
 
369
    VOID(pthread_mutex_destroy(&share->mutex));
360
370
    /* 
361
371
      We need to make sure we don't reset the crashed state.
362
372
      If we open a crashed file, wee need to close it as crashed unless
369
379
      if (azclose(&(share->archive_write)))
370
380
        rc= 1;
371
381
    }
372
 
    free((unsigned char*) share);
 
382
    my_free((uchar*) share, MYF(0));
373
383
  }
374
384
  pthread_mutex_unlock(&archive_mutex);
375
385
 
384
394
    that is shared amoung all open tables.
385
395
  */
386
396
  if (!(azopen(&(share->archive_write), share->data_file_name, 
387
 
               O_RDWR, AZ_METHOD_BLOCK)))
 
397
               O_RDWR|O_BINARY, AZ_METHOD_BLOCK)))
388
398
  {
389
399
    share->crashed= true;
390
400
    return(1);
420
430
    default:
421
431
      method= AZ_METHOD_BLOCK;
422
432
    }
423
 
    if (!(azopen(&archive, share->data_file_name, O_RDONLY, 
 
433
    if (!(azopen(&archive, share->data_file_name, O_RDONLY|O_BINARY, 
424
434
                 method)))
425
435
    {
426
436
      share->crashed= true;
438
448
*/
439
449
static const char *ha_archive_exts[] = {
440
450
  ARZ,
441
 
  NULL
 
451
  NullS
442
452
};
443
453
 
444
454
const char **ha_archive::bas_ext() const
455
465
*/
456
466
int ha_archive::open(const char *name,
457
467
                     int mode __attribute__((unused)),
458
 
                     uint32_t open_options)
 
468
                     uint open_options)
459
469
{
460
470
  int rc= 0;
461
471
  share= get_share(name, &rc);
548
558
  azio_stream create_stream;            /* Archive file we are working with */
549
559
  File frm_file;                   /* File handler for readers */
550
560
  struct stat file_stat;
551
 
  unsigned char *frm_ptr;
 
561
  uchar *frm_ptr;
552
562
 
553
563
  stats.auto_increment_value= create_info->auto_increment_value;
554
564
 
555
 
  for (uint32_t key= 0; key < table_arg->sizeKeys(); key++)
 
565
  for (uint key= 0; key < table_arg->sizeKeys(); key++)
556
566
  {
557
567
    KEY *pos= table_arg->key_info+key;
558
568
    KEY_PART_INFO *key_part=     pos->key_part;
594
604
  if (!stat(name_buff, &file_stat))
595
605
  {
596
606
    my_errno= 0;
597
 
    if (!(azopen(&create_stream, name_buff, O_CREAT|O_RDWR,
 
607
    if (!(azopen(&create_stream, name_buff, O_CREAT|O_RDWR|O_BINARY,
598
608
                 AZ_METHOD_BLOCK)))
599
609
    {
600
610
      error= errno;
613
623
    {
614
624
      if (fstat(frm_file, &file_stat))
615
625
      {
616
 
        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));
617
627
        if (frm_ptr)
618
628
        {
619
629
          my_read(frm_file, frm_ptr, file_stat.st_size, MYF(0));
620
630
          azwrite_frm(&create_stream, (char *)frm_ptr, file_stat.st_size);
621
 
          free((unsigned char*)frm_ptr);
 
631
          my_free((uchar*)frm_ptr, MYF(0));
622
632
        }
623
633
      }
624
634
      my_close(frm_file, MYF(0));
655
665
/*
656
666
  This is where the actual row is written out.
657
667
*/
658
 
int ha_archive::real_write_row(unsigned char *buf, azio_stream *writer)
 
668
int ha_archive::real_write_row(uchar *buf, azio_stream *writer)
659
669
{
660
670
  my_off_t written;
661
671
  unsigned int r_pack_length;
681
691
  the bytes required for the length in the header.
682
692
*/
683
693
 
684
 
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)))
685
695
{
686
696
  uint32_t length= (uint32_t)(table->getRecordLength() + table->sizeFields()*2);
687
697
  length+= ARCHIVE_ROW_HEADER_SIZE;
688
698
 
689
 
  uint32_t *ptr, *end;
 
699
  uint *ptr, *end;
690
700
  for (ptr= table->getBlobField(), end=ptr + table->sizeBlobFields();
691
701
       ptr != end ;
692
702
       ptr++)
698
708
}
699
709
 
700
710
 
701
 
unsigned int ha_archive::pack_row(unsigned char *record)
 
711
unsigned int ha_archive::pack_row(uchar *record)
702
712
{
703
 
  unsigned char *ptr;
 
713
  uchar *ptr;
704
714
 
705
715
  if (fix_rec_buff(max_row_length(record)))
706
716
    return(HA_ERR_OUT_OF_MEM); /* purecov: inspected */
728
738
  for implementing start_bulk_insert() is that we could skip 
729
739
  setting dirty to true each time.
730
740
*/
731
 
int ha_archive::write_row(unsigned char *buf)
 
741
int ha_archive::write_row(uchar *buf)
732
742
{
733
743
  int rc;
734
 
  unsigned char *read_buf= NULL;
 
744
  uchar *read_buf= NULL;
735
745
  uint64_t temp_auto;
736
 
  unsigned char *record=  table->record[0];
 
746
  uchar *record=  table->record[0];
737
747
 
738
748
  if (share->crashed)
739
749
    return(HA_ERR_CRASHED_ON_USAGE);
776
786
        First we create a buffer that we can use for reading rows, and can pass
777
787
        to get_row().
778
788
      */
779
 
      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))))
780
790
      {
781
791
        rc= HA_ERR_OUT_OF_MEM;
782
792
        goto error;
826
836
error:
827
837
  pthread_mutex_unlock(&share->mutex);
828
838
  if (read_buf)
829
 
    free((unsigned char*) read_buf);
 
839
    my_free((uchar*) read_buf, MYF(0));
830
840
 
831
841
  return(rc);
832
842
}
843
853
}
844
854
 
845
855
/* Initialized at each key walk (called multiple times unlike rnd_init()) */
846
 
int ha_archive::index_init(uint32_t keynr, bool sorted __attribute__((unused)))
 
856
int ha_archive::index_init(uint keynr, bool sorted __attribute__((unused)))
847
857
{
848
858
  active_index= keynr;
849
859
  return(0);
854
864
  No indexes, so if we get a request for an index search since we tell
855
865
  the optimizer that we have unique indexes, we scan
856
866
*/
857
 
int ha_archive::index_read(unsigned char *buf, const unsigned char *key,
858
 
                             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)
859
869
{
860
870
  int rc;
861
871
  rc= index_read_idx(buf, active_index, key, key_len, find_flag);
863
873
}
864
874
 
865
875
 
866
 
int ha_archive::index_read_idx(unsigned char *buf, uint32_t index, const unsigned char *key,
867
 
                               uint32_t key_len,
 
876
int ha_archive::index_read_idx(uchar *buf, uint index, const uchar *key,
 
877
                               uint key_len,
868
878
                               enum ha_rkey_function find_flag __attribute__((unused)))
869
879
{
870
880
  int rc;
896
906
}
897
907
 
898
908
 
899
 
int ha_archive::index_next(unsigned char * buf) 
 
909
int ha_archive::index_next(uchar * buf) 
900
910
901
911
  bool found= 0;
902
912
 
940
950
  This is the method that is used to read a row. It assumes that the row is 
941
951
  positioned where you want it.
942
952
*/
943
 
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)
944
954
{
945
955
  int rc;
946
956
 
959
969
 
960
970
  if (length > record_buffer->length)
961
971
  {
962
 
    unsigned char *newptr;
963
 
    if (!(newptr=(unsigned char*) my_realloc((unsigned char*) record_buffer->buffer, 
 
972
    uchar *newptr;
 
973
    if (!(newptr=(uchar*) my_realloc((uchar*) record_buffer->buffer, 
964
974
                                    length,
965
975
                                    MYF(MY_ALLOW_ZERO_PTR))))
966
976
      return(1);
973
983
  return(0);
974
984
}
975
985
 
976
 
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)
977
987
{
978
988
  unsigned int read;
979
989
  int error;
980
 
  const unsigned char *ptr;
 
990
  const uchar *ptr;
981
991
 
982
992
  read= azread_row(file_to_read, &error);
983
 
  ptr= (const unsigned char *)file_to_read->row_ptr;
 
993
  ptr= (const uchar *)file_to_read->row_ptr;
984
994
 
985
995
  if (error || read == 0)
986
996
  {
1001
1011
}
1002
1012
 
1003
1013
 
1004
 
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)
1005
1015
{
1006
1016
  int returnable= unpack_row(file_to_read, buf);
1007
1017
 
1014
1024
  or by having had ha_archive::rnd_pos() called before it is called.
1015
1025
*/
1016
1026
 
1017
 
int ha_archive::rnd_next(unsigned char *buf)
 
1027
int ha_archive::rnd_next(uchar *buf)
1018
1028
{
1019
1029
  int rc;
1020
1030
 
1041
1051
  needed.
1042
1052
*/
1043
1053
 
1044
 
void ha_archive::position(const unsigned char *record __attribute__((unused)))
 
1054
void ha_archive::position(const uchar *record __attribute__((unused)))
1045
1055
{
1046
1056
  my_store_ptr(ref, ref_length, current_position);
1047
1057
  return;
1055
1065
  correctly ordered row.
1056
1066
*/
1057
1067
 
1058
 
int ha_archive::rnd_pos(unsigned char * buf, unsigned char *pos)
 
1068
int ha_archive::rnd_pos(uchar * buf, uchar *pos)
1059
1069
{
1060
1070
  ha_statistic_increment(&SSV::ha_read_rnd_next_count);
1061
1071
  current_position= (my_off_t)my_get_ptr(pos, ref_length);
1069
1079
  rewriting the meta file. Currently it does this by calling optimize with
1070
1080
  the extended flag.
1071
1081
*/
1072
 
int ha_archive::repair(Session* session, HA_CHECK_OPT* check_opt)
 
1082
int ha_archive::repair(THD* thd, HA_CHECK_OPT* check_opt)
1073
1083
{
1074
1084
  check_opt->flags= T_EXTEND;
1075
 
  int rc= optimize(session, check_opt);
 
1085
  int rc= optimize(thd, check_opt);
1076
1086
 
1077
1087
  if (rc)
1078
1088
    return(HA_ERR_CRASHED_ON_REPAIR);
1085
1095
  The table can become fragmented if data was inserted, read, and then
1086
1096
  inserted again. What we do is open up the file and recompress it completely. 
1087
1097
*/
1088
 
int ha_archive::optimize(Session* session __attribute__((unused)),
 
1098
int ha_archive::optimize(THD* thd __attribute__((unused)),
1089
1099
                         HA_CHECK_OPT* check_opt __attribute__((unused)))
1090
1100
{
1091
1101
  int rc= 0;
1105
1115
  fn_format(writer_filename, share->table_name, "", ARN, 
1106
1116
            MY_REPLACE_EXT | MY_UNPACK_FILENAME);
1107
1117
 
1108
 
  if (!(azopen(&writer, writer_filename, O_CREAT|O_RDWR, AZ_METHOD_BLOCK)))
 
1118
  if (!(azopen(&writer, writer_filename, O_CREAT|O_RDWR|O_BINARY, AZ_METHOD_BLOCK)))
1109
1119
    return(HA_ERR_CRASHED_ON_USAGE); 
1110
1120
 
1111
1121
  /* 
1189
1199
/* 
1190
1200
  Below is an example of how to setup row level locking.
1191
1201
*/
1192
 
THR_LOCK_DATA **ha_archive::store_lock(Session *session,
 
1202
THR_LOCK_DATA **ha_archive::store_lock(THD *thd,
1193
1203
                                       THR_LOCK_DATA **to,
1194
1204
                                       enum thr_lock_type lock_type)
1195
1205
{
1208
1218
    */
1209
1219
 
1210
1220
    if ((lock_type >= TL_WRITE_CONCURRENT_INSERT &&
1211
 
         lock_type <= TL_WRITE) && !session_in_lock_tables(session)
1212
 
        && !session_tablespace_op(session))
 
1221
         lock_type <= TL_WRITE) && !thd_in_lock_tables(thd)
 
1222
        && !thd_tablespace_op(thd))
1213
1223
      lock_type = TL_WRITE_ALLOW_WRITE;
1214
1224
 
1215
1225
    /* 
1220
1230
      concurrent inserts to t2. 
1221
1231
    */
1222
1232
 
1223
 
    if (lock_type == TL_READ_NO_INSERT && !session_in_lock_tables(session)) 
 
1233
    if (lock_type == TL_READ_NO_INSERT && !thd_in_lock_tables(thd)) 
1224
1234
      lock_type = TL_READ;
1225
1235
 
1226
1236
    lock.type=lock_type;
1249
1259
/*
1250
1260
  Hints for optimizer, see ha_tina for more information
1251
1261
*/
1252
 
int ha_archive::info(uint32_t flag)
 
1262
int ha_archive::info(uint flag)
1253
1263
{
1254
1264
  /* 
1255
1265
    If dirty, we lock, and then reset/flush the data.
1284
1294
  {
1285
1295
    struct stat file_stat;  // Stat information for the data file
1286
1296
 
1287
 
    stat(share->data_file_name, &file_stat);
 
1297
    VOID(stat(share->data_file_name, &file_stat));
1288
1298
 
1289
1299
    stats.mean_rec_length= table->getRecordLength()+ buffer.alloced_length();
1290
1300
    stats.data_file_length= file_stat.st_size;
1355
1365
  Simple scan of the tables to make sure everything is ok.
1356
1366
*/
1357
1367
 
1358
 
int ha_archive::check(Session* session,
 
1368
int ha_archive::check(THD* thd,
1359
1369
                      HA_CHECK_OPT* check_opt __attribute__((unused)))
1360
1370
{
1361
1371
  int rc= 0;
1362
1372
  const char *old_proc_info;
1363
1373
  uint64_t x;
1364
1374
 
1365
 
  old_proc_info= get_session_proc_info(session);
1366
 
  set_session_proc_info(session, "Checking table");
 
1375
  old_proc_info= thd_proc_info(thd, "Checking table");
1367
1376
  /* Flush any waiting data */
1368
1377
  pthread_mutex_lock(&share->mutex);
1369
1378
  azflush(&(share->archive_write), Z_SYNC_FLUSH);
1384
1393
      break;
1385
1394
  }
1386
1395
 
1387
 
  set_session_proc_info(session, old_proc_info);
 
1396
  thd_proc_info(thd, old_proc_info);
1388
1397
 
1389
1398
  if ((rc && rc != HA_ERR_END_OF_FILE))  
1390
1399
  {
1400
1409
/*
1401
1410
  Check and repair the table if needed.
1402
1411
*/
1403
 
bool ha_archive::check_and_repair(Session *session) 
 
1412
bool ha_archive::check_and_repair(THD *thd) 
1404
1413
{
1405
1414
  HA_CHECK_OPT check_opt;
1406
1415
 
1407
1416
  check_opt.init();
1408
1417
 
1409
 
  return(repair(session, &check_opt));
 
1418
  return(repair(thd, &check_opt));
1410
1419
}
1411
1420
 
1412
1421
archive_record_buffer *ha_archive::create_record_buffer(unsigned int length) 
1420
1429
  }
1421
1430
  r->length= (int)length;
1422
1431
 
1423
 
  if (!(r->buffer= (unsigned char*) my_malloc(r->length,
 
1432
  if (!(r->buffer= (uchar*) my_malloc(r->length,
1424
1433
                                    MYF(MY_WME))))
1425
1434
  {
1426
 
    free((char*) r);
 
1435
    my_free((char*) r, MYF(MY_ALLOW_ZERO_PTR));
1427
1436
    return(NULL); /* purecov: inspected */
1428
1437
  }
1429
1438
 
1432
1441
 
1433
1442
void ha_archive::destroy_record_buffer(archive_record_buffer *r) 
1434
1443
{
1435
 
  free((char*) r->buffer);
1436
 
  free((char*) r);
 
1444
  my_free((char*) r->buffer, MYF(MY_ALLOW_ZERO_PTR));
 
1445
  my_free((char*) r, MYF(MY_ALLOW_ZERO_PTR));
1437
1446
  return;
1438
1447
}
1439
1448