Auto-merge from mysql-next-mr.
This commit is contained in:
commit
dadf820743
@ -3068,3 +3068,5 @@ libmysqld/examples/mysqltest.cc
|
||||
libmysqld/sql_signal.cc
|
||||
libmysqld/rpl_handler.cc
|
||||
libmysqld/debug_sync.cc
|
||||
libmysqld/rpl_handler.cc
|
||||
dbug/tests
|
||||
|
@ -311,6 +311,7 @@ ADD_SUBDIRECTORY(extra)
|
||||
ADD_SUBDIRECTORY(client)
|
||||
ADD_SUBDIRECTORY(sql)
|
||||
ADD_SUBDIRECTORY(libmysql)
|
||||
ADD_SUBDIRECTORY(libservices)
|
||||
ADD_SUBDIRECTORY(tests)
|
||||
IF(WITH_EMBEDDED_SERVER)
|
||||
ADD_SUBDIRECTORY(libmysqld)
|
||||
|
@ -23,7 +23,7 @@ EXTRA_DIST = INSTALL-SOURCE INSTALL-WIN-SOURCE \
|
||||
|
||||
SUBDIRS = . include @docs_dirs@ @zlib_dir@ \
|
||||
@readline_topdir@ sql-common scripts \
|
||||
@pstack_dir@ \
|
||||
@pstack_dir@ libservices \
|
||||
@sql_union_dirs@ unittest \
|
||||
@sql_server@ @man_dirs@ tests \
|
||||
netware @libmysqld_dirs@ \
|
||||
@ -32,7 +32,7 @@ SUBDIRS = . include @docs_dirs@ @zlib_dir@ \
|
||||
|
||||
DIST_SUBDIRS = . include Docs zlib \
|
||||
cmd-line-utils sql-common scripts \
|
||||
pstack \
|
||||
pstack libservices \
|
||||
strings mysys dbug extra regex libmysql libmysql_r client unittest storage plugin \
|
||||
vio sql man tests \
|
||||
netware libmysqld \
|
||||
|
@ -1161,7 +1161,6 @@ void free_used_memory()
|
||||
mysql_server_end();
|
||||
|
||||
/* Don't use DBUG after mysql_server_end() */
|
||||
DBUG_VIOLATION_HELPER_LEAVE;
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -2921,7 +2921,7 @@ AC_CONFIG_FILES(Makefile extra/Makefile mysys/Makefile dnl
|
||||
man/Makefile BUILD/Makefile vio/Makefile dnl
|
||||
libmysql/Makefile libmysql_r/Makefile client/Makefile dnl
|
||||
sql/Makefile sql/share/Makefile dnl
|
||||
sql/sql_builtin.cc sql-common/Makefile dnl
|
||||
sql/sql_builtin.cc sql-common/Makefile libservices/Makefile dnl
|
||||
dbug/Makefile scripts/Makefile include/Makefile dnl
|
||||
tests/Makefile Docs/Makefile support-files/Makefile dnl
|
||||
support-files/MacOSX/Makefile support-files/RHEL4-SElinux/Makefile dnl
|
||||
|
@ -1,3 +0,0 @@
|
||||
.deps
|
||||
Makefile
|
||||
Makefile.in
|
@ -23,19 +23,20 @@ libdbug_a_SOURCES = dbug.c sanity.c
|
||||
EXTRA_DIST = CMakeLists.txt example1.c example2.c example3.c \
|
||||
user.r monty.doc dbug_add_tags.pl \
|
||||
my_main.c main.c factorial.c dbug_analyze.c \
|
||||
CMakeLists.txt
|
||||
CMakeLists.txt tests.c tests-t.pl
|
||||
NROFF_INC = example1.r example2.r example3.r main.r \
|
||||
factorial.r output1.r output2.r output3.r \
|
||||
output4.r output5.r
|
||||
CLEANFILES = $(NROFF_INC) user.t user.ps
|
||||
CLEANFILES = $(NROFF_INC) user.t user.ps tests-t
|
||||
|
||||
|
||||
# Must be linked with libs that are not compiled yet
|
||||
noinst_PROGRAMS = factorial dbug_analyze
|
||||
noinst_PROGRAMS = factorial dbug_analyze tests
|
||||
factorial_SOURCES = my_main.c factorial.c
|
||||
tests_SOURCES = tests.c
|
||||
dbug_analyze_SOURCES = dbug_analyze.c
|
||||
|
||||
all: user.t user.ps
|
||||
all: user.t user.ps tests-t
|
||||
|
||||
user.t: user.r $(NROFF_INC)
|
||||
-nroff -mm user.r > $@
|
||||
@ -61,5 +62,7 @@ output5.r: factorial
|
||||
@RM@ -f $@
|
||||
@SED@ -e 's!\\!\\\\!g' $< > $@
|
||||
|
||||
# Don't update the files from bitkeeper
|
||||
%::SCCS/s.%
|
||||
# a hack to have executable in builddir, not in srcdir
|
||||
tests-t: tests-t.pl
|
||||
cp -f $(srcdir)/tests-t.pl ./tests-t
|
||||
|
||||
|
888
dbug/dbug.c
888
dbug/dbug.c
File diff suppressed because it is too large
Load Diff
@ -7,7 +7,7 @@ $ctags="exctags -x -f - --c-types=f -u";
|
||||
sub get_tag {
|
||||
local $.; local $_=<TAGS>;
|
||||
($symbol, $line)= /^(.*\S)\s+function\s+(\d+)/;
|
||||
$symbol=$1 if /\s(\S+)\s*\(/;
|
||||
$symbol=$1 if /[\s*]([^\s*]+)\s*\(/;
|
||||
$line=1e50 unless $line;
|
||||
}
|
||||
|
||||
@ -51,7 +51,7 @@ while($src=shift)
|
||||
$skip=!$semicolon;
|
||||
$semicolon= /;\s*$/;
|
||||
print && next if $skip ||
|
||||
(/^\s+\w+((::\w+)?|<\w+>)\s+\**\w+/ && !/^\s*return/);
|
||||
(/^\s+\w+((::\w+)?|<\w+>)\s+\**\w+/ && !/^\s*return\b/);
|
||||
last if /DBUG_ENTER/;
|
||||
print "$tab DBUG_ENTER(\"$symbol\");\n";
|
||||
print "\n" unless $_ eq "\n";
|
||||
|
@ -1,15 +0,0 @@
|
||||
|
||||
# Warning - first line left blank for sh/csh/ksh compatibility. Do not
|
||||
# remove it. fnf@Unisoft
|
||||
|
||||
# doinstall.sh --- figure out environment and do recursive make with
|
||||
# appropriate pathnames. Works under SV or BSD.
|
||||
|
||||
if [ -r /usr/include/search.h ]
|
||||
then
|
||||
# System V
|
||||
$* LLIB=/usr/lib
|
||||
else
|
||||
# 4.2 BSD
|
||||
$* LLIB=/usr/lib/lint
|
||||
fi
|
@ -1,64 +0,0 @@
|
||||
|
||||
# WARNING -- first line intentionally left blank for sh/csh/ksh
|
||||
# compatibility. Do not remove it! FNF, UniSoft Systems.
|
||||
#
|
||||
# Usage is:
|
||||
# install <from> <to>
|
||||
#
|
||||
# The file <to> is replaced with the file <from>, after first
|
||||
# moving <to> to a backup file. The backup file name is created
|
||||
# by prepending the filename (after removing any leading pathname
|
||||
# components) with "OLD".
|
||||
#
|
||||
# This script is currently not real robust in the face of signals
|
||||
# or permission problems. It also does not do (by intention) all
|
||||
# the things that the System V or BSD install scripts try to do
|
||||
#
|
||||
|
||||
if [ $# -ne 2 ]
|
||||
then
|
||||
echo "usage: $0 <from> <to>"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Now extract the dirname and basename components. Unfortunately, BSD does
|
||||
# not have dirname, so we do it the hard way.
|
||||
|
||||
fd=`expr $1'/' : '\(/\)[^/]*/$' \| $1'/' : '\(.*[^/]\)//*[^/][^/]*//*$' \| .`
|
||||
ff=`basename $1`
|
||||
td=`expr $2'/' : '\(/\)[^/]*/$' \| $2'/' : '\(.*[^/]\)//*[^/][^/]*//*$' \| .`
|
||||
tf=`basename $2`
|
||||
|
||||
# Now test to make sure that they are not the same files.
|
||||
|
||||
if [ $fd/$ff = $td/$tf ]
|
||||
then
|
||||
echo "install: input and output are same files"
|
||||
exit 2
|
||||
fi
|
||||
|
||||
# Save a copy of the "to" file as a backup.
|
||||
|
||||
if test -f $td/$tf
|
||||
then
|
||||
if test -f $td/OLD$tf
|
||||
then
|
||||
rm -f $td/OLD$tf
|
||||
fi
|
||||
mv $td/$tf $td/OLD$tf
|
||||
if [ $? != 0 ]
|
||||
then
|
||||
exit 3
|
||||
fi
|
||||
fi
|
||||
|
||||
# Now do the copy and return appropriate status
|
||||
|
||||
cp $fd/$ff $td/$tf
|
||||
if [ $? != 0 ]
|
||||
then
|
||||
exit 4
|
||||
else
|
||||
exit 0
|
||||
fi
|
||||
|
@ -1,30 +0,0 @@
|
||||
|
||||
# Warning - first line left blank for sh/csh/ksh compatibility. Do not
|
||||
# remove it. fnf@Unisoft
|
||||
|
||||
# mklintlib --- make a lint library, under either System V or 4.2 BSD
|
||||
#
|
||||
# usage: mklintlib <infile> <outfile>
|
||||
#
|
||||
|
||||
if test $# -ne 2
|
||||
then
|
||||
echo "usage: mklintlib <infile> <outfile>"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if grep SIGTSTP /usr/include/signal.h >/dev/null
|
||||
then # BSD
|
||||
if test -r /usr/include/whoami.h # 4.1
|
||||
then
|
||||
/lib/cpp -C -Dlint $1 >hlint
|
||||
(/usr/lib/lint/lint1 <hlint >$2) 2>&1 | grep -v warning
|
||||
else # 4.2
|
||||
lint -Cxxxx $1
|
||||
mv llib-lxxxx.ln $2
|
||||
fi
|
||||
else # USG
|
||||
cc -E -C -Dlint $1 | /usr/lib/lint1 -vx -Hhlint >$2
|
||||
rm -f hlint
|
||||
fi
|
||||
exit 0 # don't kill make
|
@ -1,4 +0,0 @@
|
||||
CL -I\my\include -AL -Gsm2 -FPi -DDBUG_OFF *.c
|
||||
rm \my\lib\dbug.lib
|
||||
lib.exe \my\lib\dbug dbug.obj sanity.obj;
|
||||
link /NOD /STACK:8000 main factoria,factoria,,DBUG+STRINGS+LLIBCEP+DOSCALLS;
|
26
dbug/remove_function_from_trace.pl
Executable file
26
dbug/remove_function_from_trace.pl
Executable file
@ -0,0 +1,26 @@
|
||||
#!/usr/bin/perl
|
||||
|
||||
|
||||
die <<EEE unless @ARGV;
|
||||
Usage: $0 func1 [func2 [ ...] ]
|
||||
|
||||
This filter (stdin->stdout) removes lines from dbug trace that were generated
|
||||
by specified functions and all functions down the call stack. Produces the
|
||||
same effect as if the original source had DBUG_PUSH(""); right after
|
||||
DBUG_ENTER() and DBUG_POP(); right before DBUG_RETURN in every such a function.
|
||||
EEE
|
||||
|
||||
$re=join('|', @ARGV);
|
||||
$skip='';
|
||||
|
||||
while(<STDIN>) {
|
||||
print unless $skip;
|
||||
next unless /^(?:.*: )*((?:\| )*)([<>])($re)\n/o;
|
||||
if ($2 eq '>') {
|
||||
$skip=$1.$3 unless $skip;
|
||||
next;
|
||||
}
|
||||
next if $skip ne $1.$3;
|
||||
$skip='';
|
||||
print;
|
||||
}
|
496
dbug/tests-t.pl
Executable file
496
dbug/tests-t.pl
Executable file
@ -0,0 +1,496 @@
|
||||
#!/usr/bin/env perl
|
||||
|
||||
#
|
||||
# A driver program to test DBUG features - runs tests (shell commands)
|
||||
# from the end of file to invoke tests.c, which does the real dbug work.
|
||||
#
|
||||
|
||||
use Test::More;
|
||||
|
||||
$exe=$0;
|
||||
|
||||
die unless $exe =~ s/(tests)-t(\.exe)?$/$1$2 /;
|
||||
|
||||
# load tests
|
||||
@tests=();
|
||||
while (<DATA>) {
|
||||
if (/^% \.\/tests /) {
|
||||
push @tests, [ $' ]
|
||||
} elsif (/^#/) {
|
||||
next;
|
||||
} else {
|
||||
push @{$tests[$#tests]}, $_
|
||||
}
|
||||
}
|
||||
|
||||
plan skip_all => "because dbug is disabled" if system $exe;
|
||||
|
||||
plan tests => scalar(@tests);
|
||||
|
||||
for (@tests) {
|
||||
$t=$exe . shift @$_;
|
||||
chomp($t);
|
||||
open F, '-|', $t or die "open($t|): $!";
|
||||
local $";
|
||||
$out=join($", <F>); close(F);
|
||||
# special cases are handled here:
|
||||
$out =~ s/Memory: 0x[0-9A-Fa-f]+/Memory: 0x####/g if $t =~ /dump/;
|
||||
# compare ("\n" at the beginning makes better output in case of errors)
|
||||
is("\n$out","\n@$_", $t);
|
||||
}
|
||||
|
||||
__DATA__
|
||||
% ./tests -#d
|
||||
func2: info: s=ok
|
||||
=> execute
|
||||
=> evaluate: ON
|
||||
=> evaluate_if: OFF
|
||||
main: explain: dbug explained: d
|
||||
func2: info: s=ok
|
||||
% ./tests d,ret3
|
||||
=> evaluate: OFF
|
||||
=> evaluate_if: OFF
|
||||
#
|
||||
## Testing negative lists
|
||||
#
|
||||
% ./tests d:-d,ret3
|
||||
func2: info: s=ko
|
||||
=> execute
|
||||
=> evaluate: ON
|
||||
=> evaluate_if: OFF
|
||||
main: explain: dbug explained: d:-d,ret3
|
||||
func2: info: s=ko
|
||||
% ./tests t:-d,ret3
|
||||
>main
|
||||
| >func1
|
||||
| | >func2
|
||||
| | | >func3
|
||||
| | | <func3
|
||||
| | <func2
|
||||
| <func1
|
||||
=> evaluate: OFF
|
||||
=> evaluate_if: OFF
|
||||
| >func2
|
||||
| | >func3
|
||||
| | <func3
|
||||
| <func2
|
||||
<main
|
||||
% ./tests t:d,info:-d,ret3
|
||||
>main
|
||||
| >func1
|
||||
| | >func2
|
||||
| | | >func3
|
||||
| | | <func3
|
||||
| | | info: s=ko
|
||||
| | <func2
|
||||
| <func1
|
||||
=> evaluate: OFF
|
||||
=> evaluate_if: OFF
|
||||
| >func2
|
||||
| | >func3
|
||||
| | <func3
|
||||
| | info: s=ko
|
||||
| <func2
|
||||
<main
|
||||
% ./tests t:d,info:-d,ret3:-f,func2
|
||||
>main
|
||||
| >func1
|
||||
| | | >func3
|
||||
| | | <func3
|
||||
| <func1
|
||||
=> evaluate: OFF
|
||||
=> evaluate_if: OFF
|
||||
| | >func3
|
||||
| | <func3
|
||||
<main
|
||||
% ./tests t:d,info:-d,ret3:-f,func2 d,evaluate
|
||||
=> evaluate: ON
|
||||
=> evaluate_if: OFF
|
||||
% ./tests t:d,info:-d,ret3:-f,func2 d,evaluate_if
|
||||
=> evaluate: OFF
|
||||
=> evaluate_if: ON
|
||||
% ./tests t:d:-d,ret3:-f,func2 d,evaluate_if
|
||||
=> evaluate: OFF
|
||||
=> evaluate_if: ON
|
||||
% ./tests t:d:-d,ret3:-f,func2
|
||||
>main
|
||||
| >func1
|
||||
| | | >func3
|
||||
| | | <func3
|
||||
| <func1
|
||||
=> execute
|
||||
=> evaluate: ON
|
||||
=> evaluate_if: OFF
|
||||
| explain: dbug explained: d:-d,ret3:f:-f,func2:t
|
||||
| | >func3
|
||||
| | <func3
|
||||
<main
|
||||
#
|
||||
## Adding incremental settings to the brew
|
||||
#
|
||||
% ./tests t:d:-d,ret3:-f,func2 +d,evaluate_if
|
||||
>main
|
||||
| >func1
|
||||
| | | >func3
|
||||
| | | <func3
|
||||
| <func1
|
||||
=> evaluate: OFF
|
||||
=> evaluate_if: ON
|
||||
| | >func3
|
||||
| | <func3
|
||||
<main
|
||||
#
|
||||
## DBUG_DUMP
|
||||
#
|
||||
% ./tests t:d:-d,ret3:f:-f,func2 +d,dump
|
||||
>main
|
||||
| >func1
|
||||
| | | >func3
|
||||
| | | <func3
|
||||
| <func1
|
||||
| dump: Memory: 0x#### Bytes: (27)
|
||||
64 2C 64 75 6D 70 3A 2D 64 2C 72 65 74 33 3A 66 3A 2D 66 2C 66 75 6E 63 32 3A
|
||||
74
|
||||
=> evaluate: OFF
|
||||
=> evaluate_if: OFF
|
||||
| | >func3
|
||||
| | <func3
|
||||
<main
|
||||
% ./tests t:d:-d,ret3:f:-f,func2 +d,dump
|
||||
>main
|
||||
| >func1
|
||||
| | | >func3
|
||||
| | | <func3
|
||||
| <func1
|
||||
| dump: Memory: 0x#### Bytes: (27)
|
||||
64 2C 64 75 6D 70 3A 2D 64 2C 72 65 74 33 3A 66 3A 2D 66 2C 66 75 6E 63 32 3A
|
||||
74
|
||||
=> evaluate: OFF
|
||||
=> evaluate_if: OFF
|
||||
| | >func3
|
||||
| | <func3
|
||||
<main
|
||||
% ./tests t:d:-d,ret3:f:-f,func2:+d,dump
|
||||
>main
|
||||
| >func1
|
||||
| | | >func3
|
||||
| | | <func3
|
||||
| <func1
|
||||
| dump: Memory: 0x#### Bytes: (27)
|
||||
64 2C 64 75 6D 70 3A 2D 64 2C 72 65 74 33 3A 66 3A 2D 66 2C 66 75 6E 63 32 3A
|
||||
74
|
||||
=> evaluate: OFF
|
||||
=> evaluate_if: OFF
|
||||
| | >func3
|
||||
| | <func3
|
||||
<main
|
||||
% ./tests t:d:-d,ret3:f:-f,func2 +d,dump,explain
|
||||
>main
|
||||
| >func1
|
||||
| | | >func3
|
||||
| | | <func3
|
||||
| <func1
|
||||
| dump: Memory: 0x#### Bytes: (35)
|
||||
64 2C 64 75 6D 70 2C 65 78 70 6C 61 69 6E 3A 2D 64 2C 72 65 74 33 3A 66 3A 2D
|
||||
66 2C 66 75 6E 63 32 3A 74
|
||||
=> evaluate: OFF
|
||||
=> evaluate_if: OFF
|
||||
| explain: dbug explained: d,dump,explain:-d,ret3:f:-f,func2:t
|
||||
| | >func3
|
||||
| | <func3
|
||||
<main
|
||||
% ./tests t:d:-d,ret3:f:-f,func2 +d,dump,explain:P
|
||||
dbug: >main
|
||||
dbug-tests: | >func1
|
||||
dbug-tests: | | | >func3
|
||||
dbug-tests: | | | <func3
|
||||
dbug-tests: | <func1
|
||||
dbug-tests: | dump: Memory: 0x#### Bytes: (37)
|
||||
64 2C 64 75 6D 70 2C 65 78 70 6C 61 69 6E 3A 2D 64 2C 72 65 74 33 3A 66 3A 2D
|
||||
66 2C 66 75 6E 63 32 3A 50 3A 74
|
||||
=> evaluate: OFF
|
||||
=> evaluate_if: OFF
|
||||
dbug-tests: | explain: dbug explained: d,dump,explain:-d,ret3:f:-f,func2:P:t
|
||||
dbug-tests: | | >func3
|
||||
dbug-tests: | | <func3
|
||||
dbug-tests: <main
|
||||
% ./tests t:d:-d,ret3:f:-f,func2 +d,dump,explain:P:F
|
||||
dbug: tests.c: >main
|
||||
dbug-tests: tests.c: | >func1
|
||||
dbug-tests: tests.c: | | | >func3
|
||||
dbug-tests: tests.c: | | | <func3
|
||||
dbug-tests: tests.c: | <func1
|
||||
dbug-tests: tests.c: | dump: Memory: 0x#### Bytes: (39)
|
||||
64 2C 64 75 6D 70 2C 65 78 70 6C 61 69 6E 3A 2D 64 2C 72 65 74 33 3A 66 3A 2D
|
||||
66 2C 66 75 6E 63 32 3A 46 3A 50 3A 74
|
||||
=> evaluate: OFF
|
||||
=> evaluate_if: OFF
|
||||
dbug-tests: tests.c: | explain: dbug explained: d,dump,explain:-d,ret3:f:-f,func2:F:P:t
|
||||
dbug-tests: tests.c: | | >func3
|
||||
dbug-tests: tests.c: | | <func3
|
||||
dbug-tests: tests.c: <main
|
||||
#
|
||||
## DBUG_EXPLAIN, DBUG_PUSH, DBUG_POP, DBUG_SET
|
||||
#
|
||||
% ./tests t:d:-d,ret3:f:-f,func2
|
||||
>main
|
||||
| >func1
|
||||
| | | >func3
|
||||
| | | <func3
|
||||
| <func1
|
||||
=> execute
|
||||
=> evaluate: ON
|
||||
=> evaluate_if: OFF
|
||||
| explain: dbug explained: d:-d,ret3:f:-f,func2:t
|
||||
| | >func3
|
||||
| | <func3
|
||||
<main
|
||||
% ./tests t:d:-d,ret3
|
||||
>main
|
||||
| >func1
|
||||
| | >func2
|
||||
| | | >func3
|
||||
| | | <func3
|
||||
| | | info: s=ko
|
||||
| | <func2
|
||||
| <func1
|
||||
=> execute
|
||||
=> evaluate: ON
|
||||
=> evaluate_if: OFF
|
||||
| explain: dbug explained: d:-d,ret3:t
|
||||
| >func2
|
||||
| | >func3
|
||||
| | <func3
|
||||
| | info: s=ko
|
||||
| <func2
|
||||
<main
|
||||
% ./tests d,info:-d,ret3:d,push
|
||||
func2: info: s=ko
|
||||
=> evaluate: OFF
|
||||
=> evaluate_if: OFF
|
||||
| >func2
|
||||
| | >func3
|
||||
| | <func3
|
||||
| | info: s=ko
|
||||
| <func2
|
||||
<main
|
||||
% ./tests d,info:-d,ret3:d,push,explain
|
||||
func2: info: s=ko
|
||||
=> evaluate: OFF
|
||||
=> evaluate_if: OFF
|
||||
| explain: dbug explained: d,info,push,explain:-d,ret3:t
|
||||
| >func2
|
||||
| | >func3
|
||||
| | <func3
|
||||
| | info: s=ko
|
||||
| <func2
|
||||
<main
|
||||
% ./tests d,info:-d,ret3:d,explain
|
||||
func2: info: s=ko
|
||||
=> evaluate: OFF
|
||||
=> evaluate_if: OFF
|
||||
main: explain: dbug explained: d,info,explain:-d,ret3
|
||||
func2: info: s=ko
|
||||
% ./tests d,info:-d,ret3:d,explain,pop
|
||||
func2: info: s=ko
|
||||
=> evaluate: OFF
|
||||
=> evaluate_if: OFF
|
||||
% ./tests d,info:-d,ret3:d,explain t:d,pop
|
||||
>main
|
||||
| >func1
|
||||
| | >func2
|
||||
| | | >func3
|
||||
| | | <func3
|
||||
| | <func2
|
||||
| <func1
|
||||
=> evaluate: OFF
|
||||
=> evaluate_if: OFF
|
||||
main: explain: dbug explained: d,info,explain:-d,ret3
|
||||
func2: info: s=ko
|
||||
% ./tests d,info:-d,ret3:d,explain,pop +t
|
||||
>main
|
||||
| >func1
|
||||
| | >func2
|
||||
| | | >func3
|
||||
| | | <func3
|
||||
| | | info: s=ko
|
||||
| | <func2
|
||||
| <func1
|
||||
=> evaluate: OFF
|
||||
=> evaluate_if: OFF
|
||||
main: explain: dbug explained: d,info,explain,pop:-d,ret3
|
||||
func2: info: s=ko
|
||||
% ./tests d,info:-d,ret3:d,explain,set
|
||||
func2: info: s=ko
|
||||
=> evaluate: OFF
|
||||
=> evaluate_if: OFF
|
||||
tests.c: main: explain: dbug explained: d,info,explain,set:-d,ret3:F
|
||||
tests.c: func2: info: s=ko
|
||||
% ./tests d,info:-d,ret3:d,explain,set:t
|
||||
>main
|
||||
| >func1
|
||||
| | >func2
|
||||
| | | >func3
|
||||
| | | <func3
|
||||
| | | info: s=ko
|
||||
| | <func2
|
||||
| <func1
|
||||
=> evaluate: OFF
|
||||
=> evaluate_if: OFF
|
||||
tests.c: | explain: dbug explained: d,info,explain,set:-d,ret3:F:t
|
||||
tests.c: | >func2
|
||||
tests.c: | | >func3
|
||||
tests.c: | | <func3
|
||||
tests.c: | | info: s=ko
|
||||
tests.c: | <func2
|
||||
tests.c: <main
|
||||
% ./tests t d,info:-d,ret3:d,explain,set:t
|
||||
>main
|
||||
| >func1
|
||||
| | >func2
|
||||
| | | >func3
|
||||
| | | <func3
|
||||
| | | info: s=ko
|
||||
| | <func2
|
||||
| <func1
|
||||
=> evaluate: OFF
|
||||
=> evaluate_if: OFF
|
||||
tests.c: | explain: dbug explained: d,info,explain,set:-d,ret3:F:t
|
||||
tests.c: | >func2
|
||||
tests.c: | | >func3
|
||||
tests.c: | | <func3
|
||||
tests.c: | | info: s=ko
|
||||
tests.c: | <func2
|
||||
tests.c: <main
|
||||
% ./tests t d,info:-d,ret3:d,explain,set,pop
|
||||
func2: info: s=ko
|
||||
=> evaluate: OFF
|
||||
=> evaluate_if: OFF
|
||||
| >func2
|
||||
| | >func3
|
||||
| | <func3
|
||||
| <func2
|
||||
<main
|
||||
% ./tests t:f,func2
|
||||
| | >func2
|
||||
| | <func2
|
||||
=> evaluate: OFF
|
||||
=> evaluate_if: OFF
|
||||
| >func2
|
||||
| <func2
|
||||
#
|
||||
## Testing SUBDIR rules
|
||||
#
|
||||
% ./tests t:-f,func2/:d
|
||||
>main
|
||||
| >func1
|
||||
| <func1
|
||||
=> execute
|
||||
=> evaluate: ON
|
||||
=> evaluate_if: OFF
|
||||
| explain: dbug explained: d:f:-f,func2/:t
|
||||
<main
|
||||
% ./tests t:f,func1/:d
|
||||
| >func1
|
||||
| | >func2
|
||||
| | | >func3
|
||||
| | | <func3
|
||||
| | | info: s=ok
|
||||
| | <func2
|
||||
| <func1
|
||||
=> evaluate: OFF
|
||||
=> evaluate_if: OFF
|
||||
% ./tests t:f,main/:d,pop
|
||||
>main
|
||||
| >func1
|
||||
| | >func2
|
||||
| | | >func3
|
||||
| | | <func3
|
||||
| | <func2
|
||||
| <func1
|
||||
=> evaluate: OFF
|
||||
=> evaluate_if: OFF
|
||||
% ./tests f,main/:d,push
|
||||
=> evaluate: OFF
|
||||
=> evaluate_if: OFF
|
||||
| >func2
|
||||
| | >func3
|
||||
| | <func3
|
||||
| <func2
|
||||
<main
|
||||
#
|
||||
## Testing FixTraceFlags() - when we need to traverse the call stack
|
||||
# (these tests fail with FixTraceFlags() disabled)
|
||||
#
|
||||
# delete the INCLUDE rule up the stack
|
||||
% ./tests t:f,func1/ --push1=t:f,func3/
|
||||
| >func1
|
||||
| | >func2
|
||||
| | | >func3
|
||||
| | | <func3
|
||||
| | <func2
|
||||
=> push1
|
||||
=> evaluate: OFF
|
||||
=> evaluate_if: OFF
|
||||
| | >func3
|
||||
| | <func3
|
||||
# delete the EXCLUDE rule up the stack
|
||||
% ./tests t:-f,func1/ --push1=t
|
||||
>main
|
||||
=> push1
|
||||
| <func1
|
||||
=> evaluate: OFF
|
||||
=> evaluate_if: OFF
|
||||
| >func2
|
||||
| | >func3
|
||||
| | <func3
|
||||
| <func2
|
||||
<main
|
||||
# add the INCLUDE rule up the stack
|
||||
% ./tests t:f,func3 --push1=t:f,main/
|
||||
| | | >func3
|
||||
| | | <func3
|
||||
=> push1
|
||||
| <func1
|
||||
=> evaluate: OFF
|
||||
=> evaluate_if: OFF
|
||||
| >func2
|
||||
| | >func3
|
||||
| | <func3
|
||||
| <func2
|
||||
<main
|
||||
# add the EXCLUDE rule up the stack
|
||||
% ./tests t --push1=t:-f,main/
|
||||
>main
|
||||
| >func1
|
||||
| | >func2
|
||||
| | | >func3
|
||||
| | | <func3
|
||||
| | <func2
|
||||
=> push1
|
||||
=> evaluate: OFF
|
||||
=> evaluate_if: OFF
|
||||
# change the defaults
|
||||
% ./tests t:f,func3 --push1=t
|
||||
| | | >func3
|
||||
| | | <func3
|
||||
=> push1
|
||||
| <func1
|
||||
=> evaluate: OFF
|
||||
=> evaluate_if: OFF
|
||||
| >func2
|
||||
| | >func3
|
||||
| | <func3
|
||||
| <func2
|
||||
<main
|
||||
# repeated keyword
|
||||
% ./tests d:-d,info,info
|
||||
=> execute
|
||||
=> evaluate: ON
|
||||
=> evaluate_if: OFF
|
||||
main: explain: dbug explained: d:-d,info
|
||||
% ./tests d:-d,info/,info
|
||||
=> execute
|
||||
=> evaluate: ON
|
||||
=> evaluate_if: OFF
|
||||
main: explain: dbug explained: d:-d,info/
|
87
dbug/tests.c
Normal file
87
dbug/tests.c
Normal file
@ -0,0 +1,87 @@
|
||||
/*
|
||||
A program to test DBUG features. Used by tests-t.pl
|
||||
*/
|
||||
|
||||
char *push1=0;
|
||||
|
||||
#include <my_global.h> /* This includes dbug.h */
|
||||
#include <my_pthread.h>
|
||||
#include <string.h>
|
||||
|
||||
const char *func3()
|
||||
{
|
||||
DBUG_ENTER("func3");
|
||||
DBUG_RETURN(DBUG_EVALUATE("ret3", "ok", "ko"));
|
||||
}
|
||||
|
||||
void func2()
|
||||
{
|
||||
const char *s;
|
||||
DBUG_ENTER("func2");
|
||||
s=func3();
|
||||
DBUG_PRINT("info", ("s=%s", s));
|
||||
DBUG_VOID_RETURN;
|
||||
}
|
||||
|
||||
int func1()
|
||||
{
|
||||
DBUG_ENTER("func1");
|
||||
func2();
|
||||
if (push1)
|
||||
{
|
||||
DBUG_PUSH(push1);
|
||||
fprintf(DBUG_FILE, "=> push1\n");
|
||||
}
|
||||
DBUG_RETURN(10);
|
||||
}
|
||||
|
||||
int main (int argc, char *argv[])
|
||||
{
|
||||
int i;
|
||||
#ifdef DBUG_OFF
|
||||
return 1;
|
||||
#endif
|
||||
if (argc == 1)
|
||||
return 0;
|
||||
|
||||
#if defined(HAVE_PTHREAD_INIT) && defined(THREAD)
|
||||
pthread_init(); /* Must be called before DBUG_ENTER */
|
||||
#endif
|
||||
#ifdef THREAD
|
||||
my_thread_global_init();
|
||||
#endif
|
||||
dup2(1, 2);
|
||||
for (i = 1; i < argc; i++)
|
||||
{
|
||||
if (strncmp(argv[i], "--push1=", 8) == 0)
|
||||
push1=argv[i]+8;
|
||||
else
|
||||
DBUG_PUSH (argv[i]);
|
||||
}
|
||||
{
|
||||
DBUG_ENTER ("main");
|
||||
DBUG_PROCESS ("dbug-tests");
|
||||
func1();
|
||||
DBUG_EXECUTE_IF("dump",
|
||||
{
|
||||
char s[1000];
|
||||
DBUG_EXPLAIN(s, sizeof(s)-1);
|
||||
DBUG_DUMP("dump", (uchar*)s, strlen(s));
|
||||
});
|
||||
DBUG_EXECUTE_IF("push", DBUG_PUSH("+t"); );
|
||||
DBUG_EXECUTE("execute", fprintf(DBUG_FILE, "=> execute\n"); );
|
||||
DBUG_EXECUTE_IF("set", DBUG_SET("+F"); );
|
||||
fprintf(DBUG_FILE, "=> evaluate: %s\n",
|
||||
DBUG_EVALUATE("evaluate", "ON", "OFF"));
|
||||
fprintf(DBUG_FILE, "=> evaluate_if: %s\n",
|
||||
DBUG_EVALUATE_IF("evaluate_if", "ON", "OFF"));
|
||||
DBUG_EXECUTE_IF("pop", DBUG_POP(); );
|
||||
{
|
||||
char s[1000] __attribute__((unused));
|
||||
DBUG_EXPLAIN(s, sizeof(s)-1);
|
||||
DBUG_PRINT("explain", ("dbug explained: %s", s));
|
||||
}
|
||||
func2();
|
||||
DBUG_RETURN (0);
|
||||
}
|
||||
}
|
54
dbug/user.r
54
dbug/user.r
@ -512,7 +512,7 @@ possible since all code preceding the first call to
|
||||
.B DBUG_PUSH
|
||||
is
|
||||
essentially invisible to
|
||||
.B dbug
|
||||
.I dbug
|
||||
(this can be worked around by
|
||||
inserting a temporary
|
||||
.B DBUG_PUSH(argv[1])
|
||||
@ -708,7 +708,7 @@ EX:\ \fCDBUG_PROCESS\ (argv[0]);\fR
|
||||
.SP 1
|
||||
.LI DBUG_PUSH\
|
||||
Sets a new debugger state by pushing the current
|
||||
.B dbug
|
||||
.I dbug
|
||||
state onto an internal stack and setting up the new state using the
|
||||
debug control string passed as the macro argument. The most common
|
||||
usage is to set the state specified by a debug control string
|
||||
@ -769,14 +769,14 @@ the 'd' flag. Used to conditionally execute "dangerous" actions, e.g
|
||||
to crash the program testing how recovery works, or to introduce an
|
||||
artificial delay checking for race conditions.
|
||||
.SP 1
|
||||
EX:\ \fCDBUG_EXECUTE_IF\ ("crashme",\ abort\ ());\fR
|
||||
EX:\ \fCDBUG_EXECUTE_IF\ ("crashme",\ DBUG_ABORT()\ ());\fR
|
||||
.SP 1
|
||||
.LI DBUG_EVALUATE\
|
||||
The DBUG_EVALUATE macro is similar to DBUG_EXECUTE, but it can be used in
|
||||
the expression context. The first argument is the debug keyword that is used to
|
||||
choose whether the second (keyword is enabled) or the third (keyword is not
|
||||
enabled) argument is evaluated. When
|
||||
.B dbug
|
||||
.I dbug
|
||||
is compiled off, the third argument is evaluated.
|
||||
.SP 1
|
||||
EX:\fC
|
||||
@ -796,7 +796,7 @@ EX:\fC
|
||||
.br
|
||||
if (prepare_transaction () ||
|
||||
.br
|
||||
DBUG_EVALUATE ("crashme", (abort (), 0), 0) ||
|
||||
DBUG_EVALUATE ("crashme", (DBUG_ABORT(), 0), 0) ||
|
||||
.br
|
||||
commit_transaction () )\fR
|
||||
.SP 1
|
||||
@ -875,6 +875,12 @@ library. So there will be no need to disable asserts separately with NDEBUG.
|
||||
.SP 1
|
||||
EX:\ \fCDBUG_ASSERT(\ a\ >\ 0\ );\fR
|
||||
.SP 1
|
||||
.LI DBUG_ABORT\
|
||||
This macro could be used instead of abort(). It flushes DBUG_FILE stream
|
||||
to ensure that no
|
||||
.I dbug
|
||||
output is lost and then calls abort().
|
||||
.SP 1
|
||||
.LI DBUG_EXPLAIN\
|
||||
Generates control string corresponding to the current debug state.
|
||||
The macro takes two arguments - a buffer to store the result string
|
||||
@ -910,17 +916,17 @@ via the
|
||||
.B DBUG_PUSH
|
||||
or
|
||||
.B DBUG_SET
|
||||
macros. Control string consists of colon separate flags. Colons
|
||||
macros. Control string consists of colon separated flags. Colons
|
||||
that are part of ':\\', ':/', or '::' are not considered flag
|
||||
separators. A flag may take an argument or a list of arguments.
|
||||
If a control string starts from a '+' sign it works
|
||||
.I incrementally,
|
||||
that is, it can modify existing state without overriding it. In such a
|
||||
string every flag may be preceded by a '+' or '-' to enable or disable
|
||||
a corresponding option in the debugger state. This section summarizes
|
||||
the currently available debugger options and the flag characters which
|
||||
enable or disable them. Argument lists enclosed in '[' and ']' are
|
||||
optional.
|
||||
that is, it can modify existing state without overriding it. Every
|
||||
flag may be preceded by a '+' or '-' to enable or disable a
|
||||
corresponding option in the debugger state or to add or remove
|
||||
arguments to the list. This section summarizes the currently available
|
||||
debugger options and the flag characters which enable or disable them.
|
||||
Argument lists enclosed in '[' and ']' are optional.
|
||||
.SP 2
|
||||
.BL 22
|
||||
.LI a[,file]
|
||||
@ -936,6 +942,9 @@ a complete log file in case of crashes. This mode is implicit in
|
||||
multi-threaded environment.
|
||||
.LI d[,keywords]
|
||||
Enable output from macros with specified keywords.
|
||||
Every keyword can be a
|
||||
.I glob(7)
|
||||
pattern.
|
||||
An empty list of keywords implies that all keywords are selected.
|
||||
.LI D[,time]
|
||||
Delay for specified time after each output line, to let output drain.
|
||||
@ -943,7 +952,19 @@ Time is given in tenths of a second (value of 10 is one second).
|
||||
Default is zero.
|
||||
.LI f[,functions]
|
||||
Limit debugger actions to the specified list of functions.
|
||||
Every function can be a
|
||||
.I glob(7)
|
||||
pattern.
|
||||
An empty list of functions implies that all functions are selected.
|
||||
Every function in the list may optionally be followed by a '/' -
|
||||
this will implicitly select all the functions down the call stack.
|
||||
.SP 1
|
||||
EX: \fCf,func1,func2/:-f,func3,func4/\fR
|
||||
.SP 1
|
||||
This would enable debugger in functions 'func1()', 'func2()' and all
|
||||
functions called from it (directly or indirectly). But not in
|
||||
functions 'func3()' or 'func4()' and all functions called from
|
||||
it.
|
||||
.LI F
|
||||
Mark each debugger output line with the name of the source file
|
||||
containing the macro causing the output.
|
||||
@ -952,6 +973,9 @@ Mark each debugger output line with the PID (or thread ID) of the
|
||||
current process.
|
||||
.LI g,[functions]
|
||||
Enable profiling for the specified list of functions.
|
||||
Every function can be a
|
||||
.I glob(7)
|
||||
pattern.
|
||||
An empty list of functions enables profiling for all functions.
|
||||
See
|
||||
.B PROFILING\ WITH\ DBUG
|
||||
@ -970,7 +994,11 @@ Like 'a[,file]' but overwrite old file, do not append.
|
||||
.LI O[,file]
|
||||
Like 'A[,file]' but overwrite old file, do not append.
|
||||
.LI p[,processes]
|
||||
Limit debugger actions to the specified processes. An empty list
|
||||
Limit debugger actions to the specified processes.
|
||||
Every name can be a
|
||||
.I glob(7)
|
||||
pattern.
|
||||
An empty list
|
||||
implies all processes. This is useful for processes which run child
|
||||
processes. Note that each debugger output line can be marked with the
|
||||
name of the current process via the 'P' flag. The process name must
|
||||
|
139
dbug/vargs.h
139
dbug/vargs.h
@ -1,139 +0,0 @@
|
||||
/******************************************************************************
|
||||
* *
|
||||
* N O T I C E *
|
||||
* *
|
||||
* Copyright Abandoned, 1987, Fred Fish *
|
||||
* *
|
||||
* *
|
||||
* This previously copyrighted work has been placed into the public *
|
||||
* domain by the author and may be freely used for any purpose, *
|
||||
* private or commercial. *
|
||||
* *
|
||||
* Because of the number of inquiries I was receiving about the use *
|
||||
* of this product in commercially developed works I have decided to *
|
||||
* simply make it public domain to further its unrestricted use. I *
|
||||
* specifically would be most happy to see this material become a *
|
||||
* part of the standard Unix distributions by AT&T and the Berkeley *
|
||||
* Computer Science Research Group, and a standard part of the GNU *
|
||||
* system from the Free Software Foundation. *
|
||||
* *
|
||||
* I would appreciate it, as a courtesy, if this notice is left in *
|
||||
* all copies and derivative works. Thank you. *
|
||||
* *
|
||||
* The author makes no warranty of any kind with respect to this *
|
||||
* product and explicitly disclaims any implied warranties of mer- *
|
||||
* chantability or fitness for any particular purpose. *
|
||||
* *
|
||||
******************************************************************************
|
||||
*/
|
||||
|
||||
|
||||
/*
|
||||
* FILE
|
||||
*
|
||||
* vargs.h include file for environments without varargs.h
|
||||
*
|
||||
* SCCS
|
||||
*
|
||||
* @(#)vargs.h 1.2 5/8/88
|
||||
*
|
||||
* SYNOPSIS
|
||||
*
|
||||
* #include "vargs.h"
|
||||
*
|
||||
* DESCRIPTION
|
||||
*
|
||||
* This file implements a varargs macro set for use in those
|
||||
* environments where there is no system supplied varargs. This
|
||||
* generally works because systems which don't supply a varargs
|
||||
* package are precisely those which don't strictly need a varargs
|
||||
* package. Using this one then allows us to minimize source
|
||||
* code changes. So in some sense, this is a "portable" varargs
|
||||
* since it is only used for convenience, when it is not strictly
|
||||
* needed.
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
* These macros allow us to rebuild an argument list on the stack
|
||||
* given only a va_list. We can use these to fake a function like
|
||||
* vfprintf, which gets a fixed number of arguments, the last of
|
||||
* which is a va_list, by rebuilding a stack and calling the variable
|
||||
* argument form fprintf. Of course this only works when vfprintf
|
||||
* is not available in the host environment, and thus is not available
|
||||
* for fprintf to call (which would give us an infinite loop).
|
||||
*
|
||||
* Note that ARGS_TYPE is a long, which lets us get several bytes
|
||||
* at a time while also preventing lots of "possible pointer alignment
|
||||
* problem" messages from lint. The messages are valid, because this
|
||||
* IS nonportable, but then we should only be using it in very
|
||||
* nonrestrictive environments, and using the real varargs where it
|
||||
* really counts.
|
||||
*
|
||||
*/
|
||||
|
||||
#define ARG0 a0
|
||||
#define ARG1 a1
|
||||
#define ARG2 a2
|
||||
#define ARG3 a3
|
||||
#define ARG4 a4
|
||||
#define ARG5 a5
|
||||
#define ARG6 a6
|
||||
#define ARG7 a7
|
||||
#define ARG8 a8
|
||||
#define ARG9 a9
|
||||
|
||||
#define ARGS_TYPE long
|
||||
#define ARGS_LIST ARG0,ARG1,ARG2,ARG3,ARG4,ARG5,ARG6,ARG7,ARG8,ARG9
|
||||
#define ARGS_DCL auto ARGS_TYPE ARGS_LIST
|
||||
|
||||
/*
|
||||
* A pointer of type "va_list" points to a section of memory
|
||||
* containing an array of variable sized arguments of unknown
|
||||
* number. This pointer is initialized by the va_start
|
||||
* macro to point to the first byte of the first argument.
|
||||
* We can then use it to walk through the argument list by
|
||||
* incrementing it by the size of the argument being referenced.
|
||||
*/
|
||||
|
||||
typedef char *va_list;
|
||||
|
||||
/*
|
||||
* The first variable argument overlays va_alist, which is
|
||||
* nothing more than a "handle" which allows us to get the
|
||||
* address of the first argument on the stack. Note that
|
||||
* by definition, the va_dcl macro includes the terminating
|
||||
* semicolon, which makes use of va_dcl in the source code
|
||||
* appear to be missing a semicolon.
|
||||
*/
|
||||
|
||||
#define va_dcl ARGS_TYPE va_alist;
|
||||
|
||||
/*
|
||||
* The va_start macro takes a variable of type "va_list" and
|
||||
* initializes it. In our case, it initializes a local variable
|
||||
* of type "pointer to char" to point to the first argument on
|
||||
* the stack.
|
||||
*/
|
||||
|
||||
#define va_start(list) list = (char *) &va_alist
|
||||
|
||||
/*
|
||||
* The va_end macro is a null operation for our use.
|
||||
*/
|
||||
|
||||
#define va_end(list)
|
||||
|
||||
/*
|
||||
* The va_arg macro is the tricky one. This one takes
|
||||
* a va_list as the first argument, and a type as the second
|
||||
* argument, and returns a value of the appropriate type
|
||||
* while advancing the va_list to the following argument.
|
||||
* For our case, we first increment the va_list arg by the
|
||||
* size of the type being recovered, cast the result to
|
||||
* a pointer of the appropriate type, and then dereference
|
||||
* that pointer as an array to get the previous arg (which
|
||||
* is the one we wanted.
|
||||
*/
|
||||
|
||||
#define va_arg(list,type) ((type *) (list += sizeof (type)))[-1]
|
@ -21,7 +21,8 @@ HEADERS_GEN_MAKE = my_config.h
|
||||
HEADERS_ABI = mysql.h mysql_com.h mysql_time.h \
|
||||
my_list.h my_alloc.h typelib.h mysql/plugin.h
|
||||
pkginclude_HEADERS = $(HEADERS_ABI) my_dbug.h m_string.h my_sys.h \
|
||||
my_xml.h mysql_embed.h \
|
||||
my_xml.h mysql_embed.h mysql/services.h \
|
||||
mysql/service_my_snprintf.h mysql/service_thd_alloc.h \
|
||||
my_pthread.h my_no_pthread.h \
|
||||
decimal.h errmsg.h my_global.h my_net.h \
|
||||
my_getopt.h sslopt-longopts.h my_dir.h \
|
||||
@ -36,7 +37,7 @@ noinst_HEADERS = config-win.h config-netware.h my_bit.h \
|
||||
my_nosys.h my_alarm.h queues.h rijndael.h sha1.h \
|
||||
my_aes.h my_tree.h my_trie.h hash.h thr_alarm.h \
|
||||
thr_lock.h t_ctype.h violite.h my_md5.h base64.h \
|
||||
my_handler.h my_time.h \
|
||||
my_handler.h my_time.h service_versions.h \
|
||||
my_vle.h my_user.h my_atomic.h atomic/nolock.h \
|
||||
atomic/rwlock.h atomic/x86-gcc.h atomic/x86-msvc.h \
|
||||
atomic/solaris.h \
|
||||
|
@ -250,16 +250,10 @@ extern size_t my_snprintf(char *to, size_t n, const char *fmt, ...)
|
||||
|
||||
/*
|
||||
LEX_STRING -- a pair of a C-string and its length.
|
||||
(it's part of the plugin API as a MYSQL_LEX_STRING)
|
||||
*/
|
||||
|
||||
#ifndef _my_plugin_h
|
||||
/* This definition must match the one given in mysql/plugin.h */
|
||||
struct st_mysql_lex_string
|
||||
{
|
||||
char *str;
|
||||
size_t length;
|
||||
};
|
||||
#endif
|
||||
#include <mysql/plugin.h>
|
||||
typedef struct st_mysql_lex_string LEX_STRING;
|
||||
|
||||
#define STRING_WITH_LEN(X) (X), ((size_t) (sizeof(X) - 1))
|
||||
|
@ -16,103 +16,64 @@
|
||||
#ifndef _dbug_h
|
||||
#define _dbug_h
|
||||
|
||||
#if defined(__cplusplus) && !defined(DBUG_OFF)
|
||||
class Dbug_violation_helper
|
||||
{
|
||||
public:
|
||||
inline Dbug_violation_helper() :
|
||||
_entered(TRUE)
|
||||
{ }
|
||||
|
||||
inline ~Dbug_violation_helper()
|
||||
{
|
||||
assert(!_entered);
|
||||
}
|
||||
|
||||
inline void leave()
|
||||
{
|
||||
_entered= FALSE;
|
||||
}
|
||||
|
||||
private:
|
||||
bool _entered;
|
||||
};
|
||||
#endif /* C++ */
|
||||
|
||||
#ifdef __cplusplus
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
#if !defined(DBUG_OFF) && !defined(_lint)
|
||||
struct _db_code_state_;
|
||||
extern int _db_keyword_(struct _db_code_state_ *cs, const char *keyword);
|
||||
extern int _db_keywords_(const char *, const char *);
|
||||
extern int _db_strict_keyword_(const char *keyword);
|
||||
|
||||
struct _db_stack_frame_ {
|
||||
const char *func; /* function name of the previous stack frame */
|
||||
const char *file; /* filename of the function of previous frame */
|
||||
uint level; /* this nesting level, highest bit enables tracing */
|
||||
struct _db_stack_frame_ *prev; /* pointer to the previous frame */
|
||||
};
|
||||
|
||||
struct _db_code_state_;
|
||||
extern my_bool _dbug_on_;
|
||||
extern my_bool _db_keyword_(struct _db_code_state_ *, const char *, int);
|
||||
extern int _db_explain_(struct _db_code_state_ *cs, char *buf, size_t len);
|
||||
extern int _db_explain_init_(char *buf, size_t len);
|
||||
extern void _db_setjmp_(void);
|
||||
extern void _db_longjmp_(void);
|
||||
extern int _db_is_pushed_(void);
|
||||
extern void _db_setjmp_(void);
|
||||
extern void _db_longjmp_(void);
|
||||
extern void _db_process_(const char *name);
|
||||
extern void _db_push_(const char *control);
|
||||
extern void _db_pop_(void);
|
||||
extern void _db_set_(struct _db_code_state_ *cs, const char *control);
|
||||
extern void _db_push_(const char *control);
|
||||
extern void _db_pop_(void);
|
||||
extern void _db_set_(const char *control);
|
||||
extern void _db_set_init_(const char *control);
|
||||
extern void _db_enter_(const char *_func_,const char *_file_,uint _line_,
|
||||
const char **_sfunc_,const char **_sfile_,
|
||||
uint *_slevel_, char ***);
|
||||
extern void _db_return_(uint _line_,const char **_sfunc_,const char **_sfile_,
|
||||
uint *_slevel_);
|
||||
extern void _db_pargs_(uint _line_,const char *keyword);
|
||||
extern void _db_doprnt_ _VARARGS((const char *format,...))
|
||||
extern void _db_enter_(const char *_func_, const char *_file_, uint _line_,
|
||||
struct _db_stack_frame_ *_stack_frame_);
|
||||
extern void _db_return_(uint _line_, struct _db_stack_frame_ *_stack_frame_);
|
||||
extern void _db_pargs_(uint _line_,const char *keyword);
|
||||
extern void _db_doprnt_ _VARARGS((const char *format,...))
|
||||
ATTRIBUTE_FORMAT(printf, 1, 2);
|
||||
extern void _db_dump_(uint _line_,const char *keyword,
|
||||
extern void _db_dump_(uint _line_,const char *keyword,
|
||||
const unsigned char *memory, size_t length);
|
||||
extern void _db_end_(void);
|
||||
extern void _db_lock_file_(void);
|
||||
extern void _db_unlock_file_(void);
|
||||
extern FILE *_db_fp_(void);
|
||||
extern void _db_end_(void);
|
||||
extern void _db_lock_file_(void);
|
||||
extern void _db_unlock_file_(void);
|
||||
extern FILE *_db_fp_(void);
|
||||
extern void _db_flush_();
|
||||
extern const char* _db_get_func_(void);
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
||||
#define DBUG_ENTER(a) \
|
||||
const char *_db_func_, *_db_file_; \
|
||||
uint _db_level_; \
|
||||
char **_db_framep_; \
|
||||
Dbug_violation_helper dbug_violation_helper; \
|
||||
_db_enter_ (a, __FILE__, __LINE__, &_db_func_, &_db_file_, \
|
||||
&_db_level_, &_db_framep_)
|
||||
#define DBUG_VIOLATION_HELPER_LEAVE dbug_violation_helper.leave()
|
||||
|
||||
#else /* C */
|
||||
|
||||
#define DBUG_ENTER(a) \
|
||||
const char *_db_func_, *_db_file_; \
|
||||
uint _db_level_; \
|
||||
char **_db_framep_; \
|
||||
_db_enter_ (a, __FILE__, __LINE__, &_db_func_, &_db_file_, \
|
||||
&_db_level_, &_db_framep_)
|
||||
#define DBUG_VIOLATION_HELPER_LEAVE do { } while(0)
|
||||
|
||||
#endif /* C++ */
|
||||
|
||||
#define DBUG_LEAVE \
|
||||
DBUG_VIOLATION_HELPER_LEAVE; \
|
||||
_db_return_ (__LINE__, &_db_func_, &_db_file_, &_db_level_)
|
||||
#define DBUG_ENTER(a) struct _db_stack_frame_ _db_stack_frame_; \
|
||||
_db_enter_ (a,__FILE__,__LINE__,&_db_stack_frame_)
|
||||
#define DBUG_LEAVE _db_return_ (__LINE__, &_db_stack_frame_)
|
||||
#define DBUG_RETURN(a1) do {DBUG_LEAVE; return(a1);} while(0)
|
||||
#define DBUG_VOID_RETURN do {DBUG_LEAVE; return;} while(0)
|
||||
#define DBUG_EXECUTE(keyword,a1) \
|
||||
do {if (_db_keyword_(0, (keyword))) { a1 }} while(0)
|
||||
do {if (_db_keyword_(0, (keyword), 0)) { a1 }} while(0)
|
||||
#define DBUG_EXECUTE_IF(keyword,a1) \
|
||||
do {if (_db_strict_keyword_ (keyword)) { a1 } } while(0)
|
||||
do {if (_db_keyword_(0, (keyword), 1)) { a1 }} while(0)
|
||||
#define DBUG_EVALUATE(keyword,a1,a2) \
|
||||
(_db_keyword_(0,(keyword)) ? (a1) : (a2))
|
||||
(_db_keyword_(0,(keyword), 0) ? (a1) : (a2))
|
||||
#define DBUG_EVALUATE_IF(keyword,a1,a2) \
|
||||
(_db_strict_keyword_((keyword)) ? (a1) : (a2))
|
||||
(_db_keyword_(0,(keyword), 1) ? (a1) : (a2))
|
||||
#define DBUG_PRINT(keyword,arglist) \
|
||||
do {_db_pargs_(__LINE__,keyword); _db_doprnt_ arglist;} while(0)
|
||||
#define DBUG_PUSH(a1) _db_push_ (a1)
|
||||
#define DBUG_POP() _db_pop_ ()
|
||||
#define DBUG_SET(a1) _db_set_ (0, (a1))
|
||||
#define DBUG_SET(a1) _db_set_ (a1)
|
||||
#define DBUG_SET_INITIAL(a1) _db_set_init_ (a1)
|
||||
#define DBUG_PROCESS(a1) _db_process_(a1)
|
||||
#define DBUG_FILE _db_fp_()
|
||||
@ -125,54 +86,66 @@ extern const char* _db_get_func_(void);
|
||||
#define DBUG_ASSERT(A) assert(A)
|
||||
#define DBUG_EXPLAIN(buf,len) _db_explain_(0, (buf),(len))
|
||||
#define DBUG_EXPLAIN_INITIAL(buf,len) _db_explain_init_((buf),(len))
|
||||
#define IF_DBUG(A) A
|
||||
#define _DBUG_MAX_FUNC_NAME_ 255
|
||||
#define DEBUGGER_OFF do { _dbug_on_= 0; } while(0)
|
||||
#define DEBUGGER_ON do { _dbug_on_= 1; } while(0)
|
||||
#ifndef __WIN__
|
||||
#define DBUG_ABORT() (_db_flush_(), abort())
|
||||
#else
|
||||
/*
|
||||
Avoid popup with abort/retry/ignore buttons. When BUG#31745 is fixed we can
|
||||
call abort() instead of _exit(3) (now it would cause a "test signal" popup).
|
||||
*/
|
||||
#include <crtdbg.h>
|
||||
#define DBUG_ABORT() (_db_flush_(),\
|
||||
(void)_CrtSetReportMode(_CRT_ERROR, _CRTDBG_MODE_FILE),\
|
||||
(void)_CrtSetReportFile(_CRT_ERROR, _CRTDBG_FILE_STDERR),\
|
||||
_exit(3))
|
||||
#endif
|
||||
#define DBUG_CHECK_CRASH(func, op) \
|
||||
do { \
|
||||
if (_db_keywords_((func), (op))) \
|
||||
{ abort(); } \
|
||||
} while (0)
|
||||
do { char _dbuf_[255]; strxnmov(_dbuf_, sizeof(_dbuf_)-1, (func), (op)); \
|
||||
DBUG_EXECUTE_IF(_dbuf_, DBUG_ABORT()); } while(0)
|
||||
#define DBUG_CRASH_ENTER(func) \
|
||||
DBUG_ENTER(func); DBUG_CHECK_CRASH(func, "_crash_enter")
|
||||
#define DBUG_CRASH_RETURN(val) \
|
||||
do {DBUG_CHECK_CRASH(_db_get_func_(), "_crash_return"); \
|
||||
DBUG_RETURN(val);} while(0)
|
||||
DBUG_CHECK_CRASH(_db_get_func_(), "_crash_return")
|
||||
#define DBUG_CRASH_VOID_RETURN \
|
||||
do {DBUG_CHECK_CRASH (_db_get_func_(), "_crash_return"); \
|
||||
DBUG_VOID_RETURN;} while(0)
|
||||
#else /* No debugger */
|
||||
DBUG_CHECK_CRASH (_db_get_func_(), "_crash_return")
|
||||
|
||||
#else /* No debugger */
|
||||
|
||||
#define DBUG_ENTER(a1)
|
||||
#define DBUG_LEAVE
|
||||
#define DBUG_VIOLATION_HELPER_LEAVE
|
||||
#define DBUG_RETURN(a1) do { return(a1); } while(0)
|
||||
#define DBUG_VOID_RETURN do { return; } while(0)
|
||||
#define DBUG_EXECUTE(keyword,a1) do { } while(0)
|
||||
#define DBUG_EXECUTE_IF(keyword,a1) do { } while(0)
|
||||
#define DBUG_RETURN(a1) do { return(a1); } while(0)
|
||||
#define DBUG_VOID_RETURN do { return; } while(0)
|
||||
#define DBUG_EXECUTE(keyword,a1) do { } while(0)
|
||||
#define DBUG_EXECUTE_IF(keyword,a1) do { } while(0)
|
||||
#define DBUG_EVALUATE(keyword,a1,a2) (a2)
|
||||
#define DBUG_EVALUATE_IF(keyword,a1,a2) (a2)
|
||||
#define DBUG_PRINT(keyword,arglist) do { } while(0)
|
||||
#define DBUG_PUSH(a1)
|
||||
#define DBUG_SET(a1) do { } while(0)
|
||||
#define DBUG_SET_INITIAL(a1) do { } while(0)
|
||||
#define DBUG_POP()
|
||||
#define DBUG_PROCESS(a1)
|
||||
#define DBUG_PRINT(keyword,arglist) do { } while(0)
|
||||
#define DBUG_PUSH(a1) do { } while(0)
|
||||
#define DBUG_SET(a1) do { } while(0)
|
||||
#define DBUG_SET_INITIAL(a1) do { } while(0)
|
||||
#define DBUG_POP() do { } while(0)
|
||||
#define DBUG_PROCESS(a1) do { } while(0)
|
||||
#define DBUG_SETJMP(a1) setjmp(a1)
|
||||
#define DBUG_LONGJMP(a1) longjmp(a1)
|
||||
#define DBUG_DUMP(keyword,a1,a2) do { } while(0)
|
||||
#define DBUG_END()
|
||||
#define DBUG_ASSERT(A) do { } while(0)
|
||||
#define DBUG_LOCK_FILE
|
||||
#define DBUG_DUMP(keyword,a1,a2) do { } while(0)
|
||||
#define DBUG_END() do { } while(0)
|
||||
#define DBUG_ASSERT(A) do { } while(0)
|
||||
#define DBUG_LOCK_FILE do { } while(0)
|
||||
#define DBUG_FILE (stderr)
|
||||
#define DBUG_UNLOCK_FILE
|
||||
#define DBUG_UNLOCK_FILE do { } while(0)
|
||||
#define DBUG_EXPLAIN(buf,len)
|
||||
#define DBUG_EXPLAIN_INITIAL(buf,len)
|
||||
#define IF_DBUG(A)
|
||||
#define DEBUGGER_OFF do { } while(0)
|
||||
#define DEBUGGER_ON do { } while(0)
|
||||
#define DBUG_ABORT() abort()
|
||||
#define DBUG_CRASH_ENTER(func)
|
||||
#define DBUG_CRASH_RETURN(val) do { return(val); } while(0)
|
||||
#define DBUG_CRASH_VOID_RETURN do { return; } while(0)
|
||||
#define DBUG_CRASH_RETURN(val) do { return(val); } while(0)
|
||||
#define DBUG_CRASH_VOID_RETURN do { return; } while(0)
|
||||
|
||||
#endif
|
||||
#ifdef __cplusplus
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
|
@ -649,8 +649,6 @@ C_MODE_END
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#include <my_dbug.h>
|
||||
|
||||
#define MIN_ARRAY_SIZE 0 /* Zero or One. Gcc allows zero*/
|
||||
#define ASCII_BITS_USED 8 /* Bit char used */
|
||||
#define NEAR_F /* No near function handling */
|
||||
@ -1177,6 +1175,8 @@ typedef char bool; /* Ordinary boolean values 0 1 */
|
||||
#define reg16 register
|
||||
#endif
|
||||
|
||||
#include <my_dbug.h>
|
||||
|
||||
/*
|
||||
Sometimes we want to make sure that the variable is not put into
|
||||
a register in debugging mode so we can see its value in the core
|
||||
|
@ -670,6 +670,7 @@ struct st_my_thread_var
|
||||
};
|
||||
|
||||
extern struct st_my_thread_var *_my_thread_var(void) __attribute__ ((const));
|
||||
extern void **my_thread_var_dbug();
|
||||
extern uint my_thread_end_wait_time;
|
||||
#define my_thread_var (_my_thread_var())
|
||||
#define my_errno my_thread_var->thr_errno
|
||||
|
@ -683,6 +683,8 @@ extern void my_error _VARARGS((int nr,myf MyFlags, ...));
|
||||
extern void my_printf_error _VARARGS((uint my_err, const char *format,
|
||||
myf MyFlags, ...))
|
||||
ATTRIBUTE_FORMAT(printf, 2, 4);
|
||||
extern void my_printv_error(uint error, const char *format, myf MyFlags,
|
||||
va_list ap);
|
||||
extern int my_error_register(const char** (*get_errmsgs) (),
|
||||
int first, int last);
|
||||
extern const char **my_error_unregister(int first, int last);
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* Copyright (C) 2005 MySQL AB
|
||||
/* Copyright (C) 2005 MySQL AB, 2009 Sun Microsystems, Inc.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
@ -16,12 +16,6 @@
|
||||
#ifndef _my_plugin_h
|
||||
#define _my_plugin_h
|
||||
|
||||
/* size_t */
|
||||
#include <stdlib.h>
|
||||
|
||||
typedef struct st_mysql MYSQL;
|
||||
|
||||
|
||||
/*
|
||||
On Windows, exports from DLL need to be declared
|
||||
*/
|
||||
@ -39,15 +33,7 @@ class Item;
|
||||
#define MYSQL_THD void*
|
||||
#endif
|
||||
|
||||
#ifndef _m_string_h
|
||||
/* This definition must match the one given in m_string.h */
|
||||
struct st_mysql_lex_string
|
||||
{
|
||||
char *str;
|
||||
unsigned int length;
|
||||
};
|
||||
#endif /* _m_string_h */
|
||||
typedef struct st_mysql_lex_string MYSQL_LEX_STRING;
|
||||
#include <mysql/services.h>
|
||||
|
||||
#define MYSQL_XIDDATASIZE 128
|
||||
/**
|
||||
@ -70,7 +56,7 @@ typedef struct st_mysql_xid MYSQL_XID;
|
||||
Plugin API. Common for all plugin types.
|
||||
*/
|
||||
|
||||
#define MYSQL_PLUGIN_INTERFACE_VERSION 0x0100
|
||||
#define MYSQL_PLUGIN_INTERFACE_VERSION 0x0101
|
||||
|
||||
/*
|
||||
The allowable types of plugins
|
||||
@ -126,7 +112,8 @@ enum enum_mysql_show_type
|
||||
{
|
||||
SHOW_UNDEF, SHOW_BOOL, SHOW_INT, SHOW_LONG,
|
||||
SHOW_LONGLONG, SHOW_CHAR, SHOW_CHAR_PTR,
|
||||
SHOW_ARRAY, SHOW_FUNC, SHOW_DOUBLE
|
||||
SHOW_ARRAY, SHOW_FUNC, SHOW_DOUBLE,
|
||||
SHOW_always_last
|
||||
};
|
||||
|
||||
struct st_mysql_show_var {
|
||||
@ -750,54 +737,6 @@ int thd_killed(const MYSQL_THD thd);
|
||||
*/
|
||||
unsigned long thd_get_thread_id(const MYSQL_THD thd);
|
||||
|
||||
|
||||
/**
|
||||
Allocate memory in the connection's local memory pool
|
||||
|
||||
@details
|
||||
When properly used in place of @c my_malloc(), this can significantly
|
||||
improve concurrency. Don't use this or related functions to allocate
|
||||
large chunks of memory. Use for temporary storage only. The memory
|
||||
will be freed automatically at the end of the statement; no explicit
|
||||
code is required to prevent memory leaks.
|
||||
|
||||
@see alloc_root()
|
||||
*/
|
||||
void *thd_alloc(MYSQL_THD thd, unsigned int size);
|
||||
/**
|
||||
@see thd_alloc()
|
||||
*/
|
||||
void *thd_calloc(MYSQL_THD thd, unsigned int size);
|
||||
/**
|
||||
@see thd_alloc()
|
||||
*/
|
||||
char *thd_strdup(MYSQL_THD thd, const char *str);
|
||||
/**
|
||||
@see thd_alloc()
|
||||
*/
|
||||
char *thd_strmake(MYSQL_THD thd, const char *str, unsigned int size);
|
||||
/**
|
||||
@see thd_alloc()
|
||||
*/
|
||||
void *thd_memdup(MYSQL_THD thd, const void* str, unsigned int size);
|
||||
|
||||
/**
|
||||
Create a LEX_STRING in this connection's local memory pool
|
||||
|
||||
@param thd user thread connection handle
|
||||
@param lex_str pointer to LEX_STRING object to be initialized
|
||||
@param str initializer to be copied into lex_str
|
||||
@param size length of str, in bytes
|
||||
@param allocate_lex_string flag: if TRUE, allocate new LEX_STRING object,
|
||||
instead of using lex_str value
|
||||
@return NULL on failure, or pointer to the LEX_STRING object
|
||||
|
||||
@see thd_alloc()
|
||||
*/
|
||||
MYSQL_LEX_STRING *thd_make_lex_string(MYSQL_THD thd, MYSQL_LEX_STRING *lex_str,
|
||||
const char *str, unsigned int size,
|
||||
int allocate_lex_string);
|
||||
|
||||
/**
|
||||
Get the XID for this connection's transaction
|
||||
|
||||
@ -818,64 +757,6 @@ void mysql_query_cache_invalidate4(MYSQL_THD thd,
|
||||
const char *key, unsigned int key_length,
|
||||
int using_trx);
|
||||
|
||||
/**
|
||||
Get the value of user variable as an integer.
|
||||
|
||||
This function will return the value of variable @a name as an
|
||||
integer. If the original value of the variable is not an integer,
|
||||
the value will be converted into an integer.
|
||||
|
||||
@param name user variable name
|
||||
@param value pointer to return the value
|
||||
@param null_value if not NULL, the function will set it to true if
|
||||
the value of variable is null, set to false if not
|
||||
|
||||
@retval 0 Success
|
||||
@retval 1 Variable not found
|
||||
*/
|
||||
int get_user_var_int(const char *name,
|
||||
long long int *value, int *null_value);
|
||||
|
||||
/**
|
||||
Get the value of user variable as a double precision float number.
|
||||
|
||||
This function will return the value of variable @a name as real
|
||||
number. If the original value of the variable is not a real number,
|
||||
the value will be converted into a real number.
|
||||
|
||||
@param name user variable name
|
||||
@param value pointer to return the value
|
||||
@param null_value if not NULL, the function will set it to true if
|
||||
the value of variable is null, set to false if not
|
||||
|
||||
@retval 0 Success
|
||||
@retval 1 Variable not found
|
||||
*/
|
||||
int get_user_var_real(const char *name,
|
||||
double *value, int *null_value);
|
||||
|
||||
/**
|
||||
Get the value of user variable as a string.
|
||||
|
||||
This function will return the value of variable @a name as
|
||||
string. If the original value of the variable is not a string,
|
||||
the value will be converted into a string.
|
||||
|
||||
@param name user variable name
|
||||
@param value pointer to the value buffer
|
||||
@param len length of the value buffer
|
||||
@param precision precision of the value if it is a float number
|
||||
@param null_value if not NULL, the function will set it to true if
|
||||
the value of variable is null, set to false if not
|
||||
|
||||
@retval 0 Success
|
||||
@retval 1 Variable not found
|
||||
*/
|
||||
int get_user_var_str(const char *name,
|
||||
char *value, unsigned long len,
|
||||
unsigned int precision, int *null_value);
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
@ -1,11 +1,38 @@
|
||||
#include <mysql/services.h>
|
||||
#include <mysql/service_my_snprintf.h>
|
||||
#include <stdarg.h>
|
||||
#include <stdlib.h>
|
||||
extern struct my_snprintf_service_st {
|
||||
size_t (*my_snprintf_type)(char*, size_t, const char*, ...);
|
||||
size_t (*my_vsnprintf_type)(char *, size_t, const char*, va_list);
|
||||
} *my_snprintf_service;
|
||||
size_t my_snprintf(char* to, size_t n, const char* fmt, ...);
|
||||
size_t my_vsnprintf(char *to, size_t n, const char* fmt, va_list ap);
|
||||
#include <mysql/service_thd_alloc.h>
|
||||
#include <stdlib.h>
|
||||
typedef struct st_mysql MYSQL;
|
||||
struct st_mysql_lex_string
|
||||
{
|
||||
char *str;
|
||||
unsigned int length;
|
||||
size_t length;
|
||||
};
|
||||
typedef struct st_mysql_lex_string MYSQL_LEX_STRING;
|
||||
extern struct thd_alloc_service_st {
|
||||
void *(*thd_alloc_func)(void*, unsigned int);
|
||||
void *(*thd_calloc_func)(void*, unsigned int);
|
||||
char *(*thd_strdup_func)(void*, const char *);
|
||||
char *(*thd_strmake_func)(void*, const char *, unsigned int);
|
||||
void *(*thd_memdup_func)(void*, const void*, unsigned int);
|
||||
MYSQL_LEX_STRING *(*thd_make_lex_string_func)(void*, MYSQL_LEX_STRING *,
|
||||
const char *, unsigned int, int);
|
||||
} *thd_alloc_service;
|
||||
void *thd_alloc(void* thd, unsigned int size);
|
||||
void *thd_calloc(void* thd, unsigned int size);
|
||||
char *thd_strdup(void* thd, const char *str);
|
||||
char *thd_strmake(void* thd, const char *str, unsigned int size);
|
||||
void *thd_memdup(void* thd, const void* str, unsigned int size);
|
||||
MYSQL_LEX_STRING *thd_make_lex_string(void* thd, MYSQL_LEX_STRING *lex_str,
|
||||
const char *str, unsigned int size,
|
||||
int allocate_lex_string);
|
||||
struct st_mysql_xid {
|
||||
long formatID;
|
||||
long gtrid_length;
|
||||
@ -17,7 +44,8 @@ enum enum_mysql_show_type
|
||||
{
|
||||
SHOW_UNDEF, SHOW_BOOL, SHOW_INT, SHOW_LONG,
|
||||
SHOW_LONGLONG, SHOW_CHAR, SHOW_CHAR_PTR,
|
||||
SHOW_ARRAY, SHOW_FUNC, SHOW_DOUBLE
|
||||
SHOW_ARRAY, SHOW_FUNC, SHOW_DOUBLE,
|
||||
SHOW_always_last
|
||||
};
|
||||
struct st_mysql_show_var {
|
||||
const char *name;
|
||||
@ -107,9 +135,9 @@ struct st_mysql_information_schema
|
||||
{
|
||||
int interface_version;
|
||||
};
|
||||
struct Mysql_replication {
|
||||
int interface_version;
|
||||
};
|
||||
struct Mysql_replication {
|
||||
int interface_version;
|
||||
};
|
||||
struct st_mysql_value
|
||||
{
|
||||
int (*value_type)(struct st_mysql_value *);
|
||||
@ -130,22 +158,7 @@ void thd_inc_row_count(void* thd);
|
||||
int mysql_tmpfile(const char *prefix);
|
||||
int thd_killed(const void* thd);
|
||||
unsigned long thd_get_thread_id(const void* thd);
|
||||
void *thd_alloc(void* thd, unsigned int size);
|
||||
void *thd_calloc(void* thd, unsigned int size);
|
||||
char *thd_strdup(void* thd, const char *str);
|
||||
char *thd_strmake(void* thd, const char *str, unsigned int size);
|
||||
void *thd_memdup(void* thd, const void* str, unsigned int size);
|
||||
MYSQL_LEX_STRING *thd_make_lex_string(void* thd, MYSQL_LEX_STRING *lex_str,
|
||||
const char *str, unsigned int size,
|
||||
int allocate_lex_string);
|
||||
void thd_get_xid(const void* thd, MYSQL_XID *xid);
|
||||
void mysql_query_cache_invalidate4(void* thd,
|
||||
const char *key, unsigned int key_length,
|
||||
int using_trx);
|
||||
int get_user_var_int(const char *name,
|
||||
long long int *value, int *null_value);
|
||||
int get_user_var_real(const char *name,
|
||||
double *value, int *null_value);
|
||||
int get_user_var_str(const char *name,
|
||||
char *value, unsigned long len,
|
||||
unsigned int precision, int *null_value);
|
||||
|
98
include/mysql/service_my_snprintf.h
Normal file
98
include/mysql/service_my_snprintf.h
Normal file
@ -0,0 +1,98 @@
|
||||
#ifndef MYSQL_SERVICE_MY_SNPRINTF_INCLUDED
|
||||
/* Copyright (C) 2009 Sun Microsystems, Inc.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; version 2 of the License.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
|
||||
|
||||
/**
|
||||
@file
|
||||
my_snprintf service
|
||||
|
||||
Portable and limited vsnprintf() implementation.
|
||||
|
||||
This is a portable, limited vsnprintf() implementation, with some
|
||||
extra features. "Portable" means that it'll produce identical result
|
||||
on all platforms (for example, on Windows and Linux system printf %e
|
||||
formats the exponent differently, on different systems %p either
|
||||
prints leading 0x or not, %s may accept null pointer or crash on
|
||||
it). "Limited" means that it does not support all the C89 features.
|
||||
But it supports few extensions, not in any standard.
|
||||
|
||||
my_vsnprintf(to, n, fmt, ap)
|
||||
|
||||
@param[out] to A buffer to store the result in
|
||||
@param[in] n Store up to n-1 characters, followed by an end 0
|
||||
@param[in] fmt printf-like format string
|
||||
@param[in] ap Arguments
|
||||
|
||||
@return a number of bytes written to a buffer *excluding* terminating '\0'
|
||||
|
||||
@post
|
||||
The syntax of a format string is generally the same:
|
||||
% <flag> <width> <precision> <length modifier> <format>
|
||||
where everithing but the format is optional.
|
||||
|
||||
Three one-character flags are recognized:
|
||||
'0' has the standard zero-padding semantics;
|
||||
'-' is parsed, but silently ignored;
|
||||
'`' (backtick) is only supported for strings (%s) and means that the
|
||||
string will be quoted according to MySQL identifier quoting rules.
|
||||
|
||||
Both <width> and <precision> can be specified as numbers or '*'.
|
||||
|
||||
<length modifier> can be 'l', 'll', or 'z'.
|
||||
|
||||
Supported formats are 's' (null pointer is accepted, printed as
|
||||
"(null)"), 'b' (extension, see below), 'c', 'd', 'u', 'x',
|
||||
'X', 'p' (works as 0x%x).
|
||||
|
||||
Standard syntax for positional arguments $n is supported.
|
||||
|
||||
Extensions:
|
||||
|
||||
Flag '`' (backtick): see above.
|
||||
|
||||
Format 'b': binary buffer, prints exactly <precision> bytes from the
|
||||
argument, without stopping at '\0'.
|
||||
*/
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include <stdarg.h>
|
||||
#include <stdlib.h>
|
||||
extern struct my_snprintf_service_st {
|
||||
size_t (*my_snprintf_type)(char*, size_t, const char*, ...);
|
||||
size_t (*my_vsnprintf_type)(char *, size_t, const char*, va_list);
|
||||
} *my_snprintf_service;
|
||||
|
||||
#ifdef MYSQL_DYNAMIC_PLUGIN
|
||||
|
||||
#define my_vsnprintf my_snprintf_service->my_vsnprintf_type
|
||||
#define my_snprintf my_snprintf_service->my_snprintf_type
|
||||
|
||||
#else
|
||||
|
||||
size_t my_snprintf(char* to, size_t n, const char* fmt, ...);
|
||||
size_t my_vsnprintf(char *to, size_t n, const char* fmt, va_list ap);
|
||||
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#define MYSQL_SERVICE_MY_SNPRINTF_INCLUDED
|
||||
#endif
|
||||
|
128
include/mysql/service_thd_alloc.h
Normal file
128
include/mysql/service_thd_alloc.h
Normal file
@ -0,0 +1,128 @@
|
||||
#ifndef MYSQL_SERVICE_THD_ALLOC_INCLUDED
|
||||
/* Copyright (C) 2009 Sun Microsystems, Inc.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; version 2 of the License.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
|
||||
|
||||
/**
|
||||
@file
|
||||
This service provdes functions to allocate memory in a connection local
|
||||
memory pool. The memory allocated there will be automatically freed at the
|
||||
end of the statement, don't use it for allocations that should live longer
|
||||
than that. For short living allocations this is more efficient than
|
||||
using my_malloc and friends, and automatic "garbage collection" allows not
|
||||
to think about memory leaks.
|
||||
|
||||
The pool is best for small to medium objects, don't use it for large
|
||||
allocations - they are better served with my_malloc.
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
struct st_mysql_lex_string
|
||||
{
|
||||
char *str;
|
||||
size_t length;
|
||||
};
|
||||
typedef struct st_mysql_lex_string MYSQL_LEX_STRING;
|
||||
|
||||
extern struct thd_alloc_service_st {
|
||||
void *(*thd_alloc_func)(MYSQL_THD, unsigned int);
|
||||
void *(*thd_calloc_func)(MYSQL_THD, unsigned int);
|
||||
char *(*thd_strdup_func)(MYSQL_THD, const char *);
|
||||
char *(*thd_strmake_func)(MYSQL_THD, const char *, unsigned int);
|
||||
void *(*thd_memdup_func)(MYSQL_THD, const void*, unsigned int);
|
||||
MYSQL_LEX_STRING *(*thd_make_lex_string_func)(MYSQL_THD, MYSQL_LEX_STRING *,
|
||||
const char *, unsigned int, int);
|
||||
} *thd_alloc_service;
|
||||
|
||||
#ifdef MYSQL_DYNAMIC_PLUGIN
|
||||
|
||||
#define thd_alloc(thd,size) (thd_alloc_service->thd_alloc_func((thd), (size)))
|
||||
|
||||
#define thd_calloc(thd,size) (thd_alloc_service->thd_calloc_func((thd), (size)))
|
||||
|
||||
#define thd_strdup(thd,str) (thd_alloc_service->thd_strdup_func((thd), (str)))
|
||||
|
||||
#define thd_strmake(thd,str,size) \
|
||||
(thd_alloc_service->thd_strmake_func((thd), (str), (size)))
|
||||
|
||||
#define thd_memdup(thd,str,size) \
|
||||
(thd_alloc_service->thd_memdup_func((thd), (str), (size)))
|
||||
|
||||
#define thd_make_lex_string(thd, lex_str, str, size, allocate_lex_string) \
|
||||
(thd_alloc_service->thd_make_lex_string_func((thd), (lex_str), (str), \
|
||||
(size), (allocate_lex_string)))
|
||||
|
||||
#else
|
||||
|
||||
/**
|
||||
Allocate memory in the connection's local memory pool
|
||||
|
||||
@details
|
||||
When properly used in place of @c my_malloc(), this can significantly
|
||||
improve concurrency. Don't use this or related functions to allocate
|
||||
large chunks of memory. Use for temporary storage only. The memory
|
||||
will be freed automatically at the end of the statement; no explicit
|
||||
code is required to prevent memory leaks.
|
||||
|
||||
@see alloc_root()
|
||||
*/
|
||||
void *thd_alloc(MYSQL_THD thd, unsigned int size);
|
||||
/**
|
||||
@see thd_alloc()
|
||||
*/
|
||||
void *thd_calloc(MYSQL_THD thd, unsigned int size);
|
||||
/**
|
||||
@see thd_alloc()
|
||||
*/
|
||||
char *thd_strdup(MYSQL_THD thd, const char *str);
|
||||
/**
|
||||
@see thd_alloc()
|
||||
*/
|
||||
char *thd_strmake(MYSQL_THD thd, const char *str, unsigned int size);
|
||||
/**
|
||||
@see thd_alloc()
|
||||
*/
|
||||
void *thd_memdup(MYSQL_THD thd, const void* str, unsigned int size);
|
||||
|
||||
/**
|
||||
Create a LEX_STRING in this connection's local memory pool
|
||||
|
||||
@param thd user thread connection handle
|
||||
@param lex_str pointer to LEX_STRING object to be initialized
|
||||
@param str initializer to be copied into lex_str
|
||||
@param size length of str, in bytes
|
||||
@param allocate_lex_string flag: if TRUE, allocate new LEX_STRING object,
|
||||
instead of using lex_str value
|
||||
@return NULL on failure, or pointer to the LEX_STRING object
|
||||
|
||||
@see thd_alloc()
|
||||
*/
|
||||
MYSQL_LEX_STRING *thd_make_lex_string(MYSQL_THD thd, MYSQL_LEX_STRING *lex_str,
|
||||
const char *str, unsigned int size,
|
||||
int allocate_lex_string);
|
||||
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#define MYSQL_SERVICE_THD_ALLOC_INCLUDED
|
||||
#endif
|
||||
|
30
include/mysql/services.h
Normal file
30
include/mysql/services.h
Normal file
@ -0,0 +1,30 @@
|
||||
#ifndef MYSQL_SERVICES_INCLUDED
|
||||
/* Copyright (C) 2009 Sun Microsystems, Inc.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; version 2 of the License.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include <mysql/service_my_snprintf.h>
|
||||
#include <mysql/service_thd_alloc.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#define MYSQL_SERVICES_INCLUDED
|
||||
#endif
|
||||
|
24
include/service_versions.h
Normal file
24
include/service_versions.h
Normal file
@ -0,0 +1,24 @@
|
||||
/* Copyright (C) 2009 Sun Microsystems, Inc.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; version 2 of the License.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
|
||||
|
||||
#ifdef _WIN32
|
||||
#define SERVICE_VERSION __declspec(dllexport) void *
|
||||
#else
|
||||
#define SERVICE_VERSION void *
|
||||
#endif
|
||||
|
||||
#define VERSION_my_snprintf 0x0100
|
||||
#define VERSION_thd_alloc 0x0100
|
||||
|
@ -131,7 +131,7 @@ int STDCALL mysql_server_init(int argc __attribute__((unused)),
|
||||
mysql_port = MYSQL_PORT;
|
||||
#ifndef MSDOS
|
||||
{
|
||||
struct servent *serv_ptr;
|
||||
struct servent *serv_ptr __attribute__((unused));
|
||||
char *env;
|
||||
|
||||
/*
|
||||
|
20
libservices/CMakeLists.txt
Normal file
20
libservices/CMakeLists.txt
Normal file
@ -0,0 +1,20 @@
|
||||
# Copyright (C) 2006 MySQL AB
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation; version 2 of the License.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, write to the Free Software
|
||||
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
|
||||
INCLUDE_DIRECTORIES(${CMAKE_SOURCE_DIR}/include)
|
||||
|
||||
SET(MYSQLSERVICES_SOURCES my_snprintf_service.c thd_alloc_service.c)
|
||||
|
||||
ADD_LIBRARY(mysqlservices ${MYSQLSERVICES_SOURCES})
|
100
libservices/HOWTO
Normal file
100
libservices/HOWTO
Normal file
@ -0,0 +1,100 @@
|
||||
How to create a new service
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
A "service" is a set of C functions in a structure that a
|
||||
service dynamic linker uses when a dynamic plugin is loaded.
|
||||
|
||||
If you want to export C++ class you need to provide an
|
||||
extern "C" function that will create a new instance of your class,
|
||||
and put it in a service.
|
||||
|
||||
Data structures are not part of the service structure, but they are part
|
||||
of the API you create and usually need to be declared in the same
|
||||
service_*.h file.
|
||||
|
||||
To turn a set of functions (foo_func1, foo_func2)
|
||||
into a service "foo" you need to
|
||||
|
||||
1. create a new file include/mysql/service_foo.h
|
||||
|
||||
2. the template is
|
||||
==================================================================
|
||||
#ifndef MYSQL_SERVICE_FOO_INCLUDED
|
||||
/* standard GPL header */
|
||||
|
||||
/**
|
||||
@file
|
||||
*exhaustive* description of the interface you provide.
|
||||
This file is the main user documentation of the new service
|
||||
*/
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
extern struct foo_service_st {
|
||||
int (*foo_func1_type)(...); /* fix the prototype as appropriate */
|
||||
void (*foo_func2_type)(...); /* fix the prototype as appropriate */
|
||||
} *foo_service;
|
||||
|
||||
#ifdef MYSQL_DYNAMIC_PLUGIN
|
||||
|
||||
#define foo_func1(...) foo_service->foo_func1_type(...)
|
||||
#define foo_func2(...) foo_service->foo_func2_type(...)
|
||||
|
||||
#else
|
||||
|
||||
int foo_func1_type(...); /* fix the prototype as appropriate */
|
||||
void foo_func2_type(...); /* fix the prototype as appropriate */
|
||||
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#define MYSQL_SERVICE_FOO_INCLUDED
|
||||
#endif
|
||||
==================================================================
|
||||
|
||||
the service_foo.h file should be self-contained, if it needs system headers -
|
||||
include them in it, e.g. if you use size_t - #include <stdlib.h>
|
||||
|
||||
it should also declare all the accompanying data structures, as necessary
|
||||
(e.g. thd_alloc_service declares MYSQL_LEX_STRING).
|
||||
|
||||
3. add the new file to include/Makefile.am (pkginclude_HEADERS)
|
||||
4. add the new file to include/mysql/services.h
|
||||
5. increase the minor plugin ABI version in include/mysql/plugin.h
|
||||
(MYSQL_PLUGIN_INTERFACE_VERSION = MYSQL_PLUGIN_INTERFACE_VERSION+1)
|
||||
6. add the version of your service to include/service_versions.h:
|
||||
==================================================================
|
||||
#define VERSION_foo 0x0100
|
||||
==================================================================
|
||||
|
||||
7. create a new file libservices/foo_service.h using the following template:
|
||||
==================================================================
|
||||
/* GPL header */
|
||||
#include <service_versions.h>
|
||||
SERVICE_VERSION *foo_service= (void*)VERSION_foo;
|
||||
==================================================================
|
||||
|
||||
8. add the new file to libservices/CMakeLists.txt (MYSQLSERVICES_SOURCES)
|
||||
9. add the new file to libservices/Makefile.am (libmysqlservices_a_SOURCES)
|
||||
10. and finally, register your service for dynamic linking in
|
||||
sql/sql_plugin_services.h
|
||||
10.1 fill in the service structure:
|
||||
==================================================================
|
||||
static struct foo_service_st foo_handler = {
|
||||
foo_func1,
|
||||
foo_func2
|
||||
}
|
||||
==================================================================
|
||||
|
||||
10.2 and add it to the list of services
|
||||
|
||||
==================================================================
|
||||
{ "foo_service", VERSION_foo, &foo_handler }
|
||||
==================================================================
|
||||
|
||||
that's all.
|
||||
|
19
libservices/Makefile.am
Normal file
19
libservices/Makefile.am
Normal file
@ -0,0 +1,19 @@
|
||||
# Copyright 2009 Sun Microsystems, Inc.
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation; version 2 of the License.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, write to the Free Software
|
||||
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
|
||||
AM_CPPFLAGS = -I$(top_srcdir)/include
|
||||
pkglib_LIBRARIES = libmysqlservices.a
|
||||
libmysqlservices_a_SOURCES = my_snprintf_service.c thd_alloc_service.c
|
||||
EXTRA_DIST = CMakeLists.txt
|
17
libservices/my_snprintf_service.c
Normal file
17
libservices/my_snprintf_service.c
Normal file
@ -0,0 +1,17 @@
|
||||
/* Copyright (C) 2009 Sun Microsystems, Inc.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; version 2 of the License.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
|
||||
|
||||
#include <service_versions.h>
|
||||
SERVICE_VERSION my_snprintf_service= (void*)VERSION_my_snprintf;
|
17
libservices/thd_alloc_service.c
Normal file
17
libservices/thd_alloc_service.c
Normal file
@ -0,0 +1,17 @@
|
||||
/* Copyright (C) 2009 Sun Microsystems, Inc.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; version 2 of the License.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
|
||||
|
||||
#include <service_versions.h>
|
||||
SERVICE_VERSION *thd_alloc_service= (void*)VERSION_thd_alloc;
|
@ -12,6 +12,15 @@ CREATE TABLE t1(a int) ENGINE=EXAMPLE;
|
||||
SELECT * FROM t1;
|
||||
a
|
||||
DROP TABLE t1;
|
||||
set global example_ulong_var=500;
|
||||
set global example_enum_var= e1;
|
||||
show status like 'example%';
|
||||
Variable_name Value
|
||||
example_func_example enum_var is 0, ulong_var is 500, really
|
||||
show variables like 'example%';
|
||||
Variable_name Value
|
||||
example_enum_var e1
|
||||
example_ulong_var 500
|
||||
UNINSTALL PLUGIN example;
|
||||
UNINSTALL PLUGIN EXAMPLE;
|
||||
ERROR 42000: PLUGIN EXAMPLE does not exist
|
||||
|
@ -22,6 +22,12 @@ SELECT * FROM t1;
|
||||
|
||||
DROP TABLE t1;
|
||||
|
||||
# a couple of tests for variables
|
||||
set global example_ulong_var=500;
|
||||
set global example_enum_var= e1;
|
||||
show status like 'example%';
|
||||
show variables like 'example%';
|
||||
|
||||
UNINSTALL PLUGIN example;
|
||||
--error 1305
|
||||
UNINSTALL PLUGIN EXAMPLE;
|
||||
|
@ -125,6 +125,29 @@ void my_printf_error(uint error, const char *format, myf MyFlags, ...)
|
||||
DBUG_VOID_RETURN;
|
||||
}
|
||||
|
||||
/*
|
||||
Error with va_list
|
||||
|
||||
SYNOPSIS
|
||||
my_printv_error()
|
||||
error Errno
|
||||
format Format string
|
||||
MyFlags Flags
|
||||
... variable list
|
||||
*/
|
||||
|
||||
void my_printv_error(uint error, const char *format, myf MyFlags, va_list ap)
|
||||
{
|
||||
char ebuff[ERRMSGSIZE];
|
||||
DBUG_ENTER("my_printv_error");
|
||||
DBUG_PRINT("my", ("nr: %d MyFlags: %d errno: %d format: %s",
|
||||
error, MyFlags, errno, format));
|
||||
|
||||
(void) my_vsnprintf(ebuff, sizeof(ebuff), format, ap);
|
||||
(*error_handler_hook)(error, ebuff, MyFlags);
|
||||
DBUG_VOID_RETURN;
|
||||
}
|
||||
|
||||
/*
|
||||
Give message using error_handler_hook
|
||||
|
||||
|
@ -387,6 +387,15 @@ const char *my_thread_name(void)
|
||||
}
|
||||
return tmp->name;
|
||||
}
|
||||
|
||||
/* Return pointer to DBUG for holding current state */
|
||||
|
||||
extern void **my_thread_var_dbug()
|
||||
{
|
||||
struct st_my_thread_var *tmp=
|
||||
my_pthread_getspecific(struct st_my_thread_var*,THR_KEY_mysys);
|
||||
return tmp && tmp->init ? &tmp->dbug : 0;
|
||||
}
|
||||
#endif /* DBUG_OFF */
|
||||
|
||||
|
||||
|
@ -26,7 +26,8 @@ INCLUDES = -I$(top_srcdir)/include -I$(top_builddir)/include \
|
||||
|
||||
EXTRA_LTLIBRARIES = libdaemon_example.la
|
||||
pkgplugin_LTLIBRARIES = @plugin_daemon_example_shared_target@
|
||||
libdaemon_example_la_LDFLAGS = -module -rpath $(pkgplugindir)
|
||||
libdaemon_example_la_LDFLAGS = -module -rpath $(pkgplugindir) -L$(top_builddir)/libservices -lmysqlservices
|
||||
|
||||
libdaemon_example_la_CXXFLAGS= $(AM_CFLAGS) -DMYSQL_DYNAMIC_PLUGIN
|
||||
libdaemon_example_la_CFLAGS = $(AM_CFLAGS) -DMYSQL_DYNAMIC_PLUGIN
|
||||
libdaemon_example_la_SOURCES = daemon_example.cc
|
||||
|
@ -2479,7 +2479,7 @@ CLI_MYSQL_REAL_CONNECT(MYSQL *mysql,const char *host, const char *user,
|
||||
|
||||
for (i= 0; status && hp->h_addr_list[i]; i++)
|
||||
{
|
||||
IF_DBUG(char ipaddr[18];)
|
||||
char ipaddr[18] __attribute__((unused));
|
||||
memcpy(&sock_addr.sin_addr, hp->h_addr_list[i],
|
||||
min(sizeof(sock_addr.sin_addr), (size_t) hp->h_length));
|
||||
DBUG_PRINT("info",("Trying %s...",
|
||||
|
@ -45,7 +45,7 @@ SET (SQL_SOURCE
|
||||
discover.cc ../libmysql/errmsg.c field.cc field_conv.cc
|
||||
filesort.cc gstream.cc
|
||||
ha_partition.cc
|
||||
handler.cc hash_filo.cc hash_filo.h
|
||||
handler.cc hash_filo.cc hash_filo.h sql_plugin_services.h
|
||||
hostname.cc init.cc item.cc item_buff.cc item_cmpfunc.cc
|
||||
item_create.cc item_func.cc item_geofunc.cc item_row.cc
|
||||
item_strfunc.cc item_subselect.cc item_sum.cc item_timefunc.cc
|
||||
|
@ -82,7 +82,7 @@ mysqld_LDADD = libndb.la \
|
||||
|
||||
noinst_HEADERS = item.h item_func.h item_sum.h item_cmpfunc.h \
|
||||
item_strfunc.h item_timefunc.h \
|
||||
item_xmlfunc.h \
|
||||
item_xmlfunc.h sql_plugin_services.h \
|
||||
item_create.h item_subselect.h item_row.h \
|
||||
mysql_priv.h item_geofunc.h sql_bitmap.h \
|
||||
procedure.h sql_class.h sql_lex.h sql_list.h \
|
||||
|
@ -1701,9 +1701,11 @@ uchar *sys_var_debug_sync::value_ptr(THD *thd,
|
||||
|
||||
static void debug_sync_execute(THD *thd, st_debug_sync_action *action)
|
||||
{
|
||||
IF_DBUG(const char *dsp_name= action->sync_point.c_ptr());
|
||||
IF_DBUG(const char *sig_emit= action->signal.c_ptr());
|
||||
IF_DBUG(const char *sig_wait= action->wait_for.c_ptr());
|
||||
#ifndef DBUG_OFF
|
||||
const char *dsp_name= action->sync_point.c_ptr();
|
||||
const char *sig_emit= action->signal.c_ptr();
|
||||
const char *sig_wait= action->wait_for.c_ptr();
|
||||
#endif
|
||||
DBUG_ENTER("debug_sync_execute");
|
||||
DBUG_ASSERT(thd);
|
||||
DBUG_ASSERT(action);
|
||||
|
@ -6669,9 +6669,8 @@ int Field_string::cmp(const uchar *a_ptr, const uchar *b_ptr)
|
||||
|
||||
void Field_string::sort_string(uchar *to,uint length)
|
||||
{
|
||||
IF_DBUG(uint tmp=) my_strnxfrm(field_charset,
|
||||
to, length,
|
||||
ptr, field_length);
|
||||
uint tmp __attribute__((unused))=
|
||||
my_strnxfrm(field_charset, to, length, ptr, field_length);
|
||||
DBUG_ASSERT(tmp == length);
|
||||
}
|
||||
|
||||
|
@ -4316,7 +4316,7 @@ int ha_ndbcluster::end_bulk_insert()
|
||||
}
|
||||
else
|
||||
{
|
||||
IF_DBUG(int res=) trans->restart();
|
||||
int res __attribute__((unused))= trans->restart();
|
||||
DBUG_ASSERT(res == 0);
|
||||
}
|
||||
}
|
||||
@ -5928,7 +5928,7 @@ int ha_ndbcluster::rename_table(const char *from, const char *to)
|
||||
{
|
||||
DBUG_PRINT("NDB_SHARE", ("%s temporary use_count: %u",
|
||||
share->key, share->use_count));
|
||||
IF_DBUG(int r=) rename_share(share, to);
|
||||
int r __attribute__((unused))= rename_share(share, to);
|
||||
DBUG_ASSERT(r == 0);
|
||||
}
|
||||
#endif
|
||||
@ -5952,7 +5952,7 @@ int ha_ndbcluster::rename_table(const char *from, const char *to)
|
||||
#ifdef HAVE_NDB_BINLOG
|
||||
if (share)
|
||||
{
|
||||
IF_DBUG(int ret=) rename_share(share, from);
|
||||
int ret __attribute__((unused))= rename_share(share, from);
|
||||
DBUG_ASSERT(ret == 0);
|
||||
/* ndb_share reference temporary free */
|
||||
DBUG_PRINT("NDB_SHARE", ("%s temporary free use_count: %u",
|
||||
|
@ -3390,14 +3390,14 @@ ndb_binlog_thread_handle_data_event(Ndb *ndb, NdbEventOperation *pOp,
|
||||
if (share->flags & NSF_BLOB_FLAG)
|
||||
{
|
||||
my_ptrdiff_t ptrdiff= 0;
|
||||
IF_DBUG(int ret =) get_ndb_blobs_value(table, share->ndb_value[0],
|
||||
int ret __attribute__((unused))= get_ndb_blobs_value(table, share->ndb_value[0],
|
||||
blobs_buffer[0],
|
||||
blobs_buffer_size[0],
|
||||
ptrdiff);
|
||||
DBUG_ASSERT(ret == 0);
|
||||
}
|
||||
ndb_unpack_record(table, share->ndb_value[0], &b, table->record[0]);
|
||||
IF_DBUG(int ret=) trans.write_row(originating_server_id,
|
||||
int ret __attribute__((unused))= trans.write_row(originating_server_id,
|
||||
injector::transaction::table(table,
|
||||
TRUE),
|
||||
&b, n_fields, table->record[0]);
|
||||
@ -3429,7 +3429,7 @@ ndb_binlog_thread_handle_data_event(Ndb *ndb, NdbEventOperation *pOp,
|
||||
if (share->flags & NSF_BLOB_FLAG)
|
||||
{
|
||||
my_ptrdiff_t ptrdiff= table->record[n] - table->record[0];
|
||||
IF_DBUG(int ret =) get_ndb_blobs_value(table, share->ndb_value[n],
|
||||
int ret __attribute__((unused))= get_ndb_blobs_value(table, share->ndb_value[n],
|
||||
blobs_buffer[n],
|
||||
blobs_buffer_size[n],
|
||||
ptrdiff);
|
||||
@ -3437,7 +3437,7 @@ ndb_binlog_thread_handle_data_event(Ndb *ndb, NdbEventOperation *pOp,
|
||||
}
|
||||
ndb_unpack_record(table, share->ndb_value[n], &b, table->record[n]);
|
||||
DBUG_EXECUTE("info", print_records(table, table->record[n]););
|
||||
IF_DBUG(int ret =) trans.delete_row(originating_server_id,
|
||||
int ret __attribute__((unused))= trans.delete_row(originating_server_id,
|
||||
injector::transaction::table(table,
|
||||
TRUE),
|
||||
&b, n_fields, table->record[n]);
|
||||
@ -3452,7 +3452,7 @@ ndb_binlog_thread_handle_data_event(Ndb *ndb, NdbEventOperation *pOp,
|
||||
if (share->flags & NSF_BLOB_FLAG)
|
||||
{
|
||||
my_ptrdiff_t ptrdiff= 0;
|
||||
IF_DBUG(int ret =) get_ndb_blobs_value(table, share->ndb_value[0],
|
||||
int ret __attribute__((unused))= get_ndb_blobs_value(table, share->ndb_value[0],
|
||||
blobs_buffer[0],
|
||||
blobs_buffer_size[0],
|
||||
ptrdiff);
|
||||
@ -3480,7 +3480,7 @@ ndb_binlog_thread_handle_data_event(Ndb *ndb, NdbEventOperation *pOp,
|
||||
if (share->flags & NSF_BLOB_FLAG)
|
||||
{
|
||||
my_ptrdiff_t ptrdiff= table->record[1] - table->record[0];
|
||||
IF_DBUG(int ret =) get_ndb_blobs_value(table, share->ndb_value[1],
|
||||
int ret __attribute__((unused))= get_ndb_blobs_value(table, share->ndb_value[1],
|
||||
blobs_buffer[1],
|
||||
blobs_buffer_size[1],
|
||||
ptrdiff);
|
||||
@ -3488,7 +3488,7 @@ ndb_binlog_thread_handle_data_event(Ndb *ndb, NdbEventOperation *pOp,
|
||||
}
|
||||
ndb_unpack_record(table, share->ndb_value[1], &b, table->record[1]);
|
||||
DBUG_EXECUTE("info", print_records(table, table->record[1]););
|
||||
IF_DBUG(int ret =) trans.update_row(originating_server_id,
|
||||
int ret __attribute__((unused))= trans.update_row(originating_server_id,
|
||||
injector::transaction::table(table,
|
||||
TRUE),
|
||||
&b, n_fields,
|
||||
@ -3792,7 +3792,7 @@ restart:
|
||||
{ C_STRING_WITH_LEN("mysqld startup") },
|
||||
{ C_STRING_WITH_LEN("cluster disconnect")}
|
||||
};
|
||||
IF_DBUG(int error=)
|
||||
int error __attribute__((unused))=
|
||||
inj->record_incident(thd, INCIDENT_LOST_EVENTS, msg[incident_id]);
|
||||
DBUG_ASSERT(!error);
|
||||
break;
|
||||
@ -4107,7 +4107,7 @@ restart:
|
||||
DBUG_PRINT("info", ("use_table: %.*s",
|
||||
(int) name.length, name.str));
|
||||
injector::transaction::table tbl(table, TRUE);
|
||||
IF_DBUG(int ret=) trans.use_table(::server_id, tbl);
|
||||
int ret __attribute__((unused))= trans.use_table(::server_id, tbl);
|
||||
DBUG_ASSERT(ret == 0);
|
||||
}
|
||||
}
|
||||
@ -4123,7 +4123,7 @@ restart:
|
||||
(int) name.length, name.str));
|
||||
#endif
|
||||
injector::transaction::table tbl(table, TRUE);
|
||||
IF_DBUG(int ret=) trans.use_table(::server_id, tbl);
|
||||
int ret __attribute__((unused))= trans.use_table(::server_id, tbl);
|
||||
DBUG_ASSERT(ret == 0);
|
||||
|
||||
/*
|
||||
@ -4193,7 +4193,7 @@ restart:
|
||||
else
|
||||
{
|
||||
// set injector_ndb database/schema from table internal name
|
||||
IF_DBUG(int ret=)
|
||||
int ret __attribute__((unused))=
|
||||
i_ndb->setDatabaseAndSchemaName(pOp->getEvent()->getTable());
|
||||
DBUG_ASSERT(ret == 0);
|
||||
ndb_binlog_thread_handle_non_data_event(thd, i_ndb, pOp, row);
|
||||
|
@ -1200,14 +1200,14 @@ Log_event* Log_event::read_log_event(const char* buf, uint event_len,
|
||||
*/
|
||||
if (description_event->event_type_permutation)
|
||||
{
|
||||
IF_DBUG({
|
||||
int new_event_type=
|
||||
description_event->event_type_permutation[event_type];
|
||||
DBUG_PRINT("info",
|
||||
("converting event type %d to %d (%s)",
|
||||
event_type, new_event_type,
|
||||
get_type_str((Log_event_type)new_event_type)));
|
||||
});
|
||||
#ifndef DBUG_OFF
|
||||
int new_event_type=
|
||||
description_event->event_type_permutation[event_type];
|
||||
DBUG_PRINT("info",
|
||||
("converting event type %d to %d (%s)",
|
||||
event_type, new_event_type,
|
||||
get_type_str((Log_event_type)new_event_type)));
|
||||
#endif
|
||||
event_type= description_event->event_type_permutation[event_type];
|
||||
}
|
||||
|
||||
@ -3609,10 +3609,12 @@ Format_description_log_event(uint8 binlog_ver, const char* server_ver)
|
||||
*/
|
||||
if (post_header_len)
|
||||
{
|
||||
#ifndef DBUG_OFF
|
||||
// Allows us to sanity-check that all events initialized their
|
||||
// events (see the end of this 'if' block).
|
||||
IF_DBUG(memset(post_header_len, 255,
|
||||
number_of_event_types*sizeof(uint8)););
|
||||
memset(post_header_len, 255,
|
||||
number_of_event_types*sizeof(uint8));
|
||||
#endif
|
||||
|
||||
/* Note: all event types must explicitly fill in their lengths here. */
|
||||
post_header_len[START_EVENT_V3-1]= START_V3_HEADER_LEN;
|
||||
@ -3666,11 +3668,9 @@ Format_description_log_event(uint8 binlog_ver, const char* server_ver)
|
||||
post_header_len[HEARTBEAT_LOG_EVENT-1]= 0;
|
||||
|
||||
// Sanity-check that all post header lengths are initialized.
|
||||
IF_DBUG({
|
||||
int i;
|
||||
for (i=0; i<number_of_event_types; i++)
|
||||
assert(post_header_len[i] != 255);
|
||||
});
|
||||
int i;
|
||||
for (i=0; i<number_of_event_types; i++)
|
||||
DBUG_ASSERT(post_header_len[i] != 255);
|
||||
}
|
||||
break;
|
||||
|
||||
|
@ -28,6 +28,16 @@
|
||||
|
||||
#ifndef MYSQL_CLIENT
|
||||
|
||||
/*
|
||||
the following #define adds server-only members to enum_mysql_show_type,
|
||||
that is defined in mysql/plugin.h
|
||||
it has to be before mysql/plugin.h is included.
|
||||
*/
|
||||
#define SHOW_always_last SHOW_KEY_CACHE_LONG, \
|
||||
SHOW_KEY_CACHE_LONGLONG, SHOW_LONG_STATUS, SHOW_DOUBLE_STATUS, \
|
||||
SHOW_HAVE, SHOW_MY_BOOL, SHOW_HA_ROWS, SHOW_SYS, \
|
||||
SHOW_LONG_NOFLUSH, SHOW_LONGLONG_STATUS
|
||||
|
||||
#include <my_global.h>
|
||||
#include <mysql_version.h>
|
||||
#include <mysql_embed.h>
|
||||
|
@ -16,6 +16,8 @@
|
||||
#ifndef REPLICATION_H
|
||||
#define REPLICATION_H
|
||||
|
||||
typedef struct st_mysql MYSQL;
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
@ -483,6 +485,64 @@ const char* thd_enter_cond(MYSQL_THD thd, pthread_cond_t *cond,
|
||||
*/
|
||||
void thd_exit_cond(MYSQL_THD thd, const char *old_msg);
|
||||
|
||||
/**
|
||||
Get the value of user variable as an integer.
|
||||
|
||||
This function will return the value of variable @a name as an
|
||||
integer. If the original value of the variable is not an integer,
|
||||
the value will be converted into an integer.
|
||||
|
||||
@param name user variable name
|
||||
@param value pointer to return the value
|
||||
@param null_value if not NULL, the function will set it to true if
|
||||
the value of variable is null, set to false if not
|
||||
|
||||
@retval 0 Success
|
||||
@retval 1 Variable not found
|
||||
*/
|
||||
int get_user_var_int(const char *name,
|
||||
long long int *value, int *null_value);
|
||||
|
||||
/**
|
||||
Get the value of user variable as a double precision float number.
|
||||
|
||||
This function will return the value of variable @a name as real
|
||||
number. If the original value of the variable is not a real number,
|
||||
the value will be converted into a real number.
|
||||
|
||||
@param name user variable name
|
||||
@param value pointer to return the value
|
||||
@param null_value if not NULL, the function will set it to true if
|
||||
the value of variable is null, set to false if not
|
||||
|
||||
@retval 0 Success
|
||||
@retval 1 Variable not found
|
||||
*/
|
||||
int get_user_var_real(const char *name,
|
||||
double *value, int *null_value);
|
||||
|
||||
/**
|
||||
Get the value of user variable as a string.
|
||||
|
||||
This function will return the value of variable @a name as
|
||||
string. If the original value of the variable is not a string,
|
||||
the value will be converted into a string.
|
||||
|
||||
@param name user variable name
|
||||
@param value pointer to the value buffer
|
||||
@param len length of the value buffer
|
||||
@param precision precision of the value if it is a float number
|
||||
@param null_value if not NULL, the function will set it to true if
|
||||
the value of variable is null, set to false if not
|
||||
|
||||
@retval 0 Success
|
||||
@retval 1 Variable not found
|
||||
*/
|
||||
int get_user_var_str(const char *name,
|
||||
char *value, unsigned long len,
|
||||
unsigned int precision, int *null_value);
|
||||
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
@ -583,7 +583,7 @@ terminate_slave_thread(THD *thd,
|
||||
EINVAL: invalid signal number (can't happen)
|
||||
ESRCH: thread already killed (can happen, should be ignored)
|
||||
*/
|
||||
IF_DBUG(int err= ) pthread_kill(thd->real_id, thr_client_alarm);
|
||||
int err __attribute__((unused))= pthread_kill(thd->real_id, thr_client_alarm);
|
||||
DBUG_ASSERT(err != EINVAL);
|
||||
#endif
|
||||
thd->awake(THD::NOT_KILLED);
|
||||
@ -1087,7 +1087,7 @@ static bool check_io_slave_killed(THD *thd, Master_info *mi, const char *info)
|
||||
if (io_slave_killed(thd, mi))
|
||||
{
|
||||
if (info && global_system_variables.log_warnings)
|
||||
sql_print_information(info);
|
||||
sql_print_information("%s", info);
|
||||
return TRUE;
|
||||
}
|
||||
return FALSE;
|
||||
|
@ -274,12 +274,7 @@ const char* thd_enter_cond(MYSQL_THD thd, pthread_cond_t *cond,
|
||||
if (!thd)
|
||||
thd= current_thd;
|
||||
|
||||
const char* old_msg = thd->proc_info;
|
||||
safe_mutex_assert_owner(mutex);
|
||||
thd->mysys_var->current_mutex = mutex;
|
||||
thd->mysys_var->current_cond = cond;
|
||||
thd->proc_info = msg;
|
||||
return old_msg;
|
||||
return thd->enter_cond(cond, mutex, msg);
|
||||
}
|
||||
|
||||
extern "C"
|
||||
@ -288,18 +283,7 @@ void thd_exit_cond(MYSQL_THD thd, const char *old_msg)
|
||||
if (!thd)
|
||||
thd= current_thd;
|
||||
|
||||
/*
|
||||
Putting the mutex unlock in thd_exit_cond() ensures that
|
||||
mysys_var->current_mutex is always unlocked _before_ mysys_var->mutex is
|
||||
locked (if that would not be the case, you'll get a deadlock if someone
|
||||
does a THD::awake() on you).
|
||||
*/
|
||||
pthread_mutex_unlock(thd->mysys_var->current_mutex);
|
||||
pthread_mutex_lock(&thd->mysys_var->mutex);
|
||||
thd->mysys_var->current_mutex = 0;
|
||||
thd->mysys_var->current_cond = 0;
|
||||
thd->proc_info = old_msg;
|
||||
pthread_mutex_unlock(&thd->mysys_var->mutex);
|
||||
thd->exit_cond(old_msg);
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -25,7 +25,6 @@
|
||||
|
||||
#include "log.h"
|
||||
#include "rpl_tblmap.h"
|
||||
#include "replication.h"
|
||||
|
||||
|
||||
class Reprepare_observer;
|
||||
@ -1885,11 +1884,28 @@ public:
|
||||
inline const char* enter_cond(pthread_cond_t *cond, pthread_mutex_t* mutex,
|
||||
const char* msg)
|
||||
{
|
||||
return thd_enter_cond(this, cond, mutex, msg);
|
||||
const char* old_msg = proc_info;
|
||||
safe_mutex_assert_owner(mutex);
|
||||
mysys_var->current_mutex = mutex;
|
||||
mysys_var->current_cond = cond;
|
||||
proc_info = msg;
|
||||
return old_msg;
|
||||
}
|
||||
inline void exit_cond(const char* old_msg)
|
||||
{
|
||||
thd_exit_cond(this, old_msg);
|
||||
/*
|
||||
Putting the mutex unlock in thd->exit_cond() ensures that
|
||||
mysys_var->current_mutex is always unlocked _before_ mysys_var->mutex is
|
||||
locked (if that would not be the case, you'll get a deadlock if someone
|
||||
does a THD::awake() on you).
|
||||
*/
|
||||
pthread_mutex_unlock(mysys_var->current_mutex);
|
||||
pthread_mutex_lock(&mysys_var->mutex);
|
||||
mysys_var->current_mutex = 0;
|
||||
mysys_var->current_cond = 0;
|
||||
proc_info = old_msg;
|
||||
pthread_mutex_unlock(&mysys_var->mutex);
|
||||
return;
|
||||
}
|
||||
inline time_t query_start() { query_start_used=1; return start_time; }
|
||||
inline void set_time()
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* Copyright (C) 2005 MySQL AB
|
||||
/* Copyright (C) 2005 MySQL AB, 2009 Sun Microsystems, Inc.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
@ -99,7 +99,9 @@ static int cur_plugin_info_interface_version[MYSQL_MAX_PLUGIN_TYPE_NUM]=
|
||||
MYSQL_REPLICATION_INTERFACE_VERSION,
|
||||
};
|
||||
|
||||
static bool initialized= 0;
|
||||
/* support for Services */
|
||||
|
||||
#include "sql_plugin_services.h"
|
||||
|
||||
/*
|
||||
A mutex LOCK_plugin must be acquired before accessing the
|
||||
@ -113,6 +115,8 @@ static HASH plugin_hash[MYSQL_MAX_PLUGIN_TYPE_NUM];
|
||||
static bool reap_needed= false;
|
||||
static int plugin_array_version=0;
|
||||
|
||||
static bool initialized= 0;
|
||||
|
||||
/*
|
||||
write-lock on LOCK_system_variables_hash is required before modifying
|
||||
the following variables/structures
|
||||
@ -225,6 +229,22 @@ extern bool throw_bounds_warning(THD *thd, bool fixed, bool unsignd,
|
||||
extern bool check_if_table_exists(THD *thd, TABLE_LIST *table, bool *exists);
|
||||
#endif /* EMBEDDED_LIBRARY */
|
||||
|
||||
static void report_error(int where_to, uint error, ...)
|
||||
{
|
||||
va_list args;
|
||||
if (where_to & REPORT_TO_USER)
|
||||
{
|
||||
va_start(args, error);
|
||||
my_printv_error(error, ER(error), MYF(0), args);
|
||||
va_end(args);
|
||||
}
|
||||
if (where_to & REPORT_TO_LOG)
|
||||
{
|
||||
va_start(args, error);
|
||||
error_log_print(ERROR_LEVEL, ER_DEFAULT(error), args);
|
||||
va_end(args);
|
||||
}
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
Value type thunks, allows the C world to play in the C++ world
|
||||
@ -345,7 +365,7 @@ static st_plugin_dl *plugin_dl_add(const LEX_STRING *dl, int report)
|
||||
{
|
||||
#ifdef HAVE_DLOPEN
|
||||
char dlpath[FN_REFLEN];
|
||||
uint plugin_dir_len, dummy_errors, dlpathlen;
|
||||
uint plugin_dir_len, dummy_errors, dlpathlen, i;
|
||||
struct st_plugin_dl *tmp, plugin_dl;
|
||||
void *sym;
|
||||
DBUG_ENTER("plugin_dl_add");
|
||||
@ -360,10 +380,7 @@ static st_plugin_dl *plugin_dl_add(const LEX_STRING *dl, int report)
|
||||
system_charset_info, 1) ||
|
||||
plugin_dir_len + dl->length + 1 >= FN_REFLEN)
|
||||
{
|
||||
if (report & REPORT_TO_USER)
|
||||
my_error(ER_UDF_NO_PATHS, MYF(0));
|
||||
if (report & REPORT_TO_LOG)
|
||||
sql_print_error("%s", ER_DEFAULT(ER_UDF_NO_PATHS));
|
||||
report_error(report, ER_UDF_NO_PATHS);
|
||||
DBUG_RETURN(0);
|
||||
}
|
||||
/* If this dll is already loaded just increase ref_count. */
|
||||
@ -388,21 +405,14 @@ static st_plugin_dl *plugin_dl_add(const LEX_STRING *dl, int report)
|
||||
if (*errmsg == ':') errmsg++;
|
||||
if (*errmsg == ' ') errmsg++;
|
||||
}
|
||||
if (report & REPORT_TO_USER)
|
||||
my_error(ER_CANT_OPEN_LIBRARY, MYF(0), dlpath, errno, errmsg);
|
||||
if (report & REPORT_TO_LOG)
|
||||
sql_print_error(ER_DEFAULT(ER_CANT_OPEN_LIBRARY), dlpath, errno, errmsg);
|
||||
report_error(report, ER_CANT_OPEN_LIBRARY, dlpath, errno, errmsg);
|
||||
DBUG_RETURN(0);
|
||||
}
|
||||
/* Determine interface version */
|
||||
if (!(sym= dlsym(plugin_dl.handle, plugin_interface_version_sym)))
|
||||
{
|
||||
free_plugin_mem(&plugin_dl);
|
||||
if (report & REPORT_TO_USER)
|
||||
my_error(ER_CANT_FIND_DL_ENTRY, MYF(0), plugin_interface_version_sym);
|
||||
if (report & REPORT_TO_LOG)
|
||||
sql_print_error(ER_DEFAULT(ER_CANT_FIND_DL_ENTRY),
|
||||
plugin_interface_version_sym);
|
||||
report_error(report, ER_CANT_FIND_DL_ENTRY, plugin_interface_version_sym);
|
||||
DBUG_RETURN(0);
|
||||
}
|
||||
plugin_dl.version= *(int *)sym;
|
||||
@ -411,29 +421,42 @@ static st_plugin_dl *plugin_dl_add(const LEX_STRING *dl, int report)
|
||||
(plugin_dl.version >> 8) > (MYSQL_PLUGIN_INTERFACE_VERSION >> 8))
|
||||
{
|
||||
free_plugin_mem(&plugin_dl);
|
||||
if (report & REPORT_TO_USER)
|
||||
my_error(ER_CANT_OPEN_LIBRARY, MYF(0), dlpath, 0,
|
||||
"plugin interface version mismatch");
|
||||
if (report & REPORT_TO_LOG)
|
||||
sql_print_error(ER_DEFAULT(ER_CANT_OPEN_LIBRARY), dlpath, 0,
|
||||
"plugin interface version mismatch");
|
||||
report_error(report, ER_CANT_OPEN_LIBRARY, MYF(0), dlpath, 0,
|
||||
"plugin interface version mismatch");
|
||||
DBUG_RETURN(0);
|
||||
}
|
||||
|
||||
/* link the services in */
|
||||
for (i= 0; i < array_elements(list_of_services); i++)
|
||||
{
|
||||
if ((sym= dlsym(plugin_dl.handle, list_of_services[i].name)))
|
||||
{
|
||||
uint ver= (uint)(intptr)*(void**)sym;
|
||||
if (ver > list_of_services[i].version ||
|
||||
(ver >> 8) < (list_of_services[i].version >> 8))
|
||||
{
|
||||
char buf[MYSQL_ERRMSG_SIZE];
|
||||
my_snprintf(buf, sizeof(buf),
|
||||
"service '%s' interface version mismatch",
|
||||
list_of_services[i].name);
|
||||
report_error(report, ER_CANT_OPEN_LIBRARY, dlpath, 0, buf);
|
||||
DBUG_RETURN(0);
|
||||
}
|
||||
*(void**)sym= list_of_services[i].service;
|
||||
}
|
||||
}
|
||||
|
||||
/* Find plugin declarations */
|
||||
if (!(sym= dlsym(plugin_dl.handle, plugin_declarations_sym)))
|
||||
{
|
||||
free_plugin_mem(&plugin_dl);
|
||||
if (report & REPORT_TO_USER)
|
||||
my_error(ER_CANT_FIND_DL_ENTRY, MYF(0), plugin_declarations_sym);
|
||||
if (report & REPORT_TO_LOG)
|
||||
sql_print_error(ER_DEFAULT(ER_CANT_FIND_DL_ENTRY),
|
||||
plugin_declarations_sym);
|
||||
report_error(report, ER_CANT_FIND_DL_ENTRY, MYF(0),
|
||||
plugin_declarations_sym);
|
||||
DBUG_RETURN(0);
|
||||
}
|
||||
|
||||
if (plugin_dl.version != MYSQL_PLUGIN_INTERFACE_VERSION)
|
||||
{
|
||||
int i;
|
||||
uint sizeof_st_plugin;
|
||||
struct st_mysql_plugin *old, *cur;
|
||||
char *ptr= (char *)sym;
|
||||
@ -443,11 +466,7 @@ static st_plugin_dl *plugin_dl_add(const LEX_STRING *dl, int report)
|
||||
else
|
||||
{
|
||||
#ifdef ERROR_ON_NO_SIZEOF_PLUGIN_SYMBOL
|
||||
free_plugin_mem(&plugin_dl);
|
||||
if (report & REPORT_TO_USER)
|
||||
my_error(ER_CANT_FIND_DL_ENTRY, MYF(0), sizeof_st_plugin_sym);
|
||||
if (report & REPORT_TO_LOG)
|
||||
sql_print_error(ER_DEFAULT(ER_CANT_FIND_DL_ENTRY), sizeof_st_plugin_sym);
|
||||
report_error(report, ER_CANT_FIND_DL_ENTRY, sizeof_st_plugin_sym);
|
||||
DBUG_RETURN(0);
|
||||
#else
|
||||
/*
|
||||
@ -469,10 +488,7 @@ static st_plugin_dl *plugin_dl_add(const LEX_STRING *dl, int report)
|
||||
if (!cur)
|
||||
{
|
||||
free_plugin_mem(&plugin_dl);
|
||||
if (report & REPORT_TO_USER)
|
||||
my_error(ER_OUTOFMEMORY, MYF(0), plugin_dl.dl.length);
|
||||
if (report & REPORT_TO_LOG)
|
||||
sql_print_error(ER_DEFAULT(ER_OUTOFMEMORY), plugin_dl.dl.length);
|
||||
report_error(report, ER_OUTOFMEMORY, plugin_dl.dl.length);
|
||||
DBUG_RETURN(0);
|
||||
}
|
||||
/*
|
||||
@ -494,10 +510,7 @@ static st_plugin_dl *plugin_dl_add(const LEX_STRING *dl, int report)
|
||||
if (! (plugin_dl.dl.str= (char*) my_malloc(plugin_dl.dl.length, MYF(0))))
|
||||
{
|
||||
free_plugin_mem(&plugin_dl);
|
||||
if (report & REPORT_TO_USER)
|
||||
my_error(ER_OUTOFMEMORY, MYF(0), plugin_dl.dl.length);
|
||||
if (report & REPORT_TO_LOG)
|
||||
sql_print_error(ER_DEFAULT(ER_OUTOFMEMORY), plugin_dl.dl.length);
|
||||
report_error(report, ER_OUTOFMEMORY, plugin_dl.dl.length);
|
||||
DBUG_RETURN(0);
|
||||
}
|
||||
plugin_dl.dl.length= copy_and_convert(plugin_dl.dl.str, plugin_dl.dl.length,
|
||||
@ -508,19 +521,13 @@ static st_plugin_dl *plugin_dl_add(const LEX_STRING *dl, int report)
|
||||
if (! (tmp= plugin_dl_insert_or_reuse(&plugin_dl)))
|
||||
{
|
||||
free_plugin_mem(&plugin_dl);
|
||||
if (report & REPORT_TO_USER)
|
||||
my_error(ER_OUTOFMEMORY, MYF(0), sizeof(struct st_plugin_dl));
|
||||
if (report & REPORT_TO_LOG)
|
||||
sql_print_error(ER_DEFAULT(ER_OUTOFMEMORY), sizeof(struct st_plugin_dl));
|
||||
report_error(report, ER_OUTOFMEMORY, sizeof(struct st_plugin_dl));
|
||||
DBUG_RETURN(0);
|
||||
}
|
||||
DBUG_RETURN(tmp);
|
||||
#else
|
||||
DBUG_ENTER("plugin_dl_add");
|
||||
if (report & REPORT_TO_USER)
|
||||
my_error(ER_FEATURE_DISABLED, MYF(0), "plugin", "HAVE_DLOPEN");
|
||||
if (report & REPORT_TO_LOG)
|
||||
sql_print_error(ER_DEFAULT(ER_FEATURE_DISABLED), "plugin", "HAVE_DLOPEN");
|
||||
report_error(report, ER_FEATURE_DISABLED, "plugin", "HAVE_DLOPEN");
|
||||
DBUG_RETURN(0);
|
||||
#endif
|
||||
}
|
||||
@ -637,7 +644,7 @@ static plugin_ref intern_plugin_lock(LEX *lex, plugin_ref rc CALLER_INFO_PROTO)
|
||||
/*
|
||||
For debugging, we do an additional malloc which allows the
|
||||
memory manager and/or valgrind to track locked references and
|
||||
double unlocks to aid resolving reference counting.problems.
|
||||
double unlocks to aid resolving reference counting problems.
|
||||
*/
|
||||
if (!(plugin= (plugin_ref) my_malloc_ci(sizeof(pi), MYF(MY_WME))))
|
||||
DBUG_RETURN(NULL);
|
||||
@ -720,10 +727,7 @@ static bool plugin_add(MEM_ROOT *tmp_root,
|
||||
DBUG_ENTER("plugin_add");
|
||||
if (plugin_find_internal(name, MYSQL_ANY_PLUGIN))
|
||||
{
|
||||
if (report & REPORT_TO_USER)
|
||||
my_error(ER_UDF_EXISTS, MYF(0), name->str);
|
||||
if (report & REPORT_TO_LOG)
|
||||
sql_print_error(ER_DEFAULT(ER_UDF_EXISTS), name->str);
|
||||
report_error(report, ER_UDF_EXISTS, name->str);
|
||||
DBUG_RETURN(TRUE);
|
||||
}
|
||||
/* Clear the whole struct to catch future extensions. */
|
||||
@ -750,10 +754,7 @@ static bool plugin_add(MEM_ROOT *tmp_root,
|
||||
strxnmov(buf, sizeof(buf) - 1, "API version for ",
|
||||
plugin_type_names[plugin->type].str,
|
||||
" plugin is too different", NullS);
|
||||
if (report & REPORT_TO_USER)
|
||||
my_error(ER_CANT_OPEN_LIBRARY, MYF(0), dl->str, 0, buf);
|
||||
if (report & REPORT_TO_LOG)
|
||||
sql_print_error(ER_DEFAULT(ER_CANT_OPEN_LIBRARY), dl->str, 0, buf);
|
||||
report_error(report, ER_CANT_OPEN_LIBRARY, dl->str, 0, buf);
|
||||
goto err;
|
||||
}
|
||||
tmp.plugin= plugin;
|
||||
@ -782,10 +783,7 @@ static bool plugin_add(MEM_ROOT *tmp_root,
|
||||
DBUG_RETURN(FALSE);
|
||||
}
|
||||
}
|
||||
if (report & REPORT_TO_USER)
|
||||
my_error(ER_CANT_FIND_DL_ENTRY, MYF(0), name->str);
|
||||
if (report & REPORT_TO_LOG)
|
||||
sql_print_error(ER_DEFAULT(ER_CANT_FIND_DL_ENTRY), name->str);
|
||||
report_error(report, ER_CANT_FIND_DL_ENTRY, name->str);
|
||||
err:
|
||||
plugin_dl_del(dl);
|
||||
DBUG_RETURN(TRUE);
|
||||
|
@ -35,16 +35,6 @@ class sys_var;
|
||||
|
||||
#define INITIAL_LEX_PLUGIN_LIST_SIZE 16
|
||||
|
||||
/*
|
||||
the following #define adds server-only members to enum_mysql_show_type,
|
||||
that is defined in plugin.h
|
||||
*/
|
||||
#define SHOW_FUNC SHOW_FUNC, SHOW_KEY_CACHE_LONG, SHOW_KEY_CACHE_LONGLONG, \
|
||||
SHOW_LONG_STATUS, SHOW_DOUBLE_STATUS, SHOW_HAVE, \
|
||||
SHOW_MY_BOOL, SHOW_HA_ROWS, SHOW_SYS, SHOW_LONG_NOFLUSH, \
|
||||
SHOW_LONGLONG_STATUS
|
||||
#include <mysql/plugin.h>
|
||||
#undef SHOW_FUNC
|
||||
typedef enum enum_mysql_show_type SHOW_TYPE;
|
||||
typedef struct st_mysql_show_var SHOW_VAR;
|
||||
|
||||
|
44
sql/sql_plugin_services.h
Normal file
44
sql/sql_plugin_services.h
Normal file
@ -0,0 +1,44 @@
|
||||
/* Copyright (C) 2009 Sun Microsystems, Inc.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; version 2 of the License.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
|
||||
|
||||
/* support for Services */
|
||||
#include <service_versions.h>
|
||||
|
||||
struct st_service_ref {
|
||||
const char *name;
|
||||
uint version;
|
||||
void *service;
|
||||
};
|
||||
|
||||
static struct my_snprintf_service_st my_snprintf_handler = {
|
||||
my_snprintf,
|
||||
my_vsnprintf
|
||||
};
|
||||
|
||||
static struct thd_alloc_service_st thd_alloc_handler= {
|
||||
thd_alloc,
|
||||
thd_calloc,
|
||||
thd_strdup,
|
||||
thd_strmake,
|
||||
thd_memdup,
|
||||
thd_make_lex_string
|
||||
};
|
||||
|
||||
static struct st_service_ref list_of_services[]=
|
||||
{
|
||||
{ "my_snprintf_service", VERSION_my_snprintf, &my_snprintf_handler },
|
||||
{ "thd_alloc_service", VERSION_thd_alloc, &thd_alloc_handler }
|
||||
};
|
||||
|
@ -5105,8 +5105,8 @@ greedy_search(JOIN *join,
|
||||
the interleaving state to the one of the non-extended partial plan
|
||||
on exit.
|
||||
*/
|
||||
IF_DBUG(bool is_interleave_error= )
|
||||
check_interleaving_with_nj (best_table);
|
||||
bool is_interleave_error __attribute__((unused))=
|
||||
check_interleaving_with_nj (best_table);
|
||||
/* This has been already checked by best_extension_by_limited_search */
|
||||
DBUG_ASSERT(!is_interleave_error);
|
||||
|
||||
@ -15183,7 +15183,7 @@ setup_copy_fields(THD *thd, TMP_TABLE_PARAM *param,
|
||||
Item *pos;
|
||||
List_iterator_fast<Item> li(all_fields);
|
||||
Copy_field *copy= NULL;
|
||||
IF_DBUG(Copy_field *copy_start);
|
||||
Copy_field *copy_start __attribute__((unused));
|
||||
res_selected_fields.empty();
|
||||
res_all_fields.empty();
|
||||
List_iterator_fast<Item> itr(res_all_fields);
|
||||
@ -15196,7 +15196,7 @@ setup_copy_fields(THD *thd, TMP_TABLE_PARAM *param,
|
||||
goto err2;
|
||||
|
||||
param->copy_funcs.empty();
|
||||
IF_DBUG(copy_start= copy);
|
||||
copy_start= copy;
|
||||
for (i= 0; (pos= li++); i++)
|
||||
{
|
||||
Field *field;
|
||||
|
@ -5465,7 +5465,7 @@ binlog:
|
||||
}
|
||||
VOID(pthread_mutex_unlock(&LOCK_open));
|
||||
|
||||
IF_DBUG(int result=)
|
||||
int result __attribute__((unused))=
|
||||
store_create_info(thd, table, &query,
|
||||
create_info, FALSE /* show_database */);
|
||||
|
||||
|
@ -34,7 +34,7 @@ noinst_HEADERS = ha_example.h
|
||||
|
||||
EXTRA_LTLIBRARIES = ha_example.la
|
||||
pkgplugin_LTLIBRARIES = @plugin_example_shared_target@
|
||||
ha_example_la_LDFLAGS = -module -rpath $(pkgplugindir)
|
||||
ha_example_la_LDFLAGS = -module -rpath $(pkgplugindir) -L$(top_builddir)/libservices -lmysqlservices
|
||||
ha_example_la_CXXFLAGS= $(AM_CFLAGS) -DMYSQL_DYNAMIC_PLUGIN
|
||||
ha_example_la_CFLAGS = $(AM_CFLAGS) -DMYSQL_DYNAMIC_PLUGIN
|
||||
ha_example_la_SOURCES = ha_example.cc
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* Copyright (C) 2003 MySQL AB
|
||||
/* Copyright (C) 2003 MySQL AB, 2009 Sun Microsystems, Inc.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
@ -921,6 +921,24 @@ static struct st_mysql_sys_var* example_system_variables[]= {
|
||||
NULL
|
||||
};
|
||||
|
||||
// this is an example of SHOW_FUNC and of my_snprintf() service
|
||||
static int show_func_example(MYSQL_THD thd, struct st_mysql_show_var *var,
|
||||
char *buf)
|
||||
{
|
||||
var->type= SHOW_CHAR;
|
||||
var->value= buf; // it's of SHOW_VAR_FUNC_BUFF_SIZE bytes
|
||||
my_snprintf(buf, SHOW_VAR_FUNC_BUFF_SIZE,
|
||||
"enum_var is %u, ulong_var is %lu, %.6b", // %b is MySQL extension
|
||||
srv_enum_var, srv_ulong_var, "really");
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct st_mysql_show_var func_status[]=
|
||||
{
|
||||
{"example_func_example", (char *)show_func_example, SHOW_FUNC},
|
||||
{0,0,SHOW_UNDEF}
|
||||
};
|
||||
|
||||
mysql_declare_plugin(example)
|
||||
{
|
||||
MYSQL_STORAGE_ENGINE_PLUGIN,
|
||||
@ -932,7 +950,7 @@ mysql_declare_plugin(example)
|
||||
example_init_func, /* Plugin Init */
|
||||
example_done_func, /* Plugin Deinit */
|
||||
0x0001 /* 0.1 */,
|
||||
NULL, /* status variables */
|
||||
func_status, /* status variables */
|
||||
example_system_variables, /* system variables */
|
||||
NULL /* config options */
|
||||
}
|
||||
|
@ -34,7 +34,7 @@ IF(NOT SOURCE_SUBLIBS)
|
||||
#The dll is linked to the mysqld executable
|
||||
SET(dyn_libname ha_${libname})
|
||||
ADD_LIBRARY(${dyn_libname} SHARED ${${engine}_SOURCES})
|
||||
TARGET_LINK_LIBRARIES (${dyn_libname} mysqld)
|
||||
TARGET_LINK_LIBRARIES (${dyn_libname} mysqlservices mysqld)
|
||||
IF(${engine}_LIBS)
|
||||
TARGET_LINK_LIBRARIES(${dyn_libname} ${${engine}_LIBS})
|
||||
ENDIF(${engine}_LIBS)
|
||||
|
@ -260,6 +260,14 @@ static char *process_int_arg(char *to, char *end, size_t length,
|
||||
{
|
||||
size_t diff= (length- res_length);
|
||||
bfill(to, diff, (print_type & PREZERO_ARG) ? '0' : ' ');
|
||||
if (arg_type == 'p' && print_type & PREZERO_ARG)
|
||||
{
|
||||
if (diff > 1)
|
||||
to[1]= 'x';
|
||||
else
|
||||
store_start[0]= 'x';
|
||||
store_start[1]= '0';
|
||||
}
|
||||
to+= diff;
|
||||
}
|
||||
bmove(to, store_start, res_length);
|
||||
@ -323,6 +331,7 @@ start:
|
||||
/* Get print width */
|
||||
if (*fmt == '*')
|
||||
{
|
||||
fmt++;
|
||||
fmt= get_width(fmt, &print_arr[idx].width);
|
||||
print_arr[idx].width--;
|
||||
DBUG_ASSERT(*fmt == '$' && print_arr[idx].width < MAX_ARGS);
|
||||
@ -472,6 +481,8 @@ start:
|
||||
/**
|
||||
Produces output string according to a format string
|
||||
|
||||
See the detailed documentation around my_snprintf_service_st
|
||||
|
||||
@param cs string charset
|
||||
@param to buffer where processed string will be place
|
||||
@param n size of buffer
|
||||
@ -621,54 +632,3 @@ size_t my_snprintf(char* to, size_t n, const char* fmt, ...)
|
||||
return result;
|
||||
}
|
||||
|
||||
#ifdef MAIN
|
||||
#define OVERRUN_SENTRY 250
|
||||
static void my_printf(const char * fmt, ...)
|
||||
{
|
||||
char buf[33];
|
||||
int n;
|
||||
va_list ar;
|
||||
va_start(ar, fmt);
|
||||
buf[sizeof(buf)-1]=OVERRUN_SENTRY;
|
||||
n = my_vsnprintf(buf, sizeof(buf)-1,fmt, ar);
|
||||
printf(buf);
|
||||
printf("n=%d, strlen=%d\n", n, strlen(buf));
|
||||
if ((uchar) buf[sizeof(buf)-1] != OVERRUN_SENTRY)
|
||||
{
|
||||
fprintf(stderr, "Buffer overrun\n");
|
||||
abort();
|
||||
}
|
||||
va_end(ar);
|
||||
}
|
||||
|
||||
|
||||
int main()
|
||||
{
|
||||
|
||||
my_printf("Hello\n");
|
||||
my_printf("Hello int, %d\n", 1);
|
||||
my_printf("Hello string '%s'\n", "I am a string");
|
||||
my_printf("Hello hack hack hack hack hack hack hack %d\n", 1);
|
||||
my_printf("Hello %d hack %d\n", 1, 4);
|
||||
my_printf("Hello %d hack hack hack hack hack %d\n", 1, 4);
|
||||
my_printf("Hello '%s' hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh\n", "hack");
|
||||
my_printf("Hello hhhhhhhhhhhhhh %d sssssssssssssss\n", 1);
|
||||
my_printf("Hello %u\n", 1);
|
||||
my_printf("Hex: %lx '%6lx'\n", 32, 65);
|
||||
my_printf("conn %ld to: '%-.64s' user: '%-.32s' host:\
|
||||
`%-.64s' (%-.64s)", 1, 0,0,0,0);
|
||||
|
||||
my_printf("Hello string %`s\n", "I am a string");
|
||||
my_printf("Hello %05s\n", "TEST");
|
||||
my_printf("My %1$`-.1s test\n", "QQQQ");
|
||||
my_printf("My %1$s test done %2$s\n", "DDDD", "AAAA");
|
||||
my_printf("My %1$s test %2$s, %1$-.3s\n", "DDDD", "CCCC");
|
||||
my_printf("My %1$`-.4b test\n", "QQQQ");
|
||||
my_printf("My %1$c test\n", 'X');
|
||||
my_printf("My `%010d` test1 %4x test2 %4X\n", 10, 10, 10);
|
||||
my_printf("My `%1$010d` test1 %2$4x test2 %2$4x\n", 10, 10);
|
||||
my_printf("My %1$*02$d test\n", 10, 5);
|
||||
my_printf("My %1$`s test %2$s, %1$`-.3s\n", "DDDD", "CCCC");
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
@ -21,7 +21,7 @@ LDADD = $(top_builddir)/unittest/mytap/libmytap.a \
|
||||
$(top_builddir)/dbug/libdbug.a \
|
||||
$(top_builddir)/strings/libmystrings.a
|
||||
|
||||
noinst_PROGRAMS = bitmap-t base64-t
|
||||
noinst_PROGRAMS = bitmap-t base64-t my_vsnprintf-t
|
||||
|
||||
if NEED_THREAD
|
||||
# my_atomic-t is used to check thread functions, so it is safe to
|
||||
|
155
unittest/mysys/my_vsnprintf-t.c
Normal file
155
unittest/mysys/my_vsnprintf-t.c
Normal file
@ -0,0 +1,155 @@
|
||||
/* Copyright (C) 2003 MySQL AB
|
||||
|
||||
This program is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU General Public License as
|
||||
published by the Free Software Foundation; version 2 of the License.
|
||||
|
||||
This program is distributed in the hope that it will be useful, but
|
||||
WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
|
||||
|
||||
#include <my_global.h>
|
||||
#include <m_string.h>
|
||||
#include <tap.h>
|
||||
|
||||
char buf[1024]; /* let's hope that's enough */
|
||||
|
||||
void test1(const char *res, const char *fmt, ...)
|
||||
{
|
||||
va_list args;
|
||||
size_t len;
|
||||
va_start(args,fmt);
|
||||
len= my_vsnprintf(buf, sizeof(buf)-1, fmt, args);
|
||||
va_end(args);
|
||||
ok(strlen(res) == len && strcmp(buf, res) == 0, "\"%s\"", buf);
|
||||
}
|
||||
|
||||
int main(void)
|
||||
{
|
||||
plan(47);
|
||||
|
||||
test1("Constant string",
|
||||
"Constant string");
|
||||
|
||||
test1("Format specifier s works",
|
||||
"Format specifier s %s", "works");
|
||||
test1("Format specifier b works (mysql extension)",
|
||||
"Format specifier b %.5b (mysql extension)", "works!!!");
|
||||
test1("Format specifier c !",
|
||||
"Format specifier c %c", '!');
|
||||
test1("Format specifier d 1",
|
||||
"Format specifier d %d", 1);
|
||||
test1("Format specifier u 2",
|
||||
"Format specifier u %u", 2);
|
||||
test1("Format specifier x a",
|
||||
"Format specifier x %x", 10);
|
||||
test1("Format specifier X B",
|
||||
"Format specifier X %X", 11);
|
||||
test1("Format specifier p 0x5",
|
||||
"Format specifier p %p", 5);
|
||||
|
||||
test1("Flag '-' is ignored < 1>",
|
||||
"Flag '-' is ignored <%-4d>", 1);
|
||||
test1("Flag '0' works <0006>",
|
||||
"Flag '0' works <%04d>", 6);
|
||||
|
||||
test1("Width is ignored for strings <x> <y>",
|
||||
"Width is ignored for strings <%04s> <%5s>", "x", "y");
|
||||
|
||||
test1("Precision works for strings <abcde>",
|
||||
"Precision works for strings <%.5s>", "abcdef!");
|
||||
|
||||
test1("Flag '`' (backtick) works: `abcd` `op``q` (mysql extension)",
|
||||
"Flag '`' (backtick) works: %`s %`.4s (mysql extension)",
|
||||
"abcd", "op`qrst");
|
||||
|
||||
test1("Length modifiers work: 1 * -1 * 2 * 3",
|
||||
"Length modifiers work: %d * %ld * %lld * %zd", 1, -1L, 2LL, (size_t)3);
|
||||
|
||||
test1("(null) pointer is fine",
|
||||
"%s pointer is fine", NULL);
|
||||
|
||||
test1("Positional arguments work: on the dark side they are",
|
||||
"Positional arguments work: %3$s %1$s %2$s",
|
||||
"they", "are", "on the dark side");
|
||||
|
||||
test1("Asterisk '*' as a width works: < 4>",
|
||||
"Asterisk '*' as a width works: <%*d>", 5, 4);
|
||||
|
||||
test1("Asterisk '*' as a precision works: <qwerty>",
|
||||
"Asterisk '*' as a precision works: <%.*s>", 6, "qwertyuiop");
|
||||
|
||||
test1("Positional arguments for a width: < 4>",
|
||||
"Positional arguments for a width: <%1$*2$d>", 4, 5);
|
||||
|
||||
test1("Positional arguments for a precision: <qwerty>",
|
||||
"Positional arguments for a precision: <%1$.*2$s>", "qwertyuiop", 6);
|
||||
|
||||
test1("Positional arguments and a width: <0000ab>",
|
||||
"Positional arguments and a width: <%1$06x>", 0xab);
|
||||
|
||||
test1("Padding and %p <0x12> <0x034> <0x0000ab> < 0xcd>",
|
||||
"Padding and %%p <%04p> <%05p> <%08p> <%8p>", 0x12, 0x34, 0xab, 0xcd);
|
||||
|
||||
#if MYSQL_VERSION_ID > 60000
|
||||
#error %f/%g tests go here
|
||||
#endif
|
||||
|
||||
test1("Hello",
|
||||
"Hello");
|
||||
test1("Hello int, 1",
|
||||
"Hello int, %d", 1);
|
||||
test1("Hello int, -1",
|
||||
"Hello int, %d", -1);
|
||||
test1("Hello string 'I am a string'",
|
||||
"Hello string '%s'", "I am a string");
|
||||
test1("Hello hack hack hack hack hack hack hack 1",
|
||||
"Hello hack hack hack hack hack hack hack %d", 1);
|
||||
test1("Hello 1 hack 4",
|
||||
"Hello %d hack %d", 1, 4);
|
||||
test1("Hello 1 hack hack hack hack hack 4",
|
||||
"Hello %d hack hack hack hack hack %d", 1, 4);
|
||||
test1("Hello 'hack' hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh",
|
||||
"Hello '%s' hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh", "hack");
|
||||
test1("Hello hhhhhhhhhhhhhh 1 sssssssssssssss",
|
||||
"Hello hhhhhhhhhhhhhh %d sssssssssssssss", 1);
|
||||
test1("Hello 1",
|
||||
"Hello %u", 1);
|
||||
test1("Hello 4294967295",
|
||||
"Hello %u", -1);
|
||||
test1("Hex: 20 ' 41'",
|
||||
"Hex: %lx '%6lx'", 32, 65);
|
||||
test1("conn 1 to: '(null)' user: '(null)' host: '(null)' ((null))",
|
||||
"conn %ld to: '%-.64s' user: '%-.32s' host: '%-.64s' (%-.64s)",
|
||||
1L, NULL, NULL, NULL, NULL);
|
||||
test1("Hello string `I am a string`",
|
||||
"Hello string %`s", "I am a string");
|
||||
test1("Hello TEST",
|
||||
"Hello %05s", "TEST");
|
||||
test1("My `Q` test",
|
||||
"My %1$`-.1s test", "QQQQ");
|
||||
test1("My AAAA test done DDDD",
|
||||
"My %2$s test done %1$s", "DDDD", "AAAA");
|
||||
test1("My DDDD test CCCC, DDD",
|
||||
"My %1$s test %2$s, %1$-.3s", "DDDD", "CCCC");
|
||||
test1("My QQQQ test",
|
||||
"My %1$`-.4b test", "QQQQ");
|
||||
test1("My X test",
|
||||
"My %1$c test", 'X');
|
||||
test1("My <0000000010> test1 < a> test2 < A>",
|
||||
"My <%010d> test1 <%4x> test2 <%4X>", 10, 10, 10);
|
||||
test1("My <0000000010> test1 < a> test2 < a>",
|
||||
"My <%1$010d> test1 <%2$4x> test2 <%2$4x>", 10, 10);
|
||||
test1("My 00010 test",
|
||||
"My %1$*02$d test", 10, 5);
|
||||
test1("My `DDDD` test CCCC, `DDD`",
|
||||
"My %1$`s test %2$s, %1$`-.3s", "DDDD", "CCCC");
|
||||
|
||||
return exit_status();
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user