246
271
size_t use_mem, uint32_t division_limit,
247
272
uint32_t age_threshold)
250
(void)key_cache_block_size;
252
(void)division_limit;
254
memset(keycache, 0, sizeof(KEY_CACHE));
274
uint32_t blocks, hash_links;
277
assert(key_cache_block_size >= 512);
279
if (keycache->key_cache_inited && keycache->disk_blocks > 0)
284
keycache->global_cache_w_requests= keycache->global_cache_r_requests= 0;
285
keycache->global_cache_read= keycache->global_cache_write= 0;
286
keycache->disk_blocks= -1;
287
if (! keycache->key_cache_inited)
289
keycache->key_cache_inited= 1;
291
Initialize these variables once only.
292
Their value must survive re-initialization during resizing.
294
keycache->in_resize= 0;
295
keycache->resize_in_flush= 0;
296
keycache->cnt_for_resize_op= 0;
297
keycache->waiting_for_resize_cnt.last_thread= NULL;
298
keycache->in_init= 0;
299
pthread_mutex_init(&keycache->cache_lock, MY_MUTEX_INIT_FAST);
300
keycache->resize_queue.last_thread= NULL;
303
keycache->key_cache_mem_size= use_mem;
304
keycache->key_cache_block_size= key_cache_block_size;
306
blocks= (uint32_t) (use_mem / (sizeof(BLOCK_LINK) + 2 * sizeof(HASH_LINK) +
307
sizeof(HASH_LINK*) * 5/4 + key_cache_block_size));
308
/* It doesn't make sense to have too few blocks (less than 8) */
313
/* Set my_hash_entries to the next bigger 2 power */
314
if ((keycache->hash_entries= next_power(blocks)) < blocks * 5/4)
315
keycache->hash_entries<<= 1;
316
hash_links= 2 * blocks;
317
#if defined(MAX_THREADS)
318
if (hash_links < MAX_THREADS + blocks - 1)
319
hash_links= MAX_THREADS + blocks - 1;
321
while ((length= (ALIGN_SIZE(blocks * sizeof(BLOCK_LINK)) +
322
ALIGN_SIZE(hash_links * sizeof(HASH_LINK)) +
323
ALIGN_SIZE(sizeof(HASH_LINK*) *
324
keycache->hash_entries))) +
325
((size_t) blocks * keycache->key_cache_block_size) > use_mem)
327
/* Allocate memory for cache page buffers */
328
if ((keycache->block_mem= (unsigned char *)malloc((size_t) blocks * keycache->key_cache_block_size)))
331
Allocate memory for blocks, hash_links and hash entries;
332
For each block 2 hash links are allocated
334
if ((keycache->block_root= (BLOCK_LINK*) malloc(length)))
336
free(keycache->block_mem);
337
keycache->block_mem= 0;
342
my_error(EE_OUTOFMEMORY, MYF(0), blocks * keycache->key_cache_block_size);
345
blocks= blocks / 4*3;
347
keycache->blocks_unused= blocks;
348
keycache->disk_blocks= (int) blocks;
349
keycache->hash_links= hash_links;
350
keycache->hash_root= (HASH_LINK**) ((char*) keycache->block_root +
351
ALIGN_SIZE(blocks*sizeof(BLOCK_LINK)));
352
keycache->hash_link_root= (HASH_LINK*) ((char*) keycache->hash_root +
353
ALIGN_SIZE((sizeof(HASH_LINK*) *
354
keycache->hash_entries)));
355
memset(keycache->block_root, 0,
356
keycache->disk_blocks * sizeof(BLOCK_LINK));
357
memset(keycache->hash_root, 0,
358
keycache->hash_entries * sizeof(HASH_LINK*));
359
memset(keycache->hash_link_root, 0,
360
keycache->hash_links * sizeof(HASH_LINK));
361
keycache->hash_links_used= 0;
362
keycache->free_hash_list= NULL;
363
keycache->blocks_used= keycache->blocks_changed= 0;
365
keycache->global_blocks_changed= 0;
366
keycache->blocks_available=0; /* For debugging */
368
/* The LRU chain is empty after initialization */
369
keycache->used_last= NULL;
370
keycache->used_ins= NULL;
371
keycache->free_block_list= NULL;
372
keycache->keycache_time= 0;
373
keycache->warm_blocks= 0;
374
keycache->min_warm_blocks= (division_limit ?
375
blocks * division_limit / 100 + 1 :
377
keycache->age_threshold= (age_threshold ?
378
blocks * age_threshold / 100 :
381
keycache->can_be_used= 1;
383
keycache->waiting_for_hash_link.last_thread= NULL;
384
keycache->waiting_for_block.last_thread= NULL;
385
memset(keycache->changed_blocks, 0,
386
sizeof(keycache->changed_blocks[0]) * CHANGED_BLOCKS_HASH);
387
memset(keycache->file_blocks, 0,
388
sizeof(keycache->file_blocks[0]) * CHANGED_BLOCKS_HASH);
392
/* myisam_key_buffer_size is specified too small. Disable the cache. */
393
keycache->can_be_used= 0;
396
keycache->blocks= keycache->disk_blocks > 0 ? keycache->disk_blocks : 0;
397
return((int) keycache->disk_blocks);
401
keycache->disk_blocks= 0;
403
if (keycache->block_mem)
405
free(keycache->block_mem);
406
keycache->block_mem= NULL;
408
if (keycache->block_root)
410
free((unsigned char*) keycache->block_root);
411
keycache->block_root= NULL;
414
keycache->can_be_used= 0;
424
keycache pointer to a key cache data structure
425
key_cache_block_size size of blocks to keep cached data
426
use_mem total memory to use for the new key cache
427
division_limit new division limit (if not zero)
428
age_threshold new age threshold (if not zero)
431
number of blocks in the key cache, if successful,
435
The function first compares the memory size and the block size parameters
436
with the key cache values.
438
If they differ the function free the the memory allocated for the
439
old key cache blocks by calling the end_key_cache function and
440
then rebuilds the key cache with new blocks by calling
443
The function starts the operation only when all other threads
444
performing operations with the key cache let her to proceed
445
(when cnt_for_resize=0).
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)
454
if (!keycache->key_cache_inited)
455
return(keycache->disk_blocks);
457
if(key_cache_block_size == keycache->key_cache_block_size &&
458
use_mem == keycache->key_cache_mem_size)
460
change_key_cache_param(keycache, division_limit, age_threshold);
461
return(keycache->disk_blocks);
464
keycache_pthread_mutex_lock(&keycache->cache_lock);
467
We may need to wait for another thread which is doing a resize
468
already. This cannot happen in the MySQL server though. It allows
469
one resizer only. In set_var.cc keycache->in_init is used to block
472
while (keycache->in_resize)
474
wait_on_queue(&keycache->resize_queue, &keycache->cache_lock);
478
Mark the operation in progress. This blocks other threads from doing
479
a resize in parallel. It prohibits new blocks to enter the cache.
480
Read/write requests can bypass the cache during the flush phase.
482
keycache->in_resize= 1;
484
/* Need to flush only if keycache is enabled. */
485
if (keycache->can_be_used)
487
/* Start the flush phase. */
488
keycache->resize_in_flush= 1;
490
if (flush_all_key_blocks(keycache))
492
/* TODO: if this happens, we should write a warning in the log file ! */
493
keycache->resize_in_flush= 0;
495
keycache->can_be_used= 0;
499
/* End the flush phase. */
500
keycache->resize_in_flush= 0;
504
Some direct read/write operations (bypassing the cache) may still be
505
unfinished. Wait until they are done. If the key cache can be used,
506
direct I/O is done in increments of key_cache_block_size. That is,
507
every block is checked if it is in the cache. We need to wait for
508
pending I/O before re-initializing the cache, because we may change
509
the block size. Otherwise they could check for blocks at file
510
positions where the new block division has none. We do also want to
511
wait for I/O done when (if) the cache was disabled. It must not
512
run in parallel with normal cache operation.
514
while (keycache->cnt_for_resize_op)
515
wait_on_queue(&keycache->waiting_for_resize_cnt, &keycache->cache_lock);
518
Free old cache structures, allocate new structures, and initialize
519
them. Note that the cache_lock mutex and the resize_queue are left
520
untouched. We do not lose the cache_lock and will release it only at
521
the end of this function.
523
end_key_cache(keycache, 0); /* Don't free mutex */
524
/* The following will work even if use_mem is 0 */
525
blocks= init_key_cache(keycache, key_cache_block_size, use_mem,
526
division_limit, age_threshold);
530
Mark the resize finished. This allows other threads to start a
531
resize or to request new cache blocks.
533
keycache->in_resize= 0;
535
/* Signal waiting threads. */
536
release_whole_queue(&keycache->resize_queue);
538
keycache_pthread_mutex_unlock(&keycache->cache_lock);
544
Increment counter blocking resize key cache operation
546
static inline void inc_counter_for_resize_op(KEY_CACHE *keycache)
548
keycache->cnt_for_resize_op++;
553
Decrement counter blocking resize key cache operation;
554
Signal the operation to proceed when counter becomes equal zero
556
static inline void dec_counter_for_resize_op(KEY_CACHE *keycache)
558
if (!--keycache->cnt_for_resize_op)
559
release_whole_queue(&keycache->waiting_for_resize_cnt);
563
Change the key cache parameters
566
change_key_cache_param()
567
keycache pointer to a key cache data structure
568
division_limit new division limit (if not zero)
569
age_threshold new age threshold (if not zero)
575
Presently the function resets the key cache parameters
576
concerning midpoint insertion strategy - division_limit and
580
static void change_key_cache_param(KEY_CACHE *keycache, uint32_t division_limit,
581
uint32_t age_threshold)
583
keycache_pthread_mutex_lock(&keycache->cache_lock);
585
keycache->min_warm_blocks= (keycache->disk_blocks *
586
division_limit / 100 + 1);
588
keycache->age_threshold= (keycache->disk_blocks *
589
age_threshold / 100);
590
keycache_pthread_mutex_unlock(&keycache->cache_lock);
272
607
void end_key_cache(KEY_CACHE *keycache, bool cleanup)
609
if (!keycache->key_cache_inited)
612
if (keycache->disk_blocks > 0)
614
if (keycache->block_mem)
616
free(keycache->block_mem);
617
keycache->block_mem= NULL;
618
free((unsigned char*) keycache->block_root);
619
keycache->block_root= NULL;
621
keycache->disk_blocks= -1;
622
/* Reset blocks_changed to be safe if flush_all_key_blocks is called */
623
keycache->blocks_changed= 0;
628
pthread_mutex_destroy(&keycache->cache_lock);
629
keycache->key_cache_inited= keycache->can_be_used= 0;
276
632
} /* end_key_cache */
636
Link a thread into double-linked queue of waiting threads.
640
wqueue pointer to the queue structure
641
thread pointer to the thread to be added to the queue
647
Queue is represented by a circular list of the thread structures
648
The list is double-linked of the type (**prev,*next), accessed by
649
a pointer to the last element.
652
static void link_into_queue(KEYCACHE_WQUEUE *wqueue,
653
internal::st_my_thread_var *thread)
655
internal::st_my_thread_var *last;
657
assert(!thread->next && !thread->prev);
658
if (! (last= wqueue->last_thread))
661
thread->next= thread;
662
thread->prev= &thread->next;
666
thread->prev= last->next->prev;
667
last->next->prev= &thread->next;
668
thread->next= last->next;
671
wqueue->last_thread= thread;
675
Unlink a thread from double-linked queue of waiting threads
679
wqueue pointer to the queue structure
680
thread pointer to the thread to be removed from the queue
686
See NOTES for link_into_queue
689
static void unlink_from_queue(KEYCACHE_WQUEUE *wqueue,
690
internal::st_my_thread_var *thread)
692
assert(thread->next && thread->prev);
693
if (thread->next == thread)
694
/* The queue contains only one member */
695
wqueue->last_thread= NULL;
698
thread->next->prev= thread->prev;
699
*thread->prev=thread->next;
700
if (wqueue->last_thread == thread)
701
wqueue->last_thread= STRUCT_PTR(internal::st_my_thread_var, next,
710
Add a thread to single-linked queue of waiting threads
714
wqueue Pointer to the queue structure.
715
mutex Cache_lock to acquire after awake.
721
Queue is represented by a circular list of the thread structures
722
The list is single-linked of the type (*next), accessed by a pointer
725
The function protects against stray signals by verifying that the
726
current thread is unlinked from the queue when awaking. However,
727
since several threads can wait for the same event, it might be
728
necessary for the caller of the function to check again if the
729
condition for awake is indeed matched.
732
static void wait_on_queue(KEYCACHE_WQUEUE *wqueue,
733
pthread_mutex_t *mutex)
735
internal::st_my_thread_var *last;
736
internal::st_my_thread_var *thread= my_thread_var;
739
assert(!thread->next);
740
assert(!thread->prev); /* Not required, but must be true anyway. */
741
if (! (last= wqueue->last_thread))
742
thread->next= thread;
745
thread->next= last->next;
748
wqueue->last_thread= thread;
751
Wait until thread is removed from queue by the signalling thread.
752
The loop protects against stray signals.
756
keycache_pthread_cond_wait(&thread->suspend, mutex);
758
while (thread->next);
763
Remove all threads from queue signaling them to proceed
766
release_whole_queue()
767
wqueue pointer to the queue structure
773
See notes for wait_on_queue().
774
When removed from the queue each thread is signaled via condition
775
variable thread->suspend.
778
static void release_whole_queue(KEYCACHE_WQUEUE *wqueue)
780
internal::st_my_thread_var *last;
781
internal::st_my_thread_var *next;
782
internal::st_my_thread_var *thread;
784
/* Queue may be empty. */
785
if (!(last= wqueue->last_thread))
792
/* Signal the thread. */
793
keycache_pthread_cond_signal(&thread->suspend);
794
/* Take thread from queue. */
798
while (thread != last);
800
/* Now queue is definitely empty. */
801
wqueue->last_thread= NULL;
806
Unlink a block from the chain of dirty/clean blocks
808
static void unlink_changed(BLOCK_LINK *block)
810
assert(block->prev_changed && *block->prev_changed == block);
811
if (block->next_changed)
812
block->next_changed->prev_changed= block->prev_changed;
813
*block->prev_changed= block->next_changed;
814
block->next_changed= NULL;
815
block->prev_changed= NULL;
820
Link a block into the chain of dirty/clean blocks
823
static void link_changed(BLOCK_LINK *block, BLOCK_LINK **phead)
825
assert(!block->next_changed);
826
assert(!block->prev_changed);
827
block->prev_changed= phead;
828
if ((block->next_changed= *phead))
829
(*phead)->prev_changed= &block->next_changed;
835
Link a block in a chain of clean blocks of a file.
839
keycache Key cache handle
840
block Block to relink
841
file File to be linked to
842
unlink If to unlink first
845
Unlink a block from whichever chain it is linked in, if it's
846
asked for, and link it to the chain of clean blocks of the
850
Please do never set/clear BLOCK_CHANGED outside of
851
link_to_file_list() or link_to_changed_list().
852
You would risk to damage correct counting of changed blocks
853
and to find blocks in the wrong hash.
859
static void link_to_file_list(KEY_CACHE *keycache,
860
BLOCK_LINK *block, int file,
863
assert(block->status & BLOCK_IN_USE);
864
assert(block->hash_link && block->hash_link->block == block);
865
assert(block->hash_link->file == file);
867
unlink_changed(block);
868
link_changed(block, &keycache->file_blocks[FILE_HASH(file)]);
869
if (block->status & BLOCK_CHANGED)
871
block->status&= ~BLOCK_CHANGED;
872
keycache->blocks_changed--;
873
keycache->global_blocks_changed--;
879
Re-link a block from the clean chain to the dirty chain of a file.
882
link_to_changed_list()
883
keycache key cache handle
884
block block to relink
887
Unlink a block from the chain of clean blocks of a file
888
and link it to the chain of dirty blocks of the same file.
891
Please do never set/clear BLOCK_CHANGED outside of
892
link_to_file_list() or link_to_changed_list().
893
You would risk to damage correct counting of changed blocks
894
and to find blocks in the wrong hash.
900
static void link_to_changed_list(KEY_CACHE *keycache,
903
assert(block->status & BLOCK_IN_USE);
904
assert(!(block->status & BLOCK_CHANGED));
905
assert(block->hash_link && block->hash_link->block == block);
907
unlink_changed(block);
909
&keycache->changed_blocks[FILE_HASH(block->hash_link->file)]);
910
block->status|=BLOCK_CHANGED;
911
keycache->blocks_changed++;
912
keycache->global_blocks_changed++;
917
Link a block to the LRU chain at the beginning or at the end of
922
keycache pointer to a key cache data structure
923
block pointer to the block to link to the LRU chain
924
hot <-> to link the block into the hot subchain
925
at_end <-> to link the block at the end of the subchain
931
The LRU ring is represented by a circular list of block structures.
932
The list is double-linked of the type (**prev,*next) type.
933
The LRU ring is divided into two parts - hot and warm.
934
There are two pointers to access the last blocks of these two
935
parts. The beginning of the warm part follows right after the
937
Only blocks of the warm part can be used for eviction.
938
The first block from the beginning of this subchain is always
939
taken for eviction (keycache->last_used->next)
941
LRU chain: +------+ H O T +------+
942
+----| end |----...<----| beg |----+
943
| +------+last +------+ |
944
v<-link in latest hot (new end) |
945
| link in latest warm (new end)->^
946
| +------+ W A R M +------+ |
947
+----| beg |---->...----| end |----+
951
It is also possible that the block is selected for eviction and thus
952
not linked in the LRU ring.
955
static void link_block(KEY_CACHE *keycache, BLOCK_LINK *block, bool hot,
961
assert((block->status & ~BLOCK_CHANGED) == (BLOCK_READ | BLOCK_IN_USE));
962
assert(block->hash_link); /*backptr to block NULL from free_block()*/
963
assert(!block->requests);
964
assert(block->prev_changed && *block->prev_changed == block);
965
assert(!block->next_used);
966
assert(!block->prev_used);
967
if (!hot && keycache->waiting_for_block.last_thread)
969
/* Signal that in the LRU warm sub-chain an available block has appeared */
970
internal::st_my_thread_var *last_thread=
971
keycache->waiting_for_block.last_thread;
972
internal::st_my_thread_var *first_thread= last_thread->next;
973
internal::st_my_thread_var *next_thread= first_thread;
974
HASH_LINK *hash_link= (HASH_LINK *) first_thread->opt_info;
975
internal::st_my_thread_var *thread;
979
next_thread= thread->next;
981
We notify about the event all threads that ask
982
for the same page as the first thread in the queue
984
if ((HASH_LINK *) thread->opt_info == hash_link)
986
keycache_pthread_cond_signal(&thread->suspend);
987
unlink_from_queue(&keycache->waiting_for_block, thread);
991
while (thread != last_thread);
992
hash_link->block= block;
994
NOTE: We assigned the block to the hash_link and signalled the
995
requesting thread(s). But it is possible that other threads runs
996
first. These threads see the hash_link assigned to a block which
997
is assigned to another hash_link and not marked BLOCK_IN_SWITCH.
998
This can be a problem for functions that do not select the block
999
via its hash_link: flush and free. They do only see a block which
1000
is in a "normal" state and don't know that it will be evicted soon.
1002
We cannot set BLOCK_IN_SWITCH here because only one of the
1003
requesting threads must handle the eviction. All others must wait
1004
for it to complete. If we set the flag here, the threads would not
1005
know who is in charge of the eviction. Without the flag, the first
1006
thread takes the stick and sets the flag.
1008
But we need to note in the block that is has been selected for
1009
eviction. It must not be freed. The evicting thread will not
1010
expect the block in the free list. Before freeing we could also
1011
check if block->requests > 1. But I think including another flag
1012
in the check of block->status is slightly more efficient and
1013
probably easier to read.
1015
block->status|= BLOCK_IN_EVICTION;
1018
pins= hot ? &keycache->used_ins : &keycache->used_last;
1022
ins->next_used->prev_used= &block->next_used;
1023
block->next_used= ins->next_used;
1024
block->prev_used= &ins->next_used;
1025
ins->next_used= block;
1031
/* The LRU ring is empty. Let the block point to itself. */
1032
keycache->used_last= keycache->used_ins= block->next_used= block;
1033
block->prev_used= &block->next_used;
1039
Unlink a block from the LRU chain
1043
keycache pointer to a key cache data structure
1044
block pointer to the block to unlink from the LRU chain
1050
See NOTES for link_block
1053
static void unlink_block(KEY_CACHE *keycache, BLOCK_LINK *block)
1055
assert((block->status & ~BLOCK_CHANGED) == (BLOCK_READ | BLOCK_IN_USE));
1056
assert(block->hash_link); /*backptr to block NULL from free_block()*/
1057
assert(!block->requests);
1058
assert(block->prev_changed && *block->prev_changed == block);
1059
assert(block->next_used && block->prev_used &&
1060
(block->next_used->prev_used == &block->next_used) &&
1061
(*block->prev_used == block));
1062
if (block->next_used == block)
1063
/* The list contains only one member */
1064
keycache->used_last= keycache->used_ins= NULL;
1067
block->next_used->prev_used= block->prev_used;
1068
*block->prev_used= block->next_used;
1069
if (keycache->used_last == block)
1070
keycache->used_last= STRUCT_PTR(BLOCK_LINK, next_used, block->prev_used);
1071
if (keycache->used_ins == block)
1072
keycache->used_ins=STRUCT_PTR(BLOCK_LINK, next_used, block->prev_used);
1074
block->next_used= NULL;
1075
block->prev_used= NULL;
1080
Register requests for a block.
1084
keycache Pointer to a key cache data structure.
1085
block Pointer to the block to register a request on.
1086
count Number of requests. Always 1.
1089
The first request unlinks the block from the LRU ring. This means
1090
that it is protected against eveiction.
1095
static void reg_requests(KEY_CACHE *keycache, BLOCK_LINK *block, int count)
1097
assert(block->status & BLOCK_IN_USE);
1098
assert(block->hash_link);
1100
if (!block->requests)
1101
unlink_block(keycache, block);
1102
block->requests+=count;
1107
Unregister request for a block
1108
linking it to the LRU chain if it's the last request
1112
keycache pointer to a key cache data structure
1113
block pointer to the block to link to the LRU chain
1114
at_end <-> to link the block at the end of the LRU chain
1120
Every linking to the LRU ring decrements by one a special block
1121
counter (if it's positive). If the at_end parameter is true the block is
1122
added either at the end of warm sub-chain or at the end of hot sub-chain.
1123
It is added to the hot subchain if its counter is zero and number of
1124
blocks in warm sub-chain is not less than some low limit (determined by
1125
the division_limit parameter). Otherwise the block is added to the warm
1126
sub-chain. If the at_end parameter is false the block is always added
1127
at beginning of the warm sub-chain.
1128
Thus a warm block can be promoted to the hot sub-chain when its counter
1129
becomes zero for the first time.
1130
At the same time the block at the very beginning of the hot subchain
1131
might be moved to the beginning of the warm subchain if it stays untouched
1132
for a too long time (this time is determined by parameter age_threshold).
1134
It is also possible that the block is selected for eviction and thus
1135
not linked in the LRU ring.
1138
static void unreg_request(KEY_CACHE *keycache,
1139
BLOCK_LINK *block, int at_end)
1141
assert(block->status & (BLOCK_READ | BLOCK_IN_USE));
1142
assert(block->hash_link); /*backptr to block NULL from free_block()*/
1143
assert(block->requests);
1144
assert(block->prev_changed && *block->prev_changed == block);
1145
assert(!block->next_used);
1146
assert(!block->prev_used);
1147
if (! --block->requests)
1150
if (block->hits_left)
1152
hot= !block->hits_left && at_end &&
1153
keycache->warm_blocks > keycache->min_warm_blocks;
1156
if (block->temperature == BLOCK_WARM)
1157
keycache->warm_blocks--;
1158
block->temperature= BLOCK_HOT;
1160
link_block(keycache, block, hot, (bool)at_end);
1161
block->last_hit_time= keycache->keycache_time;
1162
keycache->keycache_time++;
1164
At this place, the block might be in the LRU ring or not. If an
1165
evicter was waiting for a block, it was selected for eviction and
1166
not linked in the LRU ring.
1170
Check if we should link a hot block to the warm block sub-chain.
1171
It is possible that we select the same block as above. But it can
1172
also be another block. In any case a block from the LRU ring is
1173
selected. In other words it works even if the above block was
1174
selected for eviction and not linked in the LRU ring. Since this
1175
happens only if the LRU ring is empty, the block selected below
1176
would be NULL and the rest of the function skipped.
1178
block= keycache->used_ins;
1179
if (block && keycache->keycache_time - block->last_hit_time >
1180
keycache->age_threshold)
1182
unlink_block(keycache, block);
1183
link_block(keycache, block, 0, 0);
1184
if (block->temperature != BLOCK_WARM)
1186
keycache->warm_blocks++;
1187
block->temperature= BLOCK_WARM;
1194
Remove a reader of the page in block
1197
static void remove_reader(BLOCK_LINK *block)
1199
assert(block->status & (BLOCK_READ | BLOCK_IN_USE));
1200
assert(block->hash_link && block->hash_link->block == block);
1201
assert(block->prev_changed && *block->prev_changed == block);
1202
assert(!block->next_used);
1203
assert(!block->prev_used);
1204
assert(block->hash_link->requests);
1205
if (! --block->hash_link->requests && block->condvar)
1206
keycache_pthread_cond_signal(block->condvar);
1211
Wait until the last reader of the page in block
1212
signals on its termination
1215
static void wait_for_readers(KEY_CACHE *keycache,
1218
internal::st_my_thread_var *thread= my_thread_var;
1219
assert(block->status & (BLOCK_READ | BLOCK_IN_USE));
1220
assert(!(block->status & (BLOCK_ERROR | BLOCK_IN_FLUSH |
1222
assert(block->hash_link);
1223
assert(block->hash_link->block == block);
1224
/* Linked in file_blocks or changed_blocks hash. */
1225
assert(block->prev_changed && *block->prev_changed == block);
1226
/* Not linked in LRU ring. */
1227
assert(!block->next_used);
1228
assert(!block->prev_used);
1229
while (block->hash_link->requests)
1231
/* There must be no other waiter. We have no queue here. */
1232
assert(!block->condvar);
1233
block->condvar= &thread->suspend;
1234
keycache_pthread_cond_wait(&thread->suspend, &keycache->cache_lock);
1235
block->condvar= NULL;
280
1241
Add a hash link to a bucket in the hash_table
1255
Remove a hash link from the hash table
1258
static void unlink_hash(KEY_CACHE *keycache, HASH_LINK *hash_link)
1260
assert(hash_link->requests == 0);
1261
if ((*hash_link->prev= hash_link->next))
1262
hash_link->next->prev= hash_link->prev;
1263
hash_link->block= NULL;
1264
if (keycache->waiting_for_hash_link.last_thread)
1266
/* Signal that a free hash link has appeared */
1267
internal::st_my_thread_var *last_thread=
1268
keycache->waiting_for_hash_link.last_thread;
1269
internal::st_my_thread_var *first_thread= last_thread->next;
1270
internal::st_my_thread_var *next_thread= first_thread;
1271
KEYCACHE_PAGE *first_page= (KEYCACHE_PAGE *) (first_thread->opt_info);
1272
internal::st_my_thread_var *thread;
1274
hash_link->file= first_page->file;
1275
hash_link->diskpos= first_page->filepos;
1278
KEYCACHE_PAGE *page;
1279
thread= next_thread;
1280
page= (KEYCACHE_PAGE *) thread->opt_info;
1281
next_thread= thread->next;
1283
We notify about the event all threads that ask
1284
for the same page as the first thread in the queue
1286
if (page->file == hash_link->file && page->filepos == hash_link->diskpos)
1288
keycache_pthread_cond_signal(&thread->suspend);
1289
unlink_from_queue(&keycache->waiting_for_hash_link, thread);
1292
while (thread != last_thread);
1293
link_hash(&keycache->hash_root[KEYCACHE_HASH(hash_link->file,
1294
hash_link->diskpos)],
1298
hash_link->next= keycache->free_hash_list;
1299
keycache->free_hash_list= hash_link;
1304
Get the hash link for a page
1307
static HASH_LINK *get_hash_link(KEY_CACHE *keycache,
1308
int file, internal::my_off_t filepos)
1310
register HASH_LINK *hash_link, **start;
1314
Find the bucket in the hash table for the pair (file, filepos);
1315
start contains the head of the bucket list,
1316
hash_link points to the first member of the list
1318
hash_link= *(start= &keycache->hash_root[KEYCACHE_HASH(file, filepos)]);
1319
/* Look for an element for the pair (file, filepos) in the bucket chain */
1321
(hash_link->diskpos != filepos || hash_link->file != file))
1323
hash_link= hash_link->next;
1327
/* There is no hash link in the hash table for the pair (file, filepos) */
1328
if (keycache->free_hash_list)
1330
hash_link= keycache->free_hash_list;
1331
keycache->free_hash_list= hash_link->next;
1333
else if (keycache->hash_links_used < keycache->hash_links)
1335
hash_link= &keycache->hash_link_root[keycache->hash_links_used++];
1339
/* Wait for a free hash link */
1340
internal::st_my_thread_var *thread= my_thread_var;
1343
page.filepos= filepos;
1344
thread->opt_info= (void *) &page;
1345
link_into_queue(&keycache->waiting_for_hash_link, thread);
1346
keycache_pthread_cond_wait(&thread->suspend,
1347
&keycache->cache_lock);
1348
thread->opt_info= NULL;
1351
hash_link->file= file;
1352
hash_link->diskpos= filepos;
1353
link_hash(start, hash_link);
1355
/* Register the request for the page */
1356
hash_link->requests++;
1363
Get a block for the file page requested by a keycache read/write operation;
1364
If the page is not in the cache return a free block, if there is none
1365
return the lru block after saving its buffer if the page is dirty.
1370
keycache pointer to a key cache data structure
1371
file handler for the file to read page from
1372
filepos position of the page in the file
1373
init_hits_left how initialize the block counter for the page
1374
wrmode <-> get for writing
1375
page_st out {PAGE_READ,PAGE_TO_BE_READ,PAGE_WAIT_TO_BE_READ}
1378
Pointer to the found block if successful, 0 - otherwise
1381
For the page from file positioned at filepos the function checks whether
1382
the page is in the key cache specified by the first parameter.
1383
If this is the case it immediately returns the block.
1384
If not, the function first chooses a block for this page. If there is
1385
no not used blocks in the key cache yet, the function takes the block
1386
at the very beginning of the warm sub-chain. It saves the page in that
1387
block if it's dirty before returning the pointer to it.
1388
The function returns in the page_st parameter the following values:
1389
PAGE_READ - if page already in the block,
1390
PAGE_TO_BE_READ - if it is to be read yet by the current thread
1391
WAIT_TO_BE_READ - if it is to be read by another thread
1392
If an error occurs THE BLOCK_ERROR bit is set in the block status.
1393
It might happen that there are no blocks in LRU chain (in warm part) -
1394
all blocks are unlinked for some read/write operations. Then the function
1395
waits until first of this operations links any block back.
1398
static BLOCK_LINK *find_key_block(KEY_CACHE *keycache,
1399
int file, internal::my_off_t filepos,
1401
int wrmode, int *page_st)
1403
HASH_LINK *hash_link;
1410
If the flush phase of a resize operation fails, the cache is left
1411
unusable. This will be detected only after "goto restart".
1413
if (!keycache->can_be_used)
1417
Find the hash_link for the requested file block (file, filepos). We
1418
do always get a hash_link here. It has registered our request so
1419
that no other thread can use it for another file block until we
1420
release the request (which is done by remove_reader() usually). The
1421
hash_link can have a block assigned to it or not. If there is a
1422
block, it may be assigned to this hash_link or not. In cases where a
1423
block is evicted from the cache, it is taken from the LRU ring and
1424
referenced by the new hash_link. But the block can still be assigned
1425
to its old hash_link for some time if it needs to be flushed first,
1426
or if there are other threads still reading it.
1429
hash_link is always returned.
1430
hash_link->block can be:
1432
- not assigned to this hash_link or
1433
- assigned to this hash_link. If assigned, the block can have
1434
- invalid data (when freshly assigned) or
1435
- valid data. Valid data can be
1436
- changed over the file contents (dirty) or
1437
- not changed (clean).
1439
hash_link= get_hash_link(keycache, file, filepos);
1440
assert((hash_link->file == file) && (hash_link->diskpos == filepos));
1443
if ((block= hash_link->block) &&
1444
block->hash_link == hash_link && (block->status & BLOCK_READ))
1446
/* Assigned block with valid (changed or unchanged) contents. */
1447
page_status= PAGE_READ;
1450
else (page_status == -1)
1452
- block not assigned to this hash_link or
1453
- block assigned but not yet read from file (invalid data).
1456
if (keycache->in_resize)
1458
/* This is a request during a resize operation */
1462
internal::st_my_thread_var *thread;
1465
The file block is not in the cache. We don't need it in the
1466
cache: we are going to read or write directly to file. Cancel
1467
the request. We can simply decrement hash_link->requests because
1468
we did not release cache_lock since increasing it. So no other
1469
thread can wait for our request to become released.
1471
if (hash_link->requests == 1)
1474
We are the only one to request this hash_link (this file/pos).
1477
hash_link->requests--;
1478
unlink_hash(keycache, hash_link);
1483
More requests on the hash_link. Someone tries to evict a block
1484
for this hash_link (could have started before resizing started).
1485
This means that the LRU ring is empty. Otherwise a block could
1486
be assigned immediately. Behave like a thread that wants to
1487
evict a block for this file/pos. Add to the queue of threads
1488
waiting for a block. Wait until there is one assigned.
1490
Refresh the request on the hash-link so that it cannot be reused
1491
for another file/pos.
1493
thread= my_thread_var;
1494
thread->opt_info= (void *) hash_link;
1495
link_into_queue(&keycache->waiting_for_block, thread);
1498
keycache_pthread_cond_wait(&thread->suspend,
1499
&keycache->cache_lock);
1500
} while (thread->next);
1501
thread->opt_info= NULL;
1503
A block should now be assigned to the hash_link. But it may
1504
still need to be evicted. Anyway, we should re-check the
1505
situation. page_status must be set correctly.
1507
hash_link->requests--;
1509
} /* end of if (!block) */
1512
There is a block for this file/pos in the cache. Register a
1513
request on it. This unlinks it from the LRU ring (if it is there)
1514
and hence protects it against eviction (if not already in
1515
eviction). We need this for returning the block to the caller, for
1516
calling remove_reader() (for debugging purposes), and for calling
1517
free_block(). The only case where we don't need the request is if
1518
the block is in eviction. In that case we have to unregister the
1521
reg_requests(keycache, block, 1);
1523
if (page_status != PAGE_READ)
1526
- block not assigned to this hash_link or
1527
- block assigned but not yet read from file (invalid data).
1529
This must be a block in eviction. It will be read soon. We need
1530
to wait here until this happened. Otherwise the caller could
1531
access a wrong block or a block which is in read. While waiting
1532
we cannot lose hash_link nor block. We have registered a request
1533
on the hash_link. Everything can happen to the block but changes
1534
in the hash_link -> block relationship. In other words:
1535
everything can happen to the block but free or another completed
1538
Note that we bahave like a secondary requestor here. We just
1539
cannot return with PAGE_WAIT_TO_BE_READ. This would work for
1540
read requests and writes on dirty blocks that are not in flush
1541
only. Waiting here on COND_FOR_REQUESTED works in all
1544
assert(((block->hash_link != hash_link) &&
1545
(block->status & (BLOCK_IN_EVICTION | BLOCK_IN_SWITCH))) ||
1546
((block->hash_link == hash_link) &&
1547
!(block->status & BLOCK_READ)));
1548
wait_on_queue(&block->wqueue[COND_FOR_REQUESTED], &keycache->cache_lock);
1550
Here we can trust that the block has been assigned to this
1551
hash_link (block->hash_link == hash_link) and read into the
1552
buffer (BLOCK_READ). The worst things possible here are that the
1553
block is in free (BLOCK_REASSIGNED). But the block is still
1554
assigned to the hash_link. The freeing thread waits until we
1555
release our request on the hash_link. The block must not be
1556
again in eviction because we registered an request on it before
1559
assert(block->hash_link == hash_link);
1560
assert(block->status & (BLOCK_READ | BLOCK_IN_USE));
1561
assert(!(block->status & (BLOCK_IN_EVICTION | BLOCK_IN_SWITCH)));
1564
The block is in the cache. Assigned to the hash_link. Valid data.
1565
Note that in case of page_st == PAGE_READ, the block can be marked
1566
for eviction. In any case it can be marked for freeing.
1571
/* A reader can just read the block. */
1572
*page_st= PAGE_READ;
1573
assert((hash_link->file == file) &&
1574
(hash_link->diskpos == filepos) &&
1575
(block->hash_link == hash_link));
1580
This is a writer. No two writers for the same block can exist.
1581
This must be assured by locks outside of the key cache.
1583
assert(!(block->status & BLOCK_FOR_UPDATE));
1585
while (block->status & BLOCK_IN_FLUSH)
1588
Wait until the block is flushed to file. Do not release the
1589
request on the hash_link yet to prevent that the block is freed
1590
or reassigned while we wait. While we wait, several things can
1591
happen to the block, including another flush. But the block
1592
cannot be reassigned to another hash_link until we release our
1593
request on it. But it can be marked BLOCK_REASSIGNED from free
1594
or eviction, while they wait for us to release the hash_link.
1596
wait_on_queue(&block->wqueue[COND_FOR_SAVED], &keycache->cache_lock);
1598
If the flush phase failed, the resize could have finished while
1601
if (!keycache->in_resize)
1603
remove_reader(block);
1604
unreg_request(keycache, block, 1);
1607
assert(block->status & (BLOCK_READ | BLOCK_IN_USE));
1608
assert(!(block->status & BLOCK_FOR_UPDATE));
1609
assert(block->hash_link == hash_link);
1612
if (block->status & BLOCK_CHANGED)
1615
We want to write a block with changed contents. If the cache
1616
block size is bigger than the callers block size (e.g. MyISAM),
1617
the caller may replace part of the block only. Changes of the
1618
other part of the block must be preserved. Since the block has
1619
not yet been selected for flush, we can still add our changes.
1621
*page_st= PAGE_READ;
1622
assert((hash_link->file == file) &&
1623
(hash_link->diskpos == filepos) &&
1624
(block->hash_link == hash_link));
1629
This is a write request for a clean block. We do not want to have
1630
new dirty blocks in the cache while resizing. We will free the
1631
block and write directly to file. If the block is in eviction or
1632
in free, we just let it go.
1634
Unregister from the hash_link. This must be done before freeing
1635
the block. And it must be done if not freeing the block. Because
1636
we could have waited above, we need to call remove_reader(). Other
1637
threads could wait for us to release our request on the hash_link.
1639
remove_reader(block);
1641
/* If the block is not in eviction and not in free, we can free it. */
1642
if (!(block->status & (BLOCK_IN_EVICTION | BLOCK_IN_SWITCH |
1646
Free block as we are going to write directly to file.
1647
Although we have an exlusive lock for the updated key part,
1648
the control can be yielded by the current thread as we might
1649
have unfinished readers of other key parts in the block
1650
buffer. Still we are guaranteed not to have any readers
1651
of the key part we are writing into until the block is
1652
removed from the cache as we set the BLOCK_REASSIGNED
1653
flag (see the code below that handles reading requests).
1655
free_block(keycache, block);
1660
The block will be evicted/freed soon. Don't touch it in any way.
1661
Unregister the request that we registered above.
1663
unreg_request(keycache, block, 1);
1666
The block is still assigned to the hash_link (the file/pos that
1667
we are going to write to). Wait until the eviction/free is
1668
complete. Otherwise the direct write could complete before all
1669
readers are done with the block. So they could read outdated
1672
Since we released our request on the hash_link, it can be reused
1673
for another file/pos. Hence we cannot just check for
1674
block->hash_link == hash_link. As long as the resize is
1675
proceeding the block cannot be reassigned to the same file/pos
1676
again. So we can terminate the loop when the block is no longer
1677
assigned to this file/pos.
1681
wait_on_queue(&block->wqueue[COND_FOR_SAVED],
1682
&keycache->cache_lock);
1684
If the flush phase failed, the resize could have finished
1685
while we waited here.
1687
if (!keycache->in_resize)
1689
} while (block->hash_link &&
1690
(block->hash_link->file == file) &&
1691
(block->hash_link->diskpos == filepos));
1696
if (page_status == PAGE_READ &&
1697
(block->status & (BLOCK_IN_EVICTION | BLOCK_IN_SWITCH |
1701
This is a request for a block to be removed from cache. The block
1702
is assigned to this hash_link and contains valid data, but is
1703
marked for eviction or to be freed. Possible reasons why it has
1704
not yet been evicted/freed can be a flush before reassignment
1705
(BLOCK_IN_SWITCH), readers of the block have not finished yet
1706
(BLOCK_REASSIGNED), or the evicting thread did not yet awake after
1707
the block has been selected for it (BLOCK_IN_EVICTION).
1709
Only reading requests can proceed until the old dirty page is flushed,
1710
all others are to be suspended, then resubmitted
1712
if (!wrmode && !(block->status & BLOCK_REASSIGNED))
1715
This is a read request and the block not yet reassigned. We can
1716
register our request and proceed. This unlinks the block from
1717
the LRU ring and protects it against eviction.
1719
reg_requests(keycache, block, 1);
1724
Either this is a write request for a block that is in eviction
1725
or in free. We must not use it any more. Instead we must evict
1726
another block. But we cannot do this before the eviction/free is
1727
done. Otherwise we would find the same hash_link + block again
1730
Or this is a read request for a block in eviction/free that does
1731
not require a flush, but waits for readers to finish with the
1732
block. We do not read this block to let the eviction/free happen
1733
as soon as possible. Again we must wait so that we don't find
1734
the same hash_link + block again and again.
1736
assert(hash_link->requests);
1737
hash_link->requests--;
1738
wait_on_queue(&block->wqueue[COND_FOR_SAVED], &keycache->cache_lock);
1740
The block is no longer assigned to this hash_link.
1749
This is a request for a new block or for a block not to be removed.
1752
- block not assigned to this hash_link or
1753
- block assigned but not yet read from file,
1755
- block assigned with valid (changed or unchanged) data and
1756
- it will not be reassigned/freed.
1760
/* No block is assigned to the hash_link yet. */
1761
if (keycache->blocks_unused)
1763
if (keycache->free_block_list)
1765
/* There is a block in the free list. */
1766
block= keycache->free_block_list;
1767
keycache->free_block_list= block->next_used;
1768
block->next_used= NULL;
1772
/* There are some never used blocks, take first of them */
1773
assert(keycache->blocks_used <
1774
(uint32_t) keycache->disk_blocks);
1775
block= &keycache->block_root[keycache->blocks_used];
1776
block->buffer= ADD_TO_PTR(keycache->block_mem,
1777
((uint32_t) keycache->blocks_used*
1778
keycache->key_cache_block_size),
1780
keycache->blocks_used++;
1781
assert(!block->next_used);
1783
assert(!block->prev_used);
1784
assert(!block->next_changed);
1785
assert(!block->prev_changed);
1786
assert(!block->hash_link);
1787
assert(!block->status);
1788
assert(!block->requests);
1789
keycache->blocks_unused--;
1790
block->status= BLOCK_IN_USE;
1792
block->offset= keycache->key_cache_block_size;
1794
block->temperature= BLOCK_COLD;
1795
block->hits_left= init_hits_left;
1796
block->last_hit_time= 0;
1797
block->hash_link= hash_link;
1798
hash_link->block= block;
1799
link_to_file_list(keycache, block, file, 0);
1800
page_status= PAGE_TO_BE_READ;
1805
There are no free blocks and no never used blocks, use a block
1809
if (! keycache->used_last)
1812
The LRU ring is empty. Wait until a new block is added to
1813
it. Several threads might wait here for the same hash_link,
1814
all of them must get the same block. While waiting for a
1815
block, after a block is selected for this hash_link, other
1816
threads can run first before this one awakes. During this
1817
time interval other threads find this hash_link pointing to
1818
the block, which is still assigned to another hash_link. In
1819
this case the block is not marked BLOCK_IN_SWITCH yet, but
1820
it is marked BLOCK_IN_EVICTION.
1823
internal::st_my_thread_var *thread= my_thread_var;
1824
thread->opt_info= (void *) hash_link;
1825
link_into_queue(&keycache->waiting_for_block, thread);
1828
keycache_pthread_cond_wait(&thread->suspend,
1829
&keycache->cache_lock);
1831
while (thread->next);
1832
thread->opt_info= NULL;
1833
/* Assert that block has a request registered. */
1834
assert(hash_link->block->requests);
1835
/* Assert that block is not in LRU ring. */
1836
assert(!hash_link->block->next_used);
1837
assert(!hash_link->block->prev_used);
1840
If we waited above, hash_link->block has been assigned by
1841
link_block(). Otherwise it is still NULL. In the latter case
1842
we need to grab a block from the LRU ring ourselves.
1844
block= hash_link->block;
1847
/* Select the last block from the LRU ring. */
1848
block= keycache->used_last->next_used;
1849
block->hits_left= init_hits_left;
1850
block->last_hit_time= 0;
1851
hash_link->block= block;
1853
Register a request on the block. This unlinks it from the
1854
LRU ring and protects it against eviction.
1856
assert(!block->requests);
1857
reg_requests(keycache, block,1);
1859
We do not need to set block->status|= BLOCK_IN_EVICTION here
1860
because we will set block->status|= BLOCK_IN_SWITCH
1861
immediately without releasing the lock in between. This does
1862
also support debugging. When looking at the block, one can
1863
see if the block has been selected by link_block() after the
1864
LRU ring was empty, or if it was grabbed directly from the
1865
LRU ring in this branch.
1870
If we had to wait above, there is a small chance that another
1871
thread grabbed this block for the same file block already. But
1872
in most cases the first condition is true.
1874
if (block->hash_link != hash_link &&
1875
! (block->status & BLOCK_IN_SWITCH) )
1877
/* this is a primary request for a new page */
1878
block->status|= BLOCK_IN_SWITCH;
1880
if (block->status & BLOCK_CHANGED)
1882
/* The block contains a dirty page - push it out of the cache */
1884
if (block->status & BLOCK_IN_FLUSH)
1887
The block is marked for flush. If we do not wait here,
1888
it could happen that we write the block, reassign it to
1889
another file block, then, before the new owner can read
1890
the new file block, the flusher writes the cache block
1891
(which still has the old contents) to the new file block!
1893
wait_on_queue(&block->wqueue[COND_FOR_SAVED],
1894
&keycache->cache_lock);
1896
The block is marked BLOCK_IN_SWITCH. It should be left
1897
alone except for reading. No free, no write.
1899
assert(block->status & (BLOCK_READ | BLOCK_IN_USE));
1900
assert(!(block->status & (BLOCK_REASSIGNED |
1902
BLOCK_FOR_UPDATE)));
1906
block->status|= BLOCK_IN_FLUSH | BLOCK_IN_FLUSHWRITE;
1908
BLOCK_IN_EVICTION may be true or not. Other flags must
1911
assert((block->status & ~BLOCK_IN_EVICTION) ==
1912
(BLOCK_READ | BLOCK_IN_SWITCH |
1913
BLOCK_IN_FLUSH | BLOCK_IN_FLUSHWRITE |
1914
BLOCK_CHANGED | BLOCK_IN_USE));
1915
assert(block->hash_link);
1917
keycache_pthread_mutex_unlock(&keycache->cache_lock);
1919
The call is thread safe because only the current
1920
thread might change the block->hash_link value
1922
error= (pwrite(block->hash_link->file,
1923
block->buffer+block->offset,
1924
block->length - block->offset,
1925
block->hash_link->diskpos+ block->offset) == 0);
1926
keycache_pthread_mutex_lock(&keycache->cache_lock);
1928
/* Block status must not have changed. */
1929
assert((block->status & ~BLOCK_IN_EVICTION) ==
1930
(BLOCK_READ | BLOCK_IN_SWITCH |
1931
BLOCK_IN_FLUSH | BLOCK_IN_FLUSHWRITE |
1932
BLOCK_CHANGED | BLOCK_IN_USE));
1933
keycache->global_cache_write++;
1937
block->status|= BLOCK_REASSIGNED;
1939
The block comes from the LRU ring. It must have a hash_link
1942
assert(block->hash_link);
1943
if (block->hash_link)
1946
All pending requests for this page must be resubmitted.
1947
This must be done before waiting for readers. They could
1948
wait for the flush to complete. And we must also do it
1949
after the wait. Flushers might try to free the block while
1950
we wait. They would wait until the reassignment is
1951
complete. Also the block status must reflect the correct
1952
situation: The block is not changed nor in flush any more.
1953
Note that we must not change the BLOCK_CHANGED flag
1954
outside of link_to_file_list() so that it is always in the
1955
correct queue and the *blocks_changed counters are
1958
block->status&= ~(BLOCK_IN_FLUSH | BLOCK_IN_FLUSHWRITE);
1959
link_to_file_list(keycache, block, block->hash_link->file, 1);
1960
release_whole_queue(&block->wqueue[COND_FOR_SAVED]);
1962
The block is still assigned to its old hash_link.
1963
Wait until all pending read requests
1964
for this page are executed
1965
(we could have avoided this waiting, if we had read
1966
a page in the cache in a sweep, without yielding control)
1968
wait_for_readers(keycache, block);
1969
assert(block->hash_link && block->hash_link->block == block &&
1970
block->prev_changed);
1971
/* The reader must not have been a writer. */
1972
assert(!(block->status & BLOCK_CHANGED));
1974
/* Wake flushers that might have found the block in between. */
1975
release_whole_queue(&block->wqueue[COND_FOR_SAVED]);
1977
/* Remove the hash link for the old file block from the hash. */
1978
unlink_hash(keycache, block->hash_link);
1981
For sanity checks link_to_file_list() asserts that block
1982
and hash_link refer to each other. Hence we need to assign
1983
the hash_link first, but then we would not know if it was
1984
linked before. Hence we would not know if to unlink it. So
1985
unlink it here and call link_to_file_list(..., false).
1987
unlink_changed(block);
1989
block->status= error ? BLOCK_ERROR : BLOCK_IN_USE ;
1991
block->offset= keycache->key_cache_block_size;
1992
block->hash_link= hash_link;
1993
link_to_file_list(keycache, block, file, 0);
1994
page_status= PAGE_TO_BE_READ;
1996
assert(block->hash_link->block == block);
1997
assert(hash_link->block->hash_link == hash_link);
2002
Either (block->hash_link == hash_link),
2003
or (block->status & BLOCK_IN_SWITCH).
2005
This is for secondary requests for a new file block only.
2006
Either it is already assigned to the new hash_link meanwhile
2007
(if we had to wait due to empty LRU), or it is already in
2008
eviction by another thread. Since this block has been
2009
grabbed from the LRU ring and attached to this hash_link,
2010
another thread cannot grab the same block from the LRU ring
2011
anymore. If the block is in eviction already, it must become
2012
attached to the same hash_link and as such destined for the
2015
page_status= (((block->hash_link == hash_link) &&
2016
(block->status & BLOCK_READ)) ?
2017
PAGE_READ : PAGE_WAIT_TO_BE_READ);
2024
Block is not NULL. This hash_link points to a block.
2026
- block not assigned to this hash_link (yet) or
2027
- block assigned but not yet read from file,
2029
- block assigned with valid (changed or unchanged) data and
2030
- it will not be reassigned/freed.
2032
The first condition means hash_link points to a block in
2033
eviction. This is not necessarily marked by BLOCK_IN_SWITCH yet.
2034
But then it is marked BLOCK_IN_EVICTION. See the NOTE in
2035
link_block(). In both cases it is destined for this hash_link
2036
and its file block address. When this hash_link got its block
2037
address, the block was removed from the LRU ring and cannot be
2038
selected for eviction (for another hash_link) again.
2040
Register a request on the block. This is another protection
2043
assert(((block->hash_link != hash_link) &&
2044
(block->status & (BLOCK_IN_EVICTION | BLOCK_IN_SWITCH))) ||
2045
((block->hash_link == hash_link) &&
2046
!(block->status & BLOCK_READ)) ||
2047
((block->status & BLOCK_READ) &&
2048
!(block->status & (BLOCK_IN_EVICTION | BLOCK_IN_SWITCH))));
2049
reg_requests(keycache, block, 1);
2050
page_status= (((block->hash_link == hash_link) &&
2051
(block->status & BLOCK_READ)) ?
2052
PAGE_READ : PAGE_WAIT_TO_BE_READ);
2056
assert(page_status != -1);
2057
/* Same assert basically, but be very sure. */
2059
/* Assert that block has a request and is not in LRU ring. */
2060
assert(block->requests);
2061
assert(!block->next_used);
2062
assert(!block->prev_used);
2063
/* Assert that we return the correct block. */
2064
assert((page_status == PAGE_WAIT_TO_BE_READ) ||
2065
((block->hash_link->file == file) &&
2066
(block->hash_link->diskpos == filepos)));
2067
*page_st=page_status;
2074
Read into a key cache block buffer from disk.
2079
keycache pointer to a key cache data structure
2080
block block to which buffer the data is to be read
2081
read_length size of data to be read
2082
min_length at least so much data must be read
2083
primary <-> the current thread will read the data
2089
The function either reads a page data from file to the block buffer,
2090
or waits until another thread reads it. What page to read is determined
2091
by a block parameter - reference to a hash link for this page.
2092
If an error occurs THE BLOCK_ERROR bit is set in the block status.
2093
We do not report error when the size of successfully read
2094
portion is less than read_length, but not less than min_length.
2097
static void read_block(KEY_CACHE *keycache,
2098
BLOCK_LINK *block, uint32_t read_length,
2099
uint32_t min_length, bool primary)
2101
uint32_t got_length;
2103
/* On entry cache_lock is locked */
2108
This code is executed only by threads that submitted primary
2109
requests. Until block->status contains BLOCK_READ, all other
2110
request for the block become secondary requests. For a primary
2111
request the block must be properly initialized.
2113
assert(((block->status & ~BLOCK_FOR_UPDATE) == BLOCK_IN_USE));
2114
assert((block->length == 0));
2115
assert((block->offset == keycache->key_cache_block_size));
2116
assert((block->requests > 0));
2118
keycache->global_cache_read++;
2119
/* Page is not in buffer yet, is to be read from disk */
2120
keycache_pthread_mutex_unlock(&keycache->cache_lock);
2122
Here other threads may step in and register as secondary readers.
2123
They will register in block->wqueue[COND_FOR_REQUESTED].
2125
got_length= pread(block->hash_link->file, block->buffer, read_length, block->hash_link->diskpos);
2126
keycache_pthread_mutex_lock(&keycache->cache_lock);
2128
The block can now have been marked for free (in case of
2129
FLUSH_RELEASE). Otherwise the state must be unchanged.
2131
assert(((block->status & ~(BLOCK_REASSIGNED |
2132
BLOCK_FOR_UPDATE)) == BLOCK_IN_USE));
2133
assert((block->length == 0));
2134
assert((block->offset == keycache->key_cache_block_size));
2135
assert((block->requests > 0));
2137
if (got_length < min_length)
2138
block->status|= BLOCK_ERROR;
2141
block->status|= BLOCK_READ;
2142
block->length= got_length;
2144
Do not set block->offset here. If this block is marked
2145
BLOCK_CHANGED later, we want to flush only the modified part. So
2146
only a writer may set block->offset down from
2147
keycache->key_cache_block_size.
2150
/* Signal that all pending requests for this page now can be processed */
2151
release_whole_queue(&block->wqueue[COND_FOR_REQUESTED]);
2156
This code is executed only by threads that submitted secondary
2157
requests. At this point it could happen that the cache block is
2158
not yet assigned to the hash_link for the requested file block.
2159
But at awake from the wait this should be the case. Unfortunately
2160
we cannot assert this here because we do not know the hash_link
2161
for the requested file block nor the file and position. So we have
2162
to assert this in the caller.
2164
wait_on_queue(&block->wqueue[COND_FOR_REQUESTED], &keycache->cache_lock);
294
2170
Read a block of data from a cached file into a buffer;
362
2392
int file, internal::my_off_t filepos, int level,
363
2393
unsigned char *buff, uint32_t length)
371
assert (!keycache->key_cache_inited);
2397
if (keycache->key_cache_inited)
2399
/* Key cache is used */
2400
register BLOCK_LINK *block;
2401
uint32_t read_length;
2404
bool locked_and_incremented= false;
2407
When the keycache is once initialized, we use the cache_lock to
2408
reliably distinguish the cases of normal operation, resizing, and
2409
disabled cache. We always increment and decrement
2410
'cnt_for_resize_op' so that a resizer can wait for pending I/O.
2412
keycache_pthread_mutex_lock(&keycache->cache_lock);
2414
We do not load index data into a disabled cache nor into an
2417
if (!keycache->can_be_used || keycache->in_resize)
2419
/* Register the pseudo I/O for the next resize. */
2420
inc_counter_for_resize_op(keycache);
2421
locked_and_incremented= true;
2422
/* Loaded data may not always be aligned to cache blocks. */
2423
offset= (uint) (filepos % keycache->key_cache_block_size);
2424
/* Load data in key_cache_block_size increments. */
2427
/* Cache could be disabled or resizing in a later iteration. */
2428
if (!keycache->can_be_used || keycache->in_resize)
2430
/* Start loading at the beginning of the cache block. */
2432
/* Do not load beyond the end of the cache block. */
2433
read_length= length;
2434
set_if_smaller(read_length, keycache->key_cache_block_size-offset);
2435
assert(read_length > 0);
2437
/* The block has been read by the caller already. */
2438
keycache->global_cache_read++;
2439
/* Request the cache block that matches file/pos. */
2440
keycache->global_cache_r_requests++;
2441
block= find_key_block(keycache, file, filepos, level, 0, &page_st);
2445
This happens only for requests submitted during key cache
2446
resize. The block is not in the cache and shall not go in.
2447
Stop loading index data.
2451
if (!(block->status & BLOCK_ERROR))
2453
if ((page_st == PAGE_WAIT_TO_BE_READ) ||
2454
((page_st == PAGE_TO_BE_READ) &&
2455
(offset || (read_length < keycache->key_cache_block_size))))
2460
this is a secondary request for a block to be read into the
2461
cache. The block is in eviction. It is not yet assigned to
2462
the requested file block (It does not point to the right
2463
hash_link). So we cannot call remove_reader() on the block.
2464
And we cannot access the hash_link directly here. We need to
2465
wait until the assignment is complete. read_block() executes
2466
the correct wait when called with primary == false.
2470
this is a primary request for a block to be read into the
2471
cache and the supplied data does not fill the whole block.
2473
This function is called on behalf of a LOAD INDEX INTO CACHE
2474
statement, which is a read-only task and allows other
2475
readers. It is possible that a parallel running reader tries
2476
to access this block. If it needs more data than has been
2477
supplied here, it would report an error. To be sure that we
2478
have all data in the block that is available in the file, we
2479
read the block ourselves.
2481
Though reading again what the caller did read already is an
2482
expensive operation, we need to do this for correctness.
2484
read_block(keycache, block, keycache->key_cache_block_size,
2485
read_length + offset, (page_st == PAGE_TO_BE_READ));
2487
A secondary request must now have the block assigned to the
2488
requested file block. It does not hurt to check it for
2489
primary requests too.
2491
assert(keycache->can_be_used);
2492
assert(block->hash_link->file == file);
2493
assert(block->hash_link->diskpos == filepos);
2494
assert(block->status & (BLOCK_READ | BLOCK_IN_USE));
2496
else if (page_st == PAGE_TO_BE_READ)
2499
This is a new block in the cache. If we come here, we have
2500
data for the whole block.
2502
assert(block->hash_link->requests);
2503
assert(block->status & BLOCK_IN_USE);
2504
assert((page_st == PAGE_TO_BE_READ) ||
2505
(block->status & BLOCK_READ));
2507
#if !defined(SERIALIZED_READ_FROM_CACHE)
2508
keycache_pthread_mutex_unlock(&keycache->cache_lock);
2510
Here other threads may step in and register as secondary readers.
2511
They will register in block->wqueue[COND_FOR_REQUESTED].
2515
/* Copy data from buff */
2516
memcpy(block->buffer+offset, buff, (size_t) read_length);
2518
#if !defined(SERIALIZED_READ_FROM_CACHE)
2519
keycache_pthread_mutex_lock(&keycache->cache_lock);
2520
assert(block->status & BLOCK_IN_USE);
2521
assert((page_st == PAGE_TO_BE_READ) ||
2522
(block->status & BLOCK_READ));
2525
After the data is in the buffer, we can declare the block
2526
valid. Now other threads do not need to register as
2527
secondary readers any more. They can immediately access the
2530
block->status|= BLOCK_READ;
2531
block->length= read_length+offset;
2533
Do not set block->offset here. If this block is marked
2534
BLOCK_CHANGED later, we want to flush only the modified part. So
2535
only a writer may set block->offset down from
2536
keycache->key_cache_block_size.
2538
/* Signal all pending requests. */
2539
release_whole_queue(&block->wqueue[COND_FOR_REQUESTED]);
2544
page_st == PAGE_READ. The block is in the buffer. All data
2545
must already be present. Blocks are always read with all
2546
data available on file. Assert that the block does not have
2547
less contents than the preloader supplies. If the caller has
2548
data beyond block->length, it means that a file write has
2549
been done while this block was in cache and not extended
2550
with the new data. If the condition is met, we can simply
2553
assert((page_st == PAGE_READ) &&
2554
(read_length + offset <= block->length));
2558
A secondary request must now have the block assigned to the
2559
requested file block. It does not hurt to check it for primary
2562
assert(block->hash_link->file == file);
2563
assert(block->hash_link->diskpos == filepos);
2564
assert(block->status & (BLOCK_READ | BLOCK_IN_USE));
2565
} /* end of if (!(block->status & BLOCK_ERROR)) */
2568
remove_reader(block);
2571
Link the block into the LRU ring if it's the last submitted
2572
request for the block. This enables eviction for the block.
2574
unreg_request(keycache, block, 1);
2576
error= (block->status & BLOCK_ERROR);
2582
filepos+= read_length+offset;
2585
} while ((length-= read_length));
2588
if (locked_and_incremented)
2589
dec_counter_for_resize_op(keycache);
2590
keycache_pthread_mutex_unlock(&keycache->cache_lock);
411
2631
(void)block_length;
2632
bool locked_and_incremented= false;
415
2635
if (!dont_write)
417
2637
/* Not used in the server. */
418
2638
/* Force writing from buff into disk. */
2639
keycache->global_cache_w_requests++;
2640
keycache->global_cache_write++;
419
2641
if (pwrite(file, buff, length, filepos) == 0)
423
assert (!keycache->key_cache_inited);
2645
if (keycache->key_cache_inited)
2647
/* Key cache is used */
2648
register BLOCK_LINK *block;
2649
uint32_t read_length;
2654
When the key cache is once initialized, we use the cache_lock to
2655
reliably distinguish the cases of normal operation, resizing, and
2656
disabled cache. We always increment and decrement
2657
'cnt_for_resize_op' so that a resizer can wait for pending I/O.
2659
keycache_pthread_mutex_lock(&keycache->cache_lock);
2661
Cache resizing has two phases: Flushing and re-initializing. In
2662
the flush phase write requests can modify dirty blocks that are
2663
not yet in flush. Otherwise they are allowed to bypass the cache.
2664
find_key_block() returns NULL in both cases (clean blocks and
2667
After the flush phase new I/O requests must wait until the
2668
re-initialization is done. The re-initialization can be done only
2669
if no I/O request is in progress. The reason is that
2670
key_cache_block_size can change. With enabled cache I/O is done in
2671
chunks of key_cache_block_size. Every chunk tries to use a cache
2672
block first. If the block size changes in the middle, a block
2673
could be missed and data could be written below a cached block.
2675
while (keycache->in_resize && !keycache->resize_in_flush)
2676
wait_on_queue(&keycache->resize_queue, &keycache->cache_lock);
2677
/* Register the I/O for the next resize. */
2678
inc_counter_for_resize_op(keycache);
2679
locked_and_incremented= true;
2680
/* Requested data may not always be aligned to cache blocks. */
2681
offset= (uint) (filepos % keycache->key_cache_block_size);
2682
/* Write data in key_cache_block_size increments. */
2685
/* Cache could be disabled in a later iteration. */
2686
if (!keycache->can_be_used)
2688
/* Start writing at the beginning of the cache block. */
2690
/* Do not write beyond the end of the cache block. */
2691
read_length= length;
2692
set_if_smaller(read_length, keycache->key_cache_block_size-offset);
2693
assert(read_length > 0);
2695
/* Request the cache block that matches file/pos. */
2696
keycache->global_cache_w_requests++;
2697
block= find_key_block(keycache, file, filepos, level, 1, &page_st);
2701
This happens only for requests submitted during key cache
2702
resize. The block is not in the cache and shall not go in.
2703
Write directly to file.
2707
/* Used in the server. */
2708
keycache->global_cache_write++;
2709
keycache_pthread_mutex_unlock(&keycache->cache_lock);
2710
if (pwrite(file, (unsigned char*) buff, read_length, filepos + offset) == 0)
2712
keycache_pthread_mutex_lock(&keycache->cache_lock);
2717
Prevent block from flushing and from being selected for to be
2718
freed. This must be set when we release the cache_lock.
2719
However, we must not set the status of the block before it is
2720
assigned to this file/pos.
2722
if (page_st != PAGE_WAIT_TO_BE_READ)
2723
block->status|= BLOCK_FOR_UPDATE;
2725
We must read the file block first if it is not yet in the cache
2726
and we do not replace all of its contents.
2728
In cases where the cache block is big enough to contain (parts
2729
of) index blocks of different indexes, our request can be
2730
secondary (PAGE_WAIT_TO_BE_READ). In this case another thread is
2731
reading the file block. If the read completes after us, it
2732
overwrites our new contents with the old contents. So we have to
2733
wait for the other thread to complete the read of this block.
2734
read_block() takes care for the wait.
2736
if (!(block->status & BLOCK_ERROR) &&
2737
((page_st == PAGE_TO_BE_READ &&
2738
(offset || read_length < keycache->key_cache_block_size)) ||
2739
(page_st == PAGE_WAIT_TO_BE_READ)))
2741
read_block(keycache, block,
2742
offset + read_length >= keycache->key_cache_block_size?
2743
offset : keycache->key_cache_block_size,
2744
offset, (page_st == PAGE_TO_BE_READ));
2745
assert(keycache->can_be_used);
2746
assert(block->status & (BLOCK_READ | BLOCK_IN_USE));
2748
Prevent block from flushing and from being selected for to be
2749
freed. This must be set when we release the cache_lock.
2750
Here we set it in case we could not set it above.
2752
block->status|= BLOCK_FOR_UPDATE;
2755
The block should always be assigned to the requested file block
2756
here. It need not be BLOCK_READ when overwriting the whole block.
2758
assert(block->hash_link->file == file);
2759
assert(block->hash_link->diskpos == filepos);
2760
assert(block->status & BLOCK_IN_USE);
2761
assert((page_st == PAGE_TO_BE_READ) || (block->status & BLOCK_READ));
2763
The block to be written must not be marked BLOCK_REASSIGNED.
2764
Otherwise it could be freed in dirty state or reused without
2765
another flush during eviction. It must also not be in flush.
2766
Otherwise the old contens may have been flushed already and
2767
the flusher could clear BLOCK_CHANGED without flushing the
2770
assert(!(block->status & BLOCK_REASSIGNED));
2772
while (block->status & BLOCK_IN_FLUSHWRITE)
2775
Another thread is flushing the block. It was dirty already.
2776
Wait until the block is flushed to file. Otherwise we could
2777
modify the buffer contents just while it is written to file.
2778
An unpredictable file block contents would be the result.
2779
While we wait, several things can happen to the block,
2780
including another flush. But the block cannot be reassigned to
2781
another hash_link until we release our request on it.
2783
wait_on_queue(&block->wqueue[COND_FOR_SAVED], &keycache->cache_lock);
2784
assert(keycache->can_be_used);
2785
assert(block->status & (BLOCK_READ | BLOCK_IN_USE));
2786
/* Still must not be marked for free. */
2787
assert(!(block->status & BLOCK_REASSIGNED));
2788
assert(block->hash_link && (block->hash_link->block == block));
2792
We could perhaps release the cache_lock during access of the
2793
data like in the other functions. Locks outside of the key cache
2794
assure that readers and a writer do not access the same range of
2795
data. Parallel accesses should happen only if the cache block
2796
contains multiple index block(fragment)s. So different parts of
2797
the buffer would be read/written. An attempt to flush during
2798
memcpy() is prevented with BLOCK_FOR_UPDATE.
2800
if (!(block->status & BLOCK_ERROR))
2802
#if !defined(SERIALIZED_READ_FROM_CACHE)
2803
keycache_pthread_mutex_unlock(&keycache->cache_lock);
2805
memcpy(block->buffer+offset, buff, (size_t) read_length);
2807
#if !defined(SERIALIZED_READ_FROM_CACHE)
2808
keycache_pthread_mutex_lock(&keycache->cache_lock);
2814
/* Not used in the server. buff has been written to disk at start. */
2815
if ((block->status & BLOCK_CHANGED) &&
2816
(!offset && read_length >= keycache->key_cache_block_size))
2817
link_to_file_list(keycache, block, block->hash_link->file, 1);
2819
else if (! (block->status & BLOCK_CHANGED))
2820
link_to_changed_list(keycache, block);
2821
block->status|=BLOCK_READ;
2823
Allow block to be selected for to be freed. Since it is marked
2824
BLOCK_CHANGED too, it won't be selected for to be freed without
2827
block->status&= ~BLOCK_FOR_UPDATE;
2828
set_if_smaller(block->offset, offset);
2829
set_if_bigger(block->length, read_length+offset);
2831
/* Threads may be waiting for the changes to be complete. */
2832
release_whole_queue(&block->wqueue[COND_FOR_REQUESTED]);
2835
If only a part of the cache block is to be replaced, and the
2836
rest has been read from file, then the cache lock has been
2837
released for I/O and it could be possible that another thread
2838
wants to evict or free the block and waits for it to be
2839
released. So we must not just decrement hash_link->requests, but
2840
also wake a waiting thread.
2842
remove_reader(block);
2845
Link the block into the LRU ring if it's the last submitted
2846
request for the block. This enables eviction for the block.
2848
unreg_request(keycache, block, 1);
2850
if (block->status & BLOCK_ERROR)
2858
filepos+= read_length+offset;
2861
} while ((length-= read_length));
425
2866
/* Key cache is not used */
428
2869
/* Used in the server. */
2870
keycache->global_cache_w_requests++;
2871
keycache->global_cache_write++;
2872
if (locked_and_incremented)
2873
keycache_pthread_mutex_unlock(&keycache->cache_lock);
429
2874
if (pwrite(file, (unsigned char*) buff, length, filepos) == 0)
2876
if (locked_and_incremented)
2877
keycache_pthread_mutex_lock(&keycache->cache_lock);
2881
if (locked_and_incremented)
2883
dec_counter_for_resize_op(keycache);
2884
keycache_pthread_mutex_unlock(&keycache->cache_lock);
2895
keycache Pointer to a key cache data structure
2896
block Pointer to the block to free
2899
Remove reference to block from hash table.
2900
Remove block from the chain of clean blocks.
2901
Add block to the free list.
2904
Block must not be free (status == 0).
2905
Block must not be in free_block_list.
2906
Block must not be in the LRU ring.
2907
Block must not be in eviction (BLOCK_IN_EVICTION | BLOCK_IN_SWITCH).
2908
Block must not be in free (BLOCK_REASSIGNED).
2909
Block must not be in flush (BLOCK_IN_FLUSH).
2910
Block must not be dirty (BLOCK_CHANGED).
2911
Block must not be in changed_blocks (dirty) hash.
2912
Block must be in file_blocks (clean) hash.
2913
Block must refer to a hash_link.
2914
Block must have a request registered on it.
2917
static void free_block(KEY_CACHE *keycache, BLOCK_LINK *block)
2920
Assert that the block is not free already. And that it is in a clean
2921
state. Note that the block might just be assigned to a hash_link and
2922
not yet read (BLOCK_READ may not be set here). In this case a reader
2923
is registered in the hash_link and free_block() will wait for it
2926
assert((block->status & BLOCK_IN_USE) &&
2927
!(block->status & (BLOCK_IN_EVICTION | BLOCK_IN_SWITCH |
2928
BLOCK_REASSIGNED | BLOCK_IN_FLUSH |
2929
BLOCK_CHANGED | BLOCK_FOR_UPDATE)));
2930
/* Assert that the block is in a file_blocks chain. */
2931
assert(block->prev_changed && *block->prev_changed == block);
2932
/* Assert that the block is not in the LRU ring. */
2933
assert(!block->next_used && !block->prev_used);
2935
IMHO the below condition (if()) makes no sense. I can't see how it
2936
could be possible that free_block() is entered with a NULL hash_link
2937
pointer. The only place where it can become NULL is in free_block()
2938
(or before its first use ever, but for those blocks free_block() is
2939
not called). I don't remove the conditional as it cannot harm, but
2940
place an assert to confirm my hypothesis. Eventually the
2941
condition (if()) can be removed.
2943
assert(block->hash_link && block->hash_link->block == block);
2944
if (block->hash_link)
2947
While waiting for readers to finish, new readers might request the
2948
block. But since we set block->status|= BLOCK_REASSIGNED, they
2949
will wait on block->wqueue[COND_FOR_SAVED]. They must be signalled
2952
block->status|= BLOCK_REASSIGNED;
2953
wait_for_readers(keycache, block);
2955
The block must not have been freed by another thread. Repeat some
2956
checks. An additional requirement is that it must be read now
2959
assert(block->hash_link && block->hash_link->block == block);
2960
assert((block->status & (BLOCK_READ | BLOCK_IN_USE |
2961
BLOCK_REASSIGNED)) &&
2962
!(block->status & (BLOCK_IN_EVICTION | BLOCK_IN_SWITCH |
2963
BLOCK_IN_FLUSH | BLOCK_CHANGED |
2964
BLOCK_FOR_UPDATE)));
2965
assert(block->prev_changed && *block->prev_changed == block);
2966
assert(!block->prev_used);
2968
Unset BLOCK_REASSIGNED again. If we hand the block to an evicting
2969
thread (through unreg_request() below), other threads must not see
2970
this flag. They could become confused.
2972
block->status&= ~BLOCK_REASSIGNED;
2974
Do not release the hash_link until the block is off all lists.
2975
At least not if we hand it over for eviction in unreg_request().
2980
Unregister the block request and link the block into the LRU ring.
2981
This enables eviction for the block. If the LRU ring was empty and
2982
threads are waiting for a block, then the block wil be handed over
2983
for eviction immediately. Otherwise we will unlink it from the LRU
2984
ring again, without releasing the lock in between. So decrementing
2985
the request counter and updating statistics are the only relevant
2986
operation in this case. Assert that there are no other requests
2989
assert(block->requests == 1);
2990
unreg_request(keycache, block, 0);
2992
Note that even without releasing the cache lock it is possible that
2993
the block is immediately selected for eviction by link_block() and
2994
thus not added to the LRU ring. In this case we must not touch the
2997
if (block->status & BLOCK_IN_EVICTION)
3000
/* Here the block must be in the LRU ring. Unlink it again. */
3001
assert(block->next_used && block->prev_used &&
3002
*block->prev_used == block);
3003
unlink_block(keycache, block);
3004
if (block->temperature == BLOCK_WARM)
3005
keycache->warm_blocks--;
3006
block->temperature= BLOCK_COLD;
3008
/* Remove from file_blocks hash. */
3009
unlink_changed(block);
3011
/* Remove reference to block from hash table. */
3012
unlink_hash(keycache, block->hash_link);
3013
block->hash_link= NULL;
3017
block->offset= keycache->key_cache_block_size;
3019
/* Enforced by unlink_changed(), but just to be sure. */
3020
assert(!block->next_changed && !block->prev_changed);
3021
/* Enforced by unlink_block(): not in LRU ring nor in free_block_list. */
3022
assert(!block->next_used && !block->prev_used);
3023
/* Insert the free block in the free list. */
3024
block->next_used= keycache->free_block_list;
3025
keycache->free_block_list= block;
3026
/* Keep track of the number of currently unused blocks. */
3027
keycache->blocks_unused++;
3029
/* All pending requests for this page must be resubmitted. */
3030
release_whole_queue(&block->wqueue[COND_FOR_SAVED]);
3034
static int cmp_sec_link(BLOCK_LINK **a, BLOCK_LINK **b)
3036
return (((*a)->hash_link->diskpos < (*b)->hash_link->diskpos) ? -1 :
3037
((*a)->hash_link->diskpos > (*b)->hash_link->diskpos) ? 1 : 0);
3042
Flush a portion of changed blocks to disk,
3043
free used blocks if requested
3046
static int flush_cached_blocks(KEY_CACHE *keycache,
3047
int file, BLOCK_LINK **cache,
3049
enum flush_type type)
3053
uint32_t count= (uint) (end-cache);
3055
/* Don't lock the cache during the flush */
3056
keycache_pthread_mutex_unlock(&keycache->cache_lock);
3058
As all blocks referred in 'cache' are marked by BLOCK_IN_FLUSH
3059
we are guarunteed no thread will change them
3061
internal::my_qsort((unsigned char*) cache, count, sizeof(*cache), (qsort_cmp) cmp_sec_link);
3063
keycache_pthread_mutex_lock(&keycache->cache_lock);
3065
Note: Do not break the loop. We have registered a request on every
3066
block in 'cache'. These must be unregistered by free_block() or
3069
for ( ; cache != end ; cache++)
3071
BLOCK_LINK *block= *cache;
3073
If the block contents is going to be changed, we abandon the flush
3074
for this block. flush_key_blocks_int() will restart its search and
3075
handle the block properly.
3077
if (!(block->status & BLOCK_FOR_UPDATE))
3079
/* Blocks coming here must have a certain status. */
3080
assert(block->hash_link);
3081
assert(block->hash_link->block == block);
3082
assert(block->hash_link->file == file);
3083
assert((block->status & ~BLOCK_IN_EVICTION) ==
3084
(BLOCK_READ | BLOCK_IN_FLUSH | BLOCK_CHANGED | BLOCK_IN_USE));
3085
block->status|= BLOCK_IN_FLUSHWRITE;
3086
keycache_pthread_mutex_unlock(&keycache->cache_lock);
3087
error= (pwrite(file,
3088
block->buffer+block->offset,
3089
block->length - block->offset,
3090
block->hash_link->diskpos+ block->offset) == 0);
3091
keycache_pthread_mutex_lock(&keycache->cache_lock);
3092
keycache->global_cache_write++;
3095
block->status|= BLOCK_ERROR;
3097
last_errno= errno ? errno : -1;
3099
block->status&= ~BLOCK_IN_FLUSHWRITE;
3100
/* Block must not have changed status except BLOCK_FOR_UPDATE. */
3101
assert(block->hash_link);
3102
assert(block->hash_link->block == block);
3103
assert(block->hash_link->file == file);
3104
assert((block->status & ~(BLOCK_FOR_UPDATE | BLOCK_IN_EVICTION)) ==
3105
(BLOCK_READ | BLOCK_IN_FLUSH | BLOCK_CHANGED | BLOCK_IN_USE));
3107
Set correct status and link in right queue for free or later use.
3108
free_block() must not see BLOCK_CHANGED and it may need to wait
3109
for readers of the block. These should not see the block in the
3110
wrong hash. If not freeing the block, we need to have it in the
3113
link_to_file_list(keycache, block, file, 1);
3116
block->status&= ~BLOCK_IN_FLUSH;
3118
Let to proceed for possible waiting requests to write to the block page.
3119
It might happen only during an operation to resize the key cache.
3121
release_whole_queue(&block->wqueue[COND_FOR_SAVED]);
3122
/* type will never be FLUSH_IGNORE_CHANGED here */
3123
if (!(type == FLUSH_KEEP || type == FLUSH_FORCE_WRITE) &&
3124
!(block->status & (BLOCK_IN_EVICTION | BLOCK_IN_SWITCH |
3128
Note that a request has been registered against the block in
3129
flush_key_blocks_int().
3131
free_block(keycache, block);
3136
Link the block into the LRU ring if it's the last submitted
3137
request for the block. This enables eviction for the block.
3138
Note that a request has been registered against the block in
3139
flush_key_blocks_int().
3141
unreg_request(keycache, block, 1);
3144
} /* end of for ( ; cache != end ; cache++) */
3150
flush all key blocks for a file to disk, but don't do any mutex locks.
3153
flush_key_blocks_int()
3154
keycache pointer to a key cache data structure
3155
file handler for the file to flush to
3156
flush_type type of the flush
3159
This function doesn't do any mutex locks because it needs to be called both
3160
from flush_key_blocks and flush_all_key_blocks (the later one does the
3161
mutex lock in the resize_key_cache() function).
3163
We do only care about changed blocks that exist when the function is
3164
entered. We do not guarantee that all changed blocks of the file are
3165
flushed if more blocks change while this function is running.
3172
static int flush_key_blocks_int(KEY_CACHE *keycache,
3173
int file, enum flush_type type)
3175
BLOCK_LINK *cache_buff[FLUSH_CACHE],**cache;
3180
if (keycache->disk_blocks > 0 &&
3181
(!internal::my_disable_flush_key_blocks || type != FLUSH_KEEP))
3183
/* Key cache exists and flush is not disabled */
3185
uint32_t count= FLUSH_CACHE;
3186
BLOCK_LINK **pos,**end;
3187
BLOCK_LINK *first_in_switch= NULL;
3188
BLOCK_LINK *last_in_flush;
3189
BLOCK_LINK *last_for_update;
3190
BLOCK_LINK *last_in_switch;
3191
BLOCK_LINK *block, *next;
3193
if (type != FLUSH_IGNORE_CHANGED)
3196
Count how many key blocks we have to cache to be able
3197
to flush all dirty pages with minimum seek moves
3200
for (block= keycache->changed_blocks[FILE_HASH(file)] ;
3202
block= block->next_changed)
3204
if ((block->hash_link->file == file) &&
3205
!(block->status & BLOCK_IN_FLUSH))
3208
assert(count<= keycache->blocks_used);
3212
Allocate a new buffer only if its bigger than the one we have.
3213
Assure that we always have some entries for the case that new
3214
changed blocks appear while we need to wait for something.
3216
if ((count > FLUSH_CACHE) &&
3217
!(cache= (BLOCK_LINK**) malloc(sizeof(BLOCK_LINK*)*count)))
3220
After a restart there could be more changed blocks than now.
3221
So we should not let count become smaller than the fixed buffer.
3223
if (cache == cache_buff)
3227
/* Retrieve the blocks and write them to a buffer to be flushed */
3229
last_in_flush= NULL;
3230
last_for_update= NULL;
3231
end= (pos= cache)+count;
3232
for (block= keycache->changed_blocks[FILE_HASH(file)] ;
3236
next= block->next_changed;
3237
if (block->hash_link->file == file)
3239
if (!(block->status & (BLOCK_IN_FLUSH | BLOCK_FOR_UPDATE)))
3242
Note: The special handling of BLOCK_IN_SWITCH is obsolete
3243
since we set BLOCK_IN_FLUSH if the eviction includes a
3244
flush. It can be removed in a later version.
3246
if (!(block->status & BLOCK_IN_SWITCH))
3249
We care only for the blocks for which flushing was not
3250
initiated by another thread and which are not in eviction.
3251
Registering a request on the block unlinks it from the LRU
3252
ring and protects against eviction.
3254
reg_requests(keycache, block, 1);
3255
if (type != FLUSH_IGNORE_CHANGED)
3257
/* It's not a temporary file */
3261
This should happen relatively seldom. Remove the
3262
request because we won't do anything with the block
3263
but restart and pick it again in the next iteration.
3265
unreg_request(keycache, block, 0);
3267
This happens only if there is not enough
3268
memory for the big block
3270
if ((error= flush_cached_blocks(keycache, file, cache,
3273
/* Do not loop infinitely trying to flush in vain. */
3274
if ((last_errno == error) && (++last_errcnt > 5))
3279
Restart the scan as some other thread might have changed
3280
the changed blocks chain: the blocks that were in switch
3281
state before the flush started have to be excluded
3286
Mark the block with BLOCK_IN_FLUSH in order not to let
3287
other threads to use it for new pages and interfere with
3288
our sequence of flushing dirty file pages. We must not
3289
set this flag before actually putting the block on the
3290
write burst array called 'cache'.
3292
block->status|= BLOCK_IN_FLUSH;
3293
/* Add block to the array for a write burst. */
3298
/* It's a temporary file */
3299
assert(!(block->status & BLOCK_REASSIGNED));
3302
free_block() must not be called with BLOCK_CHANGED. Note
3303
that we must not change the BLOCK_CHANGED flag outside of
3304
link_to_file_list() so that it is always in the correct
3305
queue and the *blocks_changed counters are correct.
3307
link_to_file_list(keycache, block, file, 1);
3308
if (!(block->status & (BLOCK_IN_EVICTION | BLOCK_IN_SWITCH)))
3310
/* A request has been registered against the block above. */
3311
free_block(keycache, block);
3316
Link the block into the LRU ring if it's the last
3317
submitted request for the block. This enables eviction
3318
for the block. A request has been registered against
3321
unreg_request(keycache, block, 1);
3328
Link the block into a list of blocks 'in switch'.
3330
WARNING: Here we introduce a place where a changed block
3331
is not in the changed_blocks hash! This is acceptable for
3332
a BLOCK_IN_SWITCH. Never try this for another situation.
3333
Other parts of the key cache code rely on changed blocks
3334
being in the changed_blocks hash.
3336
unlink_changed(block);
3337
link_changed(block, &first_in_switch);
3340
else if (type != FLUSH_KEEP)
3343
During the normal flush at end of statement (FLUSH_KEEP) we
3344
do not need to ensure that blocks in flush or update by
3345
other threads are flushed. They will be flushed by them
3346
later. In all other cases we must assure that we do not have
3347
any changed block of this file in the cache when this
3350
if (block->status & BLOCK_IN_FLUSH)
3352
/* Remember the last block found to be in flush. */
3353
last_in_flush= block;
3357
/* Remember the last block found to be selected for update. */
3358
last_for_update= block;
3365
if ((error= flush_cached_blocks(keycache, file, cache, pos, type)))
3367
/* Do not loop inifnitely trying to flush in vain. */
3368
if ((last_errno == error) && (++last_errcnt > 5))
3373
Do not restart here during the normal flush at end of statement
3374
(FLUSH_KEEP). We have now flushed at least all blocks that were
3375
changed when entering this function. In all other cases we must
3376
assure that we do not have any changed block of this file in the
3377
cache when this function returns.
3379
if (type != FLUSH_KEEP)
3385
There are no blocks to be flushed by this thread, but blocks in
3386
flush by other threads. Wait until one of the blocks is flushed.
3387
Re-check the condition for last_in_flush. We may have unlocked
3388
the cache_lock in flush_cached_blocks(). The state of the block
3391
if (last_in_flush->status & BLOCK_IN_FLUSH)
3392
wait_on_queue(&last_in_flush->wqueue[COND_FOR_SAVED],
3393
&keycache->cache_lock);
3394
/* Be sure not to lose a block. They may be flushed in random order. */
3397
if (last_for_update)
3400
There are no blocks to be flushed by this thread, but blocks for
3401
update by other threads. Wait until one of the blocks is updated.
3402
Re-check the condition for last_for_update. We may have unlocked
3403
the cache_lock in flush_cached_blocks(). The state of the block
3406
if (last_for_update->status & BLOCK_FOR_UPDATE)
3407
wait_on_queue(&last_for_update->wqueue[COND_FOR_REQUESTED],
3408
&keycache->cache_lock);
3409
/* The block is now changed. Flush it. */
3414
Wait until the list of blocks in switch is empty. The threads that
3415
are switching these blocks will relink them to clean file chains
3416
while we wait and thus empty the 'first_in_switch' chain.
3418
while (first_in_switch)
3420
wait_on_queue(&first_in_switch->wqueue[COND_FOR_SAVED],
3421
&keycache->cache_lock);
3423
Do not restart here. We have flushed all blocks that were
3424
changed when entering this function and were not marked for
3425
eviction. Other threads have now flushed all remaining blocks in
3426
the course of their eviction.
3430
if (! (type == FLUSH_KEEP || type == FLUSH_FORCE_WRITE))
3432
last_for_update= NULL;
3433
last_in_switch= NULL;
3434
uint32_t total_found= 0;
3438
Finally free all clean blocks for this file.
3439
During resize this may be run by two threads in parallel.
3444
for (block= keycache->file_blocks[FILE_HASH(file)] ;
3448
/* Remember the next block. After freeing we cannot get at it. */
3449
next= block->next_changed;
3451
/* Changed blocks cannot appear in the file_blocks hash. */
3452
assert(!(block->status & BLOCK_CHANGED));
3453
if (block->hash_link->file == file)
3455
/* We must skip blocks that will be changed. */
3456
if (block->status & BLOCK_FOR_UPDATE)
3458
last_for_update= block;
3463
We must not free blocks in eviction (BLOCK_IN_EVICTION |
3464
BLOCK_IN_SWITCH) or blocks intended to be freed
3467
if (!(block->status & (BLOCK_IN_EVICTION | BLOCK_IN_SWITCH |
3470
struct st_hash_link *next_hash_link= NULL;
3471
internal::my_off_t next_diskpos= 0;
3473
uint32_t next_status= 0;
3474
uint32_t hash_requests= 0;
3478
assert(found <= keycache->blocks_used);
3481
Register a request. This unlinks the block from the LRU
3482
ring and protects it against eviction. This is required
3485
reg_requests(keycache, block, 1);
3488
free_block() may need to wait for readers of the block.
3489
This is the moment where the other thread can move the
3490
'next' block from the chain. free_block() needs to wait
3491
if there are requests for the block pending.
3493
if (next && (hash_requests= block->hash_link->requests))
3495
/* Copy values from the 'next' block and its hash_link. */
3496
next_status= next->status;
3497
next_hash_link= next->hash_link;
3498
next_diskpos= next_hash_link->diskpos;
3499
next_file= next_hash_link->file;
3500
assert(next == next_hash_link->block);
3503
free_block(keycache, block);
3505
If we had to wait and the state of the 'next' block
3506
changed, break the inner loop. 'next' may no longer be
3507
part of the current chain.
3509
We do not want to break the loop after every free_block(),
3510
not even only after waits. The chain might be quite long
3511
and contain blocks for many files. Traversing it again and
3512
again to find more blocks for this file could become quite
3515
if (next && hash_requests &&
3516
((next_status != next->status) ||
3517
(next_hash_link != next->hash_link) ||
3518
(next_file != next_hash_link->file) ||
3519
(next_diskpos != next_hash_link->diskpos) ||
3520
(next != next_hash_link->block)))
3525
last_in_switch= block;
3528
} /* end for block in file_blocks */
3532
If any clean block has been found, we may have waited for it to
3533
become free. In this case it could be possible that another clean
3534
block became dirty. This is possible if the write request existed
3535
before the flush started (BLOCK_FOR_UPDATE). Re-check the hashes.
3541
To avoid an infinite loop, wait until one of the blocks marked
3542
for update is updated.
3544
if (last_for_update)
3546
/* We did not wait. Block must not have changed status. */
3547
assert(last_for_update->status & BLOCK_FOR_UPDATE);
3548
wait_on_queue(&last_for_update->wqueue[COND_FOR_REQUESTED],
3549
&keycache->cache_lock);
3554
To avoid an infinite loop wait until one of the blocks marked
3555
for eviction is switched.
3559
/* We did not wait. Block must not have changed status. */
3560
assert(last_in_switch->status & (BLOCK_IN_EVICTION |
3563
wait_on_queue(&last_in_switch->wqueue[COND_FOR_SAVED],
3564
&keycache->cache_lock);
3568
} /* if (! (type == FLUSH_KEEP || type == FLUSH_FORCE_WRITE)) */
3570
} /* if (keycache->disk_blocks > 0 */
3573
if (cache != cache_buff)
3574
free((unsigned char*) cache);
3576
errno=last_errno; /* Return first error */
3577
return(last_errno != 0);
438
3582
Flush all blocks for a file to disk
452
3596
int flush_key_blocks(KEY_CACHE *keycache,
453
3597
int file, enum flush_type type)
457
assert (!keycache->key_cache_inited);
3601
if (!keycache->key_cache_inited)
3604
keycache_pthread_mutex_lock(&keycache->cache_lock);
3605
/* While waiting for lock, keycache could have been ended. */
3606
if (keycache->disk_blocks > 0)
3608
inc_counter_for_resize_op(keycache);
3609
res= flush_key_blocks_int(keycache, file, type);
3610
dec_counter_for_resize_op(keycache);
3612
keycache_pthread_mutex_unlock(&keycache->cache_lock);
3618
Flush all blocks in the key cache to disk.
3621
flush_all_key_blocks()
3622
keycache pointer to key cache root structure
3626
Flushing of the whole key cache is done in two phases.
3628
1. Flush all changed blocks, waiting for them if necessary. Loop
3629
until there is no changed block left in the cache.
3631
2. Free all clean blocks. Normally this means free all blocks. The
3632
changed blocks were flushed in phase 1 and became clean. However we
3633
may need to wait for blocks that are read by other threads. While we
3634
wait, a clean block could become changed if that operation started
3635
before the resize operation started. To be safe we must restart at
3638
When we can run through the changed_blocks and file_blocks hashes
3639
without finding a block any more, then we are done.
3641
Note that we hold keycache->cache_lock all the time unless we need
3642
to wait for something.
3649
static int flush_all_key_blocks(KEY_CACHE *keycache)
3652
uint32_t total_found;
3658
safe_mutex_assert_owner(&keycache->cache_lock);
3662
Phase1: Flush all changed blocks, waiting for them if necessary.
3663
Loop until there is no changed block left in the cache.
3668
/* Step over the whole changed_blocks hash array. */
3669
for (idx= 0; idx < CHANGED_BLOCKS_HASH; idx++)
3672
If an array element is non-empty, use the first block from its
3673
chain to find a file for flush. All changed blocks for this
3674
file are flushed. So the same block will not appear at this
3675
place again with the next iteration. New writes for blocks are
3676
not accepted during the flush. If multiple files share the
3677
same hash bucket, one of them will be flushed per iteration
3678
of the outer loop of phase 1.
3680
if ((block= keycache->changed_blocks[idx]))
3684
Flush dirty blocks but do not free them yet. They can be used
3685
for reading until all other blocks are flushed too.
3687
if (flush_key_blocks_int(keycache, block->hash_link->file,
3696
Phase 2: Free all clean blocks. Normally this means free all
3697
blocks. The changed blocks were flushed in phase 1 and became
3698
clean. However we may need to wait for blocks that are read by
3699
other threads. While we wait, a clean block could become changed
3700
if that operation started before the resize operation started. To
3701
be safe we must restart at phase 1.
3706
/* Step over the whole file_blocks hash array. */
3707
for (idx= 0; idx < CHANGED_BLOCKS_HASH; idx++)
3710
If an array element is non-empty, use the first block from its
3711
chain to find a file for flush. All blocks for this file are
3712
freed. So the same block will not appear at this place again
3713
with the next iteration. If multiple files share the
3714
same hash bucket, one of them will be flushed per iteration
3715
of the outer loop of phase 2.
3717
if ((block= keycache->file_blocks[idx]))
3721
if (flush_key_blocks_int(keycache, block->hash_link->file,
3730
If any clean block has been found, we may have waited for it to
3731
become free. In this case it could be possible that another clean
3732
block became dirty. This is possible if the write request existed
3733
before the resize started (BLOCK_FOR_UPDATE). Re-check the hashes.
3735
} while (total_found);
3741
Reset the counters of a key cache.
3744
reset_key_cache_counters()
3747
This procedure is used by process_key_caches() to reset the key_cache.
3750
0 on success (always because it can't fail)
3753
void reset_key_cache_counters()
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 */
3762
#if defined(KEYCACHE_TIMEOUT)
3766
unsigned int hash_link_number(HASH_LINK *hash_link, KEY_CACHE *keycache)
3768
return ((unsigned int) (((char*)hash_link-(char *) keycache->hash_link_root)/
3769
sizeof(HASH_LINK)));
3773
unsigned int block_number(BLOCK_LINK *block, KEY_CACHE *keycache)
3775
return ((unsigned int) (((char*)block-(char *)keycache->block_root)/
3776
sizeof(BLOCK_LINK)));
3780
#define KEYCACHE_DUMP_FILE "keycache_dump.txt"
3781
#define MAX_QUEUE_LEN 100
3784
static void keycache_dump(KEY_CACHE *keycache)
3786
FILE *keycache_dump_file=fopen(KEYCACHE_DUMP_FILE, "w");
3787
internal::st_my_thread_var *last;
3788
internal::st_my_thread_var *thread;
3790
HASH_LINK *hash_link;
3791
KEYCACHE_PAGE *page;
3794
fprintf(keycache_dump_file, "thread:%u\n", thread->id);
3797
thread=last=waiting_for_hash_link.last_thread;
3798
fprintf(keycache_dump_file, "queue of threads waiting for hash link\n");
3802
thread=thread->next;
3803
page= (KEYCACHE_PAGE *) thread->opt_info;
3804
fprintf(keycache_dump_file,
3805
"thread:%u, (file,filepos)=(%u,%lu)\n",
3806
thread->id,(uint) page->file,(uint32_t) page->filepos);
3807
if (++i == MAX_QUEUE_LEN)
3810
while (thread != last);
3813
thread=last=waiting_for_block.last_thread;
3814
fprintf(keycache_dump_file, "queue of threads waiting for block\n");
3818
thread=thread->next;
3819
hash_link= (HASH_LINK *) thread->opt_info;
3820
fprintf(keycache_dump_file,
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);
3824
if (++i == MAX_QUEUE_LEN)
3827
while (thread != last);
3829
for (i=0 ; i< keycache->blocks_used ; i++)
3832
block= &keycache->block_root[i];
3833
hash_link= block->hash_link;
3834
fprintf(keycache_dump_file,
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);
3839
for (j=0 ; j < 2; j++)
3841
KEYCACHE_WQUEUE *wqueue=&block->wqueue[j];
3842
thread= last= wqueue->last_thread;
3843
fprintf(keycache_dump_file, "queue #%d\n", j);
3848
thread=thread->next;
3849
fprintf(keycache_dump_file,
3850
"thread:%u\n", thread->id);
3851
if (++i == MAX_QUEUE_LEN)
3854
while (thread != last);
3858
fprintf(keycache_dump_file, "LRU chain:");
3859
block= keycache= used_last;
3864
block= block->next_used;
3865
fprintf(keycache_dump_file,
3866
"block:%u, ", block_number(block, keycache));
3868
while (block != keycache->used_last);
3870
fprintf(keycache_dump_file, "\n");
3872
fclose(keycache_dump_file);
3875
static int keycache_pthread_cond_wait(pthread_cond_t *cond,
3876
pthread_mutex_t *mutex)
3879
struct timeval now; /* time when we started waiting */
3880
struct timespec timeout; /* timeout value for the wait function */
3883
/* Get current time */
3884
gettimeofday(&now, &tz);
3885
/* Prepare timeout value */
3886
timeout.tv_sec= now.tv_sec + KEYCACHE_TIMEOUT;
3888
timeval uses microseconds.
3889
timespec uses nanoseconds.
3890
1 nanosecond = 1000 micro seconds
3892
timeout.tv_nsec= now.tv_usec * 1000;
3893
rc= pthread_cond_timedwait(cond, mutex, &timeout);
3894
if (rc == ETIMEDOUT || rc == ETIME)
3899
assert(rc != ETIMEDOUT);
3902
#endif /* defined(KEYCACHE_TIMEOUT) */