return nullptr;
}
+ // Drop GIL for blocking mon command execution
+ PyThreadState *tstate = PyEval_SaveThread();
+
std::string value;
bool found = self->this_module->get_store(what, &value);
+
+ PyEval_RestoreThread(tstate);
+
if (found) {
dout(10) << "ceph_store_get " << what << " found: " << value.c_str() << dendl;
return PyString_FromString(value.c_str());
// I am the standby and someone else is active, start modules
// in standby mode to do redirects if needed
if (!py_module_registry.is_standby_running()) {
- py_module_registry.standby_start();
+ py_module_registry.standby_start(monc);
}
}
}
-void PyModuleRegistry::standby_start()
+void PyModuleRegistry::standby_start(MonClient &mc)
{
Mutex::Locker l(lock);
assert(active_modules == nullptr);
dout(4) << "Starting modules in standby mode" << dendl;
standby_modules.reset(new StandbyPyModules(
- mgr_map, module_config, clog));
+ mgr_map, module_config, clog, mc));
std::set<std::string> failed_modules;
for (const auto &i : modules) {
const std::map<std::string, std::string> &kv_store,
MonClient &mc, LogChannelRef clog_, Objecter &objecter_,
Client &client_, Finisher &f);
- void standby_start();
+ void standby_start(MonClient &mc);
bool is_standby_running() const
{
StandbyPyModules::StandbyPyModules(
const MgrMap &mgr_map_,
- PyModuleConfig &module_config, LogChannelRef clog_)
- : state(module_config),
+ PyModuleConfig &module_config,
+ LogChannelRef clog_,
+ MonClient &monc_)
+ : state(module_config, monc_),
clog(clog_)
{
state.set_mgr_map(mgr_map_);
bool StandbyPyModule::get_config(const std::string &key,
std::string *value) const
{
- PyThreadState *tstate = PyEval_SaveThread();
- PyEval_RestoreThread(tstate);
-
const std::string global_key = PyModule::config_prefix
+ get_name() + "/" + key;
});
}
+bool StandbyPyModule::get_store(const std::string &key,
+ std::string *value) const
+{
+
+ const std::string global_key = PyModule::config_prefix
+ + get_name() + "/" + key;
+
+ dout(4) << __func__ << " key: " << global_key << dendl;
+
+ // Active modules use a cache of store values (kept up to date
+ // as writes pass through the active mgr), but standbys
+ // fetch values synchronously to get an up to date value.
+ // It's an acceptable cost because standby modules should not be
+ // doing a lot.
+
+ MonClient &monc = state.get_monc();
+
+ std::ostringstream cmd_json;
+ cmd_json << "{\"prefix\": \"config-key get\", \"key\": \""
+ << global_key << "\"}";
+
+ bufferlist outbl;
+ std::string outs;
+ C_SaferCond c;
+ monc.start_mon_command(
+ {cmd_json.str()},
+ {},
+ &outbl,
+ &outs,
+ &c);
+
+ int r = c.wait();
+ if (r == -ENOENT) {
+ return false;
+ } else if (r != 0) {
+ // This is some internal error, not meaningful to python modules,
+ // so let them just see no value.
+ derr << __func__ << " error fetching store key '" << global_key << "': "
+ << cpp_strerror(r) << " " << outs << dendl;
+ return false;
+ } else {
+ *value = outbl.to_str();
+ return true;
+ }
+}
+
std::string StandbyPyModule::get_active_uri() const
{
std::string result;
MgrMap mgr_map;
PyModuleConfig &module_config;
+ MonClient &monc;
public:
- StandbyPyModuleState(PyModuleConfig &module_config_)
- : module_config(module_config_)
+ StandbyPyModuleState(PyModuleConfig &module_config_, MonClient &monc_)
+ : module_config(module_config_), monc(monc_)
{}
void set_mgr_map(const MgrMap &mgr_map_)
mgr_map = mgr_map_;
}
+ // MonClient does all its own locking so we're happy to hand out
+ // references.
+ MonClient &get_monc() {return monc;};
+
template<typename Callback, typename...Args>
void with_mgr_map(Callback&& cb, Args&&...args) const
{
}
bool get_config(const std::string &key, std::string *value) const;
+ bool get_store(const std::string &key, std::string *value) const;
std::string get_active_uri() const;
int load();
StandbyPyModules(
const MgrMap &mgr_map_,
PyModuleConfig &module_config,
- LogChannelRef clog_);
+ LogChannelRef clog_,
+ MonClient &monc);
int start_one(PyModuleRef py_module);