Merge bk-internal.mysql.com:/home/bk/mysql-5.1-new
into serg.mylan:/usr/home/serg/Abk/mysql-5.1
This commit is contained in:
commit
5d5b9fedfe
@ -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
|
||||
|
@ -1,15 +0,0 @@
|
||||
***************
|
||||
*** 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
|
||||
};
|
56
configure.in
56
configure.in
@ -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],
|
||||
|
169
include/atomic/nolock.h
Normal file
169
include/atomic/nolock.h
Normal file
@ -0,0 +1,169 @@
|
||||
/* 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
|
||||
|
161
include/atomic/rwlock.h
Normal file
161
include/atomic/rwlock.h
Normal file
@ -0,0 +1,161 @@
|
||||
/* 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
|
||||
|
||||
|
56
include/atomic/x86-gcc.h
Normal file
56
include/atomic/x86-gcc.h
Normal file
@ -0,0 +1,56 @@
|
||||
/* 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
|
||||
|
85
include/atomic/x86-msvc.h
Normal file
85
include/atomic/x86-msvc.h
Normal file
@ -0,0 +1,85 @@
|
||||
/* 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)
|
||||
|
46
include/my_atomic.h
Normal file
46
include/my_atomic.h
Normal file
@ -0,0 +1,46 @@
|
||||
/* 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)\"" \
|
||||
|
46
mysys/my_atomic.c
Normal file
46
mysys/my_atomic.c
Normal file
@ -0,0 +1,46 @@
|
||||
/* 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
|
||||
}
|
||||
|
40
mysys/my_getncpus.c
Normal file
40
mysys/my_getncpus.c
Normal file
@ -0,0 +1,40 @@
|
||||
/* 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
|
||||
|
133
mysys/test_atomic.c
Normal file
133
mysys/test_atomic.c
Normal file
@ -0,0 +1,133 @@
|
||||
#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];
|
||||
|
11
sql/table.cc
11
sql/table.cc
@ -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=
|
||||
|
@ -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 $@
|
||||
|
Loading…
x
Reference in New Issue
Block a user