Commit 6b02f13c authored by monty@hundin.mysql.fi's avatar monty@hundin.mysql.fi

Removed compiler warnings.

Added new operators to be used with gcc 3.0.x
Update of query cache code.
Added semaphores for Windows (not yet in use)
Added pthread_mutex_trylock for windows.
parent a1f9987b
......@@ -18506,9 +18506,12 @@ If this is 0, the query cache is disabled (default).
@item @code{query_cache_startup_type}
This may be set (only numeric) to
0 (OFF, don't cache or retrieve results),
1 (ON, cache all results except @code{SELECT SQL_NO_CACHE ...} queries) or
2 (DEMAND, cache only @code{SELECT SQL_CACHE ...} queries).
@multitable @columnfractions .1 .2 .7
@item @strong{Value} @tab @strong{Alias} @tab @strong{Comment}
@item 0 @tab OFF @tab Don't cache or retrieve results.
@item 1 @tab ON @tab Cache all results except @code{SELECT SQL_NO_CACHE ...} queries.
@item 2 @tab DEMAND @tab Cache only @code{SELECT SQL_CACHE ...} queries.
@end multitable
@item @code{safe_show_databases}
Don't show databases for which the user doesn't have any database or
......@@ -34,6 +34,7 @@ see the @code{crash-me} web page at
@node Compare mSQL, Compare PostgreSQL, Comparisons, Comparisons
@subsection How MySQL Compares to @code{mSQL}
@cindex mSQL, MySQL vs mSQL, overview
@table @strong
@item Performance
......@@ -301,7 +302,7 @@ multiple connections to the server from the same process.
@subsubsection How @code{mSQL} and MySQL Client/Server Communications Protocols Differ
@cindex communications protocols
@cindex mSQL vs. MySQL
@cindex mSQL vs. MySQL, protocol
There are enough differences that it is impossible (or at least not easy)
to support both.
......@@ -557,7 +558,6 @@ satisfies your application. If you need raw speed, MySQL is probably your
best choice. If you need some of the extra features that only PostgreSQL
can offer, you should use @code{PostgreSQL}.
@cindex PostgreSQL/MySQL, strategies
@menu
* MySQL-PostgreSQL goals:: MySQL and PostgreSQL development strategies
* MySQL-PostgreSQL features:: Featurewise Comparison of MySQL and PostgreSQL
......@@ -568,6 +568,7 @@ can offer, you should use @code{PostgreSQL}.
@node MySQL-PostgreSQL goals, MySQL-PostgreSQL features, Compare PostgreSQL, Compare PostgreSQL
@subsubsection MySQL and PostgreSQL development strategies
@cindex PostgreSQL vs. MySQL, strategies
When adding things to MySQL we take pride to do an optimal, definite
solution. The code should be so good that we shouldn't have any need to
change it in the foreseeable future. We also do not like to sacrifice
......@@ -609,7 +610,7 @@ code, we are better able to coordinate new features and releases.
@node MySQL-PostgreSQL features, MySQL-PostgreSQL benchmarks, MySQL-PostgreSQL goals, Compare PostgreSQL
@subsubsection Featurewise Comparison of MySQL and PostgreSQL
@cindex PostgreSQL/MySQL, features
@cindex PostgreSQL vs. MySQL, features
On the crash-me page
(@uref{http://www.mysql.com/information/crash-me.php})
......
......@@ -385,9 +385,9 @@ static void dump_remote_log_entries(const char* logname)
}
}
static int check_header (IO_CACHE* file)
static int check_header(IO_CACHE* file)
{
char buf[PROBE_HEADER_LEN];
byte buf[PROBE_HEADER_LEN];
int old_format;
my_off_t pos = my_b_tell(file);
......
......@@ -43,7 +43,7 @@
**********************************************************************/
#define MTEST_VERSION "1.11"
#define MTEST_VERSION "1.12"
#include <my_global.h>
#include <mysql_embed.h>
......@@ -138,16 +138,16 @@ MYSQL_RES *last_result=0;
PARSER parser;
MASTER_POS master_pos;
int* block_ok; /* set to 0 if the current block should not be executed */
int *block_ok; /* set to 0 if the current block should not be executed */
int false_block_depth = 0;
const char* result_file = 0; /* if set, all results are concated and
compared against this file*/
/* if set, all results are concated and compared against this file */
const char *result_file = 0;
typedef struct
{
char* name;
char *name;
int name_len;
char* str_val;
char *str_val;
int str_val_len;
int int_val;
int alloced_len;
......@@ -158,7 +158,7 @@ typedef struct
VAR var_reg[10];
/*Perl/shell-like variable registers */
HASH var_hash;
int disable_query_log=0;
int disable_query_log=0, disable_result_log=0;
struct connection cons[MAX_CONS];
struct connection* cur_con, *next_con, *cons_end;
......@@ -181,6 +181,7 @@ Q_PING, Q_EVAL,
Q_RPL_PROBE, Q_ENABLE_RPL_PARSE,
Q_DISABLE_RPL_PARSE, Q_EVAL_RESULT,
Q_ENABLE_QUERY_LOG, Q_DISABLE_QUERY_LOG,
Q_ENABLE_RESULT_LOG, Q_DISABLE_RESULT_LOG,
Q_SERVER_START, Q_SERVER_STOP,Q_REQUIRE_MANAGER,
Q_UNKNOWN, /* Unknown command. */
Q_COMMENT, /* Comments, ignored. */
......@@ -215,6 +216,7 @@ const char *command_names[] = {
"rpl_probe", "enable_rpl_parse",
"disable_rpl_parse", "eval_result",
"enable_query_log", "disable_query_log",
"enable_result_log", "disable_result_log",
"server_start", "server_stop",
"require_manager",
0
......@@ -224,22 +226,22 @@ TYPELIB command_typelib= {array_elements(command_names),"",
command_names};
DYNAMIC_STRING ds_res;
static void die(const char* fmt, ...);
static void die(const char *fmt, ...);
static void init_var_hash();
static byte* get_var_key(const byte* rec, uint* len,
my_bool __attribute__((unused)) t);
static VAR* var_init(VAR* v, const char* name, int name_len, const char* val,
static VAR* var_init(VAR* v, const char *name, int name_len, const char *val,
int val_len);
static void var_free(void* v);
int dyn_string_cmp(DYNAMIC_STRING* ds, const char* fname);
void reject_dump(const char* record_file, char* buf, int size);
int dyn_string_cmp(DYNAMIC_STRING* ds, const char *fname);
void reject_dump(const char *record_file, char *buf, int size);
int close_connection(struct st_query* q);
VAR* var_get(const char* var_name, const char** var_name_end, int raw);
int eval_expr(VAR* v, const char* p, const char** p_end);
static int read_server_arguments(const char* name);
VAR* var_get(const char *var_name, const char** var_name_end, int raw);
int eval_expr(VAR* v, const char *p, const char** p_end);
static int read_server_arguments(const char *name);
/* Definitions for replace */
......@@ -259,9 +261,9 @@ static int insert_pointer_name(reg1 POINTER_ARRAY *pa,my_string name);
void free_pointer_array(POINTER_ARRAY *pa);
static int initialize_replace_buffer(void);
static void free_replace_buffer(void);
static void do_eval(DYNAMIC_STRING* query_eval, const char* query);
void str_to_file(const char* fname, char* str, int size);
int do_server_op(struct st_query* q,const char* op);
static void do_eval(DYNAMIC_STRING* query_eval, const char *query);
void str_to_file(const char *fname, char *str, int size);
int do_server_op(struct st_query* q,const char *op);
struct st_replace *glob_replace;
static char *out_buff;
......@@ -1960,20 +1962,20 @@ int run_query(MYSQL* mysql, struct st_query* q, int flags)
int query_len;
DBUG_ENTER("run_query");
if(q->type != Q_EVAL)
{
query = q->query;
query_len = strlen(query);
}
if (q->type != Q_EVAL)
{
query = q->query;
query_len = strlen(query);
}
else
{
init_dynamic_string(&eval_query, "", 16384, 65536);
do_eval(&eval_query, q->query);
query = eval_query.str;
query_len = eval_query.length;
}
{
init_dynamic_string(&eval_query, "", 16384, 65536);
do_eval(&eval_query, q->query);
query = eval_query.str;
query_len = eval_query.length;
}
if ( q->record_file[0])
if (q->record_file[0])
{
init_dynamic_string(&ds_tmp, "", 16384, 65536);
ds = &ds_tmp;
......@@ -2060,44 +2062,45 @@ int run_query(MYSQL* mysql, struct st_query* q, int flags)
goto end;
}
if (!res) goto end;
fields = mysql_fetch_fields(res);
num_fields = mysql_num_fields(res);
for( i = 0; i < num_fields; i++)
{
if (i)
dynstr_append_mem(ds, "\t", 1);
dynstr_append(ds, fields[i].name);
}
dynstr_append_mem(ds, "\n", 1);
if (!res)
goto end;
while((row = mysql_fetch_row(res)))
if (!disable_result_log)
{
lengths = mysql_fetch_lengths(res);
for(i = 0; i < num_fields; i++)
fields = mysql_fetch_fields(res);
num_fields = mysql_num_fields(res);
for (i = 0; i < num_fields; i++)
{
val = (char*)row[i];
len = lengths[i];
if (!val)
{
val = (char*)"NULL";
len = 4;
}
if (i)
dynstr_append_mem(ds, "\t", 1);
replace_dynstr_append_mem(ds, val, len);
dynstr_append(ds, fields[i].name);
}
dynstr_append_mem(ds, "\n", 1);
}
if (glob_replace)
free_replace();
while ((row = mysql_fetch_row(res)))
{
lengths = mysql_fetch_lengths(res);
for(i = 0; i < num_fields; i++)
{
val = (char*)row[i];
len = lengths[i];
if (!val)
{
val = (char*)"NULL";
len = 4;
}
if (i)
dynstr_append_mem(ds, "\t", 1);
replace_dynstr_append_mem(ds, val, len);
}
dynstr_append_mem(ds, "\n", 1);
}
if (glob_replace)
free_replace();
}
if (record)
{
if (!q->record_file[0] && !result_file)
......@@ -2111,7 +2114,8 @@ int run_query(MYSQL* mysql, struct st_query* q, int flags)
}
end:
if (res) mysql_free_result(res);
if (res)
mysql_free_result(res);
last_result=0;
if (ds == &ds_tmp)
dynstr_free(&ds_tmp);
......@@ -2288,10 +2292,12 @@ int main(int argc, char** argv)
case Q_DIRTY_CLOSE:
close_connection(q); break;
case Q_RPL_PROBE: do_rpl_probe(q); break;
case Q_ENABLE_RPL_PARSE: do_enable_rpl_parse(q); break;
case Q_DISABLE_RPL_PARSE: do_disable_rpl_parse(q); break;
case Q_ENABLE_QUERY_LOG: disable_query_log=0; break;
case Q_DISABLE_QUERY_LOG: disable_query_log=1; break;
case Q_ENABLE_RPL_PARSE: do_enable_rpl_parse(q); break;
case Q_DISABLE_RPL_PARSE: do_disable_rpl_parse(q); break;
case Q_ENABLE_QUERY_LOG: disable_query_log=0; break;
case Q_DISABLE_QUERY_LOG: disable_query_log=1; break;
case Q_ENABLE_RESULT_LOG: disable_result_log=0; break;
case Q_DISABLE_RESULT_LOG: disable_result_log=1; break;
case Q_SOURCE: do_source(q); break;
case Q_SLEEP: do_sleep(q); break;
case Q_REQUIRE_MANAGER: do_require_manager(q); break;
......
......@@ -253,6 +253,7 @@ inline double ulonglong2double(ulonglong value)
#define HAVE_STRPBRK
#define HAVE_STRSTR
#define HAVE_COMPRESS
#define HAVE_CREATESEMAPHORE
#ifdef NOT_USED
#define HAVE_SNPRINTF /* Gave link error */
......
......@@ -132,16 +132,17 @@ void pthread_exit(void *a); /* was #define pthread_exit(A) ExitThread(A)*/
#define pthread_equal(A,B) ((A) == (B))
#ifdef OS2
int pthread_mutex_init (pthread_mutex_t *, const pthread_mutexattr_t *);
int pthread_mutex_lock (pthread_mutex_t *);
int pthread_mutex_unlock (pthread_mutex_t *);
int pthread_mutex_destroy (pthread_mutex_t *);
extern int pthread_mutex_init (pthread_mutex_t *, const pthread_mutexattr_t *);
extern int pthread_mutex_lock (pthread_mutex_t *);
extern int pthread_mutex_unlock (pthread_mutex_t *);
extern int pthread_mutex_destroy (pthread_mutex_t *);
#define my_pthread_setprio(A,B) DosSetPriority(PRTYS_THREAD,PRTYC_NOCHANGE, B, A)
#define pthread_kill(A,B) raise(B)
#define pthread_exit(A) pthread_dummy()
#else
#define pthread_mutex_init(A,B) InitializeCriticalSection(A)
#define pthread_mutex_lock(A) (EnterCriticalSection(A),0)
#define pthread_mutex_trylock(A) (WaitForSingleObject((A), 0) == WAIT_TIMEOUT)
#define pthread_mutex_unlock(A) LeaveCriticalSection(A)
#define pthread_mutex_destroy(A) DeleteCriticalSection(A)
#define my_pthread_setprio(A,B) SetThreadPriority(GetCurrentThread(), (B))
......
/*
* Module: semaphore.h
*
* Purpose:
* Semaphores aren't actually part of the PThreads standard.
* They are defined by the POSIX Standard:
*
* POSIX 1003.1b-1993 (POSIX.1b)
*
* Pthreads-win32 - POSIX Threads Library for Win32
* Copyright (C) 1998
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public
* License along with this library; if not, write to the Free
* Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
* MA 02111-1307, USA
*/
/* This is hacked by Monty to be included in mysys library */
#ifndef _my_semaphore_h_
#define _my_semaphore_h_
#ifndef __WIN__
#include <semaphore.h>
#else
C_MODE_START
typedef HANDLE sem_t;
int sem_init (sem_t * sem, int pshared, unsigned int value);
int sem_destroy (sem_t * sem);
int sem_trywait (sem_t * sem);
int sem_wait (sem_t * sem);
int sem_post (sem_t * sem);
int sem_post_multiple (sem_t * sem,int count);
int sem_getvalue (sem_t * sem, int * sval);
C_MODE_END
#endif /* __WIN__ */
#endif /* !_my_semaphore_h_ */
......@@ -16,9 +16,7 @@
#ifndef _my_sys_h
#define _my_sys_h
#ifdef __cplusplus
extern "C" {
#endif
C_MODE_START
#ifdef HAVE_AIOWAIT
#include <sys/asynch.h> /* Used by record-cache */
......@@ -649,8 +647,6 @@ extern void sleep(int sec);
extern my_bool have_tcpip; /* Is set if tcpip is used */
#endif
#ifdef __cplusplus
}
#endif
C_MODE_END
#include "raid.h"
#endif /* _my_sys_h */
......@@ -2397,6 +2397,8 @@ mysql_fetch_row(MYSQL_RES *res)
DBUG_PRINT("info",("end of data"));
res->eof=1;
res->handle->status=MYSQL_STATUS_READY;
/* Don't clear handle in mysql_free_results */
res->handle=0;
}
}
DBUG_RETURN((MYSQL_ROW) NULL);
......
......@@ -112,11 +112,13 @@ void _ftb_parse_query(FTB *ftb, byte **start, byte *end,
while ((res=ft_get_word(start,end,&w,&param)))
{
byte r=param.plusminus;
float weight=(param.pmsign ? nwghts : wghts)[(r>5)?5:((r<-5)?-5:r)];
float weight= (float) (param.pmsign ? nwghts : wghts)[(r>5)?5:((r<-5)?-5:r)];
switch (res) {
case 1: /* word found */
ftbw=(FTB_WORD *)alloc_root(&ftb->mem_root,
sizeof(FTB_WORD) + (param.trunc ? MI_MAX_KEY_BUFF : w.len+extra));
sizeof(FTB_WORD) +
(param.trunc ? MI_MAX_KEY_BUFF :
w.len+extra));
ftbw->len=w.len+1;
ftbw->yesno=param.yesno;
ftbw->trunc=param.trunc; /* 0 or 1 */
......@@ -216,7 +218,8 @@ FT_INFO * ft_init_boolean_search(MI_INFO *info, uint keynr, byte *query,
ftb->queue.root=(byte **)alloc_root(&ftb->mem_root, (res+1)*sizeof(void*));
reinit_queue(& ftb->queue, res, 0, 0, FTB_WORD_cmp, ftb);
ftbe=(FTB_EXPR *)alloc_root(&ftb->mem_root, sizeof(FTB_EXPR));
ftbe->weight=ftbe->yesno=ftbe->nos=1;
ftbe->weight=1;
ftbe->yesno=ftbe->nos=1;
ftbe->up=0;
ftbe->ythresh=0;
ftbe->docid=HA_POS_ERROR;
......@@ -236,7 +239,8 @@ void _ftb_climb_the_tree(FTB_WORD *ftbw, my_off_t curdoc)
{
if (ftbe->docid != curdoc)
{
ftbe->cur_weight=ftbe->yesses=ftbe->nos=0;
ftbe->cur_weight=0;
ftbe->yesses=ftbe->nos=0;
ftbe->docid=curdoc;
}
if (ftbe->nos)
......@@ -373,7 +377,8 @@ float ft_boolean_find_relevance(FT_INFO *ftb, byte *record, uint length)
{
if (ftbe->docid != HA_POS_ERROR)
{
ftbe->cur_weight=ftbe->yesses=ftbe->nos=0;
ftbe->cur_weight=0;
ftbe->yesses=ftbe->nos=0;
ftbe->docid=HA_POS_ERROR;
}
else
......
......@@ -248,7 +248,8 @@ int ft_nlq_read_next(FT_INFO *handler, char *record)
}
float ft_nlq_find_relevance(FT_INFO *handler,
byte *record __attribute__((unused)), uint length __attribute__((unused)))
byte *record __attribute__((unused)),
uint length __attribute__((unused)))
{
int a,b,c;
FT_DOC *docs=handler->doc;
......@@ -267,7 +268,7 @@ float ft_nlq_find_relevance(FT_INFO *handler,
a=c;
}
if (docs[a].dpos == docid)
return docs[a].weight;
return (float) docs[a].weight;
else
return 0.0;
}
......@@ -279,7 +280,7 @@ void ft_nlq_close_search(FT_INFO *handler)
float ft_nlq_get_relevance(FT_INFO *handler)
{
return handler->doc[handler->curdoc].weight;
return (float) handler->doc[handler->curdoc].weight;
}
void ft_nlq_reinit_search(FT_INFO *handler)
......
......@@ -19,6 +19,7 @@
/* functions to work with full-text indices */
#include "ftdefs.h"
#include <math.h>
/**************************************************************
This is to make ft-code to ignore keyseg.length at all *
......@@ -186,7 +187,7 @@ int _mi_ft_update(MI_INFO *info, uint keynr, byte *keybuf,
cmp=_mi_compare_text(default_charset_info,
(uchar*) old_word->pos,old_word->len,
(uchar*) new_word->pos,new_word->len,0);
cmp2= cmp ? 0 : (abs(old_word->weight - new_word->weight) > 1.e-5);
cmp2= cmp ? 0 : (fabs(old_word->weight - new_word->weight) > 1.e-5);
if (cmp < 0 || cmp2)
{
......
reset query cache;
flush status;
drop table if exists t1;
drop table if exists t1,t2,t3;
create table t1 (a int not null);
insert into t1 values (1),(2),(3);
select * from t1;
......@@ -36,3 +36,265 @@ drop table t1;
show status like "Qcache_queries_in_cache";
Variable_name Value
Qcache_queries_in_cache 0
create table t1 (a int not null);
insert into t1 values (1),(2),(3);
create table t2 (a int not null);
insert into t2 values (4),(5),(6);
create table t3 (a int not null) type=MERGE UNION=(t1,t2) INSERT_METHOD=FIRST;
select * from t3;
a
1
2
3
4
5
6
select * from t3;
a
1
2
3
4
5
6
show status like "Qcache_hits";
Variable_name Value
Qcache_hits 2
show status like "Qcache_queries_in_cache";
Variable_name Value
Qcache_queries_in_cache 1
insert into t2 values (7);
show status like "Qcache_queries_in_cache";
Variable_name Value
Qcache_queries_in_cache 0
select * from t1;
a
1
2
3
select * from t1;
a
1
2
3
show status like "Qcache_hits";
Variable_name Value
Qcache_hits 3
show status like "Qcache_queries_in_cache";
Variable_name Value
Qcache_queries_in_cache 1
insert into t3 values (8);
show status like "Qcache_queries_in_cache";
Variable_name Value
Qcache_queries_in_cache 0
select * from t3;
a
1
2
3
8
4
5
6
7
show status like "Qcache_queries_in_cache";
Variable_name Value
Qcache_queries_in_cache 1
update t2 set a=9 where a=7;
show status like "Qcache_queries_in_cache";
Variable_name Value
Qcache_queries_in_cache 0
select * from t1;
a
1
2
3
8
show status like "Qcache_queries_in_cache";
Variable_name Value
Qcache_queries_in_cache 1
update t3 set a=10 where a=1;
show status like "Qcache_queries_in_cache";
Variable_name Value
Qcache_queries_in_cache 0
select * from t3;
a
10
2
3
8
4
5
6
9
show status like "Qcache_queries_in_cache";
Variable_name Value
Qcache_queries_in_cache 1
delete from t2 where a=9;
show status like "Qcache_queries_in_cache";
Variable_name Value
Qcache_queries_in_cache 0
select * from t1;
a
10
2
3
8
show status like "Qcache_queries_in_cache";
Variable_name Value
Qcache_queries_in_cache 1
delete from t3 where a=10;
show status like "Qcache_queries_in_cache";
Variable_name Value
Qcache_queries_in_cache 0
drop table t1, t2, t3;
set autocommit=0;
create table t1 (a int not null) type=innodb;
insert into t1 values (1),(2),(3);
select * from t1;
a
1
2
3
show status like "Qcache_queries_in_cache";
Variable_name Value
Qcache_queries_in_cache 0
drop table t1;
commit;
set autocommit=1;
create table t1 (a int not null);
insert into t1 values (1),(2),(3);
create table t2 (a int not null);
insert into t2 values (1),(2),(3);
select * from t1;
a
1
2
3
select * from t2;
a
1
2
3
insert into t1 values (4);
show status like "Qcache_free_blocks";
Variable_name Value
Qcache_free_blocks 2
flush query cache;
show status like "Qcache_free_blocks";
Variable_name Value
Qcache_free_blocks 1
drop table t1, t2;
set sql_query_cache_type=demand;
create table t1 (a int not null);
insert into t1 values (1),(2),(3);
select * from t1;
a
1
2
3
show status like "Qcache_queries_in_cache";
Variable_name Value
Qcache_queries_in_cache 0
select sql_cache * from t1;
a
1
2
3
set sql_query_cache_type=2;
select sql_cache * from t1;
a
1
2
3
show status like "Qcache_hits";
Variable_name Value
Qcache_hits 4
show status like "Qcache_queries_in_cache";
Variable_name Value
Qcache_queries_in_cache 1
set sql_query_cache_type=on;
reset query cache;
show status like "Qcache_queries_in_cache";
Variable_name Value
Qcache_queries_in_cache 0
select sql_no_cache * from t1;
a
1
2
3
show status like "Qcache_queries_in_cache";
Variable_name Value
Qcache_queries_in_cache 0
drop table t1;
create table t1 (a text not null);
select CONNECTION_ID() from t1;
CONNECTION_ID()
select FOUND_ROWS();
FOUND_ROWS()
0
select NOW() from t1;
NOW()
select CURDATE() from t1;
CURDATE()
select CURTIME() from t1;
CURTIME()
select DATABASE() from t1;
DATABASE()
select ENCRYPT("test") from t1;
ENCRYPT("test")
select LAST_INSERT_ID() from t1;
last_insert_id()
select RAND() from t1;
RAND()
select UNIX_TIMESTAMP() from t1;
UNIX_TIMESTAMP()
select USER() from t1;
USER()
select benchmark(1,1) from t1;
benchmark(1,1)
show status like "Qcache_queries_in_cache";
Variable_name Value
Qcache_queries_in_cache 0
create table t2 (a text not null);
insert into t1 values("1111111111111111111111111111111111111111111111111111");
insert into t2 select * from t1;
insert into t1 select * from t2;
insert into t2 select * from t1;
insert into t1 select * from t2;
insert into t2 select * from t1;
insert into t1 select * from t2;
insert into t2 select * from t1;
insert into t1 select * from t2;
insert into t2 select * from t1;
insert into t1 select * from t2;
insert into t2 select * from t1;
insert into t1 select * from t2;
insert into t2 select * from t1;
insert into t1 select * from t2;
insert into t2 select * from t1;
insert into t1 select * from t2;
insert into t2 select * from t1;
insert into t1 select * from t2;
drop table t2;
show status like "Qcache_hits";
Variable_name Value
Qcache_hits 4
select a as a1, a as a2 from t1;
select a as a2, a as a3 from t1;
select a as a3, a as a4 from t1;
select a as a1, a as a2 from t1;
show status like "Qcache_hits";
Variable_name Value
Qcache_hits 4
show status like "Qcache_queries_in_cache";
Variable_name Value
Qcache_queries_in_cache 2
reset query cache;
show variables like "query_cache_size";
Variable_name Value
query_cache_size 1039700
show status like "Qcache_free_memory";
Variable_name Value
Qcache_free_memory 1039700
drop table t1;
--set-variable=query_cache_size=2M
--set-variable=query_cache_size=1M
-- source include/have_innodb.inc
#
# Tests with query cache
#
......@@ -6,7 +8,12 @@
reset query cache;
flush status;
drop table if exists t1;
drop table if exists t1,t2,t3;
#
# First simple test
#
create table t1 (a int not null);
insert into t1 values (1),(2),(3);
select * from t1;
......@@ -24,3 +31,153 @@ show status like "Qcache_hits";
drop table t1;
show status like "Qcache_queries_in_cache";
#
# MERGE TABLES with INSERT/UPDATE and DELETE
#
create table t1 (a int not null);
insert into t1 values (1),(2),(3);
create table t2 (a int not null);
insert into t2 values (4),(5),(6);
create table t3 (a int not null) type=MERGE UNION=(t1,t2) INSERT_METHOD=FIRST;
# insert
select * from t3;
select * from t3;
show status like "Qcache_hits";
show status like "Qcache_queries_in_cache";
insert into t2 values (7);
show status like "Qcache_queries_in_cache";
select * from t1;
select * from t1;
show status like "Qcache_hits";
show status like "Qcache_queries_in_cache";
insert into t3 values (8);
show status like "Qcache_queries_in_cache";
# update
select * from t3;
show status like "Qcache_queries_in_cache";
update t2 set a=9 where a=7;
show status like "Qcache_queries_in_cache";
select * from t1;
show status like "Qcache_queries_in_cache";
update t3 set a=10 where a=1;
show status like "Qcache_queries_in_cache";
#delete
select * from t3;
show status like "Qcache_queries_in_cache";
delete from t2 where a=9;
show status like "Qcache_queries_in_cache";
select * from t1;
show status like "Qcache_queries_in_cache";
delete from t3 where a=10;
show status like "Qcache_queries_in_cache";
drop table t1, t2, t3;
#
# Without auto_commit.
#
set autocommit=0;
create table t1 (a int not null) type=innodb;
insert into t1 values (1),(2),(3);
select * from t1;
show status like "Qcache_queries_in_cache";
drop table t1;
commit;
set autocommit=1;
#
# FLUSH QUERY CACHE
#
create table t1 (a int not null);
insert into t1 values (1),(2),(3);
create table t2 (a int not null);
insert into t2 values (1),(2),(3);
select * from t1;
select * from t2;
insert into t1 values (4);
show status like "Qcache_free_blocks";
flush query cache;
show status like "Qcache_free_blocks";
drop table t1, t2;
#
# SELECT SQL_CACHE ...
#
set sql_query_cache_type=demand;
create table t1 (a int not null);
insert into t1 values (1),(2),(3);
select * from t1;
show status like "Qcache_queries_in_cache";
select sql_cache * from t1;
set sql_query_cache_type=2;
select sql_cache * from t1;
show status like "Qcache_hits";
show status like "Qcache_queries_in_cache";
set sql_query_cache_type=on;
#
# RESET QUERY CACHE
#
reset query cache;
show status like "Qcache_queries_in_cache";
#
# SELECT SQL_NO_CACHE
#
select sql_no_cache * from t1;
show status like "Qcache_queries_in_cache";
drop table t1;
#
# Check that queries that uses NOW(), LAST_INSERT_ID()... are not cached.
#
create table t1 (a text not null);
select CONNECTION_ID() from t1;
#GET_LOCK
#RELEASE_LOCK
#LOAD_FILE
select FOUND_ROWS();
select NOW() from t1;
select CURDATE() from t1;
select CURTIME() from t1;
select DATABASE() from t1;
select ENCRYPT("test") from t1;
select LAST_INSERT_ID() from t1;
select RAND() from t1;
select UNIX_TIMESTAMP() from t1;
select USER() from t1;
select benchmark(1,1) from t1;
show status like "Qcache_queries_in_cache";
#
# Tests when the cache is filled
#
create table t2 (a text not null);
insert into t1 values("1111111111111111111111111111111111111111111111111111");
insert into t2 select * from t1;
insert into t1 select * from t2; # 2
insert into t2 select * from t1; # 3
insert into t1 select * from t2; # 5
insert into t2 select * from t1; # 8
insert into t1 select * from t2; # 13
insert into t2 select * from t1; # 21
insert into t1 select * from t2; # 34
insert into t2 select * from t1; # 55
insert into t1 select * from t2; # 89
insert into t2 select * from t1; # 144
insert into t1 select * from t2; # 233
insert into t2 select * from t1; # 357
insert into t1 select * from t2; # 610
insert into t2 select * from t1; # 987
insert into t1 select * from t2; # 1597
insert into t2 select * from t1; # 2584
insert into t1 select * from t2; # 4181
drop table t2;
show status like "Qcache_hits";
disable_result_log;
select a as a1, a as a2 from t1;
select a as a2, a as a3 from t1;
select a as a3, a as a4 from t1;
# next query must be out of 1Mb cache
select a as a1, a as a2 from t1;
enable_result_log;
show status like "Qcache_hits";
show status like "Qcache_queries_in_cache";
reset query cache;
show variables like "query_cache_size";
show status like "Qcache_free_memory";
drop table t1;
......@@ -30,7 +30,8 @@ libmysys_a_SOURCES = my_init.c my_getwd.c mf_getdate.c\
mf_iocache.c mf_iocache2.c mf_cache.c mf_tempfile.c \
my_lock.c mf_brkhant.c my_alarm.c \
my_malloc.c my_realloc.c my_once.c mulalloc.c \
my_alloc.c safemalloc.c my_fopen.c my_fstream.c \
my_alloc.c safemalloc.c my_new.cc \
my_fopen.c my_fstream.c \
my_error.c errors.c my_div.c my_messnc.c \
mf_format.c mf_same.c mf_dirname.c mf_fn_ext.c \
my_symlink.c my_symlink2.c \
......
/* Copyright (C) 2000 MySQL AB
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
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
/*
This is a replacement of new/delete operators to be used when compiling
with gcc 3.0.x to avoid including libstdc++
*/
#include "mysys_priv.h"
#ifdef USE_MYSYS_NEW
void *operator new (size_t sz)
{
return (void *) malloc (sz ? sz+1 : sz);
}
void *operator new[] (size_t sz)
{
return (void *) malloc (sz ? sz+1 : sz);
}
void operator delete (void *ptr)
{
if (ptr)
free(ptr);
}
void operator delete[] (void *ptr) throw ()
{
if (ptr)
free(ptr);
}
#endif /* USE_MYSYS_NEW */
/*
* -------------------------------------------------------------
*
* Module: my_semaphore.c (Original: semaphore.c from pthreads library)
*
* Purpose:
* Semaphores aren't actually part of the PThreads standard.
* They are defined by the POSIX Standard:
*
* POSIX 1003.1b-1993 (POSIX.1b)
*
* -------------------------------------------------------------
*
* Pthreads-win32 - POSIX Threads Library for Win32
* Copyright (C) 1998
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public
* License along with this library; if not, write to the Free
* Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
* MA 02111-1307, USA
*/
/*
NEED_SEM is not used in MySQL and should only be needed under
Windows CE.
The big changes compared to the original version was to not allocate
any additional memory in sem_init() but to instead store everthing
we need in sem_t.
TODO:
To get HAVE_CREATESEMAPHORE we have to define the struct
in my_semaphore.h
*/
#include "mysys_priv.h"
#ifdef __WIN__
#include "my_semaphore.h"
#include <errno.h>
/*
DOCPUBLIC
This function initializes an unnamed semaphore. the
initial value of the semaphore is 'value'
PARAMETERS
sem
pointer to an instance of sem_t
pshared
if zero, this semaphore may only be shared between
threads in the same process.
if nonzero, the semaphore can be shared between
processes
value
initial value of the semaphore counter
DESCRIPTION
This function initializes an unnamed semaphore. The
initial value of the semaphore is set to 'value'.
RESULTS
0 successfully created semaphore,
-1 failed, error in errno
ERRNO
EINVAL 'sem' is not a valid semaphore,
ENOSPC a required resource has been exhausted,
ENOSYS semaphores are not supported,
EPERM the process lacks appropriate privilege
*/
int
sem_init (sem_t *sem, int pshared, unsigned int value)
{
int result = 0;
if (pshared != 0)
{
/*
We don't support creating a semaphore that can be shared between
processes
*/
result = EPERM;
}
else
{
#ifndef HAVE_CREATESEMAPHORE
sem->value = value;
sem->event = CreateEvent(NULL,
FALSE, /* manual reset */
FALSE, /* initial state */
NULL);
if (!sem->event)
result = ENOSPC;
else
{
if (value)
SetEvent(sem->event);
InitializeCriticalSection(&sem->sem_lock_cs);
}
#else /* HAVE_CREATESEMAPHORE */
*sem = CreateSemaphore (NULL, /* Always NULL */
value, /* Initial value */
0x7FFFFFFFL, /* Maximum value */
NULL); /* Name */
if (!*sem)
result = ENOSPC;
#endif /* HAVE_CREATESEMAPHORE */
}
if (result != 0)
{
errno = result;
return -1;
}
return 0;
} /* sem_init */
/*
DOCPUBLIC
This function destroys an unnamed semaphore.
PARAMETERS
sem
pointer to an instance of sem_t
DESCRIPTION
This function destroys an unnamed semaphore.
RESULTS
0 successfully destroyed semaphore,
-1 failed, error in errno
ERRNO
EINVAL 'sem' is not a valid semaphore,
ENOSYS semaphores are not supported,
EBUSY threads (or processes) are currently
blocked on 'sem'
*/
int
sem_destroy (sem_t * sem)
{
int result = 0;
#ifdef EXTRA_DEBUG
if (sem == NULL || *sem == NULL)
{
errno=EINVAL;
return;
}
#endif /* EXTRA_DEBUG */
#ifndef HAVE_CREATESEMAPHORE
if (! CloseHandle(sem->event))
result = EINVAL;
else
DeleteCriticalSection(&sem->sem_lock_cs);
#else /* HAVE_CREATESEMAPHORE */
if (!CloseHandle(*sem))
result = EINVAL;
#endif /* HAVE_CREATESEMAPHORE */
if (result)
{
errno = result;
return -1;
}
*sem=0; /* Safety */
return 0;
} /* sem_destroy */
/*
DOCPUBLIC
This function tries to wait on a semaphore.
PARAMETERS
sem
pointer to an instance of sem_t
DESCRIPTION
This function tries to wait on a semaphore. If the
semaphore value is greater than zero, it decreases
its value by one. If the semaphore value is zero, then
this function returns immediately with the error EAGAIN
RESULTS
0 successfully decreased semaphore,
-1 failed, error in errno
ERRNO
EAGAIN the semaphore was already locked,
EINVAL 'sem' is not a valid semaphore,
ENOSYS semaphores are not supported,
EINTR the function was interrupted by a signal,
EDEADLK a deadlock condition was detected.
*/
int
sem_trywait(sem_t * sem)
{
#ifndef HAVE_CREATESEMAPHORE
/* not yet implemented! */
int errno = EINVAL;
return -1;
#else /* HAVE_CREATESEMAPHORE */
#ifdef EXTRA_DEBUG
if (sem == NULL || *sem == NULL)
{
errno=EINVAL;
return -1;
}
#endif /* EXTRA_DEBUG */
if (WaitForSingleObject (*sem, 0) == WAIT_TIMEOUT)
{
errno= EAGAIN;
return -1;
}
return 0;
#endif /* HAVE_CREATESEMAPHORE */
} /* sem_trywait */
#ifndef HAVE_CREATESEMAPHORE
static void
ptw32_decrease_semaphore(sem_t * sem)
{
EnterCriticalSection(&sem->sem_lock_cs);
DBUG_ASSERT(sem->value != 0);
sem->value--;
if (sem->value != 0)
SetEvent(sem->event);
LeaveCriticalSection(&sem->sem_lock_cs);
}
static BOOL
ptw32_increase_semaphore(sem_t * sem, unsigned int n)
{
BOOL result=FALSE;
EnterCriticalSection(&sem->sem_lock_cs);
if (sem->value + n > sem->value)
{
sem->value += n;
SetEvent(sem->event);
result = TRUE;
}
LeaveCriticalSection(&sem->sem_lock_cs);
return result;
}
#endif /* HAVE_CREATESEMAPHORE */
/*
------------------------------------------------------
DOCPUBLIC
This function waits on a semaphore.
PARAMETERS
sem
pointer to an instance of sem_t
DESCRIPTION
This function waits on a semaphore. If the
semaphore value is greater than zero, it decreases
its value by one. If the semaphore value is zero, then
the calling thread (or process) is blocked until it can
successfully decrease the value or until interrupted by
a signal.
RESULTS
0 successfully decreased semaphore,
-1 failed, error in errno
ERRNO
EINVAL 'sem' is not a valid semaphore,
ENOSYS semaphores are not supported,
EINTR the function was interrupted by a signal,
EDEADLK a deadlock condition was detected.
*/
int
sem_wait(sem_t *sem)
{
int result;
#ifdef EXTRA_DEBUG
if (sem == NULL || *sem == NULL)
{
errno=EINVAL;
return -1;
}
#endif /* EXTRA_DEBUG */
#ifndef HAVE_CREATESEMAPHORE
result=WaitForSingleObject(sem->event, INFINITE);
#else
result=WaitForSingleObject(*sem, INFINITE);
#endif
if (result == WAIT_FAILED || result == WAIT_ABANDONED_0)
result = EINVAL;
else if (result == WAIT_TIMEOUT)
result = ETIMEDOUT;
else
result=0;
if (result)
{
errno = result;
return -1;
}
#ifndef HAVE_CREATESEMAPHORE
ptw32_decrease_semaphore(sem);
#endif /* HAVE_CREATESEMAPHORE */
return 0;
}
/*
------------------------------------------------------
DOCPUBLIC
This function posts a wakeup to a semaphore.
PARAMETERS
sem
pointer to an instance of sem_t
DESCRIPTION
This function posts a wakeup to a semaphore. If there
are waiting threads (or processes), one is awakened;
otherwise, the semaphore value is incremented by one.
RESULTS
0 successfully posted semaphore,
-1 failed, error in errno
ERRNO
EINVAL 'sem' is not a valid semaphore,
ENOSYS semaphores are not supported,
*/
int
sem_post (sem_t * sem)
{
#ifdef EXTRA_DEBUG
if (sem == NULL || *sem == NULL)
{
errno=EINVAL;
return -1;
}
#endif /* EXTRA_DEBUG */
#ifndef HAVE_CREATESEMAPHORE
if (! ptw32_increase_semaphore(sem, 1))
#else /* HAVE_CREATESEMAPHORE */
if (! ReleaseSemaphore(*sem, 1, 0))
#endif /* HAVE_CREATESEMAPHORE */
{
errno=EINVAL;
return -1;
}
return 0;
}
/*
------------------------------------------------------
DOCPUBLIC
This function posts multiple wakeups to a semaphore.
PARAMETERS
sem
pointer to an instance of sem_t
count
counter, must be greater than zero.
DESCRIPTION
This function posts multiple wakeups to a semaphore. If there
are waiting threads (or processes), n <= count are awakened;
the semaphore value is incremented by count - n.
RESULTS
0 successfully posted semaphore,
-1 failed, error in errno
ERRNO
EINVAL 'sem' is not a valid semaphore
or count is less than or equal to zero.
*/
int
sem_post_multiple (sem_t * sem, int count )
{
#ifdef EXTRA_DEBUG
if (sem == NULL || *sem == NULL || count <= 0)
{
errno=EINVAL;
return -1;
}
#endif /* EXTRA_DEBUG */
#ifndef HAVE_CREATESEMAPHORE
if (! ptw32_increase_semaphore (sem, count))
#else /* HAVE_CREATESEMAPHORE */
if (! ReleaseSemaphore(*sem, count, 0))
#endif /* HAVE_CREATESEMAPHORE */
{
errno = EINVAL;
return -1;
}
return 0;
}
int
sem_getvalue (sem_t *sem, int *sval)
{
errno = ENOSYS;
return -1;
} /* sem_getvalue */
#endif /* __WIN__ */
......@@ -69,7 +69,7 @@ ha_rows filesort(TABLE *table, SORT_FIELD *sortorder, uint s_length,
{
int error;
ulong memavl;
uint maxbuffer,skr;
uint maxbuffer;
BUFFPEK *buffpek;
ha_rows records;
uchar **sort_keys;
......@@ -163,7 +163,7 @@ ha_rows filesort(TABLE *table, SORT_FIELD *sortorder, uint s_length,
&tempfile, selected_records_file)) ==
HA_POS_ERROR)
goto err;
maxbuffer= my_b_tell(&buffpek_pointers)/sizeof(*buffpek);
maxbuffer= (uint) (my_b_tell(&buffpek_pointers)/sizeof(*buffpek));
if (maxbuffer == 0) // The whole set is in memory
{
......@@ -267,7 +267,7 @@ static BUFFPEK *read_buffpek_from_file(IO_CACHE *buffpek_pointers, uint count)
if (tmp)
{
if (reinit_io_cache(buffpek_pointers,READ_CACHE,0L,0,0) ||
my_b_read(buffpek_pointers, (char*) tmp, length))
my_b_read(buffpek_pointers, (byte*) tmp, length))
{
my_free((char*) tmp, MYF(0));
tmp=0;
......@@ -398,10 +398,12 @@ static ha_rows find_all_keys(SORTPARAM *param, SQL_SELECT *select,
/* Skriver en buffert med nycklar till filen */
static int write_keys(SORTPARAM *param, register uchar **sort_keys, uint count,
IO_CACHE *buffpek_pointers, IO_CACHE *tempfile)
static int
write_keys(SORTPARAM *param, register uchar **sort_keys, uint count,
IO_CACHE *buffpek_pointers, IO_CACHE *tempfile)
{
uint sort_length;
uchar **end;
BUFFPEK buffpek;
DBUG_ENTER("write_keys");
......@@ -419,10 +421,10 @@ static int write_keys(SORTPARAM *param, register uchar **sort_keys, uint count,
if ((ha_rows) count > param->max_rows)
count=(uint) param->max_rows; /* purecov: inspected */
buffpek.count=(ha_rows) count;
for (uchar **end=sort_keys+count ; sort_keys != end ; sort_keys++)
for (end=sort_keys+count ; sort_keys != end ; sort_keys++)
if (my_b_write(tempfile,(byte*) *sort_keys,(uint) sort_length))
goto err;
if (my_b_write(buffpek_pointers, (char*) &buffpek, sizeof(buffpek)))
if (my_b_write(buffpek_pointers, (byte*) &buffpek, sizeof(buffpek)))
goto err;
DBUG_RETURN(0);
......
......@@ -2019,7 +2019,9 @@ void Item_func_match::init_search(bool no_order)
}
ft_handler=table->file->ft_init_ext(mode, key,
ft_tmp->ptr(), ft_tmp->length(), join_key && !no_order);
(byte*) ft_tmp->ptr(),
ft_tmp->length(),
join_key && !no_order);
if (join_key)
{
......
......@@ -149,7 +149,7 @@ char* query_table_status(THD *thd,const char *db,const char *table_name);
#define SELECT_SMALL_RESULT 8
#define SELECT_BIG_RESULT 16
#define OPTION_FOUND_ROWS 32
#define SELECT_HIGH_PRIORITY 64 /* Intern */
#define OPTION_TO_QUERY_CACHE 64
#define SELECT_NO_JOIN_CACHE 256 /* Intern */
#define OPTION_BIG_TABLES 512 /* for SQL OPTION */
......@@ -179,7 +179,6 @@ char* query_table_status(THD *thd,const char *db,const char *table_name);
#define SELECT_NO_UNLOCK (QUERY_NO_GOOD_INDEX_USED*2)
#define TMP_TABLE_ALL_COLUMNS (SELECT_NO_UNLOCK*2)
#define OPTION_TO_QUERY_CACHE (TMP_TABLE_ALL_COLUMNS*2)
#define MODE_REAL_AS_FLOAT 1
......
......@@ -3157,12 +3157,16 @@ struct show_var_st status_vars[]= {
{"Open_streams", (char*) &my_stream_opened, SHOW_INT_CONST},
{"Opened_tables", (char*) &opened_tables, SHOW_LONG},
{"Questions", (char*) 0, SHOW_QUESTION},
{"Qcache_queries_in_cache", (char*) &query_cache.queries_in_cache,
SHOW_LONG},
{"Qcache_queries_in_cache", (char*) &query_cache.queries_in_cache, SHOW_LONG_CONST},
{"Qcache_inserts", (char*) &query_cache.inserts, SHOW_LONG},
{"Qcache_hits", (char*) &query_cache.hits, SHOW_LONG},
{"Qcache_not_cached", (char*) &query_cache.refused, SHOW_LONG},
{"Qcache_free_memory", (char*) &query_cache.free_memory,SHOW_LONG},
{"Qcache_free_memory", (char*) &query_cache.free_memory,
SHOW_LONG_CONST},
{"Qcache_free_blocks", (char*) &query_cache.free_memory_blocks,
SHOW_LONG_CONST},
{"Qcache_total_blocks", (char*) &query_cache.total_blocks,
SHOW_LONG_CONST},
{"Rpl_status", (char*) 0, SHOW_RPL_STATUS},
{"Select_full_join", (char*) &select_full_join_count, SHOW_LONG},
{"Select_full_range_join", (char*) &select_full_range_join_count, SHOW_LONG},
......
......@@ -35,11 +35,14 @@ bool do_table_inited = 0, ignore_table_inited = 0;
bool wild_do_table_inited = 0, wild_ignore_table_inited = 0;
bool table_rules_on = 0;
uint32 slave_skip_counter = 0;
/*
When slave thread exits, we need to remember the temporary tables so we
can re-use them on slave start
*/
static TABLE* save_temporary_tables = 0;
THD* slave_thd = 0;
// when slave thread exits, we need to remember the temporary tables so we
// can re-use them on slave start
THD* slave_thd = 0;
int last_slave_errno = 0;
char last_slave_error[MAX_SLAVE_ERRMSG] = "";
#ifndef DBUG_OFF
......@@ -98,14 +101,14 @@ static TABLE_RULE_ENT* find_wild(DYNAMIC_ARRAY *a, const char* key, int len)
uint i;
const char* key_end = key + len;
for(i = 0; i < a->elements; i++)
{
TABLE_RULE_ENT* e ;
get_dynamic(a, (gptr)&e, i);
if(!wild_case_compare(key, key_end, (const char*)e->db,
(const char*)(e->db + e->key_len),'\\'))
return e;
}
for (i = 0; i < a->elements; i++)
{
TABLE_RULE_ENT* e ;
get_dynamic(a, (gptr)&e, i);
if (!wild_case_compare(key, key_end, (const char*)e->db,
(const char*)(e->db + e->key_len),'\\'))
return e;
}
return 0;
}
......@@ -114,10 +117,10 @@ int tables_ok(THD* thd, TABLE_LIST* tables)
{
for (; tables; tables = tables->next)
{
if (!tables->updating)
continue;
char hash_key[2*NAME_LEN+2];
char* p;
if (!tables->updating)
continue;
p = strmov(hash_key, tables->db ? tables->db : thd->db);
*p++ = '.';
uint len = strmov(p, tables->real_name) - hash_key ;
......@@ -139,9 +142,10 @@ int tables_ok(THD* thd, TABLE_LIST* tables)
return 0;
}
// if no explicit rule found
// and there was a do list, do not replicate. If there was
// no do list, go ahead
/*
If no explicit rule found and there was a do list, do not replicate.
If there was no do list, go ahead
*/
return !do_table_inited && !wild_do_table_inited;
}
......@@ -149,12 +153,14 @@ int tables_ok(THD* thd, TABLE_LIST* tables)
int add_table_rule(HASH* h, const char* table_spec)
{
const char* dot = strchr(table_spec, '.');
if(!dot) return 1;
if (!dot)
return 1;
// len is always > 0 because we know the there exists a '.'
uint len = (uint)strlen(table_spec);
TABLE_RULE_ENT* e = (TABLE_RULE_ENT*)my_malloc(sizeof(TABLE_RULE_ENT)
+ len, MYF(MY_WME));
if(!e) return 1;
if (!e)
return 1;
e->db = (char*)e + sizeof(TABLE_RULE_ENT);
e->tbl_name = e->db + (dot - table_spec) + 1;
e->key_len = len;
......@@ -166,11 +172,12 @@ int add_table_rule(HASH* h, const char* table_spec)
int add_wild_table_rule(DYNAMIC_ARRAY* a, const char* table_spec)
{
const char* dot = strchr(table_spec, '.');
if(!dot) return 1;
if (!dot) return 1;
uint len = (uint)strlen(table_spec);
TABLE_RULE_ENT* e = (TABLE_RULE_ENT*)my_malloc(sizeof(TABLE_RULE_ENT)
+ len, MYF(MY_WME));
if(!e) return 1;
if (!e)
return 1;
e->db = (char*)e + sizeof(TABLE_RULE_ENT);
e->tbl_name = e->db + (dot - table_spec) + 1;
e->key_len = len;
......@@ -182,12 +189,12 @@ int add_wild_table_rule(DYNAMIC_ARRAY* a, const char* table_spec)
static void free_string_array(DYNAMIC_ARRAY *a)
{
uint i;
for(i = 0; i < a->elements; i++)
{
char* p;
get_dynamic(a, (gptr) &p, i);
my_free(p, MYF(MY_WME));
}
for (i = 0; i < a->elements; i++)
{
char* p;
get_dynamic(a, (gptr) &p, i);
my_free(p, MYF(MY_WME));
}
delete_dynamic(a);
}
......@@ -207,13 +214,13 @@ void end_slave()
pthread_mutex_unlock(&LOCK_slave);
end_master_info(&glob_mi);
if(do_table_inited)
if (do_table_inited)
hash_free(&replicate_do_table);
if(ignore_table_inited)
if (ignore_table_inited)
hash_free(&replicate_ignore_table);
if(wild_do_table_inited)
if (wild_do_table_inited)
free_string_array(&replicate_wild_do_table);
if(wild_ignore_table_inited)
if (wild_ignore_table_inited)
free_string_array(&replicate_wild_ignore_table);
}
......@@ -241,13 +248,13 @@ void skip_load_data_infile(NET* net)
char* rewrite_db(char* db)
{
if(replicate_rewrite_db.is_empty() || !db) return db;
if (replicate_rewrite_db.is_empty() || !db) return db;
I_List_iterator<i_string_pair> it(replicate_rewrite_db);
i_string_pair* tmp;
while((tmp=it++))
{
if(!strcmp(tmp->key, db))
if (!strcmp(tmp->key, db))
return tmp->val;
}
......@@ -257,39 +264,39 @@ char* rewrite_db(char* db)
int db_ok(const char* db, I_List<i_string> &do_list,
I_List<i_string> &ignore_list )
{
if(do_list.is_empty() && ignore_list.is_empty())
if (do_list.is_empty() && ignore_list.is_empty())
return 1; // ok to replicate if the user puts no constraints
// if the user has specified restrictions on which databases to replicate
// and db was not selected, do not replicate
if(!db)
if (!db)
return 0;
if(!do_list.is_empty()) // if the do's are not empty
{
I_List_iterator<i_string> it(do_list);
i_string* tmp;
if (!do_list.is_empty()) // if the do's are not empty
{
I_List_iterator<i_string> it(do_list);
i_string* tmp;
while((tmp=it++))
{
if(!strcmp(tmp->ptr, db))
return 1; // match
}
return 0;
while((tmp=it++))
{
if (!strcmp(tmp->ptr, db))
return 1; // match
}
return 0;
}
else // there are some elements in the don't, otherwise we cannot get here
{
I_List_iterator<i_string> it(ignore_list);
i_string* tmp;
while((tmp=it++))
{
if(!strcmp(tmp->ptr, db))
return 0; // match
}
{
I_List_iterator<i_string> it(ignore_list);
i_string* tmp;
return 1;
while((tmp=it++))
{
if (!strcmp(tmp->ptr, db))
return 0; // match
}
return 1;
}
}
static int init_strvar_from_file(char* var, int max_size, IO_CACHE* f,
......@@ -327,7 +334,7 @@ static int init_intvar_from_file(int* var, IO_CACHE* f, int default_val)
*var = atoi(buf);
return 0;
}
else if(default_val)
else if (default_val)
{
*var = default_val;
return 0;
......@@ -530,7 +537,7 @@ int fetch_nx_table(THD* thd, const char* db_name, const char* table_name,
void end_master_info(MASTER_INFO* mi)
{
if(mi->fd >= 0)
if (mi->fd >= 0)
{
end_io_cache(&mi->file);
(void)my_close(mi->fd, MYF(MY_WME));
......@@ -567,7 +574,7 @@ int init_master_info(MASTER_INFO* mi)
|| init_io_cache(&mi->file, fd, IO_SIZE*2, READ_CACHE, 0L,0,
MYF(MY_WME)))
{
if(fd >= 0)
if (fd >= 0)
my_close(fd, MYF(0));
pthread_mutex_unlock(&mi->lock);
return 1;
......@@ -587,13 +594,13 @@ int init_master_info(MASTER_INFO* mi)
}
else // file exists
{
if(fd >= 0)
if (fd >= 0)
reinit_io_cache(&mi->file, READ_CACHE, 0L,0,0);
else if((fd = my_open(fname, O_RDWR|O_BINARY, MYF(MY_WME))) < 0
else if ((fd = my_open(fname, O_RDWR|O_BINARY, MYF(MY_WME))) < 0
|| init_io_cache(&mi->file, fd, IO_SIZE*2, READ_CACHE, 0L,
0, MYF(MY_WME)))
{
if(fd >= 0)
if (fd >= 0)
my_close(fd, MYF(0));
pthread_mutex_unlock(&mi->lock);
return 1;
......@@ -608,7 +615,7 @@ int init_master_info(MASTER_INFO* mi)
mi->log_file_name[length-1]= 0; // kill \n
/* Reuse fname buffer */
if(!my_b_gets(&mi->file, fname, sizeof(fname)))
if (!my_b_gets(&mi->file, fname, sizeof(fname)))
{
msg="Error reading log file position from master info file";
goto error;
......@@ -616,7 +623,7 @@ int init_master_info(MASTER_INFO* mi)
mi->pos = strtoull(fname,(char**) 0, 10);
mi->fd = fd;
if(init_strvar_from_file(mi->host, sizeof(mi->host), &mi->file,
if (init_strvar_from_file(mi->host, sizeof(mi->host), &mi->file,
master_host) ||
init_strvar_from_file(mi->user, sizeof(mi->user), &mi->file,
master_user) ||
......@@ -654,19 +661,19 @@ int register_slave_on_master(MYSQL* mysql)
String packet;
char buf[4];
if(!report_host)
if (!report_host)
return 0;
int4store(buf, server_id);
packet.append(buf, 4);
net_store_data(&packet, report_host);
if(report_user)
if (report_user)
net_store_data(&packet, report_user);
else
packet.append((char)0);
if(report_password)
if (report_password)
net_store_data(&packet, report_user);
else
packet.append((char)0);
......@@ -678,7 +685,7 @@ int register_slave_on_master(MYSQL* mysql)
int4store(buf, 0); /* tell the master will fill in master_id */
packet.append(buf, 4);
if(mc_simple_command(mysql, COM_REGISTER_SLAVE, (char*)packet.ptr(),
if (mc_simple_command(mysql, COM_REGISTER_SLAVE, (char*)packet.ptr(),
packet.length(), 0))
{
sql_print_error("Error on COM_REGISTER_SLAVE: '%s'",
......@@ -710,7 +717,7 @@ int show_master_info(THD* thd)
field_list.push_back(new Item_empty_string("Last_error", 20));
field_list.push_back(new Item_empty_string("Skip_counter", 12));
field_list.push_back(new Item_empty_string("Last_log_seq", 12));
if(send_fields(thd, field_list, 1))
if (send_fields(thd, field_list, 1))
DBUG_RETURN(-1);
String* packet = &thd->packet;
......@@ -758,6 +765,7 @@ int flush_master_info(MASTER_INFO* mi)
return 0;
}
int st_master_info::wait_for_pos(THD* thd, String* log_name, ulonglong log_pos)
{
if (!inited) return -1;
......@@ -901,17 +909,18 @@ static int request_dump(MYSQL* mysql, MASTER_INFO* mi)
return 0;
}
static int request_table_dump(MYSQL* mysql, const char* db, const char* table)
{
char buf[1024];
char * p = buf;
uint table_len = (uint) strlen(table);
uint db_len = (uint) strlen(db);
if(table_len + db_len > sizeof(buf) - 2)
{
sql_print_error("request_table_dump: Buffer overrun");
return 1;
}
if (table_len + db_len > sizeof(buf) - 2)
{
sql_print_error("request_table_dump: Buffer overrun");
return 1;
}
*p++ = db_len;
memcpy(p, db, db_len);
......@@ -1008,12 +1017,12 @@ static int exec_event(THD* thd, NET* net, MASTER_INFO* mi, int event_len)
if (ev->server_id == ::server_id ||
(slave_skip_counter && type_code != ROTATE_EVENT))
{
if(type_code == LOAD_EVENT)
if (type_code == LOAD_EVENT)
skip_load_data_infile(net);
mi->inc_pos(event_len, ev->log_seq);
flush_master_info(mi);
if(slave_skip_counter && /* protect against common user error of
if (slave_skip_counter && /* protect against common user error of
setting the counter to 1 instead of 2
while recovering from an failed
auto-increment insert */
......@@ -1026,7 +1035,7 @@ static int exec_event(THD* thd, NET* net, MASTER_INFO* mi, int event_len)
thd->server_id = ev->server_id; // use the original server id for logging
thd->set_time(); // time the query
if(!thd->log_seq)
if (!thd->log_seq)
thd->log_seq = ev->log_seq;
if (!ev->when)
ev->when = time(NULL);
......@@ -1050,7 +1059,7 @@ This may also be a network problem, or just a bug in the master or slave code.\
pthread_handler_decl(handle_slave,arg __attribute__((unused)))
{
#ifndef DBUG_OFF
slave_begin:
slave_begin:
#endif
THD *thd; // needs to be first for thread_stack
MYSQL *mysql = NULL ;
......@@ -1065,12 +1074,12 @@ pthread_handler_decl(handle_slave,arg __attribute__((unused)))
pthread_exit((void*)1);
}
if(slave_running)
{
pthread_cond_broadcast(&COND_slave_start);
pthread_mutex_unlock(&LOCK_slave);
pthread_exit((void*)1); // safety just in case
}
if (slave_running)
{
pthread_cond_broadcast(&COND_slave_start);
pthread_mutex_unlock(&LOCK_slave);
pthread_exit((void*)1); // safety just in case
}
slave_running = 1;
abort_slave = 0;
#ifndef DBUG_OFF
......@@ -1090,10 +1099,10 @@ pthread_handler_decl(handle_slave,arg __attribute__((unused)))
pthread_detach_this_thread();
if (init_slave_thread(thd) || init_master_info(&glob_mi))
{
sql_print_error("Failed during slave thread initialization");
goto err;
}
{
sql_print_error("Failed during slave thread initialization");
goto err;
}
thd->thread_stack = (char*)&thd; // remember where our stack is
thd->temporary_tables = save_temporary_tables; // restore temp tables
threads.append(thd);
......@@ -1116,11 +1125,11 @@ pthread_handler_decl(handle_slave,arg __attribute__((unused)))
#endif
// we can get killed during safe_connect
if (!safe_connect(thd, mysql, &glob_mi))
sql_print_error("Slave: connected to master '%s@%s:%d',\
sql_print_error("Slave: connected to master '%s@%s:%d',\
replication started in log '%s' at position %s", glob_mi.user,
glob_mi.host, glob_mi.port,
RPL_LOG_NAME,
llstr(glob_mi.pos,llbuff));
glob_mi.host, glob_mi.port,
RPL_LOG_NAME,
llstr(glob_mi.pos,llbuff));
else
{
sql_print_error("Slave thread killed while connecting to master");
......@@ -1147,154 +1156,154 @@ connected:
while (!slave_killed(thd))
{
thd->proc_info = "Requesting binlog dump";
if(request_dump(mysql, &glob_mi))
{
sql_print_error("Failed on request_dump()");
if(slave_killed(thd))
{
sql_print_error("Slave thread killed while requesting master \
thd->proc_info = "Requesting binlog dump";
if (request_dump(mysql, &glob_mi))
{
sql_print_error("Failed on request_dump()");
if (slave_killed(thd))
{
sql_print_error("Slave thread killed while requesting master \
dump");
goto err;
}
thd->proc_info = "Waiiting to reconnect after a failed dump request";
if(mysql->net.vio)
vio_close(mysql->net.vio);
// first time retry immediately, assuming that we can recover
// right away - if first time fails, sleep between re-tries
// hopefuly the admin can fix the problem sometime
if(retried_once)
safe_sleep(thd, glob_mi.connect_retry);
else
retried_once = 1;
if(slave_killed(thd))
{
sql_print_error("Slave thread killed while retrying master \
goto err;
}
thd->proc_info = "Waiiting to reconnect after a failed dump request";
if (mysql->net.vio)
vio_close(mysql->net.vio);
// first time retry immediately, assuming that we can recover
// right away - if first time fails, sleep between re-tries
// hopefuly the admin can fix the problem sometime
if (retried_once)
safe_sleep(thd, glob_mi.connect_retry);
else
retried_once = 1;
if (slave_killed(thd))
{
sql_print_error("Slave thread killed while retrying master \
dump");
goto err;
}
goto err;
}
thd->proc_info = "Reconnecting after a failed dump request";
last_failed_pos=glob_mi.pos;
sql_print_error("Slave: failed dump request, reconnecting to \
thd->proc_info = "Reconnecting after a failed dump request";
last_failed_pos=glob_mi.pos;
sql_print_error("Slave: failed dump request, reconnecting to \
try again, log '%s' at postion %s", RPL_LOG_NAME,
llstr(last_failed_pos,llbuff));
if(safe_reconnect(thd, mysql, &glob_mi) || slave_killed(thd))
{
sql_print_error("Slave thread killed during or after reconnect");
goto err;
}
goto connected;
}
llstr(last_failed_pos,llbuff));
if (safe_reconnect(thd, mysql, &glob_mi) || slave_killed(thd))
{
sql_print_error("Slave thread killed during or after reconnect");
goto err;
}
goto connected;
}
while(!slave_killed(thd))
while(!slave_killed(thd))
{
thd->proc_info = "Reading master update";
ulong event_len = read_event(mysql, &glob_mi);
if (slave_killed(thd))
{
sql_print_error("Slave thread killed while reading event");
goto err;
}
if (event_len == packet_error)
{
if (mc_mysql_errno(mysql) == ER_NET_PACKET_TOO_LARGE)
{
thd->proc_info = "Reading master update";
ulong event_len = read_event(mysql, &glob_mi);
if(slave_killed(thd))
{
sql_print_error("Slave thread killed while reading event");
goto err;
}
if (event_len == packet_error)
{
if(mc_mysql_errno(mysql) == ER_NET_PACKET_TOO_LARGE)
{
sql_print_error("Log entry on master is longer than \
sql_print_error("Log entry on master is longer than \
max_allowed_packet on slave. Slave thread will be aborted. If the entry is \
really supposed to be that long, restart the server with a higher value of \
max_allowed_packet. The current value is %ld", max_allowed_packet);
goto err;
}
thd->proc_info = "Waiting to reconnect after a failed read";
if(mysql->net.vio)
vio_close(mysql->net.vio);
if(retried_once) // punish repeat offender with sleep
safe_sleep(thd, glob_mi.connect_retry);
else
retried_once = 1;
if(slave_killed(thd))
{
sql_print_error("Slave thread killed while waiting to \
goto err;
}
thd->proc_info = "Waiting to reconnect after a failed read";
if (mysql->net.vio)
vio_close(mysql->net.vio);
if (retried_once) // punish repeat offender with sleep
safe_sleep(thd, glob_mi.connect_retry);
else
retried_once = 1;
if (slave_killed(thd))
{
sql_print_error("Slave thread killed while waiting to \
reconnect after a failed read");
goto err;
}
thd->proc_info = "Reconnecting after a failed read";
last_failed_pos= glob_mi.pos;
sql_print_error("Slave: Failed reading log event, \
goto err;
}
thd->proc_info = "Reconnecting after a failed read";
last_failed_pos= glob_mi.pos;
sql_print_error("Slave: Failed reading log event, \
reconnecting to retry, log '%s' position %s", RPL_LOG_NAME,
llstr(last_failed_pos, llbuff));
if(safe_reconnect(thd, mysql, &glob_mi) || slave_killed(thd))
{
sql_print_error("Slave thread killed during or after a \
llstr(last_failed_pos, llbuff));
if (safe_reconnect(thd, mysql, &glob_mi) || slave_killed(thd))
{
sql_print_error("Slave thread killed during or after a \
reconnect done to recover from failed read");
goto err;
}
goto err;
}
goto connected;
} // if(event_len == packet_error)
goto connected;
} // if (event_len == packet_error)
thd->proc_info = "Processing master log event";
if(exec_event(thd, &mysql->net, &glob_mi, event_len))
{
sql_print_error("\
thd->proc_info = "Processing master log event";
if (exec_event(thd, &mysql->net, &glob_mi, event_len))
{
sql_print_error("\
Error running query, slave aborted. Fix the problem, and re-start \
the slave thread with \"mysqladmin start-slave\". We stopped at log \
'%s' position %s",
RPL_LOG_NAME, llstr(glob_mi.pos, llbuff));
goto err;
// there was an error running the query
// abort the slave thread, when the problem is fixed, the user
// should restart the slave with mysqladmin start-slave
}
RPL_LOG_NAME, llstr(glob_mi.pos, llbuff));
goto err;
// there was an error running the query
// abort the slave thread, when the problem is fixed, the user
// should restart the slave with mysqladmin start-slave
}
#ifndef DBUG_OFF
if(abort_slave_event_count && !--events_till_abort)
{
sql_print_error("Slave: debugging abort");
goto err;
}
if (abort_slave_event_count && !--events_till_abort)
{
sql_print_error("Slave: debugging abort");
goto err;
}
#endif
// successful exec with offset advance,
// the slave repents and his sins are forgiven!
if(glob_mi.pos > last_failed_pos)
{
retried_once = 0;
// successful exec with offset advance,
// the slave repents and his sins are forgiven!
if (glob_mi.pos > last_failed_pos)
{
retried_once = 0;
#ifndef DBUG_OFF
stuck_count = 0;
stuck_count = 0;
#endif
}
}
#ifndef DBUG_OFF
else
{
// show a little mercy, allow slave to read one more event
// before cutting him off - otherwise he gets stuck
// on Intvar events, since they do not advance the offset
// immediately
if (++stuck_count > 2)
events_till_disconnect++;
}
else
{
// show a little mercy, allow slave to read one more event
// before cutting him off - otherwise he gets stuck
// on Intvar events, since they do not advance the offset
// immediately
if (++stuck_count > 2)
events_till_disconnect++;
}
#endif
} // while(!slave_killed(thd)) - read/exec loop
} // while(!slave_killed(thd)) - read/exec loop
} // while(!slave_killed(thd)) - slave loop
// error = 0;
err:
err:
// print the current replication position
sql_print_error("Slave thread exiting, replication stopped in log '%s' at \
position %s",
RPL_LOG_NAME, llstr(glob_mi.pos,llbuff));
thd->query = thd->db = 0; // extra safety
if(mysql)
mc_mysql_close(mysql);
if (mysql)
mc_mysql_close(mysql);
thd->proc_info = "Waiting for slave mutex on exit";
pthread_mutex_lock(&LOCK_slave);
slave_running = 0;
......@@ -1309,7 +1318,7 @@ position %s",
delete thd;
my_thread_end();
#ifndef DBUG_OFF
if(abort_slave_event_count && !events_till_abort)
if (abort_slave_event_count && !events_till_abort)
goto slave_begin;
#endif
pthread_exit(0);
......@@ -1346,7 +1355,7 @@ static int connect_to_master(THD* thd, MYSQL* mysql, MASTER_INFO* mi,
events_till_disconnect = disconnect_slave_event_count;
#endif
while (!(slave_was_killed = slave_killed(thd)) &&
(reconnect ? mc_mysql_reconnect(mysql) :
(reconnect ? mc_mysql_reconnect(mysql) != 0 :
!mc_mysql_connect(mysql, mi->host, mi->user, mi->password, 0,
mi->port, 0, 0)))
{
......
......@@ -286,13 +286,8 @@ If join_results allocated new block(s) then we need call pack_cache again.
#if defined(EXTRA_DEBUG) && !defined(DBUG_OFF)
#define MUTEX_LOCK(M) { DBUG_PRINT("lock", ("mutex lock 0x%lx", (ulong)(M))); \
pthread_mutex_lock(M);}
#define SEM_LOCK(M) { int val = 0; sem_getvalue (M, &val); \
DBUG_PRINT("lock", ("sem lock 0x%lx (%d)", (ulong)(M), val)); \
sem_wait(M); DBUG_PRINT("lock", ("sem lock ok")); }
#define MUTEX_UNLOCK(M) {DBUG_PRINT("lock", ("mutex unlock 0x%lx",\
(ulong)(M))); pthread_mutex_unlock(M);}
#define SEM_UNLOCK(M) {DBUG_PRINT("lock", ("sem unlock 0x%lx", (ulong)(M))); \
sem_post(M); DBUG_PRINT("lock", ("sem unlock ok")); }
#define STRUCT_LOCK(M) {DBUG_PRINT("lock", ("%d struct lock...",__LINE__)); \
pthread_mutex_lock(M);DBUG_PRINT("lock", ("struct lock OK"));}
#define STRUCT_UNLOCK(M) { \
......@@ -313,9 +308,7 @@ If join_results allocated new block(s) then we need call pack_cache again.
#define DUMP(C) DBUG_EXECUTE("qcache", {(C)->queries_dump();(C)->tables_dump();})
#else
#define MUTEX_LOCK(M) pthread_mutex_lock(M)
#define SEM_LOCK(M) sem_wait(M)
#define MUTEX_UNLOCK(M) pthread_mutex_unlock(M)
#define SEM_UNLOCK(M) sem_post(M)
#define STRUCT_LOCK(M) pthread_mutex_lock(M)
#define STRUCT_UNLOCK(M) pthread_mutex_unlock(M)
#define BLOCK_LOCK_WR(B) B->query()->lock_writing()
......@@ -332,7 +325,7 @@ If join_results allocated new block(s) then we need call pack_cache again.
inline Query_cache_block * Query_cache_block_table::block()
{
return (Query_cache_block *)(((byte*)this) -
sizeof(Query_cache_block_table)*n -
ALIGN_SIZE(sizeof(Query_cache_block_table)*n) -
ALIGN_SIZE(sizeof(Query_cache_block)));
};
......@@ -432,7 +425,7 @@ void Query_cache_query::init_n_lock()
{
DBUG_ENTER("Query_cache_query::init_n_lock");
res=0; wri = 0; len = 0;
sem_init(&lock, 0, 1);
pthread_cond_init(&lock, NULL);
pthread_mutex_init(&clients_guard,MY_MUTEX_INIT_FAST);
clients = 0;
lock_writing();
......@@ -445,14 +438,14 @@ void Query_cache_query::init_n_lock()
void Query_cache_query::unlock_n_destroy()
{
DBUG_ENTER("Query_cache_query::unlock_n_destroy");
DBUG_PRINT("qcache", ("destroyed & unlocked query for block 0x%lx",
((byte*)this)-ALIGN_SIZE(sizeof(Query_cache_block))));
/*
The following call is not needed on system where one can destroy an
active semaphore
*/
this->unlock_writing();
DBUG_PRINT("qcache", ("destroyed & unlocked query for block 0x%lx",
((byte*)this)-ALIGN_SIZE(sizeof(Query_cache_block))));
sem_destroy(&lock);
pthread_cond_destroy(&lock);
pthread_mutex_destroy(&clients_guard);
DBUG_VOID_RETURN;
}
......@@ -468,7 +461,9 @@ void Query_cache_query::unlock_n_destroy()
void Query_cache_query::lock_writing()
{
SEM_LOCK(&lock);
MUTEX_LOCK(&clients_guard);
while (clients != 0)
pthread_cond_wait(&lock,&clients_guard);
}
......@@ -482,11 +477,17 @@ void Query_cache_query::lock_writing()
my_bool Query_cache_query::try_lock_writing()
{
DBUG_ENTER("Query_cache_block::try_lock_writing");
if (sem_trywait(&lock)!=0 || clients != 0)
if (pthread_mutex_trylock(&clients_guard))
{
DBUG_PRINT("qcache", ("can't lock mutex"));
DBUG_RETURN(0);
}
if (clients != 0)
{
DBUG_PRINT("info", ("already locked (r)"));
MUTEX_UNLOCK(&clients_guard);
DBUG_RETURN(0);
}
DBUG_PRINT("qcache", ("mutex 'lock' 0x%lx locked", (ulong) &lock));
DBUG_RETURN(1);
}
......@@ -495,15 +496,14 @@ my_bool Query_cache_query::try_lock_writing()
void Query_cache_query::lock_reading()
{
MUTEX_LOCK(&clients_guard);
if (!clients++)
SEM_LOCK(&lock);
clients++;
MUTEX_UNLOCK(&clients_guard);
}
void Query_cache_query::unlock_writing()
{
SEM_UNLOCK(&lock);
MUTEX_UNLOCK(&clients_guard);
}
......@@ -511,7 +511,7 @@ void Query_cache_query::unlock_reading()
{
MUTEX_LOCK(&clients_guard);
if (--clients == 0)
SEM_UNLOCK(&lock);
pthread_cond_broadcast(&lock);
MUTEX_UNLOCK(&clients_guard);
}
......@@ -677,6 +677,7 @@ Query_cache::Query_cache(ulong query_cache_limit,
:query_cache_size(0),
query_cache_limit(query_cache_limit),
queries_in_cache(0), hits(0), inserts(0), refused(0),
total_blocks(0),
min_allocation_unit(min_allocation_unit),
min_result_data_size(min_result_data_size),
def_query_hash_size(def_query_hash_size),
......@@ -747,7 +748,7 @@ void Query_cache::store_query(THD *thd, TABLE_LIST *tables_used)
/* Check if another thread is processing the same query? */
thd->query[thd->query_length] = (char) flags;
Query_cache_block *competitor = (Query_cache_block *)
hash_search(&queries, thd->query, thd->query_length+1);
hash_search(&queries, (byte*) thd->query, thd->query_length+1);
DBUG_PRINT("qcache", ("competitor 0x%lx, flags %x", (ulong) competitor,
flags));
if (competitor == 0)
......@@ -779,7 +780,7 @@ void Query_cache::store_query(THD *thd, TABLE_LIST *tables_used)
{
refused++;
DBUG_PRINT("warning", ("tables list including failed"));
hash_delete(&queries, (char *) query_block);
hash_delete(&queries, (byte *) query_block);
header->unlock_n_destroy();
free_memory_block(query_block);
STRUCT_UNLOCK(&structure_guard_mutex);
......@@ -790,7 +791,7 @@ void Query_cache::store_query(THD *thd, TABLE_LIST *tables_used)
queries_in_cache++;
STRUCT_UNLOCK(&structure_guard_mutex);
net->query_cache_query = (gptr) query_block;
net->query_cache_query= (gptr) query_block;
header->writer(net);
// init_n_lock make query block locked
BLOCK_UNLOCK_WR(query_block);
......@@ -890,7 +891,7 @@ Query_cache::send_result_to_client(THD *thd, char *sql, uint query_length)
}
sql[query_length] = (char) flags;
query_block = (Query_cache_block *) hash_search(&queries, sql,
query_block = (Query_cache_block *) hash_search(&queries, (byte*) sql,
query_length+1);
sql[query_length] = '\0';
......@@ -1026,20 +1027,11 @@ void Query_cache::invalidate(Query_cache_table::query_cache_table_type type)
{
STRUCT_LOCK(&structure_guard_mutex);
DUMP(this);
if (query_cache_size > 0 && tables_blocks[type] != 0)
if (query_cache_size > 0)
{
Query_cache_block *table_block = tables_blocks[type];
do
{
/* Store next block address defore deleting the current block */
Query_cache_block *next = table_block->next;
invalidate_table(table_block);
#ifdef TO_BE_DELETED
if (next == table_block) // End of list
break;
#endif
table_block = next;
} while (table_block != tables_blocks[type]);
/* invalidate_table reduce list while only root of list remain */
while (tables_blocks[type] != 0)
invalidate_table(tables_blocks[type]);
}
STRUCT_UNLOCK(&structure_guard_mutex);
}
......@@ -1060,27 +1052,11 @@ void Query_cache::invalidate(char *db)
if (query_cache_size > 0)
{
DUMP(this);
int i = 0;
for(; i < (int) Query_cache_table::TYPES_NUMBER; i++)
for (int i=0 ; i < (int) Query_cache_table::TYPES_NUMBER; i++)
{
if (tables_blocks[i] != 0) // Cache not empty
{
Query_cache_block *table_block = tables_blocks[i];
do
{
/*
Store next block address defore deletetion of current block
*/
Query_cache_block *next = table_block->next;
invalidate_table_in_db(table_block, db);
#ifdef TO_BE_DELETED
if (table_block == next)
break;
#endif
table_block = next;
} while (table_block != tables_blocks[i]);
}
/* invalidate_table reduce list while only root of list remain */
while (tables_blocks[i] !=0 )
invalidate_table(tables_blocks[i]);
}
}
STRUCT_UNLOCK(&structure_guard_mutex);
......@@ -1101,7 +1077,8 @@ void Query_cache::invalidate_by_MyISAM_filename(const char *filename)
if (query_cache_size > 0) // Safety if cache removed
{
Query_cache_block *table_block;
if ((table_block = (Query_cache_block*) hash_search(&tables, key,
if ((table_block = (Query_cache_block*) hash_search(&tables,
(byte*) key,
key_length)))
invalidate_table(table_block);
}
......@@ -1243,6 +1220,7 @@ ulong Query_cache::init_cache()
first_block = (Query_cache_block *) (cache + additional_data_size);
first_block->init(query_cache_size);
total_blocks++;
first_block->pnext=first_block->pprev=first_block;
first_block->next=first_block->prev=first_block;
......@@ -1290,8 +1268,8 @@ ulong Query_cache::init_cache()
size += inc;
}
}
bins[mem_bin_num].number= 1; // For easy end test
free_memory= 0;
bins[mem_bin_num].number = 1; // For easy end test in get_free_block
free_memory = free_memory_blocks = 0;
insert_into_free_memory_list(first_block);
DUMP(this);
......@@ -1348,6 +1326,7 @@ void Query_cache::free_cache(my_bool destruction)
/* Becasue we did a flush, all cache memory must be in one this block */
bins[0].free_blocks->destroy();
total_blocks--;
DBUG_PRINT("qcache", ("free memory %lu (should be %lu)",
free_memory , query_cache_size));
my_free((gptr) cache, MYF(MY_ALLOW_ZERO_PTR));
......@@ -1738,7 +1717,7 @@ void Query_cache::invalidate_table(TABLE_LIST *table_list)
// We don't store temporary tables => no key_length+=4 ...
if ((table_block = (Query_cache_block*)
hash_search(&tables,key,key_length)))
hash_search(&tables,(byte*) key,key_length)))
invalidate_table(table_block);
}
}
......@@ -1747,7 +1726,7 @@ void Query_cache::invalidate_table(TABLE *table)
{
Query_cache_block *table_block;
if ((table_block = ((Query_cache_block*)
hash_search(&tables, table->table_cache_key,
hash_search(&tables, (byte*) table->table_cache_key,
table->key_length))))
invalidate_table(table_block);
}
......@@ -1856,7 +1835,8 @@ Query_cache::insert_table(uint key_len, char *key,
(ulong)node, key_len));
Query_cache_block *table_block = ((Query_cache_block *)
hash_search(&tables, key, key_len));
hash_search(&tables, (byte*) key,
key_len));
if (table_block == 0)
{
......@@ -1905,6 +1885,7 @@ Query_cache::insert_table(uint key_len, char *key,
void Query_cache::unlink_table(Query_cache_block_table *node)
{
DBUG_ENTER("Query_cache::unlink_table");
node->prev->next = node->next;
node->next->prev = node->prev;
Query_cache_block_table *neighbour = node->next;
......@@ -1917,6 +1898,7 @@ void Query_cache::unlink_table(Query_cache_block_table *node)
hash_delete(&tables,(byte *) table_block);
free_memory_block(table_block);
}
DBUG_VOID_RETURN;
}
/*****************************************************************************
......@@ -2038,6 +2020,7 @@ void Query_cache::split_block(Query_cache_block *block,ulong len)
Query_cache_block *new_block = (Query_cache_block*)(((byte*) block)+len);
new_block->init(block->length - len);
total_blocks++;
block->length=len;
new_block->pnext = block->pnext;
block->pnext = new_block;
......@@ -2068,6 +2051,7 @@ Query_cache::join_free_blocks(Query_cache_block *first_block,
// May be was not free block
second_block->used=0;
second_block->destroy();
total_blocks--;
first_block->length += second_block->length;
first_block->pnext = second_block->pnext;
......@@ -2090,6 +2074,7 @@ my_bool Query_cache::append_next_free_block(Query_cache_block *block,
ulong old_len = block->length;
exclude_from_free_memory_list(next_block);
next_block->destroy();
total_blocks--;
block->length += next_block->length;
block->pnext = next_block->pnext;
......@@ -2112,6 +2097,7 @@ void Query_cache::exclude_from_free_memory_list(Query_cache_block *free_block)
double_linked_list_exclude(free_block, &bin->free_blocks);
bin->number--;
free_memory-=free_block->length;
free_memory_blocks--;
DBUG_PRINT("qcache",("exclude block 0x%lx, bin 0x%lx", (ulong) free_block,
(ulong) bin));
DBUG_VOID_RETURN;
......@@ -2207,6 +2193,7 @@ void Query_cache::insert_into_free_memory_sorted_list(Query_cache_block *
point->next = new_block;
}
free_memory+=new_block->length;
free_memory_blocks++;
DBUG_VOID_RETURN;
}
......@@ -2222,11 +2209,11 @@ Query_cache::double_linked_list_simple_include(Query_cache_block *point,
*list_pointer=point->next=point->prev=point;
else
{
// insert to and of list
point->next = (*list_pointer);
point->prev = (*list_pointer)->prev;
point->prev->next = point;
(*list_pointer)->prev = point;
(*list_pointer) = point;
}
DBUG_VOID_RETURN;
}
......@@ -2360,6 +2347,7 @@ void Query_cache::pack_cache()
{
Query_cache_block *new_block = (Query_cache_block *) border;
new_block->init(gap);
total_blocks++;
new_block->pnext = before->pnext;
before->pnext = new_block;
new_block->pprev = before;
......@@ -2395,6 +2383,7 @@ my_bool Query_cache::move_by_type(byte **border,
block->pprev->pnext=block->pnext;
block->pnext->pprev=block->pprev;
block->destroy();
total_blocks--;
DBUG_PRINT("qcache", ("added to gap (%lu)", *gap));
break;
}
......@@ -2416,7 +2405,7 @@ my_bool Query_cache::move_by_type(byte **border,
byte *key;
uint key_length;
key=query_cache_table_get_key((byte*) block, &key_length,0);
hash_search(&tables, key, key_length);
hash_search(&tables, (byte*) key, key_length);
block->destroy();
new_block->init(len);
......@@ -2432,8 +2421,10 @@ my_bool Query_cache::move_by_type(byte **border,
nlist_root->n = 0;
nlist_root->next = (tnext == list_root ? nlist_root : tnext);
nlist_root->prev = (tprev == list_root ? nlist_root: tnext);
tnext->prev = list_root;
tprev->next = list_root;
tnext->prev = nlist_root;
tprev->next = nlist_root;
for (;tnext != nlist_root; tnext=tnext->next)
tnext->parent = new_block->table();
*border += len;
*before = new_block;
/* Fix hash to point at moved block */
......@@ -2462,7 +2453,7 @@ my_bool Query_cache::move_by_type(byte **border,
byte *key;
uint key_length;
key=query_cache_query_get_key((byte*) block, &key_length,0);
hash_search(&queries, key, key_length);
hash_search(&queries, (byte*) key, key_length);
memcpy((char*) new_block->table(0), (char*) block->table(0),
ALIGN_SIZE(n_tables*sizeof(Query_cache_block_table)));
......@@ -2654,7 +2645,6 @@ my_bool Query_cache::join_results(ulong join_limit)
uint Query_cache::filename_2_table_key (char *key, const char *path)
{
char tablename[FN_REFLEN+2], *filename, *dbname;
Query_cache_block *table_block;
uint db_length;
DBUG_ENTER("Query_cache::filename_2_table_key");
......@@ -2666,7 +2656,7 @@ uint Query_cache::filename_2_table_key (char *key, const char *path)
filename= tablename + dirname_length(tablename + 2) + 2;
/* Find start of databasename */
for (dbname= filename - 2 ; dbname[-1] != FN_LIBCHAR ; dbname--) ;
db_length= (filename - dbname) - 1;
db_length= (filename - dbname) - 1;
DBUG_PRINT("qcache", ("table '%-.*s.%s'", db_length, dbname, filename));
DBUG_RETURN((uint) (strmov(strmake(key, dbname, db_length) + 1,
......
......@@ -17,8 +17,6 @@
#ifndef _SQL_CACHE_H
#define _SQL_CACHE_H
#include <semaphore.h>
/* Query cache */
/*
......@@ -105,7 +103,7 @@ struct Query_cache_query
Query_cache_block *res;
NET *wri;
ulong len;
sem_t lock; // R/W lock of block
pthread_cond_t lock; // R/W lock of block
pthread_mutex_t clients_guard;
uint clients;
......@@ -220,7 +218,8 @@ public:
/* Info */
ulong query_cache_size, query_cache_limit;
/* statistics */
ulong free_memory, queries_in_cache, hits, inserts, refused;
ulong free_memory, queries_in_cache, hits, inserts, refused,
free_memory_blocks, total_blocks;
protected:
/*
......
......@@ -1023,11 +1023,11 @@ err:
int log_loaded_block(IO_CACHE* file)
{
LOAD_FILE_INFO* lf_info;
uint block_len ;
ulong block_len ;
/* file->request_pos contains position where we started last read */
char* buffer = (char*) file->request_pos;
if (!(block_len = file->read_end - buffer))
byte *buffer = file->request_pos;
if (!(block_len = (ulong) (file->read_end - buffer)))
return 0;
lf_info = (LOAD_FILE_INFO*)file->arg;
if (lf_info->last_pos_in_file != HA_POS_ERROR &&
......@@ -1036,14 +1036,14 @@ int log_loaded_block(IO_CACHE* file)
lf_info->last_pos_in_file = file->pos_in_file;
if (lf_info->wrote_create_file)
{
Append_block_log_event a(lf_info->thd, buffer, block_len);
Append_block_log_event a(lf_info->thd, (char*) buffer, block_len);
mysql_bin_log.write(&a);
}
else
{
Create_file_log_event c(lf_info->thd,lf_info->ex,lf_info->db,
lf_info->table_name, *lf_info->fields,
lf_info->handle_dup, buffer,
lf_info->handle_dup, (char*) buffer,
block_len);
mysql_bin_log.write(&c);
lf_info->wrote_create_file = 1;
......
......@@ -3172,11 +3172,9 @@ option_value:
}
query_cache_type:
'0' { current_thd->query_cache_type = 0; }
NUM { current_thd->query_cache_type = set_zone(atoi($1.str),0,3); }
| OFF { current_thd->query_cache_type = 0; }
| '1' { current_thd->query_cache_type = 1; }
| ON { current_thd->query_cache_type = 1; }
| '2' { current_thd->query_cache_type = 2; }
| DEMAND_SYM { current_thd->query_cache_type = 2; }
text_or_password:
......
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