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). ...@@ -18506,9 +18506,12 @@ If this is 0, the query cache is disabled (default).
@item @code{query_cache_startup_type} @item @code{query_cache_startup_type}
This may be set (only numeric) to This may be set (only numeric) to
0 (OFF, don't cache or retrieve results), @multitable @columnfractions .1 .2 .7
1 (ON, cache all results except @code{SELECT SQL_NO_CACHE ...} queries) or @item @strong{Value} @tab @strong{Alias} @tab @strong{Comment}
2 (DEMAND, cache only @code{SELECT SQL_CACHE ...} queries). @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} @item @code{safe_show_databases}
Don't show databases for which the user doesn't have any database or 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 ...@@ -34,6 +34,7 @@ see the @code{crash-me} web page at
@node Compare mSQL, Compare PostgreSQL, Comparisons, Comparisons @node Compare mSQL, Compare PostgreSQL, Comparisons, Comparisons
@subsection How MySQL Compares to @code{mSQL} @subsection How MySQL Compares to @code{mSQL}
@cindex mSQL, MySQL vs mSQL, overview
@table @strong @table @strong
@item Performance @item Performance
...@@ -301,7 +302,7 @@ multiple connections to the server from the same process. ...@@ -301,7 +302,7 @@ multiple connections to the server from the same process.
@subsubsection How @code{mSQL} and MySQL Client/Server Communications Protocols Differ @subsubsection How @code{mSQL} and MySQL Client/Server Communications Protocols Differ
@cindex communications protocols @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) There are enough differences that it is impossible (or at least not easy)
to support both. to support both.
...@@ -557,7 +558,6 @@ satisfies your application. If you need raw speed, MySQL is probably your ...@@ -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 best choice. If you need some of the extra features that only PostgreSQL
can offer, you should use @code{PostgreSQL}. can offer, you should use @code{PostgreSQL}.
@cindex PostgreSQL/MySQL, strategies
@menu @menu
* MySQL-PostgreSQL goals:: MySQL and PostgreSQL development strategies * MySQL-PostgreSQL goals:: MySQL and PostgreSQL development strategies
* MySQL-PostgreSQL features:: Featurewise Comparison of MySQL and PostgreSQL * MySQL-PostgreSQL features:: Featurewise Comparison of MySQL and PostgreSQL
...@@ -568,6 +568,7 @@ can offer, you should use @code{PostgreSQL}. ...@@ -568,6 +568,7 @@ can offer, you should use @code{PostgreSQL}.
@node MySQL-PostgreSQL goals, MySQL-PostgreSQL features, Compare PostgreSQL, Compare PostgreSQL @node MySQL-PostgreSQL goals, MySQL-PostgreSQL features, Compare PostgreSQL, Compare PostgreSQL
@subsubsection MySQL and PostgreSQL development strategies @subsubsection MySQL and PostgreSQL development strategies
@cindex PostgreSQL vs. MySQL, strategies
When adding things to MySQL we take pride to do an optimal, definite 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 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 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. ...@@ -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 @node MySQL-PostgreSQL features, MySQL-PostgreSQL benchmarks, MySQL-PostgreSQL goals, Compare PostgreSQL
@subsubsection Featurewise Comparison of MySQL and PostgreSQL @subsubsection Featurewise Comparison of MySQL and PostgreSQL
@cindex PostgreSQL/MySQL, features @cindex PostgreSQL vs. MySQL, features
On the crash-me page On the crash-me page
(@uref{http://www.mysql.com/information/crash-me.php}) (@uref{http://www.mysql.com/information/crash-me.php})
......
...@@ -385,9 +385,9 @@ static void dump_remote_log_entries(const char* logname) ...@@ -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; int old_format;
my_off_t pos = my_b_tell(file); my_off_t pos = my_b_tell(file);
......
...@@ -43,7 +43,7 @@ ...@@ -43,7 +43,7 @@
**********************************************************************/ **********************************************************************/
#define MTEST_VERSION "1.11" #define MTEST_VERSION "1.12"
#include <my_global.h> #include <my_global.h>
#include <mysql_embed.h> #include <mysql_embed.h>
...@@ -138,16 +138,16 @@ MYSQL_RES *last_result=0; ...@@ -138,16 +138,16 @@ MYSQL_RES *last_result=0;
PARSER parser; PARSER parser;
MASTER_POS master_pos; 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; int false_block_depth = 0;
const char* result_file = 0; /* if set, all results are concated and /* if set, all results are concated and compared against this file */
compared against this file*/ const char *result_file = 0;
typedef struct typedef struct
{ {
char* name; char *name;
int name_len; int name_len;
char* str_val; char *str_val;
int str_val_len; int str_val_len;
int int_val; int int_val;
int alloced_len; int alloced_len;
...@@ -158,7 +158,7 @@ typedef struct ...@@ -158,7 +158,7 @@ typedef struct
VAR var_reg[10]; VAR var_reg[10];
/*Perl/shell-like variable registers */ /*Perl/shell-like variable registers */
HASH var_hash; HASH var_hash;
int disable_query_log=0; int disable_query_log=0, disable_result_log=0;
struct connection cons[MAX_CONS]; struct connection cons[MAX_CONS];
struct connection* cur_con, *next_con, *cons_end; struct connection* cur_con, *next_con, *cons_end;
...@@ -181,6 +181,7 @@ Q_PING, Q_EVAL, ...@@ -181,6 +181,7 @@ Q_PING, Q_EVAL,
Q_RPL_PROBE, Q_ENABLE_RPL_PARSE, Q_RPL_PROBE, Q_ENABLE_RPL_PARSE,
Q_DISABLE_RPL_PARSE, Q_EVAL_RESULT, Q_DISABLE_RPL_PARSE, Q_EVAL_RESULT,
Q_ENABLE_QUERY_LOG, Q_DISABLE_QUERY_LOG, 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_SERVER_START, Q_SERVER_STOP,Q_REQUIRE_MANAGER,
Q_UNKNOWN, /* Unknown command. */ Q_UNKNOWN, /* Unknown command. */
Q_COMMENT, /* Comments, ignored. */ Q_COMMENT, /* Comments, ignored. */
...@@ -215,6 +216,7 @@ const char *command_names[] = { ...@@ -215,6 +216,7 @@ const char *command_names[] = {
"rpl_probe", "enable_rpl_parse", "rpl_probe", "enable_rpl_parse",
"disable_rpl_parse", "eval_result", "disable_rpl_parse", "eval_result",
"enable_query_log", "disable_query_log", "enable_query_log", "disable_query_log",
"enable_result_log", "disable_result_log",
"server_start", "server_stop", "server_start", "server_stop",
"require_manager", "require_manager",
0 0
...@@ -224,22 +226,22 @@ TYPELIB command_typelib= {array_elements(command_names),"", ...@@ -224,22 +226,22 @@ TYPELIB command_typelib= {array_elements(command_names),"",
command_names}; command_names};
DYNAMIC_STRING ds_res; DYNAMIC_STRING ds_res;
static void die(const char* fmt, ...); static void die(const char *fmt, ...);
static void init_var_hash(); static void init_var_hash();
static byte* get_var_key(const byte* rec, uint* len, static byte* get_var_key(const byte* rec, uint* len,
my_bool __attribute__((unused)) t); 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); int val_len);
static void var_free(void* v); static void var_free(void* v);
int dyn_string_cmp(DYNAMIC_STRING* ds, const char* fname); int dyn_string_cmp(DYNAMIC_STRING* ds, const char *fname);
void reject_dump(const char* record_file, char* buf, int size); void reject_dump(const char *record_file, char *buf, int size);
int close_connection(struct st_query* q); int close_connection(struct st_query* q);
VAR* var_get(const char* var_name, const char** var_name_end, int raw); 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); int eval_expr(VAR* v, const char *p, const char** p_end);
static int read_server_arguments(const char* name); static int read_server_arguments(const char *name);
/* Definitions for replace */ /* Definitions for replace */
...@@ -259,9 +261,9 @@ static int insert_pointer_name(reg1 POINTER_ARRAY *pa,my_string name); ...@@ -259,9 +261,9 @@ static int insert_pointer_name(reg1 POINTER_ARRAY *pa,my_string name);
void free_pointer_array(POINTER_ARRAY *pa); void free_pointer_array(POINTER_ARRAY *pa);
static int initialize_replace_buffer(void); static int initialize_replace_buffer(void);
static void free_replace_buffer(void); static void free_replace_buffer(void);
static void do_eval(DYNAMIC_STRING* query_eval, const char* query); static void do_eval(DYNAMIC_STRING* query_eval, const char *query);
void str_to_file(const char* fname, char* str, int size); void str_to_file(const char *fname, char *str, int size);
int do_server_op(struct st_query* q,const char* op); int do_server_op(struct st_query* q,const char *op);
struct st_replace *glob_replace; struct st_replace *glob_replace;
static char *out_buff; static char *out_buff;
...@@ -1960,7 +1962,7 @@ int run_query(MYSQL* mysql, struct st_query* q, int flags) ...@@ -1960,7 +1962,7 @@ int run_query(MYSQL* mysql, struct st_query* q, int flags)
int query_len; int query_len;
DBUG_ENTER("run_query"); DBUG_ENTER("run_query");
if(q->type != Q_EVAL) if (q->type != Q_EVAL)
{ {
query = q->query; query = q->query;
query_len = strlen(query); query_len = strlen(query);
...@@ -1973,7 +1975,7 @@ int run_query(MYSQL* mysql, struct st_query* q, int flags) ...@@ -1973,7 +1975,7 @@ int run_query(MYSQL* mysql, struct st_query* q, int flags)
query_len = eval_query.length; query_len = eval_query.length;
} }
if ( q->record_file[0]) if (q->record_file[0])
{ {
init_dynamic_string(&ds_tmp, "", 16384, 65536); init_dynamic_string(&ds_tmp, "", 16384, 65536);
ds = &ds_tmp; ds = &ds_tmp;
...@@ -2060,11 +2062,14 @@ int run_query(MYSQL* mysql, struct st_query* q, int flags) ...@@ -2060,11 +2062,14 @@ int run_query(MYSQL* mysql, struct st_query* q, int flags)
goto end; goto end;
} }
if (!res) goto end; if (!res)
goto end;
if (!disable_result_log)
{
fields = mysql_fetch_fields(res); fields = mysql_fetch_fields(res);
num_fields = mysql_num_fields(res); num_fields = mysql_num_fields(res);
for( i = 0; i < num_fields; i++) for (i = 0; i < num_fields; i++)
{ {
if (i) if (i)
dynstr_append_mem(ds, "\t", 1); dynstr_append_mem(ds, "\t", 1);
...@@ -2073,8 +2078,7 @@ int run_query(MYSQL* mysql, struct st_query* q, int flags) ...@@ -2073,8 +2078,7 @@ int run_query(MYSQL* mysql, struct st_query* q, int flags)
dynstr_append_mem(ds, "\n", 1); dynstr_append_mem(ds, "\n", 1);
while ((row = mysql_fetch_row(res)))
while((row = mysql_fetch_row(res)))
{ {
lengths = mysql_fetch_lengths(res); lengths = mysql_fetch_lengths(res);
for(i = 0; i < num_fields; i++) for(i = 0; i < num_fields; i++)
...@@ -2092,12 +2096,11 @@ int run_query(MYSQL* mysql, struct st_query* q, int flags) ...@@ -2092,12 +2096,11 @@ int run_query(MYSQL* mysql, struct st_query* q, int flags)
dynstr_append_mem(ds, "\t", 1); dynstr_append_mem(ds, "\t", 1);
replace_dynstr_append_mem(ds, val, len); replace_dynstr_append_mem(ds, val, len);
} }
dynstr_append_mem(ds, "\n", 1); dynstr_append_mem(ds, "\n", 1);
} }
if (glob_replace) if (glob_replace)
free_replace(); free_replace();
}
if (record) if (record)
{ {
if (!q->record_file[0] && !result_file) if (!q->record_file[0] && !result_file)
...@@ -2111,7 +2114,8 @@ int run_query(MYSQL* mysql, struct st_query* q, int flags) ...@@ -2111,7 +2114,8 @@ int run_query(MYSQL* mysql, struct st_query* q, int flags)
} }
end: end:
if (res) mysql_free_result(res); if (res)
mysql_free_result(res);
last_result=0; last_result=0;
if (ds == &ds_tmp) if (ds == &ds_tmp)
dynstr_free(&ds_tmp); dynstr_free(&ds_tmp);
...@@ -2292,6 +2296,8 @@ int main(int argc, char** argv) ...@@ -2292,6 +2296,8 @@ int main(int argc, char** argv)
case Q_DISABLE_RPL_PARSE: do_disable_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_ENABLE_QUERY_LOG: disable_query_log=0; break;
case Q_DISABLE_QUERY_LOG: disable_query_log=1; 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_SOURCE: do_source(q); break;
case Q_SLEEP: do_sleep(q); break; case Q_SLEEP: do_sleep(q); break;
case Q_REQUIRE_MANAGER: do_require_manager(q); break; case Q_REQUIRE_MANAGER: do_require_manager(q); break;
......
...@@ -253,6 +253,7 @@ inline double ulonglong2double(ulonglong value) ...@@ -253,6 +253,7 @@ inline double ulonglong2double(ulonglong value)
#define HAVE_STRPBRK #define HAVE_STRPBRK
#define HAVE_STRSTR #define HAVE_STRSTR
#define HAVE_COMPRESS #define HAVE_COMPRESS
#define HAVE_CREATESEMAPHORE
#ifdef NOT_USED #ifdef NOT_USED
#define HAVE_SNPRINTF /* Gave link error */ #define HAVE_SNPRINTF /* Gave link error */
......
...@@ -132,16 +132,17 @@ void pthread_exit(void *a); /* was #define pthread_exit(A) ExitThread(A)*/ ...@@ -132,16 +132,17 @@ void pthread_exit(void *a); /* was #define pthread_exit(A) ExitThread(A)*/
#define pthread_equal(A,B) ((A) == (B)) #define pthread_equal(A,B) ((A) == (B))
#ifdef OS2 #ifdef OS2
int pthread_mutex_init (pthread_mutex_t *, const pthread_mutexattr_t *); extern int pthread_mutex_init (pthread_mutex_t *, const pthread_mutexattr_t *);
int pthread_mutex_lock (pthread_mutex_t *); extern int pthread_mutex_lock (pthread_mutex_t *);
int pthread_mutex_unlock (pthread_mutex_t *); extern int pthread_mutex_unlock (pthread_mutex_t *);
int pthread_mutex_destroy (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 my_pthread_setprio(A,B) DosSetPriority(PRTYS_THREAD,PRTYC_NOCHANGE, B, A)
#define pthread_kill(A,B) raise(B) #define pthread_kill(A,B) raise(B)
#define pthread_exit(A) pthread_dummy() #define pthread_exit(A) pthread_dummy()
#else #else
#define pthread_mutex_init(A,B) InitializeCriticalSection(A) #define pthread_mutex_init(A,B) InitializeCriticalSection(A)
#define pthread_mutex_lock(A) (EnterCriticalSection(A),0) #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_unlock(A) LeaveCriticalSection(A)
#define pthread_mutex_destroy(A) DeleteCriticalSection(A) #define pthread_mutex_destroy(A) DeleteCriticalSection(A)
#define my_pthread_setprio(A,B) SetThreadPriority(GetCurrentThread(), (B)) #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 @@ ...@@ -16,9 +16,7 @@
#ifndef _my_sys_h #ifndef _my_sys_h
#define _my_sys_h #define _my_sys_h
#ifdef __cplusplus C_MODE_START
extern "C" {
#endif
#ifdef HAVE_AIOWAIT #ifdef HAVE_AIOWAIT
#include <sys/asynch.h> /* Used by record-cache */ #include <sys/asynch.h> /* Used by record-cache */
...@@ -649,8 +647,6 @@ extern void sleep(int sec); ...@@ -649,8 +647,6 @@ extern void sleep(int sec);
extern my_bool have_tcpip; /* Is set if tcpip is used */ extern my_bool have_tcpip; /* Is set if tcpip is used */
#endif #endif
#ifdef __cplusplus C_MODE_END
}
#endif
#include "raid.h" #include "raid.h"
#endif /* _my_sys_h */ #endif /* _my_sys_h */
...@@ -2397,6 +2397,8 @@ mysql_fetch_row(MYSQL_RES *res) ...@@ -2397,6 +2397,8 @@ mysql_fetch_row(MYSQL_RES *res)
DBUG_PRINT("info",("end of data")); DBUG_PRINT("info",("end of data"));
res->eof=1; res->eof=1;
res->handle->status=MYSQL_STATUS_READY; res->handle->status=MYSQL_STATUS_READY;
/* Don't clear handle in mysql_free_results */
res->handle=0;
} }
} }
DBUG_RETURN((MYSQL_ROW) NULL); DBUG_RETURN((MYSQL_ROW) NULL);
......
...@@ -112,11 +112,13 @@ void _ftb_parse_query(FTB *ftb, byte **start, byte *end, ...@@ -112,11 +112,13 @@ void _ftb_parse_query(FTB *ftb, byte **start, byte *end,
while ((res=ft_get_word(start,end,&w,&param))) while ((res=ft_get_word(start,end,&w,&param)))
{ {
byte r=param.plusminus; 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) { switch (res) {
case 1: /* word found */ case 1: /* word found */
ftbw=(FTB_WORD *)alloc_root(&ftb->mem_root, 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->len=w.len+1;
ftbw->yesno=param.yesno; ftbw->yesno=param.yesno;
ftbw->trunc=param.trunc; /* 0 or 1 */ ftbw->trunc=param.trunc; /* 0 or 1 */
...@@ -216,7 +218,8 @@ FT_INFO * ft_init_boolean_search(MI_INFO *info, uint keynr, byte *query, ...@@ -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*)); ftb->queue.root=(byte **)alloc_root(&ftb->mem_root, (res+1)*sizeof(void*));
reinit_queue(& ftb->queue, res, 0, 0, FTB_WORD_cmp, ftb); reinit_queue(& ftb->queue, res, 0, 0, FTB_WORD_cmp, ftb);
ftbe=(FTB_EXPR *)alloc_root(&ftb->mem_root, sizeof(FTB_EXPR)); 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->up=0;
ftbe->ythresh=0; ftbe->ythresh=0;
ftbe->docid=HA_POS_ERROR; ftbe->docid=HA_POS_ERROR;
...@@ -236,7 +239,8 @@ void _ftb_climb_the_tree(FTB_WORD *ftbw, my_off_t curdoc) ...@@ -236,7 +239,8 @@ void _ftb_climb_the_tree(FTB_WORD *ftbw, my_off_t curdoc)
{ {
if (ftbe->docid != 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; ftbe->docid=curdoc;
} }
if (ftbe->nos) if (ftbe->nos)
...@@ -373,7 +377,8 @@ float ft_boolean_find_relevance(FT_INFO *ftb, byte *record, uint length) ...@@ -373,7 +377,8 @@ float ft_boolean_find_relevance(FT_INFO *ftb, byte *record, uint length)
{ {
if (ftbe->docid != HA_POS_ERROR) 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; ftbe->docid=HA_POS_ERROR;
} }
else else
......
...@@ -248,7 +248,8 @@ int ft_nlq_read_next(FT_INFO *handler, char *record) ...@@ -248,7 +248,8 @@ int ft_nlq_read_next(FT_INFO *handler, char *record)
} }
float ft_nlq_find_relevance(FT_INFO *handler, 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; int a,b,c;
FT_DOC *docs=handler->doc; FT_DOC *docs=handler->doc;
...@@ -267,7 +268,7 @@ float ft_nlq_find_relevance(FT_INFO *handler, ...@@ -267,7 +268,7 @@ float ft_nlq_find_relevance(FT_INFO *handler,
a=c; a=c;
} }
if (docs[a].dpos == docid) if (docs[a].dpos == docid)
return docs[a].weight; return (float) docs[a].weight;
else else
return 0.0; return 0.0;
} }
...@@ -279,7 +280,7 @@ void ft_nlq_close_search(FT_INFO *handler) ...@@ -279,7 +280,7 @@ void ft_nlq_close_search(FT_INFO *handler)
float ft_nlq_get_relevance(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) void ft_nlq_reinit_search(FT_INFO *handler)
......
...@@ -19,6 +19,7 @@ ...@@ -19,6 +19,7 @@
/* functions to work with full-text indices */ /* functions to work with full-text indices */
#include "ftdefs.h" #include "ftdefs.h"
#include <math.h>
/************************************************************** /**************************************************************
This is to make ft-code to ignore keyseg.length at all * 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, ...@@ -186,7 +187,7 @@ int _mi_ft_update(MI_INFO *info, uint keynr, byte *keybuf,
cmp=_mi_compare_text(default_charset_info, cmp=_mi_compare_text(default_charset_info,
(uchar*) old_word->pos,old_word->len, (uchar*) old_word->pos,old_word->len,
(uchar*) new_word->pos,new_word->len,0); (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) if (cmp < 0 || cmp2)
{ {
......
reset query cache; reset query cache;
flush status; flush status;
drop table if exists t1; drop table if exists t1,t2,t3;
create table t1 (a int not null); create table t1 (a int not null);
insert into t1 values (1),(2),(3); insert into t1 values (1),(2),(3);
select * from t1; select * from t1;
...@@ -36,3 +36,265 @@ drop table t1; ...@@ -36,3 +36,265 @@ drop table t1;
show status like "Qcache_queries_in_cache"; show status like "Qcache_queries_in_cache";
Variable_name Value Variable_name Value
Qcache_queries_in_cache 0 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 # Tests with query cache
# #
...@@ -6,7 +8,12 @@ ...@@ -6,7 +8,12 @@
reset query cache; reset query cache;
flush status; flush status;
drop table if exists t1; drop table if exists t1,t2,t3;
#
# First simple test
#
create table t1 (a int not null); create table t1 (a int not null);
insert into t1 values (1),(2),(3); insert into t1 values (1),(2),(3);
select * from t1; select * from t1;
...@@ -24,3 +31,153 @@ show status like "Qcache_hits"; ...@@ -24,3 +31,153 @@ show status like "Qcache_hits";
drop table t1; drop table t1;
show status like "Qcache_queries_in_cache"; 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\ ...@@ -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 \ mf_iocache.c mf_iocache2.c mf_cache.c mf_tempfile.c \
my_lock.c mf_brkhant.c my_alarm.c \ my_lock.c mf_brkhant.c my_alarm.c \
my_malloc.c my_realloc.c my_once.c mulalloc.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 \ my_error.c errors.c my_div.c my_messnc.c \
mf_format.c mf_same.c mf_dirname.c mf_fn_ext.c \ mf_format.c mf_same.c mf_dirname.c mf_fn_ext.c \
my_symlink.c my_symlink2.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, ...@@ -69,7 +69,7 @@ ha_rows filesort(TABLE *table, SORT_FIELD *sortorder, uint s_length,
{ {
int error; int error;
ulong memavl; ulong memavl;
uint maxbuffer,skr; uint maxbuffer;
BUFFPEK *buffpek; BUFFPEK *buffpek;
ha_rows records; ha_rows records;
uchar **sort_keys; uchar **sort_keys;
...@@ -163,7 +163,7 @@ ha_rows filesort(TABLE *table, SORT_FIELD *sortorder, uint s_length, ...@@ -163,7 +163,7 @@ ha_rows filesort(TABLE *table, SORT_FIELD *sortorder, uint s_length,
&tempfile, selected_records_file)) == &tempfile, selected_records_file)) ==
HA_POS_ERROR) HA_POS_ERROR)
goto err; 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 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) ...@@ -267,7 +267,7 @@ static BUFFPEK *read_buffpek_from_file(IO_CACHE *buffpek_pointers, uint count)
if (tmp) if (tmp)
{ {
if (reinit_io_cache(buffpek_pointers,READ_CACHE,0L,0,0) || 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)); my_free((char*) tmp, MYF(0));
tmp=0; tmp=0;
...@@ -398,10 +398,12 @@ static ha_rows find_all_keys(SORTPARAM *param, SQL_SELECT *select, ...@@ -398,10 +398,12 @@ static ha_rows find_all_keys(SORTPARAM *param, SQL_SELECT *select,
/* Skriver en buffert med nycklar till filen */ /* Skriver en buffert med nycklar till filen */
static int write_keys(SORTPARAM *param, register uchar **sort_keys, uint count, static int
write_keys(SORTPARAM *param, register uchar **sort_keys, uint count,
IO_CACHE *buffpek_pointers, IO_CACHE *tempfile) IO_CACHE *buffpek_pointers, IO_CACHE *tempfile)
{ {
uint sort_length; uint sort_length;
uchar **end;
BUFFPEK buffpek; BUFFPEK buffpek;
DBUG_ENTER("write_keys"); DBUG_ENTER("write_keys");
...@@ -419,10 +421,10 @@ static int write_keys(SORTPARAM *param, register uchar **sort_keys, uint count, ...@@ -419,10 +421,10 @@ static int write_keys(SORTPARAM *param, register uchar **sort_keys, uint count,
if ((ha_rows) count > param->max_rows) if ((ha_rows) count > param->max_rows)
count=(uint) param->max_rows; /* purecov: inspected */ count=(uint) param->max_rows; /* purecov: inspected */
buffpek.count=(ha_rows) count; 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)) if (my_b_write(tempfile,(byte*) *sort_keys,(uint) sort_length))
goto err; goto err;
if (my_b_write(buffpek_pointers, (char*) &buffpek, sizeof(buffpek))) if (my_b_write(buffpek_pointers, (byte*) &buffpek, sizeof(buffpek)))
goto err; goto err;
DBUG_RETURN(0); DBUG_RETURN(0);
......
...@@ -2019,7 +2019,9 @@ void Item_func_match::init_search(bool no_order) ...@@ -2019,7 +2019,9 @@ void Item_func_match::init_search(bool no_order)
} }
ft_handler=table->file->ft_init_ext(mode, key, 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) if (join_key)
{ {
......
...@@ -149,7 +149,7 @@ char* query_table_status(THD *thd,const char *db,const char *table_name); ...@@ -149,7 +149,7 @@ char* query_table_status(THD *thd,const char *db,const char *table_name);
#define SELECT_SMALL_RESULT 8 #define SELECT_SMALL_RESULT 8
#define SELECT_BIG_RESULT 16 #define SELECT_BIG_RESULT 16
#define OPTION_FOUND_ROWS 32 #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 SELECT_NO_JOIN_CACHE 256 /* Intern */
#define OPTION_BIG_TABLES 512 /* for SQL OPTION */ #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); ...@@ -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 SELECT_NO_UNLOCK (QUERY_NO_GOOD_INDEX_USED*2)
#define TMP_TABLE_ALL_COLUMNS (SELECT_NO_UNLOCK*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 #define MODE_REAL_AS_FLOAT 1
......
...@@ -3157,12 +3157,16 @@ struct show_var_st status_vars[]= { ...@@ -3157,12 +3157,16 @@ struct show_var_st status_vars[]= {
{"Open_streams", (char*) &my_stream_opened, SHOW_INT_CONST}, {"Open_streams", (char*) &my_stream_opened, SHOW_INT_CONST},
{"Opened_tables", (char*) &opened_tables, SHOW_LONG}, {"Opened_tables", (char*) &opened_tables, SHOW_LONG},
{"Questions", (char*) 0, SHOW_QUESTION}, {"Questions", (char*) 0, SHOW_QUESTION},
{"Qcache_queries_in_cache", (char*) &query_cache.queries_in_cache, {"Qcache_queries_in_cache", (char*) &query_cache.queries_in_cache, SHOW_LONG_CONST},
SHOW_LONG},
{"Qcache_inserts", (char*) &query_cache.inserts, SHOW_LONG}, {"Qcache_inserts", (char*) &query_cache.inserts, SHOW_LONG},
{"Qcache_hits", (char*) &query_cache.hits, SHOW_LONG}, {"Qcache_hits", (char*) &query_cache.hits, SHOW_LONG},
{"Qcache_not_cached", (char*) &query_cache.refused, 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}, {"Rpl_status", (char*) 0, SHOW_RPL_STATUS},
{"Select_full_join", (char*) &select_full_join_count, SHOW_LONG}, {"Select_full_join", (char*) &select_full_join_count, SHOW_LONG},
{"Select_full_range_join", (char*) &select_full_range_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; ...@@ -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 wild_do_table_inited = 0, wild_ignore_table_inited = 0;
bool table_rules_on = 0; bool table_rules_on = 0;
uint32 slave_skip_counter = 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; 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; int last_slave_errno = 0;
char last_slave_error[MAX_SLAVE_ERRMSG] = ""; char last_slave_error[MAX_SLAVE_ERRMSG] = "";
#ifndef DBUG_OFF #ifndef DBUG_OFF
...@@ -98,11 +101,11 @@ static TABLE_RULE_ENT* find_wild(DYNAMIC_ARRAY *a, const char* key, int len) ...@@ -98,11 +101,11 @@ static TABLE_RULE_ENT* find_wild(DYNAMIC_ARRAY *a, const char* key, int len)
uint i; uint i;
const char* key_end = key + len; const char* key_end = key + len;
for(i = 0; i < a->elements; i++) for (i = 0; i < a->elements; i++)
{ {
TABLE_RULE_ENT* e ; TABLE_RULE_ENT* e ;
get_dynamic(a, (gptr)&e, i); get_dynamic(a, (gptr)&e, i);
if(!wild_case_compare(key, key_end, (const char*)e->db, if (!wild_case_compare(key, key_end, (const char*)e->db,
(const char*)(e->db + e->key_len),'\\')) (const char*)(e->db + e->key_len),'\\'))
return e; return e;
} }
...@@ -114,10 +117,10 @@ int tables_ok(THD* thd, TABLE_LIST* tables) ...@@ -114,10 +117,10 @@ int tables_ok(THD* thd, TABLE_LIST* tables)
{ {
for (; tables; tables = tables->next) for (; tables; tables = tables->next)
{ {
if (!tables->updating)
continue;
char hash_key[2*NAME_LEN+2]; char hash_key[2*NAME_LEN+2];
char* p; char* p;
if (!tables->updating)
continue;
p = strmov(hash_key, tables->db ? tables->db : thd->db); p = strmov(hash_key, tables->db ? tables->db : thd->db);
*p++ = '.'; *p++ = '.';
uint len = strmov(p, tables->real_name) - hash_key ; uint len = strmov(p, tables->real_name) - hash_key ;
...@@ -139,9 +142,10 @@ int tables_ok(THD* thd, TABLE_LIST* tables) ...@@ -139,9 +142,10 @@ int tables_ok(THD* thd, TABLE_LIST* tables)
return 0; return 0;
} }
// if no explicit rule found /*
// and there was a do list, do not replicate. If there was If no explicit rule found and there was a do list, do not replicate.
// no do list, go ahead If there was no do list, go ahead
*/
return !do_table_inited && !wild_do_table_inited; return !do_table_inited && !wild_do_table_inited;
} }
...@@ -149,12 +153,14 @@ int tables_ok(THD* thd, TABLE_LIST* tables) ...@@ -149,12 +153,14 @@ int tables_ok(THD* thd, TABLE_LIST* tables)
int add_table_rule(HASH* h, const char* table_spec) int add_table_rule(HASH* h, const char* table_spec)
{ {
const char* dot = strchr(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 '.' // len is always > 0 because we know the there exists a '.'
uint len = (uint)strlen(table_spec); uint len = (uint)strlen(table_spec);
TABLE_RULE_ENT* e = (TABLE_RULE_ENT*)my_malloc(sizeof(TABLE_RULE_ENT) TABLE_RULE_ENT* e = (TABLE_RULE_ENT*)my_malloc(sizeof(TABLE_RULE_ENT)
+ len, MYF(MY_WME)); + len, MYF(MY_WME));
if(!e) return 1; if (!e)
return 1;
e->db = (char*)e + sizeof(TABLE_RULE_ENT); e->db = (char*)e + sizeof(TABLE_RULE_ENT);
e->tbl_name = e->db + (dot - table_spec) + 1; e->tbl_name = e->db + (dot - table_spec) + 1;
e->key_len = len; e->key_len = len;
...@@ -166,11 +172,12 @@ int add_table_rule(HASH* h, const char* table_spec) ...@@ -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) int add_wild_table_rule(DYNAMIC_ARRAY* a, const char* table_spec)
{ {
const char* dot = strchr(table_spec, '.'); const char* dot = strchr(table_spec, '.');
if(!dot) return 1; if (!dot) return 1;
uint len = (uint)strlen(table_spec); uint len = (uint)strlen(table_spec);
TABLE_RULE_ENT* e = (TABLE_RULE_ENT*)my_malloc(sizeof(TABLE_RULE_ENT) TABLE_RULE_ENT* e = (TABLE_RULE_ENT*)my_malloc(sizeof(TABLE_RULE_ENT)
+ len, MYF(MY_WME)); + len, MYF(MY_WME));
if(!e) return 1; if (!e)
return 1;
e->db = (char*)e + sizeof(TABLE_RULE_ENT); e->db = (char*)e + sizeof(TABLE_RULE_ENT);
e->tbl_name = e->db + (dot - table_spec) + 1; e->tbl_name = e->db + (dot - table_spec) + 1;
e->key_len = len; e->key_len = len;
...@@ -182,7 +189,7 @@ int add_wild_table_rule(DYNAMIC_ARRAY* a, const char* table_spec) ...@@ -182,7 +189,7 @@ int add_wild_table_rule(DYNAMIC_ARRAY* a, const char* table_spec)
static void free_string_array(DYNAMIC_ARRAY *a) static void free_string_array(DYNAMIC_ARRAY *a)
{ {
uint i; uint i;
for(i = 0; i < a->elements; i++) for (i = 0; i < a->elements; i++)
{ {
char* p; char* p;
get_dynamic(a, (gptr) &p, i); get_dynamic(a, (gptr) &p, i);
...@@ -207,13 +214,13 @@ void end_slave() ...@@ -207,13 +214,13 @@ void end_slave()
pthread_mutex_unlock(&LOCK_slave); pthread_mutex_unlock(&LOCK_slave);
end_master_info(&glob_mi); end_master_info(&glob_mi);
if(do_table_inited) if (do_table_inited)
hash_free(&replicate_do_table); hash_free(&replicate_do_table);
if(ignore_table_inited) if (ignore_table_inited)
hash_free(&replicate_ignore_table); hash_free(&replicate_ignore_table);
if(wild_do_table_inited) if (wild_do_table_inited)
free_string_array(&replicate_wild_do_table); free_string_array(&replicate_wild_do_table);
if(wild_ignore_table_inited) if (wild_ignore_table_inited)
free_string_array(&replicate_wild_ignore_table); free_string_array(&replicate_wild_ignore_table);
} }
...@@ -241,13 +248,13 @@ void skip_load_data_infile(NET* net) ...@@ -241,13 +248,13 @@ void skip_load_data_infile(NET* net)
char* rewrite_db(char* db) 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_List_iterator<i_string_pair> it(replicate_rewrite_db);
i_string_pair* tmp; i_string_pair* tmp;
while((tmp=it++)) while((tmp=it++))
{ {
if(!strcmp(tmp->key, db)) if (!strcmp(tmp->key, db))
return tmp->val; return tmp->val;
} }
...@@ -257,22 +264,22 @@ char* rewrite_db(char* db) ...@@ -257,22 +264,22 @@ char* rewrite_db(char* db)
int db_ok(const char* db, I_List<i_string> &do_list, int db_ok(const char* db, I_List<i_string> &do_list,
I_List<i_string> &ignore_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 return 1; // ok to replicate if the user puts no constraints
// if the user has specified restrictions on which databases to replicate // if the user has specified restrictions on which databases to replicate
// and db was not selected, do not replicate // and db was not selected, do not replicate
if(!db) if (!db)
return 0; return 0;
if(!do_list.is_empty()) // if the do's are not empty if (!do_list.is_empty()) // if the do's are not empty
{ {
I_List_iterator<i_string> it(do_list); I_List_iterator<i_string> it(do_list);
i_string* tmp; i_string* tmp;
while((tmp=it++)) while((tmp=it++))
{ {
if(!strcmp(tmp->ptr, db)) if (!strcmp(tmp->ptr, db))
return 1; // match return 1; // match
} }
return 0; return 0;
...@@ -284,7 +291,7 @@ int db_ok(const char* db, I_List<i_string> &do_list, ...@@ -284,7 +291,7 @@ int db_ok(const char* db, I_List<i_string> &do_list,
while((tmp=it++)) while((tmp=it++))
{ {
if(!strcmp(tmp->ptr, db)) if (!strcmp(tmp->ptr, db))
return 0; // match return 0; // match
} }
...@@ -327,7 +334,7 @@ static int init_intvar_from_file(int* var, IO_CACHE* f, int default_val) ...@@ -327,7 +334,7 @@ static int init_intvar_from_file(int* var, IO_CACHE* f, int default_val)
*var = atoi(buf); *var = atoi(buf);
return 0; return 0;
} }
else if(default_val) else if (default_val)
{ {
*var = default_val; *var = default_val;
return 0; return 0;
...@@ -530,7 +537,7 @@ int fetch_nx_table(THD* thd, const char* db_name, const char* table_name, ...@@ -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) void end_master_info(MASTER_INFO* mi)
{ {
if(mi->fd >= 0) if (mi->fd >= 0)
{ {
end_io_cache(&mi->file); end_io_cache(&mi->file);
(void)my_close(mi->fd, MYF(MY_WME)); (void)my_close(mi->fd, MYF(MY_WME));
...@@ -567,7 +574,7 @@ int init_master_info(MASTER_INFO* mi) ...@@ -567,7 +574,7 @@ int init_master_info(MASTER_INFO* mi)
|| init_io_cache(&mi->file, fd, IO_SIZE*2, READ_CACHE, 0L,0, || init_io_cache(&mi->file, fd, IO_SIZE*2, READ_CACHE, 0L,0,
MYF(MY_WME))) MYF(MY_WME)))
{ {
if(fd >= 0) if (fd >= 0)
my_close(fd, MYF(0)); my_close(fd, MYF(0));
pthread_mutex_unlock(&mi->lock); pthread_mutex_unlock(&mi->lock);
return 1; return 1;
...@@ -587,13 +594,13 @@ int init_master_info(MASTER_INFO* mi) ...@@ -587,13 +594,13 @@ int init_master_info(MASTER_INFO* mi)
} }
else // file exists else // file exists
{ {
if(fd >= 0) if (fd >= 0)
reinit_io_cache(&mi->file, READ_CACHE, 0L,0,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, || init_io_cache(&mi->file, fd, IO_SIZE*2, READ_CACHE, 0L,
0, MYF(MY_WME))) 0, MYF(MY_WME)))
{ {
if(fd >= 0) if (fd >= 0)
my_close(fd, MYF(0)); my_close(fd, MYF(0));
pthread_mutex_unlock(&mi->lock); pthread_mutex_unlock(&mi->lock);
return 1; return 1;
...@@ -608,7 +615,7 @@ int init_master_info(MASTER_INFO* mi) ...@@ -608,7 +615,7 @@ int init_master_info(MASTER_INFO* mi)
mi->log_file_name[length-1]= 0; // kill \n mi->log_file_name[length-1]= 0; // kill \n
/* Reuse fname buffer */ /* 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"; msg="Error reading log file position from master info file";
goto error; goto error;
...@@ -616,7 +623,7 @@ int init_master_info(MASTER_INFO* mi) ...@@ -616,7 +623,7 @@ int init_master_info(MASTER_INFO* mi)
mi->pos = strtoull(fname,(char**) 0, 10); mi->pos = strtoull(fname,(char**) 0, 10);
mi->fd = fd; 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) || master_host) ||
init_strvar_from_file(mi->user, sizeof(mi->user), &mi->file, init_strvar_from_file(mi->user, sizeof(mi->user), &mi->file,
master_user) || master_user) ||
...@@ -654,19 +661,19 @@ int register_slave_on_master(MYSQL* mysql) ...@@ -654,19 +661,19 @@ int register_slave_on_master(MYSQL* mysql)
String packet; String packet;
char buf[4]; char buf[4];
if(!report_host) if (!report_host)
return 0; return 0;
int4store(buf, server_id); int4store(buf, server_id);
packet.append(buf, 4); packet.append(buf, 4);
net_store_data(&packet, report_host); net_store_data(&packet, report_host);
if(report_user) if (report_user)
net_store_data(&packet, report_user); net_store_data(&packet, report_user);
else else
packet.append((char)0); packet.append((char)0);
if(report_password) if (report_password)
net_store_data(&packet, report_user); net_store_data(&packet, report_user);
else else
packet.append((char)0); packet.append((char)0);
...@@ -678,7 +685,7 @@ int register_slave_on_master(MYSQL* mysql) ...@@ -678,7 +685,7 @@ int register_slave_on_master(MYSQL* mysql)
int4store(buf, 0); /* tell the master will fill in master_id */ int4store(buf, 0); /* tell the master will fill in master_id */
packet.append(buf, 4); 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)) packet.length(), 0))
{ {
sql_print_error("Error on COM_REGISTER_SLAVE: '%s'", sql_print_error("Error on COM_REGISTER_SLAVE: '%s'",
...@@ -710,7 +717,7 @@ int show_master_info(THD* thd) ...@@ -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("Last_error", 20));
field_list.push_back(new Item_empty_string("Skip_counter", 12)); field_list.push_back(new Item_empty_string("Skip_counter", 12));
field_list.push_back(new Item_empty_string("Last_log_seq", 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); DBUG_RETURN(-1);
String* packet = &thd->packet; String* packet = &thd->packet;
...@@ -758,6 +765,7 @@ int flush_master_info(MASTER_INFO* mi) ...@@ -758,6 +765,7 @@ int flush_master_info(MASTER_INFO* mi)
return 0; return 0;
} }
int st_master_info::wait_for_pos(THD* thd, String* log_name, ulonglong log_pos) int st_master_info::wait_for_pos(THD* thd, String* log_name, ulonglong log_pos)
{ {
if (!inited) return -1; if (!inited) return -1;
...@@ -901,13 +909,14 @@ static int request_dump(MYSQL* mysql, MASTER_INFO* mi) ...@@ -901,13 +909,14 @@ static int request_dump(MYSQL* mysql, MASTER_INFO* mi)
return 0; return 0;
} }
static int request_table_dump(MYSQL* mysql, const char* db, const char* table) static int request_table_dump(MYSQL* mysql, const char* db, const char* table)
{ {
char buf[1024]; char buf[1024];
char * p = buf; char * p = buf;
uint table_len = (uint) strlen(table); uint table_len = (uint) strlen(table);
uint db_len = (uint) strlen(db); uint db_len = (uint) strlen(db);
if(table_len + db_len > sizeof(buf) - 2) if (table_len + db_len > sizeof(buf) - 2)
{ {
sql_print_error("request_table_dump: Buffer overrun"); sql_print_error("request_table_dump: Buffer overrun");
return 1; return 1;
...@@ -1008,12 +1017,12 @@ static int exec_event(THD* thd, NET* net, MASTER_INFO* mi, int event_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 || if (ev->server_id == ::server_id ||
(slave_skip_counter && type_code != ROTATE_EVENT)) (slave_skip_counter && type_code != ROTATE_EVENT))
{ {
if(type_code == LOAD_EVENT) if (type_code == LOAD_EVENT)
skip_load_data_infile(net); skip_load_data_infile(net);
mi->inc_pos(event_len, ev->log_seq); mi->inc_pos(event_len, ev->log_seq);
flush_master_info(mi); 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 setting the counter to 1 instead of 2
while recovering from an failed while recovering from an failed
auto-increment insert */ auto-increment insert */
...@@ -1026,7 +1035,7 @@ static int exec_event(THD* thd, NET* net, MASTER_INFO* mi, int event_len) ...@@ -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->server_id = ev->server_id; // use the original server id for logging
thd->set_time(); // time the query thd->set_time(); // time the query
if(!thd->log_seq) if (!thd->log_seq)
thd->log_seq = ev->log_seq; thd->log_seq = ev->log_seq;
if (!ev->when) if (!ev->when)
ev->when = time(NULL); 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.\ ...@@ -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))) pthread_handler_decl(handle_slave,arg __attribute__((unused)))
{ {
#ifndef DBUG_OFF #ifndef DBUG_OFF
slave_begin: slave_begin:
#endif #endif
THD *thd; // needs to be first for thread_stack THD *thd; // needs to be first for thread_stack
MYSQL *mysql = NULL ; MYSQL *mysql = NULL ;
...@@ -1065,7 +1074,7 @@ pthread_handler_decl(handle_slave,arg __attribute__((unused))) ...@@ -1065,7 +1074,7 @@ pthread_handler_decl(handle_slave,arg __attribute__((unused)))
pthread_exit((void*)1); pthread_exit((void*)1);
} }
if(slave_running) if (slave_running)
{ {
pthread_cond_broadcast(&COND_slave_start); pthread_cond_broadcast(&COND_slave_start);
pthread_mutex_unlock(&LOCK_slave); pthread_mutex_unlock(&LOCK_slave);
...@@ -1148,10 +1157,10 @@ connected: ...@@ -1148,10 +1157,10 @@ connected:
while (!slave_killed(thd)) while (!slave_killed(thd))
{ {
thd->proc_info = "Requesting binlog dump"; thd->proc_info = "Requesting binlog dump";
if(request_dump(mysql, &glob_mi)) if (request_dump(mysql, &glob_mi))
{ {
sql_print_error("Failed on request_dump()"); sql_print_error("Failed on request_dump()");
if(slave_killed(thd)) if (slave_killed(thd))
{ {
sql_print_error("Slave thread killed while requesting master \ sql_print_error("Slave thread killed while requesting master \
dump"); dump");
...@@ -1159,17 +1168,17 @@ dump"); ...@@ -1159,17 +1168,17 @@ dump");
} }
thd->proc_info = "Waiiting to reconnect after a failed dump request"; thd->proc_info = "Waiiting to reconnect after a failed dump request";
if(mysql->net.vio) if (mysql->net.vio)
vio_close(mysql->net.vio); vio_close(mysql->net.vio);
// first time retry immediately, assuming that we can recover // first time retry immediately, assuming that we can recover
// right away - if first time fails, sleep between re-tries // right away - if first time fails, sleep between re-tries
// hopefuly the admin can fix the problem sometime // hopefuly the admin can fix the problem sometime
if(retried_once) if (retried_once)
safe_sleep(thd, glob_mi.connect_retry); safe_sleep(thd, glob_mi.connect_retry);
else else
retried_once = 1; retried_once = 1;
if(slave_killed(thd)) if (slave_killed(thd))
{ {
sql_print_error("Slave thread killed while retrying master \ sql_print_error("Slave thread killed while retrying master \
dump"); dump");
...@@ -1181,7 +1190,7 @@ dump"); ...@@ -1181,7 +1190,7 @@ dump");
sql_print_error("Slave: failed dump request, reconnecting to \ sql_print_error("Slave: failed dump request, reconnecting to \
try again, log '%s' at postion %s", RPL_LOG_NAME, try again, log '%s' at postion %s", RPL_LOG_NAME,
llstr(last_failed_pos,llbuff)); llstr(last_failed_pos,llbuff));
if(safe_reconnect(thd, mysql, &glob_mi) || slave_killed(thd)) if (safe_reconnect(thd, mysql, &glob_mi) || slave_killed(thd))
{ {
sql_print_error("Slave thread killed during or after reconnect"); sql_print_error("Slave thread killed during or after reconnect");
goto err; goto err;
...@@ -1195,7 +1204,7 @@ try again, log '%s' at postion %s", RPL_LOG_NAME, ...@@ -1195,7 +1204,7 @@ try again, log '%s' at postion %s", RPL_LOG_NAME,
{ {
thd->proc_info = "Reading master update"; thd->proc_info = "Reading master update";
ulong event_len = read_event(mysql, &glob_mi); ulong event_len = read_event(mysql, &glob_mi);
if(slave_killed(thd)) if (slave_killed(thd))
{ {
sql_print_error("Slave thread killed while reading event"); sql_print_error("Slave thread killed while reading event");
goto err; goto err;
...@@ -1204,7 +1213,7 @@ try again, log '%s' at postion %s", RPL_LOG_NAME, ...@@ -1204,7 +1213,7 @@ try again, log '%s' at postion %s", RPL_LOG_NAME,
if (event_len == packet_error) if (event_len == packet_error)
{ {
if(mc_mysql_errno(mysql) == ER_NET_PACKET_TOO_LARGE) 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 \ max_allowed_packet on slave. Slave thread will be aborted. If the entry is \
...@@ -1214,14 +1223,14 @@ max_allowed_packet. The current value is %ld", max_allowed_packet); ...@@ -1214,14 +1223,14 @@ max_allowed_packet. The current value is %ld", max_allowed_packet);
} }
thd->proc_info = "Waiting to reconnect after a failed read"; thd->proc_info = "Waiting to reconnect after a failed read";
if(mysql->net.vio) if (mysql->net.vio)
vio_close(mysql->net.vio); vio_close(mysql->net.vio);
if(retried_once) // punish repeat offender with sleep if (retried_once) // punish repeat offender with sleep
safe_sleep(thd, glob_mi.connect_retry); safe_sleep(thd, glob_mi.connect_retry);
else else
retried_once = 1; retried_once = 1;
if(slave_killed(thd)) if (slave_killed(thd))
{ {
sql_print_error("Slave thread killed while waiting to \ sql_print_error("Slave thread killed while waiting to \
reconnect after a failed read"); reconnect after a failed read");
...@@ -1232,7 +1241,7 @@ reconnect after a failed read"); ...@@ -1232,7 +1241,7 @@ reconnect after a failed read");
sql_print_error("Slave: Failed reading log event, \ sql_print_error("Slave: Failed reading log event, \
reconnecting to retry, log '%s' position %s", RPL_LOG_NAME, reconnecting to retry, log '%s' position %s", RPL_LOG_NAME,
llstr(last_failed_pos, llbuff)); llstr(last_failed_pos, llbuff));
if(safe_reconnect(thd, mysql, &glob_mi) || slave_killed(thd)) if (safe_reconnect(thd, mysql, &glob_mi) || slave_killed(thd))
{ {
sql_print_error("Slave thread killed during or after a \ sql_print_error("Slave thread killed during or after a \
reconnect done to recover from failed read"); reconnect done to recover from failed read");
...@@ -1240,10 +1249,10 @@ reconnect done to recover from failed read"); ...@@ -1240,10 +1249,10 @@ reconnect done to recover from failed read");
} }
goto connected; goto connected;
} // if(event_len == packet_error) } // if (event_len == packet_error)
thd->proc_info = "Processing master log event"; thd->proc_info = "Processing master log event";
if(exec_event(thd, &mysql->net, &glob_mi, event_len)) if (exec_event(thd, &mysql->net, &glob_mi, event_len))
{ {
sql_print_error("\ sql_print_error("\
Error running query, slave aborted. Fix the problem, and re-start \ Error running query, slave aborted. Fix the problem, and re-start \
...@@ -1256,7 +1265,7 @@ the slave thread with \"mysqladmin start-slave\". We stopped at log \ ...@@ -1256,7 +1265,7 @@ the slave thread with \"mysqladmin start-slave\". We stopped at log \
// should restart the slave with mysqladmin start-slave // should restart the slave with mysqladmin start-slave
} }
#ifndef DBUG_OFF #ifndef DBUG_OFF
if(abort_slave_event_count && !--events_till_abort) if (abort_slave_event_count && !--events_till_abort)
{ {
sql_print_error("Slave: debugging abort"); sql_print_error("Slave: debugging abort");
goto err; goto err;
...@@ -1265,7 +1274,7 @@ the slave thread with \"mysqladmin start-slave\". We stopped at log \ ...@@ -1265,7 +1274,7 @@ the slave thread with \"mysqladmin start-slave\". We stopped at log \
// successful exec with offset advance, // successful exec with offset advance,
// the slave repents and his sins are forgiven! // the slave repents and his sins are forgiven!
if(glob_mi.pos > last_failed_pos) if (glob_mi.pos > last_failed_pos)
{ {
retried_once = 0; retried_once = 0;
#ifndef DBUG_OFF #ifndef DBUG_OFF
...@@ -1287,13 +1296,13 @@ the slave thread with \"mysqladmin start-slave\". We stopped at log \ ...@@ -1287,13 +1296,13 @@ the slave thread with \"mysqladmin start-slave\". We stopped at log \
} // while(!slave_killed(thd)) - slave loop } // while(!slave_killed(thd)) - slave loop
// error = 0; // error = 0;
err: err:
// print the current replication position // print the current replication position
sql_print_error("Slave thread exiting, replication stopped in log '%s' at \ sql_print_error("Slave thread exiting, replication stopped in log '%s' at \
position %s", position %s",
RPL_LOG_NAME, llstr(glob_mi.pos,llbuff)); RPL_LOG_NAME, llstr(glob_mi.pos,llbuff));
thd->query = thd->db = 0; // extra safety thd->query = thd->db = 0; // extra safety
if(mysql) if (mysql)
mc_mysql_close(mysql); mc_mysql_close(mysql);
thd->proc_info = "Waiting for slave mutex on exit"; thd->proc_info = "Waiting for slave mutex on exit";
pthread_mutex_lock(&LOCK_slave); pthread_mutex_lock(&LOCK_slave);
...@@ -1309,7 +1318,7 @@ position %s", ...@@ -1309,7 +1318,7 @@ position %s",
delete thd; delete thd;
my_thread_end(); my_thread_end();
#ifndef DBUG_OFF #ifndef DBUG_OFF
if(abort_slave_event_count && !events_till_abort) if (abort_slave_event_count && !events_till_abort)
goto slave_begin; goto slave_begin;
#endif #endif
pthread_exit(0); pthread_exit(0);
...@@ -1346,7 +1355,7 @@ static int connect_to_master(THD* thd, MYSQL* mysql, MASTER_INFO* mi, ...@@ -1346,7 +1355,7 @@ static int connect_to_master(THD* thd, MYSQL* mysql, MASTER_INFO* mi,
events_till_disconnect = disconnect_slave_event_count; events_till_disconnect = disconnect_slave_event_count;
#endif #endif
while (!(slave_was_killed = slave_killed(thd)) && 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, !mc_mysql_connect(mysql, mi->host, mi->user, mi->password, 0,
mi->port, 0, 0))) mi->port, 0, 0)))
{ {
......
...@@ -286,13 +286,8 @@ If join_results allocated new block(s) then we need call pack_cache again. ...@@ -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) #if defined(EXTRA_DEBUG) && !defined(DBUG_OFF)
#define MUTEX_LOCK(M) { DBUG_PRINT("lock", ("mutex lock 0x%lx", (ulong)(M))); \ #define MUTEX_LOCK(M) { DBUG_PRINT("lock", ("mutex lock 0x%lx", (ulong)(M))); \
pthread_mutex_lock(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",\ #define MUTEX_UNLOCK(M) {DBUG_PRINT("lock", ("mutex unlock 0x%lx",\
(ulong)(M))); pthread_mutex_unlock(M);} (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__)); \ #define STRUCT_LOCK(M) {DBUG_PRINT("lock", ("%d struct lock...",__LINE__)); \
pthread_mutex_lock(M);DBUG_PRINT("lock", ("struct lock OK"));} pthread_mutex_lock(M);DBUG_PRINT("lock", ("struct lock OK"));}
#define STRUCT_UNLOCK(M) { \ #define STRUCT_UNLOCK(M) { \
...@@ -313,9 +308,7 @@ If join_results allocated new block(s) then we need call pack_cache again. ...@@ -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();}) #define DUMP(C) DBUG_EXECUTE("qcache", {(C)->queries_dump();(C)->tables_dump();})
#else #else
#define MUTEX_LOCK(M) pthread_mutex_lock(M) #define MUTEX_LOCK(M) pthread_mutex_lock(M)
#define SEM_LOCK(M) sem_wait(M)
#define MUTEX_UNLOCK(M) pthread_mutex_unlock(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_LOCK(M) pthread_mutex_lock(M)
#define STRUCT_UNLOCK(M) pthread_mutex_unlock(M) #define STRUCT_UNLOCK(M) pthread_mutex_unlock(M)
#define BLOCK_LOCK_WR(B) B->query()->lock_writing() #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. ...@@ -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() inline Query_cache_block * Query_cache_block_table::block()
{ {
return (Query_cache_block *)(((byte*)this) - 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))); ALIGN_SIZE(sizeof(Query_cache_block)));
}; };
...@@ -432,7 +425,7 @@ void Query_cache_query::init_n_lock() ...@@ -432,7 +425,7 @@ void Query_cache_query::init_n_lock()
{ {
DBUG_ENTER("Query_cache_query::init_n_lock"); DBUG_ENTER("Query_cache_query::init_n_lock");
res=0; wri = 0; len = 0; 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); pthread_mutex_init(&clients_guard,MY_MUTEX_INIT_FAST);
clients = 0; clients = 0;
lock_writing(); lock_writing();
...@@ -445,14 +438,14 @@ void Query_cache_query::init_n_lock() ...@@ -445,14 +438,14 @@ void Query_cache_query::init_n_lock()
void Query_cache_query::unlock_n_destroy() void Query_cache_query::unlock_n_destroy()
{ {
DBUG_ENTER("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 The following call is not needed on system where one can destroy an
active semaphore active semaphore
*/ */
this->unlock_writing(); this->unlock_writing();
DBUG_PRINT("qcache", ("destroyed & unlocked query for block 0x%lx", pthread_cond_destroy(&lock);
((byte*)this)-ALIGN_SIZE(sizeof(Query_cache_block))));
sem_destroy(&lock);
pthread_mutex_destroy(&clients_guard); pthread_mutex_destroy(&clients_guard);
DBUG_VOID_RETURN; DBUG_VOID_RETURN;
} }
...@@ -468,7 +461,9 @@ void Query_cache_query::unlock_n_destroy() ...@@ -468,7 +461,9 @@ void Query_cache_query::unlock_n_destroy()
void Query_cache_query::lock_writing() 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() ...@@ -482,11 +477,17 @@ void Query_cache_query::lock_writing()
my_bool Query_cache_query::try_lock_writing() my_bool Query_cache_query::try_lock_writing()
{ {
DBUG_ENTER("Query_cache_block::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_PRINT("qcache", ("can't lock mutex"));
DBUG_RETURN(0); 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_PRINT("qcache", ("mutex 'lock' 0x%lx locked", (ulong) &lock));
DBUG_RETURN(1); DBUG_RETURN(1);
} }
...@@ -495,15 +496,14 @@ my_bool Query_cache_query::try_lock_writing() ...@@ -495,15 +496,14 @@ my_bool Query_cache_query::try_lock_writing()
void Query_cache_query::lock_reading() void Query_cache_query::lock_reading()
{ {
MUTEX_LOCK(&clients_guard); MUTEX_LOCK(&clients_guard);
if (!clients++) clients++;
SEM_LOCK(&lock);
MUTEX_UNLOCK(&clients_guard); MUTEX_UNLOCK(&clients_guard);
} }
void Query_cache_query::unlock_writing() void Query_cache_query::unlock_writing()
{ {
SEM_UNLOCK(&lock); MUTEX_UNLOCK(&clients_guard);
} }
...@@ -511,7 +511,7 @@ void Query_cache_query::unlock_reading() ...@@ -511,7 +511,7 @@ void Query_cache_query::unlock_reading()
{ {
MUTEX_LOCK(&clients_guard); MUTEX_LOCK(&clients_guard);
if (--clients == 0) if (--clients == 0)
SEM_UNLOCK(&lock); pthread_cond_broadcast(&lock);
MUTEX_UNLOCK(&clients_guard); MUTEX_UNLOCK(&clients_guard);
} }
...@@ -677,6 +677,7 @@ Query_cache::Query_cache(ulong query_cache_limit, ...@@ -677,6 +677,7 @@ Query_cache::Query_cache(ulong query_cache_limit,
:query_cache_size(0), :query_cache_size(0),
query_cache_limit(query_cache_limit), query_cache_limit(query_cache_limit),
queries_in_cache(0), hits(0), inserts(0), refused(0), queries_in_cache(0), hits(0), inserts(0), refused(0),
total_blocks(0),
min_allocation_unit(min_allocation_unit), min_allocation_unit(min_allocation_unit),
min_result_data_size(min_result_data_size), min_result_data_size(min_result_data_size),
def_query_hash_size(def_query_hash_size), def_query_hash_size(def_query_hash_size),
...@@ -747,7 +748,7 @@ void Query_cache::store_query(THD *thd, TABLE_LIST *tables_used) ...@@ -747,7 +748,7 @@ void Query_cache::store_query(THD *thd, TABLE_LIST *tables_used)
/* Check if another thread is processing the same query? */ /* Check if another thread is processing the same query? */
thd->query[thd->query_length] = (char) flags; thd->query[thd->query_length] = (char) flags;
Query_cache_block *competitor = (Query_cache_block *) 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, DBUG_PRINT("qcache", ("competitor 0x%lx, flags %x", (ulong) competitor,
flags)); flags));
if (competitor == 0) if (competitor == 0)
...@@ -779,7 +780,7 @@ void Query_cache::store_query(THD *thd, TABLE_LIST *tables_used) ...@@ -779,7 +780,7 @@ void Query_cache::store_query(THD *thd, TABLE_LIST *tables_used)
{ {
refused++; refused++;
DBUG_PRINT("warning", ("tables list including failed")); DBUG_PRINT("warning", ("tables list including failed"));
hash_delete(&queries, (char *) query_block); hash_delete(&queries, (byte *) query_block);
header->unlock_n_destroy(); header->unlock_n_destroy();
free_memory_block(query_block); free_memory_block(query_block);
STRUCT_UNLOCK(&structure_guard_mutex); STRUCT_UNLOCK(&structure_guard_mutex);
...@@ -790,7 +791,7 @@ void Query_cache::store_query(THD *thd, TABLE_LIST *tables_used) ...@@ -790,7 +791,7 @@ void Query_cache::store_query(THD *thd, TABLE_LIST *tables_used)
queries_in_cache++; queries_in_cache++;
STRUCT_UNLOCK(&structure_guard_mutex); STRUCT_UNLOCK(&structure_guard_mutex);
net->query_cache_query = (gptr) query_block; net->query_cache_query= (gptr) query_block;
header->writer(net); header->writer(net);
// init_n_lock make query block locked // init_n_lock make query block locked
BLOCK_UNLOCK_WR(query_block); BLOCK_UNLOCK_WR(query_block);
...@@ -890,7 +891,7 @@ Query_cache::send_result_to_client(THD *thd, char *sql, uint query_length) ...@@ -890,7 +891,7 @@ Query_cache::send_result_to_client(THD *thd, char *sql, uint query_length)
} }
sql[query_length] = (char) flags; 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); query_length+1);
sql[query_length] = '\0'; sql[query_length] = '\0';
...@@ -1026,20 +1027,11 @@ void Query_cache::invalidate(Query_cache_table::query_cache_table_type type) ...@@ -1026,20 +1027,11 @@ void Query_cache::invalidate(Query_cache_table::query_cache_table_type type)
{ {
STRUCT_LOCK(&structure_guard_mutex); STRUCT_LOCK(&structure_guard_mutex);
DUMP(this); 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 */ /* invalidate_table reduce list while only root of list remain */
Query_cache_block *next = table_block->next; while (tables_blocks[type] != 0)
invalidate_table(table_block); invalidate_table(tables_blocks[type]);
#ifdef TO_BE_DELETED
if (next == table_block) // End of list
break;
#endif
table_block = next;
} while (table_block != tables_blocks[type]);
} }
STRUCT_UNLOCK(&structure_guard_mutex); STRUCT_UNLOCK(&structure_guard_mutex);
} }
...@@ -1060,27 +1052,11 @@ void Query_cache::invalidate(char *db) ...@@ -1060,27 +1052,11 @@ void Query_cache::invalidate(char *db)
if (query_cache_size > 0) if (query_cache_size > 0)
{ {
DUMP(this); DUMP(this);
int i = 0; for (int i=0 ; i < (int) Query_cache_table::TYPES_NUMBER; i++)
for(; i < (int) Query_cache_table::TYPES_NUMBER; i++)
{
if (tables_blocks[i] != 0) // Cache not empty
{ {
Query_cache_block *table_block = tables_blocks[i]; /* invalidate_table reduce list while only root of list remain */
do while (tables_blocks[i] !=0 )
{ invalidate_table(tables_blocks[i]);
/*
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]);
}
} }
} }
STRUCT_UNLOCK(&structure_guard_mutex); STRUCT_UNLOCK(&structure_guard_mutex);
...@@ -1101,7 +1077,8 @@ void Query_cache::invalidate_by_MyISAM_filename(const char *filename) ...@@ -1101,7 +1077,8 @@ void Query_cache::invalidate_by_MyISAM_filename(const char *filename)
if (query_cache_size > 0) // Safety if cache removed if (query_cache_size > 0) // Safety if cache removed
{ {
Query_cache_block *table_block; 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))) key_length)))
invalidate_table(table_block); invalidate_table(table_block);
} }
...@@ -1243,6 +1220,7 @@ ulong Query_cache::init_cache() ...@@ -1243,6 +1220,7 @@ ulong Query_cache::init_cache()
first_block = (Query_cache_block *) (cache + additional_data_size); first_block = (Query_cache_block *) (cache + additional_data_size);
first_block->init(query_cache_size); first_block->init(query_cache_size);
total_blocks++;
first_block->pnext=first_block->pprev=first_block; first_block->pnext=first_block->pprev=first_block;
first_block->next=first_block->prev=first_block; first_block->next=first_block->prev=first_block;
...@@ -1290,8 +1268,8 @@ ulong Query_cache::init_cache() ...@@ -1290,8 +1268,8 @@ ulong Query_cache::init_cache()
size += inc; size += inc;
} }
} }
bins[mem_bin_num].number= 1; // For easy end test bins[mem_bin_num].number = 1; // For easy end test in get_free_block
free_memory= 0; free_memory = free_memory_blocks = 0;
insert_into_free_memory_list(first_block); insert_into_free_memory_list(first_block);
DUMP(this); DUMP(this);
...@@ -1348,6 +1326,7 @@ void Query_cache::free_cache(my_bool destruction) ...@@ -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 */ /* Becasue we did a flush, all cache memory must be in one this block */
bins[0].free_blocks->destroy(); bins[0].free_blocks->destroy();
total_blocks--;
DBUG_PRINT("qcache", ("free memory %lu (should be %lu)", DBUG_PRINT("qcache", ("free memory %lu (should be %lu)",
free_memory , query_cache_size)); free_memory , query_cache_size));
my_free((gptr) cache, MYF(MY_ALLOW_ZERO_PTR)); my_free((gptr) cache, MYF(MY_ALLOW_ZERO_PTR));
...@@ -1738,7 +1717,7 @@ void Query_cache::invalidate_table(TABLE_LIST *table_list) ...@@ -1738,7 +1717,7 @@ void Query_cache::invalidate_table(TABLE_LIST *table_list)
// We don't store temporary tables => no key_length+=4 ... // We don't store temporary tables => no key_length+=4 ...
if ((table_block = (Query_cache_block*) if ((table_block = (Query_cache_block*)
hash_search(&tables,key,key_length))) hash_search(&tables,(byte*) key,key_length)))
invalidate_table(table_block); invalidate_table(table_block);
} }
} }
...@@ -1747,7 +1726,7 @@ void Query_cache::invalidate_table(TABLE *table) ...@@ -1747,7 +1726,7 @@ void Query_cache::invalidate_table(TABLE *table)
{ {
Query_cache_block *table_block; Query_cache_block *table_block;
if ((table_block = ((Query_cache_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)))) table->key_length))))
invalidate_table(table_block); invalidate_table(table_block);
} }
...@@ -1856,7 +1835,8 @@ Query_cache::insert_table(uint key_len, char *key, ...@@ -1856,7 +1835,8 @@ Query_cache::insert_table(uint key_len, char *key,
(ulong)node, key_len)); (ulong)node, key_len));
Query_cache_block *table_block = ((Query_cache_block *) 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) if (table_block == 0)
{ {
...@@ -1905,6 +1885,7 @@ Query_cache::insert_table(uint key_len, char *key, ...@@ -1905,6 +1885,7 @@ Query_cache::insert_table(uint key_len, char *key,
void Query_cache::unlink_table(Query_cache_block_table *node) void Query_cache::unlink_table(Query_cache_block_table *node)
{ {
DBUG_ENTER("Query_cache::unlink_table");
node->prev->next = node->next; node->prev->next = node->next;
node->next->prev = node->prev; node->next->prev = node->prev;
Query_cache_block_table *neighbour = node->next; Query_cache_block_table *neighbour = node->next;
...@@ -1917,6 +1898,7 @@ void Query_cache::unlink_table(Query_cache_block_table *node) ...@@ -1917,6 +1898,7 @@ void Query_cache::unlink_table(Query_cache_block_table *node)
hash_delete(&tables,(byte *) table_block); hash_delete(&tables,(byte *) table_block);
free_memory_block(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) ...@@ -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); Query_cache_block *new_block = (Query_cache_block*)(((byte*) block)+len);
new_block->init(block->length - len); new_block->init(block->length - len);
total_blocks++;
block->length=len; block->length=len;
new_block->pnext = block->pnext; new_block->pnext = block->pnext;
block->pnext = new_block; block->pnext = new_block;
...@@ -2068,6 +2051,7 @@ Query_cache::join_free_blocks(Query_cache_block *first_block, ...@@ -2068,6 +2051,7 @@ Query_cache::join_free_blocks(Query_cache_block *first_block,
// May be was not free block // May be was not free block
second_block->used=0; second_block->used=0;
second_block->destroy(); second_block->destroy();
total_blocks--;
first_block->length += second_block->length; first_block->length += second_block->length;
first_block->pnext = second_block->pnext; first_block->pnext = second_block->pnext;
...@@ -2090,6 +2074,7 @@ my_bool Query_cache::append_next_free_block(Query_cache_block *block, ...@@ -2090,6 +2074,7 @@ my_bool Query_cache::append_next_free_block(Query_cache_block *block,
ulong old_len = block->length; ulong old_len = block->length;
exclude_from_free_memory_list(next_block); exclude_from_free_memory_list(next_block);
next_block->destroy(); next_block->destroy();
total_blocks--;
block->length += next_block->length; block->length += next_block->length;
block->pnext = next_block->pnext; block->pnext = next_block->pnext;
...@@ -2112,6 +2097,7 @@ void Query_cache::exclude_from_free_memory_list(Query_cache_block *free_block) ...@@ -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); double_linked_list_exclude(free_block, &bin->free_blocks);
bin->number--; bin->number--;
free_memory-=free_block->length; free_memory-=free_block->length;
free_memory_blocks--;
DBUG_PRINT("qcache",("exclude block 0x%lx, bin 0x%lx", (ulong) free_block, DBUG_PRINT("qcache",("exclude block 0x%lx, bin 0x%lx", (ulong) free_block,
(ulong) bin)); (ulong) bin));
DBUG_VOID_RETURN; DBUG_VOID_RETURN;
...@@ -2207,6 +2193,7 @@ void Query_cache::insert_into_free_memory_sorted_list(Query_cache_block * ...@@ -2207,6 +2193,7 @@ void Query_cache::insert_into_free_memory_sorted_list(Query_cache_block *
point->next = new_block; point->next = new_block;
} }
free_memory+=new_block->length; free_memory+=new_block->length;
free_memory_blocks++;
DBUG_VOID_RETURN; DBUG_VOID_RETURN;
} }
...@@ -2222,11 +2209,11 @@ Query_cache::double_linked_list_simple_include(Query_cache_block *point, ...@@ -2222,11 +2209,11 @@ Query_cache::double_linked_list_simple_include(Query_cache_block *point,
*list_pointer=point->next=point->prev=point; *list_pointer=point->next=point->prev=point;
else else
{ {
// insert to and of list
point->next = (*list_pointer); point->next = (*list_pointer);
point->prev = (*list_pointer)->prev; point->prev = (*list_pointer)->prev;
point->prev->next = point; point->prev->next = point;
(*list_pointer)->prev = point; (*list_pointer)->prev = point;
(*list_pointer) = point;
} }
DBUG_VOID_RETURN; DBUG_VOID_RETURN;
} }
...@@ -2360,6 +2347,7 @@ void Query_cache::pack_cache() ...@@ -2360,6 +2347,7 @@ void Query_cache::pack_cache()
{ {
Query_cache_block *new_block = (Query_cache_block *) border; Query_cache_block *new_block = (Query_cache_block *) border;
new_block->init(gap); new_block->init(gap);
total_blocks++;
new_block->pnext = before->pnext; new_block->pnext = before->pnext;
before->pnext = new_block; before->pnext = new_block;
new_block->pprev = before; new_block->pprev = before;
...@@ -2395,6 +2383,7 @@ my_bool Query_cache::move_by_type(byte **border, ...@@ -2395,6 +2383,7 @@ my_bool Query_cache::move_by_type(byte **border,
block->pprev->pnext=block->pnext; block->pprev->pnext=block->pnext;
block->pnext->pprev=block->pprev; block->pnext->pprev=block->pprev;
block->destroy(); block->destroy();
total_blocks--;
DBUG_PRINT("qcache", ("added to gap (%lu)", *gap)); DBUG_PRINT("qcache", ("added to gap (%lu)", *gap));
break; break;
} }
...@@ -2416,7 +2405,7 @@ my_bool Query_cache::move_by_type(byte **border, ...@@ -2416,7 +2405,7 @@ my_bool Query_cache::move_by_type(byte **border,
byte *key; byte *key;
uint key_length; uint key_length;
key=query_cache_table_get_key((byte*) block, &key_length,0); 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(); block->destroy();
new_block->init(len); new_block->init(len);
...@@ -2432,8 +2421,10 @@ my_bool Query_cache::move_by_type(byte **border, ...@@ -2432,8 +2421,10 @@ my_bool Query_cache::move_by_type(byte **border,
nlist_root->n = 0; nlist_root->n = 0;
nlist_root->next = (tnext == list_root ? nlist_root : tnext); nlist_root->next = (tnext == list_root ? nlist_root : tnext);
nlist_root->prev = (tprev == list_root ? nlist_root: tnext); nlist_root->prev = (tprev == list_root ? nlist_root: tnext);
tnext->prev = list_root; tnext->prev = nlist_root;
tprev->next = list_root; tprev->next = nlist_root;
for (;tnext != nlist_root; tnext=tnext->next)
tnext->parent = new_block->table();
*border += len; *border += len;
*before = new_block; *before = new_block;
/* Fix hash to point at moved block */ /* Fix hash to point at moved block */
...@@ -2462,7 +2453,7 @@ my_bool Query_cache::move_by_type(byte **border, ...@@ -2462,7 +2453,7 @@ my_bool Query_cache::move_by_type(byte **border,
byte *key; byte *key;
uint key_length; uint key_length;
key=query_cache_query_get_key((byte*) block, &key_length,0); 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), memcpy((char*) new_block->table(0), (char*) block->table(0),
ALIGN_SIZE(n_tables*sizeof(Query_cache_block_table))); ALIGN_SIZE(n_tables*sizeof(Query_cache_block_table)));
...@@ -2654,7 +2645,6 @@ my_bool Query_cache::join_results(ulong join_limit) ...@@ -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) uint Query_cache::filename_2_table_key (char *key, const char *path)
{ {
char tablename[FN_REFLEN+2], *filename, *dbname; char tablename[FN_REFLEN+2], *filename, *dbname;
Query_cache_block *table_block;
uint db_length; uint db_length;
DBUG_ENTER("Query_cache::filename_2_table_key"); DBUG_ENTER("Query_cache::filename_2_table_key");
......
...@@ -17,8 +17,6 @@ ...@@ -17,8 +17,6 @@
#ifndef _SQL_CACHE_H #ifndef _SQL_CACHE_H
#define _SQL_CACHE_H #define _SQL_CACHE_H
#include <semaphore.h>
/* Query cache */ /* Query cache */
/* /*
...@@ -105,7 +103,7 @@ struct Query_cache_query ...@@ -105,7 +103,7 @@ struct Query_cache_query
Query_cache_block *res; Query_cache_block *res;
NET *wri; NET *wri;
ulong len; ulong len;
sem_t lock; // R/W lock of block pthread_cond_t lock; // R/W lock of block
pthread_mutex_t clients_guard; pthread_mutex_t clients_guard;
uint clients; uint clients;
...@@ -220,7 +218,8 @@ public: ...@@ -220,7 +218,8 @@ public:
/* Info */ /* Info */
ulong query_cache_size, query_cache_limit; ulong query_cache_size, query_cache_limit;
/* statistics */ /* 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: protected:
/* /*
......
...@@ -1023,11 +1023,11 @@ err: ...@@ -1023,11 +1023,11 @@ err:
int log_loaded_block(IO_CACHE* file) int log_loaded_block(IO_CACHE* file)
{ {
LOAD_FILE_INFO* lf_info; LOAD_FILE_INFO* lf_info;
uint block_len ; ulong block_len ;
/* file->request_pos contains position where we started last read */ /* file->request_pos contains position where we started last read */
char* buffer = (char*) file->request_pos; byte *buffer = file->request_pos;
if (!(block_len = file->read_end - buffer)) if (!(block_len = (ulong) (file->read_end - buffer)))
return 0; return 0;
lf_info = (LOAD_FILE_INFO*)file->arg; lf_info = (LOAD_FILE_INFO*)file->arg;
if (lf_info->last_pos_in_file != HA_POS_ERROR && if (lf_info->last_pos_in_file != HA_POS_ERROR &&
...@@ -1036,14 +1036,14 @@ int log_loaded_block(IO_CACHE* file) ...@@ -1036,14 +1036,14 @@ int log_loaded_block(IO_CACHE* file)
lf_info->last_pos_in_file = file->pos_in_file; lf_info->last_pos_in_file = file->pos_in_file;
if (lf_info->wrote_create_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); mysql_bin_log.write(&a);
} }
else else
{ {
Create_file_log_event c(lf_info->thd,lf_info->ex,lf_info->db, Create_file_log_event c(lf_info->thd,lf_info->ex,lf_info->db,
lf_info->table_name, *lf_info->fields, lf_info->table_name, *lf_info->fields,
lf_info->handle_dup, buffer, lf_info->handle_dup, (char*) buffer,
block_len); block_len);
mysql_bin_log.write(&c); mysql_bin_log.write(&c);
lf_info->wrote_create_file = 1; lf_info->wrote_create_file = 1;
......
...@@ -3172,11 +3172,9 @@ option_value: ...@@ -3172,11 +3172,9 @@ option_value:
} }
query_cache_type: 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; } | OFF { current_thd->query_cache_type = 0; }
| '1' { current_thd->query_cache_type = 1; }
| ON { 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; } | DEMAND_SYM { current_thd->query_cache_type = 2; }
text_or_password: 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