Expose the query classifier through the luafilter

The luafilter exposes two of the main functions provided by the query
classifier API; the type and operation classification.

The functions can be used by the Lua script with minimal overhead as the
current query being executed is stored only as a pointer. The functions
should only be called inside the `routeQuery` entry point of a Lua script.
This commit is contained in:
Markus Mäkelä 2016-12-18 09:50:52 +02:00
parent 8562a5138c
commit be1b868938
2 changed files with 93 additions and 13 deletions

View File

@ -42,10 +42,6 @@ The entry points for the Lua script expect the following signatures:
- This function first loads the session script and executes in on a global
level. After this, the newSession function in the Lua scripts is called.
There is a single C function exported as a global variable for the session
script named id_gen. The id_gen function returns an integer that is unique
for this service only. This function is only accessible to the session
level scripts.
- `nil closeSession()` - session is closed
@ -73,3 +69,27 @@ The entry points for the Lua script expect the following signatures:
These functions, if found in the script, will be called whenever a call to the
matching entry point is made.
### Functions Exposed by the Luafilter
The luafilter exposes three functions that can be called from the Lua script.
- `string lua_qc_get_type()`
- Returns the type of the current query being executed as a string. The values
are the string versions of the query types defined in _query_classifier.h_
are separated by vertical bars (`|`).
This function can only be called from the `routeQuery` entry point.
- `string lua_qc_get_operation()`
- Returns the current operation type as a string. The values are defined in
_query_classifier.h_.
This function can only be called from the `routeQuery` entry point.
- `number id_gen()`
- This function generates unique integers that can be used to distinct
sessions from each other.

View File

@ -36,17 +36,19 @@
* or diagnostic being made for the session script.
*/
#include <maxscale/spinlock.h>
#include <maxscale/debug.h>
#include <maxscale/log_manager.h>
#include <maxscale/cdefs.h>
#include <lauxlib.h>
#include <lua.h>
#include <lualib.h>
#include <string.h>
#include <maxscale/filter.h>
#include <maxscale/session.h>
#include <maxscale/modutil.h>
#include "lua.h"
#include "lualib.h"
#include "lauxlib.h"
#include <maxscale/alloc.h>
#include <maxscale/debug.h>
#include <maxscale/filter.h>
#include <maxscale/log_manager.h>
#include <maxscale/modutil.h>
#include <maxscale/query_classifier.h>
#include <maxscale/session.h>
#include <maxscale/spinlock.h>
MODULE_INFO info =
{
@ -126,6 +128,45 @@ static int id_gen(lua_State* state)
return 1;
}
static int lua_qc_get_type(lua_State* state)
{
int ibuf = lua_upvalueindex(1);
GWBUF *buf = *((GWBUF**)lua_touserdata(state, ibuf));
if (buf)
{
uint32_t type = qc_get_type(buf);
char *mask = qc_typemask_to_string(type);
lua_pushstring(state, mask);
MXS_FREE(mask);
}
else
{
lua_pushliteral(state, "");
}
return 1;
}
static int lua_qc_get_operation(lua_State* state)
{
int ibuf = lua_upvalueindex(1);
GWBUF *buf = *((GWBUF**)lua_touserdata(state, ibuf));
if (buf)
{
qc_query_op_t op = qc_get_operation(buf);
const char *opstring = qc_op_to_string(op);
lua_pushstring(state, opstring);
}
else
{
lua_pushliteral(state, "");
}
return 1;
}
/**
* The Lua filter instance.
*/
@ -144,6 +185,7 @@ typedef struct
{
SESSION* session;
lua_State* lua_state;
GWBUF* current_query;
SPINLOCK lock;
DOWNSTREAM down;
UPSTREAM up;
@ -290,9 +332,20 @@ static void * newSession(FILTER *instance, SESSION *session)
}
else
{
/** Expose an ID generation function */
lua_pushcfunction(my_session->lua_state, id_gen);
lua_setglobal(my_session->lua_state, "id_gen");
/** Expose a part of the query classifier API */
lua_pushlightuserdata(my_session->lua_state, &my_session->current_query);
lua_pushcclosure(my_session->lua_state, lua_qc_get_type, 1);
lua_setglobal(my_session->lua_state, "lua_qc_get_type");
lua_pushlightuserdata(my_session->lua_state, &my_session->current_query);
lua_pushcclosure(my_session->lua_state, lua_qc_get_operation, 1);
lua_setglobal(my_session->lua_state, "lua_qc_get_operation");
/** Call the newSession entry point */
lua_getglobal(my_session->lua_state, "newSession");
if (lua_pcall(my_session->lua_state, 0, 0, 0))
{
@ -475,6 +528,10 @@ static int routeQuery(FILTER *instance, void *session, GWBUF *queue)
if (fullquery && my_session->lua_state)
{
spinlock_acquire(&my_session->lock);
/** Store the current query being processed */
my_session->current_query = queue;
lua_getglobal(my_session->lua_state, "routeQuery");
lua_pushlstring(my_session->lua_state, fullquery, strlen(fullquery));
if (lua_pcall(my_session->lua_state, 1, 1, 0))
@ -497,6 +554,9 @@ static int routeQuery(FILTER *instance, void *session, GWBUF *queue)
route = lua_toboolean(my_session->lua_state, -1);
}
}
my_session->current_query = NULL;
spinlock_release(&my_session->lock);
}