~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to storage/myisam/mf_keycache.c

  • Committer: Brian Aker
  • Date: 2008-09-04 19:31:00 UTC
  • Revision ID: brian@tangent.org-20080904193100-l849hgghfy4urj43
Changing default character set from this point on.

Show diffs side-by-side

added added

removed removed

Lines of Context:
143
143
/* types of condition variables */
144
144
#define  COND_FOR_REQUESTED 0
145
145
#define  COND_FOR_SAVED     1
 
146
#define  COND_FOR_READERS   2
146
147
 
147
148
typedef pthread_cond_t KEYCACHE_CONDVAR;
148
149
 
160
161
  struct st_block_link *block;       /* reference to the block for the page: */
161
162
  File file;                         /* from such a file                     */
162
163
  my_off_t diskpos;                  /* with such an offset                  */
163
 
  uint32_t requests;                     /* number of requests for the page      */
 
164
  uint requests;                     /* number of requests for the page      */
164
165
};
165
166
 
166
167
/* simple states of a block */
192
193
    *next_changed, **prev_changed; /* for lists of file dirty/clean blocks   */
193
194
  struct st_hash_link *hash_link; /* backward ptr to referring hash_link     */
194
195
  KEYCACHE_WQUEUE wqueue[2]; /* queues on waiting requests for new/old pages */
195
 
  uint32_t requests;          /* number of requests for the block                */
196
 
  unsigned char *buffer;           /* buffer for the block page                       */
197
 
  uint32_t offset;            /* beginning of modified data in the buffer        */
198
 
  uint32_t length;            /* end of data in the buffer                       */
199
 
  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                              */
200
201
  enum BLOCK_TEMPERATURE temperature; /* block temperature: cold, warm, hot */
201
 
  uint32_t hits_left;         /* number of hits left until promotion             */
 
202
  uint hits_left;         /* number of hits left until promotion             */
202
203
  uint64_t last_hit_time; /* timestamp of the last hit                      */
203
204
  KEYCACHE_CONDVAR *condvar; /* condition variable for 'no readers' event    */
204
205
};
219
220
                                     (uint32_t) (f)) & (keycache->hash_entries-1))
220
221
#define FILE_HASH(f)                 ((uint) (f) & (CHANGED_BLOCKS_HASH-1))
221
222
 
 
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)))
222
227
 
223
228
#ifdef KEYCACHE_TIMEOUT
224
229
static int keycache_pthread_cond_wait(pthread_cond_t *cond,
231
236
#define keycache_pthread_mutex_unlock pthread_mutex_unlock
232
237
#define keycache_pthread_cond_signal pthread_cond_signal
233
238
 
234
 
static inline uint32_t next_power(uint32_t value)
 
239
static inline uint next_power(uint value)
235
240
{
236
241
  return (uint) my_round_up_to_next_power((uint32_t) value) << 1;
237
242
}
262
267
 
263
268
*/
264
269
 
265
 
int init_key_cache(KEY_CACHE *keycache, uint32_t key_cache_block_size,
266
 
                   size_t use_mem, uint32_t division_limit,
267
 
                   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)
268
273
{
269
274
  uint32_t blocks, hash_links;
270
275
  size_t length;
403
408
  }
404
409
  if (keycache->block_root)
405
410
  {
406
 
    free((unsigned char*) keycache->block_root);
 
411
    my_free((uchar*) keycache->block_root, MYF(0));
407
412
    keycache->block_root= NULL;
408
413
  }
409
414
  my_errno= error;
441
446
    (when cnt_for_resize=0).
442
447
*/
443
448
 
444
 
int resize_key_cache(KEY_CACHE *keycache, uint32_t key_cache_block_size,
445
 
                     size_t use_mem, uint32_t division_limit,
446
 
                     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)
447
452
{
448
453
  int blocks;
449
454
 
575
580
    age_threshold.
576
581
*/
577
582
 
578
 
void change_key_cache_param(KEY_CACHE *keycache, uint32_t division_limit,
579
 
                            uint32_t age_threshold)
 
583
void change_key_cache_param(KEY_CACHE *keycache, uint division_limit,
 
584
                            uint age_threshold)
580
585
{
581
586
  keycache_pthread_mutex_lock(&keycache->cache_lock);
582
587
  if (division_limit)
613
618
    {
614
619
      free(keycache->block_mem);
615
620
      keycache->block_mem= NULL;
616
 
      free((unsigned char*) keycache->block_root);
 
621
      my_free((uchar*) keycache->block_root, MYF(0));
617
622
      keycache->block_root= NULL;
618
623
    }
619
624
    keycache->disk_blocks= -1;
1774
1779
          block->buffer= ADD_TO_PTR(keycache->block_mem,
1775
1780
                                    ((uint32_t) keycache->blocks_used*
1776
1781
                                     keycache->key_cache_block_size),
1777
 
                                    unsigned char*);
 
1782
                                    uchar*);
1778
1783
          keycache->blocks_used++;
1779
1784
          assert(!block->next_used);
1780
1785
        }
2093
2098
*/
2094
2099
 
2095
2100
static void read_block(KEY_CACHE *keycache,
2096
 
                       BLOCK_LINK *block, uint32_t read_length,
2097
 
                       uint32_t min_length, bool primary)
 
2101
                       BLOCK_LINK *block, uint read_length,
 
2102
                       uint min_length, bool primary)
2098
2103
{
2099
 
  uint32_t got_length;
 
2104
  uint got_length;
2100
2105
 
2101
2106
  /* On entry cache_lock is locked */
2102
2107
 
2192
2197
    have to be a multiple of key_cache_block_size;
2193
2198
*/
2194
2199
 
2195
 
unsigned char *key_cache_read(KEY_CACHE *keycache,
 
2200
uchar *key_cache_read(KEY_CACHE *keycache,
2196
2201
                      File file, my_off_t filepos, int level,
2197
 
                      unsigned char *buff, uint32_t length,
2198
 
                      uint32_t block_length __attribute__((unused)),
 
2202
                      uchar *buff, uint length,
 
2203
                      uint block_length __attribute__((unused)),
2199
2204
                      int return_buffer __attribute__((unused)))
2200
2205
{
2201
2206
  bool locked_and_incremented= false;
2202
2207
  int error=0;
2203
 
  unsigned char *start= buff;
 
2208
  uchar *start= buff;
2204
2209
 
2205
2210
  if (keycache->key_cache_inited)
2206
2211
  {
2207
2212
    /* Key cache is used */
2208
2213
    register BLOCK_LINK *block;
2209
 
    uint32_t read_length;
2210
 
    uint32_t offset;
2211
 
    uint32_t status;
 
2214
    uint read_length;
 
2215
    uint offset;
 
2216
    uint status;
2212
2217
    int page_st;
2213
2218
 
2214
2219
    /*
2265
2270
        */
2266
2271
        keycache->global_cache_read++;
2267
2272
        keycache_pthread_mutex_unlock(&keycache->cache_lock);
2268
 
        error= (pread(file, (unsigned char*) buff, read_length, filepos + offset) == 0);
 
2273
        error= (pread(file, (uchar*) buff, read_length, filepos + offset) == 0);
2269
2274
        keycache_pthread_mutex_lock(&keycache->cache_lock);
2270
2275
        goto next_block;
2271
2276
      }
2349
2354
 
2350
2355
  if (locked_and_incremented)
2351
2356
    keycache_pthread_mutex_unlock(&keycache->cache_lock);
2352
 
  if (pread(file, (unsigned char*) buff, length, filepos))
 
2357
  if (pread(file, (uchar*) buff, length, filepos))
2353
2358
    error= 1;
2354
2359
  if (locked_and_incremented)
2355
2360
    keycache_pthread_mutex_lock(&keycache->cache_lock);
2360
2365
    dec_counter_for_resize_op(keycache);
2361
2366
    keycache_pthread_mutex_unlock(&keycache->cache_lock);
2362
2367
  }
2363
 
  return(error ? (unsigned char*) 0 : start);
 
2368
  return(error ? (uchar*) 0 : start);
2364
2369
}
2365
2370
 
2366
2371
 
2386
2391
 
2387
2392
int key_cache_insert(KEY_CACHE *keycache,
2388
2393
                     File file, my_off_t filepos, int level,
2389
 
                     unsigned char *buff, uint32_t length)
 
2394
                     uchar *buff, uint length)
2390
2395
{
2391
2396
  int error= 0;
2392
2397
 
2394
2399
  {
2395
2400
    /* Key cache is used */
2396
2401
    register BLOCK_LINK *block;
2397
 
    uint32_t read_length;
2398
 
    uint32_t offset;
 
2402
    uint read_length;
 
2403
    uint offset;
2399
2404
    int page_st;
2400
2405
    bool locked_and_incremented= false;
2401
2406
 
2620
2625
 
2621
2626
int key_cache_write(KEY_CACHE *keycache,
2622
2627
                    File file, my_off_t filepos, int level,
2623
 
                    unsigned char *buff, uint32_t length,
2624
 
                    uint32_t block_length  __attribute__((unused)),
 
2628
                    uchar *buff, uint length,
 
2629
                    uint block_length  __attribute__((unused)),
2625
2630
                    int dont_write)
2626
2631
{
2627
2632
  bool locked_and_incremented= false;
2643
2648
  {
2644
2649
    /* Key cache is used */
2645
2650
    register BLOCK_LINK *block;
2646
 
    uint32_t read_length;
2647
 
    uint32_t offset;
 
2651
    uint read_length;
 
2652
    uint offset;
2648
2653
    int page_st;
2649
2654
 
2650
2655
    /*
2704
2709
          /* Used in the server. */
2705
2710
          keycache->global_cache_write++;
2706
2711
          keycache_pthread_mutex_unlock(&keycache->cache_lock);
2707
 
          if (pwrite(file, (unsigned char*) buff, read_length, filepos + offset) == 0)
 
2712
          if (pwrite(file, (uchar*) buff, read_length, filepos + offset) == 0)
2708
2713
            error=1;
2709
2714
          keycache_pthread_mutex_lock(&keycache->cache_lock);
2710
2715
        }
2868
2873
    keycache->global_cache_write++;
2869
2874
    if (locked_and_incremented)
2870
2875
      keycache_pthread_mutex_unlock(&keycache->cache_lock);
2871
 
    if (pwrite(file, (unsigned char*) buff, length, filepos) == 0)
 
2876
    if (pwrite(file, (uchar*) buff, length, filepos) == 0)
2872
2877
      error=1;
2873
2878
    if (locked_and_incremented)
2874
2879
      keycache_pthread_mutex_lock(&keycache->cache_lock);
3047
3052
{
3048
3053
  int error;
3049
3054
  int last_errno= 0;
3050
 
  uint32_t count= (uint) (end-cache);
 
3055
  uint count= (uint) (end-cache);
3051
3056
 
3052
3057
  /* Don't lock the cache during the flush */
3053
3058
  keycache_pthread_mutex_unlock(&keycache->cache_lock);
3055
3060
     As all blocks referred in 'cache' are marked by BLOCK_IN_FLUSH
3056
3061
     we are guarunteed no thread will change them
3057
3062
  */
3058
 
  my_qsort((unsigned char*) cache, count, sizeof(*cache), (qsort_cmp) cmp_sec_link);
 
3063
  my_qsort((uchar*) cache, count, sizeof(*cache), (qsort_cmp) cmp_sec_link);
3059
3064
 
3060
3065
  keycache_pthread_mutex_lock(&keycache->cache_lock);
3061
3066
  /*
3179
3184
  {
3180
3185
    /* Key cache exists and flush is not disabled */
3181
3186
    int error= 0;
3182
 
    uint32_t count= FLUSH_CACHE;
 
3187
    uint count= FLUSH_CACHE;
3183
3188
    BLOCK_LINK **pos,**end;
3184
3189
    BLOCK_LINK *first_in_switch= NULL;
3185
3190
    BLOCK_LINK *last_in_flush;
3428
3433
    {
3429
3434
      BLOCK_LINK *last_for_update= NULL;
3430
3435
      BLOCK_LINK *last_in_switch= NULL;
3431
 
      uint32_t total_found= 0;
3432
 
      uint32_t found;
 
3436
      uint total_found= 0;
 
3437
      uint found;
3433
3438
 
3434
3439
      /*
3435
3440
        Finally free all clean blocks for this file.
3467
3472
              struct st_hash_link *next_hash_link= NULL;
3468
3473
              my_off_t            next_diskpos= 0;
3469
3474
              File                next_file= 0;
3470
 
              uint32_t                next_status= 0;
3471
 
              uint32_t                hash_requests= 0;
 
3475
              uint                next_status= 0;
 
3476
              uint                hash_requests= 0;
3472
3477
 
3473
3478
              total_found++;
3474
3479
              found++;
3568
3573
 
3569
3574
err:
3570
3575
  if (cache != cache_buff)
3571
 
    free((unsigned char*) cache);
 
3576
    my_free((uchar*) cache, MYF(0));
3572
3577
  if (last_errno)
3573
3578
    errno=last_errno;                /* Return first error */
3574
3579
  return(last_errno != 0);
3646
3651
static int flush_all_key_blocks(KEY_CACHE *keycache)
3647
3652
{
3648
3653
  BLOCK_LINK    *block;
3649
 
  uint32_t          total_found;
3650
 
  uint32_t          found;
3651
 
  uint32_t          idx;
 
3654
  uint          total_found;
 
3655
  uint          found;
 
3656
  uint          idx;
3652
3657
 
3653
3658
  do
3654
3659
  {
3767
3772
 
3768
3773
#if defined(KEYCACHE_TIMEOUT)
3769
3774
 
3770
 
 
3771
 
static inline
3772
 
unsigned int hash_link_number(HASH_LINK *hash_link, KEY_CACHE *keycache)
3773
 
{
3774
 
  return ((unsigned int) (((char*)hash_link-(char *) keycache->hash_link_root)/
3775
 
                  sizeof(HASH_LINK)));
3776
 
}
3777
 
 
3778
 
static inline
3779
 
unsigned int block_number(BLOCK_LINK *block, KEY_CACHE *keycache)
3780
 
{
3781
 
  return ((unsigned int) (((char*)block-(char *)keycache->block_root)/
3782
 
                  sizeof(BLOCK_LINK)));
3783
 
}
3784
 
 
3785
 
 
3786
3775
#define KEYCACHE_DUMP_FILE  "keycache_dump.txt"
3787
3776
#define MAX_QUEUE_LEN  100
3788
3777
 
3795
3784
  BLOCK_LINK *block;
3796
3785
  HASH_LINK *hash_link;
3797
3786
  KEYCACHE_PAGE *page;
3798
 
  uint32_t i;
 
3787
  uint i;
3799
3788
 
3800
3789
  fprintf(keycache_dump_file, "thread:%u\n", thread->id);
3801
3790
 
3824
3813
      thread=thread->next;
3825
3814
      hash_link= (HASH_LINK *) thread->opt_info;
3826
3815
      fprintf(keycache_dump_file,
3827
 
              "thread:%u hash_link:%u (file,filepos)=(%u,%u)\n",
3828
 
              thread->id, (uint) hash_link_number(hash_link, keycache),
3829
 
              (uint) hash_link->file,(uint32_t) hash_link->diskpos);
 
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);
3830
3819
      if (++i == MAX_QUEUE_LEN)
3831
3820
        break;
3832
3821
    }
3838
3827
    block= &keycache->block_root[i];
3839
3828
    hash_link= block->hash_link;
3840
3829
    fprintf(keycache_dump_file,
3841
 
            "block:%u hash_link:%d status:%x #requests=%u "
3842
 
            "waiting_for_readers:%d\n",
3843
 
            i, (int) (hash_link ? hash_link_number(hash_link, keycache) : -1),
3844
 
            block->status, block->requests, block->condvar ? 1 : 0);
 
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);
3845
3833
    for (j=0 ; j < 2; j++)
3846
3834
    {
3847
3835
      KEYCACHE_WQUEUE *wqueue=&block->wqueue[j];
3869
3857
    {
3870
3858
      block= block->next_used;
3871
3859
      fprintf(keycache_dump_file,
3872
 
              "block:%u, ", block_number(block, keycache));
 
3860
              "block:%u, ", BLOCK_NUMBER(block));
3873
3861
    }
3874
3862
    while (block != keycache->used_last);
3875
3863
  }