summaryrefslogtreecommitdiff
path: root/sql/sql_base.cc
diff options
context:
space:
mode:
authorunknown <serg@serg.mylan>2003-10-31 10:34:34 +0100
committerunknown <serg@serg.mylan>2003-10-31 10:34:34 +0100
commitb04629049af702ba4a4ce1b0dc2d4e5d2e698da1 (patch)
treee3649ecfe44ca927dd7369b8cd2116bb28646ad0 /sql/sql_base.cc
parente9f308f0b91adb560c75f5d7e333c07949154e7d (diff)
parentff182082576e4c23fe5049597b2d5ae9b4158526 (diff)
downloadmariadb-git-b04629049af702ba4a4ce1b0dc2d4e5d2e698da1.tar.gz
Merge bk-internal:/home/bk/mysql-4.1/
into serg.mylan:/usr/home/serg/Abk/mysql-4.1 myisam/mi_check.c: Auto merged myisam/mi_delete.c: Auto merged myisam/mi_write.c: Auto merged myisam/myisamchk.c: Auto merged myisam/myisamdef.h: Auto merged mysql-test/r/mysqldump.result: Auto merged mysql-test/r/range.result: Auto merged sql/ha_myisam.cc: Auto merged sql/ha_myisam.h: Auto merged sql/ha_myisammrg.cc: Auto merged sql/handler.h: Auto merged sql/item_cmpfunc.h: Auto merged sql/mysql_priv.h: Auto merged sql/mysqld.cc: Auto merged sql/opt_range.cc: Auto merged sql/set_var.cc: Auto merged sql/sql_base.cc: Auto merged sql/sql_parse.cc: Auto merged sql/sql_table.cc: Auto merged sql/sql_test.cc: Auto merged sql/sql_yacc.yy: Auto merged
Diffstat (limited to 'sql/sql_base.cc')
-rw-r--r--sql/sql_base.cc131
1 files changed, 129 insertions, 2 deletions
diff --git a/sql/sql_base.cc b/sql/sql_base.cc
index b151400db68..cc068451ecf 100644
--- a/sql/sql_base.cc
+++ b/sql/sql_base.cc
@@ -30,6 +30,7 @@
TABLE *unused_tables; /* Used by mysql_test */
HASH open_cache; /* Used by mysql_test */
+HASH assign_cache;
static int open_unireg_entry(THD *thd,TABLE *entry,const char *db,
const char *name, const char *alias);
@@ -53,7 +54,6 @@ void table_cache_init(void)
mysql_rm_tmp_tables();
}
-
void table_cache_free(void)
{
DBUG_ENTER("table_cache_free");
@@ -63,7 +63,6 @@ void table_cache_free(void)
DBUG_VOID_RETURN;
}
-
uint cached_tables(void)
{
return open_cache.records;
@@ -762,6 +761,8 @@ TABLE *open_table(THD *thd,const char *db,const char *table_name,
reg1 TABLE *table;
char key[MAX_DBKEY_LENGTH];
uint key_length;
+ KEY_CACHE_ASMT *key_cache_asmt;
+ KEY_CACHE_VAR *key_cache;
DBUG_ENTER("open_table");
/* find a unused table in the open table cache */
@@ -802,6 +803,77 @@ TABLE *open_table(THD *thd,const char *db,const char *table_name,
my_printf_error(ER_TABLE_NOT_LOCKED,ER(ER_TABLE_NOT_LOCKED),MYF(0),alias);
DBUG_RETURN(0);
}
+
+ VOID(pthread_mutex_lock(&LOCK_assign));
+ key_cache_asmt= (KEY_CACHE_ASMT*) hash_search(&assign_cache,
+ (byte*) key, key_length) ;
+ if (thd->open_options & HA_OPEN_TO_ASSIGN)
+ {
+ /* When executing a CACHE INDEX command*/
+ if (key_cache_asmt)
+ {
+ if (key_cache_asmt->requests++)
+ {
+ /* Another thread are assigning this table to some key cache*/
+
+ /* Put the assignment request into the queue of such requests */
+ struct st_my_thread_var *last;
+ struct st_my_thread_var *thread= thd->mysys_var;
+ if (! (last= key_cache_asmt->queue))
+ thread->next= thread;
+ else
+ {
+ thread->next= last->next;
+ last->next= thread;
+ }
+ key_cache_asmt->queue= thread;
+
+ /* Wait until the request can be processed */
+ do
+ {
+ VOID(pthread_cond_wait(&thread->suspend, &LOCK_assign));
+ }
+ while (thread->next);
+ }
+ }
+ else
+ {
+ /*
+ The table has not been explicitly assigned to any key cache yet;
+ by default it's assigned to the default key cache;
+ */
+
+ if (!(key_cache_asmt=
+ (KEY_CACHE_ASMT *) my_malloc(sizeof(*key_cache_asmt),
+ MYF(MY_WME | MY_ZEROFILL))) ||
+ !(key_cache_asmt->db_name= my_strdup(db, MYF(MY_WME))) ||
+ !(key_cache_asmt->table_name= my_strdup(table_name, MYF(MY_WME))) ||
+ !(key_cache_asmt->table_key= my_memdup((const byte *) key,
+ key_length, MYF(MY_WME))))
+ {
+ VOID(pthread_mutex_unlock(&LOCK_assign));
+
+ if (key_cache_asmt)
+ {
+ if (key_cache_asmt->db_name)
+ my_free((gptr) key_cache_asmt->db_name, MYF(0));
+ if (key_cache_asmt->table_name)
+ my_free((gptr) key_cache_asmt->table_name, MYF(0));
+ my_free((gptr) key_cache_asmt, MYF(0));
+ }
+ DBUG_RETURN(NULL);
+ }
+ key_cache_asmt->key_length= key_length;
+ key_cache_asmt->key_cache= &dflt_key_cache_var;
+ VOID(my_hash_insert(&assign_cache, (byte *) key_cache_asmt));
+ key_cache_asmt->requests++;
+ }
+ key_cache_asmt->to_reassign= 0;
+ }
+
+ key_cache= key_cache_asmt ? key_cache_asmt->key_cache : &dflt_key_cache_var;
+ VOID(pthread_mutex_unlock(&LOCK_assign));
+
VOID(pthread_mutex_lock(&LOCK_open));
if (!thd->open_tables)
@@ -844,6 +916,9 @@ TABLE *open_table(THD *thd,const char *db,const char *table_name,
}
table->prev->next=table->next; /* Remove from unused list */
table->next->prev=table->prev;
+
+ table->key_cache= key_cache;
+ table->key_cache_asmt= key_cache_asmt;
}
else
{
@@ -857,6 +932,8 @@ TABLE *open_table(THD *thd,const char *db,const char *table_name,
VOID(pthread_mutex_unlock(&LOCK_open));
DBUG_RETURN(NULL);
}
+ table->key_cache= key_cache;
+ table->key_cache_asmt= key_cache_asmt;
if (open_unireg_entry(thd, table,db,table_name,alias) ||
!(table->table_cache_key=memdup_root(&table->mem_root,(char*) key,
key_length)))
@@ -875,6 +952,8 @@ TABLE *open_table(THD *thd,const char *db,const char *table_name,
table->in_use=thd;
check_unused();
+
+
VOID(pthread_mutex_unlock(&LOCK_open));
if (refresh)
{
@@ -1646,6 +1725,54 @@ bool rm_temporary_table(enum db_type base, char *path)
DBUG_RETURN(error);
}
+static void free_assign_entry(KEY_CACHE_ASMT *key_cache_asmt)
+{
+ DBUG_ENTER("free_assign_entry");
+ my_free((gptr) key_cache_asmt->table_key, MYF(0));
+ my_free((gptr) key_cache_asmt, MYF(0));
+ DBUG_VOID_RETURN;
+}
+
+static byte *assign_cache_key(const byte *record,uint *length,
+ my_bool not_used __attribute__((unused)))
+{
+ KEY_CACHE_ASMT *entry=(KEY_CACHE_ASMT *) record;
+ *length=entry->key_length;
+ return (byte*) entry->table_key;
+}
+
+void assign_cache_init(void)
+{
+ VOID(hash_init(&assign_cache, &my_charset_bin,
+ table_cache_size+16, 0, 0, assign_cache_key,
+ (hash_free_key) free_assign_entry,0));
+}
+
+void assign_cache_free(void)
+{
+ DBUG_ENTER("assign_cache_free");
+ hash_free(&assign_cache);
+ DBUG_VOID_RETURN;
+}
+
+void reassign_key_cache(KEY_CACHE_ASMT *key_cache_asmt,
+ KEY_CACHE_VAR *new_key_cache)
+{
+ if (key_cache_asmt->prev)
+ {
+ /* Unlink key_cache_asmt from the assignment list for the old key cache */
+ if ((*key_cache_asmt->prev= key_cache_asmt->next))
+ key_cache_asmt->next->prev= key_cache_asmt->prev;
+ }
+ /* Link key_cache_asmt into the assignment list for the new key cache */
+ key_cache_asmt->prev= &new_key_cache->assign_list;
+ if ((key_cache_asmt->next= new_key_cache->assign_list))
+ key_cache_asmt->next->prev= &key_cache_asmt->next;
+ new_key_cache->assign_list= key_cache_asmt;
+
+ key_cache_asmt->key_cache= new_key_cache;
+}
+
/*****************************************************************************
** find field in list or tables. if field is unqualifed and unique,