forked from opengaussexamples/examples
!47 first commit of Sysbench4RedisAndMot
Merge pull request !47 from 熊小军/master
This commit is contained in:
commit
384e4aa4f4
|
|
@ -0,0 +1,88 @@
|
|||
*.o
|
||||
*.a
|
||||
Makefile
|
||||
Makefile.in
|
||||
aclocal.m4
|
||||
autom4te.cache
|
||||
/config/config.h
|
||||
/config/ltmain.sh
|
||||
/config/stamp-h1
|
||||
/doc/manual.html
|
||||
/config.log
|
||||
/config.status
|
||||
/configure
|
||||
/libtool
|
||||
/doc/xsl/catalog.xml
|
||||
/src/.deps
|
||||
/src/.libs
|
||||
/src/sysbench
|
||||
/src/drivers/mysql/.deps
|
||||
/src/drivers/oracle/.deps
|
||||
/src/drivers/pgsql/.deps
|
||||
/src/tests/cpu/.deps
|
||||
/src/tests/fileio/.deps
|
||||
/src/tests/memory/.deps
|
||||
/src/tests/mutex/.deps
|
||||
/src/tests/oltp/.deps
|
||||
/src/tests/threads/.deps
|
||||
/TAGS
|
||||
/backup.bzr
|
||||
/config/config.guess
|
||||
/config/config.h.in
|
||||
/config/config.sub
|
||||
/src/TAGS
|
||||
/src/drivers/TAGS
|
||||
/src/drivers/mysql/TAGS
|
||||
/src/tests/TAGS
|
||||
/src/tests/cpu/TAGS
|
||||
/src/tests/fileio/TAGS
|
||||
/src/tests/memory/TAGS
|
||||
/src/tests/mutex/TAGS
|
||||
/src/tests/oltp/TAGS
|
||||
/src/tests/threads/TAGS
|
||||
/config/compile
|
||||
/config/depcomp
|
||||
/config/install-sh
|
||||
/config/missing
|
||||
/m4/libtool.m4
|
||||
/m4/ltoptions.m4
|
||||
/m4/ltsugar.m4
|
||||
/m4/ltversion.m4
|
||||
/m4/lt~obsolete.m4
|
||||
/src/drivers/drizzle/.deps
|
||||
/src/scripting/.deps
|
||||
/src/scripting/lua/src/.deps
|
||||
GPATH
|
||||
GRTAGS
|
||||
GTAGS
|
||||
/config/ar-lib
|
||||
/src/drivers/attachsql/.deps/
|
||||
/config/test-driver
|
||||
*.DS_Store
|
||||
/tests/*.log
|
||||
/tests/*.trs
|
||||
*.gcda
|
||||
*.gcno
|
||||
/tests/include/config.sh
|
||||
/third_party/concurrency_kit/include/
|
||||
/third_party/concurrency_kit/lib/
|
||||
/third_party/concurrency_kit/share/
|
||||
/third_party/concurrency_kit/tmp/
|
||||
third_party/luajit/bin/
|
||||
third_party/luajit/inc/
|
||||
third_party/luajit/lib/
|
||||
third_party/luajit/share/
|
||||
third_party/luajit/tmp/
|
||||
src/lua/internal/sysbench.lua.h
|
||||
src/lua/internal/sysbench.sql.lua.h
|
||||
/src/lua/internal/sysbench.rand.lua.h
|
||||
/src/lua/internal/sysbench.opt.lua.h
|
||||
tests/t/*.err
|
||||
/src/lua/internal/sysbench.cmdline.lua.h
|
||||
/src/lua/internal/sysbench.compat.lua.h
|
||||
/src/lua/internal/sysbench.histogram.lua.h
|
||||
parts
|
||||
prime
|
||||
stage
|
||||
*.snap
|
||||
/snap/snapcraft.yaml
|
||||
|
|
@ -0,0 +1,292 @@
|
|||
# vim ft=yaml
|
||||
#
|
||||
# Travis CI configuration
|
||||
|
||||
arch:
|
||||
- amd64
|
||||
- arm64
|
||||
|
||||
dist: trusty
|
||||
sudo: required
|
||||
|
||||
services:
|
||||
- docker
|
||||
- mysql
|
||||
- postgresql
|
||||
|
||||
git:
|
||||
depth: 100500
|
||||
|
||||
language: c
|
||||
|
||||
os:
|
||||
- linux
|
||||
- osx
|
||||
|
||||
compiler:
|
||||
- gcc
|
||||
- clang
|
||||
|
||||
env:
|
||||
matrix:
|
||||
- TARGET=distcheck
|
||||
- TARGET=test
|
||||
- TARGET=coverage
|
||||
- OS=el DIST=6
|
||||
- OS=el DIST=7
|
||||
- OS=el DIST=8
|
||||
- OS=fedora DIST=29
|
||||
- OS=fedora DIST=30
|
||||
- OS=fedora DIST=31
|
||||
- OS=ubuntu DIST=xenial
|
||||
- OS=ubuntu DIST=bionic
|
||||
- OS=ubuntu DIST=eoan
|
||||
- OS=ubuntu DIST=focal
|
||||
- OS=debian DIST=jessie
|
||||
- OS=debian DIST=stretch
|
||||
- OS=debian DIST=buster
|
||||
- OS=debian DIST=sid
|
||||
- OS=ubuntu DIST=xenial ARCH=i386
|
||||
- OS=ubuntu DIST=bionic ARCH=i386
|
||||
- OS=ubuntu DIST=eoan ARCH=i386
|
||||
- OS=debian DIST=jessie ARCH=i386
|
||||
- OS=debian DIST=stretch ARCH=i386
|
||||
- OS=debian DIST=buster ARCH=i386
|
||||
- OS=debian DIST=sid ARCH=i386
|
||||
|
||||
matrix:
|
||||
exclude:
|
||||
- env: OS=el DIST=6
|
||||
compiler: clang
|
||||
- env: OS=el DIST=7
|
||||
compiler: clang
|
||||
- env: OS=el DIST=8
|
||||
compiler: clang
|
||||
- env: OS=fedora DIST=29
|
||||
compiler: clang
|
||||
- env: OS=fedora DIST=30
|
||||
compiler: clang
|
||||
- env: OS=fedora DIST=31
|
||||
compiler: clang
|
||||
- env: OS=ubuntu DIST=xenial
|
||||
compiler: clang
|
||||
- env: OS=ubuntu DIST=bionic
|
||||
compiler: clang
|
||||
- env: OS=ubuntu DIST=disco
|
||||
compiler: clang
|
||||
- env: OS=ubuntu DIST=eoan
|
||||
compiler: clang
|
||||
- env: OS=ubuntu DIST=focal
|
||||
compiler: clang
|
||||
- env: OS=debian DIST=jessie
|
||||
compiler: clang
|
||||
- env: OS=debian DIST=stretch
|
||||
compiler: clang
|
||||
- env: OS=debian DIST=buster
|
||||
compiler: clang
|
||||
- env: OS=debian DIST=sid
|
||||
compiler: clang
|
||||
- env: OS=ubuntu DIST=xenial ARCH=i386
|
||||
compiler: clang
|
||||
- env: OS=ubuntu DIST=bionic ARCH=i386
|
||||
compiler: clang
|
||||
- env: OS=ubuntu DIST=disco ARCH=i386
|
||||
compiler: clang
|
||||
- env: OS=ubuntu DIST=eoan ARCH=i386
|
||||
compiler: clang
|
||||
- env: OS=debian DIST=jessie ARCH=i386
|
||||
compiler: clang
|
||||
- env: OS=debian DIST=stretch ARCH=i386
|
||||
compiler: clang
|
||||
- env: OS=debian DIST=buster ARCH=i386
|
||||
compiler: clang
|
||||
- env: OS=debian DIST=sid ARCH=i386
|
||||
compiler: clang
|
||||
- env: OS=ubuntu DIST=xenial ARCH=i386
|
||||
arch: arm64
|
||||
- env: OS=ubuntu DIST=bionic ARCH=i386
|
||||
arch: arm64
|
||||
- env: OS=ubuntu DIST=disco ARCH=i386
|
||||
arch: arm64
|
||||
- env: OS=ubuntu DIST=eoan ARCH=i386
|
||||
arch: arm64
|
||||
- env: OS=debian DIST=jessie ARCH=i386
|
||||
arch: arm64
|
||||
- env: OS=debian DIST=stretch ARCH=i386
|
||||
arch: arm64
|
||||
- env: OS=debian DIST=buster ARCH=i386
|
||||
arch: arm64
|
||||
- env: OS=debian DIST=sid ARCH=i386
|
||||
arch: arm64
|
||||
- env: OS=el DIST=6
|
||||
arch: arm64
|
||||
- env: OS=el DIST=6
|
||||
os: osx
|
||||
- env: OS=el DIST=7
|
||||
os: osx
|
||||
- env: OS=el DIST=8
|
||||
os: osx
|
||||
- env: OS=fedora DIST=29
|
||||
os: osx
|
||||
- env: OS=fedora DIST=30
|
||||
os: osx
|
||||
- env: OS=fedora DIST=31
|
||||
os: osx
|
||||
- env: OS=ubuntu DIST=xenial
|
||||
os: osx
|
||||
- env: OS=ubuntu DIST=bionic
|
||||
os: osx
|
||||
- env: OS=ubuntu DIST=disco
|
||||
os: osx
|
||||
- env: OS=ubuntu DIST=eoan
|
||||
os: osx
|
||||
- env: OS=ubuntu DIST=focal
|
||||
os: osx
|
||||
- env: OS=debian DIST=jessie
|
||||
os: osx
|
||||
- env: OS=debian DIST=stretch
|
||||
os: osx
|
||||
- env: OS=debian DIST=buster
|
||||
os: osx
|
||||
- env: OS=debian DIST=sid
|
||||
os: osx
|
||||
- env: TARGET=distcheck
|
||||
compiler: clang
|
||||
- env: TARGET=distcheck
|
||||
os: osx
|
||||
- env: TARGET=distcheck
|
||||
arch: arm64
|
||||
- env: TARGET=coverage
|
||||
os: osx
|
||||
- env: TARGET=coverage
|
||||
compiler: clang
|
||||
- env: TARGET=coverage
|
||||
arch: arm64
|
||||
- os: osx
|
||||
compiler: gcc
|
||||
- os: osx
|
||||
arch: arm64
|
||||
- arch: arm64
|
||||
compiler: clang
|
||||
- env: OS=debian DIST=jessie
|
||||
arch: arm64
|
||||
|
||||
addons:
|
||||
apt:
|
||||
packages:
|
||||
- libmysqlclient-dev
|
||||
- libpq-dev
|
||||
- libaio-dev
|
||||
- clang-3.6
|
||||
|
||||
before_install:
|
||||
# Upload builds corresponding to release tags to the 'sysbench'
|
||||
# repository, push other ones to 'sysbench-prereleases'
|
||||
- git describe --long --always
|
||||
- commits=$(git describe --long --always | sed -n 's/^\([0-9\.]*\)-\([0-9]*\)-\([a-z0-9]*\)/\2/p')
|
||||
- >
|
||||
if [ ${commits:-0} = 0 ]; then
|
||||
export VERSION=$(git describe)
|
||||
PACKAGECLOUD_REPO=sysbench
|
||||
else
|
||||
PACKAGECLOUD_REPO=sysbench-prereleases
|
||||
fi
|
||||
- >
|
||||
if [ "x$TARGET" = "xtest" ]; then
|
||||
case "${TRAVIS_OS_NAME:-linux}" in
|
||||
osx)
|
||||
brew update
|
||||
brew install mysql postgresql
|
||||
|
||||
# OS X requires servers to be started explicitly
|
||||
brew services start mysql
|
||||
|
||||
brew postgresql-upgrade-database
|
||||
brew services start postgresql
|
||||
|
||||
echo "Starting PostgreSQL"
|
||||
pg_ctl -wD /usr/local/var/postgres start
|
||||
echo "Creating user postgres"
|
||||
createuser -s postgres
|
||||
;;
|
||||
linux)
|
||||
export ASAN_OPTIONS="detect_leaks=0"
|
||||
if [ "${CC}" = "clang" ]; then
|
||||
CC=clang-3.6
|
||||
fi
|
||||
;;
|
||||
esac
|
||||
fi
|
||||
|
||||
install:
|
||||
- >
|
||||
case "${TRAVIS_OS_NAME:-linux}" in
|
||||
osx)
|
||||
# OS X requires this for user-local pip packages
|
||||
export PATH=~/Library/Python/2.7/bin:$PATH
|
||||
;;
|
||||
linux)
|
||||
pip install --user cpp-coveralls
|
||||
;;
|
||||
esac
|
||||
|
||||
before_script:
|
||||
- mysql -u root -e 'CREATE DATABASE sbtest'
|
||||
- psql -U postgres -c 'CREATE DATABASE sbtest'
|
||||
|
||||
script:
|
||||
- >
|
||||
if [ -n "$TARGET" ]; then
|
||||
case "$TARGET" in
|
||||
test)
|
||||
./autogen.sh && ./configure --with-mysql --with-pgsql
|
||||
make
|
||||
SBTEST_MYSQL_ARGS="--mysql-user=root" SBTEST_PGSQL_ARGS="--pgsql-user=postgres" make test
|
||||
;;
|
||||
distcheck)
|
||||
./autogen.sh && ./configure --without-mysql
|
||||
make
|
||||
make distcheck
|
||||
;;
|
||||
coverage)
|
||||
./autogen.sh && ./configure --enable-coverage --enable-asan --enable-msan --with-mysql --with-pgsql
|
||||
make -j2
|
||||
SBTEST_MYSQL_ARGS="--mysql-user=root" SBTEST_PGSQL_ARGS="--pgsql-user=postgres" make test
|
||||
;;
|
||||
esac
|
||||
else
|
||||
# To avoid name conflicts, deploy source packages only for
|
||||
# "default", i.e. x86_64 architecture
|
||||
if [[ -z "$ARCH" && "$TRAVIS_CPU_ARCH" == amd64 ]]; then
|
||||
PACKAGECLOUD_GLOB='build/*.{rpm,deb,dsc}'
|
||||
else
|
||||
# Exclude *.src.rpm and *.dsc
|
||||
PACKAGECLOUD_GLOB='build/*{[^c].rpm,.deb}'
|
||||
fi
|
||||
|
||||
git clone https://github.com/akopytov/packpack.git packpack
|
||||
packpack/packpack
|
||||
fi
|
||||
|
||||
deploy:
|
||||
# Deploy packages to PackageCloud
|
||||
- provider: packagecloud
|
||||
username: "${PACKAGECLOUD_USER}"
|
||||
repository: "${PACKAGECLOUD_REPO}"
|
||||
token: "${PACKAGECLOUD_TOKEN}"
|
||||
dist: "${OS}/${DIST}"
|
||||
package_glob: "${PACKAGECLOUD_GLOB}"
|
||||
skip_cleanup: true
|
||||
on:
|
||||
all_branches: true
|
||||
condition: -n "$OS" && -n "$DIST" && -n "$PACKAGECLOUD_TOKEN" && "$DIST" != "rawhide" && "$DIST" != "sid"
|
||||
|
||||
after_success:
|
||||
- >
|
||||
if [ "x$TARGET" = "xcoverage" ]; then
|
||||
coveralls --exclude third_party/ --gcov-options '\-lp'
|
||||
fi
|
||||
|
||||
# Local variables:
|
||||
# mode: yaml
|
||||
# End:
|
||||
|
|
@ -0,0 +1,339 @@
|
|||
GNU GENERAL PUBLIC LICENSE
|
||||
Version 2, June 1991
|
||||
|
||||
Copyright (C) 1989, 1991 Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
Everyone is permitted to copy and distribute verbatim copies
|
||||
of this license document, but changing it is not allowed.
|
||||
|
||||
Preamble
|
||||
|
||||
The licenses for most software are designed to take away your
|
||||
freedom to share and change it. By contrast, the GNU General Public
|
||||
License is intended to guarantee your freedom to share and change free
|
||||
software--to make sure the software is free for all its users. This
|
||||
General Public License applies to most of the Free Software
|
||||
Foundation's software and to any other program whose authors commit to
|
||||
using it. (Some other Free Software Foundation software is covered by
|
||||
the GNU Lesser General Public License instead.) You can apply it to
|
||||
your programs, too.
|
||||
|
||||
When we speak of free software, we are referring to freedom, not
|
||||
price. Our General Public Licenses are designed to make sure that you
|
||||
have the freedom to distribute copies of free software (and charge for
|
||||
this service if you wish), that you receive source code or can get it
|
||||
if you want it, that you can change the software or use pieces of it
|
||||
in new free programs; and that you know you can do these things.
|
||||
|
||||
To protect your rights, we need to make restrictions that forbid
|
||||
anyone to deny you these rights or to ask you to surrender the rights.
|
||||
These restrictions translate to certain responsibilities for you if you
|
||||
distribute copies of the software, or if you modify it.
|
||||
|
||||
For example, if you distribute copies of such a program, whether
|
||||
gratis or for a fee, you must give the recipients all the rights that
|
||||
you have. You must make sure that they, too, receive or can get the
|
||||
source code. And you must show them these terms so they know their
|
||||
rights.
|
||||
|
||||
We protect your rights with two steps: (1) copyright the software, and
|
||||
(2) offer you this license which gives you legal permission to copy,
|
||||
distribute and/or modify the software.
|
||||
|
||||
Also, for each author's protection and ours, we want to make certain
|
||||
that everyone understands that there is no warranty for this free
|
||||
software. If the software is modified by someone else and passed on, we
|
||||
want its recipients to know that what they have is not the original, so
|
||||
that any problems introduced by others will not reflect on the original
|
||||
authors' reputations.
|
||||
|
||||
Finally, any free program is threatened constantly by software
|
||||
patents. We wish to avoid the danger that redistributors of a free
|
||||
program will individually obtain patent licenses, in effect making the
|
||||
program proprietary. To prevent this, we have made it clear that any
|
||||
patent must be licensed for everyone's free use or not licensed at all.
|
||||
|
||||
The precise terms and conditions for copying, distribution and
|
||||
modification follow.
|
||||
|
||||
GNU GENERAL PUBLIC LICENSE
|
||||
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
|
||||
|
||||
0. This License applies to any program or other work which contains
|
||||
a notice placed by the copyright holder saying it may be distributed
|
||||
under the terms of this General Public License. The "Program", below,
|
||||
refers to any such program or work, and a "work based on the Program"
|
||||
means either the Program or any derivative work under copyright law:
|
||||
that is to say, a work containing the Program or a portion of it,
|
||||
either verbatim or with modifications and/or translated into another
|
||||
language. (Hereinafter, translation is included without limitation in
|
||||
the term "modification".) Each licensee is addressed as "you".
|
||||
|
||||
Activities other than copying, distribution and modification are not
|
||||
covered by this License; they are outside its scope. The act of
|
||||
running the Program is not restricted, and the output from the Program
|
||||
is covered only if its contents constitute a work based on the
|
||||
Program (independent of having been made by running the Program).
|
||||
Whether that is true depends on what the Program does.
|
||||
|
||||
1. You may copy and distribute verbatim copies of the Program's
|
||||
source code as you receive it, in any medium, provided that you
|
||||
conspicuously and appropriately publish on each copy an appropriate
|
||||
copyright notice and disclaimer of warranty; keep intact all the
|
||||
notices that refer to this License and to the absence of any warranty;
|
||||
and give any other recipients of the Program a copy of this License
|
||||
along with the Program.
|
||||
|
||||
You may charge a fee for the physical act of transferring a copy, and
|
||||
you may at your option offer warranty protection in exchange for a fee.
|
||||
|
||||
2. You may modify your copy or copies of the Program or any portion
|
||||
of it, thus forming a work based on the Program, and copy and
|
||||
distribute such modifications or work under the terms of Section 1
|
||||
above, provided that you also meet all of these conditions:
|
||||
|
||||
a) You must cause the modified files to carry prominent notices
|
||||
stating that you changed the files and the date of any change.
|
||||
|
||||
b) You must cause any work that you distribute or publish, that in
|
||||
whole or in part contains or is derived from the Program or any
|
||||
part thereof, to be licensed as a whole at no charge to all third
|
||||
parties under the terms of this License.
|
||||
|
||||
c) If the modified program normally reads commands interactively
|
||||
when run, you must cause it, when started running for such
|
||||
interactive use in the most ordinary way, to print or display an
|
||||
announcement including an appropriate copyright notice and a
|
||||
notice that there is no warranty (or else, saying that you provide
|
||||
a warranty) and that users may redistribute the program under
|
||||
these conditions, and telling the user how to view a copy of this
|
||||
License. (Exception: if the Program itself is interactive but
|
||||
does not normally print such an announcement, your work based on
|
||||
the Program is not required to print an announcement.)
|
||||
|
||||
These requirements apply to the modified work as a whole. If
|
||||
identifiable sections of that work are not derived from the Program,
|
||||
and can be reasonably considered independent and separate works in
|
||||
themselves, then this License, and its terms, do not apply to those
|
||||
sections when you distribute them as separate works. But when you
|
||||
distribute the same sections as part of a whole which is a work based
|
||||
on the Program, the distribution of the whole must be on the terms of
|
||||
this License, whose permissions for other licensees extend to the
|
||||
entire whole, and thus to each and every part regardless of who wrote it.
|
||||
|
||||
Thus, it is not the intent of this section to claim rights or contest
|
||||
your rights to work written entirely by you; rather, the intent is to
|
||||
exercise the right to control the distribution of derivative or
|
||||
collective works based on the Program.
|
||||
|
||||
In addition, mere aggregation of another work not based on the Program
|
||||
with the Program (or with a work based on the Program) on a volume of
|
||||
a storage or distribution medium does not bring the other work under
|
||||
the scope of this License.
|
||||
|
||||
3. You may copy and distribute the Program (or a work based on it,
|
||||
under Section 2) in object code or executable form under the terms of
|
||||
Sections 1 and 2 above provided that you also do one of the following:
|
||||
|
||||
a) Accompany it with the complete corresponding machine-readable
|
||||
source code, which must be distributed under the terms of Sections
|
||||
1 and 2 above on a medium customarily used for software interchange; or,
|
||||
|
||||
b) Accompany it with a written offer, valid for at least three
|
||||
years, to give any third party, for a charge no more than your
|
||||
cost of physically performing source distribution, a complete
|
||||
machine-readable copy of the corresponding source code, to be
|
||||
distributed under the terms of Sections 1 and 2 above on a medium
|
||||
customarily used for software interchange; or,
|
||||
|
||||
c) Accompany it with the information you received as to the offer
|
||||
to distribute corresponding source code. (This alternative is
|
||||
allowed only for noncommercial distribution and only if you
|
||||
received the program in object code or executable form with such
|
||||
an offer, in accord with Subsection b above.)
|
||||
|
||||
The source code for a work means the preferred form of the work for
|
||||
making modifications to it. For an executable work, complete source
|
||||
code means all the source code for all modules it contains, plus any
|
||||
associated interface definition files, plus the scripts used to
|
||||
control compilation and installation of the executable. However, as a
|
||||
special exception, the source code distributed need not include
|
||||
anything that is normally distributed (in either source or binary
|
||||
form) with the major components (compiler, kernel, and so on) of the
|
||||
operating system on which the executable runs, unless that component
|
||||
itself accompanies the executable.
|
||||
|
||||
If distribution of executable or object code is made by offering
|
||||
access to copy from a designated place, then offering equivalent
|
||||
access to copy the source code from the same place counts as
|
||||
distribution of the source code, even though third parties are not
|
||||
compelled to copy the source along with the object code.
|
||||
|
||||
4. You may not copy, modify, sublicense, or distribute the Program
|
||||
except as expressly provided under this License. Any attempt
|
||||
otherwise to copy, modify, sublicense or distribute the Program is
|
||||
void, and will automatically terminate your rights under this License.
|
||||
However, parties who have received copies, or rights, from you under
|
||||
this License will not have their licenses terminated so long as such
|
||||
parties remain in full compliance.
|
||||
|
||||
5. You are not required to accept this License, since you have not
|
||||
signed it. However, nothing else grants you permission to modify or
|
||||
distribute the Program or its derivative works. These actions are
|
||||
prohibited by law if you do not accept this License. Therefore, by
|
||||
modifying or distributing the Program (or any work based on the
|
||||
Program), you indicate your acceptance of this License to do so, and
|
||||
all its terms and conditions for copying, distributing or modifying
|
||||
the Program or works based on it.
|
||||
|
||||
6. Each time you redistribute the Program (or any work based on the
|
||||
Program), the recipient automatically receives a license from the
|
||||
original licensor to copy, distribute or modify the Program subject to
|
||||
these terms and conditions. You may not impose any further
|
||||
restrictions on the recipients' exercise of the rights granted herein.
|
||||
You are not responsible for enforcing compliance by third parties to
|
||||
this License.
|
||||
|
||||
7. If, as a consequence of a court judgment or allegation of patent
|
||||
infringement or for any other reason (not limited to patent issues),
|
||||
conditions are imposed on you (whether by court order, agreement or
|
||||
otherwise) that contradict the conditions of this License, they do not
|
||||
excuse you from the conditions of this License. If you cannot
|
||||
distribute so as to satisfy simultaneously your obligations under this
|
||||
License and any other pertinent obligations, then as a consequence you
|
||||
may not distribute the Program at all. For example, if a patent
|
||||
license would not permit royalty-free redistribution of the Program by
|
||||
all those who receive copies directly or indirectly through you, then
|
||||
the only way you could satisfy both it and this License would be to
|
||||
refrain entirely from distribution of the Program.
|
||||
|
||||
If any portion of this section is held invalid or unenforceable under
|
||||
any particular circumstance, the balance of the section is intended to
|
||||
apply and the section as a whole is intended to apply in other
|
||||
circumstances.
|
||||
|
||||
It is not the purpose of this section to induce you to infringe any
|
||||
patents or other property right claims or to contest validity of any
|
||||
such claims; this section has the sole purpose of protecting the
|
||||
integrity of the free software distribution system, which is
|
||||
implemented by public license practices. Many people have made
|
||||
generous contributions to the wide range of software distributed
|
||||
through that system in reliance on consistent application of that
|
||||
system; it is up to the author/donor to decide if he or she is willing
|
||||
to distribute software through any other system and a licensee cannot
|
||||
impose that choice.
|
||||
|
||||
This section is intended to make thoroughly clear what is believed to
|
||||
be a consequence of the rest of this License.
|
||||
|
||||
8. If the distribution and/or use of the Program is restricted in
|
||||
certain countries either by patents or by copyrighted interfaces, the
|
||||
original copyright holder who places the Program under this License
|
||||
may add an explicit geographical distribution limitation excluding
|
||||
those countries, so that distribution is permitted only in or among
|
||||
countries not thus excluded. In such case, this License incorporates
|
||||
the limitation as if written in the body of this License.
|
||||
|
||||
9. The Free Software Foundation may publish revised and/or new versions
|
||||
of the General Public License from time to time. Such new versions will
|
||||
be similar in spirit to the present version, but may differ in detail to
|
||||
address new problems or concerns.
|
||||
|
||||
Each version is given a distinguishing version number. If the Program
|
||||
specifies a version number of this License which applies to it and "any
|
||||
later version", you have the option of following the terms and conditions
|
||||
either of that version or of any later version published by the Free
|
||||
Software Foundation. If the Program does not specify a version number of
|
||||
this License, you may choose any version ever published by the Free Software
|
||||
Foundation.
|
||||
|
||||
10. If you wish to incorporate parts of the Program into other free
|
||||
programs whose distribution conditions are different, write to the author
|
||||
to ask for permission. For software which is copyrighted by the Free
|
||||
Software Foundation, write to the Free Software Foundation; we sometimes
|
||||
make exceptions for this. Our decision will be guided by the two goals
|
||||
of preserving the free status of all derivatives of our free software and
|
||||
of promoting the sharing and reuse of software generally.
|
||||
|
||||
NO WARRANTY
|
||||
|
||||
11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
|
||||
FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
|
||||
OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
|
||||
PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
|
||||
OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
|
||||
TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
|
||||
PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
|
||||
REPAIR OR CORRECTION.
|
||||
|
||||
12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
|
||||
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
|
||||
REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
|
||||
INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
|
||||
OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
|
||||
TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
|
||||
YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
|
||||
PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
|
||||
POSSIBILITY OF SUCH DAMAGES.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
|
||||
How to Apply These Terms to Your New Programs
|
||||
|
||||
If you develop a new program, and you want it to be of the greatest
|
||||
possible use to the public, the best way to achieve this is to make it
|
||||
free software which everyone can redistribute and change under these terms.
|
||||
|
||||
To do so, attach the following notices to the program. It is safest
|
||||
to attach them to the start of each source file to most effectively
|
||||
convey the exclusion of warranty; and each file should have at least
|
||||
the "copyright" line and a pointer to where the full notice is found.
|
||||
|
||||
<one line to give the program's name and a brief idea of what it does.>
|
||||
Copyright (C) <year> <name of author>
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License along
|
||||
with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
|
||||
Also add information on how to contact you by electronic and paper mail.
|
||||
|
||||
If the program is interactive, make it output a short notice like this
|
||||
when it starts in an interactive mode:
|
||||
|
||||
Gnomovision version 69, Copyright (C) year name of author
|
||||
Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
|
||||
This is free software, and you are welcome to redistribute it
|
||||
under certain conditions; type `show c' for details.
|
||||
|
||||
The hypothetical commands `show w' and `show c' should show the appropriate
|
||||
parts of the General Public License. Of course, the commands you use may
|
||||
be called something other than `show w' and `show c'; they could even be
|
||||
mouse-clicks or menu items--whatever suits your program.
|
||||
|
||||
You should also get your employer (if you work as a programmer) or your
|
||||
school, if any, to sign a "copyright disclaimer" for the program, if
|
||||
necessary. Here is a sample; alter the names:
|
||||
|
||||
Yoyodyne, Inc., hereby disclaims all copyright interest in the program
|
||||
`Gnomovision' (which makes passes at compilers) written by James Hacker.
|
||||
|
||||
<signature of Ty Coon>, 1 April 1989
|
||||
Ty Coon, President of Vice
|
||||
|
||||
This General Public License does not permit incorporating your program into
|
||||
proprietary programs. If your program is a subroutine library, you may
|
||||
consider it more useful to permit linking proprietary applications with the
|
||||
library. If this is what you want to do, use the GNU Lesser General
|
||||
Public License instead of this License.
|
||||
|
|
@ -0,0 +1,493 @@
|
|||
2020-04-24 Alexey Kopytov <akopytov@gmail.com>
|
||||
|
||||
* version 1.0.20
|
||||
* build/CI/packaging: Add arm64 to Travis CI matrix (#358)
|
||||
* build/CI/packaging: add Ubuntu Focal
|
||||
* build/CI/packaging: remove Fedora Rawhide from CI matrix
|
||||
* build/CI/packaging: fix regression tests to work with MySQL 8.0.19+
|
||||
* build/CI/packaging: fix macOS builds in Travis
|
||||
* build/CI/packaging: remove Ubuntu Disco (EOL)
|
||||
|
||||
2019-12-08 Alexey Kopytov <akopytov@gmail.com>
|
||||
|
||||
* version 1.0.19
|
||||
* build/CI/packaging: fix Ubuntu packaging for Bionic and later versions
|
||||
* regression tests: compatibility fix for PostgreSQL 12
|
||||
* build/CI/packaging: fix macOs builds in Travis
|
||||
* build/CI/packaging: add Fedora 31.
|
||||
|
||||
2019-10-21 Alexey Kopytov <akopytov@gmail.com>
|
||||
|
||||
* version 1.0.18
|
||||
* build/CI/packaging: add Ubuntu Eoan.
|
||||
* build/CI/packaging: remove Ubuntu Cosmic (EOL).
|
||||
* build/CI/packaging: add CentOS 8.
|
||||
* build/CI/packaging: add Ubuntu Disco.
|
||||
* build/CI/packaging: remove Ubuntu Trusty (EOL).
|
||||
* build/CI/packaging: remove Fedora 28 (EOL).
|
||||
* build/CI/packaging: add Fedora 30.
|
||||
* build/CI/packaging: cherry-pick fix for LuaJIT/LuaJIT#484 to
|
||||
fix builds on macOS Mojave.
|
||||
* build/CI/packaging: add Debian Buster
|
||||
|
||||
2019-03-15 Alexey Kopytov <akopytov@gmail.com>
|
||||
|
||||
* version 1.0.17
|
||||
* build/CI/packaging: update RPM spec to support RHEL8-beta
|
||||
(thanks to Alexey Bychko for the patch)
|
||||
* regression tests: remove unnecessary error leading to opt_rate.t instability.
|
||||
* --rate mode: return a non-zero exit code on event queue
|
||||
overflow.
|
||||
* --rate mode: fix a bogus error about eventgen thread termination
|
||||
|
||||
2018-12-16 Alexey Kopytov <akopytov@gmail.com>
|
||||
|
||||
* version 1.0.16
|
||||
* build/CI/packaging: add Ubuntu Cosmic.
|
||||
* build/CI/packaging: add Fedora 29.
|
||||
* build/CI/packaging: remove Fedora 27 (EOL).
|
||||
* SQL API: fix GH-282 (Mysql's fetch_row() is broken)
|
||||
* --rate mode: fix latency stats skew on low rates
|
||||
* Lua: Add /usr/share/lua/5.1 to LUA_PATH and /usr/lib/lua/5.1
|
||||
to LUA_CPATH.
|
||||
* build/CI/packaging: add -Wvla to default compiler flags.
|
||||
* build/CI/packaging: fix debian/changelog format
|
||||
* build/CI/packaging: fix buildpack.sh to not push multiple file
|
||||
types to packagecloud.
|
||||
* build/CI/packaging: add libaio-dev to Debian/Ubuntu build
|
||||
dependencies.
|
||||
|
||||
2018-07-03 Alexey Kopytov <akopytov@gmail.com>
|
||||
|
||||
* version 1.0.15
|
||||
* CI/build/packaging: add Fedora 28
|
||||
* CI/build/packaging: add Ubuntu Bionic
|
||||
* CI/build/packaging: remove Fedora 26 (EOL)
|
||||
* CI/build/packaging: remove Debian Wheezy (EOL)
|
||||
* fileio: fix GH-229 (--file-fsync-freq=0 seems to prevent
|
||||
fsync() at the end of the test)
|
||||
* command line: improve parsing of boolean command line options
|
||||
* tests: fix GH-220 (Testsuite api_sql_mysql.t failed ...)
|
||||
* tests: fix GH-223 (test failure on ppc64)
|
||||
* tests: fix opt_help.t to pass when the binary is not
|
||||
configured with MySQL support
|
||||
* MySQL driver: use it by default in DB benchmarks
|
||||
|
||||
2018-04-01 Alexey Kopytov <akopytov@gmail.com>
|
||||
|
||||
* version 1.0.14
|
||||
* reports: fix JSON stats reporter to produce valid JSON
|
||||
(GH-195)
|
||||
* Lua SQL API: don't crash when query_row() is called with a
|
||||
SELECT returning empty result set
|
||||
* Lua SQL API: don't crash when bulk insert API calls are used
|
||||
out of order
|
||||
* regression tests: make PostgreSQL tests compatible with the
|
||||
new dump format introduced in 10.3
|
||||
* regression tests: minor stability and coverage improvements
|
||||
|
||||
2018-02-17 Alexey Kopytov <akopytov@gmail.com>
|
||||
|
||||
* version 1.0.13
|
||||
* remove Ubuntu Zesty from CI/build/packaging matrices (EOL)
|
||||
* minor cleanups in build scripts
|
||||
* improve report formatting for long latency values
|
||||
* fileio: --file-extra-flags now accepts a list of flags rather
|
||||
than just a single value
|
||||
* OLTP: re-prepare prepared statements after reconnects, i.e. in
|
||||
cases when a server connection is lost and sysbench is
|
||||
configured to ignore such errors
|
||||
|
||||
2018-01-17 Alexey Kopytov <akopytov@gmail.com>
|
||||
|
||||
* version 1.0.12
|
||||
* improve --rate mode precision for high argument values
|
||||
* add Fedora Rawhide and Debian Sid to CI matrix
|
||||
* fix compile-time architecture detection for some Broadwell
|
||||
CPUs which were incorrectly identified as Core 2.
|
||||
* remove build dependency on xxd (and vim-minimal package)
|
||||
* fix Lua API to correctly stop the benchmark when event()
|
||||
returns a value other than nil or false (thanks to caojiafeng
|
||||
for the patch)
|
||||
* fix the fileio benchmark when the specified file size is not a
|
||||
multiple of block size
|
||||
* fix the fileio benchmark to throw a descriptive error when the
|
||||
specified file size does not match the size of files created by
|
||||
'prepare'
|
||||
* remove Fedora 25 from CI/build/packaging matrices (EOL)
|
||||
* minor improvements in tests and documentation.
|
||||
|
||||
2017-12-09 Alexey Kopytov <akopytov@gmail.com>
|
||||
|
||||
* version 1.0.11
|
||||
* add Debian Stretch to CI/build/packaging matrices
|
||||
* add Fedora 27 to CI/build/packaging matrices
|
||||
* make statistic counters usable from Lua scripts
|
||||
* fix the PostgreSQL driver to be compatible with CockroachDB
|
||||
(GH-180)
|
||||
* fix oltp_insert.lua to work correctly when both --tables and
|
||||
--threads are greater than 1 (GH-178)
|
||||
* fix FreeBSD builds by adding -rdynamic to the default linker
|
||||
flags (GH-174)
|
||||
* minor documentation updates
|
||||
|
||||
2017-10-25 Alexey Kopytov <akopytov@gmail.com>
|
||||
|
||||
* version 1.0.10
|
||||
* fixed PK conflicts in oltp_insert.lua by creating empty tables
|
||||
on 'prepare'
|
||||
* made sysbench.opt available to init()/done() by exporting it
|
||||
to the global Lua state
|
||||
* added Fedora 26 (both x86_64 and AArch64) to the list of
|
||||
supported and tested distributions
|
||||
* fixed GH-172: sysbench 1.0.9 doesn't build with mariadb 10.2.8
|
||||
* add the /usr/local LuaRocks root directory to default LUA_PATH
|
||||
and LUA_CPATH
|
||||
* removed Fedora 24, Ubuntu Precise, Yakkety from default build
|
||||
matrices
|
||||
* added Ubuntu Artful to default build matrices
|
||||
|
||||
2017-09-05 Alexey Kopytov <akopytov@gmail.com>
|
||||
|
||||
* version 1.0.9
|
||||
* fixed oltp_delete.lua to not use INSERT statements for
|
||||
consistency with other oltp_* benchmarks (GH-168)
|
||||
* added a workaround for MySQL bug #87337 "8.0.2 reintroduces
|
||||
my_bool to client API"
|
||||
* fixed building on on Debian GNU/kFreeBSD (GH-161)
|
||||
* fixed building against MariaDB 10.2 (thanks to Xavier Bachelot
|
||||
for the patch, GH-160)
|
||||
|
||||
2017-07-04 Alexey Kopytov <akopytov@gmail.com>
|
||||
|
||||
* version 1.0.8
|
||||
* fixed api_report test for slow machines (thanks to @jcfp)
|
||||
* fileio: suggest to run prepare step on missing files (thanks
|
||||
to Heinrich Schuchardt)
|
||||
* JSON reports: removed an erroneous trailing comma (GH-139)
|
||||
* added events per second to the CPU benchmark report (GH-140)
|
||||
* fixed db_connect() in legacy SQL API to use the default value
|
||||
for --db-driver (GH-146)
|
||||
* removed busy-wait in the bounded event generation mode
|
||||
(--rate) to avoid CPU hogging
|
||||
|
||||
2017-05-15 Alexey Kopytov <akopytov@gmail.com>
|
||||
|
||||
* version 1.0.7
|
||||
* Ubuntu Zesty added to package build matrix
|
||||
* fixed GH-130: Mutex Benchmark Documentation
|
||||
* fixed latency reports in the --rate mode
|
||||
* fixed compiler warnings when building against MySQL 8.0 client
|
||||
libraries
|
||||
|
||||
2017-04-13 Alexey Kopytov <akopytov@gmail.com>
|
||||
|
||||
* version 1.0.6
|
||||
* no functional changes
|
||||
* many build- and packaging-related improvements
|
||||
* Linux packages are now automatically built using Travis CI and
|
||||
packpack, hosted by packagecloud.io
|
||||
|
||||
2017-04-02 Alexey Kopytov <akopytov@gmail.com>
|
||||
|
||||
* version 1.0.5
|
||||
* various build-related documentation updates
|
||||
* benchmark can now be specified by a module name on the command
|
||||
line
|
||||
* memory benchmark: performance and scalability improvements
|
||||
* fix ARMv6 builds with system ConcurrencyKit
|
||||
* fix GH-123: Table already exists error on prepare
|
||||
* fix GH-121: make buildhost cpudetection optional
|
||||
|
||||
2017-03-13 Alexey Kopytov <akopytov@gmail.com>
|
||||
|
||||
* version 1.0.4
|
||||
* fixed a number of compilation errors and warnings that were
|
||||
specific to 32-bit platforms
|
||||
* bundle cram (regression tests framework) and use it by default
|
||||
in 'make test'
|
||||
* bundled ConcurrencyKit updated to 0.6.0
|
||||
|
||||
2017-02-26 Alexey Kopytov <akopytov@gmail.com>
|
||||
|
||||
* version 1.0.3
|
||||
* LuaJIT scalability improvements for non-x86 architectures
|
||||
* performance optimizations in oltp_read_write.lua to avoid Lua
|
||||
string management
|
||||
* fixed Illumos builds (thanks to Dillon Amburgey)
|
||||
|
||||
2017-02-17 Alexey Kopytov <akopytov@gmail.com>
|
||||
|
||||
* version 1.0.2
|
||||
* improved scalability for --report-checkpoints mode
|
||||
* fix builds on CentoOS 6 and autoconf 2.63
|
||||
* support for Snap (http://snapcraft.io) packages
|
||||
|
||||
2017-02-05 Alexey Kopytov <akopytov@gmail.com>
|
||||
|
||||
* version 1.0.1
|
||||
* fix clock_gettime runtime failure built with macOS 10.11 and
|
||||
Xcode 8.x
|
||||
|
||||
2017-02-04 Aleksei Kopytov <akopytov@gmail.com>
|
||||
|
||||
* version 1.0.0
|
||||
* too much time and too many changes since the previous formal
|
||||
release, so briefly:
|
||||
* Lua scripts instead of hard-coded C tests for database
|
||||
("oltp") benchmarks + ability to create custom workloads
|
||||
* much better single-threaded performance
|
||||
* much better scalability
|
||||
* improvements and cleanups in command line syntax and options
|
||||
* latency histograms in cumulative statistic reports
|
||||
* report hooks to print statistics in custom formats
|
||||
(CSV/JSON/XML/etc.)
|
||||
* Dropped Windows support
|
||||
* Dropped support for Oracle, Drizzle and libattachsql drivers
|
||||
|
||||
2006-10-10 Alexey Kopytov <alexeyk@mysql.com>
|
||||
|
||||
* Removed the debugging code in OLTP test which got into 0.4.7 by mistake
|
||||
* Handle ER_CHECKREAD in the same way as deadlocks in the MySQL driver
|
||||
* version 0.4.8
|
||||
|
||||
2006-05-28 Alexey Kopytov <alexeyk@mysql.com>
|
||||
|
||||
* count fsync() time as request execution time in file-fsync-all mode
|
||||
|
||||
2006-05-24 Alexey Kopytov <alexeyk@mysql.com>
|
||||
|
||||
* Added --oltp-reconnect option
|
||||
|
||||
2006-05-18 Alexey Kopytov <alexeyk@mysql.com>
|
||||
|
||||
* Allow build with non-gcc compilers
|
||||
* Fixed random numbers generation on Solaris
|
||||
* Added --mysql-ssl option
|
||||
* version 0.4.7
|
||||
|
||||
2006-04-03 Alexey Kopytov <alexeyk@mysql.com>
|
||||
|
||||
* Added a warning for inaccurate gettimeofday() implementations
|
||||
* version 0.4.6
|
||||
|
||||
2006-03-10 Alexey Kopytov <alexeyk@mysql.com>
|
||||
|
||||
* Fixed crash at the end of OLTP test
|
||||
|
||||
2006-03-03 Alexey Kopytov <alexeyk@mysql.com>
|
||||
|
||||
* Made auto_increment id column optional
|
||||
* Use TYPE= or ENGINE= in MySQL driver depending on the version of client libraries
|
||||
|
||||
2006-01-17 Alexey Kopytov <alexeyk@mysql.com>
|
||||
|
||||
* version 0.4.5
|
||||
* Added several hosts capability to MySQL driver
|
||||
* Fixed several memory leaks in OLTP test
|
||||
|
||||
2005-12-14 Alexey Kopytov <alexeyk@mysql.com>
|
||||
|
||||
* Renamed option 'mysql-table-type' to 'mysql-table-engine'
|
||||
* It's now possible to pass arbitrary engine names to MySQL driver
|
||||
* Transactions support must be explicitly specified with
|
||||
'mysql-engine-trx' option for those engines, which are unknown to SysBench
|
||||
|
||||
2005-09-27 Alexey Kopytov <alexeyk@mysql.com>
|
||||
|
||||
* Changed 'thread fairness' calculation from percents to stddev
|
||||
* Added validation mode to OLTP test (--validate switch)
|
||||
* Remove auto_increment from the 'id' field before running OLTP tests
|
||||
* Print separate time for query execution and result fetching in --debug mode
|
||||
* version 0.4.3
|
||||
|
||||
2005-07-25 Alexey Kopytov <alexeyk@mysql.com>
|
||||
|
||||
* Minor cleanups in help messages
|
||||
* Several FreeBSD-related fixes
|
||||
* Fixed the Oracle driver
|
||||
* Version 0.4.1
|
||||
|
||||
2005-03-04 Alexey Kopytov <alexeyk@mysql.com>
|
||||
|
||||
* Fixed a lot of small bugs, including portability issues on Mac OS X,
|
||||
64-bit platforms and old MySQL versions
|
||||
* Documentation added to the main tree
|
||||
* New validation mode in fileio test
|
||||
|
||||
2005-01-27 Alexey Kopytov <alexeyk@mysql.com>
|
||||
|
||||
* Fixed compilation on Solaris
|
||||
* Added call to thr_setconcurrency() on Solaris
|
||||
* Fixed an overflow bug in sb_timer_current()
|
||||
* Changed the default number of threads to 1
|
||||
* Added non-transactional mode to the OLTP test
|
||||
* Fixed bug with excessive number of connections in OLTP test
|
||||
* Handle ER_LOCK_WAIT_TIMEOUT in the same way as ER_LOCK_DEADLOCK
|
||||
* Version 0.3.2
|
||||
|
||||
2004-07-27 Alexey Kopytov <alexeyk@mysql.com>
|
||||
|
||||
* Fixed MySQL driver to use new PS API in MySQL >= 4.1.2
|
||||
|
||||
2004-07-12 Alexey Kopytov <alexeyk@mysql.com>
|
||||
|
||||
* Fixed final fsync in random I/O requests
|
||||
* Fixed several race conditions
|
||||
|
||||
2004-07-09 Alexey Kopytov <alexeyk@mysql.com>
|
||||
|
||||
* Removed --oltp-time-limit option (obsoleted by --max-time)
|
||||
|
||||
2004-07-06 Alexey Kopytov <alexeyk@mysql.com>
|
||||
|
||||
* Changed statistics output to more human-readable format
|
||||
|
||||
2004-07-04 Alexey Kopytov <alexeyk@mysql.com>
|
||||
|
||||
* Added new logger interface to internal API
|
||||
* Modified all tests to use the new logger interface
|
||||
|
||||
2004-06-17 Alexey Kopytov <alexeyk@mysql.com>
|
||||
|
||||
* Fixed table type autodetection with MySQL >= 4.1
|
||||
|
||||
2004-06-06 Alexey Kopytov <alexeyk@mysql.com>
|
||||
|
||||
* Added preliminary support of prepared statements to DB API
|
||||
|
||||
2004-05-31 Alexey Kopytov <alexeyk@mysql.com>
|
||||
|
||||
* Added slow-mmap mode for 32-bit boxes in fileio test
|
||||
|
||||
2004-05-30 Alexey Kopytov <alexeyk@mysql.com>
|
||||
|
||||
* Fixed compilation with gcc >= 3.3
|
||||
* Fixed 'prepare' command for sequential write test
|
||||
|
||||
2004-05-26 Alexey Kopytov <alexeyk@mysql.com>
|
||||
|
||||
* Changed formatting of file sizes in output
|
||||
* Fixed type cast warning on SuSE 8.1
|
||||
|
||||
2004-05-21 Alexey Kopytov <alexeyk@mysql.com>
|
||||
|
||||
* Added mutex performance benchmark
|
||||
|
||||
2004-05-12 Alexey Kopytov <alexeyk@mysql.com>
|
||||
|
||||
* Extended memory benchmark to calculate more useful results
|
||||
|
||||
2004-05-10 Alexey Kopytov <alexeyk@mysql.com>
|
||||
|
||||
* Split test file creation, test running and cleaning up into separate
|
||||
commands (prepare, run, cleanup) for fileio test
|
||||
|
||||
2004-05-05 Alexey Kopytov <alexeyk@mysql.com>
|
||||
|
||||
* Removed limit on maximum block size for fileio test
|
||||
|
||||
2004-05-04 Alexey Kopytov <alexeyk@mysql.com>
|
||||
|
||||
* added --max-time option to limit total test execution time
|
||||
|
||||
2004-05-03 Alexey Kopytov <alexeyk@mysql.com>
|
||||
|
||||
* Fixed compilation with --without-mysql option.
|
||||
|
||||
2004-04-13 Alexey Kopytov <alexeyk@mysql.com>
|
||||
|
||||
* Added mmaped I/O support to fileio test
|
||||
|
||||
2004-04-11 Alexey Kopytov <alexeyk@mysql.com>
|
||||
|
||||
* Changed default table size to a lower value in OLTP test
|
||||
|
||||
2004-04-07 Alexey Kopytov <alexeyk@mysql.com>
|
||||
|
||||
* Added automatic table type detection to MySQL driver
|
||||
* Changed the default table type for MySQL driver to InnoDB
|
||||
* Added support for BDB and NDB table types
|
||||
|
||||
2004-04-06 Alexey Kopytov <alexeyk@mysql.com>
|
||||
|
||||
* Added autoconf macro to handle older (incompatible) version of
|
||||
libaio.h
|
||||
|
||||
2004-04-05 Alexey Kopytov <alexeyk@mysql.com>
|
||||
|
||||
* Fixed compilation on 64-bit systems
|
||||
* Replaced Linux AIO calls with more portable equivalents
|
||||
|
||||
2004-04-04 Alexey Kopytov <alexeyk@mysql.com>
|
||||
|
||||
* Added parameter to specify maximum number of queued operations
|
||||
in fileio async mode (file-async-backlog)
|
||||
* Added parameter to specify extra open() flags (file-extra-flags)
|
||||
* Fixed memory allocation bug in command line parser
|
||||
|
||||
2004-04-02 Alexey Kopytov <alexeyk@mysql.com>
|
||||
|
||||
* Added Linux asynchronous I/O support to fileio test
|
||||
* Fixed bug with statistic counters
|
||||
|
||||
2004-04-01 Alexey Kopytov <alexeyk@mysql.com>
|
||||
|
||||
* Added test file creation to fileio test
|
||||
* Added read-only mode to OLTP test
|
||||
|
||||
2004-03-31 Alexey Kopytov <alexeyk@mysql.com>
|
||||
|
||||
* Close database connections in OLTP test
|
||||
* Added file-fsync-all mode for fileio test
|
||||
|
||||
2004-03-30 Alexey Kopytov <alexeyk@mysql.com>
|
||||
|
||||
* Added myisam-max-rows option for MySQL driver
|
||||
* Fixed configure.ac for cases when no MySQL libraries found
|
||||
|
||||
2004-03-10 Alexey Kopytov <alexeyk@mysql.com>
|
||||
|
||||
* Implement proper handling of table locks in OLTP test
|
||||
|
||||
2004-03-09 Alexey Kopytov <alexeyk@mysql.com>
|
||||
|
||||
* Recognize MySQL table type when creating test database
|
||||
* Fix driver-specific options
|
||||
* Now it's possible to pass MySQL root directory in --with-mysql option
|
||||
* Trim trailing '.libs' if user passed it in --with-mysql-libs option
|
||||
to configure
|
||||
|
||||
2004-03-08 Alexey Kopytov <alexeyk@mysql.com>
|
||||
|
||||
* Build drivers and tests as separate libraries (first step to
|
||||
dynamically loaded modules)
|
||||
* Display help when required arguments are missing in fileio test
|
||||
* Changed code formatting to match MySQL coding guidelines
|
||||
|
||||
2004-03-04 Alexey Kopytov <alexeyk@mysql.com>
|
||||
|
||||
* Generalized DB-dependent code
|
||||
* Added 'database capabilities' feature
|
||||
|
||||
2004-02-28 Alexey Kopytov <alexeyk@mysql.com>
|
||||
|
||||
* Fixed possible memory leak in sql request generator
|
||||
|
||||
2004-03-27 Alexey Kopytov <alexeyk@mysql.com>
|
||||
|
||||
* Split OLTP code into DB-independent part and MySQL driver
|
||||
|
||||
2004-02-23 Alexey Kopytov <alexeyk@mysql.com>
|
||||
|
||||
* Use libtool for linking with external libraries
|
||||
* Statically link external libraries when they are not installed
|
||||
|
||||
2004-02-19 Alexey Kopytov <alexeyk@mysql.com>
|
||||
|
||||
* Print more info when configure finds no MySQL development files
|
||||
* Added --with-mysql-includes and --with-mysql-libs to configure
|
||||
* Fixed compilation error when compiling without MySQL support
|
||||
* Combine several inserts into one query to speed up database creation
|
||||
|
||||
|
||||
|
|
@ -0,0 +1,46 @@
|
|||
# Copyright (C) 2004 MySQL AB
|
||||
# Copyright (C) 2004-2017 Alexey Kopytov <akopytov@gmail.com>
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation; either version 2 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, write to the Free Software
|
||||
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
|
||||
ACLOCAL_AMFLAGS = -I m4
|
||||
AM_DISTCHECK_CONFIGURE_FLAGS = --without-mysql
|
||||
|
||||
if USE_BUNDLED_LUAJIT
|
||||
LUAJIT_DIR = third_party/luajit
|
||||
endif
|
||||
|
||||
if USE_BUNDLED_CK
|
||||
CK_DIR = third_party/concurrency_kit
|
||||
endif
|
||||
|
||||
SUBDIRS = doc $(LUAJIT_DIR) $(CK_DIR) src tests
|
||||
|
||||
EXTRA_DIST = autogen.sh README.md README-WIN.txt README-Oracle.md ChangeLog \
|
||||
snap/snapcraft.yaml.in third_party/cram \
|
||||
debian/changelog debian/compat debian/control debian/copyright \
|
||||
debian/dirs debian/docs debian/install debian/rules \
|
||||
debian/source/format \
|
||||
rpm/sysbench.spec \
|
||||
scripts/buildpack.sh
|
||||
|
||||
dist-hook:
|
||||
$(MAKE) -C $(distdir)/third_party/cram clean
|
||||
|
||||
test:
|
||||
cd tests && $(MAKE) test
|
||||
|
||||
clean-local:
|
||||
$(MAKE) -C $(top_srcdir)/third_party/cram clean
|
||||
|
|
@ -0,0 +1,56 @@
|
|||
**WARNING: Oracle support is unmaintained as of sysbench 1.0. You may
|
||||
want to
|
||||
try [sysbench 0.5](https://github.com/akopytov/sysbench/tree/0.5)
|
||||
instead. The corresponding code and instructions below are still in the
|
||||
source tree in case somebody wants to update them. Patches are always
|
||||
welcome! **
|
||||
|
||||
--------------------------------------------------------------
|
||||
Oracle Build steps
|
||||
--------------------------------------------------------------
|
||||
|
||||
Using Ubuntu 14.04 - intructions dated for 21/09/2016 (Was built on AWS
|
||||
in an r3.xlarge These actions were done against 0.5 checkout)
|
||||
|
||||
* Setup Oracle Instant Client -
|
||||
https://help.ubuntu.com/community/Oracle%20Instant%20Client download
|
||||
from
|
||||
http://www.oracle.com/technetwork/database/features/instant-client/index-097480.html.
|
||||
|
||||
The following RPM's and upload them to the server:
|
||||
- oracle-instantclient12.1-basic-12.1.0.2.0-1.x86_64.rpm
|
||||
- oracle-instantclient12.1-devel-12.1.0.2.0-1.x86_64.rpm
|
||||
|
||||
```
|
||||
alien -i oracle-instantclient12.1-basic-12.1.0.2.0-1.x86_64.rpm
|
||||
alien -i oracle-instantclient12.1-devel-12.1.0.2.0-1.x86_64.rpm
|
||||
```
|
||||
|
||||
* Install Cuda - http://www.r-tutor.com/gpu-computing/cuda-installation/cuda7.5-ubuntu
|
||||
|
||||
```
|
||||
wget http://developer.download.nvidia.com/compute/cuda/repos/ubuntu1404/x86_64/cuda-repo-ubuntu1404_7.5-18_amd64.deb
|
||||
sudo dpkg -i cuda-repo-ubuntu1404_7.5-18_amd64.deb
|
||||
sudo apt-get update
|
||||
sudo apt-get install cuda
|
||||
export CUDA_HOME=/usr/local/cuda-7.5
|
||||
export LD_LIBRARY_PATH=${CUDA_HOME}/lib64
|
||||
|
||||
PATH=${CUDA_HOME}/bin:${PATH}
|
||||
export PATH
|
||||
echo "/usr/lib/oracle/12.1/client64/lib" > /etc/ld.so.conf.d/oracle-client-12.1.conf
|
||||
ldconfig
|
||||
```
|
||||
|
||||
* Build sysbench
|
||||
Use the following `configure` option to build with Oracle support:
|
||||
```
|
||||
./configure --with-oracle="/usr/lib/oracle/12.1/client64"
|
||||
```
|
||||
|
||||
Run the following commands to allow sysbench use the full number of cores:
|
||||
```
|
||||
sudo sh -c 'for x in /sys/class/net/eth0/queues/rx-*; do echo ffffffff> $x/rps_cpus; done'
|
||||
sudo sh -c "echo 32768 > /proc/sys/net/core/rps_sock_flow_entries"
|
||||
sudo sh -c "echo 4096 > /sys/class/net/eth0/queues/rx-0/rps_flow_cnt"
|
||||
```
|
||||
|
|
@ -0,0 +1,11 @@
|
|||
As of sysbench 1.0 support for native Windows builds was dropped. It may
|
||||
be re-introduced in later versions.
|
||||
|
||||
Currently, the recommended way to build sysbench on Windows is using
|
||||
Windows Subsystem for Linux available in Windows 10:
|
||||
https://msdn.microsoft.com/en-us/commandline/wsl/about
|
||||
|
||||
After installing WSL and getting a bash prompt, following Debian/Ubuntu
|
||||
build instructions is sufficient.
|
||||
|
||||
Alternatively, one can build and use sysbench 0.5 natively for Windows.
|
||||
|
|
@ -0,0 +1,290 @@
|
|||
[![Latest Release][release-badge]][release-url]
|
||||
[![Build Status][travis-badge]][travis-url]
|
||||
[![Debian Packages][deb-badge]][deb-url]
|
||||
[![RPM Packages][rpm-badge]][rpm-url]
|
||||
[![Coverage Status][coveralls-badge]][coveralls-url]
|
||||
[![License][license-badge]][license-url]
|
||||
|
||||
<!-- markdown-toc start - Don't edit this section. Run M-x markdown-toc-generate-toc again -->
|
||||
**Table of Contents**
|
||||
|
||||
- [sysbench](#sysbench)
|
||||
- [Features](#features)
|
||||
- [Installing from Binary Packages](#installing-from-binary-packages)
|
||||
- [Linux](#linux)
|
||||
- [macOS](#macos)
|
||||
- [Windows](#windows)
|
||||
- [Building and Installing From Source](#building-and-installing-from-source)
|
||||
- [Build Requirements](#build-requirements)
|
||||
- [Windows](#windows)
|
||||
- [Debian/Ubuntu](#debianubuntu)
|
||||
- [RHEL/CentOS](#rhelcentos)
|
||||
- [Fedora](#fedora)
|
||||
- [macOS](#macos)
|
||||
- [Build and Install](#build-and-install)
|
||||
- [Usage](#usage)
|
||||
- [General Syntax](#general-syntax)
|
||||
- [General Command Line Options](#general-command-line-options)
|
||||
- [Versioning](#versioning)
|
||||
|
||||
<!-- markdown-toc end -->
|
||||
|
||||
# sysbench
|
||||
|
||||
sysbench is a scriptable multi-threaded benchmark tool based on
|
||||
LuaJIT. It is most frequently used for database benchmarks, but can also
|
||||
be used to create arbitrarily complex workloads that do not involve a
|
||||
database server.
|
||||
|
||||
sysbench comes with the following bundled benchmarks:
|
||||
|
||||
- `oltp_*.lua`: a collection of OLTP-like database benchmarks
|
||||
- `fileio`: a filesystem-level benchmark
|
||||
- `cpu`: a simple CPU benchmark
|
||||
- `memory`: a memory access benchmark
|
||||
- `threads`: a thread-based scheduler benchmark
|
||||
- `mutex`: a POSIX mutex benchmark
|
||||
|
||||
## Features
|
||||
|
||||
- extensive statistics about rate and latency is available, including
|
||||
latency percentiles and histograms;
|
||||
- low overhead even with thousands of concurrent threads. sysbench is
|
||||
capable of generating and tracking hundreds of millions of events per
|
||||
second;
|
||||
- new benchmarks can be easily created by implementing pre-defined hooks
|
||||
in user-provided Lua scripts;
|
||||
- can be used as a general-purpose Lua interpreter as well, simply
|
||||
replace `#!/usr/bin/lua` with `#!/usr/bin/sysbench` in your script.
|
||||
|
||||
# Installing from Binary Packages
|
||||
|
||||
## Linux
|
||||
|
||||
The easiest way to download and install sysbench on Linux is using
|
||||
binary package repositories hosted by
|
||||
[packagecloud](https://packagecloud.io). The repositories are
|
||||
automatically updated on each sysbench release. Currently x86_64, i386
|
||||
and aarch64 binaries are available.
|
||||
|
||||
Multiple methods to download and install sysbench packages are available and
|
||||
described at <https://packagecloud.io/akopytov/sysbench/install>.
|
||||
|
||||
Quick install instructions:
|
||||
|
||||
- Debian/Ubuntu
|
||||
``` shell
|
||||
curl -s https://packagecloud.io/install/repositories/akopytov/sysbench/script.deb.sh | sudo bash
|
||||
sudo apt -y install sysbench
|
||||
```
|
||||
|
||||
- RHEL/CentOS:
|
||||
``` shell
|
||||
curl -s https://packagecloud.io/install/repositories/akopytov/sysbench/script.rpm.sh | sudo bash
|
||||
sudo yum -y install sysbench
|
||||
```
|
||||
|
||||
- Fedora:
|
||||
``` shell
|
||||
curl -s https://packagecloud.io/install/repositories/akopytov/sysbench/script.rpm.sh | sudo bash
|
||||
sudo dnf -y install sysbench
|
||||
```
|
||||
|
||||
## macOS
|
||||
|
||||
On macOS, up-to-date sysbench packages are available from Homebrew:
|
||||
```shell
|
||||
# Add --with-postgresql if you need PostgreSQL support
|
||||
brew install sysbench
|
||||
```
|
||||
|
||||
## Windows
|
||||
As of sysbench 1.0 support for native Windows builds was dropped. It may
|
||||
be re-introduced in later releases. Currently, the recommended way to
|
||||
obtain sysbench on Windows is
|
||||
using
|
||||
[Windows Subsystem for Linux available in Windows 10](https://msdn.microsoft.com/en-us/commandline/wsl/about).
|
||||
|
||||
After installing WSL and getting into he bash prompt on Windows
|
||||
following Debian/Ubuntu installation instructions is
|
||||
sufficient. Alternatively, one can use WSL to build and install sysbench
|
||||
from source, or use an older sysbench release to build a native binary.
|
||||
|
||||
# Building and Installing From Source
|
||||
|
||||
It is recommended to install sysbench from the official binary
|
||||
packages as described in
|
||||
[Installing from Binary Packages](#installing-from-binary-packages). Below
|
||||
are instruction for cases when you want to use sysbench on an
|
||||
architecture for which no binary packages are available.
|
||||
|
||||
## Build Requirements
|
||||
|
||||
### Windows
|
||||
As of sysbench 1.0 support for native Windows builds was
|
||||
dropped. It may be re-introduced in later versions. Currently, the
|
||||
recommended way to build sysbench on Windows is using
|
||||
[Windows Subsystem for Linux available in Windows 10](https://msdn.microsoft.com/en-us/commandline/wsl/about).
|
||||
|
||||
After installing WSL and getting into bash prompt on Windows, following
|
||||
Debian/Ubuntu build instructions is sufficient. Alternatively, one can
|
||||
build and use an older 0.5 release on Windows.
|
||||
|
||||
### Debian/Ubuntu
|
||||
``` shell
|
||||
apt -y install make automake libtool pkg-config libaio-dev
|
||||
# For MySQL support
|
||||
apt -y install libmysqlclient-dev libssl-dev
|
||||
# For PostgreSQL support
|
||||
apt -y install libpq-dev
|
||||
```
|
||||
|
||||
### RHEL/CentOS
|
||||
``` shell
|
||||
yum -y install make automake libtool pkgconfig libaio-devel
|
||||
# For MySQL support, replace with mysql-devel on RHEL/CentOS 5
|
||||
yum -y install mariadb-devel openssl-devel
|
||||
# For PostgreSQL support
|
||||
yum -y install postgresql-devel
|
||||
```
|
||||
|
||||
### Fedora
|
||||
``` shell
|
||||
dnf -y install make automake libtool pkgconfig libaio-devel
|
||||
# For MySQL support
|
||||
dnf -y install mariadb-devel openssl-devel
|
||||
# For PostgreSQL support
|
||||
dnf -y install postgresql-devel
|
||||
```
|
||||
|
||||
### macOS
|
||||
|
||||
Assuming you have Xcode (or Xcode Commane Line Tools) and Homebrew installed:
|
||||
``` shell
|
||||
brew install automake libtool openssl pkg-config
|
||||
# For MySQL support
|
||||
brew install mysql
|
||||
# For PostgreSQL support
|
||||
brew install postgresql
|
||||
# openssl is not linked by Homebrew, this is to avoid "ld: library not found for -lssl"
|
||||
export LDFLAGS=-L/usr/local/opt/openssl/lib
|
||||
```
|
||||
|
||||
## Build and Install
|
||||
``` shell
|
||||
./autogen.sh
|
||||
# Add --with-pgsql to build with PostgreSQL support
|
||||
./configure
|
||||
make -j
|
||||
make install
|
||||
```
|
||||
|
||||
The above will build sysbench with MySQL support by default. If you have
|
||||
MySQL headers and libraries in non-standard locations (and no
|
||||
`mysql_config` can be found in the `PATH`), you can specify them
|
||||
explicitly with `--with-mysql-includes` and `--with-mysql-libs` options
|
||||
to `./configure`.
|
||||
|
||||
To compile sysbench without MySQL support, use `--without-mysql`. If no
|
||||
database drivers are available database-related scripts will not work,
|
||||
but other benchmarks will be functional.
|
||||
|
||||
See [README-Oracle.md](README-Oracle.md) for instructions on building
|
||||
with Oracle client libraries.
|
||||
|
||||
# Usage
|
||||
|
||||
## General Syntax
|
||||
|
||||
The general command line syntax for sysbench is:
|
||||
|
||||
sysbench [options]... [testname] [command]
|
||||
|
||||
- *testname* is an optional name of a built-in test (e.g. `fileio`,
|
||||
`memory`, `cpu`, etc.), or a name of one of the bundled Lua scripts
|
||||
(e.g. `oltp_read_only`), or a *path* to a custom Lua script. If no
|
||||
test name is specified on the command line (and thus, there is no
|
||||
*command* too, as in that case it would be parsed as a *testname*), or
|
||||
the test name is a dash ("`-`"), then sysbench expects a Lua script to
|
||||
execute on its standard input.
|
||||
|
||||
- *command* is an optional argument that will be passed by sysbench to
|
||||
the built-in test or script specified with *testname*. *command*
|
||||
defines the *action* that must be performed by the test. The list of
|
||||
available commands depends on a particular test. Some tests also
|
||||
implement their own custom commands.
|
||||
|
||||
Below is a description of typical test commands and their purpose:
|
||||
|
||||
+ `prepare`: performs preparative actions for those tests which need
|
||||
them, e.g. creating the necessary files on disk for the `fileio`
|
||||
test, or filling the test database for database benchmarks.
|
||||
+ `run`: runs the actual test specified with the *testname*
|
||||
argument. This command is provided by all tests.
|
||||
+ `cleanup`: removes temporary data after the test run in those
|
||||
tests which create one.
|
||||
+ `help`: displays usage information for the test specified with the
|
||||
*testname* argument. This includes the full list of commands
|
||||
provided by the test, so it should be used to get the available
|
||||
commands.
|
||||
|
||||
- *options* is a list of zero or more command line options starting with
|
||||
`'--'`. As with commands, the `sysbench testname help` command
|
||||
should be used to describe available options provided by a
|
||||
particular test.
|
||||
|
||||
See [General command line options](README.md#general-command-line-options)
|
||||
for a description of general options provided by sysbench itself.
|
||||
|
||||
|
||||
You can use `sysbench --help` to display the general command line syntax
|
||||
and options.
|
||||
|
||||
## General Command Line Options
|
||||
|
||||
The table below lists the supported common options, their descriptions and default values:
|
||||
|
||||
*Option* | *Description* | *Default value*
|
||||
----------------------|---------------|----------------
|
||||
| `--threads` | The total number of worker threads to create | 1 |
|
||||
| `--events` | Limit for total number of requests. 0 (the default) means no limit | 0 |
|
||||
| `--time` | Limit for total execution time in seconds. 0 means no limit | 10 |
|
||||
| `--rate` | Average transactions rate. The number specifies how many events (transactions) per seconds should be executed by all threads on average. 0 (default) means unlimited rate, i.e. events are executed as fast as possible | 0 |
|
||||
| `--thread-stack-size` | Size of stack for each thread | 32K |
|
||||
| `--report-interval` | Periodically report intermediate statistics with a specified interval in seconds. Note that statistics produced by this option is per-interval rather than cumulative. 0 disables intermediate reports | 0 |
|
||||
| `--debug` | Print more debug info | off |
|
||||
| `--validate` | Perform validation of test results where possible | off |
|
||||
| `--help` | Print help on general syntax or on a test mode specified with --test, and exit | off |
|
||||
| `--verbosity` | Verbosity level (0 - only critical messages, 5 - debug) | 4 |
|
||||
| `--percentile` | sysbench measures execution times for all processed requests to display statistical information like minimal, average and maximum execution time. For most benchmarks it is also useful to know a request execution time value matching some percentile (e.g. 95% percentile means we should drop 5% of the most long requests and choose the maximal value from the remaining ones). This option allows to specify a percentile rank of query execution times to count | 95 |
|
||||
|
||||
Note that numerical values for all *size* options (like `--thread-stack-size` in this table) may be specified by appending the corresponding multiplicative suffix (K for kilobytes, M for megabytes, G for gigabytes and T for terabytes).
|
||||
|
||||
# Versioning
|
||||
|
||||
For transparency and insight into its release cycle, and for striving to maintain backward compatibility, sysbench will be maintained under the Semantic Versioning guidelines as much as possible.
|
||||
|
||||
Releases will be numbered with the following format:
|
||||
|
||||
`<major>.<minor>.<patch>`
|
||||
|
||||
And constructed with the following guidelines:
|
||||
|
||||
* Breaking backward compatibility bumps the major (and resets the minor and patch)
|
||||
* New additions without breaking backward compatibility bumps the minor (and resets the patch)
|
||||
* Bug fixes and misc changes bumps the patch
|
||||
|
||||
For more information on SemVer, please visit [http://semver.org/](http://semver.org/).
|
||||
|
||||
[coveralls-badge]: https://coveralls.io/repos/github/akopytov/sysbench/badge.svg?branch=1.0
|
||||
[coveralls-url]: https://coveralls.io/github/akopytov/sysbench?branch=1.0
|
||||
[travis-badge]: https://travis-ci.org/akopytov/sysbench.svg?branch=1.0
|
||||
[travis-url]: https://travis-ci.org/akopytov/sysbench?branch=1.0
|
||||
[license-badge]: https://img.shields.io/badge/license-GPLv2-blue.svg
|
||||
[license-url]: COPYING
|
||||
[release-badge]: https://img.shields.io/github/release/akopytov/sysbench.svg
|
||||
[release-url]: https://github.com/akopytov/sysbench/releases/latest
|
||||
[deb-badge]: https://img.shields.io/badge/Packages-Debian-red.svg?style=flat
|
||||
[deb-url]: https://packagecloud.io/akopytov/sysbench?filter=debs
|
||||
[rpm-badge]: https://img.shields.io/badge/Packages-RPM-blue.svg?style=flat
|
||||
[rpm-url]: https://packagecloud.io/akopytov/sysbench?filter=rpms
|
||||
|
|
@ -0,0 +1,98 @@
|
|||
#!/usr/bin/env bash
|
||||
# Taken from lighthttpd server (BSD). Thanks Jan!
|
||||
# Run this to generate all the initial makefiles, etc.
|
||||
|
||||
die() { echo "$@"; exit 1; }
|
||||
|
||||
ACLOCAL_FLAGS="-I m4"
|
||||
LIBTOOLIZE_FLAGS="--copy --force"
|
||||
AUTOMAKE_FLAGS="-c --foreign --add-missing"
|
||||
|
||||
ARGV0=$0
|
||||
ARGS="$@"
|
||||
|
||||
|
||||
run() {
|
||||
echo "$ARGV0: running \`$@' $ARGS"
|
||||
$@ $ARGS
|
||||
}
|
||||
|
||||
## jump out if one of the programs returns 'false'
|
||||
set -e
|
||||
|
||||
|
||||
if test x$ACLOCAL = x; then
|
||||
if test \! "x`which aclocal-1.10 2> /dev/null | grep -v '^no'`" = x; then
|
||||
ACLOCAL=aclocal-1.10
|
||||
elif test \! "x`which aclocal110 2> /dev/null | grep -v '^no'`" = x; then
|
||||
ACLOCAL=aclocal110
|
||||
elif test \! "x`which aclocal 2> /dev/null | grep -v '^no'`" = x; then
|
||||
ACLOCAL=aclocal
|
||||
else
|
||||
echo "automake 1.10.x (aclocal) wasn't found, exiting"; exit 1
|
||||
fi
|
||||
fi
|
||||
|
||||
if test x$LIBTOOLIZE = x; then
|
||||
if test \! "x`which libtoolize15 2> /dev/null | grep -v '^no'`" = x; then
|
||||
LIBTOOLIZE=libtoolize15
|
||||
elif test \! "x`which libtoolize14 2> /dev/null | grep -v '^no'`" = x; then
|
||||
LIBTOOLIZE=libtoolize14
|
||||
elif test \! "x`which glibtoolize 2> /dev/null | grep -v '^no'`" = x; then
|
||||
LIBTOOLIZE=glibtoolize
|
||||
elif test \! "x`which libtoolize 2> /dev/null | grep -v '^no'`" = x; then
|
||||
LIBTOOLIZE=libtoolize
|
||||
else
|
||||
echo "libtoolize 1.4+ wasn't found, exiting"; exit 1
|
||||
fi
|
||||
fi
|
||||
|
||||
if test x$AUTOMAKE = x; then
|
||||
if test \! "x`which automake-1.10 2> /dev/null | grep -v '^no'`" = x; then
|
||||
AUTOMAKE=automake-1.10
|
||||
elif test \! "x`which automake110 2> /dev/null | grep -v '^no'`" = x; then
|
||||
AUTOMAKE=automake110
|
||||
elif test \! "x`which automake 2> /dev/null | grep -v '^no'`" = x; then
|
||||
AUTOMAKE=automake
|
||||
else
|
||||
echo "automake 1.10.x wasn't found, exiting"; exit 1
|
||||
fi
|
||||
fi
|
||||
|
||||
|
||||
## macosx has autoconf-2.59 and autoconf-2.60
|
||||
if test x$AUTOCONF = x; then
|
||||
if test \! "x`which autoconf-2.59 2> /dev/null | grep -v '^no'`" = x; then
|
||||
AUTOCONF=autoconf-2.59
|
||||
elif test \! "x`which autoconf259 2> /dev/null | grep -v '^no'`" = x; then
|
||||
AUTOCONF=autoconf259
|
||||
elif test \! "x`which autoconf 2> /dev/null | grep -v '^no'`" = x; then
|
||||
AUTOCONF=autoconf
|
||||
else
|
||||
echo "autoconf 2.59+ wasn't found, exiting"; exit 1
|
||||
fi
|
||||
fi
|
||||
|
||||
if test x$AUTOHEADER = x; then
|
||||
if test \! "x`which autoheader-2.59 2> /dev/null | grep -v '^no'`" = x; then
|
||||
AUTOHEADER=autoheader-2.59
|
||||
elif test \! "x`which autoheader259 2> /dev/null | grep -v '^no'`" = x; then
|
||||
AUTOHEADER=autoheader259
|
||||
elif test \! "x`which autoheader 2> /dev/null | grep -v '^no'`" = x; then
|
||||
AUTOHEADER=autoheader
|
||||
else
|
||||
echo "autoconf 2.59+ (autoheader) wasn't found, exiting"; exit 1
|
||||
fi
|
||||
fi
|
||||
|
||||
run $LIBTOOLIZE $LIBTOOLIZE_FLAGS || die "Can't execute libtoolize"
|
||||
run $ACLOCAL $ACLOCAL_FLAGS || die "Can't execute aclocal"
|
||||
run $AUTOHEADER || die "Can't execute autoheader"
|
||||
run $AUTOMAKE $AUTOMAKE_FLAGS || die "Can't execute automake"
|
||||
run $AUTOCONF || die "Can't execute autoconf"
|
||||
echo -n "Libtoolized with: "
|
||||
$LIBTOOLIZE --version | head -1
|
||||
echo -n "Automade with: "
|
||||
$AUTOMAKE --version | head -1
|
||||
echo -n "Configured with: "
|
||||
$AUTOCONF --version | head -1
|
||||
|
|
@ -0,0 +1,666 @@
|
|||
#! /bin/sh
|
||||
# Output a system dependent set of variables, describing how to set the
|
||||
# run time search path of shared libraries in an executable.
|
||||
#
|
||||
# Copyright 1996-2007 Free Software Foundation, Inc.
|
||||
# Taken from GNU libtool, 2001
|
||||
# Originally by Gordon Matzigkeit <gord@gnu.ai.mit.edu>, 1996
|
||||
#
|
||||
# This file is free software; the Free Software Foundation gives
|
||||
# unlimited permission to copy and/or distribute it, with or without
|
||||
# modifications, as long as this notice is preserved.
|
||||
#
|
||||
# The first argument passed to this file is the canonical host specification,
|
||||
# CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM
|
||||
# or
|
||||
# CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM
|
||||
# The environment variables CC, GCC, LDFLAGS, LD, with_gnu_ld
|
||||
# should be set by the caller.
|
||||
#
|
||||
# The set of defined variables is at the end of this script.
|
||||
|
||||
# Known limitations:
|
||||
# - On IRIX 6.5 with CC="cc", the run time search patch must not be longer
|
||||
# than 256 bytes, otherwise the compiler driver will dump core. The only
|
||||
# known workaround is to choose shorter directory names for the build
|
||||
# directory and/or the installation directory.
|
||||
|
||||
# All known linkers require a `.a' archive for static linking (except MSVC,
|
||||
# which needs '.lib').
|
||||
libext=a
|
||||
shrext=.so
|
||||
|
||||
host="$1"
|
||||
host_cpu=`echo "$host" | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\1/'`
|
||||
host_vendor=`echo "$host" | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\2/'`
|
||||
host_os=`echo "$host" | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\3/'`
|
||||
|
||||
# Code taken from libtool.m4's _LT_CC_BASENAME.
|
||||
|
||||
for cc_temp in $CC""; do
|
||||
case $cc_temp in
|
||||
compile | *[\\/]compile | ccache | *[\\/]ccache ) ;;
|
||||
distcc | *[\\/]distcc | purify | *[\\/]purify ) ;;
|
||||
\-*) ;;
|
||||
*) break;;
|
||||
esac
|
||||
done
|
||||
cc_basename=`echo "$cc_temp" | sed -e 's%^.*/%%'`
|
||||
|
||||
# Code taken from libtool.m4's AC_LIBTOOL_PROG_COMPILER_PIC.
|
||||
|
||||
wl=
|
||||
if test "$GCC" = yes; then
|
||||
wl='-Wl,'
|
||||
else
|
||||
case "$host_os" in
|
||||
aix*)
|
||||
wl='-Wl,'
|
||||
;;
|
||||
darwin*)
|
||||
case $cc_basename in
|
||||
xlc*)
|
||||
wl='-Wl,'
|
||||
;;
|
||||
esac
|
||||
;;
|
||||
mingw* | cygwin* | pw32* | os2*)
|
||||
;;
|
||||
hpux9* | hpux10* | hpux11*)
|
||||
wl='-Wl,'
|
||||
;;
|
||||
irix5* | irix6* | nonstopux*)
|
||||
wl='-Wl,'
|
||||
;;
|
||||
newsos6)
|
||||
;;
|
||||
linux* | k*bsd*-gnu)
|
||||
case $cc_basename in
|
||||
icc* | ecc*)
|
||||
wl='-Wl,'
|
||||
;;
|
||||
pgcc | pgf77 | pgf90)
|
||||
wl='-Wl,'
|
||||
;;
|
||||
ccc*)
|
||||
wl='-Wl,'
|
||||
;;
|
||||
como)
|
||||
wl='-lopt='
|
||||
;;
|
||||
*)
|
||||
case `$CC -V 2>&1 | sed 5q` in
|
||||
*Sun\ C*)
|
||||
wl='-Wl,'
|
||||
;;
|
||||
esac
|
||||
;;
|
||||
esac
|
||||
;;
|
||||
osf3* | osf4* | osf5*)
|
||||
wl='-Wl,'
|
||||
;;
|
||||
rdos*)
|
||||
;;
|
||||
solaris*)
|
||||
wl='-Wl,'
|
||||
;;
|
||||
sunos4*)
|
||||
wl='-Qoption ld '
|
||||
;;
|
||||
sysv4 | sysv4.2uw2* | sysv4.3*)
|
||||
wl='-Wl,'
|
||||
;;
|
||||
sysv4*MP*)
|
||||
;;
|
||||
sysv5* | unixware* | sco3.2v5* | sco5v6* | OpenUNIX*)
|
||||
wl='-Wl,'
|
||||
;;
|
||||
unicos*)
|
||||
wl='-Wl,'
|
||||
;;
|
||||
uts4*)
|
||||
;;
|
||||
esac
|
||||
fi
|
||||
|
||||
# Code taken from libtool.m4's AC_LIBTOOL_PROG_LD_SHLIBS.
|
||||
|
||||
hardcode_libdir_flag_spec=
|
||||
hardcode_libdir_separator=
|
||||
hardcode_direct=no
|
||||
hardcode_minus_L=no
|
||||
|
||||
case "$host_os" in
|
||||
cygwin* | mingw* | pw32*)
|
||||
# FIXME: the MSVC++ port hasn't been tested in a loooong time
|
||||
# When not using gcc, we currently assume that we are using
|
||||
# Microsoft Visual C++.
|
||||
if test "$GCC" != yes; then
|
||||
with_gnu_ld=no
|
||||
fi
|
||||
;;
|
||||
interix*)
|
||||
# we just hope/assume this is gcc and not c89 (= MSVC++)
|
||||
with_gnu_ld=yes
|
||||
;;
|
||||
openbsd*)
|
||||
with_gnu_ld=no
|
||||
;;
|
||||
esac
|
||||
|
||||
ld_shlibs=yes
|
||||
if test "$with_gnu_ld" = yes; then
|
||||
# Set some defaults for GNU ld with shared library support. These
|
||||
# are reset later if shared libraries are not supported. Putting them
|
||||
# here allows them to be overridden if necessary.
|
||||
# Unlike libtool, we use -rpath here, not --rpath, since the documented
|
||||
# option of GNU ld is called -rpath, not --rpath.
|
||||
hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir'
|
||||
case "$host_os" in
|
||||
aix3* | aix4* | aix5*)
|
||||
# On AIX/PPC, the GNU linker is very broken
|
||||
if test "$host_cpu" != ia64; then
|
||||
ld_shlibs=no
|
||||
fi
|
||||
;;
|
||||
amigaos*)
|
||||
hardcode_libdir_flag_spec='-L$libdir'
|
||||
hardcode_minus_L=yes
|
||||
# Samuel A. Falvo II <kc5tja@dolphin.openprojects.net> reports
|
||||
# that the semantics of dynamic libraries on AmigaOS, at least up
|
||||
# to version 4, is to share data among multiple programs linked
|
||||
# with the same dynamic library. Since this doesn't match the
|
||||
# behavior of shared libraries on other platforms, we cannot use
|
||||
# them.
|
||||
ld_shlibs=no
|
||||
;;
|
||||
beos*)
|
||||
if $LD --help 2>&1 | grep ': supported targets:.* elf' > /dev/null; then
|
||||
:
|
||||
else
|
||||
ld_shlibs=no
|
||||
fi
|
||||
;;
|
||||
cygwin* | mingw* | pw32*)
|
||||
# hardcode_libdir_flag_spec is actually meaningless, as there is
|
||||
# no search path for DLLs.
|
||||
hardcode_libdir_flag_spec='-L$libdir'
|
||||
if $LD --help 2>&1 | grep 'auto-import' > /dev/null; then
|
||||
:
|
||||
else
|
||||
ld_shlibs=no
|
||||
fi
|
||||
;;
|
||||
interix[3-9]*)
|
||||
hardcode_direct=no
|
||||
hardcode_libdir_flag_spec='${wl}-rpath,$libdir'
|
||||
;;
|
||||
gnu* | linux* | k*bsd*-gnu)
|
||||
if $LD --help 2>&1 | grep ': supported targets:.* elf' > /dev/null; then
|
||||
:
|
||||
else
|
||||
ld_shlibs=no
|
||||
fi
|
||||
;;
|
||||
netbsd*)
|
||||
;;
|
||||
solaris*)
|
||||
if $LD -v 2>&1 | grep 'BFD 2\.8' > /dev/null; then
|
||||
ld_shlibs=no
|
||||
elif $LD --help 2>&1 | grep ': supported targets:.* elf' > /dev/null; then
|
||||
:
|
||||
else
|
||||
ld_shlibs=no
|
||||
fi
|
||||
;;
|
||||
sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX*)
|
||||
case `$LD -v 2>&1` in
|
||||
*\ [01].* | *\ 2.[0-9].* | *\ 2.1[0-5].*)
|
||||
ld_shlibs=no
|
||||
;;
|
||||
*)
|
||||
if $LD --help 2>&1 | grep ': supported targets:.* elf' > /dev/null; then
|
||||
hardcode_libdir_flag_spec='`test -z "$SCOABSPATH" && echo ${wl}-rpath,$libdir`'
|
||||
else
|
||||
ld_shlibs=no
|
||||
fi
|
||||
;;
|
||||
esac
|
||||
;;
|
||||
sunos4*)
|
||||
hardcode_direct=yes
|
||||
;;
|
||||
*)
|
||||
if $LD --help 2>&1 | grep ': supported targets:.* elf' > /dev/null; then
|
||||
:
|
||||
else
|
||||
ld_shlibs=no
|
||||
fi
|
||||
;;
|
||||
esac
|
||||
if test "$ld_shlibs" = no; then
|
||||
hardcode_libdir_flag_spec=
|
||||
fi
|
||||
else
|
||||
case "$host_os" in
|
||||
aix3*)
|
||||
# Note: this linker hardcodes the directories in LIBPATH if there
|
||||
# are no directories specified by -L.
|
||||
hardcode_minus_L=yes
|
||||
if test "$GCC" = yes; then
|
||||
# Neither direct hardcoding nor static linking is supported with a
|
||||
# broken collect2.
|
||||
hardcode_direct=unsupported
|
||||
fi
|
||||
;;
|
||||
aix4* | aix5*)
|
||||
if test "$host_cpu" = ia64; then
|
||||
# On IA64, the linker does run time linking by default, so we don't
|
||||
# have to do anything special.
|
||||
aix_use_runtimelinking=no
|
||||
else
|
||||
aix_use_runtimelinking=no
|
||||
# Test if we are trying to use run time linking or normal
|
||||
# AIX style linking. If -brtl is somewhere in LDFLAGS, we
|
||||
# need to do runtime linking.
|
||||
case $host_os in aix4.[23]|aix4.[23].*|aix5*)
|
||||
for ld_flag in $LDFLAGS; do
|
||||
if (test $ld_flag = "-brtl" || test $ld_flag = "-Wl,-brtl"); then
|
||||
aix_use_runtimelinking=yes
|
||||
break
|
||||
fi
|
||||
done
|
||||
;;
|
||||
esac
|
||||
fi
|
||||
hardcode_direct=yes
|
||||
hardcode_libdir_separator=':'
|
||||
if test "$GCC" = yes; then
|
||||
case $host_os in aix4.[012]|aix4.[012].*)
|
||||
collect2name=`${CC} -print-prog-name=collect2`
|
||||
if test -f "$collect2name" && \
|
||||
strings "$collect2name" | grep resolve_lib_name >/dev/null
|
||||
then
|
||||
# We have reworked collect2
|
||||
:
|
||||
else
|
||||
# We have old collect2
|
||||
hardcode_direct=unsupported
|
||||
hardcode_minus_L=yes
|
||||
hardcode_libdir_flag_spec='-L$libdir'
|
||||
hardcode_libdir_separator=
|
||||
fi
|
||||
;;
|
||||
esac
|
||||
fi
|
||||
# Begin _LT_AC_SYS_LIBPATH_AIX.
|
||||
echo 'int main () { return 0; }' > conftest.c
|
||||
${CC} ${LDFLAGS} conftest.c -o conftest
|
||||
aix_libpath=`dump -H conftest 2>/dev/null | sed -n -e '/Import File Strings/,/^$/ { /^0/ { s/^0 *\(.*\)$/\1/; p; }
|
||||
}'`
|
||||
if test -z "$aix_libpath"; then
|
||||
aix_libpath=`dump -HX64 conftest 2>/dev/null | sed -n -e '/Import File Strings/,/^$/ { /^0/ { s/^0 *\(.*\)$/\1/; p; }
|
||||
}'`
|
||||
fi
|
||||
if test -z "$aix_libpath"; then
|
||||
aix_libpath="/usr/lib:/lib"
|
||||
fi
|
||||
rm -f conftest.c conftest
|
||||
# End _LT_AC_SYS_LIBPATH_AIX.
|
||||
if test "$aix_use_runtimelinking" = yes; then
|
||||
hardcode_libdir_flag_spec='${wl}-blibpath:$libdir:'"$aix_libpath"
|
||||
else
|
||||
if test "$host_cpu" = ia64; then
|
||||
hardcode_libdir_flag_spec='${wl}-R $libdir:/usr/lib:/lib'
|
||||
else
|
||||
hardcode_libdir_flag_spec='${wl}-blibpath:$libdir:'"$aix_libpath"
|
||||
fi
|
||||
fi
|
||||
;;
|
||||
amigaos*)
|
||||
hardcode_libdir_flag_spec='-L$libdir'
|
||||
hardcode_minus_L=yes
|
||||
# see comment about different semantics on the GNU ld section
|
||||
ld_shlibs=no
|
||||
;;
|
||||
bsdi[45]*)
|
||||
;;
|
||||
cygwin* | mingw* | pw32*)
|
||||
# When not using gcc, we currently assume that we are using
|
||||
# Microsoft Visual C++.
|
||||
# hardcode_libdir_flag_spec is actually meaningless, as there is
|
||||
# no search path for DLLs.
|
||||
hardcode_libdir_flag_spec=' '
|
||||
libext=lib
|
||||
;;
|
||||
darwin* | rhapsody*)
|
||||
hardcode_direct=no
|
||||
if test "$GCC" = yes ; then
|
||||
:
|
||||
else
|
||||
case $cc_basename in
|
||||
xlc*)
|
||||
;;
|
||||
*)
|
||||
ld_shlibs=no
|
||||
;;
|
||||
esac
|
||||
fi
|
||||
;;
|
||||
dgux*)
|
||||
hardcode_libdir_flag_spec='-L$libdir'
|
||||
;;
|
||||
freebsd1*)
|
||||
ld_shlibs=no
|
||||
;;
|
||||
freebsd2.2*)
|
||||
hardcode_libdir_flag_spec='-R$libdir'
|
||||
hardcode_direct=yes
|
||||
;;
|
||||
freebsd2*)
|
||||
hardcode_direct=yes
|
||||
hardcode_minus_L=yes
|
||||
;;
|
||||
freebsd* | dragonfly*)
|
||||
hardcode_libdir_flag_spec='-R$libdir'
|
||||
hardcode_direct=yes
|
||||
;;
|
||||
hpux9*)
|
||||
hardcode_libdir_flag_spec='${wl}+b ${wl}$libdir'
|
||||
hardcode_libdir_separator=:
|
||||
hardcode_direct=yes
|
||||
# hardcode_minus_L: Not really in the search PATH,
|
||||
# but as the default location of the library.
|
||||
hardcode_minus_L=yes
|
||||
;;
|
||||
hpux10*)
|
||||
if test "$with_gnu_ld" = no; then
|
||||
hardcode_libdir_flag_spec='${wl}+b ${wl}$libdir'
|
||||
hardcode_libdir_separator=:
|
||||
hardcode_direct=yes
|
||||
# hardcode_minus_L: Not really in the search PATH,
|
||||
# but as the default location of the library.
|
||||
hardcode_minus_L=yes
|
||||
fi
|
||||
;;
|
||||
hpux11*)
|
||||
if test "$with_gnu_ld" = no; then
|
||||
hardcode_libdir_flag_spec='${wl}+b ${wl}$libdir'
|
||||
hardcode_libdir_separator=:
|
||||
case $host_cpu in
|
||||
hppa*64*|ia64*)
|
||||
hardcode_direct=no
|
||||
;;
|
||||
*)
|
||||
hardcode_direct=yes
|
||||
# hardcode_minus_L: Not really in the search PATH,
|
||||
# but as the default location of the library.
|
||||
hardcode_minus_L=yes
|
||||
;;
|
||||
esac
|
||||
fi
|
||||
;;
|
||||
irix5* | irix6* | nonstopux*)
|
||||
hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir'
|
||||
hardcode_libdir_separator=:
|
||||
;;
|
||||
netbsd*)
|
||||
hardcode_libdir_flag_spec='-R$libdir'
|
||||
hardcode_direct=yes
|
||||
;;
|
||||
newsos6)
|
||||
hardcode_direct=yes
|
||||
hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir'
|
||||
hardcode_libdir_separator=:
|
||||
;;
|
||||
openbsd*)
|
||||
if test -f /usr/libexec/ld.so; then
|
||||
hardcode_direct=yes
|
||||
if test -z "`echo __ELF__ | $CC -E - | grep __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then
|
||||
hardcode_libdir_flag_spec='${wl}-rpath,$libdir'
|
||||
else
|
||||
case "$host_os" in
|
||||
openbsd[01].* | openbsd2.[0-7] | openbsd2.[0-7].*)
|
||||
hardcode_libdir_flag_spec='-R$libdir'
|
||||
;;
|
||||
*)
|
||||
hardcode_libdir_flag_spec='${wl}-rpath,$libdir'
|
||||
;;
|
||||
esac
|
||||
fi
|
||||
else
|
||||
ld_shlibs=no
|
||||
fi
|
||||
;;
|
||||
os2*)
|
||||
hardcode_libdir_flag_spec='-L$libdir'
|
||||
hardcode_minus_L=yes
|
||||
;;
|
||||
osf3*)
|
||||
hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir'
|
||||
hardcode_libdir_separator=:
|
||||
;;
|
||||
osf4* | osf5*)
|
||||
if test "$GCC" = yes; then
|
||||
hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir'
|
||||
else
|
||||
# Both cc and cxx compiler support -rpath directly
|
||||
hardcode_libdir_flag_spec='-rpath $libdir'
|
||||
fi
|
||||
hardcode_libdir_separator=:
|
||||
;;
|
||||
solaris*)
|
||||
hardcode_libdir_flag_spec='-R$libdir'
|
||||
;;
|
||||
sunos4*)
|
||||
hardcode_libdir_flag_spec='-L$libdir'
|
||||
hardcode_direct=yes
|
||||
hardcode_minus_L=yes
|
||||
;;
|
||||
sysv4)
|
||||
case $host_vendor in
|
||||
sni)
|
||||
hardcode_direct=yes # is this really true???
|
||||
;;
|
||||
siemens)
|
||||
hardcode_direct=no
|
||||
;;
|
||||
motorola)
|
||||
hardcode_direct=no #Motorola manual says yes, but my tests say they lie
|
||||
;;
|
||||
esac
|
||||
;;
|
||||
sysv4.3*)
|
||||
;;
|
||||
sysv4*MP*)
|
||||
if test -d /usr/nec; then
|
||||
ld_shlibs=yes
|
||||
fi
|
||||
;;
|
||||
sysv4*uw2* | sysv5OpenUNIX* | sysv5UnixWare7.[01].[10]* | unixware7* | sco3.2v5.0.[024]*)
|
||||
;;
|
||||
sysv5* | sco3.2v5* | sco5v6*)
|
||||
hardcode_libdir_flag_spec='`test -z "$SCOABSPATH" && echo ${wl}-R,$libdir`'
|
||||
hardcode_libdir_separator=':'
|
||||
;;
|
||||
uts4*)
|
||||
hardcode_libdir_flag_spec='-L$libdir'
|
||||
;;
|
||||
*)
|
||||
ld_shlibs=no
|
||||
;;
|
||||
esac
|
||||
fi
|
||||
|
||||
# Check dynamic linker characteristics
|
||||
# Code taken from libtool.m4's AC_LIBTOOL_SYS_DYNAMIC_LINKER.
|
||||
# Unlike libtool.m4, here we don't care about _all_ names of the library, but
|
||||
# only about the one the linker finds when passed -lNAME. This is the last
|
||||
# element of library_names_spec in libtool.m4, or possibly two of them if the
|
||||
# linker has special search rules.
|
||||
library_names_spec= # the last element of library_names_spec in libtool.m4
|
||||
libname_spec='lib$name'
|
||||
case "$host_os" in
|
||||
aix3*)
|
||||
library_names_spec='$libname.a'
|
||||
;;
|
||||
aix4* | aix5*)
|
||||
library_names_spec='$libname$shrext'
|
||||
;;
|
||||
amigaos*)
|
||||
library_names_spec='$libname.a'
|
||||
;;
|
||||
beos*)
|
||||
library_names_spec='$libname$shrext'
|
||||
;;
|
||||
bsdi[45]*)
|
||||
library_names_spec='$libname$shrext'
|
||||
;;
|
||||
cygwin* | mingw* | pw32*)
|
||||
shrext=.dll
|
||||
library_names_spec='$libname.dll.a $libname.lib'
|
||||
;;
|
||||
darwin* | rhapsody*)
|
||||
shrext=.dylib
|
||||
library_names_spec='$libname$shrext'
|
||||
;;
|
||||
dgux*)
|
||||
library_names_spec='$libname$shrext'
|
||||
;;
|
||||
freebsd1*)
|
||||
;;
|
||||
freebsd* | dragonfly*)
|
||||
case "$host_os" in
|
||||
freebsd[123]*)
|
||||
library_names_spec='$libname$shrext$versuffix' ;;
|
||||
*)
|
||||
library_names_spec='$libname$shrext' ;;
|
||||
esac
|
||||
;;
|
||||
gnu*)
|
||||
library_names_spec='$libname$shrext'
|
||||
;;
|
||||
hpux9* | hpux10* | hpux11*)
|
||||
case $host_cpu in
|
||||
ia64*)
|
||||
shrext=.so
|
||||
;;
|
||||
hppa*64*)
|
||||
shrext=.sl
|
||||
;;
|
||||
*)
|
||||
shrext=.sl
|
||||
;;
|
||||
esac
|
||||
library_names_spec='$libname$shrext'
|
||||
;;
|
||||
interix[3-9]*)
|
||||
library_names_spec='$libname$shrext'
|
||||
;;
|
||||
irix5* | irix6* | nonstopux*)
|
||||
library_names_spec='$libname$shrext'
|
||||
case "$host_os" in
|
||||
irix5* | nonstopux*)
|
||||
libsuff= shlibsuff=
|
||||
;;
|
||||
*)
|
||||
case $LD in
|
||||
*-32|*"-32 "|*-melf32bsmip|*"-melf32bsmip ") libsuff= shlibsuff= ;;
|
||||
*-n32|*"-n32 "|*-melf32bmipn32|*"-melf32bmipn32 ") libsuff=32 shlibsuff=N32 ;;
|
||||
*-64|*"-64 "|*-melf64bmip|*"-melf64bmip ") libsuff=64 shlibsuff=64 ;;
|
||||
*) libsuff= shlibsuff= ;;
|
||||
esac
|
||||
;;
|
||||
esac
|
||||
;;
|
||||
linux*oldld* | linux*aout* | linux*coff*)
|
||||
;;
|
||||
linux* | k*bsd*-gnu)
|
||||
library_names_spec='$libname$shrext'
|
||||
;;
|
||||
knetbsd*-gnu)
|
||||
library_names_spec='$libname$shrext'
|
||||
;;
|
||||
netbsd*)
|
||||
library_names_spec='$libname$shrext'
|
||||
;;
|
||||
newsos6)
|
||||
library_names_spec='$libname$shrext'
|
||||
;;
|
||||
nto-qnx*)
|
||||
library_names_spec='$libname$shrext'
|
||||
;;
|
||||
openbsd*)
|
||||
library_names_spec='$libname$shrext$versuffix'
|
||||
;;
|
||||
os2*)
|
||||
libname_spec='$name'
|
||||
shrext=.dll
|
||||
library_names_spec='$libname.a'
|
||||
;;
|
||||
osf3* | osf4* | osf5*)
|
||||
library_names_spec='$libname$shrext'
|
||||
;;
|
||||
rdos*)
|
||||
;;
|
||||
solaris*)
|
||||
library_names_spec='$libname$shrext'
|
||||
;;
|
||||
sunos4*)
|
||||
library_names_spec='$libname$shrext$versuffix'
|
||||
;;
|
||||
sysv4 | sysv4.3*)
|
||||
library_names_spec='$libname$shrext'
|
||||
;;
|
||||
sysv4*MP*)
|
||||
library_names_spec='$libname$shrext'
|
||||
;;
|
||||
sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX* | sysv4*uw2*)
|
||||
library_names_spec='$libname$shrext'
|
||||
;;
|
||||
uts4*)
|
||||
library_names_spec='$libname$shrext'
|
||||
;;
|
||||
esac
|
||||
|
||||
sed_quote_subst='s/\(["`$\\]\)/\\\1/g'
|
||||
escaped_wl=`echo "X$wl" | sed -e 's/^X//' -e "$sed_quote_subst"`
|
||||
shlibext=`echo "$shrext" | sed -e 's,^\.,,'`
|
||||
escaped_libname_spec=`echo "X$libname_spec" | sed -e 's/^X//' -e "$sed_quote_subst"`
|
||||
escaped_library_names_spec=`echo "X$library_names_spec" | sed -e 's/^X//' -e "$sed_quote_subst"`
|
||||
escaped_hardcode_libdir_flag_spec=`echo "X$hardcode_libdir_flag_spec" | sed -e 's/^X//' -e "$sed_quote_subst"`
|
||||
|
||||
LC_ALL=C sed -e 's/^\([a-zA-Z0-9_]*\)=/acl_cv_\1=/' <<EOF
|
||||
|
||||
# How to pass a linker flag through the compiler.
|
||||
wl="$escaped_wl"
|
||||
|
||||
# Static library suffix (normally "a").
|
||||
libext="$libext"
|
||||
|
||||
# Shared library suffix (normally "so").
|
||||
shlibext="$shlibext"
|
||||
|
||||
# Format of library name prefix.
|
||||
libname_spec="$escaped_libname_spec"
|
||||
|
||||
# Library names that the linker finds when passed -lNAME.
|
||||
library_names_spec="$escaped_library_names_spec"
|
||||
|
||||
# Flag to hardcode \$libdir into a binary during linking.
|
||||
# This must work even if \$libdir does not exist.
|
||||
hardcode_libdir_flag_spec="$escaped_hardcode_libdir_flag_spec"
|
||||
|
||||
# Whether we need a single -rpath flag with a separated argument.
|
||||
hardcode_libdir_separator="$hardcode_libdir_separator"
|
||||
|
||||
# Set to yes if using DIR/libNAME.so during linking hardcodes DIR into the
|
||||
# resulting binary.
|
||||
hardcode_direct="$hardcode_direct"
|
||||
|
||||
# Set to yes if using the -LDIR flag during linking hardcodes DIR into the
|
||||
# resulting binary.
|
||||
hardcode_minus_L="$hardcode_minus_L"
|
||||
|
||||
EOF
|
||||
|
|
@ -0,0 +1,537 @@
|
|||
# Process this file with autoconf to produce a configure script.
|
||||
|
||||
AC_PREREQ(2.63)
|
||||
AC_INIT([sysbench],[1.0.20],[https://github.com/akopytov/sysbench/issues],
|
||||
[sysbench], [https://github.com/akopytov/sysbench])
|
||||
AC_CONFIG_AUX_DIR([config])
|
||||
|
||||
# Define m4_ifblank and m4_ifnblank macros from introduced in
|
||||
# autotools 2.64 m4sugar.m4 if using an earlier autotools.
|
||||
m4_ifdef([m4_ifblank], [], [
|
||||
m4_define([m4_ifblank],
|
||||
[m4_if(m4_translit([[$1]], [ ][ ][
|
||||
]), [], [$2], [$3])])
|
||||
])
|
||||
|
||||
m4_ifdef([m4_ifnblank], [], [
|
||||
m4_define([m4_ifnblank],
|
||||
[m4_if(m4_translit([[$1]], [ ][ ][
|
||||
]), [], [$3], [$2])])
|
||||
])
|
||||
|
||||
# Setting CFLAGS here prevents AC_CANONICAL_TARGET from injecting them
|
||||
SAVE_CFLAGS=${CFLAGS}
|
||||
SAVE_CXXFLAGS=${CXXFLAGS}
|
||||
CFLAGS=
|
||||
CXXFLAGS=
|
||||
AC_CANONICAL_TARGET
|
||||
|
||||
CFLAGS=${SAVE_CFLAGS}
|
||||
CXXFLAGS=${SAVE_CXXFLAGS}
|
||||
|
||||
AM_INIT_AUTOMAKE([-Wall -Werror foreign])
|
||||
AC_CONFIG_SRCDIR([src/sysbench.c])
|
||||
AC_CONFIG_HEADER([config/config.h])
|
||||
AC_CONFIG_MACRO_DIR([m4])
|
||||
|
||||
m4_pattern_forbid([^PKG_[A-Z_]+$],
|
||||
[pkg-config has to be installed to build sysbench])
|
||||
|
||||
ACX_USE_SYSTEM_EXTENSIONS
|
||||
|
||||
AC_PROG_CC
|
||||
AC_PROG_CC_C99
|
||||
AC_PROG_CPP
|
||||
AM_PROG_CC_C_O
|
||||
|
||||
if test x"$ac_cv_prog_cc_c99" = xno; then
|
||||
AC_MSG_ERROR([a C99 compiler is required to build sysbench])
|
||||
fi
|
||||
|
||||
# Try to guess the most optimal compiler architecture flag, unless it's already
|
||||
# been specified by the user via CFLAGS (or --without-gcc-arch is passed to
|
||||
# configure)
|
||||
AS_CASE([$CFLAGS],
|
||||
[*-march=*],,
|
||||
[AX_GCC_ARCHFLAG([no])]
|
||||
)
|
||||
|
||||
m4_ifdef([AM_PROG_AR], [AM_PROG_AR])
|
||||
|
||||
AC_PROG_LIBTOOL
|
||||
|
||||
AC_CHECK_PROG(sb_have_pkg_config, pkg-config, yes, no)
|
||||
if test x"$sb_have_pkg_config" = xno; then
|
||||
AC_MSG_ERROR([the pkg-config package is required to build sysbench])
|
||||
fi
|
||||
|
||||
AX_COMPILER_VENDOR
|
||||
|
||||
# Checks for user arguments
|
||||
|
||||
AC_LIB_PREFIX()
|
||||
# Additional linker flags
|
||||
AC_ARG_WITH([extra-ldflags],
|
||||
AS_HELP_STRING([--with-extra-ldflags],[additional linker flags, e.g. -all-static]),
|
||||
EXTRA_LDFLAGS=$withval
|
||||
)
|
||||
AC_SUBST(EXTRA_LDFLAGS)
|
||||
|
||||
CPPFLAGS="-D_GNU_SOURCE ${CPPFLAGS}"
|
||||
|
||||
# Mac OS X requires _DARWIN_C_SOURCE for valloc(3) to be visible
|
||||
case "${host_cpu}-${host_os}" in
|
||||
*-darwin*) CPPFLAGS="-D_DARWIN_C_SOURCE ${CPPFLAGS}";;
|
||||
esac
|
||||
|
||||
# Build optimized or debug version ?
|
||||
# First check for gcc and g++
|
||||
if test "$GCC" = "yes"
|
||||
then
|
||||
CFLAGS="-ggdb3 ${CFLAGS}"
|
||||
DEBUG_CFLAGS="-O0"
|
||||
OPTIMIZE_CFLAGS="-O2 -funroll-loops"
|
||||
GCOV_CFLAGS="-O0 --coverage"
|
||||
GCOV_LDFLAGS="-coverage"
|
||||
ASAN_CFLAGS="-fsanitize=address"
|
||||
ASAN_LDFLAGS="${ASAN_CFLAGS}"
|
||||
MSAN_CFLAGS="-fsanitize=memory"
|
||||
MSAN_LDFLAGS="${MSAN_LDFLAGS}"
|
||||
fi
|
||||
if test "$ax_cv_c_compiler_vendor" = "sun"
|
||||
then
|
||||
isainfo_k=`isainfo -k`
|
||||
if test "$target_cpu" = "sparc"
|
||||
then
|
||||
MEMALIGN_FLAGS="-xmemalign=8s"
|
||||
IS_64="-m64"
|
||||
LDFLAGS="${LDFLAGS} -L/usr/lib/${isainfo_k} -L/usr/local/lib/${isainfo_k}"
|
||||
else
|
||||
if test "$isainfo_k" = "amd64"
|
||||
then
|
||||
IS_64="-m64"
|
||||
LDFLAGS="${LDFLAGS} -L/usr/lib/${isainfo_k} -L/usr/local/lib/${isainfo_k}"
|
||||
fi
|
||||
fi
|
||||
CPPFLAGS="${CPPFLAGS} -I/usr/local/include"
|
||||
|
||||
CFLAGS="-g -mt ${IS_64} ${MEMALIGN_FLAGS} ${CFLAGS}"
|
||||
DEBUG_CFLAGS="-xO0"
|
||||
OPTIMIZE_CFLAGS="-xO2 -xlibmil -xdepend -Xa -mt -xstrconst"
|
||||
# TODO: Set flags for Gcov-enabled builds, if supported by Sun Studio
|
||||
fi
|
||||
|
||||
|
||||
# Check if we should compile with MySQL support
|
||||
AC_ARG_WITH([mysql],
|
||||
AS_HELP_STRING([--with-mysql],
|
||||
[compile with MySQL support (default is enabled)]),
|
||||
[], [with_mysql=yes])
|
||||
AC_MSG_CHECKING([whether to compile with MySQL support])
|
||||
AS_IF([test "x$with_mysql" != "xno"],
|
||||
[mysql_support=yes],
|
||||
[mysql_support=no])
|
||||
AC_MSG_RESULT([$mysql_support])
|
||||
|
||||
# Check if we should compile with Drizzle support
|
||||
AC_ARG_WITH([drizzle],
|
||||
AS_HELP_STRING([--with-drizzle],
|
||||
[compile with Drizzle support (default is disabled)]),
|
||||
[], [with_drizzle=no])
|
||||
AC_MSG_CHECKING([whether to compile with Drizzle support])
|
||||
AS_IF([test "x$with_drizzle" != "xno"],
|
||||
[drizzle_support=yes],
|
||||
[drizzle_support=no])
|
||||
AC_MSG_RESULT([$drizzle_support])
|
||||
|
||||
# Check if we should compile with libattachsql support
|
||||
AC_ARG_WITH([attachsql],
|
||||
AS_HELP_STRING([--with-attachsql],
|
||||
[compile with libattachsql support (default is disabled)]),
|
||||
[], [with_attachsql=no])
|
||||
AC_MSG_CHECKING([whether to compile with libattachsql support])
|
||||
AS_IF([test "x$with_attachsql" != "xno"],
|
||||
[attachsql_support=yes],
|
||||
[attachsql_support=no])
|
||||
AC_MSG_RESULT([$attachsql_support])
|
||||
|
||||
|
||||
# Check if we should compile with Oracle support
|
||||
AC_ARG_WITH([oracle],
|
||||
AS_HELP_STRING([--with-oracle],
|
||||
[compile with Oracle support (default is disabled)]),
|
||||
[], [with_oracle=no])
|
||||
AC_MSG_CHECKING([whether to compile with Oracle support])
|
||||
AS_IF([test "x$with_oracle" != "xno"],
|
||||
[oracle_support=yes],
|
||||
[oracle_support=no])
|
||||
AC_MSG_RESULT([$oracle_support])
|
||||
|
||||
# Check if we should compile with PostgreSQL support
|
||||
AC_ARG_WITH([pgsql],
|
||||
AS_HELP_STRING([--with-pgsql],
|
||||
[compile with PostgreSQL support (default is disabled)]),
|
||||
[], [with_pgsql=no])
|
||||
AC_MSG_CHECKING([whether to compile with PostgreSQL support])
|
||||
AS_IF([test "x$with_pgsql" != "xno"],
|
||||
[pgsql_support=yes],
|
||||
[pgsql_support=no])
|
||||
AC_MSG_RESULT([$pgsql_support])
|
||||
|
||||
# Set LuaJIT flags
|
||||
SB_LUAJIT
|
||||
|
||||
# Set Concurrency Kit flags
|
||||
SB_CONCURRENCY_KIT
|
||||
|
||||
# Check if we should enable large files support
|
||||
AC_ARG_ENABLE(largefile,
|
||||
AS_HELP_STRING([--enable-largefile],[enable large files support (default is enabled)]), ,
|
||||
enable_largefile=yes
|
||||
)
|
||||
|
||||
# For SHM_HUGETLB on Linux
|
||||
AC_CHECK_DECLS(SHM_HUGETLB,
|
||||
AC_DEFINE([HAVE_LARGE_PAGES], [1],
|
||||
[Define if you have large pages support])
|
||||
AC_DEFINE([HUGETLB_USE_PROC_MEMINFO], [1],
|
||||
[Define if /proc/meminfo shows the huge page size (Linux only)])
|
||||
, ,
|
||||
[
|
||||
#include <sys/shm.h>
|
||||
]
|
||||
)
|
||||
|
||||
# Check if we should enable Linux AIO support
|
||||
AC_ARG_ENABLE(aio,
|
||||
AS_HELP_STRING([--enable-aio],[enable Linux asynchronous I/O support (default is enabled)]), ,
|
||||
enable_aio=yes
|
||||
)
|
||||
|
||||
AC_CHECK_DECLS(O_SYNC, ,
|
||||
AC_DEFINE([O_SYNC], [O_FSYNC],
|
||||
[Define to the appropriate value for O_SYNC on your platform]),
|
||||
[
|
||||
#include <fcntl.h>
|
||||
]
|
||||
)
|
||||
|
||||
|
||||
# Checks for programs.
|
||||
AX_CHECK_DOCBOOK
|
||||
|
||||
# Checks for libraries.
|
||||
|
||||
ACX_PTHREAD
|
||||
|
||||
AC_CHECK_LIB(m, sqrt)
|
||||
|
||||
SB_CHECK_MYSQL
|
||||
|
||||
AS_IF([test "x$with_drizzle" != xno], [
|
||||
AC_LIB_HAVE_LINKFLAGS(drizzle,,
|
||||
[#include <libdrizzle/drizzle.h>],
|
||||
[
|
||||
int x= DRIZZLE_RETURN_ERROR_CODE;
|
||||
const char *version= drizzle_version();
|
||||
])
|
||||
AS_IF([test "x$ac_cv_libdrizzle" = xyes], [
|
||||
AC_DEFINE([USE_DRIZZLE],1,
|
||||
[Define to 1 if you want to compile with Drizzle support])
|
||||
])
|
||||
])
|
||||
AM_CONDITIONAL(USE_DRIZZLE, test x$ac_cv_libdrizzle = xyes)
|
||||
|
||||
AS_IF([test "x$with_attachsql" != xno], [
|
||||
AC_LIB_HAVE_LINKFLAGS(attachsql,,
|
||||
[#include <libattachsql-1.0/attachsql.h>],
|
||||
[
|
||||
const char *version= attachsql_get_library_version();
|
||||
])
|
||||
AS_IF([test "x$ac_cv_libattachsql" = xyes], [
|
||||
AC_DEFINE(USE_ATTACHSQL,1,
|
||||
[Define to 1 if you want to compile with libattachsql support])
|
||||
])
|
||||
])
|
||||
AM_CONDITIONAL(USE_ATTACHSQL, test x$ac_cv_libattachsql = xyes)
|
||||
|
||||
|
||||
AS_IF([test x$with_oracle != xno], [
|
||||
AC_DEFINE(USE_ORACLE,1,[Define to 1 if you want to compile with Oracle support])
|
||||
ORA_LIBS="-L${sb_with_oracle}/lib -lclntsh"
|
||||
ORA_CFLAGS="-I${with_oracle}/include -I${with_oracle}/rdbms/demo -I${with_oracle}/rdbms/public"
|
||||
AC_SUBST([ORA_LIBS])
|
||||
AC_SUBST([ORA_CFLAGS])
|
||||
])
|
||||
AM_CONDITIONAL(USE_ORACLE, test x$with_oracle != xno)
|
||||
|
||||
AS_IF([test x$with_pgsql != xno], [
|
||||
AC_CHECK_PGSQL([$with_pgsql])
|
||||
USE_PGSQL=1
|
||||
AC_DEFINE(USE_PGSQL,1,[Define to 1 if you want to compile with PostgreSQL support])
|
||||
AC_SUBST([PGSQL_LIBS])
|
||||
AC_SUBST([PGSQL_CFLAGS])
|
||||
])
|
||||
AM_CONDITIONAL(USE_PGSQL, test x$with_pgsql != xno)
|
||||
AC_SUBST([USE_PGSQL])
|
||||
|
||||
# Check for libaio
|
||||
AC_CHECK_AIO
|
||||
AM_CONDITIONAL(USE_AIO, test x$enable_aio = xyes)
|
||||
|
||||
# Check for advanced memory allocation libraries
|
||||
AC_CHECK_LIB([umem], [malloc], [EXTRA_LDFLAGS="$EXTRA_LDFLAGS -lumem"],
|
||||
AC_CHECK_LIB([mtmalloc], [malloc], [EXTRA_LDFLAGS="$EXTRA_LDFLAGS -lmtmalloc"])
|
||||
)
|
||||
|
||||
# Checks for header files.
|
||||
AC_HEADER_STDC
|
||||
|
||||
AC_CHECK_HEADERS([ \
|
||||
errno.h \
|
||||
fcntl.h \
|
||||
math.h \
|
||||
pthread.h \
|
||||
sched.h \
|
||||
signal.h \
|
||||
stdlib.h \
|
||||
string.h \
|
||||
sys/aio.h \
|
||||
sys/ipc.h \
|
||||
sys/time.h \
|
||||
sys/mman.h \
|
||||
sys/shm.h \
|
||||
thread.h \
|
||||
unistd.h \
|
||||
limits.h \
|
||||
libgen.h \
|
||||
])
|
||||
|
||||
|
||||
# Checks for typedefs, structures, and compiler characteristics.
|
||||
AC_TYPE_OFF_T
|
||||
AC_HEADER_TIME
|
||||
AX_TLS([],
|
||||
AC_MSG_ERROR([thread-local storage is not suppored by the target platform!])
|
||||
)
|
||||
|
||||
# Define HAVE_FUNC_ATTRIBUTE_FORMAT if compiler supports the
|
||||
# __attribute__((format...)) function attribute
|
||||
AX_GCC_FUNC_ATTRIBUTE(format)
|
||||
|
||||
# Define HAVE_FUNC_ATTRIBUTE_UNUSED if compiler supports the
|
||||
# __attribute__((unused)) function attribute
|
||||
AX_GCC_FUNC_ATTRIBUTE(unused)
|
||||
|
||||
if test "$enable_largefile" = yes; then
|
||||
AC_SYS_LARGEFILE
|
||||
fi
|
||||
|
||||
AC_CHECK_SIZEOF(size_t)
|
||||
AC_CHECK_SIZEOF(bool,,
|
||||
[
|
||||
#include <stdbool.h>
|
||||
])
|
||||
|
||||
# Checks for library functions.
|
||||
AC_FUNC_MMAP
|
||||
AC_FUNC_STRERROR_R
|
||||
|
||||
AC_SEARCH_LIBS([clock_gettime], [rt])
|
||||
|
||||
save_CFLAGS="$CFLAGS"
|
||||
CFLAGS="$CFLAGS $PTHREAD_CFLAGS"
|
||||
save_LIBS="$LIBS"
|
||||
LIBS="$PTHREAD_LIBS $LIBS"
|
||||
|
||||
AC_CHECK_FUNCS([ \
|
||||
alarm \
|
||||
clock_gettime \
|
||||
directio \
|
||||
fdatasync \
|
||||
gettimeofday \
|
||||
isatty \
|
||||
memalign \
|
||||
memset \
|
||||
posix_memalign \
|
||||
pthread_yield \
|
||||
setvbuf \
|
||||
sqrt \
|
||||
strdup \
|
||||
thr_setconcurrency \
|
||||
valloc \
|
||||
])
|
||||
|
||||
AC_CHECK_FUNC(pthread_once, ,
|
||||
AC_MSG_ERROR([*** pthread_once() is not available on this platform ***])
|
||||
)
|
||||
|
||||
LIBS="$save_LIBS"
|
||||
CFLAGS="$save_CFLAGS"
|
||||
|
||||
AC_ARG_WITH([debug],
|
||||
[AS_HELP_STRING([--with-debug],
|
||||
[Add debug code/turns off optimizations (yes|no) @<:@default=no@:>@])],
|
||||
[with_debug=$withval],
|
||||
[with_debug=no])
|
||||
|
||||
AC_ARG_ENABLE([coverage],
|
||||
[AS_HELP_STRING([--enable-coverage],
|
||||
[Toggle coverage @<:@default=no@:>@])],
|
||||
[ac_coverage="$enableval"],
|
||||
[ac_coverage="no"])
|
||||
|
||||
AC_ARG_ENABLE([asan],
|
||||
[AS_HELP_STRING([--enable-asan],
|
||||
[Enable AddressSanitizer @<:@default=no@:>@])],
|
||||
[ac_asan="$enableval"],
|
||||
[ac_asan="no"])
|
||||
|
||||
AC_ARG_ENABLE([msan],
|
||||
[AS_HELP_STRING([--enable-msan],
|
||||
[Enable MemorySanitizer @<:@default=no@:>@])],
|
||||
[ac_msan="$enableval"],
|
||||
[ac_msan="no"])
|
||||
|
||||
AC_ARG_ENABLE([fail],
|
||||
[AS_HELP_STRING([--disable-fail],
|
||||
[Turn warnings into failures @<:@default=no@:>@])],
|
||||
[ac_warn_fail="$enableval"],
|
||||
[ac_warn_fail="no"])
|
||||
|
||||
if test "$with_debug" = "yes"
|
||||
then
|
||||
# Debugging. No optimization.
|
||||
CFLAGS="${DEBUG_CFLAGS} -DDEBUG ${CFLAGS}"
|
||||
elif test "$ac_coverage" = "yes"
|
||||
then
|
||||
# Gcov-enabled build. No optimization.
|
||||
CFLAGS="${GCOV_CFLAGS} ${CFLAGS}"
|
||||
LDFLAGS="${GCOV_LDFLAGS} ${LDFLAGS}"
|
||||
else
|
||||
# Optimized version. No debug
|
||||
CFLAGS="${OPTIMIZE_CFLAGS} ${CFLAGS}"
|
||||
fi
|
||||
|
||||
if test "$ac_asan" = "yes"
|
||||
then
|
||||
# Add -fsanitize=address to CFLAGS/LDFLAGS if supported by the compiler
|
||||
AX_CHECK_COMPILE_FLAG([-fsanitize=address],
|
||||
[
|
||||
CFLAGS="${ASAN_CFLAGS} ${CFLAGS}"
|
||||
LDFLAGS="${ASAN_LDFLAGS} ${LDFLAGS}"
|
||||
])
|
||||
fi
|
||||
|
||||
if test "$ac_msan" = "yes"
|
||||
then
|
||||
# Add -fsanitize=memory to CFLAGS/LDFLAGS if supported by the compiler
|
||||
AX_CHECK_COMPILE_FLAG([-fsanitize=memory],
|
||||
[
|
||||
CFLAGS="${MSAN_CFLAGS} ${CFLAGS}"
|
||||
LDFLAGS="${MSAN_CFLAGS} ${LDFLAGS}"
|
||||
])
|
||||
fi
|
||||
|
||||
if test "$GCC" = "yes"
|
||||
then
|
||||
if test "$ac_warn_fail" = "yes"
|
||||
then
|
||||
W_FAIL="-Werror"
|
||||
fi
|
||||
|
||||
CC_WARNINGS="-Wall -Wextra -Wpointer-arith -Wbad-function-cast \
|
||||
-Wstrict-prototypes -Wnested-externs -Wno-format-zero-length \
|
||||
-Wundef -Wstrict-prototypes -Wmissing-prototypes -Wmissing-declarations \
|
||||
-Wredundant-decls -Wcast-align -Wvla ${W_FAIL}"
|
||||
fi
|
||||
|
||||
if test "$ax_cv_c_compiler_vendor" = "sun"
|
||||
then
|
||||
CC_WARNINGS="-v -errtags=yes -errwarn=%all -erroff=E_INTEGER_OVERFLOW_DETECTED -erroff=E_STATEMENT_NOT_REACHED"
|
||||
fi
|
||||
|
||||
AM_CFLAGS="${CC_WARNINGS} ${AM_CFLAGS} ${PTHREAD_CFLAGS}"
|
||||
|
||||
AM_CPPFLAGS="${AM_CPPFLAGS} -I\$(top_srcdir)/src ${LUAJIT_CFLAGS} ${CK_CFLAGS}"
|
||||
|
||||
AM_LDFLAGS="$PTHREAD_LIBS"
|
||||
|
||||
AC_SUBST(AM_CFLAGS)
|
||||
AC_SUBST(AM_CPPFLAGS)
|
||||
AC_SUBST(AM_LDFLAGS)
|
||||
|
||||
# Define SB_GIT_SHA
|
||||
git=$(which git)
|
||||
if test -n "$git"
|
||||
then
|
||||
SB_GIT_SHA=$(git rev-parse --short HEAD 2>/dev/null)
|
||||
if test -n "$SB_GIT_SHA"
|
||||
then
|
||||
SB_GIT_SHA="-$SB_GIT_SHA"
|
||||
fi
|
||||
fi
|
||||
AC_DEFINE_UNQUOTED([SB_GIT_SHA], ["$SB_GIT_SHA"], [Git commit hash, if available.])
|
||||
AC_SUBST([SB_GIT_SHA])
|
||||
|
||||
AC_CONFIG_FILES([
|
||||
Makefile
|
||||
doc/xsl/Makefile
|
||||
doc/xsl/catalog.xml
|
||||
doc/Makefile
|
||||
third_party/luajit/Makefile
|
||||
third_party/concurrency_kit/Makefile
|
||||
src/Makefile
|
||||
src/drivers/Makefile
|
||||
src/drivers/mysql/Makefile
|
||||
src/drivers/drizzle/Makefile
|
||||
src/drivers/oracle/Makefile
|
||||
src/drivers/pgsql/Makefile
|
||||
src/drivers/attachsql/Makefile
|
||||
src/tests/Makefile
|
||||
src/tests/cpu/Makefile
|
||||
src/tests/fileio/Makefile
|
||||
src/tests/memory/Makefile
|
||||
src/tests/threads/Makefile
|
||||
src/tests/mutex/Makefile
|
||||
src/lua/Makefile
|
||||
src/lua/internal/Makefile
|
||||
tests/Makefile
|
||||
tests/include/config.sh
|
||||
snap/snapcraft.yaml
|
||||
])
|
||||
AC_OUTPUT
|
||||
|
||||
AC_MSG_RESULT([===============================================================================])
|
||||
AC_MSG_RESULT([sysbench version : ${PACKAGE_VERSION}${SB_GIT_SHA}])
|
||||
AC_MSG_RESULT([CC : ${CC}])
|
||||
AC_MSG_RESULT([CFLAGS : ${CFLAGS} ${AM_CFLAGS}])
|
||||
AC_MSG_RESULT([CPPFLAGS : ${CPPFLAGS} ${AM_CPPFLAGS}])
|
||||
AC_MSG_RESULT([LDFLAGS : ${LDFLAGS} ${AM_LDFLAGS}])
|
||||
AC_MSG_RESULT([LIBS : ${LIBS}])
|
||||
AC_MSG_RESULT([EXTRA_LDFLAGS : ${EXTRA_LDFLAGS}])
|
||||
AC_MSG_RESULT([])
|
||||
AC_MSG_RESULT([prefix : $(eval echo ${prefix})])
|
||||
AC_MSG_RESULT([bindir : $(eval echo ${bindir})])
|
||||
AC_MSG_RESULT([libexecdir : $(eval echo ${libexecdir})])
|
||||
AC_MSG_RESULT([mandir : $(eval echo ${mandir})])
|
||||
AC_MSG_RESULT([datadir : $(eval echo ${datadir})])
|
||||
AC_MSG_RESULT([])
|
||||
AC_MSG_RESULT([MySQL support : ${mysql_support}])
|
||||
AC_MSG_RESULT([Drizzle support : ${drizzle_support}])
|
||||
AC_MSG_RESULT([AttachSQL support : ${attachsql_support}])
|
||||
AC_MSG_RESULT([Oracle support : ${oracle_support}])
|
||||
AC_MSG_RESULT([PostgreSQL support : ${pgsql_support}])
|
||||
AC_MSG_RESULT([])
|
||||
AC_MSG_RESULT([LuaJIT : ${sb_use_luajit}])
|
||||
AC_MSG_RESULT([LUAJIT_CFLAGS : ${LUAJIT_CFLAGS}])
|
||||
AC_MSG_RESULT([LUAJIT_LIBS : ${LUAJIT_LIBS}])
|
||||
AC_MSG_RESULT([LUAJIT_LDFLAGS : ${LUAJIT_LDFLAGS}])
|
||||
AC_MSG_RESULT([])
|
||||
AC_MSG_RESULT([Concurrency Kit : ${sb_use_ck}])
|
||||
if test "$sb_use_ck" = bundled; then
|
||||
AC_MSG_RESULT([CK_CFLAGS : ${CK_CFLAGS}])
|
||||
AC_MSG_RESULT([CK_LIBS : ${CK_LIBS}])
|
||||
AC_MSG_RESULT([configure flags : ${CK_CONFIGURE_FLAGS}])
|
||||
fi
|
||||
AC_MSG_RESULT([===============================================================================])
|
||||
|
|
@ -0,0 +1,43 @@
|
|||
sysbench (1.0.18-1) unstable; urgency=low
|
||||
|
||||
* add libssl-dev to build dependencies
|
||||
|
||||
-- Alexey Kopytov <akopytov@gmail.com> Sun, 08 Dec 2019 14:02:01 +0300
|
||||
|
||||
sysbench (1.0.15-2) unstable; urgency=low
|
||||
|
||||
* add libaio-dev to build dependencies
|
||||
|
||||
-- Alexey Kopytov <akopytov@gmail.com> Sat, 09 Jul 2018 09:24:42 +0300
|
||||
|
||||
sysbench (1.0.12-1) unstable; urgency=low
|
||||
|
||||
* remove vim-common from build dependencies
|
||||
|
||||
-- Alexey Kopytov <akopytov@gmail.com> Sat, 06 Jan 2018 10:59:42 +0300
|
||||
|
||||
sysbench (1.0.11-1) unstable; urgency=low
|
||||
|
||||
* add Debian Stretch support by adding optional build dependency on
|
||||
default-libmysqlclient-dev and replacing python-minimal with python
|
||||
(as minimal does not provide the shlex module required by cram)
|
||||
|
||||
-- Alexey Kopytov <akopytov@gmail.com> Sat, 09 Dec 2017 19:52:23 +0300
|
||||
|
||||
sysbench (1.0.6-1) unstable; urgency=low
|
||||
|
||||
* Add pkg-config, vim-common and python-minimal and libpq-dev to build dependencies.
|
||||
* Fix 'clean' target in rules.
|
||||
* Add ChangeLog and COPYING to docs.
|
||||
* Remove tests/db/*.lua from install.
|
||||
* Pass --without-gcc-arch to configure to not override compiler flags
|
||||
passed by the build system
|
||||
|
||||
-- Alexey Kopytov <akopytov@gmail.com> Thu, 13 Apr 2017 23:04:34 +0300
|
||||
|
||||
sysbench (1.0-1) unstable; urgency=low
|
||||
|
||||
* Initial release
|
||||
|
||||
-- Alexey Kopytov <akopytov@gmail.com> Wed, 10 Aug 2016 18:04:53 +0300
|
||||
|
||||
|
|
@ -0,0 +1 @@
|
|||
7
|
||||
|
|
@ -0,0 +1,25 @@
|
|||
Source: sysbench
|
||||
Section: misc
|
||||
Priority: extra
|
||||
Maintainer: Alexey Kopytov <akopytov@gmail.com>
|
||||
Build-Depends: debhelper, autoconf, automake, libaio-dev, libtool, libmysqlclient-dev | default-libmysqlclient-dev, libpq-dev, pkg-config, python, libssl-dev
|
||||
Standards-Version: 3.9.5
|
||||
Homepage: https://github.com/akopytov/sysbench
|
||||
|
||||
Package: sysbench
|
||||
Architecture: any
|
||||
Depends: ${shlibs:Depends}, ${misc:Depends}
|
||||
Description: Scriptable database and system performance benchmark
|
||||
sysbench is a scriptable multi-threaded benchmark tool based on
|
||||
LuaJIT. It is most frequently used for database benchmarks, but can also
|
||||
be used to create arbitrarily complex workloads that do not involve a
|
||||
database server.
|
||||
.
|
||||
sysbench comes with the following bundled benchmarks:
|
||||
.
|
||||
- oltp_*.lua: a collection of OLTP-like database benchmarks
|
||||
- fileio: a filesystem-level benchmark
|
||||
- cpu: a simple CPU benchmark
|
||||
- memory: a memory access benchmark
|
||||
- threads: a thread-based scheduler benchmark
|
||||
- mutex: a POSIX mutex benchmark
|
||||
|
|
@ -0,0 +1,15 @@
|
|||
Format-Specification: http://wiki.debian.org/Proposals/CopyrightFormat
|
||||
Upstream-Name: sysbench
|
||||
Upstream-Maintainer: Alexey Kopytov <akopytov@gmail.com>
|
||||
Upstream-Source: https://github.com/akopytov/sysbench
|
||||
|
||||
Files: *
|
||||
Copyright: 2016 Alexey Kopytov
|
||||
License: GPL-2
|
||||
This package is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License version 2 as
|
||||
published by the Free Software Foundation.
|
||||
.
|
||||
On Debian systems, the complete text of the GNU General
|
||||
Public License can be found in `/usr/share/common-licenses/GPL-2'.
|
||||
|
||||
|
|
@ -0,0 +1 @@
|
|||
usr/bin
|
||||
|
|
@ -0,0 +1,3 @@
|
|||
README.md
|
||||
ChangeLog
|
||||
COPYING
|
||||
|
|
@ -0,0 +1,12 @@
|
|||
#!/usr/bin/make -f
|
||||
|
||||
%:
|
||||
dh $@
|
||||
|
||||
override_dh_auto_configure:
|
||||
dh_testdir
|
||||
autoreconf -vif
|
||||
dh_auto_configure -- --with-mysql --with-pgsql --without-gcc-arch
|
||||
|
||||
override_dh_compress:
|
||||
dh_compress -X.lua
|
||||
|
|
@ -0,0 +1 @@
|
|||
3.0 (quilt)
|
||||
|
|
@ -0,0 +1,34 @@
|
|||
XSLTPROC=xsltproc
|
||||
XSLTPROC_FLAGS=@XSLTPROC_FLAGS@
|
||||
XHTML_STYLESHEET=$(srcdir)/xsl/xhtml.xsl
|
||||
CHUNK_XHTML_STYLESHEET=$(srcdir)/xsl/xhtml-chunk.xsl
|
||||
XML_CATALOG_FILES=$(srcdir)/xsl/catalog.xml
|
||||
|
||||
dist_html_DATA = manual.html
|
||||
|
||||
EXTRA_DIST=manual.xml
|
||||
|
||||
SUBDIRS = xsl
|
||||
|
||||
if have_xsltproc
|
||||
|
||||
manual.html: ${top_srcdir}/doc/manual.xml
|
||||
XML_CATALOG_FILES=$(XML_CATALOG_FILES) $(XSLTPROC) $(XSLTPROC_FLAGS) -o $@ $(XHTML_STYLESHEET) $<
|
||||
|
||||
chunk: ${top_srcdir}/doc/manual.xml
|
||||
$(XSLTPROC) $(XSLTPROC_FLAGS) $(CHUNK_XHTML_STYLESHEET) $<
|
||||
|
||||
else
|
||||
|
||||
chunk:
|
||||
|
||||
manual.html:
|
||||
touch $@
|
||||
|
||||
endif
|
||||
|
||||
clean-local:
|
||||
$(RM) -f *.html
|
||||
|
||||
distclean-local:
|
||||
$(RM) -f xsl/catalog.xml
|
||||
|
|
@ -0,0 +1,788 @@
|
|||
<?xml version="1.0" encoding='ISO-8859-1'?>
|
||||
<!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook XML V4.1.2//EN" "http://www.oasis-open.org/docbook/xml/4.1.2/docbookx.dtd">
|
||||
|
||||
<book id="sysbench-guide">
|
||||
<bookinfo>
|
||||
<title>sysbench manual</title>
|
||||
|
||||
<authorgroup>
|
||||
<author>
|
||||
<firstname>Alexey</firstname>
|
||||
<surname>Kopytov</surname>
|
||||
<affiliation>
|
||||
<address><email>kaamos@users.sourceforge.net</email></address>
|
||||
</affiliation>
|
||||
</author>
|
||||
</authorgroup>
|
||||
|
||||
<copyright>
|
||||
<year>2004-2006</year>
|
||||
<holder>MySQL AB</holder>
|
||||
</copyright></bookinfo>
|
||||
|
||||
<toc></toc>
|
||||
|
||||
<chapter id="about">
|
||||
<title>About this document</title>
|
||||
|
||||
<para>
|
||||
This document is a user manual for sysbench, a multi-threaded
|
||||
benchmark tool available from <ulink
|
||||
url="http://launchpad.net/sysbench">http://launchpad.net/sysbench</ulink>.
|
||||
This document describes features provided by the 0.4.x development
|
||||
branch of sysbench. New features available in the newer 0.5.x
|
||||
branch are not covered by this document.
|
||||
</para>
|
||||
|
||||
<section id="translations">
|
||||
<title> Translations </title>
|
||||
<para>
|
||||
The following translations of this document are currently
|
||||
available:
|
||||
|
||||
<variablelist>
|
||||
<varlistentry>
|
||||
<term>Serbo-Croatian</term>
|
||||
<listitem><para>
|
||||
<ulink url="http://science.webhostinggeeks.com/sysbench-manual">http://science.webhostinggeeks.com/sysbench-manual/</ulink>.
|
||||
</para></listitem>
|
||||
</varlistentry>
|
||||
</variablelist>
|
||||
</para>
|
||||
</section>
|
||||
|
||||
<section id="acknowledgments">
|
||||
<title> Acknowledgments </title>
|
||||
<para>
|
||||
Thanks to Vera Djuraskovic
|
||||
<email>veradjuraskovic@webhostinggeeks.com</email> for
|
||||
contributing a Serbo-Croatian translation of this document.
|
||||
</para>
|
||||
</section>
|
||||
</chapter>
|
||||
|
||||
<chapter id="introduction">
|
||||
<title>Introduction</title>
|
||||
|
||||
<para>
|
||||
sysbench is a modular, cross-platform and multi-threaded benchmark tool for evaluating OS parameters
|
||||
that are important for a system running a database under intensive load.
|
||||
</para>
|
||||
<para>
|
||||
The idea of this benchmark suite is to quickly get an impression about system performance without setting up
|
||||
complex database benchmarks or even without installing a database at all.
|
||||
</para>
|
||||
<section id="features">
|
||||
<title>Features of sysbench</title>
|
||||
<para>
|
||||
Current features allow to test the following system parameters:
|
||||
<itemizedlist>
|
||||
<listitem><para>file I/O performance</para></listitem>
|
||||
<listitem><para>scheduler performance</para></listitem>
|
||||
<listitem><para>memory allocation and transfer speed</para></listitem>
|
||||
<listitem><para>POSIX threads implementation performance</para></listitem>
|
||||
<listitem><para>database server performance</para></listitem>
|
||||
</itemizedlist>
|
||||
</para>
|
||||
</section>
|
||||
|
||||
<section id="design">
|
||||
<title>Design</title>
|
||||
<para>
|
||||
The design is very simple. sysbench runs a specified number of threads and they all execute requests in parallel.
|
||||
The actual workload produced by requests depends on the specified test mode. You can limit either the total number of
|
||||
requests or the total time for the benchmark, or both.
|
||||
</para>
|
||||
<para>
|
||||
Available test modes are implemented by compiled-in modules, and sysbench was designed to make adding new test modes
|
||||
an easy task. Each test mode may have additional (or workload-specific) options.
|
||||
</para>
|
||||
</section>
|
||||
|
||||
<section id="links">
|
||||
<title>Links</title>
|
||||
|
||||
<variablelist>
|
||||
<varlistentry>
|
||||
<term>Home page</term>
|
||||
<listitem><para>
|
||||
<ulink url="http://sysbench.sf.net/">http://sysbench.sf.net/</ulink>.
|
||||
</para></listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term>Download</term>
|
||||
<listitem><para>
|
||||
<ulink url="http://sf.net/projects/sysbench/">http://sf.net/projects/sysbench/</ulink>.
|
||||
</para></listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term>Mailing lists</term>
|
||||
<listitem><para>
|
||||
<ulink url="http://sourceforge.net/mail/?group_id=102348">sysbench-general</ulink>
|
||||
</para></listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term>Web forums</term>
|
||||
<listitem><para>
|
||||
<itemizedlist>
|
||||
<listitem>
|
||||
<ulink url="http://sourceforge.net/forum/forum.php?forum_id=353125">Developers</ulink>
|
||||
</listitem>
|
||||
<listitem>
|
||||
<ulink url="http://sourceforge.net/forum/forum.php?forum_id=353124">Help</ulink>
|
||||
</listitem>
|
||||
<listitem>
|
||||
<ulink url="http://sourceforge.net/forum/forum.php?forum_id=353123">Open discussion</ulink>
|
||||
</listitem>
|
||||
</itemizedlist>
|
||||
</para></listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term>Bug tracking system</term>
|
||||
<listitem><para>
|
||||
<itemizedlist>
|
||||
<listitem>
|
||||
<ulink url="http://sourceforge.net/tracker/?atid=631676&group_id=102348&func=browse">
|
||||
Bug reports
|
||||
</ulink>
|
||||
</listitem>
|
||||
<listitem>
|
||||
<ulink url="http://sourceforge.net/tracker/?atid=631679&group_id=102348&func=browse">
|
||||
Feature requests
|
||||
</ulink>
|
||||
</listitem>
|
||||
</itemizedlist>
|
||||
</para></listitem>
|
||||
</varlistentry>
|
||||
</variablelist>
|
||||
|
||||
</section>
|
||||
|
||||
<section id="install">
|
||||
<title>Installation</title>
|
||||
|
||||
<para>
|
||||
If you are building sysbench from a Bazaar repository rather than from a release tarball,
|
||||
you should run <command>./autogen.sh</command> before building.
|
||||
</para>
|
||||
<para>
|
||||
The following standart procedure will be sufficient to build sysbench in most cases:
|
||||
<synopsis>
|
||||
<command>./configure</command>
|
||||
<command>make</command>
|
||||
<command>make install</command>
|
||||
</synopsis>
|
||||
The above procedure will try to compile sysbench with MySQL support by default. If you have MySQL headers and libraries
|
||||
in non-standard locations (and no <command>mysql_config</command> can be found in the <constant>PATH</constant>
|
||||
environmental variable), then you can specify them explicitly with <option>--with-mysql-includes</option> and
|
||||
<option>--with-mysql-libs</option> options to <command>./configure</command>.
|
||||
</para>
|
||||
<para>
|
||||
To compile sysbench without MySQL support, use <option>--without-mysql</option>. In this case all database-related
|
||||
test modes will be unavailable.
|
||||
</para>
|
||||
<para>
|
||||
If you are running on a 64-bit platform, make sure to build a 64-bit binary by passing the proper target platform and compiler options to <command>configure</command> script. You can also consult the INSTALL file for generic installation instructions.
|
||||
</para>
|
||||
</section>
|
||||
|
||||
</chapter>
|
||||
|
||||
<chapter id="usage">
|
||||
<title>Usage</title>
|
||||
<section id="general_syntax">
|
||||
<title>General syntax</title>
|
||||
|
||||
<para>
|
||||
The general syntax for sysbench is as follows:
|
||||
<screen>
|
||||
sysbench <emphasis>[common-options]</emphasis> --test=<emphasis>name</emphasis> <emphasis>[test-options]</emphasis> <emphasis>command</emphasis>
|
||||
</screen>
|
||||
See <xref linkend="common_options"/> for a description of common options and documentation for particular test mode for a list
|
||||
of test-specific options.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
Below is a brief description of available commands and their purpose:
|
||||
<variablelist>
|
||||
<varlistentry>
|
||||
<term><command>prepare</command></term>
|
||||
<listitem>Performs preparative actions for those tests which need them, e.g. creating the necessary
|
||||
files on disk for the <option>fileio</option> test, or filling the test database for the
|
||||
<option>oltp</option> test.
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term><command>run</command></term>
|
||||
<listitem>Runs the actual test specified with the <option>--test=<emphasis>name</emphasis></option> option.
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term><command>cleanup</command></term>
|
||||
<listitem>Removes temporary data after the test run in those tests which create one.
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term><command>help</command></term>
|
||||
<listitem>Displays usage information for a test specified with the
|
||||
<option>--test=<emphasis>name</emphasis></option> option.
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
</variablelist>
|
||||
</para>
|
||||
<para>
|
||||
Also you can use <command>sysbench help</command> to display the brief usage summary and the list of available test modes.
|
||||
</para>
|
||||
</section>
|
||||
|
||||
<section id="common_options">
|
||||
<title>General command line options</title>
|
||||
<para>
|
||||
The table below lists the supported common options, their descriptions and default values:
|
||||
</para>
|
||||
<informaltable frame="all">
|
||||
<tgroup cols='3'>
|
||||
<tbody>
|
||||
<row><entry><emphasis>Option</emphasis></entry><entry><emphasis>Description</emphasis></entry><entry><emphasis>Default value</emphasis></entry></row>
|
||||
<row><entry><option>--num-threads</option></entry><entry>The total number of worker threads to create</entry><entry>1</entry></row>
|
||||
<row><entry><option>--max-requests</option></entry><entry>Limit for total number of requests. 0 means unlimited</entry><entry>10000</entry></row>
|
||||
<row><entry><option>--max-time</option></entry><entry>Limit for total execution time in seconds. 0 (default) means unlimited</entry><entry>0</entry></row>
|
||||
<row><entry><option>--thread-stack-size</option></entry><entry>Size of stack for each thread</entry><entry>32K</entry></row>
|
||||
<row><entry><option>--init-rng</option></entry><entry>Specifies if random numbers generator should be initialized from timer before the test start</entry><entry>off</entry></row>
|
||||
<row><entry><option>--report-interval</option></entry><entry>Periodically report intermediate statistics with a specified interval in seconds. Note that statistics produced by this option is per-interval rather than cumulative. 0 disables intermediate reports</entry><entry>0</entry></row>
|
||||
<row><entry><option>--test</option></entry><entry>Name of the test mode to run</entry><entry><emphasis>Required</emphasis></entry></row>
|
||||
<row><entry><option>--debug</option></entry><entry>Print more debug info</entry><entry>off</entry></row>
|
||||
<row><entry><option>--validate</option></entry><entry>Perform
|
||||
validation of test results where possible </entry><entry>off</entry></row>
|
||||
<row><entry><option>--help</option></entry><entry>Print help on general syntax or on a test mode specified with --test, and exit</entry><entry>off</entry></row>
|
||||
<row><entry><option>--verbosity</option></entry><entry>Verbosity level (0 - only critical messages, 5 - debug)</entry><entry>4</entry></row>
|
||||
<row><entry><option>--percentile</option></entry>
|
||||
<entry>
|
||||
<para>
|
||||
sysbench measures execution times for all processed
|
||||
requests to display statistical information like minimal, average and
|
||||
maximum execution time. For most benchmarks it is also useful to know
|
||||
a request execution time value matching some percentile (e.g. 95%
|
||||
percentile means we should drop 5% of the most long requests and
|
||||
choose the maximal value from the remaining ones).
|
||||
</para>
|
||||
<para>
|
||||
This option allows to specify a percentile rank of query
|
||||
execution times to count
|
||||
</para>
|
||||
</entry>
|
||||
<entry>95</entry></row>
|
||||
<row><entry><option>--validate</option></entry><entry>Perform validation of test results where possible</entry><entry>off</entry></row>
|
||||
</tbody>
|
||||
</tgroup>
|
||||
</informaltable>
|
||||
<para>
|
||||
Note that numerical values for all <emphasis>size</emphasis> options
|
||||
(like <option>--thread-stack-size</option> in this table) may be
|
||||
specified by appending the corresponding multiplicative suffix (K for
|
||||
kilobytes, M for megabytes, G for gigabytes and T for terabytes).
|
||||
</para>
|
||||
</section>
|
||||
|
||||
|
||||
<section id="test_modes">
|
||||
<title>Test modes</title>
|
||||
This section gives a detailed description for each test mode available
|
||||
in sysbench.
|
||||
|
||||
<section id="cpu_mode">
|
||||
<title><option>cpu</option></title>
|
||||
</section>
|
||||
<para>
|
||||
The <option>cpu</option> is one of the most simple benchmarks in
|
||||
sysbench. In this mode each request consists in calculation of prime numbers up to a value
|
||||
specified by the <option>--cpu-max-primes</option> option. All calculations are performed using 64-bit integers.
|
||||
</para>
|
||||
<para>
|
||||
Each thread executes the requests concurrently until either the total number of requests or the total execution
|
||||
time exceed the limits specified with the common command line options.
|
||||
</para>
|
||||
<para>
|
||||
Example:
|
||||
<screen>
|
||||
sysbench --test=cpu --cpu-max-prime=20000 run
|
||||
</screen>
|
||||
</para>
|
||||
|
||||
<section id="threads_mode">
|
||||
<title><option>threads</option></title>
|
||||
</section>
|
||||
<para>
|
||||
This test mode was written to benchmark scheduler performance, more specifically the cases
|
||||
when a scheduler has a large number of threads competing for some set of mutexes.
|
||||
</para>
|
||||
<para>
|
||||
sysbench creates a specified number of threads and a specified number of mutexes. Then each thread
|
||||
starts running the requests consisting of locking the mutex, yielding the CPU, so the thread is
|
||||
placed in the run queue by the scheduler, then unlocking the mutex when the thread is rescheduled back
|
||||
to execution. For each request, the above actions are run several times in a loop, so the more iterations
|
||||
is performed, the more concurrency is placed on each mutex.
|
||||
</para>
|
||||
<para>
|
||||
The following options are available in this test mode:
|
||||
<informaltable frame="all">
|
||||
<tgroup cols='3'>
|
||||
<tbody>
|
||||
<row><entry><emphasis>Option</emphasis></entry><entry><emphasis>Description</emphasis></entry><entry><emphasis>Default value</emphasis></entry></row>
|
||||
<row><entry><option>--thread-yields</option></entry><entry>Number of <emphasis>lock/yield/unlock</emphasis> loops to execute per each request</entry><entry>1000</entry></row>
|
||||
<row><entry><option>--thread-locks</option></entry><entry>Number of mutexes to create</entry><entry>8</entry></row>
|
||||
</tbody>
|
||||
</tgroup>
|
||||
</informaltable>
|
||||
</para>
|
||||
<para>
|
||||
Example:
|
||||
<screen>
|
||||
sysbench --num-threads=64 --test=threads --thread-yields=100 --thread-locks=2 run
|
||||
</screen>
|
||||
</para>
|
||||
|
||||
|
||||
<section id="mutex_mode">
|
||||
<title><option>mutex</option></title>
|
||||
</section>
|
||||
<para>
|
||||
This test mode was written to emulate a situation when all threads run concurrently most of the time,
|
||||
acquiring the mutex lock only for a short period of time (incrementing a global variable). So the purpose
|
||||
of this benchmarks is to examine the performance of mutex implementation.
|
||||
</para>
|
||||
<para>
|
||||
The following options are available in this test mode:
|
||||
<informaltable frame="all">
|
||||
<tgroup cols='3'>
|
||||
<tbody>
|
||||
<row><entry><emphasis>Option</emphasis></entry><entry><emphasis>Description</emphasis></entry><entry><emphasis>Default value</emphasis></entry></row>
|
||||
<row><entry><option>--mutex-num</option></entry><entry>Number of mutexes. The actual mutex to lock is chosen randomly before each lock</entry><entry>4096</entry></row>
|
||||
<row><entry><option>--mutex-locks</option></entry><entry>Number of mutex locks to acquire per each request</entry><entry>50000</entry></row>
|
||||
<row><entry><option>--mutex-loops</option></entry><entry>Number of iterations for an empty loop to perform before acquiring the lock</entry><entry>10000</entry></row>
|
||||
</tbody>
|
||||
</tgroup>
|
||||
</informaltable>
|
||||
</para>
|
||||
|
||||
|
||||
<section id="memory_mode">
|
||||
<title><option>memory</option></title>
|
||||
<para>
|
||||
This test mode can be used to benchmark sequential memory reads or writes. Depending on command line
|
||||
options each thread can access either a global or a local block for all memory operations.
|
||||
</para>
|
||||
<para>
|
||||
The following options are available in this test mode:
|
||||
<informaltable frame="all">
|
||||
<tgroup cols='3'>
|
||||
<tbody>
|
||||
<row><entry><emphasis>Option</emphasis></entry><entry><emphasis>Description</emphasis></entry><entry><emphasis>Default value</emphasis></entry></row>
|
||||
<row><entry><option>--memory-block-size</option></entry><entry>Size of memory block to use</entry><entry>1K</entry></row>
|
||||
<row><entry><option>--memory-scope</option></entry><entry>
|
||||
Possible values: <option>global</option>, <option>local</option>. Specifies whether each thread will
|
||||
use a globally allocated memory block, or a local one.
|
||||
</entry><entry>global</entry></row>
|
||||
<row><entry><option>--memory-total-size</option></entry><entry>Total size of data to transfer</entry><entry>100G</entry></row>
|
||||
<row><entry><option>--memory-oper</option></entry><entry>
|
||||
Type of memory operations. Possible values: <option>read</option>, <option>write</option>.
|
||||
</entry><entry>100G</entry></row>
|
||||
</tbody>
|
||||
</tgroup>
|
||||
</informaltable>
|
||||
</para>
|
||||
</section>
|
||||
|
||||
<section id="fileio_mode">
|
||||
<title><option>fileio</option></title>
|
||||
|
||||
<para>
|
||||
This test mode can be used to produce various kinds of file I/O workloads. At the <option>prepare</option>
|
||||
stage sysbench creates a specified number of files with a specified total size, then at the <option>run</option>
|
||||
stage, each thread performs specified I/O operations on this set of files.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
When the global <option>--validate</option> option is used with the <option>fileio</option> test mode, sysbench
|
||||
performs checksums validation on all data read from the disk. On each write operation the block is filled with random values,
|
||||
then the checksum is calculated
|
||||
and stored in the block along with the offset of this block within a file. On each read operation the block is validated
|
||||
by comparing the stored offset with the real offset, and the stored checksum with the real calculated checksum.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
The following I/O operations are supported:
|
||||
|
||||
<variablelist>
|
||||
<varlistentry>
|
||||
<term><command>seqwr</command></term>
|
||||
<listitem>sequential write
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term><command>seqrewr</command></term>
|
||||
<listitem>sequential rewrite
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term><command>seqrd</command></term>
|
||||
<listitem>sequential read
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term><command>rndrd</command></term>
|
||||
<listitem>random read
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term><command>rndwr</command></term>
|
||||
<listitem>random write
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term><command>rndrw</command></term>
|
||||
<listitem>combined random read/write
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
</variablelist>
|
||||
</para>
|
||||
|
||||
<para>
|
||||
Also, the following file access modes can be specified, if the underlying platform supports them:
|
||||
<variablelist>
|
||||
<varlistentry>
|
||||
<term>Asynchronous I/O mode</term>
|
||||
<listitem>
|
||||
At the moment only Linux AIO implementation is supported. When running in asynchronous mode,
|
||||
sysbench queues a specified number of I/O requests using Linux AIO API, then waits for
|
||||
at least one of submitted requests to complete. After that a new series of I/O requests
|
||||
is submitted.
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term>Slow <option>mmap()</option> mode</term>
|
||||
<listitem>In this mode sysbench will use <option>mmap</option>'ed I/O. However, a separate
|
||||
<option>mmap</option> will be used for each I/O request due to the limitation of 32-bit
|
||||
architectures (we cannot <option>mmap()</option> the whole file, as its size migth possibly
|
||||
exceed the maximum of 2 GB of the process address space).
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term>Fast <option>mmap()</option> mode</term>
|
||||
<listitem>On 64-bit architectures it is possible to <option>mmap()</option> the whole file
|
||||
into the process address space, avoiding the limitation of 2 GB on 32-bit platforms.
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term>Using <option>fdatasync()</option> instead of <option>fsync()</option></term>
|
||||
Flush only data buffers, but not the metadata.
|
||||
<listitem>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term>Additional flags to <option>open(2)</option></term>
|
||||
<listitem>sysbench can use additional flags to <option>open(2)</option>, such as <option>O_SYNC</option>,
|
||||
<option>O_DSYNC</option> and <option>O_DIRECT</option>.
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
</variablelist>
|
||||
</para>
|
||||
<para>
|
||||
Below is a list of test-specific option for the <command>fileio</command> mode:
|
||||
|
||||
<informaltable frame="all">
|
||||
<tgroup cols='3'>
|
||||
<tbody>
|
||||
<row><entry><emphasis>Option</emphasis></entry><entry><emphasis>Description</emphasis></entry><entry><emphasis>Default value</emphasis></entry></row>
|
||||
<row><entry><option>--file-num</option></entry><entry>Number of files to create</entry><entry>128</entry></row>
|
||||
<row><entry><option>--file-block-size</option></entry><entry>
|
||||
Block size to use in all I/O operations
|
||||
</entry><entry>16K</entry></row>
|
||||
<row><entry><option>--file-total-size</option></entry><entry>Total size of files</entry><entry>2G</entry></row>
|
||||
<row><entry><option>--file-test-mode</option></entry><entry>
|
||||
Type of workload to produce. Possible values: <option>seqwr</option>, <option>seqrewr</option>,
|
||||
<option>seqrd</option>, <option>rndrd</option>, <option>rndwr</option>, <option>rndwr</option> (see above)
|
||||
</entry><entry><emphasis>required</emphasis></entry></row>
|
||||
<row><entry><option>--file-io-mode</option></entry><entry>
|
||||
I/O mode. Possible values: <option>sync</option>, <option>async</option>, <option>map</option>,
|
||||
</entry><entry>sync</entry></row>
|
||||
<row><entry><option>--file-async-backlog</option></entry><entry>
|
||||
Number of asynchronous operations to queue per thread (only for <option>--file-io-mode=async</option>, see above)
|
||||
</entry><entry>128</entry></row>
|
||||
<row><entry><option> --file-extra-flags</option></entry><entry>
|
||||
Additional flags to use with <option>open(2)</option>
|
||||
</entry><entry></entry></row>
|
||||
<row><entry><option>--file-fsync-freq</option></entry><entry>
|
||||
Do <option>fsync()</option> after this number of requests (0 - don't use <option>fsync()</option>)
|
||||
</entry><entry>100</entry></row>
|
||||
<row><entry><option>--file-fsync-all</option></entry><entry>
|
||||
Do <option>fsync()</option> after each write operation
|
||||
</entry><entry>no</entry></row>
|
||||
<row><entry><option>--file-fsync-end</option></entry><entry>
|
||||
Do <option>fsync()</option> at the end of the test
|
||||
</entry><entry>yes</entry></row>
|
||||
<row><entry><option>--file-fsync-mode</option></entry><entry>
|
||||
Which method to use for synchronization. Possible values: <option>fsync</option>, <option>fdatasync</option> (see above)
|
||||
</entry><entry>fsync</entry></row>
|
||||
<row><entry><option>--file-merged-requests</option></entry><entry>
|
||||
Merge at most this number of I/O requests if possible (0 - don't merge)
|
||||
</entry><entry>0</entry></row>
|
||||
<row><entry><option>--file-rw-ratio</option></entry><entry>
|
||||
reads/writes ration for combined random read/write test
|
||||
</entry><entry>1.5</entry></row>
|
||||
|
||||
</tbody>
|
||||
</tgroup>
|
||||
</informaltable>
|
||||
|
||||
</para>
|
||||
|
||||
<para>
|
||||
Usage example:
|
||||
<screen>
|
||||
$ sysbench --num-threads=16 --test=fileio --file-total-size=3G --file-test-mode=rndrw prepare
|
||||
$ sysbench --num-threads=16 --test=fileio --file-total-size=3G --file-test-mode=rndrw run
|
||||
$ sysbench --num-threads=16 --test=fileio --file-total-size=3G --file-test-mode=rndrw cleanup
|
||||
</screen>
|
||||
In the above example the first command creates 128 files with the total size of 3 GB in the current directory, the
|
||||
second command runs the actual benchmark and displays the results upon completion, and the third one removes the files
|
||||
used for the test.
|
||||
</para>
|
||||
</section>
|
||||
|
||||
<section id="database_mode">
|
||||
<title><option>oltp</option></title>
|
||||
</section>
|
||||
<para>
|
||||
This test mode was written to benchmark a real database performance. At the <command>prepare</command> stage
|
||||
the following table is created in the specified database (<option>sbtest</option> by default):
|
||||
<screen>
|
||||
CREATE TABLE `sbtest` (
|
||||
`id` int(10) unsigned NOT NULL auto_increment,
|
||||
`k` int(10) unsigned NOT NULL default '0',
|
||||
`c` char(120) NOT NULL default '',
|
||||
`pad` char(60) NOT NULL default '',
|
||||
PRIMARY KEY (`id`),
|
||||
KEY `k` (`k`);
|
||||
</screen>
|
||||
Then this table is filled with a specified number of rows.
|
||||
</para>
|
||||
<para>
|
||||
The following execution modes are available at the <command>run</command> stage:
|
||||
<variablelist>
|
||||
<varlistentry>
|
||||
<term>Simple</term>
|
||||
<listitem>
|
||||
<para>
|
||||
In this mode each thread runs simple queries of the following form:
|
||||
<screen> SELECT c FROM sbtest WHERE id=<emphasis>N</emphasis> </screen>
|
||||
where <emphasis>N</emphasis> takes a random value in range 1..<emphasis><table size></emphasis>
|
||||
</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term>Advanced transactional</term>
|
||||
<listitem>
|
||||
<para>
|
||||
Each thread performs transactions on the test table. If the test table and database support transactions
|
||||
(e.g. InnoDB engine in MySQL), then <option>BEGIN</option>/<option>COMMIT</option> statements will be used
|
||||
to start/stop a transaction. Otherwise, sysbench will use <option>LOCK TABLES</option>/<option>UNLOCK TABLES
|
||||
</option> statements (e.g. for MyISAM engine in MySQL). If some rows are deleted in a transaction,
|
||||
the same rows will be inserted within the same transaction, so this test mode does not destruct any data
|
||||
in the test table and can be run multiple times on the same table.
|
||||
</para>
|
||||
|
||||
Depending on the command line options, each transaction may contain the following statements:
|
||||
<itemizedlist>
|
||||
<listitem>Point queries: <screen>SELECT c FROM sbtest WHERE id=<emphasis>N</emphasis></screen></listitem>
|
||||
<listitem>
|
||||
Range queries: <screen>SELECT c FROM sbtest WHERE id BETWEEN <emphasis>N</emphasis> AND <emphasis>M</emphasis> </screen> </listitem>
|
||||
<listitem>
|
||||
Range SUM() queries: <screen>SELECT SUM(K) FROM sbtest WHERE id BETWEEN <emphasis>N</emphasis> and <emphasis>M</emphasis></screen></listitem>
|
||||
<listitem>Range ORDER BY queries:<screen>SELECT c FROM sbtest WHERE id between <emphasis>N</emphasis> and <emphasis>M</emphasis> ORDER BY c</screen></listitem>
|
||||
<listitem>Range DISTINCT queries:<screen>SELECT DISTINCT c FROM sbtest WHERE id BETWEEN <emphasis>N</emphasis> and <emphasis>M</emphasis> ORDER BY c</screen> </listitem>
|
||||
<listitem>UPDATEs on index column:<screen>UPDATE sbtest SET k=k+1 WHERE id=<emphasis>N</emphasis> </screen> </listitem>
|
||||
<listitem>UPDATEs on non-index column:<screen>UPDATE sbtest SET c=<emphasis>N</emphasis> WHERE id=<emphasis>M</emphasis> </screen> </listitem>
|
||||
<listitem>DELETE queries:<screen>DELETE FROM sbtest WHERE id=<emphasis>N</emphasis> </screen> </listitem>
|
||||
<listitem>INSERT queries:<screen>INSERT INTO sbtest VALUES (<emphasis>...</emphasis>) </screen> </listitem>
|
||||
</itemizedlist>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
|
||||
<term>Non-transactional</term>
|
||||
<listitem>
|
||||
<para>
|
||||
This mode is similar to <command>Simple</command>, but you can also choose the query to run. Note that unlike the
|
||||
<command>Advanced transactional</command> mode, this one does not preserve the test table between requests, so
|
||||
you should recreate it with the appropriate <command>cleanup</command>/<command>prepare</command> commands between
|
||||
consecutive benchmarks.
|
||||
</para>
|
||||
<para>
|
||||
Below is a list of possible queries:
|
||||
<itemizedlist>
|
||||
<listitem>
|
||||
Point queries:
|
||||
<screen>SELECT pad FROM sbtest WHERE id=<emphasis>N</emphasis></screen>
|
||||
</listitem>
|
||||
<listitem>
|
||||
UPDATEs on index column:
|
||||
<screen>UPDATE sbtest SET k=k+1 WHERE id=<emphasis>N</emphasis></screen>
|
||||
</listitem>
|
||||
<listitem>
|
||||
UPDATEs on non-index column:
|
||||
<screen>UPDATE sbtest SET c=<emphasis>N</emphasis> WHERE id=<emphasis>M</emphasis></screen>
|
||||
</listitem>
|
||||
<listitem>
|
||||
DELETE queries:
|
||||
<screen>DELETE FROM sbtest WHERE id=<emphasis>N</emphasis></screen>
|
||||
The generated row IDs are unique over each test run, so no row is deleted twice.
|
||||
</listitem>
|
||||
<listitem>
|
||||
INSERT queries:
|
||||
<screen>INSERT INTO sbtest (k, c, pad) VALUES(<emphasis>N</emphasis>, <emphasis>M</emphasis>, <emphasis>S</emphasis>)</screen>
|
||||
</listitem>
|
||||
</itemizedlist>
|
||||
</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
</variablelist>
|
||||
</para>
|
||||
|
||||
<para>
|
||||
Below is a list of options available for the database test mode:
|
||||
|
||||
<informaltable frame="all">
|
||||
<tgroup cols='3'>
|
||||
<tbody>
|
||||
<row><entry><emphasis>Option</emphasis></entry><entry><emphasis>Description</emphasis></entry><entry><emphasis>Default value</emphasis></entry></row>
|
||||
<row><entry><option>--oltp-test-mode</option></entry><entry>Execution mode (see above). Possible values: <option>simpe</option> (simple), <option>complex</option> (advanced transactional) and <option>nontrx</option> (non-transactional)</entry><entry><option>complex</option></entry></row>
|
||||
<row><entry><option>--oltp-read-only</option></entry><entry>
|
||||
Read-only mode. No <option>UPDATE</option>, <option>DELETE</option> or <option>INSERT</option> queries will be performed.
|
||||
</entry><entry>off</entry></row>
|
||||
<row><entry><option>--oltp-reconnect</option></entry><entry>
|
||||
Re-connect to serveron each transaction.
|
||||
</entry><entry>off</entry></row>
|
||||
<row><entry><option>--oltp-range-size</option></entry><entry>Range size for range queries</entry><entry>100</entry></row>
|
||||
<row><entry><option>--oltp-point-selects</option></entry><entry>
|
||||
Number of point select queries in a single transaction
|
||||
</entry><entry>10</entry></row>
|
||||
<row><entry><option>--oltp-simple-ranges</option></entry><entry>
|
||||
Number of simple range queries in a single transaction
|
||||
</entry><entry>1</entry></row>
|
||||
<row><entry><option>--oltp-sum-ranges</option></entry><entry>
|
||||
Number of SUM range queries in a single transaction
|
||||
</entry><entry>1</entry></row>
|
||||
<row><entry><option>--oltp-order-ranges</option></entry><entry>
|
||||
Number of ORDER range queries in a single transaction
|
||||
</entry><entry>1</entry></row>
|
||||
<row><entry><option>--oltp-distinct-ranges</option></entry><entry>
|
||||
Number of DISTINCT range queries in a single transaction
|
||||
</entry><entry>1</entry></row>
|
||||
<row><entry><option>--oltp-index-updates</option></entry><entry>
|
||||
Number of index UPDATE queries in a single transaction
|
||||
</entry><entry>1</entry></row>
|
||||
<row><entry><option>--oltp-non-index-updates</option></entry><entry>
|
||||
Number of non-index UPDATE queries in a single transaction
|
||||
</entry><entry>1</entry></row>
|
||||
<row><entry><option> --oltp-nontrx-mode</option></entry><entry>
|
||||
Type of queries for non-transactional execution mode (see above). Possible values: <option>select</option>,
|
||||
<option>update_key</option>, <option>update_nokey</option>, <option>insert</option>, <option>delete</option>.
|
||||
</entry><entry><option>select</option></entry></row>
|
||||
<row><entry><option>--oltp-connect-delay</option></entry><entry>
|
||||
Time in microseconds to sleep after each connection to database
|
||||
</entry><entry>10000</entry></row>
|
||||
<row><entry><option>--oltp-user-delay-min</option></entry><entry>
|
||||
Minimum time in microseconds to sleep after each request
|
||||
</entry><entry>0</entry></row>
|
||||
<row><entry><option>--oltp-user-delay-max</option></entry><entry>
|
||||
Maximum time in microseconds to sleep after each request
|
||||
</entry><entry>0</entry></row>
|
||||
<row><entry><option>--oltp-table-name</option></entry><entry>
|
||||
Name of the test table
|
||||
</entry><entry>sbtest</entry></row>
|
||||
<row><entry><option>--oltp-table-size</option></entry><entry>
|
||||
Number of rows in the test table
|
||||
</entry><entry>10000</entry></row>
|
||||
<row><entry><option>--oltp-dist-type</option></entry><entry>
|
||||
<para>
|
||||
Distribution of random numbers. Possible values: <option>uniform</option> (uniform distribution),
|
||||
<option>gauss</option> (gaussian distribution) and <option>special</option>.
|
||||
</para>
|
||||
<para>
|
||||
With special distribution a specified percent of numbers is generated in a specified percent of cases (see options below).
|
||||
</para>
|
||||
</entry><entry><option>special</option></entry></row>
|
||||
<row><entry><option>--oltp-dist-pct</option></entry><entry>
|
||||
Percentage of values to be treated as 'special' (for special distribution)
|
||||
</entry><entry>1</entry></row>
|
||||
<row><entry><option>--oltp-dist-res</option></entry><entry>
|
||||
Percentage of cases when 'special' values are generated (for special distribution)
|
||||
</entry><entry>75</entry></row>
|
||||
<row><entry><option>--db-ps-mode</option></entry><entry>
|
||||
If the database driver supports Prepared Statements API, sysbench will use server-side prepared statements for all queries
|
||||
where possible. Otherwise, client-side (or emulated) prepared statements will be used. This option allows to force using
|
||||
emulation even when PS API is available. Possible values: <option>disable</option>, <option>auto</option>.
|
||||
</entry><entry><option>auto</option></entry></row>
|
||||
|
||||
</tbody>
|
||||
</tgroup>
|
||||
</informaltable>
|
||||
</para>
|
||||
|
||||
<para>
|
||||
Also, each database driver may provide its own options. Currently only MySQL driver is available. Below is a list of MySQL-specific options:
|
||||
|
||||
<informaltable frame="all">
|
||||
<tgroup cols='3'>
|
||||
<tbody>
|
||||
<row><entry><emphasis>Option</emphasis></entry><entry><emphasis>Description</emphasis></entry><entry><emphasis>Default value</emphasis></entry></row>
|
||||
<row><entry><option>--mysql-host</option></entry>
|
||||
<entry>
|
||||
<para>
|
||||
MySQL server host.
|
||||
</para>
|
||||
<para>
|
||||
Starting from version 0.4.5 you may specify a list of hosts separated by commas. In this case sysbench will distribute connections between specified MySQL hosts on a round-robin basis. Note that all connection ports and passwords must be the same on all hosts. Also, databases and tables must be prepared explicitely on each host before executing the benchmark.
|
||||
</para>
|
||||
</entry><entry><option>localhost</option></entry></row>
|
||||
<row><entry><option>--mysql-port</option></entry><entry>
|
||||
MySQL server port (in case TCP/IP connection should be used)
|
||||
</entry><entry>3306</entry></row>
|
||||
<row><entry><option>--mysql-socket</option></entry><entry>Unix socket file to communicate with the MySQL server</entry><entry></entry></row>
|
||||
<row><entry><option>--mysql-user</option></entry><entry>
|
||||
MySQL user
|
||||
</entry><entry>user</entry></row>
|
||||
<row><entry><option>--mysql-password</option></entry><entry>
|
||||
MySQL password
|
||||
</entry><entry></entry></row>
|
||||
<row><entry><option>--mysql-db</option></entry><entry>
|
||||
MySQL database name. Note sysbench will not automatically create this database. You should create it manually and grant
|
||||
the appropriate privileges to a user which will be used to access the test table.
|
||||
</entry><entry>sbtest</entry></row>
|
||||
<row><entry><option>--mysql-table-type</option></entry><entry>
|
||||
Type of the test table. Possible values: <option>myisam</option>, <option>innodb</option>, <option>heap</option>,
|
||||
<option>ndbcluster</option>, <option>bdb</option>.
|
||||
</entry><entry>innodb</entry></row>
|
||||
<row><entry><option>--myisam-max-rows</option></entry><entry>
|
||||
MAX_ROWS option for MyISAM tables (required for big tables)
|
||||
</entry><entry>1000000</entry></row>
|
||||
</tbody>
|
||||
</tgroup>
|
||||
</informaltable>
|
||||
</para>
|
||||
|
||||
<para>
|
||||
Example usage:
|
||||
<screen>
|
||||
$ sysbench --test=oltp --mysql-table-engine=myisam --oltp-table-size=1000000 --mysql-socket=/tmp/mysql.sock prepare
|
||||
$ sysbench --num-threads=16 --max-requests=100000 --test=oltp --oltp-table-size=1000000 --mysql-socket=/tmp/mysql.sock --oltp-read-only=on run
|
||||
</screen>
|
||||
The first command will create a MyISAM table 'sbtest' in a database 'sbtest' on a MySQL server using <option>/tmp/mysql.sock</option> socket, then fill this table with 1M records. The second command will run the actual benchmark with 16 client threads, limiting the total number of request by 100,000.
|
||||
</para>
|
||||
|
||||
</section>
|
||||
|
||||
</chapter>
|
||||
|
||||
</book>
|
||||
|
|
@ -0,0 +1,18 @@
|
|||
# Copyright (C) 2008 MySQL AB
|
||||
# Copyright (C) 2008 Alexey Kopytov <akopytov@gmail.com>
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation; either version 2 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, write to the Free Software
|
||||
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
|
||||
EXTRA_DIST=catalog.xml.in xhtml-chunk.xsl xhtml-common.xsl xhtml.xsl
|
||||
|
|
@ -0,0 +1,16 @@
|
|||
<?xml version="1.0"?>
|
||||
<!DOCTYPE catalog PUBLIC "-//OASIS/DTD Entity Resolution XML Catalog V1.0//EN"
|
||||
"http://www.oasis-open.org/committees/entity/release/1.0/catalog.dtd">
|
||||
|
||||
<catalog xmlns="urn:oasis:names:tc:entity:xmlns:xml:catalog">
|
||||
<nextCatalog catalog="@XML_CATALOG@" />
|
||||
|
||||
@CAT_ENTRY_START@
|
||||
<uri name="http://docbook.sourceforge.net/release/xsl/current/xhtml/docbook.xsl"
|
||||
uri="@DOCBOOK_ROOT@/xhtml/docbook.xsl"/>
|
||||
<uri name="http://docbook.sourceforge.net/release/xsl/current/xhtml/chunk.xsl"
|
||||
uri="@DOCBOOK_ROOT@/xhtml/chunk.xsl"/>
|
||||
@CAT_ENTRY_END@
|
||||
|
||||
<uri name="xsl/xhtml-common.xsl" uri="@top_srcdir@/doc/xsl/xhtml-common.xsl"/>
|
||||
</catalog>
|
||||
|
|
@ -0,0 +1,52 @@
|
|||
<?xml version='1.0'?>
|
||||
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
|
||||
version="1.0">
|
||||
<xsl:import href="http://docbook.sourceforge.net/release/xsl/current/xhtml/chunk.xsl"/>
|
||||
<xsl:import href="xhtml-common.xsl"/>
|
||||
|
||||
<xsl:template name="process-chunk">
|
||||
<xsl:param name="prev" select="."/>
|
||||
<xsl:param name="next" select="."/>
|
||||
|
||||
<xsl:variable name="ischunk">
|
||||
<xsl:call-template name="chunk"/>
|
||||
</xsl:variable>
|
||||
|
||||
<xsl:variable name="chunkfn">
|
||||
<xsl:if test="$ischunk='1'">
|
||||
<xsl:apply-templates mode="chunk-filename" select="."/>
|
||||
</xsl:if>
|
||||
</xsl:variable>
|
||||
|
||||
<xsl:if test="$ischunk='0'">
|
||||
<xsl:message>
|
||||
<xsl:text>Error </xsl:text>
|
||||
<xsl:value-of select="name(.)"/>
|
||||
<xsl:text> is not a chunk!</xsl:text>
|
||||
</xsl:message>
|
||||
</xsl:if>
|
||||
|
||||
<xsl:variable name="filename">
|
||||
<xsl:call-template name="make-relative-filename">
|
||||
<xsl:with-param name="base.dir" select="$base.dir"/>
|
||||
<xsl:with-param name="base.name" select="$chunkfn"/>
|
||||
</xsl:call-template>
|
||||
</xsl:variable>
|
||||
|
||||
<!-- FIXME: use Strict when the problems with width on td/th are
|
||||
sorted out. Not yet. -->
|
||||
<xsl:call-template name="write.chunk.with.doctype">
|
||||
<xsl:with-param name="filename" select="$filename"/>
|
||||
<xsl:with-param name="indent" select="'yes'"/>
|
||||
<xsl:with-param name="doctype-public">-//W3C//DTD XHTML 1.0 Transitional//EN</xsl:with-param>
|
||||
<xsl:with-param name="doctype-system">http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd</xsl:with-param>
|
||||
<xsl:with-param name="content">
|
||||
<xsl:call-template name="chunk-element-content">
|
||||
<xsl:with-param name="prev" select="$prev"/>
|
||||
<xsl:with-param name="next" select="$next"/>
|
||||
</xsl:call-template>
|
||||
</xsl:with-param>
|
||||
</xsl:call-template>
|
||||
</xsl:template>
|
||||
|
||||
</xsl:stylesheet>
|
||||
|
|
@ -0,0 +1,50 @@
|
|||
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
|
||||
version="1.0">
|
||||
|
||||
<xsl:param name="use.id.as.filename" select="1"/>
|
||||
<xsl:param name="section.autolabel" select="1"/>
|
||||
<xsl:param name="chapter.autolabel" select="1"/>
|
||||
<xsl:param name="ulink.target" select="''"/>
|
||||
|
||||
<!-- Custom template for programlisting, screen and synopsis to generate a gray
|
||||
background to the item. -->
|
||||
<xsl:template match="programlisting|screen|synopsis">
|
||||
<xsl:param name="suppress-numbers" select="'0'"/>
|
||||
<xsl:variable name="vendor" select="system-property('xsl:vendor')"/>
|
||||
<xsl:variable name="id"><xsl:call-template name="object.id"/></xsl:variable>
|
||||
|
||||
<xsl:if test="@id">
|
||||
<a href="{$id}"/>
|
||||
</xsl:if>
|
||||
|
||||
<xsl:choose>
|
||||
<xsl:when test="$suppress-numbers = '0'
|
||||
and @linenumbering = 'numbered'
|
||||
and $use.extensions != '0'
|
||||
and $linenumbering.extension != '0'">
|
||||
<xsl:variable name="rtf">
|
||||
<xsl:apply-templates/>
|
||||
</xsl:variable>
|
||||
<!-- Change the color background color in the line below. -->
|
||||
<table border="0" style="background: #E0E0E0;" width="90%">
|
||||
<tr><td>
|
||||
<pre class="{name(.)}">
|
||||
<xsl:call-template name="number.rtf.lines">
|
||||
<xsl:with-param name="rtf" select="$rtf"/>
|
||||
</xsl:call-template>
|
||||
</pre>
|
||||
</td></tr></table>
|
||||
</xsl:when>
|
||||
<xsl:otherwise>
|
||||
<!-- Change the color background color in the line below. -->
|
||||
<table border="0" style="background: #E0E0E0;" width="90%">
|
||||
<tr><td>
|
||||
<pre class="{name(.)}">
|
||||
<xsl:apply-templates/>
|
||||
</pre>
|
||||
</td></tr></table>
|
||||
</xsl:otherwise>
|
||||
</xsl:choose>
|
||||
</xsl:template>
|
||||
|
||||
</xsl:stylesheet>
|
||||
|
|
@ -0,0 +1,13 @@
|
|||
<?xml version='1.0'?>
|
||||
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
|
||||
xmlns:doc="http://nwalsh.com/xsl/documentation/1.0" version="1.0">
|
||||
|
||||
<xsl:import href="http://docbook.sourceforge.net/release/xsl/current/xhtml/docbook.xsl"/>
|
||||
<xsl:import href="xhtml-common.xsl"/>
|
||||
|
||||
<xsl:output method="xml" encoding="ISO-8859-1" indent="yes"
|
||||
doctype-public="-//W3C//DTD XHTML 1.0 Strict//EN"
|
||||
doctype-system="http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"
|
||||
/>
|
||||
|
||||
</xsl:stylesheet>
|
||||
|
|
@ -0,0 +1,294 @@
|
|||
#!/bin/sh
|
||||
#
|
||||
# install - install a program, script, or datafile
|
||||
#
|
||||
# This originates from X11R5 (mit/util/scripts/install.sh), which was
|
||||
# later released in X11R6 (xc/config/util/install.sh) with the
|
||||
# following copyright and license.
|
||||
#
|
||||
# Copyright (C) 1994 X Consortium
|
||||
#
|
||||
# Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
# of this software and associated documentation files (the "Software"), to
|
||||
# deal in the Software without restriction, including without limitation the
|
||||
# rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||
# sell copies of the Software, and to permit persons to whom the Software is
|
||||
# furnished to do so, subject to the following conditions:
|
||||
#
|
||||
# The above copyright notice and this permission notice shall be included in
|
||||
# all copies or substantial portions of the Software.
|
||||
#
|
||||
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
# X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
|
||||
# AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNEC-
|
||||
# TION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
#
|
||||
# Except as contained in this notice, the name of the X Consortium shall not
|
||||
# be used in advertising or otherwise to promote the sale, use or other deal-
|
||||
# ings in this Software without prior written authorization from the X Consor-
|
||||
# tium.
|
||||
#
|
||||
#
|
||||
# FSF changes to this file are in the public domain.
|
||||
#
|
||||
# Calling this script install-sh is preferred over install.sh, to prevent
|
||||
# `make' implicit rules from creating a file called install from it
|
||||
# when there is no Makefile.
|
||||
#
|
||||
# This script is compatible with the BSD install script, but was written
|
||||
# from scratch. It can only install one file at a time, a restriction
|
||||
# shared with many OS's install programs.
|
||||
|
||||
|
||||
# set DOITPROG to echo to test this script
|
||||
|
||||
# Don't use :- since 4.3BSD and earlier shells don't like it.
|
||||
doit="${DOITPROG-}"
|
||||
|
||||
|
||||
# put in absolute paths if you don't have them in your path; or use env. vars.
|
||||
|
||||
mvprog="${MVPROG-mv}"
|
||||
cpprog="${CPPROG-cp}"
|
||||
chmodprog="${CHMODPROG-chmod}"
|
||||
chownprog="${CHOWNPROG-chown}"
|
||||
chgrpprog="${CHGRPPROG-chgrp}"
|
||||
stripprog="${STRIPPROG-strip}"
|
||||
rmprog="${RMPROG-rm}"
|
||||
mkdirprog="${MKDIRPROG-mkdir}"
|
||||
|
||||
transformbasename=""
|
||||
transform_arg=""
|
||||
instcmd="$mvprog"
|
||||
chmodcmd="$chmodprog 0755"
|
||||
chowncmd=""
|
||||
chgrpcmd=""
|
||||
stripcmd=""
|
||||
rmcmd="$rmprog -f"
|
||||
mvcmd="$mvprog"
|
||||
src=""
|
||||
dst=""
|
||||
dir_arg=""
|
||||
|
||||
while [ x"$1" != x ]; do
|
||||
case $1 in
|
||||
-c) instcmd=$cpprog
|
||||
shift
|
||||
continue;;
|
||||
|
||||
-d) dir_arg=true
|
||||
shift
|
||||
continue;;
|
||||
|
||||
-m) chmodcmd="$chmodprog $2"
|
||||
shift
|
||||
shift
|
||||
continue;;
|
||||
|
||||
-o) chowncmd="$chownprog $2"
|
||||
shift
|
||||
shift
|
||||
continue;;
|
||||
|
||||
-g) chgrpcmd="$chgrpprog $2"
|
||||
shift
|
||||
shift
|
||||
continue;;
|
||||
|
||||
-s) stripcmd=$stripprog
|
||||
shift
|
||||
continue;;
|
||||
|
||||
-t=*) transformarg=`echo $1 | sed 's/-t=//'`
|
||||
shift
|
||||
continue;;
|
||||
|
||||
-b=*) transformbasename=`echo $1 | sed 's/-b=//'`
|
||||
shift
|
||||
continue;;
|
||||
|
||||
*) if [ x"$src" = x ]
|
||||
then
|
||||
src=$1
|
||||
else
|
||||
# this colon is to work around a 386BSD /bin/sh bug
|
||||
:
|
||||
dst=$1
|
||||
fi
|
||||
shift
|
||||
continue;;
|
||||
esac
|
||||
done
|
||||
|
||||
if [ x"$src" = x ]
|
||||
then
|
||||
echo "$0: no input file specified" >&2
|
||||
exit 1
|
||||
else
|
||||
:
|
||||
fi
|
||||
|
||||
if [ x"$dir_arg" != x ]; then
|
||||
dst=$src
|
||||
src=""
|
||||
|
||||
if [ -d "$dst" ]; then
|
||||
instcmd=:
|
||||
chmodcmd=""
|
||||
else
|
||||
instcmd=$mkdirprog
|
||||
fi
|
||||
else
|
||||
|
||||
# Waiting for this to be detected by the "$instcmd $src $dsttmp" command
|
||||
# might cause directories to be created, which would be especially bad
|
||||
# if $src (and thus $dsttmp) contains '*'.
|
||||
|
||||
if [ -f "$src" ] || [ -d "$src" ]
|
||||
then
|
||||
:
|
||||
else
|
||||
echo "$0: $src does not exist" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [ x"$dst" = x ]
|
||||
then
|
||||
echo "$0: no destination specified" >&2
|
||||
exit 1
|
||||
else
|
||||
:
|
||||
fi
|
||||
|
||||
# If destination is a directory, append the input filename; if your system
|
||||
# does not like double slashes in filenames, you may need to add some logic
|
||||
|
||||
if [ -d "$dst" ]
|
||||
then
|
||||
dst=$dst/`basename "$src"`
|
||||
else
|
||||
:
|
||||
fi
|
||||
fi
|
||||
|
||||
## this sed command emulates the dirname command
|
||||
dstdir=`echo "$dst" | sed -e 's,[^/]*$,,;s,/$,,;s,^$,.,'`
|
||||
|
||||
# Make sure that the destination directory exists.
|
||||
# this part is taken from Noah Friedman's mkinstalldirs script
|
||||
|
||||
# Skip lots of stat calls in the usual case.
|
||||
if [ ! -d "$dstdir" ]; then
|
||||
defaultIFS='
|
||||
'
|
||||
IFS="${IFS-$defaultIFS}"
|
||||
|
||||
oIFS=$IFS
|
||||
# Some sh's can't handle IFS=/ for some reason.
|
||||
IFS='%'
|
||||
set - `echo "$dstdir" | sed -e 's@/@%@g' -e 's@^%@/@'`
|
||||
IFS=$oIFS
|
||||
|
||||
pathcomp=''
|
||||
|
||||
while [ $# -ne 0 ] ; do
|
||||
pathcomp=$pathcomp$1
|
||||
shift
|
||||
|
||||
if [ ! -d "$pathcomp" ] ;
|
||||
then
|
||||
$mkdirprog "$pathcomp"
|
||||
else
|
||||
:
|
||||
fi
|
||||
|
||||
pathcomp=$pathcomp/
|
||||
done
|
||||
fi
|
||||
|
||||
if [ x"$dir_arg" != x ]
|
||||
then
|
||||
$doit $instcmd "$dst" &&
|
||||
|
||||
if [ x"$chowncmd" != x ]; then $doit $chowncmd "$dst"; else : ; fi &&
|
||||
if [ x"$chgrpcmd" != x ]; then $doit $chgrpcmd "$dst"; else : ; fi &&
|
||||
if [ x"$stripcmd" != x ]; then $doit $stripcmd "$dst"; else : ; fi &&
|
||||
if [ x"$chmodcmd" != x ]; then $doit $chmodcmd "$dst"; else : ; fi
|
||||
else
|
||||
|
||||
# If we're going to rename the final executable, determine the name now.
|
||||
|
||||
if [ x"$transformarg" = x ]
|
||||
then
|
||||
dstfile=`basename "$dst"`
|
||||
else
|
||||
dstfile=`basename "$dst" $transformbasename |
|
||||
sed $transformarg`$transformbasename
|
||||
fi
|
||||
|
||||
# don't allow the sed command to completely eliminate the filename
|
||||
|
||||
if [ x"$dstfile" = x ]
|
||||
then
|
||||
dstfile=`basename "$dst"`
|
||||
else
|
||||
:
|
||||
fi
|
||||
|
||||
# Make a couple of temp file names in the proper directory.
|
||||
|
||||
dsttmp=$dstdir/_inst.$$_
|
||||
rmtmp=$dstdir/_rm.$$_
|
||||
|
||||
# Trap to clean up temp files at exit.
|
||||
|
||||
trap 'status=$?; rm -f "$dsttmp" "$rmtmp" && exit $status' 0
|
||||
trap '(exit $?); exit' 1 2 13 15
|
||||
|
||||
# Move or copy the file name to the temp name
|
||||
|
||||
$doit $instcmd "$src" "$dsttmp" &&
|
||||
|
||||
# and set any options; do chmod last to preserve setuid bits
|
||||
|
||||
# If any of these fail, we abort the whole thing. If we want to
|
||||
# ignore errors from any of these, just make sure not to ignore
|
||||
# errors from the above "$doit $instcmd $src $dsttmp" command.
|
||||
|
||||
if [ x"$chowncmd" != x ]; then $doit $chowncmd "$dsttmp"; else :;fi &&
|
||||
if [ x"$chgrpcmd" != x ]; then $doit $chgrpcmd "$dsttmp"; else :;fi &&
|
||||
if [ x"$stripcmd" != x ]; then $doit $stripcmd "$dsttmp"; else :;fi &&
|
||||
if [ x"$chmodcmd" != x ]; then $doit $chmodcmd "$dsttmp"; else :;fi &&
|
||||
|
||||
# Now remove or move aside any old file at destination location. We try this
|
||||
# two ways since rm can't unlink itself on some systems and the destination
|
||||
# file might be busy for other reasons. In this case, the final cleanup
|
||||
# might fail but the new file should still install successfully.
|
||||
|
||||
{
|
||||
if [ -f "$dstdir/$dstfile" ]
|
||||
then
|
||||
$doit $rmcmd -f "$dstdir/$dstfile" 2>/dev/null ||
|
||||
$doit $mvcmd -f "$dstdir/$dstfile" "$rmtmp" 2>/dev/null ||
|
||||
{
|
||||
echo "$0: cannot unlink or rename $dstdir/$dstfile" >&2
|
||||
(exit 1); exit
|
||||
}
|
||||
else
|
||||
:
|
||||
fi
|
||||
} &&
|
||||
|
||||
# Now rename the file to the real destination.
|
||||
|
||||
$doit $mvcmd "$dsttmp" "$dstdir/$dstfile"
|
||||
|
||||
fi &&
|
||||
|
||||
# The final little trick to "correctly" pass the exit status to the exit trap.
|
||||
|
||||
{
|
||||
(exit 0); exit
|
||||
}
|
||||
|
|
@ -0,0 +1,38 @@
|
|||
dnl ---------------------------------------------------------------------------
|
||||
dnl Macro: AC_CHECK_AIO
|
||||
dnl Check for Linux AIO availability on the target system
|
||||
dnl Also, check the version of libaio library (at the moment, there are two
|
||||
dnl versions with incompatible interfaces).
|
||||
dnl ---------------------------------------------------------------------------
|
||||
|
||||
AC_DEFUN([AC_CHECK_AIO],[
|
||||
if test x$enable_aio = xyes; then
|
||||
AC_CHECK_HEADER([libaio.h],
|
||||
[AC_DEFINE(HAVE_LIBAIO_H,1,[Define to 1 if your system has <libaio.h> header file])],
|
||||
[enable_aio=no])
|
||||
fi
|
||||
if test x$enable_aio = xyes; then
|
||||
AC_CHECK_LIB([aio], [io_queue_init], , [enable_aio=no])
|
||||
fi
|
||||
if test x$enable_aio = xyes; then
|
||||
AC_MSG_CHECKING(if io_getevents() has an old interface)
|
||||
AC_COMPILE_IFELSE([AC_LANG_PROGRAM(
|
||||
[[
|
||||
#ifdef HAVE_LIBAIO_H
|
||||
# include <libaio.h>
|
||||
#endif
|
||||
struct io_event event;
|
||||
io_context_t ctxt;
|
||||
]],
|
||||
[[
|
||||
(void)io_getevents(ctxt, 1, &event, NULL);
|
||||
]] )
|
||||
], [
|
||||
AC_DEFINE([HAVE_OLD_GETEVENTS], 1, [Define to 1 if libaio has older getevents() interface])
|
||||
AC_MSG_RESULT(yes)
|
||||
],
|
||||
[AC_MSG_RESULT(no)]
|
||||
)
|
||||
fi
|
||||
])
|
||||
|
||||
|
|
@ -0,0 +1,71 @@
|
|||
dnl ---------------------------------------------------------------------------
|
||||
dnl Macro: AC_CHECK_PGSQL
|
||||
dnl First check for custom PostgreSQL paths in --with-pgsql-* options.
|
||||
dnl If some paths are missing, check if pg_config exists.
|
||||
dnl ---------------------------------------------------------------------------
|
||||
|
||||
AC_DEFUN([AC_CHECK_PGSQL],[
|
||||
|
||||
# Check for custom includes path
|
||||
if test [ -z "$ac_cv_pgsql_includes" ]
|
||||
then
|
||||
AC_ARG_WITH([pgsql-includes],
|
||||
AC_HELP_STRING([--with-pgsql-includes], [path to PostgreSQL header files]),
|
||||
[ac_cv_pgsql_includes=$withval])
|
||||
fi
|
||||
if test [ -n "$ac_cv_pgsql_includes" ]
|
||||
then
|
||||
AC_CACHE_CHECK([PostgreSQL includes], [ac_cv_pgsql_includes], [ac_cv_pgsql_includes=""])
|
||||
PGSQL_CFLAGS="-I$ac_cv_pgsql_includes"
|
||||
fi
|
||||
|
||||
# Check for custom library path
|
||||
|
||||
if test [ -z "$ac_cv_pgsql_libs" ]
|
||||
then
|
||||
AC_ARG_WITH([pgsql-libs],
|
||||
AC_HELP_STRING([--with-pgsql-libs], [path to PostgreSQL libraries]),
|
||||
[ac_cv_pgsql_libs=$withval])
|
||||
fi
|
||||
|
||||
if test [ -n "$ac_cv_pgsql_libs" ]
|
||||
then
|
||||
AC_CACHE_CHECK([PostgreSQL libraries], [ac_cv_pgsql_libs], [ac_cv_pgsql_libs=""])
|
||||
PGSQL_LIBS="-L$ac_cv_pgsql_libs -lpq"
|
||||
fi
|
||||
|
||||
# If some path is missing, try to autodetermine with pgsql_config
|
||||
if test [ -z "$ac_cv_pgsql_includes" -o -z "$ac_cv_pgsql_libs" ]
|
||||
then
|
||||
if test [ -z "$pgconfig" ]
|
||||
then
|
||||
AC_PATH_PROG(pgconfig,pg_config)
|
||||
fi
|
||||
if test [ -z "$pgconfig" ]
|
||||
then
|
||||
AC_MSG_ERROR([pg_config executable not found
|
||||
********************************************************************************
|
||||
ERROR: cannot find PostgreSQL libraries. If you want to compile with PosgregSQL support,
|
||||
you must either specify file locations explicitly using
|
||||
--with-pgsql-includes and --with-pgsql-libs options, or make sure path to
|
||||
pg_config is listed in your PATH environment variable. If you want to
|
||||
disable PostgreSQL support, use --without-pgsql option.
|
||||
********************************************************************************
|
||||
])
|
||||
else
|
||||
if test [ -z "$ac_cv_pgsql_includes" ]
|
||||
then
|
||||
AC_MSG_CHECKING(PostgreSQL C flags)
|
||||
PGSQL_CFLAGS="-I`${pgconfig} --includedir`"
|
||||
AC_MSG_RESULT($PGSQL_CFLAGS)
|
||||
fi
|
||||
if test [ -z "$ac_cv_pgsql_libs" ]
|
||||
then
|
||||
AC_MSG_CHECKING(PostgreSQL linker flags)
|
||||
PGSQL_LIBS="-L`${pgconfig} --libdir` -lpq"
|
||||
AC_MSG_RESULT($PGSQL_LIBS)
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
])
|
||||
|
||||
|
|
@ -0,0 +1,276 @@
|
|||
##### http://autoconf-archive.cryp.to/acx_pthread.html
|
||||
#
|
||||
# SYNOPSIS
|
||||
#
|
||||
# ACX_PTHREAD([ACTION-IF-FOUND[, ACTION-IF-NOT-FOUND]])
|
||||
#
|
||||
# DESCRIPTION
|
||||
#
|
||||
# This macro figures out how to build C programs using POSIX threads.
|
||||
# It sets the PTHREAD_LIBS output variable to the threads library and
|
||||
# linker flags, and the PTHREAD_CFLAGS output variable to any special
|
||||
# C compiler flags that are needed. (The user can also force certain
|
||||
# compiler flags/libs to be tested by setting these environment
|
||||
# variables.)
|
||||
#
|
||||
# Also sets PTHREAD_CC to any special C compiler that is needed for
|
||||
# multi-threaded programs (defaults to the value of CC otherwise).
|
||||
# (This is necessary on AIX to use the special cc_r compiler alias.)
|
||||
#
|
||||
# NOTE: You are assumed to not only compile your program with these
|
||||
# flags, but also link it with them as well. e.g. you should link
|
||||
# with $PTHREAD_CC $CFLAGS $PTHREAD_CFLAGS $LDFLAGS ... $PTHREAD_LIBS
|
||||
# $LIBS
|
||||
#
|
||||
# If you are only building threads programs, you may wish to use
|
||||
# these variables in your default LIBS, CFLAGS, and CC:
|
||||
#
|
||||
# LIBS="$PTHREAD_LIBS $LIBS"
|
||||
# CFLAGS="$CFLAGS $PTHREAD_CFLAGS"
|
||||
# CC="$PTHREAD_CC"
|
||||
#
|
||||
# In addition, if the PTHREAD_CREATE_JOINABLE thread-attribute
|
||||
# constant has a nonstandard name, defines PTHREAD_CREATE_JOINABLE to
|
||||
# that name (e.g. PTHREAD_CREATE_UNDETACHED on AIX).
|
||||
#
|
||||
# ACTION-IF-FOUND is a list of shell commands to run if a threads
|
||||
# library is found, and ACTION-IF-NOT-FOUND is a list of commands to
|
||||
# run it if it is not found. If ACTION-IF-FOUND is not specified, the
|
||||
# default action will define HAVE_PTHREAD.
|
||||
#
|
||||
# Please let the authors know if this macro fails on any platform, or
|
||||
# if you have any other suggestions or comments. This macro was based
|
||||
# on work by SGJ on autoconf scripts for FFTW (http://www.fftw.org/)
|
||||
# (with help from M. Frigo), as well as ac_pthread and hb_pthread
|
||||
# macros posted by Alejandro Forero Cuervo to the autoconf macro
|
||||
# repository. We are also grateful for the helpful feedback of
|
||||
# numerous users.
|
||||
#
|
||||
# LAST MODIFICATION
|
||||
#
|
||||
# 2006-05-29
|
||||
#
|
||||
# COPYLEFT
|
||||
#
|
||||
# Copyright (c) 2006 Steven G. Johnson <stevenj@alum.mit.edu>
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or
|
||||
# modify it under the terms of the GNU General Public License as
|
||||
# published by the Free Software Foundation; either version 2 of the
|
||||
# License, or (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful, but
|
||||
# WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
# General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, write to the Free Software
|
||||
# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
|
||||
# 02111-1307, USA.
|
||||
#
|
||||
# As a special exception, the respective Autoconf Macro's copyright
|
||||
# owner gives unlimited permission to copy, distribute and modify the
|
||||
# configure scripts that are the output of Autoconf when processing
|
||||
# the Macro. You need not follow the terms of the GNU General Public
|
||||
# License when using or distributing such scripts, even though
|
||||
# portions of the text of the Macro appear in them. The GNU General
|
||||
# Public License (GPL) does govern all other use of the material that
|
||||
# constitutes the Autoconf Macro.
|
||||
#
|
||||
# This special exception to the GPL applies to versions of the
|
||||
# Autoconf Macro released by the Autoconf Macro Archive. When you
|
||||
# make and distribute a modified version of the Autoconf Macro, you
|
||||
# may extend this special exception to the GPL to apply to your
|
||||
# modified version as well.
|
||||
|
||||
AC_DEFUN([ACX_PTHREAD], [
|
||||
AC_REQUIRE([AC_CANONICAL_HOST])
|
||||
AC_LANG_PUSH([C])
|
||||
acx_pthread_ok=no
|
||||
|
||||
# We used to check for pthread.h first, but this fails if pthread.h
|
||||
# requires special compiler flags (e.g. on True64 or Sequent).
|
||||
# It gets checked for in the link test anyway.
|
||||
|
||||
# First of all, check if the user has set any of the PTHREAD_LIBS,
|
||||
# etcetera environment variables, and if threads linking works using
|
||||
# them:
|
||||
if test x"$PTHREAD_LIBS$PTHREAD_CFLAGS" != x; then
|
||||
save_CFLAGS="$CFLAGS"
|
||||
CFLAGS="$CFLAGS $PTHREAD_CFLAGS"
|
||||
save_LIBS="$LIBS"
|
||||
LIBS="$PTHREAD_LIBS $LIBS"
|
||||
AC_MSG_CHECKING([for pthread_join in LIBS=$PTHREAD_LIBS with CFLAGS=$PTHREAD_CFLAGS])
|
||||
AC_TRY_LINK_FUNC(pthread_join, acx_pthread_ok=yes)
|
||||
AC_MSG_RESULT($acx_pthread_ok)
|
||||
if test x"$acx_pthread_ok" = xno; then
|
||||
PTHREAD_LIBS=""
|
||||
PTHREAD_CFLAGS=""
|
||||
fi
|
||||
LIBS="$save_LIBS"
|
||||
CFLAGS="$save_CFLAGS"
|
||||
fi
|
||||
|
||||
# We must check for the threads library under a number of different
|
||||
# names; the ordering is very important because some systems
|
||||
# (e.g. DEC) have both -lpthread and -lpthreads, where one of the
|
||||
# libraries is broken (non-POSIX).
|
||||
|
||||
# Create a list of thread flags to try. Items starting with a "-" are
|
||||
# C compiler flags, and other items are library names, except for "none"
|
||||
# which indicates that we try without any flags at all, and "pthread-config"
|
||||
# which is a program returning the flags for the Pth emulation library.
|
||||
|
||||
acx_pthread_flags="pthreads none -Kthread -kthread lthread -pthread -pthreads -mthreads pthread --thread-safe -mt pthread-config"
|
||||
|
||||
# The ordering *is* (sometimes) important. Some notes on the
|
||||
# individual items follow:
|
||||
|
||||
# pthreads: AIX (must check this before -lpthread)
|
||||
# none: in case threads are in libc; should be tried before -Kthread and
|
||||
# other compiler flags to prevent continual compiler warnings
|
||||
# -Kthread: Sequent (threads in libc, but -Kthread needed for pthread.h)
|
||||
# -kthread: FreeBSD kernel threads (preferred to -pthread since SMP-able)
|
||||
# lthread: LinuxThreads port on FreeBSD (also preferred to -pthread)
|
||||
# -pthread: Linux/gcc (kernel threads), BSD/gcc (userland threads)
|
||||
# -pthreads: Solaris/gcc
|
||||
# -mthreads: Mingw32/gcc, Lynx/gcc
|
||||
# -mt: Sun Workshop C (may only link SunOS threads [-lthread], but it
|
||||
# doesn't hurt to check since this sometimes defines pthreads too;
|
||||
# also defines -D_REENTRANT)
|
||||
# ... -mt is also the pthreads flag for HP/aCC
|
||||
# pthread: Linux, etcetera
|
||||
# --thread-safe: KAI C++
|
||||
# pthread-config: use pthread-config program (for GNU Pth library)
|
||||
|
||||
case "${host_cpu}-${host_os}" in
|
||||
*solaris*)
|
||||
|
||||
# On Solaris (at least, for some versions), libc contains stubbed
|
||||
# (non-functional) versions of the pthreads routines, so link-based
|
||||
# tests will erroneously succeed. (We need to link with -pthreads/-mt/
|
||||
# -lpthread.) (The stubs are missing pthread_cleanup_push, or rather
|
||||
# a function called by this macro, so we could check for that, but
|
||||
# who knows whether they'll stub that too in a future libc.) So,
|
||||
# we'll just look for -pthreads and -lpthread first:
|
||||
|
||||
acx_pthread_flags="-pthreads pthread -mt -pthread $acx_pthread_flags"
|
||||
;;
|
||||
esac
|
||||
|
||||
if test x"$acx_pthread_ok" = xno; then
|
||||
for flag in $acx_pthread_flags; do
|
||||
|
||||
case $flag in
|
||||
none)
|
||||
AC_MSG_CHECKING([whether pthreads work without any flags])
|
||||
;;
|
||||
|
||||
-*)
|
||||
AC_MSG_CHECKING([whether pthreads work with $flag])
|
||||
PTHREAD_CFLAGS="$flag"
|
||||
;;
|
||||
|
||||
pthread-config)
|
||||
AC_CHECK_PROG(acx_pthread_config, pthread-config, yes, no)
|
||||
if test x"$acx_pthread_config" = xno; then continue; fi
|
||||
PTHREAD_CFLAGS="`pthread-config --cflags`"
|
||||
PTHREAD_LIBS="`pthread-config --ldflags` `pthread-config --libs`"
|
||||
;;
|
||||
|
||||
*)
|
||||
AC_MSG_CHECKING([for the pthreads library -l$flag])
|
||||
PTHREAD_LIBS="-l$flag"
|
||||
;;
|
||||
esac
|
||||
|
||||
save_LIBS="$LIBS"
|
||||
save_CFLAGS="$CFLAGS"
|
||||
LIBS="$PTHREAD_LIBS $LIBS"
|
||||
CFLAGS="$CFLAGS $PTHREAD_CFLAGS"
|
||||
|
||||
# Check for various functions. We must include pthread.h,
|
||||
# since some functions may be macros. (On the Sequent, we
|
||||
# need a special flag -Kthread to make this header compile.)
|
||||
# We check for pthread_join because it is in -lpthread on IRIX
|
||||
# while pthread_create is in libc. We check for pthread_attr_init
|
||||
# due to DEC craziness with -lpthreads. We check for
|
||||
# pthread_cleanup_push because it is one of the few pthread
|
||||
# functions on Solaris that doesn't have a non-functional libc stub.
|
||||
# We try pthread_create on general principles.
|
||||
AC_LINK_IFELSE([AC_LANG_PROGRAM([[#include <pthread.h>]], [[pthread_t th; pthread_join(th, 0);
|
||||
pthread_attr_init(0); pthread_cleanup_push(0, 0);
|
||||
pthread_create(0,0,0,0); pthread_cleanup_pop(0); ]])],[acx_pthread_ok=yes],[])
|
||||
|
||||
LIBS="$save_LIBS"
|
||||
CFLAGS="$save_CFLAGS"
|
||||
|
||||
AC_MSG_RESULT($acx_pthread_ok)
|
||||
if test "x$acx_pthread_ok" = xyes; then
|
||||
break;
|
||||
fi
|
||||
|
||||
PTHREAD_LIBS=""
|
||||
PTHREAD_CFLAGS=""
|
||||
done
|
||||
fi
|
||||
|
||||
# Various other checks:
|
||||
if test "x$acx_pthread_ok" = xyes; then
|
||||
save_LIBS="$LIBS"
|
||||
LIBS="$PTHREAD_LIBS $LIBS"
|
||||
save_CFLAGS="$CFLAGS"
|
||||
CFLAGS="$CFLAGS $PTHREAD_CFLAGS"
|
||||
|
||||
# Detect AIX lossage: JOINABLE attribute is called UNDETACHED.
|
||||
AC_MSG_CHECKING([for joinable pthread attribute])
|
||||
attr_name=unknown
|
||||
for attr in PTHREAD_CREATE_JOINABLE PTHREAD_CREATE_UNDETACHED; do
|
||||
AC_LINK_IFELSE([AC_LANG_PROGRAM([[#include <pthread.h>]], [[int attr=$attr; return attr;]])],[attr_name=$attr; break],[])
|
||||
done
|
||||
AC_MSG_RESULT($attr_name)
|
||||
if test "$attr_name" != PTHREAD_CREATE_JOINABLE; then
|
||||
AC_DEFINE_UNQUOTED(PTHREAD_CREATE_JOINABLE, $attr_name,
|
||||
[Define to necessary symbol if this constant
|
||||
uses a non-standard name on your system.])
|
||||
fi
|
||||
|
||||
AC_MSG_CHECKING([if more special flags are required for pthreads])
|
||||
flag=no
|
||||
case "${host_cpu}-${host_os}" in
|
||||
*-aix* | *-freebsd* | *-darwin*) flag="-D_THREAD_SAFE";;
|
||||
*solaris* | *-osf* | *-hpux*) flag="-D_REENTRANT";;
|
||||
esac
|
||||
AC_MSG_RESULT(${flag})
|
||||
if test "x$flag" != xno; then
|
||||
PTHREAD_CFLAGS="$flag $PTHREAD_CFLAGS"
|
||||
fi
|
||||
|
||||
LIBS="$save_LIBS"
|
||||
CFLAGS="$save_CFLAGS"
|
||||
|
||||
# More AIX lossage: must compile with xlc_r or cc_r
|
||||
if test x"$GCC" != xyes; then
|
||||
AC_CHECK_PROGS(PTHREAD_CC, xlc_r cc_r, ${CC})
|
||||
else
|
||||
PTHREAD_CC=$CC
|
||||
fi
|
||||
else
|
||||
PTHREAD_CC="$CC"
|
||||
fi
|
||||
|
||||
AC_SUBST(PTHREAD_LIBS)
|
||||
AC_SUBST(PTHREAD_CFLAGS)
|
||||
AC_SUBST(PTHREAD_CC)
|
||||
|
||||
# Finally, execute ACTION-IF-FOUND/ACTION-IF-NOT-FOUND:
|
||||
if test x"$acx_pthread_ok" = xyes; then
|
||||
ifelse([$1],,AC_DEFINE(HAVE_PTHREAD,1,[Define if you have POSIX threads libraries and header files.]),[$1])
|
||||
:
|
||||
else
|
||||
acx_pthread_ok=no
|
||||
$2
|
||||
fi
|
||||
AC_LANG_POP([])
|
||||
])dnl ACX_PTHREAD
|
||||
|
|
@ -0,0 +1,74 @@
|
|||
# ===========================================================================
|
||||
# https://www.gnu.org/software/autoconf-archive/ax_check_compile_flag.html
|
||||
# ===========================================================================
|
||||
#
|
||||
# SYNOPSIS
|
||||
#
|
||||
# AX_CHECK_COMPILE_FLAG(FLAG, [ACTION-SUCCESS], [ACTION-FAILURE], [EXTRA-FLAGS], [INPUT])
|
||||
#
|
||||
# DESCRIPTION
|
||||
#
|
||||
# Check whether the given FLAG works with the current language's compiler
|
||||
# or gives an error. (Warnings, however, are ignored)
|
||||
#
|
||||
# ACTION-SUCCESS/ACTION-FAILURE are shell commands to execute on
|
||||
# success/failure.
|
||||
#
|
||||
# If EXTRA-FLAGS is defined, it is added to the current language's default
|
||||
# flags (e.g. CFLAGS) when the check is done. The check is thus made with
|
||||
# the flags: "CFLAGS EXTRA-FLAGS FLAG". This can for example be used to
|
||||
# force the compiler to issue an error when a bad flag is given.
|
||||
#
|
||||
# INPUT gives an alternative input source to AC_COMPILE_IFELSE.
|
||||
#
|
||||
# NOTE: Implementation based on AX_CFLAGS_GCC_OPTION. Please keep this
|
||||
# macro in sync with AX_CHECK_{PREPROC,LINK}_FLAG.
|
||||
#
|
||||
# LICENSE
|
||||
#
|
||||
# Copyright (c) 2008 Guido U. Draheim <guidod@gmx.de>
|
||||
# Copyright (c) 2011 Maarten Bosmans <mkbosmans@gmail.com>
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify it
|
||||
# under the terms of the GNU General Public License as published by the
|
||||
# Free Software Foundation, either version 3 of the License, or (at your
|
||||
# option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful, but
|
||||
# WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
|
||||
# Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License along
|
||||
# with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
#
|
||||
# As a special exception, the respective Autoconf Macro's copyright owner
|
||||
# gives unlimited permission to copy, distribute and modify the configure
|
||||
# scripts that are the output of Autoconf when processing the Macro. You
|
||||
# need not follow the terms of the GNU General Public License when using
|
||||
# or distributing such scripts, even though portions of the text of the
|
||||
# Macro appear in them. The GNU General Public License (GPL) does govern
|
||||
# all other use of the material that constitutes the Autoconf Macro.
|
||||
#
|
||||
# This special exception to the GPL applies to versions of the Autoconf
|
||||
# Macro released by the Autoconf Archive. When you make and distribute a
|
||||
# modified version of the Autoconf Macro, you may extend this special
|
||||
# exception to the GPL to apply to your modified version as well.
|
||||
|
||||
#serial 5
|
||||
|
||||
AC_DEFUN([AX_CHECK_COMPILE_FLAG],
|
||||
[
|
||||
AS_VAR_PUSHDEF([CACHEVAR],[ax_cv_check_[]_AC_LANG_ABBREV[]flags_$4_$1])dnl
|
||||
AC_CACHE_CHECK([whether _AC_LANG compiler accepts $1], CACHEVAR, [
|
||||
ax_check_save_flags=$[]_AC_LANG_PREFIX[]FLAGS
|
||||
_AC_LANG_PREFIX[]FLAGS="$[]_AC_LANG_PREFIX[]FLAGS $4 $1"
|
||||
AC_COMPILE_IFELSE([m4_default([$5],[AC_LANG_PROGRAM()])],
|
||||
[AS_VAR_SET(CACHEVAR,[yes])],
|
||||
[AS_VAR_SET(CACHEVAR,[no])])
|
||||
_AC_LANG_PREFIX[]FLAGS=$ax_check_save_flags])
|
||||
AS_VAR_IF(CACHEVAR,yes,
|
||||
[m4_default([$2], :)],
|
||||
[m4_default([$3], :)])
|
||||
AS_VAR_POPDEF([CACHEVAR])dnl
|
||||
])dnl AX_CHECK_COMPILE_FLAGS
|
||||
|
|
@ -0,0 +1,65 @@
|
|||
dnl ---------------------------------------------------------------------------
|
||||
dnl Macro: AX_CHECK_DOCBOOK
|
||||
dnl Check for availability of various DocBook utilities and perform necessary
|
||||
dnl substitutions
|
||||
dnl ---------------------------------------------------------------------------
|
||||
|
||||
AC_DEFUN([AX_CHECK_DOCBOOK], [
|
||||
# It's just rude to go over the net to build
|
||||
XSLTPROC_FLAGS=--nonet
|
||||
DOCBOOK_ROOT=
|
||||
|
||||
for i in /etc/xml/catalog /usr/local/etc/xml/catalog /opt/local/etc/xml/catalog ;
|
||||
do
|
||||
if test -f $i; then
|
||||
XML_CATALOG="$i"
|
||||
fi
|
||||
done
|
||||
|
||||
if test -z "$XML_CATALOG" ; then
|
||||
for i in /usr/share/sgml/docbook/stylesheet/xsl/nwalsh /usr/share/sgml/docbook/xsl-stylesheets/ /opt/local/share/xsl/docbook-xsl/xhtml/ ;
|
||||
do
|
||||
if test -d "$i"; then
|
||||
DOCBOOK_ROOT=$i
|
||||
fi
|
||||
done
|
||||
|
||||
# Last resort - try net
|
||||
if test -z "$DOCBOOK_ROOT"; then
|
||||
XSLTPROC_FLAGS=
|
||||
fi
|
||||
else
|
||||
CAT_ENTRY_START='<!--'
|
||||
CAT_ENTRY_END='-->'
|
||||
fi
|
||||
|
||||
AC_CHECK_PROG(XSLTPROC,xsltproc,xsltproc,)
|
||||
XSLTPROC_WORKS=no
|
||||
if test -n "$XSLTPROC"; then
|
||||
AC_MSG_CHECKING([whether xsltproc works])
|
||||
|
||||
if test -n "$XML_CATALOG"; then
|
||||
DB_FILE="http://docbook.sourceforge.net/release/xsl/current/xhtml/docbook.xsl"
|
||||
else
|
||||
DB_FILE="$DOCBOOK_ROOT/docbook.xsl"
|
||||
fi
|
||||
|
||||
$XSLTPROC $XSLTPROC_FLAGS $DB_FILE >/dev/null 2>&1 << END
|
||||
<?xml version="1.0" encoding='ISO-8859-1'?>
|
||||
<!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook XML V4.1.2//EN" "http://www.oasis-open.org/docbook/xml/4.1.2/docbookx.dtd">
|
||||
<book id="test">
|
||||
</book>
|
||||
END
|
||||
if test "$?" = 0; then
|
||||
XSLTPROC_WORKS=yes
|
||||
fi
|
||||
AC_MSG_RESULT($XSLTPROC_WORKS)
|
||||
fi
|
||||
AM_CONDITIONAL(have_xsltproc, test "$XSLTPROC_WORKS" = "yes")
|
||||
|
||||
AC_SUBST(XML_CATALOG)
|
||||
AC_SUBST(XSLTPROC_FLAGS)
|
||||
AC_SUBST(DOCBOOK_ROOT)
|
||||
AC_SUBST(CAT_ENTRY_START)
|
||||
AC_SUBST(CAT_ENTRY_END)
|
||||
])
|
||||
|
|
@ -0,0 +1,87 @@
|
|||
# ===========================================================================
|
||||
# https://www.gnu.org/software/autoconf-archive/ax_compiler_vendor.html
|
||||
# ===========================================================================
|
||||
#
|
||||
# SYNOPSIS
|
||||
#
|
||||
# AX_COMPILER_VENDOR
|
||||
#
|
||||
# DESCRIPTION
|
||||
#
|
||||
# Determine the vendor of the C/C++ compiler, e.g., gnu, intel, ibm, sun,
|
||||
# hp, borland, comeau, dec, cray, kai, lcc, metrowerks, sgi, microsoft,
|
||||
# watcom, etc. The vendor is returned in the cache variable
|
||||
# $ax_cv_c_compiler_vendor for C and $ax_cv_cxx_compiler_vendor for C++.
|
||||
#
|
||||
# LICENSE
|
||||
#
|
||||
# Copyright (c) 2008 Steven G. Johnson <stevenj@alum.mit.edu>
|
||||
# Copyright (c) 2008 Matteo Frigo
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify it
|
||||
# under the terms of the GNU General Public License as published by the
|
||||
# Free Software Foundation, either version 3 of the License, or (at your
|
||||
# option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful, but
|
||||
# WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
|
||||
# Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License along
|
||||
# with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
#
|
||||
# As a special exception, the respective Autoconf Macro's copyright owner
|
||||
# gives unlimited permission to copy, distribute and modify the configure
|
||||
# scripts that are the output of Autoconf when processing the Macro. You
|
||||
# need not follow the terms of the GNU General Public License when using
|
||||
# or distributing such scripts, even though portions of the text of the
|
||||
# Macro appear in them. The GNU General Public License (GPL) does govern
|
||||
# all other use of the material that constitutes the Autoconf Macro.
|
||||
#
|
||||
# This special exception to the GPL applies to versions of the Autoconf
|
||||
# Macro released by the Autoconf Archive. When you make and distribute a
|
||||
# modified version of the Autoconf Macro, you may extend this special
|
||||
# exception to the GPL to apply to your modified version as well.
|
||||
|
||||
#serial 16
|
||||
|
||||
AC_DEFUN([AX_COMPILER_VENDOR],
|
||||
[AC_CACHE_CHECK([for _AC_LANG compiler vendor], ax_cv_[]_AC_LANG_ABBREV[]_compiler_vendor,
|
||||
dnl Please add if possible support to ax_compiler_version.m4
|
||||
[# note: don't check for gcc first since some other compilers define __GNUC__
|
||||
vendors="intel: __ICC,__ECC,__INTEL_COMPILER
|
||||
ibm: __xlc__,__xlC__,__IBMC__,__IBMCPP__
|
||||
pathscale: __PATHCC__,__PATHSCALE__
|
||||
clang: __clang__
|
||||
cray: _CRAYC
|
||||
fujitsu: __FUJITSU
|
||||
gnu: __GNUC__
|
||||
sun: __SUNPRO_C,__SUNPRO_CC
|
||||
hp: __HP_cc,__HP_aCC
|
||||
dec: __DECC,__DECCXX,__DECC_VER,__DECCXX_VER
|
||||
borland: __BORLANDC__,__CODEGEARC__,__TURBOC__
|
||||
comeau: __COMO__
|
||||
kai: __KCC
|
||||
lcc: __LCC__
|
||||
sgi: __sgi,sgi
|
||||
microsoft: _MSC_VER
|
||||
metrowerks: __MWERKS__
|
||||
watcom: __WATCOMC__
|
||||
portland: __PGI
|
||||
tcc: __TINYC__
|
||||
unknown: UNKNOWN"
|
||||
for ventest in $vendors; do
|
||||
case $ventest in
|
||||
*:) vendor=$ventest; continue ;;
|
||||
*) vencpp="defined("`echo $ventest | sed 's/,/) || defined(/g'`")" ;;
|
||||
esac
|
||||
AC_COMPILE_IFELSE([AC_LANG_PROGRAM(,[
|
||||
#if !($vencpp)
|
||||
thisisanerror;
|
||||
#endif
|
||||
])], [break])
|
||||
done
|
||||
ax_cv_[]_AC_LANG_ABBREV[]_compiler_vendor=`echo $vendor | cut -d: -f1`
|
||||
])
|
||||
])
|
||||
|
|
@ -0,0 +1,263 @@
|
|||
# ===========================================================================
|
||||
# https://www.gnu.org/software/autoconf-archive/ax_gcc_archflag.html
|
||||
# ===========================================================================
|
||||
#
|
||||
# SYNOPSIS
|
||||
#
|
||||
# AX_GCC_ARCHFLAG([PORTABLE?], [ACTION-SUCCESS], [ACTION-FAILURE])
|
||||
#
|
||||
# DESCRIPTION
|
||||
#
|
||||
# This macro tries to guess the "native" arch corresponding to the target
|
||||
# architecture for use with gcc's -march=arch or -mtune=arch flags. If
|
||||
# found, the cache variable $ax_cv_gcc_archflag is set to this flag and
|
||||
# ACTION-SUCCESS is executed; otherwise $ax_cv_gcc_archflag is set to
|
||||
# "unknown" and ACTION-FAILURE is executed. The default ACTION-SUCCESS is
|
||||
# to add $ax_cv_gcc_archflag to the end of $CFLAGS.
|
||||
#
|
||||
# PORTABLE? should be either [yes] (default) or [no]. In the former case,
|
||||
# the flag is set to -mtune (or equivalent) so that the architecture is
|
||||
# only used for tuning, but the instruction set used is still portable. In
|
||||
# the latter case, the flag is set to -march (or equivalent) so that
|
||||
# architecture-specific instructions are enabled.
|
||||
#
|
||||
# The user can specify --with-gcc-arch=<arch> in order to override the
|
||||
# macro's choice of architecture, or --without-gcc-arch to disable this.
|
||||
#
|
||||
# When cross-compiling, or if $CC is not gcc, then ACTION-FAILURE is
|
||||
# called unless the user specified --with-gcc-arch manually.
|
||||
#
|
||||
# Requires macros: AX_CHECK_COMPILE_FLAG, AX_GCC_X86_CPUID
|
||||
#
|
||||
# (The main emphasis here is on recent CPUs, on the principle that doing
|
||||
# high-performance computing on old hardware is uncommon.)
|
||||
#
|
||||
# LICENSE
|
||||
#
|
||||
# Copyright (c) 2008 Steven G. Johnson <stevenj@alum.mit.edu>
|
||||
# Copyright (c) 2008 Matteo Frigo
|
||||
# Copyright (c) 2014 Tsukasa Oi
|
||||
# Copyright (c) 2017-2018 Alexey Kopytov
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify it
|
||||
# under the terms of the GNU General Public License as published by the
|
||||
# Free Software Foundation, either version 3 of the License, or (at your
|
||||
# option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful, but
|
||||
# WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
|
||||
# Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License along
|
||||
# with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
#
|
||||
# As a special exception, the respective Autoconf Macro's copyright owner
|
||||
# gives unlimited permission to copy, distribute and modify the configure
|
||||
# scripts that are the output of Autoconf when processing the Macro. You
|
||||
# need not follow the terms of the GNU General Public License when using
|
||||
# or distributing such scripts, even though portions of the text of the
|
||||
# Macro appear in them. The GNU General Public License (GPL) does govern
|
||||
# all other use of the material that constitutes the Autoconf Macro.
|
||||
#
|
||||
# This special exception to the GPL applies to versions of the Autoconf
|
||||
# Macro released by the Autoconf Archive. When you make and distribute a
|
||||
# modified version of the Autoconf Macro, you may extend this special
|
||||
# exception to the GPL to apply to your modified version as well.
|
||||
|
||||
#serial 21
|
||||
|
||||
AC_DEFUN([AX_GCC_ARCHFLAG],
|
||||
[AC_REQUIRE([AC_PROG_CC])
|
||||
AC_REQUIRE([AC_CANONICAL_HOST])
|
||||
AC_REQUIRE([AC_PROG_SED])
|
||||
AC_REQUIRE([AX_COMPILER_VENDOR])
|
||||
|
||||
AC_ARG_WITH(gcc-arch, [AS_HELP_STRING([--with-gcc-arch=<arch>], [use architecture <arch> for gcc -march/-mtune, instead of guessing])],
|
||||
ax_gcc_arch=$withval, ax_gcc_arch=yes)
|
||||
|
||||
AC_MSG_CHECKING([for gcc architecture flag])
|
||||
AC_MSG_RESULT([])
|
||||
AC_CACHE_VAL(ax_cv_gcc_archflag,
|
||||
[
|
||||
ax_cv_gcc_archflag="unknown"
|
||||
|
||||
if test "$GCC" = yes; then
|
||||
|
||||
if test "x$ax_gcc_arch" = xyes; then
|
||||
ax_gcc_arch=""
|
||||
if test "$cross_compiling" = no; then
|
||||
case $host_cpu in
|
||||
i[[3456]]86*|x86_64*|amd64*) # use cpuid codes
|
||||
AX_GCC_X86_CPUID(0)
|
||||
AX_GCC_X86_CPUID(1)
|
||||
case $ax_cv_gcc_x86_cpuid_0 in
|
||||
*:756e6547:6c65746e:49656e69) # Intel
|
||||
case $ax_cv_gcc_x86_cpuid_1 in
|
||||
*5[[4578]]?:*:*:*) ax_gcc_arch="pentium-mmx pentium" ;;
|
||||
*5[[123]]?:*:*:*) ax_gcc_arch=pentium ;;
|
||||
*0?61?:*:*:*|?61?:*:*:*|61?:*:*:*) ax_gcc_arch=pentiumpro ;;
|
||||
*0?6[[356]]?:*:*:*|?6[[356]]?:*:*:*|6[[356]]?:*:*:*) ax_gcc_arch="pentium2 pentiumpro" ;;
|
||||
*0?6[[78ab]]?:*:*:*|?6[[78ab]]?:*:*:*|6[[78ab]]?:*:*:*) ax_gcc_arch="pentium3 pentiumpro" ;;
|
||||
*0?6[[9d]]?:*:*:*|?6[[9d]]?:*:*:*|6[[9d]]?:*:*:*|*1?65?:*:*:*) ax_gcc_arch="pentium-m pentium3 pentiumpro" ;;
|
||||
*0?6e?:*:*:*|?6e?:*:*:*|6e?:*:*:*) ax_gcc_arch="yonah pentium-m pentium3 pentiumpro" ;;
|
||||
*0?6f?:*:*:*|?6f?:*:*:*|6f?:*:*:*|*1?66?:*:*:*) ax_gcc_arch="core2 pentium-m pentium3 pentiumpro" ;;
|
||||
*1?6[[7d]]?:*:*:*) ax_gcc_arch="penryn core2 pentium-m pentium3 pentiumpro" ;;
|
||||
*1?6[[aef]]?:*:*:*|*2?6e?:*:*:*) ax_gcc_arch="nehalem corei7 core2 pentium-m pentium3 pentiumpro" ;;
|
||||
*2?6[[5cf]]?:*:*:*) ax_gcc_arch="westmere corei7 core2 pentium-m pentium3 pentiumpro" ;;
|
||||
*2?6[[ad]]?:*:*:*) ax_gcc_arch="sandybridge corei7-avx corei7 core2 pentium-m pentium3 pentiumpro" ;;
|
||||
*3?6[[ae]]?:*:*:*) ax_gcc_arch="ivybridge core-avx-i corei7-avx corei7 core2 pentium-m pentium3 pentiumpro" ;;
|
||||
*3?6[[cf]]?:*:*:*|*4?6[[56]]?:*:*:*) ax_gcc_arch="haswell core-avx2 core-avx-i corei7-avx corei7 core2 pentium-m pentium3 pentiumpro" ;;
|
||||
*3?6d?:*:*:*|*4?6[[7f]]?:*:*:*|*5?66?:*:*:*) ax_gcc_arch="broadwell core-avx2 core-avx-i corei7-avx corei7 core2 pentium-m pentium3 pentiumpro" ;;
|
||||
*1?6c?:*:*:*|*2?6[[67]]?:*:*:*|*3?6[[56]]?:*:*:*) ax_gcc_arch="bonnell atom core2 pentium-m pentium3 pentiumpro" ;;
|
||||
*3?67?:*:*:*|*[[45]]?6[[ad]]?:*:*:*) ax_gcc_arch="silvermont atom core2 pentium-m pentium3 pentiumpro" ;;
|
||||
*000?f[[012]]?:*:*:*|?f[[012]]?:*:*:*|f[[012]]?:*:*:*) ax_gcc_arch="pentium4 pentiumpro" ;;
|
||||
*000?f[[346]]?:*:*:*|?f[[346]]?:*:*:*|f[[346]]?:*:*:*) ax_gcc_arch="nocona prescott pentium4 pentiumpro" ;;
|
||||
# fallback
|
||||
*5??:*:*:*) ax_gcc_arch=pentium ;;
|
||||
*??6??:*:*:*) ax_gcc_arch="core2 pentiumpro" ;;
|
||||
*6??:*:*:*) ax_gcc_arch=pentiumpro ;;
|
||||
*00??f??:*:*:*|??f??:*:*:*|?f??:*:*:*|f??:*:*:*) ax_gcc_arch="pentium4 pentiumpro" ;;
|
||||
esac ;;
|
||||
*:68747541:444d4163:69746e65) # AMD
|
||||
case $ax_cv_gcc_x86_cpuid_1 in
|
||||
*5[[67]]?:*:*:*) ax_gcc_arch=k6 ;;
|
||||
*5[[8]]?:*:*:*) ax_gcc_arch="k6-2 k6" ;;
|
||||
*5[[9d]]?:*:*:*) ax_gcc_arch="k6-3 k6" ;;
|
||||
*6[[12]]?:*:*:*) ax_gcc_arch="athlon k7" ;;
|
||||
*6[[34]]?:*:*:*) ax_gcc_arch="athlon-tbird k7" ;;
|
||||
*6[[678a]]?:*:*:*) ax_gcc_arch="athlon-xp athlon-4 athlon k7" ;;
|
||||
*000?f[[4578bcef]]?:*:*:*|?f[[4578bcef]]?:*:*:*|f[[4578bcef]]?:*:*:*|*001?f[[4578bcf]]?:*:*:*|1?f[[4578bcf]]?:*:*:*) ax_gcc_arch="athlon64 k8" ;;
|
||||
*002?f[[13457bcf]]?:*:*:*|2?f[[13457bcf]]?:*:*:*|*004?f[[138bcf]]?:*:*:*|4?f[[138bcf]]?:*:*:*|*005?f[[df]]?:*:*:*|5?f[[df]]?:*:*:*|*006?f[[8bcf]]?:*:*:*|6?f[[8bcf]]?:*:*:*|*007?f[[cf]]?:*:*:*|7?f[[cf]]?:*:*:*|*00c?f1?:*:*:*|c?f1?:*:*:*|*020?f3?:*:*:*|20?f3?:*:*:*) ax_gcc_arch="athlon64-sse3 k8-sse3 athlon64 k8" ;;
|
||||
*010?f[[245689a]]?:*:*:*|10?f[[245689a]]?:*:*:*|*030?f1?:*:*:*|30?f1?:*:*:*) ax_gcc_arch="barcelona amdfam10 k8" ;;
|
||||
*050?f[[12]]?:*:*:*|50?f[[12]]?:*:*:*) ax_gcc_arch="btver1 amdfam10 k8" ;;
|
||||
*060?f1?:*:*:*|60?f1?:*:*:*) ax_gcc_arch="bdver1 amdfam10 k8" ;;
|
||||
*060?f2?:*:*:*|60?f2?:*:*:*|*061?f[[03]]?:*:*:*|61?f[[03]]?:*:*:*) ax_gcc_arch="bdver2 bdver1 amdfam10 k8" ;;
|
||||
*063?f0?:*:*:*|63?f0?:*:*:*) ax_gcc_arch="bdver3 bdver2 bdver1 amdfam10 k8" ;;
|
||||
*07[[03]]?f0?:*:*:*|7[[03]]?f0?:*:*:*) ax_gcc_arch="btver2 btver1 amdfam10 k8" ;;
|
||||
# fallback
|
||||
*0[[13]]??f??:*:*:*|[[13]]??f??:*:*:*) ax_gcc_arch="barcelona amdfam10 k8" ;;
|
||||
*020?f??:*:*:*|20?f??:*:*:*) ax_gcc_arch="athlon64-sse3 k8-sse3 athlon64 k8" ;;
|
||||
*05??f??:*:*:*|5??f??:*:*:*) ax_gcc_arch="btver1 amdfam10 k8" ;;
|
||||
*060?f??:*:*:*|60?f??:*:*:*) ax_gcc_arch="bdver1 amdfam10 k8" ;;
|
||||
*061?f??:*:*:*|61?f??:*:*:*) ax_gcc_arch="bdver2 bdver1 amdfam10 k8" ;;
|
||||
*06??f??:*:*:*|6??f??:*:*:*) ax_gcc_arch="bdver3 bdver2 bdver1 amdfam10 k8" ;;
|
||||
*070?f??:*:*:*|70?f??:*:*:*) ax_gcc_arch="btver2 btver1 amdfam10 k8" ;;
|
||||
*???f??:*:*:*) ax_gcc_arch="amdfam10 k8" ;;
|
||||
esac ;;
|
||||
*:746e6543:736c7561:48727561) # IDT / VIA (Centaur)
|
||||
case $ax_cv_gcc_x86_cpuid_1 in
|
||||
*54?:*:*:*) ax_gcc_arch=winchip-c6 ;;
|
||||
*5[[89]]?:*:*:*) ax_gcc_arch=winchip2 ;;
|
||||
*66?:*:*:*) ax_gcc_arch=winchip2 ;;
|
||||
*6[[78]]?:*:*:*) ax_gcc_arch=c3 ;;
|
||||
*6[[9adf]]?:*:*:*) ax_gcc_arch="c3-2 c3" ;;
|
||||
esac ;;
|
||||
esac
|
||||
if test x"$ax_gcc_arch" = x; then # fallback
|
||||
case $host_cpu in
|
||||
i586*) ax_gcc_arch=pentium ;;
|
||||
i686*) ax_gcc_arch=pentiumpro ;;
|
||||
esac
|
||||
fi
|
||||
;;
|
||||
|
||||
sparc*)
|
||||
AC_PATH_PROG([PRTDIAG], [prtdiag], [prtdiag], [$PATH:/usr/platform/`uname -i`/sbin/:/usr/platform/`uname -m`/sbin/])
|
||||
cputype=`(((grep cpu /proc/cpuinfo | cut -d: -f2) ; ($PRTDIAG -v |grep -i sparc) ; grep -i cpu /var/run/dmesg.boot ) | head -n 1) 2> /dev/null`
|
||||
cputype=`echo "$cputype" | tr -d ' -' | $SED 's/SPARCIIi/SPARCII/' |tr $as_cr_LETTERS $as_cr_letters`
|
||||
case $cputype in
|
||||
*ultrasparciv*) ax_gcc_arch="ultrasparc4 ultrasparc3 ultrasparc v9" ;;
|
||||
*ultrasparciii*) ax_gcc_arch="ultrasparc3 ultrasparc v9" ;;
|
||||
*ultrasparc*) ax_gcc_arch="ultrasparc v9" ;;
|
||||
*supersparc*|*tms390z5[[05]]*) ax_gcc_arch="supersparc v8" ;;
|
||||
*hypersparc*|*rt62[[056]]*) ax_gcc_arch="hypersparc v8" ;;
|
||||
*cypress*) ax_gcc_arch=cypress ;;
|
||||
esac ;;
|
||||
|
||||
alphaev5) ax_gcc_arch=ev5 ;;
|
||||
alphaev56) ax_gcc_arch=ev56 ;;
|
||||
alphapca56) ax_gcc_arch="pca56 ev56" ;;
|
||||
alphapca57) ax_gcc_arch="pca57 pca56 ev56" ;;
|
||||
alphaev6) ax_gcc_arch=ev6 ;;
|
||||
alphaev67) ax_gcc_arch=ev67 ;;
|
||||
alphaev68) ax_gcc_arch="ev68 ev67" ;;
|
||||
alphaev69) ax_gcc_arch="ev69 ev68 ev67" ;;
|
||||
alphaev7) ax_gcc_arch="ev7 ev69 ev68 ev67" ;;
|
||||
alphaev79) ax_gcc_arch="ev79 ev7 ev69 ev68 ev67" ;;
|
||||
|
||||
powerpc*)
|
||||
cputype=`((grep cpu /proc/cpuinfo | head -n 1 | cut -d: -f2 | cut -d, -f1 | $SED 's/ //g') ; /usr/bin/machine ; /bin/machine; grep CPU /var/run/dmesg.boot | head -n 1 | cut -d" " -f2) 2> /dev/null`
|
||||
cputype=`echo $cputype | $SED -e 's/ppc//g;s/ *//g'`
|
||||
case $cputype in
|
||||
*750*) ax_gcc_arch="750 G3" ;;
|
||||
*740[[0-9]]*) ax_gcc_arch="$cputype 7400 G4" ;;
|
||||
*74[[4-5]][[0-9]]*) ax_gcc_arch="$cputype 7450 G4" ;;
|
||||
*74[[0-9]][[0-9]]*) ax_gcc_arch="$cputype G4" ;;
|
||||
*970*) ax_gcc_arch="970 G5 power4";;
|
||||
*POWER4*|*power4*|*gq*) ax_gcc_arch="power4 970";;
|
||||
*POWER5*|*power5*|*gr*|*gs*) ax_gcc_arch="power5 power4 970";;
|
||||
603ev|8240) ax_gcc_arch="$cputype 603e 603";;
|
||||
*) ax_gcc_arch=$cputype ;;
|
||||
esac
|
||||
ax_gcc_arch="$ax_gcc_arch powerpc"
|
||||
;;
|
||||
aarch64)
|
||||
cpuimpl=`grep 'CPU implementer' /proc/cpuinfo 2> /dev/null | cut -d: -f2 | tr -d " " | head -n 1`
|
||||
cpuarch=`grep 'CPU architecture' /proc/cpuinfo 2> /dev/null | cut -d: -f2 | tr -d " " | head -n 1`
|
||||
cpuvar=`grep 'CPU variant' /proc/cpuinfo 2> /dev/null | cut -d: -f2 | tr -d " " | head -n 1`
|
||||
case $cpuimpl in
|
||||
0x42) case $cpuarch in
|
||||
8) case $cpuvar in
|
||||
0x0) ax_gcc_arch="thunderx2t99 vulcan armv8.1-a armv8-a+lse armv8-a native" ;;
|
||||
esac
|
||||
;;
|
||||
esac
|
||||
;;
|
||||
0x43) case $cpuarch in
|
||||
8) case $cpuvar in
|
||||
0x0) ax_gcc_arch="thunderx armv8-a native" ;;
|
||||
0x1) ax_gcc_arch="thunderx+lse armv8.1-a armv8-a+lse armv8-a native" ;;
|
||||
esac
|
||||
;;
|
||||
esac
|
||||
;;
|
||||
esac
|
||||
;;
|
||||
esac
|
||||
fi # not cross-compiling
|
||||
fi # guess arch
|
||||
|
||||
if test "x$ax_gcc_arch" != x -a "x$ax_gcc_arch" != xno; then
|
||||
if test "x[]m4_default([$1],yes)" = xyes; then # if we require portable code
|
||||
flag_prefixes="-mtune="
|
||||
if test "x$ax_cv_[]_AC_LANG_ABBREV[]_compiler_vendor" = xclang; then flag_prefixes="-march="; fi
|
||||
# -mcpu=$arch and m$arch generate nonportable code on every arch except
|
||||
# x86. And some other arches (e.g. Alpha) don't accept -mtune. Grrr.
|
||||
case $host_cpu in i*86|x86_64*|amd64*) flag_prefixes="$flag_prefixes -mcpu= -m";; esac
|
||||
else
|
||||
flag_prefixes="-march= -mcpu= -m"
|
||||
fi
|
||||
for flag_prefix in $flag_prefixes; do
|
||||
for arch in $ax_gcc_arch; do
|
||||
flag="$flag_prefix$arch"
|
||||
AX_CHECK_COMPILE_FLAG($flag, [if test "x$ax_cv_[]_AC_LANG_ABBREV[]_compiler_vendor" = xclang; then
|
||||
if test "x[]m4_default([$1],yes)" = xyes; then
|
||||
if test "x$flag" = "x-march=$arch"; then flag=-mtune=$arch; fi
|
||||
fi
|
||||
fi; ax_cv_gcc_archflag=$flag; break])
|
||||
done
|
||||
test "x$ax_cv_gcc_archflag" = xunknown || break
|
||||
done
|
||||
fi
|
||||
|
||||
fi # $GCC=yes
|
||||
])
|
||||
AC_MSG_CHECKING([for gcc architecture flag])
|
||||
AC_MSG_RESULT($ax_cv_gcc_archflag)
|
||||
if test "x$ax_cv_gcc_archflag" = xunknown; then
|
||||
m4_default([$3],:)
|
||||
else
|
||||
m4_default([$2], [CFLAGS="$CFLAGS $ax_cv_gcc_archflag"])
|
||||
fi
|
||||
])
|
||||
|
|
@ -0,0 +1,238 @@
|
|||
# ===========================================================================
|
||||
# https://www.gnu.org/software/autoconf-archive/ax_gcc_func_attribute.html
|
||||
# ===========================================================================
|
||||
#
|
||||
# SYNOPSIS
|
||||
#
|
||||
# AX_GCC_FUNC_ATTRIBUTE(ATTRIBUTE)
|
||||
#
|
||||
# DESCRIPTION
|
||||
#
|
||||
# This macro checks if the compiler supports one of GCC's function
|
||||
# attributes; many other compilers also provide function attributes with
|
||||
# the same syntax. Compiler warnings are used to detect supported
|
||||
# attributes as unsupported ones are ignored by default so quieting
|
||||
# warnings when using this macro will yield false positives.
|
||||
#
|
||||
# The ATTRIBUTE parameter holds the name of the attribute to be checked.
|
||||
#
|
||||
# If ATTRIBUTE is supported define HAVE_FUNC_ATTRIBUTE_<ATTRIBUTE>.
|
||||
#
|
||||
# The macro caches its result in the ax_cv_have_func_attribute_<attribute>
|
||||
# variable.
|
||||
#
|
||||
# The macro currently supports the following function attributes:
|
||||
#
|
||||
# alias
|
||||
# aligned
|
||||
# alloc_size
|
||||
# always_inline
|
||||
# artificial
|
||||
# cold
|
||||
# const
|
||||
# constructor
|
||||
# constructor_priority for constructor attribute with priority
|
||||
# deprecated
|
||||
# destructor
|
||||
# dllexport
|
||||
# dllimport
|
||||
# error
|
||||
# externally_visible
|
||||
# fallthrough
|
||||
# flatten
|
||||
# format
|
||||
# format_arg
|
||||
# gnu_inline
|
||||
# hot
|
||||
# ifunc
|
||||
# leaf
|
||||
# malloc
|
||||
# noclone
|
||||
# noinline
|
||||
# nonnull
|
||||
# noreturn
|
||||
# nothrow
|
||||
# optimize
|
||||
# pure
|
||||
# sentinel
|
||||
# sentinel_position
|
||||
# unused
|
||||
# used
|
||||
# visibility
|
||||
# warning
|
||||
# warn_unused_result
|
||||
# weak
|
||||
# weakref
|
||||
#
|
||||
# Unsupported function attributes will be tested with a prototype
|
||||
# returning an int and not accepting any arguments and the result of the
|
||||
# check might be wrong or meaningless so use with care.
|
||||
#
|
||||
# LICENSE
|
||||
#
|
||||
# Copyright (c) 2013 Gabriele Svelto <gabriele.svelto@gmail.com>
|
||||
#
|
||||
# Copying and distribution of this file, with or without modification, are
|
||||
# permitted in any medium without royalty provided the copyright notice
|
||||
# and this notice are preserved. This file is offered as-is, without any
|
||||
# warranty.
|
||||
|
||||
#serial 9
|
||||
|
||||
AC_DEFUN([AX_GCC_FUNC_ATTRIBUTE], [
|
||||
AS_VAR_PUSHDEF([ac_var], [ax_cv_have_func_attribute_$1])
|
||||
|
||||
AC_CACHE_CHECK([for __attribute__(($1))], [ac_var], [
|
||||
AC_LINK_IFELSE([AC_LANG_PROGRAM([
|
||||
m4_case([$1],
|
||||
[alias], [
|
||||
int foo( void ) { return 0; }
|
||||
int bar( void ) __attribute__(($1("foo")));
|
||||
],
|
||||
[aligned], [
|
||||
int foo( void ) __attribute__(($1(32)));
|
||||
],
|
||||
[alloc_size], [
|
||||
void *foo(int a) __attribute__(($1(1)));
|
||||
],
|
||||
[always_inline], [
|
||||
inline __attribute__(($1)) int foo( void ) { return 0; }
|
||||
],
|
||||
[artificial], [
|
||||
inline __attribute__(($1)) int foo( void ) { return 0; }
|
||||
],
|
||||
[cold], [
|
||||
int foo( void ) __attribute__(($1));
|
||||
],
|
||||
[const], [
|
||||
int foo( void ) __attribute__(($1));
|
||||
],
|
||||
[constructor_priority], [
|
||||
int foo( void ) __attribute__((__constructor__(65535/2)));
|
||||
],
|
||||
[constructor], [
|
||||
int foo( void ) __attribute__(($1));
|
||||
],
|
||||
[deprecated], [
|
||||
int foo( void ) __attribute__(($1("")));
|
||||
],
|
||||
[destructor], [
|
||||
int foo( void ) __attribute__(($1));
|
||||
],
|
||||
[dllexport], [
|
||||
__attribute__(($1)) int foo( void ) { return 0; }
|
||||
],
|
||||
[dllimport], [
|
||||
int foo( void ) __attribute__(($1));
|
||||
],
|
||||
[error], [
|
||||
int foo( void ) __attribute__(($1("")));
|
||||
],
|
||||
[externally_visible], [
|
||||
int foo( void ) __attribute__(($1));
|
||||
],
|
||||
[fallthrough], [
|
||||
int foo( void ) {switch (0) { case 1: __attribute__(($1)); case 2: break ; }};
|
||||
],
|
||||
[flatten], [
|
||||
int foo( void ) __attribute__(($1));
|
||||
],
|
||||
[format], [
|
||||
int foo(const char *p, ...) __attribute__(($1(printf, 1, 2)));
|
||||
],
|
||||
[format_arg], [
|
||||
char *foo(const char *p) __attribute__(($1(1)));
|
||||
],
|
||||
[gnu_inline], [
|
||||
inline __attribute__(($1)) int foo( void ) { return 0; }
|
||||
],
|
||||
[hot], [
|
||||
int foo( void ) __attribute__(($1));
|
||||
],
|
||||
[ifunc], [
|
||||
int my_foo( void ) { return 0; }
|
||||
static int (*resolve_foo(void))(void) { return my_foo; }
|
||||
int foo( void ) __attribute__(($1("resolve_foo")));
|
||||
],
|
||||
[leaf], [
|
||||
__attribute__(($1)) int foo( void ) { return 0; }
|
||||
],
|
||||
[malloc], [
|
||||
void *foo( void ) __attribute__(($1));
|
||||
],
|
||||
[noclone], [
|
||||
int foo( void ) __attribute__(($1));
|
||||
],
|
||||
[noinline], [
|
||||
__attribute__(($1)) int foo( void ) { return 0; }
|
||||
],
|
||||
[nonnull], [
|
||||
int foo(char *p) __attribute__(($1(1)));
|
||||
],
|
||||
[noreturn], [
|
||||
void foo( void ) __attribute__(($1));
|
||||
],
|
||||
[nothrow], [
|
||||
int foo( void ) __attribute__(($1));
|
||||
],
|
||||
[optimize], [
|
||||
__attribute__(($1(3))) int foo( void ) { return 0; }
|
||||
],
|
||||
[pure], [
|
||||
int foo( void ) __attribute__(($1));
|
||||
],
|
||||
[sentinel], [
|
||||
int foo(void *p, ...) __attribute__(($1));
|
||||
],
|
||||
[sentinel_position], [
|
||||
int foo(void *p, ...) __attribute__(($1(1)));
|
||||
],
|
||||
[returns_nonnull], [
|
||||
void *foo( void ) __attribute__(($1));
|
||||
],
|
||||
[unused], [
|
||||
int foo( void ) __attribute__(($1));
|
||||
],
|
||||
[used], [
|
||||
int foo( void ) __attribute__(($1));
|
||||
],
|
||||
[visibility], [
|
||||
int foo_def( void ) __attribute__(($1("default")));
|
||||
int foo_hid( void ) __attribute__(($1("hidden")));
|
||||
int foo_int( void ) __attribute__(($1("internal")));
|
||||
int foo_pro( void ) __attribute__(($1("protected")));
|
||||
],
|
||||
[warning], [
|
||||
int foo( void ) __attribute__(($1("")));
|
||||
],
|
||||
[warn_unused_result], [
|
||||
int foo( void ) __attribute__(($1));
|
||||
],
|
||||
[weak], [
|
||||
int foo( void ) __attribute__(($1));
|
||||
],
|
||||
[weakref], [
|
||||
static int foo( void ) { return 0; }
|
||||
static int bar( void ) __attribute__(($1("foo")));
|
||||
],
|
||||
[
|
||||
m4_warn([syntax], [Unsupported attribute $1, the test may fail])
|
||||
int foo( void ) __attribute__(($1));
|
||||
]
|
||||
)], [])
|
||||
],
|
||||
dnl GCC doesn't exit with an error if an unknown attribute is
|
||||
dnl provided but only outputs a warning, so accept the attribute
|
||||
dnl only if no warning were issued.
|
||||
[AS_IF([test -s conftest.err],
|
||||
[AS_VAR_SET([ac_var], [no])],
|
||||
[AS_VAR_SET([ac_var], [yes])])],
|
||||
[AS_VAR_SET([ac_var], [no])])
|
||||
])
|
||||
|
||||
AS_IF([test yes = AS_VAR_GET([ac_var])],
|
||||
[AC_DEFINE_UNQUOTED(AS_TR_CPP(HAVE_FUNC_ATTRIBUTE_$1), 1,
|
||||
[Define to 1 if the system has the `$1' function attribute])], [])
|
||||
|
||||
AS_VAR_POPDEF([ac_var])
|
||||
])
|
||||
|
|
@ -0,0 +1,89 @@
|
|||
# ===========================================================================
|
||||
# https://www.gnu.org/software/autoconf-archive/ax_gcc_x86_cpuid.html
|
||||
# ===========================================================================
|
||||
#
|
||||
# SYNOPSIS
|
||||
#
|
||||
# AX_GCC_X86_CPUID(OP)
|
||||
# AX_GCC_X86_CPUID_COUNT(OP, COUNT)
|
||||
#
|
||||
# DESCRIPTION
|
||||
#
|
||||
# On Pentium and later x86 processors, with gcc or a compiler that has a
|
||||
# compatible syntax for inline assembly instructions, run a small program
|
||||
# that executes the cpuid instruction with input OP. This can be used to
|
||||
# detect the CPU type. AX_GCC_X86_CPUID_COUNT takes an additional COUNT
|
||||
# parameter that gets passed into register ECX before calling cpuid.
|
||||
#
|
||||
# On output, the values of the eax, ebx, ecx, and edx registers are stored
|
||||
# as hexadecimal strings as "eax:ebx:ecx:edx" in the cache variable
|
||||
# ax_cv_gcc_x86_cpuid_OP.
|
||||
#
|
||||
# If the cpuid instruction fails (because you are running a
|
||||
# cross-compiler, or because you are not using gcc, or because you are on
|
||||
# a processor that doesn't have this instruction), ax_cv_gcc_x86_cpuid_OP
|
||||
# is set to the string "unknown".
|
||||
#
|
||||
# This macro mainly exists to be used in AX_GCC_ARCHFLAG.
|
||||
#
|
||||
# LICENSE
|
||||
#
|
||||
# Copyright (c) 2008 Steven G. Johnson <stevenj@alum.mit.edu>
|
||||
# Copyright (c) 2008 Matteo Frigo
|
||||
# Copyright (c) 2015 Michael Petch <mpetch@capp-sysware.com>
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify it
|
||||
# under the terms of the GNU General Public License as published by the
|
||||
# Free Software Foundation, either version 3 of the License, or (at your
|
||||
# option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful, but
|
||||
# WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
|
||||
# Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License along
|
||||
# with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
#
|
||||
# As a special exception, the respective Autoconf Macro's copyright owner
|
||||
# gives unlimited permission to copy, distribute and modify the configure
|
||||
# scripts that are the output of Autoconf when processing the Macro. You
|
||||
# need not follow the terms of the GNU General Public License when using
|
||||
# or distributing such scripts, even though portions of the text of the
|
||||
# Macro appear in them. The GNU General Public License (GPL) does govern
|
||||
# all other use of the material that constitutes the Autoconf Macro.
|
||||
#
|
||||
# This special exception to the GPL applies to versions of the Autoconf
|
||||
# Macro released by the Autoconf Archive. When you make and distribute a
|
||||
# modified version of the Autoconf Macro, you may extend this special
|
||||
# exception to the GPL to apply to your modified version as well.
|
||||
|
||||
#serial 10
|
||||
|
||||
AC_DEFUN([AX_GCC_X86_CPUID],
|
||||
[AX_GCC_X86_CPUID_COUNT($1, 0)
|
||||
])
|
||||
|
||||
AC_DEFUN([AX_GCC_X86_CPUID_COUNT],
|
||||
[AC_REQUIRE([AC_PROG_CC])
|
||||
AC_LANG_PUSH([C])
|
||||
AC_CACHE_CHECK(for x86 cpuid $1 output, ax_cv_gcc_x86_cpuid_$1,
|
||||
[AC_RUN_IFELSE([AC_LANG_PROGRAM([#include <stdio.h>], [
|
||||
int op = $1, level = $2, eax, ebx, ecx, edx;
|
||||
FILE *f;
|
||||
__asm__ __volatile__ ("xchg %%ebx, %1\n"
|
||||
"cpuid\n"
|
||||
"xchg %%ebx, %1\n"
|
||||
: "=a" (eax), "=r" (ebx), "=c" (ecx), "=d" (edx)
|
||||
: "a" (op), "2" (level));
|
||||
|
||||
f = fopen("conftest_cpuid", "w"); if (!f) return 1;
|
||||
fprintf(f, "%x:%x:%x:%x\n", eax, ebx, ecx, edx);
|
||||
fclose(f);
|
||||
return 0;
|
||||
])],
|
||||
[ax_cv_gcc_x86_cpuid_$1=`cat conftest_cpuid`; rm -f conftest_cpuid],
|
||||
[ax_cv_gcc_x86_cpuid_$1=unknown; rm -f conftest_cpuid],
|
||||
[ax_cv_gcc_x86_cpuid_$1=unknown])])
|
||||
AC_LANG_POP([C])
|
||||
])
|
||||
|
|
@ -0,0 +1,74 @@
|
|||
# ===========================================================================
|
||||
# https://www.gnu.org/software/autoconf-archive/ax_tls.html
|
||||
# ===========================================================================
|
||||
#
|
||||
# SYNOPSIS
|
||||
#
|
||||
# AX_TLS([action-if-found], [action-if-not-found])
|
||||
#
|
||||
# DESCRIPTION
|
||||
#
|
||||
# Provides a test for the compiler support of thread local storage (TLS)
|
||||
# extensions. Defines TLS if it is found. Currently knows about C++11,
|
||||
# GCC/ICC, and MSVC. I think SunPro uses the same as GCC, and Borland
|
||||
# apparently supports either.
|
||||
#
|
||||
# LICENSE
|
||||
#
|
||||
# Copyright (c) 2008 Alan Woodland <ajw05@aber.ac.uk>
|
||||
# Copyright (c) 2010 Diego Elio Petteno` <flameeyes@gmail.com>
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify it
|
||||
# under the terms of the GNU General Public License as published by the
|
||||
# Free Software Foundation, either version 3 of the License, or (at your
|
||||
# option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful, but
|
||||
# WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
|
||||
# Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License along
|
||||
# with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
#
|
||||
# As a special exception, the respective Autoconf Macro's copyright owner
|
||||
# gives unlimited permission to copy, distribute and modify the configure
|
||||
# scripts that are the output of Autoconf when processing the Macro. You
|
||||
# need not follow the terms of the GNU General Public License when using
|
||||
# or distributing such scripts, even though portions of the text of the
|
||||
# Macro appear in them. The GNU General Public License (GPL) does govern
|
||||
# all other use of the material that constitutes the Autoconf Macro.
|
||||
#
|
||||
# This special exception to the GPL applies to versions of the Autoconf
|
||||
# Macro released by the Autoconf Archive. When you make and distribute a
|
||||
# modified version of the Autoconf Macro, you may extend this special
|
||||
# exception to the GPL to apply to your modified version as well.
|
||||
|
||||
#serial 14
|
||||
|
||||
AC_DEFUN([AX_TLS], [
|
||||
AC_MSG_CHECKING([for thread local storage (TLS) class])
|
||||
AC_CACHE_VAL([ac_cv_tls],
|
||||
[for ax_tls_keyword in thread_local _Thread_local __thread '__declspec(thread)' none; do
|
||||
AS_CASE([$ax_tls_keyword],
|
||||
[none], [ac_cv_tls=none ; break],
|
||||
[AC_TRY_COMPILE(
|
||||
[#include <stdlib.h>
|
||||
static void
|
||||
foo(void) {
|
||||
static ] $ax_tls_keyword [ int bar;
|
||||
exit(1);
|
||||
}],
|
||||
[],
|
||||
[ac_cv_tls=$ax_tls_keyword ; break],
|
||||
ac_cv_tls=none
|
||||
)])
|
||||
done
|
||||
])
|
||||
AC_MSG_RESULT([$ac_cv_tls])
|
||||
|
||||
AS_IF([test "$ac_cv_tls" != "none"],
|
||||
[AC_DEFINE_UNQUOTED([TLS],[$ac_cv_tls],[If the compiler supports a TLS storage class define it to that here])
|
||||
m4_ifnblank([$1],[$1])],
|
||||
[m4_ifnblank([$2],[$2])])
|
||||
])
|
||||
|
|
@ -0,0 +1,37 @@
|
|||
dnl Provide AC_USE_SYSTEM_EXTENSIONS for old autoconf machines.
|
||||
AC_DEFUN([ACX_USE_SYSTEM_EXTENSIONS],[
|
||||
ifdef([AC_USE_SYSTEM_EXTENSIONS],[
|
||||
AC_USE_SYSTEM_EXTENSIONS
|
||||
],[
|
||||
AC_BEFORE([$0], [AC_COMPILE_IFELSE])
|
||||
AC_BEFORE([$0], [AC_RUN_IFELSE])
|
||||
|
||||
AC_REQUIRE([AC_GNU_SOURCE])
|
||||
AC_REQUIRE([AC_AIX])
|
||||
AC_REQUIRE([AC_MINIX])
|
||||
|
||||
AH_VERBATIM([__EXTENSIONS__],
|
||||
[/* Enable extensions on Solaris. */
|
||||
#ifndef __EXTENSIONS__
|
||||
# undef __EXTENSIONS__
|
||||
#endif
|
||||
#ifndef _POSIX_PTHREAD_SEMANTICS
|
||||
# undef _POSIX_PTHREAD_SEMANTICS
|
||||
#endif
|
||||
#ifndef _TANDEM_SOURCE
|
||||
# undef _TANDEM_SOURCE
|
||||
#endif])
|
||||
AC_CACHE_CHECK([whether it is safe to define __EXTENSIONS__],
|
||||
[ac_cv_safe_to_define___extensions__],
|
||||
[AC_COMPILE_IFELSE(
|
||||
[AC_LANG_PROGRAM([
|
||||
# define __EXTENSIONS__ 1
|
||||
AC_INCLUDES_DEFAULT])],
|
||||
[ac_cv_safe_to_define___extensions__=yes],
|
||||
[ac_cv_safe_to_define___extensions__=no])])
|
||||
test $ac_cv_safe_to_define___extensions__ = yes &&
|
||||
AC_DEFINE([__EXTENSIONS__])
|
||||
AC_DEFINE([_POSIX_PTHREAD_SEMANTICS])
|
||||
AC_DEFINE([_TANDEM_SOURCE])
|
||||
])
|
||||
])
|
||||
|
|
@ -0,0 +1,110 @@
|
|||
# lib-ld.m4 serial 3 (gettext-0.13)
|
||||
dnl Copyright (C) 1996-2003 Free Software Foundation, Inc.
|
||||
dnl This file is free software; the Free Software Foundation
|
||||
dnl gives unlimited permission to copy and/or distribute it,
|
||||
dnl with or without modifications, as long as this notice is preserved.
|
||||
|
||||
dnl Subroutines of libtool.m4,
|
||||
dnl with replacements s/AC_/AC_LIB/ and s/lt_cv/acl_cv/ to avoid collision
|
||||
dnl with libtool.m4.
|
||||
|
||||
dnl From libtool-1.4. Sets the variable with_gnu_ld to yes or no.
|
||||
AC_DEFUN([AC_LIB_PROG_LD_GNU],
|
||||
[AC_CACHE_CHECK([if the linker ($LD) is GNU ld], acl_cv_prog_gnu_ld,
|
||||
[# I'd rather use --version here, but apparently some GNU ld's only accept -v.
|
||||
case `$LD -v 2>&1 </dev/null` in
|
||||
*GNU* | *'with BFD'*)
|
||||
acl_cv_prog_gnu_ld=yes ;;
|
||||
*)
|
||||
acl_cv_prog_gnu_ld=no ;;
|
||||
esac])
|
||||
with_gnu_ld=$acl_cv_prog_gnu_ld
|
||||
])
|
||||
|
||||
dnl From libtool-1.4. Sets the variable LD.
|
||||
AC_DEFUN([AC_LIB_PROG_LD],
|
||||
[AC_ARG_WITH(gnu-ld,
|
||||
[ --with-gnu-ld assume the C compiler uses GNU ld [default=no]],
|
||||
test "$withval" = no || with_gnu_ld=yes, with_gnu_ld=no)
|
||||
AC_REQUIRE([AC_PROG_CC])dnl
|
||||
AC_REQUIRE([AC_CANONICAL_HOST])dnl
|
||||
# Prepare PATH_SEPARATOR.
|
||||
# The user is always right.
|
||||
if test "${PATH_SEPARATOR+set}" != set; then
|
||||
echo "#! /bin/sh" >conf$$.sh
|
||||
echo "exit 0" >>conf$$.sh
|
||||
chmod +x conf$$.sh
|
||||
if (PATH="/nonexistent;."; conf$$.sh) >/dev/null 2>&1; then
|
||||
PATH_SEPARATOR=';'
|
||||
else
|
||||
PATH_SEPARATOR=:
|
||||
fi
|
||||
rm -f conf$$.sh
|
||||
fi
|
||||
ac_prog=ld
|
||||
if test "$GCC" = yes; then
|
||||
# Check if gcc -print-prog-name=ld gives a path.
|
||||
AC_MSG_CHECKING([for ld used by GCC])
|
||||
case $host in
|
||||
*-*-mingw*)
|
||||
# gcc leaves a trailing carriage return which upsets mingw
|
||||
ac_prog=`($CC -print-prog-name=ld) 2>&5 | tr -d '\015'` ;;
|
||||
*)
|
||||
ac_prog=`($CC -print-prog-name=ld) 2>&5` ;;
|
||||
esac
|
||||
case $ac_prog in
|
||||
# Accept absolute paths.
|
||||
[[\\/]* | [A-Za-z]:[\\/]*)]
|
||||
[re_direlt='/[^/][^/]*/\.\./']
|
||||
# Canonicalize the path of ld
|
||||
ac_prog=`echo $ac_prog| sed 's%\\\\%/%g'`
|
||||
while echo $ac_prog | grep "$re_direlt" > /dev/null 2>&1; do
|
||||
ac_prog=`echo $ac_prog| sed "s%$re_direlt%/%"`
|
||||
done
|
||||
test -z "$LD" && LD="$ac_prog"
|
||||
;;
|
||||
"")
|
||||
# If it fails, then pretend we aren't using GCC.
|
||||
ac_prog=ld
|
||||
;;
|
||||
*)
|
||||
# If it is relative, then search for the first ld in PATH.
|
||||
with_gnu_ld=unknown
|
||||
;;
|
||||
esac
|
||||
elif test "$with_gnu_ld" = yes; then
|
||||
AC_MSG_CHECKING([for GNU ld])
|
||||
else
|
||||
AC_MSG_CHECKING([for non-GNU ld])
|
||||
fi
|
||||
AC_CACHE_VAL(acl_cv_path_LD,
|
||||
[if test -z "$LD"; then
|
||||
IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS="${IFS}${PATH_SEPARATOR-:}"
|
||||
for ac_dir in $PATH; do
|
||||
test -z "$ac_dir" && ac_dir=.
|
||||
if test -f "$ac_dir/$ac_prog" || test -f "$ac_dir/$ac_prog$ac_exeext"; then
|
||||
acl_cv_path_LD="$ac_dir/$ac_prog"
|
||||
# Check to see if the program is GNU ld. I'd rather use --version,
|
||||
# but apparently some GNU ld's only accept -v.
|
||||
# Break only if it was the GNU/non-GNU ld that we prefer.
|
||||
case `"$acl_cv_path_LD" -v 2>&1 < /dev/null` in
|
||||
*GNU* | *'with BFD'*)
|
||||
test "$with_gnu_ld" != no && break ;;
|
||||
*)
|
||||
test "$with_gnu_ld" != yes && break ;;
|
||||
esac
|
||||
fi
|
||||
done
|
||||
IFS="$ac_save_ifs"
|
||||
else
|
||||
acl_cv_path_LD="$LD" # Let the user override the test with a path.
|
||||
fi])
|
||||
LD="$acl_cv_path_LD"
|
||||
if test -n "$LD"; then
|
||||
AC_MSG_RESULT($LD)
|
||||
else
|
||||
AC_MSG_RESULT(no)
|
||||
fi
|
||||
test -z "$LD" && AC_MSG_ERROR([no acceptable ld found in \$PATH])
|
||||
AC_LIB_PROG_LD_GNU
|
||||
])
|
||||
|
|
@ -0,0 +1,709 @@
|
|||
# lib-link.m4 serial 13 (gettext-0.17)
|
||||
dnl Copyright (C) 2001-2007 Free Software Foundation, Inc.
|
||||
dnl This file is free software; the Free Software Foundation
|
||||
dnl gives unlimited permission to copy and/or distribute it,
|
||||
dnl with or without modifications, as long as this notice is preserved.
|
||||
|
||||
dnl From Bruno Haible.
|
||||
|
||||
AC_PREREQ(2.54)
|
||||
|
||||
dnl AC_LIB_LINKFLAGS(name [, dependencies]) searches for libname and
|
||||
dnl the libraries corresponding to explicit and implicit dependencies.
|
||||
dnl Sets and AC_SUBSTs the LIB${NAME} and LTLIB${NAME} variables and
|
||||
dnl augments the CPPFLAGS variable.
|
||||
dnl Sets and AC_SUBSTs the LIB${NAME}_PREFIX variable to nonempty if libname
|
||||
dnl was found in ${LIB${NAME}_PREFIX}/$acl_libdirstem.
|
||||
AC_DEFUN([AC_LIB_LINKFLAGS],
|
||||
[
|
||||
AC_REQUIRE([AC_LIB_PREPARE_PREFIX])
|
||||
AC_REQUIRE([AC_LIB_RPATH])
|
||||
define([Name],[translit([$1],[./-], [___])])
|
||||
define([NAME],[translit([$1],[abcdefghijklmnopqrstuvwxyz./-],
|
||||
[ABCDEFGHIJKLMNOPQRSTUVWXYZ___])])
|
||||
AC_CACHE_CHECK([how to link with lib[]$1], [ac_cv_lib[]Name[]_libs], [
|
||||
AC_LIB_LINKFLAGS_BODY([$1], [$2])
|
||||
ac_cv_lib[]Name[]_libs="$LIB[]NAME"
|
||||
ac_cv_lib[]Name[]_ltlibs="$LTLIB[]NAME"
|
||||
ac_cv_lib[]Name[]_cppflags="$INC[]NAME"
|
||||
ac_cv_lib[]Name[]_prefix="$LIB[]NAME[]_PREFIX"
|
||||
])
|
||||
LIB[]NAME="$ac_cv_lib[]Name[]_libs"
|
||||
LTLIB[]NAME="$ac_cv_lib[]Name[]_ltlibs"
|
||||
INC[]NAME="$ac_cv_lib[]Name[]_cppflags"
|
||||
LIB[]NAME[]_PREFIX="$ac_cv_lib[]Name[]_prefix"
|
||||
AC_LIB_APPENDTOVAR([CPPFLAGS], [$INC]NAME)
|
||||
AC_SUBST([LIB]NAME)
|
||||
AC_SUBST([LTLIB]NAME)
|
||||
AC_SUBST([LIB]NAME[_PREFIX])
|
||||
dnl Also set HAVE_LIB[]NAME so that AC_LIB_HAVE_LINKFLAGS can reuse the
|
||||
dnl results of this search when this library appears as a dependency.
|
||||
HAVE_LIB[]NAME=yes
|
||||
undefine([Name])
|
||||
undefine([NAME])
|
||||
])
|
||||
|
||||
dnl AC_LIB_HAVE_LINKFLAGS(name, dependencies, includes, testcode)
|
||||
dnl searches for libname and the libraries corresponding to explicit and
|
||||
dnl implicit dependencies, together with the specified include files and
|
||||
dnl the ability to compile and link the specified testcode. If found, it
|
||||
dnl sets and AC_SUBSTs HAVE_LIB${NAME}=yes and the LIB${NAME} and
|
||||
dnl LTLIB${NAME} variables and augments the CPPFLAGS variable, and
|
||||
dnl #defines HAVE_LIB${NAME} to 1. Otherwise, it sets and AC_SUBSTs
|
||||
dnl HAVE_LIB${NAME}=no and LIB${NAME} and LTLIB${NAME} to empty.
|
||||
dnl Sets and AC_SUBSTs the LIB${NAME}_PREFIX variable to nonempty if libname
|
||||
dnl was found in ${LIB${NAME}_PREFIX}/$acl_libdirstem.
|
||||
AC_DEFUN([AC_LIB_HAVE_LINKFLAGS],
|
||||
[
|
||||
AC_REQUIRE([AC_LIB_PREPARE_PREFIX])
|
||||
AC_REQUIRE([AC_LIB_RPATH])
|
||||
define([Name],[translit([$1],[./-], [___])])
|
||||
define([NAME],[translit([$1],[abcdefghijklmnopqrstuvwxyz./-],
|
||||
[ABCDEFGHIJKLMNOPQRSTUVWXYZ___])])
|
||||
|
||||
dnl Search for lib[]Name and define LIB[]NAME, LTLIB[]NAME and INC[]NAME
|
||||
dnl accordingly.
|
||||
AC_LIB_LINKFLAGS_BODY([$1], [$2])
|
||||
|
||||
dnl Add $INC[]NAME to CPPFLAGS before performing the following checks,
|
||||
dnl because if the user has installed lib[]Name and not disabled its use
|
||||
dnl via --without-lib[]Name-prefix, he wants to use it.
|
||||
ac_save_CPPFLAGS="$CPPFLAGS"
|
||||
AC_LIB_APPENDTOVAR([CPPFLAGS], [$INC]NAME)
|
||||
|
||||
AC_CACHE_CHECK([for lib[]$1], [ac_cv_lib[]Name], [
|
||||
ac_save_LIBS="$LIBS"
|
||||
LIBS="$LIBS $LIB[]NAME"
|
||||
AC_TRY_LINK([$3], [$4], [ac_cv_lib[]Name=yes], [ac_cv_lib[]Name=no])
|
||||
LIBS="$ac_save_LIBS"
|
||||
])
|
||||
if test "$ac_cv_lib[]Name" = yes; then
|
||||
HAVE_LIB[]NAME=yes
|
||||
AC_DEFINE([HAVE_LIB]NAME, 1, [Define if you have the $1 library.])
|
||||
AC_MSG_CHECKING([how to link with lib[]$1])
|
||||
AC_MSG_RESULT([$LIB[]NAME])
|
||||
else
|
||||
HAVE_LIB[]NAME=no
|
||||
dnl If $LIB[]NAME didn't lead to a usable library, we don't need
|
||||
dnl $INC[]NAME either.
|
||||
CPPFLAGS="$ac_save_CPPFLAGS"
|
||||
LIB[]NAME=
|
||||
LTLIB[]NAME=
|
||||
LIB[]NAME[]_PREFIX=
|
||||
fi
|
||||
AC_SUBST([HAVE_LIB]NAME)
|
||||
AC_SUBST([LIB]NAME)
|
||||
AC_SUBST([LTLIB]NAME)
|
||||
AC_SUBST([LIB]NAME[_PREFIX])
|
||||
undefine([Name])
|
||||
undefine([NAME])
|
||||
])
|
||||
|
||||
dnl Determine the platform dependent parameters needed to use rpath:
|
||||
dnl acl_libext,
|
||||
dnl acl_shlibext,
|
||||
dnl acl_hardcode_libdir_flag_spec,
|
||||
dnl acl_hardcode_libdir_separator,
|
||||
dnl acl_hardcode_direct,
|
||||
dnl acl_hardcode_minus_L.
|
||||
AC_DEFUN([AC_LIB_RPATH],
|
||||
[
|
||||
dnl Tell automake >= 1.10 to complain if config.rpath is missing.
|
||||
m4_ifdef([AC_REQUIRE_AUX_FILE], [AC_REQUIRE_AUX_FILE([config.rpath])])
|
||||
AC_REQUIRE([AC_PROG_CC]) dnl we use $CC, $GCC, $LDFLAGS
|
||||
AC_REQUIRE([AC_LIB_PROG_LD]) dnl we use $LD, $with_gnu_ld
|
||||
AC_REQUIRE([AC_CANONICAL_HOST]) dnl we use $host
|
||||
AC_REQUIRE([AC_CONFIG_AUX_DIR_DEFAULT]) dnl we use $ac_aux_dir
|
||||
AC_CACHE_CHECK([for shared library run path origin], acl_cv_rpath, [
|
||||
CC="$CC" GCC="$GCC" LDFLAGS="$LDFLAGS" LD="$LD" with_gnu_ld="$with_gnu_ld" \
|
||||
${CONFIG_SHELL-/bin/sh} "$ac_aux_dir/config.rpath" "$host" > conftest.sh
|
||||
. ./conftest.sh
|
||||
rm -f ./conftest.sh
|
||||
acl_cv_rpath=done
|
||||
])
|
||||
wl="$acl_cv_wl"
|
||||
acl_libext="$acl_cv_libext"
|
||||
acl_shlibext="$acl_cv_shlibext"
|
||||
acl_libname_spec="$acl_cv_libname_spec"
|
||||
acl_library_names_spec="$acl_cv_library_names_spec"
|
||||
acl_hardcode_libdir_flag_spec="$acl_cv_hardcode_libdir_flag_spec"
|
||||
acl_hardcode_libdir_separator="$acl_cv_hardcode_libdir_separator"
|
||||
acl_hardcode_direct="$acl_cv_hardcode_direct"
|
||||
acl_hardcode_minus_L="$acl_cv_hardcode_minus_L"
|
||||
dnl Determine whether the user wants rpath handling at all.
|
||||
AC_ARG_ENABLE(rpath,
|
||||
[ --disable-rpath do not hardcode runtime library paths],
|
||||
:, enable_rpath=yes)
|
||||
])
|
||||
|
||||
dnl AC_LIB_LINKFLAGS_BODY(name [, dependencies]) searches for libname and
|
||||
dnl the libraries corresponding to explicit and implicit dependencies.
|
||||
dnl Sets the LIB${NAME}, LTLIB${NAME} and INC${NAME} variables.
|
||||
dnl Also, sets the LIB${NAME}_PREFIX variable to nonempty if libname was found
|
||||
dnl in ${LIB${NAME}_PREFIX}/$acl_libdirstem.
|
||||
AC_DEFUN([AC_LIB_LINKFLAGS_BODY],
|
||||
[
|
||||
AC_REQUIRE([AC_LIB_PREPARE_MULTILIB])
|
||||
define([NAME],[translit([$1],[abcdefghijklmnopqrstuvwxyz./-],
|
||||
[ABCDEFGHIJKLMNOPQRSTUVWXYZ___])])
|
||||
dnl Autoconf >= 2.61 supports dots in --with options.
|
||||
define([N_A_M_E],[m4_if(m4_version_compare(m4_defn([m4_PACKAGE_VERSION]),[2.61]),[-1],[translit([$1],[.],[_])],[$1])])
|
||||
dnl By default, look in $includedir and $libdir.
|
||||
use_additional=yes
|
||||
AC_LIB_WITH_FINAL_PREFIX([
|
||||
eval additional_includedir=\"$includedir\"
|
||||
eval additional_libdir=\"$libdir\"
|
||||
])
|
||||
AC_LIB_ARG_WITH([lib]N_A_M_E[-prefix],
|
||||
[ --with-lib]N_A_M_E[-prefix[=DIR] search for lib$1 in DIR/include and DIR/lib
|
||||
--without-lib]N_A_M_E[-prefix don't search for lib$1 in includedir and libdir],
|
||||
[
|
||||
if test "X$withval" = "Xno"; then
|
||||
use_additional=no
|
||||
else
|
||||
if test "X$withval" = "X"; then
|
||||
AC_LIB_WITH_FINAL_PREFIX([
|
||||
eval additional_includedir=\"$includedir\"
|
||||
eval additional_libdir=\"$libdir\"
|
||||
])
|
||||
else
|
||||
additional_includedir="$withval/include"
|
||||
additional_libdir="$withval/$acl_libdirstem"
|
||||
fi
|
||||
fi
|
||||
])
|
||||
dnl Search the library and its dependencies in $additional_libdir and
|
||||
dnl $LDFLAGS. Using breadth-first-seach.
|
||||
LIB[]NAME=
|
||||
LTLIB[]NAME=
|
||||
INC[]NAME=
|
||||
LIB[]NAME[]_PREFIX=
|
||||
rpathdirs=
|
||||
ltrpathdirs=
|
||||
names_already_handled=
|
||||
names_next_round='$1 $2'
|
||||
while test -n "$names_next_round"; do
|
||||
names_this_round="$names_next_round"
|
||||
names_next_round=
|
||||
for name in $names_this_round; do
|
||||
already_handled=
|
||||
for n in $names_already_handled; do
|
||||
if test "$n" = "$name"; then
|
||||
already_handled=yes
|
||||
break
|
||||
fi
|
||||
done
|
||||
if test -z "$already_handled"; then
|
||||
names_already_handled="$names_already_handled $name"
|
||||
dnl See if it was already located by an earlier AC_LIB_LINKFLAGS
|
||||
dnl or AC_LIB_HAVE_LINKFLAGS call.
|
||||
uppername=`echo "$name" | sed -e 'y|abcdefghijklmnopqrstuvwxyz./-|ABCDEFGHIJKLMNOPQRSTUVWXYZ___|'`
|
||||
eval value=\"\$HAVE_LIB$uppername\"
|
||||
if test -n "$value"; then
|
||||
if test "$value" = yes; then
|
||||
eval value=\"\$LIB$uppername\"
|
||||
test -z "$value" || LIB[]NAME="${LIB[]NAME}${LIB[]NAME:+ }$value"
|
||||
eval value=\"\$LTLIB$uppername\"
|
||||
test -z "$value" || LTLIB[]NAME="${LTLIB[]NAME}${LTLIB[]NAME:+ }$value"
|
||||
else
|
||||
dnl An earlier call to AC_LIB_HAVE_LINKFLAGS has determined
|
||||
dnl that this library doesn't exist. So just drop it.
|
||||
:
|
||||
fi
|
||||
else
|
||||
dnl Search the library lib$name in $additional_libdir and $LDFLAGS
|
||||
dnl and the already constructed $LIBNAME/$LTLIBNAME.
|
||||
found_dir=
|
||||
found_la=
|
||||
found_so=
|
||||
found_a=
|
||||
eval libname=\"$acl_libname_spec\" # typically: libname=lib$name
|
||||
if test -n "$acl_shlibext"; then
|
||||
shrext=".$acl_shlibext" # typically: shrext=.so
|
||||
else
|
||||
shrext=
|
||||
fi
|
||||
if test $use_additional = yes; then
|
||||
dir="$additional_libdir"
|
||||
dnl The same code as in the loop below:
|
||||
dnl First look for a shared library.
|
||||
if test -n "$acl_shlibext"; then
|
||||
if test -f "$dir/$libname$shrext"; then
|
||||
found_dir="$dir"
|
||||
found_so="$dir/$libname$shrext"
|
||||
else
|
||||
if test "$acl_library_names_spec" = '$libname$shrext$versuffix'; then
|
||||
ver=`(cd "$dir" && \
|
||||
for f in "$libname$shrext".*; do echo "$f"; done \
|
||||
| sed -e "s,^$libname$shrext\\\\.,," \
|
||||
| sort -t '.' -n -r -k1,1 -k2,2 -k3,3 -k4,4 -k5,5 \
|
||||
| sed 1q ) 2>/dev/null`
|
||||
if test -n "$ver" && test -f "$dir/$libname$shrext.$ver"; then
|
||||
found_dir="$dir"
|
||||
found_so="$dir/$libname$shrext.$ver"
|
||||
fi
|
||||
else
|
||||
eval library_names=\"$acl_library_names_spec\"
|
||||
for f in $library_names; do
|
||||
if test -f "$dir/$f"; then
|
||||
found_dir="$dir"
|
||||
found_so="$dir/$f"
|
||||
break
|
||||
fi
|
||||
done
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
dnl Then look for a static library.
|
||||
if test "X$found_dir" = "X"; then
|
||||
if test -f "$dir/$libname.$acl_libext"; then
|
||||
found_dir="$dir"
|
||||
found_a="$dir/$libname.$acl_libext"
|
||||
fi
|
||||
fi
|
||||
if test "X$found_dir" != "X"; then
|
||||
if test -f "$dir/$libname.la"; then
|
||||
found_la="$dir/$libname.la"
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
if test "X$found_dir" = "X"; then
|
||||
for x in $LDFLAGS $LTLIB[]NAME; do
|
||||
AC_LIB_WITH_FINAL_PREFIX([eval x=\"$x\"])
|
||||
case "$x" in
|
||||
-L*)
|
||||
dir=`echo "X$x" | sed -e 's/^X-L//'`
|
||||
dnl First look for a shared library.
|
||||
if test -n "$acl_shlibext"; then
|
||||
if test -f "$dir/$libname$shrext"; then
|
||||
found_dir="$dir"
|
||||
found_so="$dir/$libname$shrext"
|
||||
else
|
||||
if test "$acl_library_names_spec" = '$libname$shrext$versuffix'; then
|
||||
ver=`(cd "$dir" && \
|
||||
for f in "$libname$shrext".*; do echo "$f"; done \
|
||||
| sed -e "s,^$libname$shrext\\\\.,," \
|
||||
| sort -t '.' -n -r -k1,1 -k2,2 -k3,3 -k4,4 -k5,5 \
|
||||
| sed 1q ) 2>/dev/null`
|
||||
if test -n "$ver" && test -f "$dir/$libname$shrext.$ver"; then
|
||||
found_dir="$dir"
|
||||
found_so="$dir/$libname$shrext.$ver"
|
||||
fi
|
||||
else
|
||||
eval library_names=\"$acl_library_names_spec\"
|
||||
for f in $library_names; do
|
||||
if test -f "$dir/$f"; then
|
||||
found_dir="$dir"
|
||||
found_so="$dir/$f"
|
||||
break
|
||||
fi
|
||||
done
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
dnl Then look for a static library.
|
||||
if test "X$found_dir" = "X"; then
|
||||
if test -f "$dir/$libname.$acl_libext"; then
|
||||
found_dir="$dir"
|
||||
found_a="$dir/$libname.$acl_libext"
|
||||
fi
|
||||
fi
|
||||
if test "X$found_dir" != "X"; then
|
||||
if test -f "$dir/$libname.la"; then
|
||||
found_la="$dir/$libname.la"
|
||||
fi
|
||||
fi
|
||||
;;
|
||||
esac
|
||||
if test "X$found_dir" != "X"; then
|
||||
break
|
||||
fi
|
||||
done
|
||||
fi
|
||||
if test "X$found_dir" != "X"; then
|
||||
dnl Found the library.
|
||||
LTLIB[]NAME="${LTLIB[]NAME}${LTLIB[]NAME:+ }-L$found_dir -l$name"
|
||||
if test "X$found_so" != "X"; then
|
||||
dnl Linking with a shared library. We attempt to hardcode its
|
||||
dnl directory into the executable's runpath, unless it's the
|
||||
dnl standard /usr/lib.
|
||||
if test "$enable_rpath" = no || test "X$found_dir" = "X/usr/$acl_libdirstem"; then
|
||||
dnl No hardcoding is needed.
|
||||
LIB[]NAME="${LIB[]NAME}${LIB[]NAME:+ }$found_so"
|
||||
else
|
||||
dnl Use an explicit option to hardcode DIR into the resulting
|
||||
dnl binary.
|
||||
dnl Potentially add DIR to ltrpathdirs.
|
||||
dnl The ltrpathdirs will be appended to $LTLIBNAME at the end.
|
||||
haveit=
|
||||
for x in $ltrpathdirs; do
|
||||
if test "X$x" = "X$found_dir"; then
|
||||
haveit=yes
|
||||
break
|
||||
fi
|
||||
done
|
||||
if test -z "$haveit"; then
|
||||
ltrpathdirs="$ltrpathdirs $found_dir"
|
||||
fi
|
||||
dnl The hardcoding into $LIBNAME is system dependent.
|
||||
if test "$acl_hardcode_direct" = yes; then
|
||||
dnl Using DIR/libNAME.so during linking hardcodes DIR into the
|
||||
dnl resulting binary.
|
||||
LIB[]NAME="${LIB[]NAME}${LIB[]NAME:+ }$found_so"
|
||||
else
|
||||
if test -n "$acl_hardcode_libdir_flag_spec" && test "$acl_hardcode_minus_L" = no; then
|
||||
dnl Use an explicit option to hardcode DIR into the resulting
|
||||
dnl binary.
|
||||
LIB[]NAME="${LIB[]NAME}${LIB[]NAME:+ }$found_so"
|
||||
dnl Potentially add DIR to rpathdirs.
|
||||
dnl The rpathdirs will be appended to $LIBNAME at the end.
|
||||
haveit=
|
||||
for x in $rpathdirs; do
|
||||
if test "X$x" = "X$found_dir"; then
|
||||
haveit=yes
|
||||
break
|
||||
fi
|
||||
done
|
||||
if test -z "$haveit"; then
|
||||
rpathdirs="$rpathdirs $found_dir"
|
||||
fi
|
||||
else
|
||||
dnl Rely on "-L$found_dir".
|
||||
dnl But don't add it if it's already contained in the LDFLAGS
|
||||
dnl or the already constructed $LIBNAME
|
||||
haveit=
|
||||
for x in $LDFLAGS $LIB[]NAME; do
|
||||
AC_LIB_WITH_FINAL_PREFIX([eval x=\"$x\"])
|
||||
if test "X$x" = "X-L$found_dir"; then
|
||||
haveit=yes
|
||||
break
|
||||
fi
|
||||
done
|
||||
if test -z "$haveit"; then
|
||||
LIB[]NAME="${LIB[]NAME}${LIB[]NAME:+ }-L$found_dir"
|
||||
fi
|
||||
if test "$acl_hardcode_minus_L" != no; then
|
||||
dnl FIXME: Not sure whether we should use
|
||||
dnl "-L$found_dir -l$name" or "-L$found_dir $found_so"
|
||||
dnl here.
|
||||
LIB[]NAME="${LIB[]NAME}${LIB[]NAME:+ }$found_so"
|
||||
else
|
||||
dnl We cannot use $acl_hardcode_runpath_var and LD_RUN_PATH
|
||||
dnl here, because this doesn't fit in flags passed to the
|
||||
dnl compiler. So give up. No hardcoding. This affects only
|
||||
dnl very old systems.
|
||||
dnl FIXME: Not sure whether we should use
|
||||
dnl "-L$found_dir -l$name" or "-L$found_dir $found_so"
|
||||
dnl here.
|
||||
LIB[]NAME="${LIB[]NAME}${LIB[]NAME:+ }-l$name"
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
else
|
||||
if test "X$found_a" != "X"; then
|
||||
dnl Linking with a static library.
|
||||
LIB[]NAME="${LIB[]NAME}${LIB[]NAME:+ }$found_a"
|
||||
else
|
||||
dnl We shouldn't come here, but anyway it's good to have a
|
||||
dnl fallback.
|
||||
LIB[]NAME="${LIB[]NAME}${LIB[]NAME:+ }-L$found_dir -l$name"
|
||||
fi
|
||||
fi
|
||||
dnl Assume the include files are nearby.
|
||||
additional_includedir=
|
||||
case "$found_dir" in
|
||||
*/$acl_libdirstem | */$acl_libdirstem/)
|
||||
basedir=`echo "X$found_dir" | sed -e 's,^X,,' -e "s,/$acl_libdirstem/"'*$,,'`
|
||||
LIB[]NAME[]_PREFIX="$basedir"
|
||||
additional_includedir="$basedir/include"
|
||||
;;
|
||||
esac
|
||||
if test "X$additional_includedir" != "X"; then
|
||||
dnl Potentially add $additional_includedir to $INCNAME.
|
||||
dnl But don't add it
|
||||
dnl 1. if it's the standard /usr/include,
|
||||
dnl 2. if it's /usr/local/include and we are using GCC on Linux,
|
||||
dnl 3. if it's already present in $CPPFLAGS or the already
|
||||
dnl constructed $INCNAME,
|
||||
dnl 4. if it doesn't exist as a directory.
|
||||
if test "X$additional_includedir" != "X/usr/include"; then
|
||||
haveit=
|
||||
if test "X$additional_includedir" = "X/usr/local/include"; then
|
||||
if test -n "$GCC"; then
|
||||
case $host_os in
|
||||
linux* | gnu* | k*bsd*-gnu) haveit=yes;;
|
||||
esac
|
||||
fi
|
||||
fi
|
||||
if test -z "$haveit"; then
|
||||
for x in $CPPFLAGS $INC[]NAME; do
|
||||
AC_LIB_WITH_FINAL_PREFIX([eval x=\"$x\"])
|
||||
if test "X$x" = "X-I$additional_includedir"; then
|
||||
haveit=yes
|
||||
break
|
||||
fi
|
||||
done
|
||||
if test -z "$haveit"; then
|
||||
if test -d "$additional_includedir"; then
|
||||
dnl Really add $additional_includedir to $INCNAME.
|
||||
INC[]NAME="${INC[]NAME}${INC[]NAME:+ }-I$additional_includedir"
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
dnl Look for dependencies.
|
||||
if test -n "$found_la"; then
|
||||
dnl Read the .la file. It defines the variables
|
||||
dnl dlname, library_names, old_library, dependency_libs, current,
|
||||
dnl age, revision, installed, dlopen, dlpreopen, libdir.
|
||||
save_libdir="$libdir"
|
||||
case "$found_la" in
|
||||
*/* | *\\*) . "$found_la" ;;
|
||||
*) . "./$found_la" ;;
|
||||
esac
|
||||
libdir="$save_libdir"
|
||||
dnl We use only dependency_libs.
|
||||
for dep in $dependency_libs; do
|
||||
case "$dep" in
|
||||
-L*)
|
||||
additional_libdir=`echo "X$dep" | sed -e 's/^X-L//'`
|
||||
dnl Potentially add $additional_libdir to $LIBNAME and $LTLIBNAME.
|
||||
dnl But don't add it
|
||||
dnl 1. if it's the standard /usr/lib,
|
||||
dnl 2. if it's /usr/local/lib and we are using GCC on Linux,
|
||||
dnl 3. if it's already present in $LDFLAGS or the already
|
||||
dnl constructed $LIBNAME,
|
||||
dnl 4. if it doesn't exist as a directory.
|
||||
if test "X$additional_libdir" != "X/usr/$acl_libdirstem"; then
|
||||
haveit=
|
||||
if test "X$additional_libdir" = "X/usr/local/$acl_libdirstem"; then
|
||||
if test -n "$GCC"; then
|
||||
case $host_os in
|
||||
linux* | gnu* | k*bsd*-gnu) haveit=yes;;
|
||||
esac
|
||||
fi
|
||||
fi
|
||||
if test -z "$haveit"; then
|
||||
haveit=
|
||||
for x in $LDFLAGS $LIB[]NAME; do
|
||||
AC_LIB_WITH_FINAL_PREFIX([eval x=\"$x\"])
|
||||
if test "X$x" = "X-L$additional_libdir"; then
|
||||
haveit=yes
|
||||
break
|
||||
fi
|
||||
done
|
||||
if test -z "$haveit"; then
|
||||
if test -d "$additional_libdir"; then
|
||||
dnl Really add $additional_libdir to $LIBNAME.
|
||||
LIB[]NAME="${LIB[]NAME}${LIB[]NAME:+ }-L$additional_libdir"
|
||||
fi
|
||||
fi
|
||||
haveit=
|
||||
for x in $LDFLAGS $LTLIB[]NAME; do
|
||||
AC_LIB_WITH_FINAL_PREFIX([eval x=\"$x\"])
|
||||
if test "X$x" = "X-L$additional_libdir"; then
|
||||
haveit=yes
|
||||
break
|
||||
fi
|
||||
done
|
||||
if test -z "$haveit"; then
|
||||
if test -d "$additional_libdir"; then
|
||||
dnl Really add $additional_libdir to $LTLIBNAME.
|
||||
LTLIB[]NAME="${LTLIB[]NAME}${LTLIB[]NAME:+ }-L$additional_libdir"
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
;;
|
||||
-R*)
|
||||
dir=`echo "X$dep" | sed -e 's/^X-R//'`
|
||||
if test "$enable_rpath" != no; then
|
||||
dnl Potentially add DIR to rpathdirs.
|
||||
dnl The rpathdirs will be appended to $LIBNAME at the end.
|
||||
haveit=
|
||||
for x in $rpathdirs; do
|
||||
if test "X$x" = "X$dir"; then
|
||||
haveit=yes
|
||||
break
|
||||
fi
|
||||
done
|
||||
if test -z "$haveit"; then
|
||||
rpathdirs="$rpathdirs $dir"
|
||||
fi
|
||||
dnl Potentially add DIR to ltrpathdirs.
|
||||
dnl The ltrpathdirs will be appended to $LTLIBNAME at the end.
|
||||
haveit=
|
||||
for x in $ltrpathdirs; do
|
||||
if test "X$x" = "X$dir"; then
|
||||
haveit=yes
|
||||
break
|
||||
fi
|
||||
done
|
||||
if test -z "$haveit"; then
|
||||
ltrpathdirs="$ltrpathdirs $dir"
|
||||
fi
|
||||
fi
|
||||
;;
|
||||
-l*)
|
||||
dnl Handle this in the next round.
|
||||
names_next_round="$names_next_round "`echo "X$dep" | sed -e 's/^X-l//'`
|
||||
;;
|
||||
*.la)
|
||||
dnl Handle this in the next round. Throw away the .la's
|
||||
dnl directory; it is already contained in a preceding -L
|
||||
dnl option.
|
||||
names_next_round="$names_next_round "`echo "X$dep" | sed -e 's,^X.*/,,' -e 's,^lib,,' -e 's,\.la$,,'`
|
||||
;;
|
||||
*)
|
||||
dnl Most likely an immediate library name.
|
||||
LIB[]NAME="${LIB[]NAME}${LIB[]NAME:+ }$dep"
|
||||
LTLIB[]NAME="${LTLIB[]NAME}${LTLIB[]NAME:+ }$dep"
|
||||
;;
|
||||
esac
|
||||
done
|
||||
fi
|
||||
else
|
||||
dnl Didn't find the library; assume it is in the system directories
|
||||
dnl known to the linker and runtime loader. (All the system
|
||||
dnl directories known to the linker should also be known to the
|
||||
dnl runtime loader, otherwise the system is severely misconfigured.)
|
||||
LIB[]NAME="${LIB[]NAME}${LIB[]NAME:+ }-l$name"
|
||||
LTLIB[]NAME="${LTLIB[]NAME}${LTLIB[]NAME:+ }-l$name"
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
done
|
||||
done
|
||||
if test "X$rpathdirs" != "X"; then
|
||||
if test -n "$acl_hardcode_libdir_separator"; then
|
||||
dnl Weird platform: only the last -rpath option counts, the user must
|
||||
dnl pass all path elements in one option. We can arrange that for a
|
||||
dnl single library, but not when more than one $LIBNAMEs are used.
|
||||
alldirs=
|
||||
for found_dir in $rpathdirs; do
|
||||
alldirs="${alldirs}${alldirs:+$acl_hardcode_libdir_separator}$found_dir"
|
||||
done
|
||||
dnl Note: acl_hardcode_libdir_flag_spec uses $libdir and $wl.
|
||||
acl_save_libdir="$libdir"
|
||||
libdir="$alldirs"
|
||||
eval flag=\"$acl_hardcode_libdir_flag_spec\"
|
||||
libdir="$acl_save_libdir"
|
||||
LIB[]NAME="${LIB[]NAME}${LIB[]NAME:+ }$flag"
|
||||
else
|
||||
dnl The -rpath options are cumulative.
|
||||
for found_dir in $rpathdirs; do
|
||||
acl_save_libdir="$libdir"
|
||||
libdir="$found_dir"
|
||||
eval flag=\"$acl_hardcode_libdir_flag_spec\"
|
||||
libdir="$acl_save_libdir"
|
||||
LIB[]NAME="${LIB[]NAME}${LIB[]NAME:+ }$flag"
|
||||
done
|
||||
fi
|
||||
fi
|
||||
if test "X$ltrpathdirs" != "X"; then
|
||||
dnl When using libtool, the option that works for both libraries and
|
||||
dnl executables is -R. The -R options are cumulative.
|
||||
for found_dir in $ltrpathdirs; do
|
||||
LTLIB[]NAME="${LTLIB[]NAME}${LTLIB[]NAME:+ }-R$found_dir"
|
||||
done
|
||||
fi
|
||||
])
|
||||
|
||||
dnl AC_LIB_APPENDTOVAR(VAR, CONTENTS) appends the elements of CONTENTS to VAR,
|
||||
dnl unless already present in VAR.
|
||||
dnl Works only for CPPFLAGS, not for LIB* variables because that sometimes
|
||||
dnl contains two or three consecutive elements that belong together.
|
||||
AC_DEFUN([AC_LIB_APPENDTOVAR],
|
||||
[
|
||||
for element in [$2]; do
|
||||
haveit=
|
||||
for x in $[$1]; do
|
||||
AC_LIB_WITH_FINAL_PREFIX([eval x=\"$x\"])
|
||||
if test "X$x" = "X$element"; then
|
||||
haveit=yes
|
||||
break
|
||||
fi
|
||||
done
|
||||
if test -z "$haveit"; then
|
||||
[$1]="${[$1]}${[$1]:+ }$element"
|
||||
fi
|
||||
done
|
||||
])
|
||||
|
||||
dnl For those cases where a variable contains several -L and -l options
|
||||
dnl referring to unknown libraries and directories, this macro determines the
|
||||
dnl necessary additional linker options for the runtime path.
|
||||
dnl AC_LIB_LINKFLAGS_FROM_LIBS([LDADDVAR], [LIBSVALUE], [USE-LIBTOOL])
|
||||
dnl sets LDADDVAR to linker options needed together with LIBSVALUE.
|
||||
dnl If USE-LIBTOOL evaluates to non-empty, linking with libtool is assumed,
|
||||
dnl otherwise linking without libtool is assumed.
|
||||
AC_DEFUN([AC_LIB_LINKFLAGS_FROM_LIBS],
|
||||
[
|
||||
AC_REQUIRE([AC_LIB_RPATH])
|
||||
AC_REQUIRE([AC_LIB_PREPARE_MULTILIB])
|
||||
$1=
|
||||
if test "$enable_rpath" != no; then
|
||||
if test -n "$acl_hardcode_libdir_flag_spec" && test "$acl_hardcode_minus_L" = no; then
|
||||
dnl Use an explicit option to hardcode directories into the resulting
|
||||
dnl binary.
|
||||
rpathdirs=
|
||||
next=
|
||||
for opt in $2; do
|
||||
if test -n "$next"; then
|
||||
dir="$next"
|
||||
dnl No need to hardcode the standard /usr/lib.
|
||||
if test "X$dir" != "X/usr/$acl_libdirstem"; then
|
||||
rpathdirs="$rpathdirs $dir"
|
||||
fi
|
||||
next=
|
||||
else
|
||||
case $opt in
|
||||
-L) next=yes ;;
|
||||
-L*) dir=`echo "X$opt" | sed -e 's,^X-L,,'`
|
||||
dnl No need to hardcode the standard /usr/lib.
|
||||
if test "X$dir" != "X/usr/$acl_libdirstem"; then
|
||||
rpathdirs="$rpathdirs $dir"
|
||||
fi
|
||||
next= ;;
|
||||
*) next= ;;
|
||||
esac
|
||||
fi
|
||||
done
|
||||
if test "X$rpathdirs" != "X"; then
|
||||
if test -n ""$3""; then
|
||||
dnl libtool is used for linking. Use -R options.
|
||||
for dir in $rpathdirs; do
|
||||
$1="${$1}${$1:+ }-R$dir"
|
||||
done
|
||||
else
|
||||
dnl The linker is used for linking directly.
|
||||
if test -n "$acl_hardcode_libdir_separator"; then
|
||||
dnl Weird platform: only the last -rpath option counts, the user
|
||||
dnl must pass all path elements in one option.
|
||||
alldirs=
|
||||
for dir in $rpathdirs; do
|
||||
alldirs="${alldirs}${alldirs:+$acl_hardcode_libdir_separator}$dir"
|
||||
done
|
||||
acl_save_libdir="$libdir"
|
||||
libdir="$alldirs"
|
||||
eval flag=\"$acl_hardcode_libdir_flag_spec\"
|
||||
libdir="$acl_save_libdir"
|
||||
$1="$flag"
|
||||
else
|
||||
dnl The -rpath options are cumulative.
|
||||
for dir in $rpathdirs; do
|
||||
acl_save_libdir="$libdir"
|
||||
libdir="$dir"
|
||||
eval flag=\"$acl_hardcode_libdir_flag_spec\"
|
||||
libdir="$acl_save_libdir"
|
||||
$1="${$1}${$1:+ }$flag"
|
||||
done
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
AC_SUBST([$1])
|
||||
])
|
||||
|
|
@ -0,0 +1,185 @@
|
|||
# lib-prefix.m4 serial 5 (gettext-0.15)
|
||||
dnl Copyright (C) 2001-2005 Free Software Foundation, Inc.
|
||||
dnl This file is free software; the Free Software Foundation
|
||||
dnl gives unlimited permission to copy and/or distribute it,
|
||||
dnl with or without modifications, as long as this notice is preserved.
|
||||
|
||||
dnl From Bruno Haible.
|
||||
|
||||
dnl AC_LIB_ARG_WITH is synonymous to AC_ARG_WITH in autoconf-2.13, and
|
||||
dnl similar to AC_ARG_WITH in autoconf 2.52...2.57 except that is doesn't
|
||||
dnl require excessive bracketing.
|
||||
ifdef([AC_HELP_STRING],
|
||||
[AC_DEFUN([AC_LIB_ARG_WITH], [AC_ARG_WITH([$1],[[$2]],[$3],[$4])])],
|
||||
[AC_DEFUN([AC_][LIB_ARG_WITH], [AC_ARG_WITH([$1],[$2],[$3],[$4])])])
|
||||
|
||||
dnl AC_LIB_PREFIX adds to the CPPFLAGS and LDFLAGS the flags that are needed
|
||||
dnl to access previously installed libraries. The basic assumption is that
|
||||
dnl a user will want packages to use other packages he previously installed
|
||||
dnl with the same --prefix option.
|
||||
dnl This macro is not needed if only AC_LIB_LINKFLAGS is used to locate
|
||||
dnl libraries, but is otherwise very convenient.
|
||||
AC_DEFUN([AC_LIB_PREFIX],
|
||||
[
|
||||
AC_BEFORE([$0], [AC_LIB_LINKFLAGS])
|
||||
AC_REQUIRE([AC_PROG_CC])
|
||||
AC_REQUIRE([AC_CANONICAL_HOST])
|
||||
AC_REQUIRE([AC_LIB_PREPARE_MULTILIB])
|
||||
AC_REQUIRE([AC_LIB_PREPARE_PREFIX])
|
||||
dnl By default, look in $includedir and $libdir.
|
||||
use_additional=yes
|
||||
AC_LIB_WITH_FINAL_PREFIX([
|
||||
eval additional_includedir=\"$includedir\"
|
||||
eval additional_libdir=\"$libdir\"
|
||||
])
|
||||
AC_LIB_ARG_WITH([lib-prefix],
|
||||
[ --with-lib-prefix[=DIR] search for libraries in DIR/include and DIR/lib
|
||||
--without-lib-prefix don't search for libraries in includedir and libdir],
|
||||
[
|
||||
if test "X$withval" = "Xno"; then
|
||||
use_additional=no
|
||||
else
|
||||
if test "X$withval" = "X"; then
|
||||
AC_LIB_WITH_FINAL_PREFIX([
|
||||
eval additional_includedir=\"$includedir\"
|
||||
eval additional_libdir=\"$libdir\"
|
||||
])
|
||||
else
|
||||
additional_includedir="$withval/include"
|
||||
additional_libdir="$withval/$acl_libdirstem"
|
||||
fi
|
||||
fi
|
||||
])
|
||||
if test $use_additional = yes; then
|
||||
dnl Potentially add $additional_includedir to $CPPFLAGS.
|
||||
dnl But don't add it
|
||||
dnl 1. if it's the standard /usr/include,
|
||||
dnl 2. if it's already present in $CPPFLAGS,
|
||||
dnl 3. if it's /usr/local/include and we are using GCC on Linux,
|
||||
dnl 4. if it doesn't exist as a directory.
|
||||
if test "X$additional_includedir" != "X/usr/include"; then
|
||||
haveit=
|
||||
for x in $CPPFLAGS; do
|
||||
AC_LIB_WITH_FINAL_PREFIX([eval x=\"$x\"])
|
||||
if test "X$x" = "X-I$additional_includedir"; then
|
||||
haveit=yes
|
||||
break
|
||||
fi
|
||||
done
|
||||
if test -z "$haveit"; then
|
||||
if test "X$additional_includedir" = "X/usr/local/include"; then
|
||||
if test -n "$GCC"; then
|
||||
case $host_os in
|
||||
linux* | gnu* | k*bsd*-gnu) haveit=yes;;
|
||||
esac
|
||||
fi
|
||||
fi
|
||||
if test -z "$haveit"; then
|
||||
if test -d "$additional_includedir"; then
|
||||
dnl Really add $additional_includedir to $CPPFLAGS.
|
||||
CPPFLAGS="${CPPFLAGS}${CPPFLAGS:+ }-I$additional_includedir"
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
dnl Potentially add $additional_libdir to $LDFLAGS.
|
||||
dnl But don't add it
|
||||
dnl 1. if it's the standard /usr/lib,
|
||||
dnl 2. if it's already present in $LDFLAGS,
|
||||
dnl 3. if it's /usr/local/lib and we are using GCC on Linux,
|
||||
dnl 4. if it doesn't exist as a directory.
|
||||
if test "X$additional_libdir" != "X/usr/$acl_libdirstem"; then
|
||||
haveit=
|
||||
for x in $LDFLAGS; do
|
||||
AC_LIB_WITH_FINAL_PREFIX([eval x=\"$x\"])
|
||||
if test "X$x" = "X-L$additional_libdir"; then
|
||||
haveit=yes
|
||||
break
|
||||
fi
|
||||
done
|
||||
if test -z "$haveit"; then
|
||||
if test "X$additional_libdir" = "X/usr/local/$acl_libdirstem"; then
|
||||
if test -n "$GCC"; then
|
||||
case $host_os in
|
||||
linux*) haveit=yes;;
|
||||
esac
|
||||
fi
|
||||
fi
|
||||
if test -z "$haveit"; then
|
||||
if test -d "$additional_libdir"; then
|
||||
dnl Really add $additional_libdir to $LDFLAGS.
|
||||
LDFLAGS="${LDFLAGS}${LDFLAGS:+ }-L$additional_libdir"
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
])
|
||||
|
||||
dnl AC_LIB_PREPARE_PREFIX creates variables acl_final_prefix,
|
||||
dnl acl_final_exec_prefix, containing the values to which $prefix and
|
||||
dnl $exec_prefix will expand at the end of the configure script.
|
||||
AC_DEFUN([AC_LIB_PREPARE_PREFIX],
|
||||
[
|
||||
dnl Unfortunately, prefix and exec_prefix get only finally determined
|
||||
dnl at the end of configure.
|
||||
if test "X$prefix" = "XNONE"; then
|
||||
acl_final_prefix="$ac_default_prefix"
|
||||
else
|
||||
acl_final_prefix="$prefix"
|
||||
fi
|
||||
if test "X$exec_prefix" = "XNONE"; then
|
||||
acl_final_exec_prefix='${prefix}'
|
||||
else
|
||||
acl_final_exec_prefix="$exec_prefix"
|
||||
fi
|
||||
acl_save_prefix="$prefix"
|
||||
prefix="$acl_final_prefix"
|
||||
eval acl_final_exec_prefix=\"$acl_final_exec_prefix\"
|
||||
prefix="$acl_save_prefix"
|
||||
])
|
||||
|
||||
dnl AC_LIB_WITH_FINAL_PREFIX([statement]) evaluates statement, with the
|
||||
dnl variables prefix and exec_prefix bound to the values they will have
|
||||
dnl at the end of the configure script.
|
||||
AC_DEFUN([AC_LIB_WITH_FINAL_PREFIX],
|
||||
[
|
||||
acl_save_prefix="$prefix"
|
||||
prefix="$acl_final_prefix"
|
||||
acl_save_exec_prefix="$exec_prefix"
|
||||
exec_prefix="$acl_final_exec_prefix"
|
||||
$1
|
||||
exec_prefix="$acl_save_exec_prefix"
|
||||
prefix="$acl_save_prefix"
|
||||
])
|
||||
|
||||
dnl AC_LIB_PREPARE_MULTILIB creates a variable acl_libdirstem, containing
|
||||
dnl the basename of the libdir, either "lib" or "lib64".
|
||||
AC_DEFUN([AC_LIB_PREPARE_MULTILIB],
|
||||
[
|
||||
dnl There is no formal standard regarding lib and lib64. The current
|
||||
dnl practice is that on a system supporting 32-bit and 64-bit instruction
|
||||
dnl sets or ABIs, 64-bit libraries go under $prefix/lib64 and 32-bit
|
||||
dnl libraries go under $prefix/lib. We determine the compiler's default
|
||||
dnl mode by looking at the compiler's library search path. If at least
|
||||
dnl of its elements ends in /lib64 or points to a directory whose absolute
|
||||
dnl pathname ends in /lib64, we assume a 64-bit ABI. Otherwise we use the
|
||||
dnl default, namely "lib".
|
||||
acl_libdirstem=lib
|
||||
searchpath=`(LC_ALL=C $CC -print-search-dirs) 2>/dev/null | sed -n -e 's,^libraries: ,,p' | sed -e 's,^=,,'`
|
||||
if test -n "$searchpath"; then
|
||||
acl_save_IFS="${IFS= }"; IFS=":"
|
||||
for searchdir in $searchpath; do
|
||||
if test -d "$searchdir"; then
|
||||
case "$searchdir" in
|
||||
*/lib64/ | */lib64 ) acl_libdirstem=lib64 ;;
|
||||
*) searchdir=`cd "$searchdir" && pwd`
|
||||
case "$searchdir" in
|
||||
*/lib64 ) acl_libdirstem=lib64 ;;
|
||||
esac ;;
|
||||
esac
|
||||
fi
|
||||
done
|
||||
IFS="$acl_save_IFS"
|
||||
fi
|
||||
])
|
||||
|
|
@ -0,0 +1,13 @@
|
|||
# ---------------------------------------------------------------------------
|
||||
# Provide various compatibility macros for older Autoconf machines
|
||||
# Definitions were copied from the Autoconf source code.
|
||||
# ---------------------------------------------------------------------------
|
||||
m4_ifdef([AS_VAR_IF],,m4_define([AS_VAR_IF],
|
||||
[AS_LITERAL_WORD_IF([$1],
|
||||
[AS_IF(m4_ifval([$2], [[test "x$$1" = x[]$2]], [[${$1:+false} :]])],
|
||||
[AS_VAR_COPY([as_val], [$1])
|
||||
AS_IF(m4_ifval([$2], [[test "x$as_val" = x[]$2]], [[${as_val:+false} :]])],
|
||||
[AS_IF(m4_ifval([$2],
|
||||
[[eval test \"x\$"$1"\" = x"_AS_ESCAPE([$2], [`], [\"$])"]],
|
||||
[[eval \${$1:+false} :]])]),
|
||||
[$3], [$4])]))dnl
|
||||
|
|
@ -0,0 +1,138 @@
|
|||
dnl ---------------------------------------------------------------------------
|
||||
dnl Macro: SB_CHECK_MYSQL
|
||||
dnl First check if the MySQL root directory is specified with --with-mysql.
|
||||
dnl Otherwise check for custom MySQL paths in --with-mysql-includes and
|
||||
dnl --with-mysql-libs. If some paths are not specified explicitly, try to get
|
||||
dnl them from mysql_config.
|
||||
dnl ---------------------------------------------------------------------------
|
||||
|
||||
AC_DEFUN([SB_CHECK_MYSQL],[
|
||||
|
||||
AS_IF([test "x$with_mysql" != xno], [
|
||||
|
||||
# Check for custom MySQL root directory
|
||||
if test [ "x$with_mysql" != xyes -a "x$with_mysql" != xno ]
|
||||
then
|
||||
ac_cv_mysql_root=`echo "$with_mysql" | sed -e 's+/$++'`
|
||||
if test [ -d "$ac_cv_mysql_root/include" -a \
|
||||
-d "$ac_cv_mysql_root/libmysql_r" ]
|
||||
then
|
||||
ac_cv_mysql_includes="$ac_cv_mysql_root/include"
|
||||
ac_cv_mysql_libs="$ac_cv_mysql_root/libmysql_r"
|
||||
elif test [ -x "$ac_cv_mysql_root/bin/mysql_config" ]
|
||||
then
|
||||
mysqlconfig="$ac_cv_mysql_root/bin/mysql_config"
|
||||
else
|
||||
AC_MSG_ERROR([invalid MySQL root directory: $ac_cv_mysql_root])
|
||||
fi
|
||||
fi
|
||||
|
||||
# Check for custom includes path
|
||||
if test [ -z "$ac_cv_mysql_includes" ]
|
||||
then
|
||||
AC_ARG_WITH([mysql-includes],
|
||||
AC_HELP_STRING([--with-mysql-includes], [path to MySQL header files]),
|
||||
[ac_cv_mysql_includes=$withval])
|
||||
fi
|
||||
if test [ -n "$ac_cv_mysql_includes" ]
|
||||
then
|
||||
AC_CACHE_CHECK([MySQL includes], [ac_cv_mysql_includes], [ac_cv_mysql_includes=""])
|
||||
MYSQL_CFLAGS="-I$ac_cv_mysql_includes"
|
||||
fi
|
||||
|
||||
# Check for custom library path
|
||||
|
||||
if test [ -z "$ac_cv_mysql_libs" ]
|
||||
then
|
||||
AC_ARG_WITH([mysql-libs],
|
||||
AC_HELP_STRING([--with-mysql-libs], [path to MySQL libraries]),
|
||||
[ac_cv_mysql_libs=$withval])
|
||||
fi
|
||||
if test [ -n "$ac_cv_mysql_libs" ]
|
||||
then
|
||||
# Trim trailing '.libs' if user passed it in --with-mysql-libs option
|
||||
ac_cv_mysql_libs=`echo ${ac_cv_mysql_libs} | sed -e 's/.libs$//' \
|
||||
-e 's+.libs/$++'`
|
||||
AC_CACHE_CHECK([MySQL libraries], [ac_cv_mysql_libs], [ac_cv_mysql_libs=""])
|
||||
save_LDFLAGS="$LDFLAGS"
|
||||
save_LIBS="$LIBS"
|
||||
LDFLAGS="-L$ac_cv_mysql_libs"
|
||||
LIBS=""
|
||||
|
||||
# libmysqlclient_r has been removed in MySQL 5.7
|
||||
AC_SEARCH_LIBS([mysql_real_connect],
|
||||
[mysqlclient_r mysqlclient],
|
||||
[],
|
||||
AC_MSG_ERROR([cannot find MySQL client libraries in $ac_cv_mysql_libs]))
|
||||
|
||||
MYSQL_LIBS="$LDFLAGS $LIBS"
|
||||
LIBS="$save_LIBS"
|
||||
LDFLAGS="$save_LDFLAGS"
|
||||
fi
|
||||
|
||||
# If some path is missing, try to autodetermine with mysql_config
|
||||
if test [ -z "$ac_cv_mysql_includes" -o -z "$ac_cv_mysql_libs" ]
|
||||
then
|
||||
if test [ -z "$mysqlconfig" ]
|
||||
then
|
||||
AC_PATH_PROG(mysqlconfig,mysql_config)
|
||||
fi
|
||||
if test [ -z "$mysqlconfig" ]
|
||||
then
|
||||
AC_MSG_ERROR([mysql_config executable not found
|
||||
********************************************************************************
|
||||
ERROR: cannot find MySQL libraries. If you want to compile with MySQL support,
|
||||
please install the package containing MySQL client libraries and headers.
|
||||
On Debian-based systems the package name is libmysqlclient-dev.
|
||||
On RedHat-based systems, it is mysql-devel.
|
||||
If you have those libraries installed in non-standard locations,
|
||||
you must either specify file locations explicitly using
|
||||
--with-mysql-includes and --with-mysql-libs options, or make sure path to
|
||||
mysql_config is listed in your PATH environment variable. If you want to
|
||||
disable MySQL support, use --without-mysql option.
|
||||
********************************************************************************
|
||||
])
|
||||
else
|
||||
if test [ -z "$ac_cv_mysql_includes" ]
|
||||
then
|
||||
AC_MSG_CHECKING(MySQL C flags)
|
||||
MYSQL_CFLAGS=`${mysqlconfig} --cflags`
|
||||
AC_MSG_RESULT($MYSQL_CFLAGS)
|
||||
fi
|
||||
if test [ -z "$ac_cv_mysql_libs" ]
|
||||
then
|
||||
AC_MSG_CHECKING(MySQL linker flags)
|
||||
MYSQL_LIBS=`${mysqlconfig} --libs_r`
|
||||
AC_MSG_RESULT($MYSQL_LIBS)
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
|
||||
AC_DEFINE([USE_MYSQL], 1,
|
||||
[Define to 1 if you want to compile with MySQL support])
|
||||
|
||||
USE_MYSQL=1
|
||||
AC_SUBST([MYSQL_LIBS])
|
||||
AC_SUBST([MYSQL_CFLAGS])
|
||||
|
||||
AC_MSG_CHECKING([if mysql.h defines MYSQL_OPT_SSL_MODE])
|
||||
|
||||
SAVE_CFLAGS="${CFLAGS}"
|
||||
CFLAGS="${CFLAGS} ${MYSQL_CFLAGS}"
|
||||
AC_COMPILE_IFELSE([AC_LANG_PROGRAM(
|
||||
[[
|
||||
#include <mysql.h>
|
||||
|
||||
enum mysql_option opt = MYSQL_OPT_SSL_MODE;
|
||||
]])], [
|
||||
AC_DEFINE([HAVE_MYSQL_OPT_SSL_MODE], 1,
|
||||
[Define to 1 if mysql.h defines MYSQL_OPT_SSL_MODE])
|
||||
AC_MSG_RESULT([yes])
|
||||
], [AC_MSG_RESULT([no])])
|
||||
])
|
||||
CFLAGS="${SAVE_CFLAGS}"
|
||||
|
||||
|
||||
AM_CONDITIONAL([USE_MYSQL], test "x$with_mysql" != xno)
|
||||
AC_SUBST([USE_MYSQL])
|
||||
])
|
||||
|
|
@ -0,0 +1,99 @@
|
|||
# Copyright (C) 2016-2017 Alexey Kopytov <akopytov@gmail.com>
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation; either version 2 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, write to the Free Software
|
||||
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# Macro: SB_CONCURRENCY_KIT
|
||||
# ---------------------------------------------------------------------------
|
||||
AC_DEFUN([SB_CONCURRENCY_KIT], [
|
||||
|
||||
AC_ARG_WITH([system-ck],
|
||||
AC_HELP_STRING([--with-system-ck],
|
||||
[Use system-provided Concurrency Kit headers and library (requires pkg-config)]),
|
||||
[sb_use_ck="system"],
|
||||
[sb_use_ck="bundled"])
|
||||
|
||||
AC_CACHE_CHECK([whether to build with system or bundled Concurrency Kit],
|
||||
[sb_cv_lib_ck], [
|
||||
AS_IF([test "x$sb_use_ck" = "xsystem"],
|
||||
[
|
||||
sb_cv_lib_ck=[system]
|
||||
], [
|
||||
sb_cv_lib_ck=[bundled]
|
||||
])
|
||||
])
|
||||
|
||||
AS_IF([test "x$sb_cv_lib_ck" = "xsystem"],
|
||||
# let PKG_CHECK_MODULES set CK_CFLAGS and CK_LIBS for system libck
|
||||
[PKG_CHECK_MODULES([CK], [ck])],
|
||||
# Set CK_CFLAGS and CK_LIBS manually for bundled libck
|
||||
[
|
||||
CK_CFLAGS="-I\$(abs_top_builddir)/third_party/concurrency_kit/include"
|
||||
CK_LIBS="\$(abs_top_builddir)/third_party/concurrency_kit/lib/libck.a"
|
||||
|
||||
case $target_cpu in
|
||||
powerpc*|aarch64)
|
||||
# Assume 128-byte cache line on AArch64 and PowerPC
|
||||
CPPFLAGS="${CPPFLAGS} -DCK_MD_CACHELINE=128"
|
||||
;;
|
||||
# Force --platform=i*86 for CK, otherwise its configure script
|
||||
# autodetects target based on 'uname -m' which doesn't work for
|
||||
# cross-compiliation
|
||||
i486*|i586*)
|
||||
CK_CONFIGURE_FLAGS="--platform=i586"
|
||||
;;
|
||||
i686*)
|
||||
CK_CONFIGURE_FLAGS="--platform=i686"
|
||||
;;
|
||||
mips64*)
|
||||
CK_CONFIGURE_FLAGS="--use-cc-builtins"
|
||||
;;
|
||||
esac
|
||||
# Add --enable-lse to CK build flags, if LSE instructions are supported by
|
||||
# the target architecture
|
||||
if test "$cross_compiling" = no -a "$host_cpu" = aarch64; then
|
||||
AC_MSG_CHECKING([whether LSE instructions are supported])
|
||||
AC_COMPILE_IFELSE(
|
||||
[AC_LANG_PROGRAM(,
|
||||
[[
|
||||
unsigned long long d = 1, a = 1;
|
||||
unsigned long long *t = &a;
|
||||
|
||||
__asm__ __volatile__(
|
||||
"stadd %0, [%1];"
|
||||
: "+&r" (d)
|
||||
: "r" (t)
|
||||
: "memory");
|
||||
]])],
|
||||
[
|
||||
CK_CONFIGURE_FLAGS="--enable-lse"
|
||||
AC_MSG_RESULT([yes])
|
||||
],
|
||||
[
|
||||
CK_CONFIGURE_FLAGS=""
|
||||
AC_MSG_RESULT([no])
|
||||
]
|
||||
)
|
||||
|
||||
AC_SUBST([CK_CONFIGURE_FLAGS])
|
||||
fi
|
||||
]
|
||||
)
|
||||
|
||||
AC_DEFINE_UNQUOTED([SB_WITH_CK], ["$sb_use_ck"],
|
||||
[Whether system or bundled Concurrency Ki is used])
|
||||
|
||||
AM_CONDITIONAL([USE_BUNDLED_CK], [test "x$sb_use_ck" = xbundled])
|
||||
])
|
||||
|
|
@ -0,0 +1,72 @@
|
|||
# Copyright (C) 2016 Alexey Kopytov <akopytov@gmail.com>
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation; either version 2 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, write to the Free Software
|
||||
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# Macro: SB_LUAJIT
|
||||
# ---------------------------------------------------------------------------
|
||||
AC_DEFUN([SB_LUAJIT], [
|
||||
|
||||
AC_ARG_WITH([system-luajit],
|
||||
AC_HELP_STRING([--with-system-luajit],
|
||||
[Use system-provided LuaJIT headers and library (requires pkg-config)]),
|
||||
[sb_use_luajit="system"],
|
||||
[sb_use_luajit="bundled"])
|
||||
|
||||
AC_CACHE_CHECK([whether to build with system or bundled LuaJIT],
|
||||
[sb_cv_lib_luajit], [
|
||||
AS_IF([test "x$sb_use_luajit" = "xsystem"],
|
||||
[
|
||||
sb_cv_lib_luajit=[system]
|
||||
], [
|
||||
sb_cv_lib_luajit=[bundled]
|
||||
])
|
||||
])
|
||||
|
||||
AS_IF([test "x$sb_cv_lib_luajit" = "xsystem"],
|
||||
# let PKG_CHECK_MODULES set LUAJIT_CFLAGS and LUAJIT_LIBS for system libluajit
|
||||
[PKG_CHECK_MODULES([LUAJIT], [luajit])],
|
||||
# Set LUAJIT_CFLAGS and LUAJIT_LIBS manually for bundled libluajit
|
||||
[
|
||||
LUAJIT_CFLAGS="-I\$(abs_top_builddir)/third_party/luajit/inc"
|
||||
LUAJIT_LIBS="\$(abs_top_builddir)/third_party/luajit/lib/libluajit-5.1.a"
|
||||
]
|
||||
)
|
||||
|
||||
AC_DEFINE_UNQUOTED([SB_WITH_LUAJIT], ["$sb_use_luajit"],
|
||||
[Whether system or bundled LuaJIT is used])
|
||||
|
||||
AM_CONDITIONAL([USE_BUNDLED_LUAJIT], [test "x$sb_use_luajit" = xbundled])
|
||||
|
||||
AS_CASE([$host_os:$host_cpu],
|
||||
# Add extra flags when building a 64-bit application on OS X,
|
||||
# http://luajit.org/install.html
|
||||
[*darwin*:x86_64],
|
||||
[LUAJIT_LDFLAGS="-pagezero_size 10000 -image_base 100000000"],
|
||||
# -ldl and -rdynamic are required on Linux
|
||||
[*linux*:*],
|
||||
[
|
||||
LUAJIT_LIBS="$LUAJIT_LIBS -ldl"
|
||||
LUAJIT_LDFLAGS="-rdynamic"
|
||||
],
|
||||
# -rdynamic is required on FreeBSD
|
||||
[*freebsd*:*],
|
||||
[
|
||||
LUAJIT_LDFLAGS="-rdynamic"
|
||||
]
|
||||
)
|
||||
|
||||
AC_SUBST([LUAJIT_LDFLAGS])
|
||||
])
|
||||
|
|
@ -0,0 +1,336 @@
|
|||
#! /bin/sh
|
||||
# Common stub for a few missing GNU programs while installing.
|
||||
# Copyright (C) 1996, 1997, 1999, 2000, 2002, 2003 Free Software Foundation, Inc.
|
||||
# Originally by Fran,cois Pinard <pinard@iro.umontreal.ca>, 1996.
|
||||
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation; either version 2, or (at your option)
|
||||
# any later version.
|
||||
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, write to the Free Software
|
||||
# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
|
||||
# 02111-1307, USA.
|
||||
|
||||
# As a special exception to the GNU General Public License, if you
|
||||
# distribute this file as part of a program that contains a
|
||||
# configuration script generated by Autoconf, you may include it under
|
||||
# the same distribution terms that you use for the rest of that program.
|
||||
|
||||
if test $# -eq 0; then
|
||||
echo 1>&2 "Try \`$0 --help' for more information"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
run=:
|
||||
|
||||
# In the cases where this matters, `missing' is being run in the
|
||||
# srcdir already.
|
||||
if test -f configure.ac; then
|
||||
configure_ac=configure.ac
|
||||
else
|
||||
configure_ac=configure.in
|
||||
fi
|
||||
|
||||
case "$1" in
|
||||
--run)
|
||||
# Try to run requested program, and just exit if it succeeds.
|
||||
run=
|
||||
shift
|
||||
"$@" && exit 0
|
||||
;;
|
||||
esac
|
||||
|
||||
# If it does not exist, or fails to run (possibly an outdated version),
|
||||
# try to emulate it.
|
||||
case "$1" in
|
||||
|
||||
-h|--h|--he|--hel|--help)
|
||||
echo "\
|
||||
$0 [OPTION]... PROGRAM [ARGUMENT]...
|
||||
|
||||
Handle \`PROGRAM [ARGUMENT]...' for when PROGRAM is missing, or return an
|
||||
error status if there is no known handling for PROGRAM.
|
||||
|
||||
Options:
|
||||
-h, --help display this help and exit
|
||||
-v, --version output version information and exit
|
||||
--run try to run the given command, and emulate it if it fails
|
||||
|
||||
Supported PROGRAM values:
|
||||
aclocal touch file \`aclocal.m4'
|
||||
autoconf touch file \`configure'
|
||||
autoheader touch file \`config.h.in'
|
||||
automake touch all \`Makefile.in' files
|
||||
bison create \`y.tab.[ch]', if possible, from existing .[ch]
|
||||
flex create \`lex.yy.c', if possible, from existing .c
|
||||
help2man touch the output file
|
||||
lex create \`lex.yy.c', if possible, from existing .c
|
||||
makeinfo touch the output file
|
||||
tar try tar, gnutar, gtar, then tar without non-portable flags
|
||||
yacc create \`y.tab.[ch]', if possible, from existing .[ch]"
|
||||
;;
|
||||
|
||||
-v|--v|--ve|--ver|--vers|--versi|--versio|--version)
|
||||
echo "missing 0.4 - GNU automake"
|
||||
;;
|
||||
|
||||
-*)
|
||||
echo 1>&2 "$0: Unknown \`$1' option"
|
||||
echo 1>&2 "Try \`$0 --help' for more information"
|
||||
exit 1
|
||||
;;
|
||||
|
||||
aclocal*)
|
||||
if test -z "$run" && ($1 --version) > /dev/null 2>&1; then
|
||||
# We have it, but it failed.
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo 1>&2 "\
|
||||
WARNING: \`$1' is missing on your system. You should only need it if
|
||||
you modified \`acinclude.m4' or \`${configure_ac}'. You might want
|
||||
to install the \`Automake' and \`Perl' packages. Grab them from
|
||||
any GNU archive site."
|
||||
touch aclocal.m4
|
||||
;;
|
||||
|
||||
autoconf)
|
||||
if test -z "$run" && ($1 --version) > /dev/null 2>&1; then
|
||||
# We have it, but it failed.
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo 1>&2 "\
|
||||
WARNING: \`$1' is missing on your system. You should only need it if
|
||||
you modified \`${configure_ac}'. You might want to install the
|
||||
\`Autoconf' and \`GNU m4' packages. Grab them from any GNU
|
||||
archive site."
|
||||
touch configure
|
||||
;;
|
||||
|
||||
autoheader)
|
||||
if test -z "$run" && ($1 --version) > /dev/null 2>&1; then
|
||||
# We have it, but it failed.
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo 1>&2 "\
|
||||
WARNING: \`$1' is missing on your system. You should only need it if
|
||||
you modified \`acconfig.h' or \`${configure_ac}'. You might want
|
||||
to install the \`Autoconf' and \`GNU m4' packages. Grab them
|
||||
from any GNU archive site."
|
||||
files=`sed -n 's/^[ ]*A[CM]_CONFIG_HEADER(\([^)]*\)).*/\1/p' ${configure_ac}`
|
||||
test -z "$files" && files="config.h"
|
||||
touch_files=
|
||||
for f in $files; do
|
||||
case "$f" in
|
||||
*:*) touch_files="$touch_files "`echo "$f" |
|
||||
sed -e 's/^[^:]*://' -e 's/:.*//'`;;
|
||||
*) touch_files="$touch_files $f.in";;
|
||||
esac
|
||||
done
|
||||
touch $touch_files
|
||||
;;
|
||||
|
||||
automake*)
|
||||
if test -z "$run" && ($1 --version) > /dev/null 2>&1; then
|
||||
# We have it, but it failed.
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo 1>&2 "\
|
||||
WARNING: \`$1' is missing on your system. You should only need it if
|
||||
you modified \`Makefile.am', \`acinclude.m4' or \`${configure_ac}'.
|
||||
You might want to install the \`Automake' and \`Perl' packages.
|
||||
Grab them from any GNU archive site."
|
||||
find . -type f -name Makefile.am -print |
|
||||
sed 's/\.am$/.in/' |
|
||||
while read f; do touch "$f"; done
|
||||
;;
|
||||
|
||||
autom4te)
|
||||
if test -z "$run" && ($1 --version) > /dev/null 2>&1; then
|
||||
# We have it, but it failed.
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo 1>&2 "\
|
||||
WARNING: \`$1' is needed, and you do not seem to have it handy on your
|
||||
system. You might have modified some files without having the
|
||||
proper tools for further handling them.
|
||||
You can get \`$1' as part of \`Autoconf' from any GNU
|
||||
archive site."
|
||||
|
||||
file=`echo "$*" | sed -n 's/.*--output[ =]*\([^ ]*\).*/\1/p'`
|
||||
test -z "$file" && file=`echo "$*" | sed -n 's/.*-o[ ]*\([^ ]*\).*/\1/p'`
|
||||
if test -f "$file"; then
|
||||
touch $file
|
||||
else
|
||||
test -z "$file" || exec >$file
|
||||
echo "#! /bin/sh"
|
||||
echo "# Created by GNU Automake missing as a replacement of"
|
||||
echo "# $ $@"
|
||||
echo "exit 0"
|
||||
chmod +x $file
|
||||
exit 1
|
||||
fi
|
||||
;;
|
||||
|
||||
bison|yacc)
|
||||
echo 1>&2 "\
|
||||
WARNING: \`$1' is missing on your system. You should only need it if
|
||||
you modified a \`.y' file. You may need the \`Bison' package
|
||||
in order for those modifications to take effect. You can get
|
||||
\`Bison' from any GNU archive site."
|
||||
rm -f y.tab.c y.tab.h
|
||||
if [ $# -ne 1 ]; then
|
||||
eval LASTARG="\${$#}"
|
||||
case "$LASTARG" in
|
||||
*.y)
|
||||
SRCFILE=`echo "$LASTARG" | sed 's/y$/c/'`
|
||||
if [ -f "$SRCFILE" ]; then
|
||||
cp "$SRCFILE" y.tab.c
|
||||
fi
|
||||
SRCFILE=`echo "$LASTARG" | sed 's/y$/h/'`
|
||||
if [ -f "$SRCFILE" ]; then
|
||||
cp "$SRCFILE" y.tab.h
|
||||
fi
|
||||
;;
|
||||
esac
|
||||
fi
|
||||
if [ ! -f y.tab.h ]; then
|
||||
echo >y.tab.h
|
||||
fi
|
||||
if [ ! -f y.tab.c ]; then
|
||||
echo 'main() { return 0; }' >y.tab.c
|
||||
fi
|
||||
;;
|
||||
|
||||
lex|flex)
|
||||
echo 1>&2 "\
|
||||
WARNING: \`$1' is missing on your system. You should only need it if
|
||||
you modified a \`.l' file. You may need the \`Flex' package
|
||||
in order for those modifications to take effect. You can get
|
||||
\`Flex' from any GNU archive site."
|
||||
rm -f lex.yy.c
|
||||
if [ $# -ne 1 ]; then
|
||||
eval LASTARG="\${$#}"
|
||||
case "$LASTARG" in
|
||||
*.l)
|
||||
SRCFILE=`echo "$LASTARG" | sed 's/l$/c/'`
|
||||
if [ -f "$SRCFILE" ]; then
|
||||
cp "$SRCFILE" lex.yy.c
|
||||
fi
|
||||
;;
|
||||
esac
|
||||
fi
|
||||
if [ ! -f lex.yy.c ]; then
|
||||
echo 'main() { return 0; }' >lex.yy.c
|
||||
fi
|
||||
;;
|
||||
|
||||
help2man)
|
||||
if test -z "$run" && ($1 --version) > /dev/null 2>&1; then
|
||||
# We have it, but it failed.
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo 1>&2 "\
|
||||
WARNING: \`$1' is missing on your system. You should only need it if
|
||||
you modified a dependency of a manual page. You may need the
|
||||
\`Help2man' package in order for those modifications to take
|
||||
effect. You can get \`Help2man' from any GNU archive site."
|
||||
|
||||
file=`echo "$*" | sed -n 's/.*-o \([^ ]*\).*/\1/p'`
|
||||
if test -z "$file"; then
|
||||
file=`echo "$*" | sed -n 's/.*--output=\([^ ]*\).*/\1/p'`
|
||||
fi
|
||||
if [ -f "$file" ]; then
|
||||
touch $file
|
||||
else
|
||||
test -z "$file" || exec >$file
|
||||
echo ".ab help2man is required to generate this page"
|
||||
exit 1
|
||||
fi
|
||||
;;
|
||||
|
||||
makeinfo)
|
||||
if test -z "$run" && (makeinfo --version) > /dev/null 2>&1; then
|
||||
# We have makeinfo, but it failed.
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo 1>&2 "\
|
||||
WARNING: \`$1' is missing on your system. You should only need it if
|
||||
you modified a \`.texi' or \`.texinfo' file, or any other file
|
||||
indirectly affecting the aspect of the manual. The spurious
|
||||
call might also be the consequence of using a buggy \`make' (AIX,
|
||||
DU, IRIX). You might want to install the \`Texinfo' package or
|
||||
the \`GNU make' package. Grab either from any GNU archive site."
|
||||
file=`echo "$*" | sed -n 's/.*-o \([^ ]*\).*/\1/p'`
|
||||
if test -z "$file"; then
|
||||
file=`echo "$*" | sed 's/.* \([^ ]*\) *$/\1/'`
|
||||
file=`sed -n '/^@setfilename/ { s/.* \([^ ]*\) *$/\1/; p; q; }' $file`
|
||||
fi
|
||||
touch $file
|
||||
;;
|
||||
|
||||
tar)
|
||||
shift
|
||||
if test -n "$run"; then
|
||||
echo 1>&2 "ERROR: \`tar' requires --run"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# We have already tried tar in the generic part.
|
||||
# Look for gnutar/gtar before invocation to avoid ugly error
|
||||
# messages.
|
||||
if (gnutar --version > /dev/null 2>&1); then
|
||||
gnutar "$@" && exit 0
|
||||
fi
|
||||
if (gtar --version > /dev/null 2>&1); then
|
||||
gtar "$@" && exit 0
|
||||
fi
|
||||
firstarg="$1"
|
||||
if shift; then
|
||||
case "$firstarg" in
|
||||
*o*)
|
||||
firstarg=`echo "$firstarg" | sed s/o//`
|
||||
tar "$firstarg" "$@" && exit 0
|
||||
;;
|
||||
esac
|
||||
case "$firstarg" in
|
||||
*h*)
|
||||
firstarg=`echo "$firstarg" | sed s/h//`
|
||||
tar "$firstarg" "$@" && exit 0
|
||||
;;
|
||||
esac
|
||||
fi
|
||||
|
||||
echo 1>&2 "\
|
||||
WARNING: I can't seem to be able to run \`tar' with the given arguments.
|
||||
You may want to install GNU tar or Free paxutils, or check the
|
||||
command line arguments."
|
||||
exit 1
|
||||
;;
|
||||
|
||||
*)
|
||||
echo 1>&2 "\
|
||||
WARNING: \`$1' is needed, and you do not seem to have it handy on your
|
||||
system. You might have modified some files without having the
|
||||
proper tools for further handling them. Check the \`README' file,
|
||||
it often tells you about the needed prerequisites for installing
|
||||
this package. You may also peek at any GNU archive site, in case
|
||||
some other package would contain this missing \`$1' program."
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
|
||||
exit 0
|
||||
|
|
@ -0,0 +1,111 @@
|
|||
#! /bin/sh
|
||||
# mkinstalldirs --- make directory hierarchy
|
||||
# Author: Noah Friedman <friedman@prep.ai.mit.edu>
|
||||
# Created: 1993-05-16
|
||||
# Public domain
|
||||
|
||||
errstatus=0
|
||||
dirmode=""
|
||||
|
||||
usage="\
|
||||
Usage: mkinstalldirs [-h] [--help] [-m mode] dir ..."
|
||||
|
||||
# process command line arguments
|
||||
while test $# -gt 0 ; do
|
||||
case $1 in
|
||||
-h | --help | --h*) # -h for help
|
||||
echo "$usage" 1>&2
|
||||
exit 0
|
||||
;;
|
||||
-m) # -m PERM arg
|
||||
shift
|
||||
test $# -eq 0 && { echo "$usage" 1>&2; exit 1; }
|
||||
dirmode=$1
|
||||
shift
|
||||
;;
|
||||
--) # stop option processing
|
||||
shift
|
||||
break
|
||||
;;
|
||||
-*) # unknown option
|
||||
echo "$usage" 1>&2
|
||||
exit 1
|
||||
;;
|
||||
*) # first non-opt arg
|
||||
break
|
||||
;;
|
||||
esac
|
||||
done
|
||||
|
||||
for file
|
||||
do
|
||||
if test -d "$file"; then
|
||||
shift
|
||||
else
|
||||
break
|
||||
fi
|
||||
done
|
||||
|
||||
case $# in
|
||||
0) exit 0 ;;
|
||||
esac
|
||||
|
||||
case $dirmode in
|
||||
'')
|
||||
if mkdir -p -- . 2>/dev/null; then
|
||||
echo "mkdir -p -- $*"
|
||||
exec mkdir -p -- "$@"
|
||||
fi
|
||||
;;
|
||||
*)
|
||||
if mkdir -m "$dirmode" -p -- . 2>/dev/null; then
|
||||
echo "mkdir -m $dirmode -p -- $*"
|
||||
exec mkdir -m "$dirmode" -p -- "$@"
|
||||
fi
|
||||
;;
|
||||
esac
|
||||
|
||||
for file
|
||||
do
|
||||
set fnord `echo ":$file" | sed -ne 's/^:\//#/;s/^://;s/\// /g;s/^#/\//;p'`
|
||||
shift
|
||||
|
||||
pathcomp=
|
||||
for d
|
||||
do
|
||||
pathcomp="$pathcomp$d"
|
||||
case $pathcomp in
|
||||
-*) pathcomp=./$pathcomp ;;
|
||||
esac
|
||||
|
||||
if test ! -d "$pathcomp"; then
|
||||
echo "mkdir $pathcomp"
|
||||
|
||||
mkdir "$pathcomp" || lasterr=$?
|
||||
|
||||
if test ! -d "$pathcomp"; then
|
||||
errstatus=$lasterr
|
||||
else
|
||||
if test ! -z "$dirmode"; then
|
||||
echo "chmod $dirmode $pathcomp"
|
||||
lasterr=""
|
||||
chmod "$dirmode" "$pathcomp" || lasterr=$?
|
||||
|
||||
if test ! -z "$lasterr"; then
|
||||
errstatus=$lasterr
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
|
||||
pathcomp="$pathcomp/"
|
||||
done
|
||||
done
|
||||
|
||||
exit $errstatus
|
||||
|
||||
# Local Variables:
|
||||
# mode: shell-script
|
||||
# sh-indentation: 2
|
||||
# End:
|
||||
# mkinstalldirs ends here
|
||||
|
|
@ -0,0 +1,181 @@
|
|||
Summary: Scriptable database and system performance benchmark
|
||||
Name: sysbench
|
||||
# Version will be replaced by packpack
|
||||
Version: x.y.z
|
||||
Release: 1%{?dist}
|
||||
License: GPLv2+
|
||||
Group: Applications/System
|
||||
Source0: https://github.com/akopytov/%{name}/archive/%{version}/%{name}-%{version}.tar.gz
|
||||
URL: https://github.com/akopytov/sysbench/
|
||||
|
||||
%if 0%{?rhel} < 7
|
||||
BuildRequires: mysql-devel
|
||||
%else
|
||||
BuildRequires: mariadb-devel
|
||||
%endif
|
||||
BuildRequires: postgresql-devel
|
||||
BuildRequires: make
|
||||
BuildRequires: automake
|
||||
BuildRequires: libtool
|
||||
BuildRequires: pkgconfig
|
||||
BuildRequires: libaio-devel
|
||||
# Use bundled cram for tests
|
||||
%if 0%{?rhel} > 7
|
||||
BuildRequires: python2
|
||||
%else
|
||||
BuildRequires: python
|
||||
%endif
|
||||
|
||||
ExclusiveArch: %{arm} %{ix86} x86_64 %{mips} aarch64
|
||||
|
||||
|
||||
%description
|
||||
sysbench is a scriptable multi-threaded benchmark tool based on
|
||||
LuaJIT. It is most frequently used for database benchmarks, but can also
|
||||
be used to create arbitrarily complex workloads that do not involve a
|
||||
database server.
|
||||
|
||||
sysbench comes with the following bundled benchmarks:
|
||||
|
||||
- oltp_*.lua: a collection of OLTP-like database benchmarks
|
||||
- fileio: a filesystem-level benchmark
|
||||
- cpu: a simple CPU benchmark
|
||||
- memory: a memory access benchmark
|
||||
- threads: a thread-based scheduler benchmark
|
||||
- mutex: a POSIX mutex benchmark
|
||||
|
||||
%prep
|
||||
%setup -q
|
||||
|
||||
%build
|
||||
export CFLAGS="%{optflags}"
|
||||
autoreconf -vif
|
||||
%configure --with-mysql \
|
||||
--with-pgsql \
|
||||
--without-gcc-arch
|
||||
|
||||
%if 0%{?el6}
|
||||
make -j2
|
||||
%else
|
||||
%make_build
|
||||
%endif
|
||||
|
||||
%install
|
||||
%make_install
|
||||
rm -f %{buildroot}%{_docdir}/sysbench/manual.html
|
||||
|
||||
%check
|
||||
make test
|
||||
|
||||
%files
|
||||
%doc ChangeLog COPYING README.md
|
||||
%if 0%{?el6}
|
||||
%else
|
||||
%license COPYING
|
||||
%endif
|
||||
%{_bindir}/*
|
||||
%{_datadir}/%{name}
|
||||
|
||||
|
||||
%changelog
|
||||
* Fri Mar 15 2019 Alexey Bychko <abychko@gmail.com> - 1.0.16-1
|
||||
- Updated build dependencies for RHEL8-Beta.
|
||||
|
||||
* Sat Jan 6 2018 Alexey Kopytov <akopytov@gmail.com> - 1.0.12-1
|
||||
- Remove vim-common from build dependencies.
|
||||
|
||||
* Sun Apr 09 2017 Alexey Kopytov <akopytov@gmail.com> - 1.0.5-1
|
||||
- Add --without-gcc-arch to configure flags
|
||||
|
||||
* Sat Apr 08 2017 Alexey Kopytov <akopytov@gmail.com> - 1.0.5-1
|
||||
- Workarounds for make_build and license macros which are not available on EL 6.
|
||||
|
||||
* Fri Apr 07 2017 Alexey Kopytov <akopytov@gmail.com> - 1.0.5-1
|
||||
- Depend on mysql-devel rather than mariadb-devel on EL 6.
|
||||
- Use bundled cram for tests, because it's not available on EL 6.
|
||||
|
||||
* Thu Apr 06 2017 Alexey Kopytov <akopytov@gmail.com> - 1.0.5-1
|
||||
- Reuse downstream Fedora spec with modifications (prefer bundled libraries)
|
||||
|
||||
* Mon Mar 13 2017 Xavier Bachelot <xavier@bachelot.org> 1.0.4-2
|
||||
- Don't build aarch64 on el7.
|
||||
|
||||
* Mon Mar 13 2017 Xavier Bachelot <xavier@bachelot.org> 1.0.4-1
|
||||
- Fix build for i686.
|
||||
- Drop bundled cram.
|
||||
|
||||
* Wed Mar 08 2017 Xavier Bachelot <xavier@bachelot.org> 1.0.3-1
|
||||
- Update to 1.0.3 (RHBZ#1424670).
|
||||
- Restrict arches to the same ones as luajit.
|
||||
- Add --with-gcc-arch=native to configure for %%{arm} and aarch64.
|
||||
- Ignore test suite results for aarch64, it segfaults in koji.
|
||||
|
||||
* Sat Feb 25 2017 Xavier Bachelot <xavier@bachelot.org> 1.0.2-2
|
||||
- Run test suite.
|
||||
|
||||
* Sat Feb 25 2017 Xavier Bachelot <xavier@bachelot.org> 1.0.2-1
|
||||
- Update to 1.0.2 (RHBZ#1424670).
|
||||
|
||||
* Sun Feb 12 2017 Honza Horak <hhorak@redhat.com> - 1.0.0-1
|
||||
- Update to the first proper release 1.0.0
|
||||
|
||||
* Sat Feb 11 2017 Fedora Release Engineering <releng@fedoraproject.org> - 0.4.12-15
|
||||
- Rebuilt for https://fedoraproject.org/wiki/Fedora_26_Mass_Rebuild
|
||||
|
||||
* Fri Feb 05 2016 Fedora Release Engineering <releng@fedoraproject.org> - 0.4.12-14
|
||||
- Rebuilt for https://fedoraproject.org/wiki/Fedora_24_Mass_Rebuild
|
||||
|
||||
* Fri Jun 19 2015 Fedora Release Engineering <rel-eng@lists.fedoraproject.org> - 0.4.12-13
|
||||
- Rebuilt for https://fedoraproject.org/wiki/Fedora_23_Mass_Rebuild
|
||||
|
||||
* Thu Sep 04 2014 Xavier Bachelot <xavier@bachelot.org> 0.4.12-12
|
||||
- Modernize specfile.
|
||||
|
||||
* Mon Aug 18 2014 Fedora Release Engineering <rel-eng@lists.fedoraproject.org> - 0.4.12-11
|
||||
- Rebuilt for https://fedoraproject.org/wiki/Fedora_21_22_Mass_Rebuild
|
||||
|
||||
* Sun Jun 08 2014 Fedora Release Engineering <rel-eng@lists.fedoraproject.org> - 0.4.12-10
|
||||
- Rebuilt for https://fedoraproject.org/wiki/Fedora_21_Mass_Rebuild
|
||||
|
||||
* Sun Aug 04 2013 Fedora Release Engineering <rel-eng@lists.fedoraproject.org> - 0.4.12-9
|
||||
- Rebuilt for https://fedoraproject.org/wiki/Fedora_20_Mass_Rebuild
|
||||
|
||||
* Fri Feb 15 2013 Fedora Release Engineering <rel-eng@lists.fedoraproject.org> - 0.4.12-8
|
||||
- Rebuilt for https://fedoraproject.org/wiki/Fedora_19_Mass_Rebuild
|
||||
|
||||
* Sat Jul 21 2012 Fedora Release Engineering <rel-eng@lists.fedoraproject.org> - 0.4.12-7
|
||||
- Rebuilt for https://fedoraproject.org/wiki/Fedora_18_Mass_Rebuild
|
||||
|
||||
* Sat Jan 14 2012 Fedora Release Engineering <rel-eng@lists.fedoraproject.org> - 0.4.12-6
|
||||
- Rebuilt for https://fedoraproject.org/wiki/Fedora_17_Mass_Rebuild
|
||||
|
||||
* Tue Sep 06 2011 Xavier Bachelot <xavier@bachelot.org> 0.4.12-5
|
||||
- Add BR: libaio-devel (rhbz#735882).
|
||||
|
||||
* Wed Mar 23 2011 Dan Horák <dan@danny.cz> - 0.4.12-4
|
||||
- rebuilt for mysql 5.5.10 (soname bump in libmysqlclient)
|
||||
|
||||
* Wed Feb 09 2011 Fedora Release Engineering <rel-eng@lists.fedoraproject.org> - 0.4.12-3
|
||||
- Rebuilt for https://fedoraproject.org/wiki/Fedora_15_Mass_Rebuild
|
||||
|
||||
* Fri Dec 24 2010 Xavier Bachelot <xavier@bachelot.org> 0.4.12-2
|
||||
- Rebuild against new mysql.
|
||||
|
||||
* Wed Jul 07 2010 Xavier Bachelot <xavier@bachelot.org> 0.4.12-1
|
||||
- Update to 0.4.12.
|
||||
|
||||
* Fri Aug 21 2009 Tomas Mraz <tmraz@redhat.com> - 0.4.10-5
|
||||
- rebuilt with new openssl
|
||||
|
||||
* Sun Jul 26 2009 Fedora Release Engineering <rel-eng@lists.fedoraproject.org> - 0.4.10-4
|
||||
- Rebuilt for https://fedoraproject.org/wiki/Fedora_12_Mass_Rebuild
|
||||
|
||||
* Wed Mar 18 2009 Xavier Bachelot <xavier@bachelot.org> 0.4.10-3
|
||||
- License is GPLv2+, not GPLv2.
|
||||
|
||||
* Sat Mar 14 2009 Xavier Bachelot <xavier@bachelot.org> 0.4.10-2
|
||||
- Make postgres support optional, the version in rhel4 is too old.
|
||||
- Drop TODO and manual.html from %%doc, they are empty.
|
||||
|
||||
* Thu Mar 05 2009 Xavier Bachelot <xavier@bachelot.org> 0.4.10-1
|
||||
- Adapt original spec file taken from PLD.
|
||||
|
|
@ -0,0 +1,197 @@
|
|||
#!/usr/bin/env bash
|
||||
#
|
||||
# Copyright (C) 2017-2019 Alexey Kopytov <akopytov@gmail.com>
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation; either version 2 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, write to the Free Software
|
||||
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
|
||||
# Build packages for a specified architecture and upload them to packagecloud.io
|
||||
# Expects the following environment variables to be defined:
|
||||
#
|
||||
# ARCH - architecture. 'aarch64', 'x86_64 and 'i386' are currently supported
|
||||
# values. If not set, the script behaves as if it was sequentially
|
||||
# called with 'x86_64' and 'i386' values
|
||||
#
|
||||
# OS/DIST - distribution specification for packpack. When empty (the default)
|
||||
# use all disitributions available for ARCH
|
||||
#
|
||||
# PACKAGECLOUD_TOKEN - packagecloud.io API token
|
||||
#
|
||||
# PACKAGECLOUD_USER - packagecloud.io user name, defaults to 'akopytov'
|
||||
#
|
||||
# PACKAGECLOUD_REPO - packagecloud.io repository. The default is 'sysbench'
|
||||
# for releases (i.e. if git HEAD corresponds to a tag),
|
||||
# and 'sysbench-prereleases' otherwise.
|
||||
#
|
||||
# PACKAGECLOUD_EXTRA_ARGS - extra arguments to pass to the package_cloud
|
||||
# utility. Empty by default. Can be used to pass the
|
||||
# --skip-errors flag to ignore deploy errors.
|
||||
#
|
||||
# PACKPACK_REPO - packpack repository to use. Defaults to akopytov/packpack.
|
||||
|
||||
set -eu
|
||||
|
||||
PACKAGECLOUD_USER=${PACKAGECLOUD_USER:-"akopytov"}
|
||||
PACKAGECLOUD_EXTRA_ARGS=${PACKAGECLOUD_EXTRA_ARGS:-}
|
||||
PACKPACK_REPO=${PACKPACK_REPO:-akopytov/packpack}
|
||||
|
||||
distros_x86_64=(
|
||||
"el 6 x86_64"
|
||||
"el 7 x86_64"
|
||||
"el 8 x86_64"
|
||||
"fedora 29 x86_64"
|
||||
"fedora 30 x86_64"
|
||||
"fedora 31 x86_64"
|
||||
"ubuntu xenial x86_64"
|
||||
"ubuntu bionic x86_64"
|
||||
"ubuntu eoan x86_64"
|
||||
"ubuntu focal x86_64"
|
||||
"debian jessie x86_64"
|
||||
"debian stretch x86_64"
|
||||
"debian buster x86_64"
|
||||
)
|
||||
|
||||
distros_i386=(
|
||||
"ubuntu xenial i386"
|
||||
"ubuntu bionic i386"
|
||||
"ubuntu eoan i386"
|
||||
"debian jessie i386"
|
||||
"debian stretch i386"
|
||||
"debian buster i386"
|
||||
)
|
||||
|
||||
distros_aarch64=(
|
||||
"el 7 aarch64"
|
||||
"fedora 29 aarch64"
|
||||
"fedora 30 aarch64"
|
||||
"fedora 31 aarch64"
|
||||
"ubuntu bionic aarch64"
|
||||
"ubuntu eoan aarch64"
|
||||
"ubuntu focal aarch64"
|
||||
"ubuntu xenial aarch64"
|
||||
"debian jessie aarch64"
|
||||
"debian stretch aarch64"
|
||||
"debian buster aarch64"
|
||||
)
|
||||
|
||||
main()
|
||||
{
|
||||
if [ ! -r configure.ac ]; then
|
||||
echo "This script should be executed from the source root directory."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [ -z "${PACKAGECLOUD_TOKEN+x}" ]; then
|
||||
echo "This script expects PACKAGECLOUD_TOKEN to be defined."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [ ! which package_cloud >/dev/null 2>&1 ]; then
|
||||
echo "This script requires package_cloud. You can install it by running:"
|
||||
echo " gem install package_cloud"
|
||||
fi
|
||||
|
||||
if [ ! -d packpack ]; then
|
||||
git clone https://github.com/${PACKPACK_REPO} packpack
|
||||
fi
|
||||
|
||||
if [ -z "${PACKAGECLOUD_REPO+x}" ]; then
|
||||
# Upload builds corresponding to release tags to the 'sysbench'
|
||||
# repository, push other ones to 'sysbench-prereleases'
|
||||
if ! git describe --long --always >/dev/null 2>&1 ; then
|
||||
echo "Either run this script from a git repository, or specify "
|
||||
echo "the packagecloud repository explicitly with PACKAGECLOUD_REPO"
|
||||
exit 1
|
||||
fi
|
||||
local commits=$(git describe --long --always |
|
||||
sed -n 's/^\([0-9\.]*\)-\([0-9]*\)-\([a-z0-9]*\)/\2/p')
|
||||
if [ ${commits:-0} = 0 ]; then
|
||||
export PACKAGECLOUD_REPO=sysbench
|
||||
# Use short version numbers for release builds
|
||||
export VERSION=$(git describe)
|
||||
else
|
||||
export PACKAGECLOUD_REPO=sysbench-prereleases
|
||||
fi
|
||||
fi
|
||||
|
||||
declare -a distros
|
||||
|
||||
OS=${OS:-}
|
||||
DIST=${DIST:-}
|
||||
|
||||
if [ -n "${OS}" -a -n "${DIST}" ]; then
|
||||
distros=( "${OS} ${DIST} ${ARCH:-x86_64}" )
|
||||
elif [ -z "${ARCH+x}" ]; then
|
||||
distros=("${distros_x86_64[@]}" "${distros_i386[@]}")
|
||||
else
|
||||
case "$ARCH" in
|
||||
x86_64)
|
||||
distros=( "${distros_x86_64[@]}" )
|
||||
;;
|
||||
i386)
|
||||
distros=( "${distros_i386[@]}" )
|
||||
;;
|
||||
aarch64)
|
||||
distros=( "${distros_aarch64[@]}" )
|
||||
;;
|
||||
*)
|
||||
echo "Invalid ARCH value: $ARCH"
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
fi
|
||||
|
||||
export PRODUCT=sysbench
|
||||
export CHANGELOG_NAME=sysbench
|
||||
export CHANGELOG_EMAIL=akopytov@gmail.com
|
||||
|
||||
for d in "${distros[@]}"; do
|
||||
echo "*** Building package for $d ***"
|
||||
local t=( $d )
|
||||
export OS=${t[0]}
|
||||
export DIST=${t[1]}
|
||||
export ARCH=${t[2]}
|
||||
|
||||
# Replace "el" with "centos" for packpack, as there is no "el-*" docker
|
||||
# images for some architectures
|
||||
local PPOS=${OS/#el/centos}
|
||||
OS="$PPOS" packpack/packpack
|
||||
|
||||
# To avoid name conflicts, deploy source packages only for
|
||||
# "default", i.e. x86_64 architecture
|
||||
if [ "${ARCH}" = "x86_64" ]; then
|
||||
files="$(ls build/*.{rpm,deb,dsc} 2>/dev/null || :)"
|
||||
else
|
||||
files="$(ls build/*{[^c].rpm,.deb} 2>/dev/null || :)"
|
||||
fi
|
||||
|
||||
if [ -z "$files" ]; then
|
||||
echo "No package files to push"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "Pushing packages to ${PACKAGECLOUD_USER}/${PACKAGECLOUD_REPO}"
|
||||
|
||||
for f in $files ; do
|
||||
echo $f
|
||||
package_cloud push ${PACKAGECLOUD_EXTRA_ARGS} \
|
||||
${PACKAGECLOUD_USER}/${PACKAGECLOUD_REPO}/${OS}/${DIST} \
|
||||
$f
|
||||
done
|
||||
|
||||
OS=${PPOS} packpack/packpack clean
|
||||
done
|
||||
}
|
||||
|
||||
main
|
||||
|
|
@ -0,0 +1,36 @@
|
|||
name: sysbench
|
||||
version: @PACKAGE_VERSION@
|
||||
summary: Scriptable database and system performance benchmark
|
||||
description: |
|
||||
sysbench is a scriptable multi-threaded benchmark tool based on
|
||||
LuaJIT. It is most frequently used for database benchmarks, but can also
|
||||
be used to create arbitrarily complex workloads that do not involve a
|
||||
database server.
|
||||
|
||||
sysbench comes with the following bundled benchmarks:
|
||||
|
||||
- oltp_*.lua: a collection of OLTP-like database benchmarks
|
||||
- fileio: a filesystem-level benchmark
|
||||
- cpu: a simple CPU benchmark
|
||||
- memory: a memory access benchmark
|
||||
- threads: a thread-based scheduler benchmark
|
||||
- mutex: a POSIX mutex benchmark
|
||||
|
||||
grade: stable
|
||||
confinement: classic
|
||||
|
||||
apps:
|
||||
sysbench:
|
||||
command: sysbench
|
||||
plugs:
|
||||
- network
|
||||
|
||||
parts:
|
||||
sysbench:
|
||||
source: .
|
||||
plugin: autotools
|
||||
build-packages:
|
||||
- libmysqlclient-dev
|
||||
stage-packages:
|
||||
- libmysqlclient20
|
||||
- libaio1
|
||||
|
|
@ -0,0 +1,113 @@
|
|||
# Copyright (C) 2008 MySQL AB
|
||||
# Copyright (C) 2008-2017 Alexey Kopytov <akopytov@gmail.com>
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation; either version 2 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, write to the Free Software
|
||||
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
|
||||
cmake_minimum_required(VERSION 2.6)
|
||||
if(COMMAND cmake_policy)
|
||||
cmake_policy(SET CMP0003 NEW)
|
||||
endif(COMMAND cmake_policy)
|
||||
|
||||
project(sysbench)
|
||||
add_executable(sysbench
|
||||
sysbench.c
|
||||
sysbench.h
|
||||
sb_timer.c
|
||||
sb_timer.h
|
||||
sb_options.c
|
||||
sb_options.h
|
||||
sb_logger.c
|
||||
sb_logger.h
|
||||
sb_histogram.c
|
||||
sb_histogram.h
|
||||
sb_list.h
|
||||
db_driver.h
|
||||
db_driver.c
|
||||
sb_win.c
|
||||
sb_win.h
|
||||
sb_rand.c
|
||||
sb_rand.h
|
||||
sb_thread.c
|
||||
sb_thread.h
|
||||
sb_barrier.c
|
||||
sb_barrier.h
|
||||
)
|
||||
if(MSVC)
|
||||
# Link C runtime statically to avoid hassle with CRT dll redistribution.
|
||||
STRING(REPLACE "/MD" "/MT" CMAKE_C_FLAGS_RELEASE ${CMAKE_C_FLAGS_RELEASE})
|
||||
STRING(REPLACE "/MD" "/MT" CMAKE_C_FLAGS_RELWITHDEBINFO ${CMAKE_C_FLAGS_RELWITHDEBINFO})
|
||||
STRING(REPLACE "/MDd" "/MTd" CMAKE_C_FLAGS_DEBUG ${CMAKE_C_FLAGS_DEBUG})
|
||||
STRING(REPLACE "/MDd" "/MTd" CMAKE_C_FLAGS_DEBUG_INIT ${CMAKE_C_FLAGS_DEBUG_INIT})
|
||||
|
||||
STRING(REPLACE "/MD" "/MT" CMAKE_CXX_FLAGS_RELEASE ${CMAKE_CXX_FLAGS_RELEASE})
|
||||
STRING(REPLACE "/MD" "/MT" CMAKE_CXX_FLAGS_RELWITHDEBINFO ${CMAKE_CXX_FLAGS_RELWITHDEBINFO})
|
||||
STRING(REPLACE "/MDd" "/MTd" CMAKE_CXX_FLAGS_DEBUG ${CMAKE_CXX_FLAGS_DEBUG})
|
||||
STRING(REPLACE "/MDd" "/MTd" CMAKE_CXX_FLAGS_DEBUG_INIT ${CMAKE_CXX_FLAGS_DEBUG_INIT})
|
||||
|
||||
#Silence "deprecated API" warnings.
|
||||
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} /wd4996")
|
||||
|
||||
#Look for mysql.h in INCLUDE paths
|
||||
find_path(MYSQLH_PATH mysql.h ENV INCLUDE)
|
||||
message("mysql.h directory = ${MYSQLH_PATH}")
|
||||
|
||||
#Looks for libmysql.lib in LIB paths
|
||||
find_file(LIBMYSQL_LIB libmysql.lib ENV LIB)
|
||||
message("libmysql.lib = ${LIBMYSQL_LIB}")
|
||||
|
||||
#Look for libmysql.dll
|
||||
find_file(LIBMYSQL_DLL libmysql.dll ENV LIB ENV PATH)
|
||||
message("libmysql.dll = ${LIBMYSQL_DLL}")
|
||||
|
||||
#If mysql header file and client library are found, build with mysql
|
||||
if(MYSQLH_PATH AND LIBMYSQL_LIB)
|
||||
set(USE_MYSQL 1)
|
||||
|
||||
#If libmysql.dll found, copy it next to sysbench.exe in the postbuild step
|
||||
if(LIBMYSQL_DLL)
|
||||
file(TO_NATIVE_PATH ${LIBMYSQL_DLL} LIBMYSQL_DLL)
|
||||
ADD_CUSTOM_COMMAND(
|
||||
TARGET sysbench
|
||||
POST_BUILD
|
||||
COMMAND copy /y ${LIBMYSQL_DLL} $(OutDir)
|
||||
)
|
||||
endif(LIBMYSQL_DLL)
|
||||
endif(MYSQLH_PATH AND LIBMYSQL_LIB)
|
||||
endif(MSVC)
|
||||
|
||||
|
||||
if(USE_MYSQL)
|
||||
message("using mysql driver")
|
||||
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -DUSE_MYSQL")
|
||||
include_directories(${MYSQLH_PATH})
|
||||
add_subdirectory(drivers/mysql)
|
||||
target_link_libraries (sysbench sbmysql)
|
||||
target_link_libraries (sysbench ${LIBMYSQL_LIB})
|
||||
endif(USE_MYSQL)
|
||||
|
||||
add_subdirectory(tests/cpu)
|
||||
target_link_libraries (sysbench sbcpu)
|
||||
|
||||
add_subdirectory(tests/fileio)
|
||||
target_link_libraries (sysbench sbfileio)
|
||||
|
||||
add_subdirectory(tests/mutex)
|
||||
target_link_libraries (sysbench sbmutex)
|
||||
|
||||
add_subdirectory(tests/threads)
|
||||
target_link_libraries (sysbench sbthreads)
|
||||
|
||||
add_subdirectory(tests/memory)
|
||||
target_link_libraries (sysbench sbmemory)
|
||||
|
|
@ -0,0 +1,65 @@
|
|||
# Copyright (C) 2004 MySQL AB
|
||||
# Copyright (C) 2004-2017 Alexey Kopytov <akopytov@gmail.com>
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation; either version 2 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, write to the Free Software
|
||||
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
|
||||
SUBDIRS = drivers tests lua .
|
||||
|
||||
AM_CPPFLAGS += -DDATADIR=\"$(pkgdatadir)\" -DLIBDIR=\"$(pkglibdir)\"
|
||||
|
||||
bin_PROGRAMS = sysbench
|
||||
|
||||
EXTRA_LDFLAGS = @EXTRA_LDFLAGS@
|
||||
|
||||
# The following check will be extended as new database drivers will be added
|
||||
if USE_MYSQL
|
||||
mysql_ldadd = drivers/mysql/libsbmysql.a $(MYSQL_LIBS)
|
||||
endif
|
||||
|
||||
if USE_DRIZZLE
|
||||
drizzle_ldadd = drivers/drizzle/libsbdrizzle.a $(LIBDRIZZLE)
|
||||
endif
|
||||
|
||||
if USE_ATTACHSQL
|
||||
attachsql_ldadd = drivers/attachsql/libsbattachsql.a $(LIBATTACHSQL)
|
||||
endif
|
||||
|
||||
if USE_ORACLE
|
||||
ora_ldadd = drivers/oracle/libsboracle.a $(ORA_LIBS)
|
||||
endif
|
||||
|
||||
if USE_PGSQL
|
||||
pgsql_ldadd = drivers/pgsql/libsbpgsql.a $(PGSQL_LIBS)
|
||||
endif
|
||||
|
||||
sysbench_SOURCES = sysbench.c sysbench.h sb_timer.c sb_timer.h \
|
||||
sb_options.c sb_options.h sb_logger.c sb_logger.h sb_list.h db_driver.h \
|
||||
db_driver.c sb_histogram.c sb_histogram.h sb_rand.c sb_rand.h \
|
||||
sb_thread.c sb_thread.h sb_barrier.c sb_barrier.h sb_lua.c \
|
||||
sb_ck_pr.h \
|
||||
sb_lua.h sb_util.h sb_util.c sb_counter.h sb_counter.c \
|
||||
lua/internal/sysbench.lua.h lua/internal/sysbench.sql.lua.h \
|
||||
lua/internal/sysbench.rand.lua.h lua/internal/sysbench.cmdline.lua.h \
|
||||
lua/internal/sysbench.compat.lua.h lua/internal/sysbench.histogram.lua.h \
|
||||
xoroshiro128plus.h
|
||||
|
||||
sysbench_LDADD = tests/fileio/libsbfileio.a tests/threads/libsbthreads.a \
|
||||
tests/memory/libsbmemory.a tests/cpu/libsbcpu.a \
|
||||
tests/mutex/libsbmutex.a \
|
||||
$(mysql_ldadd) $(drizzle_ldadd) $(attachsql_ldadd) $(pgsql_ldadd) \
|
||||
$(ora_ldadd) $(LUAJIT_LIBS) $(CK_LIBS)
|
||||
|
||||
sysbench_LDFLAGS = $(EXTRA_LDFLAGS) $(mysql_ldflags) $(attachsql_ldflags) \
|
||||
$(pgsql_ldflags) $(ora_ldflags) $(LUAJIT_LDFLAGS)
|
||||
File diff suppressed because it is too large
Load Diff
|
|
@ -0,0 +1,346 @@
|
|||
/* Copyright (C) 2004 MySQL AB
|
||||
Copyright (C) 2004-2017 Alexey Kopytov <akopytov@gmail.com>
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#ifndef DB_DRIVER_H
|
||||
#define DB_DRIVER_H
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
# include "config.h"
|
||||
#endif
|
||||
|
||||
#include "sysbench.h"
|
||||
#include "sb_list.h"
|
||||
#include "sb_histogram.h"
|
||||
#include "sb_counter.h"
|
||||
|
||||
/* Prepared statements usage modes */
|
||||
|
||||
typedef enum
|
||||
{
|
||||
DB_PS_MODE_AUTO,
|
||||
DB_PS_MODE_DISABLE,
|
||||
} db_ps_mode_t;
|
||||
|
||||
/* Global DB API options */
|
||||
|
||||
typedef struct
|
||||
{
|
||||
db_ps_mode_t ps_mode; /* Requested prepared statements usage mode */
|
||||
char *driver; /* Requested database driver */
|
||||
unsigned char debug; /* debug flag */
|
||||
} db_globals_t;
|
||||
|
||||
/* Driver capabilities definition */
|
||||
|
||||
typedef struct
|
||||
{
|
||||
char multi_rows_insert; /* 1 if database supports multi-row inserts */
|
||||
char prepared_statements; /* 1 if database supports prepared statements */
|
||||
char auto_increment; /* 1 if database supports AUTO_INCREMENT clause */
|
||||
char needs_commit; /* 1 if database needs explicit commit after INSERTs */
|
||||
char serial; /* 1 if database supports SERIAL clause */
|
||||
char unsigned_int; /* 1 if database supports UNSIGNED INTEGER types */
|
||||
} drv_caps_t;
|
||||
|
||||
/* Database errors definition */
|
||||
|
||||
typedef enum
|
||||
{
|
||||
DB_ERROR_NONE, /* no error(s) */
|
||||
DB_ERROR_IGNORABLE, /* error should be ignored as defined by command
|
||||
line arguments or a custom error handler */
|
||||
DB_ERROR_FATAL /* non-ignorable error */
|
||||
} db_error_t;
|
||||
|
||||
|
||||
/* Available buffer types (for parameters binding) */
|
||||
|
||||
typedef enum
|
||||
{
|
||||
DB_TYPE_NONE,
|
||||
DB_TYPE_TINYINT,
|
||||
DB_TYPE_SMALLINT,
|
||||
DB_TYPE_INT,
|
||||
DB_TYPE_BIGINT,
|
||||
DB_TYPE_FLOAT,
|
||||
DB_TYPE_DOUBLE,
|
||||
DB_TYPE_TIME,
|
||||
DB_TYPE_DATE,
|
||||
DB_TYPE_DATETIME,
|
||||
DB_TYPE_TIMESTAMP,
|
||||
DB_TYPE_CHAR,
|
||||
DB_TYPE_VARCHAR
|
||||
} db_bind_type_t;
|
||||
|
||||
|
||||
/* Structure used to represent DATE, TIME, DATETIME and TIMESTAMP values */
|
||||
|
||||
typedef struct
|
||||
{
|
||||
unsigned int year;
|
||||
unsigned int month;
|
||||
unsigned int day;
|
||||
unsigned int hour;
|
||||
unsigned int minute;
|
||||
unsigned int second;
|
||||
} db_time_t;
|
||||
|
||||
|
||||
/* Structure used to bind data for prepared statements */
|
||||
|
||||
typedef struct
|
||||
{
|
||||
db_bind_type_t type;
|
||||
void *buffer;
|
||||
unsigned long *data_len;
|
||||
unsigned long max_len;
|
||||
char *is_null;
|
||||
} db_bind_t;
|
||||
|
||||
/* Forward declarations */
|
||||
|
||||
struct db_conn;
|
||||
struct db_stmt;
|
||||
struct db_result;
|
||||
struct db_row;
|
||||
|
||||
/* Driver operations definition */
|
||||
|
||||
typedef int drv_op_init(void);
|
||||
typedef int drv_op_thread_init(int);
|
||||
typedef int drv_op_describe(drv_caps_t *);
|
||||
typedef int drv_op_connect(struct db_conn *);
|
||||
typedef int drv_op_reconnect(struct db_conn *);
|
||||
typedef int drv_op_disconnect(struct db_conn *);
|
||||
typedef int drv_op_prepare(struct db_stmt *, const char *, size_t);
|
||||
typedef int drv_op_bind_param(struct db_stmt *, db_bind_t *, size_t);
|
||||
typedef int drv_op_bind_result(struct db_stmt *, db_bind_t *, size_t);
|
||||
typedef db_error_t drv_op_execute(struct db_stmt *, struct db_result *);
|
||||
typedef int drv_op_fetch(struct db_result *);
|
||||
typedef int drv_op_fetch_row(struct db_result *, struct db_row *);
|
||||
typedef db_error_t drv_op_query(struct db_conn *, const char *, size_t,
|
||||
struct db_result *);
|
||||
typedef int drv_op_free_results(struct db_result *);
|
||||
typedef int drv_op_close(struct db_stmt *);
|
||||
typedef int drv_op_thread_done(int);
|
||||
typedef int drv_op_done(void);
|
||||
|
||||
typedef struct
|
||||
{
|
||||
drv_op_init *init; /* initializate driver */
|
||||
drv_op_thread_init *thread_init; /* thread-local driver initialization */
|
||||
drv_op_describe *describe; /* describe database capabilities */
|
||||
drv_op_connect *connect; /* connect to database */
|
||||
drv_op_disconnect *disconnect; /* disconnect from database */
|
||||
drv_op_reconnect *reconnect; /* reconnect with the same parameters */
|
||||
drv_op_prepare *prepare; /* prepare statement */
|
||||
drv_op_bind_param *bind_param; /* bind params for prepared statement */
|
||||
drv_op_bind_result *bind_result; /* bind results for prepared statement */
|
||||
drv_op_execute *execute; /* execute prepared statement */
|
||||
drv_op_fetch *fetch; /* fetch row for prepared statement */
|
||||
drv_op_fetch_row *fetch_row; /* fetch row for queries */
|
||||
drv_op_free_results *free_results; /* free result set */
|
||||
drv_op_close *close; /* close prepared statement */
|
||||
drv_op_query *query; /* execute non-prepared statement */
|
||||
drv_op_thread_done *thread_done; /* thread-local driver deinitialization */
|
||||
drv_op_done *done; /* uninitialize driver */
|
||||
} drv_ops_t;
|
||||
|
||||
/* Database driver definition */
|
||||
|
||||
typedef struct
|
||||
{
|
||||
const char *sname; /* short name */
|
||||
const char *lname; /* long name */
|
||||
sb_arg_t *args; /* driver command line arguments */
|
||||
drv_ops_t ops; /* driver operations */
|
||||
|
||||
sb_list_item_t listitem; /* can be linked in a list */
|
||||
bool initialized;
|
||||
pthread_mutex_t mutex;
|
||||
} db_driver_t;
|
||||
|
||||
/* Row value definition */
|
||||
|
||||
typedef struct {
|
||||
uint32_t len; /* Value length */
|
||||
const char *ptr; /* Value string */
|
||||
} db_value_t;
|
||||
|
||||
/* Result set row definition */
|
||||
|
||||
typedef struct db_row
|
||||
{
|
||||
void *ptr; /* Driver-specific row data */
|
||||
db_value_t *values; /* Array of column values */
|
||||
} db_row_t;
|
||||
|
||||
/* Result set definition */
|
||||
|
||||
typedef struct db_result
|
||||
{
|
||||
sb_counter_type_t counter; /* Statistical counter type */
|
||||
uint32_t nrows; /* Number of affected rows */
|
||||
uint32_t nfields; /* Number of fields */
|
||||
struct db_stmt *statement; /* Pointer to prepared statement (if used) */
|
||||
void *ptr; /* Pointer to driver-specific data */
|
||||
db_row_t row; /* Last fetched row */
|
||||
} db_result_t;
|
||||
|
||||
typedef enum {
|
||||
DB_CONN_READY,
|
||||
DB_CONN_RESULT_SET,
|
||||
DB_CONN_INVALID
|
||||
} db_conn_state_t;
|
||||
|
||||
/* Database connection structure */
|
||||
|
||||
typedef struct db_conn
|
||||
{
|
||||
db_error_t error; /* Database-independent error code */
|
||||
int sql_errno; /* Database-specific error code */
|
||||
const char *sql_state; /* Database-specific SQL state */
|
||||
const char *sql_errmsg; /* Database-specific error message */
|
||||
db_driver_t *driver; /* DB driver for this connection */
|
||||
void *ptr; /* Driver-specific data */
|
||||
db_result_t rs; /* Result set */
|
||||
db_conn_state_t state; /* Connection state */
|
||||
int thread_id; /* Thread this connection belongs to */
|
||||
|
||||
unsigned int bulk_cnt; /* Current number of rows in bulk insert buffer */
|
||||
unsigned int bulk_buflen; /* Current length of bulk_buffer */
|
||||
char *bulk_buffer; /* Bulk insert query buffer */
|
||||
unsigned int bulk_ptr; /* Current position in bulk_buffer */
|
||||
unsigned int bulk_values; /* Save value of bulk_ptr */
|
||||
unsigned int bulk_commit_cnt; /* Current value of uncommitted rows */
|
||||
unsigned int bulk_commit_max; /* Maximum value of uncommitted rows */
|
||||
|
||||
char pad[SB_CACHELINE_PAD(sizeof(db_error_t) +
|
||||
sizeof(int) +
|
||||
sizeof(void *) +
|
||||
sizeof(void *) +
|
||||
sizeof(void *) +
|
||||
sizeof(void *) +
|
||||
sizeof(db_result_t) +
|
||||
sizeof(db_conn_state_t) +
|
||||
sizeof(int) +
|
||||
sizeof(int) * 2 +
|
||||
sizeof(void *) +
|
||||
sizeof(int) * 4
|
||||
)];
|
||||
} db_conn_t;
|
||||
|
||||
/* Prepared statement definition */
|
||||
|
||||
typedef struct db_stmt
|
||||
{
|
||||
db_conn_t *connection; /* Connection which this statement belongs to */
|
||||
char *query; /* Query string for emulated PS */
|
||||
db_bind_t *bound_param; /* Array of bound parameters for emulated PS */
|
||||
unsigned int bound_param_len; /* Length of the bound_param array */
|
||||
db_bind_t *bound_res; /* Array of bound results for emulated PS */
|
||||
db_bind_t *bound_res_len; /* Length of the bound_res array */
|
||||
char emulated; /* Should this statement be emulated? */
|
||||
sb_counter_type_t counter; /* Query type */
|
||||
void *ptr; /* Pointer to driver-specific data structure */
|
||||
} db_stmt_t;
|
||||
|
||||
extern db_globals_t db_globals;
|
||||
|
||||
/* Database abstraction layer calls */
|
||||
|
||||
int db_register(void);
|
||||
|
||||
void db_print_help(void);
|
||||
|
||||
db_driver_t *db_create(const char *);
|
||||
|
||||
int db_destroy(db_driver_t *);
|
||||
|
||||
int db_describe(db_driver_t *, drv_caps_t *);
|
||||
|
||||
db_conn_t *db_connection_create(db_driver_t *);
|
||||
|
||||
int db_connection_close(db_conn_t *);
|
||||
|
||||
int db_connection_reconnect(db_conn_t *con);
|
||||
|
||||
void db_connection_free(db_conn_t *con);
|
||||
|
||||
db_stmt_t *db_prepare(db_conn_t *, const char *, size_t);
|
||||
|
||||
int db_bind_param(db_stmt_t *, db_bind_t *, size_t);
|
||||
|
||||
int db_bind_result(db_stmt_t *, db_bind_t *, size_t);
|
||||
|
||||
db_result_t *db_execute(db_stmt_t *);
|
||||
|
||||
db_row_t *db_fetch_row(db_result_t *);
|
||||
|
||||
db_result_t *db_query(db_conn_t *, const char *, size_t len);
|
||||
|
||||
int db_free_results(db_result_t *);
|
||||
|
||||
int db_store_results(db_result_t *);
|
||||
|
||||
int db_close(db_stmt_t *);
|
||||
|
||||
void db_done(void);
|
||||
|
||||
int db_print_value(db_bind_t *, char *, int);
|
||||
|
||||
/* Initialize multi-row insert operation */
|
||||
int db_bulk_insert_init(db_conn_t *, const char *, size_t);
|
||||
|
||||
/* Add row to multi-row insert operation */
|
||||
int db_bulk_insert_next(db_conn_t *, const char *, size_t);
|
||||
|
||||
/* Finish multi-row insert operation */
|
||||
int db_bulk_insert_done(db_conn_t *);
|
||||
|
||||
/* Print database-specific test stats */
|
||||
void db_report_intermediate(sb_stat_t *);
|
||||
void db_report_cumulative(sb_stat_t *);
|
||||
|
||||
/* DB drivers registrars */
|
||||
|
||||
#ifdef USE_MYSQL
|
||||
int register_driver_mysql(sb_list_t *);
|
||||
#endif
|
||||
|
||||
#ifdef USE_DRIZZLE
|
||||
int register_driver_drizzle(sb_list_t *);
|
||||
#endif
|
||||
|
||||
#ifdef USE_ATTACHSQL
|
||||
int register_driver_attachsql(sb_list_t *);
|
||||
#endif
|
||||
|
||||
#ifdef USE_DRIZZLECLIENT
|
||||
int register_driver_drizzleclient(sb_list_t *);
|
||||
#endif
|
||||
|
||||
#ifdef USE_ORACLE
|
||||
int register_driver_oracle(sb_list_t *);
|
||||
#endif
|
||||
|
||||
#ifdef USE_PGSQL
|
||||
int register_driver_pgsql(sb_list_t *);
|
||||
#endif
|
||||
|
||||
#endif /* DB_DRIVER_H */
|
||||
|
|
@ -0,0 +1,38 @@
|
|||
# Copyright (C) 2004 MySQL AB
|
||||
# Copyright (C) 2004-2014 Alexey Kopytov <akopytov@gmail.com>
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation; either version 2 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, write to the Free Software
|
||||
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
|
||||
if USE_MYSQL
|
||||
MYSQL_DIR = mysql
|
||||
endif
|
||||
|
||||
if USE_DRIZZLE
|
||||
DRIZZLE_DIR = drizzle
|
||||
endif
|
||||
|
||||
if USE_ATTACHSQL
|
||||
ATTACHSQL_DIR = attachsql
|
||||
endif
|
||||
|
||||
if USE_ORACLE
|
||||
ORACLE_DIR = oracle
|
||||
endif
|
||||
|
||||
if USE_PGSQL
|
||||
PGSQL_DIR = pgsql
|
||||
endif
|
||||
|
||||
SUBDIRS = $(MYSQL_DIR) $(ORACLE_DIR) $(PGSQL_DIR) $(DRIZZLE_DIR) $(ATTACHSQL_DIR)
|
||||
|
|
@ -0,0 +1,21 @@
|
|||
# Copyright 2014 Hewlett-Packard Development Company, L.P.
|
||||
# based on the Drizzle driver:
|
||||
# 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; either version 2 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, write to the Free Software
|
||||
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
|
||||
noinst_LIBRARIES = libsbattachsql.a
|
||||
|
||||
libsbattachsql_a_SOURCES = drv_attachsql.c
|
||||
|
|
@ -0,0 +1,622 @@
|
|||
/* Copyright 2014 Hewlett-Packard Development Company, L.P.
|
||||
based on the Drizzle driver:
|
||||
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; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
# include "config.h"
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_STRING_H
|
||||
# include <string.h>
|
||||
#endif
|
||||
#ifdef HAVE_STRINGS_H
|
||||
# include <strings.h>
|
||||
#endif
|
||||
#include <stdio.h>
|
||||
|
||||
#include <stdint.h>
|
||||
#include <libattachsql-1.0/attachsql.h>
|
||||
|
||||
#include "sb_options.h"
|
||||
|
||||
#include "db_driver.h"
|
||||
|
||||
#define DEBUG(format, ...) do { if (db_globals.debug) log_text(LOG_DEBUG, format, __VA_ARGS__); } while (0)
|
||||
|
||||
/* Drizzle driver arguments */
|
||||
|
||||
static sb_arg_t attachsql_drv_args[] =
|
||||
{
|
||||
{"attachsql-host", "libAttachSQL server host", SB_ARG_TYPE_LIST, "localhost"},
|
||||
{"attachsql-port", "libAttachSQL server port", SB_ARG_TYPE_INT, "4427"},
|
||||
{"attachsql-socket", "libAttachSQL socket", SB_ARG_TYPE_STRING, NULL},
|
||||
{"attachsql-user", "libAttachSQL user", SB_ARG_TYPE_STRING, ""},
|
||||
{"attachsql-password", "libAttachSQL password", SB_ARG_TYPE_STRING, ""},
|
||||
{"attachsql-db", "libAttachSQL database name", SB_ARG_TYPE_STRING, "sbtest"},
|
||||
{NULL, NULL, SB_ARG_TYPE_NULL, NULL}
|
||||
};
|
||||
|
||||
typedef struct
|
||||
{
|
||||
sb_list_t *hosts;
|
||||
unsigned int port;
|
||||
char *socket;
|
||||
char *user;
|
||||
char *password;
|
||||
char *db;
|
||||
} attachsql_drv_args_t;
|
||||
|
||||
/* AttachSQL driver capabilities
|
||||
* At a later date we will add prepared statements to this
|
||||
*/
|
||||
|
||||
static drv_caps_t attachsql_drv_caps =
|
||||
{
|
||||
.multi_rows_insert = 1,
|
||||
.prepared_statements = 1,
|
||||
.auto_increment = 1,
|
||||
.serial = 0,
|
||||
.unsigned_int = 0,
|
||||
};
|
||||
|
||||
static attachsql_drv_args_t args; /* driver args */
|
||||
|
||||
static sb_list_item_t *hosts_pos;
|
||||
|
||||
static pthread_mutex_t hosts_mutex;
|
||||
|
||||
/* libAttachSQL driver operations */
|
||||
|
||||
static int attachsql_drv_init(void);
|
||||
static int attachsql_drv_describe(drv_caps_t *);
|
||||
static int attachsql_drv_connect(db_conn_t *);
|
||||
static int attachsql_drv_disconnect(db_conn_t *);
|
||||
static int attachsql_drv_prepare(db_stmt_t *, const char *, size_t);
|
||||
static int attachsql_drv_bind_param(db_stmt_t *, db_bind_t *, size_t);
|
||||
static int attachsql_drv_bind_result(db_stmt_t *, db_bind_t *, size_t);
|
||||
static db_error_t attachsql_drv_execute(db_stmt_t *, db_result_t *);
|
||||
static int attachsql_drv_fetch(db_result_t *);
|
||||
static int attachsql_drv_fetch_row(db_result_t *, db_row_t *);
|
||||
static db_error_t attachsql_drv_query(db_conn_t *, const char *, size_t,
|
||||
db_result_t *);
|
||||
static int attachsql_drv_free_results(db_result_t *);
|
||||
static int attachsql_drv_close(db_stmt_t *);
|
||||
static int attachsql_drv_store_results(db_result_t *);
|
||||
static int attachsql_drv_done(void);
|
||||
|
||||
/* libAttachSQL driver definition */
|
||||
|
||||
static db_driver_t attachsql_driver =
|
||||
{
|
||||
.sname = "attachsql",
|
||||
.lname = "libAttachSQL driver",
|
||||
.args = attachsql_drv_args,
|
||||
.ops =
|
||||
{
|
||||
.init = attachsql_drv_init,
|
||||
.describe = attachsql_drv_describe,
|
||||
.connect = attachsql_drv_connect,
|
||||
.disconnect = attachsql_drv_disconnect,
|
||||
.prepare = attachsql_drv_prepare,
|
||||
.bind_param = attachsql_drv_bind_param,
|
||||
.bind_result = attachsql_drv_bind_result,
|
||||
.execute = attachsql_drv_execute,
|
||||
.fetch = attachsql_drv_fetch,
|
||||
.fetch_row = attachsql_drv_fetch_row,
|
||||
.free_results = attachsql_drv_free_results,
|
||||
.close = attachsql_drv_close,
|
||||
.query = attachsql_drv_query,
|
||||
.store_results = attachsql_drv_store_results,
|
||||
.done = attachsql_drv_done
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/* Local functions */
|
||||
|
||||
/* Register libAttachSQL driver */
|
||||
|
||||
|
||||
int register_driver_attachsql(sb_list_t *drivers)
|
||||
{
|
||||
SB_LIST_ADD_TAIL(&attachsql_driver.listitem, drivers);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/* libAttachSQL driver initialization */
|
||||
|
||||
|
||||
int attachsql_drv_init(void)
|
||||
{
|
||||
args.hosts = sb_get_value_list("attachsql-host");
|
||||
if (SB_LIST_IS_EMPTY(args.hosts))
|
||||
{
|
||||
log_text(LOG_FATAL, "No libAttachSQL hosts specified, aborting");
|
||||
return 1;
|
||||
}
|
||||
hosts_pos = args.hosts;
|
||||
pthread_mutex_init(&hosts_mutex, NULL);
|
||||
|
||||
args.port = (unsigned int)sb_get_value_int("attachsql-port");
|
||||
args.socket = sb_get_value_string("attachsql-socket");
|
||||
args.user = sb_get_value_string("attachsql-user");
|
||||
args.password = sb_get_value_string("attachsql-password");
|
||||
args.db = sb_get_value_string("attachsql-db");
|
||||
attachsql_library_init();
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/* Describe database capabilities (possibly depending on table type) */
|
||||
|
||||
|
||||
int attachsql_drv_describe(drv_caps_t *caps )
|
||||
{
|
||||
*caps = attachsql_drv_caps;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/* Connect to libAttachSQL database */
|
||||
|
||||
|
||||
int attachsql_drv_connect(db_conn_t *sb_conn)
|
||||
{
|
||||
attachsql_connect_t *con= NULL;
|
||||
const char *host;
|
||||
attachsql_error_t *error= NULL;
|
||||
attachsql_return_t aret= ATTACHSQL_RETURN_NONE;
|
||||
|
||||
if (args.socket)
|
||||
{
|
||||
DEBUG("attachsql_connect_create(\"%s\", \"%s\", \"%s\", \"%s\")",
|
||||
args.socket,
|
||||
args.user,
|
||||
args.password,
|
||||
args.db);
|
||||
con= attachsql_connect_create(args.socket,
|
||||
0,
|
||||
args.user,
|
||||
args.password,
|
||||
args.db,
|
||||
&error);
|
||||
} else {
|
||||
|
||||
pthread_mutex_lock(&hosts_mutex);
|
||||
hosts_pos = SB_LIST_ITEM_NEXT(hosts_pos);
|
||||
if (hosts_pos == args.hosts)
|
||||
hosts_pos = SB_LIST_ITEM_NEXT(hosts_pos);
|
||||
host = SB_LIST_ENTRY(hosts_pos, value_t, listitem)->data;
|
||||
pthread_mutex_unlock(&hosts_mutex);
|
||||
|
||||
DEBUG("attachsql_connect_create(\"%s\", %u, \"%s\", \"%s\", \"%s\")",
|
||||
host,
|
||||
args.port,
|
||||
args.user,
|
||||
args.password,
|
||||
args.db);
|
||||
con= attachsql_connect_create(host,
|
||||
args.port,
|
||||
args.user,
|
||||
args.password,
|
||||
args.db,
|
||||
&error);
|
||||
}
|
||||
if (con == NULL)
|
||||
{
|
||||
log_text(LOG_FATAL, "unable to Add libAttachSQL Connection, aborting...");
|
||||
log_text(LOG_FATAL, "error %d: %s", attachsql_error_code(error), attachsql_error_message(error));
|
||||
attachsql_error_free(error);
|
||||
return 1;
|
||||
}
|
||||
attachsql_connect_set_option(con, ATTACHSQL_OPTION_SEMI_BLOCKING, NULL);
|
||||
|
||||
if (!attachsql_connect(con, &error))
|
||||
{
|
||||
log_text(LOG_FATAL, "unable to connect to libAttachSQL server");
|
||||
log_text(LOG_FATAL, "error %d: %s", attachsql_error_code(error), attachsql_error_message(error));
|
||||
attachsql_error_free(error);
|
||||
attachsql_connect_destroy(con);
|
||||
return 1;
|
||||
|
||||
}
|
||||
|
||||
while (aret != ATTACHSQL_RETURN_IDLE)
|
||||
{
|
||||
aret = attachsql_connect_poll(con, &error);
|
||||
|
||||
if (error)
|
||||
{
|
||||
log_text(LOG_FATAL, "unable to connect to libAttachSQL server");
|
||||
log_text(LOG_FATAL, "error %d: %s", attachsql_error_code(error), attachsql_error_message(error));
|
||||
attachsql_error_free(error);
|
||||
attachsql_connect_destroy(con);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
sb_conn->ptr = con;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/* Disconnect from libAttachSQL database */
|
||||
|
||||
|
||||
int attachsql_drv_disconnect(db_conn_t *sb_conn)
|
||||
{
|
||||
attachsql_connect_t *con = (attachsql_connect_t *)sb_conn->ptr;
|
||||
|
||||
if (con != NULL)
|
||||
{
|
||||
DEBUG("attachsql_connect_destroy(%p)", con);
|
||||
attachsql_connect_destroy(con);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/* Prepare statement */
|
||||
|
||||
|
||||
int attachsql_drv_prepare(db_stmt_t *stmt, const char *query, size_t len)
|
||||
{
|
||||
attachsql_connect_t *con= (attachsql_connect_t *)stmt->connection->ptr;
|
||||
attachsql_error_t *error= NULL;
|
||||
attachsql_return_t aret= ATTACHSQL_RETURN_NONE;
|
||||
attachsql_statement_prepare(con, len, query, &error);
|
||||
while(aret != ATTACHSQL_RETURN_EOF)
|
||||
{
|
||||
aret= attachsql_connect_poll(con, &error);
|
||||
if (error)
|
||||
{
|
||||
log_text(LOG_ALERT, "libAttachSQL Prepare Failed: %u:%s", attachsql_error_code(error), attachsql_error_message(error));
|
||||
attachsql_error_free(error);
|
||||
return DB_ERROR_FATAL;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/* Bind parameters for prepared statement */
|
||||
int attachsql_drv_bind_param(db_stmt_t *stmt, db_bind_t *params, size_t len)
|
||||
{
|
||||
/* libAttachSQL doesn't do this, you do this during execute
|
||||
* this is because sysbench doesn't set the values until that time
|
||||
*/
|
||||
|
||||
if (stmt->bound_param != NULL)
|
||||
free(stmt->bound_param);
|
||||
stmt->bound_param = (db_bind_t *)malloc(len * sizeof(db_bind_t));
|
||||
if (stmt->bound_param == NULL)
|
||||
return 1;
|
||||
memcpy(stmt->bound_param, params, len * sizeof(db_bind_t));
|
||||
stmt->bound_param_len = len;
|
||||
|
||||
return 0;
|
||||
|
||||
}
|
||||
|
||||
|
||||
/* Bind results for prepared statement */
|
||||
int attachsql_drv_bind_result(db_stmt_t *stmt, db_bind_t *params, size_t len)
|
||||
{
|
||||
(void)stmt;
|
||||
(void)params;
|
||||
(void)len;
|
||||
/* libAttachSQL doesn't do this, you get after execute */
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/* Execute prepared statement */
|
||||
|
||||
|
||||
db_error_t attachsql_drv_execute(db_stmt_t *stmt, db_result_t *rs)
|
||||
{
|
||||
(void) rs;
|
||||
attachsql_connect_t *con= (attachsql_connect_t *)stmt->connection->ptr;
|
||||
attachsql_return_t aret= ATTACHSQL_RETURN_NONE;
|
||||
attachsql_error_t *error= NULL;
|
||||
|
||||
uint16_t i;
|
||||
int8_t tinyint;
|
||||
int16_t smallint;
|
||||
int32_t normalint;
|
||||
int64_t bigint;
|
||||
float float_type;
|
||||
double double_type;
|
||||
db_time_t *time_data;
|
||||
if (con == NULL)
|
||||
return 1;
|
||||
|
||||
for (i= 0; i < stmt->bound_param_len; i++)
|
||||
{
|
||||
db_bind_t *param= &stmt->bound_param[i];
|
||||
switch(param->type)
|
||||
{
|
||||
case DB_TYPE_TINYINT:
|
||||
tinyint= *(int8_t*)param->buffer;
|
||||
attachsql_statement_set_int(con, i, tinyint, NULL);
|
||||
break;
|
||||
case DB_TYPE_SMALLINT:
|
||||
smallint= *(int16_t*)param->buffer;
|
||||
attachsql_statement_set_int(con, i, smallint, NULL);
|
||||
break;
|
||||
case DB_TYPE_INT:
|
||||
normalint= *(int32_t*)param->buffer;
|
||||
attachsql_statement_set_int(con, i, normalint, NULL);
|
||||
break;
|
||||
case DB_TYPE_BIGINT:
|
||||
bigint= *(int64_t*)param->buffer;
|
||||
attachsql_statement_set_bigint(con, i, bigint, NULL);
|
||||
break;
|
||||
case DB_TYPE_FLOAT:
|
||||
float_type= *(float*)param->buffer;
|
||||
attachsql_statement_set_float(con, i, float_type, NULL);
|
||||
break;
|
||||
case DB_TYPE_DOUBLE:
|
||||
double_type= *(double*)param->buffer;
|
||||
attachsql_statement_set_double(con, i, double_type, NULL);
|
||||
break;
|
||||
case DB_TYPE_TIME:
|
||||
time_data= (db_time_t*)param->buffer;
|
||||
attachsql_statement_set_time(con, i, time_data->hour, time_data->minute, time_data->second, 0, false, NULL);
|
||||
break;
|
||||
case DB_TYPE_DATE:
|
||||
case DB_TYPE_DATETIME:
|
||||
case DB_TYPE_TIMESTAMP:
|
||||
time_data= (db_time_t*)param->buffer;
|
||||
attachsql_statement_set_datetime(con, i, time_data->year, time_data->month, time_data->day, time_data->hour, time_data->minute, time_data->second, 0, NULL);
|
||||
break;
|
||||
case DB_TYPE_CHAR:
|
||||
case DB_TYPE_VARCHAR:
|
||||
attachsql_statement_set_string(con, i, param->max_len, param->buffer, NULL);
|
||||
case DB_TYPE_NONE:
|
||||
default:
|
||||
attachsql_statement_set_null(con, i, NULL);
|
||||
/* Not supported */
|
||||
}
|
||||
}
|
||||
|
||||
attachsql_statement_execute(con, &error);
|
||||
|
||||
while(aret != ATTACHSQL_RETURN_EOF)
|
||||
{
|
||||
aret= attachsql_connect_poll(con, &error);
|
||||
if (aret == ATTACHSQL_RETURN_ROW_READY)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
if (error)
|
||||
{
|
||||
log_text(LOG_ALERT, "libAttachSQL Execute Failed: %u:%s", attachsql_error_code(error), attachsql_error_message(error));
|
||||
attachsql_error_free(error);
|
||||
return DB_ERROR_FATAL;
|
||||
}
|
||||
}
|
||||
|
||||
return DB_ERROR_NONE;
|
||||
}
|
||||
|
||||
|
||||
/* Execute SQL query */
|
||||
|
||||
|
||||
db_error_t attachsql_drv_query(db_conn_t *sb_conn, const char *query,
|
||||
size_t len, db_result_t *rs)
|
||||
{
|
||||
(void) rs;
|
||||
attachsql_connect_t *con = sb_conn->ptr;
|
||||
unsigned int rc;
|
||||
attachsql_error_t *error= NULL;
|
||||
attachsql_return_t aret= ATTACHSQL_RETURN_NONE;
|
||||
|
||||
/* Close any previous query */
|
||||
attachsql_query_close(con);
|
||||
|
||||
DEBUG("attachsql_query(%p, \"%s\", %u)",
|
||||
con,
|
||||
query,
|
||||
len);
|
||||
attachsql_query(con, len, query, 0, NULL, &error);
|
||||
|
||||
while((aret != ATTACHSQL_RETURN_EOF) && (aret != ATTACHSQL_RETURN_ROW_READY))
|
||||
{
|
||||
aret= attachsql_connect_poll(con, &error);
|
||||
|
||||
if (error)
|
||||
{
|
||||
rc= attachsql_error_code(error);
|
||||
if (rc == 1213 || rc == 1205 || rc == 1020)
|
||||
{
|
||||
attachsql_error_free(error);
|
||||
return DB_ERROR_IGNORABLE;
|
||||
}
|
||||
log_text(LOG_ALERT, "libAttachSQL Query Failed: %u:%s", attachsql_error_code(error), attachsql_error_message(error));
|
||||
attachsql_error_free(error);
|
||||
return DB_ERROR_FATAL;
|
||||
}
|
||||
}
|
||||
//rs->connection->ptr= con;
|
||||
DEBUG("attachsql_query \"%s\" returned %d", query, aret);
|
||||
|
||||
return DB_ERROR_NONE;
|
||||
}
|
||||
|
||||
|
||||
/* Fetch row from result set of a prepared statement */
|
||||
|
||||
|
||||
int attachsql_drv_fetch(db_result_t *rs)
|
||||
{
|
||||
/* NYI */
|
||||
attachsql_connect_t *con = rs->connection->ptr;
|
||||
size_t tmp_len;
|
||||
uint16_t columns, col;
|
||||
attachsql_return_t aret= ATTACHSQL_RETURN_NONE;
|
||||
attachsql_error_t *error= NULL;
|
||||
|
||||
while((aret != ATTACHSQL_RETURN_EOF) && (aret != ATTACHSQL_RETURN_ROW_READY))
|
||||
{
|
||||
aret= attachsql_connect_poll(con, &error);
|
||||
|
||||
if (error)
|
||||
{
|
||||
log_text(LOG_ALERT, "libAttachSQL Query Failed: %u:%s", attachsql_error_code(error), attachsql_error_message(error));
|
||||
attachsql_error_free(error);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
if (aret == ATTACHSQL_RETURN_EOF)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
attachsql_statement_row_get(con, NULL);
|
||||
columns= attachsql_query_column_count(con);
|
||||
for (col= 0; col < columns; col++)
|
||||
{
|
||||
switch (attachsql_statement_get_column_type(con, col))
|
||||
{
|
||||
case ATTACHSQL_COLUMN_TYPE_TINY:
|
||||
case ATTACHSQL_COLUMN_TYPE_SHORT:
|
||||
case ATTACHSQL_COLUMN_TYPE_LONG:
|
||||
case ATTACHSQL_COLUMN_TYPE_YEAR:
|
||||
case ATTACHSQL_COLUMN_TYPE_INT24:
|
||||
attachsql_statement_get_int(con, col, &error);
|
||||
break;
|
||||
case ATTACHSQL_COLUMN_TYPE_LONGLONG:
|
||||
attachsql_statement_get_bigint(con, col, &error);
|
||||
break;
|
||||
case ATTACHSQL_COLUMN_TYPE_FLOAT:
|
||||
attachsql_statement_get_float(con, col, &error);
|
||||
break;
|
||||
case ATTACHSQL_COLUMN_TYPE_DOUBLE:
|
||||
attachsql_statement_get_double(con, col, &error);
|
||||
break;
|
||||
default:
|
||||
attachsql_statement_get_char(con, col, &tmp_len, &error);
|
||||
break;
|
||||
}
|
||||
}
|
||||
attachsql_query_row_next(con);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/* Fetch row from result set of a query */
|
||||
|
||||
|
||||
int attachsql_drv_fetch_row(db_result_t *rs, db_row_t *row)
|
||||
{
|
||||
attachsql_error_t *error= NULL;
|
||||
attachsql_return_t aret= ATTACHSQL_RETURN_NONE;
|
||||
|
||||
/* NYI */
|
||||
|
||||
attachsql_connect_t *con = rs->connection->ptr;
|
||||
|
||||
while((aret != ATTACHSQL_RETURN_EOF) && (aret != ATTACHSQL_RETURN_ROW_READY))
|
||||
{
|
||||
aret= attachsql_connect_poll(con, &error);
|
||||
|
||||
if (error)
|
||||
{
|
||||
log_text(LOG_ALERT, "libAttachSQL Query Failed: %u:%s", attachsql_error_code(error), attachsql_error_message(error));
|
||||
attachsql_error_free(error);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
if (aret == ATTACHSQL_RETURN_EOF)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
row->ptr= attachsql_query_row_get(con, NULL);
|
||||
attachsql_query_row_next(con);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/* Store results from the last query */
|
||||
|
||||
|
||||
int attachsql_drv_store_results(db_result_t *rs)
|
||||
{
|
||||
int ret= 0;
|
||||
db_row_t row;
|
||||
/* libAttachSQL can't do things in this order */
|
||||
while (ret == 0)
|
||||
{
|
||||
if (rs->statement != NULL)
|
||||
{
|
||||
ret= attachsql_drv_fetch(rs);
|
||||
}
|
||||
else
|
||||
{
|
||||
ret= attachsql_drv_fetch_row(rs, &row);
|
||||
}
|
||||
}
|
||||
|
||||
return DB_ERROR_NONE;
|
||||
}
|
||||
|
||||
|
||||
/* Free result set */
|
||||
|
||||
|
||||
int attachsql_drv_free_results(db_result_t *rs)
|
||||
{
|
||||
|
||||
if (rs->connection->ptr != NULL)
|
||||
{
|
||||
DEBUG("attachsql_query_close(%p)", rs->connection->ptr);
|
||||
attachsql_query_close(rs->connection->ptr);
|
||||
rs->connection->ptr = NULL;
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
/* Close prepared statement */
|
||||
|
||||
|
||||
int attachsql_drv_close(db_stmt_t *stmt)
|
||||
{
|
||||
attachsql_connect_t *con= (attachsql_connect_t *)stmt->connection->ptr;
|
||||
attachsql_statement_close(con);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/* Uninitialize driver */
|
||||
int attachsql_drv_done(void)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
@ -0,0 +1,19 @@
|
|||
# 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; either version 2 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, write to the Free Software
|
||||
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
|
||||
noinst_LIBRARIES = libsbdrizzle.a
|
||||
|
||||
libsbdrizzle_a_SOURCES = drv_drizzle.c
|
||||
|
|
@ -0,0 +1,706 @@
|
|||
/* 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; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
# include "config.h"
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_STRING_H
|
||||
# include <string.h>
|
||||
#endif
|
||||
#ifdef HAVE_STRINGS_H
|
||||
# include <strings.h>
|
||||
#endif
|
||||
#include <stdio.h>
|
||||
|
||||
#include <libdrizzle/drizzle_client.h>
|
||||
|
||||
#include "sb_options.h"
|
||||
|
||||
#include "db_driver.h"
|
||||
|
||||
#define DEBUG(format, ...) do { if (db_globals.debug) log_text(LOG_DEBUG, format, __VA_ARGS__); } while (0)
|
||||
|
||||
/* Drizzle driver arguments */
|
||||
|
||||
static sb_arg_t drizzle_drv_args[] =
|
||||
{
|
||||
{"drizzle-host", "Drizzle server host", SB_ARG_TYPE_LIST, "localhost"},
|
||||
{"drizzle-port", "Drizzle server port", SB_ARG_TYPE_INT, "4427"},
|
||||
{"drizzle-socket", "Drizzle socket", SB_ARG_TYPE_STRING, NULL},
|
||||
{"drizzle-user", "Drizzle user", SB_ARG_TYPE_STRING, ""},
|
||||
{"drizzle-password", "Drizzle password", SB_ARG_TYPE_STRING, ""},
|
||||
{"drizzle-db", "Drizzle database name", SB_ARG_TYPE_STRING, "sbtest"},
|
||||
{"drizzle-buffer", "Level of library buffering (none, field, row, all)", SB_ARG_TYPE_STRING, "none"},
|
||||
{"drizzle-mysql", "Use MySQL Protocol", SB_ARG_TYPE_BOOL, "off"},
|
||||
|
||||
{NULL, NULL, SB_ARG_TYPE_NULL, NULL}
|
||||
};
|
||||
|
||||
typedef enum
|
||||
{
|
||||
BUFFER_NONE,
|
||||
BUFFER_FIELD,
|
||||
BUFFER_ROW,
|
||||
BUFFER_ALL
|
||||
} buffer_level;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
sb_list_t *hosts;
|
||||
unsigned int port;
|
||||
char *socket;
|
||||
char *user;
|
||||
char *password;
|
||||
char *db;
|
||||
buffer_level buffer;
|
||||
int mysql;
|
||||
} drizzle_drv_args_t;
|
||||
|
||||
/* Drizzle driver capabilities */
|
||||
|
||||
static drv_caps_t drizzle_drv_caps =
|
||||
{
|
||||
.multi_rows_insert = 1,
|
||||
.prepared_statements = 0,
|
||||
.auto_increment = 1,
|
||||
.serial = 0,
|
||||
.unsigned_int = 0,
|
||||
};
|
||||
|
||||
static drizzle_drv_args_t args; /* driver args */
|
||||
|
||||
static sb_list_item_t *hosts_pos;
|
||||
|
||||
static pthread_mutex_t hosts_mutex;
|
||||
|
||||
static void column_info(drizzle_column_st *column);
|
||||
|
||||
/* Drizzle driver operations */
|
||||
|
||||
static int drizzle_drv_init(void);
|
||||
static int drizzle_drv_describe(drv_caps_t *);
|
||||
static int drizzle_drv_connect(db_conn_t *);
|
||||
static int drizzle_drv_disconnect(db_conn_t *);
|
||||
static int drizzle_drv_prepare(db_stmt_t *, const char *, size_t);
|
||||
static int drizzle_drv_bind_param(db_stmt_t *, db_bind_t *, size_t);
|
||||
static int drizzle_drv_bind_result(db_stmt_t *, db_bind_t *, size_t);
|
||||
static db_error_t drizzle_drv_execute(db_stmt_t *, db_result_t *);
|
||||
static int drizzle_drv_fetch(db_result_t *);
|
||||
static int drizzle_drv_fetch_row(db_result_t *, db_row_t *);
|
||||
static db_error_t drizzle_drv_query(db_conn_t *, const char *, size_t,
|
||||
db_result_t *);
|
||||
static int drizzle_drv_free_results(db_result_t *);
|
||||
static int drizzle_drv_close(db_stmt_t *);
|
||||
static int drizzle_drv_store_results(db_result_t *);
|
||||
static int drizzle_drv_done(void);
|
||||
|
||||
/* Drizzle driver definition */
|
||||
|
||||
static db_driver_t drizzle_driver =
|
||||
{
|
||||
.sname = "drizzle",
|
||||
.lname = "Drizzle driver",
|
||||
.args = drizzle_drv_args,
|
||||
.ops =
|
||||
{
|
||||
.init = drizzle_drv_init,
|
||||
.describe = drizzle_drv_describe,
|
||||
.connect = drizzle_drv_connect,
|
||||
.disconnect = drizzle_drv_disconnect,
|
||||
.prepare = drizzle_drv_prepare,
|
||||
.bind_param = drizzle_drv_bind_param,
|
||||
.bind_result = drizzle_drv_bind_result,
|
||||
.execute = drizzle_drv_execute,
|
||||
.fetch = drizzle_drv_fetch,
|
||||
.fetch_row = drizzle_drv_fetch_row,
|
||||
.free_results = drizzle_drv_free_results,
|
||||
.close = drizzle_drv_close,
|
||||
.query = drizzle_drv_query,
|
||||
.store_results = drizzle_drv_store_results,
|
||||
.done = drizzle_drv_done
|
||||
},
|
||||
};
|
||||
|
||||
|
||||
/* Local functions */
|
||||
|
||||
/* Register Drizzle driver */
|
||||
|
||||
|
||||
int register_driver_drizzle(sb_list_t *drivers)
|
||||
{
|
||||
SB_LIST_ADD_TAIL(&drizzle_driver.listitem, drivers);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/* Drizzle driver initialization */
|
||||
|
||||
|
||||
int drizzle_drv_init(void)
|
||||
{
|
||||
char *s;
|
||||
|
||||
args.hosts = sb_get_value_list("drizzle-host");
|
||||
if (SB_LIST_IS_EMPTY(args.hosts))
|
||||
{
|
||||
log_text(LOG_FATAL, "No Drizzle hosts specified, aborting");
|
||||
return 1;
|
||||
}
|
||||
hosts_pos = args.hosts;
|
||||
pthread_mutex_init(&hosts_mutex, NULL);
|
||||
|
||||
args.port = (unsigned int)sb_get_value_int("drizzle-port");
|
||||
args.socket = sb_get_value_string("drizzle-socket");
|
||||
args.user = sb_get_value_string("drizzle-user");
|
||||
args.password = sb_get_value_string("drizzle-password");
|
||||
args.db = sb_get_value_string("drizzle-db");
|
||||
s= sb_get_value_string("drizzle-buffer");
|
||||
if (!strcasecmp(s, "none"))
|
||||
args.buffer= BUFFER_NONE;
|
||||
else if (!strcasecmp(s, "field"))
|
||||
args.buffer= BUFFER_FIELD;
|
||||
else if (!strcasecmp(s, "row"))
|
||||
args.buffer= BUFFER_ROW;
|
||||
else if (!strcasecmp(s, "all"))
|
||||
args.buffer= BUFFER_ALL;
|
||||
|
||||
args.mysql= sb_get_value_flag("drizzle-mysql");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/* Describe database capabilities (possibly depending on table type) */
|
||||
|
||||
|
||||
int drizzle_drv_describe(drv_caps_t *caps )
|
||||
{
|
||||
*caps = drizzle_drv_caps;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/* Connect to Drizzle database */
|
||||
|
||||
|
||||
int drizzle_drv_connect(db_conn_t *sb_conn)
|
||||
{
|
||||
drizzle_st *drizzle_lib= NULL;
|
||||
drizzle_con_st *con= NULL;
|
||||
const char *host;
|
||||
drizzle_return_t ret;
|
||||
|
||||
drizzle_lib= drizzle_create(drizzle_lib);
|
||||
|
||||
if (args.socket)
|
||||
{
|
||||
DEBUG("drizzle_con_add_uds(%p, %p \"%s\", \"%s\", \"%s\", \"%s\", %d)",
|
||||
drizzle_lib,
|
||||
con,
|
||||
args.socket,
|
||||
args.user,
|
||||
args.password,
|
||||
args.db,
|
||||
args.mysql ? DRIZZLE_CON_MYSQL : 0);
|
||||
con= drizzle_con_add_uds(drizzle_lib,
|
||||
con,
|
||||
args.socket,
|
||||
args.user,
|
||||
args.password,
|
||||
args.db,
|
||||
args.mysql ? DRIZZLE_CON_MYSQL : 0);
|
||||
} else {
|
||||
|
||||
pthread_mutex_lock(&hosts_mutex);
|
||||
hosts_pos = SB_LIST_ITEM_NEXT(hosts_pos);
|
||||
if (hosts_pos == args.hosts)
|
||||
hosts_pos = SB_LIST_ITEM_NEXT(hosts_pos);
|
||||
host = SB_LIST_ENTRY(hosts_pos, value_t, listitem)->data;
|
||||
pthread_mutex_unlock(&hosts_mutex);
|
||||
|
||||
DEBUG("drizzle_con_add_tcp(%p, %p \"%s\", %u, \"%s\", \"%s\", \"%s\", %d)",
|
||||
drizzle_lib,
|
||||
con,
|
||||
host,
|
||||
args.port,
|
||||
args.user,
|
||||
args.password,
|
||||
args.db,
|
||||
args.mysql ? DRIZZLE_CON_MYSQL : 0);
|
||||
con= drizzle_con_add_tcp(drizzle_lib,
|
||||
con,
|
||||
host,
|
||||
args.port,
|
||||
args.user,
|
||||
args.password,
|
||||
args.db,
|
||||
args.mysql ? DRIZZLE_CON_MYSQL : 0);
|
||||
}
|
||||
|
||||
if (con == NULL)
|
||||
{
|
||||
log_text(LOG_FATAL, "unable to Add Drizzle Connection, aborting...");
|
||||
log_text(LOG_FATAL, "error %d: %s", drizzle_errno(drizzle_lib),
|
||||
drizzle_error(drizzle_lib));
|
||||
return 1;
|
||||
}
|
||||
if ((ret= drizzle_con_connect(con)) != DRIZZLE_RETURN_OK)
|
||||
{
|
||||
log_text(LOG_FATAL, "unable to connect to Drizzle server: %d", ret);
|
||||
log_text(LOG_FATAL, "error %d: %s", drizzle_errno(drizzle_lib),
|
||||
drizzle_error(drizzle_lib));
|
||||
free(con);
|
||||
return 1;
|
||||
|
||||
}
|
||||
sb_conn->ptr = con;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/* Disconnect from Drizzle database */
|
||||
|
||||
|
||||
int drizzle_drv_disconnect(db_conn_t *sb_conn)
|
||||
{
|
||||
drizzle_con_st *con = (drizzle_con_st *)sb_conn->ptr;
|
||||
|
||||
if (con != NULL)
|
||||
{
|
||||
DEBUG("drizzle_close(%p)", con);
|
||||
drizzle_con_close(con);
|
||||
free(con);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/* Prepare statement */
|
||||
|
||||
|
||||
int drizzle_drv_prepare(db_stmt_t *stmt, const char *query, size_t len)
|
||||
{
|
||||
|
||||
(void) len; /* unused */
|
||||
|
||||
/* Use client-side PS */
|
||||
stmt->emulated = 1;
|
||||
stmt->query = strdup(query);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/* Bind parameters for prepared statement */
|
||||
int drizzle_drv_bind_param(db_stmt_t *stmt, db_bind_t *params, size_t len)
|
||||
{
|
||||
drizzle_con_st *con = (drizzle_con_st *)stmt->connection->ptr;
|
||||
|
||||
if (con == NULL)
|
||||
return 1;
|
||||
|
||||
/* Use emulation */
|
||||
if (stmt->bound_param != NULL)
|
||||
free(stmt->bound_param);
|
||||
stmt->bound_param = (db_bind_t *)malloc(len * sizeof(db_bind_t));
|
||||
if (stmt->bound_param == NULL)
|
||||
return 1;
|
||||
memcpy(stmt->bound_param, params, len * sizeof(db_bind_t));
|
||||
stmt->bound_param_len = len;
|
||||
|
||||
return 0;
|
||||
|
||||
}
|
||||
|
||||
|
||||
/* Bind results for prepared statement */
|
||||
int drizzle_drv_bind_result(db_stmt_t *stmt, db_bind_t *params, size_t len)
|
||||
{
|
||||
(void)stmt;
|
||||
(void)params;
|
||||
(void)len;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/* Execute prepared statement */
|
||||
|
||||
|
||||
db_error_t drizzle_drv_execute(db_stmt_t *stmt, db_result_t *rs)
|
||||
{
|
||||
db_conn_t *con = stmt->connection;
|
||||
char *buf = NULL;
|
||||
unsigned int buflen = 0;
|
||||
unsigned int i, j, vcnt;
|
||||
char need_realloc;
|
||||
int n;
|
||||
|
||||
/* Use emulation */
|
||||
/* Build the actual query string from parameters list */
|
||||
need_realloc = 1;
|
||||
vcnt = 0;
|
||||
for (i = 0, j = 0; stmt->query[i] != '\0'; i++)
|
||||
{
|
||||
again:
|
||||
if (j+1 >= buflen || need_realloc)
|
||||
{
|
||||
buflen = (buflen > 0) ? buflen * 2 : 256;
|
||||
buf = realloc(buf, buflen);
|
||||
if (buf == NULL)
|
||||
{
|
||||
log_text(LOG_DEBUG, "ERROR: exiting drizzle_drv_execute(), memory allocation failure");
|
||||
return DB_ERROR_FATAL;
|
||||
}
|
||||
need_realloc = 0;
|
||||
}
|
||||
|
||||
if (stmt->query[i] != '?')
|
||||
{
|
||||
buf[j++] = stmt->query[i];
|
||||
continue;
|
||||
}
|
||||
|
||||
n = db_print_value(stmt->bound_param + vcnt, buf + j, (int)(buflen - j));
|
||||
if (n < 0)
|
||||
{
|
||||
need_realloc = 1;
|
||||
goto again;
|
||||
}
|
||||
j += (unsigned int)n;
|
||||
vcnt++;
|
||||
}
|
||||
buf[j] = '\0';
|
||||
|
||||
con->error = drizzle_drv_query(con, buf, j, rs);
|
||||
free(buf);
|
||||
if (con->error != DB_ERROR_NONE)
|
||||
{
|
||||
log_text(LOG_DEBUG, "ERROR: exiting drizzle_drv_execute(), database error");
|
||||
return con->error;
|
||||
}
|
||||
|
||||
return DB_ERROR_NONE;
|
||||
}
|
||||
|
||||
|
||||
/* Execute SQL query */
|
||||
|
||||
|
||||
db_error_t drizzle_drv_query(db_conn_t *sb_conn, const char *query, size_t len,
|
||||
db_result_t *rs)
|
||||
{
|
||||
drizzle_con_st *con = sb_conn->ptr;
|
||||
unsigned int rc;
|
||||
drizzle_return_t ret;
|
||||
drizzle_result_st *result= NULL;
|
||||
|
||||
DEBUG("drizzle_query(%p, %p, \"%s\", %u, %p)",
|
||||
con,
|
||||
result,
|
||||
query,
|
||||
len,
|
||||
&ret);
|
||||
result= drizzle_query(con, NULL, query, len, &ret);
|
||||
DEBUG("drizzle_query(%p) == %d", con, ret);
|
||||
|
||||
if (ret == DRIZZLE_RETURN_ERROR_CODE)
|
||||
{
|
||||
rc= drizzle_result_error_code(result);
|
||||
/* Error code constants haven't been added yet to libdrizzle
|
||||
ER_LOCK_DEADLOCK==1213
|
||||
ER_LOCK_WAIT_TIMEOUT==1205
|
||||
ER_CHECKREAD==1020
|
||||
*/
|
||||
if (rc == 1213 || rc == 1205 ||
|
||||
rc == 1020)
|
||||
return DB_ERROR_IGNORABLE;
|
||||
log_text(LOG_ALERT, "Drizzle Query Failed: %u:%s",
|
||||
drizzle_result_error_code(result),
|
||||
drizzle_result_error(result));
|
||||
return DB_ERROR_FATAL;
|
||||
}
|
||||
else if (ret != DRIZZLE_RETURN_OK)
|
||||
{
|
||||
rc = drizzle_con_errno(con);
|
||||
DEBUG("drizzle_errno(%p) = %u", drizzle_con_drizzle(con), rc);
|
||||
log_text(LOG_ALERT, "failed to execute Drizzle query: len==%d `%s`:",
|
||||
strlen(query), query);
|
||||
log_text(LOG_ALERT, "Error %d %s", drizzle_con_errno(con),
|
||||
drizzle_con_error(con));
|
||||
return DB_ERROR_FATAL;
|
||||
}
|
||||
DEBUG("drizzle_query \"%s\" returned %d", query, ret);
|
||||
|
||||
if (result == NULL)
|
||||
{
|
||||
DEBUG("drizzle_query(%p, \"%s\") == NULL",con,query);
|
||||
return DB_ERROR_FATAL;
|
||||
}
|
||||
|
||||
|
||||
rs->ptr= result;
|
||||
rs->nrows= drizzle_result_row_count(result);
|
||||
DEBUG("drizzle_result_row_count(%p) == %d",result,rs->nrows);
|
||||
|
||||
return DB_ERROR_NONE;
|
||||
}
|
||||
|
||||
|
||||
/* Fetch row from result set of a prepared statement */
|
||||
|
||||
|
||||
int drizzle_drv_fetch(db_result_t *rs)
|
||||
{
|
||||
/* NYI */
|
||||
(void)rs;
|
||||
printf("in drizzle_drv_fetch_row!\n");
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
/* Fetch row from result set of a query */
|
||||
|
||||
|
||||
int drizzle_drv_fetch_row(db_result_t *rs, db_row_t *row)
|
||||
{
|
||||
/* NYI */
|
||||
printf("in drizzle_drv_fetch_row!\n");
|
||||
(void)rs; /* unused */
|
||||
(void)row; /* unused */
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
/* Store results from the last query */
|
||||
|
||||
|
||||
int drizzle_drv_store_results(db_result_t *rs)
|
||||
{
|
||||
|
||||
drizzle_con_st *con = rs->connection->ptr;
|
||||
drizzle_result_st *res = rs->ptr;
|
||||
drizzle_return_t ret;
|
||||
drizzle_column_st *column= NULL;
|
||||
unsigned int rc;
|
||||
|
||||
|
||||
if (con == NULL || res == NULL)
|
||||
return DB_ERROR_FATAL;
|
||||
|
||||
|
||||
if (args.buffer == BUFFER_ALL)
|
||||
{
|
||||
|
||||
ret= drizzle_result_buffer(res);
|
||||
DEBUG("drizzle_result_buffer(%p) = %d", res, ret);
|
||||
if (ret != DRIZZLE_RETURN_OK)
|
||||
{
|
||||
rc = drizzle_con_errno(con);
|
||||
DEBUG("drizzle_errno(%p) = %u", drizzle_con_drizzle(con), rc);
|
||||
log_text(LOG_ALERT, "drizzle_result_buffer failed: `%p`:", res);
|
||||
log_text(LOG_ALERT, "Error %d %s",
|
||||
drizzle_con_errno(con),
|
||||
drizzle_con_error(con));
|
||||
return DB_ERROR_FATAL;
|
||||
}
|
||||
while ((column = drizzle_column_next(res)) != NULL)
|
||||
column_info(column);
|
||||
}
|
||||
else if (drizzle_result_column_count(res) > 0)
|
||||
{
|
||||
|
||||
drizzle_row_t row;
|
||||
drizzle_field_t field;
|
||||
uint64_t row_num;
|
||||
size_t offset= 0;
|
||||
size_t length;
|
||||
size_t total;
|
||||
|
||||
/* Read column meta-info */
|
||||
while (1)
|
||||
{
|
||||
column= drizzle_column_read(res, column, &ret);
|
||||
DEBUG("drizzle_column_read(%p,%p,%p) == %d",res, column, &ret, ret);
|
||||
if (ret != DRIZZLE_RETURN_OK)
|
||||
{
|
||||
rc = drizzle_con_errno(con);
|
||||
DEBUG("drizzle_errno(%p) = %u", drizzle_con_drizzle(con), rc);
|
||||
log_text(LOG_ALERT, "drizzle_column_read failed: `%p`:", res);
|
||||
log_text(LOG_ALERT, "Error %d %s",
|
||||
drizzle_con_errno(con),
|
||||
drizzle_con_error(con));
|
||||
return DB_ERROR_FATAL;
|
||||
}
|
||||
if (column == NULL)
|
||||
break;
|
||||
|
||||
column_info(column);
|
||||
drizzle_column_free(column);
|
||||
}
|
||||
|
||||
/* Actually fetch rows */
|
||||
while (1) /* Loop for rows */
|
||||
{
|
||||
if (args.buffer == BUFFER_ROW)
|
||||
{
|
||||
row= drizzle_row_buffer(res, &ret);
|
||||
DEBUG("drizzle_row_buffer(%p, %p) == %p, %d",res, &ret, row, ret);
|
||||
if (ret != DRIZZLE_RETURN_OK)
|
||||
{
|
||||
rc = drizzle_con_errno(con);
|
||||
DEBUG("drizzle_errno(%p) = %u", drizzle_con_drizzle(con), rc);
|
||||
log_text(LOG_ALERT, "drizzle_row_buffer failed: `%p`:", res);
|
||||
log_text(LOG_ALERT, "Error %d %s",
|
||||
drizzle_con_errno(con),
|
||||
drizzle_con_error(con));
|
||||
return DB_ERROR_FATAL;
|
||||
}
|
||||
|
||||
if (row == NULL)
|
||||
break;
|
||||
|
||||
DEBUG("drizzle_row_free(%p, %p)",res,row);
|
||||
drizzle_row_free(res, row);
|
||||
}
|
||||
else if (args.buffer == BUFFER_NONE || args.buffer == BUFFER_FIELD)
|
||||
{
|
||||
row_num= drizzle_row_read(res, &ret);
|
||||
DEBUG("drizzle_row_read(%p, %p) == %"PRIu64", %d",
|
||||
res, &ret, row_num, ret);
|
||||
if (ret != DRIZZLE_RETURN_OK)
|
||||
{
|
||||
rc = drizzle_con_errno(con);
|
||||
DEBUG("drizzle_errno(%p) = %u", drizzle_con_drizzle(con), rc);
|
||||
log_text(LOG_ALERT, "drizzle_row_read failed: `%p`:", res);
|
||||
log_text(LOG_ALERT, "Error %d %s",
|
||||
drizzle_con_errno(con),
|
||||
drizzle_con_error(con));
|
||||
return DB_ERROR_FATAL;
|
||||
}
|
||||
|
||||
if (row_num == 0)
|
||||
break;
|
||||
|
||||
while (1) /* Loop for fields */
|
||||
{
|
||||
|
||||
if (args.buffer == BUFFER_FIELD)
|
||||
{
|
||||
/* Since an entire field is buffered, we don't need to worry about
|
||||
partial reads. */
|
||||
field= drizzle_field_buffer(res, &total, &ret);
|
||||
DEBUG("drizzle_field_buffer(%p, &p, %p) == %p, %x, %d",
|
||||
res, &total, &ret, field, total, ret);
|
||||
length= total;
|
||||
}
|
||||
else
|
||||
{
|
||||
field= drizzle_field_read(res, &offset, &length, &total, &ret);
|
||||
DEBUG("drizzle_field_read(%p, %p, %p, %p, %p) == "
|
||||
"%p, %x, %x, %x, %d",
|
||||
res, &offset, &length, &total, &ret,
|
||||
field, offset, length, total, ret);
|
||||
}
|
||||
|
||||
if (ret == DRIZZLE_RETURN_ROW_END)
|
||||
break;
|
||||
else if (ret != DRIZZLE_RETURN_OK)
|
||||
{
|
||||
rc = drizzle_con_errno(con);
|
||||
DEBUG("drizzle_errno(%p) = %u", drizzle_con_drizzle(con), rc);
|
||||
log_text(LOG_ALERT, "drizzle_field_(buffer|read) failed: `%p`:",
|
||||
res);
|
||||
log_text(LOG_ALERT, "Error %d %s",
|
||||
drizzle_con_errno(con),
|
||||
drizzle_con_error(con));
|
||||
return DB_ERROR_FATAL;
|
||||
}
|
||||
|
||||
if (args.buffer == BUFFER_FIELD)
|
||||
drizzle_field_free(field);
|
||||
|
||||
} /* while (1) Loop for fields */
|
||||
|
||||
} /* if (args.buffer) */
|
||||
|
||||
} /* while (1) */
|
||||
}
|
||||
return DB_ERROR_NONE;
|
||||
}
|
||||
|
||||
|
||||
/* Free result set */
|
||||
|
||||
|
||||
int drizzle_drv_free_results(db_result_t *rs)
|
||||
{
|
||||
|
||||
if (rs->ptr != NULL)
|
||||
{
|
||||
DEBUG("drizzle_result_free(%p)", rs->ptr);
|
||||
drizzle_result_free(rs->ptr);
|
||||
rs->ptr = NULL;
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
/* Close prepared statement */
|
||||
|
||||
|
||||
int drizzle_drv_close(db_stmt_t *stmt)
|
||||
{
|
||||
(void)stmt;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/* Uninitialize driver */
|
||||
int drizzle_drv_done(void)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
void column_info(drizzle_column_st *column)
|
||||
{
|
||||
DEBUG("Field: catalog=%s\n"
|
||||
" db=%s\n"
|
||||
" table=%s\n"
|
||||
" org_table=%s\n"
|
||||
" name=%s\n"
|
||||
" org_name=%s\n"
|
||||
" charset=%u\n"
|
||||
" size=%u\n"
|
||||
" type=%u\n"
|
||||
" flags=%u\n",
|
||||
drizzle_column_catalog(column), drizzle_column_db(column),
|
||||
drizzle_column_table(column), drizzle_column_orig_table(column),
|
||||
drizzle_column_name(column), drizzle_column_orig_name(column),
|
||||
drizzle_column_charset(column), drizzle_column_size(column),
|
||||
drizzle_column_type(column), drizzle_column_flags(column));
|
||||
}
|
||||
|
||||
|
|
@ -0,0 +1,2 @@
|
|||
INCLUDE_DIRECTORIES(${CMAKE_SOURCE_DIR})
|
||||
ADD_LIBRARY(sbmysql drv_mysql.c)
|
||||
|
|
@ -0,0 +1,21 @@
|
|||
# Copyright (C) 2004 MySQL AB
|
||||
# Copyright (C) 2004-2008 Alexey Kopytov <akopytov@gmail.com>
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation; either version 2 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, write to the Free Software
|
||||
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
|
||||
noinst_LIBRARIES = libsbmysql.a
|
||||
|
||||
libsbmysql_a_SOURCES = drv_mysql.c
|
||||
libsbmysql_a_CPPFLAGS = $(MYSQL_CFLAGS) $(AM_CPPFLAGS)
|
||||
File diff suppressed because it is too large
Load Diff
|
|
@ -0,0 +1,21 @@
|
|||
# Copyright (C) 2005 MySQL AB
|
||||
# Copyright (C) 2005-2008 Alexey Kopytov <akopytov@gmail.com>
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation; either version 2 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, write to the Free Software
|
||||
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
|
||||
noinst_LIBRARIES = libsboracle.a
|
||||
|
||||
libsboracle_a_SOURCES = drv_oracle.c
|
||||
libsboracle_a_CPPFLAGS = $(ORA_CFLAGS) $(AM_CPPFLAGS)
|
||||
File diff suppressed because it is too large
Load Diff
|
|
@ -0,0 +1,21 @@
|
|||
# Copyright (C) 2005 MySQL AB
|
||||
# Copyright (C) 2005-2015 Alexey Kopytov <akopytov@gmail.com>
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation; either version 2 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, write to the Free Software
|
||||
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
|
||||
noinst_LIBRARIES = libsbpgsql.a
|
||||
|
||||
libsbpgsql_a_SOURCES = drv_pgsql.c
|
||||
libsbpgsql_a_CPPFLAGS = -g $(PGSQL_CFLAGS) $(AM_CPPFLAGS)
|
||||
|
|
@ -0,0 +1,821 @@
|
|||
/* Copyright (C) 2005 MySQL AB
|
||||
Copyright (C) 2005-2017 Alexey Kopytov <akopytov@gmail.com>
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
# include "config.h"
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_STRING_H
|
||||
# include <string.h>
|
||||
#endif
|
||||
#ifdef HAVE_STRINGS_H
|
||||
# include <strings.h>
|
||||
#endif
|
||||
|
||||
#include <libpq-fe.h>
|
||||
|
||||
#include "sb_options.h"
|
||||
#include "db_driver.h"
|
||||
#include "sb_rand.h"
|
||||
|
||||
#define xfree(ptr) ({ if (ptr) free((void *)ptr); ptr = NULL; })
|
||||
|
||||
/* Maximum length of text representation of bind parameters */
|
||||
#define MAX_PARAM_LENGTH 256UL
|
||||
|
||||
/* PostgreSQL driver arguments */
|
||||
|
||||
static sb_arg_t pgsql_drv_args[] =
|
||||
{
|
||||
SB_OPT("pgsql-host", "PostgreSQL server host", "localhost", STRING),
|
||||
SB_OPT("pgsql-port", "PostgreSQL server port", "5432", INT),
|
||||
SB_OPT("pgsql-user", "PostgreSQL user", "sbtest", STRING),
|
||||
SB_OPT("pgsql-password", "PostgreSQL password", "", STRING),
|
||||
SB_OPT("pgsql-db", "PostgreSQL database name", "sbtest", STRING),
|
||||
|
||||
SB_OPT_END
|
||||
};
|
||||
|
||||
typedef struct
|
||||
{
|
||||
char *host;
|
||||
char *port;
|
||||
char *user;
|
||||
char *password;
|
||||
char *db;
|
||||
} pgsql_drv_args_t;
|
||||
|
||||
/* Structure used for DB-to-PgSQL bind types map */
|
||||
|
||||
typedef struct
|
||||
{
|
||||
db_bind_type_t db_type;
|
||||
int pg_type;
|
||||
} db_pgsql_bind_map_t;
|
||||
|
||||
/* DB-to-PgSQL bind types map */
|
||||
db_pgsql_bind_map_t db_pgsql_bind_map[] =
|
||||
{
|
||||
{DB_TYPE_TINYINT, 0},
|
||||
{DB_TYPE_SMALLINT, 21},
|
||||
{DB_TYPE_INT, 23},
|
||||
{DB_TYPE_BIGINT, 20},
|
||||
{DB_TYPE_FLOAT, 700},
|
||||
{DB_TYPE_DOUBLE, 701},
|
||||
{DB_TYPE_DATETIME, 0},
|
||||
{DB_TYPE_TIMESTAMP, 1114},
|
||||
{DB_TYPE_CHAR, 18},
|
||||
{DB_TYPE_VARCHAR, 1043},
|
||||
{DB_TYPE_NONE, 0}
|
||||
};
|
||||
|
||||
/* PgSQL driver capabilities */
|
||||
|
||||
static drv_caps_t pgsql_drv_caps =
|
||||
{
|
||||
1, /* multi_rows_insert */
|
||||
1, /* prepared_statements */
|
||||
0, /* auto_increment */
|
||||
0, /* needs_commit */
|
||||
1, /* serial */
|
||||
0, /* unsigned int */
|
||||
};
|
||||
|
||||
/* Describes the PostgreSQL prepared statement */
|
||||
typedef struct pg_stmt
|
||||
{
|
||||
char *name;
|
||||
int prepared;
|
||||
int nparams;
|
||||
Oid *ptypes;
|
||||
char **pvalues;
|
||||
} pg_stmt_t;
|
||||
|
||||
static pgsql_drv_args_t args; /* driver args */
|
||||
|
||||
static char use_ps; /* whether server-side prepared statemens should be used */
|
||||
|
||||
/* PgSQL driver operations */
|
||||
|
||||
static int pgsql_drv_init(void);
|
||||
static int pgsql_drv_describe(drv_caps_t *);
|
||||
static int pgsql_drv_connect(db_conn_t *);
|
||||
static int pgsql_drv_disconnect(db_conn_t *);
|
||||
static int pgsql_drv_prepare(db_stmt_t *, const char *, size_t);
|
||||
static int pgsql_drv_bind_param(db_stmt_t *, db_bind_t *, size_t);
|
||||
static int pgsql_drv_bind_result(db_stmt_t *, db_bind_t *, size_t);
|
||||
static db_error_t pgsql_drv_execute(db_stmt_t *, db_result_t *);
|
||||
static int pgsql_drv_fetch(db_result_t *);
|
||||
static int pgsql_drv_fetch_row(db_result_t *, db_row_t *);
|
||||
static db_error_t pgsql_drv_query(db_conn_t *, const char *, size_t,
|
||||
db_result_t *);
|
||||
static int pgsql_drv_free_results(db_result_t *);
|
||||
static int pgsql_drv_close(db_stmt_t *);
|
||||
static int pgsql_drv_done(void);
|
||||
|
||||
/* PgSQL driver definition */
|
||||
|
||||
static db_driver_t pgsql_driver =
|
||||
{
|
||||
.sname = "pgsql",
|
||||
.lname = "PostgreSQL driver",
|
||||
.args = pgsql_drv_args,
|
||||
.ops =
|
||||
{
|
||||
.init = pgsql_drv_init,
|
||||
.describe = pgsql_drv_describe,
|
||||
.connect = pgsql_drv_connect,
|
||||
.disconnect = pgsql_drv_disconnect,
|
||||
.prepare = pgsql_drv_prepare,
|
||||
.bind_param = pgsql_drv_bind_param,
|
||||
.bind_result = pgsql_drv_bind_result,
|
||||
.execute = pgsql_drv_execute,
|
||||
.fetch = pgsql_drv_fetch,
|
||||
.fetch_row = pgsql_drv_fetch_row,
|
||||
.free_results = pgsql_drv_free_results,
|
||||
.close = pgsql_drv_close,
|
||||
.query = pgsql_drv_query,
|
||||
.done = pgsql_drv_done
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/* Local functions */
|
||||
|
||||
static int get_pgsql_bind_type(db_bind_type_t);
|
||||
static int get_unique_stmt_name(char *, int);
|
||||
|
||||
/* Register PgSQL driver */
|
||||
|
||||
|
||||
int register_driver_pgsql(sb_list_t *drivers)
|
||||
{
|
||||
SB_LIST_ADD_TAIL(&pgsql_driver.listitem, drivers);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* PgSQL driver initialization */
|
||||
|
||||
int pgsql_drv_init(void)
|
||||
{
|
||||
args.host = sb_get_value_string("pgsql-host");
|
||||
args.port = sb_get_value_string("pgsql-port");
|
||||
args.user = sb_get_value_string("pgsql-user");
|
||||
args.password = sb_get_value_string("pgsql-password");
|
||||
args.db = sb_get_value_string("pgsql-db");
|
||||
|
||||
use_ps = 0;
|
||||
pgsql_drv_caps.prepared_statements = 1;
|
||||
if (db_globals.ps_mode != DB_PS_MODE_DISABLE)
|
||||
use_ps = 1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/* Describe database capabilities */
|
||||
|
||||
|
||||
int pgsql_drv_describe(drv_caps_t *caps)
|
||||
{
|
||||
PGconn *con;
|
||||
|
||||
*caps = pgsql_drv_caps;
|
||||
|
||||
/* Determine the server version */
|
||||
con = PQsetdbLogin(args.host,
|
||||
args.port,
|
||||
NULL,
|
||||
NULL,
|
||||
args.db,
|
||||
args.user,
|
||||
args.password);
|
||||
if (PQstatus(con) != CONNECTION_OK)
|
||||
{
|
||||
log_text(LOG_FATAL, "Connection to database failed: %s",
|
||||
PQerrorMessage(con));
|
||||
PQfinish(con);
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Support for multi-row INSERTs is not available before 8.2 */
|
||||
if (PQserverVersion(con) < 80200)
|
||||
caps->multi_rows_insert = 0;
|
||||
|
||||
PQfinish(con);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void empty_notice_processor(void *arg, const char *msg)
|
||||
{
|
||||
(void) arg; /* unused */
|
||||
(void) msg; /* unused */
|
||||
}
|
||||
|
||||
/* Connect to database */
|
||||
|
||||
int pgsql_drv_connect(db_conn_t *sb_conn)
|
||||
{
|
||||
PGconn *con;
|
||||
|
||||
con = PQsetdbLogin(args.host,
|
||||
args.port,
|
||||
NULL,
|
||||
NULL,
|
||||
args.db,
|
||||
args.user,
|
||||
args.password);
|
||||
if (PQstatus(con) != CONNECTION_OK)
|
||||
{
|
||||
log_text(LOG_FATAL, "Connection to database failed: %s",
|
||||
PQerrorMessage(con));
|
||||
PQfinish(con);
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Silence the default notice receiver spitting NOTICE message to stderr */
|
||||
PQsetNoticeProcessor(con, empty_notice_processor, NULL);
|
||||
sb_conn->ptr = con;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Disconnect from database */
|
||||
|
||||
int pgsql_drv_disconnect(db_conn_t *sb_conn)
|
||||
{
|
||||
PGconn *con = (PGconn *)sb_conn->ptr;
|
||||
|
||||
/* These might be allocated in pgsql_check_status() */
|
||||
xfree(sb_conn->sql_state);
|
||||
xfree(sb_conn->sql_errmsg);
|
||||
|
||||
if (con != NULL)
|
||||
PQfinish(con);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/* Prepare statement */
|
||||
|
||||
|
||||
int pgsql_drv_prepare(db_stmt_t *stmt, const char *query, size_t len)
|
||||
{
|
||||
PGconn *con = (PGconn *)stmt->connection->ptr;
|
||||
PGresult *pgres;
|
||||
pg_stmt_t *pgstmt;
|
||||
char *buf = NULL;
|
||||
unsigned int vcnt;
|
||||
unsigned int need_realloc;
|
||||
unsigned int i,j;
|
||||
unsigned int buflen;
|
||||
int n;
|
||||
char name[32];
|
||||
|
||||
(void) len; /* unused */
|
||||
|
||||
if (con == NULL)
|
||||
return 1;
|
||||
|
||||
if (!use_ps)
|
||||
{
|
||||
/* Use client-side PS */
|
||||
stmt->emulated = 1;
|
||||
stmt->query = strdup(query);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Convert query to PgSQL-style named placeholders */
|
||||
need_realloc = 1;
|
||||
vcnt = 1;
|
||||
buflen = 0;
|
||||
for (i = 0, j = 0; query[i] != '\0'; i++)
|
||||
{
|
||||
again:
|
||||
if (j+1 >= buflen || need_realloc)
|
||||
{
|
||||
buflen = (buflen > 0) ? buflen * 2 : 256;
|
||||
buf = realloc(buf, buflen);
|
||||
if (buf == NULL)
|
||||
goto error;
|
||||
need_realloc = 0;
|
||||
}
|
||||
|
||||
if (query[i] != '?')
|
||||
{
|
||||
buf[j++] = query[i];
|
||||
continue;
|
||||
}
|
||||
|
||||
n = snprintf(buf + j, buflen - j, "$%d", vcnt);
|
||||
if (n < 0 || n >= (int)(buflen - j))
|
||||
{
|
||||
need_realloc = 1;
|
||||
goto again;
|
||||
}
|
||||
|
||||
j += n;
|
||||
vcnt++;
|
||||
}
|
||||
buf[j] = '\0';
|
||||
|
||||
/* Store the query to be prepared later on the first bind_param call */
|
||||
stmt->query = strdup(buf);
|
||||
free(buf);
|
||||
|
||||
pgstmt = (pg_stmt_t *)calloc(1, sizeof(pg_stmt_t));
|
||||
if (pgstmt == NULL)
|
||||
goto error;
|
||||
/* Generate random statement name */
|
||||
get_unique_stmt_name(name, sizeof(name));
|
||||
pgstmt->name = strdup(name);
|
||||
pgstmt->nparams = vcnt - 1;
|
||||
|
||||
/*
|
||||
Special keys for statements without parameters, since we don't need
|
||||
to know the types of arguments, and no calls to bind_param() will be made
|
||||
*/
|
||||
if (pgstmt->nparams == 0)
|
||||
{
|
||||
/* Do prepare */
|
||||
pgres = PQprepare(con, pgstmt->name, stmt->query, pgstmt->nparams,
|
||||
NULL);
|
||||
|
||||
if (PQresultStatus(pgres) != PGRES_COMMAND_OK)
|
||||
{
|
||||
log_text(LOG_FATAL, "PQprepare() failed: %s", PQerrorMessage(con));
|
||||
|
||||
PQclear(pgres);
|
||||
|
||||
free(stmt->query);
|
||||
free(pgstmt->name);
|
||||
free(pgstmt);
|
||||
|
||||
return 1;
|
||||
}
|
||||
PQclear(pgres);
|
||||
pgstmt->prepared = 1;
|
||||
}
|
||||
|
||||
stmt->ptr = pgstmt;
|
||||
|
||||
return 0;
|
||||
|
||||
error:
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
/* Bind parameters for prepared statement */
|
||||
|
||||
|
||||
int pgsql_drv_bind_param(db_stmt_t *stmt, db_bind_t *params, size_t len)
|
||||
{
|
||||
PGconn *con = (PGconn *)stmt->connection->ptr;
|
||||
PGresult *pgres;
|
||||
pg_stmt_t *pgstmt;
|
||||
unsigned int i;
|
||||
|
||||
if (con == NULL)
|
||||
return 1;
|
||||
|
||||
if (stmt->bound_param != NULL)
|
||||
free(stmt->bound_param);
|
||||
stmt->bound_param = (db_bind_t *)malloc(len * sizeof(db_bind_t));
|
||||
if (stmt->bound_param == NULL)
|
||||
return 1;
|
||||
memcpy(stmt->bound_param, params, len * sizeof(db_bind_t));
|
||||
stmt->bound_param_len = len;
|
||||
|
||||
if (stmt->emulated)
|
||||
return 0;
|
||||
|
||||
pgstmt = stmt->ptr;
|
||||
if (pgstmt->prepared)
|
||||
return 0;
|
||||
|
||||
/* Prepare statement here, since we need to know types of parameters */
|
||||
/* Validate parameters count */
|
||||
if ((unsigned)pgstmt->nparams != len)
|
||||
{
|
||||
log_text(LOG_ALERT, "wrong number of parameters in prepared statement");
|
||||
log_text(LOG_DEBUG, "counted: %d, passed to bind_param(): %zd",
|
||||
pgstmt->nparams, len);
|
||||
return 1;
|
||||
}
|
||||
|
||||
pgstmt->ptypes = (Oid *)malloc(len * sizeof(int));
|
||||
if (pgstmt->ptypes == NULL)
|
||||
return 1;
|
||||
|
||||
/* Convert sysbench data types to PgSQL ones */
|
||||
for (i = 0; i < len; i++)
|
||||
pgstmt->ptypes[i] = get_pgsql_bind_type(params[i].type);
|
||||
|
||||
/* Do prepare */
|
||||
pgres = PQprepare(con, pgstmt->name, stmt->query, pgstmt->nparams,
|
||||
pgstmt->ptypes);
|
||||
|
||||
if (PQresultStatus(pgres) != PGRES_COMMAND_OK)
|
||||
{
|
||||
log_text(LOG_FATAL, "PQprepare() failed: %s", PQerrorMessage(con));
|
||||
return 1;
|
||||
}
|
||||
|
||||
PQclear(pgres);
|
||||
|
||||
pgstmt->pvalues = (char **)calloc(len, sizeof(char *));
|
||||
if (pgstmt->pvalues == NULL)
|
||||
return 1;
|
||||
|
||||
/* Allocate buffers for bind parameters */
|
||||
for (i = 0; i < len; i++)
|
||||
{
|
||||
if (pgstmt->pvalues[i] != NULL)
|
||||
{
|
||||
free(pgstmt->pvalues[i]);
|
||||
}
|
||||
|
||||
pgstmt->pvalues[i] = (char *)malloc(MAX_PARAM_LENGTH);
|
||||
if (pgstmt->pvalues[i] == NULL)
|
||||
return 1;
|
||||
}
|
||||
pgstmt->prepared = 1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/* Bind results for prepared statement */
|
||||
|
||||
|
||||
int pgsql_drv_bind_result(db_stmt_t *stmt, db_bind_t *params, size_t len)
|
||||
{
|
||||
/* unused */
|
||||
(void)stmt;
|
||||
(void)params;
|
||||
(void)len;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/* Check query execution status */
|
||||
|
||||
|
||||
static db_error_t pgsql_check_status(db_conn_t *con, PGresult *pgres,
|
||||
const char *funcname, const char *query,
|
||||
db_result_t *rs)
|
||||
{
|
||||
ExecStatusType status;
|
||||
db_error_t rc;
|
||||
PGconn * const pgcon = con->ptr;
|
||||
|
||||
status = PQresultStatus(pgres);
|
||||
switch(status) {
|
||||
case PGRES_TUPLES_OK:
|
||||
rs->nrows = PQntuples(pgres);
|
||||
rs->nfields = PQnfields(pgres);
|
||||
rs->counter = SB_CNT_READ;
|
||||
|
||||
rc = DB_ERROR_NONE;
|
||||
|
||||
break;
|
||||
|
||||
case PGRES_COMMAND_OK:
|
||||
rs->nrows = strtoul(PQcmdTuples(pgres), NULL, 10);;
|
||||
rs->counter = (rs->nrows > 0) ? SB_CNT_WRITE : SB_CNT_OTHER;
|
||||
rc = DB_ERROR_NONE;
|
||||
|
||||
/*
|
||||
Since we are not returning a result set, the SQL layer will never call
|
||||
pgsql_drv_free_results(). So we must call PQclear() here.
|
||||
*/
|
||||
PQclear(pgres);
|
||||
|
||||
break;
|
||||
|
||||
case PGRES_FATAL_ERROR:
|
||||
rs->nrows = 0;
|
||||
rs->counter = SB_CNT_ERROR;
|
||||
|
||||
/*
|
||||
Duplicate strings here, because PostgreSQL will deallocate them on
|
||||
PQclear() call below. They will be deallocated either on subsequent calls
|
||||
to pgsql_check_status() or in pgsql_drv_disconnect().
|
||||
*/
|
||||
xfree(con->sql_state);
|
||||
xfree(con->sql_errmsg);
|
||||
|
||||
con->sql_state = strdup(PQresultErrorField(pgres, PG_DIAG_SQLSTATE));
|
||||
con->sql_errmsg = strdup(PQresultErrorField(pgres, PG_DIAG_MESSAGE_PRIMARY));
|
||||
|
||||
if (!strcmp(con->sql_state, "40P01") /* deadlock_detected */ ||
|
||||
!strcmp(con->sql_state, "23505") /* unique violation */ ||
|
||||
!strcmp(con->sql_state, "40001"))/* serialization_failure */
|
||||
{
|
||||
PGresult *tmp;
|
||||
tmp = PQexec(pgcon, "ROLLBACK");
|
||||
PQclear(tmp);
|
||||
rc = DB_ERROR_IGNORABLE;
|
||||
}
|
||||
else
|
||||
{
|
||||
log_text(LOG_FATAL, "%s() failed: %d %s", funcname, status,
|
||||
con->sql_errmsg);
|
||||
|
||||
if (query != NULL)
|
||||
log_text(LOG_FATAL, "failed query was: %s", query);
|
||||
|
||||
rc = DB_ERROR_FATAL;
|
||||
}
|
||||
|
||||
PQclear(pgres);
|
||||
|
||||
break;
|
||||
|
||||
default:
|
||||
rs->nrows = 0;
|
||||
rs->counter = SB_CNT_ERROR;
|
||||
rc = DB_ERROR_FATAL;
|
||||
}
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
|
||||
/* Execute prepared statement */
|
||||
|
||||
|
||||
db_error_t pgsql_drv_execute(db_stmt_t *stmt, db_result_t *rs)
|
||||
{
|
||||
db_conn_t *con = stmt->connection;
|
||||
PGconn *pgcon = (PGconn *)con->ptr;
|
||||
PGresult *pgres;
|
||||
pg_stmt_t *pgstmt;
|
||||
char *buf = NULL;
|
||||
unsigned int buflen = 0;
|
||||
unsigned int i, j, vcnt;
|
||||
char need_realloc;
|
||||
int n;
|
||||
db_error_t rc;
|
||||
unsigned long len;
|
||||
|
||||
con->sql_errno = 0;
|
||||
xfree(con->sql_state);
|
||||
xfree(con->sql_errmsg);
|
||||
|
||||
if (!stmt->emulated)
|
||||
{
|
||||
pgstmt = stmt->ptr;
|
||||
if (pgstmt == NULL)
|
||||
{
|
||||
log_text(LOG_DEBUG,
|
||||
"ERROR: exiting mysql_drv_execute(), uninitialized statement");
|
||||
return DB_ERROR_FATAL;
|
||||
}
|
||||
|
||||
/* Convert sysbench bind structures to PgSQL data */
|
||||
for (i = 0; i < (unsigned)pgstmt->nparams; i++)
|
||||
{
|
||||
if (stmt->bound_param[i].is_null && *(stmt->bound_param[i].is_null))
|
||||
continue;
|
||||
|
||||
switch (stmt->bound_param[i].type) {
|
||||
case DB_TYPE_CHAR:
|
||||
case DB_TYPE_VARCHAR:
|
||||
|
||||
len = stmt->bound_param[i].data_len[0];
|
||||
|
||||
memcpy(pgstmt->pvalues[i], stmt->bound_param[i].buffer,
|
||||
SB_MIN(MAX_PARAM_LENGTH, len));
|
||||
/* PostgreSQL requires a zero-terminated string */
|
||||
pgstmt->pvalues[i][len] = '\0';
|
||||
|
||||
break;
|
||||
default:
|
||||
db_print_value(stmt->bound_param + i, pgstmt->pvalues[i],
|
||||
MAX_PARAM_LENGTH);
|
||||
}
|
||||
}
|
||||
|
||||
pgres = PQexecPrepared(pgcon, pgstmt->name, pgstmt->nparams,
|
||||
(const char **)pgstmt->pvalues, NULL, NULL, 1);
|
||||
|
||||
rc = pgsql_check_status(con, pgres, "PQexecPrepared", NULL, rs);
|
||||
|
||||
rs->ptr = (rs->counter == SB_CNT_READ) ? (void *) pgres : NULL;
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
/* Use emulation */
|
||||
/* Build the actual query string from parameters list */
|
||||
need_realloc = 1;
|
||||
vcnt = 0;
|
||||
for (i = 0, j = 0; stmt->query[i] != '\0'; i++)
|
||||
{
|
||||
again:
|
||||
if (j+1 >= buflen || need_realloc)
|
||||
{
|
||||
buflen = (buflen > 0) ? buflen * 2 : 256;
|
||||
buf = realloc(buf, buflen);
|
||||
if (buf == NULL)
|
||||
return DB_ERROR_FATAL;
|
||||
need_realloc = 0;
|
||||
}
|
||||
|
||||
if (stmt->query[i] != '?')
|
||||
{
|
||||
buf[j++] = stmt->query[i];
|
||||
continue;
|
||||
}
|
||||
|
||||
n = db_print_value(stmt->bound_param + vcnt, buf + j, buflen - j);
|
||||
if (n < 0)
|
||||
{
|
||||
need_realloc = 1;
|
||||
goto again;
|
||||
}
|
||||
j += n;
|
||||
vcnt++;
|
||||
}
|
||||
buf[j] = '\0';
|
||||
|
||||
rc = pgsql_drv_query(con, buf, j, rs);
|
||||
|
||||
free(buf);
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
|
||||
/* Execute SQL query */
|
||||
|
||||
|
||||
db_error_t pgsql_drv_query(db_conn_t *sb_conn, const char *query, size_t len,
|
||||
db_result_t *rs)
|
||||
{
|
||||
PGconn *pgcon = sb_conn->ptr;
|
||||
PGresult *pgres;
|
||||
db_error_t rc;
|
||||
|
||||
(void)len; /* unused */
|
||||
|
||||
sb_conn->sql_errno = 0;
|
||||
xfree(sb_conn->sql_state);
|
||||
xfree(sb_conn->sql_errmsg);
|
||||
|
||||
pgres = PQexec(pgcon, query);
|
||||
rc = pgsql_check_status(sb_conn, pgres, "PQexec", query, rs);
|
||||
|
||||
rs->ptr = (rs->counter == SB_CNT_READ) ? (void *) pgres : NULL;
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
|
||||
/* Fetch row from result set of a prepared statement */
|
||||
|
||||
|
||||
int pgsql_drv_fetch(db_result_t *rs)
|
||||
{
|
||||
/* NYI */
|
||||
(void)rs;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
/* Fetch row from result set of a query */
|
||||
|
||||
|
||||
int pgsql_drv_fetch_row(db_result_t *rs, db_row_t *row)
|
||||
{
|
||||
intptr_t rownum;
|
||||
int i;
|
||||
|
||||
/*
|
||||
Use row->ptr as a row number, rather than a pointer to avoid dynamic
|
||||
memory management.
|
||||
*/
|
||||
rownum = (intptr_t) row->ptr;
|
||||
if (rownum >= (int) rs->nrows)
|
||||
return DB_ERROR_IGNORABLE;
|
||||
|
||||
for (i = 0; i < (int) rs->nfields; i++)
|
||||
{
|
||||
/*
|
||||
PQgetvalue() returns an empty string, not a NULL value for a NULL
|
||||
field. Callers of this function expect a NULL pointer in this case.
|
||||
*/
|
||||
if (PQgetisnull(rs->ptr, rownum, i))
|
||||
row->values[i].ptr = NULL;
|
||||
else
|
||||
{
|
||||
row->values[i].len = PQgetlength(rs->ptr, rownum, i);
|
||||
row->values[i].ptr = PQgetvalue(rs->ptr, rownum, i);
|
||||
}
|
||||
}
|
||||
|
||||
row->ptr = (void *) (rownum + 1);
|
||||
|
||||
return DB_ERROR_NONE;
|
||||
}
|
||||
|
||||
|
||||
/* Free result set */
|
||||
|
||||
|
||||
int pgsql_drv_free_results(db_result_t *rs)
|
||||
{
|
||||
if (rs->ptr != NULL)
|
||||
{
|
||||
PQclear((PGresult *)rs->ptr);
|
||||
rs->ptr = NULL;
|
||||
|
||||
rs->row.ptr = 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
/* Close prepared statement */
|
||||
|
||||
|
||||
int pgsql_drv_close(db_stmt_t *stmt)
|
||||
{
|
||||
pg_stmt_t *pgstmt = stmt->ptr;
|
||||
int i;
|
||||
|
||||
if (pgstmt == NULL)
|
||||
return 1;
|
||||
|
||||
if (pgstmt->name != NULL)
|
||||
free(pgstmt->name);
|
||||
if (pgstmt->ptypes != NULL)
|
||||
free(pgstmt->ptypes);
|
||||
if (pgstmt->pvalues != NULL)
|
||||
{
|
||||
for (i = 0; i < pgstmt->nparams; i++)
|
||||
if (pgstmt->pvalues[i] != NULL)
|
||||
free(pgstmt->pvalues[i]);
|
||||
free(pgstmt->pvalues);
|
||||
}
|
||||
|
||||
xfree(stmt->ptr);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/* Uninitialize driver */
|
||||
int pgsql_drv_done(void)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/* Map SQL data type to bind_type value in MYSQL_BIND */
|
||||
|
||||
|
||||
int get_pgsql_bind_type(db_bind_type_t type)
|
||||
{
|
||||
unsigned int i;
|
||||
|
||||
for (i = 0; db_pgsql_bind_map[i].db_type != DB_TYPE_NONE; i++)
|
||||
if (db_pgsql_bind_map[i].db_type == type)
|
||||
return db_pgsql_bind_map[i].pg_type;
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
int get_unique_stmt_name(char *name, int len)
|
||||
{
|
||||
return snprintf(name, len, "sbstmt%d%d",
|
||||
(int) sb_rand_uniform_uint64(),
|
||||
(int) sb_rand_uniform_uint64());
|
||||
}
|
||||
|
|
@ -0,0 +1,31 @@
|
|||
# Copyright (C) 2016 Alexey Kopytov <akopytov@gmail.com>
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation; either version 2 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, write to the Free Software
|
||||
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
|
||||
SUBDIRS = internal
|
||||
|
||||
dist_pkgdata_SCRIPTS = bulk_insert.lua \
|
||||
oltp_delete.lua \
|
||||
oltp_insert.lua \
|
||||
oltp_read_only.lua \
|
||||
oltp_read_write.lua \
|
||||
oltp_point_select.lua \
|
||||
oltp_update_index.lua \
|
||||
oltp_update_non_index.lua \
|
||||
oltp_write_only.lua\
|
||||
select_random_points.lua \
|
||||
select_random_ranges.lua
|
||||
|
||||
dist_pkgdata_DATA = oltp_common.lua
|
||||
|
|
@ -0,0 +1,56 @@
|
|||
#!/usr/bin/env sysbench
|
||||
-- -------------------------------------------------------------------------- --
|
||||
-- Bulk insert benchmark: do multi-row INSERTs concurrently in --threads
|
||||
-- threads with each thread inserting into its own table. The number of INSERTs
|
||||
-- executed by each thread is controlled by either --time or --events.
|
||||
-- -------------------------------------------------------------------------- --
|
||||
|
||||
cursize=0
|
||||
|
||||
function thread_init()
|
||||
drv = sysbench.sql.driver()
|
||||
con = drv:connect()
|
||||
end
|
||||
|
||||
function prepare()
|
||||
local i
|
||||
|
||||
local drv = sysbench.sql.driver()
|
||||
local con = drv:connect()
|
||||
|
||||
for i = 1, sysbench.opt.threads do
|
||||
print("Creating table 'sbtest" .. i .. "'...")
|
||||
con:query(string.format([[
|
||||
CREATE TABLE IF NOT EXISTS sbtest%d (
|
||||
id INTEGER NOT NULL,
|
||||
k INTEGER DEFAULT '0' NOT NULL,
|
||||
PRIMARY KEY (id))]], i))
|
||||
end
|
||||
end
|
||||
|
||||
function event()
|
||||
if (cursize == 0) then
|
||||
con:bulk_insert_init("INSERT INTO sbtest" .. thread_id+1 .. " VALUES")
|
||||
end
|
||||
|
||||
cursize = cursize + 1
|
||||
|
||||
con:bulk_insert_next("(" .. cursize .. "," .. cursize .. ")")
|
||||
end
|
||||
|
||||
function thread_done(thread_9d)
|
||||
con:bulk_insert_done()
|
||||
con:disconnect()
|
||||
end
|
||||
|
||||
function cleanup()
|
||||
local i
|
||||
|
||||
local drv = sysbench.sql.driver()
|
||||
local con = drv:connect()
|
||||
|
||||
for i = 1, sysbench.opt.threads do
|
||||
print("Dropping table 'sbtest" .. i .. "'...")
|
||||
con:query("DROP TABLE IF EXISTS sbtest" .. i )
|
||||
end
|
||||
end
|
||||
|
|
@ -0,0 +1,36 @@
|
|||
# Copyright (C) 2016-2018 Alexey Kopytov <akopytov@gmail.com>
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation; either version 2 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, write to the Free Software
|
||||
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
|
||||
BUILT_SOURCES = sysbench.lua.h sysbench.rand.lua.h sysbench.sql.lua.h \
|
||||
sysbench.compat.lua.h sysbench.cmdline.lua.h \
|
||||
sysbench.histogram.lua.h
|
||||
|
||||
CLEANFILES = $(BUILT_SOURCES)
|
||||
|
||||
EXTRA_DIST = $(BUILT_SOURCES:.h=)
|
||||
|
||||
SUFFIXES = .lua .lua.h
|
||||
|
||||
.lua.lua.h:
|
||||
@echo "Creating $@ from $<"
|
||||
@var=$$(echo $< | sed 's/\./_/g') && \
|
||||
( echo "unsigned char $${var}[] =" && \
|
||||
sed -e 's/\\/\\\\/g' \
|
||||
-e 's/"/\\"/g' \
|
||||
-e 's/^/ "/g' \
|
||||
-e 's/$$/\\n"/g' $< && \
|
||||
echo ";" && \
|
||||
echo "size_t $${var}_len = sizeof($${var}) - 1;" ) > $@
|
||||
|
|
@ -0,0 +1,215 @@
|
|||
-- Copyright (C) 2017-2018 Alexey Kopytov <akopytov@gmail.com>
|
||||
|
||||
-- This program is free software; you can redistribute it and/or modify
|
||||
-- it under the terms of the GNU General Public License as published by
|
||||
-- the Free Software Foundation; either version 2 of the License, or
|
||||
-- (at your option) any later version.
|
||||
|
||||
-- This program is distributed in the hope that it will be useful,
|
||||
-- but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
-- GNU General Public License for more details.
|
||||
|
||||
-- You should have received a copy of the GNU General Public License
|
||||
-- along with this program; if not, write to the Free Software
|
||||
-- Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
|
||||
-- ----------------------------------------------------------------------
|
||||
-- Command line option handling
|
||||
-- ----------------------------------------------------------------------
|
||||
|
||||
ffi = require("ffi")
|
||||
|
||||
ffi.cdef[[
|
||||
/* The following has been copied from sb_option.h */
|
||||
|
||||
typedef enum
|
||||
{
|
||||
SB_ARG_TYPE_NULL,
|
||||
SB_ARG_TYPE_BOOL,
|
||||
SB_ARG_TYPE_INT,
|
||||
SB_ARG_TYPE_SIZE,
|
||||
SB_ARG_TYPE_DOUBLE,
|
||||
SB_ARG_TYPE_STRING,
|
||||
SB_ARG_TYPE_LIST,
|
||||
SB_ARG_TYPE_FILE,
|
||||
SB_ARG_TYPE_MAX
|
||||
} sb_arg_type_t;
|
||||
|
||||
/* Option validation function */
|
||||
typedef bool sb_opt_validate_t(const char *, const char *);
|
||||
|
||||
/* Test option definition */
|
||||
typedef struct
|
||||
{
|
||||
const char *name;
|
||||
const char *desc;
|
||||
const char *value;
|
||||
sb_arg_type_t type;
|
||||
sb_opt_validate_t *validate;
|
||||
} sb_arg_t;
|
||||
|
||||
int sb_lua_set_test_args(sb_arg_t *args, size_t len);
|
||||
]]
|
||||
|
||||
sysbench.cmdline.ARG_NULL = ffi.C.SB_ARG_TYPE_NULL
|
||||
sysbench.cmdline.ARG_BOOL = ffi.C.SB_ARG_TYPE_BOOL
|
||||
sysbench.cmdline.ARG_INT = ffi.C.SB_ARG_TYPE_INT
|
||||
sysbench.cmdline.ARG_SIZE = ffi.C.SB_ARG_TYPE_SIZE
|
||||
sysbench.cmdline.ARG_DOUBLE = ffi.C.SB_ARG_TYPE_DOUBLE
|
||||
sysbench.cmdline.ARG_STRING = ffi.C.SB_ARG_TYPE_STRING
|
||||
sysbench.cmdline.ARG_LIST = ffi.C.SB_ARG_TYPE_LIST
|
||||
sysbench.cmdline.ARG_FILE = ffi.C.SB_ARG_TYPE_FILE
|
||||
sysbench.cmdline.ARG_MAX = ffi.C.SB_ARG_TYPE_MAX
|
||||
|
||||
-- Attribute indicating that a custom command can be executed in parallel
|
||||
sysbench.cmdline.PARALLEL_COMMAND = true
|
||||
|
||||
local arg_types = {
|
||||
boolean = sysbench.cmdline.ARG_BOOL,
|
||||
string = sysbench.cmdline.ARG_STRING,
|
||||
number = sysbench.cmdline.ARG_DOUBLE,
|
||||
table = sysbench.cmdline.ARG_LIST
|
||||
}
|
||||
|
||||
local function __genOrderedIndex( t )
|
||||
local orderedIndex = {}
|
||||
for key in pairs(t) do
|
||||
table.insert( orderedIndex, key )
|
||||
end
|
||||
table.sort( orderedIndex )
|
||||
return orderedIndex
|
||||
end
|
||||
|
||||
local function orderedNext(t, state)
|
||||
local key = nil
|
||||
if state == nil then
|
||||
t.__orderedIndex = __genOrderedIndex( t )
|
||||
key = t.__orderedIndex[1]
|
||||
else
|
||||
for i = 1,table.getn(t.__orderedIndex) do
|
||||
if t.__orderedIndex[i] == state then
|
||||
key = t.__orderedIndex[i+1]
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
if key then
|
||||
return key, t[key]
|
||||
end
|
||||
|
||||
t.__orderedIndex = nil
|
||||
return
|
||||
end
|
||||
|
||||
local function orderedPairs(t)
|
||||
return orderedNext, t, nil
|
||||
end
|
||||
|
||||
-- Parse command line options definitions, if present in the script as a
|
||||
-- 'sysbench.cmdline.options' table. If no such table exists, or if there a
|
||||
-- parsing error, return false. Return true on success. After parsing the
|
||||
-- command line arguments, option values are available as the sysbench.opt
|
||||
-- table.
|
||||
function sysbench.cmdline.read_cmdline_options()
|
||||
if sysbench.cmdline.options == nil then
|
||||
return true
|
||||
end
|
||||
|
||||
local t = type(sysbench.cmdline.options)
|
||||
assert(t == "table", "wrong type for sysbench.cmdline.options: " .. t)
|
||||
|
||||
local i = 0
|
||||
for name, def in pairs(sysbench.cmdline.options) do
|
||||
i = i+1
|
||||
end
|
||||
|
||||
local args = ffi.new('sb_arg_t[?]', i)
|
||||
i = 0
|
||||
|
||||
for name, def in orderedPairs(sysbench.cmdline.options) do
|
||||
-- name
|
||||
assert(type(name) == "string" and type(def) == "table",
|
||||
"wrong table structure in sysbench.cmdline.options")
|
||||
args[i].name = name
|
||||
|
||||
-- description
|
||||
assert(def[1] ~= nil, "nil description for option " .. name)
|
||||
args[i].desc = def[1]
|
||||
|
||||
if type(def[2]) == "table" then
|
||||
assert(type(def[3]) == "nil" or
|
||||
type(def[3]) == sysbench.cmdline.ARG_LIST,
|
||||
"wrong type for list option " .. name)
|
||||
args[i].value = table.concat(def[2], ',')
|
||||
else
|
||||
if type(def[2]) == "boolean" then
|
||||
args[i].value = def[2] and 'on' or 'off'
|
||||
elseif type(def[2]) == "number" then
|
||||
args[i].value = tostring(def[2])
|
||||
else
|
||||
args[i].value = def[2]
|
||||
end
|
||||
end
|
||||
|
||||
-- type
|
||||
local t = def[3]
|
||||
if t == nil then
|
||||
if def[2] ~= nil then
|
||||
-- Try to determine the type by the default value
|
||||
t = arg_types[type(def[2])]
|
||||
else
|
||||
t = sysbench.cmdline.ARG_STRING
|
||||
end
|
||||
end
|
||||
|
||||
assert(t ~= nil, "cannot determine type for option " .. name)
|
||||
args[i].type = t
|
||||
|
||||
-- validation function
|
||||
args[i].validate = def[4]
|
||||
|
||||
i = i + 1
|
||||
end
|
||||
|
||||
return ffi.C.sb_lua_set_test_args(args, i) == 0
|
||||
end
|
||||
|
||||
function sysbench.cmdline.command_defined(name)
|
||||
return type(sysbench.cmdline.commands) == "table" and
|
||||
sysbench.cmdline.commands[name] ~= nil and
|
||||
sysbench.cmdline.commands[name][1] ~= nil
|
||||
end
|
||||
|
||||
function sysbench.cmdline.command_parallel(name)
|
||||
return sysbench.cmdline.command_defined(name) and
|
||||
sysbench.cmdline.commands[name][2] == sysbench.cmdline.PARALLEL_COMMAND
|
||||
end
|
||||
|
||||
function sysbench.cmdline.call_command(name)
|
||||
if not sysbench.cmdline.command_defined(name) then
|
||||
return false
|
||||
end
|
||||
|
||||
local rc = sysbench.cmdline.commands[name][1]()
|
||||
|
||||
if rc == nil then
|
||||
-- handle the case when the command does not return and value as success
|
||||
return true
|
||||
else
|
||||
-- otherwise return success for any returned value other than false
|
||||
return rc and true or false
|
||||
end
|
||||
end
|
||||
|
||||
ffi.cdef[[
|
||||
void sb_print_test_options(void);
|
||||
]]
|
||||
|
||||
-- ----------------------------------------------------------------------
|
||||
-- Print descriptions of command line options, if defined by
|
||||
-- sysbench.cmdline.options
|
||||
-- ----------------------------------------------------------------------
|
||||
function sysbench.cmdline.print_test_options()
|
||||
ffi.C.sb_print_test_options()
|
||||
end
|
||||
|
|
@ -0,0 +1,75 @@
|
|||
-- Copyright (C) 2016-2017 Alexey Kopytov <akopytov@gmail.com>
|
||||
|
||||
-- This program is free software; you can redistribute it and/or modify
|
||||
-- it under the terms of the GNU General Public License as published by
|
||||
-- the Free Software Foundation; either version 2 of the License, or
|
||||
-- (at your option) any later version.
|
||||
|
||||
-- This program is distributed in the hope that it will be useful,
|
||||
-- but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
-- GNU General Public License for more details.
|
||||
|
||||
-- You should have received a copy of the GNU General Public License
|
||||
-- along with this program; if not, write to the Free Software
|
||||
-- Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
|
||||
-- ----------------------------------------------------------------------
|
||||
-- Compatibility wrappers/aliases. These may be removed in later versions
|
||||
-- ----------------------------------------------------------------------
|
||||
|
||||
thread_id = sysbench.tid
|
||||
|
||||
test = sysbench.cmdline.script_path
|
||||
|
||||
function sb_rnd()
|
||||
-- Keep lower 32 bits from sysbench.rand.uniform_uint64() and convert them to
|
||||
-- a Lua number
|
||||
return tonumber(sysbench.rand.uniform_uint64() % 4294967296)
|
||||
end
|
||||
|
||||
sb_rand = sysbench.rand.default
|
||||
sb_rand_str = sysbench.rand.string
|
||||
sb_rand_uniform = sysbench.rand.uniform
|
||||
sb_rand_gaussian = sysbench.rand.gaussian
|
||||
sb_rand_special = sysbench.rand.special
|
||||
|
||||
function sb_rand_uniq(a, b)
|
||||
local res
|
||||
if type(a) == "nil" then
|
||||
a = 0
|
||||
end
|
||||
if type(b) == "nil" then
|
||||
b = 4294967295
|
||||
end
|
||||
repeat
|
||||
res = sysbench.rand.unique()
|
||||
until res >= a and res <= b
|
||||
return res
|
||||
end
|
||||
|
||||
db_connect = sysbench.db.connect
|
||||
db_disconnect = sysbench.db.disconnect
|
||||
|
||||
db_query = sysbench.db.query
|
||||
|
||||
db_bulk_insert_init = sysbench.db.bulk_insert_init
|
||||
db_bulk_insert_next = sysbench.db.bulk_insert_next
|
||||
db_bulk_insert_done = sysbench.db.bulk_insert_done
|
||||
|
||||
db_prepare = sysbench.db.prepare
|
||||
db_bind_param = sysbench.db.bind_param
|
||||
db_bind_result = sysbench.db.bind_result
|
||||
db_execute = sysbench.db.execute
|
||||
|
||||
db_store_results = sysbench.db.store_results
|
||||
db_free_results = sysbench.db.free_results
|
||||
|
||||
db_close = sysbench.db.close
|
||||
|
||||
DB_ERROR_NONE = sysbench.db.DB_ERROR_NONE
|
||||
DB_ERROR_RESTART_TRANSACTION = sysbench.db.DB_ERROR_RESTART_TRANSACTION
|
||||
DB_ERROR_FAILED = sysbench.db.DB_ERROR_FAILED
|
||||
|
||||
mysql_table_engine = mysql_table_engine or "innodb"
|
||||
myisam_max_rows = 1000000
|
||||
|
|
@ -0,0 +1,68 @@
|
|||
-- Copyright (C) 2017 Alexey Kopytov <akopytov@gmail.com>
|
||||
|
||||
-- This program is free software; you can redistribute it and/or modify
|
||||
-- it under the terms of the GNU General Public License as published by
|
||||
-- the Free Software Foundation; either version 2 of the License, or
|
||||
-- (at your option) any later version.
|
||||
|
||||
-- This program is distributed in the hope that it will be useful,
|
||||
-- but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
-- GNU General Public License for more details.
|
||||
|
||||
-- You should have received a copy of the GNU General Public License
|
||||
-- along with this program; if not, write to the Free Software
|
||||
-- Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
|
||||
-- ----------------------------------------------------------------------
|
||||
-- Bounded histograms API
|
||||
-- ----------------------------------------------------------------------
|
||||
|
||||
ffi = require("ffi")
|
||||
|
||||
sysbench.histogram = {}
|
||||
|
||||
ffi.cdef[[
|
||||
typedef struct histogram sb_histogram_t;
|
||||
|
||||
/*
|
||||
Allocate a new histogram and initialize it with sb_histogram_init().
|
||||
*/
|
||||
sb_histogram_t *sb_histogram_new(size_t size, double range_min,
|
||||
double range_max);
|
||||
|
||||
/*
|
||||
Deallocate a histogram allocated with sb_histogram_new().
|
||||
*/
|
||||
void sb_histogram_delete(sb_histogram_t *h);
|
||||
|
||||
/* Update histogram with a given value. */
|
||||
void sb_histogram_update(sb_histogram_t *h, double value);
|
||||
|
||||
/*
|
||||
Print a given histogram to stdout
|
||||
*/
|
||||
void sb_histogram_print(sb_histogram_t *h);
|
||||
]]
|
||||
|
||||
local histogram = {}
|
||||
|
||||
function histogram:update(value)
|
||||
ffi.C.sb_histogram_update(self, value)
|
||||
end
|
||||
|
||||
function histogram:print()
|
||||
ffi.C.sb_histogram_print(self)
|
||||
end
|
||||
|
||||
local histogram_mt = {
|
||||
__index = histogram,
|
||||
__tostring = '<sb_histogram>'
|
||||
}
|
||||
ffi.metatype('sb_histogram_t', histogram_mt)
|
||||
|
||||
function sysbench.histogram.new(size, range_min, range_max)
|
||||
local h = ffi.C.sb_histogram_new(size, range_min, range_max)
|
||||
|
||||
return ffi.gc(h, ffi.C.sb_histogram_delete)
|
||||
end
|
||||
|
|
@ -0,0 +1,160 @@
|
|||
-- Copyright (C) 2016-2018 Alexey Kopytov <akopytov@gmail.com>
|
||||
|
||||
-- This program is free software; you can redistribute it and/or modify
|
||||
-- it under the terms of the GNU General Public License as published by
|
||||
-- the Free Software Foundation; either version 2 of the License, or
|
||||
-- (at your option) any later version.
|
||||
|
||||
-- This program is distributed in the hope that it will be useful,
|
||||
-- but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
-- GNU General Public License for more details.
|
||||
|
||||
-- You should have received a copy of the GNU General Public License
|
||||
-- along with this program; if not, write to the Free Software
|
||||
-- Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
|
||||
ffi = require("ffi")
|
||||
|
||||
ffi.cdef[[
|
||||
void sb_event_start(int thread_id);
|
||||
void sb_event_stop(int thread_id);
|
||||
bool sb_more_events(int thread_id);
|
||||
]]
|
||||
|
||||
-- ----------------------------------------------------------------------
|
||||
-- Main event loop. This is a Lua version of sysbench.c:thread_run()
|
||||
-- ----------------------------------------------------------------------
|
||||
function thread_run(thread_id)
|
||||
while ffi.C.sb_more_events(thread_id) do
|
||||
ffi.C.sb_event_start(thread_id)
|
||||
|
||||
local success, ret
|
||||
repeat
|
||||
success, ret = pcall(event, thread_id)
|
||||
|
||||
if not success then
|
||||
if type(ret) == "table" and
|
||||
ret.errcode == sysbench.error.RESTART_EVENT
|
||||
then
|
||||
if sysbench.hooks.before_restart_event then
|
||||
sysbench.hooks.before_restart_event(ret)
|
||||
end
|
||||
else
|
||||
error(ret, 2) -- propagate unknown errors
|
||||
end
|
||||
end
|
||||
until success
|
||||
|
||||
-- Stop the benchmark if event() returns a value other than nil or false
|
||||
if ret then
|
||||
break
|
||||
end
|
||||
|
||||
ffi.C.sb_event_stop(thread_id)
|
||||
end
|
||||
end
|
||||
|
||||
-- ----------------------------------------------------------------------
|
||||
-- Hooks
|
||||
-- ----------------------------------------------------------------------
|
||||
|
||||
sysbench.hooks = {
|
||||
-- sql_error_ignorable = <func>,
|
||||
-- report_intermediate = <func>,
|
||||
-- report_cumulative = <func>
|
||||
}
|
||||
|
||||
-- Report statistics in the CSV format. Add the following to your
|
||||
-- script to replace the default human-readable reports
|
||||
--
|
||||
-- sysbench.hooks.report_intermediate = sysbench.report_csv
|
||||
function sysbench.report_csv(stat)
|
||||
local seconds = stat.time_interval
|
||||
print(string.format("%.0f,%u,%4.2f," ..
|
||||
"%4.2f,%4.2f,%4.2f,%4.2f," ..
|
||||
"%4.2f,%4.2f," ..
|
||||
"%4.2f",
|
||||
stat.time_total,
|
||||
stat.threads_running,
|
||||
stat.events / seconds,
|
||||
(stat.reads + stat.writes + stat.other) / seconds,
|
||||
stat.reads / seconds,
|
||||
stat.writes / seconds,
|
||||
stat.other / seconds,
|
||||
stat.latency_pct * 1000,
|
||||
stat.errors / seconds,
|
||||
stat.reconnects / seconds
|
||||
))
|
||||
end
|
||||
|
||||
-- Report statistics in the JSON format. Add the following to your
|
||||
-- script to replace the default human-readable reports
|
||||
--
|
||||
-- sysbench.hooks.report_intermediate = sysbench.report_json
|
||||
function sysbench.report_json(stat)
|
||||
if not gobj then
|
||||
io.write('[\n')
|
||||
-- hack to print the closing bracket when the Lua state of the reporting
|
||||
-- thread is closed
|
||||
gobj = newproxy(true)
|
||||
getmetatable(gobj).__gc = function () io.write('\n]\n') end
|
||||
else
|
||||
io.write(',\n')
|
||||
end
|
||||
|
||||
local seconds = stat.time_interval
|
||||
io.write(([[
|
||||
{
|
||||
"time": %4.0f,
|
||||
"threads": %u,
|
||||
"tps": %4.2f,
|
||||
"qps": {
|
||||
"total": %4.2f,
|
||||
"reads": %4.2f,
|
||||
"writes": %4.2f,
|
||||
"other": %4.2f
|
||||
},
|
||||
"latency": %4.2f,
|
||||
"errors": %4.2f,
|
||||
"reconnects": %4.2f
|
||||
}]]):format(
|
||||
stat.time_total,
|
||||
stat.threads_running,
|
||||
stat.events / seconds,
|
||||
(stat.reads + stat.writes + stat.other) / seconds,
|
||||
stat.reads / seconds,
|
||||
stat.writes / seconds,
|
||||
stat.other / seconds,
|
||||
stat.latency_pct * 1000,
|
||||
stat.errors / seconds,
|
||||
stat.reconnects / seconds
|
||||
))
|
||||
end
|
||||
|
||||
-- Report statistics in the default human-readable format. You can use it if you
|
||||
-- want to augment default reports with your own statistics. Call it from your
|
||||
-- own report hook, e.g.:
|
||||
--
|
||||
-- function sysbench.hooks.report_intermediate(stat)
|
||||
-- print("my stat: ", val)
|
||||
-- sysbench.report_default(stat)
|
||||
-- end
|
||||
function sysbench.report_default(stat)
|
||||
local seconds = stat.time_interval
|
||||
print(string.format("[ %.0fs ] thds: %u tps: %4.2f qps: %4.2f " ..
|
||||
"(r/w/o: %4.2f/%4.2f/%4.2f) lat (ms,%u%%): %4.2f " ..
|
||||
"err/s %4.2f reconn/s: %4.2f",
|
||||
stat.time_total,
|
||||
stat.threads_running,
|
||||
stat.events / seconds,
|
||||
(stat.reads + stat.writes + stat.other) / seconds,
|
||||
stat.reads / seconds,
|
||||
stat.writes / seconds,
|
||||
stat.other / seconds,
|
||||
sysbench.opt.percentile,
|
||||
stat.latency_pct * 1000,
|
||||
stat.errors / seconds,
|
||||
stat.reconnects / seconds
|
||||
))
|
||||
end
|
||||
|
|
@ -0,0 +1,74 @@
|
|||
-- Copyright (C) 2016-2017 Alexey Kopytov <akopytov@gmail.com>
|
||||
|
||||
-- This program is free software; you can redistribute it and/or modify
|
||||
-- it under the terms of the GNU General Public License as published by
|
||||
-- the Free Software Foundation; either version 2 of the License, or
|
||||
-- (at your option) any later version.
|
||||
|
||||
-- This program is distributed in the hope that it will be useful,
|
||||
-- but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
-- GNU General Public License for more details.
|
||||
|
||||
-- You should have received a copy of the GNU General Public License
|
||||
-- along with this program; if not, write to the Free Software
|
||||
-- Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
|
||||
ffi = require("ffi")
|
||||
|
||||
-- ----------------------------------------------------------------------
|
||||
-- Pseudo-random number generation API
|
||||
-- ----------------------------------------------------------------------
|
||||
|
||||
sysbench.rand = {}
|
||||
|
||||
ffi.cdef[[
|
||||
uint64_t sb_rand_uniform_uint64(void);
|
||||
uint32_t sb_rand_default(uint32_t, uint32_t);
|
||||
uint32_t sb_rand_uniform(uint32_t, uint32_t);
|
||||
uint32_t sb_rand_gaussian(uint32_t, uint32_t);
|
||||
uint32_t sb_rand_special(uint32_t, uint32_t);
|
||||
uint32_t sb_rand_pareto(uint32_t, uint32_t);
|
||||
uint32_t sb_rand_unique(void);
|
||||
void sb_rand_str(const char *, char *);
|
||||
double sb_rand_uniform_double(void);
|
||||
]]
|
||||
|
||||
function sysbench.rand.uniform_uint64()
|
||||
return ffi.C.sb_rand_uniform_uint64()
|
||||
end
|
||||
|
||||
function sysbench.rand.default(a, b)
|
||||
return ffi.C.sb_rand_default(a, b)
|
||||
end
|
||||
|
||||
function sysbench.rand.uniform(a, b)
|
||||
return ffi.C.sb_rand_uniform(a, b)
|
||||
end
|
||||
|
||||
function sysbench.rand.gaussian(a, b)
|
||||
return ffi.C.sb_rand_gaussian(a, b)
|
||||
end
|
||||
|
||||
function sysbench.rand.special(a, b)
|
||||
return ffi.C.sb_rand_special(a, b)
|
||||
end
|
||||
|
||||
function sysbench.rand.pareto(a, b)
|
||||
return ffi.C.sb_rand_pareto(a, b)
|
||||
end
|
||||
|
||||
function sysbench.rand.unique()
|
||||
return ffi.C.sb_rand_unique()
|
||||
end
|
||||
|
||||
function sysbench.rand.string(fmt)
|
||||
local buflen = #fmt
|
||||
local buf = ffi.new("uint8_t[?]", buflen)
|
||||
ffi.C.sb_rand_str(fmt, buf)
|
||||
return ffi.string(buf, buflen)
|
||||
end
|
||||
|
||||
function sysbench.rand.uniform_double()
|
||||
return ffi.C.sb_rand_uniform_double()
|
||||
end
|
||||
|
|
@ -0,0 +1,492 @@
|
|||
-- Copyright (C) 2017 Alexey Kopytov <akopytov@gmail.com>
|
||||
|
||||
-- This program is free software; you can redistribute it and/or modify
|
||||
-- it under the terms of the GNU General Public License as published by
|
||||
-- the Free Software Foundation; either version 2 of the License, or
|
||||
-- (at your option) any later version.
|
||||
|
||||
-- This program is distributed in the hope that it will be useful,
|
||||
-- but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
-- GNU General Public License for more details.
|
||||
|
||||
-- You should have received a copy of the GNU General Public License
|
||||
-- along with this program; if not, write to the Free Software
|
||||
-- Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
|
||||
-- ----------------------------------------------------------------------
|
||||
-- SQL API
|
||||
-- ----------------------------------------------------------------------
|
||||
|
||||
ffi = require("ffi")
|
||||
|
||||
sysbench.sql = {}
|
||||
|
||||
ffi.cdef[[
|
||||
/*
|
||||
The following definitions have been copied with modifications from db_driver.h
|
||||
*/
|
||||
|
||||
typedef enum
|
||||
{
|
||||
DB_ERROR_NONE, /* no error(s) */
|
||||
DB_ERROR_IGNORABLE, /* error should be ignored as defined by command
|
||||
line arguments or a custom error handler */
|
||||
DB_ERROR_FATAL /* non-ignorable error */
|
||||
} sql_error_t;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
const char *sname; /* short name */
|
||||
const char *lname; /* long name */
|
||||
|
||||
const char opaque[?];
|
||||
} sql_driver;
|
||||
|
||||
typedef struct {
|
||||
uint32_t len; /* Value length */
|
||||
const char *ptr; /* Value string */
|
||||
} sql_value;
|
||||
|
||||
/* Result set row definition */
|
||||
|
||||
typedef struct
|
||||
{
|
||||
void *ptr; /* Driver-specific row data */
|
||||
sql_value *values; /* Array of column values */
|
||||
} sql_row;
|
||||
|
||||
/* Query type for statistics */
|
||||
|
||||
typedef enum
|
||||
{
|
||||
SB_CNT_OTHER,
|
||||
SB_CNT_READ,
|
||||
SB_CNT_WRITE,
|
||||
SB_CNT_TRX,
|
||||
SB_CNT_ERROR,
|
||||
SB_CNT_RECONNECT,
|
||||
SB_CNT_MAX
|
||||
} sb_counter_type;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
sql_error_t error; /* Driver-independent error code */
|
||||
int sql_errno; /* Driver-specific error code */
|
||||
const char *sql_state; /* Database-specific SQL state */
|
||||
const char *sql_errmsg; /* Database-specific error message */
|
||||
sql_driver *driver; /* DB driver for this connection */
|
||||
|
||||
const char opaque[?];
|
||||
} sql_connection;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
sql_connection *connection;
|
||||
|
||||
const char opaque[?];
|
||||
} sql_statement;
|
||||
|
||||
/* Result set definition */
|
||||
|
||||
typedef struct
|
||||
{
|
||||
sb_counter_type counter; /* Statistical counter type */
|
||||
uint32_t nrows; /* Number of affected rows */
|
||||
uint32_t nfields; /* Number of fields */
|
||||
sql_statement *statement; /* Pointer to prepared statement (if used) */
|
||||
void *ptr; /* Pointer to driver-specific data */
|
||||
sql_row row; /* Last fetched row */
|
||||
} sql_result;
|
||||
|
||||
typedef enum
|
||||
{
|
||||
SQL_TYPE_NONE,
|
||||
SQL_TYPE_TINYINT,
|
||||
SQL_TYPE_SMALLINT,
|
||||
SQL_TYPE_INT,
|
||||
SQL_TYPE_BIGINT,
|
||||
SQL_TYPE_FLOAT,
|
||||
SQL_TYPE_DOUBLE,
|
||||
SQL_TYPE_TIME,
|
||||
SQL_TYPE_DATE,
|
||||
SQL_TYPE_DATETIME,
|
||||
SQL_TYPE_TIMESTAMP,
|
||||
SQL_TYPE_CHAR,
|
||||
SQL_TYPE_VARCHAR
|
||||
} sql_bind_type_t;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
sql_bind_type_t type;
|
||||
void *buffer;
|
||||
unsigned long *data_len;
|
||||
unsigned long max_len;
|
||||
char *is_null;
|
||||
} sql_bind;
|
||||
|
||||
sql_driver *db_create(const char *);
|
||||
int db_destroy(sql_driver *drv);
|
||||
|
||||
sql_connection *db_connection_create(sql_driver * drv);
|
||||
int db_connection_close(sql_connection *con);
|
||||
int db_connection_reconnect(sql_connection *con);
|
||||
void db_connection_free(sql_connection *con);
|
||||
|
||||
int db_bulk_insert_init(sql_connection *, const char *, size_t);
|
||||
int db_bulk_insert_next(sql_connection *, const char *, size_t);
|
||||
int db_bulk_insert_done(sql_connection *);
|
||||
|
||||
sql_result *db_query(sql_connection *con, const char *query, size_t len);
|
||||
|
||||
sql_row *db_fetch_row(sql_result *rs);
|
||||
|
||||
sql_statement *db_prepare(sql_connection *con, const char *query, size_t len);
|
||||
int db_bind_param(sql_statement *stmt, sql_bind *params, size_t len);
|
||||
int db_bind_result(sql_statement *stmt, sql_bind *results, size_t len);
|
||||
sql_result *db_execute(sql_statement *stmt);
|
||||
int db_close(sql_statement *stmt);
|
||||
|
||||
int db_free_results(sql_result *);
|
||||
]]
|
||||
|
||||
local sql_driver = ffi.typeof('sql_driver *')
|
||||
local sql_connection = ffi.typeof('sql_connection *')
|
||||
local sql_statement = ffi.typeof('sql_statement *')
|
||||
local sql_bind = ffi.typeof('sql_bind');
|
||||
local sql_result = ffi.typeof('sql_result');
|
||||
local sql_value = ffi.typeof('sql_value');
|
||||
local sql_row = ffi.typeof('sql_row');
|
||||
|
||||
sysbench.sql.type =
|
||||
{
|
||||
NONE = ffi.C.SQL_TYPE_NONE,
|
||||
TINYINT = ffi.C.SQL_TYPE_TINYINT,
|
||||
SMALLINT = ffi.C.SQL_TYPE_SMALLINT,
|
||||
INT = ffi.C.SQL_TYPE_INT,
|
||||
BIGINT = ffi.C.SQL_TYPE_BIGINT,
|
||||
FLOAT = ffi.C.SQL_TYPE_FLOAT,
|
||||
DOUBLE = ffi.C.SQL_TYPE_DOUBLE,
|
||||
TIME = ffi.C.SQL_TYPE_TIME,
|
||||
DATE = ffi.C.SQL_TYPE_DATE,
|
||||
DATETIME = ffi.C.SQL_TYPE_DATETIME,
|
||||
TIMESTAMP = ffi.C.SQL_TYPE_TIMESTAMP,
|
||||
CHAR = ffi.C.SQL_TYPE_CHAR,
|
||||
VARCHAR = ffi.C.SQL_TYPE_VARCHAR
|
||||
}
|
||||
|
||||
-- Initialize a given SQL driver and return a handle to it to create
|
||||
-- connections. A nil driver name (i.e. no function argument) initializes the
|
||||
-- default driver, i.e. the one specified with --db-driver on the command line.
|
||||
function sysbench.sql.driver(driver_name)
|
||||
local drv = ffi.C.db_create(driver_name)
|
||||
if (drv == nil) then
|
||||
error("failed to initialize the DB driver", 2)
|
||||
end
|
||||
return ffi.gc(drv, ffi.C.db_destroy)
|
||||
end
|
||||
|
||||
-- sql_driver methods
|
||||
local driver_methods = {}
|
||||
|
||||
function driver_methods.connect(self)
|
||||
local con = ffi.C.db_connection_create(self)
|
||||
if con == nil then
|
||||
error("connection creation failed", 2)
|
||||
end
|
||||
return ffi.gc(con, ffi.C.db_connection_free)
|
||||
end
|
||||
|
||||
function driver_methods.name(self)
|
||||
return ffi.string(self.sname)
|
||||
end
|
||||
|
||||
-- sql_driver metatable
|
||||
local driver_mt = {
|
||||
__index = driver_methods,
|
||||
__gc = ffi.C.db_destroy,
|
||||
__tostring = function() return '<sql_driver>' end,
|
||||
}
|
||||
ffi.metatype("sql_driver", driver_mt)
|
||||
|
||||
-- sql_connection methods
|
||||
local connection_methods = {}
|
||||
|
||||
function connection_methods.disconnect(self)
|
||||
return assert(ffi.C.db_connection_close(self) == 0)
|
||||
end
|
||||
|
||||
function connection_methods.reconnect(self)
|
||||
return assert(ffi.C.db_connection_reconnect(self) == 0)
|
||||
end
|
||||
|
||||
function connection_methods.check_error(self, rs, query)
|
||||
if rs ~= nil or self.error == sysbench.sql.error.NONE then
|
||||
return rs
|
||||
end
|
||||
|
||||
if self.sql_state == nil or self.sql_errmsg == nil then
|
||||
-- It must be an API error, don't bother trying to downgrade it an
|
||||
-- ignorable error
|
||||
error("SQL API error", 3)
|
||||
end
|
||||
|
||||
local sql_state = ffi.string(self.sql_state)
|
||||
local sql_errmsg = ffi.string(self.sql_errmsg)
|
||||
|
||||
-- Create an error descriptor containing connection, failed query, SQL error
|
||||
-- number, state and error message provided by the SQL driver
|
||||
errdesc = {
|
||||
connection = self,
|
||||
query = query,
|
||||
sql_errno = self.sql_errno,
|
||||
sql_state = sql_state,
|
||||
sql_errmsg = sql_errmsg
|
||||
}
|
||||
|
||||
-- Check if the error has already been marked as ignorable by the driver, or
|
||||
-- there is an error hook that allows downgrading it to IGNORABLE
|
||||
if (self.error == sysbench.sql.error.FATAL and
|
||||
type(sysbench.hooks.sql_error_ignorable) == "function" and
|
||||
sysbench.hooks.sql_error_ignorable(errdesc)) or
|
||||
self.error == sysbench.sql.error.IGNORABLE
|
||||
then
|
||||
-- Throw a 'restart event' exception that can be caught by the user script
|
||||
-- to do some extra steps to restart a transaction (e.g. reprepare
|
||||
-- statements after a reconnect). Otherwise it will be caught by
|
||||
-- thread_run() in sysbench.lua, in which case the entire current event
|
||||
-- will be restarted without extra processing.
|
||||
errdesc.errcode = sysbench.error.RESTART_EVENT
|
||||
error(errdesc, 3)
|
||||
end
|
||||
|
||||
-- Just throw a regular error message on a fatal error
|
||||
error(string.format("SQL error, errno = %d, state = '%s': %s",
|
||||
self.sql_errno, sql_state, sql_errmsg), 2)
|
||||
end
|
||||
|
||||
function connection_methods.query(self, query)
|
||||
local rs = ffi.C.db_query(self, query, #query)
|
||||
return self:check_error(rs, query)
|
||||
end
|
||||
|
||||
function connection_methods.bulk_insert_init(self, query)
|
||||
return assert(ffi.C.db_bulk_insert_init(self, query, #query) == 0,
|
||||
"db_bulk_insert_init() failed")
|
||||
end
|
||||
|
||||
function connection_methods.bulk_insert_next(self, val)
|
||||
return assert(ffi.C.db_bulk_insert_next(self, val, #val) == 0,
|
||||
"db_bulk_insert_next() failed")
|
||||
end
|
||||
|
||||
function connection_methods.bulk_insert_done(self)
|
||||
return assert(ffi.C.db_bulk_insert_done(self) == 0,
|
||||
"db_bulk_insert_done() failed")
|
||||
end
|
||||
|
||||
function connection_methods.prepare(self, query)
|
||||
local stmt = ffi.C.db_prepare(self, query, #query)
|
||||
if stmt == nil then
|
||||
self:check_error(nil, query)
|
||||
end
|
||||
return stmt
|
||||
end
|
||||
|
||||
-- A convenience wrapper around sql_connection:query() and
|
||||
-- sql_result:fetch_row(). Executes the specified query and returns the first
|
||||
-- row from the result set, if available, or nil otherwise
|
||||
function connection_methods.query_row(self, query)
|
||||
local rs = self:query(query)
|
||||
|
||||
if rs == nil or rs.nrows == 0 then
|
||||
return nil
|
||||
end
|
||||
|
||||
return unpack(rs:fetch_row(), 1, rs.nfields)
|
||||
end
|
||||
|
||||
-- sql_connection metatable
|
||||
local connection_mt = {
|
||||
__index = connection_methods,
|
||||
__tostring = function() return '<sql_connection>' end,
|
||||
__gc = ffi.C.db_connection_free,
|
||||
}
|
||||
ffi.metatype("sql_connection", connection_mt)
|
||||
|
||||
-- sql_param
|
||||
local sql_param = {}
|
||||
function sql_param.set(self, value)
|
||||
local sql_type = sysbench.sql.type
|
||||
local btype = self.type
|
||||
|
||||
if (value == nil) then
|
||||
self.is_null[0] = true
|
||||
return
|
||||
end
|
||||
|
||||
self.is_null[0] = false
|
||||
|
||||
if btype == sql_type.TINYINT or
|
||||
btype == sql_type.SMALLINT or
|
||||
btype == sql_type.INT or
|
||||
btype == sql_type.BIGINT
|
||||
then
|
||||
self.buffer[0] = value
|
||||
elseif btype == sql_type.FLOAT or
|
||||
btype == sql_type.DOUBLE
|
||||
then
|
||||
self.buffer[1] = value
|
||||
elseif btype == sql_type.CHAR or
|
||||
btype == sql_type.VARCHAR
|
||||
then
|
||||
local len = #value
|
||||
len = self.max_len < len and self.max_len or len
|
||||
ffi.copy(self.buffer, value, len)
|
||||
self.data_len[0] = len
|
||||
else
|
||||
error("Unsupported argument type: " .. btype, 2)
|
||||
end
|
||||
end
|
||||
|
||||
function sql_param.set_rand_str(self, fmt)
|
||||
local sql_type = sysbench.sql.type
|
||||
local btype = self.type
|
||||
|
||||
self.is_null[0] = false
|
||||
|
||||
if btype == sql_type.CHAR or
|
||||
btype == sql_type.VARCHAR
|
||||
then
|
||||
local len = #fmt
|
||||
len = self.max_len < len and self.max_len or len
|
||||
ffi.C.sb_rand_str(fmt, self.buffer)
|
||||
self.data_len[0] = len
|
||||
else
|
||||
error("Unsupported argument type: " .. btype, 2)
|
||||
end
|
||||
end
|
||||
|
||||
sql_param.__index = sql_param
|
||||
sql_param.__tostring = function () return '<sql_param>' end
|
||||
|
||||
-- sql_statement methods
|
||||
local statement_methods = {}
|
||||
|
||||
function statement_methods.bind_create(self, btype, max_len)
|
||||
local sql_type = sysbench.sql.type
|
||||
|
||||
local param = setmetatable({}, sql_param)
|
||||
|
||||
if btype == sql_type.TINYINT or
|
||||
btype == sql_type.SMALLINT or
|
||||
btype == sql_type.INT or
|
||||
btype == sql_type.BIGINT
|
||||
then
|
||||
param.type = sql_type.BIGINT
|
||||
param.buffer = ffi.new('int64_t[1]')
|
||||
param.max_len = 8
|
||||
elseif btype == sql_type.FLOAT or
|
||||
btype == sql_type.DOUBLE
|
||||
then
|
||||
param.type = sql_type.DOUBLE
|
||||
param.buffer = ffi.new('double[1]')
|
||||
param.max_len = 8
|
||||
elseif btype == sql_type.CHAR or
|
||||
btype == sql_type.VARCHAR
|
||||
then
|
||||
param.type = sql_type.VARCHAR
|
||||
param.buffer = ffi.new('char[?]', max_len)
|
||||
param.max_len = max_len
|
||||
else
|
||||
error("Unsupported argument type: " .. btype, 2)
|
||||
end
|
||||
|
||||
param.data_len = ffi.new('unsigned long[1]')
|
||||
param.is_null = ffi.new('char[1]')
|
||||
|
||||
return param
|
||||
end
|
||||
|
||||
function statement_methods.bind_param(self, ...)
|
||||
local len = select('#', ...)
|
||||
if len < 1 then return nil end
|
||||
|
||||
local binds = ffi.new("sql_bind[?]", len)
|
||||
|
||||
local i, param
|
||||
|
||||
for i, param in ipairs({...}) do
|
||||
binds[i-1].type = param.type
|
||||
binds[i-1].buffer = param.buffer
|
||||
binds[i-1].data_len = param.data_len
|
||||
binds[i-1].max_len = param.max_len
|
||||
binds[i-1].is_null = param.is_null
|
||||
end
|
||||
return ffi.C.db_bind_param(self, binds, len)
|
||||
end
|
||||
|
||||
function statement_methods.execute(self)
|
||||
local rs = ffi.C.db_execute(self)
|
||||
return self.connection:check_error(rs, '<prepared statement>')
|
||||
end
|
||||
|
||||
function statement_methods.close(self)
|
||||
return ffi.C.db_close(self)
|
||||
end
|
||||
|
||||
-- sql_statement metatable
|
||||
local statement_mt = {
|
||||
__index = statement_methods,
|
||||
__tostring = function() return '<sql_statement>' end,
|
||||
__gc = ffi.C.db_close,
|
||||
}
|
||||
ffi.metatype("sql_statement", statement_mt)
|
||||
|
||||
local bind_mt = {
|
||||
__tostring = function() return '<sql_bind>' end,
|
||||
}
|
||||
ffi.metatype("sql_bind", bind_mt)
|
||||
|
||||
-- sql_result methods
|
||||
local result_methods = {}
|
||||
|
||||
-- Returns the next row of values from a result set, or nil if there are no more
|
||||
-- rows to fetch. Values are returned as an array, i.e. a table with numeric
|
||||
-- indexes starting from 1. The total number of values (i.e. fields in a result
|
||||
-- set) can be obtained from sql_result.nfields.
|
||||
function result_methods.fetch_row(self)
|
||||
local res = {}
|
||||
local row = ffi.C.db_fetch_row(self)
|
||||
|
||||
if row == nil then
|
||||
return nil
|
||||
end
|
||||
|
||||
local i
|
||||
for i = 0, self.nfields-1 do
|
||||
if row.values[i].ptr ~= nil then -- not a NULL value
|
||||
res[i+1] = ffi.string(row.values[i].ptr, tonumber(row.values[i].len))
|
||||
end
|
||||
end
|
||||
|
||||
return res
|
||||
end
|
||||
|
||||
function result_methods.free(self)
|
||||
return assert(ffi.C.db_free_results(self) == 0, "db_free_results() failed")
|
||||
end
|
||||
|
||||
-- sql_results metatable
|
||||
local result_mt = {
|
||||
__index = result_methods,
|
||||
__tostring = function() return '<sql_result>' end,
|
||||
__gc = ffi.C.db_free_results
|
||||
}
|
||||
ffi.metatype("sql_result", result_mt)
|
||||
|
||||
-- error codes
|
||||
sysbench.sql.error = {}
|
||||
sysbench.sql.error.NONE = ffi.C.DB_ERROR_NONE
|
||||
sysbench.sql.error.IGNORABLE = ffi.C.DB_ERROR_IGNORABLE
|
||||
sysbench.sql.error.FATAL = ffi.C.DB_ERROR_FATAL
|
||||
|
|
@ -0,0 +1,503 @@
|
|||
-- Copyright (C) 2006-2018 Alexey Kopytov <akopytov@gmail.com>
|
||||
|
||||
-- This program is free software; you can redistribute it and/or modify
|
||||
-- it under the terms of the GNU General Public License as published by
|
||||
-- the Free Software Foundation; either version 2 of the License, or
|
||||
-- (at your option) any later version.
|
||||
|
||||
-- This program is distributed in the hope that it will be useful,
|
||||
-- but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
-- GNU General Public License for more details.
|
||||
|
||||
-- You should have received a copy of the GNU General Public License
|
||||
-- along with this program; if not, write to the Free Software
|
||||
-- Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
|
||||
-- -----------------------------------------------------------------------------
|
||||
-- Common code for OLTP benchmarks.
|
||||
-- -----------------------------------------------------------------------------
|
||||
|
||||
function init()
|
||||
assert(event ~= nil,
|
||||
"this script is meant to be included by other OLTP scripts and " ..
|
||||
"should not be called directly.")
|
||||
end
|
||||
|
||||
if sysbench.cmdline.command == nil then
|
||||
error("Command is required. Supported commands: prepare, prewarm, run, " ..
|
||||
"cleanup, help")
|
||||
end
|
||||
|
||||
-- Command line options
|
||||
sysbench.cmdline.options = {
|
||||
table_size =
|
||||
{"Number of rows per table", 10000},
|
||||
range_size =
|
||||
{"Range size for range SELECT queries", 100},
|
||||
tables =
|
||||
{"Number of tables", 1},
|
||||
point_selects =
|
||||
{"Number of point SELECT queries per transaction", 10},
|
||||
simple_ranges =
|
||||
{"Number of simple range SELECT queries per transaction", 1},
|
||||
sum_ranges =
|
||||
{"Number of SELECT SUM() queries per transaction", 1},
|
||||
order_ranges =
|
||||
{"Number of SELECT ORDER BY queries per transaction", 1},
|
||||
distinct_ranges =
|
||||
{"Number of SELECT DISTINCT queries per transaction", 1},
|
||||
index_updates =
|
||||
{"Number of UPDATE index queries per transaction", 1},
|
||||
non_index_updates =
|
||||
{"Number of UPDATE non-index queries per transaction", 1},
|
||||
delete_inserts =
|
||||
{"Number of DELETE/INSERT combinations per transaction", 1},
|
||||
range_selects =
|
||||
{"Enable/disable all range SELECT queries", true},
|
||||
auto_inc =
|
||||
{"Use AUTO_INCREMENT column as Primary Key (for MySQL), " ..
|
||||
"or its alternatives in other DBMS. When disabled, use " ..
|
||||
"client-generated IDs", true},
|
||||
skip_trx =
|
||||
{"Don't start explicit transactions and execute all queries " ..
|
||||
"in the AUTOCOMMIT mode", false},
|
||||
secondary =
|
||||
{"Use a secondary index in place of the PRIMARY KEY", false},
|
||||
create_secondary =
|
||||
{"Create a secondary index in addition to the PRIMARY KEY", true},
|
||||
mysql_storage_engine =
|
||||
{"Storage engine, if MySQL is used", "innodb"},
|
||||
pgsql_variant =
|
||||
{"Use this PostgreSQL variant when running with the " ..
|
||||
"PostgreSQL driver. The only currently supported " ..
|
||||
"variant is 'redshift'. When enabled, " ..
|
||||
"create_secondary is automatically disabled, and " ..
|
||||
"delete_inserts is set to 0"}
|
||||
}
|
||||
|
||||
-- Prepare the dataset. This command supports parallel execution, i.e. will
|
||||
-- benefit from executing with --threads > 1 as long as --tables > 1
|
||||
function cmd_prepare()
|
||||
local drv = sysbench.sql.driver()
|
||||
local con = drv:connect()
|
||||
|
||||
for i = sysbench.tid % sysbench.opt.threads + 1, sysbench.opt.tables,
|
||||
sysbench.opt.threads do
|
||||
create_table(drv, con, i)
|
||||
end
|
||||
end
|
||||
|
||||
-- Preload the dataset into the server cache. This command supports parallel
|
||||
-- execution, i.e. will benefit from executing with --threads > 1 as long as
|
||||
-- --tables > 1
|
||||
--
|
||||
-- PS. Currently, this command is only meaningful for MySQL/InnoDB benchmarks
|
||||
function cmd_prewarm()
|
||||
local drv = sysbench.sql.driver()
|
||||
local con = drv:connect()
|
||||
|
||||
assert(drv:name() == "mysql", "prewarm is currently MySQL only")
|
||||
|
||||
-- Do not create on disk tables for subsequent queries
|
||||
con:query("SET tmp_table_size=2*1024*1024*1024")
|
||||
con:query("SET max_heap_table_size=2*1024*1024*1024")
|
||||
|
||||
for i = sysbench.tid % sysbench.opt.threads + 1, sysbench.opt.tables,
|
||||
sysbench.opt.threads do
|
||||
local t = "sbtest" .. i
|
||||
print("Prewarming table " .. t)
|
||||
con:query("ANALYZE TABLE sbtest" .. i)
|
||||
con:query(string.format(
|
||||
"SELECT AVG(id) FROM " ..
|
||||
"(SELECT * FROM %s FORCE KEY (PRIMARY) " ..
|
||||
"LIMIT %u) t",
|
||||
t, sysbench.opt.table_size))
|
||||
con:query(string.format(
|
||||
"SELECT COUNT(*) FROM " ..
|
||||
"(SELECT * FROM %s WHERE k LIKE '%%0%%' LIMIT %u) t",
|
||||
t, sysbench.opt.table_size))
|
||||
end
|
||||
end
|
||||
|
||||
-- Implement parallel prepare and prewarm commands
|
||||
sysbench.cmdline.commands = {
|
||||
prepare = {cmd_prepare, sysbench.cmdline.PARALLEL_COMMAND},
|
||||
prewarm = {cmd_prewarm, sysbench.cmdline.PARALLEL_COMMAND}
|
||||
}
|
||||
|
||||
|
||||
-- Template strings of random digits with 11-digit groups separated by dashes
|
||||
|
||||
-- 10 groups, 119 characters
|
||||
local c_value_template = "###########-###########-###########-" ..
|
||||
"###########-###########-###########-" ..
|
||||
"###########-###########-###########-" ..
|
||||
"###########"
|
||||
|
||||
-- 5 groups, 59 characters
|
||||
local pad_value_template = "###########-###########-###########-" ..
|
||||
"###########-###########"
|
||||
|
||||
function get_c_value()
|
||||
return sysbench.rand.string(c_value_template)
|
||||
end
|
||||
|
||||
function get_pad_value()
|
||||
return sysbench.rand.string(pad_value_template)
|
||||
end
|
||||
|
||||
function create_table(drv, con, table_num)
|
||||
local id_index_def, id_def
|
||||
local engine_def = ""
|
||||
local extra_table_options = ""
|
||||
local query
|
||||
|
||||
if sysbench.opt.secondary then
|
||||
id_index_def = "KEY xid"
|
||||
else
|
||||
id_index_def = "PRIMARY KEY"
|
||||
end
|
||||
|
||||
if drv:name() == "mysql" or drv:name() == "attachsql" or
|
||||
drv:name() == "drizzle"
|
||||
then
|
||||
if sysbench.opt.auto_inc then
|
||||
id_def = "INTEGER NOT NULL AUTO_INCREMENT"
|
||||
else
|
||||
id_def = "INTEGER NOT NULL"
|
||||
end
|
||||
engine_def = "/*! ENGINE = " .. sysbench.opt.mysql_storage_engine .. " */"
|
||||
extra_table_options = mysql_table_options or ""
|
||||
elseif drv:name() == "pgsql"
|
||||
then
|
||||
if not sysbench.opt.auto_inc then
|
||||
id_def = "INTEGER NOT NULL"
|
||||
elseif pgsql_variant == 'redshift' then
|
||||
id_def = "INTEGER IDENTITY(1,1)"
|
||||
else
|
||||
id_def = "SERIAL"
|
||||
end
|
||||
else
|
||||
error("Unsupported database driver:" .. drv:name())
|
||||
end
|
||||
|
||||
print(string.format("Creating table 'sbtest%d'...", table_num))
|
||||
|
||||
query = string.format([[
|
||||
CREATE TABLE sbtest%d(
|
||||
id %s,
|
||||
k INTEGER DEFAULT '0' NOT NULL,
|
||||
c CHAR(120) DEFAULT '' NOT NULL,
|
||||
pad CHAR(60) DEFAULT '' NOT NULL,
|
||||
%s (id)
|
||||
) %s %s]],
|
||||
table_num, id_def, id_index_def, engine_def, extra_table_options)
|
||||
|
||||
con:query(query)
|
||||
|
||||
if (sysbench.opt.table_size > 0) then
|
||||
print(string.format("Inserting %d records into 'sbtest%d'",
|
||||
sysbench.opt.table_size, table_num))
|
||||
end
|
||||
|
||||
if sysbench.opt.auto_inc then
|
||||
query = "INSERT INTO sbtest" .. table_num .. "(k, c, pad) VALUES"
|
||||
else
|
||||
query = "INSERT INTO sbtest" .. table_num .. "(id, k, c, pad) VALUES"
|
||||
end
|
||||
|
||||
con:bulk_insert_init(query)
|
||||
|
||||
local c_val
|
||||
local pad_val
|
||||
|
||||
for i = 1, sysbench.opt.table_size do
|
||||
|
||||
c_val = get_c_value()
|
||||
pad_val = get_pad_value()
|
||||
|
||||
if (sysbench.opt.auto_inc) then
|
||||
query = string.format("(%d, '%s', '%s')",
|
||||
sb_rand(1, sysbench.opt.table_size), c_val,
|
||||
pad_val)
|
||||
else
|
||||
query = string.format("(%d, %d, '%s', '%s')",
|
||||
i, sb_rand(1, sysbench.opt.table_size), c_val,
|
||||
pad_val)
|
||||
end
|
||||
|
||||
con:bulk_insert_next(query)
|
||||
end
|
||||
|
||||
con:bulk_insert_done()
|
||||
|
||||
if sysbench.opt.create_secondary then
|
||||
print(string.format("Creating a secondary index on 'sbtest%d'...",
|
||||
table_num))
|
||||
con:query(string.format("CREATE INDEX k_%d ON sbtest%d(k)",
|
||||
table_num, table_num))
|
||||
end
|
||||
end
|
||||
|
||||
local t = sysbench.sql.type
|
||||
local stmt_defs = {
|
||||
point_selects = {
|
||||
"SELECT c FROM sbtest%u WHERE id=?",
|
||||
t.INT},
|
||||
simple_ranges = {
|
||||
"SELECT c FROM sbtest%u WHERE id BETWEEN ? AND ?",
|
||||
t.INT, t.INT},
|
||||
sum_ranges = {
|
||||
"SELECT SUM(k) FROM sbtest%u WHERE id BETWEEN ? AND ?",
|
||||
t.INT, t.INT},
|
||||
order_ranges = {
|
||||
"SELECT c FROM sbtest%u WHERE id BETWEEN ? AND ? ORDER BY c",
|
||||
t.INT, t.INT},
|
||||
distinct_ranges = {
|
||||
"SELECT DISTINCT c FROM sbtest%u WHERE id BETWEEN ? AND ? ORDER BY c",
|
||||
t.INT, t.INT},
|
||||
index_updates = {
|
||||
"UPDATE sbtest%u SET k=k+1 WHERE id=?",
|
||||
t.INT},
|
||||
non_index_updates = {
|
||||
"UPDATE sbtest%u SET c=? WHERE id=?",
|
||||
{t.CHAR, 120}, t.INT},
|
||||
deletes = {
|
||||
"DELETE FROM sbtest%u WHERE id=?",
|
||||
t.INT},
|
||||
inserts = {
|
||||
"INSERT INTO sbtest%u (id, k, c, pad) VALUES (?, ?, ?, ?)",
|
||||
t.INT, t.INT, {t.CHAR, 120}, {t.CHAR, 60}},
|
||||
}
|
||||
|
||||
function prepare_begin()
|
||||
stmt.begin = con:prepare("BEGIN")
|
||||
end
|
||||
|
||||
function prepare_commit()
|
||||
stmt.commit = con:prepare("COMMIT")
|
||||
end
|
||||
|
||||
function prepare_for_each_table(key)
|
||||
for t = 1, sysbench.opt.tables do
|
||||
stmt[t][key] = con:prepare(string.format(stmt_defs[key][1], t))
|
||||
|
||||
local nparam = #stmt_defs[key] - 1
|
||||
|
||||
if nparam > 0 then
|
||||
param[t][key] = {}
|
||||
end
|
||||
|
||||
for p = 1, nparam do
|
||||
local btype = stmt_defs[key][p+1]
|
||||
local len
|
||||
|
||||
if type(btype) == "table" then
|
||||
len = btype[2]
|
||||
btype = btype[1]
|
||||
end
|
||||
if btype == sysbench.sql.type.VARCHAR or
|
||||
btype == sysbench.sql.type.CHAR then
|
||||
param[t][key][p] = stmt[t][key]:bind_create(btype, len)
|
||||
else
|
||||
param[t][key][p] = stmt[t][key]:bind_create(btype)
|
||||
end
|
||||
end
|
||||
|
||||
if nparam > 0 then
|
||||
stmt[t][key]:bind_param(unpack(param[t][key]))
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function prepare_point_selects()
|
||||
prepare_for_each_table("point_selects")
|
||||
end
|
||||
|
||||
function prepare_simple_ranges()
|
||||
prepare_for_each_table("simple_ranges")
|
||||
end
|
||||
|
||||
function prepare_sum_ranges()
|
||||
prepare_for_each_table("sum_ranges")
|
||||
end
|
||||
|
||||
function prepare_order_ranges()
|
||||
prepare_for_each_table("order_ranges")
|
||||
end
|
||||
|
||||
function prepare_distinct_ranges()
|
||||
prepare_for_each_table("distinct_ranges")
|
||||
end
|
||||
|
||||
function prepare_index_updates()
|
||||
prepare_for_each_table("index_updates")
|
||||
end
|
||||
|
||||
function prepare_non_index_updates()
|
||||
prepare_for_each_table("non_index_updates")
|
||||
end
|
||||
|
||||
function prepare_delete_inserts()
|
||||
prepare_for_each_table("deletes")
|
||||
prepare_for_each_table("inserts")
|
||||
end
|
||||
|
||||
function thread_init()
|
||||
drv = sysbench.sql.driver()
|
||||
con = drv:connect()
|
||||
|
||||
-- Create global nested tables for prepared statements and their
|
||||
-- parameters. We need a statement and a parameter set for each combination
|
||||
-- of connection/table/query
|
||||
stmt = {}
|
||||
param = {}
|
||||
|
||||
for t = 1, sysbench.opt.tables do
|
||||
stmt[t] = {}
|
||||
param[t] = {}
|
||||
end
|
||||
|
||||
-- This function is a 'callback' defined by individual benchmark scripts
|
||||
prepare_statements()
|
||||
end
|
||||
|
||||
-- Close prepared statements
|
||||
function close_statements()
|
||||
for t = 1, sysbench.opt.tables do
|
||||
for k, s in pairs(stmt[t]) do
|
||||
stmt[t][k]:close()
|
||||
end
|
||||
end
|
||||
if (stmt.begin ~= nil) then
|
||||
stmt.begin:close()
|
||||
end
|
||||
if (stmt.commit ~= nil) then
|
||||
stmt.commit:close()
|
||||
end
|
||||
end
|
||||
|
||||
function thread_done()
|
||||
close_statements()
|
||||
con:disconnect()
|
||||
end
|
||||
|
||||
function cleanup()
|
||||
local drv = sysbench.sql.driver()
|
||||
local con = drv:connect()
|
||||
|
||||
for i = 1, sysbench.opt.tables do
|
||||
print(string.format("Dropping table 'sbtest%d'...", i))
|
||||
con:query("DROP TABLE IF EXISTS sbtest" .. i )
|
||||
end
|
||||
end
|
||||
|
||||
local function get_table_num()
|
||||
return sysbench.rand.uniform(1, sysbench.opt.tables)
|
||||
end
|
||||
|
||||
local function get_id()
|
||||
return sysbench.rand.default(1, sysbench.opt.table_size)
|
||||
end
|
||||
|
||||
function begin()
|
||||
stmt.begin:execute()
|
||||
end
|
||||
|
||||
function commit()
|
||||
stmt.commit:execute()
|
||||
end
|
||||
|
||||
function execute_point_selects()
|
||||
local tnum = get_table_num()
|
||||
local i
|
||||
|
||||
for i = 1, sysbench.opt.point_selects do
|
||||
param[tnum].point_selects[1]:set(get_id())
|
||||
|
||||
stmt[tnum].point_selects:execute()
|
||||
end
|
||||
end
|
||||
|
||||
local function execute_range(key)
|
||||
local tnum = get_table_num()
|
||||
|
||||
for i = 1, sysbench.opt[key] do
|
||||
local id = get_id()
|
||||
|
||||
param[tnum][key][1]:set(id)
|
||||
param[tnum][key][2]:set(id + sysbench.opt.range_size - 1)
|
||||
|
||||
stmt[tnum][key]:execute()
|
||||
end
|
||||
end
|
||||
|
||||
function execute_simple_ranges()
|
||||
execute_range("simple_ranges")
|
||||
end
|
||||
|
||||
function execute_sum_ranges()
|
||||
execute_range("sum_ranges")
|
||||
end
|
||||
|
||||
function execute_order_ranges()
|
||||
execute_range("order_ranges")
|
||||
end
|
||||
|
||||
function execute_distinct_ranges()
|
||||
execute_range("distinct_ranges")
|
||||
end
|
||||
|
||||
function execute_index_updates()
|
||||
local tnum = get_table_num()
|
||||
|
||||
for i = 1, sysbench.opt.index_updates do
|
||||
param[tnum].index_updates[1]:set(get_id())
|
||||
|
||||
stmt[tnum].index_updates:execute()
|
||||
end
|
||||
end
|
||||
|
||||
function execute_non_index_updates()
|
||||
local tnum = get_table_num()
|
||||
|
||||
for i = 1, sysbench.opt.non_index_updates do
|
||||
param[tnum].non_index_updates[1]:set_rand_str(c_value_template)
|
||||
param[tnum].non_index_updates[2]:set(get_id())
|
||||
|
||||
stmt[tnum].non_index_updates:execute()
|
||||
end
|
||||
end
|
||||
|
||||
function execute_delete_inserts()
|
||||
local tnum = get_table_num()
|
||||
|
||||
for i = 1, sysbench.opt.delete_inserts do
|
||||
local id = get_id()
|
||||
local k = get_id()
|
||||
|
||||
param[tnum].deletes[1]:set(id)
|
||||
|
||||
param[tnum].inserts[1]:set(id)
|
||||
param[tnum].inserts[2]:set(k)
|
||||
param[tnum].inserts[3]:set_rand_str(c_value_template)
|
||||
param[tnum].inserts[4]:set_rand_str(pad_value_template)
|
||||
|
||||
stmt[tnum].deletes:execute()
|
||||
stmt[tnum].inserts:execute()
|
||||
end
|
||||
end
|
||||
|
||||
-- Re-prepare statements if we have reconnected, which is possible when some of
|
||||
-- the listed error codes are in the --mysql-ignore-errors list
|
||||
function sysbench.hooks.before_restart_event(errdesc)
|
||||
if errdesc.sql_errno == 2013 or -- CR_SERVER_LOST
|
||||
errdesc.sql_errno == 2055 or -- CR_SERVER_LOST_EXTENDED
|
||||
errdesc.sql_errno == 2006 or -- CR_SERVER_GONE_ERROR
|
||||
errdesc.sql_errno == 2011 -- CR_TCP_CONNECTION
|
||||
then
|
||||
close_statements()
|
||||
prepare_statements()
|
||||
end
|
||||
end
|
||||
|
|
@ -0,0 +1,34 @@
|
|||
#!/usr/bin/env sysbench
|
||||
-- Copyright (C) 2006-2017 Alexey Kopytov <akopytov@gmail.com>
|
||||
|
||||
-- This program is free software; you can redistribute it and/or modify
|
||||
-- it under the terms of the GNU General Public License as published by
|
||||
-- the Free Software Foundation; either version 2 of the License, or
|
||||
-- (at your option) any later version.
|
||||
|
||||
-- This program is distributed in the hope that it will be useful,
|
||||
-- but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
-- GNU General Public License for more details.
|
||||
|
||||
-- You should have received a copy of the GNU General Public License
|
||||
-- along with this program; if not, write to the Free Software
|
||||
-- Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
|
||||
-- ----------------------------------------------------------------------
|
||||
-- Delete-Only OLTP benchmark
|
||||
-- ----------------------------------------------------------------------
|
||||
|
||||
require("oltp_common")
|
||||
|
||||
function prepare_statements()
|
||||
prepare_for_each_table("deletes")
|
||||
end
|
||||
|
||||
function event()
|
||||
local tnum = sysbench.rand.uniform(1, sysbench.opt.tables)
|
||||
local id = sysbench.rand.default(1, sysbench.opt.table_size)
|
||||
|
||||
param[tnum].deletes[1]:set(id)
|
||||
stmt[tnum].deletes:execute()
|
||||
end
|
||||
|
|
@ -0,0 +1,65 @@
|
|||
#!/usr/bin/env sysbench
|
||||
-- Copyright (C) 2006-2017 Alexey Kopytov <akopytov@gmail.com>
|
||||
|
||||
-- This program is free software; you can redistribute it and/or modify
|
||||
-- it under the terms of the GNU General Public License as published by
|
||||
-- the Free Software Foundation; either version 2 of the License, or
|
||||
-- (at your option) any later version.
|
||||
|
||||
-- This program is distributed in the hope that it will be useful,
|
||||
-- but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
-- GNU General Public License for more details.
|
||||
|
||||
-- You should have received a copy of the GNU General Public License
|
||||
-- along with this program; if not, write to the Free Software
|
||||
-- Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
|
||||
-- ----------------------------------------------------------------------
|
||||
-- Insert-Only OLTP benchmark
|
||||
-- ----------------------------------------------------------------------
|
||||
|
||||
require("oltp_common")
|
||||
|
||||
sysbench.cmdline.commands.prepare = {
|
||||
function ()
|
||||
if (not sysbench.opt.auto_inc) then
|
||||
-- Create empty tables on prepare when --auto-inc is off, since IDs
|
||||
-- generated on prepare may collide later with values generated by
|
||||
-- sysbench.rand.unique()
|
||||
sysbench.opt.table_size=0
|
||||
end
|
||||
|
||||
cmd_prepare()
|
||||
end,
|
||||
sysbench.cmdline.PARALLEL_COMMAND
|
||||
}
|
||||
|
||||
function prepare_statements()
|
||||
-- We do not use prepared statements here, but oltp_common.sh expects this
|
||||
-- function to be defined
|
||||
end
|
||||
|
||||
function event()
|
||||
local table_name = "sbtest" .. sysbench.rand.uniform(1, sysbench.opt.tables)
|
||||
local k_val = sysbench.rand.default(1, sysbench.opt.table_size)
|
||||
local c_val = get_c_value()
|
||||
local pad_val = get_pad_value()
|
||||
|
||||
if (drv:name() == "pgsql" and sysbench.opt.auto_inc) then
|
||||
con:query(string.format("INSERT INTO %s (k, c, pad) VALUES " ..
|
||||
"(%d, '%s', '%s')",
|
||||
table_name, k_val, c_val, pad_val))
|
||||
else
|
||||
if (sysbench.opt.auto_inc) then
|
||||
i = 0
|
||||
else
|
||||
-- Convert a uint32_t value to SQL INT
|
||||
i = sysbench.rand.unique() - 2147483648
|
||||
end
|
||||
|
||||
con:query(string.format("INSERT INTO %s (id, k, c, pad) VALUES " ..
|
||||
"(%d, %d, '%s', '%s')",
|
||||
table_name, i, k_val, c_val, pad_val))
|
||||
end
|
||||
end
|
||||
|
|
@ -0,0 +1,34 @@
|
|||
#!/usr/bin/env sysbench
|
||||
-- Copyright (C) 2006-2017 Alexey Kopytov <akopytov@gmail.com>
|
||||
|
||||
-- This program is free software; you can redistribute it and/or modify
|
||||
-- it under the terms of the GNU General Public License as published by
|
||||
-- the Free Software Foundation; either version 2 of the License, or
|
||||
-- (at your option) any later version.
|
||||
|
||||
-- This program is distributed in the hope that it will be useful,
|
||||
-- but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
-- GNU General Public License for more details.
|
||||
|
||||
-- You should have received a copy of the GNU General Public License
|
||||
-- along with this program; if not, write to the Free Software
|
||||
-- Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
|
||||
-- ----------------------------------------------------------------------
|
||||
-- OLTP Point Select benchmark
|
||||
-- ----------------------------------------------------------------------
|
||||
|
||||
require("oltp_common")
|
||||
|
||||
function prepare_statements()
|
||||
-- use 1 query per event, rather than sysbench.opt.point_selects which
|
||||
-- defaults to 10 in other OLTP scripts
|
||||
sysbench.opt.point_selects=1
|
||||
|
||||
prepare_point_selects()
|
||||
end
|
||||
|
||||
function event()
|
||||
execute_point_selects()
|
||||
end
|
||||
|
|
@ -0,0 +1,57 @@
|
|||
#!/usr/bin/env sysbench
|
||||
-- Copyright (C) 2006-2017 Alexey Kopytov <akopytov@gmail.com>
|
||||
|
||||
-- This program is free software; you can redistribute it and/or modify
|
||||
-- it under the terms of the GNU General Public License as published by
|
||||
-- the Free Software Foundation; either version 2 of the License, or
|
||||
-- (at your option) any later version.
|
||||
|
||||
-- This program is distributed in the hope that it will be useful,
|
||||
-- but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
-- GNU General Public License for more details.
|
||||
|
||||
-- You should have received a copy of the GNU General Public License
|
||||
-- along with this program; if not, write to the Free Software
|
||||
-- Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
|
||||
-- ----------------------------------------------------------------------
|
||||
-- Read-Only OLTP benchmark
|
||||
-- ----------------------------------------------------------------------
|
||||
|
||||
require("oltp_common")
|
||||
|
||||
function prepare_statements()
|
||||
prepare_point_selects()
|
||||
|
||||
if not sysbench.opt.skip_trx then
|
||||
prepare_begin()
|
||||
prepare_commit()
|
||||
end
|
||||
|
||||
if sysbench.opt.range_selects then
|
||||
prepare_simple_ranges()
|
||||
prepare_sum_ranges()
|
||||
prepare_order_ranges()
|
||||
prepare_distinct_ranges()
|
||||
end
|
||||
end
|
||||
|
||||
function event()
|
||||
if not sysbench.opt.skip_trx then
|
||||
begin()
|
||||
end
|
||||
|
||||
execute_point_selects()
|
||||
|
||||
if sysbench.opt.range_selects then
|
||||
execute_simple_ranges()
|
||||
execute_sum_ranges()
|
||||
execute_order_ranges()
|
||||
execute_distinct_ranges()
|
||||
end
|
||||
|
||||
if not sysbench.opt.skip_trx then
|
||||
commit()
|
||||
end
|
||||
end
|
||||
|
|
@ -0,0 +1,65 @@
|
|||
#!/usr/bin/env sysbench
|
||||
-- Copyright (C) 2006-2017 Alexey Kopytov <akopytov@gmail.com>
|
||||
|
||||
-- This program is free software; you can redistribute it and/or modify
|
||||
-- it under the terms of the GNU General Public License as published by
|
||||
-- the Free Software Foundation; either version 2 of the License, or
|
||||
-- (at your option) any later version.
|
||||
|
||||
-- This program is distributed in the hope that it will be useful,
|
||||
-- but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
-- GNU General Public License for more details.
|
||||
|
||||
-- You should have received a copy of the GNU General Public License
|
||||
-- along with this program; if not, write to the Free Software
|
||||
-- Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
|
||||
-- ----------------------------------------------------------------------
|
||||
-- Read/Write OLTP benchmark
|
||||
-- ----------------------------------------------------------------------
|
||||
|
||||
require("oltp_common")
|
||||
|
||||
function prepare_statements()
|
||||
if not sysbench.opt.skip_trx then
|
||||
prepare_begin()
|
||||
prepare_commit()
|
||||
end
|
||||
|
||||
prepare_point_selects()
|
||||
|
||||
if sysbench.opt.range_selects then
|
||||
prepare_simple_ranges()
|
||||
prepare_sum_ranges()
|
||||
prepare_order_ranges()
|
||||
prepare_distinct_ranges()
|
||||
end
|
||||
|
||||
prepare_index_updates()
|
||||
prepare_non_index_updates()
|
||||
prepare_delete_inserts()
|
||||
end
|
||||
|
||||
function event()
|
||||
if not sysbench.opt.skip_trx then
|
||||
begin()
|
||||
end
|
||||
|
||||
execute_point_selects()
|
||||
|
||||
if sysbench.opt.range_selects then
|
||||
execute_simple_ranges()
|
||||
execute_sum_ranges()
|
||||
execute_order_ranges()
|
||||
execute_distinct_ranges()
|
||||
end
|
||||
|
||||
execute_index_updates()
|
||||
execute_non_index_updates()
|
||||
execute_delete_inserts()
|
||||
|
||||
if not sysbench.opt.skip_trx then
|
||||
commit()
|
||||
end
|
||||
end
|
||||
|
|
@ -0,0 +1,30 @@
|
|||
#!/usr/bin/env sysbench
|
||||
-- Copyright (C) 2006-2017 Alexey Kopytov <akopytov@gmail.com>
|
||||
|
||||
-- This program is free software; you can redistribute it and/or modify
|
||||
-- it under the terms of the GNU General Public License as published by
|
||||
-- the Free Software Foundation; either version 2 of the License, or
|
||||
-- (at your option) any later version.
|
||||
|
||||
-- This program is distributed in the hope that it will be useful,
|
||||
-- but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
-- GNU General Public License for more details.
|
||||
|
||||
-- You should have received a copy of the GNU General Public License
|
||||
-- along with this program; if not, write to the Free Software
|
||||
-- Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
|
||||
-- ----------------------------------------------------------------------
|
||||
-- Update-Index OLTP benchmark
|
||||
-- ----------------------------------------------------------------------
|
||||
|
||||
require("oltp_common")
|
||||
|
||||
function prepare_statements()
|
||||
prepare_index_updates()
|
||||
end
|
||||
|
||||
function event()
|
||||
execute_index_updates(con)
|
||||
end
|
||||
|
|
@ -0,0 +1,30 @@
|
|||
#!/usr/bin/env sysbench
|
||||
-- Copyright (C) 2006-2017 Alexey Kopytov <akopytov@gmail.com>
|
||||
|
||||
-- This program is free software; you can redistribute it and/or modify
|
||||
-- it under the terms of the GNU General Public License as published by
|
||||
-- the Free Software Foundation; either version 2 of the License, or
|
||||
-- (at your option) any later version.
|
||||
|
||||
-- This program is distributed in the hope that it will be useful,
|
||||
-- but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
-- GNU General Public License for more details.
|
||||
|
||||
-- You should have received a copy of the GNU General Public License
|
||||
-- along with this program; if not, write to the Free Software
|
||||
-- Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
|
||||
-- ----------------------------------------------------------------------
|
||||
-- Update-Non-Index OLTP benchmark
|
||||
-- ----------------------------------------------------------------------
|
||||
|
||||
require("oltp_common")
|
||||
|
||||
function prepare_statements()
|
||||
prepare_non_index_updates()
|
||||
end
|
||||
|
||||
function event()
|
||||
execute_non_index_updates()
|
||||
end
|
||||
|
|
@ -0,0 +1,47 @@
|
|||
#!/usr/bin/env sysbench
|
||||
-- Copyright (C) 2006-2017 Alexey Kopytov <akopytov@gmail.com>
|
||||
|
||||
-- This program is free software; you can redistribute it and/or modify
|
||||
-- it under the terms of the GNU General Public License as published by
|
||||
-- the Free Software Foundation; either version 2 of the License, or
|
||||
-- (at your option) any later version.
|
||||
|
||||
-- This program is distributed in the hope that it will be useful,
|
||||
-- but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
-- GNU General Public License for more details.
|
||||
|
||||
-- You should have received a copy of the GNU General Public License
|
||||
-- along with this program; if not, write to the Free Software
|
||||
-- Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
|
||||
-- ----------------------------------------------------------------------
|
||||
-- Write-Only OLTP benchmark
|
||||
-- ----------------------------------------------------------------------
|
||||
|
||||
require("oltp_common")
|
||||
|
||||
function prepare_statements()
|
||||
if not sysbench.opt.skip_trx then
|
||||
prepare_begin()
|
||||
prepare_commit()
|
||||
end
|
||||
|
||||
prepare_index_updates()
|
||||
prepare_non_index_updates()
|
||||
prepare_delete_inserts()
|
||||
end
|
||||
|
||||
function event()
|
||||
if not sysbench.opt.skip_trx then
|
||||
begin()
|
||||
end
|
||||
|
||||
execute_index_updates()
|
||||
execute_non_index_updates()
|
||||
execute_delete_inserts()
|
||||
|
||||
if not sysbench.opt.skip_trx then
|
||||
commit()
|
||||
end
|
||||
end
|
||||
|
|
@ -0,0 +1,72 @@
|
|||
#!/usr/bin/env sysbench
|
||||
-- This test is designed for testing MariaDB's key_cache_segments for MyISAM,
|
||||
-- and should work with other storage engines as well.
|
||||
--
|
||||
-- For details about key_cache_segments please refer to:
|
||||
-- http://kb.askmonty.org/v/segmented-key-cache
|
||||
--
|
||||
|
||||
require("oltp_common")
|
||||
|
||||
-- Add random_points to the list of standard OLTP options
|
||||
sysbench.cmdline.options.random_points =
|
||||
{"Number of random points in the IN() clause in generated SELECTs", 10}
|
||||
|
||||
-- Override standard prepare/cleanup OLTP functions, as this benchmark does not
|
||||
-- support multiple tables
|
||||
oltp_prepare = prepare
|
||||
oltp_cleanup = cleanup
|
||||
|
||||
function prepare()
|
||||
assert(sysbench.opt.tables == 1, "this benchmark does not support " ..
|
||||
"--tables > 1")
|
||||
oltp_prepare()
|
||||
end
|
||||
|
||||
function cleanup()
|
||||
assert(sysbench.opt.tables == 1, "this benchmark does not support " ..
|
||||
"--tables > 1")
|
||||
oltp_cleanup()
|
||||
end
|
||||
|
||||
function thread_init()
|
||||
drv = sysbench.sql.driver()
|
||||
con = drv:connect()
|
||||
|
||||
local points = string.rep("?, ", sysbench.opt.random_points - 1) .. "?"
|
||||
|
||||
stmt = con:prepare(string.format([[
|
||||
SELECT id, k, c, pad
|
||||
FROM sbtest1
|
||||
WHERE k IN (%s)
|
||||
]], points))
|
||||
|
||||
params = {}
|
||||
for j = 1, sysbench.opt.random_points do
|
||||
params[j] = stmt:bind_create(sysbench.sql.type.INT)
|
||||
end
|
||||
|
||||
stmt:bind_param(unpack(params))
|
||||
|
||||
rlen = sysbench.opt.table_size / sysbench.opt.threads
|
||||
|
||||
thread_id = sysbench.tid % sysbench.opt.threads
|
||||
end
|
||||
|
||||
function thread_done()
|
||||
stmt:close()
|
||||
con:disconnect()
|
||||
end
|
||||
|
||||
function event()
|
||||
-- To prevent overlapping of our range queries we need to partition the whole
|
||||
-- table into 'threads' segments and then make each thread work with its
|
||||
-- own segment.
|
||||
for i = 1, sysbench.opt.random_points do
|
||||
local rmin = rlen * thread_id
|
||||
local rmax = rmin + rlen
|
||||
params[i]:set(sb_rand(rmin, rmax))
|
||||
end
|
||||
|
||||
stmt:execute()
|
||||
end
|
||||
|
|
@ -0,0 +1,77 @@
|
|||
#!/usr/bin/env sysbench
|
||||
-- This test is designed for testing MariaDB's key_cache_segments for MyISAM,
|
||||
-- and should work with other storage engines as well.
|
||||
--
|
||||
-- For details about key_cache_segments please refer to:
|
||||
-- http://kb.askmonty.org/v/segmented-key-cache
|
||||
--
|
||||
|
||||
require("oltp_common")
|
||||
|
||||
-- Add --number-of-ranges and --delta to the list of standard OLTP options
|
||||
sysbench.cmdline.options.number_of_ranges =
|
||||
{"Number of random BETWEEN ranges per SELECT", 10}
|
||||
sysbench.cmdline.options.delta =
|
||||
{"Size of BETWEEN ranges", 5}
|
||||
|
||||
-- Override standard prepare/cleanup OLTP functions, as this benchmark does not
|
||||
-- support multiple tables
|
||||
oltp_prepare = prepare
|
||||
oltp_cleanup = cleanup
|
||||
|
||||
function prepare()
|
||||
assert(sysbench.opt.tables == 1, "this benchmark does not support " ..
|
||||
"--tables > 1")
|
||||
oltp_prepare()
|
||||
end
|
||||
|
||||
function cleanup()
|
||||
assert(sysbench.opt.tables == 1, "this benchmark does not support " ..
|
||||
"--tables > 1")
|
||||
oltp_cleanup()
|
||||
end
|
||||
|
||||
function thread_init()
|
||||
drv = sysbench.sql.driver()
|
||||
con = drv:connect()
|
||||
|
||||
local ranges = string.rep("k BETWEEN ? AND ? OR ",
|
||||
sysbench.opt.number_of_ranges - 1) ..
|
||||
"k BETWEEN ? AND ?"
|
||||
|
||||
stmt = con:prepare(string.format([[
|
||||
SELECT count(k)
|
||||
FROM sbtest1
|
||||
WHERE %s]], ranges))
|
||||
|
||||
params = {}
|
||||
for j = 1, sysbench.opt.number_of_ranges*2 do
|
||||
params[j] = stmt:bind_create(sysbench.sql.type.INT)
|
||||
end
|
||||
|
||||
stmt:bind_param(unpack(params))
|
||||
|
||||
rlen = sysbench.opt.table_size / sysbench.opt.threads
|
||||
|
||||
thread_id = sysbench.tid % sysbench.opt.threads
|
||||
end
|
||||
|
||||
function thread_done()
|
||||
stmt:close()
|
||||
con:disconnect()
|
||||
end
|
||||
|
||||
function event()
|
||||
-- To prevent overlapping of our range queries we need to partition the whole
|
||||
-- table into 'threads' segments and then make each thread work with its
|
||||
-- own segment.
|
||||
for i = 1, sysbench.opt.number_of_ranges*2, 2 do
|
||||
local rmin = rlen * thread_id
|
||||
local rmax = rmin + rlen
|
||||
local val = sb_rand(rmin, rmax)
|
||||
params[i]:set(val)
|
||||
params[i+1]:set(val + sysbench.opt.delta)
|
||||
end
|
||||
|
||||
stmt:execute()
|
||||
end
|
||||
|
|
@ -0,0 +1,104 @@
|
|||
/*
|
||||
Copyright (C) 2016 Alexey Kopytov <akopytov@gmail.com>
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
/*
|
||||
Thread barrier implementation. It differs from pthread_barrier_t in two ways:
|
||||
|
||||
- it's more portable (will also work on OS X and Windows with existing
|
||||
pthread_* wrappers in sb_win.c).
|
||||
|
||||
- it allows defining a callback function which is called right before
|
||||
signaling the participating threads to continue, i.e. as soon as the
|
||||
required number of threads reach the barrier. The callback can also signal
|
||||
an error to sb_barrier_wait() callers by returning a non-zero value. In
|
||||
which case sb_barrier_wait() returns a negative value to all callers.
|
||||
*/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
# include "config.h"
|
||||
#endif
|
||||
|
||||
#include "sb_barrier.h"
|
||||
|
||||
int sb_barrier_init(sb_barrier_t *barrier, unsigned int count,
|
||||
sb_barrier_cb_t callback, void *arg)
|
||||
{
|
||||
if (count == 0)
|
||||
return 1;
|
||||
|
||||
if (pthread_mutex_init(&barrier->mutex, NULL) ||
|
||||
pthread_cond_init(&barrier->cond, NULL))
|
||||
return 1;
|
||||
|
||||
barrier->init_count = count;
|
||||
barrier->count = count;
|
||||
barrier->callback = callback;
|
||||
barrier->arg = arg;
|
||||
barrier->serial = 0;
|
||||
barrier->error = 0;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int sb_barrier_wait(sb_barrier_t *barrier)
|
||||
{
|
||||
int res;
|
||||
|
||||
pthread_mutex_lock(&barrier->mutex);
|
||||
|
||||
if (!--barrier->count)
|
||||
{
|
||||
barrier->serial++;
|
||||
barrier->count = barrier->init_count;
|
||||
|
||||
res = SB_BARRIER_SERIAL_THREAD;
|
||||
|
||||
pthread_cond_broadcast(&barrier->cond);
|
||||
|
||||
if (barrier->callback != NULL && barrier->callback(barrier->arg) != 0)
|
||||
{
|
||||
barrier->error = 1;
|
||||
res = -1;
|
||||
}
|
||||
|
||||
pthread_mutex_unlock(&barrier->mutex);
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
unsigned int serial = barrier->serial;
|
||||
|
||||
do {
|
||||
pthread_cond_wait(&barrier->cond, &barrier->mutex);
|
||||
} while (serial == barrier->serial);
|
||||
|
||||
res = barrier->error ? -1 : 0;
|
||||
|
||||
pthread_mutex_unlock(&barrier->mutex);
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
|
||||
void sb_barrier_destroy(sb_barrier_t *barrier)
|
||||
{
|
||||
pthread_mutex_destroy(&barrier->mutex);
|
||||
pthread_cond_destroy(&barrier->cond);
|
||||
}
|
||||
|
|
@ -0,0 +1,58 @@
|
|||
/*
|
||||
Copyright (C) 2016 Alexey Kopytov <akopytov@gmail.com>
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
/* Thread barrier implementation. */
|
||||
|
||||
#ifndef SB_BARRIER_H
|
||||
#define SB_BARRIER_H
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
# include "config.h"
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_PTHREAD_H
|
||||
# include <pthread.h>
|
||||
#endif
|
||||
|
||||
#ifdef _WIN32
|
||||
#include "sb_win.h"
|
||||
#endif
|
||||
|
||||
#define SB_BARRIER_SERIAL_THREAD 1
|
||||
|
||||
typedef int (*sb_barrier_cb_t)(void *);
|
||||
|
||||
typedef struct {
|
||||
unsigned int count;
|
||||
unsigned int init_count;
|
||||
unsigned int serial;
|
||||
pthread_mutex_t mutex;
|
||||
pthread_cond_t cond;
|
||||
sb_barrier_cb_t callback;
|
||||
void *arg;
|
||||
int error;
|
||||
} sb_barrier_t;
|
||||
|
||||
int sb_barrier_init(sb_barrier_t *barrier, unsigned int count,
|
||||
sb_barrier_cb_t callback, void *arg);
|
||||
|
||||
int sb_barrier_wait(sb_barrier_t *barrier);
|
||||
|
||||
void sb_barrier_destroy(sb_barrier_t *barrier);
|
||||
|
||||
#endif /* SB_BARRIER_H */
|
||||
|
|
@ -0,0 +1,236 @@
|
|||
/*
|
||||
Copyright (C) 2017 Alexey Kopytov <akopytov@gmail.com>
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
/*
|
||||
* This file incorporates work covered by the following copyright and
|
||||
* permission notice:
|
||||
*
|
||||
* Copyright 2010 Samy Al Bahra.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
/*
|
||||
Compatibility wrappers for ConcurrencyKit functions. ConcurrencyKit does not
|
||||
implement 64-bit atomic primitives on some 32-bit architectures (e.g. x86,
|
||||
ARMv6) natively. Newer versions support the CK_USE_CC_BUILTINS define which
|
||||
allows resorting to compiler builtins emulating 64-bit atomics on 32-bit
|
||||
architectures. However, one might want to build with an old,
|
||||
distribution-provided CK version where that option is not available. For those
|
||||
versions, define 64-bit atomics as aliases to GCC builtins. A cleaner solution
|
||||
would be to define the corresponding sysbench data structures as 32-bit
|
||||
integers on those architectures, but the amount of extra code to implement and
|
||||
support is not worth it. Code below has been copied with modifications from
|
||||
gcc/ck_pr.h from the ConcurrencyKit distribution.
|
||||
*/
|
||||
|
||||
#ifndef SB_CK_H
|
||||
#define SB_CK_H
|
||||
|
||||
#include "ck_pr.h"
|
||||
|
||||
#if !defined(CK_F_PR_LOAD_64)
|
||||
|
||||
#ifndef __GNUC__
|
||||
# error Unsupported platform
|
||||
#endif
|
||||
|
||||
#include <ck_cc.h>
|
||||
|
||||
#define CK_PR_ACCESS(x) (*(volatile __typeof__(x) *)&(x))
|
||||
|
||||
#define CK_PR_LOAD(S, M, T) \
|
||||
CK_CC_INLINE static T \
|
||||
ck_pr_md_load_##S(const M *target) \
|
||||
{ \
|
||||
T r; \
|
||||
ck_pr_barrier(); \
|
||||
r = CK_PR_ACCESS(*(const T *)target); \
|
||||
ck_pr_barrier(); \
|
||||
return (r); \
|
||||
} \
|
||||
CK_CC_INLINE static void \
|
||||
ck_pr_md_store_##S(M *target, T v) \
|
||||
{ \
|
||||
ck_pr_barrier(); \
|
||||
CK_PR_ACCESS(*(T *)target) = v; \
|
||||
ck_pr_barrier(); \
|
||||
return; \
|
||||
}
|
||||
|
||||
#define CK_PR_LOAD_S(S, T) CK_PR_LOAD(S, T, T)
|
||||
|
||||
CK_PR_LOAD_S(64, uint64_t)
|
||||
|
||||
#undef CK_PR_LOAD_S
|
||||
#undef CK_PR_LOAD
|
||||
|
||||
#define CK_PR_LOAD_SAFE(SRC, TYPE) ck_pr_md_load_##TYPE((SRC))
|
||||
|
||||
#define CK_PR_STORE_SAFE(DST, VAL, TYPE) \
|
||||
ck_pr_md_store_##TYPE( \
|
||||
((void)sizeof(*(DST) = (VAL)), (DST)), \
|
||||
(VAL))
|
||||
|
||||
#define ck_pr_load_64(SRC) CK_PR_LOAD_SAFE((SRC), 64)
|
||||
#define ck_pr_store_64(DST, VAL) CK_PR_STORE_SAFE((DST), (VAL), 64)
|
||||
|
||||
/*
|
||||
* Atomic compare and swap.
|
||||
*/
|
||||
#define CK_PR_CAS(S, M, T) \
|
||||
CK_CC_INLINE static bool \
|
||||
ck_pr_cas_##S(M *target, T compare, T set) \
|
||||
{ \
|
||||
bool z; \
|
||||
z = __sync_bool_compare_and_swap((T *)target, compare, set); \
|
||||
return z; \
|
||||
}
|
||||
|
||||
#define CK_PR_CAS_S(S, T) CK_PR_CAS(S, T, T)
|
||||
|
||||
CK_PR_CAS_S(64, uint64_t)
|
||||
|
||||
#undef CK_PR_CAS_S
|
||||
#undef CK_PR_CAS
|
||||
|
||||
#define CK_PR_CAS_O(S, T) \
|
||||
CK_CC_INLINE static bool \
|
||||
ck_pr_cas_##S##_value(T *target, T compare, T set, T *v) \
|
||||
{ \
|
||||
set = __sync_val_compare_and_swap(target, compare, set);\
|
||||
*v = set; \
|
||||
return (set == compare); \
|
||||
}
|
||||
|
||||
CK_PR_CAS_O(64, uint64_t)
|
||||
|
||||
#undef CK_PR_CAS_O
|
||||
|
||||
/*
|
||||
* Atomic store-only binary operations.
|
||||
*/
|
||||
#define CK_PR_BINARY(K, S, M, T) \
|
||||
CK_CC_INLINE static void \
|
||||
ck_pr_##K##_##S(M *target, T d) \
|
||||
{ \
|
||||
d = __sync_fetch_and_##K((T *)target, d); \
|
||||
return; \
|
||||
}
|
||||
|
||||
#define CK_PR_BINARY_S(K, S, T) CK_PR_BINARY(K, S, T, T)
|
||||
|
||||
#define CK_PR_GENERATE(K) \
|
||||
CK_PR_BINARY_S(K, 64, uint64_t)
|
||||
|
||||
CK_PR_GENERATE(add)
|
||||
CK_PR_GENERATE(sub)
|
||||
CK_PR_GENERATE(and)
|
||||
CK_PR_GENERATE(or)
|
||||
CK_PR_GENERATE(xor)
|
||||
|
||||
#undef CK_PR_GENERATE
|
||||
#undef CK_PR_BINARY_S
|
||||
#undef CK_PR_BINARY
|
||||
|
||||
#define CK_PR_UNARY(S, M, T) \
|
||||
CK_CC_INLINE static void \
|
||||
ck_pr_inc_##S(M *target) \
|
||||
{ \
|
||||
ck_pr_add_##S(target, (T)1); \
|
||||
return; \
|
||||
} \
|
||||
CK_CC_INLINE static void \
|
||||
ck_pr_dec_##S(M *target) \
|
||||
{ \
|
||||
ck_pr_sub_##S(target, (T)1); \
|
||||
return; \
|
||||
}
|
||||
|
||||
#define CK_PR_UNARY_S(S, M) CK_PR_UNARY(S, M, M)
|
||||
|
||||
CK_PR_UNARY_S(64, uint64_t)
|
||||
|
||||
#undef CK_PR_UNARY_S
|
||||
#undef CK_PR_UNARY
|
||||
|
||||
#define CK_PR_FAA(S, M, T, C) \
|
||||
CK_CC_INLINE static C \
|
||||
ck_pr_faa_##S(M *target, T delta) \
|
||||
{ \
|
||||
T previous; \
|
||||
C punt; \
|
||||
punt = (C)ck_pr_md_load_##S(target); \
|
||||
previous = (T)punt; \
|
||||
while (ck_pr_cas_##S##_value(target, \
|
||||
(C)previous, \
|
||||
(C)(previous + delta), \
|
||||
&previous) == false) \
|
||||
ck_pr_stall(); \
|
||||
\
|
||||
return ((C)previous); \
|
||||
}
|
||||
|
||||
#define CK_PR_FAS(S, M, C) \
|
||||
CK_CC_INLINE static C \
|
||||
ck_pr_fas_##S(M *target, C update) \
|
||||
{ \
|
||||
C previous; \
|
||||
previous = ck_pr_md_load_##S(target); \
|
||||
while (ck_pr_cas_##S##_value(target, \
|
||||
previous, \
|
||||
update, \
|
||||
&previous) == false) \
|
||||
ck_pr_stall(); \
|
||||
\
|
||||
return (previous); \
|
||||
}
|
||||
|
||||
#define CK_PR_FAA_S(S, M) CK_PR_FAA(S, M, M, M)
|
||||
#define CK_PR_FAS_S(S, M) CK_PR_FAS(S, M, M)
|
||||
|
||||
CK_PR_FAA_S(64, uint64_t)
|
||||
CK_PR_FAS_S(64, uint64_t)
|
||||
|
||||
#undef CK_PR_FAA_S
|
||||
#undef CK_PR_FAA
|
||||
#undef CK_PR_FAS_S
|
||||
#undef CK_PR_FAS
|
||||
|
||||
#endif /* !CK_F_PR_LOAD_64*/
|
||||
#endif /* SB_CK_H */
|
||||
|
|
@ -0,0 +1,94 @@
|
|||
/*
|
||||
Copyright (C) 2017 Alexey Kopytov <akopytov@gmail.com>
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
# include "config.h"
|
||||
#endif
|
||||
|
||||
#include "sb_counter.h"
|
||||
#include "sysbench.h"
|
||||
#include "sb_util.h"
|
||||
#include "sb_ck_pr.h"
|
||||
|
||||
sb_counters_t *sb_counters CK_CC_CACHELINE;
|
||||
|
||||
static sb_counters_t last_intermediate_counters;
|
||||
static sb_counters_t last_cumulative_counters;
|
||||
|
||||
/* Initialize per-thread stats */
|
||||
|
||||
int sb_counters_init(void)
|
||||
{
|
||||
SB_COMPILE_TIME_ASSERT(sizeof(sb_counters_t) % CK_MD_CACHELINE == 0);
|
||||
|
||||
sb_counters = sb_alloc_per_thread_array(sizeof(sb_counters_t));
|
||||
|
||||
return sb_counters == NULL;
|
||||
}
|
||||
|
||||
void sb_counters_done(void)
|
||||
{
|
||||
if (sb_counters != NULL)
|
||||
{
|
||||
free(sb_counters);
|
||||
sb_counters = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
static void sb_counters_merge(sb_counters_t dst)
|
||||
{
|
||||
for (size_t t = 0; t < SB_CNT_MAX; t++)
|
||||
for (size_t i = 0; i < sb_globals.threads; i++)
|
||||
dst[t] += sb_counter_val(i, t);
|
||||
}
|
||||
|
||||
static void sb_counters_checkpoint(sb_counters_t dst, sb_counters_t cp)
|
||||
{
|
||||
for (size_t i = 0; i < SB_CNT_MAX; i++)
|
||||
{
|
||||
uint64_t tmp = cp[i];
|
||||
cp[i] = dst[i];
|
||||
dst[i] = dst[i] - tmp;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
Return aggregate counter values since the last intermediate report. This is
|
||||
not thread-safe as it updates the global last report state, so it must be
|
||||
called from a single thread.
|
||||
*/
|
||||
void sb_counters_agg_intermediate(sb_counters_t val)
|
||||
{
|
||||
memset(val, 0, sizeof(sb_counters_t));
|
||||
|
||||
sb_counters_merge(val);
|
||||
sb_counters_checkpoint(val, last_intermediate_counters);
|
||||
}
|
||||
|
||||
/*
|
||||
Return aggregate counter values since the last cumulative report. This is
|
||||
not thread-safe as it updates the global last report state, so it must be
|
||||
called from a single thread.
|
||||
*/
|
||||
void sb_counters_agg_cumulative(sb_counters_t val)
|
||||
{
|
||||
memset(val, 0, sizeof(sb_counters_t));
|
||||
|
||||
sb_counters_merge(val);
|
||||
sb_counters_checkpoint(val, last_cumulative_counters);
|
||||
}
|
||||
|
|
@ -0,0 +1,105 @@
|
|||
/*
|
||||
Copyright (C) 2017 Alexey Kopytov <akopytov@gmail.com>
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#ifndef SB_COUNTER_H
|
||||
#define SB_COUNTER_H
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
# include "config.h"
|
||||
#endif
|
||||
|
||||
#ifdef STDC_HEADERS
|
||||
# include <inttypes.h>
|
||||
#endif
|
||||
|
||||
#include "sb_util.h"
|
||||
#include "sb_ck_pr.h"
|
||||
|
||||
/* Statistic counter types */
|
||||
|
||||
typedef enum {
|
||||
SB_CNT_OTHER, /* unknown type of queries */
|
||||
SB_CNT_READ, /* reads */
|
||||
SB_CNT_WRITE, /* writes */
|
||||
SB_CNT_EVENT, /* events */
|
||||
SB_CNT_ERROR, /* errors */
|
||||
SB_CNT_RECONNECT, /* reconnects */
|
||||
SB_CNT_MAX
|
||||
} sb_counter_type_t;
|
||||
|
||||
/*
|
||||
sizeof(sb_counter_t) must be a multiple of CK_MD_CACHELINE to avoid cache
|
||||
line sharing.
|
||||
*/
|
||||
typedef uint64_t
|
||||
sb_counters_t[SB_ALIGN(SB_CNT_MAX * sizeof(uint64_t), CK_MD_CACHELINE) /
|
||||
sizeof(uint64_t)];
|
||||
|
||||
extern sb_counters_t *sb_counters;
|
||||
|
||||
int sb_counters_init(void);
|
||||
|
||||
void sb_counters_done(void);
|
||||
|
||||
/*
|
||||
Cannot use C99 inline here, because CK atomic primitives use static inlines
|
||||
which in turn leads to compiler warnings. So for performance reasons the
|
||||
following functions are defined 'static inline' too everywhere except sb_lua.c
|
||||
where they are declared and defined as external linkage functions to be
|
||||
available from LuaJIT FFI.
|
||||
*/
|
||||
#ifndef SB_LUA_EXPORT
|
||||
# define SB_LUA_INLINE static inline
|
||||
#else
|
||||
# define SB_LUA_INLINE
|
||||
uint64_t sb_counter_val(int thread_id, sb_counter_type_t type);
|
||||
void sb_counter_inc(int thread_id, sb_counter_type_t type);
|
||||
#endif
|
||||
|
||||
/* Return the current value for a given counter */
|
||||
SB_LUA_INLINE
|
||||
uint64_t sb_counter_val(int thread_id, sb_counter_type_t type)
|
||||
{
|
||||
return ck_pr_load_64(&sb_counters[thread_id][type]);
|
||||
}
|
||||
|
||||
/* Increment a given stat counter for a given thread */
|
||||
SB_LUA_INLINE
|
||||
void sb_counter_inc(int thread_id, sb_counter_type_t type)
|
||||
{
|
||||
ck_pr_store_64(&sb_counters[thread_id][type],
|
||||
sb_counter_val(thread_id, type)+1);
|
||||
}
|
||||
|
||||
#undef SB_LUA_INLINE
|
||||
|
||||
/*
|
||||
Return aggregate counter values since the last intermediate report. This is
|
||||
not thread-safe as it updates the global last report state, so it must be
|
||||
called from a single thread.
|
||||
*/
|
||||
void sb_counters_agg_intermediate(sb_counters_t val);
|
||||
|
||||
/*
|
||||
Return aggregate counter values since the last cumulative report. This is
|
||||
not thread-safe as it updates the global last report state, so it must be
|
||||
called from a single thread.
|
||||
*/
|
||||
void sb_counters_agg_cumulative(sb_counters_t val);
|
||||
|
||||
#endif
|
||||
|
|
@ -0,0 +1,27 @@
|
|||
/* Copyright (C) 2016 Alexey Kopytov <akopytov@gmail.com>
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
/* Global and portability-related macros */
|
||||
|
||||
#ifndef SB_GLOBAL_H
|
||||
#define SB_GLOBAL_H
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#endif /* SB_GLOBAL_H */
|
||||
|
|
@ -0,0 +1,373 @@
|
|||
/* Copyright (C) 2011-2017 Alexey Kopytov.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
# include "config.h"
|
||||
#endif
|
||||
#ifdef _WIN32
|
||||
#include "sb_win.h"
|
||||
#endif
|
||||
|
||||
#ifdef STDC_HEADERS
|
||||
# include <stdio.h>
|
||||
# include <stdlib.h>
|
||||
#endif
|
||||
#ifdef HAVE_STRING_H
|
||||
# include <string.h>
|
||||
#endif
|
||||
#ifdef HAVE_MATH_H
|
||||
# include <math.h>
|
||||
#endif
|
||||
|
||||
#include "sysbench.h"
|
||||
#include "sb_histogram.h"
|
||||
#include "sb_logger.h"
|
||||
#include "sb_rand.h"
|
||||
|
||||
#include "sb_ck_pr.h"
|
||||
#include "ck_cc.h"
|
||||
|
||||
#include "sb_util.h"
|
||||
|
||||
|
||||
/*
|
||||
Number of slots for current histogram array. TODO: replace this constant with
|
||||
some autodetection code based on the number of available cores or some such.
|
||||
*/
|
||||
#define SB_HISTOGRAM_NSLOTS 128
|
||||
|
||||
/* Global latency histogram */
|
||||
sb_histogram_t sb_latency_histogram CK_CC_CACHELINE;
|
||||
|
||||
|
||||
int sb_histogram_init(sb_histogram_t *h, size_t size,
|
||||
double range_min, double range_max)
|
||||
{
|
||||
size_t i;
|
||||
uint64_t *tmp;
|
||||
|
||||
/* Allocate memory for cumulative_array + temp_array + all slot arrays */
|
||||
tmp = (uint64_t *) calloc(size * (SB_HISTOGRAM_NSLOTS + 2), sizeof(uint64_t));
|
||||
h->interm_slots = (uint64_t **) malloc(SB_HISTOGRAM_NSLOTS *
|
||||
sizeof(uint64_t *));
|
||||
|
||||
if (tmp == NULL || h->interm_slots == NULL)
|
||||
{
|
||||
log_text(LOG_FATAL,
|
||||
"Failed to allocate memory for a histogram object, size = %zd",
|
||||
size);
|
||||
return 1;
|
||||
}
|
||||
|
||||
h->cumulative_array = tmp;
|
||||
tmp += size;
|
||||
|
||||
h->temp_array = tmp;
|
||||
tmp += size;
|
||||
|
||||
for (i = 0; i < SB_HISTOGRAM_NSLOTS; i++)
|
||||
{
|
||||
h->interm_slots[i] = tmp;
|
||||
tmp += size;
|
||||
}
|
||||
|
||||
h->range_deduct = log(range_min);
|
||||
h->range_mult = (size - 1) / (log(range_max) - h->range_deduct);
|
||||
|
||||
h->range_min = range_min;
|
||||
h->range_max = range_max;
|
||||
|
||||
h->array_size = size;
|
||||
|
||||
pthread_rwlock_init(&h->lock, NULL);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
void sb_histogram_update(sb_histogram_t *h, double value)
|
||||
{
|
||||
size_t slot;
|
||||
ssize_t i;
|
||||
|
||||
slot = sb_rand_uniform_uint64() % SB_HISTOGRAM_NSLOTS;
|
||||
|
||||
i = floor((log(value) - h->range_deduct) * h->range_mult + 0.5);
|
||||
if (SB_UNLIKELY(i < 0))
|
||||
i = 0;
|
||||
else if (SB_UNLIKELY(i >= (ssize_t) (h->array_size)))
|
||||
i = h->array_size - 1;
|
||||
|
||||
ck_pr_inc_64(&h->interm_slots[slot][i]);
|
||||
}
|
||||
|
||||
|
||||
double sb_histogram_get_pct_intermediate(sb_histogram_t *h,
|
||||
double percentile)
|
||||
{
|
||||
size_t i, s;
|
||||
uint64_t nevents, ncur, nmax;
|
||||
double res;
|
||||
|
||||
nevents = 0;
|
||||
|
||||
/*
|
||||
This can be called concurrently with other sb_histogram_get_pct_*()
|
||||
functions, so use the lock to protect shared structures. This will not block
|
||||
sb_histogram_update() calls, but we make sure we don't lose any concurrent
|
||||
increments by atomically fetching each array element and replacing it with
|
||||
0.
|
||||
*/
|
||||
pthread_rwlock_wrlock(&h->lock);
|
||||
|
||||
/*
|
||||
Merge intermediate slots into temp_array.
|
||||
*/
|
||||
const size_t size = h->array_size;
|
||||
uint64_t * const array = h->temp_array;
|
||||
|
||||
for (i = 0; i < size; i++)
|
||||
{
|
||||
array[i] = ck_pr_fas_64(&h->interm_slots[0][i], 0);
|
||||
nevents += array[i];
|
||||
}
|
||||
|
||||
for (s = 1; s < SB_HISTOGRAM_NSLOTS; s++)
|
||||
{
|
||||
for (i = 0; i < size; i++)
|
||||
{
|
||||
uint64_t t;
|
||||
|
||||
t = ck_pr_fas_64(&h->interm_slots[s][i], 0);
|
||||
|
||||
array[i] += t;
|
||||
nevents += t;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
Now that we have an aggregate 'snapshot' of current arrays and the total
|
||||
number of events in it, calculate the current, intermediate percentile value
|
||||
to return.
|
||||
*/
|
||||
nmax = floor(nevents * percentile / 100 + 0.5);
|
||||
|
||||
ncur = 0;
|
||||
for (i = 0; i < size; i++)
|
||||
{
|
||||
ncur += array[i];
|
||||
if (ncur >= nmax)
|
||||
break;
|
||||
}
|
||||
|
||||
res = exp(i / h->range_mult + h->range_deduct);
|
||||
|
||||
/* Finally, add temp_array into accumulated values in cumulative_array. */
|
||||
for (i = 0; i < size; i++)
|
||||
{
|
||||
h->cumulative_array[i] += array[i];
|
||||
}
|
||||
|
||||
h->cumulative_nevents += nevents;
|
||||
|
||||
pthread_rwlock_unlock(&h->lock);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
Aggregate arrays from intermediate slots into cumulative_array. This should be
|
||||
called with the histogram lock write-locked.
|
||||
*/
|
||||
static void merge_intermediate_into_cumulative(sb_histogram_t *h)
|
||||
{
|
||||
size_t i, s;
|
||||
uint64_t nevents;
|
||||
|
||||
nevents = h->cumulative_nevents;
|
||||
|
||||
const size_t size = h->array_size;
|
||||
uint64_t * const array = h->cumulative_array;
|
||||
|
||||
for (s = 0; s < SB_HISTOGRAM_NSLOTS; s++)
|
||||
{
|
||||
for (i = 0; i < size; i++)
|
||||
{
|
||||
uint64_t t = ck_pr_fas_64(&h->interm_slots[s][i], 0);
|
||||
array[i] += t;
|
||||
nevents += t;
|
||||
}
|
||||
}
|
||||
|
||||
h->cumulative_nevents = nevents;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
Calculate a given percentile from the cumulative array. This should be called
|
||||
with the histogram lock either read- or write-locked.
|
||||
*/
|
||||
static double get_pct_cumulative(sb_histogram_t *h, double percentile)
|
||||
{
|
||||
size_t i;
|
||||
uint64_t ncur, nmax;
|
||||
|
||||
nmax = floor(h->cumulative_nevents * percentile / 100 + 0.5);
|
||||
|
||||
ncur = 0;
|
||||
for (i = 0; i < h->array_size; i++)
|
||||
{
|
||||
ncur += h->cumulative_array[i];
|
||||
if (ncur >= nmax)
|
||||
break;
|
||||
}
|
||||
|
||||
return exp(i / h->range_mult + h->range_deduct);
|
||||
}
|
||||
|
||||
|
||||
double sb_histogram_get_pct_cumulative(sb_histogram_t *h, double percentile)
|
||||
{
|
||||
double res;
|
||||
|
||||
/*
|
||||
This can be called concurrently with other sb_histogram_get_pct_*()
|
||||
functions, so use the lock to protect shared structures. This will not block
|
||||
sb_histogram_update() calls, but we make sure we don't lose any concurrent
|
||||
increments by atomically fetching each array element and replacing it with
|
||||
0.
|
||||
*/
|
||||
pthread_rwlock_wrlock(&h->lock);
|
||||
|
||||
merge_intermediate_into_cumulative(h);
|
||||
|
||||
res = get_pct_cumulative(h, percentile);
|
||||
|
||||
pthread_rwlock_unlock(&h->lock);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
|
||||
double sb_histogram_get_pct_checkpoint(sb_histogram_t *h,
|
||||
double percentile)
|
||||
{
|
||||
double res;
|
||||
|
||||
/*
|
||||
This can be called concurrently with other sb_histogram_get_pct_*()
|
||||
functions, so use the lock to protect shared structures. This will not block
|
||||
sb_histogram_update() calls, but we make sure we don't lose any concurrent
|
||||
increments by atomically fetching each array element and replacing it with
|
||||
0.
|
||||
*/
|
||||
pthread_rwlock_wrlock(&h->lock);
|
||||
|
||||
merge_intermediate_into_cumulative(h);
|
||||
|
||||
res = get_pct_cumulative(h, percentile);
|
||||
|
||||
/* Reset the cumulative array */
|
||||
memset(h->cumulative_array, 0, h->array_size * sizeof(uint64_t));
|
||||
h->cumulative_nevents = 0;
|
||||
|
||||
pthread_rwlock_unlock(&h->lock);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
|
||||
void sb_histogram_print(sb_histogram_t *h)
|
||||
{
|
||||
uint64_t maxcnt;
|
||||
int width;
|
||||
size_t i;
|
||||
|
||||
pthread_rwlock_wrlock(&h->lock);
|
||||
|
||||
merge_intermediate_into_cumulative(h);
|
||||
|
||||
uint64_t * const array = h->cumulative_array;
|
||||
|
||||
maxcnt = 0;
|
||||
for (i = 0; i < h->array_size; i++)
|
||||
{
|
||||
if (array[i] > maxcnt)
|
||||
maxcnt = array[i];
|
||||
}
|
||||
|
||||
if (maxcnt == 0)
|
||||
return;
|
||||
|
||||
printf(" value ------------- distribution ------------- count\n");
|
||||
|
||||
for (i = 0; i < h->array_size; i++)
|
||||
{
|
||||
if (array[i] == 0)
|
||||
continue;
|
||||
|
||||
width = floor(array[i] * (double) 40 / maxcnt + 0.5);
|
||||
|
||||
printf("%12.3f |%-40.*s %lu\n",
|
||||
exp(i / h->range_mult + h->range_deduct), /* value */
|
||||
width, "****************************************", /* distribution */
|
||||
(unsigned long) array[i]); /* count */
|
||||
}
|
||||
|
||||
pthread_rwlock_unlock(&h->lock);
|
||||
}
|
||||
|
||||
|
||||
void sb_histogram_done(sb_histogram_t *h)
|
||||
{
|
||||
pthread_rwlock_destroy(&h->lock);
|
||||
|
||||
free(h->cumulative_array);
|
||||
free(h->interm_slots);
|
||||
}
|
||||
|
||||
/*
|
||||
Allocate a new histogram and initialize it with sb_histogram_init().
|
||||
*/
|
||||
|
||||
sb_histogram_t *sb_histogram_new(size_t size, double range_min,
|
||||
double range_max)
|
||||
{
|
||||
sb_histogram_t *h;
|
||||
|
||||
if ((h = malloc(sizeof(*h))) == NULL)
|
||||
return NULL;
|
||||
|
||||
if (sb_histogram_init(h, size, range_min, range_max))
|
||||
{
|
||||
free(h);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return h;
|
||||
}
|
||||
|
||||
/*
|
||||
Deallocate a histogram allocated with sb_histogram_new().
|
||||
*/
|
||||
|
||||
void sb_histogram_delete(sb_histogram_t *h)
|
||||
{
|
||||
sb_histogram_done(h);
|
||||
free(h);
|
||||
}
|
||||
|
|
@ -0,0 +1,119 @@
|
|||
/* Copyright (C) 2011-2017 Alexey Kopytov.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#ifndef SB_HISTOGRAM_H
|
||||
#define SB_HISTOGRAM_H
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#ifdef HAVE_PTHREAD_H
|
||||
# include <pthread.h>
|
||||
#endif
|
||||
|
||||
typedef struct {
|
||||
/*
|
||||
Cumulative histogram array. Updated 'on demand' by
|
||||
sb_histogram_get_pct_intermediate(). Protected by 'lock'.
|
||||
*/
|
||||
uint64_t *cumulative_array;
|
||||
/*
|
||||
Total number of events in cumulative_array. Updated on demand by
|
||||
sb_histogram_get_pct_intermediate(). Protected by 'lock'.
|
||||
*/
|
||||
uint64_t cumulative_nevents;
|
||||
/*
|
||||
Temporary array for intermediate percentile calculations. Protected by
|
||||
'lock'.
|
||||
*/
|
||||
uint64_t *temp_array;
|
||||
/*
|
||||
Intermediate histogram values are split into multiple slots and updated
|
||||
with atomics. Aggregations into cumulative values is performed by
|
||||
sb_histogram_get_pct_intermediate() function.
|
||||
*/
|
||||
uint64_t **interm_slots;
|
||||
/* Number of elements in each array */
|
||||
size_t array_size;
|
||||
/* Lower bound of values to track */
|
||||
double range_min;
|
||||
/* Upper bound of values to track */
|
||||
double range_max;
|
||||
/* Value to deduct to calculate histogram range based on array element */
|
||||
double range_deduct;
|
||||
/* Value to multiply to calculate histogram range based array element */
|
||||
double range_mult;
|
||||
/*
|
||||
rwlock to protect cumulative_array and cumulative_nevents from concurrent
|
||||
updates.
|
||||
*/
|
||||
pthread_rwlock_t lock;
|
||||
} sb_histogram_t;
|
||||
|
||||
/* Global latency histogram */
|
||||
extern sb_histogram_t sb_latency_histogram;
|
||||
|
||||
/*
|
||||
Allocate a new histogram and initialize it with sb_histogram_init().
|
||||
*/
|
||||
sb_histogram_t *sb_histogram_new(size_t size, double range_min,
|
||||
double range_max);
|
||||
|
||||
/*
|
||||
Deallocate a histogram allocated with sb_histogram_new().
|
||||
*/
|
||||
void sb_histogram_delete(sb_histogram_t *h);
|
||||
|
||||
/*
|
||||
Initialize a new histogram object with a given array size and value bounds.
|
||||
*/
|
||||
int sb_histogram_init(sb_histogram_t *h, size_t size,
|
||||
double range_min, double range_max);
|
||||
|
||||
/* Update histogram with a given value. */
|
||||
void sb_histogram_update(sb_histogram_t *h, double value);
|
||||
|
||||
/*
|
||||
Calculate a given percentile value from the intermediate histogram values,
|
||||
then merge intermediate values into cumulative ones atomically, i.e. in a way
|
||||
that no concurrent updates are lost and will be accounted in either the
|
||||
current or later merge of intermediate clues.
|
||||
*/
|
||||
double sb_histogram_get_pct_intermediate(sb_histogram_t *h, double percentile);
|
||||
|
||||
/*
|
||||
Merge intermediate histogram values into cumulative ones and calculate a given
|
||||
percentile value from the cumulative array.
|
||||
*/
|
||||
double sb_histogram_get_pct_cumulative(sb_histogram_t *h, double percentile);
|
||||
|
||||
/*
|
||||
Similar to sb_histogram_get_pct_cumulative(), but also resets cumulative
|
||||
stats right after calculating the returned percentile. The reset happens
|
||||
atomically so that no conucrrent updates are lost after percentile
|
||||
calculation. This is currently used only by 'checkpoint' reports.
|
||||
*/
|
||||
double sb_histogram_get_pct_checkpoint(sb_histogram_t *h, double percentile);
|
||||
|
||||
/*
|
||||
Print a given histogram to stdout
|
||||
*/
|
||||
void sb_histogram_print(sb_histogram_t *h);
|
||||
|
||||
/* Destroy a given histogram object */
|
||||
void sb_histogram_done(sb_histogram_t *h);
|
||||
|
||||
#endif
|
||||
|
|
@ -0,0 +1,120 @@
|
|||
/* Copyright (C) 2004 MySQL AB
|
||||
Copyright (C) 2004-2014 Alexey Kopytov <akopytov@gmail.com>
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#ifndef SB_LIST_H
|
||||
|
||||
#define SB_LIST_H
|
||||
|
||||
typedef struct sb_list_item_t
|
||||
{
|
||||
struct sb_list_item_t *next_p;
|
||||
struct sb_list_item_t *prev_p;
|
||||
}
|
||||
sb_list_item_t;
|
||||
|
||||
typedef sb_list_item_t sb_list_item;
|
||||
typedef sb_list_item_t sb_list_t ;
|
||||
|
||||
#ifndef offsetof
|
||||
# define offsetof(type, member) ((size_t) &((type *)0)->member)
|
||||
#endif
|
||||
|
||||
#define SB_LIST_DECLARE(name) \
|
||||
SB_LIST_T name = { &(name), &(name) }
|
||||
|
||||
#define SB_LIST_INIT(head_p) \
|
||||
do { \
|
||||
(head_p)->next_p = (head_p); \
|
||||
(head_p)->prev_p = (head_p); \
|
||||
} while (0)
|
||||
|
||||
#define SB_LIST_ITEM_INIT(item_p) \
|
||||
SB_LIST_INIT(item_p)
|
||||
|
||||
#define SB_LIST_ADD(item_p, head_p) \
|
||||
do { \
|
||||
(item_p)->next_p = (head_p)->next_p; \
|
||||
(item_p)->prev_p = (head_p); \
|
||||
(head_p)->next_p = (item_p); \
|
||||
(item_p)->next_p->prev_p = (item_p); \
|
||||
} while (0)
|
||||
|
||||
#define SB_LIST_ADD_TAIL(item_p, head_p) \
|
||||
do { \
|
||||
(item_p)->prev_p = (head_p)->prev_p; \
|
||||
(item_p)->next_p = (head_p); \
|
||||
(head_p)->prev_p = (item_p); \
|
||||
(item_p)->prev_p->next_p = (item_p); \
|
||||
} while (0);
|
||||
|
||||
#define SB_LIST_DELETE(old_item_p) \
|
||||
do { \
|
||||
(old_item_p)->next_p->prev_p = (old_item_p)->prev_p; \
|
||||
(old_item_p)->prev_p->next_p = (old_item_p)->next_p; \
|
||||
} while (0)
|
||||
|
||||
#define SB_LIST_REPLACE(item_p, old_item_p) \
|
||||
do { \
|
||||
(item_p)->next_p = (old_item_p)->next_p; \
|
||||
(item_p)->prev_p = (old_item_p)->prev_p; \
|
||||
(item_p)->next_p->prev_p = (item_p); \
|
||||
(item_p)->prev_p->next_p = (item_p); \
|
||||
} while (0)
|
||||
|
||||
#define SB_LIST_IS_EMPTY(head_p) \
|
||||
((head_p)->next_p == (head_p))
|
||||
|
||||
#define SB_LIST_ITEM_IN_LIST(item_p) \
|
||||
((item_p)->next_p != (item_p))
|
||||
|
||||
#define SB_LIST_ITEM_FIRST(item_p, head_p) \
|
||||
((item_p)->prev_p != (head_p))
|
||||
|
||||
#define SB_LIST_ITEM_LAST(item_p, head_p) \
|
||||
((item_p)->next_p == (head_p))
|
||||
|
||||
#define SB_LIST_ITEM_NEXT(item_p) \
|
||||
((item_p)->next_p)
|
||||
|
||||
#define SB_LIST_ITEM_PREV(item_p) \
|
||||
((item_p)->prev_p)
|
||||
|
||||
#define SB_LIST_ENTRY(ptr, type, member) \
|
||||
((type *)(void *)(((char *)(ptr) - offsetof(type, member))))
|
||||
|
||||
#define SB_LIST_ONCE(pos_p, head_p) \
|
||||
pos_p= (head_p)->next_p; if (pos_p != (head_p))
|
||||
|
||||
#define SB_LIST_FOR_EACH(pos_p, head_p) \
|
||||
for (pos_p = (head_p)->next_p; pos_p != (head_p); pos_p = pos_p->next_p)
|
||||
|
||||
#define SB_LIST_ENUM_START(head_p) \
|
||||
(head_p)
|
||||
|
||||
#define SB_LIST_ENUM_NEXT(pos_p, head_p) \
|
||||
((pos_p->next_p != (head_p)) ? (pos_p->next_p) : NULL)
|
||||
|
||||
#define SB_LIST_FOR_EACH_SAFE(pos_p, temp_p, head_p) \
|
||||
for (pos_p = (head_p)->next_p, temp_p = (pos_p)->next_p; pos_p != (head_p); \
|
||||
pos_p = temp_p, temp_p = (pos_p)->next_p)
|
||||
|
||||
#define SB_LIST_FOR_EACH_REV_SAFE(pos_p, temp_p, head_p) \
|
||||
for (pos_p = (head_p)->prev_p, temp_p = (pos_p)->prev_p; pos_p != (head_p); \
|
||||
pos_p = temp_p, temp_p = (pos_p)->prev_p)
|
||||
|
||||
#endif /* SB_LIST_H */
|
||||
|
|
@ -0,0 +1,517 @@
|
|||
/* Copyright (C) 2004 MySQL AB
|
||||
Copyright (C) 2004-2017 Alexey Kopytov <akopytov@gmail.com>
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
# include "config.h"
|
||||
#endif
|
||||
#ifdef _WIN32
|
||||
#include "sb_win.h"
|
||||
#endif
|
||||
|
||||
#ifdef STDC_HEADERS
|
||||
# include <stdio.h>
|
||||
# include <stdarg.h>
|
||||
# include <string.h>
|
||||
#endif
|
||||
#ifdef HAVE_ERRNO_H
|
||||
# include <errno.h>
|
||||
#endif
|
||||
#ifdef HAVE_MATH_H
|
||||
# include <math.h>
|
||||
#endif
|
||||
|
||||
#include "sysbench.h"
|
||||
#include "sb_list.h"
|
||||
#include "sb_logger.h"
|
||||
#include "sb_histogram.h"
|
||||
|
||||
#include "ck_cc.h"
|
||||
|
||||
#define TEXT_BUFFER_SIZE 4096
|
||||
#define ERROR_BUFFER_SIZE 256
|
||||
|
||||
/*
|
||||
Use 1024-element array for latency histogram tracking values between 0.001
|
||||
milliseconds and 100 seconds.
|
||||
*/
|
||||
#define OPER_LOG_GRANULARITY 1024
|
||||
#define OPER_LOG_MIN_VALUE 1e-3
|
||||
#define OPER_LOG_MAX_VALUE 1E5
|
||||
|
||||
/* Array of message handlers (one chain per message type) */
|
||||
|
||||
static sb_list_t handlers[LOG_MSG_TYPE_MAX];
|
||||
|
||||
/* set after logger initialization */
|
||||
static unsigned char initialized;
|
||||
|
||||
static pthread_mutex_t text_mutex;
|
||||
static unsigned int text_cnt;
|
||||
static char text_buf[TEXT_BUFFER_SIZE];
|
||||
|
||||
|
||||
static int text_handler_init(void);
|
||||
static int text_handler_process(log_msg_t *msg);
|
||||
|
||||
static int oper_handler_init(void);
|
||||
static int oper_handler_done(void);
|
||||
|
||||
/* Built-in log handlers */
|
||||
|
||||
/* Text messages handler */
|
||||
|
||||
static sb_arg_t text_handler_args[] =
|
||||
{
|
||||
SB_OPT("verbosity", "verbosity level {5 - debug, 0 - only critical messages}",
|
||||
"3", INT),
|
||||
|
||||
SB_OPT_END
|
||||
};
|
||||
|
||||
static log_handler_t text_handler = {
|
||||
{
|
||||
&text_handler_init,
|
||||
&text_handler_process,
|
||||
NULL,
|
||||
},
|
||||
text_handler_args,
|
||||
{0,0}
|
||||
};
|
||||
|
||||
/* Operation start/stop messages handler */
|
||||
|
||||
static sb_arg_t oper_handler_args[] =
|
||||
{
|
||||
SB_OPT("percentile", "percentile to calculate in latency statistics (1-100). "
|
||||
"Use the special value of 0 to disable percentile calculations",
|
||||
"95", INT),
|
||||
SB_OPT("histogram", "print latency histogram in report", "off", BOOL),
|
||||
|
||||
SB_OPT_END
|
||||
};
|
||||
|
||||
static log_handler_t oper_handler = {
|
||||
{
|
||||
oper_handler_init,
|
||||
NULL,
|
||||
oper_handler_done,
|
||||
},
|
||||
oper_handler_args,
|
||||
{0,0}
|
||||
};
|
||||
|
||||
|
||||
/* Register logger and all handlers */
|
||||
|
||||
|
||||
int log_register(void)
|
||||
{
|
||||
unsigned int i;
|
||||
|
||||
for (i = 0; i < LOG_MSG_TYPE_MAX; i++)
|
||||
SB_LIST_INIT(handlers + i);
|
||||
|
||||
log_add_handler(LOG_MSG_TYPE_TEXT, &text_handler);
|
||||
log_add_handler(LOG_MSG_TYPE_OPER, &oper_handler);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/* Display command line options for registered log handlers */
|
||||
|
||||
|
||||
void log_print_help(void)
|
||||
{
|
||||
unsigned int i;
|
||||
sb_list_item_t *pos;
|
||||
log_handler_t *handler;
|
||||
|
||||
printf("Log options:\n");
|
||||
|
||||
for (i = 0; i < LOG_MSG_TYPE_MAX; i++)
|
||||
{
|
||||
SB_LIST_FOR_EACH(pos, handlers + i)
|
||||
{
|
||||
handler = SB_LIST_ENTRY(pos, log_handler_t, listitem);
|
||||
if (handler->args != NULL)
|
||||
sb_print_options(handler->args);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* Initialize logger and all handlers */
|
||||
|
||||
|
||||
int log_init(void)
|
||||
{
|
||||
unsigned int i;
|
||||
sb_list_item_t *pos;
|
||||
log_handler_t *handler;
|
||||
|
||||
for (i = 0; i < LOG_MSG_TYPE_MAX; i++)
|
||||
{
|
||||
SB_LIST_FOR_EACH(pos, handlers + i)
|
||||
{
|
||||
handler = SB_LIST_ENTRY(pos, log_handler_t, listitem);
|
||||
if (handler->ops.init != NULL && handler->ops.init())
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
/* required to let log_text() pass messages to handlers */
|
||||
initialized = 1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/* Uninitialize logger and all handlers */
|
||||
|
||||
|
||||
void log_done(void)
|
||||
{
|
||||
unsigned int i;
|
||||
sb_list_item_t *pos;
|
||||
log_handler_t *handler;
|
||||
|
||||
for (i = 0; i < LOG_MSG_TYPE_MAX; i++)
|
||||
{
|
||||
SB_LIST_FOR_EACH(pos, handlers + i)
|
||||
{
|
||||
handler = SB_LIST_ENTRY(pos, log_handler_t, listitem);
|
||||
if (handler->ops.done != NULL)
|
||||
handler->ops.done();
|
||||
}
|
||||
}
|
||||
|
||||
initialized = 0;
|
||||
}
|
||||
|
||||
|
||||
/* Add handler for a specified type of messages */
|
||||
|
||||
|
||||
int log_add_handler(log_msg_type_t type, log_handler_t *handler)
|
||||
{
|
||||
if (type <= LOG_MSG_TYPE_MIN || type >= LOG_MSG_TYPE_MAX)
|
||||
return 1;
|
||||
|
||||
if (handler->args != NULL)
|
||||
sb_register_arg_set(handler->args);
|
||||
|
||||
SB_LIST_ADD_TAIL(&handler->listitem, handlers + type);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/* Main function to dispatch log messages */
|
||||
|
||||
|
||||
void log_msg(log_msg_t *msg)
|
||||
{
|
||||
sb_list_item_t *pos;
|
||||
log_handler_t *handler;
|
||||
|
||||
SB_LIST_FOR_EACH(pos, handlers + msg->type)
|
||||
{
|
||||
handler = SB_LIST_ENTRY(pos, log_handler_t, listitem);
|
||||
if (handler->ops.process != NULL)
|
||||
handler->ops.process(msg);
|
||||
}
|
||||
}
|
||||
|
||||
static const char *get_msg_prefix(log_msg_priority_t priority)
|
||||
{
|
||||
const char * prefix;
|
||||
|
||||
switch (priority) {
|
||||
case LOG_FATAL:
|
||||
prefix = "FATAL: ";
|
||||
break;
|
||||
case LOG_ALERT:
|
||||
prefix = "ALERT: ";
|
||||
break;
|
||||
case LOG_WARNING:
|
||||
prefix = "WARNING: ";
|
||||
break;
|
||||
case LOG_DEBUG:
|
||||
prefix = "DEBUG: ";
|
||||
break;
|
||||
default:
|
||||
prefix = "";
|
||||
break;
|
||||
}
|
||||
|
||||
return prefix;
|
||||
}
|
||||
|
||||
/* printf-like wrapper to log text messages */
|
||||
|
||||
|
||||
void log_text(log_msg_priority_t priority, const char *fmt, ...)
|
||||
{
|
||||
log_msg_t msg;
|
||||
log_msg_text_t text_msg;
|
||||
char buf[TEXT_BUFFER_SIZE];
|
||||
va_list ap;
|
||||
int n, clen, maxlen;
|
||||
|
||||
maxlen = TEXT_BUFFER_SIZE;
|
||||
clen = 0;
|
||||
|
||||
va_start(ap, fmt);
|
||||
n = vsnprintf(buf + clen, maxlen, fmt, ap);
|
||||
va_end(ap);
|
||||
if (n < 0 || n >= maxlen)
|
||||
n = maxlen;
|
||||
clen += n;
|
||||
maxlen -= n;
|
||||
snprintf(buf + clen, maxlen, "\n");
|
||||
|
||||
/*
|
||||
No race condition here because log_init() is supposed to be called
|
||||
in a single-threaded stage
|
||||
*/
|
||||
if (!initialized)
|
||||
{
|
||||
printf("%s%s", get_msg_prefix(priority), buf);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
msg.type = LOG_MSG_TYPE_TEXT;
|
||||
msg.data = (void *)&text_msg;
|
||||
text_msg.priority = priority;
|
||||
text_msg.text = buf;
|
||||
text_msg.flags = 0;
|
||||
|
||||
log_msg(&msg);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
variant of log_text() which prepends log lines with the elapsed time of a
|
||||
specified timer.
|
||||
*/
|
||||
|
||||
|
||||
void log_timestamp(log_msg_priority_t priority, double seconds,
|
||||
const char *fmt, ...)
|
||||
{
|
||||
log_msg_t msg;
|
||||
log_msg_text_t text_msg;
|
||||
char buf[TEXT_BUFFER_SIZE];
|
||||
va_list ap;
|
||||
int n, clen, maxlen;
|
||||
|
||||
maxlen = TEXT_BUFFER_SIZE;
|
||||
clen = 0;
|
||||
|
||||
n = snprintf(buf, maxlen, "[ %.0fs ] ", seconds);
|
||||
clen += n;
|
||||
maxlen -= n;
|
||||
|
||||
va_start(ap, fmt);
|
||||
n = vsnprintf(buf + clen, maxlen, fmt, ap);
|
||||
va_end(ap);
|
||||
if (n < 0 || n >= maxlen)
|
||||
n = maxlen;
|
||||
clen += n;
|
||||
maxlen -= n;
|
||||
snprintf(buf + clen, maxlen, "\n");
|
||||
|
||||
/*
|
||||
No race condition here because log_init() is supposed to be called
|
||||
in a single-threaded stage
|
||||
*/
|
||||
if (!initialized)
|
||||
{
|
||||
printf("%s%s", get_msg_prefix(priority), buf);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
msg.type = LOG_MSG_TYPE_TEXT;
|
||||
msg.data = (void *)&text_msg;
|
||||
text_msg.priority = priority;
|
||||
text_msg.text = buf;
|
||||
/* Skip duplicate checks */
|
||||
text_msg.flags = LOG_MSG_TEXT_ALLOW_DUPLICATES;
|
||||
|
||||
log_msg(&msg);
|
||||
}
|
||||
|
||||
|
||||
/* printf-like wrapper to log system error messages */
|
||||
|
||||
|
||||
void log_errno(log_msg_priority_t priority, const char *fmt, ...)
|
||||
{
|
||||
char buf[TEXT_BUFFER_SIZE];
|
||||
char errbuf[ERROR_BUFFER_SIZE];
|
||||
va_list ap;
|
||||
int n;
|
||||
int old_errno;
|
||||
char *tmp;
|
||||
|
||||
#ifdef _WIN32
|
||||
LPVOID lpMsgBuf;
|
||||
old_errno = GetLastError();
|
||||
FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM |
|
||||
FORMAT_MESSAGE_ALLOCATE_BUFFER |
|
||||
FORMAT_MESSAGE_IGNORE_INSERTS,
|
||||
NULL, old_errno,
|
||||
0, (LPTSTR)&lpMsgBuf, 0, NULL);
|
||||
tmp = (char *)lpMsgBuf;
|
||||
#else
|
||||
old_errno = errno;
|
||||
#ifdef HAVE_STRERROR_R
|
||||
#ifdef STRERROR_R_CHAR_P
|
||||
tmp = strerror_r(old_errno, errbuf, sizeof(errbuf));
|
||||
#else
|
||||
strerror_r(old_errno, errbuf, sizeof(errbuf));
|
||||
tmp = errbuf;
|
||||
#endif /* STRERROR_R_CHAR_P */
|
||||
#else /* !HAVE_STRERROR_P */
|
||||
strncpy(errbuf, strerror(old_errno), sizeof(errbuf));
|
||||
tmp = errbuf;
|
||||
#endif /* HAVE_STRERROR_P */
|
||||
#endif /* WIN32 */
|
||||
|
||||
va_start(ap, fmt);
|
||||
n = vsnprintf(buf, TEXT_BUFFER_SIZE, fmt, ap);
|
||||
va_end(ap);
|
||||
if (n < 0 || n == TEXT_BUFFER_SIZE)
|
||||
return;
|
||||
snprintf(buf + n, TEXT_BUFFER_SIZE - n, " errno = %d (%s)", old_errno,
|
||||
tmp);
|
||||
|
||||
#ifdef _WIN32
|
||||
LocalFree(lpMsgBuf);
|
||||
#endif
|
||||
|
||||
log_text(priority, "%s", buf);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* Initialize text handler */
|
||||
|
||||
|
||||
int text_handler_init(void)
|
||||
{
|
||||
#ifdef HAVE_SETVBUF
|
||||
/* Set stdout to unbuffered mode */
|
||||
setvbuf(stdout, NULL, _IONBF, 0);
|
||||
#endif
|
||||
|
||||
sb_globals.verbosity = sb_get_value_int("verbosity");
|
||||
|
||||
if (sb_globals.verbosity > LOG_DEBUG)
|
||||
{
|
||||
printf("Invalid value for verbosity: %d\n", sb_globals.verbosity);
|
||||
return 1;
|
||||
}
|
||||
|
||||
pthread_mutex_init(&text_mutex, NULL);
|
||||
text_cnt = 0;
|
||||
text_buf[0] = '\0';
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/* Print text message to the log */
|
||||
|
||||
|
||||
int text_handler_process(log_msg_t *msg)
|
||||
{
|
||||
log_msg_text_t *text_msg = (log_msg_text_t *)msg->data;
|
||||
|
||||
if (text_msg->priority > sb_globals.verbosity)
|
||||
return 0;
|
||||
|
||||
if (!(text_msg->flags & LOG_MSG_TEXT_ALLOW_DUPLICATES))
|
||||
{
|
||||
pthread_mutex_lock(&text_mutex);
|
||||
if (!strcmp(text_buf, text_msg->text))
|
||||
{
|
||||
text_cnt++;
|
||||
pthread_mutex_unlock(&text_mutex);
|
||||
|
||||
return 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (text_cnt > 0)
|
||||
printf("(last message repeated %u times)\n", text_cnt);
|
||||
|
||||
text_cnt = 0;
|
||||
strncpy(text_buf, text_msg->text, TEXT_BUFFER_SIZE);
|
||||
}
|
||||
pthread_mutex_unlock(&text_mutex);
|
||||
}
|
||||
|
||||
printf("%s%s", get_msg_prefix(text_msg->priority), text_msg->text);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/* Initialize operation messages handler */
|
||||
|
||||
|
||||
int oper_handler_init(void)
|
||||
{
|
||||
int tmp;
|
||||
|
||||
tmp = sb_get_value_int("percentile");
|
||||
if (tmp < 0 || tmp > 100)
|
||||
{
|
||||
log_text(LOG_FATAL, "Invalid value for --percentile: %d",
|
||||
tmp);
|
||||
return 1;
|
||||
}
|
||||
sb_globals.percentile = tmp;
|
||||
|
||||
sb_globals.histogram = sb_get_value_flag("histogram");
|
||||
if (sb_globals.percentile == 0 && sb_globals.histogram != 0)
|
||||
{
|
||||
log_text(LOG_FATAL, "--histogram cannot be used with --percentile=0");
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (sb_histogram_init(&sb_latency_histogram, OPER_LOG_GRANULARITY,
|
||||
OPER_LOG_MIN_VALUE, OPER_LOG_MAX_VALUE))
|
||||
return 1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/* Uninitialize operations messages handler */
|
||||
|
||||
int oper_handler_done(void)
|
||||
{
|
||||
sb_histogram_done(&sb_latency_histogram);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -0,0 +1,153 @@
|
|||
/* Copyright (C) 2004 MySQL AB
|
||||
Copyright (C) 2004-2016 Alexey Kopytov <akopytov@gmail.com>
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#ifndef SB_LOGGER_H
|
||||
#define SB_LOGGER_H
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
# include "config.h"
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_PTHREAD_H
|
||||
# include <pthread.h>
|
||||
#endif
|
||||
|
||||
#include "sb_util.h"
|
||||
#include "sb_options.h"
|
||||
#include "sb_timer.h"
|
||||
#include "sb_histogram.h"
|
||||
|
||||
/* Text message flags (used in the 'flags' field of log_text_msg_t) */
|
||||
|
||||
#define LOG_MSG_TEXT_ALLOW_DUPLICATES 1
|
||||
|
||||
/* Message types definition */
|
||||
|
||||
typedef enum {
|
||||
LOG_MSG_TYPE_MIN, /* used for internal purposes */
|
||||
LOG_MSG_TYPE_TEXT, /* arbitrary text messages */
|
||||
LOG_MSG_TYPE_OPER, /* operation start/stop messages */
|
||||
LOG_MSG_TYPE_MAX /* used for internal purposes */
|
||||
} log_msg_type_t;
|
||||
|
||||
/* Message priorities definition */
|
||||
|
||||
typedef enum {
|
||||
LOG_FATAL, /* system is unusable */
|
||||
LOG_ALERT, /* user actions must be taken */
|
||||
LOG_WARNING, /* warnings */
|
||||
LOG_NOTICE, /* normal but significant messages */
|
||||
LOG_INFO, /* informational messages */
|
||||
LOG_DEBUG, /* debug-level messages */
|
||||
LOG_MAX /* used for internal purposes */
|
||||
} log_msg_priority_t;
|
||||
|
||||
/* Text message definition */
|
||||
|
||||
typedef struct {
|
||||
log_msg_priority_t priority;
|
||||
char *text;
|
||||
unsigned int flags;
|
||||
} log_msg_text_t;
|
||||
|
||||
/* Operation start/stop message definition */
|
||||
|
||||
typedef enum {
|
||||
LOG_MSG_OPER_START,
|
||||
LOG_MSG_OPER_STOP
|
||||
} log_msg_oper_action_t;
|
||||
|
||||
typedef struct {
|
||||
log_msg_oper_action_t action;
|
||||
int thread_id;
|
||||
} log_msg_oper_t;
|
||||
|
||||
/* General log message definition */
|
||||
|
||||
typedef struct {
|
||||
log_msg_type_t type;
|
||||
void *data;
|
||||
} log_msg_t;
|
||||
|
||||
/* Log handler operations definition */
|
||||
|
||||
typedef int log_op_register(void); /* register handler options */
|
||||
typedef int log_op_init(void); /* initialize log handler */
|
||||
typedef int log_op_process(log_msg_t *msg); /* process message */
|
||||
typedef int log_op_done(void); /* uninitialize log handler */
|
||||
|
||||
/* Log handler operations structure */
|
||||
|
||||
typedef struct {
|
||||
log_op_init *init;
|
||||
log_op_process *process;
|
||||
log_op_done *done;
|
||||
} log_handler_ops_t;
|
||||
|
||||
/* Log handler definition */
|
||||
|
||||
typedef struct {
|
||||
log_handler_ops_t ops; /* handler operations */
|
||||
sb_arg_t *args; /* handler arguments */
|
||||
sb_list_item_t listitem; /* can be linked in a list */
|
||||
} log_handler_t;
|
||||
|
||||
/* Register logger */
|
||||
|
||||
int log_register(void);
|
||||
|
||||
/* Display command line options for all register log handlers */
|
||||
|
||||
void log_print_help(void);
|
||||
|
||||
/* Initialize logger */
|
||||
|
||||
int log_init(void);
|
||||
|
||||
/* Add handler for a specified type of messages */
|
||||
|
||||
int log_add_handler(log_msg_type_t type, log_handler_t *handler);
|
||||
|
||||
/* Main function to dispatch log messages */
|
||||
|
||||
void log_msg(log_msg_t *);
|
||||
|
||||
/* printf-like wrapper to log text messages */
|
||||
|
||||
void log_text(log_msg_priority_t priority, const char *fmt, ...)
|
||||
SB_ATTRIBUTE_FORMAT(printf, 2, 3);
|
||||
|
||||
/*
|
||||
variant of log_text() which prepends log lines with a elapsed time of the
|
||||
specified timer.
|
||||
*/
|
||||
|
||||
void log_timestamp(log_msg_priority_t priority, double seconds,
|
||||
const char *fmt, ...)
|
||||
SB_ATTRIBUTE_FORMAT(printf, 3, 4);
|
||||
|
||||
/* printf-like wrapper to log system error messages */
|
||||
|
||||
void log_errno(log_msg_priority_t priority, const char *fmt, ...)
|
||||
SB_ATTRIBUTE_FORMAT(printf, 2, 3);
|
||||
|
||||
/* Uninitialize logger */
|
||||
|
||||
void log_done(void);
|
||||
|
||||
#endif /* SB_LOGGER_H */
|
||||
File diff suppressed because it is too large
Load Diff
|
|
@ -0,0 +1,42 @@
|
|||
/* Copyright (C) 2006 MySQL AB
|
||||
Copyright (C) 2006-2018 Alexey Kopytov <akopytov@gmail.com>
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
# include "config.h"
|
||||
#endif
|
||||
|
||||
#include "sysbench.h"
|
||||
#include "lua.h"
|
||||
|
||||
/* Load a specified Lua script */
|
||||
|
||||
sb_test_t *sb_load_lua(const char *testname);
|
||||
|
||||
void sb_lua_done(void);
|
||||
|
||||
int sb_lua_hook_call(lua_State *L, const char *name);
|
||||
|
||||
bool sb_lua_custom_command_defined(const char *name);
|
||||
|
||||
int sb_lua_call_custom_command(const char *name);
|
||||
|
||||
int sb_lua_report_thread_init(void);
|
||||
|
||||
void sb_lua_report_thread_done(void *);
|
||||
|
||||
bool sb_lua_loaded(void);
|
||||
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue