cerr << "ERROR: cannot specify tenant in background context" << std::endl;
return EINVAL;
}
- rc = rgw::lua::write_script(dpp(), store, tenant, null_yield, script_ctx, script);
+ auto lua_manager = store->get_lua_manager();
+ rc = rgw::lua::write_script(dpp(), lua_manager.get(), tenant, null_yield, script_ctx, script);
if (rc < 0) {
cerr << "ERROR: failed to put script. error: " << rc << std::endl;
return -rc;
cerr << "ERROR: invalid script context: " << *str_script_ctx << ". must be one of: preRequest, postRequest, background" << std::endl;
return EINVAL;
}
+ auto lua_manager = store->get_lua_manager();
std::string script;
- const auto rc = rgw::lua::read_script(dpp(), store, tenant, null_yield, script_ctx, script);
+ const auto rc = rgw::lua::read_script(dpp(), lua_manager.get(), tenant, null_yield, script_ctx, script);
if (rc == -ENOENT) {
std::cout << "no script exists for context: " << *str_script_ctx <<
(tenant.empty() ? "" : (" in tenant: " + tenant)) << std::endl;
cerr << "ERROR: invalid script context: " << *str_script_ctx << ". must be one of: preRequest, postRequest, background" << std::endl;
return EINVAL;
}
- const auto rc = rgw::lua::delete_script(dpp(), store, tenant, null_yield, script_ctx);
+ auto lua_manager = store->get_lua_manager();
+ const auto rc = rgw::lua::delete_script(dpp(), lua_manager.get(), tenant, null_yield, script_ctx);
if (rc < 0) {
cerr << "ERROR: failed to remove script. error: " << rc << std::endl;
return -rc;
parse_buffer& buffer, bool is_ssl,
SharedMutex& pause_mutex,
rgw::dmclock::Scheduler *scheduler,
+ std::unique_ptr<rgw::sal::LuaManager>& lua_manager,
boost::system::error_code& ec,
yield_context yield)
{
*env.auth_registry, &client, env.olog, y,
scheduler, &user, &latency,
env.ratelimiting->get_active(),
- &http_ret, env.lua_background);
+ env.lua_background,
+ lua_manager,
+ &http_ret);
if (cct->_conf->subsys.should_gather(ceph_subsys_rgw_access, 1)) {
// access log line elements begin per Apache Combined Log Format with additions following
#endif
SharedMutex pause_mutex;
std::unique_ptr<rgw::dmclock::Scheduler> scheduler;
+ std::unique_ptr<rgw::sal::LuaManager> lua_manager;
struct Listener {
tcp::endpoint endpoint;
public:
AsioFrontend(const RGWProcessEnv& env, RGWFrontendConfig* conf,
dmc::SchedulerCtx& sched_ctx)
- : env(env), conf(conf), pause_mutex(context.get_executor())
+ : env(env), conf(conf), pause_mutex(context.get_executor()),
+ lua_manager(env.store->get_lua_manager())
{
auto sched_t = dmc::get_scheduler_t(ctx());
switch(sched_t){
conn->buffer.consume(bytes);
handle_connection(context, env, stream, timeout, header_limit,
conn->buffer, true, pause_mutex, scheduler.get(),
+ lua_manager,
ec, yield);
if (!ec) {
// ssl shutdown (ignoring errors)
boost::system::error_code ec;
handle_connection(context, env, conn->socket, timeout, header_limit,
conn->buffer, false, pause_mutex, scheduler.get(),
+ lua_manager,
ec, yield);
conn->socket.shutdown(tcp_socket::shutdown_both, ec);
}, make_stack_allocator());
{
env.store = store;
env.auth_registry = std::move(auth_registry);
+ lua_manager = store->get_lua_manager();
// unpause to unblock connections
pause_mutex.unlock();
int ret = process_request(store, rest, req, uri_prefix,
*auth_registry, &client_io, olog,
null_yield, nullptr, nullptr, nullptr,
- ratelimit.get_active(), nullptr);
+ ratelimit.get_active(),
+ nullptr,
+ lua_manager);
if (ret < 0) {
/* we don't really care about return code */
dout(20) << "process_request() returned " << ret << dendl;
}
-int read_script(const DoutPrefixProvider *dpp, rgw::sal::Store* store, const std::string& tenant, optional_yield y, context ctx, std::string& script)
+int read_script(const DoutPrefixProvider *dpp, sal::LuaManager* manager, const std::string& tenant, optional_yield y, context ctx, std::string& script)
{
- auto lua_mgr = store->get_lua_manager();
- return lua_mgr->get_script(dpp, y, script_oid(ctx, tenant), script);
+ return manager->get_script(dpp, y, script_oid(ctx, tenant), script);
+
}
-int write_script(const DoutPrefixProvider *dpp, rgw::sal::Store* store, const std::string& tenant, optional_yield y, context ctx, const std::string& script)
+int write_script(const DoutPrefixProvider *dpp, sal::LuaManager* manager, const std::string& tenant, optional_yield y, context ctx, const std::string& script)
{
- auto lua_mgr = store->get_lua_manager();
-
- return lua_mgr->put_script(dpp, y, script_oid(ctx, tenant), script);
+ return manager->put_script(dpp, y, script_oid(ctx, tenant), script);
}
-int delete_script(const DoutPrefixProvider *dpp, rgw::sal::Store* store, const std::string& tenant, optional_yield y, context ctx)
+int delete_script(const DoutPrefixProvider *dpp, sal::LuaManager* manager, const std::string& tenant, optional_yield y, context ctx)
{
- auto lua_mgr = store->get_lua_manager();
-
- return lua_mgr->del_script(dpp, y, script_oid(ctx, tenant));
+ return manager->del_script(dpp, y, script_oid(ctx, tenant));
}
#ifdef WITH_RADOSGW_LUA_PACKAGES
class lua_State;
class rgw_user;
+class DoutPrefixProvider;
namespace rgw::sal {
class RadosStore;
+ class LuaManager;
}
namespace rgw::lua {
bool verify(const std::string& script, std::string& err_msg);
// store a lua script in a context
-int write_script(const DoutPrefixProvider *dpp, rgw::sal::Store* store, const std::string& tenant, optional_yield y, context ctx, const std::string& script);
+int write_script(const DoutPrefixProvider *dpp, rgw::sal::LuaManager* manager, const std::string& tenant, optional_yield y, context ctx, const std::string& script);
// read the stored lua script from a context
-int read_script(const DoutPrefixProvider *dpp, rgw::sal::Store* store, const std::string& tenant, optional_yield y, context ctx, std::string& script);
+int read_script(const DoutPrefixProvider *dpp, rgw::sal::LuaManager* manager, const std::string& tenant, optional_yield y, context ctx, std::string& script);
// delete the stored lua script from a context
-int delete_script(const DoutPrefixProvider *dpp, rgw::sal::Store* store, const std::string& tenant, optional_yield y, context ctx);
+int delete_script(const DoutPrefixProvider *dpp, rgw::sal::LuaManager* manager, const std::string& tenant, optional_yield y, context ctx);
using packages_t = std::set<std::string>;
+#include "rgw_sal_rados.h"
#include "rgw_lua_background.h"
#include "rgw_lua.h"
#include "rgw_lua_utils.h"
int execute_interval) :
execute_interval(execute_interval),
dp(cct, dout_subsys, "lua background: "),
- store(store),
+ lua_manager(store->get_lua_manager()),
cct(cct),
luarocks_path(luarocks_path) {}
cond.notify_all();
}
-void Background::resume(rgw::sal::Store* _store) {
- store = _store;
+void Background::resume(rgw::sal::Store* store) {
+ lua_manager = store->get_lua_manager();
paused = false;
cond.notify_all();
}
return -EAGAIN;
}
std::string tenant;
- return rgw::lua::read_script(&dp, store, tenant, null_yield, rgw::lua::context::background, rgw_script);
+ return rgw::lua::read_script(&dp, lua_manager.get(), tenant, null_yield, rgw::lua::context::background, rgw_script);
}
const BackgroundMapValue Background::empty_table_value;
bool paused = false;
int execute_interval;
const DoutPrefix dp;
- rgw::sal::Store* store;
+ std::unique_ptr<rgw::sal::LuaManager> lua_manager;
CephContext* const cct;
const std::string luarocks_path;
std::thread runner;
string* user,
ceph::coarse_real_clock::duration* latency,
std::shared_ptr<RateLimiter> ratelimit,
- int* http_ret,
- rgw::lua::Background* lua_background)
+ rgw::lua::Background* lua_background,
+ std::unique_ptr<rgw::sal::LuaManager>& lua_manager,
+ int* http_ret)
{
int ret = client_io->init(g_ceph_context);
dout(1) << "====== starting new request req=" << hex << req << dec
{
s->trace_enabled = tracing::rgw::tracer.is_enabled();
std::string script;
- auto rc = rgw::lua::read_script(s, store, s->bucket_tenant, s->yield, rgw::lua::context::preRequest, script);
+ auto rc = rgw::lua::read_script(s, lua_manager.get(), s->bucket_tenant, s->yield, rgw::lua::context::preRequest, script);
if (rc == -ENOENT) {
// no script, nothing to do
} else if (rc < 0) {
s->trace->SetAttribute(tracing::rgw::OBJECT_NAME, s->object->get_name());
}
std::string script;
- auto rc = rgw::lua::read_script(s, store, s->bucket_tenant, s->yield, rgw::lua::context::postRequest, script);
+ auto rc = rgw::lua::read_script(s, lua_manager.get(), s->bucket_tenant, s->yield, rgw::lua::context::postRequest, script);
if (rc == -ENOENT) {
// no script, nothing to do
} else if (rc < 0) {
int sock_fd;
std::string uri_prefix;
rgw::lua::Background* lua_background;
+ std::unique_ptr<rgw::sal::LuaManager> lua_manager;
struct RGWWQ : public DoutPrefixProvider, public ThreadPool::WorkQueue<RGWRequest> {
RGWProcess* process;
sock_fd(-1),
uri_prefix(pe->uri_prefix),
lua_background(pe->lua_background),
+ lua_manager(store->get_lua_manager()),
req_wq(this,
ceph::make_timespan(g_conf()->rgw_op_thread_timeout),
ceph::make_timespan(g_conf()->rgw_op_thread_suicide_timeout),
rgw_auth_registry_ptr_t auth_registry) {
this->store = store;
this->auth_registry = std::move(auth_registry);
+ lua_manager = store->get_lua_manager();
m_tp.unpause();
}
std::string* user,
ceph::coarse_real_clock::duration* latency,
std::shared_ptr<RateLimiter> ratelimit,
- int* http_ret = nullptr,
- rgw::lua::Background* lua_background = nullptr);
+ rgw::lua::Background* lua_background,
+ std::unique_ptr<rgw::sal::LuaManager>& lua_manager,
+ int* http_ret = nullptr);
extern int rgw_process_authenticated(RGWHandler_REST* handler,
RGWOp*& op,
return store->svc()->zone->get_zone().tier_type;
}
-RadosLuaManager::RadosLuaManager(RadosStore* _s) : store(_s)
-{
- pool = store->svc()->zone->get_zone_params().log_pool;
-}
+RadosLuaManager::RadosLuaManager(RadosStore* _s) :
+ store(_s),
+ pool((store->svc() && store->svc()->zone) ? store->svc()->zone->get_zone_params().log_pool : rgw_pool())
+{ }
int RadosLuaManager::get_script(const DoutPrefixProvider* dpp, optional_yield y, const std::string& key, std::string& script)
{
+ if (pool.empty()) {
+ ldpp_dout(dpp, 10) << "WARNING: missing pool when reading lua script " << dendl;
+ return 0;
+ }
bufferlist bl;
int r = rgw_get_system_obj(store->svc()->sysobj, pool, key, bl, nullptr, nullptr, y, dpp);
int RadosLuaManager::put_script(const DoutPrefixProvider* dpp, optional_yield y, const std::string& key, const std::string& script)
{
+ if (pool.empty()) {
+ ldpp_dout(dpp, 10) << "WARNING: missing pool when writing lua script " << dendl;
+ return 0;
+ }
bufferlist bl;
ceph::encode(script, bl);
int RadosLuaManager::del_script(const DoutPrefixProvider* dpp, optional_yield y, const std::string& key)
{
+ if (pool.empty()) {
+ ldpp_dout(dpp, 10) << "WARNING: missing pool when deleting lua script " << dendl;
+ return 0;
+ }
int r = rgw_delete_system_obj(dpp, store->svc()->sysobj, pool, key, nullptr, y);
if (r < 0 && r != -ENOENT) {
return r;
};
class RadosLuaManager : public StoreLuaManager {
- RadosStore* store;
+ RadosStore* const store;
rgw_pool pool;
public:
ASSERT_NE(rc, 0);
}
+#define MAKE_STORE auto store = std::unique_ptr<sal::RadosStore>(new sal::RadosStore); \
+ store->setRados(new RGWRados);
+
TEST(TestRGWLua, OpsLog)
{
const std::string script = R"(
end
)";
- auto store = std::unique_ptr<sal::RadosStore>(new sal::RadosStore);
- store->setRados(new RGWRados);
+ MAKE_STORE;
struct MockOpsLogSink : OpsLogSink {
bool logged = false;
class TestBackground : public rgw::lua::Background {
const unsigned read_time;
+
protected:
int read_script() override {
// don't read the object from the store
}
public:
- TestBackground(const std::string& script, unsigned read_time = 0) :
- rgw::lua::Background(nullptr, g_cct, "", 1 /*run every second*/),
+ TestBackground(sal::RadosStore* store, const std::string& script, unsigned read_time = 0) :
+ rgw::lua::Background(store, g_cct, "", /* luarocks path */ 1 /* run every second */),
read_time(read_time) {
// the script is passed in the constructor
rgw_script = script;
TEST(TestRGWLuaBackground, Start)
{
+ MAKE_STORE;
{
// ctr and dtor without running
- TestBackground lua_background("");
+ TestBackground lua_background(store.get(), "");
}
{
// ctr and dtor with running
- TestBackground lua_background("");
+ TestBackground lua_background(store.get(), "");
lua_background.start();
}
}
RGW[key] = value
)";
- TestBackground lua_background(script);
+ MAKE_STORE;
+ TestBackground lua_background(store.get(), script);
lua_background.start();
std::this_thread::sleep_for(wait_time);
EXPECT_EQ(get_table_value<std::string>(lua_background, "hello"), "world");
RGW[key] = value
)";
- TestBackground lua_background(background_script);
+ MAKE_STORE;
+ TestBackground lua_background(store.get(), background_script);
lua_background.start();
std::this_thread::sleep_for(wait_time);
ASSERT_EQ(rc, 0);
EXPECT_EQ(get_table_value<std::string>(lua_background, "hello"), "from request");
// now we resume and let the background set the value
- lua_background.resume(nullptr);
+ lua_background.resume(store.get());
std::this_thread::sleep_for(wait_time);
EXPECT_EQ(get_table_value<std::string>(lua_background, "hello"), "from background");
}
end
)";
- TestBackground lua_background(script);
+ MAKE_STORE;
+ TestBackground lua_background(store.get(), script);
lua_background.start();
std::this_thread::sleep_for(wait_time);
const auto value_len = get_table_value<std::string>(lua_background, "hello").size();
end
)";
+ MAKE_STORE;
constexpr auto long_wait_time = std::chrono::seconds(6);
- TestBackground lua_background(script, 2);
+ TestBackground lua_background(store.get(), script, 2);
lua_background.start();
std::this_thread::sleep_for(long_wait_time);
const auto value_len = get_table_value<std::string>(lua_background, "hello").size();
RGW[key] = value
)";
- TestBackground lua_background(script);
+ MAKE_STORE;
+ TestBackground lua_background(store.get(), script);
lua_background.pause();
lua_background.start();
std::this_thread::sleep_for(wait_time);
EXPECT_EQ(get_table_value<std::string>(lua_background, "hello"), "");
- lua_background.resume(nullptr);
+ lua_background.resume(store.get());
std::this_thread::sleep_for(wait_time);
EXPECT_EQ(get_table_value<std::string>(lua_background, "hello"), "world");
}
end
)";
- TestBackground lua_background(script);
+ MAKE_STORE;
+ TestBackground lua_background(store.get(), script);
lua_background.start();
std::this_thread::sleep_for(wait_time);
const auto value_len = get_table_value<std::string>(lua_background, "hello").size();
std::this_thread::sleep_for(wait_time);
// no change in len
EXPECT_EQ(value_len, get_table_value<std::string>(lua_background, "hello").size());
- lua_background.resume(nullptr);
+ lua_background.resume(store.get());
std::this_thread::sleep_for(wait_time);
// should be a change in len
EXPECT_GT(get_table_value<std::string>(lua_background, "hello").size(), value_len);
end
)";
- TestBackground lua_background(script);
+ MAKE_STORE;
+ TestBackground lua_background(store.get(), script);
lua_background.start();
std::this_thread::sleep_for(wait_time);
const auto value_len = get_table_value<std::string>(lua_background, "hello").size();
TEST(TestRGWLuaBackground, TableValues)
{
- TestBackground lua_background("");
+ MAKE_STORE;
+ TestBackground lua_background(store.get(), "");
const std::string request_script = R"(
RGW["key1"] = "string value"
TEST(TestRGWLuaBackground, TablePersist)
{
- TestBackground lua_background("");
+ MAKE_STORE;
+ TestBackground lua_background(store.get(), "");
std::string request_script = R"(
RGW["key1"] = "string value"
TEST(TestRGWLuaBackground, TableValuesFromRequest)
{
- TestBackground lua_background("");
+ MAKE_STORE;
+ TestBackground lua_background(store.get(), "");
lua_background.start();
const std::string request_script = R"(
TEST(TestRGWLuaBackground, TableInvalidValue)
{
- TestBackground lua_background("");
+ MAKE_STORE;
+ TestBackground lua_background(store.get(), "");
lua_background.start();
const std::string request_script = R"(
TEST(TestRGWLuaBackground, TableErase)
{
- TestBackground lua_background("");
+ MAKE_STORE;
+ TestBackground lua_background(store.get(), "");
std::string request_script = R"(
RGW["size"] = 0
TEST(TestRGWLuaBackground, TableIterate)
{
- TestBackground lua_background("");
+ MAKE_STORE;
+ TestBackground lua_background(store.get(), "");
const std::string request_script = R"(
RGW["key1"] = "string value"
TEST(TestRGWLuaBackground, TableIncrement)
{
- TestBackground lua_background("");
+ MAKE_STORE;
+ TestBackground lua_background(store.get(), "");
const std::string request_script = R"(
RGW["key1"] = 42
TEST(TestRGWLuaBackground, TableIncrementBy)
{
- TestBackground lua_background("");
+ MAKE_STORE;
+ TestBackground lua_background(store.get(), "");
const std::string request_script = R"(
RGW["key1"] = 42
TEST(TestRGWLuaBackground, TableDecrement)
{
- TestBackground lua_background("");
+ MAKE_STORE;
+ TestBackground lua_background(store.get(), "");
const std::string request_script = R"(
RGW["key1"] = 42
TEST(TestRGWLuaBackground, TableDecrementBy)
{
- TestBackground lua_background("");
+ MAKE_STORE;
+ TestBackground lua_background(store.get(), "");
const std::string request_script = R"(
RGW["key1"] = 42
TEST(TestRGWLuaBackground, TableIncrementValueError)
{
- TestBackground lua_background("");
+ MAKE_STORE;
+ TestBackground lua_background(store.get(), "");
std::string request_script = R"(
-- cannot increment string values
TEST(TestRGWLuaBackground, TableIncrementError)
{
- TestBackground lua_background("");
+ MAKE_STORE;
+ TestBackground lua_background(store.get(), "");
std::string request_script = R"(
-- missing argument