Merge branch 'release-1.3.0' into develop

This commit is contained in:
Markus Makela
2016-01-08 11:14:02 +02:00
46 changed files with 349 additions and 257 deletions

View File

@ -5,7 +5,7 @@ if(BUILD_TESTS OR BUILD_TOOLS)
elseif(WITH_TCMALLOC)
target_link_libraries(fullcore ${TCMALLOC_LIBRARIES})
endif()
target_link_libraries(fullcore ${CURL_LIBRARIES} utils log_manager pthread ${LZMA_LINK_FLAGS} ${EMBEDDED_LIB} ${PCRE_LINK_FLAGS} ssl aio rt crypt dl crypto inih z m stdc++)
target_link_libraries(fullcore ${CURL_LIBRARIES} utils ${PCRE2_LIBRARIES} log_manager pthread ${LZMA_LINK_FLAGS} ${EMBEDDED_LIB} ${PCRE_LINK_FLAGS} ssl aio rt crypt dl crypto inih z m stdc++)
add_dependencies(fullcore pcre2)
endif()
@ -22,15 +22,15 @@ elseif(WITH_TCMALLOC)
target_link_libraries(maxscale ${TCMALLOC_LIBRARIES})
endif()
target_link_libraries(maxscale ${LZMA_LINK_FLAGS} ${EMBEDDED_LIB} ${PCRE_LINK_FLAGS} ${CURL_LIBRARIES} log_manager utils ssl aio pthread crypt dl crypto inih z rt m stdc++)
target_link_libraries(maxscale ${LZMA_LINK_FLAGS} ${PCRE2_LIBRARIES} ${EMBEDDED_LIB} ${PCRE_LINK_FLAGS} ${CURL_LIBRARIES} log_manager utils ssl aio pthread crypt dl crypto inih z rt m stdc++)
install(TARGETS maxscale DESTINATION ${MAXSCALE_BINDIR})
add_executable(maxkeys maxkeys.c spinlock.c secrets.c utils.c gwdirs.c random_jkiss.c ${CMAKE_SOURCE_DIR}/log_manager/log_manager.cc)
target_link_libraries(maxkeys utils pthread crypt crypto)
target_link_libraries(maxkeys utils pthread crypt crypto ${PCRE2_LIBRARIES})
install(TARGETS maxkeys DESTINATION ${MAXSCALE_BINDIR})
add_executable(maxpasswd maxpasswd.c spinlock.c secrets.c utils.c gwdirs.c random_jkiss.c ${CMAKE_SOURCE_DIR}/log_manager/log_manager.cc)
target_link_libraries(maxpasswd utils pthread crypt crypto)
target_link_libraries(maxpasswd utils pthread crypt crypto ${PCRE2_LIBRARIES})
install(TARGETS maxpasswd DESTINATION ${MAXSCALE_BINDIR})
if(BUILD_TESTS)

View File

@ -1578,15 +1578,33 @@ handle_global_item(const char *name, const char *value)
int i;
if (strcmp(name, "threads") == 0)
{
int thrcount = atoi(value);
if (thrcount > 0)
if (strcmp(name, "auto") == 0)
{
gateway.n_threads = thrcount;
if ((gateway.n_threads = get_processor_count()) > 1)
{
gateway.n_threads--;
}
}
else
{
MXS_WARNING("Invalid value for 'threads': %s.", value);
return 0;
int thrcount = atoi(value);
if (thrcount > 0)
{
gateway.n_threads = thrcount;
int processor_count = get_processor_count();
if (thrcount > processor_count)
{
MXS_WARNING("Number of threads set to %d which is greater than"
" the number of processors available: %d",
thrcount, processor_count);
}
}
else
{
MXS_WARNING("Invalid value for 'threads': %s.", value);
return 0;
}
}
}
else if (strcmp(name, "non_blocking_polls") == 0)
@ -1706,7 +1724,7 @@ global_defaults()
{
uint8_t mac_addr[6]="";
struct utsname uname_data;
gateway.n_threads = get_processor_count();
gateway.n_threads = DEFAULT_NTHREADS;
gateway.n_nbpoll = DEFAULT_NBPOLLS;
gateway.pollsleep = DEFAULT_POLLSLEEP;
gateway.auth_conn_timeout = DEFAULT_AUTH_CONNECT_TIMEOUT;
@ -1922,7 +1940,7 @@ process_config_update(CONFIG_CONTEXT *context)
"count or\n\t<int>%% for specifying the "
"maximum percentage of available the "
"slaves that will be connected.",
((SERVICE*)obj->element)->name,
service->name,
param->name,
param->value);
}
@ -1960,7 +1978,7 @@ process_config_update(CONFIG_CONTEXT *context)
"for parameter \'%s.%s = %s\'\n\tExpected "
"type is <int> for maximum "
"slave replication lag.",
((SERVICE*)obj->element)->name,
service->name,
param->name,
param->value);
}
@ -2528,6 +2546,7 @@ config_get_ifaddr(unsigned char *output)
{
memcpy(output, ifr.ifr_hwaddr.sa_data, 6);
}
close(sock);
return success;
}

View File

@ -2343,29 +2343,30 @@ static void *
dbusers_keyread(int fd)
{
MYSQL_USER_HOST *dbkey;
int tmp;
if ((dbkey = (MYSQL_USER_HOST *) malloc(sizeof(MYSQL_USER_HOST))) == NULL)
{
return NULL;
}
if (read(fd, &tmp, sizeof(tmp)) != sizeof(tmp))
int user_size;
if (read(fd, &user_size, sizeof(user_size)) != sizeof(user_size))
{
free(dbkey);
return NULL;
}
if ((dbkey->user = (char *) malloc(tmp + 1)) == NULL)
if ((dbkey->user = (char *) malloc(user_size + 1)) == NULL)
{
free(dbkey);
return NULL;
}
if (read(fd, dbkey->user, tmp) != tmp)
if (read(fd, dbkey->user, user_size) != user_size)
{
free(dbkey->user);
free(dbkey);
return NULL;
}
dbkey->user[tmp] = 0; // NULL Terminate
dbkey->user[user_size] = 0; // NULL Terminate
if (read(fd, &dbkey->ipv4, sizeof(dbkey->ipv4)) != sizeof(dbkey->ipv4))
{
free(dbkey->user);
@ -2378,28 +2379,30 @@ dbusers_keyread(int fd)
free(dbkey);
return NULL;
}
if (read(fd, &tmp, sizeof(tmp)) != sizeof(tmp))
int res_size;
if (read(fd, &res_size, sizeof(res_size)) != sizeof(res_size))
{
free(dbkey->user);
free(dbkey);
return NULL;
}
if (tmp != -1)
else if (res_size != -1)
{
if ((dbkey->resource = (char *) malloc(tmp + 1)) == NULL)
if ((dbkey->resource = (char *) malloc(res_size + 1)) == NULL)
{
free(dbkey->user);
free(dbkey);
return NULL;
}
if (read(fd, dbkey->resource, tmp) != tmp)
if (read(fd, dbkey->resource, res_size) != res_size)
{
free(dbkey->resource);
free(dbkey->user);
free(dbkey);
return NULL;
}
dbkey->resource[tmp] = 0; // NULL Terminate
dbkey->resource[res_size] = 0; // NULL Terminate
}
else // NULL is valid, so represent with a length of -1
{

View File

@ -643,6 +643,9 @@ dcb_process_victim_queue(DCB *listofdcb)
}
else
{
#if defined(FAKE_CODE)
conn_open[dcb->fd] = false;
#endif /* FAKE_CODE */
dcb->fd = DCBFD_CLOSED;
MXS_DEBUG("%lu [dcb_process_victim_queue] Closed socket "
@ -650,9 +653,6 @@ dcb_process_victim_queue(DCB *listofdcb)
pthread_self(),
dcb->fd,
dcb);
#if defined(FAKE_CODE)
conn_open[dcb->fd] = false;
#endif /* FAKE_CODE */
}
}

View File

@ -1024,7 +1024,7 @@ int main(int argc, char **argv)
int n_services;
int eno = 0; /*< local variable for errno */
int opt;
int daemon_pipe[2];
int daemon_pipe[2] = {-1, -1};
bool parent_process;
int child_status;
void** threads = NULL; /*< thread list */

View File

@ -237,8 +237,8 @@ long get_processor_count()
#ifdef _SC_NPROCESSORS_ONLN
if ((processors = sysconf(_SC_NPROCESSORS_ONLN)) <= 0)
{
MXS_WARNING("Unable to establish the number of available cores. Defaulting to 4.");
processors = 4;
MXS_WARNING("Unable to establish the number of available cores. Defaulting to 1.");
processors = 1;
}
#else
#error _SC_NPROCESSORS_ONLN not available.

View File

@ -17,66 +17,101 @@
*/
#include <gwdirs.h>
#include <gw.h>
/**
* Set the configuration file directory
* @param str Path to directory
*/
void set_configdir(char* str)
{
free(configdir);
clean_up_pathname(str);
configdir = str;
}
/**
* Set the log file directory
* @param str Path to directory
*/
void set_logdir(char* str)
{
free(logdir);
clean_up_pathname(str);
logdir = str;
}
/**
* Set the language file directory
* @param str Path to directory
*/
void set_langdir(char* str)
{
free(langdir);
clean_up_pathname(str);
langdir = str;
}
/**
* Set the PID file directory
* @param str Path to directory
*/
void set_piddir(char* str)
{
free(piddir);
clean_up_pathname(str);
piddir = str;
}
/**
* Set the cache directory
* @param str Path to directory
*/
void set_cachedir(char* param)
{
free(cachedir);
clean_up_pathname(param);
cachedir = param;
}
/**
* Set the data directory
* @param str Path to directory
*/
void set_datadir(char* param)
{
free(maxscaledatadir);
clean_up_pathname(param);
maxscaledatadir = param;
}
/**
* Set the library directory. Modules will be loaded from here.
* @param str Path to directory
*/
void set_libdir(char* param)
{
free(libdir);
clean_up_pathname(param);
libdir = param;
}
/**
* Get the directory with all the modules.
* @return The module directory
*/
char* get_libdir()
{
return libdir ? libdir : (char*)default_libdir;
return libdir ? libdir : (char*) default_libdir;
}
void set_libdir(char* param)
{
if (libdir)
{
free(libdir);
}
libdir = param;
}
/**
* Get the service cache directory
* @return The path to the cache directory
*/
char* get_cachedir()
{
return cachedir ? cachedir : (char*)default_cachedir;
}
void set_cachedir(char* param)
{
if (cachedir)
{
free(cachedir);
}
cachedir = param;
return cachedir ? cachedir : (char*) default_cachedir;
}
/**
@ -85,35 +120,41 @@ void set_cachedir(char* param)
*/
char* get_datadir()
{
return maxscaledatadir ? maxscaledatadir : (char*)default_datadir;
}
void set_datadir(char* param)
{
if (maxscaledatadir)
{
free(maxscaledatadir);
}
maxscaledatadir = param;
return maxscaledatadir ? maxscaledatadir : (char*) default_datadir;
}
/**
* Get the configuration file directory
* @return The path to the configuration file directory
*/
char* get_configdir()
{
return configdir ? configdir : (char*)default_configdir;
return configdir ? configdir : (char*) default_configdir;
}
/**
* Get the PID file directory which contains maxscale.pid
* @return Path to the PID file directory
*/
char* get_piddir()
{
return piddir ? piddir : (char*)default_piddir;
return piddir ? piddir : (char*) default_piddir;
}
/**
* Return the log file directory
* @return Path to the log file directory
*/
char* get_logdir()
{
return logdir ? logdir : (char*)default_logdir;
return logdir ? logdir : (char*) default_logdir;
}
/**
* Path to the directory which contains the errmsg.sys language file
* @return Path to the language file directory
*/
char* get_langdir()
{
return langdir ? langdir : (char*)default_langdir;
return langdir ? langdir : (char*) default_langdir;
}

View File

@ -25,6 +25,8 @@
#include <gwdirs.h>
#include <random_jkiss.h>
#include "gw.h"
/**
* Generate a random printable character
*
@ -67,6 +69,7 @@ secrets_readKeys(const char* path)
if (path != NULL)
{
snprintf(secret_file, PATH_MAX, "%s/.secrets", path);
clean_up_pathname(secret_file);
}
else
{
@ -224,7 +227,7 @@ int secrets_writeKeys(const char *path)
}
snprintf(secret_file, PATH_MAX + 9, "%s/.secrets", path);
secret_file[PATH_MAX + 9] = '\0';
clean_up_pathname(secret_file);
/* Open for writing | Create | Truncate the file for writing */
if ((fd = open(secret_file, O_CREAT | O_WRONLY | O_TRUNC, S_IRUSR)) < 0)

View File

@ -278,3 +278,44 @@ char *create_hex_sha1_sha1_passwd(char *passwd)
return hexpasswd;
}
/**
* Remove duplicate and trailing forward slashes from a path.
* @param path Path to clean up
*/
void clean_up_pathname(char *path)
{
char *data = path;
size_t len = strlen(path);
if (len > PATH_MAX)
{
MXS_WARNING("Pathname too long: %s", path);
}
while (*data != '\0')
{
if (*data == '/')
{
if (*(data + 1) == '/')
{
memmove(data, data + 1, len);
len--;
}
else if (*(data + 1) == '\0' && data != path)
{
*data = '\0';
}
else
{
data++;
len--;
}
}
else
{
data++;
len--;
}
}
}

View File

@ -89,4 +89,5 @@ int parse_bindconfig(char *, unsigned short, struct sockaddr_in *);
int setipaddress(struct in_addr *, char *);
char* get_libdir();
long get_processor_count();
void clean_up_pathname(char *path);
#endif

View File

@ -41,6 +41,7 @@
#define DEFAULT_POLLSLEEP 1000 /**< Default poll wait time (milliseconds) */
#define _SYSNAME_STR_LENGTH 256 /**< sysname len */
#define _RELEASE_STR_LENGTH 256 /**< release len */
#define DEFAULT_NTHREADS 1 /**< Default number of polling threads */
/**
* Maximum length for configuration parameter value.
*/

View File

@ -3,12 +3,11 @@
# Global parameters
#
# Number of threads is autodetected, uncomment for manual configuration
# Complete list of configuration options:
# https://github.com/mariadb-corporation/MaxScale/blob/master/Documentation/Getting-Started/Configuration-Guide.md
[maxscale]
#threads=8
threads=1
# Server definitions
#

View File

@ -11,7 +11,7 @@ if(BUILD_RABBITMQ)
endif()
add_library(regexfilter SHARED regexfilter.c)
target_link_libraries(regexfilter log_manager ${PCRE2_LIBRARIES})
target_link_libraries(regexfilter log_manager)
add_dependencies(regexfilter pcre2)
set_target_properties(regexfilter PROPERTIES VERSION "1.1.0")
install(TARGETS regexfilter DESTINATION ${MAXSCALE_LIBDIR})

View File

@ -998,7 +998,7 @@ bool parse_rule_definition(FW_INSTANCE* instance, RULE* ruledef, char* rule, cha
{
bool escaped = false;
regex_t *re;
char* start, *str;
char* start;
tok = strtok_r(NULL, " ", saveptr);
char delim = '\'';
int n_char = 0;
@ -1052,20 +1052,13 @@ bool parse_rule_definition(FW_INSTANCE* instance, RULE* ruledef, char* rule, cha
goto retblock;
}
str = calloc(((tok - start) + 1), sizeof(char));
if (str == NULL)
{
MXS_ERROR("Fatal Error: malloc returned NULL.");
rval = false;
goto retblock;
}
char str[(tok - start) + 1];
re = (regex_t*) malloc(sizeof(regex_t));
if (re == NULL)
{
MXS_ERROR("Fatal Error: malloc returned NULL.");
rval = false;
free(str);
goto retblock;
}
@ -1083,7 +1076,6 @@ bool parse_rule_definition(FW_INSTANCE* instance, RULE* ruledef, char* rule, cha
ruledef->type = RT_REGEX;
ruledef->data = (void*) re;
}
free(str);
}
else if (strcmp(tok, "limit_queries") == 0)
@ -1277,11 +1269,8 @@ createInstance(char **options, FILTER_PARAMETER **params)
{
if (strcmp(params[i]->name, "rules") == 0)
{
if (filename)
{
free(filename);
}
filename = strdup(params[i]->value);
filename = params[i]->value;
break;
}
}
@ -1292,6 +1281,7 @@ createInstance(char **options, FILTER_PARAMETER **params)
if (strcmp(options[i], "ignorecase") == 0)
{
my_instance->regflags |= REG_ICASE;
break;
}
}
}
@ -1310,7 +1300,6 @@ createInstance(char **options, FILTER_PARAMETER **params)
MXS_ERROR("Error while opening rule file for firewall filter.");
hashtable_free(my_instance->htable);
free(my_instance);
free(filename);
return NULL;
}
@ -1360,16 +1349,15 @@ createInstance(char **options, FILTER_PARAMETER **params)
if (file_empty)
{
MXS_ERROR("dbfwfilter: File is empty: %s", filename);
free(filename);
err = true;
goto retblock;
}
fclose(file);
free(filename);
/**Apply the rules to users*/
ptr = my_instance->userstrings;
my_instance->userstrings = NULL;
if (ptr == NULL)
{
@ -2205,6 +2193,10 @@ bool parse_at_times(const char** tok, char** saveptr, RULE* ruledef)
{
ruledef->active = tr;
}
else
{
free(tr);
}
return success;
}

View File

@ -502,7 +502,7 @@ createInstance(char **options, FILTER_PARAMETER **params)
MQ_INSTANCE *my_instance;
int paramcount = 0, parammax = 64, i = 0, x = 0, arrsize = 0;
FILTER_PARAMETER** paramlist;
char** arr;
char** arr = NULL;
char taskname[512];
if ((my_instance = calloc(1, sizeof(MQ_INSTANCE))))
@ -514,6 +514,8 @@ createInstance(char **options, FILTER_PARAMETER **params)
if ((my_instance->conn = amqp_new_connection()) == NULL)
{
free(paramlist);
free(my_instance);
return NULL;
}
my_instance->channel = 1;
@ -610,6 +612,10 @@ createInstance(char **options, FILTER_PARAMETER **params)
if (arrsize > 0)
{
for (int x = 0; x < arrsize; x++)
{
free(arr[x]);
}
free(arr);
}
arrsize = 0;
@ -777,7 +783,11 @@ createInstance(char **options, FILTER_PARAMETER **params)
snprintf(taskname, 511, "mqtask%d", atomic_add(&hktask_id, 1));
hktask_add(taskname, sendMessage, (void*) my_instance, 5);
for (int x = 0; x < arrsize; x++)
{
free(arr[x]);
}
free(arr);
}
return(FILTER *) my_instance;
}
@ -834,7 +844,7 @@ void sendMessage(void* data)
{
MQ_INSTANCE *instance = (MQ_INSTANCE*) data;
mqmessage *tmp;
int err_num;
int err_num = AMQP_STATUS_OK;
spinlock_acquire(&instance->rconn_lock);
if (instance->conn_stat != AMQP_STATUS_OK)

View File

@ -391,7 +391,7 @@ routeQuery(FILTER *instance, void *session, GWBUF *queue)
REGEX_SESSION *my_session = (REGEX_SESSION *) session;
char *sql, *newsql;
if (modutil_is_SQL(queue))
if (my_session->active && modutil_is_SQL(queue))
{
if (queue->next != NULL)
{

View File

@ -611,7 +611,7 @@ monitorMain(void *arg)
evtype = mon_get_event_type(ptr);
if (isGaleraEvent(evtype))
{
MXS_INFO("Server changed state: %s[%s:%u]: %s",
MXS_NOTICE("Server changed state: %s[%s:%u]: %s",
ptr->server->unique_name,
ptr->server->name, ptr->server->port,
mon_get_event_name(ptr));

View File

@ -652,7 +652,7 @@ monitorMain(void *arg)
evtype = mon_get_event_type(ptr);
if (isMySQLEvent(evtype))
{
MXS_INFO("Server changed state: %s[%s:%u]: %s",
MXS_NOTICE("Server changed state: %s[%s:%u]: %s",
ptr->server->unique_name,
ptr->server->name, ptr->server->port,
mon_get_event_name(ptr));

View File

@ -946,7 +946,7 @@ monitorMain(void *arg)
evtype = mon_get_event_type(ptr);
if (isMySQLEvent(evtype))
{
MXS_INFO("Server changed state: %s[%s:%u]: %s",
MXS_NOTICE("Server changed state: %s[%s:%u]: %s",
ptr->server->unique_name,
ptr->server->name, ptr->server->port,
mon_get_event_name(ptr));

View File

@ -417,7 +417,7 @@ monitorMain(void *arg)
evtype = mon_get_event_type(ptr);
if (isNdbEvent(evtype))
{
MXS_INFO("Server changed state: %s[%s:%u]: %s",
MXS_NOTICE("Server changed state: %s[%s:%u]: %s",
ptr->server->unique_name,
ptr->server->name, ptr->server->port,
mon_get_event_name(ptr));

View File

@ -360,6 +360,10 @@ int n_connect = 0;
}
n_connect++;
}
else
{
close(so);
}
}
}

View File

@ -353,9 +353,12 @@ static int gw_read_backend_event(DCB *dcb) {
}
spinlock_release(&dcb->delayqlock);
/* try reload users' table for next connection */
if (backend_protocol->protocol_auth_state ==
MYSQL_AUTH_FAILED)
/* Only reload the users table if authentication failed and the
* client session is not stopping. It is possible that authentication
* fails because the client has closed the connection before all
* backends have done authentication. */
if (backend_protocol->protocol_auth_state == MYSQL_AUTH_FAILED &&
dcb->session->state != SESSION_STATE_STOPPING)
{
service_refresh_users(dcb->session->service);
}
@ -694,12 +697,15 @@ gw_MySQLWrite_backend(DCB *dcb, GWBUF *queue)
switch (backend_protocol->protocol_auth_state) {
case MYSQL_HANDSHAKE_FAILED:
case MYSQL_AUTH_FAILED:
MXS_ERROR("Unable to write to backend '%s' due to "
"%s failure. Server in state %s.",
dcb->server->unique_name,
backend_protocol->protocol_auth_state == MYSQL_HANDSHAKE_FAILED ?
"handshake" : "authentication",
STRSRVSTATUS(dcb->server));
if (dcb->session->state != SESSION_STATE_STOPPING)
{
MXS_ERROR("Unable to write to backend '%s' due to "
"%s failure. Server in state %s.",
dcb->server->unique_name,
backend_protocol->protocol_auth_state == MYSQL_HANDSHAKE_FAILED ?
"handshake" : "authentication",
STRSRVSTATUS(dcb->server));
}
/** Consume query buffer */
while ((queue = gwbuf_consume(
queue,

View File

@ -20,7 +20,7 @@ add_executable(maxbinlogcheck maxbinlogcheck.c blr_file.c blr_cache.c blr_master
${CMAKE_SOURCE_DIR}/log_manager/log_manager.cc ${CMAKE_SOURCE_DIR}/server/core/externcmd.c)
target_link_libraries(maxbinlogcheck utils ssl pthread ${LZMA_LINK_FLAGS} ${EMBEDDED_LIB} ${PCRE_LINK_FLAGS} aio rt crypt dl crypto inih z m stdc++ ${CURL_LIBRARIES})
target_link_libraries(maxbinlogcheck utils ssl pthread ${LZMA_LINK_FLAGS} ${EMBEDDED_LIB} ${PCRE_LINK_FLAGS} aio rt crypt dl crypto inih z m stdc++ ${CURL_LIBRARIES} ${PCRE2_LIBRARIES})
install(TARGETS maxbinlogcheck DESTINATION bin)

View File

@ -156,6 +156,7 @@ MAXINFO_TREE *col, *table;
{
/** Unknown token after RESTART MONITOR|SERVICE */
*parse_error = PARSE_SYNTAX_ERROR;
free(text);
free_tree(tree);
return NULL;
}
@ -376,7 +377,10 @@ int i;
}
if (s1 == s2)
{
*text = NULL;
return NULL;
}
*text = strndup(s1, s2 - s1);
for (i = 0; keywords[i].text; i++)

View File

@ -569,8 +569,8 @@ char* get_shard_target_name(ROUTER_INSTANCE* router, ROUTER_CLIENT_SES* client,
query = modutil_get_SQL(buffer);
if((tmp = strcasestr(query,"from")))
{
char* tok = strtok(tmp, " ;");
tok = strtok(NULL," ;");
char *saved, *tok = strtok_r(tmp, " ;", &saved);
tok = strtok_r(NULL, " ;", &saved);
ss_dassert(tok != NULL);
tmp = (char*) hashtable_fetch(ht, tok);
@ -652,49 +652,6 @@ bool check_shard_status(ROUTER_INSTANCE* router, char* shard)
return rval;
}
/**
* Turn a string into an array of strings. The last element in the list is a NULL
* pointer.
* @param str String to tokenize
* @return Pointer to an array of strings.
*/
char** tokenize_string(char* str)
{
char *tok;
char **list = NULL;
int sz = 2, count = 0;
tok = strtok(str,", ");
if(tok == NULL)
return NULL;
list = (char**)malloc(sizeof(char*)*(sz));
while(tok)
{
if(count + 1 >= sz)
{
char** tmp = realloc(list,sizeof(char*)*(sz*2));
if(tmp == NULL)
{
char errbuf[STRERROR_BUFLEN];
MXS_ERROR("realloc returned NULL: %s.",
strerror_r(errno, errbuf, sizeof(errbuf)));
free(list);
return NULL;
}
list = tmp;
sz *= 2;
}
list[count] = strdup(tok);
count++;
tok = strtok(NULL,", ");
}
list[count] = NULL;
return list;
}
/**
* A fake DCB read function used to forward queued queries.
* @param dcb Internal DCB used by the router session
@ -1254,7 +1211,7 @@ static void* newSession(
if(db[0] != 0x0)
{
/* Store the database the client is connecting to */
strncpy(client_rses->connect_db,db,MYSQL_DATABASE_MAXLEN+1);
snprintf(client_rses->connect_db, MYSQL_DATABASE_MAXLEN + 1, "%s", db);
}
@ -3797,7 +3754,7 @@ static bool route_session_write(
unsigned char packet_type,
skygw_query_type_t qtype)
{
bool succp;
bool succp = false;
rses_property_t* prop;
backend_ref_t* backend_ref;
int i;

View File

@ -482,8 +482,8 @@ get_shard_target_name(ROUTER_INSTANCE* router, ROUTER_CLIENT_SES* client, GWBUF*
query = modutil_get_SQL(buffer);
if((tmp = strcasestr(query,"from")))
{
char* tok = strtok(tmp, " ;");
tok = strtok(NULL," ;");
char *saved, *tok = strtok_r(tmp, " ;", &saved);
tok = strtok_r(NULL, " ;", &saved);
ss_dassert(tok != NULL);
tmp = (char*) hashtable_fetch(ht, tok);
if(tmp)
@ -542,44 +542,6 @@ get_shard_target_name(ROUTER_INSTANCE* router, ROUTER_CLIENT_SES* client, GWBUF*
return rval;
}
char**
tokenize_string(char* str)
{
char *tok;
char **list = NULL;
int sz = 2, count = 0;
tok = strtok(str, ", ");
if(tok == NULL)
return NULL;
list = (char**) malloc(sizeof(char*)*(sz));
while(tok)
{
if(count + 1 >= sz)
{
char** tmp = realloc(list, sizeof(char*)*(sz * 2));
if(tmp == NULL)
{
char errbuf[STRERROR_BUFLEN];
MXS_ERROR("realloc returned NULL: %s.",
strerror_r(errno, errbuf, sizeof(errbuf)));
free(list);
return NULL;
}
list = tmp;
sz *= 2;
}
list[count] = strdup(tok);
count++;
tok = strtok(NULL, ", ");
}
list[count] = NULL;
return list;
}
/**
* This is the function used to channel replies from a subservice up to the client.
* The values passed are set in the newSession function.
@ -1497,7 +1459,7 @@ gen_show_dbs_response(ROUTER_INSTANCE* router, ROUTER_CLIENT_SES* client)
rval = gwbuf_append(rval, last_packet);
rval = gwbuf_make_contiguous(rval);
hashtable_iterator_free(iter);
return rval;
}