Merge remote-tracking branch 'origin/develop' into filter_harness

This commit is contained in:
Markus Makela 2014-10-06 09:43:42 +03:00
commit 1adc6ac5e8
200 changed files with 3089 additions and 1092 deletions

141
CMakeLists.txt Normal file
View File

@ -0,0 +1,141 @@
cmake_minimum_required(VERSION 2.6)
include(macros.cmake)
enable_testing()
set_variables()
set_maxscale_version()
set(CMAKE_INSTALL_PREFIX "${INSTALL_DIR}" CACHE INTERNAL "Prefix prepended to install directories." FORCE)
project(MaxScale)
check_deps()
check_dirs()
set(CMAKE_INSTALL_RPATH ${CMAKE_INSTALL_RPATH}:${CMAKE_INSTALL_PREFIX}/lib:${CMAKE_INSTALL_PREFIX}/modules)
configure_file(${CMAKE_SOURCE_DIR}/server/include/version.h.in ${CMAKE_SOURCE_DIR}/server/include/version.h)
configure_file(${CMAKE_SOURCE_DIR}/maxscale.conf.in ${CMAKE_SOURCE_DIR}/maxscale.conf.prep @ONLY)
configure_file(${CMAKE_SOURCE_DIR}/etc/init.d/maxscale.in ${CMAKE_SOURCE_DIR}/etc/init.d/maxscale.prep @ONLY)
configure_file(${CMAKE_SOURCE_DIR}/etc/ubuntu/init.d/maxscale.in ${CMAKE_SOURCE_DIR}/etc/ubuntu/init.d/maxscale.prep @ONLY)
set(CMAKE_C_FLAGS "-Wall -fPIC")
set(CMAKE_CXX_FLAGS "-Wall -fPIC")
if(BUILD_TYPE MATCHES Debug)
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -ggdb -pthread -pipe -DSS_DEBUG -Wformat -Werror=format-security -fstack-protector --param=ssp-buffer-size=4")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -ggdb -pthread -pipe -DSS_DEBUG -Wformat -Werror=format-security -fstack-protector --param=ssp-buffer-size=4")
message(STATUS "Generating debugging symbols")
elseif(BUILD_TYPE MATCHES Optimized)
if(NOT (DEFINED OLEVEL))
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -O2")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -O2")
message(STATUS "Optimization level at: 2")
endif()
else()
endif()
if(DEFINED OLEVEL )
if((OLEVEL GREATER -1) AND (OLEVEL LESS 4) )
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -O${OLEVEL}")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -O${OLEVEL}")
message(STATUS "Optimization level at: ${OLEVEL}")
else()
message(WARNING "Optimization level was set to a bad value, ignoring it. (Valid values are 0-3)")
endif()
endif()
if(GCOV)
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fprofile-arcs -ftest-coverage")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fprofile-arcs -ftest-coverage")
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -lgcov")
endif()
subdirs(MYSQL_DIR_ALL ${MYSQL_DIR})
foreach(DIR ${MYSQL_DIR_ALL})
include_directories(${DIR})
endforeach()
include_directories(${MYSQL_DIR}/..)
include_directories(utils)
include_directories(log_manager)
include_directories(query_classifier)
include_directories(server/include)
include_directories(server/inih)
include_directories(server/modules/include)
add_subdirectory(utils)
add_subdirectory(log_manager)
add_subdirectory(query_classifier)
add_subdirectory(server)
add_subdirectory(client)
# Install startup scripts and ldconfig files
if( NOT ( (DEFINED INSTALL_SYSTEM_FILES) AND ( NOT ( INSTALL_SYSTEM_FILES ) ) ) )
install(FILES maxscale.conf.prep RENAME maxscale.conf DESTINATION /etc/ld.so.conf.d/ PERMISSIONS WORLD_EXECUTE WORLD_READ)
if(DEB_BASED)
install(FILES etc/ubuntu/init.d/maxscale.prep RENAME maxscale DESTINATION /etc/init.d/ PERMISSIONS WORLD_EXECUTE)
else()
install(FILES etc/init.d/maxscale.prep RENAME maxscale DESTINATION /etc/init.d/ PERMISSIONS WORLD_EXECUTE)
endif()
message(STATUS "Installing maxscale.conf to: /etc/ld.so.conf.d")
message(STATUS "Installing startup scripts to: /etc/init.d")
endif()
file(GLOB DOCS Documentation/*.pdf)
message(STATUS "Installing MaxScale to: ${CMAKE_INSTALL_PREFIX}/")
install(FILES server/MaxScale_template.cnf DESTINATION etc)
install(FILES ${ERRMSG} DESTINATION mysql)
install(FILES ${DOCS} DESTINATION Documentation)
# See if we are on a RPM-capable or DEB-capable system
find_program(RPMBUILD rpmbuild)
find_program(DEBBUILD dpkg-buildpackage)
if(NOT ( ${RPMBUILD} STREQUAL "RPMBUILD-NOTFOUND" ) )
message(STATUS "Generating RPM packages")
set(CPACK_GENERATOR "${CPACK_GENERATOR};RPM")
endif()
if(NOT ( ${DEBBUILD} STREQUAL "DEBBUILD-NOTFOUND" ) )
set(CPACK_GENERATOR "${CPACK_GENERATOR};DEB")
execute_process(COMMAND dpgk --print-architecture OUTPUT_VARIABLE DEB_ARCHITECTURE)
set(CPACK_DEBIAN_PACKAGE_ARCHITECTURE ${DEB_ARCHITECTURE})
set (CPACK_DEBIAN_PACKAGE_SHLIBDEPS ON)
message(STATUS "Generating DEB packages for ${DEB_ARCHITECTURE}")
endif()
set(CPACK_PACKAGE_DESCRIPTION_SUMMARY "MaxScale")
set(CPACK_PACKAGE_VERSION_MAJOR "${MAXSCALE_VERSION_MAJOR}")
set(CPACK_PACKAGE_VERSION_MINOR "${MAXSCALE_VERSION_MINOR}")
set(CPACK_PACKAGE_VERSION_PATCH "${MAXSCALE_VERSION_PATCH}")
set(CPACK_PACKAGE_CONTACT "MariaDB Corporation Ab")
set(CPACK_PACKAGE_FILE_NAME "maxscale-${MAXSCALE_VERSION}")
set(CPACK_PACKAGE_NAME "maxscale")
set(CPACK_PACKAGE_VENDOR "MariaDB Corporation Ab")
set(CPACK_PACKAGE_DESCRIPTION_FILE ${CMAKE_SOURCE_DIR}/README)
set(CPACK_PACKAGING_INSTALL_PREFIX "${CMAKE_INSTALL_PREFIX}")
set(CPACK_RPM_SPEC_INSTALL_POST "/sbin/ldconfig")
set(CPACK_RPM_PACKAGE_NAME "maxscale")
set(CPACK_RPM_PACKAGE_VENDOR "MariaDB Corporation Ab")
set(CPACK_RPM_PACKAGE_LICENSE "GPLv2")
set(CPACK_RPM_EXCLUDE_FROM_AUTO_FILELIST_ADDITION "/etc /etc/ld.so.conf.d /etc/init.d /etc/rc.d/init.d")
set(CPACK_RPM_SPEC_MORE_DEFINE "%define ignore \#")
set(CPACK_RPM_USER_FILELIST "%ignore /etc/init.d")
set(CPACK_RPM_USER_FILELIST "%ignore /etc/ld.so.conf.d")
set(CPACK_RPM_USER_FILELIST "%ignore /etc")
include(CPack)
add_custom_target(testall
COMMAND ${CMAKE_COMMAND} -DDEPS_OK=Y -DBUILD_TESTS=Y -DBUILD_TYPE=Debug -DINSTALL_DIR=${CMAKE_BINARY_DIR} -DINSTALL_SYSTEM_FILES=N ${CMAKE_SOURCE_DIR}
COMMAND make install
COMMAND /bin/sh -c "${CMAKE_BINARY_DIR}/bin/maxscale -c ${CMAKE_BINARY_DIR} &>/dev/null"
COMMAND /bin/sh -c "make test || echo \"Test results written to: ${CMAKE_BINARY_DIR}/Testing/Temporary/\""
COMMAND killall maxscale
COMMENT "Running full test suite" VERBATIM)

View File

@ -1,4 +1,4 @@
This source code is distributed as part of SkySQL MaxScale. It is free
This source code is distributed as part of MariaDB Corporation MaxScale. It is free
software: you can redistribute it and/or modify it under the terms of the
GNU General Public License as published by the Free Software Foundation,
version 2.
@ -12,9 +12,9 @@ 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.
Copyright SkySQL Ab 2013
Copyright MariaDB Corporation Ab 2013
SkySQL Corporation Ab
MariaDB Corporation Corporation Ab
Tekniikantie 12
02150 Espoo
Finland

Binary file not shown.

View File

@ -1,4 +1,4 @@
# This file is distributed as part of the SkySQL Gateway. It is free
# This file is distributed as part of the MariaDB Corporation MaxScale. It is free
# software: you can redistribute it and/or modify it under the terms of the
# GNU General Public License as published by the Free Software Foundation,
# version 2.
@ -12,7 +12,7 @@
# this program; if not, write to the Free Software Foundation, Inc., 51
# Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
#
# Copyright SkySQL Ab 2013
# Copyright MariaDB Corporation Ab 2013
#
# Revision History
# Date Who Description
@ -57,7 +57,7 @@ depend:
install:
(cd server; make DEST=$(DEST) install)
(cd log_manager; make DEST=$(DEST) install)
(cd query_classifier; make DEST=$(DEST) install)
(cd query_classifier;touch depend; make DEST=$(DEST) install)
(cd client; make DEST=$(DEST) install)
cleantests:

75
README
View File

@ -1,6 +1,6 @@
/** \mainpage MaxScale by SkySQL
/** \mainpage MaxScale by MariaDB Corporation
The SkySQL MaxScale is an intelligent proxy that allows forwarding of
The MariaDB Corporation MaxScale is an intelligent proxy that allows forwarding of
database statements to one or more database servers using complex rules,
a semantic understanding of the database statements and the roles of
the various servers within the backend cluster of databases.
@ -28,7 +28,7 @@ issues and communicate with the MaxScale community.
Send email to [maxscale@googlegroups.com](mailto:maxscale@googlegroups.com)
or use the [forum](http://groups.google.com/forum/#!forum/maxscale) interface
Bugs can be reported in the SkySQL bugs database
Bugs can be reported in the MariaDB Corporation bugs database
[bug.skysql.com](http://bugs.skysql.com)
\section Building Building MaxScale
@ -59,6 +59,10 @@ to the --relocate option.
rpm -i --force --relocate=/usr/=$PREFIX/usr/ MariaDB-5.5.34-centos6-x86_64-common.rpm MariaDB-5.5.34-centos6-x86_64-compat.rpm MariaDB-5.5.34-centos6-x86_64-devel.rpm
You can also use the included 'unpack_rpm.sh' script to unpack the RPMs without installing them.
./unpack_rpm <location of MariaDB RPMs> <extraction destination>
This README assumes $PREFIX = $HOME.
MaxScale may be built with the embedded MariaDB library either linked
@ -152,6 +156,71 @@ max_connections=4096
Please check errmsg.sys is found in the MaxScale install_dir DEST/MaxScale/mysql
\section Building Building MaxScale with CMake
You can also build MaxScale with CMake which makes the build process a bit more simple.
All the same dependencies are required as with the normal MaxScale build with the addition of CMake
version 2.6 for regular builds and 2.8.12 or newer if you wish to generate packages.
CMake tries to find all the required directories and files on its own but if it can't find them or you wish to
explicitly state the locations you can pass additional options to CMake by using the -D flag. To confirm the variable
values, you can run CMake in interactive mode by using the -i flag or use a CMake GUI (for example, ccmake for command line).
It is highly recommended to make a separate build directory to build into. This keeps the source and build trees clean and
makes it easy to get rid of everything you built by simply deleting the build directory.
To build MaxScale using CMake:
cd <path to MaxScale source>
mkdir build
cd build
cmake ..
make
make install
This generates the required makefiles in the current directory, compiles and links all the programs and installs
all the required files in their right places.
If you have your headers and libraries in non-standard locations, you can define those locations at configuration time as such:
cmake -D<variable>=<value>
By default, MaxScale installs to '/usr/local/skysql/maxscale' and places init.d scripts and ldconfig files into their folders. Change the INSTALL_DIR
variable to your desired installation directory and set INSTALL_SYSTEM_FILES=N to prevent the init.d script and ldconfig file installation.
If you run into any trouble while configuring CMake, you can always remove the 'CMakeCache.txt' file to clear CMake's
internal cache. This resets all values to their defaults and can be used to fix a 'stuck' configuration of CMake. This
is also a good reason why you should always build into a separate directory, because you can safely wipe the build directory clean without the
danger of deleting important files when something goes wrong.
The default values that CMake uses can be found in the 'macros.cmake' file. If you wish to change these, edit the 'macros.cmake' file
or define the variables manually at configuration time.
All the variables that control the CMake build process:
INSTALL_DIR=<path> Installation directory
BUILD_TYPE=[None|Debug|Release] Type of the build, defaults to Release (optimized)
INSTALL_SYSTEM_FILES=[Y|N] Install startup scripts and ld configuration files
EMBEDDED_LIB=<path> Path to the embedded library location (libmysqld.a for static and libmysqld.so for dynamic)
MYSQL_DIR=<path> Path to MySQL headers
ERRMSG=<path> Path to errmsg.sys file
STATIC_EMBEDDED=[Y|N] Whether to link the static or the dynamic verson of the library
GCOV=[Y|N] Generate gcov output
OLEVEL=<0-3> Level of optimization
BUILD_TESTS=[Y|N] Build tests
DEPS_OK=[Y|N] Check dependencies, use N when you want to force a recheck of values
DEBUG_OUTPUT=[Y|N] Produce debugging output when configuring CMake
RABBITMQ_LIB=<path> Path to RabbitMQ-C libraries
RABBITMQ_HEADERS=<path> Path to RabbitMQ-C headers
MYSQL_CLIENT_LIB=<path> Path to MySQL client libraries
MYSQL_CLIENT_HEADERS=<path> Path to MySQL client headers
\section Running Running MaxScale
MaxScale consists of a core executable and a number of modules that implement

View File

@ -1 +1 @@
1.0.0-beta
1.0.1-beta

7
client/CMakeLists.txt Normal file
View File

@ -0,0 +1,7 @@
add_executable(maxadmin maxadmin.c)
find_library(HIST edit)
if(HIST)
add_definitions(-DHISTORY)
target_link_libraries(maxadmin ${HIST})
endif()
install(TARGETS maxadmin DESTINATION bin)

View File

@ -12,7 +12,7 @@
# this program; if not, write to the Free Software Foundation, Inc., 51
# Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
#
# Copyright SkySQL Ab 2014
# Copyright MariaDB Corporation Ab 2014
#
# Revision History
# Date Who Description

View File

@ -13,7 +13,7 @@
* this program; if not, write to the Free Software Foundation, Inc., 51
* Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Copyright SkySQL Ab 2014
* Copyright MariaDB Corporation Ab 2014
*/
/**
@ -273,7 +273,10 @@ char c;
}
else if (*buf)
{
sendCommand(so, buf);
if (!sendCommand(so, buf))
{
return 0;
}
}
}
@ -298,6 +301,7 @@ connectMaxScale(char *hostname, char *port)
{
struct sockaddr_in addr;
int so;
int keepalive = 1;
if ((so = socket(AF_INET, SOCK_STREAM, 0)) < 0)
{
@ -315,6 +319,9 @@ int so;
hostname, port, strerror(errno));
return -1;
}
if (setsockopt(so, SOL_SOCKET,
SO_KEEPALIVE, &keepalive , sizeof(keepalive )))
perror("setsockopt");
return so;
}
@ -387,11 +394,14 @@ authMaxScale(int so, char *user, char *password)
{
char buf[20];
read(so, buf, 4);
if (read(so, buf, 4) != 4)
return 0;
write(so, user, strlen(user));
read(so, buf, 8);
if (read(so, buf, 8) != 8)
return 0;
write(so, password, strlen(password));
read(so, buf, 6);
if (read(so, buf, 6) != 6)
return 0;
return strncmp(buf, "FAILED", 6);
}
@ -412,10 +422,11 @@ sendCommand(int so, char *cmd)
char buf[80];
int i, j, newline = 1;
write(so, cmd, strlen(cmd));
if (write(so, cmd, strlen(cmd)) == -1)
return 0;
while (1)
{
if ((i = read(so, buf, 80)) == -1)
if ((i = read(so, buf, 80)) <= 0)
return 0;
for (j = 0; j < i; j++)
{

View File

@ -0,0 +1,53 @@
#!/bin/sh
failure=0
passed=0
clients=20
cmdcnt=1000
echo Running $clients parallel iterations of $cmdcnt commands
for ((cnt=0; cnt<$clients; cnt++ )); do
for ((i=0; i<$cmdcnt; i++ )); do
maxadmin -pskysql show services;
done >/dev/null &
done >& /dev/null
peak=0
while [ "`jobs -p`" != "" ]; do
jobs >& /dev/null
zombies=`maxadmin -pskysql list dcbs | grep -ci zombies`
if [ $zombies -gt $peak ] ; then
peak=$zombies
fi
sleep 1
done
if [ $peak -gt 10 ]; then
echo "High peak zombie count ($peak): Failed"
failure=`expr $failure + 1`
else
passed=`expr $passed + 1`
echo "Zombie collection ($peak): Passed"
fi
zombies=`maxadmin -pskysql list dcbs | grep -ci zombies`
if [ $zombies != "0" ]; then
echo "Residual zombie DCBs: Failed"
failure=`expr $failure + 1`
else
passed=`expr $passed + 1`
echo "Residual zombie DCBs: Passed"
fi
sessions=`maxadmin -pskysql list services | awk -F\| '/ cli/ { print $3 }'`
if [ $sessions -gt 3 ]; then
echo "Session shutdown, $sessions: Failed"
failure=`expr $failure + 1`
else
passed=`expr $passed + 1`
echo "Session shutdown: Passed"
fi
sessions=`maxadmin -pskysql list services | awk -F\| '/ cli/ { print $4 }'`
echo "Test run complete. $passed passes, $failure failures"
echo "$sessions CLI sessions executed"
exit $failure

View File

@ -0,0 +1,210 @@
#!/bin/sh
failure=0
passed=0
maxadmin -pskysql help >& /dev/null
if [ $? -eq "1" ]; then
echo "Auth test (correct password): Failed"
failure=`expr $failure + 1`
else
passed=`expr $passed + 1`
echo "Auth test (correct password): Passed"
fi
maxadmin -pwrongpasswd help >& /dev/null
if [ $? -eq "0" ]; then
echo "Auth test (wrong password): Failed"
failure=`expr $failure + 1`
else
passed=`expr $passed + 1`
echo "Auth test (wrong password): Passed"
fi
maxadmin --password=skysql help >& /dev/null
if [ $? -eq "1" ]; then
echo "Auth test (long option): Failed"
failure=`expr $failure + 1`
else
passed=`expr $passed + 1`
echo "Auth test (long option): Passed"
fi
maxadmin -pskysql enable log debug >& /dev/null
if [ $? -eq "1" ]; then
echo "Enable debug log: Failed"
failure=`expr $failure + 1`
else
passed=`expr $passed + 1`
echo "Enable debug log: Passed"
fi
maxadmin -pskysql enable log trace >& /dev/null
if [ $? -eq "1" ]; then
echo "Enable trace log: Failed"
failure=`expr $failure + 1`
else
passed=`expr $passed + 1`
echo "Enable trace log: Passed"
fi
maxadmin -pskysql disable log debug >& /dev/null
if [ $? -eq "1" ]; then
echo "Disable debug log: Failed"
failure=`expr $failure + 1`
else
passed=`expr $passed + 1`
echo "Disable debug log: Passed"
fi
maxadmin -pskysql disable log trace >& /dev/null
if [ $? -eq "1" ]; then
echo "Disable trace log: Failed"
failure=`expr $failure + 1`
else
passed=`expr $passed + 1`
echo "Disable trace log: Passed"
fi
for cmd in clients dcbs filters listeners modules monitors services servers sessions threads
do
maxadmin -pskysql list $cmd | grep -s '-' >& /dev/null
if [ $? -eq "1" ]; then
echo "list command ($cmd): Failed"
failure=`expr $failure + 1`
else
passed=`expr $passed + 1`
echo "list command ($cmd): Passed"
fi
done
for cmd in dcbs dbusers epoll filters modules monitors services servers sessions threads users
do
maxadmin -pskysql show $cmd | grep -s ' ' >& /dev/null
if [ $? -eq "1" ]; then
echo "show command ($cmd): Failed"
failure=`expr $failure + 1`
else
passed=`expr $passed + 1`
echo "show command ($cmd): Passed"
fi
done
master=`maxadmin -pskysql list servers | awk '/Master/ { print $1; }'`
if [ $? -eq "1" ]; then
echo "Extract master server: Failed"
failure=`expr $failure + 1`
else
passed=`expr $passed + 1`
echo "Extract master server: Passed"
fi
if [ "$master" = "" ]; then
echo "Get master server: Failed"
failure=`expr $failure + 1`
else
passed=`expr $passed + 1`
echo "Get master server: Passed"
fi
maxadmin -pskysql show server $master | grep -s 'Master' >& /dev/null
if [ $? -eq "1" ]; then
echo "show server master: Failed"
failure=`expr $failure + 1`
else
passed=`expr $passed + 1`
echo "show server master: Passed"
fi
maxadmin -pskysql set server $master maint >& /dev/null
if [ $? -eq "1" ]; then
echo "set server: Failed"
failure=`expr $failure + 1`
else
passed=`expr $passed + 1`
echo "set server: Passed"
fi
maxadmin -pskysql list servers | grep $master | grep -s Maint >& /dev/null
if [ $? -eq "1" ]; then
echo "set maintenance mode: Failed"
failure=`expr $failure + 1`
else
passed=`expr $passed + 1`
echo "set maintenance mode: Passed"
fi
maxadmin -pskysql clear server $master maint >& /dev/null
if [ $? -eq "1" ]; then
echo "clear server: Failed"
failure=`expr $failure + 1`
else
passed=`expr $passed + 1`
echo "clear server: Passed"
fi
maxadmin -pskysql list servers | grep $master | grep -s Maint >& /dev/null
if [ $? -eq "0" ]; then
echo "clear maintenance mode: Failed"
failure=`expr $failure + 1`
else
passed=`expr $passed + 1`
echo "clear maintenance mode: Passed"
fi
dcbs=`maxadmin -pskysql list dcbs | awk -F\| '/listening/ { if ( NF > 1 ) print $1 }'`
if [ $? -eq "1" ]; then
echo "Get dcb listeners: Failed"
failure=`expr $failure + 1`
else
passed=`expr $passed + 1`
echo "Get dcb listeners: Passed"
fi
for i in $dcbs
do
maxadmin -pskysql show dcb $i | grep -s 'listening' >& /dev/null
if [ $? -eq "1" ]; then
echo "show dcb listeners: Failed"
failure=`expr $failure + 1`
else
passed=`expr $passed + 1`
echo "show dcb listeners: Passed"
fi
done
sessions=`maxadmin -pskysql list sessions | awk -F\| '/Listener/ { if ( NF > 1 ) print $1 }'`
if [ $? -eq "1" ]; then
echo "Get listener sessions: Failed"
failure=`expr $failure + 1`
else
passed=`expr $passed + 1`
echo "Get listener sessions: Passed"
fi
for i in $sessions
do
maxadmin -pskysql show session $i | grep -s 'Listener' >& /dev/null
if [ $? -eq "1" ]; then
echo "show session listeners: Failed"
failure=`expr $failure + 1`
else
passed=`expr $passed + 1`
echo "show session listeners: Passed"
fi
done
filters=`maxadmin -pskysql list filters | awk -F\| '{ if ( NF > 1 ) print $1 }'| grep -v Options`
if [ $? -eq "1" ]; then
echo "Get Filter list: Failed"
failure=`expr $failure + 1`
else
passed=`expr $passed + 1`
echo "Get filter list: Passed"
fi
for i in $filters
do
maxadmin -pskysql show filter $i | grep -s 'Filter' >& /dev/null
if [ $? -eq "1" ]; then
echo "show filter: Failed"
failure=`expr $failure + 1`
else
passed=`expr $passed + 1`
echo "show filter: Passed"
fi
done
echo "Test run complete. $passed passes, $failure failures"
exit $failure

2
debian/control vendored
View File

@ -9,7 +9,7 @@ Package: maxscale
Architecture: any
Depends: ${shlibs:Depends}, ${misc:Depends}
Description: MaxScale
The SkySQL MaxScale is an intelligent proxy that allows forwarding of
The MariaDB Corporation MaxScale is an intelligent proxy that allows forwarding of
database statements to one or more database servers using complex rules,
a semantic understanding of the database statements and the roles of
the various servers within the backend cluster of databases.

View File

@ -1,6 +1,6 @@
#!/bin/sh
#
# maxscale: The SkySQL MaxScale database proxy
# maxscale: The MariaDB Corporation MaxScale database proxy
#
# description: MaxScale provides database specific proxy functionality
#

157
etc/init.d/maxscale.in Executable file
View File

@ -0,0 +1,157 @@
#!/bin/sh
#
# maxscale: The MariaDB Corporation MaxScale database proxy
#
# description: MaxScale provides database specific proxy functionality
#
# processname: maxscale
#
### BEGIN INIT INFO
# Provides: maxscale
# Required-Start: $syslog $local_fs
# Required-Stop: $syslog $local_fs
# Default-Start: 2 3 4 5
# Default-Stop: 0 1 6
# Short-Description: The maxscale database proxy
# Description: MaxScale is a database proxy server that can be used to front end
# database clusters offering different routing, filtering and protocol choices
### END INIT INFO
#############################################
# MaxScale HOME, PIDFILE, LIB
#############################################
export MAXSCALE_HOME=@INSTALL_DIR@
export MAXSCALE_PIDFILE=$MAXSCALE_HOME/log/maxscale.pid
export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:$MAXSCALE_HOME/lib
###############################
# LSB Exit codes (non-Status)
###############################
_RETVAL_GENERIC=1
_RETVAL_NOT_INSTALLED=5
_RETVAL_NOT_RUNNING=7
###############################
# LSB Status action Exit codes
###############################
_RETVAL_STATUS_OK=0
_RETVAL_STATUS_NOT_RUNNING=3
# Sanity checks.
[ -x $MAXSCALE_HOME/bin/maxscale ] || exit $_RETVAL_NOT_INSTALLED
# Source function library.
. /etc/rc.d/init.d/functions
# we can rearrange this easily
processname=maxscale
servicename=maxscale
RETVAL=0
start() {
echo -n $"Starting MaxScale: "
my_check=`status -p $MAXSCALE_PIDFILE $MAXSCALE_HOME/bin/maxscale`
CHECK_RET=$?
[ $CHECK_RET -eq 0 ] && echo -n " found $my_check" && success && CHECK_RET=0
daemon --pidfile $MAXSCALE_PIDFILE $MAXSCALE_HOME/bin/maxscale >& /dev/null
RETVAL=$?
[ $RETVAL -eq 0 ] && touch /var/lock/subsys/$servicename
if [ $CHECK_RET -ne 0 ]; then
sleep 2
my_check=`status -p $MAXSCALE_PIDFILE $MAXSCALE_HOME/bin/maxscale`
CHECK_RET=$?
[ $CHECK_RET -eq 0 ] && echo -n $my_check && success || failure
fi
# Return rigth code
if [ $RETVAL -ne 0 ]; then
failure
RETVAL=$_RETVAL_NOT_RUNNING
fi
echo
return $RETVAL
}
stop() {
echo -n $"Stopping MaxScale: "
killproc -p $MAXSCALE_PIDFILE -TERM
RETVAL=$?
echo
[ $RETVAL -eq 0 ] && rm -f /var/lock/subsys/$servicename
# Return rigth code
if [ $RETVAL -ne 0 ]; then
RETVAL=$_RETVAL_NOT_RUNNING
fi
return $RETVAL
}
reload() {
echo -n $"Reloading MaxScale: "
killproc -p $MAXSCALE_PIDFILE $MAXSCALE_HOME/bin/maxscale -HUP
RETVAL=$?
echo
}
# See how we were called.
case "$1" in
start)
start
;;
stop)
stop
;;
status)
# return 0 on success
# return 3 on any error
echo -n $"Checking MaxScale status: "
status -p $MAXSCALE_PIDFILE 'MaxScale'
RETVAL=$?
if [ $RETVAL -ne 0 ]; then
echo -ne "\033[1A"
[ $RETVAL -eq 1 ] && warning || failure
echo -ne "\033[1B"
RETVAL=$_RETVAL_STATUS_NOT_RUNNING
else
echo -ne "\033[1A"
success
echo -ne "\033[1B"
RETVAL=$_RETVAL_STATUS_OK
fi
exit $RETVAL
;;
restart)
stop
start
;;
condrestart)
if [ -f /var/lock/subsys/$servicename ]; then
stop
start
fi
;;
reload)
reload
RETVAL=$?
;;
*)
echo $"Usage: $0 {start|stop|status|restart|condrestart|reload}"
;;
esac
exit $RETVAL

View File

@ -1,6 +1,6 @@
#!/bin/sh
#
# maxscale: The SkySQL MaxScale database proxy
# maxscale: The MariaDB Corporation MaxScale database proxy
#
# description: MaxScale provides database specific proxy functionality
#

View File

@ -0,0 +1,145 @@
#!/bin/sh
#
# maxscale: The MariaDB Corporation MaxScale database proxy
#
# description: MaxScale provides database specific proxy functionality
#
# processname: maxscale
#
### BEGIN INIT INFO
# Provides: maxscale
# Required-Start: $syslog $local_fs
# Required-Stop: $syslog $local_fs
# Default-Start: 2 3 4 5
# Default-Stop: 0 1 6
# Short-Description: The maxscale database proxy
# Description: MaxScale is a database proxy server that can be used to front end
# database clusters offering different routing, filtering and protocol choices
### END INIT INFO
#############################################
# MaxScale HOME, PIDFILE, LIB
#############################################
export MAXSCALE_HOME=@INSTALL_DIR@
export MAXSCALE_PIDFILE=$MAXSCALE_HOME/log/maxscale.pid
export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:$MAXSCALE_HOME/lib
###############################
# LSB Exit codes (non-Status)
###############################
_RETVAL_GENERIC=1
_RETVAL_NOT_INSTALLED=5
_RETVAL_NOT_RUNNING=7
###############################
# LSB Status action Exit codes
###############################
_RETVAL_STATUS_OK=0
_RETVAL_STATUS_NOT_RUNNING=3
# Sanity checks.
[ -x $MAXSCALE_HOME/bin/maxscale ] || exit $_RETVAL_NOT_INSTALLED
#################################
# stop/start/status related vars
#################################
NAME=maxscale
DAEMON=$MAXSCALE_HOME/bin/maxscale
# Source function library.
. /lib/lsb/init-functions
# we can rearrange this easily
processname=maxscale
servicename=maxscale
RETVAL=0
start() {
log_daemon_msg "Starting MaxScale"
start_daemon -p $MAXSCALE_PIDFILE $DAEMON 2> /dev/null
sleep 2
status_of_proc -p $MAXSCALE_PIDFILE $DAEMON $NAME
log_end_msg $?
}
stop() {
log_daemon_msg "Stopping MaxScale"
killproc -p $PIDFILE $DAEMON 2>&1 /dev/null
maxscale_wait_stop
log_end_msg $?
}
reload() {
log_daemon_msg "Reloading MaxScale"
killproc -p $MAXSCALE_PIDFILE $DAEMON 1
log_end_msg $?
}
maxscale_wait_stop() {
PIDTMP=$(pidofproc -p $MAXSCALE_PIDFILE $MAXSCALE_HOME/bin/maxscale)
kill -TERM "${PIDTMP:-}" 2> /dev/null;
if [ -n "${PIDTMP:-}" ] && kill -0 "${PIDTMP:-}" 2> /dev/null; then
local i=0
while kill -0 "${PIDTMP:-}" 2> /dev/null; do
if [ $i = '60' ]; then
break
STATUS=2
fi
[ "$VERBOSE" != no ] && log_progress_msg "."
sleep 1
i=$(($i+1))
done
return $STATUS
else
return $STATUS
fi
}
# See how we were called.
case "$1" in
start)
start
;;
stop)
stop
;;
status)
# return 0 on success
# return 3 on any error
log_daemon_msg "Checking MaxScale"
status_of_proc -p $MAXSCALE_PIDFILE $DAEMON $NAME
RETVAL=$?
if [ $RETVAL -ne 0 ]; then
[ $RETVAL -eq 1 ]
RETVAL=$_RETVAL_STATUS_NOT_RUNNING
else
RETVAL=$_RETVAL_STATUS_OK
fi
log_end_msg $RETVAL
;;
restart)
stop
start
;;
reload)
reload
RETVAL=$?
;;
*)
echo $"Usage: $0 {start|stop|status|restart|reload}"
;;
esac
exit $RETVAL

View File

@ -0,0 +1,6 @@
add_library(log_manager SHARED log_manager.cc)
target_link_libraries(log_manager pthread aio stdc++)
install(TARGETS log_manager DESTINATION lib)
if(BUILD_TESTS)
add_subdirectory(test)
endif()

View File

@ -1,5 +1,5 @@
/*
* This file is distributed as part of the SkySQL Gateway. It is free
* This file is distributed as part of the MariaDB Corporation MaxScale. It is free
* software: you can redistribute it and/or modify it under the terms of the
* GNU General Public License as published by the Free Software Foundation,
* version 2.
@ -13,7 +13,7 @@
* this program; if not, write to the Free Software Foundation, Inc., 51
* Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Copyright SkySQL Ab 2013
* Copyright MariaDB Corporation Ab 2013-2014
*/
#include <sys/types.h>
#include <sys/stat.h>
@ -75,7 +75,7 @@ int lm_enabled_logfiles_bitmask = 0;
* Path to directory in which all files are stored to shared memory
* by the OS.
*/
const char* shm_pathname = "/dev/shm";
const char* shm_pathname_prefix = "/dev/shm/";
/** Logfile ids from call argument '-s' */
char* shmem_id_str = NULL;
@ -404,7 +404,7 @@ return_succp:
/**
* @node Initializes log managing routines in SkySQL Gateway.
* @node Initializes log managing routines in MariaDB Corporation MaxScale.
*
* Parameters:
* @param p_ctx - in, give
@ -755,7 +755,12 @@ static int logmanager_write_log(
break;
}
}
wp[safe_str_len-1] = '\n';
/** remove double line feed */
if (wp[safe_str_len-2] == '\n')
{
wp[safe_str_len-2]=' ';
}
wp[safe_str_len-1] = '\n';
blockbuf_unregister(bb);
/**
@ -2063,11 +2068,34 @@ static bool logfile_init(
* pointing to shm file is created and located to the file
* directory.
*/
if (store_shmem) {
logfile->lf_filepath = strdup(shm_pathname);
if (store_shmem)
{
char* c;
pid_t pid = getpid();
int len = strlen(shm_pathname_prefix)+
get_decimal_len((size_t)pid);
c = (char *)calloc(len, sizeof(char));
if (c == NULL)
{
succp = false;
goto file_create_fail;
}
sprintf(c, "%s%d", shm_pathname_prefix, pid);
logfile->lf_filepath = c;
if (mkdir(c, S_IRWXU | S_IRWXG) != 0 &&
errno != EEXIST)
{
succp = false;
goto file_create_fail;
}
logfile->lf_linkpath = strdup(fn->fn_logpath);
logfile->lf_linkpath = add_slash(logfile->lf_linkpath);
} else {
}
else
{
logfile->lf_filepath = strdup(fn->fn_logpath);
}
logfile->lf_filepath = add_slash(logfile->lf_filepath);
@ -2146,7 +2174,7 @@ static bool logfile_init(
}
}
}
file_create_fail:
file_create_fail:
if (namecreatefail || nameconflicts)
{
logfile->lf_name_seqno += 1;
@ -2161,7 +2189,7 @@ static bool logfile_init(
free(logfile->lf_full_link_name);
logfile->lf_full_link_name = NULL;
}
goto return_with_succp;
}
} while (namecreatefail || nameconflicts);
/**

View File

@ -1,5 +1,5 @@
/*
* This file is distributed as part of the SkySQL Gateway. It is free
* This file is distributed as part of the MariaDB Corporation MaxScale. It is free
* software: you can redistribute it and/or modify it under the terms of the
* GNU General Public License as published by the Free Software Foundation,
* version 2.
@ -13,7 +13,7 @@
* this program; if not, write to the Free Software Foundation, Inc., 51
* Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Copyright SkySQL Ab 2013
* Copyright MariaDB Corporation Ab 2013-2014
*/

View File

@ -0,0 +1,5 @@
add_executable(testlog testlog.c)
add_executable(testorder testorder.c)
target_link_libraries(testlog pthread log_manager utils)
target_link_libraries(testorder pthread log_manager utils)
add_test(NAME TestLogOrder COMMAND ${CMAKE_CURRENT_SOURCE_DIR}/logorder.sh ${CMAKE_CURRENT_BINARY_DIR}/test.log 500 0 500 ${CMAKE_CURRENT_BINARY_DIR})

View File

@ -2,24 +2,33 @@
if [[ $# -lt 4 ]]
then
echo "Usage: logorder.sh <iterations> <frequency of flushes> <message size>"
echo "Usage: logorder.sh <iterations> <frequency of flushes> <message size> <log file>"
echo "To disable log flushing, use 0 for flush frequency"
exit
fi
rm *.log
if [ $# -eq 5 ]
then
TDIR=$5
else
TDIR=$PWD
fi
#Create large messages
$PWD/testorder $1 $2 $3
$TDIR/testorder $1 $2 $3
TESTLOG=$4
MCOUNT=$1
BLOCKS=`cat skygw_err1.log |tr -s ' '|grep -o 'block:[[:digit:]]\+'|cut -d ':' -f 2`
MESSAGES=`cat skygw_err1.log |tr -s ' '|grep -o 'message|[[:digit:]]\+'|cut -d '|' -f 2`
BLOCKS=`cat $TDIR/skygw_err1.log |tr -s ' '|grep -o 'block:[[:digit:]]\+'|cut -d ':' -f 2`
MESSAGES=`cat $TDIR/skygw_err1.log |tr -s ' '|grep -o 'message|[[:digit:]]\+'|cut -d '|' -f 2`
prev=0
error=0
all_errors=0
for i in $BLOCKS
do
@ -27,6 +36,7 @@ do
if [[ $i -le $prev ]]
then
error=1
all_errors=1
echo "block mismatch: $i was after $prev." >> $TESTLOG
fi
prev=$i
@ -48,6 +58,7 @@ do
if [[ $i -ne $(( prev + 1 )) ]]
then
error=1
all_errors=1
echo "message mismatch: $i was after $prev." >> $TESTLOG
fi
prev=$i
@ -59,3 +70,9 @@ then
else
echo "Error: block buffer messages were written in the wrong order" >> $TESTLOG
fi
if [ $# -eq 5 ]
then
cat $TESTLOG
exit $all_errors
fi

View File

@ -1,5 +1,5 @@
/*
* This file is distributed as part of the SkySQL Gateway. It is free
* This file is distributed as part of the MariaDB Corporation MaxScale. It is free
* software: you can redistribute it and/or modify it under the terms of the
* GNU General Public License as published by the Free Software Foundation,
* version 2.
@ -13,7 +13,7 @@
* this program; if not, write to the Free Software Foundation, Inc., 51
* Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Copyright SkySQL Ab 2013
* Copyright MariaDB Corporation Ab 2013-2014
*/

View File

@ -1,5 +1,5 @@
/*
* This file is distributed as part of the SkySQL Gateway. It is free
* This file is distributed as part of the MariaDB Corporation MaxScale. It is free
* software: you can redistribute it and/or modify it under the terms of the
* GNU General Public License as published by the Free Software Foundation,
* version 2.
@ -13,7 +13,7 @@
* this program; if not, write to the Free Software Foundation, Inc., 51
* Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Copyright SkySQL Ab 2013
* Copyright MariaDB Corporation Ab 2013-2014
*/
#include <unistd.h>

227
macros.cmake Normal file
View File

@ -0,0 +1,227 @@
macro(set_maxscale_version)
#MaxScale version number
set(MAXSCALE_VERSION_MAJOR "1")
set(MAXSCALE_VERSION_MINOR "0")
set(MAXSCALE_VERSION_PATCH "1")
set(MAXSCALE_VERSION_NUMERIC "${MAXSCALE_VERSION_MAJOR}.${MAXSCALE_VERSION_MINOR}.${MAXSCALE_VERSION_PATCH}")
set(MAXSCALE_VERSION "${MAXSCALE_VERSION_MAJOR}.${MAXSCALE_VERSION_MINOR}.${MAXSCALE_VERSION_PATCH}-beta")
endmacro()
macro(set_variables)
# Installation directory
set(INSTALL_DIR "/usr/local/skysql/maxscale/" CACHE PATH "MaxScale installation directory.")
# Build type
set(BUILD_TYPE "None" CACHE STRING "Build type, possible values are:None, Debug, Optimized.")
# hostname or IP address of MaxScale's host
set(TEST_HOST "127.0.0.1" CACHE STRING "hostname or IP address of MaxScale's host")
# port of read connection router module
set(TEST_PORT_RW "4008" CACHE STRING "port of read connection router module")
# port of read/write split router module
set(TEST_PORT_RW "4006" CACHE STRING "port of read/write split router module")
# port of read/write split router module with hints
set(TEST_PORT_RW_HINT "4006" CACHE STRING "port of read/write split router module with hints")
# master test server server_id
set(TEST_MASTER_ID "3000" CACHE STRING "master test server server_id")
# username of MaxScale user
set(TEST_USER "maxuser" CACHE STRING "username of MaxScale user")
# password of MaxScale user
set(TEST_PASSWORD "maxpwd" CACHE STRING "password of MaxScale user")
# Use static version of libmysqld
set(STATIC_EMBEDDED TRUE CACHE BOOL "Use static version of libmysqld")
# Build RabbitMQ components
set(BUILD_RABBITMQ FALSE CACHE BOOL "Build RabbitMQ components")
# Use gcov build flags
set(GCOV FALSE CACHE BOOL "Use gcov build flags")
# Install init.d scripts and ldconf configuration files
set(INSTALL_SYSTEM_FILES TRUE CACHE BOOL "Install init.d scripts and ldconf configuration files")
# Build tests
set(BUILD_TESTS FALSE CACHE BOOL "Build tests")
endmacro()
macro(check_deps)
# Check for libraries MaxScale depends on
set(MAXSCALE_DEPS aio ssl crypt crypto z m dl rt pthread)
foreach(lib ${MAXSCALE_DEPS})
find_library(lib${lib} ${lib})
if((DEFINED lib${lib}) AND (${lib${lib}} STREQUAL "lib${lib}-NOTFOUND"))
set(DEPS_ERROR TRUE)
set(FAILED_DEPS "${FAILED_DEPS} lib${lib}")
elseif(DEBUG_OUTPUT)
message(STATUS "Library was found at: ${lib${lib}}")
endif()
endforeach()
if(DEPS_ERROR)
set(DEPS_OK FALSE CACHE BOOL "If all the dependencies were found.")
message(FATAL_ERROR "Cannot find dependencies: ${FAILED_DEPS}")
endif()
endmacro()
macro(check_dirs)
# This variable is used to prevent redundant checking of dependencies
set(DEPS_OK TRUE CACHE BOOL "If all the dependencies were found.")
# Find the MySQL headers if they were not defined
if(DEFINED MYSQL_DIR)
if(DEBUG_OUTPUT)
message(STATUS "Searching for MySQL headers at: ${MYSQL_DIR}")
endif()
find_path(MYSQL_DIR_LOC mysql.h PATHS ${MYSQL_DIR} PATH_SUFFIXES mysql mariadb NO_DEFAULT_PATH)
endif()
find_path(MYSQL_DIR_LOC mysql.h PATH_SUFFIXES mysql mariadb)
if(DEBUG_OUTPUT)
message(STATUS "Search returned: ${MYSQL_DIR_LOC}")
endif()
if(${MYSQL_DIR_LOC} STREQUAL "MYSQL_DIR_LOC-NOTFOUND")
set(DEPS_OK FALSE CACHE BOOL "If all the dependencies were found.")
message(FATAL_ERROR "Fatal Error: MySQL headers were not found.")
else()
message(STATUS "Using MySQL headers found at: ${MYSQL_DIR}")
set(MYSQL_DIR ${MYSQL_DIR_LOC} CACHE PATH "Path to MySQL headers" FORCE)
endif()
set(MYSQL_DIR_LOC "" INTERNAL)
# Find the errmsg.sys file if it was not defied
if( DEFINED ERRMSG )
find_file(ERRMSG_FILE errmsg.sys PATHS ${ERRMSG} NO_DEFAULT_PATH)
endif()
find_file(ERRMSG_FILE errmsg.sys PATHS /usr/share/mysql /usr/local/share/mysql PATH_SUFFIXES english)
if(${ERRMSG_FILE} MATCHES "ERRMSG_FILE-NOTFOUND")
set(DEPS_OK FALSE CACHE BOOL "If all the dependencies were found.")
message(FATAL_ERROR "Fatal Error: The errmsg.sys file was not found, please define the path to it by using -DERRMSG=<path>")
else()
message(STATUS "Using errmsg.sys found at: ${ERRMSG_FILE}")
endif()
set(ERRMSG ${ERRMSG_FILE} CACHE FILEPATH "Path to the errmsg.sys file." FORCE)
set(ERRMSG_FILE "" INTERNAL)
# Find the embedded mysql library
if(STATIC_EMBEDDED)
set(OLD_SUFFIXES ${CMAKE_FIND_LIBRARY_SUFFIXES})
set(CMAKE_FIND_LIBRARY_SUFFIXES ".a")
if (DEFINED EMBEDDED_LIB)
if(DEBUG_OUTPUT)
message(STATUS "Searching for libmysqld.a at: ${EMBEDDED_LIB}")
endif()
find_library(EMBEDDED_LIB_STATIC libmysqld.a PATHS ${EMBEDDED_LIB} PATH_SUFFIXES mysql mariadb NO_DEFAULT_PATH)
else()
find_library(EMBEDDED_LIB_STATIC libmysqld.a PATH_SUFFIXES mysql mariadb)
endif()
if(DEBUG_OUTPUT)
message(STATUS "Search returned: ${EMBEDDED_LIB_STATIC}")
endif()
set(EMBEDDED_LIB ${EMBEDDED_LIB_STATIC} CACHE FILEPATH "Path to libmysqld" FORCE)
set(CMAKE_FIND_LIBRARY_SUFFIXES ${OLD_SUFFIXES})
set(OLD_SUFFIXES "" INTERNAL)
else()
if (DEFINED EMBEDDED_LIB)
if(DEBUG_OUTPUT)
message(STATUS "Searching for libmysqld.so at: ${EMBEDDED_LIB}")
endif()
find_library(EMBEDDED_LIB_DYNAMIC mysqld PATHS ${EMBEDDED_LIB} PATH_SUFFIXES mysql mariadb NO_DEFAULT_PATH)
else()
find_library(EMBEDDED_LIB_DYNAMIC mysqld PATH_SUFFIXES mysql mariadb)
endif()
if(DEBUG_OUTPUT)
message(STATUS "Search returned: ${EMBEDDED_LIB_DYNAMIC}")
endif()
set(EMBEDDED_LIB ${EMBEDDED_LIB_DYNAMIC} CACHE FILEPATH "Path to libmysqld" FORCE)
endif()
set(EMBEDDED_LIB_DYNAMIC "" INTERNAL)
set(EMBEDDED_LIB_STATIC "" INTERNAL)
# Inform the user about the embedded library
if( (${EMBEDDED_LIB} STREQUAL "EMBEDDED_LIB_STATIC-NOTFOUND") OR (${EMBEDDED_LIB} STREQUAL "EMBEDDED_LIB_DYNAMIC-NOTFOUND"))
set(DEPS_OK FALSE CACHE BOOL "If all the dependencies were found.")
message(FATAL_ERROR "Library not found: libmysqld. If your install of MySQL is in a non-default location, please provide the location with -DEMBEDDED_LIB=<path to library>")
else()
get_filename_component(EMBEDDED_LIB ${EMBEDDED_LIB} REALPATH)
message(STATUS "Using embedded library: ${EMBEDDED_LIB}")
endif()
# Check which init.d script to install
find_file(RPM_FNC functions PATHS /etc/rc.d/init.d)
if(${RPM_FNC} MATCHES "RPM_FNC-NOTFOUND")
find_file(DEB_FNC init-functions PATHS /lib/lsb)
if(${DEB_FNC} MATCHES "DEB_FNC-NOTFOUND")
set(DEPS_OK FALSE CACHE BOOL "If all the dependencies were found.")
message(FATAL_ERROR "Cannot find required init-functions in /lib/lsb/ or /etc/rc.d/init.d/, please confirm that your system files are OK.")
else()
set(DEB_BASED TRUE CACHE BOOL "If init.d script uses /lib/lsb/init-functions instead of /etc/rc.d/init.d/functions.")
endif()
else()
set(DEB_BASED FALSE CACHE BOOL "If init.d script uses /lib/lsb/init-functions instead of /etc/rc.d/init.d/functions.")
endif()
set(DEB_FNC "" INTERNAL)
set(RPM_FNC "" INTERNAL)
#Check RabbitMQ headers and libraries
if(BUILD_RABBITMQ)
if(DEFINED RABBITMQ_LIB)
find_library(RMQ_LIB rabbitmq PATHS ${RABBITMQ_LIB} NO_DEFAULT_PATH)
endif()
find_library(RMQ_LIB rabbitmq)
if(RMQ_LIB STREQUAL "RMQ_LIB-NOTFOUND")
set(DEPS_OK FALSE CACHE BOOL "If all the dependencies were found.")
message(FATAL_ERROR "Cannot find RabbitMQ libraries, please define the path to the libraries with -DRABBITMQ_LIB=<path>")
else()
set(RABBITMQ_LIB ${RMQ_LIB} CACHE PATH "Path to RabbitMQ libraries" FORCE)
message(STATUS "Using RabbitMQ libraries found at: ${RABBITMQ_LIB}")
endif()
if(DEFINED RABBITMQ_HEADERS)
find_file(RMQ_HEADERS amqp.h PATHS ${RABBITMQ_HEADERS} NO_DEFAULT_PATH)
endif()
find_file(RMQ_HEADERS amqp.h)
if(RMQ_HEADERS STREQUAL "RMQ_HEADERS-NOTFOUND")
set(DEPS_OK FALSE CACHE BOOL "If all the dependencies were found.")
message(FATAL_ERROR "Cannot find RabbitMQ headers, please define the path to the headers with -DRABBITMQ_HEADERS=<path>")
else()
set(RABBITMQ_HEADERS ${RMQ_HEADERS} CACHE PATH "Path to RabbitMQ headers" FORCE)
message(STATUS "Using RabbitMQ headers found at: ${RABBITMQ_HEADERS}")
endif()
endif()
endmacro()
function(subdirs VAR DIRPATH)
if(${CMAKE_VERSION} VERSION_LESS 2.12 )
set(COMP_VAR PATH)
else()
set(COMP_VAR DIRECTORY)
endif()
file(GLOB_RECURSE SDIR ${DIRPATH}/*)
foreach(LOOP ${SDIR})
get_filename_component(LOOP ${LOOP} ${COMP_VAR})
list(APPEND ALLDIRS ${LOOP})
endforeach()
list(REMOVE_DUPLICATES ALLDIRS)
set(${VAR} "${ALLDIRS}" CACHE PATH " " FORCE)
endfunction()

2
maxscale.conf.in Normal file
View File

@ -0,0 +1,2 @@
@INSTALL_DIR@/modules
@INSTALL_DIR@/lib

View File

@ -0,0 +1,5 @@
add_library(query_classifier SHARED query_classifier.cc)
install(TARGETS query_classifier DESTINATION lib)
if(BUILD_TESTS)
add_subdirectory(test)
endif()

View File

@ -1,7 +1,7 @@
/**
* @section LICENCE
*
* This file is distributed as part of the SkySQL Gateway. It is
* This file is distributed as part of the MariaDB Corporation MaxScale. It is
* free software: you can redistribute it and/or modify it under
* the terms of the GNU General Public License as published by the
* Free Software Foundation, version 2.
@ -16,7 +16,7 @@
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
* 02110-1301 USA.
*
* Copyright SkySQL Ab
* Copyright MariaDB Corporation Ab
*
* @file
*
@ -359,17 +359,37 @@ static bool create_parse_tree(
Parser_state parser_state;
bool failp = FALSE;
const char* virtual_db = "skygw_virtual";
#if defined(SS_DEBUG_EXTRA)
LOGIF(LM, (skygw_log_write_flush(
LOGFILE_MESSAGE,
"[readwritesplit:create_parse_tree] 1.")));
#endif
if (parser_state.init(thd, thd->query(), thd->query_length())) {
failp = TRUE;
goto return_here;
}
mysql_reset_thd_for_next_command(thd);
/** Set some database to thd so that parsing won't fail because of
* missing database. Then parse. */
failp = thd->set_db(virtual_db, strlen(virtual_db));
#if defined(SS_DEBUG_EXTRA)
LOGIF(LM, (skygw_log_write_flush(
LOGFILE_MESSAGE,
"[readwritesplit:create_parse_tree] 2.")));
#endif
mysql_reset_thd_for_next_command(thd);
#if defined(SS_DEBUG_EXTRA)
LOGIF(LM, (skygw_log_write_flush(
LOGFILE_MESSAGE,
"[readwritesplit:create_parse_tree] 3.")));
#endif
/**
* Set some database to thd so that parsing won't fail because of
* missing database. Then parse.
*/
failp = thd->set_db(virtual_db, strlen(virtual_db));
#if defined(SS_DEBUG_EXTRA)
LOGIF(LM, (skygw_log_write_flush(
LOGFILE_MESSAGE,
"[readwritesplit:create_parse_tree] 4.")));
#endif
if (failp) {
LOGIF(LE, (skygw_log_write_flush(
LOGFILE_ERROR,
@ -377,6 +397,11 @@ static bool create_parse_tree(
}
failp = parse_sql(thd, &parser_state, NULL);
#if defined(SS_DEBUG_EXTRA)
LOGIF(LM, (skygw_log_write_flush(
LOGFILE_MESSAGE,
"[readwritesplit:create_parse_tree] 5.")));
#endif
if (failp) {
LOGIF(LD, (skygw_log_write(
LOGFILE_DEBUG,
@ -614,7 +639,17 @@ static skygw_query_type_t resolve_query_type(
type |= QUERY_TYPE_PREPARE_NAMED_STMT;
goto return_qtype;
break;
case SQLCOM_SHOW_DATABASES:
type |= QUERY_TYPE_SHOW_DATABASES;
goto return_qtype;
break;
case SQLCOM_SHOW_TABLES:
type |= QUERY_TYPE_SHOW_TABLES;
goto return_qtype;
break;
default:
break;
}
@ -798,8 +833,7 @@ static skygw_query_type_t resolve_query_type(
LOGIF(LD, (skygw_log_write(
LOGFILE_DEBUG,
"%lu [resolve_query_type] "
"Unknown functype %d. Something "
"has gone wrong.",
"Functype %d.",
pthread_self(),
ftype)));
break;
@ -1350,3 +1384,49 @@ static void parsing_info_set_plain_str(
pi->pi_query_plain_str = str;
}
/**
* Generate a string of query type value.
* Caller must free the memory of the resulting string.
*
* @param qtype Query type value, combination of values listed in
* query_classifier.h
*
* @return string representing the query type value
*/
char* skygw_get_qtype_str(
skygw_query_type_t qtype)
{
int t1 = (int)qtype;
int t2 = 1;
skygw_query_type_t t = QUERY_TYPE_UNKNOWN;
char* qtype_str = NULL;
/**
* Test values (bits) and clear matching bits from t1 one by one until
* t1 is completely cleared.
*/
while (t1 != 0)
{
if (t1&t2)
{
t = (skygw_query_type_t)t2;
if (qtype_str == NULL)
{
qtype_str = strdup(STRQTYPE(t));
}
else
{
size_t len = strlen(STRQTYPE(t));
/** reallocate space for delimiter, new string and termination */
qtype_str = (char *)realloc(qtype_str, strlen(qtype_str)+1+len+1);
snprintf(qtype_str+strlen(qtype_str), 1+len+1, "|%s", STRQTYPE(t));
}
/** Remove found value from t1 */
t1 &= ~t2;
}
t2 <<= 1;
}
return qtype_str;
}

View File

@ -1,5 +1,5 @@
/*
This file is distributed as part of the SkySQL Gateway. It is free
This file is distributed as part of the MariaDB Corporation MaxScale. It is free
software: you can redistribute it and/or modify it under the terms of the
GNU General Public License as published by the Free Software Foundation,
version 2.
@ -13,7 +13,7 @@ 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.
Copyright SkySQL Ab
Copyright MariaDB Corporation Ab
*/
@ -54,7 +54,9 @@ typedef enum {
QUERY_TYPE_PREPARE_STMT = 0x020000, /*< Prepared stmt with id provided by server:all */
QUERY_TYPE_EXEC_STMT = 0x040000, /*< Execute prepared statement:master or any */
QUERY_TYPE_CREATE_TMP_TABLE = 0x080000, /*< Create temporary table:master (could be all) */
QUERY_TYPE_READ_TMP_TABLE = 0x100000 /*< Read temporary table:master (could be any) */
QUERY_TYPE_READ_TMP_TABLE = 0x100000, /*< Read temporary table:master (could be any) */
QUERY_TYPE_SHOW_DATABASES = 0x200000, /*< Show list of databases */
QUERY_TYPE_SHOW_TABLES = 0x400000 /*< Show list of tables */
} skygw_query_type_t;
@ -91,6 +93,7 @@ bool parse_query (GWBUF* querybuf);
parsing_info_t* parsing_info_init(void (*donefun)(void *));
void parsing_info_done(void* ptr);
bool query_is_parsed(GWBUF* buf);
char* skygw_get_qtype_str(skygw_query_type_t qtype);
EXTERN_C_BLOCK_END

View File

@ -0,0 +1 @@
add_subdirectory(canonical_tests)

View File

@ -0,0 +1,12 @@
file(COPY ${ERRMSG} DESTINATION ${CMAKE_CURRENT_BINARY_DIR})
if(${ERRMSG} MATCHES "ERRMSG-NOTFOUND")
message(FATAL_ERROR "The errmsg.sys file was not found, please define the path with -DERRMSG=<path>")
endif()
add_executable(canonizer canonizer.c)
target_link_libraries(canonizer pthread query_classifier z dl ssl aio crypt crypto rt m ${EMBEDDED_LIB} fullcore stdc++)
add_test(NAME TestCanonicalQuery COMMAND ${CMAKE_CURRENT_SOURCE_DIR}/canontest.sh
${CMAKE_CURRENT_BINARY_DIR}/test.log
${CMAKE_CURRENT_SOURCE_DIR}/input.sql
${CMAKE_CURRENT_BINARY_DIR}/output.sql
${CMAKE_CURRENT_SOURCE_DIR}/expected.sql
$<TARGET_FILE:canonizer>)

View File

@ -7,7 +7,7 @@
#include <mysql.h>
static char* server_options[] = {
"SkySQL Gateway",
"MariaDB Corporation MaxScale",
"--datadir=./",
"--language=./",
"--skip-innodb",

View File

@ -1,5 +1,5 @@
#! /bin/sh
if [[ $# -ne 4 ]]
if [[ $# -lt 4 ]]
then
echo "Usage: canontest.sh <logfile name> <input file> <output file> <expected output>"
exit 0
@ -9,13 +9,29 @@ INPUT=$2
OUTPUT=$3
EXPECTED=$4
DIFFLOG=diff.out
$PWD/canonizer $INPUT $OUTPUT
if [ $# -eq 5 ]
then
EXECUTABLE=$5
else
EXECUTABLE=$PWD/canonizer
fi
$EXECUTABLE $INPUT $OUTPUT
diff $OUTPUT $EXPECTED > $DIFFLOG
if [ $? -eq 0 ]
then
echo "PASSED" >> $TESTLOG
exval=0
else
echo "FAILED" >> $TESTLOG
echo "Diff output: " >> $TESTLOG
cat $DIFFLOG >> $TESTLOG
exval=1
fi
if [ $# -eq 5 ]
then
cat $TESTLOG
exit $exval
fi

View File

@ -1,7 +1,7 @@
select md5(?) =?, sleep(?), rand(?);
select * from my1 where md5(?) =?;
select md5(?) =?;
select * from my1 where md5(?) =?;
select md5("?") =?, sleep(?), rand(?)
select * from my1 where md5("?") =?
select md5("?") =?
select * from my1 where md5("?") =?
select sleep(?)
select * from tst where lname='?'
select ?,?,?,?,?,? from tst
@ -13,5 +13,5 @@ create table tst(fname varchar(30), lname varchar(30))
update tst set lname="?" where fname like '?' or lname like '?'
delete from tst where lname like '?' and fname like '?'
select ? from tst where fname='?' or lname like '?'
select ?,?,?,? from tst where name='?' or name='?' or name='?'
select ?,?,?,? from tst where name='?' or name='?' or name='?' or name='?'
select count(?),count(?),count(?),count(?),count (?),count(?) from tst

View File

@ -13,7 +13,7 @@ static char datadir[1024] = "";
static char mysqldir[1024] = "";
static char* server_options[] = {
"SkySQL Gateway",
"MariaDB Corporation MaxScale",
"--datadir=",
"--default-storage-engine=myisam",
NULL

View File

@ -1,44 +1,21 @@
cmake_minimum_required (VERSION 2.6)
if (NOT ( DEFINED MYSQL_CLIENT_LIB ) )
find_library(MYSQL_CLIENT_LIB NAMES mysqlclient PATHS /usr/lib /usr/lib64 PATH_SUFFIXES mysql mariadb)
endif()
set(CMAKE_LIBRARY_PATH ${CMAKE_LIBRARY_PATH} /usr/lib /usr/lib64 /usr/local/lib /usr/local/lib64 /usr/lib/mariadb /usr/lib64/mariadb)
set(CMAKE_INCLUDE_PATH ${CMAKE_INCLUDE_PATH} /usr/include /usr/local/include /usr/include/mysql /usr/local/include/mysql /usr/include/mariadb /usr/local/include/mariadb)
if (NOT ( DEFINED MYSQL_CLIENT_HEADERS ) )
find_path(MYSQL_CLIENT_HEADERS NAMES mysql.h PATH_SUFFIXES mysql mariadb)
endif()
include(InstallRequiredSystemLibraries)
project (consumer)
find_path(MYSQL_INCLUDE_DIRS mysql.h)
find_library(MYSQL_LIBRARIES NAMES mysqlclient)
find_library(RABBITMQ_C_LIBRARIES NAMES rabbitmq)
include_directories(${MYSQL_INCLUDE_DIRS})
include_directories(${RABBITMQ_C_INCLUDE_DIRS})
include_directories(${CMAKE_SOURCE_DIR}/inih)
add_subdirectory (inih)
link_directories(${CMAKE_SOURCE_DIR}/inih)
if(RABBITMQ_C_LIBRARIES AND MYSQL_LIBRARIES AND MYSQL_INCLUDE_DIRS)
add_executable (consumer consumer.c ${MYSQL_LIBRARIES} ${RABBITMQ_C_LIBRARIES})
target_link_libraries(consumer mysqlclient)
target_link_libraries(consumer rabbitmq)
target_link_libraries(consumer inih)
install(TARGETS consumer DESTINATION bin)
install(FILES consumer.cnf DESTINATION share/consumer)
if( ( RABBITMQ_LIB AND RABBITMQ_HEADERS ) AND ( NOT ( ${MYSQL_CLIENT_LIB} STREQUAL "MYSQL_CLIENT_LIB-NOTFOUND" ) ) AND ( NOT ( ${MYSQL_CLIENT_HEADERS} STREQUAL "MYSQL_CLIENT_HEADERS-NOTFOUND" ) ) )
include_directories(${MYSQL_CLIENT_HEADERS})
add_executable (consumer consumer.c)
target_link_libraries(consumer ${MYSQL_CLIENT_LIB} rabbitmq inih)
install(TARGETS consumer DESTINATION bin)
install(FILES consumer.cnf DESTINATION etc)
else(RABBITMQ_C_LIBRARIES AND MYSQL_LIBRARIES AND MYSQL_INCLUDE_DIRS)
message(FATAL_ERROR "Error: Can not find requred libraries: libmysqld, librabbitmq.")
else()
endif(RABBITMQ_C_LIBRARIES AND MYSQL_LIBRARIES AND MYSQL_INCLUDE_DIRS)
message(FATAL_ERROR "Error: Can not find requred libraries and headers: librabbitmq libmysqlclient")
set(CPACK_PACKAGE_DESCRIPTION_SUMMARY "RabbitMQ Consumer Client")
set(CPACK_PACKAGE_NAME "RabbitMQ Consumer")
set(CPACK_GENERATOR "RPM")
set(CPACK_PACKAGE_VERSION_MAJOR "1")
set(CPACK_PACKAGE_VERSION_MINOR "0")
set(CPACK_RPM_PACKAGE_NAME "rabbitmq-consumer")
set(CPACK_RPM_PACKAGE_VENDOR "SkySQL Ab")
set(CPACK_RPM_PACKAGE_AUTOREQPROV " no")
include(CPack)
endif()

View File

@ -1,7 +1,7 @@
Portions of this software contain modifications contributed by SkySQL, Ab.
Portions of this software contain modifications contributed by MariaDB Corporation, Ab.
These contributions are used with the following license:
Copyright (c) 2013, SkySQL Ab. All rights reserved.
Copyright (c) 2013, MariaDB Corporation Ab. All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
@ -12,7 +12,7 @@ are met:
copyright notice, this list of conditions and the following
disclaimer in the documentation and/or other materials
provided with the distribution.
* Neither the name of the SkySQL Ab. nor the names of its
* Neither the name of the MariaDB Corporation Ab. nor the names of its
contributors may be used to endorse or promote products
derived from this software without specific prior written
permission.

View File

@ -1,10 +1,10 @@
/*
Copyright (c) 2003, 2011, Oracle and/or its affiliates. All rights
reserved.
Copyright (c) 2013, SkySQL Ab
Copyright (c) 2013, MariaDB Corporation Ab
Portions of this file contain modifications contributed and copyrighted by
SkySQL, Ab. Those modifications are gratefully acknowledged and are described
MariaDB Corporation, Ab. Those modifications are gratefully acknowledged and are described
briefly in the source code.
This program is free software; you can redistribute it and/or
@ -23,7 +23,7 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
02110-1301 USA
*/
/*
SkySQL change details:
MariaDB Corporation change details:
- Removed unnecessary file driver
Author: Jan Lindström (jan.lindstrom@skysql.com

View File

@ -1,10 +1,10 @@
/*
Copyright (c) 2003, 2011, Oracle and/or its affiliates. All rights
reserved.
Copyright (c) 2013, SkySQL Ab
Copyright (c) 2013-2014, MariaDB Corporation Ab
Portions of this file contain modifications contributed and copyrighted by
SkySQL, Ab. Those modifications are gratefully acknowledged and are described
MariaDB Corporation, Ab. Those modifications are gratefully acknowledged and are described
briefly in the source code.
This program is free software; you can redistribute it and/or

View File

@ -1,10 +1,10 @@
/*
Copyright (c) 2003, 2011, Oracle and/or its affiliates. All rights
reserved.
Copyright (c) 2013, SkySQL Ab
Copyright (c) 2013, MariaDB Corporation Ab
Portions of this file contain modifications contributed and copyrighted by
SkySQL, Ab. Those modifications are gratefully acknowledged and are described
MariaDB Corporation, Ab. Those modifications are gratefully acknowledged and are described
briefly in the source code.
This program is free software; you can redistribute it and/or
@ -23,7 +23,7 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
02110-1301 USA
*/
/*
SkySQL change details:
MariaDB Corporation change details:
- Added GTID event handler
Author: Jan Lindström (jan.lindstrom@skysql.com

View File

@ -1,10 +1,10 @@
/*
Copyright (c) 2003, 2011, Oracle and/or its affiliates. All rights
reserved.
Copyright (c) 2013, SkySQL Ab
Copyright (c) 2013-2014, MariaDB Corporation Ab
Portions of this file contain modifications contributed and copyrighted by
SkySQL, Ab. Those modifications are gratefully acknowledged and are described
MariaDB Corporation, Ab. Those modifications are gratefully acknowledged and are described
briefly in the source code.
This program is free software; you can redistribute it and/or
@ -23,7 +23,7 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
02110-1301 USA
*/
/*
SkySQL change details:
MariaDB Corporation change details:
- Added GTID event handler
Author: Jan Lindström (jan.lindstrom@skysql.com

View File

@ -1,10 +1,10 @@
/*
Copyright (c) 2003, 2011, Oracle and/or its affiliates. All rights
reserved.
Copyright (c) 2013, SkySQL Ab
Copyright (c) 2013, MariaDB Corporation Ab
Portions of this file contain modifications contributed and copyrighted by
SkySQL, Ab. Those modifications are gratefully acknowledged and are described
MariaDB Corporation, Ab. Those modifications are gratefully acknowledged and are described
briefly in the source code.
This program is free software; you can redistribute it and/or
@ -23,7 +23,7 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
02110-1301 USA
*/
/*
SkySQL change details:
MariaDB Corporation change details:
- Added support for setting binlog position based on GTID
- Added support for MySQL and MariDB server types

View File

@ -1,10 +1,10 @@
/*
Copyright (c) 2003, 2011, Oracle and/or its affiliates. All rights
reserved.
Copyright (c) 2013, SkySQL Ab
Copyright (c) 2013-2014, MariaDB Corporation Ab
Portions of this file contain modifications contributed and copyrighted by
SkySQL, Ab. Those modifications are gratefully acknowledged and are described
MariaDB Corporation, Ab. Those modifications are gratefully acknowledged and are described
briefly in the source code.
This program is free software; you can redistribute it and/or
@ -23,7 +23,7 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
02110-1301 USA
*/
/*
SkySQL change details:
MariaDB Corporation change details:
- Added support for setting binlog position based on GTID
- Added support for MySQL and MariDB server types

View File

@ -1,10 +1,10 @@
/*
Copyright (c) 2003, 2011, Oracle and/or its affiliates. All rights
reserved.
Copyright (c) 2013, SkySQL Ab
Copyright (c) 2013, MariaDB Corporation Ab
Portions of this file contain modifications contributed and copyrighted by
SkySQL, Ab. Those modifications are gratefully acknowledged and are described
MariaDB Corporation, Ab. Those modifications are gratefully acknowledged and are described
briefly in the source code.
This program is free software; you can redistribute it and/or
@ -23,7 +23,7 @@
02110-1301 USA
*/
/*
SkySQL change details:
MariaDB Corporation change details:
- Added support for GTID event handling for both MySQL and MariaDB
Author: Jan Lindström (jan.lindstrom@skysql.com

View File

@ -1,10 +1,10 @@
/*
Copyright (c) 2003, 2011, Oracle and/or its affiliates. All rights
reserved.
Copyright (c) 2013, SkySQL Ab
Copyright (c) 2013-2014, MariaDB Corporation Ab
Portions of this file contain modifications contributed and copyrighted by
SkySQL, Ab. Those modifications are gratefully acknowledged and are described
MariaDB Corporation, Ab. Those modifications are gratefully acknowledged and are described
briefly in the source code.
This program is free software; you can redistribute it and/or
@ -23,7 +23,7 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
02110-1301 USA
*/
/*
SkySQL change details:
MariaDB Corporation change details:
- Added support for GTID event handling for both MySQL and MariaDB
- Added support for setting binlog position based on GTID

View File

@ -1,10 +1,10 @@
/*
Copyright (c) 2003, 2011, Oracle and/or its affiliates. All rights
reserved.
Copyright (c) 2013, SkySQL Ab
Copyright (c) 2013, MariaDB Corporation Ab
Portions of this file contain modifications contributed and copyrighted by
SkySQL, Ab. Those modifications are gratefully acknowledged and are described
MariaDB Corporation, Ab. Those modifications are gratefully acknowledged and are described
briefly in the source code.
This program is free software; you can redistribute it and/or
@ -23,7 +23,7 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
02110-1301 USA
*/
/*
SkySQL change details:
MariaDB Corporation change details:
- Added support for GTID event handling for both MySQL and MariaDB
Author: Jan Lindström (jan.lindstrom@skysql.com

View File

@ -1,10 +1,10 @@
/*
Copyright (c) 2003, 2011, Oracle and/or its affiliates. All rights
reserved.
Copyright (c) 2013, SkySQL Ab
Copyright (c) 2013-2014, MariaDB Corporation Ab
Portions of this file contain modifications contributed and copyrighted by
SkySQL, Ab. Those modifications are gratefully acknowledged and are described
MariaDB Corporation, Ab. Those modifications are gratefully acknowledged and are described
briefly in the source code.
This program is free software; you can redistribute it and/or
@ -23,7 +23,7 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
02110-1301 USA
*/
/*
SkySQL change details:
MariaDB Corporation change details:
- Added support for GTID event handling for both MySQL and MariaDB
Author: Jan Lindström (jan.lindstrom@skysql.com

View File

@ -1,8 +1,8 @@
/*
Copyright (C) 2013, SkySQL Ab
Copyright (C) 2013, MariaDB Corporation Ab
This file is distributed as part of the SkySQL Gateway. It is free
This file is distributed as part of the MariaDB Corporation MaxScale. It is free
software: you can redistribute it and/or modify it under the terms of the
GNU General Public License as published by the Free Software Foundation,
version 2.

View File

@ -1,7 +1,7 @@
/*
Copyright (C) 2013, SkySQL Ab
Copyright (C) 2013-2014, MariaDB Corporation Ab
This file is distributed as part of the SkySQL Gateway. It is free
This file is distributed as part of the MariaDB Corporation MaxScale. It is free
software: you can redistribute it and/or modify it under the terms of the
GNU General Public License as published by the Free Software Foundation,
version 2.

View File

@ -1,8 +1,8 @@
/*
Copyright (C) 2013, SkySQL Ab
Copyright (C) 2013-2014, MariaDB Corporation Ab
This file is distributed as part of the SkySQL Gateway. It is free
This file is distributed as part of the MariaDB Corporation MaxScale. It is free
software: you can redistribute it and/or modify it under the terms of the
GNU General Public License as published by the Free Software Foundation,
version 2.

View File

@ -1,10 +1,10 @@
/*
Copyright (c) 2003, 2011, Oracle and/or its affiliates. All rights
reserved.
Copyright (c) 2013, SkySQL Ab
Copyright (c) 2013, MariaDB Corporation Ab
Portions of this file contain modifications contributed and copyrighted by
SkySQL, Ab. Those modifications are gratefully acknowledged and are described
MariaDB Corporation, Ab. Those modifications are gratefully acknowledged and are described
briefly in the source code.
This program is free software; you can redistribute it and/or
@ -23,7 +23,7 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
02110-1301 USA
*/
/*
SkySQL change details:
MariaDB Corporation change details:
- Added support for GTID event handling for both MySQL and MariaDB
Author: Jan Lindström (jan.lindstrom@skysql.com

View File

@ -1,10 +1,10 @@
/*
Copyright (c) 2003, 2011, Oracle and/or its affiliates. All rights
reserved.
Copyright (c) 2013, SkySQL Ab
Copyright (c) 2013, MariaDB Corporation Ab
Portions of this file contain modifications contributed and copyrighted by
SkySQL, Ab. Those modifications are gratefully acknowledged and are described
MariaDB Corporation, Ab. Those modifications are gratefully acknowledged and are described
briefly in the source code.
This program is free software; you can redistribute it and/or
@ -23,7 +23,7 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
02110-1301 USA
*/
/*
SkySQL change details:
MariaDB Corporation change details:
- Added support for GTID event handling for both MySQL and MariaDB
- Added support for starting binlog dump from GTID position
- Added error handling using exceptions

View File

@ -1,10 +1,10 @@
/*
Copyright (c) 2003, 2011, Oracle and/or its affiliates. All rights
reserved.
Copyright (c) 2013, SkySQL Ab
Copyright (c) 2013-2014, MariaDB Corporation Ab
Portions of this file contain modifications contributed and copyrighted by
SkySQL, Ab. Those modifications are gratefully acknowledged and are described
MariaDB Corporation, Ab. Those modifications are gratefully acknowledged and are described
briefly in the source code.
This program is free software; you can redistribute it and/or
@ -23,7 +23,7 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
02110-1301 USA
*/
/*
SkySQL change details:
MariaDB Corporation change details:
- Added support for GTID event handling for both MySQL and MariaDB
- Added support for starting binlog dump from GTID position
- Added support for MariaDB server

View File

@ -1,8 +1,8 @@
/*
Copyright (C) 2013, SkySQL Ab
Copyright (C) 2013, MariaDB Corporation Ab
This file is distributed as part of the SkySQL Gateway. It is free
This file is distributed as part of the MariaDB Corporation MaxScale. It is free
software: you can redistribute it and/or modify it under the terms of the
GNU General Public License as published by the Free Software Foundation,
version 2.

View File

@ -14,7 +14,7 @@ echo "Looking for MaxScale in [${BINARY_PATH}]"
if [ -s "${BINARY_PATH}/bin/maxscale" ]; then
if [ -x "${BINARY_PATH}/bin/maxscale" ]; then
MAXSCALE_VERSION=`strings ${BINARY_PATH}/bin/maxscale | grep "SkySQL MaxScale" | awk '{print $3}' | head -1`
MAXSCALE_VERSION=`strings ${BINARY_PATH}/bin/maxscale | grep "MariaDB Corporation MaxScale" | awk '{print $3}' | head -1`
echo "Found MaxScale, version: ${MAXSCALE_VERSION}"
fi
else

6
server/CMakeLists.txt Normal file
View File

@ -0,0 +1,6 @@
add_subdirectory(core)
add_subdirectory(modules)
add_subdirectory(inih)
if(BUILD_TESTS)
add_subdirectory(test)
endif()

View File

@ -1,4 +1,4 @@
# This file is distributed as part of the SkySQL Gateway. It is free
# This file is distributed as part of the MariaDB Corporation MaxScale. It is free
# software: you can redistribute it and/or modify it under the terms of the
# GNU General Public License as published by the Free Software Foundation,
# version 2.
@ -12,7 +12,7 @@
# this program; if not, write to the Free Software Foundation, Inc., 51
# Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
#
# Copyright SkySQL Ab 2013
# Copyright MariaDB Corporation Ab 2013
#
# Revision History
# Date Who Description

View File

@ -0,0 +1,23 @@
if(BUILD_TESTS)
file(GLOB FULLCORE_SRC *.c)
add_library(fullcore STATIC ${FULLCORE_SRC})
target_link_libraries(fullcore log_manager utils pthread ${EMBEDDED_LIB} ssl aio rt crypt dl crypto inih z m stdc++)
endif()
add_executable(maxscale atomic.c buffer.c spinlock.c gateway.c
gw_utils.c utils.c dcb.c load_utils.c session.c service.c server.c
poll.c config.c users.c hashtable.c dbusers.c thread.c gwbitmask.c
monitor.c adminusers.c secrets.c filter.c modutil.c hint.c housekeeper.c)
target_link_libraries(maxscale ${EMBEDDED_LIB} log_manager utils ssl aio pthread crypt dl crypto inih z rt m stdc++)
install(TARGETS maxscale DESTINATION bin)
add_executable(maxkeys maxkeys.c secrets.c utils.c)
target_link_libraries(maxkeys log_manager utils pthread crypt crypto)
install(TARGETS maxkeys DESTINATION bin)
add_executable(maxpasswd maxpasswd.c secrets.c utils.c)
target_link_libraries(maxpasswd log_manager utils pthread crypt crypto)
install(TARGETS maxpasswd DESTINATION bin)
if(BUILD_TESTS)
add_subdirectory(test)
endif()

View File

@ -1,4 +1,4 @@
# This file is distributed as part of the SkySQL Gateway. It is free
# This file is distributed as part of the MariaDB Corporation MaxScale. It is free
# software: you can redistribute it and/or modify it under the terms of the
# GNU General Public License as published by the Free Software Foundation,
# version 2.
@ -12,7 +12,7 @@
# this program; if not, write to the Free Software Foundation, Inc., 51
# Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
#
# Copyright SkySQL Ab 2013
# Copyright MariaDB Corporation Ab 2013
#
# Revision History
# Date Who Description
@ -47,7 +47,7 @@ CC=cc
CFLAGS=-c -I/usr/include -I../include -I../modules/include -I../inih \
$(MYSQL_HEADERS) \
-I$(LOGPATH) -I$(UTILSPATH) \
-Wall -g
-Wall -pedantic -g
LDFLAGS=-rdynamic -L$(LOGPATH) \
-Wl,-rpath,$(DEST)/lib \

View File

@ -1,5 +1,5 @@
/*
* This file is distributed as part of the SkySQL Gateway. It is free
* This file is distributed as part of the MariaDB Corporation MaxScale. It is free
* software: you can redistribute it and/or modify it under the terms of the
* GNU General Public License as published by the Free Software Foundation,
* version 2.
@ -13,7 +13,7 @@
* this program; if not, write to the Free Software Foundation, Inc., 51
* Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Copyright SkySQL Ab 2013
* Copyright MariaDB Corporation Ab 2013-2014
*/
#include <stdio.h>
#include <stdlib.h>

View File

@ -1,5 +1,5 @@
/*
* This file is distributed as part of the SkySQL Gateway. It is free
* This file is distributed as part of the MariaDB Corporation MaxScale. It is free
* software: you can redistribute it and/or modify it under the terms of the
* GNU General Public License as published by the Free Software Foundation,
* version 2.
@ -13,7 +13,7 @@
* this program; if not, write to the Free Software Foundation, Inc., 51
* Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Copyright SkySQL Ab 2013
* Copyright MariaDB Corporation Ab 2013-2014
*/
/**

View File

@ -65,20 +65,20 @@ gwbuf_alloc(unsigned int size)
GWBUF *rval;
SHARED_BUF *sbuf;
// Allocate the buffer header
/* Allocate the buffer header */
if ((rval = (GWBUF *)malloc(sizeof(GWBUF))) == NULL)
{
return NULL;
}
// Allocate the shared data buffer
/* Allocate the shared data buffer */
if ((sbuf = (SHARED_BUF *)malloc(sizeof(SHARED_BUF))) == NULL)
{
free(rval);
return NULL;
}
// Allocate the space for the actual data
/* Allocate the space for the actual data */
if ((sbuf->data = (unsigned char *)malloc(size)) == NULL)
{
free(rval);
@ -87,7 +87,7 @@ SHARED_BUF *sbuf;
}
spinlock_init(&rval->gwbuf_lock);
rval->start = sbuf->data;
rval->end = rval->start + size;
rval->end = (void *)((char *)rval->start+size);
sbuf->refcount = 1;
rval->sbuf = sbuf;
rval->next = NULL;
@ -197,8 +197,8 @@ GWBUF *gwbuf_clone_portion(
atomic_add(&buf->sbuf->refcount, 1);
clonebuf->sbuf = buf->sbuf;
clonebuf->gwbuf_type = buf->gwbuf_type; /*< clone info bits too */
clonebuf->start = (void *)((char*)buf->start)+start_offset;
clonebuf->end = (void *)((char *)clonebuf->start)+length;
clonebuf->start = (void *)((char*)buf->start+start_offset);
clonebuf->end = (void *)((char *)clonebuf->start+length);
clonebuf->gwbuf_type = buf->gwbuf_type; /*< clone the type for now */
clonebuf->properties = NULL;
clonebuf->hint = NULL;
@ -277,8 +277,6 @@ return_clonebuf:
GWBUF *
gwbuf_append(GWBUF *head, GWBUF *tail)
{
GWBUF *ptr = head;
if (!head)
return tail;
CHK_GWBUF(head);
@ -311,7 +309,7 @@ GWBUF *rval = head;
CHK_GWBUF(head);
GWBUF_CONSUME(head, length);
CHK_GWBUF(head);
CHK_GWBUF(head);
if (GWBUF_EMPTY(head))
{
@ -370,11 +368,36 @@ gwbuf_trim(GWBUF *buf, unsigned int n_bytes)
gwbuf_consume(buf, GWBUF_LENGTH(buf));
return NULL;
}
buf->end -= n_bytes;
buf->end = (void *)((char *)buf->end - n_bytes);
return buf;
}
/**
* Trim bytes from the end of a GWBUF structure that may be the first
* in a list. If the buffer has n_bytes or less then it will be freed and
* the next buffer in the list will be returned, or if none, NULL.
*
* @param head The buffer to trim
* @param n_bytes The number of bytes to trim off
* @return The buffer chain or NULL if buffer chain now empty
*/
GWBUF *
gwbuf_rtrim(GWBUF *head, unsigned int n_bytes)
{
GWBUF *rval = head;
CHK_GWBUF(head);
GWBUF_RTRIM(head, n_bytes);
CHK_GWBUF(head);
if (GWBUF_EMPTY(head))
{
rval = head->next;
gwbuf_free(head);
}
return rval;
}
/**
* Set given type to all buffers on the list.
* *

View File

@ -1,5 +1,5 @@
/*
* This file is distributed as part of the SkySQL Gateway. It is free
* This file is distributed as part of the MariaDB Corporation MaxScale. It is free
* software: you can redistribute it and/or modify it under the terms of the
* GNU General Public License as published by the Free Software Foundation,
* version 2.
@ -13,7 +13,7 @@
* this program; if not, write to the Free Software Foundation, Inc., 51
* Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Copyright SkySQL Ab 2013
* Copyright MariaDB Corporation Ab 2013-2014
*/
/**
@ -131,7 +131,7 @@ CONFIG_PARAMETER *param, *p1;
ptr->element = NULL;
cntxt->next = ptr;
}
/* Check to see if the paramter already exists for the section */
/* Check to see if the parameter already exists for the section */
p1 = ptr->parameters;
while (p1)
{

View File

@ -1,5 +1,5 @@
/*
* This file is distributed as part of the SkySQL Gateway. It is free
* This file is distributed as part of the MariaDB Corporation MaxScale. It is free
* software: you can redistribute it and/or modify it under the terms of the
* GNU General Public License as published by the Free Software Foundation,
* version 2.
@ -13,7 +13,7 @@
* this program; if not, write to the Free Software Foundation, Inc., 51
* Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Copyright SkySQL Ab 2013
* Copyright MariaDB Corporation Ab 2013-2014
*/
/**

View File

@ -1,5 +1,5 @@
/*
* This file is distributed as part of the SkySQL Gateway. It is free
* This file is distributed as part of the MariaDB Corporation MaxScale. It is free
* software: you can redistribute it and/or modify it under the terms of the
* GNU General Public License as published by the Free Software Foundation,
* version 2.
@ -13,7 +13,7 @@
* this program; if not, write to the Free Software Foundation, Inc., 51
* Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Copyright SkySQL Ab 2013
* Copyright MariaDB Corporation Ab 2013-2014
*/
/**
@ -32,7 +32,7 @@
* 12/06/13 Mark Riddoch Initial implementation
* 21/06/13 Massimiliano Pinto free_dcb is used
* 25/06/13 Massimiliano Pinto Added checks to session and router_session
* 28/06/13 Mark Riddoch Changed the free mechanism ti
* 28/06/13 Mark Riddoch Changed the free mechanism to
* introduce a zombie state for the
* dcb
* 02/07/2013 Massimiliano Pinto Addition of delayqlock, delayq and
@ -73,7 +73,7 @@
extern int lm_enabled_logfiles_bitmask;
static DCB *allDCBs = NULL; /* Diagnotics need a list of DCBs */
static DCB *allDCBs = NULL; /* Diagnostics need a list of DCBs */
static DCB *zombies = NULL;
static SPINLOCK dcbspin = SPINLOCK_INIT;
static SPINLOCK zombiespin = SPINLOCK_INIT;
@ -88,6 +88,7 @@ static DCB* dcb_get_next (DCB* dcb);
static int dcb_null_write(DCB *dcb, GWBUF *buf);
static int dcb_null_close(DCB *dcb);
static int dcb_null_auth(DCB *dcb, SERVER *server, SESSION *session, GWBUF *buf);
static int dcb_isvalid_nolock(DCB *dcb);
/**
* Return the pointer to the lsit of zombie DCB's
@ -123,12 +124,6 @@ DCB *rval;
rval->dcb_errhandle_called = false;
#endif
rval->dcb_role = role;
#if 1
simple_mutex_init(&rval->dcb_write_lock, "DCB write mutex");
simple_mutex_init(&rval->dcb_read_lock, "DCB read mutex");
rval->dcb_write_active = false;
rval->dcb_read_active = false;
#endif
spinlock_init(&rval->dcb_initlock);
spinlock_init(&rval->writeqlock);
spinlock_init(&rval->delayqlock);
@ -141,6 +136,13 @@ DCB *rval;
rval->polloutbusy = 0;
rval->writecheck = 0;
rval->fd = -1;
rval->evq.next = NULL;
rval->evq.prev = NULL;
rval->evq.pending_events = 0;
rval->evq.processing = 0;
spinlock_init(&rval->evq.eventqlock);
memset(&rval->stats, 0, sizeof(DCBSTATS)); // Zero the statistics
rval->state = DCB_STATE_ALLOC;
bitmask_init(&rval->memdata.bitmask);
@ -218,43 +220,11 @@ dcb_add_to_zombieslist(DCB *dcb)
spinlock_release(&zombiespin);
return;
}
#if 1
/*<
* Add closing dcb to the top of the list.
*/
dcb->memdata.next = zombies;
zombies = dcb;
#else
if (zombies == NULL) {
zombies = dcb;
} else {
DCB *ptr = zombies;
while (ptr->memdata.next)
{
ss_info_dassert(
ptr->memdata.next->state == DCB_STATE_ZOMBIE,
"Next zombie is not in DCB_STATE_ZOMBIE state");
ss_info_dassert(
ptr != dcb,
"Attempt to add DCB to zombies list although it "
"is already there.");
if (ptr == dcb)
{
LOGIF(LE, (skygw_log_write_flush(
LOGFILE_ERROR,
"Error : Attempt to add DCB to zombies "
"list when it is already in the list")));
break;
}
ptr = ptr->memdata.next;
}
if (ptr != dcb) {
ptr->memdata.next = dcb;
}
}
#endif
/*<
* Set state which indicates that it has been added to zombies
* list.
@ -389,8 +359,6 @@ DCB_CALLBACK *cb;
spinlock_release(&dcb->cb_lock);
bitmask_free(&dcb->memdata.bitmask);
simple_mutex_done(&dcb->dcb_read_lock);
simple_mutex_done(&dcb->dcb_write_lock);
free(dcb);
}
@ -404,15 +372,10 @@ DCB_CALLBACK *cb;
* the memdata.bitmask then the DCB is no longer able to be
* referenced and it can be finally removed.
*
* The excluded DCB allows a thread to exclude a DCB from zombie processing.
* It is used when a thread calls dcb_process_zombies when there is
* a DCB that the caller knows it will continue processing with.
*
* @param threadid The thread ID of the caller
* @param excluded The DCB the thread currently uses, NULL or valid DCB.
*/
DCB *
dcb_process_zombies(int threadid, DCB *excluded)
dcb_process_zombies(int threadid)
{
DCB *ptr, *lptr;
DCB* dcb_list = NULL;
@ -446,9 +409,10 @@ bool succp = false;
CHK_DCB(ptr);
/*
* Skip processing of the excluded DCB
* Skip processing of DCB's that are
* in the event queue waiting to be processed.
*/
if (ptr == excluded)
if (ptr->evq.next || ptr->evq.prev)
{
lptr = ptr;
ptr = ptr->memdata.next;
@ -522,7 +486,6 @@ bool succp = false;
/*<
* Close file descriptor and move to clean-up phase.
*/
ss_dassert(excluded != dcb);
rc = close(dcb->fd);
if (rc < 0) {
@ -1255,7 +1218,7 @@ printDCB(DCB *dcb)
static void
spin_reporter(void *dcb, char *desc, int value)
{
dcb_printf((DCB *)dcb, "\t\t%-35s %d\n", desc, value);
dcb_printf((DCB *)dcb, "\t\t%-40s %d\n", desc, value);
}
@ -1316,10 +1279,6 @@ DCB *dcb;
dcb_printf(pdcb, "\t\tNo. of Writes: %d\n", dcb->stats.n_writes);
dcb_printf(pdcb, "\t\tNo. of Buffered Writes: %d\n", dcb->stats.n_buffered);
dcb_printf(pdcb, "\t\tNo. of Accepts: %d\n", dcb->stats.n_accepts);
dcb_printf(pdcb, "\t\tNo. of busy polls: %d\n", dcb->stats.n_busypolls);
dcb_printf(pdcb, "\t\tNo. of read rechecks: %d\n", dcb->stats.n_readrechecks);
dcb_printf(pdcb, "\t\tNo. of busy write polls: %d\n", dcb->stats.n_busywrpolls);
dcb_printf(pdcb, "\t\tNo. of write rechecks: %d\n", dcb->stats.n_writerechecks);
dcb_printf(pdcb, "\t\tNo. of High Water Events: %d\n", dcb->stats.n_high_water);
dcb_printf(pdcb, "\t\tNo. of Low Water Events: %d\n", dcb->stats.n_low_water);
if (dcb->flags & DCBF_CLONE)
@ -1427,10 +1386,6 @@ dprintDCB(DCB *pdcb, DCB *dcb)
dcb->stats.n_buffered);
dcb_printf(pdcb, "\t\tNo. of Accepts: %d\n",
dcb->stats.n_accepts);
dcb_printf(pdcb, "\t\tNo. of busy polls: %d\n", dcb->stats.n_busypolls);
dcb_printf(pdcb, "\t\tNo. of read rechecks: %d\n", dcb->stats.n_readrechecks);
dcb_printf(pdcb, "\t\tNo. of busy write polls: %d\n", dcb->stats.n_busywrpolls);
dcb_printf(pdcb, "\t\tNo. of write rechecks: %d\n", dcb->stats.n_writerechecks);
dcb_printf(pdcb, "\t\tNo. of High Water Events: %d\n",
dcb->stats.n_high_water);
dcb_printf(pdcb, "\t\tNo. of Low Water Events: %d\n",
@ -1939,113 +1894,40 @@ dcb_isvalid(DCB *dcb)
DCB *ptr;
int rval = 0;
if (dcb)
{
spinlock_acquire(&dcbspin);
rval = dcb_isvalid_nolock(dcb);
spinlock_release(&dcbspin);
}
return rval;
}
/**
* Check the passed DCB to ensure it is in the list of allDCBS.
* Requires that the DCB list is already locked before call.
*
* @param dcb The DCB to check
* @return 1 if the DCB is in the list, otherwise 0
*/
static int
dcb_isvalid_nolock(DCB *dcb)
{
DCB *ptr;
int rval = 0;
if (dcb)
{
ptr = allDCBs;
while (ptr)
while (ptr && ptr != dcb)
{
if (ptr == dcb)
{
rval = 1;
break;
}
ptr = ptr->next;
}
spinlock_release(&dcbspin);
return rval;
}
/**
* Called by the EPOLLIN event. Take care of calling the protocol
* read entry point and managing multiple threads competing for the DCB
* without blocking those threads.
*
* This mechanism does away with the need for a mutex on the EPOLLIN event
* and instead implements a queuing mechanism in which nested events are
* queued on the DCB such that when the thread processing the first event
* returns it will read the queued event and process it. This allows the
* thread that would otherwise have to wait to process the nested event
* to return immediately and and process other events.
*
* @param dcb The DCB that has data available
* @param thread_id The ID of the calling thread
* @param nozombies If non-zero then do not do zombie processing
*/
void
dcb_pollin(DCB *dcb, int thread_id, int nozombies)
{
spinlock_acquire(&dcb->pollinlock);
if (dcb->pollinbusy == 0)
{
dcb->pollinbusy = 1;
do {
if (dcb->readcheck)
{
dcb->stats.n_readrechecks++;
if (!nozombies)
dcb_process_zombies(thread_id, dcb);
}
dcb->readcheck = 0;
spinlock_release(&dcb->pollinlock);
dcb->func.read(dcb);
spinlock_acquire(&dcb->pollinlock);
} while (dcb->readcheck);
dcb->pollinbusy = 0;
}
else
{
dcb->stats.n_busypolls++;
dcb->readcheck = 1;
}
spinlock_release(&dcb->pollinlock);
}
/**
* Called by the EPOLLOUT event. Take care of calling the protocol
* write_ready entry point and managing multiple threads competing for the DCB
* without blocking those threads.
*
* This mechanism does away with the need for a mutex on the EPOLLOUT event
* and instead implements a queuing mechanism in which nested events are
* queued on the DCB such that when the thread processing the first event
* returns it will read the queued event and process it. This allows the
* thread that would otherwise have to wait to process the nested event
* to return immediately and and process other events.
*
* @param dcb The DCB thats available for writes
* @param thread_id The ID of the calling thread
* @param nozombies If non-zero then do not do zombie processing
*/
void
dcb_pollout(DCB *dcb, int thread_id, int nozombies)
{
spinlock_acquire(&dcb->polloutlock);
if (dcb->polloutbusy == 0)
{
dcb->polloutbusy = 1;
do {
if (dcb->writecheck)
{
if (!nozombies)
dcb_process_zombies(thread_id, dcb);
dcb->stats.n_writerechecks++;
}
dcb->writecheck = 0;
spinlock_release(&dcb->polloutlock);
dcb->func.write_ready(dcb);
spinlock_acquire(&dcb->polloutlock);
} while (dcb->writecheck);
dcb->polloutbusy = 0;
}
else
{
dcb->stats.n_busywrpolls++;
dcb->writecheck = 1;
}
spinlock_release(&dcb->polloutlock);
rval = (ptr == dcb);
}
return rval;
}
@ -2058,33 +1940,11 @@ dcb_pollout(DCB *dcb, int thread_id, int nozombies)
static DCB *
dcb_get_next (DCB* dcb)
{
DCB* p;
spinlock_acquire(&dcbspin);
p = allDCBs;
if (dcb == NULL || p == NULL)
{
dcb = p;
}
else
{
while (p != NULL && dcb != p)
{
p = p->next;
}
if (p != NULL)
{
dcb = p->next;
}
else
{
dcb = NULL;
}
if (dcb) {
dcb = dcb_isvalid_nolock(dcb) ? dcb->next : NULL;
}
else dcb = allDCBs;
spinlock_release(&dcbspin);
return dcb;

View File

@ -1,5 +1,5 @@
/*
* This file is distributed as part of MaxScale from SkySQL. It is free
* This file is distributed as part of MaxScale from MariaDB Corporation. It is free
* software: you can redistribute it and/or modify it under the terms of the
* GNU General Public License as published by the Free Software Foundation,
* version 2.
@ -13,7 +13,7 @@
* this program; if not, write to the Free Software Foundation, Inc., 51
* Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Copyright SkySQL Ab 2014
* Copyright MariaDB Corporation Ab 2014
*/
/**

View File

@ -1,5 +1,5 @@
/*
* This file is distributed as part of the SkySQL Gateway. It is free
* This file is distributed as part of the MariaDB Corporation MaxScale. It is free
* software: you can redistribute it and/or modify it under the terms of the
* GNU General Public License as published by the Free Software Foundation,
* version 2.
@ -13,7 +13,7 @@
* this program; if not, write to the Free Software Foundation, Inc., 51
* Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Copyright SkySQL Ab 2013
* Copyright MariaDB Corporation Ab 2013-2014
*
*/
@ -88,7 +88,7 @@ extern int lm_enabled_logfiles_bitmask;
* is not fixed here and will be updated elsewhere.
*/
static char* server_options[] = {
"SkySQL Gateway",
"MariaDB Corporation MaxScale",
"--no-defaults",
"--datadir=",
"--language=",
@ -387,7 +387,7 @@ static bool file_write_header(
*t = time(NULL);
*tm = *localtime(t);
header_buf1 = "\n\nSkySQL MaxScale " MAXSCALE_VERSION "\t";
header_buf1 = "\n\nMariaDB Corporation MaxScale " MAXSCALE_VERSION "\t";
header_buf2 = strdup(asctime(tm));
if (header_buf2 == NULL) {
@ -1539,7 +1539,7 @@ int main(int argc, char **argv)
}
LOGIF(LM, (skygw_log_write(
LOGFILE_MESSAGE,
"SkySQL MaxScale %s (C) SkySQL Ab 2013,2014",
"MariaDB Corporation MaxScale %s (C) MariaDB Corporation Ab 2013-2014",
MAXSCALE_VERSION)));
LOGIF(LM, (skygw_log_write(
LOGFILE_MESSAGE,
@ -1646,6 +1646,7 @@ void
shutdown_server()
{
poll_shutdown();
hkshutdown();
log_flush_shutdown();
}

View File

@ -1,5 +1,5 @@
/*
* This file is distributed as part of the SkySQL Gateway. It is free
* This file is distributed as part of the MariaDB Corporation MaxScale. It is free
* software: you can redistribute it and/or modify it under the terms of the
* GNU General Public License as published by the Free Software Foundation,
* version 2.
@ -13,7 +13,7 @@
* this program; if not, write to the Free Software Foundation, Inc., 51
* Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Copyright SkySQL Ab 2013
* Copyright MariaDB Corporation Ab 2013-2014
*
*/
@ -34,6 +34,7 @@
* 25-09-2013 Massimiliano Pinto setipaddress uses getaddrinfo
* 06-02-2014 Mark Riddoch Added parse_bindconfig
* 10-02-2014 Massimiliano Pinto Added return code to setipaddress
* 02-09-2014 Martin Brampton Replace C++ comment with C comment
*
*@endverbatim
*/
@ -148,7 +149,7 @@ void gw_daemonize(void) {
}
if (pid != 0) {
// exit from main
/* exit from main */
exit(0);
}

View File

@ -1,5 +1,5 @@
/*
* This file is distributed as part of the SkySQL Gateway. It is free
* This file is distributed as part of the MariaDB Corporation MaxScale. It is free
* software: you can redistribute it and/or modify it under the terms of the
* GNU General Public License as published by the Free Software Foundation,
* version 2.
@ -13,7 +13,7 @@
* this program; if not, write to the Free Software Foundation, Inc., 51
* Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Copyright SkySQL Ab 2013
* Copyright MariaDB Corporation Ab 2013-2014
*/
#include <stdlib.h>
#include <string.h>

View File

@ -1,5 +1,5 @@
/*
* This file is distributed as part of the SkySQL Gateway. It is free
* This file is distributed as part of the MariaDB Corporation MaxScale. It is free
* software: you can redistribute it and/or modify it under the terms of the
* GNU General Public License as published by the Free Software Foundation,
* version 2.
@ -13,7 +13,7 @@
* this program; if not, write to the Free Software Foundation, Inc., 51
* Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Copyright SkySQL Ab 2013
* Copyright MariaDB Corporation Ab 2013-2014
*/
#include <stdio.h>
#include <stdlib.h>

View File

@ -13,7 +13,7 @@
* this program; if not, write to the Free Software Foundation, Inc., 51
* Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Copyright SkySQL Ab 2014
* Copyright MariaDB Corporation Ab 2014
*/
#include <stdio.h>
#include <stdlib.h>

View File

@ -1,5 +1,5 @@
/*
* This file is distributed as part of the SkySQL Gateway. It is free
* This file is distributed as part of the MariaDB Corporation MaxScale. It is free
* software: you can redistribute it and/or modify it under the terms of the
* GNU General Public License as published by the Free Software Foundation,
* version 2.
@ -13,7 +13,7 @@
* this program; if not, write to the Free Software Foundation, Inc., 51
* Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Copyright SkySQL Ab 2014
* Copyright MariaDB Corporation Ab 2014
*/
#include <stdlib.h>
#include <string.h>
@ -42,6 +42,8 @@ static HKTASK *tasks = NULL;
*/
static SPINLOCK tasklock = SPINLOCK_INIT;
static int do_shutdown = 0;
static void hkthread(void *);
/**
@ -172,6 +174,8 @@ void *taskdata;
for (;;)
{
if (do_shutdown)
return;
thread_millisleep(1000);
now = time(0);
spinlock_acquire(&tasklock);
@ -194,3 +198,13 @@ void *taskdata;
spinlock_release(&tasklock);
}
}
/**
* Called to shutdown the housekeeper
*
*/
void
hkshutdown()
{
do_shutdown = 1;
}

View File

@ -1,5 +1,5 @@
/*
* This file is distributed as part of the SkySQL Gateway. It is free
* This file is distributed as part of the MariaDB Corporation MaxScale. It is free
* software: you can redistribute it and/or modify it under the terms of the
* GNU General Public License as published by the Free Software Foundation,
* version 2.
@ -13,7 +13,7 @@
* this program; if not, write to the Free Software Foundation, Inc., 51
* Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Copyright SkySQL Ab 2013
* Copyright MariaDB Corporation Ab 2013-2014
*/
/**

View File

@ -1,5 +1,5 @@
/*
* This file is distributed as part of the SkySQL Gateway. It is free
* This file is distributed as part of the MariaDB Corporation MaxScale. It is free
* software: you can redistribute it and/or modify it under the terms of the
* GNU General Public License as published by the Free Software Foundation,
* version 2.
@ -13,7 +13,7 @@
* this program; if not, write to the Free Software Foundation, Inc., 51
* Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Copyright SkySQL Ab 2013
* Copyright MariaDB Corporation Ab 2013-2014
*/
/**

View File

@ -1,5 +1,5 @@
/*
* This file is distributed as part of the SkySQL Gateway. It is free
* This file is distributed as part of the MariaDB Corporation MaxScale. It is free
* software: you can redistribute it and/or modify it under the terms of the
* GNU General Public License as published by the Free Software Foundation,
* version 2.
@ -13,7 +13,7 @@
* this program; if not, write to the Free Software Foundation, Inc., 51
* Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Copyright SkySQL Ab 2013
* Copyright MariaDB Corporation Ab 2013-2014
*/
/**

View File

@ -1,5 +1,5 @@
/*
* This file is distributed as part of MaxScale from SkySQL. It is free
* This file is distributed as part of MaxScale from MariaDB Corporation. It is free
* software: you can redistribute it and/or modify it under the terms of the
* GNU General Public License as published by the Free Software Foundation,
* version 2.
@ -13,7 +13,7 @@
* this program; if not, write to the Free Software Foundation, Inc., 51
* Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Copyright SkySQL Ab 2014
* Copyright MariaDB Corporation Ab 2014
*/
/**
@ -76,7 +76,7 @@ unsigned char *ptr;
ptr = GWBUF_DATA(buf);
*length = *ptr++;
*length += (*ptr++ << 8);
*length += (*ptr++ << 8);
*length += (*ptr++ << 16);
ptr += 2; // Skip sequence id and COM_QUERY byte
*length = *length - 1;
*sql = (char *)ptr;
@ -111,7 +111,7 @@ unsigned char *ptr;
ptr = GWBUF_DATA(buf);
*residual = *ptr++;
*residual += (*ptr++ << 8);
*residual += (*ptr++ << 8);
*residual += (*ptr++ << 16);
ptr += 2; // Skip sequence id and COM_QUERY byte
*residual = *residual - 1;
*length = GWBUF_LENGTH(buf) - 5;
@ -143,7 +143,7 @@ GWBUF *addition;
ptr = GWBUF_DATA(orig);
length = *ptr++;
length += (*ptr++ << 8);
length += (*ptr++ << 8);
length += (*ptr++ << 16);
ptr += 2; // Skip sequence id and COM_QUERY byte
newlength = strlen(sql);
@ -178,11 +178,11 @@ GWBUF *addition;
*
* @param buf GWBUF buffer including the query
*
* @return Plaint text query if the packet type is COM_QUERY. Otherwise return
* @return Plain text query if the packet type is COM_QUERY. Otherwise return
* a string including the packet type.
*/
char* modutil_get_query(
GWBUF* buf)
char *
modutil_get_query(GWBUF *buf)
{
uint8_t* packet;
mysql_server_cmd_t packet_type;

View File

@ -1,5 +1,5 @@
/*
* This file is distributed as part of the SkySQL Gateway. It is free
* This file is distributed as part of the MariaDB Corporation MaxScale. It is free
* software: you can redistribute it and/or modify it under the terms of the
* GNU General Public License as published by the Free Software Foundation,
* version 2.
@ -13,7 +13,7 @@
* this program; if not, write to the Free Software Foundation, Inc., 51
* Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Copyright SkySQL Ab 2013
* Copyright MariaDB Corporation Ab 2013-2014
*/
/**
@ -234,17 +234,17 @@ MONITOR *ptr;
spinlock_acquire(&monLock);
ptr = allMonitors;
dcb_printf(dcb, "+----------------------+---------------------\n");
dcb_printf(dcb, "| %-20s | Status\n", "Monitor");
dcb_printf(dcb, "+----------------------+---------------------\n");
dcb_printf(dcb, "---------------------+---------------------\n");
dcb_printf(dcb, "%-20s | Status\n", "Monitor");
dcb_printf(dcb, "---------------------+---------------------\n");
while (ptr)
{
dcb_printf(dcb, "| %-20s | %s\n", ptr->name,
dcb_printf(dcb, "%-20s | %s\n", ptr->name,
ptr->state & MONITOR_STATE_RUNNING
? "Running" : "Stopped");
ptr = ptr->next;
}
dcb_printf(dcb, "+----------------------+---------------------\n");
dcb_printf(dcb, "---------------------+---------------------\n");
spinlock_release(&monLock);
}

View File

@ -1,5 +1,5 @@
/*
* This file is distributed as part of the SkySQL Gateway. It is free
* This file is distributed as part of the MariaDB Corporation MaxScale. It is free
* software: you can redistribute it and/or modify it under the terms of the
* GNU General Public License as published by the Free Software Foundation,
* version 2.
@ -13,7 +13,7 @@
* this program; if not, write to the Free Software Foundation, Inc., 51
* Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Copyright SkySQL Ab 2013
* Copyright MariaDB Corporation Ab 2013-2014
*/
#include <stdio.h>
#include <string.h>
@ -30,6 +30,13 @@
#include <gw.h>
#include <config.h>
#include <housekeeper.h>
#include <mysql.h>
#define PROFILE_POLL 1
#if PROFILE_POLL
#include <rdtsc.h>
#endif
extern int lm_enabled_logfiles_bitmask;
@ -47,6 +54,11 @@ extern int lm_enabled_logfiles_bitmask;
* etc.
* 23/09/14 Mark Riddoch Make use of RDHUP conditional to allow CentOS 5
* builds.
* 24/09/14 Mark Riddoch Introduction of the event queue for processing the
* incoming events rather than processing them immediately
* in the loop after the epoll_wait. This allows for better
* thread utilisaiton and fairer scheduling of the event
* processing.
*
* @endverbatim
*/
@ -65,6 +77,11 @@ static GWBITMASK poll_mask;
static simple_mutex_t epoll_wait_mutex; /*< serializes calls to epoll_wait */
#endif
static int n_waiting = 0; /*< No. of threads in epoll_wait */
static int process_pollq(int thread_id);
DCB *eventq = NULL;
SPINLOCK pollqlock = SPINLOCK_INIT;
/**
* Thread load average, this is the average number of descriptors in each
@ -125,6 +142,8 @@ static struct {
int n_nothreads; /*< Number of times no threads are polling */
int n_fds[MAXNFDS]; /*< Number of wakeups with particular
n_fds value */
int evq_length; /*< Event queue length */
int evq_max; /*< Maximum event queue length */
} pollStats;
/**
@ -338,6 +357,17 @@ return_rc:
* deschedule a process if a timeout is included, but will not do this if a 0 timeout
* value is given. this improves performance when the gateway is under heavy load.
*
* In order to provide a fairer means of sharign the threads between the different
* DCB's the poll mechanism has been decoupled from the processing of the events.
* The events are now recieved via the epoll_wait call, a queue of DCB's that have
* events pending is maintained and as new events arrive the DCB is added to the end
* of this queue. If an eent arrives for a DCB alreayd in the queue, then the event
* bits are added to the DCB but the DCB mantains the same point in the queue unless
* the original events are already being processed. If they are being processed then
* the DCB is moved to the back of the queue, this means that a DCB that is receiving
* events at a high rate will not block the execution of events for other DCB's and
* should result in a fairer polling strategy.
*
* @param arg The thread ID passed as a void * to satisfy the threading package
*/
void
@ -346,8 +376,6 @@ poll_waitevents(void *arg)
struct epoll_event events[MAX_EVENTS];
int i, nfds;
int thread_id = (int)arg;
bool no_op = false;
static bool process_zombies_only = false; /*< flag for all threads */
DCB *zombies = NULL;
/** Add this thread to the bitmask of running polling threads */
@ -362,20 +390,19 @@ DCB *zombies = NULL;
while (1)
{
/* Process of the queue of waiting requests */
while (do_shutdown == 0 && process_pollq(thread_id))
{
if (thread_data)
thread_data[thread_id].state = THREAD_ZPROCESSING;
zombies = dcb_process_zombies(thread_id);
}
atomic_add(&n_waiting, 1);
#if BLOCKINGPOLL
nfds = epoll_wait(epoll_fd, events, MAX_EVENTS, -1);
atomic_add(&n_waiting, -1);
#else /* BLOCKINGPOLL */
if (!no_op) {
LOGIF(LD, (skygw_log_write(
LOGFILE_DEBUG,
"%lu [poll_waitevents] MaxScale thread "
"%d > epoll_wait <",
pthread_self(),
thread_id)));
no_op = TRUE;
}
#if MUTEX_EPOLL
simple_mutex_lock(&epoll_wait_mutex, TRUE);
#endif
@ -396,32 +423,19 @@ DCB *zombies = NULL;
pthread_self(),
nfds,
eno)));
no_op = FALSE;
}
else if (nfds == 0)
/*
* If there are no new descriptors from the non-blocking call
* and nothing to proces on the event queue then for do a
* blocking call to epoll_wait.
*/
else if (nfds == 0 && process_pollq(thread_id) == 0)
{
atomic_add(&n_waiting, -1);
if (process_zombies_only) {
#if MUTEX_EPOLL
simple_mutex_unlock(&epoll_wait_mutex);
#endif
goto process_zombies;
} else {
nfds = epoll_wait(epoll_fd,
atomic_add(&n_waiting, 1);
nfds = epoll_wait(epoll_fd,
events,
MAX_EVENTS,
EPOLL_TIMEOUT);
/*<
* When there are zombies to be cleaned up but
* no client requests, allow all threads to call
* dcb_process_zombies without having to wait
* for the timeout.
*/
if (nfds == 0 && dcb_get_zombies() != NULL)
{
process_zombies_only = true;
}
}
}
else
{
@ -457,228 +471,64 @@ DCB *zombies = NULL;
atomic_add(&load_samples, 1);
atomic_add(&load_nfds, nfds);
/*
* Process every DCB that has a new event and add
* it to the poll queue.
* If the DCB is currently beign processed then we
* or in the new eent bits to the pending event bits
* and leave it in the queue.
* If the DCB was not already in the queue then it was
* idle and is added to the queue to process after
* setting the event bits.
*/
for (i = 0; i < nfds; i++)
{
DCB *dcb = (DCB *)events[i].data.ptr;
__uint32_t ev = events[i].events;
CHK_DCB(dcb);
if (thread_data)
spinlock_acquire(&pollqlock);
if (DCB_POLL_BUSY(dcb))
{
thread_data[thread_id].cur_dcb = dcb;
thread_data[thread_id].event = ev;
dcb->evq.pending_events |= ev;
}
#if defined(SS_DEBUG)
if (dcb_fake_write_ev[dcb->fd] != 0) {
LOGIF(LD, (skygw_log_write(
LOGFILE_DEBUG,
"%lu [poll_waitevents] "
"Added fake events %d to ev %d.",
pthread_self(),
dcb_fake_write_ev[dcb->fd],
ev)));
ev |= dcb_fake_write_ev[dcb->fd];
dcb_fake_write_ev[dcb->fd] = 0;
}
#endif
ss_debug(spinlock_acquire(&dcb->dcb_initlock);)
ss_dassert(dcb->state != DCB_STATE_ALLOC);
ss_dassert(dcb->state != DCB_STATE_DISCONNECTED);
ss_dassert(dcb->state != DCB_STATE_FREED);
ss_debug(spinlock_release(&dcb->dcb_initlock);)
LOGIF(LD, (skygw_log_write(
LOGFILE_DEBUG,
"%lu [poll_waitevents] event %d dcb %p "
"role %s",
pthread_self(),
ev,
dcb,
STRDCBROLE(dcb->dcb_role))));
if (ev & EPOLLOUT)
else
{
int eno = 0;
eno = gw_getsockerrno(dcb->fd);
if (eno == 0) {
#if MUTEX_BLOCK
simple_mutex_lock(
&dcb->dcb_write_lock,
true);
ss_info_dassert(
!dcb->dcb_write_active,
"Write already active");
dcb->dcb_write_active = TRUE;
atomic_add(
&pollStats.n_write,
1);
dcb->func.write_ready(dcb);
dcb->dcb_write_active = FALSE;
simple_mutex_unlock(
&dcb->dcb_write_lock);
#else
atomic_add(&pollStats.n_write,
1);
dcb_pollout(dcb, thread_id, nfds);
#endif
} else {
LOGIF(LD, (skygw_log_write(
LOGFILE_DEBUG,
"%lu [poll_waitevents] "
"EPOLLOUT due %d, %s. "
"dcb %p, fd %i",
pthread_self(),
eno,
strerror(eno),
dcb,
dcb->fd)));
}
}
if (ev & EPOLLIN)
{
#if MUTEX_BLOCK
simple_mutex_lock(&dcb->dcb_read_lock,
true);
ss_info_dassert(!dcb->dcb_read_active,
"Read already active");
dcb->dcb_read_active = TRUE;
#endif
if (dcb->state == DCB_STATE_LISTENING)
dcb->evq.pending_events = ev;
if (eventq)
{
LOGIF(LD, (skygw_log_write(
LOGFILE_DEBUG,
"%lu [poll_waitevents] "
"Accept in fd %d",
pthread_self(),
dcb->fd)));
atomic_add(
&pollStats.n_accept, 1);
dcb->func.accept(dcb);
}
else
{
LOGIF(LD, (skygw_log_write(
LOGFILE_DEBUG,
"%lu [poll_waitevents] "
"Read in dcb %p fd %d",
pthread_self(),
dcb,
dcb->fd)));
atomic_add(&pollStats.n_read, 1);
#if MUTEX_BLOCK
dcb->func.read(dcb);
#else
dcb_pollin(dcb, thread_id, nfds);
#endif
}
#if MUTEX_BLOCK
dcb->dcb_read_active = FALSE;
simple_mutex_unlock(
&dcb->dcb_read_lock);
#endif
}
if (ev & EPOLLERR)
{
int eno = gw_getsockerrno(dcb->fd);
#if defined(SS_DEBUG)
if (eno == 0) {
eno = dcb_fake_write_errno[dcb->fd];
LOGIF(LD, (skygw_log_write(
LOGFILE_DEBUG,
"%lu [poll_waitevents] "
"Added fake errno %d. "
"%s",
pthread_self(),
eno,
strerror(eno))));
}
dcb_fake_write_errno[dcb->fd] = 0;
#endif
if (eno != 0) {
LOGIF(LD, (skygw_log_write(
LOGFILE_DEBUG,
"%lu [poll_waitevents] "
"EPOLLERR due %d, %s.",
pthread_self(),
eno,
strerror(eno))));
}
atomic_add(&pollStats.n_error, 1);
dcb->func.error(dcb);
}
if (ev & EPOLLHUP)
{
int eno = 0;
eno = gw_getsockerrno(dcb->fd);
LOGIF(LD, (skygw_log_write(
LOGFILE_DEBUG,
"%lu [poll_waitevents] "
"EPOLLHUP on dcb %p, fd %d. "
"Errno %d, %s.",
pthread_self(),
dcb,
dcb->fd,
eno,
strerror(eno))));
atomic_add(&pollStats.n_hup, 1);
spinlock_acquire(&dcb->dcb_initlock);
if ((dcb->flags & DCBF_HUNG) == 0)
{
dcb->flags |= DCBF_HUNG;
spinlock_release(&dcb->dcb_initlock);
dcb->func.hangup(dcb);
dcb->evq.prev = eventq->evq.prev;
eventq->evq.prev->evq.next = dcb;
eventq->evq.prev = dcb;
dcb->evq.next = eventq;
}
else
spinlock_release(&dcb->dcb_initlock);
}
#ifdef EPOLLRDHUP
if (ev & EPOLLRDHUP)
{
int eno = 0;
eno = gw_getsockerrno(dcb->fd);
LOGIF(LD, (skygw_log_write(
LOGFILE_DEBUG,
"%lu [poll_waitevents] "
"EPOLLRDHUP on dcb %p, fd %d. "
"Errno %d, %s.",
pthread_self(),
dcb,
dcb->fd,
eno,
strerror(eno))));
atomic_add(&pollStats.n_hup, 1);
spinlock_acquire(&dcb->dcb_initlock);
if ((dcb->flags & DCBF_HUNG) == 0)
{
dcb->flags |= DCBF_HUNG;
spinlock_release(&dcb->dcb_initlock);
dcb->func.hangup(dcb);
eventq = dcb;
dcb->evq.prev = dcb;
dcb->evq.next = dcb;
}
pollStats.evq_length++;
if (pollStats.evq_length > pollStats.evq_max)
{
pollStats.evq_max = pollStats.evq_length;
}
else
spinlock_release(&dcb->dcb_initlock);
}
#endif
} /*< for */
no_op = FALSE;
} /*< if (nfds > 0) */
process_zombies:
if (thread_data)
{
thread_data[thread_id].state = THREAD_ZPROCESSING;
spinlock_release(&pollqlock);
}
}
zombies = dcb_process_zombies(thread_id, NULL);
if (zombies == NULL) {
process_zombies_only = false;
}
/*
* If there was nothing to process then process the zombie queue
*/
if (process_pollq(thread_id) == 0)
{
if (thread_data)
{
thread_data[thread_id].state = THREAD_ZPROCESSING;
}
zombies = dcb_process_zombies(thread_id);
}
if (do_shutdown)
{
/*<
@ -701,6 +551,320 @@ process_zombies:
} /*< while(1) */
}
/**
* Process of the queue of DCB's that have outstanding events
*
* The first event on the queue will be chosen to be executed by this thread,
* all other events will be left on the queue and may be picked up by other
* threads. When the processing is complete the thread will take the DCB off the
* queue if there are no pending events that have arrived since the thread started
* to process the DCB. If there are pending events the DCB will be moved to the
* back of the queue so that other DCB's will have a share of the threads to
* execute events for them.
*
* @param thread_id The thread ID of the calling thread
* @return 0 if no DCB's have been processed
*/
static int
process_pollq(int thread_id)
{
DCB *dcb;
int found = 0;
uint32_t ev;
spinlock_acquire(&pollqlock);
if (eventq == NULL)
{
/* Nothing to process */
spinlock_release(&pollqlock);
return 0;
}
dcb = eventq;
if (dcb->evq.next == dcb->evq.prev && dcb->evq.processing == 0)
{
found = 1;
dcb->evq.processing = 1;
}
else if (dcb->evq.next == dcb->evq.prev)
{
/* Only item in queue is being processed */
spinlock_release(&pollqlock);
return 0;
}
else
{
do {
dcb = dcb->evq.next;
} while (dcb != eventq && dcb->evq.processing == 1);
if (dcb->evq.processing == 0)
{
/* Found DCB to process */
dcb->evq.processing = 1;
found = 1;
}
}
if (found)
{
ev = dcb->evq.pending_events;
dcb->evq.pending_events = 0;
}
spinlock_release(&pollqlock);
if (found == 0)
return 0;
CHK_DCB(dcb);
if (thread_data)
{
thread_data[thread_id].state = THREAD_PROCESSING;
thread_data[thread_id].cur_dcb = dcb;
thread_data[thread_id].event = ev;
}
#if defined(SS_DEBUG)
if (dcb_fake_write_ev[dcb->fd] != 0) {
LOGIF(LD, (skygw_log_write(
LOGFILE_DEBUG,
"%lu [poll_waitevents] "
"Added fake events %d to ev %d.",
pthread_self(),
dcb_fake_write_ev[dcb->fd],
ev)));
ev |= dcb_fake_write_ev[dcb->fd];
dcb_fake_write_ev[dcb->fd] = 0;
}
#endif
ss_debug(spinlock_acquire(&dcb->dcb_initlock);)
ss_dassert(dcb->state != DCB_STATE_ALLOC);
ss_dassert(dcb->state != DCB_STATE_DISCONNECTED);
ss_dassert(dcb->state != DCB_STATE_FREED);
ss_debug(spinlock_release(&dcb->dcb_initlock);)
LOGIF(LD, (skygw_log_write(
LOGFILE_DEBUG,
"%lu [poll_waitevents] event %d dcb %p "
"role %s",
pthread_self(),
ev,
dcb,
STRDCBROLE(dcb->dcb_role))));
if (ev & EPOLLOUT)
{
int eno = 0;
eno = gw_getsockerrno(dcb->fd);
if (eno == 0) {
#if MUTEX_BLOCK
simple_mutex_lock(
&dcb->dcb_write_lock,
true);
ss_info_dassert(
!dcb->dcb_write_active,
"Write already active");
dcb->dcb_write_active = TRUE;
atomic_add(
&pollStats.n_write,
1);
dcb->func.write_ready(dcb);
dcb->dcb_write_active = FALSE;
simple_mutex_unlock(
&dcb->dcb_write_lock);
#else
atomic_add(&pollStats.n_write,
1);
dcb->func.write_ready(dcb);
#endif
} else {
LOGIF(LD, (skygw_log_write(
LOGFILE_DEBUG,
"%lu [poll_waitevents] "
"EPOLLOUT due %d, %s. "
"dcb %p, fd %i",
pthread_self(),
eno,
strerror(eno),
dcb,
dcb->fd)));
}
}
if (ev & EPOLLIN)
{
#if MUTEX_BLOCK
simple_mutex_lock(&dcb->dcb_read_lock,
true);
ss_info_dassert(!dcb->dcb_read_active,
"Read already active");
dcb->dcb_read_active = TRUE;
#endif
if (dcb->state == DCB_STATE_LISTENING)
{
LOGIF(LD, (skygw_log_write(
LOGFILE_DEBUG,
"%lu [poll_waitevents] "
"Accept in fd %d",
pthread_self(),
dcb->fd)));
atomic_add(
&pollStats.n_accept, 1);
dcb->func.accept(dcb);
}
else
{
LOGIF(LD, (skygw_log_write(
LOGFILE_DEBUG,
"%lu [poll_waitevents] "
"Read in dcb %p fd %d",
pthread_self(),
dcb,
dcb->fd)));
atomic_add(&pollStats.n_read, 1);
dcb->func.read(dcb);
}
#if MUTEX_BLOCK
dcb->dcb_read_active = FALSE;
simple_mutex_unlock(
&dcb->dcb_read_lock);
#endif
}
if (ev & EPOLLERR)
{
int eno = gw_getsockerrno(dcb->fd);
#if defined(SS_DEBUG)
if (eno == 0) {
eno = dcb_fake_write_errno[dcb->fd];
LOGIF(LD, (skygw_log_write(
LOGFILE_DEBUG,
"%lu [poll_waitevents] "
"Added fake errno %d. "
"%s",
pthread_self(),
eno,
strerror(eno))));
}
dcb_fake_write_errno[dcb->fd] = 0;
#endif
if (eno != 0) {
LOGIF(LD, (skygw_log_write(
LOGFILE_DEBUG,
"%lu [poll_waitevents] "
"EPOLLERR due %d, %s.",
pthread_self(),
eno,
strerror(eno))));
}
atomic_add(&pollStats.n_error, 1);
dcb->func.error(dcb);
}
if (ev & EPOLLHUP)
{
int eno = 0;
eno = gw_getsockerrno(dcb->fd);
LOGIF(LD, (skygw_log_write(
LOGFILE_DEBUG,
"%lu [poll_waitevents] "
"EPOLLHUP on dcb %p, fd %d. "
"Errno %d, %s.",
pthread_self(),
dcb,
dcb->fd,
eno,
strerror(eno))));
atomic_add(&pollStats.n_hup, 1);
spinlock_acquire(&dcb->dcb_initlock);
if ((dcb->flags & DCBF_HUNG) == 0)
{
dcb->flags |= DCBF_HUNG;
spinlock_release(&dcb->dcb_initlock);
dcb->func.hangup(dcb);
}
else
spinlock_release(&dcb->dcb_initlock);
}
#ifdef EPOLLRDHUP
if (ev & EPOLLRDHUP)
{
int eno = 0;
eno = gw_getsockerrno(dcb->fd);
LOGIF(LD, (skygw_log_write(
LOGFILE_DEBUG,
"%lu [poll_waitevents] "
"EPOLLRDHUP on dcb %p, fd %d. "
"Errno %d, %s.",
pthread_self(),
dcb,
dcb->fd,
eno,
strerror(eno))));
atomic_add(&pollStats.n_hup, 1);
spinlock_acquire(&dcb->dcb_initlock);
if ((dcb->flags & DCBF_HUNG) == 0)
{
dcb->flags |= DCBF_HUNG;
spinlock_release(&dcb->dcb_initlock);
dcb->func.hangup(dcb);
}
else
spinlock_release(&dcb->dcb_initlock);
}
#endif
spinlock_acquire(&pollqlock);
if (dcb->evq.pending_events == 0)
{
/* No pending events so remove from the queue */
if (dcb->evq.prev != dcb)
{
dcb->evq.prev->evq.next = dcb->evq.next;
dcb->evq.next->evq.prev = dcb->evq.prev;
if (eventq == dcb)
eventq = dcb->evq.next;
}
else
{
eventq = NULL;
}
dcb->evq.next = NULL;
dcb->evq.prev = NULL;
pollStats.evq_length--;
}
else
{
/*
* We have a pending event, move to the end of the queue
* if there are any other DCB's in the queue.
*
* If we are the first item on the queue this is easy, we
* just bump the eventq pointer.
*/
if (dcb->evq.prev != dcb)
{
if (eventq == dcb)
eventq = dcb->evq.next;
else
{
dcb->evq.prev->evq.next = dcb->evq.next;
dcb->evq.next->evq.prev = dcb->evq.prev;
dcb->evq.prev = eventq->evq.prev;
dcb->evq.next = eventq;
eventq->evq.prev = dcb;
dcb->evq.prev->evq.next = dcb;
}
}
}
dcb->evq.processing = 0;
spinlock_release(&pollqlock);
return 1;
}
/**
* Shutdown the polling loop
*/
@ -721,6 +885,20 @@ poll_bitmask()
return &poll_mask;
}
/**
* Display an entry from the spinlock statistics data
*
* @param dcb The DCB to print to
* @param desc Description of the statistic
* @param value The statistic value
*/
static void
spin_reporter(void *dcb, char *desc, int value)
{
dcb_printf((DCB *)dcb, "\t%-40s %d\n", desc, value);
}
/**
* Debug routine to print the polling statistics
*
@ -745,6 +923,10 @@ int i;
pollStats.n_accept);
dcb_printf(dcb, "Number of times no threads polling: %d\n",
pollStats.n_nothreads);
dcb_printf(dcb, "Current event queue length: %d\n",
pollStats.evq_length);
dcb_printf(dcb, "Maximum event queue length: %d\n",
pollStats.evq_max);
dcb_printf(dcb, "No of poll completions with descriptors\n");
dcb_printf(dcb, "\tNo. of descriptors\tNo. of poll completions.\n");
@ -754,6 +936,11 @@ int i;
}
dcb_printf(dcb, "\t>= %d\t\t\t%d\n", MAXNFDS,
pollStats.n_fds[MAXNFDS-1]);
#if SPINLOCK_PROFILE
dcb_printf(dcb, "Event queue lock statistics:\n");
spinlock_stats(&pollqlock, spin_reporter, dcb);
#endif
}
/**

View File

@ -1,5 +1,5 @@
/*
* This file is distributed as part of the SkySQL Gateway. It is free
* This file is distributed as part of the MariaDB Corporation MaxScale. It is free
* software: you can redistribute it and/or modify it under the terms of the
* GNU General Public License as published by the Free Software Foundation,
* version 2.
@ -13,7 +13,7 @@
* this program; if not, write to the Free Software Foundation, Inc., 51
* Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Copyright SkySQL Ab 2013
* Copyright MariaDB Corporation Ab 2013-2014
*/
#include <secrets.h>
@ -74,16 +74,29 @@ int len;
snprintf(secret_file, 255, "%s/etc/.secrets", home);
/* Try to access secrets file */
if (access(secret_file, R_OK) == -1) {
if (access(secret_file, R_OK) == -1)
{
int eno = errno;
errno = 0;
LOGIF(LE, (skygw_log_write_flush(
LOGFILE_ERROR,
"Error : access for secrets file "
"[%s] failed. Error %d, %s.",
secret_file,
eno,
strerror(eno))));
if (eno == ENOENT)
{
LOGIF(LM, (skygw_log_write(
LOGFILE_MESSAGE,
"Encrypted password file %s can't be accessed "
"(%s). Password encryption is not used.",
secret_file,
strerror(eno))));
}
else
{
LOGIF(LE, (skygw_log_write_flush(
LOGFILE_ERROR,
"Error : access for secrets file "
"[%s] failed. Error %d, %s.",
secret_file,
eno,
strerror(eno))));
}
return NULL;
}

View File

@ -1,5 +1,5 @@
/*
* This file is distributed as part of the SkySQL Gateway. It is free
* This file is distributed as part of the MariaDB Corporation MaxScale. It is free
* software: you can redistribute it and/or modify it under the terms of the
* GNU General Public License as published by the Free Software Foundation,
* version 2.
@ -13,7 +13,7 @@
* this program; if not, write to the Free Software Foundation, Inc., 51
* Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Copyright SkySQL Ab 2013
* Copyright MariaDB Corporation Ab 2013-2014
*/
/**

View File

@ -1,5 +1,5 @@
/*
* This file is distributed as part of the SkySQL Gateway. It is free
* This file is distributed as part of the MariaDB Corporation MaxScale. It is free
* software: you can redistribute it and/or modify it under the terms of the
* GNU General Public License as published by the Free Software Foundation,
* version 2.
@ -13,7 +13,7 @@
* this program; if not, write to the Free Software Foundation, Inc., 51
* Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Copyright SkySQL Ab 2013
* Copyright MariaDB Corporation Ab 2013-2014
*/
/**
@ -91,10 +91,10 @@ static void service_add_qualified_param(
* @param servname The service name
* @param router Name of the router module this service uses
*
* @return The newly created service or NULL if an error occured
* @return The newly created service or NULL if an error occurred
*/
SERVICE *
service_alloc(char *servname, char *router)
service_alloc(const char *servname, const char *router)
{
SERVICE *service;
@ -152,7 +152,7 @@ SERVICE *service;
/**
* Check to see if a service pointer is valid
*
* @param service The poitner to check
* @param service The pointer to check
* @return 1 if the service is in the list of all services
*/
int

View File

@ -1,5 +1,5 @@
/*
* This file is distributed as part of the SkySQL Gateway. It is free
* This file is distributed as part of the MariaDB Corporation MaxScale. It is free
* software: you can redistribute it and/or modify it under the terms of the
* GNU General Public License as published by the Free Software Foundation,
* version 2.
@ -13,7 +13,7 @@
* this program; if not, write to the Free Software Foundation, Inc., 51
* Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Copyright SkySQL Ab 2013
* Copyright MariaDB Corporation Ab 2013-2014
*/
/**

View File

@ -1,5 +1,5 @@
/*
* This file is distributed as part of the SkySQL Gateway. It is free
* This file is distributed as part of the MariaDB Corporation MaxScale. It is free
* software: you can redistribute it and/or modify it under the terms of the
* GNU General Public License as published by the Free Software Foundation,
* version 2.
@ -13,11 +13,11 @@
* this program; if not, write to the Free Software Foundation, Inc., 51
* Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Copyright SkySQL Ab 2013
* Copyright MariaDB Corporation Ab 2013-2014
*/
/**
* @file spinlock.c - Spinlock operations for the SkySQL Gateway
* @file spinlock.c - Spinlock operations for the MariaDB Corporation MaxScale
*
* @verbatim
* Revision History
@ -30,6 +30,7 @@
#include <spinlock.h>
#include <atomic.h>
#include <time.h>
/**
* Initialise a spinlock.
@ -39,13 +40,13 @@
void
spinlock_init(SPINLOCK *lock)
{
lock->lock = 0;
lock->lock = 0;
#if SPINLOCK_PROFILE
lock->spins = 0;
lock->acquired = 0;
lock->waiting = 0;
lock->max_waiting = 0;
lock->contended = 0;
lock->spins = 0;
lock->acquired = 0;
lock->waiting = 0;
lock->max_waiting = 0;
lock->contended = 0;
#endif
}
@ -62,24 +63,30 @@ int spins = 0;
atomic_add(&(lock->waiting), 1);
#endif
while (atomic_add(&(lock->lock), 1) != 0)
{
atomic_add(&(lock->lock), -1);
#ifdef __GNUC__
while (__sync_lock_test_and_set(&(lock->lock), 1))
while (lock->lock) {
#else
while (atomic_add(&(lock->lock), 1) != 0)
{
atomic_add(&(lock->lock), -1);
#endif
#if SPINLOCK_PROFILE
atomic_add(&(lock->spins), 1);
spins++;
#endif
}
#if SPINLOCK_PROFILE
if (spins)
{
lock->contended++;
if (lock->maxspins < spins)
lock->maxspins = spins;
}
lock->acquired++;
lock->owner = THREAD_SHELF();
atomic_add(&(lock->waiting), -1);
if (spins)
{
lock->contended++;
if (lock->maxspins < spins)
lock->maxspins = spins;
}
lock->acquired++;
lock->owner = THREAD_SHELF();
atomic_add(&(lock->waiting), -1);
#endif
}
@ -92,16 +99,20 @@ int spins = 0;
int
spinlock_acquire_nowait(SPINLOCK *lock)
{
if (atomic_add(&(lock->lock), 1) != 0)
{
atomic_add(&(lock->lock), -1);
return FALSE;
}
#if SPINLOCK_PROFILE
lock->acquired++;
lock->owner = THREAD_SHELF();
#ifdef __GNUC__
if (__sync_lock_test_and_set(&(lock->lock), 1)) return FALSE;
#else
if (atomic_add(&(lock->lock), 1) != 0)
{
atomic_add(&(lock->lock), -1);
return FALSE;
}
#endif
return TRUE;
#if SPINLOCK_PROFILE
lock->acquired++;
lock->owner = THREAD_SHELF();
#endif
return TRUE;
}
/*
@ -112,11 +123,16 @@ spinlock_acquire_nowait(SPINLOCK *lock)
void
spinlock_release(SPINLOCK *lock)
{
#if SPINLOCK_PROFILE
if (lock->waiting > lock->max_waiting)
lock->max_waiting = lock->waiting;
#if SPINLOCK_PROFILE
if (lock->waiting > lock->max_waiting)
lock->max_waiting = lock->waiting;
#endif
#ifdef __GNUC__
__sync_synchronize(); /* Memory barrier. */
lock->lock = 0;
#else
atomic_add(&(lock->lock), -1);
#endif
atomic_add(&(lock->lock), -1);
}
/**

View File

@ -0,0 +1,13 @@
add_executable(test_hash testhash.c)
add_executable(test_spinlock testspinlock.c)
add_executable(test_filter testfilter.c)
add_executable(test_adminusers testadminusers.c)
target_link_libraries(test_hash fullcore)
target_link_libraries(test_spinlock fullcore)
target_link_libraries(test_filter fullcore)
target_link_libraries(test_adminusers fullcore)
add_test(TestHash test_hash)
add_test(TestSpinlock test_spinlock)
add_test(TestFilter test_filter)
add_test(TestAdminUsers test_adminusers)

View File

@ -18,10 +18,11 @@ LDFLAGS=-rdynamic -L$(LOGPATH) -L$(EMBEDDED_LIB) \
-Wl,-rpath,$(LOGPATH) -Wl,-rpath,$(UTILSPATH) \
-Wl,-rpath,$(EMBEDDED_LIB)
LIBS= -lz -lm -lcrypt -lcrypto -ldl -laio -lrt -pthread -llog_manager \
-L../../inih/extra -linih -lssl -lstdc++ -lmysqld
LIBS= -L$(EMBEDDED_LIB) -lmysqld \
-lz -lm -lcrypt -lcrypto -ldl -laio -lrt -pthread -llog_manager \
-L../../inih/extra -linih -lssl -lstdc++
TESTS=testhash testspinlock testfilter testadminusers
TESTS=testhash testspinlock testbuffer testmodutil testpoll testservice testdcb testfilter testadminusers
cleantests:
- $(DEL) *.o
@ -47,6 +48,39 @@ testspinlock: testspinlock.c
-I$(ROOT_PATH)/utils \
testspinlock.c ../spinlock.o ../atomic.o ../thread.o -o testspinlock
testmodutil: testmodutil.c
$(CC) $(CFLAGS) \
-I$(ROOT_PATH)/server/include \
-I$(ROOT_PATH)/utils \
testmodutil.c ../modutil.o ../buffer.o ../atomic.o -o testmodutil
testbuffer: testbuffer.c
$(CC) $(CFLAGS) \
-I$(ROOT_PATH)/server/include \
-I$(ROOT_PATH)/utils \
testbuffer.c ../buffer.o ../atomic.o -o testbuffer
testpoll: testpoll.c
$(CC) $(CFLAGS) $(LDFLAGS) \
-I$(ROOT_PATH)/server/include \
-I$(ROOT_PATH)/utils \
-I$(ROOT_PATH)/log_manager \
testpoll.c libcore.a $(UTILSPATH)/skygw_utils.o $(LIBS) -o testpoll
testservice: testservice.c
$(CC) $(CFLAGS) $(LDFLAGS) \
-I$(ROOT_PATH)/server/include \
-I$(ROOT_PATH)/utils \
-I$(ROOT_PATH)/log_manager \
testservice.c libcore.a $(UTILSPATH)/skygw_utils.o $(LIBS) -o testservice
testdcb: testdcb.c
$(CC) $(CFLAGS) $(LDFLAGS) \
-I$(ROOT_PATH)/server/include \
-I$(ROOT_PATH)/utils \
-I$(ROOT_PATH)/log_manager \
testdcb.c libcore.a $(UTILSPATH)/skygw_utils.o $(LIBS) -o testdcb
testfilter: testfilter.c libcore.a
$(CC) $(CFLAGS) $(LDFLAGS) \
-I$(ROOT_PATH)/server/include \

View File

@ -1,5 +1,5 @@
/*
* This file is distributed as part of the SkySQL Gateway. It is free
* This file is distributed as part of the MariaDB Corporation MaxScale. It is free
* software: you can redistribute it and/or modify it under the terms of the
* GNU General Public License as published by the Free Software Foundation,
* version 2.
@ -13,7 +13,7 @@
* this program; if not, write to the Free Software Foundation, Inc., 51
* Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Copyright SkySQL Ab 2013
* Copyright MariaDB Corporation Ab 2013-2014
*/
/**

View File

@ -13,7 +13,7 @@
* this program; if not, write to the Free Software Foundation, Inc., 51
* Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Copyright SkySQL Ab 2014
* Copyright MariaDB Corporation Ab 2014
*/
/**

View File

@ -13,7 +13,7 @@
* this program; if not, write to the Free Software Foundation, Inc., 51
* Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Copyright SkySQL Ab 2014
* Copyright MariaDB Corporation Ab 2014
*/
/**

View File

@ -13,7 +13,7 @@
* this program; if not, write to the Free Software Foundation, Inc., 51
* Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Copyright SkySQL Ab 2014
* Copyright MariaDB Corporation Ab 2014
*/
/**

View File

@ -13,7 +13,7 @@
* this program; if not, write to the Free Software Foundation, Inc., 51
* Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Copyright SkySQL Ab 2014
* Copyright MariaDB Corporation Ab 2014
*/
/**
@ -105,12 +105,16 @@ test2()
{
SPINLOCK lck;
void *handle;
struct timespec sleeptime;
sleeptime.tv_sec = 10;
sleeptime.tv_nsec = 0;
acquire_time = 0;
spinlock_init(&lck);
spinlock_acquire(&lck);
handle = thread_start(test2_helper, (void *)&lck);
sleep(10);
nanosleep(&sleeptime, NULL);
spinlock_release(&lck);
thread_wait(handle);
@ -122,12 +126,118 @@ void *handle;
return 0;
}
main(int argc, char **argv)
/**
* test3 spinlock_acquire tests process bound threads
*
* Check that spinlock correctly blocks all other threads whilst the spinlock
* is held.
*
* Start multiple threads that obtain spinlock and run process bound
*/
#define THREADS 5
#define ITERATIONS 50000
#define PROCESS_LOOP 10000
#define SECONDS 15
#define NANOTIME 100000
static int times_run, failures;
static volatile int active;
static int threadrun[THREADS];
static int nowait[THREADS];
static SPINLOCK lck;
static void
test3_helper(void *data)
{
// SPINLOCK *lck = (SPINLOCK *)data;
int i;
int n = *(int *)data;
struct timespec sleeptime;
time_t rawtime;
sleeptime.tv_sec = 0;
sleeptime.tv_nsec = 1;
while (1) {
if (spinlock_acquire_nowait(&lck)) {
nowait[n]++;
}
else {
spinlock_acquire(&lck);
}
if (times_run++ > ITERATIONS) {
break;
}
threadrun[n]++;
/*
if (99 == (times_run % 100)) {
time ( &rawtime );
fprintf(stderr, "%s Done %d iterations of test, in thread %d.\n", asctime (localtime ( &rawtime )), times_run, n);
}
*/
if (0 != active) {
fprintf(stderr, "spinlock: test 3 failed with active non-zero after lock obtained.\n");
failures++;
}
else {
active = 1;
for (i=0; i<PROCESS_LOOP; i++);
}
active = 0;
spinlock_release(&lck);
for (i=0; i<(4*PROCESS_LOOP); i++);
// nanosleep(&sleeptime, NULL);
}
spinlock_release(&lck);
}
static int
test3()
{
// SPINLOCK lck;
void *handle[THREADS];
int i;
int tnum[THREADS];
time_t rawtime;
struct timespec sleeptime;
sleeptime.tv_sec = 20;
sleeptime.tv_nsec = NANOTIME;
times_run = 0;
active = 0;
failures = 0;
spinlock_init(&lck);
time ( &rawtime );
fprintf(stderr, "%s Starting %d threads.\n", asctime (localtime ( &rawtime )), THREADS);
for (i = 0; i<THREADS; i++) {
threadrun[i] = 0;
tnum[i] = i;
handle[i] = thread_start(test3_helper, &tnum[i]);
}
for (i = 0; i<THREADS; i++) {
fprintf(stderr, "spinlock_test 3 thread %d ran %d times, no wait %d times before waits.\n", i, threadrun[i], nowait[i]);
}
for (i = 0; i<THREADS; i++) {
time ( &rawtime );
fprintf(stderr, "%s spinlock_test 3 finished sleeps, about to wait for thread %d.\n", asctime (localtime ( &rawtime )), i);
thread_wait(handle[i]);
}
for (i = 0; i<THREADS; i++) {
fprintf(stderr, "spinlock_test 3 thread %d ran %d times, no wait %d times.\n", i, threadrun[i], nowait[i]);
}
time ( &rawtime );
fprintf(stderr, "%s spinlock_test 3 completed, %d failures.\n", asctime (localtime ( &rawtime )), failures);
return 0 == failures ? 0: 1;
}
int main(int argc, char **argv)
{
int result = 0;
result += test1();
result += test2();
result += test3();
exit(result);
}

View File

@ -1,5 +1,5 @@
/*
* This file is distributed as part of the SkySQL Gateway. It is free
* This file is distributed as part of the MariaDB Corporation MaxScale. It is free
* software: you can redistribute it and/or modify it under the terms of the
* GNU General Public License as published by the Free Software Foundation,
* version 2.
@ -13,7 +13,7 @@
* this program; if not, write to the Free Software Foundation, Inc., 51
* Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Copyright SkySQL Ab 2013
* Copyright MariaDB Corporation Ab 2013-2014
*/
#include <thread.h>
#include <pthread.h>

View File

@ -1,5 +1,5 @@
/*
* This file is distributed as part of the SkySQL Gateway. It is free
* This file is distributed as part of the MariaDB Corporation MaxScale. It is free
* software: you can redistribute it and/or modify it under the terms of the
* GNU General Public License as published by the Free Software Foundation,
* version 2.
@ -13,7 +13,7 @@
* this program; if not, write to the Free Software Foundation, Inc., 51
* Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Copyright SkySQL Ab 2013
* Copyright MariaDB Corporation Ab 2013-2014
*/
#include <stdio.h>
#include <stdlib.h>

View File

@ -1,5 +1,5 @@
/*
* This file is distributed as part of the SkySQL Gateway. It is free
* This file is distributed as part of the MariaDB Corporation MaxScale. It is free
* software: you can redistribute it and/or modify it under the terms of the
* GNU General Public License as published by the Free Software Foundation,
* version 2.
@ -13,7 +13,7 @@
* this program; if not, write to the Free Software Foundation, Inc., 51
* Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Copyright SkySQL Ab 2013
* Copyright MariaDB Corporation Ab 2013-2014
*
*/
@ -27,8 +27,9 @@
* 10-06-2013 Massimiliano Pinto Initial implementation
* 12-06-2013 Massimiliano Pinto Read function trought
* the gwbuff strategy
* 13-06-2013 Massimiliano Pinto Gateway local authentication
* 13-06-2013 Massimiliano Pinto MaxScale local authentication
* basics
* 02-09-2014 Martin Brampton Replaced C++ comments by C comments
*
* @endverbatim
*/
@ -44,19 +45,19 @@
extern int lm_enabled_logfiles_bitmask;
// used in the hex2bin function
/* used in the hex2bin function */
#define char_val(X) (X >= '0' && X <= '9' ? X-'0' :\
X >= 'A' && X <= 'Z' ? X-'A'+10 :\
X >= 'a' && X <= 'z' ? X-'a'+10 :\
'\177')
// used in the bin2hex function
/* used in the bin2hex function */
char hex_upper[] = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
char hex_lower[] = "0123456789abcdefghijklmnopqrstuvwxyz";
//////////////////////////////////////////
//backend read event triggered by EPOLLIN
//////////////////////////////////////////
/*****************************************
* backend read event triggered by EPOLLIN
*****************************************/
int setnonblocking(int fd) {
@ -91,17 +92,17 @@ char *gw_strend(register const char *s) {
return (char*) (s-1);
}
///////////////////////////////
// generate a random char
//////////////////////////////
/*****************************************
* generate a random char
*****************************************/
static char gw_randomchar() {
return (char)((rand() % 78) + 30);
}
/////////////////////////////////
// generate a random string
// output must be pre allocated
/////////////////////////////////
/*****************************************
* generate a random string
* output must be pre allocated
*****************************************/
int gw_generate_random_str(char *output, int len) {
int i;
@ -116,10 +117,10 @@ int gw_generate_random_str(char *output, int len) {
return 0;
}
/////////////////////////////////
// hex string to binary data
// output must be pre allocated
/////////////////////////////////
/*****************************************
* hex string to binary data
* output must be pre allocated
*****************************************/
int gw_hex2bin(uint8_t *out, const char *in, unsigned int len) {
const char *in_end= in + len;
@ -140,10 +141,10 @@ int gw_hex2bin(uint8_t *out, const char *in, unsigned int len) {
return 0;
}
/////////////////////////////////
// binary data to hex string
// output must be pre allocated
/////////////////////////////////
/*****************************************
* binary data to hex string
* output must be pre allocated
*****************************************/
char *gw_bin2hex(char *out, const uint8_t *in, unsigned int len) {
const uint8_t *in_end= in + len;
if (len == 0 || in == NULL) {
@ -159,12 +160,12 @@ char *gw_bin2hex(char *out, const uint8_t *in, unsigned int len) {
return out;
}
///////////////////////////////////////////////////////
// fill a preallocated buffer with XOR(str1, str2)
// XOR between 2 equal len strings
// note that XOR(str1, XOR(str1 CONCAT str2)) == str2
// and that XOR(str1, str2) == XOR(str2, str1)
///////////////////////////////////////////////////////
/****************************************************
* fill a preallocated buffer with XOR(str1, str2)
* XOR between 2 equal len strings
* note that XOR(str1, XOR(str1 CONCAT str2)) == str2
* and that XOR(str1, str2) == XOR(str2, str1)
*****************************************************/
void gw_str_xor(uint8_t *output, const uint8_t *input1, const uint8_t *input2, unsigned int len) {
const uint8_t *input1_end = NULL;
input1_end = input1 + len;
@ -175,10 +176,10 @@ void gw_str_xor(uint8_t *output, const uint8_t *input1, const uint8_t *input2, u
*output = '\0';
}
/////////////////////////////////////////////////////////////
// fill a 20 bytes preallocated with SHA1 digest (160 bits)
// for one input on in_len bytes
/////////////////////////////////////////////////////////////
/**********************************************************
* fill a 20 bytes preallocated with SHA1 digest (160 bits)
* for one input on in_len bytes
**********************************************************/
void gw_sha1_str(const uint8_t *in, int in_len, uint8_t *out) {
unsigned char hash[SHA_DIGEST_LENGTH];
@ -186,10 +187,10 @@ void gw_sha1_str(const uint8_t *in, int in_len, uint8_t *out) {
memcpy(out, hash, SHA_DIGEST_LENGTH);
}
/////////////////////////////////////////////////////////////
// fill 20 bytes preallocated with SHA1 digest (160 bits)
// for two inputs, in_len and in2_len bytes
/////////////////////////////////////////////////////////////
/********************************************************
* fill 20 bytes preallocated with SHA1 digest (160 bits)
* for two inputs, in_len and in2_len bytes
********************************************************/
void gw_sha1_2_str(const uint8_t *in, int in_len, const uint8_t *in2, int in2_len, uint8_t *out) {
SHA_CTX context;
unsigned char hash[SHA_DIGEST_LENGTH];

View File

@ -1,7 +1,7 @@
#ifndef _ADMINUSERS_H
#define _ADMINUSERS_H
/*
* This file is distributed as part of the SkySQL Gateway. It is free
* This file is distributed as part of the MariaDB Corporation MaxScale. It is free
* software: you can redistribute it and/or modify it under the terms of the
* GNU General Public License as published by the Free Software Foundation,
* version 2.
@ -15,7 +15,7 @@
* this program; if not, write to the Free Software Foundation, Inc., 51
* Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Copyright SkySQL Ab 2013
* Copyright MariaDB Corporation Ab 2013-2014
*/
/**

View File

@ -1,7 +1,7 @@
#ifndef _ATOMIC_H
#define _ATOMIC_H
/*
* This file is distributed as part of the SkySQL Gateway. It is free
* This file is distributed as part of the MariaDB Corporation MaxScale. It is free
* software: you can redistribute it and/or modify it under the terms of the
* GNU General Public License as published by the Free Software Foundation,
* version 2.
@ -15,7 +15,7 @@
* this program; if not, write to the Free Software Foundation, Inc., 51
* Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Copyright SkySQL Ab 2013
* Copyright MariaDB Corporation Ab 2013-2014
*/
/**

View File

@ -1,7 +1,7 @@
#ifndef _BUFFER_H
#define _BUFFER_H
/*
* This file is distributed as part of the SkySQL Gateway. It is free
* This file is distributed as part of the MariaDB Corporation MaxScale. It is free
* software: you can redistribute it and/or modify it under the terms of the
* GNU General Public License as published by the Free Software Foundation,
* version 2.
@ -15,7 +15,7 @@
* this program; if not, write to the Free Software Foundation, Inc., 51
* Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Copyright SkySQL Ab 2013
* Copyright MariaDB Corporation Ab 2013-2014
*/
/**
@ -40,6 +40,9 @@
* 16/07/2013 Massimiliano Pinto Added command type for the queue
* 10/07/2014 Mark Riddoch Addition of hints
* 15/07/2014 Mark Riddoch Added buffer properties
* 03/10/2014 Martin Brampton Pointer arithmetic standard conformity
* Add more buffer handling macros
* Add gwbuf_rtrim (handle chains)
*
* @endverbatim
*/
@ -47,6 +50,7 @@
#include <skygw_debug.h>
#include <hint.h>
#include <spinlock.h>
#include <stdint.h>
EXTERN_C_BLOCK_BEGIN
@ -146,19 +150,25 @@ typedef struct gwbuf {
/*<
* Macros to access the data in the buffers
*/
/*< First valid, uncomsumed byte in the buffer */
/*< First valid, unconsumed byte in the buffer */
#define GWBUF_DATA(b) ((b)->start)
/*< Number of bytes in the individual buffer */
#define GWBUF_LENGTH(b) ((b)->end - (b)->start)
#define GWBUF_LENGTH(b) ((char *)(b)->end - (char *)(b)->start)
/*< Return the byte at offset byte from the start of the unconsumed portion of the buffer */
#define GWBUF_DATA_CHAR(b, byte) (GWBUF_LENGTH(b) < ((byte)+1) ? -1 : *(((char *)(b)->start)+4))
/*< Check that the data in a buffer has the SQL marker*/
#define GWBUF_IS_SQL(b) (0x03 == GWBUF_DATA_CHAR(b,4))
/*< True if all bytes in the buffer have been consumed */
#define GWBUF_EMPTY(b) ((b)->start == (b)->end)
#define GWBUF_EMPTY(b) ((char *)(b)->start >= (char *)(b)->end)
/*< Consume a number of bytes in the buffer */
#define GWBUF_CONSUME(b, bytes) (b)->start += (bytes)
#define GWBUF_CONSUME(b, bytes) ((b)->start = bytes > ((char *)(b)->end - (char *)(b)->start) ? (b)->end : (void *)((char *)(b)->start + (bytes)));
#define GWBUF_RTRIM(b, bytes) (b)->end -= (bytes)
#define GWBUF_RTRIM(b, bytes) ((b)->end = bytes > ((char *)(b)->end - (char *)(b)->start) ? (b)->start : (void *)((char *)(b)->end - (bytes)));
#define GWBUF_TYPE(b) (b)->gwbuf_type
/*<
@ -170,6 +180,7 @@ extern GWBUF *gwbuf_clone(GWBUF *buf);
extern GWBUF *gwbuf_append(GWBUF *head, GWBUF *tail);
extern GWBUF *gwbuf_consume(GWBUF *head, unsigned int length);
extern GWBUF *gwbuf_trim(GWBUF *head, unsigned int length);
extern GWBUF *gwbuf_rtrim(GWBUF *head, unsigned int length);
extern unsigned int gwbuf_length(GWBUF *head);
extern GWBUF *gwbuf_clone_portion(GWBUF *head, size_t offset, size_t len);
extern GWBUF *gwbuf_clone_transform(GWBUF *head, gwbuf_type_t type);

View File

@ -1,7 +1,7 @@
#ifndef _CONFIG_H
#define _CONFIG_H
/*
* This file is distributed as part of the SkySQL Gateway. It is free
* This file is distributed as part of the MariaDB Corporation MaxScale. It is free
* software: you can redistribute it and/or modify it under the terms of the
* GNU General Public License as published by the Free Software Foundation,
* version 2.
@ -15,7 +15,7 @@
* this program; if not, write to the Free Software Foundation, Inc., 51
* Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Copyright SkySQL Ab 2013
* Copyright MariaDB Corporation Ab 2013-2014
*/
#include <skygw_utils.h>

View File

@ -1,7 +1,7 @@
#ifndef _DBUSERS_H
#define _DBUSERS_H
/*
* This file is distributed as part of the SkySQL Gateway. It is free
* This file is distributed as part of the MariaDB Corporation MaxScale. It is free
* software: you can redistribute it and/or modify it under the terms of the
* GNU General Public License as published by the Free Software Foundation,
* version 2.
@ -15,7 +15,7 @@
* this program; if not, write to the Free Software Foundation, Inc., 51
* Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Copyright SkySQL Ab 2013
* Copyright MariaDB Corporation Ab 2013-2014
*/
#include <service.h>

View File

@ -1,7 +1,7 @@
#ifndef _DCB_H
#define _DCB_H
/*
* This file is distributed as part of the SkySQL Gateway. It is free
* This file is distributed as part of the MariaDB Corporation MaxScale. It is free
* software: you can redistribute it and/or modify it under the terms of the
* GNU General Public License as published by the Free Software Foundation,
* version 2.
@ -15,7 +15,7 @@
* this program; if not, write to the Free Software Foundation, Inc., 51
* Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Copyright SkySQL Ab 2013
* Copyright MariaDB Corporation Ab 2013-2014
*/
#include <spinlock.h>
#include <buffer.h>
@ -53,7 +53,8 @@ struct service;
* 07/02/2014 Massimiliano Pinto Added ipv4 data struct into for dcb
* 07/05/2014 Mark Riddoch Addition of callback mechanism
* 08/05/2014 Mark Riddoch Addition of writeq high and low watermarks
* 27/08/2014 Mark Ridddoch Addition of write event queuing
* 27/08/2014 Mark Riddoch Addition of write event queuing
* 23/09/2014 Mark Riddoch New poll processing queue
*
* @endverbatim
*/
@ -65,7 +66,7 @@ struct dcb;
* The operations that can be performed on the descriptor
*
* read EPOLLIN handler for the socket
* write Gateway data write entry point
* write MaxScale data write entry point
* write_ready EPOLLOUT handler for the socket, indicates
* that the socket is ready to send more data
* error EPOLLERR handler for the socket
@ -73,7 +74,7 @@ struct dcb;
* accept Accept handler for listener socket only
* connect Create a connection to the specified server
* for the session pased in
* close Gateway close entry point for the socket
* close MaxScale close entry point for the socket
* listen Create a listener for the protocol
* auth Authentication entry point
* session Session handling entry point
@ -97,6 +98,14 @@ typedef struct gw_protocol {
int (*session)(struct dcb *, void *);
} GWPROTOCOL;
typedef struct {
struct dcb *next;
struct dcb *prev;
uint32_t pending_events;
int processing;
SPINLOCK eventqlock;
} DCBEVENTQ;
/**
* The GWPROTOCOL version data. The following should be updated whenever
* the GWPROTOCOL structure is changed. See the rules defined in modinfo.h
@ -114,10 +123,6 @@ typedef struct dcbstats {
int n_buffered; /*< Number of buffered writes */
int n_high_water; /*< Number of crosses of high water mark */
int n_low_water; /*< Number of crosses of low water mark */
int n_busypolls; /*< Number of read polls whiel reading */
int n_readrechecks; /*< Number of rechecks for reads */
int n_busywrpolls; /*< Number of write polls while writing */
int n_writerechecks;/*< Number of rechecks for writes */
} DCBSTATS;
/**
@ -204,12 +209,7 @@ typedef struct dcb {
#endif
dcb_role_t dcb_role;
SPINLOCK dcb_initlock;
#if 1
simple_mutex_t dcb_read_lock;
simple_mutex_t dcb_write_lock;
bool dcb_read_active;
bool dcb_write_active;
#endif
DCBEVENTQ evq; /**< The event queue for this DCB */
int fd; /**< The descriptor */
dcb_state_t state; /**< Current descriptor state */
int flags; /**< DCB flags */
@ -271,8 +271,8 @@ int fail_accept_errno;
#define DCB_BELOW_LOW_WATER(x) ((x)->low_water && (x)->writeqlen < (x)->low_water)
#define DCB_ABOVE_HIGH_WATER(x) ((x)->high_water && (x)->writeqlen > (x)->high_water)
void dcb_pollin(DCB *, int, int);
void dcb_pollout(DCB *, int, int);
#define DCB_POLL_BUSY(x) ((x)->evq.next != NULL)
DCB *dcb_get_zombies(void);
int gw_write(
#if defined(SS_DEBUG)
@ -289,7 +289,7 @@ DCB *dcb_clone(DCB *);
int dcb_read(DCB *, GWBUF **);
int dcb_drain_writeq(DCB *);
void dcb_close(DCB *);
DCB *dcb_process_zombies(int, DCB*); /* Process Zombies except the one behind the pointer */
DCB *dcb_process_zombies(int); /* Process Zombies except the one behind the pointer */
void printAllDCBs(); /* Debug to print all DCB in the system */
void printDCB(DCB *); /* Debug print routine */
void dprintAllDCBs(DCB *); /* Debug to print all DCB in the system */

View File

@ -1,7 +1,7 @@
#ifndef _FILTER_H
#define _FILTER_H
/*
* This file is distributed as part of the SkySQL Gateway. It is free
* This file is distributed as part of the MariaDB Corporation MaxScale. It is free
* software: you can redistribute it and/or modify it under the terms of the
* GNU General Public License as published by the Free Software Foundation,
* version 2.
@ -15,7 +15,7 @@
* this program; if not, write to the Free Software Foundation, Inc., 51
* Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Copyright SkySQL Ab 2014
* Copyright MariaDB Corporation Ab 2014
*/
/**

Some files were not shown because too many files have changed in this diff Show More