Commit 2aea94f4 authored by jimw@mysql.com's avatar jimw@mysql.com

Merge bk-internal:/home/bk/mysql-4.1

into mysql.com:/home/jimw/my/mysql-4.1-clean
parents acca8f7a 6dc84298
...@@ -22,7 +22,7 @@ ...@@ -22,7 +22,7 @@
void Querycache_stream::store_char(char c) void Querycache_stream::store_char(char c)
{ {
if (data_end == cur_data) if (data_end == cur_data)
use_next_block(); use_next_block(TRUE);
*(cur_data++)= c; *(cur_data++)= c;
#ifndef DBUG_OFF #ifndef DBUG_OFF
stored_size++; stored_size++;
...@@ -42,13 +42,13 @@ void Querycache_stream::store_short(ushort s) ...@@ -42,13 +42,13 @@ void Querycache_stream::store_short(ushort s)
} }
if (data_end == cur_data) if (data_end == cur_data)
{ {
use_next_block(); use_next_block(TRUE);
int2store(cur_data, s); int2store(cur_data, s);
cur_data+= 2; cur_data+= 2;
return; return;
} }
*cur_data= ((byte *)(&s))[0]; *cur_data= ((byte *)(&s))[0];
use_next_block(); use_next_block(TRUE);
*(cur_data++)= ((byte *)(&s))[1]; *(cur_data++)= ((byte *)(&s))[1];
} }
...@@ -66,7 +66,7 @@ void Querycache_stream::store_int(uint i) ...@@ -66,7 +66,7 @@ void Querycache_stream::store_int(uint i)
} }
if (!rest_len) if (!rest_len)
{ {
use_next_block(); use_next_block(TRUE);
int4store(cur_data, i); int4store(cur_data, i);
cur_data+= 4; cur_data+= 4;
return; return;
...@@ -74,7 +74,7 @@ void Querycache_stream::store_int(uint i) ...@@ -74,7 +74,7 @@ void Querycache_stream::store_int(uint i)
char buf[4]; char buf[4];
int4store(buf, i); int4store(buf, i);
memcpy(cur_data, buf, rest_len); memcpy(cur_data, buf, rest_len);
use_next_block(); use_next_block(TRUE);
memcpy(cur_data, buf+rest_len, 4-rest_len); memcpy(cur_data, buf+rest_len, 4-rest_len);
cur_data+= 4-rest_len; cur_data+= 4-rest_len;
} }
...@@ -93,13 +93,13 @@ void Querycache_stream::store_ll(ulonglong ll) ...@@ -93,13 +93,13 @@ void Querycache_stream::store_ll(ulonglong ll)
} }
if (!rest_len) if (!rest_len)
{ {
use_next_block(); use_next_block(TRUE);
int8store(cur_data, ll); int8store(cur_data, ll);
cur_data+= 8; cur_data+= 8;
return; return;
} }
memcpy(cur_data, &ll, rest_len); memcpy(cur_data, &ll, rest_len);
use_next_block(); use_next_block(TRUE);
memcpy(cur_data, ((byte*)&ll)+rest_len, 8-rest_len); memcpy(cur_data, ((byte*)&ll)+rest_len, 8-rest_len);
cur_data+= 8-rest_len; cur_data+= 8-rest_len;
} }
...@@ -112,14 +112,14 @@ void Querycache_stream::store_str_only(const char *str, uint str_len) ...@@ -112,14 +112,14 @@ void Querycache_stream::store_str_only(const char *str, uint str_len)
do do
{ {
size_t rest_len= data_end - cur_data; size_t rest_len= data_end - cur_data;
if (rest_len > str_len) if (rest_len >= str_len)
{ {
memcpy(cur_data, str, str_len); memcpy(cur_data, str, str_len);
cur_data+= str_len; cur_data+= str_len;
return; return;
} }
memcpy(cur_data, str, rest_len); memcpy(cur_data, str, rest_len);
use_next_block(); use_next_block(TRUE);
str_len-= rest_len; str_len-= rest_len;
str+= rest_len; str+= rest_len;
} while(str_len); } while(str_len);
...@@ -145,7 +145,7 @@ void Querycache_stream::store_safe_str(const char *str, uint str_len) ...@@ -145,7 +145,7 @@ void Querycache_stream::store_safe_str(const char *str, uint str_len)
char Querycache_stream::load_char() char Querycache_stream::load_char()
{ {
if (cur_data == data_end) if (cur_data == data_end)
use_next_block(); use_next_block(FALSE);
return *(cur_data++); return *(cur_data++);
} }
...@@ -160,13 +160,13 @@ ushort Querycache_stream::load_short() ...@@ -160,13 +160,13 @@ ushort Querycache_stream::load_short()
} }
if (data_end == cur_data) if (data_end == cur_data)
{ {
use_next_block(); use_next_block(FALSE);
result= uint2korr(cur_data); result= uint2korr(cur_data);
cur_data+= 2; cur_data+= 2;
return result; return result;
} }
((byte*)&result)[0]= *cur_data; ((byte*)&result)[0]= *cur_data;
use_next_block(); use_next_block(FALSE);
((byte*)&result)[1]= *(cur_data++); ((byte*)&result)[1]= *(cur_data++);
return result; return result;
} }
...@@ -183,14 +183,14 @@ uint Querycache_stream::load_int() ...@@ -183,14 +183,14 @@ uint Querycache_stream::load_int()
} }
if (!rest_len) if (!rest_len)
{ {
use_next_block(); use_next_block(FALSE);
result= uint4korr(cur_data); result= uint4korr(cur_data);
cur_data+= 4; cur_data+= 4;
return result; return result;
} }
char buf[4]; char buf[4];
memcpy(buf, cur_data, rest_len); memcpy(buf, cur_data, rest_len);
use_next_block(); use_next_block(FALSE);
memcpy(buf+rest_len, cur_data, 4-rest_len); memcpy(buf+rest_len, cur_data, 4-rest_len);
cur_data+= 4-rest_len; cur_data+= 4-rest_len;
result= uint4korr(buf); result= uint4korr(buf);
...@@ -209,13 +209,13 @@ ulonglong Querycache_stream::load_ll() ...@@ -209,13 +209,13 @@ ulonglong Querycache_stream::load_ll()
} }
if (!rest_len) if (!rest_len)
{ {
use_next_block(); use_next_block(FALSE);
result= uint8korr(cur_data); result= uint8korr(cur_data);
cur_data+= 8; cur_data+= 8;
return result; return result;
} }
memcpy(&result, cur_data, rest_len); memcpy(&result, cur_data, rest_len);
use_next_block(); use_next_block(FALSE);
memcpy(((byte*)&result)+rest_len, cur_data, 8-rest_len); memcpy(((byte*)&result)+rest_len, cur_data, 8-rest_len);
cur_data+= 8-rest_len; cur_data+= 8-rest_len;
return result; return result;
...@@ -226,7 +226,7 @@ void Querycache_stream::load_str_only(char *buffer, uint str_len) ...@@ -226,7 +226,7 @@ void Querycache_stream::load_str_only(char *buffer, uint str_len)
do do
{ {
size_t rest_len= data_end - cur_data; size_t rest_len= data_end - cur_data;
if (rest_len > str_len) if (rest_len >= str_len)
{ {
memcpy(buffer, cur_data, str_len); memcpy(buffer, cur_data, str_len);
cur_data+= str_len; cur_data+= str_len;
...@@ -234,7 +234,7 @@ void Querycache_stream::load_str_only(char *buffer, uint str_len) ...@@ -234,7 +234,7 @@ void Querycache_stream::load_str_only(char *buffer, uint str_len)
break; break;
} }
memcpy(buffer, cur_data, rest_len); memcpy(buffer, cur_data, rest_len);
use_next_block(); use_next_block(FALSE);
str_len-= rest_len; str_len-= rest_len;
buffer+= rest_len; buffer+= rest_len;
} while(str_len); } while(str_len);
......
...@@ -22,18 +22,39 @@ class Querycache_stream ...@@ -22,18 +22,39 @@ class Querycache_stream
uint headers_len; uint headers_len;
public: public:
#ifndef DBUG_OFF #ifndef DBUG_OFF
Query_cache_block *first_block;
uint stored_size; uint stored_size;
#endif #endif
Querycache_stream(Query_cache_block *ini_block, uint ini_headers_len) : Querycache_stream(Query_cache_block *ini_block, uint ini_headers_len) :
block(ini_block), headers_len(ini_headers_len) block(ini_block), headers_len(ini_headers_len)
{ {
use_next_block(); cur_data= ((byte*)block)+headers_len;
data_end= cur_data + (block->used-headers_len);
#ifndef DBUG_OFF #ifndef DBUG_OFF
first_block= ini_block;
stored_size= 0; stored_size= 0;
#endif #endif
} }
void use_next_block() void use_next_block(bool writing)
{ {
/*
This shouldn't be called if there is only one block, or to loop
around to the first block again. That means we're trying to write
more data than we allocated space for.
*/
DBUG_ASSERT(block->next != block);
DBUG_ASSERT(block->next != first_block);
block= block->next;
/*
While writing, update the type of each block as we write to it.
While reading, make sure that the block is of the expected type.
*/
if (writing)
block->type= Query_cache_block::RES_CONT;
else
DBUG_ASSERT(block->type == Query_cache_block::RES_CONT);
cur_data= ((byte*)block)+headers_len; cur_data= ((byte*)block)+headers_len;
data_end= cur_data + (block->used-headers_len); data_end= cur_data + (block->used-headers_len);
} }
......
...@@ -685,6 +685,12 @@ then ...@@ -685,6 +685,12 @@ then
fi fi
MYSQL_CLIENT_TEST="$MYSQL_CLIENT_TEST --no-defaults --testcase --user=root --socket=$MASTER_MYSOCK --port=$MYSQL_TCP_PORT --silent $EXTRA_MYSQL_CLIENT_TEST_OPT" MYSQL_CLIENT_TEST="$MYSQL_CLIENT_TEST --no-defaults --testcase --user=root --socket=$MASTER_MYSOCK --port=$MYSQL_TCP_PORT --silent $EXTRA_MYSQL_CLIENT_TEST_OPT"
# Need to pass additional arguments to MYSQL_CLIENT_TEST for embedded server
# -A marks each argument for passing to the function which initializes the
# embedded library
if [ "x$USE_EMBEDDED_SERVER" = "x1" ]; then
MYSQL_CLIENT_TEST="$MYSQL_CLIENT_TEST -A --language=$LANGUAGE -A --datadir=$SLAVE_MYDDIR -A --character-sets-dir=$CHARSETSDIR"
fi
MYSQL_DUMP="$MYSQL_DUMP --no-defaults -uroot --socket=$MASTER_MYSOCK --password=$DBPASSWD $EXTRA_MYSQLDUMP_OPT" MYSQL_DUMP="$MYSQL_DUMP --no-defaults -uroot --socket=$MASTER_MYSOCK --password=$DBPASSWD $EXTRA_MYSQLDUMP_OPT"
MYSQL_BINLOG="$MYSQL_BINLOG --no-defaults --local-load=$MYSQL_TMP_DIR $EXTRA_MYSQLBINLOG_OPT" MYSQL_BINLOG="$MYSQL_BINLOG --no-defaults --local-load=$MYSQL_TMP_DIR $EXTRA_MYSQLBINLOG_OPT"
MYSQL_FIX_SYSTEM_TABLES="$MYSQL_FIX_SYSTEM_TABLES --no-defaults --host=localhost --port=$MASTER_MYPORT --socket=$MASTER_MYSOCK --user=root --password=$DBPASSWD --basedir=$BASEDIR --bindir=$CLIENT_BINDIR --verbose" MYSQL_FIX_SYSTEM_TABLES="$MYSQL_FIX_SYSTEM_TABLES --no-defaults --host=localhost --port=$MASTER_MYPORT --socket=$MASTER_MYSOCK --user=root --password=$DBPASSWD --basedir=$BASEDIR --bindir=$CLIENT_BINDIR --verbose"
......
This diff is collapsed.
...@@ -685,4 +685,49 @@ repair table t1; ...@@ -685,4 +685,49 @@ repair table t1;
show status like 'qcache_queries_in_cache'; show status like 'qcache_queries_in_cache';
drop table t1; drop table t1;
# Bug #9549: Make sure cached queries that span more than one cache block
# are handled properly in the embedded server.
# We just want a small query cache, so we can fragment it easily
set GLOBAL query_cache_size=64*1024;
# This actually gives us a usable cache size of about 48K
# Each table is about 14K
create table t1 (a text);
insert into t1 values (repeat('abcdefghijklmnopqrstuvwxyz', 550));
create table t2 (a text);
insert into t2 values (repeat('ijklmnopqrstuvwxyzabcdefgh', 550));
# Load a query from each table into the query cache
--disable_result_log
select a from t1; # Q1
select a from t2; # Q2
--enable_result_log
show status like 'Qcache_%_blocks';
# Now the cache looks like (14K for Q1)(14K for Q2)(20K free)
# Flush Q1 from the cache by adding an out-of-order chunk to t1
insert into t1 select reverse(a) from t1;
show status like 'Qcache_%_blocks';
# Now the cache looks like (14K free)(14K for Q2)(20K free)
# Load our new data into the query cache
--disable_result_log
select a from t1; # Q3
--enable_result_log
show status like 'Qcache_%_blocks';
# Now the cache should be like (14K for Q3)(14K for Q2)(14K for Q3)(6K free)
# Note that Q3 is split across two chunks!
# Load Q3 from the cache, and actually pay attention to the results
select a from t1;
flush query cache;
drop table t1, t2;
set GLOBAL query_cache_size=0; set GLOBAL query_cache_size=0;
...@@ -1933,6 +1933,11 @@ my_bool Query_cache::write_result_data(Query_cache_block **result_block, ...@@ -1933,6 +1933,11 @@ my_bool Query_cache::write_result_data(Query_cache_block **result_block,
type = Query_cache_block::RES_CONT; type = Query_cache_block::RES_CONT;
} while (block != *result_block); } while (block != *result_block);
#else #else
/*
Set type of first block, emb_store_querycache_result() will handle
the others.
*/
(*result_block)->type= type;
Querycache_stream qs(*result_block, headers_len); Querycache_stream qs(*result_block, headers_len);
emb_store_querycache_result(&qs, (THD*)data); emb_store_querycache_result(&qs, (THD*)data);
#endif /*!EMBEDDED_LIBRARY*/ #endif /*!EMBEDDED_LIBRARY*/
......
...@@ -30,6 +30,7 @@ ...@@ -30,6 +30,7 @@
#define VER "2.1" #define VER "2.1"
#define MAX_TEST_QUERY_LENGTH 300 /* MAX QUERY BUFFER LENGTH */ #define MAX_TEST_QUERY_LENGTH 300 /* MAX QUERY BUFFER LENGTH */
#define MAX_SERVER_ARGS 64
/* set default options */ /* set default options */
static int opt_testcase = 0; static int opt_testcase = 0;
...@@ -48,6 +49,18 @@ static unsigned int test_count= 0; ...@@ -48,6 +49,18 @@ static unsigned int test_count= 0;
static unsigned int opt_count= 0; static unsigned int opt_count= 0;
static unsigned int iter_count= 0; static unsigned int iter_count= 0;
static const char *opt_basedir= "./";
static int embedded_server_arg_count= 0;
static char *embedded_server_args[MAX_SERVER_ARGS];
static const char *embedded_server_groups[]= {
"server",
"embedded",
"mysql_client_test_SERVER",
NullS
};
static time_t start_time, end_time; static time_t start_time, end_time;
static double total_time; static double total_time;
...@@ -93,6 +106,8 @@ static void client_disconnect(); ...@@ -93,6 +106,8 @@ static void client_disconnect();
#define DIE_UNLESS(expr) \ #define DIE_UNLESS(expr) \
((void) ((expr) ? 0 : (die(__FILE__, __LINE__, #expr), 0))) ((void) ((expr) ? 0 : (die(__FILE__, __LINE__, #expr), 0)))
#define DIE(expr) \
die(__FILE__, __LINE__, #expr)
void die(const char *file, int line, const char *expr) void die(const char *file, int line, const char *expr)
{ {
...@@ -11617,7 +11632,7 @@ static void test_bug7990() ...@@ -11617,7 +11632,7 @@ static void test_bug7990()
static void test_bug8378() static void test_bug8378()
{ {
#ifdef HAVE_CHARSET_gbk #if defined(HAVE_CHARSET_gbk) && !defined(EMBEDDED_LIBRARY)
MYSQL *lmysql; MYSQL *lmysql;
char out[9]; /* strlen(TEST_BUG8378)*2+1 */ char out[9]; /* strlen(TEST_BUG8378)*2+1 */
int len; int len;
...@@ -11664,6 +11679,8 @@ static char **defaults_argv; ...@@ -11664,6 +11679,8 @@ static char **defaults_argv;
static struct my_option client_test_long_options[] = static struct my_option client_test_long_options[] =
{ {
{"basedir", 'b', "Basedir for tests.", (gptr*) &opt_basedir,
(gptr*) &opt_basedir, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
{"count", 't', "Number of times test to be executed", (char **) &opt_count, {"count", 't', "Number of times test to be executed", (char **) &opt_count,
(char **) &opt_count, 0, GET_UINT, REQUIRED_ARG, 1, 0, 0, 0, 0, 0}, (char **) &opt_count, 0, GET_UINT, REQUIRED_ARG, 1, 0, 0, 0, 0, 0},
{"database", 'D', "Database to use", (char **) &opt_db, (char **) &opt_db, {"database", 'D', "Database to use", (char **) &opt_db, (char **) &opt_db,
...@@ -11679,6 +11696,8 @@ static struct my_option client_test_long_options[] = ...@@ -11679,6 +11696,8 @@ static struct my_option client_test_long_options[] =
0, 0, 0, GET_STR, OPT_ARG, 0, 0, 0, 0, 0, 0}, 0, 0, 0, GET_STR, OPT_ARG, 0, 0, 0, 0, 0, 0},
{"port", 'P', "Port number to use for connection", (char **) &opt_port, {"port", 'P', "Port number to use for connection", (char **) &opt_port,
(char **) &opt_port, 0, GET_UINT, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, (char **) &opt_port, 0, GET_UINT, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
{"server-arg", 'A', "Send embedded server this as a parameter.",
0, 0, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
{"show-tests", 'T', "Show all tests' names", 0, 0, 0, GET_NO_ARG, NO_ARG, {"show-tests", 'T', "Show all tests' names", 0, 0, 0, GET_NO_ARG, NO_ARG,
0, 0, 0, 0, 0, 0}, 0, 0, 0, 0, 0, 0},
{"silent", 's', "Be more silent", 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, {"silent", 's', "Be more silent", 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0,
...@@ -11899,6 +11918,25 @@ get_one_option(int optid, const struct my_option *opt __attribute__((unused)), ...@@ -11899,6 +11918,25 @@ get_one_option(int optid, const struct my_option *opt __attribute__((unused)),
else else
opt_silent++; opt_silent++;
break; break;
case 'A':
/*
When the embedded server is being tested, the test suite needs to be
able to pass command-line arguments to the embedded server so it can
locate the language files and data directory. The test suite
(mysql-test-run) never uses config files, just command-line options.
*/
if (!embedded_server_arg_count)
{
embedded_server_arg_count= 1;
embedded_server_args[0]= (char*) "";
}
if (embedded_server_arg_count == MAX_SERVER_ARGS-1 ||
!(embedded_server_args[embedded_server_arg_count++]=
my_strdup(argument, MYF(MY_FAE))))
{
DIE("Can't use server argument");
}
break;
case 'T': case 'T':
{ {
struct my_tests_st *fptr; struct my_tests_st *fptr;
...@@ -11967,6 +12005,11 @@ int main(int argc, char **argv) ...@@ -11967,6 +12005,11 @@ int main(int argc, char **argv)
defaults_argv= argv; defaults_argv= argv;
get_options(&argc, &argv); get_options(&argc, &argv);
if (mysql_server_init(embedded_server_arg_count,
embedded_server_args,
(char**) embedded_server_groups))
DIE("Can't initialize MySQL server");
client_connect(); /* connect to server */ client_connect(); /* connect to server */
total_time= 0; total_time= 0;
...@@ -12019,6 +12062,12 @@ int main(int argc, char **argv) ...@@ -12019,6 +12062,12 @@ int main(int argc, char **argv)
client_disconnect(); /* disconnect from server */ client_disconnect(); /* disconnect from server */
free_defaults(defaults_argv); free_defaults(defaults_argv);
print_test_output(); print_test_output();
while (embedded_server_arg_count > 1)
my_free(embedded_server_args[--embedded_server_arg_count],MYF(0));
mysql_server_end();
my_end(0); my_end(0);
exit(0); exit(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