1
0
mirror of https://github.com/MariaDB/server.git synced 2025-07-27 18:02:13 +03:00

5.5-merge

This commit is contained in:
Sergei Golubchik
2011-07-02 22:08:51 +02:00
3220 changed files with 94894 additions and 422456 deletions

View File

@ -334,6 +334,7 @@ TODO list:
#include "tztime.h" // struct Time_zone
#include "sql_acl.h" // SELECT_ACL
#include "sql_base.h" // TMP_TABLE_KEY_EXTRA
#include "debug_sync.h" // DEBUG_SYNC
#ifdef HAVE_QUERY_CACHE
#include <m_ctype.h>
#include <my_dir.h>
@ -342,6 +343,7 @@ TODO list:
#include "../storage/myisammrg/myrg_def.h"
#include "probes_mysql.h"
#include "log_slow.h"
#include "transaction.h"
#ifdef EMBEDDED_LIBRARY
#include "emb_qcache.h"
@ -371,42 +373,6 @@ TODO list:
__LINE__,(ulong)(B)));B->query()->unlock_reading();}
#define DUMP(C) DBUG_EXECUTE("qcache", {\
(C)->cache_dump(); (C)->queries_dump();(C)->tables_dump();})
/**
Causes the thread to wait in a spin lock for a query kill signal.
This function is used by the test frame work to identify race conditions.
The signal is caught and ignored and the thread is not killed.
*/
static void debug_wait_for_kill(const char *info)
{
const char *prev_info;
THD *thd;
char buff[1024];
DBUG_ENTER("debug_wait_for_kill");
thd= current_thd;
prev_info= thd->proc_info;
thd->proc_info= info;
sql_print_information("%s", info);
while(!thd->killed)
my_sleep(1000);
thd->killed= THD::NOT_KILLED;
/*
Remove the set debug variable, to ensure we don't get stuck on it again
This is needed as for MyISAM, invalidate_table() may be called twice
(Once from mysql_delete() and once from mi_update_status())
*/
sprintf(buff, "-d,%s", info);
DBUG_SET(buff);
sql_print_information("Exit debug_wait_for_kill");
thd->proc_info= prev_info;
DBUG_VOID_RETURN;
}
#else
#define RW_WLOCK(M) mysql_rwlock_wrlock(M)
#define RW_RLOCK(M) mysql_rwlock_rdlock(M)
@ -418,6 +384,52 @@ static void debug_wait_for_kill(const char *info)
#define DUMP(C)
#endif
/**
Macro that executes the requested action at a synchronization point
only if the thread has a associated THD session.
*/
#if defined(ENABLED_DEBUG_SYNC)
#define QC_DEBUG_SYNC(name) \
do { \
THD *thd= current_thd; \
if (thd) \
DEBUG_SYNC(thd, name); \
} while (0)
#else
#define QC_DEBUG_SYNC(name)
#endif
/**
Thread state to be used when the query cache lock needs to be acquired.
Sets the thread state name in the constructor, resets on destructor.
*/
struct Query_cache_wait_state
{
THD *m_thd;
const char *m_proc_info;
Query_cache_wait_state(THD *thd, const char *func,
const char *file, unsigned int line)
: m_thd(thd),
m_proc_info(NULL)
{
if (m_thd)
m_proc_info= set_thd_proc_info(m_thd,
"Waiting for query cache lock",
func, file, line);
}
~Query_cache_wait_state()
{
if (m_thd)
set_thd_proc_info(m_thd, m_proc_info, NULL, NULL, 0);
}
};
/**
Serialize access to the query cache.
If the lock cannot be granted the thread hangs in a conditional wait which
@ -439,6 +451,8 @@ static void debug_wait_for_kill(const char *info)
bool Query_cache::try_lock(bool use_timeout)
{
bool interrupt= FALSE;
THD *thd= current_thd;
Query_cache_wait_state wait_state(thd, __func__, __FILE__, __LINE__);
DBUG_ENTER("Query_cache::try_lock");
mysql_mutex_lock(&structure_guard_mutex);
@ -448,7 +462,6 @@ bool Query_cache::try_lock(bool use_timeout)
{
m_cache_lock_status= Query_cache::LOCKED;
#ifndef DBUG_OFF
THD *thd= current_thd;
if (thd)
m_cache_lock_thread_id= thd->thread_id;
#endif
@ -507,6 +520,8 @@ bool Query_cache::try_lock(bool use_timeout)
void Query_cache::lock_and_suspend(void)
{
THD *thd= current_thd;
Query_cache_wait_state wait_state(thd, __func__, __FILE__, __LINE__);
DBUG_ENTER("Query_cache::lock_and_suspend");
mysql_mutex_lock(&structure_guard_mutex);
@ -514,7 +529,6 @@ void Query_cache::lock_and_suspend(void)
mysql_cond_wait(&COND_cache_status_changed, &structure_guard_mutex);
m_cache_lock_status= Query_cache::LOCKED_NO_WAIT;
#ifndef DBUG_OFF
THD *thd= current_thd;
if (thd)
m_cache_lock_thread_id= thd->thread_id;
#endif
@ -535,6 +549,8 @@ void Query_cache::lock_and_suspend(void)
void Query_cache::lock(void)
{
THD *thd= current_thd;
Query_cache_wait_state wait_state(thd, __func__, __FILE__, __LINE__);
DBUG_ENTER("Query_cache::lock");
mysql_mutex_lock(&structure_guard_mutex);
@ -542,7 +558,6 @@ void Query_cache::lock(void)
mysql_cond_wait(&COND_cache_status_changed, &structure_guard_mutex);
m_cache_lock_status= Query_cache::LOCKED;
#ifndef DBUG_OFF
THD *thd= current_thd;
if (thd)
m_cache_lock_thread_id= thd->thread_id;
#endif
@ -882,9 +897,7 @@ Query_cache::insert(Query_cache_tls *query_cache_tls,
if (is_disabled() || query_cache_tls->first_query_block == NULL)
DBUG_VOID_RETURN;
DBUG_EXECUTE_IF("wait_in_query_cache_insert",
debug_wait_for_kill("wait_in_query_cache_insert"); );
QC_DEBUG_SYNC("wait_in_query_cache_insert");
if (try_lock())
DBUG_VOID_RETURN;
@ -1695,6 +1708,8 @@ def_week_frmt: %lu, in_trans: %d, autocommit: %d",
}
else
thd->lex->safe_to_cache_query= 0; // Don't try to cache this
/* End the statement transaction potentially started by engine. */
trans_rollback_stmt(thd);
goto err_unlock; // Parse query
}
else
@ -1737,6 +1752,14 @@ def_week_frmt: %lu, in_trans: %d, autocommit: %d",
thd->limit_found_rows = query->found_rows();
thd->status_var.last_query_cost= 0.0;
thd->query_plan_flags= (thd->query_plan_flags & ~QPLAN_QC_NO) | QPLAN_QC;
/*
End the statement transaction potentially started by an
engine callback. We ignore the return value for now,
since as long as EOF packet is part of the query cache
response, we can't handle it anyway.
*/
(void) trans_commit_stmt(thd);
if (!thd->stmt_da->is_set())
thd->stmt_da->disable_status();
@ -1786,8 +1809,7 @@ void Query_cache::invalidate(THD *thd, TABLE_LIST *tables_used,
invalidate_table(thd, tables_used);
}
DBUG_EXECUTE_IF("wait_after_query_cache_invalidate",
debug_wait_for_kill("wait_after_query_cache_invalidate"););
DEBUG_SYNC(thd, "wait_after_query_cache_invalidate");
DBUG_VOID_RETURN;
}
@ -1978,8 +2000,7 @@ void Query_cache::flush()
if (is_disabled())
DBUG_VOID_RETURN;
DBUG_EXECUTE_IF("wait_in_query_cache_flush1",
debug_wait_for_kill("wait_in_query_cache_flush1"););
QC_DEBUG_SYNC("wait_in_query_cache_flush1");
lock_and_suspend();
if (query_cache_size > 0)
@ -2319,9 +2340,7 @@ void Query_cache::free_cache()
void Query_cache::flush_cache()
{
DBUG_EXECUTE_IF("wait_in_query_cache_flush2",
debug_wait_for_kill("wait_in_query_cache_flush2"););
QC_DEBUG_SYNC("wait_in_query_cache_flush2");
my_hash_reset(&queries);
while (queries_blocks != 0)
@ -2767,8 +2786,7 @@ void Query_cache::invalidate_table(THD *thd, TABLE *table)
void Query_cache::invalidate_table(THD *thd, uchar * key, uint32 key_length)
{
DBUG_EXECUTE_IF("wait_in_query_cache_invalidate1",
debug_wait_for_kill("wait_in_query_cache_invalidate1"); );
DEBUG_SYNC(thd, "wait_in_query_cache_invalidate1");
/*
Lock the query cache and queue all invalidation attempts to avoid
@ -2776,9 +2794,7 @@ void Query_cache::invalidate_table(THD *thd, uchar * key, uint32 key_length)
*/
lock();
DBUG_EXECUTE_IF("wait_in_query_cache_invalidate2",
debug_wait_for_kill("wait_in_query_cache_invalidate2"); );
DEBUG_SYNC(thd, "wait_in_query_cache_invalidate2");
if (query_cache_size > 0)
invalidate_table_internal(thd, key, key_length);
@ -2828,7 +2844,6 @@ Query_cache::invalidate_query_block_list(THD *thd,
Query_cache_block *query_block= list_root->next->block();
BLOCK_LOCK_WR(query_block);
free_query(query_block);
DBUG_EXECUTE_IF("debug_cache_locks", sleep(10););
}
}