diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-21 11:54:28 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-21 11:54:28 +0000 |
commit | e6918187568dbd01842d8d1d2c808ce16a894239 (patch) | |
tree | 64f88b554b444a49f656b6c656111a145cbbaa28 /src/rgw/rgw_lua_data_filter.cc | |
parent | Initial commit. (diff) | |
download | ceph-e6918187568dbd01842d8d1d2c808ce16a894239.tar.xz ceph-e6918187568dbd01842d8d1d2c808ce16a894239.zip |
Adding upstream version 18.2.2.upstream/18.2.2
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'src/rgw/rgw_lua_data_filter.cc')
-rw-r--r-- | src/rgw/rgw_lua_data_filter.cc | 143 |
1 files changed, 143 insertions, 0 deletions
diff --git a/src/rgw/rgw_lua_data_filter.cc b/src/rgw/rgw_lua_data_filter.cc new file mode 100644 index 000000000..9ebaf3453 --- /dev/null +++ b/src/rgw/rgw_lua_data_filter.cc @@ -0,0 +1,143 @@ +#include "rgw_lua_data_filter.h" +#include "rgw_lua_utils.h" +#include "rgw_lua_request.h" +#include "rgw_lua_background.h" +#include "rgw_process_env.h" +#include <lua.hpp> + +namespace rgw::lua { + +void push_bufferlist_byte(lua_State* L, bufferlist::iterator& it) { + char byte[1]; + it.copy(1, byte); + lua_pushlstring(L, byte, 1); +} + +struct BufferlistMetaTable : public EmptyMetaTable { + + static std::string TableName() {return "Data";} + static std::string Name() {return TableName() + "Meta";} + + static int IndexClosure(lua_State* L) { + auto bl = reinterpret_cast<bufferlist*>(lua_touserdata(L, lua_upvalueindex(1))); + const auto index = luaL_checkinteger(L, 2); + if (index <= 0 || index > bl->length()) { + // lua arrays start from 1 + lua_pushnil(L); + return ONE_RETURNVAL; + } + auto it = bl->begin(index-1); + if (it != bl->end()) { + push_bufferlist_byte(L, it); + } else { + lua_pushnil(L); + } + + return ONE_RETURNVAL; + } + + static int PairsClosure(lua_State* L) { + auto bl = reinterpret_cast<bufferlist*>(lua_touserdata(L, lua_upvalueindex(1))); + ceph_assert(bl); + lua_pushlightuserdata(L, bl); + lua_pushcclosure(L, stateless_iter, ONE_UPVAL); // push the stateless iterator function + lua_pushnil(L); // indicate this is the first call + // return stateless_iter, nil + + return TWO_RETURNVALS; + } + + static int stateless_iter(lua_State* L) { + // based on: http://lua-users.org/wiki/GeneralizedPairsAndIpairs + auto bl = reinterpret_cast<bufferlist*>(lua_touserdata(L, lua_upvalueindex(1))); + lua_Integer index; + if (lua_isnil(L, -1)) { + index = 1; + } else { + index = luaL_checkinteger(L, -1) + 1; + } + + // lua arrays start from 1 + auto it = bl->begin(index-1); + + if (index > bl->length()) { + // index of the last element was provided + lua_pushnil(L); + lua_pushnil(L); + // return nil, nil + } else { + lua_pushinteger(L, index); + push_bufferlist_byte(L, it); + // return key, value + } + + return TWO_RETURNVALS; + } + + static int LenClosure(lua_State* L) { + const auto bl = reinterpret_cast<bufferlist*>(lua_touserdata(L, lua_upvalueindex(1))); + + lua_pushinteger(L, bl->length()); + + return ONE_RETURNVAL; + } +}; + +int RGWObjFilter::execute(bufferlist& bl, off_t offset, const char* op_name) const { + auto L = luaL_newstate(); + lua_state_guard lguard(L); + + open_standard_libs(L); + + create_debug_action(L, s->cct); + + // create the "Data" table + create_metatable<BufferlistMetaTable>(L, true, &bl); + lua_getglobal(L, BufferlistMetaTable::TableName().c_str()); + ceph_assert(lua_istable(L, -1)); + + // create the "Request" table + request::create_top_metatable(L, s, op_name); + + // create the "Offset" variable + lua_pushinteger(L, offset); + lua_setglobal(L, "Offset"); + + if (s->penv.lua.background) { + // create the "RGW" table + s->penv.lua.background->create_background_metatable(L); + lua_getglobal(L, rgw::lua::RGWTable::TableName().c_str()); + ceph_assert(lua_istable(L, -1)); + } + + try { + // execute the lua script + if (luaL_dostring(L, script.c_str()) != LUA_OK) { + const std::string err(lua_tostring(L, -1)); + ldpp_dout(s, 1) << "Lua ERROR: " << err << dendl; + return -EINVAL; + } + } catch (const std::runtime_error& e) { + ldpp_dout(s, 1) << "Lua ERROR: " << e.what() << dendl; + return -EINVAL; + } + + return 0; +} + +int RGWGetObjFilter::handle_data(bufferlist& bl, + off_t bl_ofs, + off_t bl_len) { + filter.execute(bl, bl_ofs, "get_obj"); + // return value is ignored since we don't want to fail execution if lua script fails + return RGWGetObj_Filter::handle_data(bl, bl_ofs, bl_len); +} + +int RGWPutObjFilter::process(bufferlist&& data, uint64_t logical_offset) { + filter.execute(data, logical_offset, "put_obj"); + // return value is ignored since we don't want to fail execution if lua script fails + return rgw::putobj::Pipe::process(std::move(data), logical_offset); +} + +} // namespace rgw::lua + |