MAX-157. Added support for hints in rwsplit router.

buffer.c: added memory release for hint of a GWBUF
hint.c: added bool hint_exists()
hint.h: added placeholder for hint type HINT_ROUTE_TO_ALL which doesn't have implementation yet.
filter/Makefile: fixed dependency issue
hintparser.c: added const char* token_get_keyword(), hint_parser:added NULL check, hint_next_token: fixed off-by-one bug
readwritesplit.h: added bitfield for hints' use, which includes route targets and flag for case where user hinted to route to named backend server.
readwritesplit.c: added function route_target_t get_route_target() for resolving route target based on 1) query type (from query_classifier) 2) transaction state (active/not) and 3) hints. Modified get_dcb, which is called in routeQuery to provide pointer to correct backend DCB. Now get_dcb also takes server unique name as a parameter if such a hint was found. for hints' use, which includes  enter the commit message for your changes.
This commit is contained in:
VilhoRaatikka
2014-07-31 23:40:02 +03:00
parent ef924cdc00
commit 4f3d746f4e
8 changed files with 342 additions and 136 deletions

View File

@ -74,16 +74,16 @@ libhintfilter.so:
clean:
rm -f $(OBJ) $(MODULES)
(cd hint; make clean)
(cd hint; touch depend.mk; make clean)
tags:
ctags $(SRCS) $(HDRS)
(cd hint; make tags)
(cd hint; touch depend.mk; make tags)
depend:
@rm -f depend.mk
cc -M $(CFLAGS) $(SRCS) > depend.mk
(cd hint; make depend)
(cd hint; touch depend.mk; make depend)
install: $(MODULES)
install -D $(MODULES) $(DEST)/modules

View File

@ -18,11 +18,15 @@
#include <stdio.h>
#include <ctype.h>
#include <string.h>
#include <skygw_utils.h>
#include <log_manager.h>
#include <filter.h>
#include <modinfo.h>
#include <modutil.h>
#include <mysqlhint.h>
extern int lm_enabled_logfiles_bitmask;
/**
* hintparser.c - Find any comment in the SQL packet and look for MAXSCALE
* hints in that comment.
@ -49,15 +53,61 @@ struct {
{ "server", TOK_SERVER },
{ NULL, 0 }
};
/**
HINT_TOKEN kwords[] = {
{ TOK_MAXSCALE, "maxscale" },
{ TOK_PREPARE, "prepare" },
{ TOK_START, "start" },
{ TOK_START, "begin" },
{ TOK_STOP, "stop" },
{ TOK_STOP, "end" },
{ TOK_EQUAL, "=" },
{ TOK_ROUTE, "route" },
{ TOK_TO, "to" },
{ TOK_MASTER, "master" },
{ TOK_SLAVE, "slave" },
{ TOK_SERVER, "server" },
{ 0, NULL}
};
*/
static HINT_TOKEN *hint_next_token(GWBUF **buf, char **ptr);
static void hint_pop(HINT_SESSION *);
static HINT *lookup_named_hint(HINT_SESSION *, char *);
static void create_named_hint(HINT_SESSION *, char *, HINT *);
static void hint_push(HINT_SESSION *, HINT *);
static const char* token_get_keyword (TOKEN_VALUE token);
typedef enum { HM_EXECUTE, HM_START, HM_PREPARE } HINT_MODE;
static const char* token_get_keyword (
TOKEN_VALUE token)
{
switch (token) {
case TOK_EOL:
return "End of line";
break;
default:
{
int i = 0;
while (i < TOK_EOL && keywords[i].token != token)
i++;
ss_dassert(i != TOK_EOL);
if (i == TOK_EOL)
{
return "Unknown token";
}
else
{
return keywords[i].keyword;
}
}
break;
}
}
/**
* Parse the hint comments in the MySQL statement passed in request.
* Add any hints to the buffer for later processing.
@ -160,8 +210,20 @@ HINT_MODE mode = HM_EXECUTE;
}
tok = hint_next_token(&buf, &ptr);
if (tok == NULL)
{
goto retblock;
}
if (tok->token != TOK_MAXSCALE)
{
LOGIF(LE, (skygw_log_write_flush(
LOGFILE_ERROR,
"Error : Invalid hint string '%s'. Hint should start "
"with keyword '%s'",
token_get_keyword(tok->token),
token_get_keyword(TOK_MAXSCALE))));
free(tok);
goto retblock;
}
@ -369,7 +431,7 @@ HINT_TOKEN *tok;
return NULL;
tok->value = NULL;
dest = word;
while (*ptr <= (char *)((*buf)->end) || (*buf)->next)
while (*ptr < (char *)((*buf)->end) || (*buf)->next)
{
if (inword && inquote == '\0' &&
(**ptr == '=' || isspace(**ptr)))