Merge
This commit is contained in:
5
Makefile
5
Makefile
@ -21,6 +21,7 @@
|
|||||||
# targets
|
# targets
|
||||||
# 18/06/13 Mark Riddoch Addition of install target
|
# 18/06/13 Mark Riddoch Addition of install target
|
||||||
# 21/06/13 Mark Riddoch Addition of inih
|
# 21/06/13 Mark Riddoch Addition of inih
|
||||||
|
# 08/07/13 Mark Riddoch Addition of monitor modules
|
||||||
|
|
||||||
DEST=/usr/local/skysql
|
DEST=/usr/local/skysql
|
||||||
|
|
||||||
@ -30,17 +31,20 @@ all:
|
|||||||
(cd modules/routing; make)
|
(cd modules/routing; make)
|
||||||
(cd modules/routing/readwritesplit; make)
|
(cd modules/routing/readwritesplit; make)
|
||||||
(cd modules/protocol; make)
|
(cd modules/protocol; make)
|
||||||
|
(cd modules/monitor; make)
|
||||||
|
|
||||||
clean:
|
clean:
|
||||||
(cd Documentation; rm -rf html)
|
(cd Documentation; rm -rf html)
|
||||||
(cd core; make clean)
|
(cd core; make clean)
|
||||||
(cd modules/routing; make clean)
|
(cd modules/routing; make clean)
|
||||||
(cd modules/protocol; make clean)
|
(cd modules/protocol; make clean)
|
||||||
|
(cd modules/monitor; make clean)
|
||||||
|
|
||||||
depend:
|
depend:
|
||||||
(cd core; make depend)
|
(cd core; make depend)
|
||||||
(cd modules/routing; make depend)
|
(cd modules/routing; make depend)
|
||||||
(cd modules/protocol; make depend)
|
(cd modules/protocol; make depend)
|
||||||
|
(cd modules/monitor; make depend)
|
||||||
|
|
||||||
documentation:
|
documentation:
|
||||||
doxygen doxygate
|
doxygen doxygate
|
||||||
@ -49,3 +53,4 @@ install:
|
|||||||
(cd core; make DEST=$(DEST) install)
|
(cd core; make DEST=$(DEST) install)
|
||||||
(cd modules/routing; make DEST=$(DEST) install)
|
(cd modules/routing; make DEST=$(DEST) install)
|
||||||
(cd modules/protocol; make DEST=$(DEST) install)
|
(cd modules/protocol; make DEST=$(DEST) install)
|
||||||
|
(cd modules/moinitor; make DEST=$(DEST) install)
|
||||||
|
|||||||
@ -55,7 +55,8 @@ LDFLAGS=-rdynamic -L$(LOGPATH) \
|
|||||||
|
|
||||||
SRCS= atomic.c buffer.c spinlock.c gateway.c gateway_mysql_protocol.c \
|
SRCS= atomic.c buffer.c spinlock.c gateway.c gateway_mysql_protocol.c \
|
||||||
gw_utils.c utils.c dcb.c load_utils.c session.c service.c server.c \
|
gw_utils.c utils.c dcb.c load_utils.c session.c service.c server.c \
|
||||||
poll.c config.c users.c hashtable.c dbusers.c thread.c gwbitmask.c
|
poll.c config.c users.c hashtable.c dbusers.c thread.c gwbitmask.c \
|
||||||
|
monitor.c
|
||||||
|
|
||||||
HDRS= ../include/atomic.h ../include/buffer.h ../include/dcb.h \
|
HDRS= ../include/atomic.h ../include/buffer.h ../include/dcb.h \
|
||||||
../include/gateway_mysql.h ../include/gw.h ../include/mysql_protocol.h \
|
../include/gateway_mysql.h ../include/gw.h ../include/mysql_protocol.h \
|
||||||
|
|||||||
@ -24,6 +24,7 @@
|
|||||||
*
|
*
|
||||||
* Date Who Description
|
* Date Who Description
|
||||||
* 21/06/13 Mark Riddoch Initial implementation
|
* 21/06/13 Mark Riddoch Initial implementation
|
||||||
|
* 08/07/13 mark Riddoch Addition on monitor module support
|
||||||
*
|
*
|
||||||
* @endverbatim
|
* @endverbatim
|
||||||
*/
|
*/
|
||||||
@ -35,6 +36,7 @@
|
|||||||
#include <service.h>
|
#include <service.h>
|
||||||
#include <server.h>
|
#include <server.h>
|
||||||
#include <users.h>
|
#include <users.h>
|
||||||
|
#include <monitor.h>
|
||||||
|
|
||||||
static int process_config_context(CONFIG_CONTEXT *);
|
static int process_config_context(CONFIG_CONTEXT *);
|
||||||
static void free_config_context(CONFIG_CONTEXT *);
|
static void free_config_context(CONFIG_CONTEXT *);
|
||||||
@ -155,8 +157,12 @@ CONFIG_CONTEXT *obj;
|
|||||||
char *address = config_get_value(obj->parameters, "address");
|
char *address = config_get_value(obj->parameters, "address");
|
||||||
char *port = config_get_value(obj->parameters, "port");
|
char *port = config_get_value(obj->parameters, "port");
|
||||||
char *protocol = config_get_value(obj->parameters, "protocol");
|
char *protocol = config_get_value(obj->parameters, "protocol");
|
||||||
|
char *monuser = config_get_value(obj->parameters, "monitoruser");
|
||||||
|
char *monpw = config_get_value(obj->parameters, "monitorpw");
|
||||||
if (address && port && protocol)
|
if (address && port && protocol)
|
||||||
obj->element = server_alloc(address, protocol, atoi(port));
|
obj->element = server_alloc(address, protocol, atoi(port));
|
||||||
|
if (obj->element && monuser && monpw)
|
||||||
|
serverAddMonUser(obj->element, monuser, monpw);
|
||||||
}
|
}
|
||||||
|
|
||||||
obj = obj->next;
|
obj = obj->next;
|
||||||
@ -215,6 +221,30 @@ CONFIG_CONTEXT *obj;
|
|||||||
serviceAddProtocol(ptr->element, protocol, atoi(port));
|
serviceAddProtocol(ptr->element, protocol, atoi(port));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
else if (!strcmp(type, "monitor"))
|
||||||
|
{
|
||||||
|
char *module = config_get_value(obj->parameters, "module");
|
||||||
|
char *servers = config_get_value(obj->parameters, "servers");
|
||||||
|
if (module)
|
||||||
|
{
|
||||||
|
obj->element = monitor_alloc(obj->object, module);
|
||||||
|
if (servers && obj->element)
|
||||||
|
{
|
||||||
|
char *s = strtok(servers, ",");
|
||||||
|
while (s)
|
||||||
|
{
|
||||||
|
CONFIG_CONTEXT *obj1 = context;
|
||||||
|
while (obj1)
|
||||||
|
{
|
||||||
|
if (strcmp(s, obj1->object) == 0 && obj->element && obj1->element)
|
||||||
|
monitorAddServer(obj->element, obj1->element);
|
||||||
|
obj1 = obj1->next;
|
||||||
|
}
|
||||||
|
s = strtok(NULL, ",");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
obj = obj->next;
|
obj = obj->next;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -45,13 +45,14 @@
|
|||||||
int
|
int
|
||||||
load_mysql_users(SERVICE *service)
|
load_mysql_users(SERVICE *service)
|
||||||
{
|
{
|
||||||
MYSQL* con = NULL;
|
MYSQL *con = NULL;
|
||||||
MYSQL_ROW row;
|
MYSQL_ROW row;
|
||||||
MYSQL_RES* result = NULL;
|
MYSQL_RES *result = NULL;
|
||||||
int num_fields = 0;
|
int num_fields = 0;
|
||||||
char* service_user = NULL;
|
char *service_user = NULL;
|
||||||
char* service_passwd = NULL;
|
char *service_passwd = NULL;
|
||||||
int total_users = 0;
|
int total_users = 0;
|
||||||
|
SERVER *server;
|
||||||
|
|
||||||
serviceGetUser(service, &service_user, &service_passwd);
|
serviceGetUser(service, &service_user, &service_passwd);
|
||||||
/** multi-thread environment requires that thread init succeeds. */
|
/** multi-thread environment requires that thread init succeeds. */
|
||||||
@ -67,15 +68,25 @@ load_mysql_users(SERVICE *service)
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (mysql_real_connect(
|
/*
|
||||||
con,
|
* Attempt to connect to each database in the service in turn until
|
||||||
service->databases->name,
|
* we find one that we can connect to or until we run out of databases
|
||||||
service_user,
|
* to try
|
||||||
service_passwd,
|
*/
|
||||||
NULL,
|
server = service->databases;
|
||||||
service->databases->port,
|
while (server && mysql_real_connect(con,
|
||||||
NULL, 0) == NULL)
|
server->name,
|
||||||
{
|
service_user,
|
||||||
|
service_passwd,
|
||||||
|
NULL,
|
||||||
|
server->port,
|
||||||
|
NULL,
|
||||||
|
0) == NULL)
|
||||||
|
{
|
||||||
|
server = server->nextdb;
|
||||||
|
}
|
||||||
|
if (server == NULL)
|
||||||
|
{
|
||||||
fprintf(stderr, "%s\n", mysql_error(con));
|
fprintf(stderr, "%s\n", mysql_error(con));
|
||||||
mysql_close(con);
|
mysql_close(con);
|
||||||
return -1;
|
return -1;
|
||||||
|
|||||||
@ -183,6 +183,7 @@ dcb_final_free(DCB *dcb)
|
|||||||
free(dcb->data);
|
free(dcb->data);
|
||||||
if (dcb->remote)
|
if (dcb->remote)
|
||||||
free(dcb->remote);
|
free(dcb->remote);
|
||||||
|
bitmask_free(&dcb->memdata.bitmask);
|
||||||
free(dcb);
|
free(dcb);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -635,7 +636,7 @@ va_list args;
|
|||||||
vsnprintf(GWBUF_DATA(buf), 10240, fmt, args);
|
vsnprintf(GWBUF_DATA(buf), 10240, fmt, args);
|
||||||
va_end(args);
|
va_end(args);
|
||||||
|
|
||||||
buf->end = GWBUF_DATA(buf) + strlen(GWBUF_DATA(buf)) + 1;
|
buf->end = GWBUF_DATA(buf) + strlen(GWBUF_DATA(buf));
|
||||||
dcb->func.write(dcb, buf);
|
dcb->func.write(dcb, buf);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -53,6 +53,21 @@ bitmask_init(GWBITMASK *bitmask)
|
|||||||
spinlock_init(&bitmask->lock);
|
spinlock_init(&bitmask->lock);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Free a bitmask that is no longer required
|
||||||
|
*
|
||||||
|
* @param bitmask
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
bitmask_free(GWBITMASK *bitmask)
|
||||||
|
{
|
||||||
|
if (bitmask->length)
|
||||||
|
{
|
||||||
|
free(bitmask->bits);
|
||||||
|
bitmask->length = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Set the bit at the specified bit position in the bitmask.
|
* Set the bit at the specified bit position in the bitmask.
|
||||||
* The bitmask will automatically be extended if the bit is
|
* The bitmask will automatically be extended if the bit is
|
||||||
|
|||||||
116
core/monitor.c
Normal file
116
core/monitor.c
Normal file
@ -0,0 +1,116 @@
|
|||||||
|
/*
|
||||||
|
* This file is distributed as part of the SkySQL Gateway. It is free
|
||||||
|
* software: you can redistribute it and/or modify it under the terms of the
|
||||||
|
* GNU General Public License as published by the Free Software Foundation,
|
||||||
|
* version 2.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||||
|
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||||
|
* FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
|
||||||
|
* details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License along with
|
||||||
|
* this program; if not, write to the Free Software Foundation, Inc., 51
|
||||||
|
* Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||||
|
*
|
||||||
|
* Copyright SkySQL Ab 2013
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @file monitor.c - The monitor module management routines
|
||||||
|
*
|
||||||
|
* @verbatim
|
||||||
|
* Revision History
|
||||||
|
*
|
||||||
|
* Date Who Description
|
||||||
|
* 08/07/13 Mark Riddoch Initial implementation
|
||||||
|
*
|
||||||
|
* @endverbatim
|
||||||
|
*/
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <monitor.h>
|
||||||
|
#include <spinlock.h>
|
||||||
|
#include <modules.h>
|
||||||
|
|
||||||
|
|
||||||
|
static MONITOR *allMonitors = NULL;
|
||||||
|
static SPINLOCK monLock = SPINLOCK_INIT;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Allocate a new monitor, load the associated module for the monitor
|
||||||
|
* and start execution on the monitor.
|
||||||
|
*
|
||||||
|
* @param name The name of the monitor module to load
|
||||||
|
* @return The newly created monitor
|
||||||
|
*/
|
||||||
|
MONITOR *
|
||||||
|
monitor_alloc(char *name, char *module)
|
||||||
|
{
|
||||||
|
MONITOR *mon;
|
||||||
|
|
||||||
|
if ((mon = (MONITOR *)malloc(sizeof(MONITOR))) == NULL)
|
||||||
|
{
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
mon->name = strdup(name);
|
||||||
|
mon->module = strdup(module);
|
||||||
|
if ((mon->module = load_module(module, MODULE_MONITOR)) == NULL)
|
||||||
|
{
|
||||||
|
fprintf(stderr, "Unable to load monitor module '%s'\n", name);
|
||||||
|
free(mon->name);
|
||||||
|
free(mon);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
mon->handle = (*mon->module->startMonitor)();
|
||||||
|
|
||||||
|
spinlock_acquire(&monLock);
|
||||||
|
mon->next = allMonitors;
|
||||||
|
allMonitors = mon;
|
||||||
|
spinlock_release(&monLock);
|
||||||
|
|
||||||
|
return mon;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Free a monitor, first stop the monitor and then remove the monitor from
|
||||||
|
* the chain of monitors and free the memory.
|
||||||
|
*
|
||||||
|
* @param mon The monitor to free
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
monitor_free(MONITOR *mon)
|
||||||
|
{
|
||||||
|
MONITOR *ptr;
|
||||||
|
|
||||||
|
mon->module->stopMonitor(mon->handle);
|
||||||
|
spinlock_acquire(&monLock);
|
||||||
|
if (allMonitors == mon)
|
||||||
|
allMonitors = mon->next;
|
||||||
|
else
|
||||||
|
{
|
||||||
|
ptr = allMonitors;
|
||||||
|
while (ptr->next && ptr->next != mon)
|
||||||
|
ptr = ptr->next;
|
||||||
|
if (ptr->next)
|
||||||
|
ptr->next = mon->next;
|
||||||
|
}
|
||||||
|
spinlock_release(&monLock);
|
||||||
|
free(mon->name);
|
||||||
|
free(mon);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add a server to a monitor. Simply register the server that needs to be
|
||||||
|
* monitored to the running monitor module.
|
||||||
|
*
|
||||||
|
* @param mon The Monitor instance
|
||||||
|
* @param server The Server to add to the monitoring
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
monitorAddServer(MONITOR *mon, SERVER *server)
|
||||||
|
{
|
||||||
|
mon->module->registerServer(mon->handle, server);
|
||||||
|
}
|
||||||
@ -238,3 +238,18 @@ server_clear_status(SERVER *server, int bit)
|
|||||||
{
|
{
|
||||||
server->status &= ~bit;
|
server->status &= ~bit;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add a user name and password to use for monitoring the
|
||||||
|
* state of the server.
|
||||||
|
*
|
||||||
|
* @param server The server to update
|
||||||
|
* @param user The user name to use
|
||||||
|
* @param passwd The password of the user
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
serverAddMonUser(SERVER *server, char *user, char *passwd)
|
||||||
|
{
|
||||||
|
server->monuser = strdup(user);
|
||||||
|
server->monpw = strdup(passwd);
|
||||||
|
}
|
||||||
|
|||||||
@ -61,3 +61,18 @@ void *rval;
|
|||||||
|
|
||||||
pthread_join((pthread_t)thd, &rval);
|
pthread_join((pthread_t)thd, &rval);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Put the thread to sleep for a number of milliseconds
|
||||||
|
*
|
||||||
|
* @param ms Number of milliseconds to sleep
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
thread_millisleep(int ms)
|
||||||
|
{
|
||||||
|
struct timespec req;
|
||||||
|
|
||||||
|
req.tv_sec = ms / 1000;
|
||||||
|
req.tv_nsec = (ms % 1000) * 1000000;
|
||||||
|
nanosleep(&req, NULL);
|
||||||
|
}
|
||||||
|
|||||||
11
gateway.cnf
11
gateway.cnf
@ -18,18 +18,24 @@ type=server
|
|||||||
address=127.0.0.1
|
address=127.0.0.1
|
||||||
port=3306
|
port=3306
|
||||||
protocol=MySQLBackend
|
protocol=MySQLBackend
|
||||||
|
monitoruser=massi
|
||||||
|
monitorpw=massi
|
||||||
|
|
||||||
[server2]
|
[server2]
|
||||||
type=server
|
type=server
|
||||||
address=127.0.0.1
|
address=127.0.0.1
|
||||||
port=3307
|
port=3307
|
||||||
protocol=MySQLBackend
|
protocol=MySQLBackend
|
||||||
|
monitoruser=massi
|
||||||
|
monitorpw=massi
|
||||||
|
|
||||||
[server3]
|
[server3]
|
||||||
type=server
|
type=server
|
||||||
address=127.0.0.1
|
address=127.0.0.1
|
||||||
port=3308
|
port=3308
|
||||||
protocol=MySQLBackend
|
protocol=MySQLBackend
|
||||||
|
monitoruser=massi
|
||||||
|
monitorpw=massi
|
||||||
|
|
||||||
[Debug Service]
|
[Debug Service]
|
||||||
type=service
|
type=service
|
||||||
@ -46,3 +52,8 @@ type=listener
|
|||||||
service=Test Service
|
service=Test Service
|
||||||
protocol=MySQLClient
|
protocol=MySQLClient
|
||||||
port=4006
|
port=4006
|
||||||
|
|
||||||
|
[MySQL Monitor]
|
||||||
|
type=monitor
|
||||||
|
module=mysqlmon
|
||||||
|
servers=server1,server2,server3
|
||||||
|
|||||||
@ -44,6 +44,7 @@ typedef struct {
|
|||||||
} GWBITMASK;
|
} GWBITMASK;
|
||||||
|
|
||||||
extern void bitmask_init(GWBITMASK *);
|
extern void bitmask_init(GWBITMASK *);
|
||||||
|
extern void bitmask_free(GWBITMASK *);
|
||||||
extern void bitmask_set(GWBITMASK *, int);
|
extern void bitmask_set(GWBITMASK *, int);
|
||||||
extern void bitmask_clear(GWBITMASK *, int);
|
extern void bitmask_clear(GWBITMASK *, int);
|
||||||
extern int bitmask_isset(GWBITMASK *, int);
|
extern int bitmask_isset(GWBITMASK *, int);
|
||||||
|
|||||||
@ -29,6 +29,7 @@
|
|||||||
*
|
*
|
||||||
* Date Who Description
|
* Date Who Description
|
||||||
* 13/06/13 Mark Riddoch Initial implementation
|
* 13/06/13 Mark Riddoch Initial implementation
|
||||||
|
* 08/07/13 Mark Riddoch Addition of monitor modules
|
||||||
* @endverbatim
|
* @endverbatim
|
||||||
*/
|
*/
|
||||||
|
|
||||||
@ -47,6 +48,7 @@ typedef struct modules {
|
|||||||
*/
|
*/
|
||||||
#define MODULE_PROTOCOL "Protocol" /**< A protocol module type */
|
#define MODULE_PROTOCOL "Protocol" /**< A protocol module type */
|
||||||
#define MODULE_ROUTER "Router" /**< A router module type */
|
#define MODULE_ROUTER "Router" /**< A router module type */
|
||||||
|
#define MODULE_MONITOR "Monitor" /**< A database monitor module type */
|
||||||
|
|
||||||
|
|
||||||
extern void *load_module(const char *module, const char *type);
|
extern void *load_module(const char *module, const char *type);
|
||||||
|
|||||||
79
include/monitor.h
Normal file
79
include/monitor.h
Normal file
@ -0,0 +1,79 @@
|
|||||||
|
#ifndef _MONITOR_H
|
||||||
|
#define _MONITOR_H
|
||||||
|
/*
|
||||||
|
* This file is distributed as part of the SkySQL Gateway. It is free
|
||||||
|
* software: you can redistribute it and/or modify it under the terms of the
|
||||||
|
* GNU General Public License as published by the Free Software Foundation,
|
||||||
|
* version 2.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||||
|
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||||
|
* FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
|
||||||
|
* details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License along with
|
||||||
|
* this program; if not, write to the Free Software Foundation, Inc., 51
|
||||||
|
* Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||||
|
*
|
||||||
|
* Copyright SkySQL Ab 2013
|
||||||
|
*/
|
||||||
|
#include <server.h>
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @file monitor.h The interface to the monitor module
|
||||||
|
*
|
||||||
|
* @verbatim
|
||||||
|
* Revision History
|
||||||
|
*
|
||||||
|
* Date Who Description
|
||||||
|
* 07/07/13 Mark Riddoch Initial implementation
|
||||||
|
*
|
||||||
|
* @endverbatim
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The "Module Object" for a monitor module.
|
||||||
|
*
|
||||||
|
* The monitor modules are designed to monitor the backend databases that the gateway
|
||||||
|
* connects to and provide information regarding the status of the databases that
|
||||||
|
* is used in the routing decisions.
|
||||||
|
*
|
||||||
|
* startMonitor is called to start the monitoring process, it is called on the main
|
||||||
|
* thread of the gateway and is responsible for creating a thread for the monitor
|
||||||
|
* itself to run on. This should use the entry points defined in the thread.h
|
||||||
|
* header file rather than make direct calls to the operating system thrading libraries.
|
||||||
|
* The return from startMonitor is a void * handle that will be passed to all other monitor
|
||||||
|
* API calls.
|
||||||
|
*
|
||||||
|
* stopMonitor is responsible for shuting down and destroying a monitor, it is called
|
||||||
|
* with the void * handle that was returned by startMonitor.
|
||||||
|
*
|
||||||
|
* registerServer is called to register a server that must be monitored with a running
|
||||||
|
* monitor. this will be called with the handle returned from the startMonitor call and
|
||||||
|
* the SERVER structure that the monitor must update and monitor. The SERVER structure
|
||||||
|
* contains the information required to connect to the monitored server.
|
||||||
|
*
|
||||||
|
* unregisterServer is called to remove a server from the set of servers that need to be
|
||||||
|
* monitored.
|
||||||
|
*/
|
||||||
|
typedef struct {
|
||||||
|
void *(*startMonitor)();
|
||||||
|
void (*stopMonitor)(void *);
|
||||||
|
void (*registerServer)(void *, SERVER *);
|
||||||
|
void (*unregisterServer)(void *, SERVER *);
|
||||||
|
} MONITOR_OBJECT;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Representation of the running monitor.
|
||||||
|
*/
|
||||||
|
typedef struct monitor {
|
||||||
|
char *name; /**< The name of the monitor module */
|
||||||
|
MONITOR_OBJECT *module; /**< The "monitor object" */
|
||||||
|
void *handle; /**< Handle returned from startMonitor */
|
||||||
|
struct monitor *next; /**< Next monitor in the linked list */
|
||||||
|
} MONITOR;
|
||||||
|
|
||||||
|
extern MONITOR *monitor_alloc(char *, char *);
|
||||||
|
extern void monitor_free(MONITOR *);
|
||||||
|
extern void monitorAddServer(MONITOR *, SERVER *);
|
||||||
|
#endif
|
||||||
@ -54,6 +54,8 @@ typedef struct server {
|
|||||||
unsigned short port; /**< Port to listen on */
|
unsigned short port; /**< Port to listen on */
|
||||||
char *protocol; /**< Protocol module to use */
|
char *protocol; /**< Protocol module to use */
|
||||||
unsigned int status; /**< Status flag bitmap for the server */
|
unsigned int status; /**< Status flag bitmap for the server */
|
||||||
|
char *monuser; /**< User name to use to monitor the db */
|
||||||
|
char *monpw; /**< Password to use to monitor the db */
|
||||||
SERVER_STATS stats; /**< The server statistics */
|
SERVER_STATS stats; /**< The server statistics */
|
||||||
struct server *next; /**< Next server */
|
struct server *next; /**< Next server */
|
||||||
struct server *nextdb; /**< Next server in list attached to a service */
|
struct server *nextdb; /**< Next server in list attached to a service */
|
||||||
@ -100,4 +102,5 @@ extern void dprintServer(DCB *, SERVER *);
|
|||||||
extern char *server_status(SERVER *);
|
extern char *server_status(SERVER *);
|
||||||
extern void server_set_status(SERVER *, int);
|
extern void server_set_status(SERVER *, int);
|
||||||
extern void server_clear_status(SERVER *, int);
|
extern void server_clear_status(SERVER *, int);
|
||||||
|
extern void serverAddMonUser(SERVER *, char *, char *);
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@ -33,5 +33,6 @@
|
|||||||
|
|
||||||
extern void *thread_start(void (*entry)(void *), void *arg);
|
extern void *thread_start(void (*entry)(void *), void *arg);
|
||||||
extern void thread_wait(void *thd);
|
extern void thread_wait(void *thd);
|
||||||
|
extern void thread_millisleep(int ms);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
64
modules/include/httpd.h
Normal file
64
modules/include/httpd.h
Normal file
@ -0,0 +1,64 @@
|
|||||||
|
/*
|
||||||
|
* This file is distributed as part of the SkySQL Gateway. It is free
|
||||||
|
* software: you can redistribute it and/or modify it under the terms of the
|
||||||
|
* GNU General Public License as published by the Free Software Foundation,
|
||||||
|
* version 2.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||||
|
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||||
|
* FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
|
||||||
|
* details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License along with
|
||||||
|
* this program; if not, write to the Free Software Foundation, Inc., 51
|
||||||
|
* Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||||
|
*
|
||||||
|
* Copyright SkySQL Ab 2013
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Revision History
|
||||||
|
*
|
||||||
|
* Date Who Description
|
||||||
|
* 08-07-2013 Massimiliano Pinto Added HTTPD protocol header file
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <dcb.h>
|
||||||
|
#include <buffer.h>
|
||||||
|
#include <service.h>
|
||||||
|
#include <session.h>
|
||||||
|
#include <sys/ioctl.h>
|
||||||
|
#include <errno.h>
|
||||||
|
#include <sys/socket.h>
|
||||||
|
#include <netinet/in.h>
|
||||||
|
#include <arpa/inet.h>
|
||||||
|
#include <router.h>
|
||||||
|
#include <poll.h>
|
||||||
|
#include <atomic.h>
|
||||||
|
#include <gw.h>
|
||||||
|
|
||||||
|
#define HTTPD_METHOD_MAXLEN 128
|
||||||
|
#define HTTPD_USER_MAXLEN 128
|
||||||
|
#define HTTPD_HOSTNAME_MAXLEN 512
|
||||||
|
#define HTTPD_USERAGENT_MAXLEN 1024
|
||||||
|
#define HTTPD_FIELD_MAXLEN 8192
|
||||||
|
#define HTTPD_REQUESTLINE_MAXLEN 8192
|
||||||
|
|
||||||
|
/**
|
||||||
|
* HTTPD session specific data
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
typedef struct httpd_session {
|
||||||
|
char user[HTTPD_USER_MAXLEN]; /**< username for authentication*/
|
||||||
|
char *cookies; /**< all input cookies */
|
||||||
|
char hostname[HTTPD_HOSTNAME_MAXLEN]; /**< The hostname */
|
||||||
|
char useragent[HTTPD_USERAGENT_MAXLEN]; /**< The useragent */
|
||||||
|
char method[HTTPD_METHOD_MAXLEN]; /**< The HTTPD Method */
|
||||||
|
char *url; /**< the URL in the request */
|
||||||
|
char *path_info; /**< the Pathinfo, starts with /, is the extra path segments after the document name */
|
||||||
|
char *query_string; /**< the Query string, starts with ?, after path_info and document name */
|
||||||
|
int headers_received; /**< All the headers has been received, if 1 */
|
||||||
|
} HTTPD_session;
|
||||||
59
modules/monitor/Makefile
Normal file
59
modules/monitor/Makefile
Normal file
@ -0,0 +1,59 @@
|
|||||||
|
# This file is distributed as part of the SkySQL Gateway. It is free
|
||||||
|
# software: you can redistribute it and/or modify it under the terms of the
|
||||||
|
# GNU General Public License as published by the Free Software Foundation,
|
||||||
|
# version 2.
|
||||||
|
#
|
||||||
|
# This program is distributed in the hope that it will be useful, but WITHOUT
|
||||||
|
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||||
|
# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
|
||||||
|
# details.
|
||||||
|
#
|
||||||
|
# You should have received a copy of the GNU General Public License along with
|
||||||
|
# this program; if not, write to the Free Software Foundation, Inc., 51
|
||||||
|
# Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||||
|
#
|
||||||
|
# Copyright SkySQL Ab 2013
|
||||||
|
#
|
||||||
|
# Revision History
|
||||||
|
# Date Who Description
|
||||||
|
# 08/07/13 Mark Riddoch Initial implementation
|
||||||
|
|
||||||
|
include ../../../build_gateway.inc
|
||||||
|
LOGPATH := $(ROOT_PATH)/log_manager
|
||||||
|
UTILSPATH := $(ROOT_PATH)/utils
|
||||||
|
|
||||||
|
CC=cc
|
||||||
|
CFLAGS=-c -fPIC -I. -I/usr/include -I../include -I../../include -I$(LOGPATH) \
|
||||||
|
-I$(UTILSPATH) -I/usr/include/mysql -Wall -g
|
||||||
|
LDFLAGS=-shared -L$(LOGPATH) -Wl,-rpath,$(LOGPATH) -Wl,-rpath,$(UTILSPATH)
|
||||||
|
MYSQLSRCS=mysql_mon.c
|
||||||
|
MYSQLOBJ=$(MYSQLSRCS:.c=.o)
|
||||||
|
SRCS=$(MYSQLSRCS)
|
||||||
|
OBJ=$(SRCS:.c=.o)
|
||||||
|
LIBS=$(UTILSPATH)/skygw_utils.o -llog_manager \
|
||||||
|
-L/packages/mariadb-5.5.25/libmysql -lmysqlclient
|
||||||
|
MODULES=libmysqlmon.so
|
||||||
|
|
||||||
|
|
||||||
|
all: $(MODULES)
|
||||||
|
|
||||||
|
libmysqlmon.so: $(MYSQLOBJ)
|
||||||
|
$(CC) $(LDFLAGS) $(MYSQLOBJ) $(LIBS) -o $@
|
||||||
|
|
||||||
|
.c.o:
|
||||||
|
$(CC) $(CFLAGS) $< -o $@
|
||||||
|
|
||||||
|
clean:
|
||||||
|
rm -f $(OBJ) $(MODULES)
|
||||||
|
|
||||||
|
tags:
|
||||||
|
ctags $(SRCS) $(HDRS)
|
||||||
|
|
||||||
|
depend:
|
||||||
|
@rm -f depend.mk
|
||||||
|
cc -M $(CFLAGS) $(SRCS) > depend.mk
|
||||||
|
|
||||||
|
install: $(MODULES)
|
||||||
|
install -D $< $(DEST)/gateway/modules
|
||||||
|
|
||||||
|
include depend.mk
|
||||||
16
modules/monitor/depend.mk
Normal file
16
modules/monitor/depend.mk
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
mysql_mon.o: mysql_mon.c /usr/include/stdio.h /usr/include/features.h \
|
||||||
|
/usr/include/sys/cdefs.h /usr/include/bits/wordsize.h \
|
||||||
|
/usr/include/gnu/stubs.h /usr/include/gnu/stubs-64.h \
|
||||||
|
/usr/lib/gcc/x86_64-redhat-linux/4.4.6/include/stddef.h \
|
||||||
|
/usr/include/bits/types.h /usr/include/bits/typesizes.h \
|
||||||
|
/usr/include/libio.h /usr/include/_G_config.h /usr/include/wchar.h \
|
||||||
|
/usr/lib/gcc/x86_64-redhat-linux/4.4.6/include/stdarg.h \
|
||||||
|
/usr/include/bits/stdio_lim.h /usr/include/bits/sys_errlist.h \
|
||||||
|
../../include/monitor.h mysqlmon.h ../../include/server.h \
|
||||||
|
../../include/dcb.h ../../include/spinlock.h ../../include/thread.h \
|
||||||
|
/usr/include/pthread.h /usr/include/endian.h /usr/include/bits/endian.h \
|
||||||
|
/usr/include/bits/byteswap.h /usr/include/sched.h /usr/include/time.h \
|
||||||
|
/usr/include/bits/sched.h /usr/include/bits/time.h \
|
||||||
|
/usr/include/xlocale.h /usr/include/bits/pthreadtypes.h \
|
||||||
|
/usr/include/bits/setjmp.h ../../include/buffer.h \
|
||||||
|
../../include/gwbitmask.h
|
||||||
223
modules/monitor/mysql_mon.c
Normal file
223
modules/monitor/mysql_mon.c
Normal file
@ -0,0 +1,223 @@
|
|||||||
|
/*
|
||||||
|
* This file is distributed as part of the SkySQL Gateway. It is free
|
||||||
|
* software: you can redistribute it and/or modify it under the terms of the
|
||||||
|
* GNU General Public License as published by the Free Software Foundation,
|
||||||
|
* version 2.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||||
|
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||||
|
* FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
|
||||||
|
* details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License along with
|
||||||
|
* this program; if not, write to the Free Software Foundation, Inc., 51
|
||||||
|
* Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||||
|
*
|
||||||
|
* Copyright SkySQL Ab 2013
|
||||||
|
*/
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <monitor.h>
|
||||||
|
#include <mysqlmon.h>
|
||||||
|
#include <thread.h>
|
||||||
|
|
||||||
|
static void monitorMain(void *);
|
||||||
|
|
||||||
|
static char *version_str = "V1.0.0";
|
||||||
|
|
||||||
|
static void *startMonitor();
|
||||||
|
static void stopMonitor(void *);
|
||||||
|
static void registerServer(void *, SERVER *);
|
||||||
|
static void unregisterServer(void *, SERVER *);
|
||||||
|
|
||||||
|
static MONITOR_OBJECT MyObject = { startMonitor, stopMonitor, registerServer, unregisterServer };
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Implementation of the mandatory version entry point
|
||||||
|
*
|
||||||
|
* @return version string of the module
|
||||||
|
*/
|
||||||
|
char *
|
||||||
|
version()
|
||||||
|
{
|
||||||
|
return version_str;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The module initialisation routine, called when the module
|
||||||
|
* is first loaded.
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
ModuleInit()
|
||||||
|
{
|
||||||
|
fprintf(stderr, "Initialise the MySQL Monitor module.\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The module entry point routine. It is this routine that
|
||||||
|
* must populate the structure that is referred to as the
|
||||||
|
* "module object", this is a structure with the set of
|
||||||
|
* external entry points for this module.
|
||||||
|
*
|
||||||
|
* @return The module object
|
||||||
|
*/
|
||||||
|
MONITOR_OBJECT *
|
||||||
|
GetModuleObject()
|
||||||
|
{
|
||||||
|
return &MyObject;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Start the instance of the monitor, returning a handle on the monitor.
|
||||||
|
*
|
||||||
|
* This function creates a thread to execute the actual monitoring.
|
||||||
|
*
|
||||||
|
* @return A handle to use when interacting with the monitor
|
||||||
|
*/
|
||||||
|
static void *
|
||||||
|
startMonitor()
|
||||||
|
{
|
||||||
|
MYSQL_MONITOR *handle;
|
||||||
|
|
||||||
|
if ((handle = (MYSQL_MONITOR *)malloc(sizeof(MYSQL_MONITOR))) == NULL)
|
||||||
|
return NULL;
|
||||||
|
handle->databases = NULL;
|
||||||
|
handle->shutdown = 0;
|
||||||
|
spinlock_init(&handle->lock);
|
||||||
|
thread_start(monitorMain, handle);
|
||||||
|
return handle;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Stop a running monitor
|
||||||
|
*
|
||||||
|
* @param handle Handle on thr running monior
|
||||||
|
*/
|
||||||
|
static void
|
||||||
|
stopMonitor(void *arg)
|
||||||
|
{
|
||||||
|
MYSQL_MONITOR *handle = (MYSQL_MONITOR *)arg;
|
||||||
|
|
||||||
|
handle->shutdown = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Register a server that must be added to the monitored servers for
|
||||||
|
* a monitoring module.
|
||||||
|
*
|
||||||
|
* @param handle A handle on the running monitor module
|
||||||
|
* @param server The server to add
|
||||||
|
*/
|
||||||
|
static void
|
||||||
|
registerServer(void *arg, SERVER *server)
|
||||||
|
{
|
||||||
|
MYSQL_MONITOR *handle = (MYSQL_MONITOR *)arg;
|
||||||
|
MONITOR_SERVERS *ptr, *db;
|
||||||
|
|
||||||
|
if ((db = (MONITOR_SERVERS *)malloc(sizeof(MONITOR_SERVERS))) == NULL)
|
||||||
|
return;
|
||||||
|
db->server = server;
|
||||||
|
db->con = NULL;
|
||||||
|
db->next = NULL;
|
||||||
|
spinlock_acquire(&handle->lock);
|
||||||
|
if (handle->databases == NULL)
|
||||||
|
handle->databases = db;
|
||||||
|
else
|
||||||
|
{
|
||||||
|
ptr = handle->databases;
|
||||||
|
while (ptr->next != NULL)
|
||||||
|
ptr = ptr->next;
|
||||||
|
ptr->next = db;
|
||||||
|
}
|
||||||
|
spinlock_release(&handle->lock);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Remove a server from those being monitored by a monitoring module
|
||||||
|
*
|
||||||
|
* @param handle A handle on the running monitor module
|
||||||
|
* @param server The server to remove
|
||||||
|
*/
|
||||||
|
static void
|
||||||
|
unregisterServer(void *arg, SERVER *server)
|
||||||
|
{
|
||||||
|
MYSQL_MONITOR *handle = (MYSQL_MONITOR *)arg;
|
||||||
|
MONITOR_SERVERS *ptr, *lptr;
|
||||||
|
|
||||||
|
spinlock_acquire(&handle->lock);
|
||||||
|
if (handle->databases == NULL)
|
||||||
|
{
|
||||||
|
spinlock_release(&handle->lock);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (handle->databases->server == server)
|
||||||
|
{
|
||||||
|
ptr = handle->databases;
|
||||||
|
handle->databases = handle->databases->next;
|
||||||
|
free(ptr);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
ptr = handle->databases;
|
||||||
|
while (ptr->next != NULL && ptr->next->server != server)
|
||||||
|
ptr = ptr->next;
|
||||||
|
if (ptr->next)
|
||||||
|
{
|
||||||
|
lptr = ptr->next;
|
||||||
|
ptr->next = ptr->next->next;
|
||||||
|
free(lptr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
spinlock_release(&handle->lock);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Monitor an individual server
|
||||||
|
*
|
||||||
|
* @param database The database to probe
|
||||||
|
*/
|
||||||
|
static void
|
||||||
|
monitorDatabase(MONITOR_SERVERS *database)
|
||||||
|
{
|
||||||
|
if (database->con == NULL || mysql_ping(database->con) != 0)
|
||||||
|
{
|
||||||
|
database->con = mysql_init(NULL);
|
||||||
|
if (mysql_real_connect(database->con, database->server->name,
|
||||||
|
database->server->monuser, database->server->monpw,
|
||||||
|
NULL, database->server->port, NULL, 0) == NULL)
|
||||||
|
{
|
||||||
|
server_clear_status(database->server, SERVER_RUNNING);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// If we get this far then we have a workign connection
|
||||||
|
server_set_status(database->server, SERVER_RUNNING);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The entry point for the monitoring module thread
|
||||||
|
*
|
||||||
|
* @param arg The handle of the monitor
|
||||||
|
*/
|
||||||
|
static void
|
||||||
|
monitorMain(void *arg)
|
||||||
|
{
|
||||||
|
MYSQL_MONITOR *handle = (MYSQL_MONITOR *)arg;
|
||||||
|
MONITOR_SERVERS *ptr;
|
||||||
|
|
||||||
|
while (1)
|
||||||
|
{
|
||||||
|
thread_millisleep(1000);
|
||||||
|
|
||||||
|
if (handle->shutdown)
|
||||||
|
return;
|
||||||
|
ptr = handle->databases;
|
||||||
|
while (ptr)
|
||||||
|
{
|
||||||
|
monitorDatabase(ptr);
|
||||||
|
ptr = ptr->next;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
55
modules/monitor/mysqlmon.h
Normal file
55
modules/monitor/mysqlmon.h
Normal file
@ -0,0 +1,55 @@
|
|||||||
|
#ifndef _MYSQLMON_H
|
||||||
|
#define _MYSQLMON_H
|
||||||
|
/*
|
||||||
|
* This file is distributed as part of the SkySQL Gateway. It is free
|
||||||
|
* software: you can redistribute it and/or modify it under the terms of the
|
||||||
|
* GNU General Public License as published by the Free Software Foundation,
|
||||||
|
* version 2.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||||
|
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||||
|
* FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
|
||||||
|
* details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License along with
|
||||||
|
* this program; if not, write to the Free Software Foundation, Inc., 51
|
||||||
|
* Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||||
|
*
|
||||||
|
* Copyright SkySQL Ab 2013
|
||||||
|
*/
|
||||||
|
#include <server.h>
|
||||||
|
#include <spinlock.h>
|
||||||
|
#include <mysql.h>
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @file mysqlmon.h - The MySQL monitor functionality within the gateway
|
||||||
|
*
|
||||||
|
* @verbatim
|
||||||
|
* Revision History
|
||||||
|
*
|
||||||
|
* Date Who Description
|
||||||
|
* 08/07/13 Mark Riddoch Initial implementation
|
||||||
|
*
|
||||||
|
* @endverbatim
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The linked list of servers that are being monitored by the MySQL
|
||||||
|
* Monitor module.
|
||||||
|
*/
|
||||||
|
typedef struct monitor_servers {
|
||||||
|
SERVER *server; /**< The server being monitored */
|
||||||
|
MYSQL *con; /**< The MySQL connection */
|
||||||
|
struct monitor_servers
|
||||||
|
*next; /**< The next server in the list */
|
||||||
|
} MONITOR_SERVERS;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The handle for an instance of a MySQL Monitor module
|
||||||
|
*/
|
||||||
|
typedef struct {
|
||||||
|
SPINLOCK lock; /**< The monitor spinlock */
|
||||||
|
int shutdown; /**< Flag to shutdown the monitor thread */
|
||||||
|
MONITOR_SERVERS *databases; /**< Linked list of servers to monitor */
|
||||||
|
} MYSQL_MONITOR;
|
||||||
|
#endif
|
||||||
@ -53,7 +53,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#define ISspace(x) isspace((int)(x))
|
#define ISspace(x) isspace((int)(x))
|
||||||
#define HTTP_SERVER_STRING "Gateway(c) v.1.0.0\r\n"
|
#define HTTP_SERVER_STRING "Gateway(c) v.1.0.0"
|
||||||
static char *version_str = "V1.0.0";
|
static char *version_str = "V1.0.0";
|
||||||
|
|
||||||
static int httpd_read_event(DCB* dcb);
|
static int httpd_read_event(DCB* dcb);
|
||||||
@ -65,7 +65,7 @@ static int httpd_accept(DCB *dcb);
|
|||||||
static int httpd_close(DCB *dcb);
|
static int httpd_close(DCB *dcb);
|
||||||
static int httpd_listen(DCB *dcb, char *config);
|
static int httpd_listen(DCB *dcb, char *config);
|
||||||
static int httpd_get_line(int sock, char *buf, int size);
|
static int httpd_get_line(int sock, char *buf, int size);
|
||||||
static void httpd_send_headers(int client, const char *filename);
|
static void httpd_send_headers(DCB *dcb, int final);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The "module object" for the httpd protocol module.
|
* The "module object" for the httpd protocol module.
|
||||||
@ -82,9 +82,6 @@ static GWPROTOCOL MyObject = {
|
|||||||
httpd_listen /**< Create a listener */
|
httpd_listen /**< Create a listener */
|
||||||
};
|
};
|
||||||
|
|
||||||
static void
|
|
||||||
httpd_command(DCB *, char *cmd);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Implementation of the mandatory version entry point
|
* Implementation of the mandatory version entry point
|
||||||
*
|
*
|
||||||
@ -130,19 +127,18 @@ static int
|
|||||||
httpd_read_event(DCB* dcb)
|
httpd_read_event(DCB* dcb)
|
||||||
{
|
{
|
||||||
int n = -1;
|
int n = -1;
|
||||||
GWBUF *head = NULL;
|
//SESSION *session = dcb->session;
|
||||||
SESSION *session = dcb->session;
|
//ROUTER_OBJECT *router = session->service->router;
|
||||||
ROUTER_OBJECT *router = session->service->router;
|
//ROUTER *router_instance = session->service->router_instance;
|
||||||
ROUTER *router_instance = session->service->router_instance;
|
//void *rsession = session->router_session;
|
||||||
void *rsession = session->router_session;
|
|
||||||
|
|
||||||
int numchars = 1;
|
int numchars = 1;
|
||||||
char buf[1024];
|
char buf[1024];
|
||||||
char *query_string = NULL;
|
char *query_string = NULL;
|
||||||
char *path_info = NULL;
|
//char *path_info = NULL;
|
||||||
char method[255];
|
char method[255];
|
||||||
char url[255];
|
char url[255];
|
||||||
char path[512];
|
//char path[512];
|
||||||
int cgi = 0;
|
int cgi = 0;
|
||||||
size_t i, j;
|
size_t i, j;
|
||||||
GWBUF *buffer=NULL;
|
GWBUF *buffer=NULL;
|
||||||
@ -162,21 +158,20 @@ GWBUF *buffer=NULL;
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((buffer = gwbuf_alloc(1024)) == NULL) {
|
|
||||||
//httpd_error(dcb->fd);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (strcasecmp(method, "POST") == 0)
|
if (strcasecmp(method, "POST") == 0)
|
||||||
cgi = 1;
|
cgi = 1;
|
||||||
|
|
||||||
i = 0;
|
i = 0;
|
||||||
while (ISspace(buf[j]) && (j < sizeof(buf)))
|
|
||||||
|
while (ISspace(buf[j]) && (j < sizeof(buf))) {
|
||||||
j++;
|
j++;
|
||||||
|
}
|
||||||
|
|
||||||
while (!ISspace(buf[j]) && (i < sizeof(url) - 1) && (j < sizeof(buf))) {
|
while (!ISspace(buf[j]) && (i < sizeof(url) - 1) && (j < sizeof(buf))) {
|
||||||
url[i] = buf[j];
|
url[i] = buf[j];
|
||||||
i++; j++;
|
i++; j++;
|
||||||
}
|
}
|
||||||
|
|
||||||
url[i] = '\0';
|
url[i] = '\0';
|
||||||
|
|
||||||
if (strcasecmp(method, "GET") == 0) {
|
if (strcasecmp(method, "GET") == 0) {
|
||||||
@ -193,12 +188,23 @@ GWBUF *buffer=NULL;
|
|||||||
while ((numchars > 0) && strcmp("\n", buf)) /* read & discard headers */
|
while ((numchars > 0) && strcmp("\n", buf)) /* read & discard headers */
|
||||||
numchars = httpd_get_line(dcb->fd, buf, sizeof(buf));
|
numchars = httpd_get_line(dcb->fd, buf, sizeof(buf));
|
||||||
|
|
||||||
httpd_send_headers(dcb->fd, NULL);
|
|
||||||
|
|
||||||
strcpy(GWBUF_DATA(buffer), "Welcome to HTTPD Gateway (c)\n");
|
/* send all the basic headers and close with \r\n */
|
||||||
|
httpd_send_headers(dcb, 1);
|
||||||
|
|
||||||
dcb->func.write(dcb, buffer);
|
if ((buffer = gwbuf_alloc(1024)) == NULL) {
|
||||||
|
//httpd_error(dcb->fd);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (strcmp(url, "/show") == 0) {
|
||||||
|
dprintAllDCBs(dcb);
|
||||||
|
} else {
|
||||||
|
|
||||||
|
dcb_printf(dcb, "Welcome to HTTPD Gateway (c) %s\n", version_str);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* force the client connecton close */
|
||||||
dcb_close(dcb);
|
dcb_close(dcb);
|
||||||
|
|
||||||
dcb->state = DCB_STATE_POLLING;
|
dcb->state = DCB_STATE_POLLING;
|
||||||
@ -367,63 +373,77 @@ short pnum;
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* HTTPD command implementation
|
* HTTPD get line from client
|
||||||
*
|
|
||||||
* Called for each command in the HTTP stream.
|
|
||||||
*
|
|
||||||
* Currently we do no command execution
|
|
||||||
*
|
|
||||||
* @param dcb The client DCB
|
|
||||||
* @param cmd The command stream
|
|
||||||
*/
|
*/
|
||||||
static void
|
|
||||||
httpd_command(DCB *dcb, char *cmd)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
static int httpd_get_line(int sock, char *buf, int size) {
|
static int httpd_get_line(int sock, char *buf, int size) {
|
||||||
int i = 0;
|
int i = 0;
|
||||||
char c = '\0';
|
char c = '\0';
|
||||||
int n;
|
int n;
|
||||||
|
|
||||||
while ((i < size - 1) && (c != '\n'))
|
while ((i < size - 1) && (c != '\n')) {
|
||||||
{
|
n = recv(sock, &c, 1, 0);
|
||||||
n = recv(sock, &c, 1, 0);
|
/* DEBUG printf("%02X\n", c); */
|
||||||
/* DEBUG printf("%02X\n", c); */
|
if (n > 0) {
|
||||||
if (n > 0)
|
if (c == '\r') {
|
||||||
{
|
n = recv(sock, &c, 1, MSG_PEEK);
|
||||||
if (c == '\r')
|
/* DEBUG printf("%02X\n", c); */
|
||||||
{
|
if ((n > 0) && (c == '\n'))
|
||||||
n = recv(sock, &c, 1, MSG_PEEK);
|
recv(sock, &c, 1, 0);
|
||||||
/* DEBUG printf("%02X\n", c); */
|
else
|
||||||
if ((n > 0) && (c == '\n'))
|
c = '\n';
|
||||||
recv(sock, &c, 1, 0);
|
}
|
||||||
else
|
buf[i] = c;
|
||||||
c = '\n';
|
i++;
|
||||||
}
|
} else
|
||||||
buf[i] = c;
|
c = '\n';
|
||||||
i++;
|
}
|
||||||
}
|
|
||||||
else
|
|
||||||
c = '\n';
|
|
||||||
}
|
|
||||||
buf[i] = '\0';
|
|
||||||
|
|
||||||
return(i);
|
buf[i] = '\0';
|
||||||
|
|
||||||
|
return i;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void httpd_send_headers(int client, const char *filename)
|
/**
|
||||||
|
* HTTPD send basic headers with 200 OK
|
||||||
|
*/
|
||||||
|
static void httpd_send_headers(DCB *dcb, int final)
|
||||||
{
|
{
|
||||||
char buf[1024];
|
char date[64] = "";
|
||||||
(void)filename; /* could use filename to determine file type */
|
const char *fmt = "%a, %d %b %Y %H:%M:%S GMT";
|
||||||
|
time_t httpd_current_time = time(NULL);
|
||||||
|
|
||||||
strcpy(buf, "HTTP/1.0 200 OK\r\n");
|
strftime(date, sizeof(date), fmt, localtime(&httpd_current_time));
|
||||||
send(client, buf, strlen(buf), 0);
|
|
||||||
strcpy(buf, HTTP_SERVER_STRING);
|
dcb_printf(dcb, "HTTP/1.1 200 OK\r\nDate: %s\r\nServer: %s\r\nConnection: close\r\nContent-Type: text/plain\r\n", date, HTTP_SERVER_STRING);
|
||||||
send(client, buf, strlen(buf), 0);
|
|
||||||
sprintf(buf, "Content-Type: text/html\r\n");
|
/* close the headers */
|
||||||
send(client, buf, strlen(buf), 0);
|
if (final) {
|
||||||
strcpy(buf, "\r\n");
|
dcb_printf(dcb, "\r\n");
|
||||||
send(client, buf, strlen(buf), 0);
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* HTTPD get line from client
|
||||||
|
*/
|
||||||
|
static int httpd_dcb_readline(DCB *dcb) {
|
||||||
|
int n = -1;
|
||||||
|
char c = '\0';
|
||||||
|
char *ptr = NULL;
|
||||||
|
GWBUF *buffer = NULL;
|
||||||
|
|
||||||
|
buffer = NULL;
|
||||||
|
|
||||||
|
n = dcb_read(dcb, &buffer);
|
||||||
|
|
||||||
|
ptr = GWBUF_DATA(buffer);
|
||||||
|
|
||||||
|
while (ptr) {
|
||||||
|
c = *ptr;
|
||||||
|
ptr++;
|
||||||
|
}
|
||||||
|
|
||||||
|
buffer = gwbuf_consume(buffer, gwbuf_length(buffer));
|
||||||
|
|
||||||
|
return n;
|
||||||
}
|
}
|
||||||
///
|
///
|
||||||
|
|||||||
Reference in New Issue
Block a user