diff -Nur mysql-5.0.25-nightly-20060823.orig/sql/hash_filo.cc mysql-5.0.25-nightly-20060823.host_cache00/sql/hash_filo.cc --- mysql-5.0.25-nightly-20060823.orig/sql/hash_filo.cc 2006-08-22 23:09:16.000000000 -0700 +++ mysql-5.0.25-nightly-20060823.host_cache00/sql/hash_filo.cc 2006-09-25 20:30:32.000000000 -0700 @@ -16,8 +16,8 @@ /* -** A class for static sized hash tables where old entries are deleted according -** to usage. + A class for statically-sized hash tables, where entries maintained in + least recently used order using a doubly-linked list for easy traversal. */ #ifdef USE_PRAGMA_IMPLEMENTATION @@ -26,3 +26,107 @@ #include "mysql_priv.h" #include "hash_filo.h" + +hash_filo::hash_filo(uint size_arg, uint key_offset_arg, uint key_length_arg, + hash_get_key get_key_arg, hash_free_key free_element_arg, + CHARSET_INFO *hash_charset_arg) + :size(size_arg), key_offset(key_offset_arg), key_length(key_length_arg), + get_key(get_key_arg), free_element(free_element_arg), init(0), + hash_charset(hash_charset_arg) +{ + bzero((char*) &cache, sizeof(cache)); +} + +hash_filo::~hash_filo() +{ + if (init) + { + if (cache.array.buffer) /* Avoid problems with thread library */ + (void) hash_free(&cache); + pthread_mutex_destroy(&lock); + } +} + +void hash_filo::clear(bool locked) +{ + if (!init) + { + init=1; + (void) pthread_mutex_init(&lock, MY_MUTEX_INIT_FAST); + } + if (!locked) + (void) pthread_mutex_lock(&lock); + (void) hash_free(&cache); + (void) hash_init(&cache, hash_charset, size, key_offset, + key_length, get_key, free_element, 0); + if (!locked) + (void) pthread_mutex_unlock(&lock); + newest_element_p= oldest_element_p= NULL; +} + +void hash_filo::resize(uint new_size) +{ + (void) pthread_mutex_lock(&lock); + size= new_size; + clear(1); + (void) pthread_mutex_unlock(&lock); +} + +hash_filo_element *hash_filo::search(gptr key, uint length) +{ + hash_filo_element *entry= (hash_filo_element*) hash_search(&cache, + (byte*) key, + length); + if (entry) + { // Found; link it first + if (entry != newest_element_p) + { // Relink used-chain + if (entry == oldest_element_p) + oldest_element_p= entry->newer_element_p; + else { + entry->older_element_p->newer_element_p= entry->newer_element_p; + entry->newer_element_p->older_element_p= entry->older_element_p; + } + if ((entry->older_element_p= newest_element_p)) + newest_element_p->newer_element_p= entry; + newest_element_p= entry; + } + } + return entry; +} + +my_bool hash_filo::add(hash_filo_element *entry) +{ + if(unlikely(size == 0)) { + /* Our HASH size is 0, so throw away any entries attempted. */ + if(free_element) + (*free_element)(entry); + return 0; + } + + if (cache.records == size) + { + hash_filo_element *tmp= oldest_element_p; + + if((oldest_element_p= oldest_element_p->newer_element_p)) + oldest_element_p->older_element_p= NULL; + else + newest_element_p = NULL; + + hash_delete(&cache, (byte*) tmp); + } + + if (my_hash_insert(&cache, (byte*) entry)) + { + if (free_element) + (*free_element)(entry); // This should never happen + return 1; + } + + if ((entry->older_element_p= newest_element_p)) + newest_element_p->newer_element_p= entry; + else + oldest_element_p= entry; + newest_element_p= entry; + return 0; +} diff -Nur mysql-5.0.25-nightly-20060823.orig/sql/hash_filo.h mysql-5.0.25-nightly-20060823.host_cache00/sql/hash_filo.h --- mysql-5.0.25-nightly-20060823.orig/sql/hash_filo.h 2006-08-22 23:09:19.000000000 -0700 +++ mysql-5.0.25-nightly-20060823.host_cache00/sql/hash_filo.h 2006-09-25 20:30:32.000000000 -0700 @@ -16,8 +16,8 @@ /* -** A class for static sized hash tables where old entries are deleted in -** first-in-last-out to usage. + A class for statically-sized hash tables, where entries maintained in + least recently used order using a doubly-linked list for easy traversal. */ #ifndef HASH_FILO_H @@ -29,106 +29,43 @@ class hash_filo_element { - hash_filo_element *next_used,*prev_used; + hash_filo_element *newer_element_p, *older_element_p; public: hash_filo_element() {} + hash_filo_element *newer_element() { return newer_element_p; } + hash_filo_element *older_element() { return older_element_p; } friend class hash_filo; }; class hash_filo { - const uint size, key_offset, key_length; + uint size; + const uint key_offset, key_length; const hash_get_key get_key; hash_free_key free_element; bool init; CHARSET_INFO *hash_charset; - hash_filo_element *first_link,*last_link; + hash_filo_element *newest_element_p, *oldest_element_p; + public: pthread_mutex_t lock; HASH cache; - hash_filo(uint size_arg, uint key_offset_arg , uint key_length_arg, - hash_get_key get_key_arg, hash_free_key free_element_arg, - CHARSET_INFO *hash_charset_arg) - :size(size_arg), key_offset(key_offset_arg), key_length(key_length_arg), - get_key(get_key_arg), free_element(free_element_arg),init(0), - hash_charset(hash_charset_arg) - { - bzero((char*) &cache,sizeof(cache)); - } - - ~hash_filo() - { - if (init) - { - if (cache.array.buffer) /* Avoid problems with thread library */ - (void) hash_free(&cache); - pthread_mutex_destroy(&lock); - } - } - void clear(bool locked=0) - { - if (!init) - { - init=1; - (void) pthread_mutex_init(&lock,MY_MUTEX_INIT_FAST); - } - if (!locked) - (void) pthread_mutex_lock(&lock); - (void) hash_free(&cache); - (void) hash_init(&cache,hash_charset,size,key_offset, - key_length, get_key, free_element,0); - if (!locked) - (void) pthread_mutex_unlock(&lock); - first_link=last_link=0; - } - - hash_filo_element *search(gptr key,uint length) - { - hash_filo_element *entry=(hash_filo_element*) - hash_search(&cache,(byte*) key,length); - if (entry) - { // Found; link it first - if (entry != first_link) - { // Relink used-chain - if (entry == last_link) - last_link=entry->prev_used; - else - { - entry->next_used->prev_used = entry->prev_used; - entry->prev_used->next_used = entry->next_used; - } - if ((entry->next_used= first_link)) - first_link->prev_used=entry; - first_link=entry; - } - } - return entry; - } - - my_bool add(hash_filo_element *entry) - { - if (cache.records == size) - { - hash_filo_element *tmp=last_link; - last_link=last_link->prev_used; - hash_delete(&cache,(byte*) tmp); - } - if (my_hash_insert(&cache,(byte*) entry)) - { - if (free_element) - (*free_element)(entry); // This should never happen - return 1; - } - if ((entry->next_used=first_link)) - first_link->prev_used=entry; - else - last_link=entry; - first_link=entry; - return 0; - } + hash_filo(uint size_arg, uint key_offset_arg, uint key_length_arg, + hash_get_key get_key_arg, hash_free_key free_element_arg, + CHARSET_INFO *hash_charset_arg); + ~hash_filo(); + + hash_filo_element *newest_element() { return newest_element_p; } + hash_filo_element *oldest_element() { return oldest_element_p; } + + void clear(bool locked=0); + void resize(uint new_size); + + hash_filo_element *search(gptr key, uint length); + my_bool add(hash_filo_element *entry); }; #endif