~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to mysys/mf_iocache.c

  • Committer: Brian Aker
  • Date: 2008-07-18 20:10:26 UTC
  • mfrom: (51.3.29 remove-dbug)
  • Revision ID: brian@tangent.org-20080718201026-tto5golt0xhwqe4a
Merging in Jay's final patch on dbug.

Show diffs side-by-side

added added

removed removed

Lines of Context:
152
152
  size_t min_cache;
153
153
  my_off_t pos;
154
154
  my_off_t end_of_file= ~(my_off_t) 0;
155
 
  DBUG_ENTER("init_io_cache");
156
 
  DBUG_PRINT("enter",("cache: 0x%lx  type: %d  pos: %ld",
157
 
                      (ulong) info, (int) type, (ulong) seek_offset));
158
155
 
159
156
  info->file= file;
160
157
  info->type= TYPE_NOT_SET;         /* Don't set it until mutex are created */
180
177
        the beginning of whatever this file is, then somebody made a bad
181
178
        assumption.
182
179
      */
183
 
      DBUG_ASSERT(seek_offset == 0);
 
180
      assert(seek_offset == 0);
184
181
    }
185
182
    else
186
183
      info->seek_not_done= test(seek_offset != pos);
190
187
  info->share=0;
191
188
 
192
189
  if (!cachesize && !(cachesize= my_default_record_cache_size))
193
 
    DBUG_RETURN(1);                             /* No cache requested */
 
190
    return(1);                          /* No cache requested */
194
191
  min_cache=use_async_io ? IO_SIZE*4 : IO_SIZE*2;
195
192
  if (type == READ_CACHE || type == SEQ_READ_APPEND)
196
193
  {                                             /* Assume file isn't growing */
235
232
        break;                                  /* Enough memory found */
236
233
      }
237
234
      if (cachesize == min_cache)
238
 
        DBUG_RETURN(2);                         /* Can't alloc cache */
 
235
        return(2);                              /* Can't alloc cache */
239
236
      /* Try with less memory */
240
237
      cachesize= (cachesize*3/4 & ~(min_cache-1));
241
238
    }
242
239
  }
243
240
 
244
 
  DBUG_PRINT("info",("init_io_cache: cachesize = %lu", (ulong) cachesize));
245
241
  info->read_length=info->buffer_length=cachesize;
246
242
  info->myflags=cache_myflags & ~(MY_NABP | MY_FNABP);
247
243
  info->request_pos= info->read_pos= info->write_pos = info->buffer;
273
269
#ifdef HAVE_AIOWAIT
274
270
  if (use_async_io && ! my_disable_async_io)
275
271
  {
276
 
    DBUG_PRINT("info",("Using async io"));
277
272
    info->read_length/=2;
278
273
    info->read_function=_my_b_async_read;
279
274
  }
280
275
  info->inited=info->aio_result.pending=0;
281
276
#endif
282
 
  DBUG_RETURN(0);
 
277
  return(0);
283
278
}                                               /* init_io_cache */
284
279
 
285
280
        /* Wait until current request is ready */
296
291
      {
297
292
        if (errno == EINTR)
298
293
          continue;
299
 
        DBUG_PRINT("error",("No aio request, error: %d",errno));
300
294
        result->pending=0;                      /* Assume everythings is ok */
301
295
        break;
302
296
      }
322
316
                        bool use_async_io __attribute__((unused)),
323
317
                        bool clear_cache)
324
318
{
325
 
  DBUG_ENTER("reinit_io_cache");
326
 
  DBUG_PRINT("enter",("cache: 0x%lx type: %d  seek_offset: %lu  clear_cache: %d",
327
 
                      (ulong) info, type, (ulong) seek_offset,
328
 
                      (int) clear_cache));
329
 
 
330
319
  /* One can't do reinit with the following types */
331
 
  DBUG_ASSERT(type != READ_NET && info->type != READ_NET &&
 
320
  assert(type != READ_NET && info->type != READ_NET &&
332
321
              type != WRITE_NET && info->type != WRITE_NET &&
333
322
              type != SEQ_READ_APPEND && info->type != SEQ_READ_APPEND);
334
323
 
377
366
      info->end_of_file=my_b_tell(info);
378
367
    /* flush cache if we want to reuse it */
379
368
    if (!clear_cache && my_b_flush_io_cache(info,1))
380
 
      DBUG_RETURN(1);
 
369
      return(1);
381
370
    info->pos_in_file=seek_offset;
382
371
    /* Better to do always do a seek */
383
372
    info->seek_not_done=1;
407
396
  }
408
397
  info->inited=0;
409
398
#endif
410
 
  DBUG_RETURN(0);
 
399
  return(0);
411
400
} /* reinit_io_cache */
412
401
 
413
402
 
444
433
{
445
434
  size_t length,diff_length,left_length, max_length;
446
435
  my_off_t pos_in_file;
447
 
  DBUG_ENTER("_my_b_read");
448
436
 
449
437
  if ((left_length= (size_t) (info->read_end-info->read_pos)))
450
438
  {
451
 
    DBUG_ASSERT(Count >= left_length);  /* User is not using my_b_read() */
 
439
    assert(Count >= left_length);       /* User is not using my_b_read() */
452
440
    memcpy(Buffer,info->read_pos, left_length);
453
441
    Buffer+=left_length;
454
442
    Count-=left_length;
478
466
        info->file is a pipe or socket or FIFO.  We never should have tried
479
467
        to seek on that.  See Bugs#25807 and #22828 for more info.
480
468
      */
481
 
      DBUG_ASSERT(my_errno != ESPIPE);
 
469
      assert(my_errno != ESPIPE);
482
470
      info->error= -1;
483
 
      DBUG_RETURN(1);
 
471
      return(1);
484
472
    }
485
473
  }
486
474
 
491
479
    if (info->end_of_file <= pos_in_file)
492
480
    {                                   /* End of file */
493
481
      info->error= (int) left_length;
494
 
      DBUG_RETURN(1);
 
482
      return(1);
495
483
    }
496
484
    length=(Count & (size_t) ~(IO_SIZE-1))-diff_length;
497
485
    if ((read_length= my_read(info->file,Buffer, length, info->myflags))
499
487
    {
500
488
      info->error= (read_length == (size_t) -1 ? -1 :
501
489
                    (int) (read_length+left_length));
502
 
      DBUG_RETURN(1);
 
490
      return(1);
503
491
    }
504
492
    Count-=length;
505
493
    Buffer+=length;
517
505
    if (Count)
518
506
    {
519
507
      info->error= left_length;         /* We only got this many char */
520
 
      DBUG_RETURN(1);
 
508
      return(1);
521
509
    }
522
510
    length=0;                           /* Didn't read any chars */
523
511
  }
530
518
    info->pos_in_file= pos_in_file;
531
519
    info->error= length == (size_t) -1 ? -1 : (int) (length+left_length);
532
520
    info->read_pos=info->read_end=info->buffer;
533
 
    DBUG_RETURN(1);
 
521
    return(1);
534
522
  }
535
523
  info->read_pos=info->buffer+Count;
536
524
  info->read_end=info->buffer+length;
537
525
  info->pos_in_file=pos_in_file;
538
526
  memcpy(Buffer, info->buffer, Count);
539
 
  DBUG_RETURN(0);
 
527
  return(0);
540
528
}
541
529
 
542
530
 
611
599
void init_io_cache_share(IO_CACHE *read_cache, IO_CACHE_SHARE *cshare,
612
600
                         IO_CACHE *write_cache, uint num_threads)
613
601
{
614
 
  DBUG_ENTER("init_io_cache_share");
615
 
  DBUG_PRINT("io_cache_share", ("read_cache: 0x%lx  share: 0x%lx  "
616
 
                                "write_cache: 0x%lx  threads: %u",
617
 
                                (long) read_cache, (long) cshare,
618
 
                                (long) write_cache, num_threads));
619
 
 
620
 
  DBUG_ASSERT(num_threads > 1);
621
 
  DBUG_ASSERT(read_cache->type == READ_CACHE);
622
 
  DBUG_ASSERT(!write_cache || (write_cache->type == WRITE_CACHE));
 
602
  assert(num_threads > 1);
 
603
  assert(read_cache->type == READ_CACHE);
 
604
  assert(!write_cache || (write_cache->type == WRITE_CACHE));
623
605
 
624
606
  pthread_mutex_init(&cshare->mutex, MY_MUTEX_INIT_FAST);
625
607
  pthread_cond_init(&cshare->cond, 0);
641
623
  if (write_cache)
642
624
    write_cache->share= cshare;
643
625
 
644
 
  DBUG_VOID_RETURN;
 
626
  return;
645
627
}
646
628
 
647
629
 
668
650
{
669
651
  IO_CACHE_SHARE *cshare= cache->share;
670
652
  uint total;
671
 
  DBUG_ENTER("remove_io_thread");
672
653
 
673
654
  /* If the writer goes, it needs to flush the write cache. */
674
655
  if (cache == cshare->source_cache)
675
656
    flush_io_cache(cache);
676
657
 
677
658
  pthread_mutex_lock(&cshare->mutex);
678
 
  DBUG_PRINT("io_cache_share", ("%s: 0x%lx",
679
 
                                (cache == cshare->source_cache) ?
680
 
                                "writer" : "reader", (long) cache));
681
659
 
682
660
  /* Remove from share. */
683
661
  total= --cshare->total_threads;
684
 
  DBUG_PRINT("io_cache_share", ("remaining threads: %u", total));
685
662
 
686
663
  /* Detach from share. */
687
664
  cache->share= NULL;
689
666
  /* If the writer goes, let the readers know. */
690
667
  if (cache == cshare->source_cache)
691
668
  {
692
 
    DBUG_PRINT("io_cache_share", ("writer leaves"));
693
669
    cshare->source_cache= NULL;
694
670
  }
695
671
 
696
672
  /* If all threads are waiting for me to join the lock, wake them. */
697
673
  if (!--cshare->running_threads)
698
674
  {
699
 
    DBUG_PRINT("io_cache_share", ("the last running thread leaves, wake all"));
700
675
    pthread_cond_signal(&cshare->cond_writer);
701
676
    pthread_cond_broadcast(&cshare->cond);
702
677
  }
705
680
 
706
681
  if (!total)
707
682
  {
708
 
    DBUG_PRINT("io_cache_share", ("last thread removed, destroy share"));
709
683
    pthread_cond_destroy (&cshare->cond_writer);
710
684
    pthread_cond_destroy (&cshare->cond);
711
685
    pthread_mutex_destroy(&cshare->mutex);
712
686
  }
713
687
 
714
 
  DBUG_VOID_RETURN;
 
688
  return;
715
689
}
716
690
 
717
691
 
746
720
static int lock_io_cache(IO_CACHE *cache, my_off_t pos)
747
721
{
748
722
  IO_CACHE_SHARE *cshare= cache->share;
749
 
  DBUG_ENTER("lock_io_cache");
750
723
 
751
724
  /* Enter the lock. */
752
725
  pthread_mutex_lock(&cshare->mutex);
753
726
  cshare->running_threads--;
754
 
  DBUG_PRINT("io_cache_share", ("%s: 0x%lx  pos: %lu  running: %u",
755
 
                                (cache == cshare->source_cache) ?
756
 
                                "writer" : "reader", (long) cache, (ulong) pos,
757
 
                                cshare->running_threads));
758
727
 
759
728
  if (cshare->source_cache)
760
729
  {
765
734
      /* The writer waits until all readers are here. */
766
735
      while (cshare->running_threads)
767
736
      {
768
 
        DBUG_PRINT("io_cache_share", ("writer waits in lock"));
769
737
        pthread_cond_wait(&cshare->cond_writer, &cshare->mutex);
770
738
      }
771
 
      DBUG_PRINT("io_cache_share", ("writer awoke, going to copy"));
772
 
 
773
739
      /* Stay locked. Leave the lock later by unlock_io_cache(). */
774
 
      DBUG_RETURN(1);
 
740
      return(1);
775
741
    }
776
742
 
777
743
    /* The last thread wakes the writer. */
778
744
    if (!cshare->running_threads)
779
745
    {
780
 
      DBUG_PRINT("io_cache_share", ("waking writer"));
781
746
      pthread_cond_signal(&cshare->cond_writer);
782
747
    }
783
748
 
789
754
    while ((!cshare->read_end || (cshare->pos_in_file < pos)) &&
790
755
           cshare->source_cache)
791
756
    {
792
 
      DBUG_PRINT("io_cache_share", ("reader waits in lock"));
793
757
      pthread_cond_wait(&cshare->cond, &cshare->mutex);
794
758
    }
795
759
 
803
767
    */
804
768
    if (!cshare->read_end || (cshare->pos_in_file < pos))
805
769
    {
806
 
      DBUG_PRINT("io_cache_share", ("reader found writer removed. EOF"));
807
770
      cshare->read_end= cshare->buffer; /* Empty buffer. */
808
771
      cshare->error= 0; /* EOF is not an error. */
809
772
    }
816
779
    */
817
780
    if (!cshare->running_threads)
818
781
    {
819
 
      DBUG_PRINT("io_cache_share", ("last thread joined, going to read"));
820
782
      /* Stay locked. Leave the lock later by unlock_io_cache(). */
821
 
      DBUG_RETURN(1);
 
783
      return(1);
822
784
    }
823
785
 
824
786
    /*
831
793
    while ((!cshare->read_end || (cshare->pos_in_file < pos)) &&
832
794
           cshare->running_threads)
833
795
    {
834
 
      DBUG_PRINT("io_cache_share", ("reader waits in lock"));
835
796
      pthread_cond_wait(&cshare->cond, &cshare->mutex);
836
797
    }
837
798
 
838
799
    /* If the block is not yet read, continue with a locked cache and read. */
839
800
    if (!cshare->read_end || (cshare->pos_in_file < pos))
840
801
    {
841
 
      DBUG_PRINT("io_cache_share", ("reader awoke, going to read"));
842
802
      /* Stay locked. Leave the lock later by unlock_io_cache(). */
843
 
      DBUG_RETURN(1);
 
803
      return(1);
844
804
    }
845
805
 
846
806
    /* Another thread did read the block already. */
847
807
  }
848
 
  DBUG_PRINT("io_cache_share", ("reader awoke, going to process %u bytes",
849
 
                                (uint) (cshare->read_end ? (size_t)
850
 
                                        (cshare->read_end - cshare->buffer) :
851
 
                                        0)));
852
808
 
853
809
  /*
854
810
    Leave the lock. Do not call unlock_io_cache() later. The thread that
855
811
    filled the buffer did this and marked all threads as running.
856
812
  */
857
813
  pthread_mutex_unlock(&cshare->mutex);
858
 
  DBUG_RETURN(0);
 
814
  return(0);
859
815
}
860
816
 
861
817
 
889
845
static void unlock_io_cache(IO_CACHE *cache)
890
846
{
891
847
  IO_CACHE_SHARE *cshare= cache->share;
892
 
  DBUG_ENTER("unlock_io_cache");
893
 
  DBUG_PRINT("io_cache_share", ("%s: 0x%lx  pos: %lu  running: %u",
894
 
                                (cache == cshare->source_cache) ?
895
 
                                "writer" : "reader",
896
 
                                (long) cache, (ulong) cshare->pos_in_file,
897
 
                                cshare->total_threads));
898
848
 
899
849
  cshare->running_threads= cshare->total_threads;
900
850
  pthread_cond_broadcast(&cshare->cond);
901
851
  pthread_mutex_unlock(&cshare->mutex);
902
 
  DBUG_VOID_RETURN;
 
852
  return;
903
853
}
904
854
 
905
855
 
945
895
  my_off_t pos_in_file;
946
896
  size_t length, diff_length, left_length;
947
897
  IO_CACHE_SHARE *cshare= cache->share;
948
 
  DBUG_ENTER("_my_b_read_r");
949
898
 
950
899
  if ((left_length= (size_t) (cache->read_end - cache->read_pos)))
951
900
  {
952
 
    DBUG_ASSERT(Count >= left_length);  /* User is not using my_b_read() */
 
901
    assert(Count >= left_length);       /* User is not using my_b_read() */
953
902
    memcpy(Buffer, cache->read_pos, left_length);
954
903
    Buffer+= left_length;
955
904
    Count-= left_length;
970
919
    if (length == 0)
971
920
    {
972
921
      cache->error= (int) left_length;
973
 
      DBUG_RETURN(1);
 
922
      return(1);
974
923
    }
975
924
    if (lock_io_cache(cache, pos_in_file))
976
925
    {
977
926
      /* With a synchronized write/read cache we won't come here... */
978
 
      DBUG_ASSERT(!cshare->source_cache);
 
927
      assert(!cshare->source_cache);
979
928
      /*
980
929
        ... unless the writer has gone before this thread entered the
981
930
        lock. Simulate EOF in this case. It can be distinguished by
998
947
          {
999
948
            cache->error= -1;
1000
949
            unlock_io_cache(cache);
1001
 
            DBUG_RETURN(1);
 
950
            return(1);
1002
951
          }
1003
952
        }
1004
953
        len= my_read(cache->file, cache->buffer, length, cache->myflags);
1005
954
      }
1006
 
      DBUG_PRINT("io_cache_share", ("read %lu bytes", (ulong) len));
1007
 
 
1008
955
      cache->read_end=    cache->buffer + (len == (size_t) -1 ? 0 : len);
1009
956
      cache->error=       (len == length ? 0 : (int) len);
1010
957
      cache->pos_in_file= pos_in_file;
1034
981
    cache->seek_not_done= 0;
1035
982
    if (len == 0 || len == (size_t) -1)
1036
983
    {
1037
 
      DBUG_PRINT("io_cache_share", ("reader error. len %lu  left %lu",
1038
 
                                    (ulong) len, (ulong) left_length));
1039
984
      cache->error= (int) left_length;
1040
 
      DBUG_RETURN(1);
 
985
      return(1);
1041
986
    }
1042
987
    cnt= (len > Count) ? Count : len;
1043
988
    memcpy(Buffer, cache->read_pos, cnt);
1046
991
    left_length+= cnt;
1047
992
    cache->read_pos+= cnt;
1048
993
  }
1049
 
  DBUG_RETURN(0);
 
994
  return(0);
1050
995
}
1051
996
 
1052
997
 
1072
1017
{
1073
1018
  IO_CACHE_SHARE *cshare= write_cache->share;
1074
1019
 
1075
 
  DBUG_ASSERT(cshare->source_cache == write_cache);
 
1020
  assert(cshare->source_cache == write_cache);
1076
1021
  /*
1077
1022
    write_length is usually less or equal to buffer_length.
1078
1023
    It can be bigger if _my_b_write() is called with a big length.
1084
1029
 
1085
1030
    rc= lock_io_cache(write_cache, write_cache->pos_in_file);
1086
1031
    /* The writing thread does always have the lock when it awakes. */
1087
 
    DBUG_ASSERT(rc);
 
1032
    assert(rc);
1088
1033
 
1089
1034
    memcpy(cshare->buffer, write_buffer, copy_length);
1090
1035
 
1123
1068
  /* first, read the regular buffer */
1124
1069
  if ((left_length=(size_t) (info->read_end-info->read_pos)))
1125
1070
  {
1126
 
    DBUG_ASSERT(Count > left_length);   /* User is not using my_b_read() */
 
1071
    assert(Count > left_length);        /* User is not using my_b_read() */
1127
1072
    memcpy(Buffer,info->read_pos, left_length);
1128
1073
    Buffer+=left_length;
1129
1074
    Count-=left_length;
1205
1150
 
1206
1151
      /*
1207
1152
         added the line below to make
1208
 
         DBUG_ASSERT(pos_in_file==info->end_of_file) pass.
 
1153
         assert(pos_in_file==info->end_of_file) pass.
1209
1154
         otherwise this does not appear to be needed
1210
1155
      */
1211
1156
      pos_in_file += length;
1232
1177
    size_t copy_len;
1233
1178
    size_t transfer_len;
1234
1179
 
1235
 
    DBUG_ASSERT(info->append_read_pos <= info->write_pos);
 
1180
    assert(info->append_read_pos <= info->write_pos);
1236
1181
    /*
1237
1182
      TODO: figure out if the assert below is needed or correct.
1238
1183
    */
1239
 
    DBUG_ASSERT(pos_in_file == info->end_of_file);
 
1184
    assert(pos_in_file == info->end_of_file);
1240
1185
    copy_len=min(Count, len_in_buff);
1241
1186
    memcpy(Buffer, info->append_read_pos, copy_len);
1242
1187
    info->append_read_pos += copy_len;
1338
1283
        read_length-=offset;                    /* Bytes left from read_pos */
1339
1284
      }
1340
1285
    }
1341
 
#ifndef DBUG_OFF
1342
 
    if (info->aio_read_pos > info->pos_in_file)
1343
 
    {
1344
 
      my_errno=EINVAL;
1345
 
      return(info->read_length= (size_t) -1);
1346
 
    }
1347
 
#endif
1348
1286
        /* Copy found bytes to buffer */
1349
1287
    length=min(Count,read_length);
1350
1288
    memcpy(Buffer,info->read_pos,(size_t) length);
1423
1361
  if (max_length)
1424
1362
  {
1425
1363
    info->aio_result.result.aio_errno=AIO_INPROGRESS;   /* Marker for test */
1426
 
    DBUG_PRINT("aioread",("filepos: %ld  length: %lu",
1427
 
                          (ulong) next_pos_in_file, (ulong) max_length));
1428
1364
    if (aioread(info->file,read_buffer, max_length,
1429
1365
                (my_off_t) next_pos_in_file,MY_SEEK_SET,
1430
1366
                &info->aio_result.result))
1431
1367
    {                                           /* Skip async io */
1432
1368
      my_errno=errno;
1433
 
      DBUG_PRINT("error",("got error: %d, aio_result: %d from aioread, async skipped",
1434
 
                          errno, info->aio_result.result.aio_errno));
1435
1369
      if (info->request_pos != info->buffer)
1436
1370
      {
1437
1371
        bmove(info->buffer,info->request_pos,
1553
1487
    Assert that we cannot come here with a shared cache. If we do one
1554
1488
    day, we might need to add a call to copy_to_read_buffer().
1555
1489
  */
1556
 
  DBUG_ASSERT(!info->share);
 
1490
  assert(!info->share);
1557
1491
 
1558
1492
  lock_append_buffer(info);
1559
1493
  rest_length= (size_t) (info->write_end - info->write_pos);
1619
1553
    Assert that we cannot come here with a shared cache. If we do one
1620
1554
    day, we might need to add a call to copy_to_read_buffer().
1621
1555
  */
1622
 
  DBUG_ASSERT(!info->share);
 
1556
  assert(!info->share);
1623
1557
 
1624
1558
  if (pos < info->pos_in_file)
1625
1559
  {
1674
1608
  size_t length;
1675
1609
  bool append_cache;
1676
1610
  my_off_t pos_in_file;
1677
 
  DBUG_ENTER("my_b_flush_io_cache");
1678
 
  DBUG_PRINT("enter", ("cache: 0x%lx", (long) info));
1679
1611
 
1680
1612
  if (!(append_cache = (info->type == SEQ_READ_APPEND)))
1681
1613
    need_append_buffer_lock=0;
1685
1617
    if (info->file == -1)
1686
1618
    {
1687
1619
      if (real_open_cached_file(info))
1688
 
        DBUG_RETURN((info->error= -1));
 
1620
        return((info->error= -1));
1689
1621
    }
1690
1622
    LOCK_APPEND_BUFFER;
1691
1623
 
1711
1643
            MY_FILEPOS_ERROR)
1712
1644
        {
1713
1645
          UNLOCK_APPEND_BUFFER;
1714
 
          DBUG_RETURN((info->error= -1));
 
1646
          return((info->error= -1));
1715
1647
        }
1716
1648
        if (!append_cache)
1717
1649
          info->seek_not_done=0;
1733
1665
      else
1734
1666
      {
1735
1667
        info->end_of_file+=(info->write_pos-info->append_read_pos);
1736
 
        DBUG_ASSERT(info->end_of_file == my_tell(info->file,MYF(0)));
 
1668
        assert(info->end_of_file == my_tell(info->file,MYF(0)));
1737
1669
      }
1738
1670
 
1739
1671
      info->append_read_pos=info->write_pos=info->write_buffer;
1740
1672
      ++info->disk_writes;
1741
1673
      UNLOCK_APPEND_BUFFER;
1742
 
      DBUG_RETURN(info->error);
 
1674
      return(info->error);
1743
1675
    }
1744
1676
  }
1745
1677
#ifdef HAVE_AIOWAIT
1750
1682
  }
1751
1683
#endif
1752
1684
  UNLOCK_APPEND_BUFFER;
1753
 
  DBUG_RETURN(0);
 
1685
  return(0);
1754
1686
}
1755
1687
 
1756
1688
/*
1774
1706
{
1775
1707
  int error=0;
1776
1708
  IO_CACHE_CALLBACK pre_close;
1777
 
  DBUG_ENTER("end_io_cache");
1778
 
  DBUG_PRINT("enter",("cache: 0x%lx", (ulong) info));
1779
1709
 
1780
1710
  /*
1781
1711
    Every thread must call remove_io_thread(). The last one destroys
1782
1712
    the share elements.
1783
1713
  */
1784
 
  DBUG_ASSERT(!info->share || !info->share->total_threads);
 
1714
  assert(!info->share || !info->share->total_threads);
1785
1715
 
1786
1716
  if ((pre_close=info->pre_close))
1787
1717
  {
1802
1732
    info->type= TYPE_NOT_SET;
1803
1733
    pthread_mutex_destroy(&info->append_buffer_lock);
1804
1734
  }
1805
 
  DBUG_RETURN(error);
 
1735
  return(error);
1806
1736
} /* end_io_cache */
1807
1737
 
1808
1738