Merge branch 'cmake_build' into query_classifier_test
This commit is contained in:
@ -1,8 +1,7 @@
|
||||
cmake_minimum_required(VERSION 2.8.12)
|
||||
cmake_minimum_required(VERSION 2.6)
|
||||
|
||||
include(macros.cmake)
|
||||
|
||||
|
||||
enable_testing()
|
||||
set_variables()
|
||||
set_maxscale_version()
|
||||
|
29
README
29
README
@ -157,7 +157,7 @@ Please check errmsg.sys is found in the MaxScale install_dir DEST/MaxScale/mysql
|
||||
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 or newer if you wish to generate packages.
|
||||
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
|
||||
@ -166,12 +166,15 @@ values, you can run CMake in interactive mode by using the -i flag or use a CMak
|
||||
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 default, MaxScale installs to /usr/local/skysql 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.
|
||||
To build MaxScale using CMake:
|
||||
|
||||
To build and install MaxScale using CMake with a custom install location and a separate build directory:
|
||||
cd <path to MaxScale source>
|
||||
|
||||
cmake -D_INSTALL_DIR=<install destination> <path to MaxScale source>
|
||||
mkdir build
|
||||
|
||||
cd build
|
||||
|
||||
cmake ..
|
||||
|
||||
make
|
||||
|
||||
@ -184,19 +187,33 @@ To build MaxScale using the ccmake GUI:
|
||||
|
||||
ccmake <path to MaxScale source>
|
||||
|
||||
|
||||
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.
|
||||
|
||||
All the parameters affecting CMake can be found in 'macros.cmake'. This file also has the parameters CMake uses for testing.
|
||||
|
||||
Variables controlling the CMake build process:
|
||||
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, filename included
|
||||
MYSQL_DIR=<path> Path to MySQL headers
|
||||
ERRMSG=<path> Path to errmsg.sys file
|
||||
STATIC_EMBEDDED=[Y|N] Link the static or the dynamic verson of the library
|
||||
GCOV=[Y|N] Generate gcov output
|
||||
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
|
||||
|
||||
|
@ -33,7 +33,7 @@ endif
|
||||
|
||||
CC=cc
|
||||
|
||||
CFLAGS=-c -Wall -g $(HISTFLAG)
|
||||
CFLAGS=-c -Wall -g $(HISTFLAG) -I ../server/include
|
||||
|
||||
SRCS= maxadmin.c
|
||||
|
||||
|
@ -47,6 +47,9 @@
|
||||
#include <dirent.h>
|
||||
#include <locale.h>
|
||||
#include <errno.h>
|
||||
#include <getopt.h>
|
||||
|
||||
#include <version.h>
|
||||
|
||||
#ifdef HISTORY
|
||||
#include <histedit.h>
|
||||
@ -59,6 +62,7 @@ static int sendCommand(int so, char *cmd);
|
||||
static void DoSource(int so, char *cmd);
|
||||
static void DoUsage();
|
||||
static int isquit(char *buf);
|
||||
static void PrintVersion(const char *progname);
|
||||
|
||||
#ifdef HISTORY
|
||||
static char *
|
||||
@ -70,6 +74,16 @@ prompt(EditLine *el __attribute__((__unused__)))
|
||||
}
|
||||
#endif
|
||||
|
||||
static struct option long_options[] = {
|
||||
{"host", required_argument, 0, 'h'},
|
||||
{"user", required_argument, 0, 'u'},
|
||||
{"password", required_argument, 0, 'p'},
|
||||
{"port", required_argument, 0, 'P'},
|
||||
{"version", no_argument, 0, 'v'},
|
||||
{"help", no_argument, 0, '?'},
|
||||
{0, 0, 0, 0}
|
||||
};
|
||||
|
||||
/**
|
||||
* The main for the maxadmin client
|
||||
*
|
||||
@ -79,7 +93,7 @@ prompt(EditLine *el __attribute__((__unused__)))
|
||||
int
|
||||
main(int argc, char **argv)
|
||||
{
|
||||
int i, num, rv, fatal = 0;
|
||||
int i, num, rv;
|
||||
#ifdef HISTORY
|
||||
char *buf;
|
||||
EditLine *el = NULL;
|
||||
@ -96,106 +110,38 @@ char *user = "admin";
|
||||
char *passwd = NULL;
|
||||
int so, cmdlen;
|
||||
char *cmd;
|
||||
int argno = 0;
|
||||
int option_index = 0;
|
||||
char c;
|
||||
|
||||
cmd = malloc(1);
|
||||
*cmd = 0;
|
||||
cmdlen = 1;
|
||||
|
||||
for (i = 1; i < argc; i++)
|
||||
while ((c = getopt_long(argc, argv, "h:p:P:u:v?",
|
||||
long_options, &option_index))
|
||||
>= 0)
|
||||
{
|
||||
if (argv[i][0] == '-')
|
||||
{
|
||||
switch (argv[i][1])
|
||||
{
|
||||
case 'u': /* User */
|
||||
if (argv[i][2])
|
||||
user = &(argv[i][2]);
|
||||
else if (i + 1 < argc)
|
||||
user = argv[++i];
|
||||
else
|
||||
{
|
||||
fprintf(stderr, "Missing username"
|
||||
"in -u option.\n");
|
||||
fatal = 1;
|
||||
}
|
||||
switch (c) {
|
||||
case 'h':
|
||||
hostname = strdup(optarg);
|
||||
break;
|
||||
case 'p': /* Password */
|
||||
if (argv[i][2])
|
||||
passwd = &(argv[i][2]);
|
||||
else if (i + 1 < argc)
|
||||
passwd = argv[++i];
|
||||
else
|
||||
{
|
||||
fprintf(stderr, "Missing password "
|
||||
"in -p option.\n");
|
||||
fatal = 1;
|
||||
}
|
||||
case 'p':
|
||||
passwd = strdup(optarg);
|
||||
break;
|
||||
case 'h': /* hostname */
|
||||
if (argv[i][2])
|
||||
hostname = &(argv[i][2]);
|
||||
else if (i + 1 < argc)
|
||||
hostname = argv[++i];
|
||||
else
|
||||
{
|
||||
fprintf(stderr, "Missing hostname value "
|
||||
"in -h option.\n");
|
||||
fatal = 1;
|
||||
}
|
||||
case 'P':
|
||||
port = strdup(optarg);
|
||||
break;
|
||||
case 'P': /* Port */
|
||||
if (argv[i][2])
|
||||
port = &(argv[i][2]);
|
||||
else if (i + 1 < argc)
|
||||
port = argv[++i];
|
||||
else
|
||||
{
|
||||
fprintf(stderr, "Missing Port value "
|
||||
"in -P option.\n");
|
||||
fatal = 1;
|
||||
}
|
||||
break;
|
||||
case '-':
|
||||
{
|
||||
char *word;
|
||||
|
||||
word = &argv[i][2];
|
||||
if (strcmp(word, "help") == 0)
|
||||
{
|
||||
DoUsage();
|
||||
exit(0);
|
||||
}
|
||||
case 'u':
|
||||
user = strdup(optarg);
|
||||
break;
|
||||
case 'v':
|
||||
PrintVersion(*argv);
|
||||
exit(EXIT_SUCCESS);
|
||||
case '?':
|
||||
DoUsage(*argv);
|
||||
exit(optopt ? EXIT_FAILURE : EXIT_SUCCESS);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Arguments after the second argument are quoted
|
||||
* to allow for quoted names on the command line
|
||||
* to be passed on in quotes.
|
||||
*/
|
||||
if (argno++ > 1)
|
||||
{
|
||||
cmdlen += strlen(argv[i]) + 3;
|
||||
cmd = realloc(cmd, cmdlen);
|
||||
strcat(cmd, "\"");
|
||||
strcat(cmd, argv[i]);
|
||||
strcat(cmd, "\" ");
|
||||
}
|
||||
else
|
||||
{
|
||||
cmdlen += strlen(argv[i]) + 1;
|
||||
cmd = realloc(cmd, cmdlen);
|
||||
strcat(cmd, argv[i]);
|
||||
strcat(cmd, " ");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (fatal)
|
||||
exit(1);
|
||||
|
||||
if (passwd == NULL)
|
||||
{
|
||||
@ -533,23 +479,34 @@ FILE *fp;
|
||||
return;
|
||||
}
|
||||
|
||||
/**
|
||||
* Print version information
|
||||
*/
|
||||
static void
|
||||
PrintVersion(const char *progname)
|
||||
{
|
||||
printf("%s Version %s\n", progname, MAXSCALE_VERSION);
|
||||
}
|
||||
|
||||
/**
|
||||
* Display the --help text.
|
||||
*/
|
||||
static void
|
||||
DoUsage()
|
||||
DoUsage(const char *progname)
|
||||
{
|
||||
printf("maxadmin: The MaxScale administrative and monitor client.\n\n");
|
||||
printf("Usage: maxadmin [-u user] [-p password] [-h hostname] [-P port] [<command file> | <command>]\n\n");
|
||||
printf(" -u user The user name to use for the connection, default\n");
|
||||
PrintVersion(progname);
|
||||
printf("The MaxScale administrative and monitor client.\n\n");
|
||||
printf("Usage: %s [-u user] [-p password] [-h hostname] [-P port] [<command file> | <command>]\n\n", progname);
|
||||
printf(" -u|--user=... The user name to use for the connection, default\n");
|
||||
printf(" is admin.\n");
|
||||
printf(" -p password The user password, if not given the password will\n");
|
||||
printf(" -p|--password=... The user password, if not given the password will\n");
|
||||
printf(" be prompted for interactively\n");
|
||||
printf(" -h hostname The maxscale host to connecto to. The default is\n");
|
||||
printf(" -h|--hostname=... The maxscale host to connecto to. The default is\n");
|
||||
printf(" localhost\n");
|
||||
printf(" -P port The port to use for the connection, the default\n");
|
||||
printf(" -P|--port=... The port to use for the connection, the default\n");
|
||||
printf(" port is 6603.\n");
|
||||
printf(" --help Print this help text.\n");
|
||||
printf(" -v|--version print version information and exit\n");
|
||||
printf(" -?|--help Print this help text.\n");
|
||||
printf("Any remaining arguments are treated as MaxScale commands or a file\n");
|
||||
printf("containing commands to execute.\n");
|
||||
}
|
||||
|
@ -255,7 +255,7 @@ static int logmanager_write_log(
|
||||
bool use_valist,
|
||||
bool spread_down,
|
||||
size_t len,
|
||||
char* str,
|
||||
const char* str,
|
||||
va_list valist);
|
||||
|
||||
static blockbuf_t* blockbuf_init(logfile_id_t id);
|
||||
@ -609,7 +609,7 @@ static int logmanager_write_log(
|
||||
bool use_valist,
|
||||
bool spread_down,
|
||||
size_t str_len,
|
||||
char* str,
|
||||
const char* str,
|
||||
va_list valist)
|
||||
{
|
||||
logfile_t* lf;
|
||||
@ -623,7 +623,7 @@ static int logmanager_write_log(
|
||||
CHK_LOGMANAGER(lm);
|
||||
|
||||
if (id < LOGFILE_FIRST || id > LOGFILE_LAST) {
|
||||
char* errstr = "Invalid logfile id argument.";
|
||||
const char* errstr = "Invalid logfile id argument.";
|
||||
/**
|
||||
* invalid id, since we don't have logfile yet.
|
||||
*/
|
||||
@ -1181,7 +1181,7 @@ static bool logfile_set_enabled(
|
||||
CHK_LOGMANAGER(lm);
|
||||
|
||||
if (id < LOGFILE_FIRST || id > LOGFILE_LAST) {
|
||||
char* errstr = "Invalid logfile id argument.";
|
||||
const char* errstr = "Invalid logfile id argument.";
|
||||
/**
|
||||
* invalid id, since we don't have logfile yet.
|
||||
*/
|
||||
@ -1235,7 +1235,7 @@ return_succp:
|
||||
|
||||
int skygw_log_write_flush(
|
||||
logfile_id_t id,
|
||||
char* str,
|
||||
const char* str,
|
||||
...)
|
||||
{
|
||||
int err = 0;
|
||||
@ -1291,7 +1291,7 @@ return_err:
|
||||
|
||||
int skygw_log_write(
|
||||
logfile_id_t id,
|
||||
char* str,
|
||||
const char* str,
|
||||
...)
|
||||
{
|
||||
int err = 0;
|
||||
|
@ -72,9 +72,9 @@ void skygw_logmanager_exit(void);
|
||||
* free private write buffer list
|
||||
*/
|
||||
void skygw_log_done(void);
|
||||
int skygw_log_write(logfile_id_t id, char* format, ...);
|
||||
int skygw_log_write(logfile_id_t id, const char* format, ...);
|
||||
int skygw_log_flush(logfile_id_t id);
|
||||
int skygw_log_write_flush(logfile_id_t id, char* format, ...);
|
||||
int skygw_log_write_flush(logfile_id_t id, const char* format, ...);
|
||||
int skygw_log_enable(logfile_id_t id);
|
||||
int skygw_log_disable(logfile_id_t id);
|
||||
|
||||
|
47
macros.cmake
47
macros.cmake
@ -70,6 +70,7 @@ macro(check_deps)
|
||||
|
||||
if(DEPS_ERROR)
|
||||
message(FATAL_ERROR "Cannot find dependencies: ${FAILED_DEPS}")
|
||||
set(DEPS_OK FALSE CACHE BOOL "If all the dependencies were found.")
|
||||
endif()
|
||||
|
||||
endmacro()
|
||||
@ -86,19 +87,23 @@ macro(check_dirs)
|
||||
set(MYSQL_DIR ${MYSQL_DIR_LOC} CACHE PATH "Path to MySQL headers" FORCE)
|
||||
if(${MYSQL_DIR} STREQUAL "MYSQL_DIR-NOTFOUND")
|
||||
message(FATAL_ERROR "Fatal Error: MySQL headers were not found.")
|
||||
set(DEPS_OK FALSE CACHE BOOL "If all the dependencies were found.")
|
||||
else()
|
||||
message(STATUS "Using MySQL headers found at: ${MYSQL_DIR}")
|
||||
endif()
|
||||
|
||||
# Find the errmsg.sys file if it was not defied
|
||||
if( NOT ( DEFINED ERRMSG ) )
|
||||
find_file(ERRMSG errmsg.sys PATHS /usr/share/mysql /usr/local/share/mysql ${CUSTOM_ERRMSG} PATH_SUFFIXES english)
|
||||
if(${ERRMSG} STREQUAL "ERRMSG-NOTFOUND")
|
||||
message(FATAL_ERROR "Fatal Error: The errmsg.sys file was not found.")
|
||||
elseif(DEBUG_OUTPUT)
|
||||
message(STATUS "Using errmsg.sys found at: ${ERRMSG}")
|
||||
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")
|
||||
message(FATAL_ERROR "Fatal Error: The errmsg.sys file was not found, please define the path to it by using -DERRMSG=<path>")
|
||||
set(DEPS_OK FALSE CACHE BOOL "If all the dependencies were found.")
|
||||
else()
|
||||
message(STATUS "Using errmsg.sys found at: ${ERRMSG_FILE}")
|
||||
endif()
|
||||
set(ERRMSG ${ERRMSG_FILE} CACHE FILEPATH "Path to the errmsg.sys file." FORCE)
|
||||
|
||||
# Find the embedded mysql library
|
||||
if(STATIC_EMBEDDED)
|
||||
@ -132,6 +137,7 @@ macro(check_dirs)
|
||||
# Inform the user about the embedded library
|
||||
if( (${EMBEDDED_LIB} STREQUAL "EMBEDDED_LIB_STATIC-NOTFOUND") OR (${EMBEDDED_LIB} STREQUAL "EMBEDDED_LIB_DYNAMIC-NOTFOUND"))
|
||||
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>")
|
||||
set(DEPS_OK FALSE CACHE BOOL "If all the dependencies were found.")
|
||||
else()
|
||||
get_filename_component(EMBEDDED_LIB ${EMBEDDED_LIB} REALPATH)
|
||||
message(STATUS "Using embedded library: ${EMBEDDED_LIB}")
|
||||
@ -144,6 +150,7 @@ macro(check_dirs)
|
||||
find_file(DEB_FNC init-functions PATHS /lib/lsb)
|
||||
if(${DEB_FNC} MATCHES "DEB_FNC-NOTFOUND")
|
||||
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.")
|
||||
set(DEPS_OK FALSE CACHE BOOL "If all the dependencies were found.")
|
||||
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()
|
||||
@ -151,6 +158,34 @@ macro(check_dirs)
|
||||
set(DEB_BASED FALSE CACHE BOOL "If init.d script uses /lib/lsb/init-functions instead of /etc/rc.d/init.d/functions.")
|
||||
endif()
|
||||
|
||||
#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")
|
||||
message(FATAL_ERROR "Cannot find RabbitMQ libraries, please define the path to the libraries with -DRABBITMQ_LIB=<path>")
|
||||
set(DEPS_OK FALSE CACHE BOOL "If all the dependencies were found.")
|
||||
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")
|
||||
message(FATAL_ERROR "Cannot find RabbitMQ headers, please define the path to the headers with -DRABBITMQ_HEADERS=<path>")
|
||||
set(DEPS_OK FALSE CACHE BOOL "If all the dependencies were found.")
|
||||
else()
|
||||
set(RABBITMQ_HEADERS ${RMQ_HEADERS} CACHE PATH "Path to RabbitMQ headers" FORCE)
|
||||
message(STATUS "Using RabbitMQ headers found at: ${RABBITMQ_HEADERS}")
|
||||
endif()
|
||||
|
||||
endif()
|
||||
|
||||
set(DEPS_OK TRUE CACHE BOOL "If all the dependencies were found.")
|
||||
|
||||
|
@ -1 +1,3 @@
|
||||
add_subdirectory(canonical_tests)
|
||||
add_executable(classify classify.c)
|
||||
target_link_libraries(classify fullcore)
|
@ -1,4 +1,7 @@
|
||||
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
|
||||
|
@ -1,7 +1,13 @@
|
||||
if (NOT ( DEFINED MYSQL_CLIENT_LIB ) )
|
||||
find_library(MYSQL_CLIENT_LIB NAMES mysqlclient PATHS /usr/lib /usr/lib64 PATH_SUFFIXES mysql mariadb)
|
||||
endif()
|
||||
|
||||
if( ( RABBITMQ_LIB AND RABBITMQ_HEADERS ) AND ( NOT ( ${MYSQL_CLIENT_LIB} STREQUAL "MYSQL_CLIENT_LIB-NOTFOUND" ) ) )
|
||||
if (NOT ( DEFINED MYSQL_CLIENT_HEADERS ) )
|
||||
find_path(MYSQL_CLIENT_HEADERS NAMES mysql.h PATH_SUFFIXES mysql mariadb)
|
||||
endif()
|
||||
|
||||
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)
|
||||
|
@ -1575,6 +1575,7 @@ static char *service_params[] =
|
||||
"use_sql_variables_in", /*< rwsplit only */
|
||||
"version_string",
|
||||
"filters",
|
||||
"weightby",
|
||||
NULL
|
||||
};
|
||||
|
||||
|
@ -403,13 +403,16 @@ DCB_CALLBACK *cb;
|
||||
* operation of clearing this bit means that no bits are set in
|
||||
* the memdata.bitmask then the DCB is no longer able to be
|
||||
* referenced and it can be finally removed.
|
||||
* Thread won't clear its bit from bitmask of the DCB it is still using.
|
||||
*
|
||||
* 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 dcb_in_use The DCB the thread currently uses, NULL or valid DCB.
|
||||
* @param excluded The DCB the thread currently uses, NULL or valid DCB.
|
||||
*/
|
||||
DCB *
|
||||
dcb_process_zombies(int threadid, DCB *dcb_in_use)
|
||||
dcb_process_zombies(int threadid, DCB *excluded)
|
||||
{
|
||||
DCB *ptr, *lptr;
|
||||
DCB* dcb_list = NULL;
|
||||
@ -426,19 +429,34 @@ bool succp = false;
|
||||
if (!zombies)
|
||||
return NULL;
|
||||
|
||||
/*
|
||||
* Process the zombie queue and create a list of DCB's that can be
|
||||
* finally freed. This processing is down under a spinlock that
|
||||
* will prevent new entries being added to the zombie queue. Therefore
|
||||
* we do not want to do any expensive operations under this spinlock
|
||||
* as it will block other threads. The expensive operations will be
|
||||
* performed on the victim queue within holding the zombie queue
|
||||
* spinlock.
|
||||
*/
|
||||
spinlock_acquire(&zombiespin);
|
||||
ptr = zombies;
|
||||
lptr = NULL;
|
||||
while (ptr)
|
||||
{
|
||||
CHK_DCB(ptr);
|
||||
/** Don't clear the bit from DCB the user currently uses */
|
||||
if (dcb_in_use == NULL || ptr != dcb_in_use)
|
||||
|
||||
/*
|
||||
* Skip processing of the excluded DCB
|
||||
*/
|
||||
if (ptr == excluded)
|
||||
{
|
||||
bitmask_clear(&ptr->memdata.bitmask, threadid);
|
||||
lptr = ptr;
|
||||
ptr = ptr->memdata.next;
|
||||
}
|
||||
if (ptr == dcb_in_use)
|
||||
ss_dassert(!bitmask_isallclear(&ptr->memdata.bitmask));
|
||||
else
|
||||
{
|
||||
|
||||
bitmask_clear(&ptr->memdata.bitmask, threadid);
|
||||
|
||||
if (bitmask_isallclear(&ptr->memdata.bitmask))
|
||||
{
|
||||
@ -449,9 +467,9 @@ bool succp = false;
|
||||
*
|
||||
* ptr is the DCB we are processing
|
||||
* lptr is the previous DCB on the zombie queue
|
||||
* or NULL if the DCB is at the head of the queue
|
||||
* tptr is the DCB after the one we are processing
|
||||
* on the zombie queue
|
||||
* or NULL if the DCB is at the head of the
|
||||
* queue tptr is the DCB after the one we are
|
||||
* processing on the zombie queue
|
||||
*/
|
||||
DCB *tptr = ptr->memdata.next;
|
||||
if (lptr == NULL)
|
||||
@ -460,8 +478,9 @@ bool succp = false;
|
||||
lptr->memdata.next = tptr;
|
||||
LOGIF(LD, (skygw_log_write_flush(
|
||||
LOGFILE_DEBUG,
|
||||
"%lu [dcb_process_zombies] Remove dcb %p fd %d "
|
||||
"in state %s from zombies list.",
|
||||
"%lu [dcb_process_zombies] Remove dcb "
|
||||
"%p fd %d " "in state %s from the "
|
||||
"list of zombies.",
|
||||
pthread_self(),
|
||||
ptr,
|
||||
ptr->fd,
|
||||
@ -487,17 +506,23 @@ bool succp = false;
|
||||
ptr = ptr->memdata.next;
|
||||
}
|
||||
}
|
||||
}
|
||||
spinlock_release(&zombiespin);
|
||||
|
||||
/*
|
||||
* Process the victim queue. These are DCBs that are not in
|
||||
* use by any thread.
|
||||
* The corresponding file descriptor is closed, the DCB marked
|
||||
* as disconnected and the DCB itself is fianlly freed.
|
||||
*/
|
||||
dcb = dcb_list;
|
||||
/** Close, and set DISCONNECTED victims */
|
||||
while (dcb != NULL) {
|
||||
DCB* dcb_next = NULL;
|
||||
int rc = 0;
|
||||
/*<
|
||||
* Close file descriptor and move to clean-up phase.
|
||||
*/
|
||||
ss_dassert(dcb_in_use != dcb);
|
||||
ss_dassert(excluded != dcb);
|
||||
rc = close(dcb->fd);
|
||||
|
||||
if (rc < 0) {
|
||||
@ -1119,8 +1144,8 @@ int above_water;
|
||||
/**
|
||||
* Removes dcb from poll set, and adds it to zombies list. As a consequense,
|
||||
* dcb first moves to DCB_STATE_NOPOLLING, and then to DCB_STATE_ZOMBIE state.
|
||||
* At the end of the function state may not be DCB_STATE_ZOMBIE because once dcb_initlock
|
||||
* is released parallel threads may change the state.
|
||||
* At the end of the function state may not be DCB_STATE_ZOMBIE because once
|
||||
* dcb_initlock is released parallel threads may change the state.
|
||||
*
|
||||
* Parameters:
|
||||
* @param dcb The DCB to close
|
||||
@ -1943,9 +1968,11 @@ int rval = 0;
|
||||
* 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)
|
||||
dcb_pollin(DCB *dcb, int thread_id, int nozombies)
|
||||
{
|
||||
|
||||
spinlock_acquire(&dcb->pollinlock);
|
||||
@ -1956,6 +1983,7 @@ dcb_pollin(DCB *dcb, int thread_id)
|
||||
if (dcb->readcheck)
|
||||
{
|
||||
dcb->stats.n_readrechecks++;
|
||||
if (!nozombies)
|
||||
dcb_process_zombies(thread_id, dcb);
|
||||
}
|
||||
dcb->readcheck = 0;
|
||||
@ -1987,9 +2015,11 @@ dcb_pollin(DCB *dcb, int thread_id)
|
||||
* 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)
|
||||
dcb_pollout(DCB *dcb, int thread_id, int nozombies)
|
||||
{
|
||||
|
||||
spinlock_acquire(&dcb->polloutlock);
|
||||
@ -1999,6 +2029,7 @@ dcb_pollout(DCB *dcb, int thread_id)
|
||||
do {
|
||||
if (dcb->writecheck)
|
||||
{
|
||||
if (!nozombies)
|
||||
dcb_process_zombies(thread_id, dcb);
|
||||
dcb->stats.n_writerechecks++;
|
||||
}
|
||||
|
@ -44,6 +44,7 @@
|
||||
#include <string.h>
|
||||
#include <gw.h>
|
||||
#include <unistd.h>
|
||||
#include <getopt.h>
|
||||
#include <service.h>
|
||||
#include <server.h>
|
||||
#include <dcb.h>
|
||||
@ -131,6 +132,17 @@ static bool libmysqld_started = FALSE;
|
||||
*/
|
||||
static bool daemon_mode = true;
|
||||
|
||||
const char *progname = NULL;
|
||||
static struct option long_options[] = {
|
||||
{"homedir", required_argument, 0, 'c'},
|
||||
{"config", required_argument, 0, 'f'},
|
||||
{"nodeamon", required_argument, 0, 'd'},
|
||||
{"log", required_argument, 0, 'l'},
|
||||
{"version", no_argument, 0, 'v'},
|
||||
{"help", no_argument, 0, '?'},
|
||||
{0, 0, 0, 0}
|
||||
};
|
||||
|
||||
static void log_flush_shutdown(void);
|
||||
static void log_flush_cb(void* arg);
|
||||
static int write_pid_file(char *); /* write MaxScale pidfile */
|
||||
@ -878,15 +890,19 @@ return_cnf_file_buf:
|
||||
return cnf_file_buf;
|
||||
}
|
||||
|
||||
|
||||
static void usage(void)
|
||||
{
|
||||
fprintf(stderr,
|
||||
"*\n* Usage : maxscale [-h] | [-d] [-c <home "
|
||||
"directory>] [-f <config file name>]\n* where:\n* "
|
||||
"-h help\n* -d enable running in terminal process (default:disabled)\n* "
|
||||
"-c relative|absolute MaxScale home directory\n* "
|
||||
"-f relative|absolute pathname of MaxScale configuration file (default:MAXSCALE_HOME/etc/MaxScale.cnf)\n*\n");
|
||||
"\nUsage : %s [-h] | [-d] [-c <home directory>] [-f <config file name>]\n\n"
|
||||
" -d|--nodaemon enable running in terminal process (default:disabled)\n"
|
||||
" -c|--homedir=... relative|absolute MaxScale home directory\n"
|
||||
" -f|--config=... relative|absolute pathname of MaxScale configuration file\n"
|
||||
" (default: $MAXSCALE_HOME/etc/MaxScale.cnf)\n"
|
||||
" -l|--log=... log to file or shared memory\n"
|
||||
" -lfile or -lshm - defaults to shared memory\n"
|
||||
" -v|--version print version info and exit\n"
|
||||
" -?|--help show this help\n"
|
||||
, progname);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -943,6 +959,8 @@ int main(int argc, char **argv)
|
||||
char* cnf_file_path = NULL; /*< conf file, to be freed */
|
||||
char* cnf_file_arg = NULL; /*< conf filename from cmd-line arg */
|
||||
void* log_flush_thr = NULL;
|
||||
int option_index;
|
||||
int logtofile = 0; /* Use shared memory or file */
|
||||
ssize_t log_flush_timeout_ms = 0;
|
||||
sigset_t sigset;
|
||||
sigset_t sigpipe_mask;
|
||||
@ -954,6 +972,8 @@ int main(int argc, char **argv)
|
||||
sigemptyset(&sigpipe_mask);
|
||||
sigaddset(&sigpipe_mask, SIGPIPE);
|
||||
|
||||
progname = *argv;
|
||||
|
||||
#if defined(SS_DEBUG)
|
||||
memset(conn_open, 0, sizeof(bool)*10240);
|
||||
memset(dcb_fake_write_errno, 0, sizeof(unsigned char)*10240);
|
||||
@ -980,7 +1000,8 @@ int main(int argc, char **argv)
|
||||
goto return_main;
|
||||
}
|
||||
}
|
||||
while ((opt = getopt(argc, argv, "dc:f:h")) != -1)
|
||||
while ((opt = getopt_long(argc, argv, "dc:f:l:v?",
|
||||
long_options, &option_index)) != -1)
|
||||
{
|
||||
bool succp = true;
|
||||
|
||||
@ -1062,6 +1083,33 @@ int main(int argc, char **argv)
|
||||
}
|
||||
break;
|
||||
|
||||
case 'v':
|
||||
rc = EXIT_SUCCESS;
|
||||
goto return_main;
|
||||
|
||||
case 'l':
|
||||
if (strncasecmp(optarg, "file") == 0)
|
||||
logtofile = 1;
|
||||
else if (strncasecmp(optarg, "shm") == 0)
|
||||
logtofile = 0;
|
||||
else
|
||||
{
|
||||
char* logerr = "Configuration file argument "
|
||||
"identifier \'-l\' was specified but "
|
||||
"the argument didn't specify\n a valid "
|
||||
"configuration file or the argument "
|
||||
"was missing.";
|
||||
print_log_n_stderr(true, true, logerr, logerr, 0);
|
||||
usage();
|
||||
succp = false;
|
||||
}
|
||||
break;
|
||||
|
||||
case '?':
|
||||
usage();
|
||||
rc = EXIT_SUCCESS;
|
||||
goto return_main;
|
||||
|
||||
default:
|
||||
usage();
|
||||
succp = false;
|
||||
@ -1345,6 +1393,16 @@ int main(int argc, char **argv)
|
||||
argv[0] = "MaxScale";
|
||||
argv[1] = "-j";
|
||||
argv[2] = buf;
|
||||
if (logtofile)
|
||||
{
|
||||
argv[3] = "-l"; /*< write to syslog */
|
||||
argv[4] = "LOGFILE_MESSAGE,LOGFILE_ERROR"
|
||||
"LOGFILE_DEBUG,LOGFILE_TRACE";
|
||||
argv[5] = NULL;
|
||||
skygw_logmanager_init(5, argv);
|
||||
}
|
||||
else
|
||||
{
|
||||
argv[3] = "-s"; /*< store to shared memory */
|
||||
argv[4] = "LOGFILE_DEBUG,LOGFILE_TRACE"; /*< ..these logs to shm */
|
||||
argv[5] = "-l"; /*< write to syslog */
|
||||
@ -1352,6 +1410,7 @@ int main(int argc, char **argv)
|
||||
argv[7] = NULL;
|
||||
skygw_logmanager_init(7, argv);
|
||||
}
|
||||
}
|
||||
|
||||
/*<
|
||||
* Resolve the full pathname for configuration file and check for
|
||||
|
@ -16,6 +16,7 @@
|
||||
* Copyright SkySQL Ab 2014
|
||||
*/
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <housekeeper.h>
|
||||
#include <thread.h>
|
||||
#include <spinlock.h>
|
||||
|
@ -125,7 +125,7 @@ unsigned char *ptr;
|
||||
/**
|
||||
* Replace the contents of a GWBUF with the new SQL statement passed as a text string.
|
||||
* The routine takes care of the modification needed to the MySQL packet,
|
||||
* returning a GWBUF chian that cna be used to send the data to a MySQL server
|
||||
* returning a GWBUF chain that can be used to send the data to a MySQL server
|
||||
*
|
||||
* @param orig The original request in a GWBUF
|
||||
* @param sql The SQL text to replace in the packet
|
||||
|
@ -49,10 +49,19 @@ extern int lm_enabled_logfiles_bitmask;
|
||||
* @endverbatim
|
||||
*/
|
||||
|
||||
/**
|
||||
* Control the use of mutexes for the epoll_wait call. Setting to 1 will
|
||||
* cause the epoll_wait calls to be moved under a mutex. This may be useful
|
||||
* for debuggign purposes but should be avoided in general use.
|
||||
*/
|
||||
#define MUTEX_EPOLL 0
|
||||
|
||||
static int epoll_fd = -1; /*< The epoll file descriptor */
|
||||
static int do_shutdown = 0; /*< Flag the shutdown of the poll subsystem */
|
||||
static GWBITMASK poll_mask;
|
||||
#if MUTEX_EPOLL
|
||||
static simple_mutex_t epoll_wait_mutex; /*< serializes calls to epoll_wait */
|
||||
#endif
|
||||
static int n_waiting = 0; /*< No. of threads in epoll_wait */
|
||||
|
||||
/**
|
||||
@ -154,7 +163,9 @@ int i;
|
||||
thread_data[i].state = THREAD_STOPPED;
|
||||
}
|
||||
}
|
||||
#if MUTEX_EPOLL
|
||||
simple_mutex_init(&epoll_wait_mutex, "epoll_wait_mutex");
|
||||
#endif
|
||||
|
||||
hktask_add("Load Average", poll_loadav, NULL, POLL_LOAD_FREQ);
|
||||
n_avg_samples = 15 * 60 / POLL_LOAD_FREQ;
|
||||
@ -359,7 +370,7 @@ DCB *zombies = NULL;
|
||||
thread_id)));
|
||||
no_op = TRUE;
|
||||
}
|
||||
#if 0
|
||||
#if MUTEX_EPOLL
|
||||
simple_mutex_lock(&epoll_wait_mutex, TRUE);
|
||||
#endif
|
||||
if (thread_data)
|
||||
@ -385,7 +396,7 @@ DCB *zombies = NULL;
|
||||
{
|
||||
atomic_add(&n_waiting, -1);
|
||||
if (process_zombies_only) {
|
||||
#if 0
|
||||
#if MUTEX_EPOLL
|
||||
simple_mutex_unlock(&epoll_wait_mutex);
|
||||
#endif
|
||||
goto process_zombies;
|
||||
@ -413,7 +424,7 @@ DCB *zombies = NULL;
|
||||
|
||||
if (n_waiting == 0)
|
||||
atomic_add(&pollStats.n_nothreads, 1);
|
||||
#if 0
|
||||
#if MUTEX_EPOLL
|
||||
simple_mutex_unlock(&epoll_wait_mutex);
|
||||
#endif
|
||||
#endif /* BLOCKINGPOLL */
|
||||
@ -504,7 +515,7 @@ DCB *zombies = NULL;
|
||||
#else
|
||||
atomic_add(&pollStats.n_write,
|
||||
1);
|
||||
dcb_pollout(dcb, thread_id);
|
||||
dcb_pollout(dcb, thread_id, nfds);
|
||||
#endif
|
||||
} else {
|
||||
LOGIF(LD, (skygw_log_write(
|
||||
@ -554,7 +565,7 @@ DCB *zombies = NULL;
|
||||
#if MUTEX_BLOCK
|
||||
dcb->func.read(dcb);
|
||||
#else
|
||||
dcb_pollin(dcb, thread_id);
|
||||
dcb_pollin(dcb, thread_id, nfds);
|
||||
#endif
|
||||
}
|
||||
#if MUTEX_BLOCK
|
||||
@ -609,8 +620,16 @@ DCB *zombies = NULL;
|
||||
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);
|
||||
}
|
||||
|
||||
if (ev & EPOLLRDHUP)
|
||||
{
|
||||
@ -628,8 +647,16 @@ DCB *zombies = NULL;
|
||||
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);
|
||||
}
|
||||
} /*< for */
|
||||
no_op = FALSE;
|
||||
}
|
||||
|
@ -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);
|
||||
void dcb_pollout(DCB *, int);
|
||||
void dcb_pollin(DCB *, int, int);
|
||||
void dcb_pollout(DCB *, int, int);
|
||||
DCB *dcb_get_zombies(void);
|
||||
int gw_write(
|
||||
#if defined(SS_DEBUG)
|
||||
@ -317,6 +317,9 @@ void dcb_call_foreach (DCB_REASON reason);
|
||||
void dcb_call_foreach (
|
||||
DCB_REASON reason);
|
||||
|
||||
/* DCB flags values */
|
||||
#define DCBF_CLONE 0x0001 /* DCB is a clone */
|
||||
/**
|
||||
* DCB flags values
|
||||
*/
|
||||
#define DCBF_CLONE 0x0001 /*< DCB is a clone */
|
||||
#define DCBF_HUNG 0x0002 /*< Hangup has been dispatched */
|
||||
#endif /* _DCB_H */
|
||||
|
@ -1,11 +1,7 @@
|
||||
if(BUILD_RABBITMQ)
|
||||
if(RABBITMQ_LIB AND RABBITMQ_HEADERS)
|
||||
add_library(mqfilter SHARED mqfilter.c)
|
||||
target_link_libraries(mqfilter query_classifier log_manager utils rabbitmq)
|
||||
install(TARGETS mqfilter DESTINATION modules)
|
||||
else()
|
||||
message(ERROR "Error: Cannot find the required librabbitmq-c locations, please check that you have them configured correctly.")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
add_library(regexfilter SHARED regexfilter.c)
|
||||
|
Reference in New Issue
Block a user