Commit d835f4ef authored by unknown's avatar unknown

Merge bk-internal.mysql.com:/home/bk/mysql-4.1

into narttu.mysql.fi:/my/mysql-4.1
parents b137dfca 1c6e45ef
......@@ -219,9 +219,9 @@ extern my_bool my_charset_same(CHARSET_INFO *cs1, CHARSET_INFO *cs2);
/* statistics */
extern ulong _my_cache_w_requests,_my_cache_write,_my_cache_r_requests,
_my_cache_read;
extern ulong _my_blocks_used,_my_blocks_changed;
extern ulong my_cache_w_requests, my_cache_write, my_cache_r_requests,
my_cache_read;
extern ulong my_blocks_used, my_blocks_changed;
extern uint key_cache_block_size;
extern ulong my_file_opened,my_stream_opened, my_tmp_file_created;
extern my_bool key_cache_inited, my_init_done;
......
......@@ -646,13 +646,13 @@ int main(int argc, char *argv[])
(long) range_records > (long) records*14/10+2)
{
printf("mi_records_range for key: %d returned %ld; Should be about %ld\n",
i, range_records, records);
i, (long) range_records, (long) records);
goto end;
}
if (verbose && records)
{
printf("mi_records_range returned %ld; Exact is %ld (diff: %4.2g %%)\n",
range_records,records,
(long) range_records, (long) records,
labs((long) range_records-(long) records)*100.0/records);
}
......@@ -667,7 +667,7 @@ int main(int argc, char *argv[])
{
puts("Wrong info from mi_info");
printf("Got: records: %ld delete: %ld i_keys: %d\n",
info.records,info.deleted,info.keys);
(long) info.records, (long) info.deleted,info.keys);
}
if (verbose)
{
......@@ -822,8 +822,8 @@ w_requests: %10lu\n\
writes: %10lu\n\
r_requests: %10lu\n\
reads: %10lu\n",
_my_blocks_used,_my_cache_w_requests, _my_cache_write,
_my_cache_r_requests,_my_cache_read);
my_blocks_used, my_cache_w_requests, my_cache_write,
my_cache_r_requests, my_cache_read);
}
end_key_cache();
if (blob_buffer)
......
......@@ -272,7 +272,7 @@ int run_test(const char *filename)
create_key(key, nrecords*upd);
print_key(key," INTERSECT\n");
hrows=mi_records_in_range(file,0,key,0,HA_READ_MBR_INTERSECT,record+1,0,0);
printf(" %ld rows\n",hrows);
printf(" %ld rows\n", (long) hrows);
if (mi_close(file)) goto err;
......
......@@ -84,19 +84,23 @@
#define COND_FOR_READERS 2
typedef pthread_cond_t KEYCACHE_CONDVAR;
/* info about requests in a waiting queue */
typedef struct st_keycache_wqueue
{ /* info about requests in a waiting queue */
{
struct st_my_thread_var *last_thread; /* circular list of waiting threads */
} KEYCACHE_WQUEUE;
/* descriptor of the page in the key cache block buffer */
typedef struct st_keycache_page
{ /* descriptor of the page in the key cache block buffer */
{
int file; /* file to which the page belongs to */
my_off_t filepos; /* position of the page in the file */
} KEYCACHE_PAGE;
/* element in the chain of a hash table bucket */
typedef struct st_hash_link
{ /* element in the chain of a hash table bucket */
{
struct st_hash_link *next, **prev; /* to connect links in the same bucket */
struct st_block_link *block; /* reference to the block for the page: */
File file; /* from such a file */
......@@ -117,8 +121,9 @@ typedef struct st_hash_link
#define PAGE_TO_BE_READ 1
#define PAGE_WAIT_TO_BE_READ 2
/* key cache block */
typedef struct st_block_link
{ /* key cache block */
{
struct st_block_link
*next_used, **prev_used; /* to connect links in the LRU chain (ring) */
struct st_block_link
......@@ -148,35 +153,31 @@ static KEYCACHE_WQUEUE
static KEYCACHE_WQUEUE
waiting_for_block; /* queue of requests waiting for a free block */
static HASH_LINK **_my_hash_root; /* arr. of entries into hash table buckets */
static uint _my_hash_entries; /* max number of entries in the hash table */
static HASH_LINK *_my_hash_link_root; /* memory for hash table links */
static int _my_hash_links; /* max number of hash links */
static int _my_hash_links_used; /* number of hash links currently used */
static HASH_LINK *_my_free_hash_list; /* list of free hash links */
static BLOCK_LINK *_my_block_root; /* memory for block links */
static int _my_disk_blocks; /* max number of blocks in the cache */
static byte HUGE_PTR *_my_block_mem; /* memory for block buffers */
static BLOCK_LINK *_my_used_last; /* ptr to the last block of the LRU chain */
ulong _my_blocks_used, /* number of currently used blocks */
_my_blocks_changed; /* number of currently dirty blocks */
static HASH_LINK **my_hash_root; /* arr. of entries into hash table buckets */
static uint my_hash_entries; /* max number of entries in the hash table */
static HASH_LINK *my_hash_link_root; /* memory for hash table links */
static int my_hash_links; /* max number of hash links */
static int my_hash_links_used; /* number of hash links currently used */
static HASH_LINK *my_free_hash_list; /* list of free hash links */
static BLOCK_LINK *my_block_root; /* memory for block links */
static int my_disk_blocks; /* max number of blocks in the cache */
static byte HUGE_PTR *my_block_mem; /* memory for block buffers */
static BLOCK_LINK *my_used_last; /* ptr to the last block of the LRU chain */
ulong my_blocks_used, /* number of currently used blocks */
my_blocks_changed; /* number of currently dirty blocks */
#if defined(KEYCACHE_DEBUG)
static
ulong _my_blocks_available; /* number of blocks available in the LRU chain */
ulong my_blocks_available; /* number of blocks available in the LRU chain */
#endif /* defined(KEYCACHE_DEBUG) */
ulong _my_cache_w_requests,_my_cache_write, /* counters */
_my_cache_r_requests,_my_cache_read; /* for statistics */
ulong my_cache_w_requests, my_cache_write, /* counters */
my_cache_r_requests, my_cache_read; /* for statistics */
static BLOCK_LINK
*changed_blocks[CHANGED_BLOCKS_HASH]; /* hash table for file dirty blocks */
static BLOCK_LINK
*file_blocks[CHANGED_BLOCKS_HASH]; /* hash table for other file blocks */
/* that are not free */
#ifndef DBUG_OFF
static my_bool _my_printed;
#endif
#define KEYCACHE_HASH(f, pos) \
(((ulong) ((pos) >> key_cache_shift)+(ulong) (f)) & (_my_hash_entries-1))
(((ulong) ((pos) >> key_cache_shift)+(ulong) (f)) & (my_hash_entries-1))
#define FILE_HASH(f) ((uint) (f) & (CHANGED_BLOCKS_HASH-1))
#define DEFAULT_KEYCACHE_DEBUG_LOG "keycache_debug.log"
......@@ -230,9 +231,9 @@ static long keycache_thread_id;
#endif /* defined(KEYCACHE_DEBUG) || !defined(DBUG_OFF) */
#define BLOCK_NUMBER(b) \
((uint) (((char*)(b) - (char *) _my_block_root) / sizeof(BLOCK_LINK)))
((uint) (((char*)(b) - (char *) my_block_root) / sizeof(BLOCK_LINK)))
#define HASH_LINK_NUMBER(h) \
((uint) (((char*)(h) - (char *) _my_hash_link_root) / sizeof(HASH_LINK)))
((uint) (((char*)(h) - (char *) my_hash_link_root) / sizeof(HASH_LINK)))
#if (defined(KEYCACHE_TIMEOUT) && !defined(__WIN__)) || defined(KEYCACHE_DEBUG)
static int keycache_pthread_cond_wait(pthread_cond_t *cond,
......@@ -269,6 +270,7 @@ static uint next_power(uint value)
Initialize the key cache,
return number of blocks in it
*/
int init_key_cache(ulong use_mem)
{
uint blocks, hash_links, length;
......@@ -277,7 +279,7 @@ int init_key_cache(ulong use_mem)
DBUG_ENTER("init_key_cache");
KEYCACHE_DEBUG_OPEN;
if (key_cache_inited && _my_disk_blocks > 0)
if (key_cache_inited && my_disk_blocks > 0)
{
DBUG_PRINT("warning",("key cache already in use"));
DBUG_RETURN(0);
......@@ -285,51 +287,48 @@ int init_key_cache(ulong use_mem)
if (! key_cache_inited)
{
key_cache_inited=TRUE;
_my_disk_blocks= -1;
my_disk_blocks= -1;
key_cache_shift=my_bit_log2(key_cache_block_size);
DBUG_PRINT("info",("key_cache_block_size: %u",
key_cache_block_size));
#ifndef DBUG_OFF
_my_printed=0;
#endif
}
_my_cache_w_requests=_my_cache_r_requests=_my_cache_read=_my_cache_write=0;
my_cache_w_requests= my_cache_r_requests= my_cache_read= my_cache_write=0;
_my_block_mem=NULL;
_my_block_root=NULL;
my_block_mem=NULL;
my_block_root=NULL;
blocks= (uint) (use_mem/(sizeof(BLOCK_LINK)+2*sizeof(HASH_LINK)+
sizeof(HASH_LINK*)*5/4+key_cache_block_size));
/* It doesn't make sense to have too few blocks (less than 8) */
if (blocks >= 8 && _my_disk_blocks < 0)
if (blocks >= 8 && my_disk_blocks < 0)
{
for (;;)
{
/* Set _my_hash_entries to the next bigger 2 power */
if ((_my_hash_entries=next_power(blocks)) < blocks*5/4)
_my_hash_entries<<=1;
/* Set my_hash_entries to the next bigger 2 power */
if ((my_hash_entries=next_power(blocks)) < blocks*5/4)
my_hash_entries<<=1;
hash_links=2*blocks;
#if defined(MAX_THREADS)
if (hash_links < MAX_THREADS + blocks - 1)
hash_links=MAX_THREADS + blocks - 1;
#endif
while ((length=blocks*sizeof(BLOCK_LINK)+hash_links*sizeof(HASH_LINK)+
sizeof(HASH_LINK*)*_my_hash_entries)+
((ulong) blocks << key_cache_shift) >
use_mem)
while ((length=(ALIGN_SIZE(blocks*sizeof(BLOCK_LINK))+
ALIGN_SIZE(hash_links*sizeof(HASH_LINK))+
ALIGN_SIZE(sizeof(HASH_LINK*)*my_hash_entries)))+
((ulong) blocks << key_cache_shift) > use_mem)
blocks--;
/* Allocate memory for cache page buffers */
if ((_my_block_mem=my_malloc_lock((ulong) blocks*key_cache_block_size,
if ((my_block_mem=my_malloc_lock((ulong) blocks*key_cache_block_size,
MYF(0))))
{
/*
Allocate memory for blocks, hash_links and hash entries;
For each block 2 hash links are allocated
*/
if ((_my_block_root=(BLOCK_LINK*) my_malloc((uint) length,MYF(0))))
if ((my_block_root=(BLOCK_LINK*) my_malloc((uint) length,MYF(0))))
break;
my_free_lock(_my_block_mem,MYF(0));
my_free_lock(my_block_mem,MYF(0));
}
if (blocks < 8)
{
......@@ -338,29 +337,32 @@ int init_key_cache(ulong use_mem)
}
blocks=blocks/4*3;
}
_my_disk_blocks=(int) blocks;
_my_hash_links=hash_links;
_my_hash_root=(HASH_LINK**) (_my_block_root+blocks);
_my_hash_link_root=(HASH_LINK*) (_my_hash_root+_my_hash_entries);
bzero((byte*) _my_block_root,_my_disk_blocks*sizeof(BLOCK_LINK));
bzero((byte*) _my_hash_root,_my_hash_entries*sizeof(HASH_LINK*));
bzero((byte*) _my_hash_link_root,_my_hash_links*sizeof(HASH_LINK));
_my_hash_links_used=0;
_my_free_hash_list=NULL;
_my_blocks_used=_my_blocks_changed=0;
my_disk_blocks=(int) blocks;
my_hash_links=hash_links;
my_hash_root= (HASH_LINK**) ((char*) my_block_root +
ALIGN_SIZE(blocks*sizeof(BLOCK_LINK)));
my_hash_link_root= (HASH_LINK*) ((char*) my_hash_root +
ALIGN_SIZE((sizeof(HASH_LINK*) *
my_hash_entries)));
bzero((byte*) my_block_root, my_disk_blocks*sizeof(BLOCK_LINK));
bzero((byte*) my_hash_root, my_hash_entries*sizeof(HASH_LINK*));
bzero((byte*) my_hash_link_root, my_hash_links*sizeof(HASH_LINK));
my_hash_links_used=0;
my_free_hash_list=NULL;
my_blocks_used= my_blocks_changed=0;
#if defined(KEYCACHE_DEBUG)
_my_blocks_available=0;
my_blocks_available=0;
#endif
/* The LRU chain is empty after initialization */
_my_used_last=NULL;
my_used_last=NULL;
waiting_for_hash_link.last_thread=NULL;
waiting_for_block.last_thread=NULL;
DBUG_PRINT("exit",
("disk_blocks: %d block_root: %lx hash_entries: %d hash_root: %lx \
hash_links: %d hash_link_root %lx",
_my_disk_blocks,_my_block_root,_my_hash_entries,_my_hash_root,
_my_hash_links,_my_hash_link_root));
my_disk_blocks, my_block_root, my_hash_entries, my_hash_root,
my_hash_links, my_hash_link_root));
}
bzero((gptr) changed_blocks,sizeof(changed_blocks[0])*CHANGED_BLOCKS_HASH);
bzero((gptr) file_blocks,sizeof(file_blocks[0])*CHANGED_BLOCKS_HASH);
......@@ -369,10 +371,10 @@ int init_key_cache(ulong use_mem)
err:
error=my_errno;
if (_my_block_mem)
my_free_lock((gptr) _my_block_mem,MYF(0));
if (_my_block_mem)
my_free((gptr) _my_block_root,MYF(0));
if (my_block_mem)
my_free_lock((gptr) my_block_mem,MYF(0));
if (my_block_mem)
my_free((gptr) my_block_root,MYF(0));
my_errno=error;
DBUG_RETURN(0);
}
......@@ -402,25 +404,26 @@ int resize_key_cache(ulong use_mem)
/*
Remove key_cache from memory
*/
void end_key_cache(void)
{
DBUG_ENTER("end_key_cache");
if (_my_disk_blocks > 0)
if (my_disk_blocks > 0)
{
if (_my_block_mem)
if (my_block_mem)
{
my_free_lock((gptr) _my_block_mem,MYF(0));
my_free((gptr) _my_block_root,MYF(0));
my_free_lock((gptr) my_block_mem,MYF(0));
my_free((gptr) my_block_root,MYF(0));
}
_my_disk_blocks= -1;
my_disk_blocks= -1;
}
KEYCACHE_DEBUG_CLOSE;
key_cache_inited=0;
DBUG_PRINT("status",
("used: %d changed: %d w_requests: %ld \
writes: %ld r_requests: %ld reads: %ld",
_my_blocks_used,_my_blocks_changed,_my_cache_w_requests,
_my_cache_write,_my_cache_r_requests,_my_cache_read));
my_blocks_used, my_blocks_changed, my_cache_w_requests,
my_cache_write, my_cache_r_requests, my_cache_read));
DBUG_VOID_RETURN;
} /* end_key_cache */
......@@ -428,12 +431,14 @@ void end_key_cache(void)
/*
Link a thread into double-linked queue of waiting threads
*/
static inline void link_into_queue(KEYCACHE_WQUEUE *wqueue,
struct st_my_thread_var *thread)
{
struct st_my_thread_var *last;
if (! (last=wqueue->last_thread))
{ /* Queue is empty */
{
/* Queue is empty */
thread->next=thread;
thread->prev=&thread->next;
}
......@@ -450,6 +455,7 @@ static inline void link_into_queue(KEYCACHE_WQUEUE *wqueue,
/*
Unlink a thread from double-linked queue of waiting threads
*/
static inline void unlink_from_queue(KEYCACHE_WQUEUE *wqueue,
struct st_my_thread_var *thread)
{
......@@ -472,6 +478,7 @@ static inline void unlink_from_queue(KEYCACHE_WQUEUE *wqueue,
/*
Add a thread to single-linked queue of waiting threads
*/
static inline void add_to_queue(KEYCACHE_WQUEUE *wqueue,
struct st_my_thread_var *thread)
{
......@@ -490,7 +497,8 @@ static inline void add_to_queue(KEYCACHE_WQUEUE *wqueue,
/*
Remove all threads from queue signaling them to proceed
*/
static inline void release_queue(KEYCACHE_WQUEUE *wqueue)
static void release_queue(KEYCACHE_WQUEUE *wqueue)
{
struct st_my_thread_var *last=wqueue->last_thread;
struct st_my_thread_var *next=last->next;
......@@ -511,6 +519,7 @@ static inline void release_queue(KEYCACHE_WQUEUE *wqueue)
/*
Unlink a block from the chain of dirty/clean blocks
*/
static inline void unlink_changed(BLOCK_LINK *block)
{
if (block->next_changed)
......@@ -522,6 +531,7 @@ static inline void unlink_changed(BLOCK_LINK *block)
/*
Link a block into the chain of dirty/clean blocks
*/
static inline void link_changed(BLOCK_LINK *block, BLOCK_LINK **phead)
{
block->prev_changed=phead;
......@@ -535,7 +545,8 @@ static inline void link_changed(BLOCK_LINK *block, BLOCK_LINK **phead)
Unlink a block from the chain of dirty/clean blocks, if it's asked for,
and link it to the chain of clean blocks for the specified file
*/
static inline void link_to_file_list(BLOCK_LINK *block,int file,
static void link_to_file_list(BLOCK_LINK *block,int file,
my_bool unlink)
{
if (unlink)
......@@ -544,7 +555,7 @@ static inline void link_to_file_list(BLOCK_LINK *block,int file,
if (block->status & BLOCK_CHANGED)
{
block->status&=~BLOCK_CHANGED;
_my_blocks_changed--;
my_blocks_changed--;
}
}
......@@ -553,18 +564,20 @@ static inline void link_to_file_list(BLOCK_LINK *block,int file,
Unlink a block from the chain of clean blocks for the specified
file and link it to the chain of dirty blocks for this file
*/
static inline void link_to_changed_list(BLOCK_LINK *block)
{
unlink_changed(block);
link_changed(block,&changed_blocks[FILE_HASH(block->hash_link->file)]);
block->status|=BLOCK_CHANGED;
_my_blocks_changed++;
my_blocks_changed++;
}
/*
Link a block to the LRU chain at the beginning or at the end
*/
static void link_block(BLOCK_LINK *block, my_bool at_end)
{
KEYCACHE_DBUG_ASSERT(! (block->hash_link && block->hash_link->requests));
......@@ -597,33 +610,33 @@ static void link_block(BLOCK_LINK *block, my_bool at_end)
KEYCACHE_DBUG_PRINT("link_block",
("linked,unlinked block %u status=%x #requests=%u #available=%u",
BLOCK_NUMBER(block),block->status,
block->requests,_my_blocks_available));
block->requests, my_blocks_available));
#endif
return;
}
if (_my_used_last)
if (my_used_last)
{
_my_used_last->next_used->prev_used=&block->next_used;
block->next_used=_my_used_last->next_used;
block->prev_used=&_my_used_last->next_used;
_my_used_last->next_used=block;
my_used_last->next_used->prev_used=&block->next_used;
block->next_used= my_used_last->next_used;
block->prev_used= &my_used_last->next_used;
my_used_last->next_used=block;
if (at_end)
_my_used_last=block;
my_used_last=block;
}
else
{
/* The LRU chain is empty */
_my_used_last=block->next_used=block;
my_used_last=block->next_used=block;
block->prev_used=&block->next_used;
}
KEYCACHE_THREAD_TRACE("link_block");
#if defined(KEYCACHE_DEBUG)
_my_blocks_available++;
my_blocks_available++;
KEYCACHE_DBUG_PRINT("link_block",
("linked block %u:%1u status=%x #requests=%u #available=%u",
BLOCK_NUMBER(block),at_end,block->status,
block->requests,_my_blocks_available));
KEYCACHE_DBUG_ASSERT(_my_blocks_available <= _my_blocks_used);
block->requests, my_blocks_available));
KEYCACHE_DBUG_ASSERT(my_blocks_available <= my_blocks_used);
#endif
}
......@@ -631,28 +644,29 @@ static void link_block(BLOCK_LINK *block, my_bool at_end)
/*
Unlink a block from the LRU chain
*/
static inline void unlink_block(BLOCK_LINK *block)
static void unlink_block(BLOCK_LINK *block)
{
if (block->next_used == block)
/* The list contains only one member */
_my_used_last=NULL;
my_used_last=NULL;
else
{
block->next_used->prev_used=block->prev_used;
*block->prev_used=block->next_used;
if (_my_used_last == block)
_my_used_last=STRUCT_PTR(BLOCK_LINK, next_used, block->prev_used);
if (my_used_last == block)
my_used_last=STRUCT_PTR(BLOCK_LINK, next_used, block->prev_used);
}
block->next_used=NULL;
KEYCACHE_THREAD_TRACE("unlink_block");
#if defined(KEYCACHE_DEBUG)
_my_blocks_available--;
my_blocks_available--;
KEYCACHE_DBUG_PRINT("unlink_block",
("unlinked block %u status=%x #requests=%u #available=%u",
BLOCK_NUMBER(block),block->status,
block->requests,_my_blocks_available));
KEYCACHE_DBUG_ASSERT(_my_blocks_available >= 0);
block->requests, my_blocks_available));
KEYCACHE_DBUG_ASSERT(my_blocks_available >= 0);
#endif
}
......@@ -660,7 +674,7 @@ static inline void unlink_block(BLOCK_LINK *block)
/*
Register requests for a block
*/
static inline void reg_requests(BLOCK_LINK *block, int count)
static void reg_requests(BLOCK_LINK *block, int count)
{
if (! block->requests)
/* First request for the block unlinks it */
......@@ -673,6 +687,7 @@ static inline void reg_requests(BLOCK_LINK *block, int count)
Unregister request for a block
linking it to the LRU chain if it's the last request
*/
static inline void unreg_request(BLOCK_LINK *block, int at_end)
{
if (! --block->requests)
......@@ -682,6 +697,7 @@ static inline void unreg_request(BLOCK_LINK *block, int at_end)
/*
Remove a reader of the page in block
*/
static inline void remove_reader(BLOCK_LINK *block)
{
if (! --block->hash_link->requests && block->condvar)
......@@ -706,8 +722,9 @@ static inline void wait_for_readers(BLOCK_LINK *block)
/*
add a hash link to a bucket in the hash_table
Add a hash link to a bucket in the hash_table
*/
static inline void link_hash(HASH_LINK **start, HASH_LINK *hash_link)
{
if (*start)
......@@ -721,7 +738,8 @@ static inline void link_hash(HASH_LINK **start, HASH_LINK *hash_link)
/*
Remove a hash link from the hash table
*/
static inline void unlink_hash(HASH_LINK *hash_link)
static void unlink_hash(HASH_LINK *hash_link)
{
KEYCACHE_DBUG_PRINT("unlink_hash", ("file %u, filepos %lu #requests=%u",
(uint) hash_link->file,(ulong) hash_link->diskpos, hash_link->requests));
......@@ -730,7 +748,8 @@ static inline void unlink_hash(HASH_LINK *hash_link)
hash_link->next->prev=hash_link->prev;
hash_link->block=NULL;
if (waiting_for_hash_link.last_thread)
{ /* Signal that A free hash link appeared */
{
/* Signal that A free hash link appeared */
struct st_my_thread_var *last_thread=waiting_for_hash_link.last_thread;
struct st_my_thread_var *first_thread=last_thread->next;
struct st_my_thread_var *next_thread=first_thread;
......@@ -756,18 +775,20 @@ static inline void unlink_hash(HASH_LINK *hash_link)
}
}
while (thread != last_thread);
link_hash(&_my_hash_root[KEYCACHE_HASH(hash_link->file,
link_hash(&my_hash_root[KEYCACHE_HASH(hash_link->file,
hash_link->diskpos)], hash_link);
return;
}
hash_link->next=_my_free_hash_list;
_my_free_hash_list=hash_link;
hash_link->next= my_free_hash_list;
my_free_hash_list=hash_link;
}
/*
Get the hash link for a page
*/
static inline HASH_LINK *get_hash_link(int file, my_off_t filepos)
static HASH_LINK *get_hash_link(int file, my_off_t filepos)
{
reg1 HASH_LINK *hash_link, **start;
KEYCACHE_PAGE page;
......@@ -784,7 +805,7 @@ static inline HASH_LINK *get_hash_link(int file, my_off_t filepos)
start contains the head of the bucket list,
hash_link points to the first member of the list
*/
hash_link=*(start=&_my_hash_root[KEYCACHE_HASH(file, filepos)]);
hash_link= *(start= &my_hash_root[KEYCACHE_HASH(file, filepos)]);
#if defined(KEYCACHE_DEBUG)
cnt=0;
#endif
......@@ -795,7 +816,7 @@ static inline HASH_LINK *get_hash_link(int file, my_off_t filepos)
hash_link= hash_link->next;
#if defined(KEYCACHE_DEBUG)
cnt++;
if (! (cnt <= _my_hash_links_used))
if (! (cnt <= my_hash_links_used))
{
int i;
for (i=0, hash_link=*start ;
......@@ -805,22 +826,24 @@ static inline HASH_LINK *get_hash_link(int file, my_off_t filepos)
(uint) hash_link->file,(ulong) hash_link->diskpos));
}
}
KEYCACHE_DBUG_ASSERT(n <= _my_hash_links_used);
KEYCACHE_DBUG_ASSERT(n <= my_hash_links_used);
#endif
}
if (! hash_link)
{ /* There is no hash link in the hash table for the pair (file, filepos) */
if (_my_free_hash_list)
{
hash_link=_my_free_hash_list;
_my_free_hash_list=hash_link->next;
/* There is no hash link in the hash table for the pair (file, filepos) */
if (my_free_hash_list)
{
hash_link= my_free_hash_list;
my_free_hash_list=hash_link->next;
}
else if (_my_hash_links_used < _my_hash_links)
else if (my_hash_links_used < my_hash_links)
{
hash_link= &_my_hash_link_root[_my_hash_links_used++];
hash_link= &my_hash_link_root[my_hash_links_used++];
}
else
{ /* Wait for a free hash link */
{
/* Wait for a free hash link */
struct st_my_thread_var *thread=my_thread_var;
KEYCACHE_DBUG_PRINT("get_hash_link", ("waiting"));
page.file=file; page.filepos=filepos;
......@@ -846,6 +869,7 @@ static inline HASH_LINK *get_hash_link(int file, my_off_t filepos)
If the page is not in the cache return a free block, if there is none
return the lru block after saving its buffer if the page is dirty
*/
static BLOCK_LINK *find_key_block(int file, my_off_t filepos,
int wrmode, int *page_st)
{
......@@ -874,8 +898,8 @@ static BLOCK_LINK *find_key_block(int file, my_off_t filepos,
page_status=PAGE_READ;
if (page_status == PAGE_READ && (block->status & BLOCK_IN_SWITCH))
{ /* This is a request for a page to be removed from cache */
{
/* This is a request for a page to be removed from cache */
KEYCACHE_DBUG_PRINT("find_key_block",
("request for old page in block %u",BLOCK_NUMBER(block)));
/*
......@@ -907,20 +931,23 @@ static BLOCK_LINK *find_key_block(int file, my_off_t filepos,
}
}
else
{ /* This is a request for a new page or for a page not to be removed */
{
/* This is a request for a new page or for a page not to be removed */
if (! block)
{ /* No block is assigned for the page yet */
if (_my_blocks_used < (uint) _my_disk_blocks)
{ /* There are some never used blocks, take first of them */
hash_link->block=block= &_my_block_root[_my_blocks_used];
block->buffer=ADD_TO_PTR(_my_block_mem,
((ulong) _my_blocks_used*key_cache_block_size),
{
/* No block is assigned for the page yet */
if (my_blocks_used < (uint) my_disk_blocks)
{
/* There are some never used blocks, take first of them */
hash_link->block=block= &my_block_root[my_blocks_used];
block->buffer=ADD_TO_PTR(my_block_mem,
((ulong) my_blocks_used*key_cache_block_size),
byte*);
block->status=0;
block->length=0;
block->offset=key_cache_block_size;
block->requests=1;
_my_blocks_used++;
my_blocks_used++;
link_to_file_list(block, file, 0);
block->hash_link=hash_link;
page_status=PAGE_TO_BE_READ;
......@@ -928,14 +955,15 @@ static BLOCK_LINK *find_key_block(int file, my_off_t filepos,
("got never used block %u",BLOCK_NUMBER(block)));
}
else
{ /* There are no never used blocks, use a block from the LRU chain */
{
/* There are no never used blocks, use a block from the LRU chain */
/*
Wait until a new block is added to the LRU chain;
several threads might wait here for the same page,
all of them must get the same block
*/
if (! _my_used_last)
if (! my_used_last)
{
struct st_my_thread_var *thread=my_thread_var;
thread->opt_info=(void *) hash_link;
......@@ -954,20 +982,23 @@ static BLOCK_LINK *find_key_block(int file, my_off_t filepos,
Take the first block from the LRU chain
unlinking it from the chain
*/
block=_my_used_last->next_used;
block= my_used_last->next_used;
reg_requests(block,1);
hash_link->block=block;
}
if (block->hash_link != hash_link && ! (block->status & BLOCK_IN_SWITCH) )
{ /* this is a primary request for a new page */
if (block->hash_link != hash_link &&
! (block->status & BLOCK_IN_SWITCH) )
{
/* this is a primary request for a new page */
block->status|=BLOCK_IN_SWITCH;
KEYCACHE_DBUG_PRINT("find_key_block",
("got block %u for new page",BLOCK_NUMBER(block)));
if (block->status & BLOCK_CHANGED)
{ /* The block contains a dirty page - push it out of the cache */
{
/* The block contains a dirty page - push it out of the cache */
KEYCACHE_DBUG_PRINT("find_key_block",("block is dirty"));
......@@ -980,7 +1011,7 @@ static BLOCK_LINK *find_key_block(int file, my_off_t filepos,
block->length,block->hash_link->diskpos,
MYF(MY_NABP | MY_WAIT_IF_FULL));
keycache_pthread_mutex_lock(&THR_LOCK_keycache);
_my_cache_write++;
my_cache_write++;
}
block->status|=BLOCK_REASSIGNED;
......@@ -1019,7 +1050,7 @@ static BLOCK_LINK *find_key_block(int file, my_off_t filepos,
}
}
_my_cache_read++;
my_cache_read++;
}
else
{
......@@ -1046,6 +1077,7 @@ static BLOCK_LINK *find_key_block(int file, my_off_t filepos,
do not to report error when the size of successfully read
portion is less than read_length, but not less than min_length
*/
static void read_block(BLOCK_LINK *block, uint read_length,
uint min_length, my_bool primary)
{
......@@ -1055,7 +1087,8 @@ static void read_block(BLOCK_LINK *block, uint read_length,
KEYCACHE_THREAD_TRACE("read_block");
if (primary)
{ /*
{
/*
This code is executed only by threads
that submitted primary requests
*/
......@@ -1082,7 +1115,8 @@ static void read_block(BLOCK_LINK *block, uint read_length,
release_queue(&block->wqueue[COND_FOR_REQUESTED]);
}
else
{ /*
{
/*
This code is executed only by threads
that submitted secondary requests
*/
......@@ -1122,8 +1156,9 @@ byte *key_cache_read(File file, my_off_t filepos, byte *buff, uint length,
DBUG_PRINT("enter", ("file %u, filepos %lu, length %u",
(uint) file,(ulong) filepos,length));
if (_my_disk_blocks > 0)
{ /* Key cache is used */
if (my_disk_blocks > 0)
{
/* Key cache is used */
reg1 BLOCK_LINK *block;
uint offset= (uint) (filepos & (key_cache_block_size-1));
byte *start=buff;
......@@ -1144,7 +1179,7 @@ byte *key_cache_read(File file, my_off_t filepos, byte *buff, uint length,
key_cache_block_size : length;
KEYCACHE_DBUG_ASSERT(read_length > 0);
keycache_pthread_mutex_lock(&THR_LOCK_keycache);
_my_cache_r_requests++;
my_cache_r_requests++;
block=find_key_block(file,filepos,0,&page_st);
if (page_st != PAGE_READ)
{
......@@ -1212,8 +1247,8 @@ byte *key_cache_read(File file, my_off_t filepos, byte *buff, uint length,
}
/* Key cache is not used */
statistic_increment(_my_cache_r_requests,&THR_LOCK_keycache);
statistic_increment(_my_cache_read,&THR_LOCK_keycache);
statistic_increment(my_cache_r_requests,&THR_LOCK_keycache);
statistic_increment(my_cache_read,&THR_LOCK_keycache);
if (my_pread(file,(byte*) buff,length,filepos,MYF(MY_NABP)))
error=1;
DBUG_RETURN(error? (byte*) 0 : buff);
......@@ -1227,6 +1262,7 @@ byte *key_cache_read(File file, my_off_t filepos, byte *buff, uint length,
if !dont_write then all dirty pages involved in writing should
have been flushed from key cache before the function starts
*/
int key_cache_write(File file, my_off_t filepos, byte *buff, uint length,
uint block_length __attribute__((unused)),
int dont_write)
......@@ -1239,8 +1275,9 @@ int key_cache_write(File file, my_off_t filepos, byte *buff, uint length,
(uint) file,(ulong) filepos,length,block_length));
if (!dont_write)
{ /* Force writing from buff into disk */
statistic_increment(_my_cache_write, &THR_LOCK_keycache);
{
/* Force writing from buff into disk */
statistic_increment(my_cache_write, &THR_LOCK_keycache);
if (my_pwrite(file,buff,length,filepos,MYF(MY_NABP | MY_WAIT_IF_FULL)))
DBUG_RETURN(1);
}
......@@ -1249,8 +1286,9 @@ int key_cache_write(File file, my_off_t filepos, byte *buff, uint length,
DBUG_EXECUTE("check_keycache",test_key_cache("start of key_cache_write",1););
#endif
if (_my_disk_blocks > 0)
{ /* Key cache is used */
if (my_disk_blocks > 0)
{
/* Key cache is used */
uint read_length;
uint offset= (uint) (filepos & (key_cache_block_size-1));
int page_st;
......@@ -1263,7 +1301,7 @@ int key_cache_write(File file, my_off_t filepos, byte *buff, uint length,
key_cache_block_size : length;
KEYCACHE_DBUG_ASSERT(read_length > 0);
keycache_pthread_mutex_lock(&THR_LOCK_keycache);
_my_cache_w_requests++;
my_cache_w_requests++;
block=find_key_block(file, filepos, 1, &page_st);
if (page_st != PAGE_READ &&
(offset || read_length < key_cache_block_size))
......@@ -1273,7 +1311,8 @@ int key_cache_write(File file, my_off_t filepos, byte *buff, uint length,
offset,(my_bool)(page_st == PAGE_TO_BE_READ));
if (!dont_write)
{ /* buff has been written to disk at start */
{
/* buff has been written to disk at start */
if ((block->status & BLOCK_CHANGED) &&
(!offset && read_length >= key_cache_block_size))
link_to_file_list(block, block->hash_link->file, 1);
......@@ -1318,8 +1357,8 @@ int key_cache_write(File file, my_off_t filepos, byte *buff, uint length,
/* Key cache is not used */
if (dont_write)
{
statistic_increment(_my_cache_w_requests, &THR_LOCK_keycache);
statistic_increment(_my_cache_write, &THR_LOCK_keycache);
statistic_increment(my_cache_w_requests, &THR_LOCK_keycache);
statistic_increment(my_cache_write, &THR_LOCK_keycache);
if (my_pwrite(file,(byte*) buff,length,filepos,MYF(MY_NABP | MY_WAIT_IF_FULL)))
error=1;
}
......@@ -1337,6 +1376,7 @@ int key_cache_write(File file, my_off_t filepos, byte *buff, uint length,
remove it from the chain file of dirty/clean blocks
and add it at the beginning of the LRU chain
*/
static void free_block(BLOCK_LINK *block)
{
KEYCACHE_THREAD_TRACE("free block");
......@@ -1372,6 +1412,7 @@ static int cmp_sec_link(BLOCK_LINK **a, BLOCK_LINK **b)
Flush a portion of changed blocks to disk,
free used blocks if requested
*/
static int flush_cached_blocks(File file, BLOCK_LINK **cache,
BLOCK_LINK **end,
enum flush_type type)
......@@ -1399,7 +1440,7 @@ static int flush_cached_blocks(File file, BLOCK_LINK **cache,
error=my_pwrite(file,block->buffer+block->offset,block->length,
block->hash_link->diskpos,MYF(MY_NABP | MY_WAIT_IF_FULL));
keycache_pthread_mutex_lock(&THR_LOCK_keycache);
_my_cache_write++;
my_cache_write++;
if (error)
{
block->status|= BLOCK_ERROR;
......@@ -1409,7 +1450,7 @@ static int flush_cached_blocks(File file, BLOCK_LINK **cache,
/* type will never be FLUSH_IGNORE_CHANGED here */
if (! (type == FLUSH_KEEP || type == FLUSH_FORCE_WRITE))
{
_my_blocks_changed--;
my_blocks_changed--;
free_block(block);
}
else
......@@ -1427,13 +1468,14 @@ static int flush_cached_blocks(File file, BLOCK_LINK **cache,
/*
Flush all blocks for a file to disk
*/
int flush_key_blocks(File file, enum flush_type type)
{
int last_errno=0;
BLOCK_LINK *cache_buff[FLUSH_CACHE],**cache;
DBUG_ENTER("flush_key_blocks");
DBUG_PRINT("enter",("file: %d blocks_used: %d blocks_changed: %d",
file,_my_blocks_used,_my_blocks_changed));
file, my_blocks_used, my_blocks_changed));
#if !defined(DBUG_OFF) && defined(EXTRA_DEBUG)
DBUG_EXECUTE("check_keycache",test_key_cache("start of flush_key_blocks",0););
......@@ -1442,9 +1484,10 @@ int flush_key_blocks(File file, enum flush_type type)
keycache_pthread_mutex_lock(&THR_LOCK_keycache);
cache=cache_buff;
if (_my_disk_blocks > 0 &&
if (my_disk_blocks > 0 &&
(!my_disable_flush_key_blocks || type != FLUSH_KEEP))
{ /* Key cache exists and flush is not disabled */
{
/* Key cache exists and flush is not disabled */
int error=0;
uint count=0;
BLOCK_LINK **pos,**end;
......@@ -1467,7 +1510,7 @@ int flush_key_blocks(File file, enum flush_type type)
if (block->hash_link->file == file)
{
count++;
KEYCACHE_DBUG_ASSERT(count<=_my_blocks_used);
KEYCACHE_DBUG_ASSERT(count<= my_blocks_used);
}
}
/* Allocate a new buffer only if its bigger than the one we have */
......@@ -1488,7 +1531,7 @@ int flush_key_blocks(File file, enum flush_type type)
{
#if defined(KEYCACHE_DEBUG)
cnt++;
KEYCACHE_DBUG_ASSERT(cnt <= _my_blocks_used);
KEYCACHE_DBUG_ASSERT(cnt <= my_blocks_used);
#endif
next=block->next_changed;
if (block->hash_link->file == file)
......@@ -1501,15 +1544,18 @@ int flush_key_blocks(File file, enum flush_type type)
block->status|= BLOCK_IN_FLUSH;
if (! (block->status & BLOCK_IN_SWITCH))
{ /*
{
/*
We care only for the blocks for which flushing was not
initiated by other threads as a result of page swapping
*/
reg_requests(block,1);
if (type != FLUSH_IGNORE_CHANGED)
{ /* It's not a temporary file */
{
/* It's not a temporary file */
if (pos == end)
{ /*
{
/*
This happens only if there is not enough
memory for the big block
*/
......@@ -1527,12 +1573,13 @@ int flush_key_blocks(File file, enum flush_type type)
else
{
/* It's a temporary file */
_my_blocks_changed--;
my_blocks_changed--;
free_block(block);
}
}
else
{ /* Link the block into a list of blocks 'in switch' */
{
/* Link the block into a list of blocks 'in switch' */
unlink_changed(block);
link_changed(block,&first_in_switch);
}
......@@ -1561,7 +1608,7 @@ int flush_key_blocks(File file, enum flush_type type)
}
#if defined(KEYCACHE_DEBUG)
cnt++;
KEYCACHE_DBUG_ASSERT(cnt <= _my_blocks_used);
KEYCACHE_DBUG_ASSERT(cnt <= my_blocks_used);
#endif
}
/* The following happens very seldom */
......@@ -1576,7 +1623,7 @@ int flush_key_blocks(File file, enum flush_type type)
{
#if defined(KEYCACHE_DEBUG)
cnt++;
KEYCACHE_DBUG_ASSERT(cnt <= _my_blocks_used);
KEYCACHE_DBUG_ASSERT(cnt <= my_blocks_used);
#endif
next=block->next_changed;
if (block->hash_link->file == file &&
......@@ -1607,27 +1654,28 @@ int flush_key_blocks(File file, enum flush_type type)
/*
Flush all blocks in the key cache to disk
*/
static int flush_all_key_blocks()
{
#if defined(KEYCACHE_DEBUG)
uint cnt=0;
#endif
while (_my_blocks_changed > 0)
while (my_blocks_changed > 0)
{
BLOCK_LINK *block;
for (block=_my_used_last->next_used ; ; block=block->next_used)
for (block= my_used_last->next_used ; ; block=block->next_used)
{
if (block->hash_link)
{
#if defined(KEYCACHE_DEBUG)
cnt++;
KEYCACHE_DBUG_ASSERT(cnt <= _my_blocks_used);
KEYCACHE_DBUG_ASSERT(cnt <= my_blocks_used);
#endif
if (flush_key_blocks(block->hash_link->file, FLUSH_RELEASE))
return 1;
break;
}
if (block == _my_used_last)
if (block == my_used_last)
break;
}
}
......@@ -1698,11 +1746,11 @@ static void keycache_dump()
}
while (thread != last);
for (i=0 ; i< _my_blocks_used ; i++)
for (i=0 ; i< my_blocks_used ; i++)
{
int j;
block=&_my_block_root[i];
hash_link=block->hash_link;
block= &my_block_root[i];
hash_link= block->hash_link;
fprintf(keycache_dump_file,
"block:%u hash_link:%d status:%x #requests=%u waiting_for_readers:%d\n",
i, (int) (hash_link ? HASH_LINK_NUMBER(hash_link) : -1),
......@@ -1713,6 +1761,7 @@ static void keycache_dump()
thread=last=wqueue->last_thread;
fprintf(keycache_dump_file, "queue #%d\n", j);
if (thread)
{
do
{
thread=thread->next;
......@@ -1724,16 +1773,19 @@ static void keycache_dump()
while (thread != last);
}
}
}
fprintf(keycache_dump_file, "LRU chain:");
block=_my_used_last;
block= my_used_last;
if (block)
{
do
{
block=block->next_used;
fprintf(keycache_dump_file,
"block:%u, ", BLOCK_NUMBER(block));
}
while (block != _my_used_last);
while (block != my_used_last);
}
fprintf(keycache_dump_file, "\n");
fclose(keycache_dump_file);
......@@ -1867,4 +1919,3 @@ void keycache_debug_log_close(void)
#endif /* defined(KEYCACHE_DEBUG_LOG) */
#endif /* defined(KEYCACHE_DEBUG) */
......@@ -4415,13 +4415,13 @@ struct show_var_st status_vars[]= {
{"Handler_rollback", (char*) &ha_rollback_count, SHOW_LONG},
{"Handler_update", (char*) &ha_update_count, SHOW_LONG},
{"Handler_write", (char*) &ha_write_count, SHOW_LONG},
{"Key_blocks_used", (char*) &_my_blocks_used, SHOW_LONG_CONST},
{"Key_read_requests", (char*) &_my_cache_r_requests, SHOW_LONG},
{"Key_reads", (char*) &_my_cache_read, SHOW_LONG},
{"Key_write_requests", (char*) &_my_cache_w_requests, SHOW_LONG},
{"Key_writes", (char*) &_my_cache_write, SHOW_LONG},
{"Key_blocks_used", (char*) &my_blocks_used, SHOW_LONG_CONST},
{"Key_read_requests", (char*) &my_cache_r_requests, SHOW_LONG},
{"Key_reads", (char*) &my_cache_read, SHOW_LONG},
{"Key_write_requests", (char*) &my_cache_w_requests, SHOW_LONG},
{"Key_writes", (char*) &my_cache_write, SHOW_LONG},
{"Max_used_connections", (char*) &max_used_connections, SHOW_LONG},
{"Not_flushed_key_blocks", (char*) &_my_blocks_changed, SHOW_LONG_CONST},
{"Not_flushed_key_blocks", (char*) &my_blocks_changed, SHOW_LONG_CONST},
{"Not_flushed_delayed_rows", (char*) &delayed_rows_in_use, SHOW_LONG_CONST},
{"Open_tables", (char*) 0, SHOW_OPENTABLES},
{"Open_files", (char*) &my_file_opened, SHOW_LONG_CONST},
......
......@@ -321,8 +321,8 @@ w_requests: %10lu\n\
writes: %10lu\n\
r_requests: %10lu\n\
reads: %10lu\n",
_my_blocks_used,_my_blocks_changed,_my_cache_w_requests,
_my_cache_write,_my_cache_r_requests,_my_cache_read);
my_blocks_used,my_blocks_changed,my_cache_w_requests,
my_cache_write,my_cache_r_requests,my_cache_read);
pthread_mutex_unlock(&THR_LOCK_keycache);
if (thd)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment