Commit ea6a22bf authored by Konstantin Osipov's avatar Konstantin Osipov

Introduce thd->query_cache_tls (thread

local storage for query cache). 
We need more than one pointer in a thread to
represent the query cache and net->query_cache_query can not be used
any more (due to ABI compatibility issues and to different life
time of NET and THD).
This is a backport of the following patch from 6.0:
----------------------------------------------------------
revno: 2476.1157.2
committer: kostja@bodhi.(none)
timestamp: Sat 2007-06-16 13:29:24 +0400
parent 10390cec
...@@ -32,7 +32,7 @@ typedef struct st_net { ...@@ -32,7 +32,7 @@ typedef struct st_net {
my_bool unused2; my_bool unused2;
my_bool compress; my_bool compress;
my_bool unused3; my_bool unused3;
unsigned char *query_cache_query; unsigned char *unused;
unsigned int last_errno; unsigned int last_errno;
unsigned char error; unsigned char error;
my_bool unused4; my_bool unused4;
......
...@@ -264,10 +264,9 @@ typedef struct st_net { ...@@ -264,10 +264,9 @@ typedef struct st_net {
*/ */
#endif #endif
/* /*
'query_cache_query' should be accessed only via query cache Unused, please remove with the next incompatible ABI change.
functions and methods to maintain proper locking.
*/ */
unsigned char *query_cache_query; unsigned char *unused;
unsigned int last_errno; unsigned int last_errno;
unsigned char error; unsigned char error;
my_bool unused4; /* Please remove with the next incompatible ABI change. */ my_bool unused4; /* Please remove with the next incompatible ABI change. */
......
...@@ -905,6 +905,8 @@ struct Query_cache_query_flags ...@@ -905,6 +905,8 @@ struct Query_cache_query_flags
}; };
#define QUERY_CACHE_FLAGS_SIZE sizeof(Query_cache_query_flags) #define QUERY_CACHE_FLAGS_SIZE sizeof(Query_cache_query_flags)
#include "sql_cache.h" #include "sql_cache.h"
#define query_cache_abort(A) query_cache.abort(A)
#define query_cache_end_of_result(A) query_cache.end_of_result(A)
#define query_cache_store_query(A, B) query_cache.store_query(A, B) #define query_cache_store_query(A, B) query_cache.store_query(A, B)
#define query_cache_destroy() query_cache.destroy() #define query_cache_destroy() query_cache.destroy()
#define query_cache_result_size_limit(A) query_cache.result_size_limit(A) #define query_cache_result_size_limit(A) query_cache.result_size_limit(A)
......
...@@ -95,8 +95,8 @@ extern pthread_mutex_t LOCK_bytes_sent , LOCK_bytes_received; ...@@ -95,8 +95,8 @@ extern pthread_mutex_t LOCK_bytes_sent , LOCK_bytes_received;
#ifndef MYSQL_INSTANCE_MANAGER #ifndef MYSQL_INSTANCE_MANAGER
#ifdef HAVE_QUERY_CACHE #ifdef HAVE_QUERY_CACHE
#define USE_QUERY_CACHE #define USE_QUERY_CACHE
extern void query_cache_init_query(NET *net); extern void query_cache_insert(const char *packet, ulong length,
extern void query_cache_insert(NET *net, const char *packet, ulong length); unsigned pkt_nr);
#endif // HAVE_QUERY_CACHE #endif // HAVE_QUERY_CACHE
#define update_statistics(A) A #define update_statistics(A) A
#endif /* MYSQL_INSTANCE_MANGER */ #endif /* MYSQL_INSTANCE_MANGER */
...@@ -132,11 +132,7 @@ my_bool my_net_init(NET *net, Vio* vio) ...@@ -132,11 +132,7 @@ my_bool my_net_init(NET *net, Vio* vio)
net->compress=0; net->reading_or_writing=0; net->compress=0; net->reading_or_writing=0;
net->where_b = net->remain_in_buf=0; net->where_b = net->remain_in_buf=0;
net->last_errno=0; net->last_errno=0;
#ifdef USE_QUERY_CACHE net->unused= 0;
query_cache_init_query(net);
#else
net->query_cache_query= 0;
#endif
if (vio != 0) /* If real connection */ if (vio != 0) /* If real connection */
{ {
...@@ -586,7 +582,7 @@ net_real_write(NET *net,const uchar *packet, size_t len) ...@@ -586,7 +582,7 @@ net_real_write(NET *net,const uchar *packet, size_t len)
DBUG_ENTER("net_real_write"); DBUG_ENTER("net_real_write");
#if defined(MYSQL_SERVER) && defined(USE_QUERY_CACHE) #if defined(MYSQL_SERVER) && defined(USE_QUERY_CACHE)
query_cache_insert(net, (char*) packet, len); query_cache_insert((char*) packet, len, net->pkt_nr);
#endif #endif
if (net->error == 2) if (net->error == 2)
......
...@@ -789,19 +789,20 @@ uchar *query_cache_query_get_key(const uchar *record, size_t *length, ...@@ -789,19 +789,20 @@ uchar *query_cache_query_get_key(const uchar *record, size_t *length,
Note on double-check locking (DCL) usage. Note on double-check locking (DCL) usage.
Below, in query_cache_insert(), query_cache_abort() and Below, in query_cache_insert(), query_cache_abort() and
query_cache_end_of_result() we use what is called double-check Query_cache::end_of_result() we use what is called double-check
locking (DCL) for NET::query_cache_query. I.e. we test it first locking (DCL) for Query_cache_tls::first_query_block.
without a lock, and, if positive, test again under the lock. I.e. we test it first without a lock, and, if positive, test again
under the lock.
This means that if we see 'NET::query_cache_query == 0' without a This means that if we see 'first_query_block == 0' without a
lock we will skip the operation. But this is safe here: when we lock we will skip the operation. But this is safe here: when we
started to cache a query, we called Query_cache::store_query(), and started to cache a query, we called Query_cache::store_query(), and
NET::query_cache_query was set to non-zero in this thread (and the 'first_query_block' was set to non-zero in this thread (and the
thread always sees results of its memory operations, mutex or not). thread always sees results of its memory operations, mutex or not).
If later we see 'NET::query_cache_query == 0' without locking a If later we see 'first_query_block == 0' without locking a
mutex, that may only mean that some other thread have reset it by mutex, that may only mean that some other thread have reset it by
invalidating the query. Skipping the operation in this case is the invalidating the query. Skipping the operation in this case is the
right thing to do, as NET::query_cache_query won't get non-zero for right thing to do, as first_query_block won't get non-zero for
this query again. this query again.
See also comments in Query_cache::store_query() and See also comments in Query_cache::store_query() and
...@@ -810,56 +811,71 @@ uchar *query_cache_query_get_key(const uchar *record, size_t *length, ...@@ -810,56 +811,71 @@ uchar *query_cache_query_get_key(const uchar *record, size_t *length,
NOTE, however, that double-check locking is not applicable in NOTE, however, that double-check locking is not applicable in
'invalidate' functions, as we may erroneously skip invalidation, 'invalidate' functions, as we may erroneously skip invalidation,
because the thread doing invalidation may never see non-zero because the thread doing invalidation may never see non-zero
NET::query_cache_query. 'first_query_block'.
*/ */
void query_cache_init_query(NET *net) /**
libmysql convenience wrapper to insert data into query cache.
*/
void query_cache_insert(const char *packet, ulong length,
unsigned pkt_nr)
{ {
THD *thd= current_thd;
/* /*
It is safe to initialize 'NET::query_cache_query' without a lock Current_thd can be NULL when a new connection is immediately ended
here, because before it will be accessed from different threads it due to "Too many connections". thd->store_globals() has not been
will be set in this thread under a lock, and access from the same called at this time and hence my_pthread_setspecific_ptr(THR_THD,
thread is always safe. this) has not been called for this thread.
*/ */
net->query_cache_query= 0;
if (!thd)
return;
query_cache.insert(&thd->query_cache_tls,
packet, length,
pkt_nr);
} }
/* /**
Insert the packet into the query cache. Insert the packet into the query cache.
*/ */
void query_cache_insert(NET *net, const char *packet, ulong length) void
Query_cache::insert(Query_cache_tls *query_cache_tls,
const char *packet, ulong length,
unsigned pkt_nr)
{ {
DBUG_ENTER("query_cache_insert"); DBUG_ENTER("Query_cache::insert");
/* See the comment on double-check locking usage above. */ /* See the comment on double-check locking usage above. */
if (net->query_cache_query == 0) if (query_cache_tls->first_query_block == NULL)
DBUG_VOID_RETURN; DBUG_VOID_RETURN;
DBUG_EXECUTE_IF("wait_in_query_cache_insert", DBUG_EXECUTE_IF("wait_in_query_cache_insert",
debug_wait_for_kill("wait_in_query_cache_insert"); ); debug_wait_for_kill("wait_in_query_cache_insert"); );
if (query_cache.try_lock())
if (try_lock())
DBUG_VOID_RETURN; DBUG_VOID_RETURN;
Query_cache_block *query_block= (Query_cache_block*)net->query_cache_query; Query_cache_block *query_block = query_cache_tls->first_query_block;
if (!query_block) if (query_block == NULL)
{ {
/* /*
We lost the writer and the currently processed query has been We lost the writer and the currently processed query has been
invalidated; there is nothing left to do. invalidated; there is nothing left to do.
*/ */
query_cache.unlock(); unlock();
DBUG_VOID_RETURN; DBUG_VOID_RETURN;
} }
BLOCK_LOCK_WR(query_block); BLOCK_LOCK_WR(query_block);
Query_cache_query *header= query_block->query(); Query_cache_query *header= query_block->query();
Query_cache_block *result= header->result(); Query_cache_block *result= header->result();
DUMP(&query_cache); DUMP(this);
DBUG_PRINT("qcache", ("insert packet %lu bytes long",length)); DBUG_PRINT("qcache", ("insert packet %lu bytes long",length));
/* /*
...@@ -867,7 +883,7 @@ void query_cache_insert(NET *net, const char *packet, ulong length) ...@@ -867,7 +883,7 @@ void query_cache_insert(NET *net, const char *packet, ulong length)
still need structure_guard_mutex to free the query, and therefore unlock still need structure_guard_mutex to free the query, and therefore unlock
it later in this function. it later in this function.
*/ */
if (!query_cache.append_result_data(&result, length, (uchar*) packet, if (!append_result_data(&result, length, (uchar*) packet,
query_block)) query_block))
{ {
DBUG_PRINT("warning", ("Can't append data")); DBUG_PRINT("warning", ("Can't append data"));
...@@ -877,60 +893,63 @@ void query_cache_insert(NET *net, const char *packet, ulong length) ...@@ -877,60 +893,63 @@ void query_cache_insert(NET *net, const char *packet, ulong length)
query_cache.free_query(query_block); query_cache.free_query(query_block);
query_cache.refused++; query_cache.refused++;
// append_result_data no success => we need unlock // append_result_data no success => we need unlock
query_cache.unlock(); unlock();
DBUG_VOID_RETURN; DBUG_VOID_RETURN;
} }
header->result(result); header->result(result);
header->last_pkt_nr= net->pkt_nr; header->last_pkt_nr= pkt_nr;
BLOCK_UNLOCK_WR(query_block); BLOCK_UNLOCK_WR(query_block);
DBUG_EXECUTE("check_querycache",query_cache.check_integrity(0);); DBUG_EXECUTE("check_querycache",check_integrity(0););
DBUG_VOID_RETURN; DBUG_VOID_RETURN;
} }
void query_cache_abort(NET *net) void
Query_cache::abort(Query_cache_tls *query_cache_tls)
{ {
DBUG_ENTER("query_cache_abort"); DBUG_ENTER("query_cache_abort");
THD *thd= current_thd; THD *thd= current_thd;
/* See the comment on double-check locking usage above. */ /* See the comment on double-check locking usage above. */
if (net->query_cache_query == 0) if (query_cache_tls->first_query_block == NULL)
DBUG_VOID_RETURN; DBUG_VOID_RETURN;
if (query_cache.try_lock()) if (try_lock())
DBUG_VOID_RETURN; DBUG_VOID_RETURN;
/* /*
While we were waiting another thread might have changed the status While we were waiting another thread might have changed the status
of the writer. Make sure the writer still exists before continue. of the writer. Make sure the writer still exists before continue.
*/ */
Query_cache_block *query_block= ((Query_cache_block*) Query_cache_block *query_block= query_cache_tls->first_query_block;
net->query_cache_query);
if (query_block) if (query_block)
{ {
thd_proc_info(thd, "storing result in query cache"); thd_proc_info(thd, "storing result in query cache");
DUMP(&query_cache); DUMP(this);
BLOCK_LOCK_WR(query_block); BLOCK_LOCK_WR(query_block);
// The following call will remove the lock on query_block // The following call will remove the lock on query_block
query_cache.free_query(query_block); free_query(query_block);
net->query_cache_query= 0; query_cache_tls->first_query_block= NULL;
DBUG_EXECUTE("check_querycache",query_cache.check_integrity(1);); DBUG_EXECUTE("check_querycache", check_integrity(1););
} }
query_cache.unlock(); unlock();
DBUG_VOID_RETURN; DBUG_VOID_RETURN;
} }
void query_cache_end_of_result(THD *thd) void Query_cache::end_of_result(THD *thd)
{ {
Query_cache_block *query_block; Query_cache_block *query_block;
DBUG_ENTER("query_cache_end_of_result"); Query_cache_tls *query_cache_tls= &thd->query_cache_tls;
ulonglong limit_found_rows= thd->limit_found_rows;
DBUG_ENTER("Query_cache::end_of_result");
/* See the comment on double-check locking usage above. */ /* See the comment on double-check locking usage above. */
if (thd->net.query_cache_query == 0) if (query_cache_tls->first_query_block == NULL)
DBUG_VOID_RETURN; DBUG_VOID_RETURN;
/* Ensure that only complete results are cached. */ /* Ensure that only complete results are cached. */
...@@ -938,19 +957,19 @@ void query_cache_end_of_result(THD *thd) ...@@ -938,19 +957,19 @@ void query_cache_end_of_result(THD *thd)
if (thd->killed) if (thd->killed)
{ {
query_cache_abort(&thd->net); query_cache_abort(&thd->query_cache_tls);
DBUG_VOID_RETURN; DBUG_VOID_RETURN;
} }
#ifdef EMBEDDED_LIBRARY #ifdef EMBEDDED_LIBRARY
query_cache_insert(&thd->net, (char*)thd, insert(query_cache_tls, (char*)thd,
emb_count_querycache_size(thd)); emb_count_querycache_size(thd), 0);
#endif #endif
if (query_cache.try_lock()) if (try_lock())
DBUG_VOID_RETURN; DBUG_VOID_RETURN;
query_block= ((Query_cache_block*) thd->net.query_cache_query); query_block= query_cache_tls->first_query_block;
if (query_block) if (query_block)
{ {
/* /*
...@@ -959,7 +978,7 @@ void query_cache_end_of_result(THD *thd) ...@@ -959,7 +978,7 @@ void query_cache_end_of_result(THD *thd)
block, the writer should be dropped. block, the writer should be dropped.
*/ */
thd_proc_info(thd, "storing result in query cache"); thd_proc_info(thd, "storing result in query cache");
DUMP(&query_cache); DUMP(this);
BLOCK_LOCK_WR(query_block); BLOCK_LOCK_WR(query_block);
Query_cache_query *header= query_block->query(); Query_cache_query *header= query_block->query();
Query_cache_block *last_result_block; Query_cache_block *last_result_block;
...@@ -976,8 +995,8 @@ void query_cache_end_of_result(THD *thd) ...@@ -976,8 +995,8 @@ void query_cache_end_of_result(THD *thd)
and removed from QC. and removed from QC.
*/ */
DBUG_ASSERT(0); DBUG_ASSERT(0);
query_cache.free_query(query_block); free_query(query_block);
query_cache.unlock(); unlock();
DBUG_VOID_RETURN; DBUG_VOID_RETURN;
} }
last_result_block= header->result()->prev; last_result_block= header->result()->prev;
...@@ -986,17 +1005,17 @@ void query_cache_end_of_result(THD *thd) ...@@ -986,17 +1005,17 @@ void query_cache_end_of_result(THD *thd)
if (last_result_block->length >= query_cache.min_allocation_unit + len) if (last_result_block->length >= query_cache.min_allocation_unit + len)
query_cache.split_block(last_result_block,len); query_cache.split_block(last_result_block,len);
header->found_rows(current_thd->limit_found_rows); header->found_rows(limit_found_rows);
header->result()->type= Query_cache_block::RESULT; header->result()->type= Query_cache_block::RESULT;
/* Drop the writer. */ /* Drop the writer. */
header->writer(0); header->writer(0);
thd->net.query_cache_query= 0; query_cache_tls->first_query_block= NULL;
BLOCK_UNLOCK_WR(query_block); BLOCK_UNLOCK_WR(query_block);
DBUG_EXECUTE("check_querycache",query_cache.check_integrity(1);); DBUG_EXECUTE("check_querycache", check_integrity(1););
} }
query_cache.unlock();
unlock();
DBUG_VOID_RETURN; DBUG_VOID_RETURN;
} }
...@@ -1074,7 +1093,7 @@ ulong Query_cache::resize(ulong query_cache_size_arg) ...@@ -1074,7 +1093,7 @@ ulong Query_cache::resize(ulong query_cache_size_arg)
Drop the writer; this will cancel any attempts to store Drop the writer; this will cancel any attempts to store
the processed statement associated with this writer. the processed statement associated with this writer.
*/ */
query->writer()->query_cache_query= 0; query->writer()->first_query_block= NULL;
query->writer(0); query->writer(0);
refused++; refused++;
} }
...@@ -1268,8 +1287,8 @@ def_week_frmt: %lu, in_trans: %d, autocommit: %d", ...@@ -1268,8 +1287,8 @@ def_week_frmt: %lu, in_trans: %d, autocommit: %d",
double_linked_list_simple_include(query_block, &queries_blocks); double_linked_list_simple_include(query_block, &queries_blocks);
inserts++; inserts++;
queries_in_cache++; queries_in_cache++;
net->query_cache_query= (uchar*) query_block; thd->query_cache_tls.first_query_block= query_block;
header->writer(net); header->writer(&thd->query_cache_tls);
header->tables_type(tables_type); header->tables_type(tables_type);
unlock(); unlock();
...@@ -1325,7 +1344,10 @@ Query_cache::send_result_to_client(THD *thd, char *sql, uint query_length) ...@@ -1325,7 +1344,10 @@ Query_cache::send_result_to_client(THD *thd, char *sql, uint query_length)
{ {
ulonglong engine_data; ulonglong engine_data;
Query_cache_query *query; Query_cache_query *query;
Query_cache_block *first_result_block, *result_block; #ifndef EMBEDDED_LIBRARY
Query_cache_block *first_result_block;
#endif
Query_cache_block *result_block;
Query_cache_block_table *block_table, *block_table_end; Query_cache_block_table *block_table, *block_table_end;
ulong tot_length; ulong tot_length;
Query_cache_query_flags flags; Query_cache_query_flags flags;
...@@ -1396,12 +1418,6 @@ Query_cache::send_result_to_client(THD *thd, char *sql, uint query_length) ...@@ -1396,12 +1418,6 @@ Query_cache::send_result_to_client(THD *thd, char *sql, uint query_length)
if (query_cache_size == 0) if (query_cache_size == 0)
goto err_unlock; goto err_unlock;
/*
Check that we haven't forgot to reset the query cache variables;
make sure there are no attached query cache writer to this thread.
*/
DBUG_ASSERT(thd->net.query_cache_query == 0);
Query_cache_block *query_block; Query_cache_block *query_block;
tot_length= query_length + thd->db_length + 1 + QUERY_CACHE_FLAGS_SIZE; tot_length= query_length + thd->db_length + 1 + QUERY_CACHE_FLAGS_SIZE;
...@@ -1483,7 +1499,10 @@ def_week_frmt: %lu, in_trans: %d, autocommit: %d", ...@@ -1483,7 +1499,10 @@ def_week_frmt: %lu, in_trans: %d, autocommit: %d",
BLOCK_LOCK_RD(query_block); BLOCK_LOCK_RD(query_block);
query = query_block->query(); query = query_block->query();
result_block= first_result_block= query->result(); result_block= query->result();
#ifndef EMBEDDED_LIBRARY
first_result_block= result_block;
#endif
if (result_block == 0 || result_block->type != Query_cache_block::RESULT) if (result_block == 0 || result_block->type != Query_cache_block::RESULT)
{ {
...@@ -2261,7 +2280,7 @@ void Query_cache::free_query_internal(Query_cache_block *query_block) ...@@ -2261,7 +2280,7 @@ void Query_cache::free_query_internal(Query_cache_block *query_block)
if (query->writer() != 0) if (query->writer() != 0)
{ {
/* Tell MySQL that this query should not be cached anymore */ /* Tell MySQL that this query should not be cached anymore */
query->writer()->query_cache_query= 0; query->writer()->first_query_block= NULL;
query->writer(0); query->writer(0);
} }
double_linked_list_exclude(query_block, &queries_blocks); double_linked_list_exclude(query_block, &queries_blocks);
...@@ -3474,7 +3493,8 @@ Query_cache::process_and_count_tables(THD *thd, TABLE_LIST *tables_used, ...@@ -3474,7 +3493,8 @@ Query_cache::process_and_count_tables(THD *thd, TABLE_LIST *tables_used,
*/ */
TABLE_COUNTER_TYPE TABLE_COUNTER_TYPE
Query_cache::is_cacheable(THD *thd, uint32 query_len, char *query, LEX *lex, Query_cache::is_cacheable(THD *thd, size_t query_len, const char *query,
LEX *lex,
TABLE_LIST *tables_used, uint8 *tables_type) TABLE_LIST *tables_used, uint8 *tables_type)
{ {
TABLE_COUNTER_TYPE table_count; TABLE_COUNTER_TYPE table_count;
...@@ -3773,10 +3793,10 @@ my_bool Query_cache::move_by_type(uchar **border, ...@@ -3773,10 +3793,10 @@ my_bool Query_cache::move_by_type(uchar **border,
If someone is writing to this block, inform the writer that the block If someone is writing to this block, inform the writer that the block
has been moved. has been moved.
*/ */
NET *net = new_block->query()->writer(); Query_cache_tls *query_cache_tls= new_block->query()->writer();
if (net != 0) if (query_cache_tls != NULL)
{ {
net->query_cache_query= (uchar*) new_block; query_cache_tls->first_query_block= new_block;
} }
/* Fix hash to point at moved block */ /* Fix hash to point at moved block */
hash_replace(&queries, &record_idx, (uchar*) new_block); hash_replace(&queries, &record_idx, (uchar*) new_block);
......
...@@ -64,6 +64,8 @@ struct Query_cache_table; ...@@ -64,6 +64,8 @@ struct Query_cache_table;
struct Query_cache_query; struct Query_cache_query;
struct Query_cache_result; struct Query_cache_result;
class Query_cache; class Query_cache;
struct Query_cache_tls;
struct st_lex;
/** /**
This class represents a node in the linked chain of queries This class represents a node in the linked chain of queries
...@@ -137,7 +139,7 @@ struct Query_cache_query ...@@ -137,7 +139,7 @@ struct Query_cache_query
ulonglong limit_found_rows; ulonglong limit_found_rows;
rw_lock_t lock; rw_lock_t lock;
Query_cache_block *res; Query_cache_block *res;
NET *wri; Query_cache_tls *wri;
ulong len; ulong len;
uint8 tbls_type; uint8 tbls_type;
unsigned int last_pkt_nr; unsigned int last_pkt_nr;
...@@ -149,8 +151,8 @@ struct Query_cache_query ...@@ -149,8 +151,8 @@ struct Query_cache_query
inline void found_rows(ulonglong rows) { limit_found_rows= rows; } inline void found_rows(ulonglong rows) { limit_found_rows= rows; }
inline Query_cache_block *result() { return res; } inline Query_cache_block *result() { return res; }
inline void result(Query_cache_block *p) { res= p; } inline void result(Query_cache_block *p) { res= p; }
inline NET *writer() { return wri; } inline Query_cache_tls *writer() { return wri; }
inline void writer(NET *p) { wri= p; } inline void writer(Query_cache_tls *p) { wri= p; }
inline uint8 tables_type() { return tbls_type; } inline uint8 tables_type() { return tbls_type; }
inline void tables_type(uint8 type) { tbls_type= type; } inline void tables_type(uint8 type) { tbls_type= type; }
inline ulong length() { return len; } inline ulong length() { return len; }
...@@ -407,7 +409,8 @@ protected: ...@@ -407,7 +409,8 @@ protected:
If query is cacheable return number tables in query If query is cacheable return number tables in query
(query without tables not cached) (query without tables not cached)
*/ */
TABLE_COUNTER_TYPE is_cacheable(THD *thd, uint32 query_len, char *query, TABLE_COUNTER_TYPE is_cacheable(THD *thd, size_t query_len,
const char *query,
LEX *lex, TABLE_LIST *tables_used, LEX *lex, TABLE_LIST *tables_used,
uint8 *tables_type); uint8 *tables_type);
TABLE_COUNTER_TYPE process_and_count_tables(THD *thd, TABLE_COUNTER_TYPE process_and_count_tables(THD *thd,
...@@ -462,10 +465,13 @@ protected: ...@@ -462,10 +465,13 @@ protected:
void destroy(); void destroy();
friend void query_cache_init_query(NET *net); void insert(Query_cache_tls *query_cache_tls,
friend void query_cache_insert(NET *net, const char *packet, ulong length); const char *packet,
friend void query_cache_end_of_result(THD *thd); ulong length,
friend void query_cache_abort(NET *net); unsigned pkt_nr);
void end_of_result(THD *thd);
void abort(Query_cache_tls *query_cache_tls);
/* /*
The following functions are only used when debugging The following functions are only used when debugging
...@@ -493,9 +499,4 @@ protected: ...@@ -493,9 +499,4 @@ protected:
extern Query_cache query_cache; extern Query_cache query_cache;
extern TYPELIB query_cache_type_typelib; extern TYPELIB query_cache_type_typelib;
void query_cache_init_query(NET *net);
void query_cache_insert(NET *net, const char *packet, ulong length);
void query_cache_end_of_result(THD *thd);
void query_cache_abort(NET *net);
#endif #endif
...@@ -501,9 +501,6 @@ THD::THD() ...@@ -501,9 +501,6 @@ THD::THD()
net.vio=0; net.vio=0;
#endif #endif
client_capabilities= 0; // minimalistic client client_capabilities= 0; // minimalistic client
#ifdef HAVE_QUERY_CACHE
query_cache_init_query(&net); // If error on boot
#endif
ull=0; ull=0;
system_thread= NON_SYSTEM_THREAD; system_thread= NON_SYSTEM_THREAD;
cleanup_done= abort_on_warning= no_warnings_for_error= 0; cleanup_done= abort_on_warning= no_warnings_for_error= 0;
...@@ -796,7 +793,7 @@ THD::raise_condition_no_handler(uint sql_errno, ...@@ -796,7 +793,7 @@ THD::raise_condition_no_handler(uint sql_errno,
MYSQL_ERROR *cond= NULL; MYSQL_ERROR *cond= NULL;
DBUG_ENTER("THD::raise_condition_no_handler"); DBUG_ENTER("THD::raise_condition_no_handler");
query_cache_abort(& net); query_cache_abort(&query_cache_tls);
/* FIXME: broken special case */ /* FIXME: broken special case */
if (no_warnings_for_error && (level == MYSQL_ERROR::WARN_LEVEL_ERROR)) if (no_warnings_for_error && (level == MYSQL_ERROR::WARN_LEVEL_ERROR))
......
...@@ -315,6 +315,27 @@ typedef enum enum_diag_condition_item_name ...@@ -315,6 +315,27 @@ typedef enum enum_diag_condition_item_name
*/ */
extern const LEX_STRING Diag_condition_item_names[]; extern const LEX_STRING Diag_condition_item_names[];
/**
Query_cache_tls -- query cache thread local data.
*/
class Query_cache_block;
struct Query_cache_tls
{
/*
'first_query_block' should be accessed only via query cache
functions and methods to maintain proper locking.
*/
Query_cache_block *first_query_block;
void set_first_query_block(Query_cache_block *first_query_block_arg)
{
first_query_block= first_query_block_arg;
}
Query_cache_tls() :first_query_block(NULL) {}
};
#include "sql_lex.h" /* Must be here */ #include "sql_lex.h" /* Must be here */
class Delayed_insert; class Delayed_insert;
...@@ -1239,6 +1260,9 @@ public: ...@@ -1239,6 +1260,9 @@ public:
fields then. fields then.
*/ */
struct st_mysql_stmt *current_stmt; struct st_mysql_stmt *current_stmt;
#endif
#ifdef HAVE_QUERY_CACHE
Query_cache_tls query_cache_tls;
#endif #endif
NET net; // client connection descriptor NET net; // client connection descriptor
Protocol *protocol; // Current protocol Protocol *protocol; // Current protocol
......
...@@ -6026,7 +6026,7 @@ void mysql_parse(THD *thd, const char *inBuf, uint length, ...@@ -6026,7 +6026,7 @@ void mysql_parse(THD *thd, const char *inBuf, uint length,
DBUG_PRINT("info",("Command aborted. Fatal_error: %d", DBUG_PRINT("info",("Command aborted. Fatal_error: %d",
thd->is_fatal_error)); thd->is_fatal_error));
query_cache_abort(&thd->net); query_cache_abort(&thd->query_cache_tls);
} }
if (thd->lex->sphead) if (thd->lex->sphead)
{ {
......
...@@ -9187,7 +9187,7 @@ remove_eq_conds(THD *thd, COND *cond, Item::cond_result *cond_value) ...@@ -9187,7 +9187,7 @@ remove_eq_conds(THD *thd, COND *cond, Item::cond_result *cond_value)
thd->substitute_null_with_insert_id)) thd->substitute_null_with_insert_id))
{ {
#ifdef HAVE_QUERY_CACHE #ifdef HAVE_QUERY_CACHE
query_cache_abort(&thd->net); query_cache_abort(&thd->query_cache_tls);
#endif #endif
COND *new_cond; COND *new_cond;
if ((new_cond= new Item_func_eq(args[0], if ((new_cond= new Item_func_eq(args[0],
......
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