1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
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
|