blob: 3cdf81041c48ab859121ab5a1aad2c3a791663bd [file] [log] [blame]
/*
Licensed to the Apache Software Foundation (ASF) under one
or more contributor license agreements. See the NOTICE file
distributed with this work for additional information
regarding copyright ownership. The ASF licenses this file
to you under the Apache License, Version 2.0 (the
"License"); you may not use this file except in compliance
with the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
#ifndef LUA_STATE_H_
#define LUA_STATE_H_
#include <string>
#include <vector>
#include <utility>
#include <pthread.h>
#include <lua.hpp>
/*
Lua Plugin threading model
For remapping, we need to support multiple indepedent Lua plugin
instances. Each instance is handled by a LuaPluginInstance object.
Each plugin instance maintains a pool of lua_States which are
independent Lua interpeters. The LuaThreadState object owns a single
lua_State, holding additional hook data that is needed to de-multiplex
events.
There are two basic code paths to obtaining a LuaThreadState. If
we already have a lua_State, then we can use the __instanceid and
__threadid global variables to identify the LuaThreadState object.
If we don't have a lua_State, then we know the instance ID from the
hook continuation data (attached per LuaPluginInstance), and we
choose a state by hashing the thread ID.
Traffic Server +-> LuaPluginInstance[0]
| +-> LuaThreadState[0]
| +-> LuaThreadState[1]
| +-> LuaThreadState[2]
| +-> LuaThreadState[3]
|
+-> LuaPluginInstance[1]
| +-> LuaThreadState[0]
| +-> LuaThreadState[1]
| +-> LuaThreadState[2]
| +-> LuaThreadState[3]
|
+-> LuaPluginInstance[2]
+-> LuaThreadState[0]
+-> LuaThreadState[1]
+-> LuaThreadState[2]
+-> LuaThreadState[3]
*/
typedef uint32_t instanceid_t;
struct LuaThreadState;
struct LuaPluginInstance;
// Per-thread lua_State. Used to execute Lua-side code in ethreads.
struct LuaThreadState
{
lua_State * lua;
int hookrefs[TS_HTTP_LAST_HOOK];
LuaPluginInstance * instance;
pthread_mutex_t mutex;
LuaThreadState();
~LuaThreadState();
bool alloc(LuaPluginInstance *, unsigned);
bool init(LuaPluginInstance *);
void release();
private:
LuaThreadState(const LuaThreadState&); // disable
LuaThreadState& operator=(const LuaThreadState&); // disable
};
struct LuaPluginInstance
{
typedef std::vector<std::string> pathlist_t;
typedef TSCont demux_table_t[TS_HTTP_LAST_HOOK];
LuaPluginInstance();
~LuaPluginInstance();
void invalidate();
void init(unsigned argc, const char ** argv);
struct {
demux_table_t global;
demux_table_t txn;
demux_table_t ssn;
} demux;
instanceid_t instanceid;
pathlist_t paths;
std::vector<LuaThreadState *> states;
private:
LuaPluginInstance(const LuaPluginInstance&); // disable
LuaPluginInstance& operator=(const LuaPluginInstance&); // disable
};
instanceid_t LuaPluginRegister(unsigned argc, const char ** argv);
void LuaPluginUnregister(instanceid_t instanceid);
// Acquire a locked Lua thread state belonging to the given instance.
std::pair<LuaThreadState *, LuaPluginInstance *> LuaThreadStateAcquire(instanceid_t);
std::pair<LuaThreadState *, LuaPluginInstance *> LuaThreadStateAcquire(lua_State *);
// Return the previously acquired Lua thread state.
void LuaThreadStateRelease(LuaThreadState *);
struct ScopedLuaState
{
explicit ScopedLuaState(instanceid_t instanceid)
: ptr(LuaThreadStateAcquire(instanceid)) {
}
explicit ScopedLuaState(lua_State * lua)
: ptr(LuaThreadStateAcquire(lua)) {
}
~ScopedLuaState() {
LuaThreadStateRelease(this->ptr.first);
}
operator bool() const {
return this->ptr.first != NULL;
}
LuaThreadState * operator->() const {
return this->ptr.first;
}
LuaPluginInstance * instance() const {
return this->ptr.second;
}
private:
std::pair<LuaThreadState *, LuaPluginInstance *> ptr;
};
#endif // LUA_STATE_H_