~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to storage/myisam/mf_keycache.c

  • Committer: Brian Aker
  • Date: 2008-12-16 07:07:50 UTC
  • Revision ID: brian@tangent.org-20081216070750-o5ykltxxqvn2awrx
Fixed errors test.

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