return on_finish(-EINVAL, "unknown command prefix "s + prefix, empty);
}
+ // make sure one of the registered commands with this prefix validates.
+ while (!validate_cmd(m_cct, p->second.desc, cmdmap, errss)) {
+ ++p;
+ if (p->first != prefix) {
+ return on_finish(-EINVAL, "invalid command json", empty);
+ }
+ }
+
// Drop lock to avoid cycles in cases where the hook takes
// the same lock that was held during calls to register/unregister,
// and set in_hook to allow unregister to wait for us before
in_hook = true;
auto hook = p->second.hook;
l.unlock();
- if (!validate(prefix, cmdmap, empty)) {
- on_finish(-EINVAL, "invalid command json", empty);
- } else {
- hook->call_async(prefix, cmdmap, format, inbl, on_finish);
- }
+ hook->call_async(prefix, cmdmap, format, inbl, on_finish);
+
l.lock();
in_hook = false;
in_hook_cond.notify_all();
wakeup();
}
-
-bool AdminSocket::validate(const std::string& prefix,
- const cmdmap_t& cmdmap,
- bufferlist& out) const
-{
- stringstream os;
- if (validate_cmd(m_cct, hooks.at(prefix).desc, cmdmap, os)) {
- return true;
- } else {
- out.append(os);
- return false;
- }
-}
-
int AdminSocket::register_command(std::string_view cmddesc,
AdminSocketHook *hook,
std::string_view help)
std::unique_lock l(lock);
string prefix = cmddesc_get_prefix(cmddesc);
auto i = hooks.find(prefix);
- if (i != hooks.cend()) {
- ldout(m_cct, 5) << "register_command " << prefix << " hook " << hook
+ if (i != hooks.cend() &&
+ i->second.desc == cmddesc) {
+ ldout(m_cct, 5) << "register_command " << prefix
+ << " cmddesc " << cmddesc << " hook " << hook
<< " EEXIST" << dendl;
ret = -EEXIST;
} else {
void entry() noexcept;
bool do_accept();
void do_tell_queue();
- bool validate(const std::string& command,
- const cmdmap_t& cmdmap,
- ceph::buffer::list& out) const;
CephContext *m_cct;
std::string m_path;
: hook(hook), desc(desc), help(help) {}
};
- std::map<std::string, hook_info, std::less<>> hooks;
+ std::multimap<std::string, hook_info, std::less<>> hooks;
friend class AdminSocketTest;
friend class HelpHook;