Commit d44fbafb authored by Rich Prohaska's avatar Rich Prohaska Committed by Yoni Fogel

refs #5254 merge fast upserts to mainline. enabled on mysql 5.6 only for now.

git-svn-id: file:///svn/mysql/tokudb-engine/tokudb-engine@50363 c7de825b-a66e-492c-adef-691d508d4ae1
parent 7eb14199
#called from the top level Makefile
MYSQLDATAdir = $(localstatedir)
MYSQLSHAREdir = $(pkgdatadir)
MYSQLBASEdir = $(prefix)
MYSQLLIBdir = $(pkglibdir)
pkgplugindir = $(pkglibdir)/plugin
INCLUDES = -I$(top_builddir)/include \
-I$(top_srcdir)/include \
-I$(top_srcdir)/regex \
-I$(top_srcdir)/sql \
-I$(srcdir) \
-I$(TOKUFRACTALTREE)/include
LDADD =
DEFS = @DEFS@
noinst_HEADERS =
EXTRA_LTLIBRARIES = ha_tokudb.la
pkgplugin_LTLIBRARIES = @plugin_tokudb_shared_target@
ha_tokudb_la_LIBADD = -L$(TOKUFRACTALTREE)/lib -l$(TOKUFRACTALTREE_LIBNAME) -l$(TOKUPORTABILITY_LIBNAME) -lz -lstdc++
ha_tokudb_la_LDFLAGS = -module -rpath $(pkgplugindir)
ha_tokudb_la_CXXFLAGS = $(AM_CXXFLAGS) -DMYSQL_DYNAMIC_PLUGIN -DTOKUDB_VERSION=\"$(TOKUDB_VERSION)\" -Wall
ha_tokudb_la_SOURCES = ha_tokudb.cc
EXTRA_LIBRARIES = libtokudb.a
noinst_LIBRARIES = @plugin_tokudb_static_target@
libtokudb_a_CXXFLAGS = $(AM_CXXFLAGS) -Wall
libtokudb_a_SOURCES = ha_tokudb.cc
EXTRA_DIST = CMakeLists.txt plug.in
# Don't update the files from bitkeeper
%::SCCS/s.%
# Makefile.in generated by automake 1.11.1 from Makefile.am.
# @configure_input@
# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
# 2003, 2004, 2005, 2006, 2007, 2008, 2009 Free Software Foundation,
# Inc.
# This Makefile.in is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it,
# with or without modifications, as long as this notice is preserved.
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
# PARTICULAR PURPOSE.
@SET_MAKE@
#called from the top level Makefile
VPATH = @srcdir@
pkgdatadir = $(datadir)/@PACKAGE@
pkgincludedir = $(includedir)/@PACKAGE@
pkglibdir = $(libdir)/@PACKAGE@
pkglibexecdir = $(libexecdir)/@PACKAGE@
am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
install_sh_DATA = $(install_sh) -c -m 644
install_sh_PROGRAM = $(install_sh) -c
install_sh_SCRIPT = $(install_sh) -c
INSTALL_HEADER = $(INSTALL_DATA)
transform = $(program_transform_name)
NORMAL_INSTALL = :
PRE_INSTALL = :
POST_INSTALL = :
NORMAL_UNINSTALL = :
PRE_UNINSTALL = :
POST_UNINSTALL = :
build_triplet = @build@
host_triplet = @host@
target_triplet = @target@
subdir = storage/tokudb
DIST_COMMON = $(noinst_HEADERS) $(srcdir)/Makefile.am \
$(srcdir)/Makefile.in
ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
am__aclocal_m4_deps = $(top_srcdir)/config/ac-macros/maintainer.m4 \
$(top_srcdir)/config/ac-macros/alloca.m4 \
$(top_srcdir)/config/ac-macros/check_cpu.m4 \
$(top_srcdir)/config/ac-macros/character_sets.m4 \
$(top_srcdir)/config/ac-macros/compiler_flag.m4 \
$(top_srcdir)/config/ac-macros/plugins.m4 \
$(top_srcdir)/config/ac-macros/ha_ndbcluster.m4 \
$(top_srcdir)/config/ac-macros/large_file.m4 \
$(top_srcdir)/config/ac-macros/misc.m4 \
$(top_srcdir)/config/ac-macros/readline.m4 \
$(top_srcdir)/config/ac-macros/ssl.m4 \
$(top_srcdir)/config/ac-macros/zlib.m4 \
$(top_srcdir)/configure.in
am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
$(ACLOCAL_M4)
mkinstalldirs = $(install_sh) -d
CONFIG_HEADER = $(top_builddir)/include/config.h
CONFIG_CLEAN_FILES =
CONFIG_CLEAN_VPATH_FILES =
LIBRARIES = $(noinst_LIBRARIES)
AM_V_AR = $(am__v_AR_$(V))
am__v_AR_ = $(am__v_AR_$(AM_DEFAULT_VERBOSITY))
am__v_AR_0 = @echo " AR " $@;
AM_V_at = $(am__v_at_$(V))
am__v_at_ = $(am__v_at_$(AM_DEFAULT_VERBOSITY))
am__v_at_0 = @
libtokudb_a_AR = $(AR) $(ARFLAGS)
libtokudb_a_LIBADD =
am_libtokudb_a_OBJECTS = libtokudb_a-ha_tokudb.$(OBJEXT)
libtokudb_a_OBJECTS = $(am_libtokudb_a_OBJECTS)
am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`;
am__vpath_adj = case $$p in \
$(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \
*) f=$$p;; \
esac;
am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`;
am__install_max = 40
am__nobase_strip_setup = \
srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'`
am__nobase_strip = \
for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||"
am__nobase_list = $(am__nobase_strip_setup); \
for p in $$list; do echo "$$p $$p"; done | \
sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \
$(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \
if (++n[$$2] == $(am__install_max)) \
{ print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \
END { for (dir in files) print dir, files[dir] }'
am__base_list = \
sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \
sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g'
am__installdirs = "$(DESTDIR)$(pkgplugindir)"
LTLIBRARIES = $(pkgplugin_LTLIBRARIES)
ha_tokudb_la_DEPENDENCIES =
am_ha_tokudb_la_OBJECTS = ha_tokudb_la-ha_tokudb.lo
ha_tokudb_la_OBJECTS = $(am_ha_tokudb_la_OBJECTS)
AM_V_lt = $(am__v_lt_$(V))
am__v_lt_ = $(am__v_lt_$(AM_DEFAULT_VERBOSITY))
am__v_lt_0 = --silent
ha_tokudb_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) \
$(LIBTOOLFLAGS) --mode=link $(CXXLD) $(ha_tokudb_la_CXXFLAGS) \
$(CXXFLAGS) $(ha_tokudb_la_LDFLAGS) $(LDFLAGS) -o $@
DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir)/include
depcomp = $(SHELL) $(top_srcdir)/depcomp
am__depfiles_maybe = depfiles
am__mv = mv -f
CXXCOMPILE = $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \
$(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS)
LTCXXCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) \
$(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) \
$(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \
$(AM_CXXFLAGS) $(CXXFLAGS)
AM_V_CXX = $(am__v_CXX_$(V))
am__v_CXX_ = $(am__v_CXX_$(AM_DEFAULT_VERBOSITY))
am__v_CXX_0 = @echo " CXX " $@;
CXXLD = $(CXX)
CXXLINK = $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) \
$(LIBTOOLFLAGS) --mode=link $(CXXLD) $(AM_CXXFLAGS) \
$(CXXFLAGS) $(AM_LDFLAGS) $(LDFLAGS) -o $@
AM_V_CXXLD = $(am__v_CXXLD_$(V))
am__v_CXXLD_ = $(am__v_CXXLD_$(AM_DEFAULT_VERBOSITY))
am__v_CXXLD_0 = @echo " CXXLD " $@;
AM_V_GEN = $(am__v_GEN_$(V))
am__v_GEN_ = $(am__v_GEN_$(AM_DEFAULT_VERBOSITY))
am__v_GEN_0 = @echo " GEN " $@;
SOURCES = $(libtokudb_a_SOURCES) $(ha_tokudb_la_SOURCES)
DIST_SOURCES = $(libtokudb_a_SOURCES) $(ha_tokudb_la_SOURCES)
HEADERS = $(noinst_HEADERS)
ETAGS = etags
CTAGS = ctags
DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
ABI_CHECK = @ABI_CHECK@
ACLOCAL = @ACLOCAL@
ALLOCA = @ALLOCA@
AMTAR = @AMTAR@
AM_CFLAGS = @AM_CFLAGS@
AM_CXXFLAGS = @AM_CXXFLAGS@
AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@
AR = @AR@
ARFLAGS = @ARFLAGS@
AS = @AS@
ASFLAGS = @ASFLAGS@
AUTOCONF = @AUTOCONF@
AUTOHEADER = @AUTOHEADER@
AUTOMAKE = @AUTOMAKE@
AVAILABLE_LANGUAGES = @AVAILABLE_LANGUAGES@
AWK = @AWK@
CC = @CC@
CCAS = @CCAS@
CCASDEPMODE = @CCASDEPMODE@
CCASFLAGS = @CCASFLAGS@
CCDEPMODE = @CCDEPMODE@
CC_VERSION = @CC_VERSION@
CFLAGS = @CFLAGS@
CHECK_PID = @CHECK_PID@
CHMOD = @CHMOD@
CLIENT_EXTRA_LDFLAGS = @CLIENT_EXTRA_LDFLAGS@
CLIENT_LIBS = @CLIENT_LIBS@
CLIENT_THREAD_LIBS = @CLIENT_THREAD_LIBS@
CMP = @CMP@
COMPILATION_COMMENT = @COMPILATION_COMMENT@
CONF_COMMAND = @CONF_COMMAND@
CP = @CP@
CPP = @CPP@
CPPFLAGS = @CPPFLAGS@
CXX = @CXX@
CXXCPP = @CXXCPP@
CXXDEPMODE = @CXXDEPMODE@
CXXFLAGS = @CXXFLAGS@
CXXLDFLAGS = @CXXLDFLAGS@
CXX_VERSION = @CXX_VERSION@
CYGPATH_W = @CYGPATH_W@
DEFS = @DEFS@
DEPDIR = @DEPDIR@
DIFF = @DIFF@
DOT_FRM_VERSION = @DOT_FRM_VERSION@
DOXYGEN = @DOXYGEN@
DSYMUTIL = @DSYMUTIL@
DUMPBIN = @DUMPBIN@
DVIS = @DVIS@
ECHO_C = @ECHO_C@
ECHO_N = @ECHO_N@
ECHO_T = @ECHO_T@
EGREP = @EGREP@
EXEEXT = @EXEEXT@
FGREP = @FGREP@
FIND_PROC = @FIND_PROC@
GETCONF = @GETCONF@
GREP = @GREP@
GXX = @GXX@
HOSTNAME = @HOSTNAME@
INNODB_DYNAMIC_CFLAGS = @INNODB_DYNAMIC_CFLAGS@
INSTALL = @INSTALL@
INSTALL_DATA = @INSTALL_DATA@
INSTALL_PROGRAM = @INSTALL_PROGRAM@
INSTALL_SCRIPT = @INSTALL_SCRIPT@
INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
KILL = @KILL@
LD = @LD@
LDFLAGS = @LDFLAGS@
LD_VERSION_SCRIPT = @LD_VERSION_SCRIPT@
LIBDL = @LIBDL@
LIBEDIT_LOBJECTS = @LIBEDIT_LOBJECTS@
LIBOBJS = @LIBOBJS@
LIBS = @LIBS@
LIBTOOL = @LIBTOOL@
LIB_EXTRA_CCFLAGS = @LIB_EXTRA_CCFLAGS@
LIPO = @LIPO@
LM_CFLAGS = @LM_CFLAGS@
LN = @LN@
LN_CP_F = @LN_CP_F@
LN_S = @LN_S@
LTLIBOBJS = @LTLIBOBJS@
MACHINE_TYPE = @MACHINE_TYPE@
MAKEINDEX = @MAKEINDEX@
MAKEINFO = @MAKEINFO@
MAKE_BINARY_DISTRIBUTION_OPTIONS = @MAKE_BINARY_DISTRIBUTION_OPTIONS@
MAKE_SHELL = @MAKE_SHELL@
MKDIR_P = @MKDIR_P@
MV = @MV@
MYSQLD_DEFAULT_SWITCHES = @MYSQLD_DEFAULT_SWITCHES@
MYSQLD_EXTRA_LDFLAGS = @MYSQLD_EXTRA_LDFLAGS@
MYSQLD_EXTRA_LIBS = @MYSQLD_EXTRA_LIBS@
MYSQLD_USER = @MYSQLD_USER@
MYSQL_BASE_VERSION = @MYSQL_BASE_VERSION@
MYSQL_COPYRIGHT_YEAR = @MYSQL_COPYRIGHT_YEAR@
MYSQL_NO_DASH_VERSION = @MYSQL_NO_DASH_VERSION@
MYSQL_PREVIOUS_BASE_VERSION = @MYSQL_PREVIOUS_BASE_VERSION@
MYSQL_SERVER_SUFFIX = @MYSQL_SERVER_SUFFIX@
MYSQL_TCP_PORT = @MYSQL_TCP_PORT@
MYSQL_TCP_PORT_DEFAULT = @MYSQL_TCP_PORT_DEFAULT@
MYSQL_UNIX_ADDR = @MYSQL_UNIX_ADDR@
MYSQL_U_SCORE_VERSION = @MYSQL_U_SCORE_VERSION@
MYSQL_VERSION_ID = @MYSQL_VERSION_ID@
NDB_DEFS = @NDB_DEFS@
NDB_LD_VERSION_SCRIPT = @NDB_LD_VERSION_SCRIPT@
NDB_SCI_INCLUDES = @NDB_SCI_INCLUDES@
NDB_SCI_LIBS = @NDB_SCI_LIBS@
NDB_SHARED_LIB_MAJOR_VERSION = @NDB_SHARED_LIB_MAJOR_VERSION@
NDB_SHARED_LIB_VERSION = @NDB_SHARED_LIB_VERSION@
NDB_SIZEOF_CHAR = @NDB_SIZEOF_CHAR@
NDB_SIZEOF_CHARP = @NDB_SIZEOF_CHARP@
NDB_SIZEOF_INT = @NDB_SIZEOF_INT@
NDB_SIZEOF_LONG = @NDB_SIZEOF_LONG@
NDB_SIZEOF_LONG_LONG = @NDB_SIZEOF_LONG_LONG@
NDB_SIZEOF_SHORT = @NDB_SIZEOF_SHORT@
NDB_VERSION_BUILD = @NDB_VERSION_BUILD@
NDB_VERSION_MAJOR = @NDB_VERSION_MAJOR@
NDB_VERSION_MINOR = @NDB_VERSION_MINOR@
NDB_VERSION_STATUS = @NDB_VERSION_STATUS@
NM = @NM@
NMEDIT = @NMEDIT@
NOINST_LDFLAGS = @NOINST_LDFLAGS@
NON_THREADED_LIBS = @NON_THREADED_LIBS@
OBJDUMP = @OBJDUMP@
OBJEXT = @OBJEXT@
OTOOL = @OTOOL@
OTOOL64 = @OTOOL64@
PACKAGE = @PACKAGE@
PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
PACKAGE_NAME = @PACKAGE_NAME@
PACKAGE_STRING = @PACKAGE_STRING@
PACKAGE_TARNAME = @PACKAGE_TARNAME@
PACKAGE_VERSION = @PACKAGE_VERSION@
PATH_SEPARATOR = @PATH_SEPARATOR@
PDFLATEX = @PDFLATEX@
PDFMANUAL = @PDFMANUAL@
PERL = @PERL@
PERL5 = @PERL5@
PROTOCOL_VERSION = @PROTOCOL_VERSION@
PS = @PS@
RANLIB = @RANLIB@
RM = @RM@
SAVE_ASFLAGS = @SAVE_ASFLAGS@
SAVE_CC = @SAVE_CC@
SAVE_CFLAGS = @SAVE_CFLAGS@
SAVE_CXX = @SAVE_CXX@
SAVE_CXXFLAGS = @SAVE_CXXFLAGS@
SAVE_CXXLDFLAGS = @SAVE_CXXLDFLAGS@
SAVE_LDFLAGS = @SAVE_LDFLAGS@
SED = @SED@
SET_MAKE = @SET_MAKE@
SHARED_LIB_MAJOR_VERSION = @SHARED_LIB_MAJOR_VERSION@
SHARED_LIB_VERSION = @SHARED_LIB_VERSION@
SHELL = @SHELL@
STATIC_NSS_FLAGS = @STATIC_NSS_FLAGS@
STRIP = @STRIP@
SYSTEM_TYPE = @SYSTEM_TYPE@
TAR = @TAR@
TARGET_LINUX = @TARGET_LINUX@
TERMCAP_LIB = @TERMCAP_LIB@
TEST_NDBCLUSTER = @TEST_NDBCLUSTER@
THREAD_LOBJECTS = @THREAD_LOBJECTS@
VERSION = @VERSION@
WRAPLIBS = @WRAPLIBS@
YACC = @YACC@
ZLIB_DEPS = @ZLIB_DEPS@
ZLIB_INCLUDES = @ZLIB_INCLUDES@
ZLIB_LIBS = @ZLIB_LIBS@
abs_builddir = @abs_builddir@
abs_srcdir = @abs_srcdir@
abs_top_builddir = @abs_top_builddir@
abs_top_srcdir = @abs_top_srcdir@
ac_ct_CC = @ac_ct_CC@
ac_ct_CXX = @ac_ct_CXX@
ac_ct_DUMPBIN = @ac_ct_DUMPBIN@
am__include = @am__include@
am__leading_dot = @am__leading_dot@
am__quote = @am__quote@
am__tar = @am__tar@
am__untar = @am__untar@
bindir = @bindir@
build = @build@
build_alias = @build_alias@
build_cpu = @build_cpu@
build_os = @build_os@
build_vendor = @build_vendor@
builddir = @builddir@
condition_dependent_plugin_includes = @condition_dependent_plugin_includes@
condition_dependent_plugin_links = @condition_dependent_plugin_links@
condition_dependent_plugin_modules = @condition_dependent_plugin_modules@
condition_dependent_plugin_objects = @condition_dependent_plugin_objects@
datadir = @datadir@
datarootdir = @datarootdir@
docdir = @docdir@
docs_dirs = @docs_dirs@
dvidir = @dvidir@
exec_prefix = @exec_prefix@
extra_docs = @extra_docs@
host = @host@
host_alias = @host_alias@
host_cpu = @host_cpu@
host_os = @host_os@
host_vendor = @host_vendor@
htmldir = @htmldir@
includedir = @includedir@
infodir = @infodir@
innodb_system_libs = @innodb_system_libs@
install_sh = @install_sh@
libdir = @libdir@
libexecdir = @libexecdir@
libmysqld_dirs = @libmysqld_dirs@
localedir = @localedir@
localstatedir = @localstatedir@
lt_ECHO = @lt_ECHO@
man1_files = @man1_files@
man8_files = @man8_files@
man_dirs = @man_dirs@
mandir = @mandir@
mkdir_p = @mkdir_p@
mysql_pg_dirs = @mysql_pg_dirs@
mysql_pg_distdirs = @mysql_pg_distdirs@
mysql_pg_unittest_dirs = @mysql_pg_unittest_dirs@
mysql_plugin_defs = @mysql_plugin_defs@
mysql_plugin_dirs = @mysql_plugin_dirs@
mysql_plugin_libs = @mysql_plugin_libs@
mysql_se_dirs = @mysql_se_dirs@
mysql_se_distdirs = @mysql_se_distdirs@
mysql_se_unittest_dirs = @mysql_se_unittest_dirs@
ndb_bin_am_ldflags = @ndb_bin_am_ldflags@
ndb_cxxflags_fix = @ndb_cxxflags_fix@
ndb_mgmclient_libs = @ndb_mgmclient_libs@
ndb_opt_subdirs = @ndb_opt_subdirs@
ndb_port = @ndb_port@
ndb_transporter_opt_objs = @ndb_transporter_opt_objs@
ndbcluster_includes = @ndbcluster_includes@
ndbcluster_libs = @ndbcluster_libs@
ndbcluster_system_libs = @ndbcluster_system_libs@
netware_dir = @netware_dir@
oldincludedir = @oldincludedir@
openssl_includes = @openssl_includes@
openssl_libs = @openssl_libs@
pdfdir = @pdfdir@
plugin_archive_shared_target = @plugin_archive_shared_target@
plugin_archive_static_target = @plugin_archive_static_target@
plugin_blackhole_shared_target = @plugin_blackhole_shared_target@
plugin_blackhole_static_target = @plugin_blackhole_static_target@
plugin_csv_shared_target = @plugin_csv_shared_target@
plugin_csv_static_target = @plugin_csv_static_target@
plugin_example_shared_target = @plugin_example_shared_target@
plugin_example_static_target = @plugin_example_static_target@
plugin_federated_shared_target = @plugin_federated_shared_target@
plugin_federated_static_target = @plugin_federated_static_target@
plugin_heap_shared_target = @plugin_heap_shared_target@
plugin_heap_static_target = @plugin_heap_static_target@
plugin_innobase_shared_target = @plugin_innobase_shared_target@
plugin_innobase_static_target = @plugin_innobase_static_target@
plugin_innodb_plugin_shared_target = @plugin_innodb_plugin_shared_target@
plugin_innodb_plugin_static_target = @plugin_innodb_plugin_static_target@
plugin_myisam_shared_target = @plugin_myisam_shared_target@
plugin_myisam_static_target = @plugin_myisam_static_target@
plugin_myisammrg_shared_target = @plugin_myisammrg_shared_target@
plugin_myisammrg_static_target = @plugin_myisammrg_static_target@
plugin_ndbcluster_shared_target = @plugin_ndbcluster_shared_target@
plugin_ndbcluster_static_target = @plugin_ndbcluster_static_target@
plugin_partition_shared_target = @plugin_partition_shared_target@
plugin_partition_static_target = @plugin_partition_static_target@
plugin_tokudb_shared_target = @plugin_tokudb_shared_target@
plugin_tokudb_static_target = @plugin_tokudb_static_target@
prefix = @prefix@
program_transform_name = @program_transform_name@
psdir = @psdir@
readline_basedir = @readline_basedir@
readline_dir = @readline_dir@
readline_h_ln_cmd = @readline_h_ln_cmd@
readline_link = @readline_link@
readline_topdir = @readline_topdir@
sbindir = @sbindir@
server_scripts = @server_scripts@
sharedstatedir = @sharedstatedir@
sql_client_dirs = @sql_client_dirs@
sql_server = @sql_server@
sql_server_dirs = @sql_server_dirs@
sql_union_dirs = @sql_union_dirs@
srcdir = @srcdir@
sysconfdir = @sysconfdir@
target = @target@
target_alias = @target_alias@
target_cpu = @target_cpu@
target_os = @target_os@
target_vendor = @target_vendor@
tools_dirs = @tools_dirs@
top_build_prefix = @top_build_prefix@
top_builddir = @top_builddir@
top_srcdir = @top_srcdir@
uname_prog = @uname_prog@
yassl_dir = @yassl_dir@
yassl_h_ln_cmd = @yassl_h_ln_cmd@
yassl_libs = @yassl_libs@
yassl_taocrypt_extra_cxxflags = @yassl_taocrypt_extra_cxxflags@
yassl_thread_cxxflags = @yassl_thread_cxxflags@
zlib_dir = @zlib_dir@
MYSQLDATAdir = $(localstatedir)
MYSQLSHAREdir = $(pkgdatadir)
MYSQLBASEdir = $(prefix)
MYSQLLIBdir = $(pkglibdir)
pkgplugindir = $(pkglibdir)/plugin
INCLUDES = -I$(top_builddir)/include \
-I$(top_srcdir)/include \
-I$(top_srcdir)/regex \
-I$(top_srcdir)/sql \
-I$(srcdir) \
-I$(TOKUFRACTALTREE)/include
LDADD =
noinst_HEADERS =
EXTRA_LTLIBRARIES = ha_tokudb.la
pkgplugin_LTLIBRARIES = @plugin_tokudb_shared_target@
ha_tokudb_la_LIBADD = -L$(TOKUFRACTALTREE)/lib -l$(TOKUFRACTALTREE_LIBNAME) -l$(TOKUPORTABILITY_LIBNAME) -lz -lstdc++
ha_tokudb_la_LDFLAGS = -module -rpath $(pkgplugindir)
ha_tokudb_la_CXXFLAGS = $(AM_CXXFLAGS) -DMYSQL_DYNAMIC_PLUGIN -DTOKUDB_VERSION=\"$(TOKUDB_VERSION)\" -Wall
ha_tokudb_la_SOURCES = ha_tokudb.cc
EXTRA_LIBRARIES = libtokudb.a
noinst_LIBRARIES = @plugin_tokudb_static_target@
libtokudb_a_CXXFLAGS = $(AM_CXXFLAGS) -Wall
libtokudb_a_SOURCES = ha_tokudb.cc
EXTRA_DIST = CMakeLists.txt plug.in
all: all-am
.SUFFIXES:
.SUFFIXES: .cc .lo .o .obj
$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps)
@for dep in $?; do \
case '$(am__configure_deps)' in \
*$$dep*) \
( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \
&& { if test -f $@; then exit 0; else break; fi; }; \
exit 1;; \
esac; \
done; \
echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu storage/tokudb/Makefile'; \
$(am__cd) $(top_srcdir) && \
$(AUTOMAKE) --gnu storage/tokudb/Makefile
.PRECIOUS: Makefile
Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
@case '$?' in \
*config.status*) \
cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \
*) \
echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \
cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \
esac;
$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
$(top_srcdir)/configure: $(am__configure_deps)
cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
$(ACLOCAL_M4): $(am__aclocal_m4_deps)
cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
$(am__aclocal_m4_deps):
clean-noinstLIBRARIES:
-test -z "$(noinst_LIBRARIES)" || rm -f $(noinst_LIBRARIES)
libtokudb.a: $(libtokudb_a_OBJECTS) $(libtokudb_a_DEPENDENCIES)
$(AM_V_at)-rm -f libtokudb.a
$(AM_V_AR)$(libtokudb_a_AR) libtokudb.a $(libtokudb_a_OBJECTS) $(libtokudb_a_LIBADD)
$(AM_V_at)$(RANLIB) libtokudb.a
install-pkgpluginLTLIBRARIES: $(pkgplugin_LTLIBRARIES)
@$(NORMAL_INSTALL)
test -z "$(pkgplugindir)" || $(MKDIR_P) "$(DESTDIR)$(pkgplugindir)"
@list='$(pkgplugin_LTLIBRARIES)'; test -n "$(pkgplugindir)" || list=; \
list2=; for p in $$list; do \
if test -f $$p; then \
list2="$$list2 $$p"; \
else :; fi; \
done; \
test -z "$$list2" || { \
echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 '$(DESTDIR)$(pkgplugindir)'"; \
$(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 "$(DESTDIR)$(pkgplugindir)"; \
}
uninstall-pkgpluginLTLIBRARIES:
@$(NORMAL_UNINSTALL)
@list='$(pkgplugin_LTLIBRARIES)'; test -n "$(pkgplugindir)" || list=; \
for p in $$list; do \
$(am__strip_dir) \
echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f '$(DESTDIR)$(pkgplugindir)/$$f'"; \
$(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f "$(DESTDIR)$(pkgplugindir)/$$f"; \
done
clean-pkgpluginLTLIBRARIES:
-test -z "$(pkgplugin_LTLIBRARIES)" || rm -f $(pkgplugin_LTLIBRARIES)
@list='$(pkgplugin_LTLIBRARIES)'; for p in $$list; do \
dir="`echo $$p | sed -e 's|/[^/]*$$||'`"; \
test "$$dir" != "$$p" || dir=.; \
echo "rm -f \"$${dir}/so_locations\""; \
rm -f "$${dir}/so_locations"; \
done
ha_tokudb.la: $(ha_tokudb_la_OBJECTS) $(ha_tokudb_la_DEPENDENCIES)
$(AM_V_CXXLD)$(ha_tokudb_la_LINK) $(ha_tokudb_la_OBJECTS) $(ha_tokudb_la_LIBADD) $(LIBS)
mostlyclean-compile:
-rm -f *.$(OBJEXT)
distclean-compile:
-rm -f *.tab.c
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ha_tokudb_la-ha_tokudb.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libtokudb_a-ha_tokudb.Po@am__quote@
.cc.o:
@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXXCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@
@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCXX_FALSE@ $(CXXCOMPILE) -c -o $@ $<
.cc.obj:
@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXXCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'`
@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@
@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCXX_FALSE@ $(CXXCOMPILE) -c -o $@ `$(CYGPATH_W) '$<'`
.cc.lo:
@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LTCXXCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo
@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@
@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCXX_FALSE@ $(LTCXXCOMPILE) -c -o $@ $<
libtokudb_a-ha_tokudb.o: ha_tokudb.cc
@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libtokudb_a_CXXFLAGS) $(CXXFLAGS) -MT libtokudb_a-ha_tokudb.o -MD -MP -MF $(DEPDIR)/libtokudb_a-ha_tokudb.Tpo -c -o libtokudb_a-ha_tokudb.o `test -f 'ha_tokudb.cc' || echo '$(srcdir)/'`ha_tokudb.cc
@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libtokudb_a-ha_tokudb.Tpo $(DEPDIR)/libtokudb_a-ha_tokudb.Po
@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@
@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='ha_tokudb.cc' object='libtokudb_a-ha_tokudb.o' libtool=no @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libtokudb_a_CXXFLAGS) $(CXXFLAGS) -c -o libtokudb_a-ha_tokudb.o `test -f 'ha_tokudb.cc' || echo '$(srcdir)/'`ha_tokudb.cc
libtokudb_a-ha_tokudb.obj: ha_tokudb.cc
@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libtokudb_a_CXXFLAGS) $(CXXFLAGS) -MT libtokudb_a-ha_tokudb.obj -MD -MP -MF $(DEPDIR)/libtokudb_a-ha_tokudb.Tpo -c -o libtokudb_a-ha_tokudb.obj `if test -f 'ha_tokudb.cc'; then $(CYGPATH_W) 'ha_tokudb.cc'; else $(CYGPATH_W) '$(srcdir)/ha_tokudb.cc'; fi`
@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libtokudb_a-ha_tokudb.Tpo $(DEPDIR)/libtokudb_a-ha_tokudb.Po
@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@
@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='ha_tokudb.cc' object='libtokudb_a-ha_tokudb.obj' libtool=no @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCXX_FALSE@ $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libtokudb_a_CXXFLAGS) $(CXXFLAGS) -c -o libtokudb_a-ha_tokudb.obj `if test -f 'ha_tokudb.cc'; then $(CYGPATH_W) 'ha_tokudb.cc'; else $(CYGPATH_W) '$(srcdir)/ha_tokudb.cc'; fi`
ha_tokudb_la-ha_tokudb.lo: ha_tokudb.cc
@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ha_tokudb_la_CXXFLAGS) $(CXXFLAGS) -MT ha_tokudb_la-ha_tokudb.lo -MD -MP -MF $(DEPDIR)/ha_tokudb_la-ha_tokudb.Tpo -c -o ha_tokudb_la-ha_tokudb.lo `test -f 'ha_tokudb.cc' || echo '$(srcdir)/'`ha_tokudb.cc
@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/ha_tokudb_la-ha_tokudb.Tpo $(DEPDIR)/ha_tokudb_la-ha_tokudb.Plo
@am__fastdepCXX_FALSE@ $(AM_V_CXX) @AM_BACKSLASH@
@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='ha_tokudb.cc' object='ha_tokudb_la-ha_tokudb.lo' libtool=yes @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCXX_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ha_tokudb_la_CXXFLAGS) $(CXXFLAGS) -c -o ha_tokudb_la-ha_tokudb.lo `test -f 'ha_tokudb.cc' || echo '$(srcdir)/'`ha_tokudb.cc
mostlyclean-libtool:
-rm -f *.lo
clean-libtool:
-rm -rf .libs _libs
ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES)
list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
unique=`for i in $$list; do \
if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
done | \
$(AWK) '{ files[$$0] = 1; nonempty = 1; } \
END { if (nonempty) { for (i in files) print i; }; }'`; \
mkid -fID $$unique
tags: TAGS
TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
$(TAGS_FILES) $(LISP)
set x; \
here=`pwd`; \
list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
unique=`for i in $$list; do \
if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
done | \
$(AWK) '{ files[$$0] = 1; nonempty = 1; } \
END { if (nonempty) { for (i in files) print i; }; }'`; \
shift; \
if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \
test -n "$$unique" || unique=$$empty_fix; \
if test $$# -gt 0; then \
$(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
"$$@" $$unique; \
else \
$(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
$$unique; \
fi; \
fi
ctags: CTAGS
CTAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
$(TAGS_FILES) $(LISP)
list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
unique=`for i in $$list; do \
if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
done | \
$(AWK) '{ files[$$0] = 1; nonempty = 1; } \
END { if (nonempty) { for (i in files) print i; }; }'`; \
test -z "$(CTAGS_ARGS)$$unique" \
|| $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \
$$unique
GTAGS:
here=`$(am__cd) $(top_builddir) && pwd` \
&& $(am__cd) $(top_srcdir) \
&& gtags -i $(GTAGS_ARGS) "$$here"
distclean-tags:
-rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
distdir: $(DISTFILES)
@srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
list='$(DISTFILES)'; \
dist_files=`for file in $$list; do echo $$file; done | \
sed -e "s|^$$srcdirstrip/||;t" \
-e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \
case $$dist_files in \
*/*) $(MKDIR_P) `echo "$$dist_files" | \
sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \
sort -u` ;; \
esac; \
for file in $$dist_files; do \
if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
if test -d $$d/$$file; then \
dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \
if test -d "$(distdir)/$$file"; then \
find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
fi; \
if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \
find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
fi; \
cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \
else \
test -f "$(distdir)/$$file" \
|| cp -p $$d/$$file "$(distdir)/$$file" \
|| exit 1; \
fi; \
done
check-am: all-am
check: check-am
all-am: Makefile $(LIBRARIES) $(LTLIBRARIES) $(HEADERS)
installdirs:
for dir in "$(DESTDIR)$(pkgplugindir)"; do \
test -z "$$dir" || $(MKDIR_P) "$$dir"; \
done
install: install-am
install-exec: install-exec-am
install-data: install-data-am
uninstall: uninstall-am
install-am: all-am
@$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
installcheck: installcheck-am
install-strip:
$(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
`test -z '$(STRIP)' || \
echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install
mostlyclean-generic:
clean-generic:
distclean-generic:
-test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
-test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES)
maintainer-clean-generic:
@echo "This command is intended for maintainers to use"
@echo "it deletes files that may require special tools to rebuild."
clean: clean-am
clean-am: clean-generic clean-libtool clean-noinstLIBRARIES \
clean-pkgpluginLTLIBRARIES mostlyclean-am
distclean: distclean-am
-rm -rf ./$(DEPDIR)
-rm -f Makefile
distclean-am: clean-am distclean-compile distclean-generic \
distclean-tags
dvi: dvi-am
dvi-am:
html: html-am
html-am:
info: info-am
info-am:
install-data-am: install-pkgpluginLTLIBRARIES
install-dvi: install-dvi-am
install-dvi-am:
install-exec-am:
install-html: install-html-am
install-html-am:
install-info: install-info-am
install-info-am:
install-man:
install-pdf: install-pdf-am
install-pdf-am:
install-ps: install-ps-am
install-ps-am:
installcheck-am:
maintainer-clean: maintainer-clean-am
-rm -rf ./$(DEPDIR)
-rm -f Makefile
maintainer-clean-am: distclean-am maintainer-clean-generic
mostlyclean: mostlyclean-am
mostlyclean-am: mostlyclean-compile mostlyclean-generic \
mostlyclean-libtool
pdf: pdf-am
pdf-am:
ps: ps-am
ps-am:
uninstall-am: uninstall-pkgpluginLTLIBRARIES
.MAKE: install-am install-strip
.PHONY: CTAGS GTAGS all all-am check check-am clean clean-generic \
clean-libtool clean-noinstLIBRARIES clean-pkgpluginLTLIBRARIES \
ctags distclean distclean-compile distclean-generic \
distclean-libtool distclean-tags distdir dvi dvi-am html \
html-am info info-am install install-am install-data \
install-data-am install-dvi install-dvi-am install-exec \
install-exec-am install-html install-html-am install-info \
install-info-am install-man install-pdf install-pdf-am \
install-pkgpluginLTLIBRARIES install-ps install-ps-am \
install-strip installcheck installcheck-am installdirs \
maintainer-clean maintainer-clean-generic mostlyclean \
mostlyclean-compile mostlyclean-generic mostlyclean-libtool \
pdf pdf-am ps ps-am tags uninstall uninstall-am \
uninstall-pkgpluginLTLIBRARIES
# Don't update the files from bitkeeper
%::SCCS/s.%
# Tell versions [3.59,3.63) of GNU make to not export all variables.
# Otherwise a system limit (for SysV at least) may be exceeded.
.NOEXPORT:
TARGETS= CMakeLists.txt
.DELETE_ON_ERROR:
.PHONY: CMakeLists.txt #It depends on the contents of the TOKUDB_DIR variable, simpler to just make it phony then depend on that.
ifeq ($(TOKUDB_DIR),)
#error
CMakeLists.txt: CMakeLists.in
false #Need to define TOKUDB_DIR
else
CMakeLists.txt: CMakeLists.in
sed -e "s?TOKUDB_DIR_REPLACE_ME?$(TOKUDB_DIR)?g" \
-e "s?TOKUDB_OBJ_DIR_REPLACE_ME?$(TOKUDB_OBJ_DIR)?g" \
-e "s?TOKUDB_VERSION_REPLACE_ME?$(TOKUDB_VERSION)?g" < $< > $@
endif
clean:
rm -f $(TARGETS)
...@@ -661,15 +661,14 @@ void set_key_filter(MY_BITMAP* key_filter, KEY* key, TABLE* table, bool get_offs ...@@ -661,15 +661,14 @@ void set_key_filter(MY_BITMAP* key_filter, KEY* key, TABLE* table, bool get_offs
// key is only the first 3 characters, and we end up losing the last 7 bytes of the // key is only the first 3 characters, and we end up losing the last 7 bytes of the
// column // column
// //
TOKU_TYPE toku_type; TOKU_TYPE toku_type = mysql_to_toku_type(field);
toku_type = mysql_to_toku_type(field); switch (toku_type) {
switch(toku_type) { case toku_type_blob:
case(toku_type_blob):
break; break;
case(toku_type_varbinary): case toku_type_varbinary:
case(toku_type_varstring): case toku_type_varstring:
case(toku_type_fixbinary): case toku_type_fixbinary:
case(toku_type_fixstring): case toku_type_fixstring:
if (key->key_part[curr_key_index].length == field->field_length) { if (key->key_part[curr_key_index].length == field->field_length) {
bitmap_set_bit(key_filter,i); bitmap_set_bit(key_filter,i);
} }
...@@ -8017,8 +8016,13 @@ void ha_tokudb::set_dup_value_for_pk(DBT* key) { ...@@ -8017,8 +8016,13 @@ void ha_tokudb::set_dup_value_for_pk(DBT* key) {
// table admin // table admin
#include "ha_tokudb_admin.cc" #include "ha_tokudb_admin.cc"
// alter table code for various mysql distros // update functions
#include "ha_tokudb_update_fun.cc" #include "ha_tokudb_update_fun.cc"
// fast updates
#include "ha_tokudb_update.cc"
// alter table code for various mysql distros
#include "ha_tokudb_alter_51.cc" #include "ha_tokudb_alter_51.cc"
#include "ha_tokudb_alter_55.cc" #include "ha_tokudb_alter_55.cc"
#include "ha_tokudb_alter_56.cc" #include "ha_tokudb_alter_56.cc"
......
...@@ -669,6 +669,18 @@ private: ...@@ -669,6 +669,18 @@ private:
#if TOKU_INCLUDE_WRITE_FRM_DATA #if TOKU_INCLUDE_WRITE_FRM_DATA
int write_frm_data(const uchar *frm_data, size_t frm_len); int write_frm_data(const uchar *frm_data, size_t frm_len);
#endif #endif
#if TOKU_INCLUDE_UPSERT
public:
bool fast_update(THD *thd, List<Item> &fields, List<Item> &values, Item *conds, int *error_ret);
private:
bool check_fast_update(THD *thd, List<Item> &fields, List<Item> &values, Item *conds);
int send_update_message(List<Item> &fields, List<Item> &values, Item *conds, DB_TXN *txn);
public:
bool upsert(THD *thd, uchar *record, List<Item> &update_fields, List<Item> &update_values, int *error_ret);
private:
bool check_upsert(THD *thd, List<Item> &update_fields, List<Item> &update_values);
int send_upsert_message(THD *thd, uchar *record, List<Item> &update_fields, List<Item> &update_values, DB_TXN *txn);
#endif
}; };
#if MYSQL_VERSION_ID >= 50506 #if MYSQL_VERSION_ID >= 50506
......
...@@ -49,8 +49,7 @@ public: ...@@ -49,8 +49,7 @@ public:
}; };
// Debug function to print out an alter table operation // Debug function to print out an alter table operation
void void ha_tokudb::print_alter_info(TABLE *altered_table, Alter_inplace_info *ha_alter_info) {
ha_tokudb::print_alter_info(TABLE *altered_table, Alter_inplace_info *ha_alter_info) {
printf("***are keys of two tables same? %d\n", tables_have_same_keys(table, altered_table, false, false)); printf("***are keys of two tables same? %d\n", tables_have_same_keys(table, altered_table, false, false));
if (ha_alter_info->handler_flags) { if (ha_alter_info->handler_flags) {
printf("***alter flags set ***\n"); printf("***alter flags set ***\n");
...@@ -103,8 +102,7 @@ ha_tokudb::print_alter_info(TABLE *altered_table, Alter_inplace_info *ha_alter_i ...@@ -103,8 +102,7 @@ ha_tokudb::print_alter_info(TABLE *altered_table, Alter_inplace_info *ha_alter_i
// Given two tables with equal number of fields, find all of the fields with different types // Given two tables with equal number of fields, find all of the fields with different types
// and return the indexes of the different fields in the changed_fields array. This function ignores field // and return the indexes of the different fields in the changed_fields array. This function ignores field
// name differences. // name differences.
static int static int find_changed_fields(TABLE *table_a, TABLE *table_b, Dynamic_array<uint> &changed_fields) {
find_changed_fields(TABLE *table_a, TABLE *table_b, Dynamic_array<uint> &changed_fields) {
for (uint i = 0; i < table_a->s->fields; i++) { for (uint i = 0; i < table_a->s->fields; i++) {
Field *field_a = table_a->field[i]; Field *field_a = table_a->field[i];
Field *field_b = table_b->field[i]; Field *field_b = table_b->field[i];
...@@ -119,8 +117,7 @@ static bool change_length_is_supported(TABLE *table, TABLE *altered_table, Alter ...@@ -119,8 +117,7 @@ static bool change_length_is_supported(TABLE *table, TABLE *altered_table, Alter
static bool change_type_is_supported(TABLE *table, TABLE *altered_table, Alter_inplace_info *ha_alter_info, tokudb_alter_ctx *ctx); static bool change_type_is_supported(TABLE *table, TABLE *altered_table, Alter_inplace_info *ha_alter_info, tokudb_alter_ctx *ctx);
// The ha_alter_info->handler_flags can not be trusted. This function maps the bogus handler flags to something we like. // The ha_alter_info->handler_flags can not be trusted. This function maps the bogus handler flags to something we like.
static ulong static ulong fix_handler_flags(TABLE *table, TABLE *altered_table, Alter_inplace_info *ha_alter_info) {
fix_handler_flags(TABLE *table, TABLE *altered_table, Alter_inplace_info *ha_alter_info) {
ulong handler_flags = ha_alter_info->handler_flags; ulong handler_flags = ha_alter_info->handler_flags;
// workaround for fill_alter_inplace_info bug (#5193) // workaround for fill_alter_inplace_info bug (#5193)
...@@ -151,8 +148,7 @@ fix_handler_flags(TABLE *table, TABLE *altered_table, Alter_inplace_info *ha_alt ...@@ -151,8 +148,7 @@ fix_handler_flags(TABLE *table, TABLE *altered_table, Alter_inplace_info *ha_alt
} }
// Require that there is no intersection of add and drop names. // Require that there is no intersection of add and drop names.
static bool static bool is_disjoint_add_drop(Alter_inplace_info *ha_alter_info) {
is_disjoint_add_drop(Alter_inplace_info *ha_alter_info) {
for (uint d = 0; d < ha_alter_info->index_drop_count; d++) { for (uint d = 0; d < ha_alter_info->index_drop_count; d++) {
KEY *drop_key = ha_alter_info->index_drop_buffer[d]; KEY *drop_key = ha_alter_info->index_drop_buffer[d];
for (uint a = 0; a < ha_alter_info->index_add_count; a++) { for (uint a = 0; a < ha_alter_info->index_add_count; a++) {
...@@ -180,8 +176,7 @@ static bool only_flags(ulong bits, ulong mask) { ...@@ -180,8 +176,7 @@ static bool only_flags(ulong bits, ulong mask) {
// must set WRITE_ALLOW_WRITE lock type in the external lock method to avoid deadlocks // must set WRITE_ALLOW_WRITE lock type in the external lock method to avoid deadlocks
// with the MDL lock and the table lock // with the MDL lock and the table lock
// HA_ALTER_INPLACE_EXCLUSIVE_LOCK: the alter operation requires an exclusive MDL no concurrent reads, no writes // HA_ALTER_INPLACE_EXCLUSIVE_LOCK: the alter operation requires an exclusive MDL no concurrent reads, no writes
enum_alter_inplace_result enum_alter_inplace_result ha_tokudb::check_if_supported_inplace_alter(TABLE *altered_table, Alter_inplace_info *ha_alter_info) {
ha_tokudb::check_if_supported_inplace_alter(TABLE *altered_table, Alter_inplace_info *ha_alter_info) {
TOKUDB_DBUG_ENTER("check_if_supported_alter"); TOKUDB_DBUG_ENTER("check_if_supported_alter");
if (tokudb_debug & TOKUDB_DEBUG_ALTER_TABLE_INFO) { if (tokudb_debug & TOKUDB_DEBUG_ALTER_TABLE_INFO) {
...@@ -334,8 +329,7 @@ ha_tokudb::check_if_supported_inplace_alter(TABLE *altered_table, Alter_inplace_ ...@@ -334,8 +329,7 @@ ha_tokudb::check_if_supported_inplace_alter(TABLE *altered_table, Alter_inplace_
} }
// Prepare for the alter operations // Prepare for the alter operations
bool bool ha_tokudb::prepare_inplace_alter_table(TABLE *altered_table, Alter_inplace_info *ha_alter_info) {
ha_tokudb::prepare_inplace_alter_table(TABLE *altered_table, Alter_inplace_info *ha_alter_info) {
TOKUDB_DBUG_ENTER("prepare_inplace_alter_table"); TOKUDB_DBUG_ENTER("prepare_inplace_alter_table");
tokudb_alter_ctx *ctx = static_cast<tokudb_alter_ctx *>(ha_alter_info->handler_ctx); tokudb_alter_ctx *ctx = static_cast<tokudb_alter_ctx *>(ha_alter_info->handler_ctx);
assert(transaction); // transaction must exist after table is locked assert(transaction); // transaction must exist after table is locked
...@@ -345,8 +339,7 @@ ha_tokudb::prepare_inplace_alter_table(TABLE *altered_table, Alter_inplace_info ...@@ -345,8 +339,7 @@ ha_tokudb::prepare_inplace_alter_table(TABLE *altered_table, Alter_inplace_info
} }
// Execute the alter operations. // Execute the alter operations.
bool bool ha_tokudb::inplace_alter_table(TABLE *altered_table, Alter_inplace_info *ha_alter_info) {
ha_tokudb::inplace_alter_table(TABLE *altered_table, Alter_inplace_info *ha_alter_info) {
TOKUDB_DBUG_ENTER("inplace_alter_table"); TOKUDB_DBUG_ENTER("inplace_alter_table");
int error = 0; int error = 0;
...@@ -398,8 +391,7 @@ ha_tokudb::inplace_alter_table(TABLE *altered_table, Alter_inplace_info *ha_alte ...@@ -398,8 +391,7 @@ ha_tokudb::inplace_alter_table(TABLE *altered_table, Alter_inplace_info *ha_alte
DBUG_RETURN(result); DBUG_RETURN(result);
} }
int int ha_tokudb::alter_table_add_index(TABLE *altered_table, Alter_inplace_info *ha_alter_info) {
ha_tokudb::alter_table_add_index(TABLE *altered_table, Alter_inplace_info *ha_alter_info) {
// sort keys in add index order // sort keys in add index order
KEY *key_info = (KEY*) my_malloc(sizeof (KEY) * ha_alter_info->index_add_count, MYF(MY_WME)); KEY *key_info = (KEY*) my_malloc(sizeof (KEY) * ha_alter_info->index_add_count, MYF(MY_WME));
...@@ -446,8 +438,7 @@ static bool find_index_of_key(const char *key_name, KEY *key_info, uint key_coun ...@@ -446,8 +438,7 @@ static bool find_index_of_key(const char *key_name, KEY *key_info, uint key_coun
return false; return false;
} }
int int ha_tokudb::alter_table_drop_index(TABLE *altered_table, Alter_inplace_info *ha_alter_info) {
ha_tokudb::alter_table_drop_index(TABLE *altered_table, Alter_inplace_info *ha_alter_info) {
KEY *key_info = table->key_info; KEY *key_info = table->key_info;
// translate key names to indexes into the key_info array // translate key names to indexes into the key_info array
uint index_drop_offsets[ha_alter_info->index_drop_count]; uint index_drop_offsets[ha_alter_info->index_drop_count];
...@@ -471,8 +462,7 @@ ha_tokudb::alter_table_drop_index(TABLE *altered_table, Alter_inplace_info *ha_a ...@@ -471,8 +462,7 @@ ha_tokudb::alter_table_drop_index(TABLE *altered_table, Alter_inplace_info *ha_a
return error; return error;
} }
int int ha_tokudb::alter_table_add_or_drop_column(TABLE *altered_table, Alter_inplace_info *ha_alter_info) {
ha_tokudb::alter_table_add_or_drop_column(TABLE *altered_table, Alter_inplace_info *ha_alter_info) {
tokudb_alter_ctx *ctx = static_cast<tokudb_alter_ctx *>(ha_alter_info->handler_ctx); tokudb_alter_ctx *ctx = static_cast<tokudb_alter_ctx *>(ha_alter_info->handler_ctx);
int error; int error;
uchar *column_extra = NULL; uchar *column_extra = NULL;
...@@ -555,8 +545,7 @@ ha_tokudb::alter_table_add_or_drop_column(TABLE *altered_table, Alter_inplace_in ...@@ -555,8 +545,7 @@ ha_tokudb::alter_table_add_or_drop_column(TABLE *altered_table, Alter_inplace_in
// Commit or abort the alter operations. // Commit or abort the alter operations.
// If commit then write the new frm data to the status using the alter transaction. // If commit then write the new frm data to the status using the alter transaction.
// If abort then abort the alter transaction and try to rollback the non-transactional changes. // If abort then abort the alter transaction and try to rollback the non-transactional changes.
bool bool ha_tokudb::commit_inplace_alter_table(TABLE *altered_table, Alter_inplace_info *ha_alter_info, bool commit) {
ha_tokudb::commit_inplace_alter_table(TABLE *altered_table, Alter_inplace_info *ha_alter_info, bool commit) {
TOKUDB_DBUG_ENTER("commit_inplace_alter_table"); TOKUDB_DBUG_ENTER("commit_inplace_alter_table");
tokudb_alter_ctx *ctx = static_cast<tokudb_alter_ctx *>(ha_alter_info->handler_ctx); tokudb_alter_ctx *ctx = static_cast<tokudb_alter_ctx *>(ha_alter_info->handler_ctx);
...@@ -615,8 +604,7 @@ ha_tokudb::commit_inplace_alter_table(TABLE *altered_table, Alter_inplace_info * ...@@ -615,8 +604,7 @@ ha_tokudb::commit_inplace_alter_table(TABLE *altered_table, Alter_inplace_info *
} }
// Setup the altered table's key and col info. // Setup the altered table's key and col info.
int int ha_tokudb::setup_kc_info(TABLE *altered_table, KEY_AND_COL_INFO *altered_kc_info) {
ha_tokudb::setup_kc_info(TABLE *altered_table, KEY_AND_COL_INFO *altered_kc_info) {
int error = allocate_key_and_col_info(altered_table->s, altered_kc_info); int error = allocate_key_and_col_info(altered_table->s, altered_kc_info);
if (error == 0) if (error == 0)
error = initialize_key_and_col_info(altered_table->s, altered_table, altered_kc_info, hidden_primary_key, primary_key); error = initialize_key_and_col_info(altered_table->s, altered_table, altered_kc_info, hidden_primary_key, primary_key);
...@@ -624,8 +612,7 @@ ha_tokudb::setup_kc_info(TABLE *altered_table, KEY_AND_COL_INFO *altered_kc_info ...@@ -624,8 +612,7 @@ ha_tokudb::setup_kc_info(TABLE *altered_table, KEY_AND_COL_INFO *altered_kc_info
} }
// Expand the variable length fields offsets from 1 to 2 bytes. // Expand the variable length fields offsets from 1 to 2 bytes.
int int ha_tokudb::alter_table_expand_varchar_offsets(TABLE *altered_table, Alter_inplace_info *ha_alter_info) {
ha_tokudb::alter_table_expand_varchar_offsets(TABLE *altered_table, Alter_inplace_info *ha_alter_info) {
int error = 0; int error = 0;
tokudb_alter_ctx *ctx = static_cast<tokudb_alter_ctx *>(ha_alter_info->handler_ctx); tokudb_alter_ctx *ctx = static_cast<tokudb_alter_ctx *>(ha_alter_info->handler_ctx);
...@@ -677,8 +664,7 @@ ha_tokudb::alter_table_expand_varchar_offsets(TABLE *altered_table, Alter_inplac ...@@ -677,8 +664,7 @@ ha_tokudb::alter_table_expand_varchar_offsets(TABLE *altered_table, Alter_inplac
} }
// Return true if a field is part of a key // Return true if a field is part of a key
static bool static bool field_in_key(KEY *key, Field *field) {
field_in_key(KEY *key, Field *field) {
for (uint i = 0; i < key->key_parts; i++) { for (uint i = 0; i < key->key_parts; i++) {
KEY_PART_INFO *key_part = &key->key_part[i]; KEY_PART_INFO *key_part = &key->key_part[i];
if (strcmp(key_part->field->field_name, field->field_name) == 0) if (strcmp(key_part->field->field_name, field->field_name) == 0)
...@@ -688,8 +674,7 @@ field_in_key(KEY *key, Field *field) { ...@@ -688,8 +674,7 @@ field_in_key(KEY *key, Field *field) {
} }
// Return true if a field is part of any key // Return true if a field is part of any key
static bool static bool field_in_key_of_table(TABLE *table, Field *field) {
field_in_key_of_table(TABLE *table, Field *field) {
for (uint i = 0; i < table->s->keys; i++) { for (uint i = 0; i < table->s->keys; i++) {
if (field_in_key(&table->key_info[i], field)) if (field_in_key(&table->key_info[i], field))
return true; return true;
...@@ -698,8 +683,7 @@ field_in_key_of_table(TABLE *table, Field *field) { ...@@ -698,8 +683,7 @@ field_in_key_of_table(TABLE *table, Field *field) {
} }
// Return true if all changed varchar/varbinary field lengths can be changed inplace, otherwise return false // Return true if all changed varchar/varbinary field lengths can be changed inplace, otherwise return false
static bool static bool change_varchar_length_is_supported(Field *old_field, Field *new_field, TABLE *table, TABLE *altered_table, Alter_inplace_info *ha_alter_info, tokudb_alter_ctx *ctx) {
change_varchar_length_is_supported(Field *old_field, Field *new_field, TABLE *table, TABLE *altered_table, Alter_inplace_info *ha_alter_info, tokudb_alter_ctx *ctx) {
if (old_field->real_type() != MYSQL_TYPE_VARCHAR || if (old_field->real_type() != MYSQL_TYPE_VARCHAR ||
new_field->real_type() != MYSQL_TYPE_VARCHAR || new_field->real_type() != MYSQL_TYPE_VARCHAR ||
old_field->binary() != new_field->binary() || old_field->binary() != new_field->binary() ||
...@@ -714,8 +698,7 @@ change_varchar_length_is_supported(Field *old_field, Field *new_field, TABLE *ta ...@@ -714,8 +698,7 @@ change_varchar_length_is_supported(Field *old_field, Field *new_field, TABLE *ta
} }
// Return true if all changed field lengths can be changed inplace, otherwise return false // Return true if all changed field lengths can be changed inplace, otherwise return false
static bool static bool change_length_is_supported(TABLE *table, TABLE *altered_table, Alter_inplace_info *ha_alter_info, tokudb_alter_ctx *ctx) {
change_length_is_supported(TABLE *table, TABLE *altered_table, Alter_inplace_info *ha_alter_info, tokudb_alter_ctx *ctx) {
if (table->s->fields != altered_table->s->fields) if (table->s->fields != altered_table->s->fields)
return false; return false;
if (table->s->null_bytes != altered_table->s->null_bytes) if (table->s->null_bytes != altered_table->s->null_bytes)
...@@ -740,8 +723,7 @@ change_length_is_supported(TABLE *table, TABLE *altered_table, Alter_inplace_inf ...@@ -740,8 +723,7 @@ change_length_is_supported(TABLE *table, TABLE *altered_table, Alter_inplace_inf
} }
// Debug function that ensures that the array is sorted // Debug function that ensures that the array is sorted
static bool static bool is_sorted(Dynamic_array<uint> &a) {
is_sorted(Dynamic_array<uint> &a) {
bool r = true; bool r = true;
if (a.elements() > 0) { if (a.elements() > 0) {
uint lastelement = a.at(0); uint lastelement = a.at(0);
...@@ -752,8 +734,7 @@ is_sorted(Dynamic_array<uint> &a) { ...@@ -752,8 +734,7 @@ is_sorted(Dynamic_array<uint> &a) {
return r; return r;
} }
int int ha_tokudb::alter_table_expand_columns(TABLE *altered_table, Alter_inplace_info *ha_alter_info) {
ha_tokudb::alter_table_expand_columns(TABLE *altered_table, Alter_inplace_info *ha_alter_info) {
int error = 0; int error = 0;
tokudb_alter_ctx *ctx = static_cast<tokudb_alter_ctx *>(ha_alter_info->handler_ctx); tokudb_alter_ctx *ctx = static_cast<tokudb_alter_ctx *>(ha_alter_info->handler_ctx);
assert(is_sorted(ctx->changed_fields)); // since we build the changed_fields array in field order, it must be sorted assert(is_sorted(ctx->changed_fields)); // since we build the changed_fields array in field order, it must be sorted
...@@ -765,9 +746,15 @@ ha_tokudb::alter_table_expand_columns(TABLE *altered_table, Alter_inplace_info * ...@@ -765,9 +746,15 @@ ha_tokudb::alter_table_expand_columns(TABLE *altered_table, Alter_inplace_info *
return error; return error;
} }
// Return true if the field is an unsigned int
static bool is_unsigned(Field *f) {
return (f->flags & UNSIGNED_FLAG) != 0;
}
// Return the starting offset in the value for a particular index (selected by idx) of a // Return the starting offset in the value for a particular index (selected by idx) of a
// particular field (selected by expand_field_num) // particular field (selected by expand_field_num)
static uint32_t field_offset(uint32_t null_bytes, KEY_AND_COL_INFO *kc_info, int idx, int expand_field_num) { // TODO: replace this?
static uint32_t alter_table_field_offset(uint32_t null_bytes, KEY_AND_COL_INFO *kc_info, int idx, int expand_field_num) {
uint32_t offset = null_bytes; uint32_t offset = null_bytes;
for (int i = 0; i < expand_field_num; i++) { for (int i = 0; i < expand_field_num; i++) {
if (bitmap_is_set(&kc_info->key_filters[idx], i)) // skip key fields if (bitmap_is_set(&kc_info->key_filters[idx], i)) // skip key fields
...@@ -777,14 +764,8 @@ static uint32_t field_offset(uint32_t null_bytes, KEY_AND_COL_INFO *kc_info, int ...@@ -777,14 +764,8 @@ static uint32_t field_offset(uint32_t null_bytes, KEY_AND_COL_INFO *kc_info, int
return offset; return offset;
} }
// Return true of the field is an unsigned int
static bool is_unsigned(Field *f) {
return (f->flags & UNSIGNED_FLAG) != 0;
}
// Send an expand message into all clustered indexes including the primary // Send an expand message into all clustered indexes including the primary
int int ha_tokudb::alter_table_expand_one_column(TABLE *altered_table, Alter_inplace_info *ha_alter_info, int expand_field_num) {
ha_tokudb::alter_table_expand_one_column(TABLE *altered_table, Alter_inplace_info *ha_alter_info, int expand_field_num) {
int error = 0; int error = 0;
tokudb_alter_ctx *ctx = static_cast<tokudb_alter_ctx *>(ha_alter_info->handler_ctx); tokudb_alter_ctx *ctx = static_cast<tokudb_alter_ctx *>(ha_alter_info->handler_ctx);
...@@ -830,8 +811,8 @@ ha_tokudb::alter_table_expand_one_column(TABLE *altered_table, Alter_inplace_inf ...@@ -830,8 +811,8 @@ ha_tokudb::alter_table_expand_one_column(TABLE *altered_table, Alter_inplace_inf
// for all trees that have values, make an expand update message and broadcast it into the tree // for all trees that have values, make an expand update message and broadcast it into the tree
if (i == primary_key || (table_share->key_info[i].flags & HA_CLUSTERING)) { if (i == primary_key || (table_share->key_info[i].flags & HA_CLUSTERING)) {
uint32_t old_offset = field_offset(table_share->null_bytes, ctx->table_kc_info, i, expand_field_num); uint32_t old_offset = alter_table_field_offset(table_share->null_bytes, ctx->table_kc_info, i, expand_field_num);
uint32_t new_offset = field_offset(table_share->null_bytes, ctx->altered_table_kc_info, i, expand_field_num); uint32_t new_offset = alter_table_field_offset(table_share->null_bytes, ctx->altered_table_kc_info, i, expand_field_num);
assert(old_offset <= new_offset); assert(old_offset <= new_offset);
uint32_t old_length = ctx->table_kc_info->field_lengths[expand_field_num]; uint32_t old_length = ctx->table_kc_info->field_lengths[expand_field_num];
...@@ -882,9 +863,20 @@ ha_tokudb::alter_table_expand_one_column(TABLE *altered_table, Alter_inplace_inf ...@@ -882,9 +863,20 @@ ha_tokudb::alter_table_expand_one_column(TABLE *altered_table, Alter_inplace_inf
return error; return error;
} }
// Return true if two fixed length fields can be changed inplace
static bool change_fixed_length_is_supported(TABLE *table, TABLE *altered_table, Field *old_field, Field *new_field, tokudb_alter_ctx *ctx) {
// no change in size is supported
if (old_field->pack_length() == new_field->pack_length())
return true;
// shrink is not supported
if (old_field->pack_length() > new_field->pack_length())
return false;
ctx->expand_fixed_update_needed = true;
return true;
}
// Return true if the MySQL type is an int or unsigned int type // Return true if the MySQL type is an int or unsigned int type
static bool static bool is_int_type(enum_field_types t) {
is_int_type(enum_field_types t) {
switch (t) { switch (t) {
case MYSQL_TYPE_TINY: case MYSQL_TYPE_TINY:
case MYSQL_TYPE_SHORT: case MYSQL_TYPE_SHORT:
...@@ -897,22 +889,8 @@ is_int_type(enum_field_types t) { ...@@ -897,22 +889,8 @@ is_int_type(enum_field_types t) {
} }
} }
// Return true if two fixed length fields can be changed inplace
static bool
change_fixed_length_is_supported(TABLE *table, TABLE *altered_table, Field *old_field, Field *new_field, tokudb_alter_ctx *ctx) {
// no change in size is supported
if (old_field->pack_length() == new_field->pack_length())
return true;
// shrink is not supported
if (old_field->pack_length() > new_field->pack_length())
return false;
ctx->expand_fixed_update_needed = true;
return true;
}
// Return true if two field types can be changed inplace // Return true if two field types can be changed inplace
static bool static bool change_field_type_is_supported(Field *old_field, Field *new_field, TABLE *table, TABLE *altered_table, Alter_inplace_info *ha_alter_info, tokudb_alter_ctx *ctx) {
change_field_type_is_supported(Field *old_field, Field *new_field, TABLE *table, TABLE *altered_table, Alter_inplace_info *ha_alter_info, tokudb_alter_ctx *ctx) {
enum_field_types old_type = old_field->real_type(); enum_field_types old_type = old_field->real_type();
enum_field_types new_type = new_field->real_type(); enum_field_types new_type = new_field->real_type();
if (is_int_type(old_type)) { if (is_int_type(old_type)) {
...@@ -951,8 +929,7 @@ change_field_type_is_supported(Field *old_field, Field *new_field, TABLE *table, ...@@ -951,8 +929,7 @@ change_field_type_is_supported(Field *old_field, Field *new_field, TABLE *table,
} }
// Return true if all changed field types can be changed inplace // Return true if all changed field types can be changed inplace
static bool static bool change_type_is_supported(TABLE *table, TABLE *altered_table, Alter_inplace_info *ha_alter_info, tokudb_alter_ctx *ctx) {
change_type_is_supported(TABLE *table, TABLE *altered_table, Alter_inplace_info *ha_alter_info, tokudb_alter_ctx *ctx) {
if (table->s->null_bytes != altered_table->s->null_bytes) if (table->s->null_bytes != altered_table->s->null_bytes)
return false; return false;
if (table->s->fields != altered_table->s->fields) if (table->s->fields != altered_table->s->fields)
...@@ -974,8 +951,7 @@ change_type_is_supported(TABLE *table, TABLE *altered_table, Alter_inplace_info ...@@ -974,8 +951,7 @@ change_type_is_supported(TABLE *table, TABLE *altered_table, Alter_inplace_info
// Allocate and initialize a new descriptor for a dictionary in the altered table identified with idx. // Allocate and initialize a new descriptor for a dictionary in the altered table identified with idx.
// Return the new descriptor in the row_descriptor DBT. // Return the new descriptor in the row_descriptor DBT.
// Return non-zero on error. // Return non-zero on error.
int int ha_tokudb::new_row_descriptor(TABLE *table, TABLE *altered_table, Alter_inplace_info *ha_alter_info, uint32_t idx, DBT *row_descriptor) {
ha_tokudb::new_row_descriptor(TABLE *table, TABLE *altered_table, Alter_inplace_info *ha_alter_info, uint32_t idx, DBT *row_descriptor) {
int error = 0; int error = 0;
tokudb_alter_ctx *ctx = static_cast<tokudb_alter_ctx *>(ha_alter_info->handler_ctx); tokudb_alter_ctx *ctx = static_cast<tokudb_alter_ctx *>(ha_alter_info->handler_ctx);
row_descriptor->size = get_max_desc_size(ctx->altered_table_kc_info, altered_table); row_descriptor->size = get_max_desc_size(ctx->altered_table_kc_info, altered_table);
...@@ -1006,5 +982,4 @@ ha_tokudb::new_row_descriptor(TABLE *table, TABLE *altered_table, Alter_inplace_ ...@@ -1006,5 +982,4 @@ ha_tokudb::new_row_descriptor(TABLE *table, TABLE *altered_table, Alter_inplace_
return error; return error;
} }
#endif #endif
#if TOKU_INCLUDE_UPSERT
// Point updates and upserts
//
// Restrictions:
// No triggers
// No binary logging
// Primary key must be defined
// Simple and compound primary key
// Int, char and varchar primary key types
// No updates on fields that are part of any key
// No clustering keys
// Integer and char field updates
// Update expressions:
// x = constant
// x = x+constant
// x = x-constant
// x = if(x=0,0,x-1)
// Session variable enables fast updates and fast upserts
// Session variable disables slow updates and slow upserts
// Bugs:
// Does this work with hot indexing? Probably not.
// Future features:
// Support more primary key types
// Allow statement based binary logging
// Force statement logging for fast updates
// Support clustering keys using broadcast updates
// Support primary key ranges using multicast messages
// Support more complicated update expressions
// Replace field_offset
int tokudb_fast_update_debug = 0;
int tokudb_upsert_debug = 0;
// Debug function to dump an Item
static void dump_item(Item *item) {
fprintf(stderr, "%u", item->type());
switch (item->type()) {
case Item::FUNC_ITEM: {
Item_func *func = static_cast<Item_func*>(item);
uint n = func->argument_count();
Item **arguments = func->arguments();
fprintf(stderr, ":func=%u,%s,%u(", func->functype(), func->func_name(), n);
for (uint i = 0; i < n ; i++) {
dump_item(arguments[i]);
if (i < n-1)
fprintf(stderr,",");
}
fprintf(stderr, ")");
break;
}
case Item::INT_ITEM: {
Item_int *int_item = static_cast<Item_int*>(item);
fprintf(stderr, ":int=%lld", int_item->val_int());
break;
}
case Item::STRING_ITEM: {
Item_string *str_item = static_cast<Item_string*>(item);
fprintf(stderr, ":str=%s", str_item->val_str(NULL)->c_ptr());
break;
}
case Item::FIELD_ITEM: {
Item_field *field_item = static_cast<Item_field*>(item);
fprintf(stderr, ":field=%s.%s.%s", field_item->db_name, field_item->table_name, field_item->field_name);
break;
}
case Item::COND_ITEM: {
Item_cond *cond_item = static_cast<Item_cond*>(item);
fprintf(stderr, ":cond=%s(\n", cond_item->func_name());
List_iterator<Item> li(*cond_item->argument_list());
Item *list_item;
while ((list_item = li++)) {
dump_item(list_item);
fprintf(stderr, "\n");
}
fprintf(stderr, ")\n");
break;
}
default:
break;
}
}
// Debug function to dump an Item list
static void dump_item_list(const char *h, List<Item> &l) {
fprintf(stderr, "%s elements=%u\n", h, l.elements);
List_iterator<Item> li(l);
Item *item;
while ((item = li++) != NULL) {
dump_item(item);
fprintf(stderr, "\n");
}
}
// Find a Field by its Item name
static Field *find_field_by_name(TABLE *table, Item *item) {
if (item->type() != Item::FIELD_ITEM)
return NULL;
Item_field *field_item = static_cast<Item_field*>(item);
#if 0
if (strcmp(table->s->db.str, field_item->db_name) != 0 ||
strcmp(table->s->table_name.str, field_item->table_name) != 0)
return NULL;
// TODO: item->field may be a shortcut instead of this table lookup
Field *found_field = NULL;
for (uint i = 0; i < table->s->fields; i++) {
Field *test_field = table->s->field[i];
if (strcmp(field_item->field_name, test_field->field_name) == 0) {
found_field = test_field;
break;
}
}
return found_field;
#else
return field_item->field;
#endif
}
// Return the starting offset in the value for a particular index (selected by idx) of a
// particular field (selected by expand_field_num).
// This only works for fixed length fields
static uint32_t update_field_offset(uint32_t null_bytes, KEY_AND_COL_INFO *kc_info, int idx, int expand_field_num) {
uint32_t offset = null_bytes;
for (int i = 0; i < expand_field_num; i++) {
if (bitmap_is_set(&kc_info->key_filters[idx], i)) // skip key fields
continue;
offset += kc_info->field_lengths[i];
}
return offset;
}
// Determine if an update operation can be offloaded to the storage engine.
// The update operation consists of a list of update expressions (fields[i] = values[i]), and a list
// of where conditions (conds). The function returns true is the update is handled in the storage engine.
// Otherwise, false is returned.
bool ha_tokudb::fast_update(THD *thd, List<Item> &fields, List<Item> &values, Item *conds, int *error_ret) {
int error = 0;
if (tokudb_fast_update_debug) {
dump_item_list("fields", fields);
dump_item_list("values", values);
if (conds) {
fprintf(stderr, "conds\n"); dump_item(conds); fprintf(stderr, "\n");
}
}
if (fields.elements < 1 || fields.elements != values.elements)
return false; // something is fishy with the parameters
if (thd->is_strict_mode() || !transaction || !check_fast_update(thd, fields, values, conds)) {
error = 1;
} else {
error = send_update_message(fields, values, conds, transaction);
}
if (error == 0) {
error = -1; // success for mysql_update TODO: move this into the mysql code
} else {
if (get_disable_slow_update(thd))
error = HA_ERR_UNSUPPORTED;
else
return false;
print_error(error, MYF(0));
}
*error_ret = error;
return true;
}
// Return true if an expression is a simple int expression or a simple function of +- int expression.
static bool check_int_result(Item *item) {
Item::Type t = item->type();
if (t == Item::INT_ITEM)
return true;
else if (t == Item::FUNC_ITEM) {
Item_func *item_func = static_cast<Item_func*>(item);
if (strcmp(item_func->func_name(), "+") != 0 && strcmp(item_func->func_name(), "-") != 0)
return false;
if (item_func->argument_count() != 1)
return false;
Item **arguments = item_func->arguments();
if (arguments[0]->type() != Item::INT_ITEM)
return false;
return true;
} else
return false;
}
// Return true if an expression looks like field_name op constant.
static bool check_x_op_constant(const char *field_name, Item *item, const char *op, Item **item_constant) {
if (item->type() != Item::FUNC_ITEM)
return false;
Item_func *item_func = static_cast<Item_func*>(item);
if (strcmp(item_func->func_name(), op) != 0)
return false;
Item **arguments = item_func->arguments();
uint n = item_func->argument_count();
if (n != 2)
return false;
if (arguments[0]->type() != Item::FIELD_ITEM)
return false;
Item_field *arg0 = static_cast<Item_field*>(arguments[0]);
if (strcmp(field_name, arg0->field_name) != 0)
return false;
if (!check_int_result(arguments[1]))
return false;
*item_constant = arguments[1];
return true;
}
// Return true if an expression looks like field_name = constant
static bool check_x_equal_0(const char *field_name, Item *item) {
Item *item_constant;
if (!check_x_op_constant(field_name, item, "=", &item_constant))
return false;
if (item_constant->val_int() != 0)
return false;
return true;
}
// Return true if an expression looks like fieldname - 1
static bool check_x_minus_1(const char *field_name, Item *item) {
Item *item_constant;
if (!check_x_op_constant(field_name, item, "-", &item_constant))
return false;
if (item_constant->val_int() != 1)
return false;
return true;
}
// Return true if an expression looks like if(fieldname=0, 0, fieldname-1) and
// the field named by fieldname is an unsigned int.
static bool check_decr_floor_expression(Field *lhs_field, Item *item) {
if (item->type() != Item::FUNC_ITEM)
return false;
Item_func *item_func = static_cast<Item_func*>(item);
Item **arguments = item_func->arguments();
uint n = item_func->argument_count();
if (n != 3)
return false;
if (!check_x_equal_0(lhs_field->field_name, arguments[0]))
return false;
if (arguments[1]->type() != Item::INT_ITEM || arguments[1]->val_int() != 0)
return false;
if (!check_x_minus_1(lhs_field->field_name, arguments[2]))
return false;
if (!(lhs_field->flags & UNSIGNED_FLAG))
return false;
return true;
}
// Check if lhs = rhs expression is simple. Return true if it is.
static bool check_simple_update_expression(Item *lhs_item, Item *rhs_item, TABLE *table) {
Field *lhs_field = find_field_by_name(table, lhs_item);
if (lhs_field == NULL)
return false;
if (!lhs_field->part_of_key.is_clear_all())
return false;
enum_field_types lhs_type = lhs_field->type();
Item::Type rhs_type = rhs_item->type();
switch (lhs_type) {
case MYSQL_TYPE_TINY:
case MYSQL_TYPE_SHORT:
case MYSQL_TYPE_INT24:
case MYSQL_TYPE_LONG:
case MYSQL_TYPE_LONGLONG:
if (check_int_result(rhs_item))
return true;
Item *item_constant;
if (check_x_op_constant(lhs_field->field_name, rhs_item, "+", &item_constant))
return true;
if (check_x_op_constant(lhs_field->field_name, rhs_item, "-", &item_constant))
return true;
if (check_decr_floor_expression(lhs_field, rhs_item))
return true;
break;
case MYSQL_TYPE_STRING:
if (rhs_type == Item::INT_ITEM || rhs_type == Item::STRING_ITEM)
return true;
break;
default:
break;
}
return false;
}
// Check that all update expressions are simple. Return true if they are.
static bool check_all_update_expressions(List<Item> &fields, List<Item> &values, TABLE *table) {
List_iterator<Item> lhs_i(fields);
List_iterator<Item> rhs_i(values);
while (1) {
Item *lhs_item = lhs_i++;
if (lhs_item == NULL)
break;
Item *rhs_item = rhs_i++;
if (rhs_item == NULL)
assert(0); // can not happen
if (!check_simple_update_expression(lhs_item, rhs_item, table))
return false;
}
return true;
}
#if 0
static bool field_name_in_primary_key(TABLE *table, const char *field_name) {
if (table->s->primary_key >= table->s->keys)
return false;
KEY *key = &table->s->key_info[table->s->primary_key];
if (key->key_parts != 1)
return false;
KEY_PART_INFO *key_part = &key->key_part[0];
if (key->key_length != key_part->store_length)
return false;
if (strcmp(field_name, key_part->field->field_name) != 0)
return false;
return true;
}
#endif
// Check that an expression looks like fieldname = constant, fieldname is part of the
// primary key, and the named field is an int, char or varchar type. Return true if it does.
static bool check_pk_field_equal_constant(Item *item, TABLE *table, MY_BITMAP &pk_fields) {
if (item->type() != Item::FUNC_ITEM)
return false;
Item_func *func = static_cast<Item_func*>(item);
if (strcmp(func->func_name(), "=") != 0)
return false;
uint n = func->argument_count();
if (n != 2)
return false;
Item **arguments = func->arguments();
Field *field = find_field_by_name(table, arguments[0]);
if (field == NULL)
return false;
if (!bitmap_test_and_clear(&pk_fields, field->field_index))
return false;
switch (field->type()) {
case MYSQL_TYPE_TINY:
case MYSQL_TYPE_SHORT:
case MYSQL_TYPE_INT24:
case MYSQL_TYPE_LONG:
case MYSQL_TYPE_LONGLONG:
case MYSQL_TYPE_STRING:
case MYSQL_TYPE_VARCHAR:
return arguments[1]->type() == Item::INT_ITEM || arguments[1]->type() == Item::STRING_ITEM;
default:
return false;
}
}
// Check that the where condition covers all of the primary key components with fieldname = constant
// expressions. Return true if it does.
static bool check_point_update(Item *conds, TABLE *table) {
bool result = false;
if (conds == NULL)
return false; // no where condition on the update
if (table->s->primary_key >= table->s->keys)
return false; // no primary key defined
// use a bitmap of the primary key fields to keep track of those fields that are covered
// by the where conditions
MY_BITMAP pk_fields;
if (bitmap_init(&pk_fields, NULL, table->s->fields, FALSE)) // 1 -> failure
return false;
KEY *key = &table->s->key_info[table->s->primary_key];
for (uint i = 0; i < key->key_parts; i++)
bitmap_set_bit(&pk_fields, key->key_part[i].field->field_index);
switch (conds->type()) {
case Item::FUNC_ITEM:
result = check_pk_field_equal_constant(conds, table, pk_fields);
break;
case Item::COND_ITEM: {
Item_cond *cond_item = static_cast<Item_cond*>(conds);
if (strcmp(cond_item->func_name(), "and") != 0)
break;
List_iterator<Item> li(*cond_item->argument_list());
Item *list_item;
result = true;
while (result == true && (list_item = li++)) {
result = check_pk_field_equal_constant(list_item, table, pk_fields);
}
break;
}
default:
break;
}
if (!bitmap_is_clear_all(&pk_fields))
result = false;
bitmap_free(&pk_fields);
return result;
}
// Return true if there are any clustering keys (except the primary).
// Precompute this when the table is opened.
static bool clustering_keys_exist(TABLE *table) {
for (uint i = 0; i < table->s->keys; i++)
if (i != table->s->primary_key && (table->s->key_info[i].flags & HA_CLUSTERING))
return true;
return false;
}
#include <binlog.h>
// Check if an update operation can be handled by this storage engine. Return true if it can.
bool ha_tokudb::check_fast_update(THD *thd, List<Item> &fields, List<Item> &values, Item *conds) {
// no triggers
if (table->triggers)
return false;
// no binlog
if (mysql_bin_log.is_open())
return false;
// no clustering keys (need to broadcast an increment into the clustering keys since we are selecting with the primary key)
if (clustering_keys_exist(table))
return false;
// fast updates enabled with session variable
if (!get_enable_fast_update(thd))
return false;
if (!check_all_update_expressions(fields, values, table))
return false;
if (!check_point_update(conds, table))
return false;
return true;
}
// Marshall a simple row descriptor to a buffer.
static void marshall_simple_descriptor(tokudb::buffer &b, TABLE *table, KEY_AND_COL_INFO &kc_info, uint key_num) {
Simple_row_descriptor sd;
sd.m_fixed_field_offset = table->s->null_bytes;
sd.m_var_field_offset = sd.m_fixed_field_offset + kc_info.mcp_info[key_num].fixed_field_size;
sd.m_var_offset_bytes = kc_info.mcp_info[key_num].len_of_offsets;
sd.m_num_var_fields = sd.m_var_offset_bytes == 0 ? 0 : kc_info.mcp_info[key_num].len_of_offsets / sd.m_var_offset_bytes;
sd.append(b);
}
static inline uint32_t get_null_bit_position(uint32_t null_bit);
// Marshall update operatins to a buffer.
static void marshall_simple_update(tokudb::buffer &b, Item *lhs_item, Item *rhs_item, TABLE *table, TOKUDB_SHARE *share) {
// figure out the update operation type (again)
Field *lhs_field = find_field_by_name(table, lhs_item);
assert(lhs_field); // we found it before, so this should work
// compute the update info
uint32_t field_type;
uint32_t field_num = lhs_field->field_index;
uint32_t field_null_num = 0;
if (lhs_field->real_maybe_null())
field_null_num = (1<<31) + (field_num/8)*8 + get_null_bit_position(lhs_field->null_bit);
uint32_t offset = update_field_offset(table->s->null_bytes, &share->kc_info, table->s->primary_key, lhs_field->field_index);
void *v_ptr = NULL;
uint32_t v_length;
uint32_t update_operation;
longlong v_ll;
String v_str;
switch (lhs_field->type()) {
case MYSQL_TYPE_TINY:
case MYSQL_TYPE_SHORT:
case MYSQL_TYPE_INT24:
case MYSQL_TYPE_LONG:
case MYSQL_TYPE_LONGLONG: {
Field_num *lhs_num = static_cast<Field_num*>(lhs_field);
field_type = lhs_num->unsigned_flag ? UPDATE_TYPE_UINT : UPDATE_TYPE_INT;
switch (rhs_item->type()) {
case Item::INT_ITEM: {
update_operation = '=';
v_ll = rhs_item->val_int();
v_length = lhs_field->pack_length();
v_ptr = &v_ll;
break;
}
case Item::FUNC_ITEM: {
Item_func *rhs_func = static_cast<Item_func*>(rhs_item);
Item **arguments = rhs_func->arguments();
if (strcmp(rhs_func->func_name(), "if") == 0) {
update_operation = '-'; // we only support one if function for now, and it is a descrement with floor.
v_ll = 1;
} else if (rhs_func->argument_count() == 1) {
update_operation = '=';
v_ll = rhs_func->val_int();
} else {
update_operation = rhs_func->func_name()[0];
v_ll = arguments[1]->val_int();
}
v_length = lhs_field->pack_length();
v_ptr = &v_ll;
break;
}
default:
assert(0);
}
break;
}
case MYSQL_TYPE_STRING: {
update_operation = '=';
field_type = lhs_field->binary() ? UPDATE_TYPE_BINARY : UPDATE_TYPE_CHAR;
v_str = *rhs_item->val_str(&v_str);
v_length = v_str.length();
if (v_length >= lhs_field->pack_length()) {
v_length = lhs_field->pack_length();
v_str.length(v_length); // truncate
} else {
v_length = lhs_field->pack_length();
uchar pad_char = lhs_field->binary() ? 0 : lhs_field->charset()->pad_char;
v_str.fill(lhs_field->pack_length(), pad_char); // pad
}
v_ptr = v_str.c_ptr();
break;
}
default:
assert(0);
}
// marshall the update fields into the buffer
b.append(&update_operation, sizeof update_operation);
b.append(&field_type, sizeof field_type);
b.append(&field_num, sizeof field_num);
b.append(&field_null_num, sizeof field_null_num);
b.append(&offset, sizeof offset);
b.append(&v_length, sizeof v_length);
b.append(v_ptr, v_length);
}
// Save an item's value into the appropriate field. Return 0 if successful.
static int save_in_field(Item *item, TABLE *table) {
assert(item->type() == Item::FUNC_ITEM);
Item_func *func = static_cast<Item_func*>(item);
assert(strcmp(func->func_name(), "=") == 0);
uint n = func->argument_count();
assert(n == 2);
Item **arguments = func->arguments();
assert(arguments[0]->type() == Item::FIELD_ITEM);
Item_field *field_item = static_cast<Item_field*>(arguments[0]);
my_bitmap_map *old_map = dbug_tmp_use_all_columns(table, table->write_set);
int error = arguments[1]->save_in_field(field_item->field, 0);
dbug_tmp_restore_column_map(table->write_set, old_map);
return error;
}
// Generate an update message for an update operation and send it into the primary tree. Return 0 if successful.
int ha_tokudb::send_update_message(List<Item> &fields, List<Item> &values, Item *conds, DB_TXN *txn) {
int error;
// Save the primary key from the where conditions
Item::Type t = conds->type();
if (t == Item::FUNC_ITEM) {
error = save_in_field(conds, table);
} else if (t == Item::COND_ITEM) {
Item_cond *cond_item = static_cast<Item_cond*>(conds);
List_iterator<Item> li(*cond_item->argument_list());
Item *list_item;
for (error = 0; error == 0 && (list_item = li++); ) {
error = save_in_field(list_item, table);
}
} else
assert(0);
if (error)
return error;
// put the primary key into key_buff and wrap it with key_dbt
DBT key_dbt;
bool has_null;
create_dbt_key_from_table(&key_dbt, primary_key, key_buff, table->record[0], &has_null);
// construct the update message
tokudb::buffer update_message;
uchar operation = UPDATE_OP_SIMPLE_UPDATE;
update_message.append(&operation, sizeof operation);
uint32_t update_mode = 0;
update_message.append(&update_mode, sizeof update_mode);
// append the descriptor
marshall_simple_descriptor(update_message, table, share->kc_info, primary_key);
// append the updates
List_iterator<Item> lhs_i(fields);
List_iterator<Item> rhs_i(values);
while (error == 0) {
Item *lhs_item = lhs_i++;
if (lhs_item == NULL)
break;
Item *rhs_item = rhs_i++;
if (rhs_item == NULL)
assert(0); // can not happen
marshall_simple_update(update_message, lhs_item, rhs_item, table, share);
}
// send the message
DBT update_dbt; memset(&update_dbt, 0, sizeof update_dbt);
update_dbt.data = update_message.data();
update_dbt.size = update_message.size();
error = share->key_file[primary_key]->update(share->key_file[primary_key], txn, &key_dbt, &update_dbt, 0);
return error;
}
// Determine if an upsert operation can be offloaded to the storage engine.
// An upsert consists of a row and a list of update expressions (update_fields[i] = update_values[i]).
// The function returns true is the upsert is handled in the storage engine. Otherwise, false is returned.
bool ha_tokudb::upsert(THD *thd, uchar *record, List<Item> &update_fields, List<Item> &update_values, int *error_ret) {
int error = 0;
if (tokudb_upsert_debug) {
fprintf(stderr, "upsert\n");
dump_item_list("update_fields", update_fields);
dump_item_list("update_values", update_values);
}
if (update_fields.elements < 1 || update_fields.elements != update_values.elements)
return false; // not an upsert or something is fishy with the parameters
if (thd->is_strict_mode() || !transaction || !check_upsert(thd, update_fields, update_values)) {
if (get_disable_slow_upsert(thd))
error = HA_ERR_UNSUPPORTED;
else
return false;
}
if (error == 0)
error = send_upsert_message(thd, record, update_fields, update_values, transaction);
if (error != 0)
print_error(error, MYF(0));
*error_ret = error;
return true;
}
// Check if an upsert can be handled by this storage engine. Return trus if it can.
bool ha_tokudb::check_upsert(THD *thd, List<Item> &update_fields, List<Item> &update_values) {
// no triggers
if (table->triggers)
return false;
// no binlog
if (mysql_bin_log.is_open())
return false;
// primary key must exist
// no auto increment?
if (table->s->primary_key >= table->s->keys)
return false;
// no clustering keys (need to broadcast an increment into the clustering keys since we are selecting with the primary key)
if (clustering_keys_exist(table))
return false;
if (!get_enable_fast_upsert(thd))
return false;
if (!check_all_update_expressions(update_fields, update_values, table))
return false;
return true;
}
// Generate an upsert message and send it into the primary tree. Return 0 if successful.
int ha_tokudb::send_upsert_message(THD *thd, uchar *record, List<Item> &update_fields, List<Item> &update_values, DB_TXN *txn) {
int error = 0;
// generate primary key
DBT key_dbt;
bool has_null;
create_dbt_key_from_table(&key_dbt, primary_key, primary_key_buff, record, &has_null);
// generate packed row
DBT row;
error = pack_row(&row, (const uchar *) record, primary_key);
if (error)
return error;
tokudb::buffer update_message;
// append the operation
uchar operation = UPDATE_OP_SIMPLE_UPSERT;
update_message.append(&operation, sizeof operation);
uint32_t update_mode = 0;
update_message.append(&update_mode, sizeof update_mode);
// append the row
uint32_t row_length = row.size;
update_message.append(&row_length, sizeof row_length);
update_message.append(row.data, row_length);
// append the descriptor
marshall_simple_descriptor(update_message, table, share->kc_info, primary_key);
// append the update expressions
List_iterator<Item> lhs_i(update_fields);
List_iterator<Item> rhs_i(update_values);
while (1) {
Item *lhs_item = lhs_i++;
if (lhs_item == NULL)
break;
Item *rhs_item = rhs_i++;
if (rhs_item == NULL)
assert(0); // can not happen
marshall_simple_update(update_message, lhs_item, rhs_item, table, share);
}
// send the upsert message
DBT update_dbt; memset(&update_dbt, 0, sizeof update_dbt);
update_dbt.data = update_message.data();
update_dbt.size = update_message.size();
error = share->key_file[primary_key]->update(share->key_file[primary_key], txn, &key_dbt, &update_dbt, 0);
return error;
}
#endif
...@@ -4,11 +4,26 @@ ...@@ -4,11 +4,26 @@
// is expanded beyond 1 byte. // is expanded beyond 1 byte.
enum { enum {
UPDATE_OP_COL_ADD_OR_DROP = 0, UPDATE_OP_COL_ADD_OR_DROP = 0,
UPDATE_OP_EXPAND_VARIABLE_OFFSETS = 1, UPDATE_OP_EXPAND_VARIABLE_OFFSETS = 1,
UPDATE_OP_EXPAND_INT = 2, UPDATE_OP_EXPAND_INT = 2,
UPDATE_OP_EXPAND_UINT = 3, UPDATE_OP_EXPAND_UINT = 3,
UPDATE_OP_EXPAND_CHAR = 4, UPDATE_OP_EXPAND_CHAR = 4,
UPDATE_OP_EXPAND_BINARY = 5, UPDATE_OP_EXPAND_BINARY = 5,
UPDATE_OP_SIMPLE_UPDATE = 10,
UPDATE_OP_SIMPLE_UPSERT = 11,
};
// Field types used in the update messages
enum {
UPDATE_TYPE_UNKNOWN = 0,
UPDATE_TYPE_INT = 1,
UPDATE_TYPE_UINT = 2,
UPDATE_TYPE_CHAR = 3,
UPDATE_TYPE_BINARY = 4,
UPDATE_TYPE_VARCHAR = 5,
UPDATE_TYPE_VARBINARY = 6,
}; };
#define UP_COL_ADD_OR_DROP UPDATE_OP_COL_ADD_OR_DROP #define UP_COL_ADD_OR_DROP UPDATE_OP_COL_ADD_OR_DROP
...@@ -67,28 +82,62 @@ enum { ...@@ -67,28 +82,62 @@ enum {
// These expand messages are used to expand the size of a fixed length field. // These expand messages are used to expand the size of a fixed length field.
// The field type is encoded in the operation code. // The field type is encoded in the operation code.
// operation 1 == UPDATE_OP_EXPAND_INT, UPDATE_OP_EXPAND_UINT, UPDATE_OP_EXPAND_CHAR, UPDATE_OP_EXPAND_BINARY // operation 1 == UPDATE_OP_EXPAND_INT/UINT/CHAR/BINARY
// offset 4 starting offset of the field in the row's value // offset 4 offset of the field
// old length 4 the old length of the field's value // old length 4 the old length of the field's value
// new length 4 the new length of the field's value // new length 4 the new length of the field's value
// operation 1 == UPDATE_OP_EXPAND_CHAR, UPDATE_OP_EXPAND_BINARY // operation 1 == UPDATE_OP_EXPAND_CHAR/BINARY
// offset 4 starting offset of the field in the row's value // offset 4 offset of the field
// old length 4 the old length of the field's value // old length 4 the old length of the field's value
// new length 4 the new length of the field's value // new length 4 the new length of the field's value
// pad char 1 // pad char 1
// The int add and sub update messages are used to add or subtract a constant to or from an integer field. // Simple row descriptor:
// operation 1 == UPDATE_OP_INT_ADD, UPDATE_OP_INT_SUB, UPDATE_OP_UINT_ADD, UPDATE_OP_UINT_SUB // fixed field offset 4
// offset 4 starting offset of the int type field // var field offset 4
// length 4 length of the int type field // var_offset_bytes 1
// value 4 value to add or subtract (common use case is increment or decrement by 1) // num_var_fields 4
// Field descriptor:
// field type 4
// field num 4
// field null num 4
// field offset 4
// field length 4
// Simple update operation:
// update operation 4 == { '=', '+', '-' }
// x = k
// x = x + k
// x = x - k
// field descriptor
// optional value:
// value length 4 == N, length of the value
// value N value to add or subtract
// Simple update message:
// Operation 1 == UPDATE_OP_UPDATE_FIELD
// Update mode 4
// Simple row descriptor
// Simple update ops []
// Simple upsert message:
// Operation 1 == UPDATE_OP_UPSERT
// Update mode 4
// Insert row:
// length 4 == N
// data N
// Simple row descriptor
// Simple update ops []
#include "tokudb_buffer.h"
#include "tokudb_math.h"
// //
// checks whether the bit at index pos in data is set or not // checks whether the bit at index pos in data is set or not
// //
static inline bool static inline bool is_overall_null_position_set(uchar* data, uint32_t pos) {
is_overall_null_position_set(uchar* data, uint32_t pos) {
uint32_t offset = pos/8; uint32_t offset = pos/8;
uchar remainder = pos%8; uchar remainder = pos%8;
uchar null_bit = 1<<remainder; uchar null_bit = 1<<remainder;
...@@ -98,8 +147,7 @@ is_overall_null_position_set(uchar* data, uint32_t pos) { ...@@ -98,8 +147,7 @@ is_overall_null_position_set(uchar* data, uint32_t pos) {
// //
// sets the bit at index pos in data to 1 if is_null, 0 otherwise // sets the bit at index pos in data to 1 if is_null, 0 otherwise
// //
static inline void static inline void set_overall_null_position(uchar* data, uint32_t pos, bool is_null) {
set_overall_null_position(uchar* data, uint32_t pos, bool is_null) {
uint32_t offset = pos/8; uint32_t offset = pos/8;
uchar remainder = pos%8; uchar remainder = pos%8;
uchar null_bit = 1<<remainder; uchar null_bit = 1<<remainder;
...@@ -111,8 +159,7 @@ set_overall_null_position(uchar* data, uint32_t pos, bool is_null) { ...@@ -111,8 +159,7 @@ set_overall_null_position(uchar* data, uint32_t pos, bool is_null) {
} }
} }
static inline void static inline void copy_null_bits(
copy_null_bits(
uint32_t start_old_pos, uint32_t start_old_pos,
uint32_t start_new_pos, uint32_t start_new_pos,
uint32_t num_bits, uint32_t num_bits,
...@@ -133,8 +180,7 @@ copy_null_bits( ...@@ -133,8 +180,7 @@ copy_null_bits(
} }
} }
static inline void static inline void copy_var_fields(
copy_var_fields(
uint32_t start_old_num_var_field, //index of var fields that we should start writing uint32_t start_old_num_var_field, //index of var fields that we should start writing
uint32_t num_var_fields, // number of var fields to copy uint32_t num_var_fields, // number of var fields to copy
uchar* old_var_field_offset_ptr, //static ptr to where offset bytes begin in old row uchar* old_var_field_offset_ptr, //static ptr to where offset bytes begin in old row
...@@ -179,8 +225,7 @@ copy_var_fields( ...@@ -179,8 +225,7 @@ copy_var_fields(
*num_offset_bytes_written = (uint32_t)(curr_new_var_field_offset_ptr - start_new_var_field_offset_ptr); *num_offset_bytes_written = (uint32_t)(curr_new_var_field_offset_ptr - start_new_var_field_offset_ptr);
} }
static inline uint32_t static inline uint32_t copy_toku_blob(uchar* to_ptr, uchar* from_ptr, uint32_t len_bytes, bool skip) {
copy_toku_blob(uchar* to_ptr, uchar* from_ptr, uint32_t len_bytes, bool skip) {
uint32_t length = 0; uint32_t length = 0;
if (!skip) { if (!skip) {
memcpy(to_ptr, from_ptr, len_bytes); memcpy(to_ptr, from_ptr, len_bytes);
...@@ -192,8 +237,7 @@ copy_toku_blob(uchar* to_ptr, uchar* from_ptr, uint32_t len_bytes, bool skip) { ...@@ -192,8 +237,7 @@ copy_toku_blob(uchar* to_ptr, uchar* from_ptr, uint32_t len_bytes, bool skip) {
return (length + len_bytes); return (length + len_bytes);
} }
static int static int tokudb_hcad_update_fun(
tokudb_hcad_update_fun(
DB* db, DB* db,
const DBT *key, const DBT *key,
const DBT *old_val, const DBT *old_val,
...@@ -624,8 +668,7 @@ cleanup: ...@@ -624,8 +668,7 @@ cleanup:
} }
// Expand the variable offset array in the old row given the update mesage in the extra. // Expand the variable offset array in the old row given the update mesage in the extra.
static int static int tokudb_expand_variable_offsets(
tokudb_expand_variable_offsets(
DB* db, DB* db,
const DBT *key, const DBT *key,
const DBT *old_val, const DBT *old_val,
...@@ -635,24 +678,22 @@ tokudb_expand_variable_offsets( ...@@ -635,24 +678,22 @@ tokudb_expand_variable_offsets(
) )
{ {
int error = 0; int error = 0;
uchar *extra_pos = (uchar *)extra->data; tokudb::buffer extra_val(extra->data, 0, extra->size);
// decode the operation // decode the operation
uchar operation = extra_pos[0]; uchar operation;
extra_val.consume(&operation, sizeof operation);
assert(operation == UPDATE_OP_EXPAND_VARIABLE_OFFSETS); assert(operation == UPDATE_OP_EXPAND_VARIABLE_OFFSETS);
extra_pos += sizeof operation;
// decode number of offsets // decode number of offsets
uint32_t number_of_offsets; uint32_t number_of_offsets;
memcpy(&number_of_offsets, extra_pos, sizeof number_of_offsets); extra_val.consume(&number_of_offsets, sizeof number_of_offsets);
extra_pos += sizeof number_of_offsets;
// decode the offset start // decode the offset start
uint32_t offset_start; uint32_t offset_start;
memcpy(&offset_start, extra_pos, sizeof offset_start); extra_val.consume(&offset_start, sizeof offset_start);
extra_pos += sizeof offset_start;
assert(extra_pos == (uchar *)extra->data + extra->size); assert(extra_val.size() == extra_val.limit());
DBT new_val; memset(&new_val, 0, sizeof new_val); DBT new_val; memset(&new_val, 0, sizeof new_val);
...@@ -706,8 +747,7 @@ cleanup: ...@@ -706,8 +747,7 @@ cleanup:
} }
// Expand an int field in a old row given the expand message in the extra. // Expand an int field in a old row given the expand message in the extra.
static int static int tokudb_expand_int_field(
tokudb_expand_int_field(
DB* db, DB* db,
const DBT *key, const DBT *key,
const DBT *old_val, const DBT *old_val,
...@@ -717,25 +757,19 @@ tokudb_expand_int_field( ...@@ -717,25 +757,19 @@ tokudb_expand_int_field(
) )
{ {
int error = 0; int error = 0;
uchar *extra_pos = (uchar *)extra->data; tokudb::buffer extra_val(extra->data, 0, extra->size);
uchar operation = extra_pos[0]; uchar operation;
extra_val.consume(&operation, sizeof operation);
assert(operation == UPDATE_OP_EXPAND_INT || operation == UPDATE_OP_EXPAND_UINT); assert(operation == UPDATE_OP_EXPAND_INT || operation == UPDATE_OP_EXPAND_UINT);
extra_pos += sizeof operation;
uint32_t the_offset; uint32_t the_offset;
memcpy(&the_offset, extra_pos, sizeof the_offset); extra_val.consume(&the_offset, sizeof the_offset);
extra_pos += sizeof the_offset;
uint32_t old_length; uint32_t old_length;
memcpy(&old_length, extra_pos, sizeof old_length); extra_val.consume(&old_length, sizeof old_length);
extra_pos += sizeof old_length;
uint32_t new_length; uint32_t new_length;
memcpy(&new_length, extra_pos, sizeof new_length); extra_val.consume(&new_length, sizeof new_length);
extra_pos += sizeof new_length; assert(extra_val.size() == extra_val.limit());
assert(extra_pos == (uchar *)extra->data + extra->size); // consumed the entire message
assert(new_length >= old_length); // expand only assert(new_length >= old_length); // expand only
DBT new_val; memset(&new_val, 0, sizeof new_val); DBT new_val; memset(&new_val, 0, sizeof new_val);
...@@ -801,8 +835,7 @@ cleanup: ...@@ -801,8 +835,7 @@ cleanup:
} }
// Expand a char field in a old row given the expand message in the extra. // Expand a char field in a old row given the expand message in the extra.
static int static int tokudb_expand_char_field(
tokudb_expand_char_field(
DB* db, DB* db,
const DBT *key, const DBT *key,
const DBT *old_val, const DBT *old_val,
...@@ -812,29 +845,21 @@ tokudb_expand_char_field( ...@@ -812,29 +845,21 @@ tokudb_expand_char_field(
) )
{ {
int error = 0; int error = 0;
uchar *extra_pos = (uchar *)extra->data; tokudb::buffer extra_val(extra->data, 0, extra->size);
uchar operation = extra_pos[0]; uchar operation;
extra_val.consume(&operation, sizeof operation);
assert(operation == UPDATE_OP_EXPAND_CHAR || operation == UPDATE_OP_EXPAND_BINARY); assert(operation == UPDATE_OP_EXPAND_CHAR || operation == UPDATE_OP_EXPAND_BINARY);
extra_pos += sizeof operation;
uint32_t the_offset; uint32_t the_offset;
memcpy(&the_offset, extra_pos, sizeof the_offset); extra_val.consume(&the_offset, sizeof the_offset);
extra_pos += sizeof the_offset;
uint32_t old_length; uint32_t old_length;
memcpy(&old_length, extra_pos, sizeof old_length); extra_val.consume(&old_length, sizeof old_length);
extra_pos += sizeof old_length;
uint32_t new_length; uint32_t new_length;
memcpy(&new_length, extra_pos, sizeof new_length); extra_val.consume(&new_length, sizeof new_length);
extra_pos += sizeof new_length; uchar pad_char;
extra_val.consume(&pad_char, sizeof pad_char);
uchar pad_char = 0; assert(extra_val.size() == extra_val.limit());
memcpy(&pad_char, extra_pos, sizeof pad_char);
extra_pos += sizeof pad_char;
assert(extra_pos == (uchar *)extra->data + extra->size); // consumed the entire message
assert(new_length >= old_length); // expand only assert(new_length >= old_length); // expand only
DBT new_val; memset(&new_val, 0, sizeof new_val); DBT new_val; memset(&new_val, 0, sizeof new_val);
...@@ -892,8 +917,290 @@ cleanup: ...@@ -892,8 +917,290 @@ cleanup:
return error; return error;
} }
int class Simple_row_descriptor {
tokudb_update_fun( public:
Simple_row_descriptor() : m_fixed_field_offset(0), m_var_field_offset(0), m_var_offset_bytes(0), m_num_var_fields(0) {
}
~Simple_row_descriptor() {
}
void consume(tokudb::buffer &b) {
b.consume(&m_fixed_field_offset, sizeof m_fixed_field_offset);
b.consume(&m_var_field_offset, sizeof m_var_field_offset);
b.consume(&m_var_offset_bytes, sizeof m_var_offset_bytes);
b.consume(&m_num_var_fields, sizeof m_num_var_fields);
}
void append(tokudb::buffer &b) {
b.append(&m_fixed_field_offset, sizeof m_fixed_field_offset);
b.append(&m_var_field_offset, sizeof m_var_field_offset);
b.append(&m_var_offset_bytes, sizeof m_var_offset_bytes);
b.append(&m_num_var_fields, sizeof m_num_var_fields);
}
public:
uint32_t m_fixed_field_offset;
uint32_t m_var_field_offset;
uint8_t m_var_offset_bytes;
uint32_t m_num_var_fields;
};
// Update a fixed field: new_val@offset = extra_val
static void set_fixed_field(uint32_t the_offset, uint32_t length, uint32_t field_num, uint32_t field_null_num,
tokudb::buffer &new_val, void *extra_val) {
assert(the_offset + length <= new_val.size());
new_val.replace(the_offset, length, extra_val, length);
if (field_null_num)
set_overall_null_position((uchar *) new_val.data(), field_null_num & ~(1<<31), false);
}
// Update an int field: signed newval@offset = old_val@offset OP extra_val
static void int_op(uint32_t operation, uint32_t update_mode, uint32_t the_offset, uint32_t length, uint32_t field_num, uint32_t field_null_num,
tokudb::buffer &new_val, tokudb::buffer &old_val, void *extra_val) {
assert(the_offset + length <= new_val.size());
assert(the_offset + length <= old_val.size());
assert(length == 1 || length == 2 || length == 3 || length == 4 || length == 8);
assert(update_mode == 0);
uchar *old_val_ptr = (uchar *) old_val.data();
bool field_is_null = false;
if (field_null_num)
field_is_null = is_overall_null_position_set(old_val_ptr, field_null_num & ~(1<<31));
int64_t v = 0;
memcpy(&v, old_val_ptr + the_offset, length);
v = tokudb::int_sign_extend(v, 8*length);
int64_t extra_v = 0;
memcpy(&extra_v, extra_val, length);
extra_v = tokudb::int_sign_extend(extra_v, 8*length);
switch (operation) {
case '+':
if (!field_is_null) {
bool over;
v = tokudb::int_add(v, extra_v, 8*length, over);
if (over) {
if (extra_v > 0)
v = tokudb::int_high_endpoint(8*length);
else
v = tokudb::int_low_endpoint(8*length);
over = false;
}
if (!over)
new_val.replace(the_offset, length, &v, length);
}
break;
case '-':
if (!field_is_null) {
bool over;
v = tokudb::int_sub(v, extra_v, 8*length, over);
if (over) {
if (extra_v > 0)
v = tokudb::int_low_endpoint(8*length);
else
v = tokudb::int_high_endpoint(8*length);
over = false;
}
if (!over)
new_val.replace(the_offset, length, &v, length);
}
break;
default:
assert(0);
}
}
// Update an unsigned field: unsigned newval@offset = old_val@offset OP extra_val
static void uint_op(uint32_t operation, uint32_t update_mode, uint32_t the_offset, uint32_t length, uint32_t field_num, uint32_t field_null_num,
tokudb::buffer &new_val, tokudb::buffer &old_val, void *extra_val) {
assert(the_offset + length <= new_val.size());
assert(the_offset + length <= old_val.size());
assert(length == 1 || length == 2 || length == 3 || length == 4 || length == 8);
assert(update_mode == 0);
uchar *old_val_ptr = (uchar *) old_val.data();
bool field_is_null = false;
if (field_null_num)
field_is_null = is_overall_null_position_set(old_val_ptr, field_null_num & ~(1<<31));
uint64_t v = 0;
memcpy(&v, old_val_ptr + the_offset, length);
uint64_t extra_v = 0;
memcpy(&extra_v, extra_val, length);
switch (operation) {
case '+':
if (!field_is_null) {
bool over;
v = tokudb::uint_add(v, extra_v, 8*length, over);
if (over) {
v = tokudb::uint_high_endpoint(8*length);
over = false;
}
if (!over)
new_val.replace(the_offset, length, &v, length);
}
break;
case '-':
if (!field_is_null) {
bool over;
v = tokudb::uint_sub(v, extra_v, 8*length, over);
if (over) {
v = tokudb::uint_low_endpoint(8*length);
over = false;
}
if (!over)
new_val.replace(the_offset, length, &v, length);
}
break;
default:
assert(0);
}
}
// Decode and apply a sequence of update operations defined in the extra to the old value and put the result
// in the new value.
static void apply_updates(tokudb::buffer &new_val, tokudb::buffer &old_val, tokudb::buffer &extra_val,
uint32_t update_mode, Simple_row_descriptor &sd) {
while (extra_val.size() < extra_val.limit()) {
// get the update operation
uint32_t update_operation;
extra_val.consume(&update_operation, sizeof update_operation);
uint32_t field_type;
extra_val.consume(&field_type, sizeof field_type);
uint32_t field_num;
extra_val.consume(&field_num, sizeof field_num);
uint32_t field_null_num;
extra_val.consume(&field_null_num, sizeof field_null_num);
uint32_t the_offset;
extra_val.consume(&the_offset, sizeof the_offset);
uint32_t length;
extra_val.consume(&length, sizeof length);
void *extra_val_ptr = extra_val.consume_ptr(length);
// apply the update
switch (field_type) {
case UPDATE_TYPE_INT:
if (update_operation == '=')
set_fixed_field(the_offset, length, field_num, field_null_num, new_val, extra_val_ptr);
else
int_op(update_operation, update_mode, the_offset, length, field_num, field_null_num, new_val, old_val, extra_val_ptr);
break;
case UPDATE_TYPE_UINT:
if (update_operation == '=')
set_fixed_field(the_offset, length, field_num, field_null_num, new_val, extra_val_ptr);
else
uint_op(update_operation, update_mode, the_offset, length, field_num, field_null_num, new_val, old_val, extra_val_ptr);
break;
case UPDATE_TYPE_CHAR:
case UPDATE_TYPE_BINARY:
if (update_operation == '=')
set_fixed_field(the_offset, length, field_num, field_null_num, new_val, extra_val_ptr);
else
assert(0);
break;
default:
assert(0);
break;
}
}
}
// Simple update handler. Decode the update message, apply the update operations to the old value, and set
// the new value.
static int tokudb_simple_update_fun(
DB* db,
const DBT *key_dbt,
const DBT *old_val_dbt,
const DBT *extra,
void (*set_val)(const DBT *new_val_dbt, void *set_extra),
void *set_extra
)
{
tokudb::buffer extra_val(extra->data, 0, extra->size);
uchar operation;
extra_val.consume(&operation, sizeof operation);
assert(operation == UPDATE_OP_SIMPLE_UPDATE);
uint32_t update_mode;
extra_val.consume(&update_mode, sizeof update_mode);
if (old_val_dbt != NULL) {
// get the simple descriptor
Simple_row_descriptor sd;
sd.consume(extra_val);
tokudb::buffer old_val(old_val_dbt->data, old_val_dbt->size, old_val_dbt->size);
// new val = old val
tokudb::buffer new_val;
new_val.append(old_val_dbt->data, old_val_dbt->size);
// apply updates to new val
apply_updates(new_val, old_val, extra_val, update_mode, sd);
// set the new val
DBT new_val_dbt; memset(&new_val_dbt, 0, sizeof new_val_dbt);
new_val_dbt.data = new_val.data();
new_val_dbt.size = new_val.size();
set_val(&new_val_dbt, set_extra);
}
return 0;
}
// Simple upsert handler. Decode the upsert message. If the key does not exist, then insert a new value from the extra.
// Otherwise, apply the update operations to the old value, and then set the new value.
static int tokudb_simple_upsert_fun(
DB* db,
const DBT *key_dbt,
const DBT *old_val_dbt,
const DBT *extra,
void (*set_val)(const DBT *new_val_dbt, void *set_extra),
void *set_extra
)
{
tokudb::buffer extra_val(extra->data, 0, extra->size);
uchar operation;
extra_val.consume(&operation, sizeof operation);
assert(operation == UPDATE_OP_SIMPLE_UPSERT);
uint32_t update_mode;
extra_val.consume(&update_mode, sizeof update_mode);
uint32_t insert_length;
extra_val.consume(&insert_length, sizeof insert_length);
void *insert_row = extra_val.consume_ptr(insert_length);
if (old_val_dbt == NULL) {
// insert a new row
DBT new_val_dbt; memset(&new_val_dbt, 0, sizeof new_val_dbt);
new_val_dbt.size = insert_length;
new_val_dbt.data = insert_row;
set_val(&new_val_dbt, set_extra);
} else {
// decode the simple descriptor
Simple_row_descriptor sd;
sd.consume(extra_val);
tokudb::buffer old_val(old_val_dbt->data, old_val_dbt->size, old_val_dbt->size);
// new val = old val
tokudb::buffer new_val;
new_val.append(old_val_dbt->data, old_val_dbt->size);
// apply updates to new val
apply_updates(new_val, old_val, extra_val, update_mode, sd);
// set the new val
DBT new_val_dbt; memset(&new_val_dbt, 0, sizeof new_val_dbt);
new_val_dbt.data = new_val.data();
new_val_dbt.size = new_val.size();
set_val(&new_val_dbt, set_extra);
}
return 0;
}
// This function is the update callback function that is registered with the YDB environment.
// It uses the first byte in the update message to identify the update message type and call
// the handler for that message.
int tokudb_update_fun(
DB* db, DB* db,
const DBT *key, const DBT *key,
const DBT *old_val, const DBT *old_val,
...@@ -904,7 +1211,7 @@ tokudb_update_fun( ...@@ -904,7 +1211,7 @@ tokudb_update_fun(
{ {
uchar *extra_pos = (uchar *)extra->data; uchar *extra_pos = (uchar *)extra->data;
uchar operation = extra_pos[0]; uchar operation = extra_pos[0];
int error = 0; int error;
switch (operation) { switch (operation) {
case UPDATE_OP_COL_ADD_OR_DROP: case UPDATE_OP_COL_ADD_OR_DROP:
error = tokudb_hcad_update_fun(db, key, old_val, extra, set_val, set_extra); error = tokudb_hcad_update_fun(db, key, old_val, extra, set_val, set_extra);
...@@ -920,6 +1227,12 @@ tokudb_update_fun( ...@@ -920,6 +1227,12 @@ tokudb_update_fun(
case UPDATE_OP_EXPAND_BINARY: case UPDATE_OP_EXPAND_BINARY:
error = tokudb_expand_char_field(db, key, old_val, extra, set_val, set_extra); error = tokudb_expand_char_field(db, key, old_val, extra, set_val, set_extra);
break; break;
case UPDATE_OP_SIMPLE_UPDATE:
error = tokudb_simple_update_fun(db, key, old_val, extra, set_val, set_extra);
break;
case UPDATE_OP_SIMPLE_UPSERT:
error = tokudb_simple_upsert_fun(db, key, old_val, extra, set_val, set_extra);
break;
default: default:
error = EINVAL; error = EINVAL;
break; break;
......
...@@ -43,6 +43,7 @@ ...@@ -43,6 +43,7 @@
#define TOKU_INCLUDE_XA 1 #define TOKU_INCLUDE_XA 1
#define TOKU_PARTITION_WRITE_FRM_DATA 1 #define TOKU_PARTITION_WRITE_FRM_DATA 1
#define TOKU_INCLUDE_WRITE_FRM_DATA 1 #define TOKU_INCLUDE_WRITE_FRM_DATA 1
#define TOKU_INCLUDE_UPSERT 1
#elif 50500 <= MYSQL_VERSION_ID && MYSQL_VERSION_ID <= 50599 #elif 50500 <= MYSQL_VERSION_ID && MYSQL_VERSION_ID <= 50599
#define TOKU_INCLUDE_ALTER_56 1 #define TOKU_INCLUDE_ALTER_56 1
......
...@@ -139,6 +139,36 @@ static MYSQL_THDVAR_UINT(read_buf_size, ...@@ -139,6 +139,36 @@ static MYSQL_THDVAR_UINT(read_buf_size,
1*1024*1024, // max 1*1024*1024, // max
1 // blocksize??? 1 // blocksize???
); );
#if TOKU_INCLUDE_UPSERT
static MYSQL_THDVAR_BOOL(enable_fast_update,
PLUGIN_VAR_THDLOCAL,
"enable fast update",
NULL, // check
NULL, // update
false // default
);
static MYSQL_THDVAR_BOOL(disable_slow_update,
PLUGIN_VAR_THDLOCAL,
"disable slow update",
NULL, // check
NULL, // update
false // default
);
static MYSQL_THDVAR_BOOL(enable_fast_upsert,
PLUGIN_VAR_THDLOCAL,
"enable fast upsert",
NULL, // check
NULL, // update
false // default
);
static MYSQL_THDVAR_BOOL(disable_slow_upsert,
PLUGIN_VAR_THDLOCAL,
"disable slow upsert",
NULL, // check
NULL, // update
false // default
);
#endif
static void tokudb_checkpoint_lock(THD * thd); static void tokudb_checkpoint_lock(THD * thd);
static void tokudb_checkpoint_unlock(THD * thd); static void tokudb_checkpoint_unlock(THD * thd);
...@@ -707,6 +737,24 @@ uint get_tokudb_read_buf_size(THD* thd) { ...@@ -707,6 +737,24 @@ uint get_tokudb_read_buf_size(THD* thd) {
return THDVAR(thd, read_buf_size); return THDVAR(thd, read_buf_size);
} }
#if TOKU_INCLUDE_UPSERT
bool get_enable_fast_update(THD* thd) {
return (THDVAR(thd, enable_fast_update) != 0);
}
bool get_disable_slow_update(THD* thd) {
return (THDVAR(thd, disable_slow_update) != 0);
}
bool get_enable_fast_upsert(THD* thd) {
return (THDVAR(thd, enable_fast_upsert) != 0);
}
bool get_disable_slow_upsert(THD* thd) {
return (THDVAR(thd, disable_slow_upsert) != 0);
}
#endif
typedef struct txn_progress_info { typedef struct txn_progress_info {
char status[200]; char status[200];
THD* thd; THD* thd;
...@@ -1628,6 +1676,12 @@ static struct st_mysql_sys_var *tokudb_system_variables[] = { ...@@ -1628,6 +1676,12 @@ static struct st_mysql_sys_var *tokudb_system_variables[] = {
MYSQL_SYSVAR(read_block_size), MYSQL_SYSVAR(read_block_size),
MYSQL_SYSVAR(read_buf_size), MYSQL_SYSVAR(read_buf_size),
MYSQL_SYSVAR(row_format), MYSQL_SYSVAR(row_format),
#if TOKU_INCLUDE_UPSERT
MYSQL_SYSVAR(enable_fast_update),
MYSQL_SYSVAR(disable_slow_update),
MYSQL_SYSVAR(enable_fast_upsert),
MYSQL_SYSVAR(disable_slow_upsert),
#endif
NULL NULL
}; };
......
...@@ -33,6 +33,12 @@ uint get_tokudb_block_size(THD* thd); ...@@ -33,6 +33,12 @@ uint get_tokudb_block_size(THD* thd);
uint get_tokudb_read_block_size(THD* thd); uint get_tokudb_read_block_size(THD* thd);
uint get_tokudb_read_buf_size(THD* thd); uint get_tokudb_read_buf_size(THD* thd);
srv_row_format_t get_row_format(THD *thd); srv_row_format_t get_row_format(THD *thd);
#if TOKU_INCLUDE_UPSERT
bool get_enable_fast_update(THD *thd);
bool get_disable_slow_update(THD *thd);
bool get_enable_fast_upsert(THD *thd);
bool get_disable_slow_upsert(THD *thd);
#endif
extern HASH tokudb_open_tables; extern HASH tokudb_open_tables;
extern pthread_mutex_t tokudb_mutex; extern pthread_mutex_t tokudb_mutex;
......
MYSQL_STORAGE_ENGINE(tokudb,,[TokuDB Storage Engine with Fractal Trees], [TokuDB Engine with Fractal Trees], [max,max-no-ndb])
MYSQL_PLUGIN_DIRECTORY(tokudb, [storage/tokudb])
MYSQL_PLUGIN_DYNAMIC(tokudb, [ha_tokudb.la])
SRCS = $(wildcard *.cc)
TARGETS = $(patsubst %.cc,%,$(SRCS))
CHECKS = $(patsubst %,%.check,$(TARGETS))
CPPFLAGS = -I..
CXXFLAGS = -g
ifeq ($(GCOV),1)
CXXFLAGS += -fprofile-arcs -ftest-coverage
endif
all: $(TARGETS)
clean:
rm -rf $(TARGETS) *.gcov *.gcno *.gcda
check: $(CHECKS)
true
%.check: %
valgrind ./$<
#include <stdio.h>
#include <stdint.h>
#include <stdlib.h>
#include <assert.h>
#include <tokudb_math.h>
using namespace tokudb;
static void test(int length_bits) {
int64_t max = (1ULL << (length_bits-1)) - 1;
for (int64_t x = -max-1; x <= max; x++) {
for (int64_t y = -max-1; y <= max; y++) {
bool over;
int64_t n = int_add(x, y, length_bits, over);
printf("%lld %lld %lld %u\n", x, y, n, over);
}
}
}
int main(int argc, char *argv[]) {
if (argc > 1) {
for (int i = 1; i < argc; i++) {
test(atoi(argv[i]));
}
}
return 0;
}
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <assert.h>
#include <tokudb_buffer.h>
static void test_null() {
tokudb::buffer b;
assert(b.data() == NULL && b.size() == 0 && b.limit() == 0);
b.append(NULL, 0);
assert(b.data() == NULL && b.size() == 0 && b.limit() == 0);
}
static void append_az(tokudb::buffer &b) {
for (char c = 'a'; c <= 'z'; c++) {
b.append(&c, sizeof c);
}
}
static void assert_az(tokudb::buffer &b) {
char *bp = NULL;
for (int i = 0; i < b.size(); i++) {
bp = (char *) b.data() + i;
assert(*bp == 'a'+i);
}
assert(*bp == 'z');
}
static void assert_AZ(tokudb::buffer &b) {
char *bp = NULL;
for (int i = 0; i < b.size(); i++) {
bp = (char *) b.data() + i;
assert(*bp == 'A'+i);
}
assert(*bp == 'Z');
}
static void test_append() {
tokudb::buffer a;
a.append(NULL, 0);
append_az(a);
a.append(NULL, 0);
assert(a.size() == 'z'-'a'+1);
assert(a.size() <= a.limit());
assert_az(a);
tokudb::buffer b(a.data(), 0, a.size());
for (int i = 0; i < b.limit(); i++) {
assert(i <= a.size());
char *ap = (char *) a.data() + i;
assert(i <= b.limit());
char *bp = (char *) b.data() + i;
assert(*ap == *bp);
}
}
static void test_consume() {
tokudb::buffer a;
append_az(a);
tokudb::buffer b(a.data(), 0, a.size());
for (int i = 0; i < b.limit(); i++) {
char c;
b.consume(&c, 1);
assert(c == 'a'+i);
}
assert(b.size() == b.limit());
}
static void test_consume_ptr() {
tokudb::buffer a;
append_az(a);
tokudb::buffer b(a.data(), 0, a.size());
for (int i = 0; i < b.limit(); i++) {
void *p = b.consume_ptr(1);
char c = *(char *)p;
assert(c == 'a'+i);
}
assert(b.size() == b.limit());
assert(b.consume_ptr(1) == NULL);
}
static void test_replace() {
tokudb::buffer a;
append_az(a);
assert_az(a);
for (int i = 0; i < a.size(); i++) {
char newc[1] = { 'A' + i };
a.replace(i, 1, newc, 1);
}
assert_AZ(a);
}
static void test_replace_grow() {
tokudb::buffer a;
append_az(a);
assert_az(a);
// grow field
int s = a.size();
for (int i = 0; i < s; i++) {
char newc[2] = { 'a'+i, 'a'+i };
size_t s = a.size();
a.replace(2*i, 1, newc, 2);
assert(a.size() == s+1);
}
for (int i = 0; i < a.size()/2; i++) {
char *cp = (char *) a.data() + 2*i;
assert(cp[0] == 'a'+i && cp[1] == 'a'+i);
}
}
static void test_replace_shrink() {
tokudb::buffer a;
for (char c = 'a'; c <= 'z'; c++) {
a.append(&c, sizeof c);
a.append(&c, sizeof c);
}
// shrink field
for (int i = 0; i < a.size(); i++) {
char newc[1] = { 'a'+i };
size_t s = a.size();
a.replace(i, 2, newc, 1);
assert(a.size() == s-1);
}
assert_az(a);
}
static void test_replace_null() {
tokudb::buffer a;
append_az(a);
assert_az(a);
// insert between all
int n = a.size();
for (int i = 0; i < n; i++) {
char newc[1] = { 'a'+i };
a.replace(2*i, 0, newc, 1);
}
a.replace(a.size(), 0, (void *)"!", 1);
a.append((void *)"?", 1);
}
int main() {
test_null();
test_append();
test_consume();
test_consume_ptr();
test_replace();
test_replace_grow();
test_replace_shrink();
test_replace_null();
return 0;
}
#include <stdio.h>
#include <stdint.h>
#include <stdlib.h>
#include <assert.h>
#include <tokudb_math.h>
using namespace tokudb;
static void test_uint_range(uint length_bits) {
assert(uint_low_endpoint(length_bits) == 0);
if (length_bits == 64)
assert(uint_high_endpoint(length_bits) == ~0ULL);
else
assert(uint_high_endpoint(length_bits) == (1ULL<<length_bits)-1);
}
static void test_uint8() {
printf("%s\n", __FUNCTION__);
test_uint_range(8);
bool over;
uint8_t n;
uint64_t m;
for (uint64_t x = 0; x <= (1ULL<<8)-1; x++) {
for (uint64_t y = 0; y <= (1ULL<<8)-1; y++) {
n = uint_add(x, y, 8, over);
m = x + y;
if (m > (1ULL<<8)-1)
assert(over);
else
assert(!over && n == (m % 256));
n = uint_sub(x, y, 8, over);
m = x - y;
if (m > x)
assert(over);
else
assert(!over && n == (m % 256));
}
}
}
static void test_uint16() {
printf("%s\n", __FUNCTION__);
test_uint_range(16);
bool over;
uint16_t n;
uint64_t m;
for (uint64_t x = 0; x <= (1ULL<<16)-1; x++) {
for (uint64_t y = 0; y <= (1ULL<<16)-1; y++) {
n = uint_add(x, y, 16, over);
m = x + y;
if (m > (1ULL<<16)-1)
assert(over);
else
assert(!over && n == (m % (1ULL<<16)));
n = uint_sub(x, y, 16, over);
m = x - y;
if (m > x)
assert(over);
else
assert(!over && n == (m % (1ULL<<16)));
}
}
}
static void test_uint24() {
printf("%s\n", __FUNCTION__);
test_uint_range(24);
bool over;
uint64_t s;
s = uint_add((1ULL<<24)-1, (1ULL<<24)-1, 24, over); assert(over);
s = uint_add((1ULL<<24)-1, 1, 24, over); assert(over);
s = uint_add((1ULL<<24)-1, 0, 24, over); assert(!over && s == (1ULL<<24)-1);
s = uint_add(0, 1, 24, over); assert(!over && s == 1);
s = uint_add(0, 0, 24, over); assert(!over && s == 0);
s = uint_sub(0, 0, 24, over); assert(!over && s == 0);
s = uint_sub(0, 1, 24, over); assert(over);
s = uint_sub(0, (1ULL<<24)-1, 24, over); assert(over);
s = uint_sub((1ULL<<24)-1, (1ULL<<24)-1, 24, over); assert(!over && s == 0);
}
static void test_uint32() {
printf("%s\n", __FUNCTION__);
test_uint_range(32);
bool over;
uint64_t s;
s = uint_add((1ULL<<32)-1, (1ULL<<32)-1, 32, over); assert(over);
s = uint_add((1ULL<<32)-1, 1, 32, over); assert(over);
s = uint_add((1ULL<<32)-1, 0, 32, over); assert(!over && s == (1ULL<<32)-1);
s = uint_add(0, 1, 32, over); assert(!over && s == 1);
s = uint_add(0, 0, 32, over); assert(!over && s == 0);
s = uint_sub(0, 0, 32, over); assert(!over && s == 0);
s = uint_sub(0, 1, 32, over); assert(over);
s = uint_sub(0, (1ULL<<32)-1, 32, over); assert(over);
s = uint_sub((1ULL<<32)-1, (1ULL<<32)-1, 32, over); assert(!over && s == 0);
}
static void test_uint64() {
printf("%s\n", __FUNCTION__);
test_uint_range(64);
bool over;
uint64_t s;
s = uint_add(~0ULL, ~0ULL, 64, over); assert(over);
s = uint_add(~0ULL, 1, 64, over); assert(over);
s = uint_add(~0ULL, 0, 64, over); assert(!over && s == ~0ULL);
s = uint_add(0, 1, 64, over); assert(!over && s == 1);
s = uint_add(0, 0, 64, over); assert(!over && s == 0);
s = uint_sub(0, 0, 64, over); assert(!over && s == 0);
s = uint_sub(0, 1, 64, over); assert(over);
s = uint_sub(0, ~0ULL, 64, over); assert(over);
s = uint_sub(~0ULL, ~0ULL, 64, over); assert(!over && s == 0);
}
static int64_t sign_extend(uint length_bits, int64_t n) {
return n | ~((1ULL<<(length_bits-1))-1);
}
static void test_int_range(uint length_bits) {
assert(int_high_endpoint(length_bits) == (1ULL<<(length_bits-1))-1);
assert(int_low_endpoint(length_bits) == sign_extend(length_bits, 1ULL<<(length_bits-1)));
}
static void test_int8() {
printf("%s\n", __FUNCTION__);
test_int_range(8);
int64_t max = (1LL << 7);
for (int64_t x = -max; x <= max-1; x++) {
for (int64_t y = -max; y <= max-1; y++) {
bool over;
int64_t n, m;
n = int_add(x, y, 8, over);
m = x + y;
if (m > max-1)
assert(over);
else if (m < -max)
assert(over);
else
assert(!over && n == m);
n = int_sub(x, y, 8, over);
m = x - y;
if (m > max-1)
assert(over);
else if (m < -max)
assert(over);
else
assert(!over && n == m);
}
}
}
static void test_int16() {
printf("%s\n", __FUNCTION__);
test_int_range(16);
int64_t max = (1LL << 15);
for (int64_t x = -max; x <= max-1; x++) {
for (int64_t y = -max; y <= max-1; y++) {
bool over;
int64_t n, m;
n = int_add(x, y, 16, over);
m = x + y;
if (m > max-1)
assert(over);
else if (m < -max)
assert(over);
else
assert(!over && n == m);
n = int_sub(x, y, 16, over);
m = x - y;
if (m > max-1)
assert(over);
else if (m < -max)
assert(over);
else
assert(!over && n == m);
}
}
}
static void test_int24() {
printf("%s\n", __FUNCTION__);
test_int_range(24);
int64_t s;
bool over;
s = int_add(1, (1ULL<<23)-1, 24, over); assert(over);
s = int_add((1ULL<<23)-1, 1, 24, over); assert(over);
s = int_sub(-1, (1ULL<<23), 24, over); assert(!over && s == (1ULL<<23)-1);
s = int_sub((1ULL<<23), 1, 24, over); assert(over);
s = int_add(0, 0, 24, over); assert(!over && s == 0);
s = int_sub(0, 0, 24, over); assert(!over && s == 0);
s = int_add(0, -1, 24, over); assert(!over && s == -1);
s = int_sub(0, 1, 24, over); assert(!over && s == -1);
s = int_add(0, (1ULL<<23), 24, over); assert(!over && (s & (1ULL<<24)-1) == (1ULL<<23));
s = int_sub(0, (1ULL<<23)-1, 24, over); assert(!over && (s & (1ULL<<24)-1) == (1ULL<<23)+1);
s = int_add(-1, 0, 24, over); assert(!over && s == -1);
s = int_add(-1, 1, 24, over); assert(!over && s == 0);
s = int_sub(-1, -1, 24, over); assert(!over && s == 0);
s = int_sub(-1, (1ULL<<23)-1, 24, over); assert(!over && (s & (1ULL<<24)-1) == (1ULL<<23));
}
static void test_int32() {
printf("%s\n", __FUNCTION__);
test_int_range(32);
int64_t s;
bool over;
s = int_add(1, (1ULL<<31)-1, 32, over); assert(over);
s = int_add((1ULL<<31)-1, 1, 32, over); assert(over);
s = int_sub(-1, (1ULL<<31), 32, over); assert(s == (1ULL<<31)-1 && !over);
s = int_sub((1ULL<<31), 1, 32, over); assert(over);
s = int_add(0, 0, 32, over); assert(s == 0 && !over);
s = int_sub(0, 0, 32, over); assert(s == 0 && !over);
s = int_add(0, -1, 32, over); assert(s == -1 && !over);
s = int_sub(0, 1, 32, over); assert(s == -1 && !over);
s = int_add(0, (1ULL<<31), 32, over); assert((s & (1ULL<<32)-1) == (1ULL<<31) && !over);
s = int_sub(0, (1ULL<<31)-1, 32, over); assert((s & (1ULL<<32)-1) == (1ULL<<31)+1 && !over);
s = int_add(-1, 0, 32, over); assert(s == -1 && !over);
s = int_add(-1, 1, 32, over); assert(s == 0 && !over);
s = int_sub(-1, -1, 32, over); assert(s == 0 && !over);
s = int_sub(-1, (1ULL<<31)-1, 32, over); assert((s & (1ULL<<32)-1) == (1ULL<<31) && !over);
}
static void test_int64() {
printf("%s\n", __FUNCTION__);
test_int_range(64);
int64_t s;
bool over;
s = int_add(1, (1ULL<<63)-1, 64, over); assert(over);
s = int_add((1ULL<<63)-1, 1, 64, over); assert(over);
s = int_sub(-1, (1ULL<<63), 64, over); assert(s == (1ULL<<63)-1 && !over);
s = int_sub((1ULL<<63), 1, 64, over); assert(over);
s = int_add(0, 0, 64, over); assert(s == 0 && !over);
s = int_sub(0, 0, 64, over); assert(s == 0 && !over);
s = int_add(0, -1, 64, over); assert(s == -1 && !over);
s = int_sub(0, 1, 64, over); assert(s == -1 && !over);
s = int_add(0, (1ULL<<63), 64, over); assert(s == (1ULL<<63) && !over);
s = int_sub(0, (1ULL<<63)-1, 64, over); assert(s == (1ULL<<63)+1 && !over);
s = int_add(-1, 0, 64, over); assert(s == -1 && !over);
s = int_add(-1, 1, 64, over); assert(s == 0 && !over);
s = int_sub(-1, -1, 64, over); assert(s == 0 && !over);
s = int_sub(-1, (1ULL<<63)-1, 64, over); assert(s == (1ULL<<63) && !over);
}
static void test_int_sign(uint length_bits) {
printf("%s %u\n", __FUNCTION__, length_bits);
int64_t n;
n = int_high_endpoint(length_bits);
assert(int_sign_extend(n, length_bits) == n);
n = (1ULL<<(length_bits-1));
assert(int_sign_extend(n, length_bits) == -n);
}
static void test_int_sign() {
test_int_sign(8);
test_int_sign(16);
test_int_sign(24);
test_int_sign(32);
test_int_sign(64);
}
int main(int argc, char *argv[]) {
if (1) test_int_sign();
if (1) test_int8();
if (1) test_int16();
if (1) test_int24();
if (1) test_int32();
if (1) test_int64();
if (1) test_uint8();
if (1) test_uint16();
if (1) test_uint24();
if (1) test_uint32();
if (1) test_uint64();
return 0;
}
#include <stdio.h>
#include <stdint.h>
#include <stdlib.h>
#include <assert.h>
#include <tokudb_math.h>
using namespace tokudb;
static void test(int length_bits) {
printf("%s %d\n", __FUNCTION__, length_bits);
uint64_t max = (1ULL << length_bits) - 1;
for (uint64_t x = 0; x <= max; x++) {
for (uint64_t y = 0; y <= max; y++) {
bool over;
uint64_t n = uint_add(x, y, max, over);
printf("%llu %llu %llu\n", x, y, n);
}
}
}
int main(int argc, char *argv[]) {
if (argc > 1) {
for (int i = 1; i < argc; i++) {
test(atoi(argv[i]));
}
}
return 0;
}
#if !defined(_TOKUDB_BUFFER_H)
#define _TOKUDB_BUFFER_H
namespace tokudb {
// A Buffer manages a contiguous chunk of memory and supports appending new data to the end of the buffer, and
// consuming chunks from the beginning of the buffer. The buffer will reallocate memory when appending
// new data to a full buffer.
class buffer {
public:
buffer(void *data, size_t s, size_t l) : m_data(data), m_size(s), m_limit(l), m_is_static(true) {
}
buffer() : m_data(NULL), m_size(0), m_limit(0), m_is_static(false) {
}
virtual ~buffer() {
if (!m_is_static)
free(m_data);
}
// Return a pointer to the end of the buffer suitable for appending a fixed number of bytes.
void *append_ptr(size_t s) {
maybe_realloc(s);
void *p = (char *) m_data + m_size;
m_size += s;
return p;
}
// Append bytes to the buffer
void append(void *p, size_t s) {
memcpy(append_ptr(s), p, s);
}
// Return a pointer to the next location in the buffer where bytes are consumed from.
void *consume_ptr(size_t s) {
if (m_size + s > m_limit)
return NULL;
void *p = (char *) m_data + m_size;
m_size += s;
return p;
}
// Consume bytes from the buffer.
void consume(void *p, size_t s) {
memcpy(p, consume_ptr(s), s);
}
// Replace a field in the buffer with new data. If the new data size is different, then readjust the
// size of the buffer and move things around.
void replace(size_t offset, size_t old_s, void *new_p, size_t new_s) {
assert(offset + old_s <= m_size);
if (new_s > old_s)
maybe_realloc(new_s - old_s);
char *data_offset = (char *) m_data + offset;
if (new_s != old_s) {
size_t n = m_size - (offset + old_s);
assert(offset + new_s + n <= m_limit && offset + old_s + n <= m_limit);
memmove(data_offset + new_s, data_offset + old_s, n);
if (new_s > old_s)
m_size += new_s - old_s;
else
m_size -= old_s - new_s;
assert(m_size <= m_limit);
}
memcpy(data_offset, new_p, new_s);
}
// Return a pointer to the data in the buffer
void *data() {
return m_data;
}
// Return the size of the data in the buffer
size_t size() {
return m_size;
}
// Return the size of the underlying memory in the buffer
size_t limit() {
return m_limit;
}
private:
// Maybe reallocate the buffer when it becomes full by doubling its size.
void maybe_realloc(size_t s) {
if (m_size + s > m_limit) {
size_t new_limit = m_limit * 2;
if (new_limit < m_size + s)
new_limit = m_size + s;
assert(!m_is_static);
m_data = realloc(m_data, new_limit);
m_limit = new_limit;
}
}
private:
void *m_data;
size_t m_size;
size_t m_limit;
bool m_is_static;
};
};
#endif
#if !defined(_TOKUDB_MATH_H)
#define _TOKUDB_MATH_H
namespace tokudb {
// Add and subtract ints with overflow detection.
// Overflow detection adapted from "Hackers Delight", Henry S. Warren
// Return a bit mask for bits 0 .. length_bits-1
static uint64_t uint_mask(uint length_bits) __attribute__((unused));
static uint64_t uint_mask(uint length_bits) {
return length_bits == 64 ? ~0ULL : (1ULL<<length_bits)-1;
}
// Return the highest unsigned int with a given number of bits
static uint64_t uint_high_endpoint(uint length_bits) __attribute__((unused));
static uint64_t uint_high_endpoint(uint length_bits) {
return uint_mask(length_bits);
}
// Return the lowest unsigned int with a given number of bits
static uint64_t uint_low_endpoint(uint length_bits) __attribute__((unused));
static uint64_t uint_low_endpoint(uint length_bits) {
return 0;
}
// Add two unsigned integers with max maximum value.
// If there is an overflow then set the sum to the max.
// Return the sum and the overflow.
static uint64_t uint_add(uint64_t x, uint64_t y, uint length_bits, bool &over) __attribute__((unused));
static uint64_t uint_add(uint64_t x, uint64_t y, uint length_bits, bool &over) {
uint64_t mask = uint_mask(length_bits);
assert((x & ~mask) == 0 && (y & ~mask) == 0);
uint64_t s = (x + y) & mask;
over = s < x; // check for overflow
return s;
}
// Subtract two unsigned ints with max maximum value.
// If there is an over then set the difference to 0.
// Return the difference and the overflow.
static uint64_t uint_sub(uint64_t x, uint64_t y, uint length_bits, bool &over) __attribute__((unused));
static uint64_t uint_sub(uint64_t x, uint64_t y, uint length_bits, bool &over) {
uint64_t mask = uint_mask(length_bits);
assert((x & ~mask) == 0 && (y & ~mask) == 0);
uint64_t s = (x - y) & mask;
over = s > x; // check for overflow
return s;
}
// Return the highest int with a given number of bits
static int64_t int_high_endpoint(uint length_bits) __attribute__((unused));
static int64_t int_high_endpoint(uint length_bits) {
return (1ULL<<(length_bits-1))-1;
}
// Return the lowest int with a given number of bits
static int64_t int_low_endpoint(uint length_bits) __attribute__((unused));
static int64_t int_low_endpoint(uint length_bits) {
int64_t mask = uint_mask(length_bits);
return (1ULL<<(length_bits-1)) | ~mask;
}
// Sign extend to 64 bits an int with a given number of bits
static int64_t int_sign_extend(int64_t n, uint length_bits) __attribute__((unused));
static int64_t int_sign_extend(int64_t n, uint length_bits) {
if (n & (1ULL<<(length_bits-1)))
n |= ~uint_mask(length_bits);
return n;
}
// Add two signed ints with max maximum value.
// If there is an overflow then set the sum to the max or the min of the int range,
// depending on the sign bit.
// Sign extend to 64 bits.
// Return the sum and the overflow.
static int64_t int_add(int64_t x, int64_t y, uint length_bits, bool &over) __attribute__((unused));
static int64_t int_add(int64_t x, int64_t y, uint length_bits, bool &over) {
int64_t mask = uint_mask(length_bits);
int64_t n = (x + y) & mask;
over = (((n ^ x) & (n ^ y)) >> (length_bits-1)) & 1; // check for overflow
if (n & (1LL<<(length_bits-1)))
n |= ~mask; // sign extend
return n;
}
// Subtract two signed ints.
// If there is an overflow then set the sum to the max or the min of the int range,
// depending on the sign bit.
// Sign extend to 64 bits.
// Return the sum and the overflow.
static int64_t int_sub(int64_t x, int64_t y, uint length_bits, bool &over) __attribute__((unused));
static int64_t int_sub(int64_t x, int64_t y, uint length_bits, bool &over) {
int64_t mask = uint_mask(length_bits);
int64_t n = (x - y) & mask;
over = (((x ^ y) & (n ^ x)) >> (length_bits-1)) & 1; // check for overflow
if (n & (1LL<<(length_bits-1)))
n |= ~mask; // sign extend
return n;
}
} // namespace tokudb
#endif
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