Merge branch 'release-1.0GA' into MAX-324

Conflicts:
	server/MaxScale_template.cnf
	server/core/service.c
This commit is contained in:
Markus Makela
2015-01-06 04:45:30 +02:00
96 changed files with 2931 additions and 1001 deletions

View File

@ -179,7 +179,7 @@ gwbuf_clone(GWBUF *buf)
{
GWBUF *rval;
if ((rval = (GWBUF *)malloc(sizeof(GWBUF))) == NULL)
if ((rval = (GWBUF *)calloc(1,sizeof(GWBUF))) == NULL)
{
ss_dassert(rval != NULL);
LOGIF(LE, (skygw_log_write_flush(
@ -194,16 +194,43 @@ GWBUF *rval;
rval->start = buf->start;
rval->end = buf->end;
rval->gwbuf_type = buf->gwbuf_type;
rval->properties = NULL;
rval->hint = NULL;
rval->gwbuf_info = buf->gwbuf_info;
rval->gwbuf_bufobj = buf->gwbuf_bufobj;
rval->next = NULL;
rval->tail = rval;
CHK_GWBUF(rval);
return rval;
}
/**
* Clone whole GWBUF list instead of single buffer.
*
* @param buf head of the list to be cloned till the tail of it
*
* @return head of the cloned list or NULL if the list was empty.
*/
GWBUF* gwbuf_clone_all(
GWBUF* buf)
{
GWBUF* rval;
GWBUF* clonebuf;
if (buf == NULL)
{
return NULL;
}
/** Store the head of the list to rval. */
clonebuf = gwbuf_clone(buf);
rval = clonebuf;
while (buf->next)
{
buf = buf->next;
clonebuf->next = gwbuf_clone(buf);
clonebuf = clonebuf->next;
}
return rval;
}
GWBUF *gwbuf_clone_portion(
GWBUF *buf,

View File

@ -1891,7 +1891,7 @@ config_truth_value(char *str)
{
return 1;
}
if (strcasecmp(str, "flase") == 0 || strcasecmp(str, "off") == 0)
if (strcasecmp(str, "false") == 0 || strcasecmp(str, "off") == 0)
{
return 0;
}

View File

@ -52,8 +52,32 @@
#include <mysqld_error.h>
#define DEFAULT_CONNECT_TIMEOUT 3
#define DEFAULT_READ_TIMEOUT 1
#define DEFAULT_WRITE_TIMEOUT 2
#define USERS_QUERY_NO_ROOT " AND user NOT IN ('root')"
#define LOAD_MYSQL_USERS_QUERY "SELECT user, host, password, concat(user,host,password,Select_priv) AS userdata, Select_priv AS anydb FROM mysql.user WHERE user IS NOT NULL AND user <> ''"
#if 0
# define LOAD_MYSQL_USERS_QUERY \
"SELECT DISTINCT \
user.user AS user, \
user.host AS host, \
user.password AS password, \
concat(user.user,user.host,user.password, \
IF((user.Select_priv+0)||find_in_set('Select',Coalesce(tp.Table_priv,0)),'Y','N') , \
COALESCE( db.db,tp.db, '')) AS userdata, \
user.Select_priv AS anydb, \
COALESCE( db.db,tp.db, NULL) AS db \
FROM \
mysql.user LEFT JOIN \
mysql.db ON user.user=db.user AND user.host=db.host LEFT JOIN \
mysql.tables_priv tp ON user.user=tp.user AND user.host=tp.host \
WHERE user.user IS NOT NULL AND user.user <> ''"
#else
# define LOAD_MYSQL_USERS_QUERY "SELECT user, host, password, concat(user,host,password,Select_priv) AS userdata, Select_priv AS anydb FROM mysql.user WHERE user IS NOT NULL AND user <> ''"
#endif
#define MYSQL_USERS_COUNT "SELECT COUNT(1) AS nusers FROM mysql.user"
#define MYSQL_USERS_WITH_DB_ORDER " ORDER BY host DESC"
@ -85,6 +109,11 @@ void *resource_fetch(HASHTABLE *, char *);
int resource_add(HASHTABLE *, char *, char *);
int resource_hash(char *);
static int normalize_hostname(char *input_host, char *output_host);
static int gw_mysql_set_timeouts(
MYSQL* handle,
int read_timeout,
int write_timeout,
int connect_timeout);
/**
* Load the user/passwd form mysql.user table into the service users' hashtable
@ -219,7 +248,7 @@ HASHTABLE *oldresources;
int add_mysql_users_with_host_ipv4(USERS *users, char *user, char *host, char *passwd, char *anydb, char *db) {
struct sockaddr_in serv_addr;
MYSQL_USER_HOST key;
char ret_ip[INET_ADDRSTRLEN + 1]="";
char ret_ip[400]="";
int ret = 0;
if (users == NULL || user == NULL || host == NULL) {
@ -409,7 +438,8 @@ getDatabases(SERVICE *service, MYSQL *con)
*
* @param service The current service
* @param users The users table into which to load the users
* @return -1 on any error or the number of users inserted (0 means no users at all)
* @return -1 on any error or the number of users inserted
* (0 means no users at all)
*/
static int
getUsers(SERVICE *service, USERS *users)
@ -421,20 +451,24 @@ getUsers(SERVICE *service, USERS *users)
char *service_passwd = NULL;
char *dpwd;
int total_users = 0;
SERVER *server;
SERVER_REF *server;
char *users_query;
unsigned char hash[SHA_DIGEST_LENGTH]="";
char *users_data = NULL;
int nusers = 0;
int users_data_row_len = MYSQL_USER_MAXLEN + MYSQL_HOST_MAXLEN + MYSQL_PASSWORD_LEN + sizeof(char) + MYSQL_DATABASE_MAXLEN;
int users_data_row_len = MYSQL_USER_MAXLEN +
MYSQL_HOST_MAXLEN +
MYSQL_PASSWORD_LEN +
sizeof(char) +
MYSQL_DATABASE_MAXLEN;
int dbnames = 0;
int db_grants = 0;
serviceGetUser(service, &service_user, &service_passwd);
if (service_user == NULL || service_passwd == NULL)
return -1;
if (serviceGetUser(service, &service_user, &service_passwd) == 0)
{
ss_dassert(service_passwd == NULL || service_user == NULL);
return -1;
}
con = mysql_init(NULL);
if (con == NULL) {
@ -444,13 +478,26 @@ getUsers(SERVICE *service, USERS *users)
mysql_error(con))));
return -1;
}
/** Set read, write and connect timeout values */
if (gw_mysql_set_timeouts(con,
DEFAULT_READ_TIMEOUT,
DEFAULT_WRITE_TIMEOUT,
DEFAULT_CONNECT_TIMEOUT))
{
LOGIF(LE, (skygw_log_write_flush(
LOGFILE_ERROR,
"Error : failed to set timeout values for backend "
"connection.")));
mysql_close(con);
return -1;
}
if (mysql_options(con, MYSQL_OPT_USE_REMOTE_CONNECTION, NULL)) {
LOGIF(LE, (skygw_log_write_flush(
LOGFILE_ERROR,
"Error : failed to set external connection. "
"It is needed for backend server connections. "
"Exiting.")));
"It is needed for backend server connections.")));
mysql_close(con);
return -1;
}
/**
@ -458,46 +505,69 @@ getUsers(SERVICE *service, USERS *users)
* out of databases
* to try
*/
server = service->databases;
server = service->dbref;
dpwd = decryptPassword(service_passwd);
/* Select a server with Master bit, if available */
while (server != NULL && !(server->status & SERVER_MASTER)) {
server = server->nextdb;
while (server != NULL && !(server->server->status & SERVER_MASTER)) {
server = server->next;
}
if (service->svc_do_shutdown)
{
free(dpwd);
mysql_close(con);
return -1;
}
/* Try loading data from master server */
if (server != NULL && (mysql_real_connect(con, server->name, service_user, dpwd, NULL, server->port, NULL, 0) != NULL)) {
if (server != NULL &&
(mysql_real_connect(con,
server->server->name, service_user,
dpwd,
NULL,
server->server->port,
NULL, 0) != NULL))
{
LOGIF(LD, (skygw_log_write_flush(
LOGFILE_DEBUG,
"Dbusers : Loading data from backend database with Master role [%s:%i] "
"for service [%s]",
server->name,
server->port,
"Dbusers : Loading data from backend database with "
"Master role [%s:%i] for service [%s]",
server->server->name,
server->server->port,
service->name)));
} else {
/* load data from other servers via loop */
server = service->databases;
server = service->dbref;
while (server != NULL && (mysql_real_connect(con,
server->name,
service_user,
dpwd,
NULL,
server->port,
NULL,
0) == NULL))
while (!service->svc_do_shutdown &&
server != NULL &&
(mysql_real_connect(con,
server->server->name,
service_user,
dpwd,
NULL,
server->server->port,
NULL,
0) == NULL))
{
server = server->nextdb;
server = server->next;
}
if (service->svc_do_shutdown)
{
free(dpwd);
mysql_close(con);
return -1;
}
if (server != NULL) {
LOGIF(LD, (skygw_log_write_flush(
LOGFILE_DEBUG,
"Dbusers : Loading data from backend database [%s:%i] "
"for service [%s]",
server->name,
server->port,
"Dbusers : Loading data from backend database "
"[%s:%i] for service [%s]",
server->server->name,
server->server->port,
service->name)));
}
}
@ -515,9 +585,7 @@ getUsers(SERVICE *service, USERS *users)
return -1;
}
/* count users */
/* start with users and db grants for users */
/** Count users. Start with users and db grants for users */
if (mysql_query(con, MYSQL_USERS_WITH_DB_COUNT)) {
if (mysql_errno(con) != ER_TABLEACCESS_DENIED_ERROR) {
/* This is an error we cannot handle, return */
@ -1193,3 +1261,58 @@ int useorig = 0;
return netmask;
}
/**
* Set read, write and connect timeout values for MySQL database connection.
*
* @param handle MySQL handle
* @param read_timeout Read timeout value in seconds
* @param write_timeout Write timeout value in seconds
* @param connect_timeout Connect timeout value in seconds
*
* @return 0 if succeed, 1 if failed
*/
static int gw_mysql_set_timeouts(
MYSQL* handle,
int read_timeout,
int write_timeout,
int connect_timeout)
{
int rc;
if ((rc = mysql_options(handle,
MYSQL_OPT_READ_TIMEOUT,
(void *)&read_timeout)))
{
LOGIF(LE, (skygw_log_write_flush(
LOGFILE_ERROR,
"Error : failed to set read timeout for backend "
"connection.")));
goto retblock;
}
if ((rc = mysql_options(handle,
MYSQL_OPT_CONNECT_TIMEOUT,
(void *)&connect_timeout)))
{
LOGIF(LE, (skygw_log_write_flush(
LOGFILE_ERROR,
"Error : failed to set connect timeout for backend "
"connection.")));
goto retblock;
}
if ((rc = mysql_options(handle,
MYSQL_OPT_WRITE_TIMEOUT,
(void *)&write_timeout)))
{
LOGIF(LE, (skygw_log_write_flush(
LOGFILE_ERROR,
"Error : failed to set write timeout for backend "
"connection.")));
goto retblock;
}
retblock:
return rc;
}

View File

@ -190,7 +190,7 @@ DCB *rval;
rval->readcheck = 0;
rval->polloutbusy = 0;
rval->writecheck = 0;
rval->fd = -1;
rval->fd = DCBFD_CLOSED;
rval->evq.next = NULL;
rval->evq.prev = NULL;
@ -235,8 +235,10 @@ DCB *rval;
void
dcb_free(DCB *dcb)
{
if (dcb->fd == -1)
if (dcb->fd == DCBFD_CLOSED)
{
dcb_final_free(dcb);
}
else
{
LOGIF(LE, (skygw_log_write_flush(
@ -308,7 +310,7 @@ DCB *clone;
return NULL;
}
clone->fd = -1;
clone->fd = DCBFD_CLOSED;
clone->flags |= DCBF_CLONE;
clone->state = orig->state;
clone->data = orig->data;
@ -319,7 +321,10 @@ DCB *clone;
clone->protocol = orig->protocol;
clone->func.write = dcb_null_write;
clone->func.close = dcb_null_close;
/**
* Close triggers closing of router session as well which is needed.
*/
clone->func.close = orig->func.close;
clone->func.auth = dcb_null_auth;
return clone;
@ -383,22 +388,25 @@ DCB_CALLBACK *cb;
*/
{
SESSION *local_session = dcb->session;
dcb->session = NULL;
CHK_SESSION(local_session);
/*<
* Remove reference from session if dcb is client.
*/
if (local_session->client == dcb) {
local_session->client = NULL;
}
dcb->session = NULL;
/**
* Set session's client pointer NULL so that other threads
* won't try to call dcb_close for client DCB
* after this call.
*/
if (local_session->client == dcb)
{
spinlock_acquire(&local_session->ses_lock);
local_session->client = NULL;
spinlock_release(&local_session->ses_lock);
}
session_free(local_session);
}
}
if (dcb->protocol && ((dcb->flags & DCBF_CLONE) ==0))
free(dcb->protocol);
if (dcb->data && ((dcb->flags & DCBF_CLONE) ==0))
free(dcb->data);
if (dcb->protocol && (!DCB_IS_CLONE(dcb)))
free(dcb->protocol);
if (dcb->remote)
free(dcb->remote);
if (dcb->user)
@ -423,7 +431,6 @@ DCB_CALLBACK *cb;
}
spinlock_release(&dcb->cb_lock);
bitmask_free(&dcb->memdata.bitmask);
free(dcb);
}
@ -551,40 +558,42 @@ bool succp = false;
DCB* dcb_next = NULL;
int rc = 0;
/*<
* Close file descriptor and move to clean-up phase.
*/
rc = close(dcb->fd);
if (dcb->fd > 0)
{
/*<
* Close file descriptor and move to clean-up phase.
*/
rc = close(dcb->fd);
if (rc < 0) {
int eno = errno;
errno = 0;
LOGIF(LE, (skygw_log_write_flush(
LOGFILE_ERROR,
"Error : Failed to close "
"socket %d on dcb %p due error %d, %s.",
dcb->fd,
dcb,
eno,
strerror(eno))));
}
#if defined(SS_DEBUG)
else {
LOGIF(LD, (skygw_log_write_flush(
LOGFILE_DEBUG,
"%lu [dcb_process_zombies] Closed socket "
"%d on dcb %p.",
pthread_self(),
dcb->fd,
dcb)));
#endif /* SS_DEBUG */
if (rc < 0)
{
int eno = errno;
errno = 0;
LOGIF(LE, (skygw_log_write_flush(
LOGFILE_ERROR,
"Error : Failed to close "
"socket %d on dcb %p due error %d, %s.",
dcb->fd,
dcb,
eno,
strerror(eno))));
}
else
{
dcb->fd = DCBFD_CLOSED;
LOGIF(LD, (skygw_log_write_flush(
LOGFILE_DEBUG,
"%lu [dcb_process_zombies] Closed socket "
"%d on dcb %p.",
pthread_self(),
dcb->fd,
dcb)));
#if defined(FAKE_CODE)
conn_open[dcb->fd] = false;
conn_open[dcb->fd] = false;
#endif /* FAKE_CODE */
#if defined(SS_DEBUG)
ss_debug(dcb->fd = -1;)
}
#endif /* SS_DEBUG */
}
}
LOGIF_MAYBE(LT, (dcb_get_ses_log_info(
dcb,
&tls_log_info.li_sesid,
@ -657,7 +666,7 @@ int rc;
}
fd = dcb->func.connect(dcb, server, session);
if (fd == -1) {
if (fd == DCBFD_CLOSED) {
LOGIF(LD, (skygw_log_write(
LOGFILE_DEBUG,
"%lu [dcb_connect] Failed to connect to server %s:%d, "
@ -683,7 +692,7 @@ int rc;
session->client,
session->client->fd)));
}
ss_dassert(dcb->fd == -1); /*< must be uninitialized at this point */
ss_dassert(dcb->fd == DCBFD_CLOSED); /*< must be uninitialized at this point */
/*<
* Successfully connected to backend. Assign file descriptor to dcb
*/
@ -704,7 +713,7 @@ int rc;
*/
rc = poll_add_dcb(dcb);
if (rc == -1) {
if (rc == DCBFD_CLOSED) {
dcb_set_state(dcb, DCB_STATE_DISCONNECTED, NULL);
dcb_final_free(dcb);
return NULL;
@ -736,11 +745,22 @@ int dcb_read(
GWBUF *buffer = NULL;
int b;
int rc;
int n ;
int n;
int nread = 0;
CHK_DCB(dcb);
while (true)
if (dcb->fd <= 0)
{
LOGIF(LE, (skygw_log_write_flush(
LOGFILE_ERROR,
"Error : Read failed, dcb is %s.",
dcb->fd == DCBFD_CLOSED ? "closed" : "cloned, not readable")));
n = 0;
goto return_n;
}
while (true)
{
int bufsize;
@ -864,6 +884,14 @@ int below_water;
below_water = (dcb->high_water && dcb->writeqlen < dcb->high_water) ? 1 : 0;
ss_dassert(queue != NULL);
if (dcb->fd <= 0)
{
LOGIF(LE, (skygw_log_write_flush(
LOGFILE_ERROR,
"Error : Write failed, dcb is %s.",
dcb->fd == DCBFD_CLOSED ? "closed" : "cloned, not writable")));
return 0;
}
/**
* SESSION_STATE_STOPPING means that one of the backends is closing
* the router session. Some backends may have not completed
@ -877,7 +905,8 @@ int below_water;
dcb->state != DCB_STATE_POLLING &&
dcb->state != DCB_STATE_LISTENING &&
dcb->state != DCB_STATE_NOPOLLING &&
dcb->session->state != SESSION_STATE_STOPPING))
(dcb->session == NULL ||
dcb->session->state != SESSION_STATE_STOPPING)))
{
LOGIF(LD, (skygw_log_write(
LOGFILE_DEBUG,
@ -888,7 +917,7 @@ int below_water;
dcb,
STRDCBSTATE(dcb->state),
dcb->fd)));
ss_dassert(false);
//ss_dassert(false);
return 0;
}
@ -1209,46 +1238,42 @@ dcb_close(DCB *dcb)
*/
if (dcb->state == DCB_STATE_POLLING)
{
if (dcb->fd != -1)
{
rc = poll_remove_dcb(dcb);
rc = poll_remove_dcb(dcb);
if (rc == 0) {
LOGIF(LD, (skygw_log_write(
LOGFILE_DEBUG,
"%lu [dcb_close] Removed dcb %p in state %s from "
"poll set.",
pthread_self(),
dcb,
STRDCBSTATE(dcb->state))));
} else {
LOGIF(LE, (skygw_log_write(
LOGFILE_ERROR,
"Error : Removing DCB fd == %d in state %s from "
"poll set failed.",
dcb->fd,
STRDCBSTATE(dcb->state))));
}
if (rc == 0)
if (rc == 0) {
LOGIF(LD, (skygw_log_write(
LOGFILE_DEBUG,
"%lu [dcb_close] Removed dcb %p in state %s from "
"poll set.",
pthread_self(),
dcb,
STRDCBSTATE(dcb->state))));
} else {
LOGIF(LE, (skygw_log_write(
LOGFILE_ERROR,
"Error : Removing DCB fd == %d in state %s from "
"poll set failed.",
dcb->fd,
STRDCBSTATE(dcb->state))));
}
if (rc == 0)
{
/**
* close protocol and router session
*/
if (dcb->func.close != NULL)
{
/**
* close protocol and router session
*/
if (dcb->func.close != NULL)
{
dcb->func.close(dcb);
}
dcb_call_callback(dcb, DCB_REASON_CLOSE);
if (dcb->state == DCB_STATE_NOPOLLING)
{
dcb_add_to_zombieslist(dcb);
}
dcb->func.close(dcb);
}
/** Call possible callback for this DCB in case of close */
dcb_call_callback(dcb, DCB_REASON_CLOSE);
if (dcb->state == DCB_STATE_NOPOLLING)
{
dcb_add_to_zombieslist(dcb);
}
}
ss_dassert(dcb->state == DCB_STATE_NOPOLLING ||
dcb->state == DCB_STATE_ZOMBIE);
}
@ -1585,7 +1610,9 @@ void dcb_hashtable_stats(
hashsize);
dcb_printf(dcb, "\tNo. of entries: %d\n", total);
dcb_printf(dcb, "\tAverage chain length: %.1f\n", (float)total / hashsize);
dcb_printf(dcb,
"\tAverage chain length: %.1f\n",
(hashsize == 0 ? (float)hashsize : (float)total / hashsize));
dcb_printf(dcb, "\tLongest chain length: %d\n", longest);
}
@ -1757,14 +1784,16 @@ static bool dcb_set_state_nomutex(
* @param dcb The DCB to write buffer
* @param buf Buffer to write
* @param nbytes Number of bytes to write
* @return Number of written bytes
*/
int
gw_write(DCB *dcb, const void *buf, size_t nbytes)
{
int w;
int w = 0;
int fd = dcb->fd;
#if defined(FAKE_CODE)
if (dcb_fake_write_errno[fd] != 0) {
if (fd > 0 && dcb_fake_write_errno[fd] != 0)
{
ss_dassert(dcb_fake_write_ev[fd] != 0);
w = write(fd, buf, nbytes/2); /*< leave peer to read missing bytes */
@ -1772,11 +1801,15 @@ gw_write(DCB *dcb, const void *buf, size_t nbytes)
w = -1;
errno = dcb_fake_write_errno[fd];
}
} else {
} else if (fd > 0)
{
w = write(fd, buf, nbytes);
}
#else
w = write(fd, buf, nbytes);
if (fd > 0)
{
w = write(fd, buf, nbytes);
}
#endif /* FAKE_CODE */
#if defined(SS_DEBUG_MYSQL)
@ -1958,6 +1991,12 @@ DCB_CALLBACK *cb, *nextcb;
{
nextcb = cb->next;
spinlock_release(&dcb->cb_lock);
LOGIF(LD, (skygw_log_write(LOGFILE_DEBUG,
"%lu [dcb_call_callback] %s",
pthread_self(),
STRDCBREASON(reason))));
cb->cb(dcb, reason, cb->userdata);
spinlock_acquire(&dcb->cb_lock);
cb = nextcb;
@ -2043,6 +2082,10 @@ dcb_get_next (DCB* dcb)
void
dcb_call_foreach(DCB_REASON reason)
{
LOGIF(LD, (skygw_log_write(LOGFILE_DEBUG,
"%lu [dcb_call_foreach]",
pthread_self())));
switch (reason) {
case DCB_REASON_CLOSE:
case DCB_REASON_DRAINED:
@ -2075,7 +2118,7 @@ dcb_call_foreach(DCB_REASON reason)
/**
* Null protocol write routine used for cloned dcb's. It merely consumes
* buffers written on the cloned DCB.
* buffers written on the cloned DCB and sets the DCB_REPLIED flag.
*
* @param dcb The descriptor control block
* @param buf The buffer being written
@ -2088,6 +2131,9 @@ dcb_null_write(DCB *dcb, GWBUF *buf)
{
buf = gwbuf_consume(buf, GWBUF_LENGTH(buf));
}
dcb->flags |= DCBF_REPLIED;
return 1;
}

View File

@ -91,28 +91,31 @@ filter_free(FILTER_DEF *filter)
{
FILTER_DEF *ptr;
/* First of all remove from the linked list */
spinlock_acquire(&filter_spin);
if (allFilters == filter)
if (filter)
{
allFilters = filter->next;
}
else
{
ptr = allFilters;
while (ptr && ptr->next != filter)
/* First of all remove from the linked list */
spinlock_acquire(&filter_spin);
if (allFilters == filter)
{
ptr = ptr->next;
allFilters = filter->next;
}
if (ptr)
ptr->next = filter->next;
}
spinlock_release(&filter_spin);
else
{
ptr = allFilters;
while (ptr && ptr->next != filter)
{
ptr = ptr->next;
}
if (ptr)
ptr->next = filter->next;
}
spinlock_release(&filter_spin);
/* Clean up session and free the memory */
free(filter->name);
free(filter->module);
free(filter);
/* Clean up session and free the memory */
free(filter->name);
free(filter->module);
free(filter);
}
}
/**

View File

@ -56,6 +56,7 @@
#include <config.h>
#include <poll.h>
#include <housekeeper.h>
#include <service.h>
#include <memlog.h>
#include <stdlib.h>
@ -572,7 +573,7 @@ return_succp:
static bool resolve_maxscale_homedir(
char** p_home_dir)
{
bool succp;
bool succp = false;
char* tmp;
char* tmp2;
char* log_context = NULL;
@ -1837,7 +1838,8 @@ return_main:
void
shutdown_server()
{
poll_shutdown();
service_shutdown();
poll_shutdown();
hkshutdown();
memlog_flush_all();
log_flush_shutdown();

View File

@ -81,7 +81,7 @@ setipaddress(struct in_addr *a, char *p) {
if ((rc = getaddrinfo(p, NULL, &hint, &ai)) != 0) {
LOGIF(LE, (skygw_log_write_flush(
LOGFILE_ERROR,
"Error : getaddrinfo failed for [%s] due [%s]",
"Error: Failed to obtain address for host %s, %s",
p,
gai_strerror(rc))));
@ -94,7 +94,7 @@ setipaddress(struct in_addr *a, char *p) {
if ((rc = getaddrinfo(p, NULL, &hint, &ai)) != 0) {
LOGIF(LE, (skygw_log_write_flush(
LOGFILE_ERROR,
"Error : getaddrinfo failed for [%s] due [%s]",
"Error: Failed to obtain address for host %s, %s",
p,
gai_strerror(rc))));

View File

@ -449,28 +449,33 @@ void hashtable_get_stats(
int i;
int j;
ht = (HASHTABLE *)table;
CHK_HASHTABLE(ht);
*nelems = 0;
*longest = 0;
hashtable_read_lock(ht);
for (i = 0; i < ht->hashsize; i++)
*nelems = 0;
*longest = 0;
*hashsize = 0;
if (table != NULL)
{
j = 0;
entries = ht->entries[i];
while (entries)
ht = (HASHTABLE *)table;
CHK_HASHTABLE(ht);
hashtable_read_lock(ht);
for (i = 0; i < ht->hashsize; i++)
{
j++;
entries = entries->next;
j = 0;
entries = ht->entries[i];
while (entries)
{
j++;
entries = entries->next;
}
*nelems += j;
if (j > *longest) {
*longest = j;
}
}
*nelems += j;
if (j > *longest) {
*longest = j;
}
*hashsize = ht->hashsize;
hashtable_read_unlock(ht);
}
*hashsize = ht->hashsize;
hashtable_read_unlock(ht);
}
@ -503,7 +508,7 @@ hashtable_read_lock(HASHTABLE *table)
;
spinlock_acquire(&table->spin);
}
table->n_readers++;
atomic_add(&table->n_readers, 1);
spinlock_release(&table->spin);
}

View File

@ -121,6 +121,40 @@ unsigned char *ptr;
return 1;
}
/**
* Calculate the length of MySQL packet and how much is missing from the GWBUF
* passed as parameter.
*
* This routine assumes that there is only one MySQL packet in the buffer.
*
* @param buf buffer list including the query, may consist of
* multiple buffers
* @param nbytes_missing pointer to missing bytecount
*
* @return the length of MySQL packet and writes missing bytecount to
* nbytes_missing.
*/
int modutil_MySQL_query_len(
GWBUF* buf,
int* nbytes_missing)
{
int len;
int buflen;
if (!modutil_is_SQL(buf))
{
len = 0;
goto retblock;
}
len = MYSQL_GET_PACKET_LEN((uint8_t *)GWBUF_DATA(buf));
*nbytes_missing = len-1;
buflen = gwbuf_length(buf);
*nbytes_missing -= buflen-5;
retblock:
return len;
}
/**
@ -178,7 +212,7 @@ GWBUF *addition;
/**
* Extract the SQL from a COM_QUERY packet and return in a NULL terminated buffer.
* The buffer shoudl be freed by the caller when it is no longer required.
* The buffer should be freed by the caller when it is no longer required.
*
* If the packet is not a COM_QUERY packet then the function will return NULL
*
@ -234,7 +268,7 @@ modutil_get_query(GWBUF *buf)
uint8_t* packet;
mysql_server_cmd_t packet_type;
size_t len;
char* query_str;
char* query_str = NULL;
packet = GWBUF_DATA(buf);
packet_type = packet[4];
@ -252,7 +286,7 @@ modutil_get_query(GWBUF *buf)
case MYSQL_COM_QUERY:
len = MYSQL_GET_PACKET_LEN(packet)-1; /*< distract 1 for packet type byte */
if ((query_str = (char *)malloc(len+1)) == NULL)
if (len < 1 || len > ~(size_t)0 - 1 || (query_str = (char *)malloc(len+1)) == NULL)
{
goto retblock;
}
@ -262,7 +296,7 @@ modutil_get_query(GWBUF *buf)
default:
len = strlen(STRPACKETTYPE(packet_type))+1;
if ((query_str = (char *)malloc(len+1)) == NULL)
if (len < 1 || len > ~(size_t)0 - 1 || (query_str = (char *)malloc(len+1)) == NULL)
{
goto retblock;
}
@ -390,3 +424,72 @@ int modutil_send_mysql_err_packet (
return dcb->func.write(dcb, buf);
}
/**
* Buffer contains at least one of the following:
* complete [complete] [partial] mysql packet
*
* return pointer to gwbuf containing a complete packet or
* NULL if no complete packet was found.
*/
GWBUF* modutil_get_next_MySQL_packet(
GWBUF** p_readbuf)
{
GWBUF* packetbuf;
GWBUF* readbuf;
size_t buflen;
size_t packetlen;
size_t totalbuflen;
uint8_t* data;
size_t nbytes_copied = 0;
uint8_t* target;
readbuf = *p_readbuf;
if (readbuf == NULL)
{
packetbuf = NULL;
goto return_packetbuf;
}
CHK_GWBUF(readbuf);
if (GWBUF_EMPTY(readbuf))
{
packetbuf = NULL;
goto return_packetbuf;
}
totalbuflen = gwbuf_length(readbuf);
data = (uint8_t *)GWBUF_DATA((readbuf));
packetlen = MYSQL_GET_PACKET_LEN(data)+4;
/** packet is incomplete */
if (packetlen > totalbuflen)
{
packetbuf = NULL;
goto return_packetbuf;
}
packetbuf = gwbuf_alloc(packetlen);
target = GWBUF_DATA(packetbuf);
packetbuf->gwbuf_type = readbuf->gwbuf_type; /*< Copy the type too */
/**
* Copy first MySQL packet to packetbuf and leave posible other
* packets to read buffer.
*/
while (nbytes_copied < packetlen && totalbuflen > 0)
{
uint8_t* src = GWBUF_DATA((*p_readbuf));
size_t bytestocopy;
buflen = GWBUF_LENGTH((*p_readbuf));
bytestocopy = MIN(buflen,packetlen-nbytes_copied);
memcpy(target+nbytes_copied, src, bytestocopy);
*p_readbuf = gwbuf_consume((*p_readbuf), bytestocopy);
totalbuflen = gwbuf_length((*p_readbuf));
nbytes_copied += bytestocopy;
}
ss_dassert(buflen == 0 || nbytes_copied == packetlen);
return_packetbuf:
return packetbuf;
}

View File

@ -341,19 +341,26 @@ poll_remove_dcb(DCB *dcb)
/*<
* Set state to NOPOLLING and remove dcb from poll set.
*/
if (dcb_set_state(dcb, new_state, &old_state)) {
rc = epoll_ctl(epoll_fd, EPOLL_CTL_DEL, dcb->fd, &ev);
if (dcb_set_state(dcb, new_state, &old_state))
{
/**
* Only positive fds can be removed from epoll set.
*/
if (dcb->fd > 0)
{
rc = epoll_ctl(epoll_fd, EPOLL_CTL_DEL, dcb->fd, &ev);
if (rc != 0) {
int eno = errno;
errno = 0;
LOGIF(LE, (skygw_log_write_flush(
LOGFILE_ERROR,
"Error : epoll_ctl failed due %d, %s.",
eno,
strerror(eno))));
}
ss_dassert(rc == 0); /*< trap in debug */
if (rc != 0) {
int eno = errno;
errno = 0;
LOGIF(LE, (skygw_log_write_flush(
LOGFILE_ERROR,
"Error : epoll_ctl failed due %d, %s.",
eno,
strerror(eno))));
}
ss_dassert(rc == 0); /*< trap in debug */
}
}
/*<
* This call was redundant, but the end result is correct.
@ -1323,7 +1330,6 @@ void poll_add_epollin_event_to_dcb(
}
static void poll_add_event_to_dcb(
DCB* dcb,
GWBUF* buf,

View File

@ -252,6 +252,7 @@ MAXKEYS key;
"Error : failed opening /dev/random. Error %d, %s.",
errno,
strerror(errno))));
close(fd);
return 1;
}
@ -260,6 +261,7 @@ MAXKEYS key;
LOGIF(LE, (skygw_log_write_flush(
LOGFILE_ERROR,
"Error : failed to read /dev/random.")));
close(fd);
close(randfd);
return 1;
}

View File

@ -68,25 +68,16 @@ server_alloc(char *servname, char *protocol, unsigned short port)
{
SERVER *server;
if ((server = (SERVER *)malloc(sizeof(SERVER))) == NULL)
if ((server = (SERVER *)calloc(1, sizeof(SERVER))) == NULL)
return NULL;
server->name = strdup(servname);
server->protocol = strdup(protocol);
server->port = port;
memset(&server->stats, 0, sizeof(SERVER_STATS));
server->status = SERVER_RUNNING;
server->nextdb = NULL;
server->monuser = NULL;
server->monpw = NULL;
server->unique_name = NULL;
server->server_string = NULL;
server->node_id = -1;
server->rlag = -2;
server->node_ts = 0;
server->parameters = NULL;
server->master_id = -1;
server->depth = -1;
server->slaves = NULL;
spinlock_acquire(&server_spin);
server->next = allServers;
@ -451,6 +442,12 @@ void
server_set_status(SERVER *server, int bit)
{
server->status |= bit;
/** clear error logged flag before the next failure */
if (SERVER_IS_MASTER(server))
{
server->master_err_is_logged = false;
}
}
/**

View File

@ -87,7 +87,6 @@ static void service_add_qualified_param(
SERVICE* svc,
CONFIG_PARAMETER* param);
/**
* Allocate a new service for the gateway to support
*
@ -102,7 +101,7 @@ service_alloc(const char *servname, const char *router)
{
SERVICE *service;
if ((service = (SERVICE *)malloc(sizeof(SERVICE))) == NULL)
if ((service = (SERVICE *)calloc(1, sizeof(SERVICE))) == NULL)
return NULL;
if ((service->router = load_module(router, MODULE_ROUTER)) == NULL)
{
@ -132,27 +131,10 @@ SERVICE *service;
free(service);
return NULL;
}
service->version_string = NULL;
memset(&service->stats, 0, sizeof(SERVICE_STATS));
service->ports = NULL;
service->stats.started = time(0);
service->state = SERVICE_STATE_ALLOC;
service->credentials.name = NULL;
service->credentials.authdata = NULL;
service->enable_root = 0;
service->localhost_match_wildcard_host = 0;
service->routerOptions = NULL;
service->databases = NULL;
service->svc_config_param = NULL;
service->svc_config_version = 0;
service->filters = NULL;
service->n_filters = 0;
service->weightby = 0;
service->users = NULL;
service->resources = NULL;
spinlock_init(&service->spin);
spinlock_init(&service->users_table_spin);
memset(&service->rate_limit, 0, sizeof(SERVICE_REFRESH_RATE));
spinlock_acquire(&service_spin);
service->next = allServices;
@ -233,11 +215,6 @@ GWPROTOCOL *funcs;
(port->address == NULL ? "0.0.0.0" : port->address),
port->port,
service->name)));
hashtable_free(service->users->data);
free(service->users);
dcb_free(port->listener);
port->listener = NULL;
goto retblock;
}
/* At service start last update is set to USERS_REFRESH_TIME seconds earlier.
* This way MaxScale could try reloading users' just after startup
@ -349,28 +326,28 @@ serviceStart(SERVICE *service)
SERV_PROTOCOL *port;
int listeners = 0;
service->router_instance = service->router->createInstance(service,
service->routerOptions);
if ((service->router_instance = service->router->createInstance(service,
service->routerOptions)) == NULL)
{
LOGIF(LE, (skygw_log_write_flush(LOGFILE_ERROR,
"%s: Failed to create router instance for service. Service not started.",
service->name)));
service->state = SERVICE_STATE_FAILED;
return 0;
}
if (service->router_instance == NULL)
port = service->ports;
while (!service->svc_do_shutdown && port)
{
LOGIF(LE, (skygw_log_write_flush(
LOGFILE_ERROR,
"Error : starting the %s service failed.",
service->name)));
listeners += serviceStartPort(service, port);
port = port->next;
}
else
if (listeners)
{
port = service->ports;
while (port)
{
listeners += serviceStartPort(service, port);
port = port->next;
}
if (listeners)
service->stats.started = time(0);
service->state = SERVICE_STATE_STARTED;
service->stats.started = time(0);
}
return listeners;
}
@ -405,12 +382,21 @@ int
serviceStartAll()
{
SERVICE *ptr;
int n = 0;
int n = 0,i;
ptr = allServices;
while (ptr)
while (ptr && !ptr->svc_do_shutdown)
{
n += serviceStart(ptr);
n += (i = serviceStart(ptr));
if(i == 0)
{
LOGIF(LE, (skygw_log_write(
LOGFILE_ERROR,
"Error : Failed to start service '%s'.",
ptr->name)));
}
ptr = ptr->next;
}
return n;
@ -439,6 +425,7 @@ int listeners = 0;
port = port->next;
}
service->state = SERVICE_STATE_STOPPED;
return listeners;
}
@ -481,7 +468,7 @@ int
service_free(SERVICE *service)
{
SERVICE *ptr;
SERVER_REF *srv;
if (service->stats.n_current)
return 0;
/* First of all remove from the linked list */
@ -503,6 +490,13 @@ SERVICE *ptr;
spinlock_release(&service_spin);
/* Clean up session and free the memory */
while(service->dbref){
srv = service->dbref;
service->dbref = service->dbref->next;
free(srv);
}
free(service->name);
free(service->routerModule);
if (service->credentials.name)
@ -581,8 +575,13 @@ void
serviceAddBackend(SERVICE *service, SERVER *server)
{
spinlock_acquire(&service->spin);
server->nextdb = service->databases;
service->databases = server;
SERVER_REF *sref;
if((sref = calloc(1,sizeof(SERVER_REF))) != NULL)
{
sref->next = service->dbref;
sref->server = server;
service->dbref = sref;
}
spinlock_release(&service->spin);
}
@ -596,12 +595,12 @@ serviceAddBackend(SERVICE *service, SERVER *server)
int
serviceHasBackend(SERVICE *service, SERVER *server)
{
SERVER *ptr;
SERVER_REF *ptr;
spinlock_acquire(&service->spin);
ptr = service->databases;
while (ptr && ptr != server)
ptr = ptr->nextdb;
ptr = service->dbref;
while (ptr && ptr->server != server)
ptr = ptr->next;
spinlock_release(&service->spin);
return ptr != NULL;
@ -759,7 +758,7 @@ int n = 0;
if ((flist = (FILTER_DEF **)malloc(sizeof(FILTER_DEF *))) == NULL)
{
LOGIF(LE, (skygw_log_write_flush(LOGFILE_ERROR,
"Out of memory adding filters to service.\n")));
"Error : Out of memory adding filters to service.\n")));
return;
}
ptr = strtok_r(filters, "|", &brkt);
@ -770,14 +769,14 @@ int n = 0;
(n + 1) * sizeof(FILTER_DEF *))) == NULL)
{
LOGIF(LE, (skygw_log_write_flush(LOGFILE_ERROR,
"Out of memory adding filters to service.\n")));
"Error : Out of memory adding filters to service.\n")));
return;
}
if ((flist[n-1] = filter_find(trim(ptr))) == NULL)
{
LOGIF(LE, (skygw_log_write_flush(
LOGFILE_ERROR,
"Unable to find filter '%s' for service '%s'\n",
"Warning : Unable to find filter '%s' for service '%s'\n",
trim(ptr), service->name
)));
n--;
@ -819,7 +818,7 @@ SERVICE *service;
void
printService(SERVICE *service)
{
SERVER *ptr = service->databases;
SERVER_REF *ptr = service->dbref;
struct tm result;
char time_buf[30];
int i;
@ -832,8 +831,8 @@ int i;
printf("\tBackend databases\n");
while (ptr)
{
printf("\t\t%s:%d Protocol: %s\n", ptr->name, ptr->port, ptr->protocol);
ptr = ptr->nextdb;
printf("\t\t%s:%d Protocol: %s\n", ptr->server->name, ptr->server->port, ptr->server->protocol);
ptr = ptr->next;
}
if (service->n_filters)
{
@ -900,7 +899,7 @@ SERVICE *ptr;
*/
void dprintService(DCB *dcb, SERVICE *service)
{
SERVER *server = service->databases;
SERVER_REF *server = service->dbref;
struct tm result;
char timebuf[30];
int i;
@ -910,7 +909,22 @@ int i;
service->name);
dcb_printf(dcb, "\tRouter: %s (%p)\n",
service->routerModule, service->router);
if (service->router)
switch (service->state)
{
case SERVICE_STATE_STARTED:
dcb_printf(dcb, "\tState: Started\n");
break;
case SERVICE_STATE_STOPPED:
dcb_printf(dcb, "\tState: Stopped\n");
break;
case SERVICE_STATE_FAILED:
dcb_printf(dcb, "\tState: Failed\n");
break;
case SERVICE_STATE_ALLOC:
dcb_printf(dcb, "\tState: Allocated\n");
break;
}
if (service->router && service->router_instance)
service->router->diagnostics(service->router_instance, dcb);
dcb_printf(dcb, "\tStarted: %s",
asctime_r(localtime_r(&service->stats.started, &result), timebuf));
@ -929,9 +943,9 @@ int i;
dcb_printf(dcb, "\tBackend databases\n");
while (server)
{
dcb_printf(dcb, "\t\t%s:%d Protocol: %s\n", server->name, server->port,
server->protocol);
server = server->nextdb;
dcb_printf(dcb, "\t\t%s:%d Protocol: %s\n", server->server->name, server->server->port,
server->server->protocol);
server = server->next;
}
if (service->weightby)
dcb_printf(dcb, "\tRouting weight parameter: %s\n",
@ -1397,3 +1411,16 @@ serviceEnableLocalhostMatchWildcardHost(SERVICE *service, int action)
return 1;
}
void service_shutdown()
{
SERVICE* svc;
spinlock_acquire(&service_spin);
svc = allServices;
while (svc != NULL)
{
svc->svc_do_shutdown = true;
svc = svc->next;
}
spinlock_release(&service_spin);
}

View File

@ -85,12 +85,21 @@ session_alloc(SERVICE *service, DCB *client_dcb)
"session object due error %d, %s.",
errno,
strerror(errno))));
if (client_dcb->data && !DCB_IS_CLONE(client_dcb))
{
free(client_dcb->data);
client_dcb->data = NULL;
}
goto return_session;
}
#if defined(SS_DEBUG)
session->ses_chk_top = CHK_NUM_SESSION;
session->ses_chk_tail = CHK_NUM_SESSION;
#endif
if (DCB_IS_CLONE(client_dcb))
{
session->ses_is_child = true;
}
spinlock_init(&session->ses_lock);
/*<
* Prevent backend threads from accessing before session is completely
@ -149,6 +158,7 @@ session_alloc(SERVICE *service, DCB *client_dcb)
* Decrease refcount, set dcb's session pointer NULL
* and set session pointer to NULL.
*/
session->client = NULL;
session_free(session);
client_dcb->session = NULL;
session = NULL;
@ -189,6 +199,7 @@ session_alloc(SERVICE *service, DCB *client_dcb)
* Decrease refcount, set dcb's session pointer NULL
* and set session pointer to NULL.
*/
session->client = NULL;
session_free(session);
client_dcb->session = NULL;
session = NULL;
@ -207,6 +218,7 @@ session_alloc(SERVICE *service, DCB *client_dcb)
if (session->state != SESSION_STATE_READY)
{
spinlock_release(&session->ses_lock);
session->client = NULL;
session_free(session);
client_dcb->session = NULL;
session = NULL;
@ -331,12 +343,16 @@ int session_unlink_dcb(
if (nlink == 0)
{
session->state = SESSION_STATE_FREE;
session->state = SESSION_STATE_TO_BE_FREED;
}
if (dcb != NULL)
{
dcb->session = NULL;
if (session->client == dcb)
{
session->client = NULL;
}
dcb->session = NULL;
}
spinlock_release(&session->ses_lock);
@ -357,7 +373,6 @@ bool session_free(
int i;
CHK_SESSION(session);
/*<
* Remove one reference. If there are no references left,
* free session.
@ -388,8 +403,12 @@ bool session_free(
spinlock_release(&session_spin);
atomic_add(&session->service->stats.n_current, -1);
/* Free router_session and session */
if (session->router_session) {
/**
* If session is not child of some other session, free router_session.
* Otherwise let the parent free it.
*/
if (!session->ses_is_child && session->router_session)
{
session->service->router->freeSession(
session->service->router_instance,
session->router_session);
@ -422,7 +441,17 @@ bool session_free(
/** Disable trace and decrease trace logger counter */
session_disable_log(session, LT);
free(session);
/** If session doesn't have parent referencing to it, it can be freed */
if (!session->ses_is_child)
{
session->state = SESSION_STATE_FREE;
if (session->data)
{
free(session->data);
}
free(session);
}
succp = true;
return_succp :
@ -687,6 +716,15 @@ session_state(int state)
return "Listener Session";
case SESSION_STATE_LISTENER_STOPPED:
return "Stopped Listener Session";
#ifdef SS_DEBUG
case SESSION_STATE_STOPPING:
return "Stopping session";
case SESSION_STATE_TO_BE_FREED:
return "Session to be freed";
case SESSION_STATE_FREE:
return "Freed session";
#endif
default:
return "Invalid State";
}

View File

@ -35,7 +35,7 @@ add_test(TestBuffer test_buffer)
add_test(TestDCB test_dcb)
add_test(TestModutil test_modutil)
add_test(TestPoll test_poll)
add_test(TestService test_service)
add_test(TestService /bin/sh -c " MAXSCALE_HOME=${CMAKE_BINARY_DIR} && ${CMAKE_CURRENT_BINAR_DIR}/test_service")
add_test(TestServer test_server)
add_test(TestUsers test_users)
add_test(TestAdminUsers test_adminusers)

View File

@ -272,6 +272,8 @@ char *home, buf[1024];
if ((home = getenv("MAXSCALE_HOME")) == NULL || strlen(home) >= 1024)
home = "/usr/local/skysql";
sprintf(buf, "%s/etc/passwd", home);
if(!is_valid_posix_path(buf))
exit(1);
if (strcmp(buf, "/etc/passwd") != 0)
unlink(buf);

View File

@ -49,11 +49,13 @@ HINT *hint;
char* name = strdup("name");
hint = hint_create_parameter(NULL, name, "value");
free(name);
skygw_log_sync_all();
ss_info_dassert(NULL != hint, "New hint list should not be null");
ss_info_dassert(0 == strcmp("value", hint->value), "Hint value should be correct");
ss_info_dassert(0 != hint_exists(&hint, HINT_PARAMETER), "Hint of parameter type should exist");
ss_dfprintf(stderr, "\t..done\nFree hints.");
if (NULL != hint) hint_free(hint);
skygw_log_sync_all();
ss_dfprintf(stderr, "\t..done\n");
return 0;

View File

@ -51,7 +51,7 @@ int result;
"testpoll : Initialise the polling system.");
poll_init();
ss_dfprintf(stderr, "\t..done\nAdd a DCB");
dcb = dcb_alloc(DCB_ROLE_SERVICE_LISTENER);
dcb = dcb_alloc(DCB_ROLE_REQUEST_HANDLER);
if(dcb == NULL){
ss_dfprintf(stderr, "\nError on function call: dcb_alloc() returned NULL.\n");

View File

@ -48,7 +48,7 @@ char *status;
ss_dfprintf(stderr,
"testserver : creating server called MyServer");
server = server_alloc("MyServer", "HTTPD", 9876);
skygw_log_sync_all();
//ss_info_dassert(NULL != service, "New server with valid protocol and port must not be null");
//ss_info_dassert(0 != service_isvalid(service), "Service must be valid after creation");
@ -56,26 +56,32 @@ char *status;
ss_dfprintf(stderr, "\t..done\nTest Parameter for Server.");
ss_info_dassert(NULL == serverGetParameter(server, "name"), "Parameter should be null when not set");
serverAddParameter(server, "name", "value");
skygw_log_sync_all();
ss_info_dassert(0 == strcmp("value", serverGetParameter(server, "name")), "Parameter should be returned correctly");
ss_dfprintf(stderr, "\t..done\nTesting Unique Name for Server.");
ss_info_dassert(NULL == server_find_by_unique_name("uniquename"), "Should not find non-existent unique name.");
server_set_unique_name(server, "uniquename");
skygw_log_sync_all();
ss_info_dassert(server == server_find_by_unique_name("uniquename"), "Should find by unique name.");
ss_dfprintf(stderr, "\t..done\nTesting Status Setting for Server.");
status = server_status(server);
skygw_log_sync_all();
ss_info_dassert(0 == strcmp("Running", status), "Status of Server should be Running by default.");
if (NULL != status) free(status);
server_set_status(server, SERVER_MASTER);
status = server_status(server);
skygw_log_sync_all();
ss_info_dassert(0 == strcmp("Master, Running", status), "Should find correct status.");
server_clear_status(server, SERVER_MASTER);
free(status);
status = server_status(server);
skygw_log_sync_all();
ss_info_dassert(0 == strcmp("Running", status), "Status of Server should be Running after master status cleared.");
if (NULL != status) free(status);
ss_dfprintf(stderr, "\t..done\nRun Prints for Server and all Servers.");
printServer(server);
printAllServers();
skygw_log_sync_all();
ss_dfprintf(stderr, "\t..done\nFreeing Server.");
ss_info_dassert(0 != server_free(server), "Free should succeed");
ss_dfprintf(stderr, "\t..done\n");

View File

@ -30,7 +30,7 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <maxscale_test.h>
#include <service.h>
/**
@ -42,15 +42,27 @@ test1()
{
SERVICE *service;
int result;
int argc = 3;
char buffer[1024];
sprintf(buffer,"%s",TEST_LOG_DIR);
char* argv[] = {
"log_manager",
"-j",
buffer,
NULL
};
skygw_logmanager_init(argc,argv);
/* Service tests */
ss_dfprintf(stderr,
"testservice : creating service called MyService with router nonexistent");
service = service_alloc("MyService", "non-existent");
skygw_log_sync_all();
ss_info_dassert(NULL == service, "New service with invalid router should be null");
ss_info_dassert(0 == service_isvalid(service), "Service must not be valid after incorrect creation");
ss_dfprintf(stderr, "\t..done\nValid service creation, router testroute.");
service = service_alloc("MyService", "testroute");
skygw_log_sync_all();
ss_info_dassert(NULL != service, "New service with valid router must not be null");
ss_info_dassert(0 != service_isvalid(service), "Service must be valid after creation");
ss_info_dassert(0 == strcmp("MyService", service_get_name(service)), "Service must have given name");
@ -58,12 +70,16 @@ int result;
ss_info_dassert(0 != serviceAddProtocol(service, "HTTPD", "localhost", 9876), "Add Protocol should succeed");
ss_info_dassert(0 != serviceHasProtocol(service, "HTTPD", 9876), "Service should have new protocol as requested");
serviceStartProtocol(service, "HTTPD", 9876);
skygw_log_sync_all();
ss_dfprintf(stderr, "\t..done\nStarting Service.");
result = serviceStart(service);
skygw_log_sync_all();
ss_info_dassert(0 != result, "Start should succeed");
result = serviceStop(service);
skygw_log_sync_all();
ss_info_dassert(0 != result, "Stop should succeed");
result = serviceStartAll();
skygw_log_sync_all();
ss_info_dassert(0 != result, "Start all should succeed");
ss_dfprintf(stderr, "\t..done\nStopping Service.");

View File

@ -33,6 +33,8 @@
#include <users.h>
#include "log_manager.h"
/**
* test1 Allocate table of users and mess around with it
*
@ -49,26 +51,34 @@ int result, count;
ss_dfprintf(stderr,
"testusers : Initialise the user table.");
users = users_alloc();
skygw_log_sync_all();
ss_info_dassert(NULL != users, "Allocating user table should not return NULL.")
ss_dfprintf(stderr, "\t..done\nAdd a user");
count = users_add(users, "username", "authorisation");
skygw_log_sync_all();
ss_info_dassert(1 == count, "Should add one user");
authdata = users_fetch(users, "username");
skygw_log_sync_all();
ss_info_dassert(NULL != authdata, "Fetch valid user must not return NULL");
ss_info_dassert(0 == strcmp("authorisation", authdata), "User authorisation should be correct");
ss_dfprintf(stderr, "\t..done\nPrint users");
usersPrint(users);
skygw_log_sync_all();
ss_dfprintf(stderr, "\t..done\nUpdate a user");
count = users_update(users, "username", "newauth");
skygw_log_sync_all();
ss_info_dassert(1 == count, "Should update just one user");
authdata = users_fetch(users, "username");
skygw_log_sync_all();
ss_info_dassert(NULL != authdata, "Fetch valid user must not return NULL");
ss_info_dassert(0 == strcmp("newauth", authdata), "User authorisation should be correctly updated");
ss_dfprintf(stderr, "\t..done\nDelete a user.");
count = users_delete(users, "username");
skygw_log_sync_all();
ss_info_dassert(1 == count, "Should delete just one user");
ss_dfprintf(stderr, "\t..done\nFree user table.");
users_free(users);
skygw_log_sync_all();
ss_dfprintf(stderr, "\t..done\n");
return 0;

View File

@ -183,32 +183,41 @@ char *sep;
void *user;
dcb_printf(dcb, "Users table data\n");
dcb_hashtable_stats(dcb, users->data);
if ((iter = hashtable_iterator(users->data)) != NULL)
if (users == NULL || users->data == NULL)
{
dcb_printf(dcb, "User names: ");
sep = "";
dcb_printf(dcb, "Users table is empty\n");
}
else
{
dcb_hashtable_stats(dcb, users->data);
if ((iter = hashtable_iterator(users->data)) != NULL)
{
dcb_printf(dcb, "User names: ");
sep = "";
if (users->usersCustomUserFormat != NULL) {
while ((user = hashtable_next(iter)) != NULL)
{
char *custom_user;
custom_user = users->usersCustomUserFormat(user);
if (custom_user) {
dcb_printf(dcb, "%s%s", sep, custom_user);
free(custom_user);
if (users->usersCustomUserFormat != NULL) {
while ((user = hashtable_next(iter)) != NULL)
{
char *custom_user;
custom_user = users->usersCustomUserFormat(user);
if (custom_user) {
dcb_printf(dcb, "%s%s", sep, custom_user);
free(custom_user);
sep = ", ";
}
}
} else {
while ((user = hashtable_next(iter)) != NULL)
{
dcb_printf(dcb, "%s%s", sep, (char *)user);
sep = ", ";
}
}
} else {
while ((user = hashtable_next(iter)) != NULL)
{
dcb_printf(dcb, "%s%s", sep, (char *)user);
sep = ", ";
}
}
dcb_printf(dcb, "\n");
hashtable_iterator_free(iter);
hashtable_iterator_free(iter);
}
}
dcb_printf(dcb, "\n");
}