~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to drizzled/internal/mf_iocache.cc

  • Committer: Brian Aker
  • Date: 2010-11-07 00:54:27 UTC
  • mfrom: (1909.1.2 merge)
  • Revision ID: brian@tangent.org-20101107005427-a3kcx1lytrm36a97
Rollup merge of iocache work.

Show diffs side-by-side

added added

removed removed

Lines of Context:
70
70
namespace internal
71
71
{
72
72
 
73
 
static int _my_b_read(register IO_CACHE *info, unsigned char *Buffer, size_t Count);
74
 
static int _my_b_write(register IO_CACHE *info, const unsigned char *Buffer, size_t Count);
 
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);
75
75
 
76
76
/**
77
77
 * @brief
78
 
 *   Lock appends for the IO_CACHE if required (need_append_buffer_lock)   
 
78
 *   Lock appends for the st_io_cache if required (need_append_buffer_lock)   
79
79
 */
80
80
inline
81
 
static void lock_append_buffer(register IO_CACHE *, int )
 
81
static void lock_append_buffer(register st_io_cache *, int )
82
82
{
83
83
}
84
84
 
85
85
/**
86
86
 * @brief
87
 
 *   Unlock appends for the IO_CACHE if required (need_append_buffer_lock)   
 
87
 *   Unlock appends for the st_io_cache if required (need_append_buffer_lock)   
88
88
 */
89
89
inline
90
 
static void unlock_append_buffer(register IO_CACHE *, int )
 
90
static void unlock_append_buffer(register st_io_cache *, int )
91
91
{
92
92
}
93
93
 
114
114
 
115
115
/**
116
116
 * @brief 
117
 
 *   Setup internal pointers inside IO_CACHE
 
117
 *   Setup internal pointers inside st_io_cache
118
118
 * 
119
119
 * @details
120
 
 *   This is called on automatically on init or reinit of IO_CACHE
121
 
 *   It must be called externally if one moves or copies an IO_CACHE object.
 
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.
122
122
 * 
123
123
 * @param info Cache handler to setup
124
124
 */
125
 
void setup_io_cache(IO_CACHE* info)
 
125
void st_io_cache::setup_io_cache()
126
126
{
127
127
  /* Ensure that my_b_tell() and my_b_bytes_in_cache works */
128
 
  if (info->type == WRITE_CACHE)
 
128
  if (type == WRITE_CACHE)
129
129
  {
130
 
    info->current_pos= &info->write_pos;
131
 
    info->current_end= &info->write_end;
 
130
    current_pos= &write_pos;
 
131
    current_end= &write_end;
132
132
  }
133
133
  else
134
134
  {
135
 
    info->current_pos= &info->read_pos;
136
 
    info->current_end= &info->read_end;
 
135
    current_pos= &read_pos;
 
136
    current_end= &read_end;
137
137
  }
138
138
}
139
139
 
140
140
 
141
 
static void
142
 
init_functions(IO_CACHE* info)
 
141
void st_io_cache::init_functions()
143
142
{
144
 
  enum cache_type type= info->type;
145
143
  switch (type) {
146
144
  case READ_NET:
147
145
    /*
153
151
    */
154
152
    break;
155
153
  default:
156
 
    info->read_function = _my_b_read;
157
 
    info->write_function = _my_b_write;
 
154
    read_function = _my_b_read;
 
155
    write_function = _my_b_write;
158
156
  }
159
157
 
160
 
  setup_io_cache(info);
 
158
  setup_io_cache();
161
159
}
162
160
 
163
161
/**
164
162
 * @brief
165
 
 *   Initialize an IO_CACHE object
 
163
 *   Initialize an st_io_cache object
166
164
 *
167
 
 * @param info Cache handler to initialize
168
165
 * @param file File that should be associated with the handler
169
166
 *                 If == -1 then real_open_cached_file() will be called when it's time to open file.
170
167
 * @param cachesize Size of buffer to allocate for read/write
178
175
 * @retval 0 success
179
176
 * @retval # error
180
177
 */
181
 
int init_io_cache(IO_CACHE *info, int file, size_t cachesize,
182
 
                  enum cache_type type, my_off_t seek_offset,
183
 
                  bool use_async_io, myf cache_myflags)
 
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)
184
181
{
185
182
  size_t min_cache;
186
183
  off_t pos;
187
 
  my_off_t end_of_file= ~(my_off_t) 0;
 
184
  my_off_t end_of_file_local= ~(my_off_t) 0;
188
185
 
189
 
  info->file= file;
190
 
  info->type= TYPE_NOT_SET;         /* Don't set it until mutex are created */
191
 
  info->pos_in_file= seek_offset;
192
 
  info->pre_close = info->pre_read = info->post_read = 0;
193
 
  info->arg = 0;
194
 
  info->alloced_buffer = 0;
195
 
  info->buffer=0;
196
 
  info->seek_not_done= 0;
 
186
  file= file_arg;
 
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;
 
190
  arg = 0;
 
191
  alloced_buffer = 0;
 
192
  buffer=0;
 
193
  seek_not_done= 0;
197
194
 
198
195
  if (file >= 0)
199
196
  {
204
201
         This kind of object doesn't support seek() or tell(). Don't set a
205
202
         flag that will make us again try to seek() later and fail.
206
203
      */
207
 
      info->seek_not_done= 0;
 
204
      seek_not_done= 0;
208
205
      /*
209
206
        Additionally, if we're supposed to start somewhere other than the
210
207
        the beginning of whatever this file is, then somebody made a bad
213
210
      assert(seek_offset == 0);
214
211
    }
215
212
    else
216
 
      info->seek_not_done= test(seek_offset != (my_off_t)pos);
 
213
      seek_not_done= test(seek_offset != (my_off_t)pos);
217
214
  }
218
215
 
219
216
  if (!cachesize && !(cachesize= my_default_record_cache_size))
220
 
    return(1);                          /* No cache requested */
 
217
    return 1;                           /* No cache requested */
221
218
  min_cache=use_async_io ? IO_SIZE*4 : IO_SIZE*2;
222
 
  if (type == READ_CACHE)
 
219
  if (type_arg == READ_CACHE)
223
220
  {                                             /* Assume file isn't growing */
224
221
    if (!(cache_myflags & MY_DONT_CHECK_FILESIZE))
225
222
    {
226
223
      /* Calculate end of file to avoid allocating oversized buffers */
227
 
      end_of_file=lseek(file,0L,SEEK_END);
 
224
      end_of_file_local=lseek(file,0L,SEEK_END);
228
225
      /* Need to reset seek_not_done now that we just did a seek. */
229
 
      info->seek_not_done= end_of_file == seek_offset ? 0 : 1;
230
 
      if (end_of_file < seek_offset)
231
 
        end_of_file=seek_offset;
 
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;
232
229
      /* Trim cache size if the file is very small */
233
 
      if ((my_off_t) cachesize > end_of_file-seek_offset+IO_SIZE*2-1)
 
230
      if ((my_off_t) cachesize > end_of_file_local-seek_offset+IO_SIZE*2-1)
234
231
      {
235
 
        cachesize= (size_t) (end_of_file-seek_offset)+IO_SIZE*2-1;
 
232
        cachesize= (size_t) (end_of_file_local-seek_offset)+IO_SIZE*2-1;
236
233
        use_async_io=0;                         /* No need to use async */
237
234
      }
238
235
    }
239
236
  }
240
237
  cache_myflags &= ~MY_DONT_CHECK_FILESIZE;
241
 
  if (type != READ_NET && type != WRITE_NET)
 
238
  if (type_arg != READ_NET && type_arg != WRITE_NET)
242
239
  {
243
240
    /* Retry allocating memory in smaller blocks until we get one */
244
241
    cachesize= ((cachesize + min_cache-1) & ~(min_cache-1));
248
245
      if (cachesize < min_cache)
249
246
        cachesize = min_cache;
250
247
      buffer_block= cachesize;
251
 
      if ((type == READ_CACHE) and (not global_read_buffer.add(buffer_block)))
 
248
      if ((type_arg == READ_CACHE) and (not global_read_buffer.add(buffer_block)))
252
249
      {
253
250
        my_error(ER_OUT_OF_GLOBAL_READMEMORY, MYF(ME_ERROR+ME_WAITTANG));
254
251
        return 2;
255
252
      }
256
253
 
257
 
      if ((info->buffer=
 
254
      if ((buffer=
258
255
           (unsigned char*) malloc(buffer_block)) != 0)
259
256
      {
260
 
        info->write_buffer=info->buffer;
261
 
        info->alloced_buffer= true;
 
257
        write_buffer=buffer;
 
258
        alloced_buffer= true;
262
259
        break;                                  /* Enough memory found */
263
260
      }
264
261
      if (cachesize == min_cache)
265
262
      {
266
 
        if (type == READ_CACHE)
 
263
        if (type_arg == READ_CACHE)
267
264
          global_read_buffer.sub(buffer_block);
268
 
        return(2);                              /* Can't alloc cache */
 
265
        return 2;                               /* Can't alloc cache */
269
266
      }
270
267
      /* Try with less memory */
271
 
      if (type == READ_CACHE)
 
268
      if (type_arg == READ_CACHE)
272
269
        global_read_buffer.sub(buffer_block);
273
270
      cachesize= (cachesize*3/4 & ~(min_cache-1));
274
271
    }
275
272
  }
276
273
 
277
 
  info->read_length=info->buffer_length=cachesize;
278
 
  info->myflags=cache_myflags & ~(MY_NABP | MY_FNABP);
279
 
  info->request_pos= info->read_pos= info->write_pos = info->buffer;
 
274
  read_length=buffer_length=cachesize;
 
275
  myflags=cache_myflags & ~(MY_NABP | MY_FNABP);
 
276
  request_pos= read_pos= write_pos = buffer;
280
277
 
281
 
  if (type == WRITE_CACHE)
282
 
    info->write_end=
283
 
      info->buffer+info->buffer_length- (seek_offset & (IO_SIZE-1));
 
278
  if (type_arg == WRITE_CACHE)
 
279
    write_end=
 
280
      buffer+buffer_length- (seek_offset & (IO_SIZE-1));
284
281
  else
285
 
    info->read_end=info->buffer;                /* Nothing in cache */
 
282
    read_end=buffer;            /* Nothing in cache */
286
283
 
287
284
  /* End_of_file may be changed by user later */
288
 
  info->end_of_file= end_of_file;
289
 
  info->error=0;
290
 
  info->type= type;
291
 
  init_functions(info);
 
285
  end_of_file= end_of_file_local;
 
286
  error= 0;
 
287
  type= type_arg;
 
288
  init_functions();
292
289
#ifdef HAVE_AIOWAIT
293
290
  if (use_async_io && ! my_disable_async_io)
294
291
  {
295
 
    info->read_length/=2;
296
 
    info->read_function=_my_b_async_read;
 
292
    read_length/=2;
 
293
    read_function=_my_b_async_read;
297
294
  }
298
 
  info->inited=info->aio_result.pending=0;
 
295
  inited= aio_result.pending= 0;
299
296
#endif
300
 
  return(0);
 
297
  return 0;
301
298
}                                               /* init_io_cache */
302
299
 
303
300
        /* Wait until current request is ready */
322
319
        break;
323
320
    }
324
321
  }
325
 
  return;
326
322
}
327
323
#endif
328
324
 
336
332
 *   If we are doing a reinit of a cache where we have the start of the file
337
333
 *   in the cache, we are reusing this memory without flushing it to disk.
338
334
 */
339
 
bool reinit_io_cache(IO_CACHE *info, enum cache_type type,
340
 
                        my_off_t seek_offset,
341
 
                        bool use_async_io,
342
 
                        bool clear_cache)
 
335
bool st_io_cache::reinit_io_cache(enum cache_type type_arg,
 
336
                                  my_off_t seek_offset,
 
337
                                  bool use_async_io,
 
338
                                  bool clear_cache)
343
339
{
344
340
  /* One can't do reinit with the following types */
345
 
  assert(type != READ_NET && info->type != READ_NET &&
346
 
              type != WRITE_NET && info->type != WRITE_NET);
 
341
  assert(type_arg != READ_NET && type != READ_NET &&
 
342
              type_arg != WRITE_NET && type != WRITE_NET);
347
343
 
348
344
  /* If the whole file is in memory, avoid flushing to disk */
349
345
  if (! clear_cache &&
350
 
      seek_offset >= info->pos_in_file &&
351
 
      seek_offset <= my_b_tell(info))
 
346
      seek_offset >= pos_in_file &&
 
347
      seek_offset <= my_b_tell(this))
352
348
  {
353
349
    /* Reuse current buffer without flushing it to disk */
354
350
    unsigned char *pos;
355
 
    if (info->type == WRITE_CACHE && type == READ_CACHE)
 
351
    if (type == WRITE_CACHE && type_arg == READ_CACHE)
356
352
    {
357
 
      info->read_end=info->write_pos;
358
 
      info->end_of_file=my_b_tell(info);
 
353
      read_end=write_pos;
 
354
      end_of_file=my_b_tell(this);
359
355
      /*
360
356
        Trigger a new seek only if we have a valid
361
357
        file handle.
362
358
      */
363
 
      info->seek_not_done= (info->file != -1);
 
359
      seek_not_done= (file != -1);
364
360
    }
365
 
    else if (type == WRITE_CACHE)
 
361
    else if (type_arg == WRITE_CACHE)
366
362
    {
367
 
      if (info->type == READ_CACHE)
 
363
      if (type == READ_CACHE)
368
364
      {
369
 
        info->write_end=info->write_buffer+info->buffer_length;
370
 
        info->seek_not_done=1;
 
365
        write_end=write_buffer+buffer_length;
 
366
        seek_not_done=1;
371
367
      }
372
 
      info->end_of_file = ~(my_off_t) 0;
 
368
      end_of_file = ~(my_off_t) 0;
373
369
    }
374
 
    pos=info->request_pos+(seek_offset-info->pos_in_file);
375
 
    if (type == WRITE_CACHE)
376
 
      info->write_pos=pos;
 
370
    pos=request_pos+(seek_offset-pos_in_file);
 
371
    if (type_arg == WRITE_CACHE)
 
372
      write_pos=pos;
377
373
    else
378
 
      info->read_pos= pos;
 
374
      read_pos= pos;
379
375
#ifdef HAVE_AIOWAIT
380
 
    my_aiowait(&info->aio_result);              /* Wait for outstanding req */
 
376
    my_aiowait(&aio_result);            /* Wait for outstanding req */
381
377
#endif
382
378
  }
383
379
  else
386
382
      If we change from WRITE_CACHE to READ_CACHE, assume that everything
387
383
      after the current positions should be ignored
388
384
    */
389
 
    if (info->type == WRITE_CACHE && type == READ_CACHE)
390
 
      info->end_of_file=my_b_tell(info);
 
385
    if (type == WRITE_CACHE && type_arg == READ_CACHE)
 
386
      end_of_file=my_b_tell(this);
391
387
    /* flush cache if we want to reuse it */
392
 
    if (!clear_cache && my_b_flush_io_cache(info,1))
393
 
      return(1);
394
 
    info->pos_in_file=seek_offset;
 
388
    if (!clear_cache && my_b_flush_io_cache(this, 1))
 
389
      return 1;
 
390
    pos_in_file=seek_offset;
395
391
    /* Better to do always do a seek */
396
 
    info->seek_not_done=1;
397
 
    info->request_pos=info->read_pos=info->write_pos=info->buffer;
398
 
    if (type == READ_CACHE)
 
392
    seek_not_done=1;
 
393
    request_pos=read_pos=write_pos=buffer;
 
394
    if (type_arg == READ_CACHE)
399
395
    {
400
 
      info->read_end=info->buffer;              /* Nothing in cache */
 
396
      read_end=buffer;          /* Nothing in cache */
401
397
    }
402
398
    else
403
399
    {
404
 
      info->write_end=(info->buffer + info->buffer_length -
 
400
      write_end=(buffer + buffer_length -
405
401
                       (seek_offset & (IO_SIZE-1)));
406
 
      info->end_of_file= ~(my_off_t) 0;
 
402
      end_of_file= ~(my_off_t) 0;
407
403
    }
408
404
  }
409
 
  info->type=type;
410
 
  info->error=0;
411
 
  init_functions(info);
 
405
  type= type_arg;
 
406
  error=0;
 
407
  init_functions();
412
408
 
413
409
#ifdef HAVE_AIOWAIT
414
410
  if (use_async_io && ! my_disable_async_io &&
415
 
      ((uint32_t) info->buffer_length <
416
 
       (uint32_t) (info->end_of_file - seek_offset)))
 
411
      ((uint32_t) buffer_length <
 
412
       (uint32_t) (end_of_file - seek_offset)))
417
413
  {
418
 
    info->read_length=info->buffer_length/2;
419
 
    info->read_function=_my_b_async_read;
 
414
    read_length=buffer_length/2;
 
415
    read_function=_my_b_async_read;
420
416
  }
421
 
  info->inited=0;
 
417
  inited= 0;
422
418
#else
423
419
  (void)use_async_io;
424
420
#endif
425
 
  return(0);
 
421
  return 0;
426
422
} /* reinit_io_cache */
427
423
 
428
424
/**
439
435
 *   types than my_off_t unless you can be sure that their value fits.
440
436
 *   Same applies to differences of file offsets.
441
437
 *
442
 
 * @param info IO_CACHE pointer @param Buffer Buffer to retrieve count bytes
 
438
 * @param info st_io_cache pointer @param Buffer Buffer to retrieve count bytes
443
439
 * from file @param Count Number of bytes to read into Buffer
444
440
 * 
445
441
 * @retval 0 We succeeded in reading all data
446
442
 * @retval 1 Error: can't read requested characters
447
443
 */
448
 
static int _my_b_read(register IO_CACHE *info, unsigned char *Buffer, size_t Count)
 
444
static int _my_b_read(register st_io_cache *info, unsigned char *Buffer, size_t Count)
449
445
{
450
 
  size_t length,diff_length,left_length, max_length;
451
 
  my_off_t pos_in_file;
 
446
  size_t length_local,diff_length,left_length, max_length;
 
447
  my_off_t pos_in_file_local;
452
448
 
453
449
  if ((left_length= (size_t) (info->read_end-info->read_pos)))
454
450
  {
459
455
  }
460
456
 
461
457
  /* pos_in_file always point on where info->buffer was read */
462
 
  pos_in_file=info->pos_in_file+ (size_t) (info->read_end - info->buffer);
 
458
  pos_in_file_local=info->pos_in_file+ (size_t) (info->read_end - info->buffer);
463
459
 
464
460
  /*
465
 
    Whenever a function which operates on IO_CACHE flushes/writes
466
 
    some part of the IO_CACHE to disk it will set the property
 
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
467
463
    "seek_not_done" to indicate this to other functions operating
468
 
    on the IO_CACHE.
 
464
    on the st_io_cache.
469
465
  */
470
466
  if (info->seek_not_done)
471
467
  {
472
 
    if ((lseek(info->file,pos_in_file,SEEK_SET) != MY_FILEPOS_ERROR))
 
468
    if ((lseek(info->file,pos_in_file_local,SEEK_SET) != MY_FILEPOS_ERROR))
473
469
    {
474
470
      /* No error, reset seek_not_done flag. */
475
471
      info->seek_not_done= 0;
487
483
    }
488
484
  }
489
485
 
490
 
  diff_length= (size_t) (pos_in_file & (IO_SIZE-1));
 
486
  diff_length= (size_t) (pos_in_file_local & (IO_SIZE-1));
491
487
  if (Count >= (size_t) (IO_SIZE+(IO_SIZE-diff_length)))
492
488
  {                                     /* Fill first intern buffer */
493
489
    size_t read_length;
494
 
    if (info->end_of_file <= pos_in_file)
 
490
    if (info->end_of_file <= pos_in_file_local)
495
491
    {                                   /* End of file */
496
492
      info->error= (int) left_length;
497
493
      return(1);
498
494
    }
499
 
    length=(Count & (size_t) ~(IO_SIZE-1))-diff_length;
500
 
    if ((read_length= my_read(info->file,Buffer, length, info->myflags))
501
 
        != 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)
502
497
    {
503
498
      info->error= (read_length == (size_t) -1 ? -1 :
504
499
                    (int) (read_length+left_length));
505
500
      return(1);
506
501
    }
507
 
    Count-=length;
508
 
    Buffer+=length;
509
 
    pos_in_file+=length;
510
 
    left_length+=length;
 
502
    Count-= length_local;
 
503
    Buffer+= length_local;
 
504
    pos_in_file_local+= length_local;
 
505
    left_length+= length_local;
511
506
    diff_length=0;
512
507
  }
513
508
 
514
509
  max_length= info->read_length-diff_length;
515
510
  if (info->type != READ_FIFO &&
516
 
      max_length > (info->end_of_file - pos_in_file))
517
 
    max_length= (size_t) (info->end_of_file - pos_in_file);
 
511
      max_length > (info->end_of_file - pos_in_file_local))
 
512
    max_length= (size_t) (info->end_of_file - pos_in_file_local);
518
513
  if (!max_length)
519
514
  {
520
515
    if (Count)
522
517
      info->error= static_cast<int>(left_length);       /* We only got this many char */
523
518
      return(1);
524
519
    }
525
 
    length=0;                           /* Didn't read any chars */
 
520
     length_local=0;                            /* Didn't read any chars */
526
521
  }
527
 
  else if ((length= my_read(info->file,info->buffer, max_length,
 
522
  else if (( length_local= my_read(info->file,info->buffer, max_length,
528
523
                            info->myflags)) < Count ||
529
 
           length == (size_t) -1)
 
524
            length_local == (size_t) -1)
530
525
  {
531
 
    if (length != (size_t) -1)
532
 
      memcpy(Buffer, info->buffer, length);
533
 
    info->pos_in_file= pos_in_file;
534
 
    info->error= length == (size_t) -1 ? -1 : (int) (length+left_length);
 
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);
535
530
    info->read_pos=info->read_end=info->buffer;
536
531
    return(1);
537
532
  }
538
533
  info->read_pos=info->buffer+Count;
539
 
  info->read_end=info->buffer+length;
540
 
  info->pos_in_file=pos_in_file;
 
534
  info->read_end=info->buffer+ length_local;
 
535
  info->pos_in_file=pos_in_file_local;
541
536
  memcpy(Buffer, info->buffer, Count);
542
537
  return(0);
543
538
}
547
542
 
548
543
/**
549
544
 * @brief
550
 
 *   Read from the IO_CACHE into a buffer and feed asynchronously from disk when needed.
 
545
 *   Read from the st_io_cache into a buffer and feed asynchronously from disk when needed.
551
546
 *
552
 
 * @param info IO_CACHE pointer
 
547
 * @param info st_io_cache pointer
553
548
 * @param Buffer Buffer to retrieve count bytes from file
554
549
 * @param Count Number of bytes to read into Buffer
555
550
 * 
556
551
 * @retval -1 An error has occurred; errno is set.
557
552
 * @retval 0 Success
558
 
 * @retval 1 An error has occurred; IO_CACHE to error state.
 
553
 * @retval 1 An error has occurred; st_io_cache to error state.
559
554
 */
560
 
int _my_b_async_read(register IO_CACHE *info, unsigned char *Buffer, size_t Count)
 
555
int _my_b_async_read(register st_io_cache *info, unsigned char *Buffer, size_t Count)
561
556
{
562
 
  size_t length,read_length,diff_length,left_length,use_length,org_Count;
 
557
  size_t length_local,read_length,diff_length,left_length,use_length,org_Count;
563
558
  size_t max_length;
564
559
  my_off_t next_pos_in_file;
565
560
  unsigned char *read_buffer;
620
615
      }
621
616
    }
622
617
        /* Copy found bytes to buffer */
623
 
    length=min(Count,read_length);
624
 
    memcpy(Buffer,info->read_pos,(size_t) length);
625
 
    Buffer+=length;
626
 
    Count-=length;
627
 
    left_length+=length;
 
618
    length_local=min(Count,read_length);
 
619
    memcpy(Buffer,info->read_pos,(size_t) length_local);
 
620
    Buffer+=length_local;
 
621
    Count-=length_local;
 
622
    left_length+=length_local;
628
623
    info->read_end=info->rc_pos+read_length;
629
 
    info->read_pos+=length;
 
624
    info->read_pos+=length_local;
630
625
  }
631
626
  else
632
627
    next_pos_in_file=(info->pos_in_file+ (size_t)
724
719
 * @brief
725
720
 *   Read one byte when buffer is empty
726
721
 */
727
 
int _my_b_get(IO_CACHE *info)
 
722
int _my_b_get(st_io_cache *info)
728
723
{
729
724
  unsigned char buff;
730
725
  IO_CACHE_CALLBACK pre_read,post_read;
739
734
 
740
735
/**
741
736
 * @brief
742
 
 *   Write a byte buffer to IO_CACHE and flush to disk if IO_CACHE is full.
 
737
 *   Write a byte buffer to st_io_cache and flush to disk if st_io_cache is full.
743
738
 *
744
739
 * @retval -1 On error; errno contains error code.
745
740
 * @retval 0 On success
746
741
 * @retval 1 On error on write
747
742
 */
748
 
int _my_b_write(register IO_CACHE *info, const unsigned char *Buffer, size_t Count)
 
743
int _my_b_write(register st_io_cache *info, const unsigned char *Buffer, size_t Count)
749
744
{
750
 
  size_t rest_length,length;
 
745
  size_t rest_length,length_local;
751
746
 
752
747
  if (info->pos_in_file+info->buffer_length > info->end_of_file)
753
748
  {
765
760
    return 1;
766
761
  if (Count >= IO_SIZE)
767
762
  {                                     /* Fill first intern buffer */
768
 
    length=Count & (size_t) ~(IO_SIZE-1);
 
763
    length_local=Count & (size_t) ~(IO_SIZE-1);
769
764
    if (info->seek_not_done)
770
765
    {
771
766
      /*
772
 
        Whenever a function which operates on IO_CACHE flushes/writes
773
 
        some part of the IO_CACHE to disk it will set the property
 
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
774
769
        "seek_not_done" to indicate this to other functions operating
775
 
        on the IO_CACHE.
 
770
        on the st_io_cache.
776
771
      */
777
772
      if (lseek(info->file,info->pos_in_file,SEEK_SET))
778
773
      {
781
776
      }
782
777
      info->seek_not_done=0;
783
778
    }
784
 
    if (my_write(info->file, Buffer, length, info->myflags | MY_NABP))
 
779
    if (my_write(info->file, Buffer, length_local, info->myflags | MY_NABP))
785
780
      return info->error= -1;
786
781
 
787
 
    Count-=length;
788
 
    Buffer+=length;
789
 
    info->pos_in_file+=length;
 
782
    Count-=length_local;
 
783
    Buffer+=length_local;
 
784
    info->pos_in_file+=length_local;
790
785
  }
791
786
  memcpy(info->write_pos,Buffer,(size_t) Count);
792
787
  info->write_pos+=Count;
799
794
 *   As all write calls to the data goes through the cache,
800
795
 *   we will never get a seek over the end of the buffer.
801
796
 */
802
 
int my_block_write(register IO_CACHE *info, const unsigned char *Buffer, size_t Count,
 
797
int my_block_write(register st_io_cache *info, const unsigned char *Buffer, size_t Count,
803
798
                   my_off_t pos)
804
799
{
805
 
  size_t length;
 
800
  size_t length_local;
806
801
  int error=0;
807
802
 
808
803
  if (pos < info->pos_in_file)
811
806
    if (pos + Count <= info->pos_in_file)
812
807
      return (pwrite(info->file, Buffer, Count, pos) == 0);
813
808
    /* Write the part of the block that is before buffer */
814
 
    length= (uint32_t) (info->pos_in_file - pos);
815
 
    if (pwrite(info->file, Buffer, length, pos) == 0)
 
809
    length_local= (uint32_t) (info->pos_in_file - pos);
 
810
    if (pwrite(info->file, Buffer, length_local, pos) == 0)
816
811
      info->error= error= -1;
817
 
    Buffer+=length;
818
 
    pos+=  length;
819
 
    Count-= length;
 
812
    Buffer+=length_local;
 
813
    pos+=  length_local;
 
814
    Count-= length_local;
820
815
  }
821
816
 
822
817
  /* Check if we want to write inside the used part of the buffer.*/
823
 
  length= (size_t) (info->write_end - info->buffer);
824
 
  if (pos < info->pos_in_file + length)
 
818
  length_local= (size_t) (info->write_end - info->buffer);
 
819
  if (pos < info->pos_in_file + length_local)
825
820
  {
826
821
    size_t offset= (size_t) (pos - info->pos_in_file);
827
 
    length-=offset;
828
 
    if (length > Count)
829
 
      length=Count;
830
 
    memcpy(info->buffer+offset, Buffer, length);
831
 
    Buffer+=length;
832
 
    Count-= length;
833
 
    /* Fix length of buffer if the new data was larger */
834
 
    if (info->buffer+length > info->write_pos)
835
 
      info->write_pos=info->buffer+length;
 
822
    length_local-=offset;
 
823
    if (length_local > Count)
 
824
      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;
836
831
    if (!Count)
837
832
      return (error);
838
833
  }
846
841
 * @brief
847
842
 *   Flush write cache 
848
843
 */
849
 
int my_b_flush_io_cache(IO_CACHE *info, int need_append_buffer_lock)
 
844
int my_b_flush_io_cache(st_io_cache *info, int need_append_buffer_lock)
850
845
{
851
 
  size_t length;
 
846
  size_t length_local;
852
847
  bool append_cache= false;
853
 
  my_off_t pos_in_file;
 
848
  my_off_t pos_in_file_local;
854
849
 
855
850
  if (info->type == WRITE_CACHE || append_cache)
856
851
  {
857
852
    if (info->file == -1)
858
853
    {
859
 
      if (real_open_cached_file(info))
 
854
      if (info->real_open_cached_file())
860
855
        return((info->error= -1));
861
856
    }
862
857
    lock_append_buffer(info, need_append_buffer_lock);
863
858
 
864
 
    if ((length=(size_t) (info->write_pos - info->write_buffer)))
 
859
    if ((length_local=(size_t) (info->write_pos - info->write_buffer)))
865
860
    {
866
 
      pos_in_file=info->pos_in_file;
 
861
      pos_in_file_local=info->pos_in_file;
867
862
      /*
868
863
        If we have append cache, we always open the file with
869
864
        O_APPEND which moves the pos to EOF automatically on every write
870
865
      */
871
866
      if (!append_cache && info->seek_not_done)
872
867
      {                                 /* File touched, do seek */
873
 
        if (lseek(info->file,pos_in_file,SEEK_SET) == MY_FILEPOS_ERROR)
 
868
        if (lseek(info->file,pos_in_file_local,SEEK_SET) == MY_FILEPOS_ERROR)
874
869
        {
875
870
          unlock_append_buffer(info, need_append_buffer_lock);
876
871
          return((info->error= -1));
879
874
          info->seek_not_done=0;
880
875
      }
881
876
      if (!append_cache)
882
 
        info->pos_in_file+=length;
 
877
        info->pos_in_file+=length_local;
883
878
      info->write_end= (info->write_buffer+info->buffer_length-
884
 
                        ((pos_in_file+length) & (IO_SIZE-1)));
 
879
                        ((pos_in_file_local+length_local) & (IO_SIZE-1)));
885
880
 
886
 
      if (my_write(info->file,info->write_buffer,length,
 
881
      if (my_write(info->file,info->write_buffer,length_local,
887
882
                   info->myflags | MY_NABP))
888
883
        info->error= -1;
889
884
      else
890
885
        info->error= 0;
891
886
      if (!append_cache)
892
887
      {
893
 
        set_if_bigger(info->end_of_file,(pos_in_file+length));
 
888
        set_if_bigger(info->end_of_file,(pos_in_file_local+length_local));
894
889
      }
895
890
      else
896
891
      {
917
912
 
918
913
/**
919
914
 * @brief
920
 
 *   Free an IO_CACHE object
 
915
 *   Free an st_io_cache object
921
916
 * 
922
917
 * @detail
923
918
 *   It's currently safe to call this if one has called init_io_cache()
924
919
 *   on the 'info' object, even if init_io_cache() failed.
925
920
 *   This function is also safe to call twice with the same handle.
926
921
 * 
927
 
 * @param info IO_CACHE Handle to free
 
922
 * @param info st_io_cache Handle to free
928
923
 * 
929
924
 * @retval 0 ok
930
925
 * @retval # Error
931
926
 */
932
 
int end_io_cache(IO_CACHE *info)
 
927
int st_io_cache::end_io_cache()
933
928
{
934
 
  int error=0;
935
 
  IO_CACHE_CALLBACK pre_close;
936
 
 
937
 
  if ((pre_close=info->pre_close))
938
 
  {
939
 
    (*pre_close)(info);
940
 
    info->pre_close= 0;
941
 
  }
942
 
  if (info->alloced_buffer)
943
 
  {
944
 
    if (info->type == READ_CACHE)
945
 
      global_read_buffer.sub(info->buffer_length);
946
 
    info->alloced_buffer=0;
947
 
    if (info->file != -1)                       /* File doesn't exist */
948
 
      error= my_b_flush_io_cache(info,1);
949
 
    free((unsigned char*) info->buffer);
950
 
    info->buffer=info->read_pos=(unsigned char*) 0;
951
 
  }
952
 
 
953
 
  return(error);
 
929
  int _error=0;
 
930
 
 
931
  if (pre_close)
 
932
  {
 
933
    (*pre_close)(this);
 
934
    pre_close= 0;
 
935
  }
 
936
  if (alloced_buffer)
 
937
  {
 
938
    if (type == READ_CACHE)
 
939
      global_read_buffer.sub(buffer_length);
 
940
    alloced_buffer=0;
 
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;
 
945
  }
 
946
 
 
947
  return _error;
954
948
} /* end_io_cache */
955
949
 
956
950
} /* namespace internal */