=== modified file 'Percona-Server/storage/myisam/ha_myisam.cc'
--- Percona-Server/storage/myisam/ha_myisam.cc	2013-01-18 04:53:12 +0000
+++ Percona-Server/storage/myisam/ha_myisam.cc	2013-02-25 04:28:26 +0000
@@ -2179,6 +2179,9 @@
   myisam_hton->flags= HTON_CAN_RECREATE | HTON_SUPPORT_LOG_TABLES;
   myisam_hton->is_supported_system_table= myisam_is_supported_system_table;
 
+  if (mi_init_open_table_hash(table_cache_size))
+    return 1;
+
   return 0;
 }
 

=== modified file 'Percona-Server/storage/myisam/mi_close.c'
--- Percona-Server/storage/myisam/mi_close.c	2012-08-29 12:49:37 +0000
+++ Percona-Server/storage/myisam/mi_close.c	2013-02-25 04:28:26 +0000
@@ -1,4 +1,4 @@
-/* Copyright (c) 2000, 2011, Oracle and/or its affiliates. All rights reserved.
+/* Copyright (c) 2001, 2011, Oracle and/or its affiliates. All rights reserved.
 
    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
@@ -31,8 +31,7 @@
 		      (long) info, (uint) share->reopen,
                       (uint) share->tot_locks));
 
-  if (info->open_list.data)
-    mysql_mutex_lock(&THR_LOCK_myisam);
+  mysql_mutex_lock(&THR_LOCK_myisam);
   if (info->lock_type == F_EXTRA_LCK)
     info->lock_type=F_UNLCK;			/* HA_EXTRA_NO_USER_CHANGE */
 
@@ -55,8 +54,7 @@
     info->opt_flag&= ~(READ_CACHE_USED | WRITE_CACHE_USED);
   }
   flag= !--share->reopen;
-  if (info->open_list.data)
-    myisam_open_list= list_delete(myisam_open_list, &info->open_list);
+  my_hash_delete(&myisam_open_table_hash, (uchar *) info);
   mysql_mutex_unlock(&share->intern_lock);
 
   my_free(mi_get_rec_buff_ptr(info, info->rec_buff));
@@ -110,8 +108,7 @@
     }
     my_free(info->s);
   }
-  if (info->open_list.data)
-    mysql_mutex_unlock(&THR_LOCK_myisam);
+  mysql_mutex_unlock(&THR_LOCK_myisam);
   if (info->ftparser_param)
   {
     my_free(info->ftparser_param);

=== modified file 'Percona-Server/storage/myisam/mi_dbug.c'
--- Percona-Server/storage/myisam/mi_dbug.c	2012-03-06 14:29:42 +0000
+++ Percona-Server/storage/myisam/mi_dbug.c	2013-02-25 04:28:26 +0000
@@ -181,14 +181,14 @@
 my_bool check_table_is_closed(const char *name, const char *where)
 {
   char filename[FN_REFLEN];
-  LIST *pos;
+  uint idx;
   DBUG_ENTER("check_table_is_closed");
 
   (void) fn_format(filename,name,"",MI_NAME_IEXT,4+16+32);
   mysql_mutex_lock(&THR_LOCK_myisam);
-  for (pos=myisam_open_list ; pos ; pos=pos->next)
+  for (idx= 0; idx < myisam_open_table_hash.records; ++idx)
   {
-    MI_INFO *info=(MI_INFO*) pos->data;
+    MI_INFO *info=(MI_INFO*) my_hash_element(&myisam_open_table_hash, idx);
     MYISAM_SHARE *share=info->s;
     if (!strcmp(share->unique_file_name,filename))
     {

=== modified file 'Percona-Server/storage/myisam/mi_keycache.c'
--- Percona-Server/storage/myisam/mi_keycache.c	2011-09-07 10:08:09 +0000
+++ Percona-Server/storage/myisam/mi_keycache.c	2013-02-25 04:28:26 +0000
@@ -138,16 +138,16 @@
 void mi_change_key_cache(KEY_CACHE *old_key_cache,
 			 KEY_CACHE *new_key_cache)
 {
-  LIST *pos;
+  uint idx;
   DBUG_ENTER("mi_change_key_cache");
 
   /*
     Lock list to ensure that no one can close the table while we manipulate it
   */
   mysql_mutex_lock(&THR_LOCK_myisam);
-  for (pos=myisam_open_list ; pos ; pos=pos->next)
+  for (idx= 0; idx < myisam_open_table_hash.records; ++idx)
   {
-    MI_INFO *info= (MI_INFO*) pos->data;
+    MI_INFO *info=(MI_INFO*) my_hash_element(&myisam_open_table_hash, idx);
     MYISAM_SHARE *share= info->s;
     if (share->key_cache == old_key_cache)
       mi_assign_to_key_cache(info, (ulonglong) ~0, new_key_cache);

=== modified file 'Percona-Server/storage/myisam/mi_open.c'
--- Percona-Server/storage/myisam/mi_open.c	2012-11-14 11:44:35 +0000
+++ Percona-Server/storage/myisam/mi_open.c	2013-02-25 04:28:26 +0000
@@ -48,23 +48,76 @@
 }
 
 
-/******************************************************************************
-** Return the shared struct if the table is already open.
-** In MySQL the server will handle version issues.
-******************************************************************************/
-
+/*
+  Get the value used as hash key (helper function for the 
+  open table hash).  Function is used as a callback 
+  from the hash table
+*/
+static uchar *mi_open_table_hash_key(const uchar *record, size_t *length,
+                                     my_bool not_used __attribute__((unused)))
+{
+  MI_INFO *info= (MI_INFO *) record;
+  *length= info->s->unique_name_length;
+  return (uchar*) info->s->unique_file_name;
+}
+
+/**
+  Initialize open table hash
+ 
+  Function is normally called from myisam_init
+  with the system variable table_cache_size used
+  as hash_size.
+
+  @param[in]      hash_size Initial has size (elements)
+  @return         inidicates success or failure of initialization
+    @retval 0 success
+    @retval 1 failure
+
+*/
+int mi_init_open_table_hash(ulong hash_size)
+{
+  if (hash_size == 0)
+    hash_size= 32; /* default hash size */
+
+  if (my_hash_init(&myisam_open_table_hash, &my_charset_filename, 
+                   hash_size, 0, 0, mi_open_table_hash_key, 0, 0))
+    return 1; /* error */
+  
+  return 0;
+}
+
+
+/**
+  Retrieve the shared struct if the table is already
+  open (i.e  in the open table hash)
+
+  @param[in] filename table file name
+  @return    shared struct, 0 if not in the cache
+*/
 MI_INFO *test_if_reopen(char *filename)
 {
-  LIST *pos;
+  HASH_SEARCH_STATE current_record;
+  int len= strlen(filename);
 
-  for (pos=myisam_open_list ; pos ; pos=pos->next)
+  MI_INFO *info= (MI_INFO*) my_hash_first(&myisam_open_table_hash, 
+                                          (uchar *) filename, 
+                                          len, &current_record);
+  /*
+    There might be more than one instance of a table share for
+    a given table in the hash table.  We're interested in the one with 
+    last_version set, so we iterate until we find it
+  */
+  while (info)
   {
-    MI_INFO *info=(MI_INFO*) pos->data;
     MYISAM_SHARE *share=info->s;
-    if (!strcmp(share->unique_file_name,filename) && share->last_version)
-      return info;
+    if (share->last_version)
+      break;
+    
+    info= (MI_INFO*) my_hash_next(&myisam_open_table_hash, 
+                                  (uchar *) filename, 
+                                  len, &current_record);
   }
-  return 0;
+  return info;
 }
 
 
@@ -649,8 +702,8 @@
 
   if (!internal_table)
   {
-    m_info->open_list.data= (void*) m_info;
-    myisam_open_list= list_add(myisam_open_list, &m_info->open_list);
+    if (my_hash_insert(&myisam_open_table_hash, (uchar *) m_info))
+      goto err;
     mysql_mutex_unlock(&THR_LOCK_myisam);
   }
 

=== modified file 'Percona-Server/storage/myisam/mi_panic.c'
--- Percona-Server/storage/myisam/mi_panic.c	2011-09-07 10:08:09 +0000
+++ Percona-Server/storage/myisam/mi_panic.c	2013-02-25 04:28:26 +0000
@@ -27,22 +27,36 @@
 int mi_panic(enum ha_panic_function flag)
 {
   int error=0;
-  LIST *list_element,*next_open;
   MI_INFO *info;
+  uint idx;
   DBUG_ENTER("mi_panic");
 
   mysql_mutex_lock(&THR_LOCK_myisam);
-  for (list_element=myisam_open_list ; list_element ; list_element=next_open)
+
+  if (!my_hash_inited(&myisam_open_table_hash))
+    goto finish;
+
+  if (flag == HA_PANIC_CLOSE)
   {
-    next_open=list_element->next;		/* Save if close */
-    info=(MI_INFO*) list_element->data;
-    switch (flag) {
-    case HA_PANIC_CLOSE:
+    while (myisam_open_table_hash.records)
+    {
+      /*
+         As long as there are records in the hash, fetch the
+         first, and close it.
+      */
+      info=(MI_INFO*) my_hash_element(&myisam_open_table_hash, 0);
       mysql_mutex_unlock(&THR_LOCK_myisam);     /* Not exactly right... */
       if (mi_close(info))
-	error=my_errno;
+        error= my_errno;
       mysql_mutex_lock(&THR_LOCK_myisam);
-      break;
+    }
+  }
+
+  for (idx= 0; idx < myisam_open_table_hash.records; ++idx)
+  {
+    info=(MI_INFO*) my_hash_element(&myisam_open_table_hash, idx);
+    switch (flag) {
+    case HA_PANIC_CLOSE: break;
     case HA_PANIC_WRITE:		/* Do this to free databases */
 #ifdef CANT_OPEN_FILES_TWICE
       if (info->s->options & HA_OPTION_READ_ONLY_DATA)
@@ -111,6 +125,8 @@
     (void) mi_log(0);				/* Close log if neaded */
     ft_free_stopwords();
   }
+
+finish:
   mysql_mutex_unlock(&THR_LOCK_myisam);
   if (!error)
     DBUG_RETURN(0);

=== modified file 'Percona-Server/storage/myisam/mi_static.c'
--- Percona-Server/storage/myisam/mi_static.c	2011-12-09 21:08:37 +0000
+++ Percona-Server/storage/myisam/mi_static.c	2013-02-25 04:28:26 +0000
@@ -22,7 +22,7 @@
 #include "myisamdef.h"
 #endif
 
-LIST	*myisam_open_list=0;
+HASH    myisam_open_table_hash;
 uchar	myisam_file_magic[]=
 { (uchar) 254, (uchar) 254,'\007', '\001', };
 uchar	myisam_pack_file_magic[]=

=== modified file 'Percona-Server/storage/myisam/myisamchk.c'
--- Percona-Server/storage/myisam/myisamchk.c	2013-01-18 04:53:12 +0000
+++ Percona-Server/storage/myisam/myisamchk.c	2013-02-25 04:28:26 +0000
@@ -89,6 +89,12 @@
   get_options(&argc,(char***) &argv);
   myisam_quick_table_bits=decode_bits;
   error=0;
+  if (mi_init_open_table_hash(0))
+  {
+    fprintf(stderr, "Can't initialize MyISAM storage engine\n");
+    exit(-1);
+  }
+
   while (--argc >= 0)
   {
     int new_error=myisamchk(&check_param, *(argv++));

=== modified file 'Percona-Server/storage/myisam/myisamdef.h'
--- Percona-Server/storage/myisam/myisamdef.h	2012-03-06 14:29:42 +0000
+++ Percona-Server/storage/myisam/myisamdef.h	2013-02-25 04:28:26 +0000
@@ -22,6 +22,7 @@
 #include <my_pthread.h>
 #include <thr_lock.h>
 #include <mysql/psi/mysql_file.h>
+#include "hash.h"
 
 /* undef map from my_nosys; We need test-if-disk full */
 #if defined(my_write)
@@ -284,7 +285,6 @@
   uint	data_changed;			/* Somebody has changed data */
   uint	save_update;			/* When using KEY_READ */
   int	save_lastinx;
-  LIST	open_list;
   IO_CACHE rec_cache;			/* When cacheing records */
   uint  preload_buff_size;              /* When preloading indexes */
   myf lock_wait;			/* is 0 or MY_DONT_WAIT */
@@ -471,8 +471,7 @@
 #endif
 
 	/* Some extern variables */
-
-extern LIST *myisam_open_list;
+extern HASH myisam_open_table_hash;
 extern uchar myisam_file_magic[], myisam_pack_file_magic[];
 extern uint myisam_read_vec[], myisam_readnext_vec[];
 extern uint myisam_quick_table_bits;
@@ -754,6 +753,7 @@
 void mi_disable_non_unique_index(MI_INFO *info, ha_rows rows);
 
 extern MI_INFO *test_if_reopen(char *filename);
+extern int mi_init_open_table_hash(ulong size);
 my_bool check_table_is_closed(const char *name, const char *where);
 int mi_open_datafile(MI_INFO *info, MYISAM_SHARE *share, const char *orn_name,
                      File file_to_dup);

=== modified file 'Percona-Server/storage/myisam/myisampack.c'
--- Percona-Server/storage/myisam/myisampack.c	2013-02-12 07:47:19 +0000
+++ Percona-Server/storage/myisam/myisampack.c	2013-02-25 04:28:26 +0000
@@ -208,9 +208,12 @@
   char **default_argv;
   MY_INIT(argv[0]);
 
-  if (load_defaults("my",load_default_groups,&argc,&argv))
+  if (load_defaults("my",load_default_groups,&argc,&argv) ||
+      mi_init_open_table_hash(0))
+  {
+    fputs("Can't initialize MyISAM storage engine", stderr);
     exit(1);
-
+  }
   default_argv= argv;
   get_options(&argc,&argv);
 

