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:
@ -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
|
- 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.
|
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
|
- `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
|
These functions, if found in the script, will be called whenever a call to the
|
||||||
matching entry point is made.
|
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.
|
||||||
|
@ -36,17 +36,19 @@
|
|||||||
* or diagnostic being made for the session script.
|
* or diagnostic being made for the session script.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <maxscale/spinlock.h>
|
#include <maxscale/cdefs.h>
|
||||||
#include <maxscale/debug.h>
|
#include <lauxlib.h>
|
||||||
#include <maxscale/log_manager.h>
|
#include <lua.h>
|
||||||
|
#include <lualib.h>
|
||||||
#include <string.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/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 =
|
MODULE_INFO info =
|
||||||
{
|
{
|
||||||
@ -126,6 +128,45 @@ static int id_gen(lua_State* state)
|
|||||||
return 1;
|
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.
|
* The Lua filter instance.
|
||||||
*/
|
*/
|
||||||
@ -144,6 +185,7 @@ typedef struct
|
|||||||
{
|
{
|
||||||
SESSION* session;
|
SESSION* session;
|
||||||
lua_State* lua_state;
|
lua_State* lua_state;
|
||||||
|
GWBUF* current_query;
|
||||||
SPINLOCK lock;
|
SPINLOCK lock;
|
||||||
DOWNSTREAM down;
|
DOWNSTREAM down;
|
||||||
UPSTREAM up;
|
UPSTREAM up;
|
||||||
@ -290,9 +332,20 @@ static void * newSession(FILTER *instance, SESSION *session)
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
/** Expose an ID generation function */
|
||||||
lua_pushcfunction(my_session->lua_state, id_gen);
|
lua_pushcfunction(my_session->lua_state, id_gen);
|
||||||
lua_setglobal(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");
|
lua_getglobal(my_session->lua_state, "newSession");
|
||||||
if (lua_pcall(my_session->lua_state, 0, 0, 0))
|
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)
|
if (fullquery && my_session->lua_state)
|
||||||
{
|
{
|
||||||
spinlock_acquire(&my_session->lock);
|
spinlock_acquire(&my_session->lock);
|
||||||
|
|
||||||
|
/** Store the current query being processed */
|
||||||
|
my_session->current_query = queue;
|
||||||
|
|
||||||
lua_getglobal(my_session->lua_state, "routeQuery");
|
lua_getglobal(my_session->lua_state, "routeQuery");
|
||||||
lua_pushlstring(my_session->lua_state, fullquery, strlen(fullquery));
|
lua_pushlstring(my_session->lua_state, fullquery, strlen(fullquery));
|
||||||
if (lua_pcall(my_session->lua_state, 1, 1, 0))
|
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);
|
route = lua_toboolean(my_session->lua_state, -1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
my_session->current_query = NULL;
|
||||||
|
|
||||||
spinlock_release(&my_session->lock);
|
spinlock_release(&my_session->lock);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user