~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to plugin/myisam/mf_keycache.cc

  • Committer: Brian Aker
  • Date: 2010-02-10 18:04:24 UTC
  • mfrom: (1286.1.5 build)
  • Revision ID: brian@gaz-20100210180424-03ypoyifmlc2lgcp
Merge of Brian/Padraig

Show diffs side-by-side

added added

removed removed

Lines of Context:
101
101
  I/O finished.
102
102
*/
103
103
 
104
 
#include <drizzled/global.h>
105
 
#include <mysys/mysys_err.h>
106
 
#include <mysys/my_sys.h>
107
 
#include <keycache.h>
108
 
#include <mystrings/m_string.h>
109
 
#include <mysys/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
using namespace drizzled;
 
114
 
 
115
static void change_key_cache_param(KEY_CACHE *keycache, uint32_t division_limit,
 
116
                            uint32_t age_threshold);
 
117
 
113
118
/*
114
119
  Some compilation flags have been added specifically for this module
115
120
  to control the following:
143
148
/* types of condition variables */
144
149
#define  COND_FOR_REQUESTED 0
145
150
#define  COND_FOR_SAVED     1
146
 
#define  COND_FOR_READERS   2
147
151
 
148
152
typedef pthread_cond_t KEYCACHE_CONDVAR;
149
153
 
151
155
struct st_keycache_page
152
156
{
153
157
  int file;               /* file to which the page belongs to  */
154
 
  my_off_t filepos;       /* position of the page in the file   */
 
158
  internal::my_off_t filepos;       /* position of the page in the file   */
155
159
};
156
160
 
157
161
/* element in the chain of a hash table bucket */
159
163
{
160
164
  struct st_hash_link *next, **prev; /* to connect links in the same bucket  */
161
165
  struct st_block_link *block;       /* reference to the block for the page: */
162
 
  File file;                         /* from such a file                     */
163
 
  my_off_t diskpos;                  /* with such an offset                  */
164
 
  uint requests;                     /* number of requests for the page      */
 
166
  int file;                         /* from such a file                     */
 
167
  internal::my_off_t diskpos;                  /* with such an offset                  */
 
168
  uint32_t requests;                     /* number of requests for the page      */
165
169
};
166
170
 
167
171
/* simple states of a block */
193
197
    *next_changed, **prev_changed; /* for lists of file dirty/clean blocks   */
194
198
  struct st_hash_link *hash_link; /* backward ptr to referring hash_link     */
195
199
  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                              */
 
200
  uint32_t requests;          /* number of requests for the block                */
 
201
  unsigned char *buffer;           /* buffer for the block page                       */
 
202
  uint32_t offset;            /* beginning of modified data in the buffer        */
 
203
  uint32_t length;            /* end of data in the buffer                       */
 
204
  uint32_t status;            /* state of the block                              */
201
205
  enum BLOCK_TEMPERATURE temperature; /* block temperature: cold, warm, hot */
202
 
  uint hits_left;         /* number of hits left until promotion             */
 
206
  uint32_t hits_left;         /* number of hits left until promotion             */
203
207
  uint64_t last_hit_time; /* timestamp of the last hit                      */
204
208
  KEYCACHE_CONDVAR *condvar; /* condition variable for 'no readers' event    */
205
209
};
220
224
                                     (uint32_t) (f)) & (keycache->hash_entries-1))
221
225
#define FILE_HASH(f)                 ((uint) (f) & (CHANGED_BLOCKS_HASH-1))
222
226
 
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
227
 
228
228
#ifdef KEYCACHE_TIMEOUT
229
229
static int keycache_pthread_cond_wait(pthread_cond_t *cond,
236
236
#define keycache_pthread_mutex_unlock pthread_mutex_unlock
237
237
#define keycache_pthread_cond_signal pthread_cond_signal
238
238
 
239
 
static inline uint next_power(uint value)
 
239
static inline uint32_t next_power(uint32_t value)
240
240
{
241
 
  return (uint) my_round_up_to_next_power((uint32_t) value) << 1;
 
241
  return my_round_up_to_next_power(value) << 1;
242
242
}
243
243
 
244
244
 
267
267
 
268
268
*/
269
269
 
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)
 
270
int init_key_cache(KEY_CACHE *keycache, uint32_t key_cache_block_size,
 
271
                   size_t use_mem, uint32_t division_limit,
 
272
                   uint32_t age_threshold)
273
273
{
274
274
  uint32_t blocks, hash_links;
275
275
  size_t length;
325
325
             ((size_t) blocks * keycache->key_cache_block_size) > use_mem)
326
326
        blocks--;
327
327
      /* Allocate memory for cache page buffers */
328
 
      if ((keycache->block_mem= malloc((size_t) blocks * keycache->key_cache_block_size)))
 
328
      if ((keycache->block_mem= (unsigned char *)malloc((size_t) blocks * keycache->key_cache_block_size)))
329
329
      {
330
330
        /*
331
331
          Allocate memory for blocks, hash_links and hash entries;
332
332
          For each block 2 hash links are allocated
333
333
        */
334
 
        if ((keycache->block_root= (BLOCK_LINK*) my_malloc(length,
335
 
                                                           MYF(0))))
 
334
        if ((keycache->block_root= (BLOCK_LINK*) malloc(length)))
336
335
          break;
337
336
        free(keycache->block_mem);
338
337
        keycache->block_mem= 0;
339
338
      }
340
339
      if (blocks < 8)
341
340
      {
342
 
        my_errno= ENOMEM;
 
341
        errno= ENOMEM;
343
342
        my_error(EE_OUTOFMEMORY, MYF(0), blocks * keycache->key_cache_block_size);
344
343
        goto err;
345
344
      }
390
389
  }
391
390
  else
392
391
  {
393
 
    /* key_buffer_size is specified too small. Disable the cache. */
 
392
    /* myisam_key_buffer_size is specified too small. Disable the cache. */
394
393
    keycache->can_be_used= 0;
395
394
  }
396
395
 
398
397
  return((int) keycache->disk_blocks);
399
398
 
400
399
err:
401
 
  error= my_errno;
 
400
  error= errno;
402
401
  keycache->disk_blocks= 0;
403
402
  keycache->blocks=  0;
404
403
  if (keycache->block_mem)
408
407
  }
409
408
  if (keycache->block_root)
410
409
  {
411
 
    my_free((uchar*) keycache->block_root, MYF(0));
 
410
    free((unsigned char*) keycache->block_root);
412
411
    keycache->block_root= NULL;
413
412
  }
414
 
  my_errno= error;
 
413
  errno= error;
415
414
  keycache->can_be_used= 0;
416
415
  return(0);
417
416
}
446
445
    (when cnt_for_resize=0).
447
446
*/
448
447
 
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)
 
448
int resize_key_cache(KEY_CACHE *keycache, uint32_t key_cache_block_size,
 
449
                     size_t use_mem, uint32_t division_limit,
 
450
                     uint32_t age_threshold)
452
451
{
453
452
  int blocks;
454
453
 
472
471
  */
473
472
  while (keycache->in_resize)
474
473
  {
475
 
    /* purecov: begin inspected */
476
474
    wait_on_queue(&keycache->resize_queue, &keycache->cache_lock);
477
 
    /* purecov: end */
478
475
  }
479
476
 
480
477
  /*
580
577
    age_threshold.
581
578
*/
582
579
 
583
 
void change_key_cache_param(KEY_CACHE *keycache, uint division_limit,
584
 
                            uint age_threshold)
 
580
static void change_key_cache_param(KEY_CACHE *keycache, uint32_t division_limit,
 
581
                            uint32_t age_threshold)
585
582
{
586
583
  keycache_pthread_mutex_lock(&keycache->cache_lock);
587
584
  if (division_limit)
618
615
    {
619
616
      free(keycache->block_mem);
620
617
      keycache->block_mem= NULL;
621
 
      my_free((uchar*) keycache->block_root, MYF(0));
 
618
      free((unsigned char*) keycache->block_root);
622
619
      keycache->block_root= NULL;
623
620
    }
624
621
    keycache->disk_blocks= -1;
653
650
*/
654
651
 
655
652
static void link_into_queue(KEYCACHE_WQUEUE *wqueue,
656
 
                                   struct st_my_thread_var *thread)
 
653
                            internal::st_my_thread_var *thread)
657
654
{
658
 
  struct st_my_thread_var *last;
 
655
  internal::st_my_thread_var *last;
659
656
 
660
657
  assert(!thread->next && !thread->prev);
661
658
  if (! (last= wqueue->last_thread))
690
687
*/
691
688
 
692
689
static void unlink_from_queue(KEYCACHE_WQUEUE *wqueue,
693
 
                                     struct st_my_thread_var *thread)
 
690
                                     internal::st_my_thread_var *thread)
694
691
{
695
692
  assert(thread->next && thread->prev);
696
693
  if (thread->next == thread)
701
698
    thread->next->prev= thread->prev;
702
699
    *thread->prev=thread->next;
703
700
    if (wqueue->last_thread == thread)
704
 
      wqueue->last_thread= STRUCT_PTR(struct st_my_thread_var, next,
 
701
      wqueue->last_thread= STRUCT_PTR(internal::st_my_thread_var, next,
705
702
                                      thread->prev);
706
703
  }
707
704
  thread->next= NULL;
735
732
static void wait_on_queue(KEYCACHE_WQUEUE *wqueue,
736
733
                          pthread_mutex_t *mutex)
737
734
{
738
 
  struct st_my_thread_var *last;
739
 
  struct st_my_thread_var *thread= my_thread_var;
 
735
  internal::st_my_thread_var *last;
 
736
  internal::st_my_thread_var *thread= my_thread_var;
740
737
 
741
738
  /* Add to queue. */
742
739
  assert(!thread->next);
780
777
 
781
778
static void release_whole_queue(KEYCACHE_WQUEUE *wqueue)
782
779
{
783
 
  struct st_my_thread_var *last;
784
 
  struct st_my_thread_var *next;
785
 
  struct st_my_thread_var *thread;
 
780
  internal::st_my_thread_var *last;
 
781
  internal::st_my_thread_var *next;
 
782
  internal::st_my_thread_var *thread;
786
783
 
787
784
  /* Queue may be empty. */
788
785
  if (!(last= wqueue->last_thread))
808
805
/*
809
806
  Unlink a block from the chain of dirty/clean blocks
810
807
*/
811
 
static inline void unlink_changed(BLOCK_LINK *block)
 
808
static void unlink_changed(BLOCK_LINK *block)
812
809
{
813
810
  assert(block->prev_changed && *block->prev_changed == block);
814
811
  if (block->next_changed)
823
820
  Link a block into the chain of dirty/clean blocks
824
821
*/
825
822
 
826
 
static inline void link_changed(BLOCK_LINK *block, BLOCK_LINK **phead)
 
823
static void link_changed(BLOCK_LINK *block, BLOCK_LINK **phead)
827
824
{
828
825
  assert(!block->next_changed);
829
826
  assert(!block->prev_changed);
970
967
  if (!hot && keycache->waiting_for_block.last_thread)
971
968
  {
972
969
    /* Signal that in the LRU warm sub-chain an available block has appeared */
973
 
    struct st_my_thread_var *last_thread=
 
970
    internal::st_my_thread_var *last_thread=
974
971
                               keycache->waiting_for_block.last_thread;
975
 
    struct st_my_thread_var *first_thread= last_thread->next;
976
 
    struct st_my_thread_var *next_thread= first_thread;
 
972
    internal::st_my_thread_var *first_thread= last_thread->next;
 
973
    internal::st_my_thread_var *next_thread= first_thread;
977
974
    HASH_LINK *hash_link= (HASH_LINK *) first_thread->opt_info;
978
 
    struct st_my_thread_var *thread;
 
975
    internal::st_my_thread_var *thread;
979
976
    do
980
977
    {
981
978
      thread= next_thread;
1218
1215
static void wait_for_readers(KEY_CACHE *keycache,
1219
1216
                             BLOCK_LINK *block)
1220
1217
{
1221
 
  struct st_my_thread_var *thread= my_thread_var;
 
1218
  internal::st_my_thread_var *thread= my_thread_var;
1222
1219
  assert(block->status & (BLOCK_READ | BLOCK_IN_USE));
1223
1220
  assert(!(block->status & (BLOCK_ERROR | BLOCK_IN_FLUSH |
1224
1221
                                 BLOCK_CHANGED)));
1267
1264
  if (keycache->waiting_for_hash_link.last_thread)
1268
1265
  {
1269
1266
    /* Signal that a free hash link has appeared */
1270
 
    struct st_my_thread_var *last_thread=
 
1267
    internal::st_my_thread_var *last_thread=
1271
1268
                               keycache->waiting_for_hash_link.last_thread;
1272
 
    struct st_my_thread_var *first_thread= last_thread->next;
1273
 
    struct st_my_thread_var *next_thread= first_thread;
 
1269
    internal::st_my_thread_var *first_thread= last_thread->next;
 
1270
    internal::st_my_thread_var *next_thread= first_thread;
1274
1271
    KEYCACHE_PAGE *first_page= (KEYCACHE_PAGE *) (first_thread->opt_info);
1275
 
    struct st_my_thread_var *thread;
 
1272
    internal::st_my_thread_var *thread;
1276
1273
 
1277
1274
    hash_link->file= first_page->file;
1278
1275
    hash_link->diskpos= first_page->filepos;
1308
1305
*/
1309
1306
 
1310
1307
static HASH_LINK *get_hash_link(KEY_CACHE *keycache,
1311
 
                                int file, my_off_t filepos)
 
1308
                                int file, internal::my_off_t filepos)
1312
1309
{
1313
1310
  register HASH_LINK *hash_link, **start;
1314
1311
 
1340
1337
    else
1341
1338
    {
1342
1339
      /* Wait for a free hash link */
1343
 
      struct st_my_thread_var *thread= my_thread_var;
 
1340
      internal::st_my_thread_var *thread= my_thread_var;
1344
1341
      KEYCACHE_PAGE page;
1345
1342
      page.file= file;
1346
1343
      page.filepos= filepos;
1399
1396
*/
1400
1397
 
1401
1398
static BLOCK_LINK *find_key_block(KEY_CACHE *keycache,
1402
 
                                  File file, my_off_t filepos,
 
1399
                                  int file, internal::my_off_t filepos,
1403
1400
                                  int init_hits_left,
1404
1401
                                  int wrmode, int *page_st)
1405
1402
{
1462
1459
 
1463
1460
    if (!block)
1464
1461
    {
1465
 
      struct st_my_thread_var *thread;
 
1462
      internal::st_my_thread_var *thread;
1466
1463
 
1467
1464
      /*
1468
1465
        The file block is not in the cache. We don't need it in the
1779
1776
          block->buffer= ADD_TO_PTR(keycache->block_mem,
1780
1777
                                    ((uint32_t) keycache->blocks_used*
1781
1778
                                     keycache->key_cache_block_size),
1782
 
                                    uchar*);
 
1779
                                    unsigned char*);
1783
1780
          keycache->blocks_used++;
1784
1781
          assert(!block->next_used);
1785
1782
        }
1823
1820
            it is marked BLOCK_IN_EVICTION.
1824
1821
          */
1825
1822
 
1826
 
          struct st_my_thread_var *thread= my_thread_var;
 
1823
          internal::st_my_thread_var *thread= my_thread_var;
1827
1824
          thread->opt_info= (void *) hash_link;
1828
1825
          link_into_queue(&keycache->waiting_for_block, thread);
1829
1826
          do
2098
2095
*/
2099
2096
 
2100
2097
static void read_block(KEY_CACHE *keycache,
2101
 
                       BLOCK_LINK *block, uint read_length,
2102
 
                       uint min_length, bool primary)
 
2098
                       BLOCK_LINK *block, uint32_t read_length,
 
2099
                       uint32_t min_length, bool primary)
2103
2100
{
2104
 
  uint got_length;
 
2101
  uint32_t got_length;
2105
2102
 
2106
2103
  /* On entry cache_lock is locked */
2107
2104
 
2197
2194
    have to be a multiple of key_cache_block_size;
2198
2195
*/
2199
2196
 
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)))
 
2197
unsigned char *key_cache_read(KEY_CACHE *keycache,
 
2198
                      int file, internal::my_off_t filepos, int level,
 
2199
                      unsigned char *buff, uint32_t length,
 
2200
                      uint32_t block_length,
 
2201
                      int return_buffer)
2205
2202
{
 
2203
  (void)block_length;
 
2204
  (void)return_buffer;
2206
2205
  bool locked_and_incremented= false;
2207
2206
  int error=0;
2208
 
  uchar *start= buff;
 
2207
  unsigned char *start= buff;
2209
2208
 
2210
2209
  if (keycache->key_cache_inited)
2211
2210
  {
2212
2211
    /* Key cache is used */
2213
2212
    register BLOCK_LINK *block;
2214
 
    uint read_length;
2215
 
    uint offset;
2216
 
    uint status;
 
2213
    uint32_t read_length;
 
2214
    uint32_t offset;
 
2215
    uint32_t status;
2217
2216
    int page_st;
2218
2217
 
2219
2218
    /*
2270
2269
        */
2271
2270
        keycache->global_cache_read++;
2272
2271
        keycache_pthread_mutex_unlock(&keycache->cache_lock);
2273
 
        error= (pread(file, (uchar*) buff, read_length, filepos + offset) == 0);
 
2272
        error= (pread(file, (unsigned char*) buff, read_length, filepos + offset) == 0);
2274
2273
        keycache_pthread_mutex_lock(&keycache->cache_lock);
2275
2274
        goto next_block;
2276
2275
      }
2299
2298
            this could only happen if we are using a file with
2300
2299
            small key blocks and are trying to read outside the file
2301
2300
          */
2302
 
          my_errno= -1;
 
2301
          errno= -1;
2303
2302
          block->status|= BLOCK_ERROR;
2304
2303
        }
2305
2304
      }
2354
2353
 
2355
2354
  if (locked_and_incremented)
2356
2355
    keycache_pthread_mutex_unlock(&keycache->cache_lock);
2357
 
  if (pread(file, (uchar*) buff, length, filepos))
 
2356
  if (!pread(file, (unsigned char*) buff, length, filepos))
2358
2357
    error= 1;
2359
2358
  if (locked_and_incremented)
2360
2359
    keycache_pthread_mutex_lock(&keycache->cache_lock);
2365
2364
    dec_counter_for_resize_op(keycache);
2366
2365
    keycache_pthread_mutex_unlock(&keycache->cache_lock);
2367
2366
  }
2368
 
  return(error ? (uchar*) 0 : start);
 
2367
  return(error ? (unsigned char*) 0 : start);
2369
2368
}
2370
2369
 
2371
2370
 
2390
2389
*/
2391
2390
 
2392
2391
int key_cache_insert(KEY_CACHE *keycache,
2393
 
                     File file, my_off_t filepos, int level,
2394
 
                     uchar *buff, uint length)
 
2392
                     int file, internal::my_off_t filepos, int level,
 
2393
                     unsigned char *buff, uint32_t length)
2395
2394
{
2396
2395
  int error= 0;
2397
2396
 
2399
2398
  {
2400
2399
    /* Key cache is used */
2401
2400
    register BLOCK_LINK *block;
2402
 
    uint read_length;
2403
 
    uint offset;
 
2401
    uint32_t read_length;
 
2402
    uint32_t offset;
2404
2403
    int page_st;
2405
2404
    bool locked_and_incremented= false;
2406
2405
 
2624
2623
*/
2625
2624
 
2626
2625
int key_cache_write(KEY_CACHE *keycache,
2627
 
                    File file, my_off_t filepos, int level,
2628
 
                    uchar *buff, uint length,
2629
 
                    uint block_length  __attribute__((unused)),
 
2626
                    int file, internal::my_off_t filepos, int level,
 
2627
                    unsigned char *buff, uint32_t length,
 
2628
                    uint32_t block_length,
2630
2629
                    int dont_write)
2631
2630
{
 
2631
  (void)block_length;
2632
2632
  bool locked_and_incremented= false;
2633
2633
  int error=0;
2634
2634
 
2635
2635
  if (!dont_write)
2636
2636
  {
2637
 
    /* purecov: begin inspected */
2638
2637
    /* Not used in the server. */
2639
2638
    /* Force writing from buff into disk. */
2640
2639
    keycache->global_cache_w_requests++;
2641
2640
    keycache->global_cache_write++;
2642
2641
    if (pwrite(file, buff, length, filepos) == 0)
2643
2642
      return(1);
2644
 
    /* purecov: end */
2645
2643
  }
2646
2644
 
2647
2645
  if (keycache->key_cache_inited)
2648
2646
  {
2649
2647
    /* Key cache is used */
2650
2648
    register BLOCK_LINK *block;
2651
 
    uint read_length;
2652
 
    uint offset;
 
2649
    uint32_t read_length;
 
2650
    uint32_t offset;
2653
2651
    int page_st;
2654
2652
 
2655
2653
    /*
2709
2707
          /* Used in the server. */
2710
2708
          keycache->global_cache_write++;
2711
2709
          keycache_pthread_mutex_unlock(&keycache->cache_lock);
2712
 
          if (pwrite(file, (uchar*) buff, read_length, filepos + offset) == 0)
 
2710
          if (pwrite(file, (unsigned char*) buff, read_length, filepos + offset) == 0)
2713
2711
            error=1;
2714
2712
          keycache_pthread_mutex_lock(&keycache->cache_lock);
2715
2713
        }
2873
2871
    keycache->global_cache_write++;
2874
2872
    if (locked_and_incremented)
2875
2873
      keycache_pthread_mutex_unlock(&keycache->cache_lock);
2876
 
    if (pwrite(file, (uchar*) buff, length, filepos) == 0)
 
2874
    if (pwrite(file, (unsigned char*) buff, length, filepos) == 0)
2877
2875
      error=1;
2878
2876
    if (locked_and_incremented)
2879
2877
      keycache_pthread_mutex_lock(&keycache->cache_lock);
3046
3044
*/
3047
3045
 
3048
3046
static int flush_cached_blocks(KEY_CACHE *keycache,
3049
 
                               File file, BLOCK_LINK **cache,
 
3047
                               int file, BLOCK_LINK **cache,
3050
3048
                               BLOCK_LINK **end,
3051
3049
                               enum flush_type type)
3052
3050
{
3053
3051
  int error;
3054
3052
  int last_errno= 0;
3055
 
  uint count= (uint) (end-cache);
 
3053
  uint32_t count= (uint) (end-cache);
3056
3054
 
3057
3055
  /* Don't lock the cache during the flush */
3058
3056
  keycache_pthread_mutex_unlock(&keycache->cache_lock);
3060
3058
     As all blocks referred in 'cache' are marked by BLOCK_IN_FLUSH
3061
3059
     we are guarunteed no thread will change them
3062
3060
  */
3063
 
  my_qsort((uchar*) cache, count, sizeof(*cache), (qsort_cmp) cmp_sec_link);
 
3061
  internal::my_qsort((unsigned char*) cache, count, sizeof(*cache), (qsort_cmp) cmp_sec_link);
3064
3062
 
3065
3063
  keycache_pthread_mutex_lock(&keycache->cache_lock);
3066
3064
  /*
3172
3170
*/
3173
3171
 
3174
3172
static int flush_key_blocks_int(KEY_CACHE *keycache,
3175
 
                                File file, enum flush_type type)
 
3173
                                int file, enum flush_type type)
3176
3174
{
3177
3175
  BLOCK_LINK *cache_buff[FLUSH_CACHE],**cache;
3178
3176
  int last_errno= 0;
3180
3178
 
3181
3179
  cache= cache_buff;
3182
3180
  if (keycache->disk_blocks > 0 &&
3183
 
      (!my_disable_flush_key_blocks || type != FLUSH_KEEP))
 
3181
      (!internal::my_disable_flush_key_blocks || type != FLUSH_KEEP))
3184
3182
  {
3185
3183
    /* Key cache exists and flush is not disabled */
3186
3184
    int error= 0;
3187
 
    uint count= FLUSH_CACHE;
 
3185
    uint32_t count= FLUSH_CACHE;
3188
3186
    BLOCK_LINK **pos,**end;
3189
3187
    BLOCK_LINK *first_in_switch= NULL;
3190
3188
    BLOCK_LINK *last_in_flush;
3191
3189
    BLOCK_LINK *last_for_update;
 
3190
    BLOCK_LINK *last_in_switch;
3192
3191
    BLOCK_LINK *block, *next;
3193
3192
 
3194
3193
    if (type != FLUSH_IGNORE_CHANGED)
3215
3214
        changed blocks appear while we need to wait for something.
3216
3215
      */
3217
3216
      if ((count > FLUSH_CACHE) &&
3218
 
          !(cache= (BLOCK_LINK**) my_malloc(sizeof(BLOCK_LINK*)*count,
3219
 
                                            MYF(0))))
 
3217
          !(cache= (BLOCK_LINK**) malloc(sizeof(BLOCK_LINK*)*count)))
3220
3218
        cache= cache_buff;
3221
3219
      /*
3222
3220
        After a restart there could be more changed blocks than now.
3431
3429
 
3432
3430
    if (! (type == FLUSH_KEEP || type == FLUSH_FORCE_WRITE))
3433
3431
    {
3434
 
      BLOCK_LINK *last_for_update= NULL;
3435
 
      BLOCK_LINK *last_in_switch= NULL;
3436
 
      uint total_found= 0;
3437
 
      uint found;
 
3432
      last_for_update= NULL;
 
3433
      last_in_switch= NULL;
 
3434
      uint32_t total_found= 0;
 
3435
      uint32_t found;
3438
3436
 
3439
3437
      /*
3440
3438
        Finally free all clean blocks for this file.
3470
3468
                                   BLOCK_REASSIGNED)))
3471
3469
            {
3472
3470
              struct st_hash_link *next_hash_link= NULL;
3473
 
              my_off_t            next_diskpos= 0;
3474
 
              File                next_file= 0;
3475
 
              uint                next_status= 0;
3476
 
              uint                hash_requests= 0;
 
3471
              internal::my_off_t            next_diskpos= 0;
 
3472
              int                next_file= 0;
 
3473
              uint32_t                next_status= 0;
 
3474
              uint32_t                hash_requests= 0;
3477
3475
 
3478
3476
              total_found++;
3479
3477
              found++;
3573
3571
 
3574
3572
err:
3575
3573
  if (cache != cache_buff)
3576
 
    my_free((uchar*) cache, MYF(0));
 
3574
    free((unsigned char*) cache);
3577
3575
  if (last_errno)
3578
3576
    errno=last_errno;                /* Return first error */
3579
3577
  return(last_errno != 0);
3596
3594
*/
3597
3595
 
3598
3596
int flush_key_blocks(KEY_CACHE *keycache,
3599
 
                     File file, enum flush_type type)
 
3597
                     int file, enum flush_type type)
3600
3598
{
3601
3599
  int res= 0;
3602
3600
 
3651
3649
static int flush_all_key_blocks(KEY_CACHE *keycache)
3652
3650
{
3653
3651
  BLOCK_LINK    *block;
3654
 
  uint          total_found;
3655
 
  uint          found;
3656
 
  uint          idx;
 
3652
  uint32_t          total_found;
 
3653
  uint32_t          found;
 
3654
  uint32_t          idx;
3657
3655
 
3658
3656
  do
3659
3657
  {
3744
3742
 
3745
3743
  SYNOPSIS
3746
3744
    reset_key_cache_counters()
3747
 
    name       the name of a key cache
3748
 
    key_cache  pointer to the key kache to be reset
3749
3745
 
3750
3746
  DESCRIPTION
3751
 
   This procedure is used by process_key_caches() to reset the counters of all
3752
 
   currently used key caches, both the default one and the named ones.
 
3747
   This procedure is used by process_key_caches() to reset the key_cache.
3753
3748
 
3754
3749
  RETURN
3755
3750
    0 on success (always because it can't fail)
3756
3751
*/
3757
3752
 
3758
 
int reset_key_cache_counters(const char *name __attribute__((unused)),
3759
 
                             KEY_CACHE *key_cache)
 
3753
void reset_key_cache_counters()
3760
3754
{
3761
 
  if (!key_cache->key_cache_inited)
3762
 
  {
3763
 
    return(0);
3764
 
  }
3765
 
  key_cache->global_blocks_changed= 0;   /* Key_blocks_not_flushed */
3766
 
  key_cache->global_cache_r_requests= 0; /* Key_read_requests */
3767
 
  key_cache->global_cache_read= 0;       /* Key_reads */
3768
 
  key_cache->global_cache_w_requests= 0; /* Key_write_requests */
3769
 
  key_cache->global_cache_write= 0;      /* Key_writes */
3770
 
  return(0);
 
3755
  dflt_key_cache->global_blocks_changed= 0;   /* Key_blocks_not_flushed */
 
3756
  dflt_key_cache->global_cache_r_requests= 0; /* Key_read_requests */
 
3757
  dflt_key_cache->global_cache_read= 0;       /* Key_reads */
 
3758
  dflt_key_cache->global_cache_w_requests= 0; /* Key_write_requests */
 
3759
  dflt_key_cache->global_cache_write= 0;      /* Key_writes */
3771
3760
}
3772
3761
 
3773
3762
#if defined(KEYCACHE_TIMEOUT)
3774
3763
 
 
3764
 
 
3765
static inline
 
3766
unsigned int hash_link_number(HASH_LINK *hash_link, KEY_CACHE *keycache)
 
3767
{
 
3768
  return ((unsigned int) (((char*)hash_link-(char *) keycache->hash_link_root)/
 
3769
                  sizeof(HASH_LINK)));
 
3770
}
 
3771
 
 
3772
static inline
 
3773
unsigned int block_number(BLOCK_LINK *block, KEY_CACHE *keycache)
 
3774
{
 
3775
  return ((unsigned int) (((char*)block-(char *)keycache->block_root)/
 
3776
                  sizeof(BLOCK_LINK)));
 
3777
}
 
3778
 
 
3779
 
3775
3780
#define KEYCACHE_DUMP_FILE  "keycache_dump.txt"
3776
3781
#define MAX_QUEUE_LEN  100
3777
3782
 
3779
3784
static void keycache_dump(KEY_CACHE *keycache)
3780
3785
{
3781
3786
  FILE *keycache_dump_file=fopen(KEYCACHE_DUMP_FILE, "w");
3782
 
  struct st_my_thread_var *last;
3783
 
  struct st_my_thread_var *thread;
 
3787
  internal::st_my_thread_var *last;
 
3788
  internal::st_my_thread_var *thread;
3784
3789
  BLOCK_LINK *block;
3785
3790
  HASH_LINK *hash_link;
3786
3791
  KEYCACHE_PAGE *page;
3787
 
  uint i;
 
3792
  uint32_t i;
3788
3793
 
3789
3794
  fprintf(keycache_dump_file, "thread:%u\n", thread->id);
3790
3795
 
3813
3818
      thread=thread->next;
3814
3819
      hash_link= (HASH_LINK *) thread->opt_info;
3815
3820
      fprintf(keycache_dump_file,
3816
 
        "thread:%u hash_link:%u (file,filepos)=(%u,%u)\n",
3817
 
        thread->id, (uint) HASH_LINK_NUMBER(hash_link),
3818
 
        (uint) hash_link->file,(uint32_t) hash_link->diskpos);
 
3821
              "thread:%u hash_link:%u (file,filepos)=(%u,%u)\n",
 
3822
              thread->id, (uint) hash_link_number(hash_link, keycache),
 
3823
              (uint) hash_link->file,(uint32_t) hash_link->diskpos);
3819
3824
      if (++i == MAX_QUEUE_LEN)
3820
3825
        break;
3821
3826
    }
3827
3832
    block= &keycache->block_root[i];
3828
3833
    hash_link= block->hash_link;
3829
3834
    fprintf(keycache_dump_file,
3830
 
            "block:%u hash_link:%d status:%x #requests=%u waiting_for_readers:%d\n",
3831
 
            i, (int) (hash_link ? HASH_LINK_NUMBER(hash_link) : -1),
3832
 
            block->status, block->requests, block->condvar ? 1 : 0);
 
3835
            "block:%u hash_link:%d status:%x #requests=%u "
 
3836
            "waiting_for_readers:%d\n",
 
3837
            i, (int) (hash_link ? hash_link_number(hash_link, keycache) : -1),
 
3838
            block->status, block->requests, block->condvar ? 1 : 0);
3833
3839
    for (j=0 ; j < 2; j++)
3834
3840
    {
3835
3841
      KEYCACHE_WQUEUE *wqueue=&block->wqueue[j];
3857
3863
    {
3858
3864
      block= block->next_used;
3859
3865
      fprintf(keycache_dump_file,
3860
 
              "block:%u, ", BLOCK_NUMBER(block));
 
3866
              "block:%u, ", block_number(block, keycache));
3861
3867
    }
3862
3868
    while (block != keycache->used_last);
3863
3869
  }