~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to storage/myisam/mf_keycache.c

  • Committer: Patrick Galbraith
  • Date: 2008-07-24 16:57:40 UTC
  • mto: (202.2.4 rename-mysql-to-drizzle)
  • mto: This revision was merged to the branch mainline in revision 212.
  • Revision ID: patg@ishvara-20080724165740-x58yw6zs6d9o17lf
Most everything working with client rename
mysqlslap test still fails... can't connect to the server

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>
 
104
#include "my_global.h"
 
105
#include "mysys_err.h"
 
106
#include <my_sys.h>
107
107
#include <keycache.h>
108
 
#include <mystrings/m_string.h>
109
 
#include <mysys/my_bit.h>
 
108
#include <m_string.h>
 
109
#include <my_bit.h>
110
110
#include <errno.h>
111
111
#include <stdarg.h>
112
112
 
161
161
  struct st_block_link *block;       /* reference to the block for the page: */
162
162
  File file;                         /* from such a file                     */
163
163
  my_off_t diskpos;                  /* with such an offset                  */
164
 
  uint32_t requests;                     /* number of requests for the page      */
 
164
  uint requests;                     /* number of requests for the page      */
165
165
};
166
166
 
167
167
/* simple states of a block */
193
193
    *next_changed, **prev_changed; /* for lists of file dirty/clean blocks   */
194
194
  struct st_hash_link *hash_link; /* backward ptr to referring hash_link     */
195
195
  KEYCACHE_WQUEUE wqueue[2]; /* queues on waiting requests for new/old pages */
196
 
  uint32_t requests;          /* number of requests for the block                */
197
 
  unsigned char *buffer;           /* buffer for the block page                       */
198
 
  uint32_t offset;            /* beginning of modified data in the buffer        */
199
 
  uint32_t length;            /* end of data in the buffer                       */
200
 
  uint32_t status;            /* state of the block                              */
 
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                              */
201
201
  enum BLOCK_TEMPERATURE temperature; /* block temperature: cold, warm, hot */
202
 
  uint32_t hits_left;         /* number of hits left until promotion             */
 
202
  uint hits_left;         /* number of hits left until promotion             */
203
203
  uint64_t last_hit_time; /* timestamp of the last hit                      */
204
204
  KEYCACHE_CONDVAR *condvar; /* condition variable for 'no readers' event    */
205
205
};
216
216
static void free_block(KEY_CACHE *keycache, BLOCK_LINK *block);
217
217
 
218
218
#define KEYCACHE_HASH(f, pos)                                                 \
219
 
(((uint32_t) ((pos) / keycache->key_cache_block_size) +                          \
220
 
                                     (uint32_t) (f)) & (keycache->hash_entries-1))
 
219
(((ulong) ((pos) / keycache->key_cache_block_size) +                          \
 
220
                                     (ulong) (f)) & (keycache->hash_entries-1))
221
221
#define FILE_HASH(f)                 ((uint) (f) & (CHANGED_BLOCKS_HASH-1))
222
222
 
223
223
#define BLOCK_NUMBER(b)                                                       \
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 uint32_t next_power(uint32_t value)
 
239
static inline uint next_power(uint value)
240
240
{
241
241
  return (uint) my_round_up_to_next_power((uint32_t) value) << 1;
242
242
}
267
267
 
268
268
*/
269
269
 
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)
 
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)
273
273
{
274
 
  uint32_t blocks, hash_links;
 
274
  ulong blocks, hash_links;
275
275
  size_t length;
276
276
  int error;
277
277
  assert(key_cache_block_size >= 512);
303
303
  keycache->key_cache_mem_size= use_mem;
304
304
  keycache->key_cache_block_size= key_cache_block_size;
305
305
 
306
 
  blocks= (uint32_t) (use_mem / (sizeof(BLOCK_LINK) + 2 * sizeof(HASH_LINK) +
 
306
  blocks= (ulong) (use_mem / (sizeof(BLOCK_LINK) + 2 * sizeof(HASH_LINK) +
307
307
                              sizeof(HASH_LINK*) * 5/4 + key_cache_block_size));
308
308
  /* It doesn't make sense to have too few blocks (less than 8) */
309
309
  if (blocks >= 8)
353
353
    keycache->hash_link_root= (HASH_LINK*) ((char*) keycache->hash_root +
354
354
                                            ALIGN_SIZE((sizeof(HASH_LINK*) *
355
355
                                                        keycache->hash_entries)));
356
 
    memset(keycache->block_root, 0,
357
 
           keycache->disk_blocks * sizeof(BLOCK_LINK));
358
 
    memset(keycache->hash_root, 0,
359
 
           keycache->hash_entries * sizeof(HASH_LINK*));
360
 
    memset(keycache->hash_link_root, 0,
361
 
           keycache->hash_links * sizeof(HASH_LINK));
 
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));
362
362
    keycache->hash_links_used= 0;
363
363
    keycache->free_hash_list= NULL;
364
364
    keycache->blocks_used= keycache->blocks_changed= 0;
383
383
 
384
384
    keycache->waiting_for_hash_link.last_thread= NULL;
385
385
    keycache->waiting_for_block.last_thread= NULL;
386
 
    memset(keycache->changed_blocks, 0,
387
 
           sizeof(keycache->changed_blocks[0]) * CHANGED_BLOCKS_HASH);
388
 
    memset(keycache->file_blocks, 0,
389
 
           sizeof(keycache->file_blocks[0]) * CHANGED_BLOCKS_HASH);
 
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);
390
390
  }
391
391
  else
392
392
  {
408
408
  }
409
409
  if (keycache->block_root)
410
410
  {
411
 
    free((unsigned char*) keycache->block_root);
 
411
    my_free((uchar*) keycache->block_root, MYF(0));
412
412
    keycache->block_root= NULL;
413
413
  }
414
414
  my_errno= error;
446
446
    (when cnt_for_resize=0).
447
447
*/
448
448
 
449
 
int resize_key_cache(KEY_CACHE *keycache, uint32_t key_cache_block_size,
450
 
                     size_t use_mem, uint32_t division_limit,
451
 
                     uint32_t age_threshold)
 
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)
452
452
{
453
453
  int blocks;
454
454
 
580
580
    age_threshold.
581
581
*/
582
582
 
583
 
void change_key_cache_param(KEY_CACHE *keycache, uint32_t division_limit,
584
 
                            uint32_t age_threshold)
 
583
void change_key_cache_param(KEY_CACHE *keycache, uint division_limit,
 
584
                            uint age_threshold)
585
585
{
586
586
  keycache_pthread_mutex_lock(&keycache->cache_lock);
587
587
  if (division_limit)
607
607
    none
608
608
*/
609
609
 
610
 
void end_key_cache(KEY_CACHE *keycache, bool cleanup)
 
610
void end_key_cache(KEY_CACHE *keycache, my_bool cleanup)
611
611
{
612
612
  if (!keycache->key_cache_inited)
613
613
    return;
618
618
    {
619
619
      free(keycache->block_mem);
620
620
      keycache->block_mem= NULL;
621
 
      free((unsigned char*) keycache->block_root);
 
621
      my_free((uchar*) keycache->block_root, MYF(0));
622
622
      keycache->block_root= NULL;
623
623
    }
624
624
    keycache->disk_blocks= -1;
861
861
 
862
862
static void link_to_file_list(KEY_CACHE *keycache,
863
863
                              BLOCK_LINK *block, int file,
864
 
                              bool unlink_block)
 
864
                              my_bool unlink_block)
865
865
{
866
866
  assert(block->status & BLOCK_IN_USE);
867
867
  assert(block->hash_link && block->hash_link->block == block);
955
955
    not linked in the LRU ring.
956
956
*/
957
957
 
958
 
static void link_block(KEY_CACHE *keycache, BLOCK_LINK *block, bool hot,
959
 
                       bool at_end)
 
958
static void link_block(KEY_CACHE *keycache, BLOCK_LINK *block, my_bool hot,
 
959
                       my_bool at_end)
960
960
{
961
961
  BLOCK_LINK *ins;
962
962
  BLOCK_LINK **pins;
1149
1149
  assert(!block->prev_used);
1150
1150
  if (! --block->requests)
1151
1151
  {
1152
 
    bool hot;
 
1152
    my_bool hot;
1153
1153
    if (block->hits_left)
1154
1154
      block->hits_left--;
1155
1155
    hot= !block->hits_left && at_end &&
1160
1160
        keycache->warm_blocks--;
1161
1161
      block->temperature= BLOCK_HOT;
1162
1162
    }
1163
 
    link_block(keycache, block, hot, (bool)at_end);
 
1163
    link_block(keycache, block, hot, (my_bool)at_end);
1164
1164
    block->last_hit_time= keycache->keycache_time;
1165
1165
    keycache->keycache_time++;
1166
1166
    /*
1774
1774
        {
1775
1775
          /* There are some never used blocks, take first of them */
1776
1776
          assert(keycache->blocks_used <
1777
 
                      (uint32_t) keycache->disk_blocks);
 
1777
                      (ulong) keycache->disk_blocks);
1778
1778
          block= &keycache->block_root[keycache->blocks_used];
1779
1779
          block->buffer= ADD_TO_PTR(keycache->block_mem,
1780
 
                                    ((uint32_t) keycache->blocks_used*
 
1780
                                    ((ulong) keycache->blocks_used*
1781
1781
                                     keycache->key_cache_block_size),
1782
 
                                    unsigned char*);
 
1782
                                    uchar*);
1783
1783
          keycache->blocks_used++;
1784
1784
          assert(!block->next_used);
1785
1785
        }
2098
2098
*/
2099
2099
 
2100
2100
static void read_block(KEY_CACHE *keycache,
2101
 
                       BLOCK_LINK *block, uint32_t read_length,
2102
 
                       uint32_t min_length, bool primary)
 
2101
                       BLOCK_LINK *block, uint read_length,
 
2102
                       uint min_length, my_bool primary)
2103
2103
{
2104
 
  uint32_t got_length;
 
2104
  uint got_length;
2105
2105
 
2106
2106
  /* On entry cache_lock is locked */
2107
2107
 
2197
2197
    have to be a multiple of key_cache_block_size;
2198
2198
*/
2199
2199
 
2200
 
unsigned char *key_cache_read(KEY_CACHE *keycache,
 
2200
uchar *key_cache_read(KEY_CACHE *keycache,
2201
2201
                      File file, my_off_t filepos, int level,
2202
 
                      unsigned char *buff, uint32_t length,
2203
 
                      uint32_t block_length __attribute__((unused)),
 
2202
                      uchar *buff, uint length,
 
2203
                      uint block_length __attribute__((unused)),
2204
2204
                      int return_buffer __attribute__((unused)))
2205
2205
{
2206
 
  bool locked_and_incremented= false;
 
2206
  my_bool locked_and_incremented= false;
2207
2207
  int error=0;
2208
 
  unsigned char *start= buff;
 
2208
  uchar *start= buff;
2209
2209
 
2210
2210
  if (keycache->key_cache_inited)
2211
2211
  {
2212
2212
    /* Key cache is used */
2213
2213
    register BLOCK_LINK *block;
2214
 
    uint32_t read_length;
2215
 
    uint32_t offset;
2216
 
    uint32_t status;
 
2214
    uint read_length;
 
2215
    uint offset;
 
2216
    uint status;
2217
2217
    int page_st;
2218
2218
 
2219
2219
    /*
2270
2270
        */
2271
2271
        keycache->global_cache_read++;
2272
2272
        keycache_pthread_mutex_unlock(&keycache->cache_lock);
2273
 
        error= (pread(file, (unsigned char*) buff, read_length, filepos + offset) == 0);
 
2273
        error= (pread(file, (uchar*) buff, read_length, filepos + offset) == 0);
2274
2274
        keycache_pthread_mutex_lock(&keycache->cache_lock);
2275
2275
        goto next_block;
2276
2276
      }
2281
2281
          /* The requested page is to be read into the block buffer */
2282
2282
          read_block(keycache, block,
2283
2283
                     keycache->key_cache_block_size, read_length+offset,
2284
 
                     (bool)(page_st == PAGE_TO_BE_READ));
 
2284
                     (my_bool)(page_st == PAGE_TO_BE_READ));
2285
2285
          /*
2286
2286
            A secondary request must now have the block assigned to the
2287
2287
            requested file block. It does not hurt to check it for
2314
2314
#endif
2315
2315
 
2316
2316
          /* Copy data from the cache buffer */
2317
 
          memcpy(buff, block->buffer+offset, (size_t) read_length);
 
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);
2318
2321
 
2319
2322
#if !defined(SERIALIZED_READ_FROM_CACHE)
2320
2323
          keycache_pthread_mutex_lock(&keycache->cache_lock);
2354
2357
 
2355
2358
  if (locked_and_incremented)
2356
2359
    keycache_pthread_mutex_unlock(&keycache->cache_lock);
2357
 
  if (pread(file, (unsigned char*) buff, length, filepos))
 
2360
  if (pread(file, (uchar*) buff, length, filepos))
2358
2361
    error= 1;
2359
2362
  if (locked_and_incremented)
2360
2363
    keycache_pthread_mutex_lock(&keycache->cache_lock);
2365
2368
    dec_counter_for_resize_op(keycache);
2366
2369
    keycache_pthread_mutex_unlock(&keycache->cache_lock);
2367
2370
  }
2368
 
  return(error ? (unsigned char*) 0 : start);
 
2371
  return(error ? (uchar*) 0 : start);
2369
2372
}
2370
2373
 
2371
2374
 
2391
2394
 
2392
2395
int key_cache_insert(KEY_CACHE *keycache,
2393
2396
                     File file, my_off_t filepos, int level,
2394
 
                     unsigned char *buff, uint32_t length)
 
2397
                     uchar *buff, uint length)
2395
2398
{
2396
2399
  int error= 0;
2397
2400
 
2399
2402
  {
2400
2403
    /* Key cache is used */
2401
2404
    register BLOCK_LINK *block;
2402
 
    uint32_t read_length;
2403
 
    uint32_t offset;
 
2405
    uint read_length;
 
2406
    uint offset;
2404
2407
    int page_st;
2405
 
    bool locked_and_incremented= false;
 
2408
    my_bool locked_and_incremented= false;
2406
2409
 
2407
2410
    /*
2408
2411
      When the keycache is once initialized, we use the cache_lock to
2514
2517
#endif
2515
2518
 
2516
2519
          /* Copy data from buff */
2517
 
          memcpy(block->buffer+offset, buff, (size_t) read_length);
 
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);
2518
2524
 
2519
2525
#if !defined(SERIALIZED_READ_FROM_CACHE)
2520
2526
          keycache_pthread_mutex_lock(&keycache->cache_lock);
2625
2631
 
2626
2632
int key_cache_write(KEY_CACHE *keycache,
2627
2633
                    File file, my_off_t filepos, int level,
2628
 
                    unsigned char *buff, uint32_t length,
2629
 
                    uint32_t block_length  __attribute__((unused)),
 
2634
                    uchar *buff, uint length,
 
2635
                    uint block_length  __attribute__((unused)),
2630
2636
                    int dont_write)
2631
2637
{
2632
 
  bool locked_and_incremented= false;
 
2638
  my_bool locked_and_incremented= false;
2633
2639
  int error=0;
2634
2640
 
2635
2641
  if (!dont_write)
2648
2654
  {
2649
2655
    /* Key cache is used */
2650
2656
    register BLOCK_LINK *block;
2651
 
    uint32_t read_length;
2652
 
    uint32_t offset;
 
2657
    uint read_length;
 
2658
    uint offset;
2653
2659
    int page_st;
2654
2660
 
2655
2661
    /*
2709
2715
          /* Used in the server. */
2710
2716
          keycache->global_cache_write++;
2711
2717
          keycache_pthread_mutex_unlock(&keycache->cache_lock);
2712
 
          if (pwrite(file, (unsigned char*) buff, read_length, filepos + offset) == 0)
 
2718
          if (pwrite(file, (uchar*) buff, read_length, filepos + offset) == 0)
2713
2719
            error=1;
2714
2720
          keycache_pthread_mutex_lock(&keycache->cache_lock);
2715
2721
        }
2804
2810
#if !defined(SERIALIZED_READ_FROM_CACHE)
2805
2811
        keycache_pthread_mutex_unlock(&keycache->cache_lock);
2806
2812
#endif
2807
 
        memcpy(block->buffer+offset, buff, (size_t) read_length);
 
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);
2808
2817
 
2809
2818
#if !defined(SERIALIZED_READ_FROM_CACHE)
2810
2819
        keycache_pthread_mutex_lock(&keycache->cache_lock);
2873
2882
    keycache->global_cache_write++;
2874
2883
    if (locked_and_incremented)
2875
2884
      keycache_pthread_mutex_unlock(&keycache->cache_lock);
2876
 
    if (pwrite(file, (unsigned char*) buff, length, filepos) == 0)
 
2885
    if (pwrite(file, (uchar*) buff, length, filepos) == 0)
2877
2886
      error=1;
2878
2887
    if (locked_and_incremented)
2879
2888
      keycache_pthread_mutex_lock(&keycache->cache_lock);
3052
3061
{
3053
3062
  int error;
3054
3063
  int last_errno= 0;
3055
 
  uint32_t count= (uint) (end-cache);
 
3064
  uint count= (uint) (end-cache);
3056
3065
 
3057
3066
  /* Don't lock the cache during the flush */
3058
3067
  keycache_pthread_mutex_unlock(&keycache->cache_lock);
3060
3069
     As all blocks referred in 'cache' are marked by BLOCK_IN_FLUSH
3061
3070
     we are guarunteed no thread will change them
3062
3071
  */
3063
 
  my_qsort((unsigned char*) cache, count, sizeof(*cache), (qsort_cmp) cmp_sec_link);
 
3072
  my_qsort((uchar*) cache, count, sizeof(*cache), (qsort_cmp) cmp_sec_link);
3064
3073
 
3065
3074
  keycache_pthread_mutex_lock(&keycache->cache_lock);
3066
3075
  /*
3184
3193
  {
3185
3194
    /* Key cache exists and flush is not disabled */
3186
3195
    int error= 0;
3187
 
    uint32_t count= FLUSH_CACHE;
 
3196
    uint count= FLUSH_CACHE;
3188
3197
    BLOCK_LINK **pos,**end;
3189
3198
    BLOCK_LINK *first_in_switch= NULL;
3190
3199
    BLOCK_LINK *last_in_flush;
3433
3442
    {
3434
3443
      BLOCK_LINK *last_for_update= NULL;
3435
3444
      BLOCK_LINK *last_in_switch= NULL;
3436
 
      uint32_t total_found= 0;
3437
 
      uint32_t found;
 
3445
      uint total_found= 0;
 
3446
      uint found;
3438
3447
 
3439
3448
      /*
3440
3449
        Finally free all clean blocks for this file.
3469
3478
            if (!(block->status & (BLOCK_IN_EVICTION | BLOCK_IN_SWITCH |
3470
3479
                                   BLOCK_REASSIGNED)))
3471
3480
            {
3472
 
              struct st_hash_link *next_hash_link= NULL;
3473
 
              my_off_t            next_diskpos= 0;
3474
 
              File                next_file= 0;
3475
 
              uint32_t                next_status= 0;
3476
 
              uint32_t                hash_requests= 0;
 
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;
3477
3486
 
3478
3487
              total_found++;
3479
3488
              found++;
3573
3582
 
3574
3583
err:
3575
3584
  if (cache != cache_buff)
3576
 
    free((unsigned char*) cache);
 
3585
    my_free((uchar*) cache, MYF(0));
3577
3586
  if (last_errno)
3578
3587
    errno=last_errno;                /* Return first error */
3579
3588
  return(last_errno != 0);
3651
3660
static int flush_all_key_blocks(KEY_CACHE *keycache)
3652
3661
{
3653
3662
  BLOCK_LINK    *block;
3654
 
  uint32_t          total_found;
3655
 
  uint32_t          found;
3656
 
  uint32_t          idx;
 
3663
  uint          total_found;
 
3664
  uint          found;
 
3665
  uint          idx;
3657
3666
 
3658
3667
  do
3659
3668
  {
3784
3793
  BLOCK_LINK *block;
3785
3794
  HASH_LINK *hash_link;
3786
3795
  KEYCACHE_PAGE *page;
3787
 
  uint32_t i;
 
3796
  uint i;
3788
3797
 
3789
3798
  fprintf(keycache_dump_file, "thread:%u\n", thread->id);
3790
3799
 
3798
3807
      page= (KEYCACHE_PAGE *) thread->opt_info;
3799
3808
      fprintf(keycache_dump_file,
3800
3809
              "thread:%u, (file,filepos)=(%u,%lu)\n",
3801
 
              thread->id,(uint) page->file,(uint32_t) page->filepos);
 
3810
              thread->id,(uint) page->file,(ulong) page->filepos);
3802
3811
      if (++i == MAX_QUEUE_LEN)
3803
3812
        break;
3804
3813
    }
3813
3822
      thread=thread->next;
3814
3823
      hash_link= (HASH_LINK *) thread->opt_info;
3815
3824
      fprintf(keycache_dump_file,
3816
 
        "thread:%u hash_link:%u (file,filepos)=(%u,%u)\n",
 
3825
        "thread:%u hash_link:%u (file,filepos)=(%u,%lu)\n",
3817
3826
        thread->id, (uint) HASH_LINK_NUMBER(hash_link),
3818
 
        (uint) hash_link->file,(uint32_t) hash_link->diskpos);
 
3827
        (uint) hash_link->file,(ulong) hash_link->diskpos);
3819
3828
      if (++i == MAX_QUEUE_LEN)
3820
3829
        break;
3821
3830
    }