Commit 5d5b9fed authored by serg@serg.mylan's avatar serg@serg.mylan

Merge bk-internal.mysql.com:/home/bk/mysql-5.1-new

into serg.mylan:/usr/home/serg/Abk/mysql-5.1
parents 2e16f1ec efdf221d
......@@ -1771,3 +1771,4 @@ vio/viotest.cpp
zlib/*.ds?
zlib/*.vcproj
libmysqld/event_scheduler.cc
mysys/test_atomic
......@@ -83,13 +83,13 @@ link_sources:
for f in $(sql_src) ; do \
rm -f $$f; \
@LN_CP_F@ $(top_srcdir)/sql/$$f $$f; \
done; \
for f in $(strings_src) ; do \
rm -f $(srcdir)/$$f; \
@LN_CP_F@ $(top_srcdir)/strings/$$f $$f; \
done; \
rm -f $(srcdir)/my_user.c; \
@LN_CP_F@ $(top_srcdir)/sql-common/my_user.c my_user.c
done;
for f in $(strings_src) ; do \
rm -f $(srcdir)/$$f; \
@LN_CP_F@ $(top_srcdir)/strings/$$f $$f; \
done;
-rm -f $(srcdir)/my_user.c;
@LN_CP_F@ $(top_srcdir)/sql-common/my_user.c my_user.c
# Don't update the files from bitkeeper
......
***************
*** 50,55 ****
OPT_NDBCLUSTER, OPT_NDB_CONNECTSTRING,
#endif
OPT_TRIGGERS,
OPT_IGNORE_TABLE,OPT_INSERT_IGNORE,OPT_SHOW_WARNINGS,OPT_DROP_DATABASE,
! OPT_TZ_UTC, OPT_AUTO_CLOSE
};
--- 50,55 ----
OPT_NDBCLUSTER, OPT_NDB_CONNECTSTRING,
#endif
OPT_TRIGGERS,
OPT_IGNORE_TABLE,OPT_INSERT_IGNORE,OPT_SHOW_WARNINGS,OPT_DROP_DATABASE,
! OPT_TZ_UTC, OPT_AUTO_CLOSE, OPT_SSL_VERIFY_SERVER_CERT
};
......@@ -778,48 +778,6 @@ struct request_info *req;
AC_SUBST(WRAPLIBS)
if test "$TARGET_LINUX" = "true"; then
AC_MSG_CHECKING([for atomic operations])
AC_LANG_SAVE
AC_LANG_CPLUSPLUS
atom_ops=
AC_TRY_RUN([
#include <asm/atomic.h>
int main()
{
atomic_t v;
atomic_set(&v, 23);
atomic_add(5, &v);
return atomic_read(&v) == 28 ? 0 : -1;
}
],
[AC_DEFINE([HAVE_ATOMIC_ADD], [1],
[atomic_add() from <asm/atomic.h> (Linux only)])
atom_ops="${atom_ops}atomic_add "],
)
AC_TRY_RUN([
#include <asm/atomic.h>
int main()
{
atomic_t v;
atomic_set(&v, 23);
atomic_sub(5, &v);
return atomic_read(&v) == 18 ? 0 : -1;
}
],
[AC_DEFINE([HAVE_ATOMIC_SUB], [1],
[atomic_sub() from <asm/atomic.h> (Linux only)])
atom_ops="${atom_ops}atomic_sub "],
)
if test -z "$atom_ops"; then atom_ops="no"; fi
AC_MSG_RESULT($atom_ops)
AC_LANG_RESTORE
AC_ARG_WITH(pstack,
[ --with-pstack Use the pstack backtrace library],
[ USE_PSTACK=$withval ],
......@@ -1631,6 +1589,20 @@ then
fi
fi
AC_ARG_WITH([atomic-ops],
AC_HELP_STRING([--with-atomic-ops=rwlocks|smp|up],
[Implement atomic operations using pthread rwlocks or atomic CPU
instructions for multi-processor (default) or uniprocessor
configuration]), , [with_atomic_ops=smp])
case "$with_atomic_ops" in
"up") AC_DEFINE([MY_ATOMIC_MODE_DUMMY], [1],
[Assume single-CPU mode, no concurrency]) ;;
"rwlocks") AC_DEFINE([MY_ATOMIC_MODE_RWLOCKS], [1],
[Use pthread rwlocks for atomic ops]) ;;
"smp") ;;
*) AC_MSG_ERROR(["$with_atomic_ops" is not a valid value for --with-atomic-ops]) ;;
esac
# Force static compilation to avoid linking problems/get more speed
AC_ARG_WITH(mysqld-ldflags,
[ --with-mysqld-ldflags Extra linking arguments for mysqld],
......
/* Copyright (C) 2006 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 */
#if defined(__i386__) || defined(_M_IX86)
#ifdef MY_ATOMIC_MODE_DUMMY
# define LOCK ""
#else
# define LOCK "lock "
#endif
#ifdef __GNUC__
#include "x86-gcc.h"
#elif defined(_MSC_VER)
#include "x86-msvc.h"
#endif
#endif
#ifdef make_atomic_add_body8
#ifdef HAVE_INLINE
#define make_atomic_add(S) \
static inline uint ## S _my_atomic_add ## S( \
my_atomic_ ## S ## _t *a, uint ## S v) \
{ \
make_atomic_add_body ## S; \
return v; \
}
#define make_atomic_swap(S) \
static inline uint ## S _my_atomic_swap ## S( \
my_atomic_ ## S ## _t *a, uint ## S v) \
{ \
make_atomic_swap_body ## S; \
return v; \
}
#define make_atomic_cas(S) \
static inline uint _my_atomic_cas ## S(my_atomic_ ## S ## _t *a,\
uint ## S *cmp, uint ## S set) \
{ \
uint8 ret; \
make_atomic_cas_body ## S; \
return ret; \
}
#define make_atomic_load(S) \
static inline uint ## S _my_atomic_load ## S( \
my_atomic_ ## S ## _t *a) \
{ \
uint ## S ret; \
make_atomic_load_body ## S; \
return ret; \
}
#define make_atomic_store(S) \
static inline void _my_atomic_store ## S( \
my_atomic_ ## S ## _t *a, uint ## S v) \
{ \
make_atomic_store_body ## S; \
}
#else /* no inline functions */
#define make_atomic_add(S) \
extern uint ## S _my_atomic_add ## S( \
my_atomic_ ## S ## _t *a, uint ## S v);
#define make_atomic_swap(S) \
extern uint ## S _my_atomic_swap ## S( \
my_atomic_ ## S ## _t *a, uint ## S v);
#define make_atomic_cas(S) \
extern uint _my_atomic_cas ## S(my_atomic_ ## S ## _t *a, \
uint ## S *cmp, uint ## S set);
#define make_atomic_load(S) \
extern uint ## S _my_atomic_load ## S( \
my_atomic_ ## S ## _t *a);
#define make_atomic_store(S) \
extern void _my_atomic_store ## S( \
my_atomic_ ## S ## _t *a, uint ## S v);
#endif
make_atomic_add( 8)
make_atomic_add(16)
make_atomic_add(32)
make_atomic_cas( 8)
make_atomic_cas(16)
make_atomic_cas(32)
make_atomic_load( 8)
make_atomic_load(16)
make_atomic_load(32)
make_atomic_store( 8)
make_atomic_store(16)
make_atomic_store(32)
make_atomic_swap( 8)
make_atomic_swap(16)
make_atomic_swap(32)
#undef make_atomic_add_body8
#undef make_atomic_cas_body8
#undef make_atomic_load_body8
#undef make_atomic_store_body8
#undef make_atomic_swap_body8
#undef make_atomic_add_body16
#undef make_atomic_cas_body16
#undef make_atomic_load_body16
#undef make_atomic_store_body16
#undef make_atomic_swap_body16
#undef make_atomic_add_body32
#undef make_atomic_cas_body32
#undef make_atomic_load_body32
#undef make_atomic_store_body32
#undef make_atomic_swap_body32
#undef make_atomic_add
#undef make_atomic_cas
#undef make_atomic_load
#undef make_atomic_store
#undef make_atomic_swap
#define my_atomic_add8(a,v,L) _my_atomic_add8(a,v)
#define my_atomic_add16(a,v,L) _my_atomic_add16(a,v)
#define my_atomic_add32(a,v,L) _my_atomic_add32(a,v)
#define my_atomic_cas8(a,c,v,L) _my_atomic_cas8(a,c,v)
#define my_atomic_cas16(a,c,v,L) _my_atomic_cas16(a,c,v)
#define my_atomic_cas32(a,c,v,L) _my_atomic_cas32(a,c,v)
#define my_atomic_load8(a,L) _my_atomic_load8(a)
#define my_atomic_load16(a,L) _my_atomic_load16(a)
#define my_atomic_load32(a,L) _my_atomic_load32(a)
#define my_atomic_store8(a,v,L) _my_atomic_store8(a,v)
#define my_atomic_store16(a,v,L) _my_atomic_store16(a,v)
#define my_atomic_store32(a,v,L) _my_atomic_store32(a,v)
#define my_atomic_swap8(a,v,L) _my_atomic_swap8(a,v)
#define my_atomic_swap16(a,v,L) _my_atomic_swap16(a,v)
#define my_atomic_swap32(a,v,L) _my_atomic_swap32(a,v)
#define my_atomic_rwlock_t typedef int
#define my_atomic_rwlock_destroy(name)
#define my_atomic_rwlock_init(name)
#define my_atomic_rwlock_rdlock(name)
#define my_atomic_rwlock_wrlock(name)
#define my_atomic_rwlock_rdunlock(name)
#define my_atomic_rwlock_wrunlock(name)
#endif
/* Copyright (C) 2006 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 */
typedef struct {pthread_rwlock_t rw;} my_atomic_rwlock_t;
#ifdef MY_ATOMIC_EXTRA_DEBUG
#define CHECK_RW if (rw) if (a->rw) assert(rw == a->rw); else a->rw=rw;
#else
#define CHECK_RW
#endif
#ifdef MY_ATOMIC_MODE_DUMMY
/*
the following can never be enabled by ./configure, one need to put #define in
a source to trigger the following warning. The resulting code will be broken,
it only makes sense to do it to see now test_atomic detects broken
implementations (another way is to run a UP build on an SMP box).
*/
#warning MY_ATOMIC_MODE_DUMMY and MY_ATOMIC_MODE_RWLOCKS are incompatible
#define my_atomic_rwlock_destroy(name)
#define my_atomic_rwlock_init(name)
#define my_atomic_rwlock_rdlock(name)
#define my_atomic_rwlock_wrlock(name)
#define my_atomic_rwlock_rdunlock(name)
#define my_atomic_rwlock_wrunlock(name)
#else
#define my_atomic_rwlock_destroy(name) pthread_rwlock_destroy(& (name)->rw)
#define my_atomic_rwlock_init(name) pthread_rwlock_init(& (name)->rw, 0)
#define my_atomic_rwlock_rdlock(name) pthread_rwlock_rdlock(& (name)->rw)
#define my_atomic_rwlock_wrlock(name) pthread_rwlock_wrlock(& (name)->rw)
#define my_atomic_rwlock_rdunlock(name) pthread_rwlock_unlock(& (name)->rw)
#define my_atomic_rwlock_wrunlock(name) pthread_rwlock_unlock(& (name)->rw)
#endif
#ifdef HAVE_INLINE
#define make_atomic_add(S) \
static inline uint ## S my_atomic_add ## S( \
my_atomic_ ## S ## _t *a, uint ## S v, my_atomic_rwlock_t *rw) \
{ \
uint ## S ret; \
CHECK_RW; \
if (rw) my_atomic_rwlock_wrlock(rw); \
ret= a->val; \
a->val+= v; \
if (rw) my_atomic_rwlock_wrunlock(rw); \
return ret; \
}
#define make_atomic_swap(S) \
static inline uint ## S my_atomic_swap ## S( \
my_atomic_ ## S ## _t *a, uint ## S v, my_atomic_rwlock_t *rw) \
{ \
uint ## S ret; \
CHECK_RW; \
if (rw) my_atomic_rwlock_wrlock(rw); \
ret= a->val; \
a->val= v; \
if (rw) my_atomic_rwlock_wrunlock(rw); \
return ret; \
}
#define make_atomic_cas(S) \
static inline uint my_atomic_cas ## S(my_atomic_ ## S ## _t *a, \
uint ## S *cmp, uint ## S set, my_atomic_rwlock_t *rw) \
{ \
uint ret; \
CHECK_RW; \
if (rw) my_atomic_rwlock_wrlock(rw); \
if (ret= (a->val == *cmp)) a->val= set; else *cmp=a->val; \
if (rw) my_atomic_rwlock_wrunlock(rw); \
return ret; \
}
#define make_atomic_load(S) \
static inline uint ## S my_atomic_load ## S( \
my_atomic_ ## S ## _t *a, my_atomic_rwlock_t *rw) \
{ \
uint ## S ret; \
CHECK_RW; \
if (rw) my_atomic_rwlock_wrlock(rw); \
ret= a->val; \
if (rw) my_atomic_rwlock_wrunlock(rw); \
return ret; \
}
#define make_atomic_store(S) \
static inline void my_atomic_store ## S( \
my_atomic_ ## S ## _t *a, uint ## S v, my_atomic_rwlock_t *rw) \
{ \
CHECK_RW; \
if (rw) my_atomic_rwlock_rdlock(rw); \
(a)->val= (v); \
if (rw) my_atomic_rwlock_rdunlock(rw); \
}
#else /* no inline functions */
#define make_atomic_add(S) \
extern uint ## S my_atomic_add ## S( \
my_atomic_ ## S ## _t *a, uint ## S v, my_atomic_rwlock_t *rw);
#define make_atomic_swap(S) \
extern uint ## S my_atomic_swap ## S( \
my_atomic_ ## S ## _t *a, uint ## S v, my_atomic_rwlock_t *rw);
#define make_atomic_cas(S) \
extern uint my_atomic_cas ## S(my_atomic_ ## S ## _t *a, \
uint ## S *cmp, uint ## S set, my_atomic_rwlock_t *rw);
#define make_atomic_load(S) \
extern uint ## S my_atomic_load ## S( \
my_atomic_ ## S ## _t *a, my_atomic_rwlock_t *rw);
#define make_atomic_store(S) \
extern void my_atomic_store ## S( \
my_atomic_ ## S ## _t *a, uint ## S v, my_atomic_rwlock_t *rw);
#endif
make_atomic_add( 8)
make_atomic_add(16)
make_atomic_add(32)
make_atomic_add(64)
make_atomic_cas( 8)
make_atomic_cas(16)
make_atomic_cas(32)
make_atomic_cas(64)
make_atomic_load( 8)
make_atomic_load(16)
make_atomic_load(32)
make_atomic_load(64)
make_atomic_store( 8)
make_atomic_store(16)
make_atomic_store(32)
make_atomic_store(64)
make_atomic_swap( 8)
make_atomic_swap(16)
make_atomic_swap(32)
make_atomic_swap(64)
#undef make_atomic_add
#undef make_atomic_cas
#undef make_atomic_load
#undef make_atomic_store
#undef make_atomic_swap
#undef CHECK_RW
/* Copyright (C) 2006 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 */
/*
XXX 64-bit atomic operations can be implemented using
cmpxchg8b, if necessary
*/
#define make_atomic_add_body8 \
asm volatile (LOCK "xadd %0, %1;" : "+r" (v) , "+m" (a->val))
#define make_atomic_swap_body8 \
asm volatile ("xchg %0, %1;" : "+r" (v) , "+m" (a->val))
#define make_atomic_cas_body8 \
asm volatile (LOCK "cmpxchg %3, %0; setz %2;" \
: "+m" (a->val), "+a" (*cmp), "=q" (ret): "r" (set))
#ifdef MY_ATOMIC_MODE_DUMMY
#define make_atomic_load_body8 ret=a->val
#define make_atomic_store_body8 a->val=v
#else
/*
Actually 32-bit reads/writes are always atomic on x86
But we add LOCK here anyway to force memory barriers
*/
#define make_atomic_load_body8 \
ret=0; \
asm volatile (LOCK "cmpxchg %2, %0" \
: "+m" (a->val), "+a" (ret): "r" (ret))
#define make_atomic_store_body8 \
asm volatile ("xchg %0, %1;" : "+m" (a->val) : "r" (v))
#endif
#define make_atomic_add_body16 make_atomic_add_body8
#define make_atomic_add_body32 make_atomic_add_body8
#define make_atomic_cas_body16 make_atomic_cas_body8
#define make_atomic_cas_body32 make_atomic_cas_body8
#define make_atomic_load_body16 make_atomic_load_body8
#define make_atomic_load_body32 make_atomic_load_body8
#define make_atomic_store_body16 make_atomic_store_body8
#define make_atomic_store_body32 make_atomic_store_body8
#define make_atomic_swap_body16 make_atomic_swap_body8
#define make_atomic_swap_body32 make_atomic_swap_body8
/* Copyright (C) 2006 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 */
/*
XXX 64-bit atomic operations can be implemented using
cmpxchg8b, if necessary
*/
// Would it be better to use intrinsics ?
// (InterlockedCompareExchange, InterlockedCompareExchange16
// InterlockedExchangeAdd, InterlockedExchange)
#define make_atomic_add_body(REG) \
_asm { \
_asm mov REG, v \
_asm LOCK xadd a->val, REG \
_asm movzx v, REG \
}
#define make_atomic_cas_body(AREG,REG2) \
_asm { \
_asm mov AREG, *cmp \
_asm mov REG2, set \
_asm LOCK cmpxchg a->val, REG2 \
_asm mov *cmp, AREG \
_asm setz al \
_asm movzx ret, al \
}
#define make_atomic_swap_body(REG) \
_asm { \
_asm mov REG, v \
_asm xchg a->val, REG \
_asm mov v, REG \
}
#ifdef MY_ATOMIC_MODE_DUMMY
#define make_atomic_load_body(AREG,REG) ret=a->val
#define make_atomic_store_body(REG) a->val=v
#else
/*
Actually 32-bit reads/writes are always atomic on x86
But we add LOCK here anyway to force memory barriers
*/
#define make_atomic_load_body(AREG,REG2) \
_asm { \
_asm mov AREG, 0 \
_asm mov REG2, AREG \
_asm LOCK cmpxchg a->val, REG2 \
_asm mov ret, AREG \
}
#define make_atomic_store_body(REG) \
_asm { \
_asm mov REG, v \
_asm xchg a->val, REG \
}
#endif
#define make_atomic_add_body8 make_atomic_add_body(al)
#define make_atomic_add_body16 make_atomic_add_body(ax)
#define make_atomic_add_body32 make_atomic_add_body(eax)
#define make_atomic_cas_body8 make_atomic_cas_body(al, bl)
#define make_atomic_cas_body16 make_atomic_cas_body(ax, bx)
#define make_atomic_cas_body32 make_atomic_cas_body(eax, ebx)
#define make_atomic_load_body8 make_atomic_load_body(al, bl)
#define make_atomic_load_body16 make_atomic_load_body(ax, bx)
#define make_atomic_load_body32 make_atomic_load_body(eax, ebx)
#define make_atomic_store_body8 make_atomic_store_body(al)
#define make_atomic_store_body16 make_atomic_store_body(ax)
#define make_atomic_store_body32 make_atomic_store_body(eax)
#define make_atomic_swap_body8 make_atomic_swap_body(al)
#define make_atomic_swap_body16 make_atomic_swap_body(ax)
#define make_atomic_swap_body32 make_atomic_swap_body(eax)
/* Copyright (C) 2006 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 */
#ifndef atomic_rwlock_init
#ifdef MY_ATOMIC_EXTRA_DEBUG
#ifndef MY_ATOMIC_MODE_RWLOCKS
#error MY_ATOMIC_EXTRA_DEBUG can be only used with MY_ATOMIC_MODE_RWLOCKS
#endif
#define LOCK_PTR void *rw;
#else
#define LOCK_PTR
#endif
typedef volatile struct {uint8 val; LOCK_PTR} my_atomic_8_t;
typedef volatile struct {uint16 val; LOCK_PTR} my_atomic_16_t;
typedef volatile struct {uint32 val; LOCK_PTR} my_atomic_32_t;
typedef volatile struct {uint64 val; LOCK_PTR} my_atomic_64_t;
#ifndef MY_ATOMIC_MODE_RWLOCKS
#include "atomic/nolock.h"
#endif
#ifndef my_atomic_rwlock_init
#include "atomic/rwlock.h"
#endif
#define MY_ATOMIC_OK 0
#define MY_ATOMIC_NOT_1CPU 1
extern int my_atomic_initialize();
#endif
......@@ -181,6 +181,17 @@
#define HOT_DATA
#endif
/*
now let's figure out if inline functions are supported
autoconf defines 'inline' to be empty, if not
*/
#define inline_test_1(X) X ## 1
#define inline_test_2(X) inline_test_1(X)
#if inline_test_2(inline) != 1
#define HAVE_INLINE
#endif
#undef inline_test_2
#undef inline_test_1
/*
The following macros are used to control inlining a bit more than
......@@ -889,6 +900,8 @@ typedef unsigned long ulonglong; /* ulong or unsigned long long */
typedef long longlong;
#endif
#endif
typedef longlong int64;
typedef ulonglong uint64;
#if defined(NO_CLIENT_LONG_LONG)
typedef unsigned long my_ulonglong;
......
......@@ -98,9 +98,11 @@ struct st_mysql_plugin
API for Full-text parser plugin. (MYSQL_FTPARSER_PLUGIN)
*/
#define MYSQL_FTPARSER_INTERFACE_VERSION 0x0000
#define MYSQL_FTPARSER_INTERFACE_VERSION 0x0100
/* Parsing modes. Set in MYSQL_FTPARSER_PARAM::mode */
enum enum_ftparser_mode
{
/*
Fast and simple mode. This mode is used for indexing, and natural
language queries.
......@@ -109,7 +111,7 @@ struct st_mysql_plugin
index. Stopwords or too short/long words should not be returned. The
'boolean_info' argument of mysql_add_word() does not have to be set.
*/
#define MYSQL_FTPARSER_SIMPLE_MODE 0
MYSQL_FTPARSER_SIMPLE_MODE= 0,
/*
Parse with stopwords mode. This mode is used in boolean searches for
......@@ -120,7 +122,7 @@ struct st_mysql_plugin
or long. The 'boolean_info' argument of mysql_add_word() does not
have to be set.
*/
#define MYSQL_FTPARSER_WITH_STOPWORDS 1
MYSQL_FTPARSER_WITH_STOPWORDS= 1,
/*
Parse in boolean mode. This mode is used to parse a boolean query string.
......@@ -133,7 +135,8 @@ struct st_mysql_plugin
MYSQL_FTPARSER_WITH_STOPWORDS mode, no word should be ignored.
Instead, use FT_TOKEN_STOPWORD for the token type of such a word.
*/
#define MYSQL_FTPARSER_FULL_BOOLEAN_INFO 2
MYSQL_FTPARSER_FULL_BOOLEAN_INFO= 2
};
/*
Token types for boolean mode searching (used for the type member of
......@@ -198,6 +201,17 @@ typedef struct st_mysql_ftparser_boolean_info
char *quot;
} MYSQL_FTPARSER_BOOLEAN_INFO;
/*
The following flag means that buffer with a string (document, word)
may be overwritten by the caller before the end of the parsing (that is
before st_mysql_ftparser::deinit() call). If one needs the string
to survive between two successive calls of the parsing function, she
needs to save a copy of it. The flag may be set by MySQL before calling
st_mysql_ftparser::parse(), or it may be set by a plugin before calling
st_mysql_ftparser_param::mysql_parse() or
st_mysql_ftparser_param::mysql_add_word().
*/
#define MYSQL_FTFLAGS_NEED_COPY 1
/*
An argument of the full-text parser plugin. This structure is
......@@ -209,22 +223,20 @@ typedef struct st_mysql_ftparser_boolean_info
to invoke the MySQL default parser. If plugin's role is to extract
textual data from .doc, .pdf or .xml content, it might extract
plaintext from the content, and then pass the text to the default
MySQL parser to be parsed. When mysql_parser is called, its param
argument should be given as the mysql_ftparam value.
MySQL parser to be parsed.
mysql_add_word: A server callback to add a new word. When parsing
a document, the server sets this to point at a function that adds
the word to MySQL full-text index. When parsing a search query,
this function will add the new word to the list of words to search
for. When mysql_add_word is called, its param argument should be
given as the mysql_ftparam value. boolean_info can be NULL for all
cases except when mode is MYSQL_FTPARSER_FULL_BOOLEAN_INFO.
for. The boolean_info argument can be NULL for all cases except
when mode is MYSQL_FTPARSER_FULL_BOOLEAN_INFO.
ftparser_state: A generic pointer. The plugin can set it to point
to information to be used internally for its own purposes.
mysql_ftparam: This is set by the server. It is passed as the first
argument to the mysql_parse or mysql_add_word callback. The plugin
mysql_ftparam: This is set by the server. It is used by MySQL functions
called via mysql_parse() and mysql_add_word() callback. The plugin
should not modify it.
cs: Information about the character set of the document or query string.
......@@ -233,21 +245,26 @@ typedef struct st_mysql_ftparser_boolean_info
length: Length of the document or query string, in bytes.
flags: See MYSQL_FTFLAGS_* constants above.
mode: The parsing mode. With boolean operators, with stopwords, or
nothing. See MYSQL_FTPARSER_* constants above.
nothing. See enum_ftparser_mode above.
*/
typedef struct st_mysql_ftparser_param
{
int (*mysql_parse)(void *param, char *doc, int doc_len);
int (*mysql_add_word)(void *param, char *word, int word_len,
int (*mysql_parse)(struct st_mysql_ftparser_param *,
char *doc, int doc_len);
int (*mysql_add_word)(struct st_mysql_ftparser_param *,
char *word, int word_len,
MYSQL_FTPARSER_BOOLEAN_INFO *boolean_info);
void *ftparser_state;
void *mysql_ftparam;
struct charset_info_st *cs;
char *doc;
int length;
int mode;
int flags;
enum enum_ftparser_mode mode;
} MYSQL_FTPARSER_PARAM;
/*
......
......@@ -20,8 +20,7 @@ MYSQLBASEdir= $(prefix)
INCLUDES = @ZLIB_INCLUDES@ -I$(top_builddir)/include \
-I$(top_srcdir)/include -I$(srcdir)
pkglib_LIBRARIES = libmysys.a
LDADD = libmysys.a ../dbug/libdbug.a \
../strings/libmystrings.a
LDADD = libmysys.a $(top_builddir)/strings/libmystrings.a
noinst_HEADERS = mysys_priv.h my_static.h
libmysys_a_SOURCES = my_init.c my_getwd.c mf_getdate.c my_mmap.c \
mf_path.c mf_loadpath.c my_file.c \
......@@ -32,7 +31,7 @@ libmysys_a_SOURCES = my_init.c my_getwd.c mf_getdate.c my_mmap.c \
mf_tempdir.c my_lock.c mf_brkhant.c my_alarm.c \
my_malloc.c my_realloc.c my_once.c mulalloc.c \
my_alloc.c safemalloc.c my_new.cc \
my_vle.c \
my_vle.c my_atomic.c \
my_fopen.c my_fstream.c my_getsystime.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 \
......@@ -40,7 +39,7 @@ libmysys_a_SOURCES = my_init.c my_getwd.c mf_getdate.c my_mmap.c \
mf_pack.c mf_unixpath.c mf_strip.c \
mf_wcomp.c mf_wfile.c my_gethwaddr.c \
mf_qsort.c mf_qsort2.c mf_sort.c \
ptr_cmp.c mf_radix.c queues.c \
ptr_cmp.c mf_radix.c queues.c my_getncpus.c \
tree.c trie.c list.c hash.c array.c string.c typelib.c \
my_copy.c my_append.c my_lib.c \
my_delete.c my_rename.c my_redel.c \
......@@ -64,7 +63,7 @@ libmysys_a_LIBADD = @THREAD_LOBJECTS@
# testhash_DEPENDENCIES= $(LIBRARIES)
# test_charset_DEPENDENCIES= $(LIBRARIES)
# charset2html_DEPENDENCIES= $(LIBRARIES)
EXTRA_PROGRAMS =
noinst_PROGRAMS= test_atomic$(EXEEXT)
DEFS = -DDEFAULT_BASEDIR=\"$(prefix)\" \
-DDATADIR="\"$(MYSQLDATAdir)\"" \
-DDEFAULT_CHARSET_HOME="\"$(MYSQLBASEdir)\"" \
......
/* Copyright (C) 2006 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 */
#include <my_global.h>
#include <my_pthread.h>
#ifndef HAVE_INLINE
/*
the following will cause all inline functions to be instantiated
*/
#define HAVE_INLINE
#define static extern
#endif
#include <my_atomic.h>
/*
checks that the current build of atomic ops
can run on this machine
RETURN
ATOMIC_xxx values, see my_atomic.h
*/
int my_atomic_initialize()
{
/* currently the only thing worth checking is SMP/UP issue */
#ifdef MY_ATOMIC_MODE_DUMMY
return my_getncpus() == 1 ? MY_ATOMIC_OK : MY_ATOMIC_NOT_1CPU;
#else
return MY_ATOMIC_OK;
#endif
}
/* Copyright (C) 2006 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 */
/* get the number of (online) CPUs */
#include "mysys_priv.h"
#include <unistd.h>
static int ncpus=0;
#ifdef _SC_NPROCESSORS_ONLN
int my_getncpus()
{
if (!ncpus)
ncpus= sysconf(_SC_NPROCESSORS_ONLN);
return ncpus;
}
#else
/* unknown */
int my_getncpus()
{
return 2;
}
#endif
#include <my_global.h>
#include <my_sys.h>
#include <my_atomic.h>
my_atomic_32_t a32,b32,c32;
my_atomic_rwlock_t rwl;
pthread_attr_t thr_attr;
pthread_mutex_t mutex;
pthread_cond_t cond;
int N;
/* add and sub a random number in a loop. Must get 0 at the end */
pthread_handler_t test_atomic_add_handler(void *arg)
{
int m=*(int *)arg;
int32 x;
for (x=((int)(&m)); m ; m--)
{
x=x*m+0x87654321;
my_atomic_add32(&a32, x, &rwl);
my_atomic_add32(&a32, -x, &rwl);
}
pthread_mutex_lock(&mutex);
N--;
if (!N) pthread_cond_signal(&cond);
pthread_mutex_unlock(&mutex);
}
/*
1. generate thread number 0..N-1 from b32
2. add it to a32
3. swap thread numbers in c32
4. (optionally) one more swap to avoid 0 as a result
5. subtract result from a32
must get 0 in a32 at the end
*/
pthread_handler_t test_atomic_swap_handler(void *arg)
{
int m=*(int *)arg;
uint32 x=my_atomic_add32(&b32, 1, &rwl);
my_atomic_add32(&a32, x, &rwl);
for (; m ; m--)
x=my_atomic_swap32(&c32, x,&rwl);
if (!x)
x=my_atomic_swap32(&c32, x,&rwl);
my_atomic_add32(&a32, -x, &rwl);
pthread_mutex_lock(&mutex);
N--;
if (!N) pthread_cond_signal(&cond);
pthread_mutex_unlock(&mutex);
}
/*
same as test_atomic_add_handler, but my_atomic_add32 is emulated with
(slower) my_atomic_cas32
*/
pthread_handler_t test_atomic_cas_handler(void *arg)
{
int m=*(int *)arg;
int32 x;
for (x=((int)(&m)); m ; m--)
{
uint32 y=my_atomic_load32(&a32, &rwl);
x=x*m+0x87654321;
while (!my_atomic_cas32(&a32, &y, y+x, &rwl)) ;
while (!my_atomic_cas32(&a32, &y, y-x, &rwl)) ;
}
pthread_mutex_lock(&mutex);
N--;
if (!N) pthread_cond_signal(&cond);
pthread_mutex_unlock(&mutex);
}
void test_atomic(const char *test, pthread_handler handler, int n, int m)
{
pthread_t t;
ulonglong now=my_getsystime();
my_atomic_store32(&a32, 0, &rwl);
my_atomic_store32(&b32, 0, &rwl);
my_atomic_store32(&c32, 0, &rwl);
printf("Testing %s with %d threads, %d iterations... ", test, n, m);
for (N=n ; n ; n--)
pthread_create(&t, &thr_attr, handler, &m);
pthread_mutex_lock(&mutex);
while (N)
pthread_cond_wait(&cond, &mutex);
pthread_mutex_unlock(&mutex);
now=my_getsystime()-now;
printf("got %lu in %g secs\n", my_atomic_load32(&a32, &rwl),
((double)now)/1e7);
}
int main()
{
int err;
#ifdef _IONBF
setvbuf(stdout, 0, _IONBF, 0);
#endif
printf("N CPUs: %d\n", my_getncpus());
if ((err= my_atomic_initialize()))
{
printf("my_atomic_initialize() failed. Error=%d\n", err);
return 1;
}
pthread_attr_init(&thr_attr);
pthread_attr_setdetachstate(&thr_attr,PTHREAD_CREATE_DETACHED);
pthread_mutex_init(&mutex, 0);
pthread_cond_init(&cond, 0);
my_atomic_rwlock_init(&rwl);
test_atomic("my_atomic_add32", test_atomic_add_handler, 100,1000000);
test_atomic("my_atomic_swap32", test_atomic_swap_handler, 100,1000000);
test_atomic("my_atomic_cas32", test_atomic_cas_handler, 100,1000000);
pthread_mutex_destroy(&mutex);
pthread_cond_destroy(&cond);
pthread_attr_destroy(&thr_attr);
my_atomic_rwlock_destroy(&rwl);
return 0;
}
......@@ -144,10 +144,7 @@ static void add_word(MYSQL_FTPARSER_PARAM *param, char *word, size_t len)
MYSQL_FTPARSER_BOOLEAN_INFO bool_info=
{ FT_TOKEN_WORD, 0, 0, 0, 0, ' ', 0 };
if (param->mode == MYSQL_FTPARSER_FULL_BOOLEAN_INFO)
param->mysql_add_word(param->mysql_ftparam, word, len, &bool_info);
else
param->mysql_add_word(param->mysql_ftparam, word, len, 0);
param->mysql_add_word(param, word, len, &bool_info);
}
/*
......
......@@ -1632,6 +1632,8 @@ public:
#endif
char *str_to_hex(char *to, const char *from, uint len);
#ifdef HAVE_ROW_BASED_REPLICATION
/*****************************************************************************
Table map log event class
......@@ -1640,7 +1642,6 @@ char *str_to_hex(char *to, const char *from, uint len);
identifier (an integer number).
****************************************************************************/
class Table_map_log_event : public Log_event
{
public:
......@@ -1747,6 +1748,7 @@ private:
****************************************************************************/
class Rows_log_event : public Log_event
{
public:
......@@ -2118,5 +2120,6 @@ private:
#endif
};
#endif /* HAVE_ROW_BASED_REPLICATION */
#endif /* _log_event_h */
......@@ -47,8 +47,8 @@ static int min_plugin_interface_version= 0x0000;
static int min_plugin_info_interface_version[MYSQL_MAX_PLUGIN_TYPE_NUM]=
{
0x0000,
0x0000,
0x0000
MYSQL_HANDLERTON_INTERFACE_VERSION,
MYSQL_FTPARSER_INTERFACE_VERSION
};
static int cur_plugin_info_interface_version[MYSQL_MAX_PLUGIN_TYPE_NUM]=
{
......@@ -56,6 +56,7 @@ static int cur_plugin_info_interface_version[MYSQL_MAX_PLUGIN_TYPE_NUM]=
MYSQL_HANDLERTON_INTERFACE_VERSION,
MYSQL_FTPARSER_INTERFACE_VERSION
};
static DYNAMIC_ARRAY plugin_dl_array;
static DYNAMIC_ARRAY plugin_array;
static HASH plugin_hash[MYSQL_MAX_PLUGIN_TYPE_NUM];
......
......@@ -2355,12 +2355,23 @@ table_check_intact(TABLE *table, uint table_f_count,
// previous MySQL version
error= TRUE;
if (MYSQL_VERSION_ID > table->s->mysql_version)
{
my_error(ER_COL_COUNT_DOESNT_MATCH_PLEASE_UPDATE, MYF(0), table->alias,
table_f_count, table->s->fields, table->s->mysql_version,
MYSQL_VERSION_ID);
sql_print_error(ER(ER_COL_COUNT_DOESNT_MATCH_PLEASE_UPDATE),
table->alias, table_f_count, table->s->fields,
table->s->mysql_version, MYSQL_VERSION_ID);
DBUG_RETURN(error);
}
else if (MYSQL_VERSION_ID == table->s->mysql_version)
{
my_error(ER_COL_COUNT_DOESNT_MATCH_CORRUPTED,MYF(0), table->alias,
table_f_count, table->s->fields);
sql_print_error(ER(ER_COL_COUNT_DOESNT_MATCH_CORRUPTED), table->alias,
table_f_count, table->s->fields);
}
else
/*
moving from newer mysql to older one -> let's say not an error but
......
......@@ -160,7 +160,6 @@ static int FTB_WORD_cmp_list(CHARSET_INFO *cs, FTB_WORD **a, FTB_WORD **b)
typedef struct st_my_ftb_param
{
MYSQL_FTPARSER_PARAM *up;
FTB *ftb;
FTB_EXPR *ftbe;
byte *up_quot;
......@@ -168,10 +167,11 @@ typedef struct st_my_ftb_param
} MY_FTB_PARAM;
static int ftb_query_add_word(void *param, char *word, int word_len,
static int ftb_query_add_word(MYSQL_FTPARSER_PARAM *param,
char *word, int word_len,
MYSQL_FTPARSER_BOOLEAN_INFO *info)
{
MY_FTB_PARAM *ftb_param= (MY_FTB_PARAM *)param;
MY_FTB_PARAM *ftb_param= param->mysql_ftparam;
FTB_WORD *ftbw;
FTB_EXPR *ftbe, *tmp_expr;
FT_WORD *phrase_word;
......@@ -269,9 +269,10 @@ static int ftb_query_add_word(void *param, char *word, int word_len,
}
static int ftb_parse_query_internal(void *param, char *query, int len)
static int ftb_parse_query_internal(MYSQL_FTPARSER_PARAM *param,
char *query, int len)
{
MY_FTB_PARAM *ftb_param= (MY_FTB_PARAM *)param;
MY_FTB_PARAM *ftb_param= param->mysql_ftparam;
MYSQL_FTPARSER_BOOLEAN_INFO info;
CHARSET_INFO *cs= ftb_param->ftb->charset;
char **start= &query;
......@@ -281,7 +282,7 @@ static int ftb_parse_query_internal(void *param, char *query, int len)
info.prev= ' ';
info.quot= 0;
while (ft_get_word(cs, start, end, &w, &info))
ftb_param->up->mysql_add_word(param, w.pos, w.len, &info);
param->mysql_add_word(param, w.pos, w.len, &info);
return(0);
}
......@@ -299,7 +300,6 @@ static void _ftb_parse_query(FTB *ftb, byte *query, uint len,
if (! (param= ftparser_call_initializer(ftb->info, ftb->keynr, 0)))
DBUG_VOID_RETURN;
ftb_param.up= param;
ftb_param.ftb= ftb;
ftb_param.depth= 0;
ftb_param.ftbe= ftb->root;
......@@ -311,6 +311,7 @@ static void _ftb_parse_query(FTB *ftb, byte *query, uint len,
param->cs= ftb->charset;
param->doc= query;
param->length= len;
param->flags= 0;
param->mode= MYSQL_FTPARSER_FULL_BOOLEAN_INFO;
parser->parse(param);
DBUG_VOID_RETURN;
......@@ -571,7 +572,6 @@ err:
typedef struct st_my_ftb_phrase_param
{
MYSQL_FTPARSER_PARAM *up;
LIST *phrase;
LIST *document;
CHARSET_INFO *cs;
......@@ -581,10 +581,11 @@ typedef struct st_my_ftb_phrase_param
} MY_FTB_PHRASE_PARAM;
static int ftb_phrase_add_word(void *param, char *word, int word_len,
static int ftb_phrase_add_word(MYSQL_FTPARSER_PARAM *param,
char *word, int word_len,
MYSQL_FTPARSER_BOOLEAN_INFO *boolean_info __attribute__((unused)))
{
MY_FTB_PHRASE_PARAM *phrase_param= (MY_FTB_PHRASE_PARAM *)param;
MY_FTB_PHRASE_PARAM *phrase_param= param->mysql_ftparam;
FT_WORD *w= (FT_WORD *)phrase_param->document->data;
LIST *phrase, *document;
w->pos= word;
......@@ -611,14 +612,15 @@ static int ftb_phrase_add_word(void *param, char *word, int word_len,
}
static int ftb_check_phrase_internal(void *param, char *document, int len)
static int ftb_check_phrase_internal(MYSQL_FTPARSER_PARAM *param,
char *document, int len)
{
FT_WORD word;
MY_FTB_PHRASE_PARAM *phrase_param= (MY_FTB_PHRASE_PARAM *)param;
MY_FTB_PHRASE_PARAM *phrase_param= param->mysql_ftparam;
const char *docend= document + len;
while (ft_simple_get_word(phrase_param->cs, &document, docend, &word, FALSE))
{
phrase_param->up->mysql_add_word(param, word.pos, word.len, 0);
param->mysql_add_word(param, word.pos, word.len, 0);
if (phrase_param->match)
return 1;
}
......@@ -651,7 +653,6 @@ static int _ftb_check_phrase(FTB *ftb, const byte *document, uint len,
if (! (param= ftparser_call_initializer(ftb->info, ftb->keynr, 1)))
DBUG_RETURN(0);
ftb_param.up= param;
ftb_param.phrase= ftbe->phrase;
ftb_param.document= ftbe->document;
ftb_param.cs= ftb->charset;
......@@ -665,6 +666,7 @@ static int _ftb_check_phrase(FTB *ftb, const byte *document, uint len,
param->cs= ftb->charset;
param->doc= (byte *)document;
param->length= len;
param->flags= 0;
param->mode= MYSQL_FTPARSER_WITH_STOPWORDS;
parser->parse(param);
DBUG_RETURN(ftb_param.match ? 1 : 0);
......@@ -820,16 +822,16 @@ err:
typedef struct st_my_ftb_find_param
{
MYSQL_FTPARSER_PARAM *up;
FT_INFO *ftb;
FT_SEG_ITERATOR *ftsi;
} MY_FTB_FIND_PARAM;
static int ftb_find_relevance_add_word(void *param, char *word, int len,
static int ftb_find_relevance_add_word(MYSQL_FTPARSER_PARAM *param,
char *word, int len,
MYSQL_FTPARSER_BOOLEAN_INFO *boolean_info __attribute__((unused)))
{
MY_FTB_FIND_PARAM *ftb_param= (MY_FTB_FIND_PARAM *)param;
MY_FTB_FIND_PARAM *ftb_param= param->mysql_ftparam;
FT_INFO *ftb= ftb_param->ftb;
FTB_WORD *ftbw;
int a, b, c;
......@@ -859,14 +861,15 @@ static int ftb_find_relevance_add_word(void *param, char *word, int len,
}
static int ftb_find_relevance_parse(void *param, char *doc, int len)
static int ftb_find_relevance_parse(MYSQL_FTPARSER_PARAM *param,
char *doc, int len)
{
MY_FTB_FIND_PARAM *ftb_param=(MY_FTB_FIND_PARAM *)param;
MY_FTB_FIND_PARAM *ftb_param= param->mysql_ftparam;
FT_INFO *ftb= ftb_param->ftb;
char *end= doc + len;
FT_WORD w;
while (ft_simple_get_word(ftb->charset, &doc, end, &w, TRUE))
ftb_param->up->mysql_add_word(param, w.pos, w.len, 0);
param->mysql_add_word(param, w.pos, w.len, 0);
return(0);
}
......@@ -910,12 +913,12 @@ float ft_boolean_find_relevance(FT_INFO *ftb, byte *record, uint length)
_mi_ft_segiterator_init(ftb->info, ftb->keynr, record, &ftsi);
memcpy(&ftsi2, &ftsi, sizeof(ftsi));
ftb_param.up= param;
ftb_param.ftb= ftb;
ftb_param.ftsi= &ftsi2;
param->mysql_parse= ftb_find_relevance_parse;
param->mysql_add_word= ftb_find_relevance_add_word;
param->mysql_ftparam= (void *)&ftb_param;
param->flags= 0;
param->cs= ftb->charset;
param->mode= MYSQL_FTPARSER_SIMPLE_MODE;
while (_mi_ft_segiterator(&ftsi))
......
......@@ -235,7 +235,9 @@ FT_INFO *ft_init_nlq_search(MI_INFO *info, uint keynr, byte *query,
NULL, NULL);
ft_parse_init(&wtree, aio.charset);
if (ft_parse(&wtree, query, query_len, 0, parser, ftparser_param))
ftparser_param->flags= 0;
if (ft_parse(&wtree, query, query_len, parser, ftparser_param,
&wtree.mem_root))
goto err;
if (tree_walk(&wtree, (tree_walk_action)&walk_and_match, &aio,
......@@ -255,7 +257,9 @@ FT_INFO *ft_init_nlq_search(MI_INFO *info, uint keynr, byte *query,
if (!(*info->read_record)(info,docid,record))
{
info->update|= HA_STATE_AKTIV;
_mi_ft_parse(&wtree, info, keynr, record, 1, ftparser_param);
ftparser_param->flags= MYSQL_FTFLAGS_NEED_COPY;
_mi_ft_parse(&wtree, info, keynr, record, ftparser_param,
&wtree.mem_root);
}
}
delete_queue(&best);
......
......@@ -24,15 +24,12 @@ typedef struct st_ft_docstat {
double sum;
} FT_DOCSTAT;
typedef struct st_my_ft_parser_param
{
MYSQL_FTPARSER_PARAM *up;
TREE *wtree;
my_bool with_alloc;
TREE *wtree;
MEM_ROOT *mem_root;
} MY_FT_PARSER_PARAM;
static int FT_WORD_cmp(CHARSET_INFO* cs, FT_WORD *w1, FT_WORD *w2)
{
return mi_compare_text(cs, (uchar*) w1->pos, w1->len,
......@@ -49,14 +46,14 @@ static int walk_and_copy(FT_WORD *word,uint32 count,FT_DOCSTAT *docstat)
/* transforms tree of words into the array, applying normalization */
FT_WORD * ft_linearize(TREE *wtree)
FT_WORD * ft_linearize(TREE *wtree, MEM_ROOT *mem_root)
{
FT_WORD *wlist,*p;
FT_DOCSTAT docstat;
DBUG_ENTER("ft_linearize");
if ((wlist=(FT_WORD *) my_malloc(sizeof(FT_WORD)*
(1+wtree->elements_in_tree),MYF(0))))
if ((wlist=(FT_WORD *) alloc_root(mem_root, sizeof(FT_WORD)*
(1+wtree->elements_in_tree))))
{
docstat.list=wlist;
docstat.uniq=wtree->elements_in_tree;
......@@ -241,19 +238,20 @@ void ft_parse_init(TREE *wtree, CHARSET_INFO *cs)
}
static int ft_add_word(void *param, byte *word, uint word_len,
static int ft_add_word(MYSQL_FTPARSER_PARAM *param,
char *word, int word_len,
MYSQL_FTPARSER_BOOLEAN_INFO *boolean_info __attribute__((unused)))
{
TREE *wtree;
FT_WORD w;
MY_FT_PARSER_PARAM *ft_param=param->mysql_ftparam;
DBUG_ENTER("ft_add_word");
wtree= ((MY_FT_PARSER_PARAM *)param)->wtree;
if (((MY_FT_PARSER_PARAM *)param)->with_alloc)
wtree= ft_param->wtree;
if (param->flags & MYSQL_FTFLAGS_NEED_COPY)
{
byte *ptr;
/* allocating the data in the tree - to avoid mallocs and frees */
DBUG_ASSERT(wtree->with_delete == 0);
ptr= (byte *)alloc_root(&wtree->mem_root, word_len);
ptr= (byte *)alloc_root(ft_param->mem_root, word_len);
memcpy(ptr, word, word_len);
w.pos= ptr;
}
......@@ -269,32 +267,32 @@ static int ft_add_word(void *param, byte *word, uint word_len,
}
static int ft_parse_internal(void *param, byte *doc, int doc_len)
static int ft_parse_internal(MYSQL_FTPARSER_PARAM *param,
byte *doc, int doc_len)
{
byte *end=doc+doc_len;
MY_FT_PARSER_PARAM *ft_param=(MY_FT_PARSER_PARAM *)param;
MY_FT_PARSER_PARAM *ft_param=param->mysql_ftparam;
TREE *wtree= ft_param->wtree;
FT_WORD w;
DBUG_ENTER("ft_parse_internal");
while (ft_simple_get_word(wtree->custom_arg, &doc, end, &w, TRUE))
if (ft_param->up->mysql_add_word(param, w.pos, w.len, 0))
if (param->mysql_add_word(param, w.pos, w.len, 0))
DBUG_RETURN(1);
DBUG_RETURN(0);
}
int ft_parse(TREE *wtree, byte *doc, int doclen, my_bool with_alloc,
int ft_parse(TREE *wtree, byte *doc, int doclen,
struct st_mysql_ftparser *parser,
MYSQL_FTPARSER_PARAM *param)
MYSQL_FTPARSER_PARAM *param, MEM_ROOT *mem_root)
{
MY_FT_PARSER_PARAM my_param;
DBUG_ENTER("ft_parse");
DBUG_ASSERT(parser);
my_param.up= param;
my_param.wtree= wtree;
my_param.with_alloc= with_alloc;
my_param.mem_root= mem_root;
param->mysql_parse= ft_parse_internal;
param->mysql_add_word= ft_add_word;
......@@ -356,6 +354,7 @@ MYSQL_FTPARSER_PARAM *ftparser_call_initializer(MI_INFO *info,
info->ftparser_param= (MYSQL_FTPARSER_PARAM *)
my_malloc(MAX_PARAM_NR * sizeof(MYSQL_FTPARSER_PARAM) *
info->s->ftparsers, MYF(MY_WME|MY_ZEROFILL));
init_alloc_root(&info->ft_memroot, FTPARSER_MEMROOT_ALLOC_SIZE, 0);
if (! info->ftparser_param)
return 0;
}
......@@ -387,6 +386,7 @@ MYSQL_FTPARSER_PARAM *ftparser_call_initializer(MI_INFO *info,
void ftparser_call_deinitializer(MI_INFO *info)
{
uint i, j, keys= info->s->state.header.keys;
free_root(&info->ft_memroot, MYF(0));
if (! info->ftparser_param)
return;
for (i= 0; i < keys; i++)
......
......@@ -629,7 +629,7 @@ const char *ft_precompiled_stopwords[] = {
static int ft_default_parser_parse(MYSQL_FTPARSER_PARAM *param)
{
return param->mysql_parse(param->mysql_ftparam, param->doc, param->length);
return param->mysql_parse(param, param->doc, param->length);
}
struct st_mysql_ftparser ft_default_parser=
......
......@@ -77,7 +77,7 @@ uint _mi_ft_segiterator(register FT_SEG_ITERATOR *ftsi)
{
uint pack_length= (ftsi->seg->bit_start);
ftsi->len= (pack_length == 1 ? (uint) *(uchar*) ftsi->pos :
uint2korr(ftsi->pos));
uint2korr(ftsi->pos));
ftsi->pos+= pack_length; /* Skip VARCHAR length */
DBUG_RETURN(1);
}
......@@ -95,9 +95,8 @@ uint _mi_ft_segiterator(register FT_SEG_ITERATOR *ftsi)
/* parses a document i.e. calls ft_parse for every keyseg */
uint _mi_ft_parse(TREE *parsed, MI_INFO *info, uint keynr,
const byte *record, my_bool with_alloc,
MYSQL_FTPARSER_PARAM *param)
uint _mi_ft_parse(TREE *parsed, MI_INFO *info, uint keynr, const byte *record,
MYSQL_FTPARSER_PARAM *param, MEM_ROOT *mem_root)
{
FT_SEG_ITERATOR ftsi;
struct st_mysql_ftparser *parser;
......@@ -110,14 +109,14 @@ uint _mi_ft_parse(TREE *parsed, MI_INFO *info, uint keynr,
while (_mi_ft_segiterator(&ftsi))
{
if (ftsi.pos)
if (ft_parse(parsed, (byte *)ftsi.pos, ftsi.len, with_alloc, parser,
param))
if (ft_parse(parsed, (byte *)ftsi.pos, ftsi.len, parser, param, mem_root))
DBUG_RETURN(1);
}
DBUG_RETURN(0);
}
FT_WORD * _mi_ft_parserecord(MI_INFO *info, uint keynr, const byte *record)
FT_WORD *_mi_ft_parserecord(MI_INFO *info, uint keynr, const byte *record,
MEM_ROOT *mem_root)
{
TREE ptree;
MYSQL_FTPARSER_PARAM *param;
......@@ -125,10 +124,11 @@ FT_WORD * _mi_ft_parserecord(MI_INFO *info, uint keynr, const byte *record)
if (! (param= ftparser_call_initializer(info, keynr, 0)))
DBUG_RETURN(NULL);
bzero((char*) &ptree, sizeof(ptree));
if (_mi_ft_parse(&ptree, info, keynr, record, 0, param))
param->flags= 0;
if (_mi_ft_parse(&ptree, info, keynr, record, param, mem_root))
DBUG_RETURN(NULL);
DBUG_RETURN(ft_linearize(&ptree));
DBUG_RETURN(ft_linearize(&ptree, mem_root));
}
static int _mi_ft_store(MI_INFO *info, uint keynr, byte *keybuf,
......@@ -206,10 +206,11 @@ int _mi_ft_update(MI_INFO *info, uint keynr, byte *keybuf,
int cmp, cmp2;
DBUG_ENTER("_mi_ft_update");
if (!(old_word=oldlist=_mi_ft_parserecord(info, keynr, oldrec)))
goto err0;
if (!(new_word=newlist=_mi_ft_parserecord(info, keynr, newrec)))
goto err1;
if (!(old_word=oldlist=_mi_ft_parserecord(info, keynr, oldrec,
&info->ft_memroot)) ||
!(new_word=newlist=_mi_ft_parserecord(info, keynr, newrec,
&info->ft_memroot)))
goto err;
error=0;
while(old_word->pos && new_word->pos)
......@@ -222,13 +223,13 @@ int _mi_ft_update(MI_INFO *info, uint keynr, byte *keybuf,
{
key_length=_ft_make_key(info,keynr,keybuf,old_word,pos);
if ((error=_mi_ck_delete(info,keynr,(uchar*) keybuf,key_length)))
goto err2;
goto err;
}
if (cmp > 0 || cmp2)
{
key_length=_ft_make_key(info,keynr,keybuf,new_word,pos);
if ((error=_mi_ck_write(info,keynr,(uchar*) keybuf,key_length)))
goto err2;
goto err;
}
if (cmp<=0) old_word++;
if (cmp>=0) new_word++;
......@@ -238,11 +239,8 @@ int _mi_ft_update(MI_INFO *info, uint keynr, byte *keybuf,
else if (new_word->pos)
error=_mi_ft_store(info,keynr,keybuf,new_word,pos);
err2:
my_free((char*) newlist,MYF(0));
err1:
my_free((char*) oldlist,MYF(0));
err0:
err:
free_root(&info->ft_memroot, MYF(MY_MARK_BLOCKS_FREE));
DBUG_RETURN(error);
}
......@@ -255,12 +253,13 @@ int _mi_ft_add(MI_INFO *info, uint keynr, byte *keybuf, const byte *record,
int error= -1;
FT_WORD *wlist;
DBUG_ENTER("_mi_ft_add");
DBUG_PRINT("enter",("keynr: %d",keynr));
if ((wlist=_mi_ft_parserecord(info, keynr, record)))
{
if ((wlist=_mi_ft_parserecord(info, keynr, record, &info->ft_memroot)))
error=_mi_ft_store(info,keynr,keybuf,wlist,pos);
my_free((char*) wlist,MYF(0));
}
free_root(&info->ft_memroot, MYF(MY_MARK_BLOCKS_FREE));
DBUG_PRINT("exit",("Return: %d",error));
DBUG_RETURN(error);
}
......@@ -275,11 +274,10 @@ int _mi_ft_del(MI_INFO *info, uint keynr, byte *keybuf, const byte *record,
DBUG_ENTER("_mi_ft_del");
DBUG_PRINT("enter",("keynr: %d",keynr));
if ((wlist=_mi_ft_parserecord(info, keynr, record)))
{
if ((wlist=_mi_ft_parserecord(info, keynr, record, &info->ft_memroot)))
error=_mi_ft_erase(info,keynr,keybuf,wlist,pos);
my_free((char*) wlist,MYF(0));
}
free_root(&info->ft_memroot, MYF(MY_MARK_BLOCKS_FREE));
DBUG_PRINT("exit",("Return: %d",error));
DBUG_RETURN(error);
}
......
......@@ -30,6 +30,8 @@
#define FT_MAX_WORD_LEN_FOR_SORT 31
#define FTPARSER_MEMROOT_ALLOC_SIZE 65536
#define COMPILE_STOPWORDS_IN
/* Interested readers may consult SMART
......@@ -119,12 +121,12 @@ void _mi_ft_segiterator_dummy_init(const byte *, uint, FT_SEG_ITERATOR *);
uint _mi_ft_segiterator(FT_SEG_ITERATOR *);
void ft_parse_init(TREE *, CHARSET_INFO *);
int ft_parse(TREE *, byte *, int, my_bool, struct st_mysql_ftparser *parser,
MYSQL_FTPARSER_PARAM *param);
FT_WORD * ft_linearize(TREE *);
FT_WORD * _mi_ft_parserecord(MI_INFO *, uint, const byte *);
uint _mi_ft_parse(TREE *, MI_INFO *, uint, const byte *, my_bool,
MYSQL_FTPARSER_PARAM *param);
int ft_parse(TREE *, byte *, int, struct st_mysql_ftparser *parser,
MYSQL_FTPARSER_PARAM *, MEM_ROOT *);
FT_WORD * ft_linearize(TREE *, MEM_ROOT *);
FT_WORD * _mi_ft_parserecord(MI_INFO *, uint, const byte *, MEM_ROOT *);
uint _mi_ft_parse(TREE *, MI_INFO *, uint, const byte *,
MYSQL_FTPARSER_PARAM *, MEM_ROOT *);
FT_INFO *ft_init_nlq_search(MI_INFO *, uint, byte *, uint, uint, byte *);
FT_INFO *ft_init_boolean_search(MI_INFO *, uint, byte *, uint, CHARSET_INFO *);
......
......@@ -2117,6 +2117,7 @@ int mi_repair_by_sort(MI_CHECK *param, register MI_INFO *info,
my_seek(param->read_cache.file,0L,MY_SEEK_END,MYF(0));
sort_param.wordlist=NULL;
init_alloc_root(&sort_param.wordroot, FTPARSER_MEMROOT_ALLOC_SIZE, 0);
if (share->data_file_type == DYNAMIC_RECORD)
length=max(share->base.min_pack_length+1,share->base.min_block_length);
......@@ -2179,12 +2180,36 @@ int mi_repair_by_sort(MI_CHECK *param, register MI_INFO *info,
{
uint ft_max_word_len_for_sort=FT_MAX_WORD_LEN_FOR_SORT*
sort_param.keyinfo->seg->charset->mbmaxlen;
sort_info.max_records=
(ha_rows) (sort_info.filelength/ft_min_word_len+1);
sort_param.key_length+=ft_max_word_len_for_sort-HA_FT_MAXBYTELEN;
/*
fulltext indexes may have much more entries than the
number of rows in the table. We estimate the number here.
Note, built-in parser is always nr. 0 - see ftparser_call_initializer()
*/
if (sort_param.keyinfo->ftparser_nr == 0)
{
/*
for built-in parser the number of generated index entries
cannot be larger than the size of the data file divided
by the minimal word's length
*/
sort_info.max_records=
(ha_rows) (sort_info.filelength/ft_min_word_len+1);
}
else
{
/*
for external plugin parser we cannot tell anything at all :(
so, we'll use all the sort memory and start from ~10 buffpeks.
(see _create_index_by_sort)
*/
sort_info.max_records=
10*param->sort_buffer_length/sort_param.key_length;
}
sort_param.key_read=sort_ft_key_read;
sort_param.key_write=sort_ft_key_write;
sort_param.key_length+=ft_max_word_len_for_sort-HA_FT_MAXBYTELEN;
}
else
{
......@@ -2200,6 +2225,7 @@ int mi_repair_by_sort(MI_CHECK *param, register MI_INFO *info,
goto err;
}
param->calc_checksum=0; /* No need to calc glob_crc */
free_root(&sort_param.wordroot, MYF(0));
/* Set for next loop */
sort_info.max_records= (ha_rows) info->state->records;
......@@ -2589,6 +2615,7 @@ int mi_repair_parallel(MI_CHECK *param, register MI_INFO *info,
uint ft_max_word_len_for_sort=FT_MAX_WORD_LEN_FOR_SORT*
sort_param[i].keyinfo->seg->charset->mbmaxlen;
sort_param[i].key_length+=ft_max_word_len_for_sort-HA_FT_MAXBYTELEN;
init_alloc_root(&sort_param[i].wordroot, FTPARSER_MEMROOT_ALLOC_SIZE, 0);
}
}
sort_info.total_keys=i;
......@@ -2810,10 +2837,11 @@ static int sort_ft_key_read(MI_SORT_PARAM *sort_param, void *key)
{
for (;;)
{
my_free((char*) wptr, MYF(MY_ALLOW_ZERO_PTR));
free_root(&sort_param->wordroot, MYF(MY_MARK_BLOCKS_FREE));
if ((error=sort_get_next_record(sort_param)))
DBUG_RETURN(error);
if (!(wptr=_mi_ft_parserecord(info,sort_param->key,sort_param->record)))
if (!(wptr=_mi_ft_parserecord(info,sort_param->key,sort_param->record,
&sort_param->wordroot)))
DBUG_RETURN(1);
if (wptr->pos)
break;
......@@ -2837,7 +2865,7 @@ static int sort_ft_key_read(MI_SORT_PARAM *sort_param, void *key)
#endif
if (!wptr->pos)
{
my_free((char*) sort_param->wordlist, MYF(0));
free_root(&sort_param->wordroot, MYF(MY_MARK_BLOCKS_FREE));
sort_param->wordlist=0;
error=sort_write_record(sort_param);
}
......
......@@ -235,13 +235,14 @@ struct st_myisam_info {
/* accumulate indexfile changes between write's */
TREE *bulk_insert;
DYNAMIC_ARRAY *ft1_to_ft2; /* used only in ft1->ft2 conversion */
MYSQL_FTPARSER_PARAM *ftparser_param; /* share info between init/deinit */
char *filename; /* parameter to open filename */
uchar *buff, /* Temp area for key */
*lastkey,*lastkey2; /* Last used search key */
uchar *first_mbr_key; /* Searhed spatial key */
byte *rec_buff; /* Tempbuff for recordpack */
uchar *int_keypos, /* Save position for next/previous */
MEM_ROOT ft_memroot; /* used by the parser */
MYSQL_FTPARSER_PARAM *ftparser_param; /* share info between init/deinit */
char *filename; /* parameter to open filename */
uchar *buff, /* Temp area for key */
*lastkey,*lastkey2; /* Last used search key */
uchar *first_mbr_key; /* Searhed spatial key */
byte *rec_buff; /* Tempbuff for recordpack */
uchar *int_keypos, /* Save position for next/previous */
*int_maxpos; /* -""- */
uint int_nod_flag; /* -""- */
uint32 int_keytree_version; /* -""- */
......@@ -325,6 +326,7 @@ typedef struct st_mi_sort_param
uchar **sort_keys;
byte *rec_buff;
void *wordlist, *wordptr;
MEM_ROOT wordroot;
char *record;
MY_TMPDIR *tmpdir;
int (*key_cmp)(struct st_mi_sort_param *, const void *, const void *);
......
......@@ -447,6 +447,7 @@ err:
close_cached_file(&info->tempfile_for_exceptions);
ok:
free_root(&info->wordroot, MYF(0));
remove_io_thread(&info->read_cache);
pthread_mutex_lock(&info->sort_info->mutex);
info->sort_info->threads_running--;
......
......@@ -23,5 +23,5 @@ examples:
cd examples && $(MAKE)
unit: $(srcdir)/unit.pl
cp $< $@
cp $(srcdir)/unit.pl $@
chmod +x $@
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