~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to plugin/myisam/mf_keycache.cc

Merge Monty.

Show diffs side-by-side

added added

removed removed

Lines of Context:
101
101
  I/O finished.
102
102
*/
103
103
 
104
 
#include "my_global.h"
105
 
#include "mysys_err.h"
106
 
#include <my_sys.h>
107
 
#include <keycache.h>
108
 
#include <m_string.h>
109
 
#include <my_bit.h>
 
104
#include "config.h"
 
105
#include "drizzled/my_error.h"
 
106
#include "drizzled/internal/my_sys.h"
 
107
#include "keycache.h"
 
108
#include "drizzled/internal/m_string.h"
 
109
#include "drizzled/internal/my_bit.h"
110
110
#include <errno.h>
111
111
#include <stdarg.h>
112
112
 
 
113
static void change_key_cache_param(KEY_CACHE *keycache, uint32_t division_limit,
 
114
                            uint32_t age_threshold);
 
115
 
113
116
/*
114
117
  Some compilation flags have been added specifically for this module
115
118
  to control the following:
143
146
/* types of condition variables */
144
147
#define  COND_FOR_REQUESTED 0
145
148
#define  COND_FOR_SAVED     1
146
 
#define  COND_FOR_READERS   2
147
149
 
148
150
typedef pthread_cond_t KEYCACHE_CONDVAR;
149
151
 
159
161
{
160
162
  struct st_hash_link *next, **prev; /* to connect links in the same bucket  */
161
163
  struct st_block_link *block;       /* reference to the block for the page: */
162
 
  File file;                         /* from such a file                     */
 
164
  int file;                         /* from such a file                     */
163
165
  my_off_t diskpos;                  /* with such an offset                  */
164
 
  uint requests;                     /* number of requests for the page      */
 
166
  uint32_t requests;                     /* number of requests for the page      */
165
167
};
166
168
 
167
169
/* simple states of a block */
193
195
    *next_changed, **prev_changed; /* for lists of file dirty/clean blocks   */
194
196
  struct st_hash_link *hash_link; /* backward ptr to referring hash_link     */
195
197
  KEYCACHE_WQUEUE wqueue[2]; /* queues on waiting requests for new/old pages */
196
 
  uint requests;          /* number of requests for the block                */
197
 
  uchar *buffer;           /* buffer for the block page                       */
198
 
  uint offset;            /* beginning of modified data in the buffer        */
199
 
  uint length;            /* end of data in the buffer                       */
200
 
  uint status;            /* state of the block                              */
 
198
  uint32_t requests;          /* number of requests for the block                */
 
199
  unsigned char *buffer;           /* buffer for the block page                       */
 
200
  uint32_t offset;            /* beginning of modified data in the buffer        */
 
201
  uint32_t length;            /* end of data in the buffer                       */
 
202
  uint32_t status;            /* state of the block                              */
201
203
  enum BLOCK_TEMPERATURE temperature; /* block temperature: cold, warm, hot */
202
 
  uint hits_left;         /* number of hits left until promotion             */
 
204
  uint32_t hits_left;         /* number of hits left until promotion             */
203
205
  uint64_t last_hit_time; /* timestamp of the last hit                      */
204
206
  KEYCACHE_CONDVAR *condvar; /* condition variable for 'no readers' event    */
205
207
};
216
218
static void free_block(KEY_CACHE *keycache, BLOCK_LINK *block);
217
219
 
218
220
#define KEYCACHE_HASH(f, pos)                                                 \
219
 
(((ulong) ((pos) / keycache->key_cache_block_size) +                          \
220
 
                                     (ulong) (f)) & (keycache->hash_entries-1))
 
221
(((uint32_t) ((pos) / keycache->key_cache_block_size) +                          \
 
222
                                     (uint32_t) (f)) & (keycache->hash_entries-1))
221
223
#define FILE_HASH(f)                 ((uint) (f) & (CHANGED_BLOCKS_HASH-1))
222
224
 
223
 
#define BLOCK_NUMBER(b)                                                       \
224
 
  ((uint) (((char*)(b)-(char *) keycache->block_root)/sizeof(BLOCK_LINK)))
225
 
#define HASH_LINK_NUMBER(h)                                                   \
226
 
  ((uint) (((char*)(h)-(char *) keycache->hash_link_root)/sizeof(HASH_LINK)))
227
225
 
228
226
#ifdef KEYCACHE_TIMEOUT
229
227
static int keycache_pthread_cond_wait(pthread_cond_t *cond,
236
234
#define keycache_pthread_mutex_unlock pthread_mutex_unlock
237
235
#define keycache_pthread_cond_signal pthread_cond_signal
238
236
 
239
 
static inline uint next_power(uint value)
 
237
static inline uint32_t next_power(uint32_t value)
240
238
{
241
239
  return (uint) my_round_up_to_next_power((uint32_t) value) << 1;
242
240
}
267
265
 
268
266
*/
269
267
 
270
 
int init_key_cache(KEY_CACHE *keycache, uint key_cache_block_size,
271
 
                   size_t use_mem, uint division_limit,
272
 
                   uint age_threshold)
 
268
int init_key_cache(KEY_CACHE *keycache, uint32_t key_cache_block_size,
 
269
                   size_t use_mem, uint32_t division_limit,
 
270
                   uint32_t age_threshold)
273
271
{
274
 
  ulong blocks, hash_links;
 
272
  uint32_t blocks, hash_links;
275
273
  size_t length;
276
274
  int error;
277
275
  assert(key_cache_block_size >= 512);
303
301
  keycache->key_cache_mem_size= use_mem;
304
302
  keycache->key_cache_block_size= key_cache_block_size;
305
303
 
306
 
  blocks= (ulong) (use_mem / (sizeof(BLOCK_LINK) + 2 * sizeof(HASH_LINK) +
 
304
  blocks= (uint32_t) (use_mem / (sizeof(BLOCK_LINK) + 2 * sizeof(HASH_LINK) +
307
305
                              sizeof(HASH_LINK*) * 5/4 + key_cache_block_size));
308
306
  /* It doesn't make sense to have too few blocks (less than 8) */
309
307
  if (blocks >= 8)
325
323
             ((size_t) blocks * keycache->key_cache_block_size) > use_mem)
326
324
        blocks--;
327
325
      /* Allocate memory for cache page buffers */
328
 
      if ((keycache->block_mem= malloc((size_t) blocks * keycache->key_cache_block_size)))
 
326
      if ((keycache->block_mem= (unsigned char *)malloc((size_t) blocks * keycache->key_cache_block_size)))
329
327
      {
330
328
        /*
331
329
          Allocate memory for blocks, hash_links and hash entries;
332
330
          For each block 2 hash links are allocated
333
331
        */
334
 
        if ((keycache->block_root= (BLOCK_LINK*) my_malloc(length,
335
 
                                                           MYF(0))))
 
332
        if ((keycache->block_root= (BLOCK_LINK*) malloc(length)))
336
333
          break;
337
334
        free(keycache->block_mem);
338
335
        keycache->block_mem= 0;
339
336
      }
340
337
      if (blocks < 8)
341
338
      {
342
 
        my_errno= ENOMEM;
 
339
        errno= ENOMEM;
343
340
        my_error(EE_OUTOFMEMORY, MYF(0), blocks * keycache->key_cache_block_size);
344
341
        goto err;
345
342
      }
353
350
    keycache->hash_link_root= (HASH_LINK*) ((char*) keycache->hash_root +
354
351
                                            ALIGN_SIZE((sizeof(HASH_LINK*) *
355
352
                                                        keycache->hash_entries)));
356
 
    bzero((uchar*) keycache->block_root,
357
 
          keycache->disk_blocks * sizeof(BLOCK_LINK));
358
 
    bzero((uchar*) keycache->hash_root,
359
 
          keycache->hash_entries * sizeof(HASH_LINK*));
360
 
    bzero((uchar*) keycache->hash_link_root,
361
 
          keycache->hash_links * sizeof(HASH_LINK));
 
353
    memset(keycache->block_root, 0,
 
354
           keycache->disk_blocks * sizeof(BLOCK_LINK));
 
355
    memset(keycache->hash_root, 0,
 
356
           keycache->hash_entries * sizeof(HASH_LINK*));
 
357
    memset(keycache->hash_link_root, 0,
 
358
           keycache->hash_links * sizeof(HASH_LINK));
362
359
    keycache->hash_links_used= 0;
363
360
    keycache->free_hash_list= NULL;
364
361
    keycache->blocks_used= keycache->blocks_changed= 0;
383
380
 
384
381
    keycache->waiting_for_hash_link.last_thread= NULL;
385
382
    keycache->waiting_for_block.last_thread= NULL;
386
 
    bzero((uchar*) keycache->changed_blocks,
387
 
          sizeof(keycache->changed_blocks[0]) * CHANGED_BLOCKS_HASH);
388
 
    bzero((uchar*) keycache->file_blocks,
389
 
          sizeof(keycache->file_blocks[0]) * CHANGED_BLOCKS_HASH);
 
383
    memset(keycache->changed_blocks, 0,
 
384
           sizeof(keycache->changed_blocks[0]) * CHANGED_BLOCKS_HASH);
 
385
    memset(keycache->file_blocks, 0,
 
386
           sizeof(keycache->file_blocks[0]) * CHANGED_BLOCKS_HASH);
390
387
  }
391
388
  else
392
389
  {
398
395
  return((int) keycache->disk_blocks);
399
396
 
400
397
err:
401
 
  error= my_errno;
 
398
  error= errno;
402
399
  keycache->disk_blocks= 0;
403
400
  keycache->blocks=  0;
404
401
  if (keycache->block_mem)
408
405
  }
409
406
  if (keycache->block_root)
410
407
  {
411
 
    my_free((uchar*) keycache->block_root, MYF(0));
 
408
    free((unsigned char*) keycache->block_root);
412
409
    keycache->block_root= NULL;
413
410
  }
414
 
  my_errno= error;
 
411
  errno= error;
415
412
  keycache->can_be_used= 0;
416
413
  return(0);
417
414
}
446
443
    (when cnt_for_resize=0).
447
444
*/
448
445
 
449
 
int resize_key_cache(KEY_CACHE *keycache, uint key_cache_block_size,
450
 
                     size_t use_mem, uint division_limit,
451
 
                     uint age_threshold)
 
446
int resize_key_cache(KEY_CACHE *keycache, uint32_t key_cache_block_size,
 
447
                     size_t use_mem, uint32_t division_limit,
 
448
                     uint32_t age_threshold)
452
449
{
453
450
  int blocks;
454
451
 
472
469
  */
473
470
  while (keycache->in_resize)
474
471
  {
475
 
    /* purecov: begin inspected */
476
472
    wait_on_queue(&keycache->resize_queue, &keycache->cache_lock);
477
 
    /* purecov: end */
478
473
  }
479
474
 
480
475
  /*
580
575
    age_threshold.
581
576
*/
582
577
 
583
 
void change_key_cache_param(KEY_CACHE *keycache, uint division_limit,
584
 
                            uint age_threshold)
 
578
static void change_key_cache_param(KEY_CACHE *keycache, uint32_t division_limit,
 
579
                            uint32_t age_threshold)
585
580
{
586
581
  keycache_pthread_mutex_lock(&keycache->cache_lock);
587
582
  if (division_limit)
607
602
    none
608
603
*/
609
604
 
610
 
void end_key_cache(KEY_CACHE *keycache, my_bool cleanup)
 
605
void end_key_cache(KEY_CACHE *keycache, bool cleanup)
611
606
{
612
607
  if (!keycache->key_cache_inited)
613
608
    return;
618
613
    {
619
614
      free(keycache->block_mem);
620
615
      keycache->block_mem= NULL;
621
 
      my_free((uchar*) keycache->block_root, MYF(0));
 
616
      free((unsigned char*) keycache->block_root);
622
617
      keycache->block_root= NULL;
623
618
    }
624
619
    keycache->disk_blocks= -1;
808
803
/*
809
804
  Unlink a block from the chain of dirty/clean blocks
810
805
*/
811
 
static inline void unlink_changed(BLOCK_LINK *block)
 
806
static void unlink_changed(BLOCK_LINK *block)
812
807
{
813
808
  assert(block->prev_changed && *block->prev_changed == block);
814
809
  if (block->next_changed)
823
818
  Link a block into the chain of dirty/clean blocks
824
819
*/
825
820
 
826
 
static inline void link_changed(BLOCK_LINK *block, BLOCK_LINK **phead)
 
821
static void link_changed(BLOCK_LINK *block, BLOCK_LINK **phead)
827
822
{
828
823
  assert(!block->next_changed);
829
824
  assert(!block->prev_changed);
861
856
 
862
857
static void link_to_file_list(KEY_CACHE *keycache,
863
858
                              BLOCK_LINK *block, int file,
864
 
                              my_bool unlink_block)
 
859
                              bool unlink_block)
865
860
{
866
861
  assert(block->status & BLOCK_IN_USE);
867
862
  assert(block->hash_link && block->hash_link->block == block);
955
950
    not linked in the LRU ring.
956
951
*/
957
952
 
958
 
static void link_block(KEY_CACHE *keycache, BLOCK_LINK *block, my_bool hot,
959
 
                       my_bool at_end)
 
953
static void link_block(KEY_CACHE *keycache, BLOCK_LINK *block, bool hot,
 
954
                       bool at_end)
960
955
{
961
956
  BLOCK_LINK *ins;
962
957
  BLOCK_LINK **pins;
1149
1144
  assert(!block->prev_used);
1150
1145
  if (! --block->requests)
1151
1146
  {
1152
 
    my_bool hot;
 
1147
    bool hot;
1153
1148
    if (block->hits_left)
1154
1149
      block->hits_left--;
1155
1150
    hot= !block->hits_left && at_end &&
1160
1155
        keycache->warm_blocks--;
1161
1156
      block->temperature= BLOCK_HOT;
1162
1157
    }
1163
 
    link_block(keycache, block, hot, (my_bool)at_end);
 
1158
    link_block(keycache, block, hot, (bool)at_end);
1164
1159
    block->last_hit_time= keycache->keycache_time;
1165
1160
    keycache->keycache_time++;
1166
1161
    /*
1399
1394
*/
1400
1395
 
1401
1396
static BLOCK_LINK *find_key_block(KEY_CACHE *keycache,
1402
 
                                  File file, my_off_t filepos,
 
1397
                                  int file, my_off_t filepos,
1403
1398
                                  int init_hits_left,
1404
1399
                                  int wrmode, int *page_st)
1405
1400
{
1774
1769
        {
1775
1770
          /* There are some never used blocks, take first of them */
1776
1771
          assert(keycache->blocks_used <
1777
 
                      (ulong) keycache->disk_blocks);
 
1772
                      (uint32_t) keycache->disk_blocks);
1778
1773
          block= &keycache->block_root[keycache->blocks_used];
1779
1774
          block->buffer= ADD_TO_PTR(keycache->block_mem,
1780
 
                                    ((ulong) keycache->blocks_used*
 
1775
                                    ((uint32_t) keycache->blocks_used*
1781
1776
                                     keycache->key_cache_block_size),
1782
 
                                    uchar*);
 
1777
                                    unsigned char*);
1783
1778
          keycache->blocks_used++;
1784
1779
          assert(!block->next_used);
1785
1780
        }
2098
2093
*/
2099
2094
 
2100
2095
static void read_block(KEY_CACHE *keycache,
2101
 
                       BLOCK_LINK *block, uint read_length,
2102
 
                       uint min_length, my_bool primary)
 
2096
                       BLOCK_LINK *block, uint32_t read_length,
 
2097
                       uint32_t min_length, bool primary)
2103
2098
{
2104
 
  uint got_length;
 
2099
  uint32_t got_length;
2105
2100
 
2106
2101
  /* On entry cache_lock is locked */
2107
2102
 
2197
2192
    have to be a multiple of key_cache_block_size;
2198
2193
*/
2199
2194
 
2200
 
uchar *key_cache_read(KEY_CACHE *keycache,
2201
 
                      File file, my_off_t filepos, int level,
2202
 
                      uchar *buff, uint length,
2203
 
                      uint block_length __attribute__((unused)),
2204
 
                      int return_buffer __attribute__((unused)))
 
2195
unsigned char *key_cache_read(KEY_CACHE *keycache,
 
2196
                      int file, my_off_t filepos, int level,
 
2197
                      unsigned char *buff, uint32_t length,
 
2198
                      uint32_t block_length,
 
2199
                      int return_buffer)
2205
2200
{
2206
 
  my_bool locked_and_incremented= false;
 
2201
  (void)block_length;
 
2202
  (void)return_buffer;
 
2203
  bool locked_and_incremented= false;
2207
2204
  int error=0;
2208
 
  uchar *start= buff;
 
2205
  unsigned char *start= buff;
2209
2206
 
2210
2207
  if (keycache->key_cache_inited)
2211
2208
  {
2212
2209
    /* Key cache is used */
2213
2210
    register BLOCK_LINK *block;
2214
 
    uint read_length;
2215
 
    uint offset;
2216
 
    uint status;
 
2211
    uint32_t read_length;
 
2212
    uint32_t offset;
 
2213
    uint32_t status;
2217
2214
    int page_st;
2218
2215
 
2219
2216
    /*
2270
2267
        */
2271
2268
        keycache->global_cache_read++;
2272
2269
        keycache_pthread_mutex_unlock(&keycache->cache_lock);
2273
 
        error= (pread(file, (uchar*) buff, read_length, filepos + offset) == 0);
 
2270
        error= (pread(file, (unsigned char*) buff, read_length, filepos + offset) == 0);
2274
2271
        keycache_pthread_mutex_lock(&keycache->cache_lock);
2275
2272
        goto next_block;
2276
2273
      }
2281
2278
          /* The requested page is to be read into the block buffer */
2282
2279
          read_block(keycache, block,
2283
2280
                     keycache->key_cache_block_size, read_length+offset,
2284
 
                     (my_bool)(page_st == PAGE_TO_BE_READ));
 
2281
                     (bool)(page_st == PAGE_TO_BE_READ));
2285
2282
          /*
2286
2283
            A secondary request must now have the block assigned to the
2287
2284
            requested file block. It does not hurt to check it for
2299
2296
            this could only happen if we are using a file with
2300
2297
            small key blocks and are trying to read outside the file
2301
2298
          */
2302
 
          my_errno= -1;
 
2299
          errno= -1;
2303
2300
          block->status|= BLOCK_ERROR;
2304
2301
        }
2305
2302
      }
2314
2311
#endif
2315
2312
 
2316
2313
          /* Copy data from the cache buffer */
2317
 
          if (!(read_length & 511))
2318
 
            bmove512(buff, block->buffer+offset, read_length);
2319
 
          else
2320
 
            memcpy(buff, block->buffer+offset, (size_t) read_length);
 
2314
          memcpy(buff, block->buffer+offset, (size_t) read_length);
2321
2315
 
2322
2316
#if !defined(SERIALIZED_READ_FROM_CACHE)
2323
2317
          keycache_pthread_mutex_lock(&keycache->cache_lock);
2357
2351
 
2358
2352
  if (locked_and_incremented)
2359
2353
    keycache_pthread_mutex_unlock(&keycache->cache_lock);
2360
 
  if (pread(file, (uchar*) buff, length, filepos))
 
2354
  if (!pread(file, (unsigned char*) buff, length, filepos))
2361
2355
    error= 1;
2362
2356
  if (locked_and_incremented)
2363
2357
    keycache_pthread_mutex_lock(&keycache->cache_lock);
2368
2362
    dec_counter_for_resize_op(keycache);
2369
2363
    keycache_pthread_mutex_unlock(&keycache->cache_lock);
2370
2364
  }
2371
 
  return(error ? (uchar*) 0 : start);
 
2365
  return(error ? (unsigned char*) 0 : start);
2372
2366
}
2373
2367
 
2374
2368
 
2393
2387
*/
2394
2388
 
2395
2389
int key_cache_insert(KEY_CACHE *keycache,
2396
 
                     File file, my_off_t filepos, int level,
2397
 
                     uchar *buff, uint length)
 
2390
                     int file, my_off_t filepos, int level,
 
2391
                     unsigned char *buff, uint32_t length)
2398
2392
{
2399
2393
  int error= 0;
2400
2394
 
2402
2396
  {
2403
2397
    /* Key cache is used */
2404
2398
    register BLOCK_LINK *block;
2405
 
    uint read_length;
2406
 
    uint offset;
 
2399
    uint32_t read_length;
 
2400
    uint32_t offset;
2407
2401
    int page_st;
2408
 
    my_bool locked_and_incremented= false;
 
2402
    bool locked_and_incremented= false;
2409
2403
 
2410
2404
    /*
2411
2405
      When the keycache is once initialized, we use the cache_lock to
2517
2511
#endif
2518
2512
 
2519
2513
          /* Copy data from buff */
2520
 
          if (!(read_length & 511))
2521
 
            bmove512(block->buffer+offset, buff, read_length);
2522
 
          else
2523
 
            memcpy(block->buffer+offset, buff, (size_t) read_length);
 
2514
          memcpy(block->buffer+offset, buff, (size_t) read_length);
2524
2515
 
2525
2516
#if !defined(SERIALIZED_READ_FROM_CACHE)
2526
2517
          keycache_pthread_mutex_lock(&keycache->cache_lock);
2630
2621
*/
2631
2622
 
2632
2623
int key_cache_write(KEY_CACHE *keycache,
2633
 
                    File file, my_off_t filepos, int level,
2634
 
                    uchar *buff, uint length,
2635
 
                    uint block_length  __attribute__((unused)),
 
2624
                    int file, my_off_t filepos, int level,
 
2625
                    unsigned char *buff, uint32_t length,
 
2626
                    uint32_t block_length,
2636
2627
                    int dont_write)
2637
2628
{
2638
 
  my_bool locked_and_incremented= false;
 
2629
  (void)block_length;
 
2630
  bool locked_and_incremented= false;
2639
2631
  int error=0;
2640
2632
 
2641
2633
  if (!dont_write)
2642
2634
  {
2643
 
    /* purecov: begin inspected */
2644
2635
    /* Not used in the server. */
2645
2636
    /* Force writing from buff into disk. */
2646
2637
    keycache->global_cache_w_requests++;
2647
2638
    keycache->global_cache_write++;
2648
2639
    if (pwrite(file, buff, length, filepos) == 0)
2649
2640
      return(1);
2650
 
    /* purecov: end */
2651
2641
  }
2652
2642
 
2653
2643
  if (keycache->key_cache_inited)
2654
2644
  {
2655
2645
    /* Key cache is used */
2656
2646
    register BLOCK_LINK *block;
2657
 
    uint read_length;
2658
 
    uint offset;
 
2647
    uint32_t read_length;
 
2648
    uint32_t offset;
2659
2649
    int page_st;
2660
2650
 
2661
2651
    /*
2715
2705
          /* Used in the server. */
2716
2706
          keycache->global_cache_write++;
2717
2707
          keycache_pthread_mutex_unlock(&keycache->cache_lock);
2718
 
          if (pwrite(file, (uchar*) buff, read_length, filepos + offset) == 0)
 
2708
          if (pwrite(file, (unsigned char*) buff, read_length, filepos + offset) == 0)
2719
2709
            error=1;
2720
2710
          keycache_pthread_mutex_lock(&keycache->cache_lock);
2721
2711
        }
2810
2800
#if !defined(SERIALIZED_READ_FROM_CACHE)
2811
2801
        keycache_pthread_mutex_unlock(&keycache->cache_lock);
2812
2802
#endif
2813
 
        if (!(read_length & 511))
2814
 
          bmove512(block->buffer+offset, buff, read_length);
2815
 
        else
2816
 
          memcpy(block->buffer+offset, buff, (size_t) read_length);
 
2803
        memcpy(block->buffer+offset, buff, (size_t) read_length);
2817
2804
 
2818
2805
#if !defined(SERIALIZED_READ_FROM_CACHE)
2819
2806
        keycache_pthread_mutex_lock(&keycache->cache_lock);
2882
2869
    keycache->global_cache_write++;
2883
2870
    if (locked_and_incremented)
2884
2871
      keycache_pthread_mutex_unlock(&keycache->cache_lock);
2885
 
    if (pwrite(file, (uchar*) buff, length, filepos) == 0)
 
2872
    if (pwrite(file, (unsigned char*) buff, length, filepos) == 0)
2886
2873
      error=1;
2887
2874
    if (locked_and_incremented)
2888
2875
      keycache_pthread_mutex_lock(&keycache->cache_lock);
3055
3042
*/
3056
3043
 
3057
3044
static int flush_cached_blocks(KEY_CACHE *keycache,
3058
 
                               File file, BLOCK_LINK **cache,
 
3045
                               int file, BLOCK_LINK **cache,
3059
3046
                               BLOCK_LINK **end,
3060
3047
                               enum flush_type type)
3061
3048
{
3062
3049
  int error;
3063
3050
  int last_errno= 0;
3064
 
  uint count= (uint) (end-cache);
 
3051
  uint32_t count= (uint) (end-cache);
3065
3052
 
3066
3053
  /* Don't lock the cache during the flush */
3067
3054
  keycache_pthread_mutex_unlock(&keycache->cache_lock);
3069
3056
     As all blocks referred in 'cache' are marked by BLOCK_IN_FLUSH
3070
3057
     we are guarunteed no thread will change them
3071
3058
  */
3072
 
  my_qsort((uchar*) cache, count, sizeof(*cache), (qsort_cmp) cmp_sec_link);
 
3059
  my_qsort((unsigned char*) cache, count, sizeof(*cache), (qsort_cmp) cmp_sec_link);
3073
3060
 
3074
3061
  keycache_pthread_mutex_lock(&keycache->cache_lock);
3075
3062
  /*
3181
3168
*/
3182
3169
 
3183
3170
static int flush_key_blocks_int(KEY_CACHE *keycache,
3184
 
                                File file, enum flush_type type)
 
3171
                                int file, enum flush_type type)
3185
3172
{
3186
3173
  BLOCK_LINK *cache_buff[FLUSH_CACHE],**cache;
3187
3174
  int last_errno= 0;
3193
3180
  {
3194
3181
    /* Key cache exists and flush is not disabled */
3195
3182
    int error= 0;
3196
 
    uint count= FLUSH_CACHE;
 
3183
    uint32_t count= FLUSH_CACHE;
3197
3184
    BLOCK_LINK **pos,**end;
3198
3185
    BLOCK_LINK *first_in_switch= NULL;
3199
3186
    BLOCK_LINK *last_in_flush;
3200
3187
    BLOCK_LINK *last_for_update;
 
3188
    BLOCK_LINK *last_in_switch;
3201
3189
    BLOCK_LINK *block, *next;
3202
3190
 
3203
3191
    if (type != FLUSH_IGNORE_CHANGED)
3224
3212
        changed blocks appear while we need to wait for something.
3225
3213
      */
3226
3214
      if ((count > FLUSH_CACHE) &&
3227
 
          !(cache= (BLOCK_LINK**) my_malloc(sizeof(BLOCK_LINK*)*count,
3228
 
                                            MYF(0))))
 
3215
          !(cache= (BLOCK_LINK**) malloc(sizeof(BLOCK_LINK*)*count)))
3229
3216
        cache= cache_buff;
3230
3217
      /*
3231
3218
        After a restart there could be more changed blocks than now.
3440
3427
 
3441
3428
    if (! (type == FLUSH_KEEP || type == FLUSH_FORCE_WRITE))
3442
3429
    {
3443
 
      BLOCK_LINK *last_for_update= NULL;
3444
 
      BLOCK_LINK *last_in_switch= NULL;
3445
 
      uint total_found= 0;
3446
 
      uint found;
 
3430
      last_for_update= NULL;
 
3431
      last_in_switch= NULL;
 
3432
      uint32_t total_found= 0;
 
3433
      uint32_t found;
3447
3434
 
3448
3435
      /*
3449
3436
        Finally free all clean blocks for this file.
3478
3465
            if (!(block->status & (BLOCK_IN_EVICTION | BLOCK_IN_SWITCH |
3479
3466
                                   BLOCK_REASSIGNED)))
3480
3467
            {
3481
 
              struct st_hash_link *next_hash_link;
3482
 
              my_off_t            next_diskpos;
3483
 
              File                next_file;
3484
 
              uint                next_status;
3485
 
              uint                hash_requests;
 
3468
              struct st_hash_link *next_hash_link= NULL;
 
3469
              my_off_t            next_diskpos= 0;
 
3470
              int                next_file= 0;
 
3471
              uint32_t                next_status= 0;
 
3472
              uint32_t                hash_requests= 0;
3486
3473
 
3487
3474
              total_found++;
3488
3475
              found++;
3582
3569
 
3583
3570
err:
3584
3571
  if (cache != cache_buff)
3585
 
    my_free((uchar*) cache, MYF(0));
 
3572
    free((unsigned char*) cache);
3586
3573
  if (last_errno)
3587
3574
    errno=last_errno;                /* Return first error */
3588
3575
  return(last_errno != 0);
3605
3592
*/
3606
3593
 
3607
3594
int flush_key_blocks(KEY_CACHE *keycache,
3608
 
                     File file, enum flush_type type)
 
3595
                     int file, enum flush_type type)
3609
3596
{
3610
3597
  int res= 0;
3611
3598
 
3660
3647
static int flush_all_key_blocks(KEY_CACHE *keycache)
3661
3648
{
3662
3649
  BLOCK_LINK    *block;
3663
 
  uint          total_found;
3664
 
  uint          found;
3665
 
  uint          idx;
 
3650
  uint32_t          total_found;
 
3651
  uint32_t          found;
 
3652
  uint32_t          idx;
3666
3653
 
3667
3654
  do
3668
3655
  {
3753
3740
 
3754
3741
  SYNOPSIS
3755
3742
    reset_key_cache_counters()
3756
 
    name       the name of a key cache
3757
 
    key_cache  pointer to the key kache to be reset
3758
3743
 
3759
3744
  DESCRIPTION
3760
 
   This procedure is used by process_key_caches() to reset the counters of all
3761
 
   currently used key caches, both the default one and the named ones.
 
3745
   This procedure is used by process_key_caches() to reset the key_cache.
3762
3746
 
3763
3747
  RETURN
3764
3748
    0 on success (always because it can't fail)
3765
3749
*/
3766
3750
 
3767
 
int reset_key_cache_counters(const char *name __attribute__((unused)),
3768
 
                             KEY_CACHE *key_cache)
 
3751
void reset_key_cache_counters()
3769
3752
{
3770
 
  if (!key_cache->key_cache_inited)
3771
 
  {
3772
 
    return(0);
3773
 
  }
3774
 
  key_cache->global_blocks_changed= 0;   /* Key_blocks_not_flushed */
3775
 
  key_cache->global_cache_r_requests= 0; /* Key_read_requests */
3776
 
  key_cache->global_cache_read= 0;       /* Key_reads */
3777
 
  key_cache->global_cache_w_requests= 0; /* Key_write_requests */
3778
 
  key_cache->global_cache_write= 0;      /* Key_writes */
3779
 
  return(0);
 
3753
  dflt_key_cache->global_blocks_changed= 0;   /* Key_blocks_not_flushed */
 
3754
  dflt_key_cache->global_cache_r_requests= 0; /* Key_read_requests */
 
3755
  dflt_key_cache->global_cache_read= 0;       /* Key_reads */
 
3756
  dflt_key_cache->global_cache_w_requests= 0; /* Key_write_requests */
 
3757
  dflt_key_cache->global_cache_write= 0;      /* Key_writes */
3780
3758
}
3781
3759
 
3782
3760
#if defined(KEYCACHE_TIMEOUT)
3783
3761
 
 
3762
 
 
3763
static inline
 
3764
unsigned int hash_link_number(HASH_LINK *hash_link, KEY_CACHE *keycache)
 
3765
{
 
3766
  return ((unsigned int) (((char*)hash_link-(char *) keycache->hash_link_root)/
 
3767
                  sizeof(HASH_LINK)));
 
3768
}
 
3769
 
 
3770
static inline
 
3771
unsigned int block_number(BLOCK_LINK *block, KEY_CACHE *keycache)
 
3772
{
 
3773
  return ((unsigned int) (((char*)block-(char *)keycache->block_root)/
 
3774
                  sizeof(BLOCK_LINK)));
 
3775
}
 
3776
 
 
3777
 
3784
3778
#define KEYCACHE_DUMP_FILE  "keycache_dump.txt"
3785
3779
#define MAX_QUEUE_LEN  100
3786
3780
 
3793
3787
  BLOCK_LINK *block;
3794
3788
  HASH_LINK *hash_link;
3795
3789
  KEYCACHE_PAGE *page;
3796
 
  uint i;
 
3790
  uint32_t i;
3797
3791
 
3798
3792
  fprintf(keycache_dump_file, "thread:%u\n", thread->id);
3799
3793
 
3807
3801
      page= (KEYCACHE_PAGE *) thread->opt_info;
3808
3802
      fprintf(keycache_dump_file,
3809
3803
              "thread:%u, (file,filepos)=(%u,%lu)\n",
3810
 
              thread->id,(uint) page->file,(ulong) page->filepos);
 
3804
              thread->id,(uint) page->file,(uint32_t) page->filepos);
3811
3805
      if (++i == MAX_QUEUE_LEN)
3812
3806
        break;
3813
3807
    }
3822
3816
      thread=thread->next;
3823
3817
      hash_link= (HASH_LINK *) thread->opt_info;
3824
3818
      fprintf(keycache_dump_file,
3825
 
        "thread:%u hash_link:%u (file,filepos)=(%u,%lu)\n",
3826
 
        thread->id, (uint) HASH_LINK_NUMBER(hash_link),
3827
 
        (uint) hash_link->file,(ulong) hash_link->diskpos);
 
3819
              "thread:%u hash_link:%u (file,filepos)=(%u,%u)\n",
 
3820
              thread->id, (uint) hash_link_number(hash_link, keycache),
 
3821
              (uint) hash_link->file,(uint32_t) hash_link->diskpos);
3828
3822
      if (++i == MAX_QUEUE_LEN)
3829
3823
        break;
3830
3824
    }
3836
3830
    block= &keycache->block_root[i];
3837
3831
    hash_link= block->hash_link;
3838
3832
    fprintf(keycache_dump_file,
3839
 
            "block:%u hash_link:%d status:%x #requests=%u waiting_for_readers:%d\n",
3840
 
            i, (int) (hash_link ? HASH_LINK_NUMBER(hash_link) : -1),
3841
 
            block->status, block->requests, block->condvar ? 1 : 0);
 
3833
            "block:%u hash_link:%d status:%x #requests=%u "
 
3834
            "waiting_for_readers:%d\n",
 
3835
            i, (int) (hash_link ? hash_link_number(hash_link, keycache) : -1),
 
3836
            block->status, block->requests, block->condvar ? 1 : 0);
3842
3837
    for (j=0 ; j < 2; j++)
3843
3838
    {
3844
3839
      KEYCACHE_WQUEUE *wqueue=&block->wqueue[j];
3866
3861
    {
3867
3862
      block= block->next_used;
3868
3863
      fprintf(keycache_dump_file,
3869
 
              "block:%u, ", BLOCK_NUMBER(block));
 
3864
              "block:%u, ", block_number(block, keycache));
3870
3865
    }
3871
3866
    while (block != keycache->used_last);
3872
3867
  }