12
12
You should have received a copy of the GNU General Public License
13
13
along with this program; if not, write to the Free Software
14
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */
14
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
17
17
Cashing of files with only does (sequential) read or writes of fixed-
52
52
#include "drizzled/internal/my_sys.h"
53
53
#include "drizzled/internal/m_string.h"
54
#include "drizzled/drizzled.h"
55
54
#ifdef HAVE_AIOWAIT
56
55
#include "drizzled/error.h"
57
56
#include "drizzled/internal/aio_result.h"
73
static int _my_b_read(register st_io_cache *info, unsigned char *Buffer, size_t Count);
74
static int _my_b_write(register st_io_cache *info, const unsigned char *Buffer, size_t Count);
72
static int _my_b_read(register IO_CACHE *info, unsigned char *Buffer, size_t Count);
73
static int _my_b_write(register IO_CACHE *info, const unsigned char *Buffer, size_t Count);
78
* Lock appends for the st_io_cache if required (need_append_buffer_lock)
77
* Lock appends for the IO_CACHE if required (need_append_buffer_lock)
81
static void lock_append_buffer(register st_io_cache *, int )
80
static void lock_append_buffer(register IO_CACHE *, int )
87
* Unlock appends for the st_io_cache if required (need_append_buffer_lock)
86
* Unlock appends for the IO_CACHE if required (need_append_buffer_lock)
90
static void unlock_append_buffer(register st_io_cache *, int )
89
static void unlock_append_buffer(register IO_CACHE *, int )
117
* Setup internal pointers inside st_io_cache
116
* Setup internal pointers inside IO_CACHE
120
* This is called on automatically on init or reinit of st_io_cache
121
* It must be called externally if one moves or copies an st_io_cache object.
119
* This is called on automatically on init or reinit of IO_CACHE
120
* It must be called externally if one moves or copies an IO_CACHE object.
123
122
* @param info Cache handler to setup
125
void st_io_cache::setup_io_cache()
124
void setup_io_cache(IO_CACHE* info)
127
126
/* Ensure that my_b_tell() and my_b_bytes_in_cache works */
128
if (type == WRITE_CACHE)
127
if (info->type == WRITE_CACHE)
130
current_pos= &write_pos;
131
current_end= &write_end;
129
info->current_pos= &info->write_pos;
130
info->current_end= &info->write_end;
135
current_pos= &read_pos;
136
current_end= &read_end;
134
info->current_pos= &info->read_pos;
135
info->current_end= &info->read_end;
141
void st_io_cache::init_functions()
141
init_functions(IO_CACHE* info)
143
enum cache_type type= info->type;
154
read_function = _my_b_read;
155
write_function = _my_b_write;
155
info->read_function = _my_b_read;
156
info->write_function = _my_b_write;
159
setup_io_cache(info);
163
* Initialize an st_io_cache object
164
* Initialize an IO_CACHE object
166
* @param info Cache handler to initialize
165
167
* @param file File that should be associated with the handler
166
168
* If == -1 then real_open_cached_file() will be called when it's time to open file.
167
169
* @param cachesize Size of buffer to allocate for read/write
175
177
* @retval 0 success
176
178
* @retval # error
178
int st_io_cache::init_io_cache(int file_arg, size_t cachesize,
179
enum cache_type type_arg, my_off_t seek_offset,
180
bool use_async_io, myf cache_myflags)
180
int init_io_cache(IO_CACHE *info, int file, size_t cachesize,
181
enum cache_type type, my_off_t seek_offset,
182
bool use_async_io, myf cache_myflags)
182
184
size_t min_cache;
184
my_off_t end_of_file_local= ~(my_off_t) 0;
186
my_off_t end_of_file= ~(my_off_t) 0;
187
type= TYPE_NOT_SET; /* Don't set it until mutex are created */
188
pos_in_file= seek_offset;
189
pre_close = pre_read = post_read = 0;
189
info->type= TYPE_NOT_SET; /* Don't set it until mutex are created */
190
info->pos_in_file= seek_offset;
191
info->pre_close = info->pre_read = info->post_read = 0;
193
info->alloced_buffer = 0;
195
info->seek_not_done= 0;
201
203
This kind of object doesn't support seek() or tell(). Don't set a
202
204
flag that will make us again try to seek() later and fail.
206
info->seek_not_done= 0;
206
208
Additionally, if we're supposed to start somewhere other than the
207
209
the beginning of whatever this file is, then somebody made a bad
210
212
assert(seek_offset == 0);
213
seek_not_done= test(seek_offset != (my_off_t)pos);
215
info->seek_not_done= test(seek_offset != (my_off_t)pos);
216
218
if (!cachesize && !(cachesize= my_default_record_cache_size))
217
return 1; /* No cache requested */
219
return(1); /* No cache requested */
218
220
min_cache=use_async_io ? IO_SIZE*4 : IO_SIZE*2;
219
if (type_arg == READ_CACHE)
221
if (type == READ_CACHE)
220
222
{ /* Assume file isn't growing */
221
223
if (!(cache_myflags & MY_DONT_CHECK_FILESIZE))
223
225
/* Calculate end of file to avoid allocating oversized buffers */
224
end_of_file_local=lseek(file,0L,SEEK_END);
226
end_of_file=lseek(file,0L,SEEK_END);
225
227
/* Need to reset seek_not_done now that we just did a seek. */
226
seek_not_done= end_of_file_local == seek_offset ? 0 : 1;
227
if (end_of_file_local < seek_offset)
228
end_of_file_local=seek_offset;
228
info->seek_not_done= end_of_file == seek_offset ? 0 : 1;
229
if (end_of_file < seek_offset)
230
end_of_file=seek_offset;
229
231
/* Trim cache size if the file is very small */
230
if ((my_off_t) cachesize > end_of_file_local-seek_offset+IO_SIZE*2-1)
232
if ((my_off_t) cachesize > end_of_file-seek_offset+IO_SIZE*2-1)
232
cachesize= (size_t) (end_of_file_local-seek_offset)+IO_SIZE*2-1;
234
cachesize= (size_t) (end_of_file-seek_offset)+IO_SIZE*2-1;
233
235
use_async_io=0; /* No need to use async */
237
239
cache_myflags &= ~MY_DONT_CHECK_FILESIZE;
238
if (type_arg != READ_NET && type_arg != WRITE_NET)
240
if (type != READ_NET && type != WRITE_NET)
240
242
/* Retry allocating memory in smaller blocks until we get one */
241
243
cachesize= ((cachesize + min_cache-1) & ~(min_cache-1));
245
247
if (cachesize < min_cache)
246
248
cachesize = min_cache;
247
249
buffer_block= cachesize;
248
if ((type_arg == READ_CACHE) and (not global_read_buffer.add(buffer_block)))
250
my_error(ER_OUT_OF_GLOBAL_READMEMORY, MYF(ME_ERROR+ME_WAITTANG));
255
251
(unsigned char*) malloc(buffer_block)) != 0)
258
alloced_buffer= true;
253
info->write_buffer=info->buffer;
254
info->alloced_buffer= true;
259
255
break; /* Enough memory found */
261
257
if (cachesize == min_cache)
263
if (type_arg == READ_CACHE)
264
global_read_buffer.sub(buffer_block);
265
return 2; /* Can't alloc cache */
258
return(2); /* Can't alloc cache */
267
259
/* Try with less memory */
268
if (type_arg == READ_CACHE)
269
global_read_buffer.sub(buffer_block);
270
260
cachesize= (cachesize*3/4 & ~(min_cache-1));
274
read_length=buffer_length=cachesize;
275
myflags=cache_myflags & ~(MY_NABP | MY_FNABP);
276
request_pos= read_pos= write_pos = buffer;
264
info->read_length=info->buffer_length=cachesize;
265
info->myflags=cache_myflags & ~(MY_NABP | MY_FNABP);
266
info->request_pos= info->read_pos= info->write_pos = info->buffer;
278
if (type_arg == WRITE_CACHE)
280
buffer+buffer_length- (seek_offset & (IO_SIZE-1));
268
if (type == WRITE_CACHE)
270
info->buffer+info->buffer_length- (seek_offset & (IO_SIZE-1));
282
read_end=buffer; /* Nothing in cache */
272
info->read_end=info->buffer; /* Nothing in cache */
284
274
/* End_of_file may be changed by user later */
285
end_of_file= end_of_file_local;
275
info->end_of_file= end_of_file;
278
init_functions(info);
289
279
#ifdef HAVE_AIOWAIT
290
280
if (use_async_io && ! my_disable_async_io)
293
read_function=_my_b_async_read;
282
info->read_length/=2;
283
info->read_function=_my_b_async_read;
295
inited= aio_result.pending= 0;
285
info->inited=info->aio_result.pending=0;
298
288
} /* init_io_cache */
300
290
/* Wait until current request is ready */
332
323
* If we are doing a reinit of a cache where we have the start of the file
333
324
* in the cache, we are reusing this memory without flushing it to disk.
335
bool st_io_cache::reinit_io_cache(enum cache_type type_arg,
336
my_off_t seek_offset,
326
bool reinit_io_cache(IO_CACHE *info, enum cache_type type,
327
my_off_t seek_offset,
340
331
/* One can't do reinit with the following types */
341
assert(type_arg != READ_NET && type != READ_NET &&
342
type_arg != WRITE_NET && type != WRITE_NET);
332
assert(type != READ_NET && info->type != READ_NET &&
333
type != WRITE_NET && info->type != WRITE_NET);
344
335
/* If the whole file is in memory, avoid flushing to disk */
345
336
if (! clear_cache &&
346
seek_offset >= pos_in_file &&
347
seek_offset <= my_b_tell(this))
337
seek_offset >= info->pos_in_file &&
338
seek_offset <= my_b_tell(info))
349
340
/* Reuse current buffer without flushing it to disk */
350
341
unsigned char *pos;
351
if (type == WRITE_CACHE && type_arg == READ_CACHE)
342
if (info->type == WRITE_CACHE && type == READ_CACHE)
354
end_of_file=my_b_tell(this);
344
info->read_end=info->write_pos;
345
info->end_of_file=my_b_tell(info);
356
347
Trigger a new seek only if we have a valid
359
seek_not_done= (file != -1);
350
info->seek_not_done= (info->file != -1);
361
else if (type_arg == WRITE_CACHE)
352
else if (type == WRITE_CACHE)
363
if (type == READ_CACHE)
354
if (info->type == READ_CACHE)
365
write_end=write_buffer+buffer_length;
356
info->write_end=info->write_buffer+info->buffer_length;
357
info->seek_not_done=1;
368
end_of_file = ~(my_off_t) 0;
359
info->end_of_file = ~(my_off_t) 0;
370
pos=request_pos+(seek_offset-pos_in_file);
371
if (type_arg == WRITE_CACHE)
361
pos=info->request_pos+(seek_offset-info->pos_in_file);
362
if (type == WRITE_CACHE)
375
366
#ifdef HAVE_AIOWAIT
376
my_aiowait(&aio_result); /* Wait for outstanding req */
367
my_aiowait(&info->aio_result); /* Wait for outstanding req */
382
373
If we change from WRITE_CACHE to READ_CACHE, assume that everything
383
374
after the current positions should be ignored
385
if (type == WRITE_CACHE && type_arg == READ_CACHE)
386
end_of_file=my_b_tell(this);
376
if (info->type == WRITE_CACHE && type == READ_CACHE)
377
info->end_of_file=my_b_tell(info);
387
378
/* flush cache if we want to reuse it */
388
if (!clear_cache && my_b_flush_io_cache(this, 1))
390
pos_in_file=seek_offset;
379
if (!clear_cache && my_b_flush_io_cache(info,1))
381
info->pos_in_file=seek_offset;
391
382
/* Better to do always do a seek */
393
request_pos=read_pos=write_pos=buffer;
394
if (type_arg == READ_CACHE)
383
info->seek_not_done=1;
384
info->request_pos=info->read_pos=info->write_pos=info->buffer;
385
if (type == READ_CACHE)
396
read_end=buffer; /* Nothing in cache */
387
info->read_end=info->buffer; /* Nothing in cache */
400
write_end=(buffer + buffer_length -
391
info->write_end=(info->buffer + info->buffer_length -
401
392
(seek_offset & (IO_SIZE-1)));
402
end_of_file= ~(my_off_t) 0;
393
info->end_of_file= ~(my_off_t) 0;
398
init_functions(info);
409
400
#ifdef HAVE_AIOWAIT
410
401
if (use_async_io && ! my_disable_async_io &&
411
((uint32_t) buffer_length <
412
(uint32_t) (end_of_file - seek_offset)))
402
((uint32_t) info->buffer_length <
403
(uint32_t) (info->end_of_file - seek_offset)))
414
read_length=buffer_length/2;
415
read_function=_my_b_async_read;
405
info->read_length=info->buffer_length/2;
406
info->read_function=_my_b_async_read;
419
410
(void)use_async_io;
422
413
} /* reinit_io_cache */
435
426
* types than my_off_t unless you can be sure that their value fits.
436
427
* Same applies to differences of file offsets.
438
* @param info st_io_cache pointer @param Buffer Buffer to retrieve count bytes
429
* @param info IO_CACHE pointer @param Buffer Buffer to retrieve count bytes
439
430
* from file @param Count Number of bytes to read into Buffer
441
432
* @retval 0 We succeeded in reading all data
442
433
* @retval 1 Error: can't read requested characters
444
static int _my_b_read(register st_io_cache *info, unsigned char *Buffer, size_t Count)
435
static int _my_b_read(register IO_CACHE *info, unsigned char *Buffer, size_t Count)
446
size_t length_local,diff_length,left_length, max_length;
447
my_off_t pos_in_file_local;
437
size_t length,diff_length,left_length, max_length;
438
my_off_t pos_in_file;
449
440
if ((left_length= (size_t) (info->read_end-info->read_pos)))
457
448
/* pos_in_file always point on where info->buffer was read */
458
pos_in_file_local=info->pos_in_file+ (size_t) (info->read_end - info->buffer);
449
pos_in_file=info->pos_in_file+ (size_t) (info->read_end - info->buffer);
461
Whenever a function which operates on st_io_cache flushes/writes
462
some part of the st_io_cache to disk it will set the property
452
Whenever a function which operates on IO_CACHE flushes/writes
453
some part of the IO_CACHE to disk it will set the property
463
454
"seek_not_done" to indicate this to other functions operating
466
457
if (info->seek_not_done)
468
if ((lseek(info->file,pos_in_file_local,SEEK_SET) != MY_FILEPOS_ERROR))
459
if ((lseek(info->file,pos_in_file,SEEK_SET) != MY_FILEPOS_ERROR))
470
461
/* No error, reset seek_not_done flag. */
471
462
info->seek_not_done= 0;
486
diff_length= (size_t) (pos_in_file_local & (IO_SIZE-1));
477
diff_length= (size_t) (pos_in_file & (IO_SIZE-1));
487
478
if (Count >= (size_t) (IO_SIZE+(IO_SIZE-diff_length)))
488
479
{ /* Fill first intern buffer */
489
480
size_t read_length;
490
if (info->end_of_file <= pos_in_file_local)
481
if (info->end_of_file <= pos_in_file)
491
482
{ /* End of file */
492
483
info->error= (int) left_length;
495
length_local=(Count & (size_t) ~(IO_SIZE-1))-diff_length;
496
if ((read_length= my_read(info->file,Buffer, length_local, info->myflags)) != length_local)
486
length=(Count & (size_t) ~(IO_SIZE-1))-diff_length;
487
if ((read_length= my_read(info->file,Buffer, length, info->myflags))
498
490
info->error= (read_length == (size_t) -1 ? -1 :
499
491
(int) (read_length+left_length));
502
Count-= length_local;
503
Buffer+= length_local;
504
pos_in_file_local+= length_local;
505
left_length+= length_local;
509
501
max_length= info->read_length-diff_length;
510
502
if (info->type != READ_FIFO &&
511
max_length > (info->end_of_file - pos_in_file_local))
512
max_length= (size_t) (info->end_of_file - pos_in_file_local);
503
max_length > (info->end_of_file - pos_in_file))
504
max_length= (size_t) (info->end_of_file - pos_in_file);
517
509
info->error= static_cast<int>(left_length); /* We only got this many char */
520
length_local=0; /* Didn't read any chars */
512
length=0; /* Didn't read any chars */
522
else if (( length_local= my_read(info->file,info->buffer, max_length,
514
else if ((length= my_read(info->file,info->buffer, max_length,
523
515
info->myflags)) < Count ||
524
length_local == (size_t) -1)
516
length == (size_t) -1)
526
if ( length_local != (size_t) -1)
527
memcpy(Buffer, info->buffer, length_local);
528
info->pos_in_file= pos_in_file_local;
529
info->error= length_local == (size_t) -1 ? -1 : (int) ( length_local+left_length);
518
if (length != (size_t) -1)
519
memcpy(Buffer, info->buffer, length);
520
info->pos_in_file= pos_in_file;
521
info->error= length == (size_t) -1 ? -1 : (int) (length+left_length);
530
522
info->read_pos=info->read_end=info->buffer;
533
525
info->read_pos=info->buffer+Count;
534
info->read_end=info->buffer+ length_local;
535
info->pos_in_file=pos_in_file_local;
526
info->read_end=info->buffer+length;
527
info->pos_in_file=pos_in_file;
536
528
memcpy(Buffer, info->buffer, Count);
545
* Read from the st_io_cache into a buffer and feed asynchronously from disk when needed.
537
* Read from the IO_CACHE into a buffer and feed asynchronously from disk when needed.
547
* @param info st_io_cache pointer
539
* @param info IO_CACHE pointer
548
540
* @param Buffer Buffer to retrieve count bytes from file
549
541
* @param Count Number of bytes to read into Buffer
551
543
* @retval -1 An error has occurred; errno is set.
552
544
* @retval 0 Success
553
* @retval 1 An error has occurred; st_io_cache to error state.
545
* @retval 1 An error has occurred; IO_CACHE to error state.
555
int _my_b_async_read(register st_io_cache *info, unsigned char *Buffer, size_t Count)
547
int _my_b_async_read(register IO_CACHE *info, unsigned char *Buffer, size_t Count)
557
size_t length_local,read_length,diff_length,left_length,use_length,org_Count;
549
size_t length,read_length,diff_length,left_length,use_length,org_Count;
558
550
size_t max_length;
559
551
my_off_t next_pos_in_file;
560
552
unsigned char *read_buffer;
617
609
/* Copy found bytes to buffer */
618
length_local=min(Count,read_length);
619
memcpy(Buffer,info->read_pos,(size_t) length_local);
620
Buffer+=length_local;
622
left_length+=length_local;
610
length=min(Count,read_length);
611
memcpy(Buffer,info->read_pos,(size_t) length);
623
615
info->read_end=info->rc_pos+read_length;
624
info->read_pos+=length_local;
616
info->read_pos+=length;
627
619
next_pos_in_file=(info->pos_in_file+ (size_t)
720
712
* Read one byte when buffer is empty
722
int _my_b_get(st_io_cache *info)
714
int _my_b_get(IO_CACHE *info)
724
716
unsigned char buff;
725
717
IO_CACHE_CALLBACK pre_read,post_read;
737
* Write a byte buffer to st_io_cache and flush to disk if st_io_cache is full.
729
* Write a byte buffer to IO_CACHE and flush to disk if IO_CACHE is full.
739
731
* @retval -1 On error; errno contains error code.
740
732
* @retval 0 On success
741
733
* @retval 1 On error on write
743
int _my_b_write(register st_io_cache *info, const unsigned char *Buffer, size_t Count)
735
int _my_b_write(register IO_CACHE *info, const unsigned char *Buffer, size_t Count)
745
size_t rest_length,length_local;
737
size_t rest_length,length;
747
739
if (info->pos_in_file+info->buffer_length > info->end_of_file)
750
742
return info->error = -1;
761
753
if (Count >= IO_SIZE)
762
754
{ /* Fill first intern buffer */
763
length_local=Count & (size_t) ~(IO_SIZE-1);
755
length=Count & (size_t) ~(IO_SIZE-1);
764
756
if (info->seek_not_done)
767
Whenever a function which operates on st_io_cache flushes/writes
768
some part of the st_io_cache to disk it will set the property
759
Whenever a function which operates on IO_CACHE flushes/writes
760
some part of the IO_CACHE to disk it will set the property
769
761
"seek_not_done" to indicate this to other functions operating
772
764
if (lseek(info->file,info->pos_in_file,SEEK_SET))
777
769
info->seek_not_done=0;
779
if (my_write(info->file, Buffer, length_local, info->myflags | MY_NABP))
771
if (my_write(info->file, Buffer, length, info->myflags | MY_NABP))
780
772
return info->error= -1;
783
Buffer+=length_local;
784
info->pos_in_file+=length_local;
776
info->pos_in_file+=length;
786
778
memcpy(info->write_pos,Buffer,(size_t) Count);
787
779
info->write_pos+=Count;
794
786
* As all write calls to the data goes through the cache,
795
787
* we will never get a seek over the end of the buffer.
797
int my_block_write(register st_io_cache *info, const unsigned char *Buffer, size_t Count,
789
int my_block_write(register IO_CACHE *info, const unsigned char *Buffer, size_t Count,
803
795
if (pos < info->pos_in_file)
806
798
if (pos + Count <= info->pos_in_file)
807
799
return (pwrite(info->file, Buffer, Count, pos) == 0);
808
800
/* Write the part of the block that is before buffer */
809
length_local= (uint32_t) (info->pos_in_file - pos);
810
if (pwrite(info->file, Buffer, length_local, pos) == 0)
801
length= (uint32_t) (info->pos_in_file - pos);
802
if (pwrite(info->file, Buffer, length, pos) == 0)
811
803
info->error= error= -1;
812
Buffer+=length_local;
814
Count-= length_local;
817
809
/* Check if we want to write inside the used part of the buffer.*/
818
length_local= (size_t) (info->write_end - info->buffer);
819
if (pos < info->pos_in_file + length_local)
810
length= (size_t) (info->write_end - info->buffer);
811
if (pos < info->pos_in_file + length)
821
813
size_t offset= (size_t) (pos - info->pos_in_file);
822
length_local-=offset;
823
if (length_local > Count)
825
memcpy(info->buffer+offset, Buffer, length_local);
826
Buffer+=length_local;
827
Count-= length_local;
828
/* Fix length_local of buffer if the new data was larger */
829
if (info->buffer+length_local > info->write_pos)
830
info->write_pos=info->buffer+length_local;
817
memcpy(info->buffer+offset, Buffer, length);
820
/* Fix length of buffer if the new data was larger */
821
if (info->buffer+length > info->write_pos)
822
info->write_pos=info->buffer+length;
842
834
* Flush write cache
844
int my_b_flush_io_cache(st_io_cache *info, int need_append_buffer_lock)
836
int my_b_flush_io_cache(IO_CACHE *info, int need_append_buffer_lock)
847
839
bool append_cache= false;
848
my_off_t pos_in_file_local;
840
my_off_t pos_in_file;
850
842
if (info->type == WRITE_CACHE || append_cache)
852
844
if (info->file == -1)
854
if (info->real_open_cached_file())
846
if (real_open_cached_file(info))
855
847
return((info->error= -1));
857
849
lock_append_buffer(info, need_append_buffer_lock);
859
if ((length_local=(size_t) (info->write_pos - info->write_buffer)))
851
if ((length=(size_t) (info->write_pos - info->write_buffer)))
861
pos_in_file_local=info->pos_in_file;
853
pos_in_file=info->pos_in_file;
863
855
If we have append cache, we always open the file with
864
856
O_APPEND which moves the pos to EOF automatically on every write
866
858
if (!append_cache && info->seek_not_done)
867
859
{ /* File touched, do seek */
868
if (lseek(info->file,pos_in_file_local,SEEK_SET) == MY_FILEPOS_ERROR)
860
if (lseek(info->file,pos_in_file,SEEK_SET) == MY_FILEPOS_ERROR)
870
862
unlock_append_buffer(info, need_append_buffer_lock);
871
863
return((info->error= -1));
874
866
info->seek_not_done=0;
876
868
if (!append_cache)
877
info->pos_in_file+=length_local;
869
info->pos_in_file+=length;
878
870
info->write_end= (info->write_buffer+info->buffer_length-
879
((pos_in_file_local+length_local) & (IO_SIZE-1)));
871
((pos_in_file+length) & (IO_SIZE-1)));
881
if (my_write(info->file,info->write_buffer,length_local,
873
if (my_write(info->file,info->write_buffer,length,
882
874
info->myflags | MY_NABP))
886
878
if (!append_cache)
888
set_if_bigger(info->end_of_file,(pos_in_file_local+length_local));
880
set_if_bigger(info->end_of_file,(pos_in_file+length));
915
* Free an st_io_cache object
907
* Free an IO_CACHE object
918
910
* It's currently safe to call this if one has called init_io_cache()
919
911
* on the 'info' object, even if init_io_cache() failed.
920
912
* This function is also safe to call twice with the same handle.
922
* @param info st_io_cache Handle to free
914
* @param info IO_CACHE Handle to free
925
917
* @retval # Error
927
int st_io_cache::end_io_cache()
919
int end_io_cache(IO_CACHE *info)
938
if (type == READ_CACHE)
939
global_read_buffer.sub(buffer_length);
941
if (file != -1) /* File doesn't exist */
942
_error= my_b_flush_io_cache(this, 1);
943
free((unsigned char*) buffer);
944
buffer=read_pos=(unsigned char*) 0;
922
IO_CACHE_CALLBACK pre_close;
924
if ((pre_close=info->pre_close))
929
if (info->alloced_buffer)
931
info->alloced_buffer=0;
932
if (info->file != -1) /* File doesn't exist */
933
error= my_b_flush_io_cache(info,1);
934
free((unsigned char*) info->buffer);
935
info->buffer=info->read_pos=(unsigned char*) 0;
948
939
} /* end_io_cache */
950
941
} /* namespace internal */