} else if (op_reset) {
r.reset_roots(roots);
} else if (op_release) {
- r.release_roots();
+ r.release();
} else if (op_cancel) {
- r.cancel_roots();
+ r.cancel();
}
double timeout;
struct CancelAll: public QuiesceDbManager::RequestContext {
mds_rank_t whoami;
CancelAll(mds_rank_t whoami) : whoami(whoami) {
- request.cancel_roots();
+ request.cancel();
}
void finish(int rc) override {
dout(rc == 0 ? 15 : 3) << "injected cancel all completed with rc: " << rc << dendl;
/// for when `roots` is empty
enum RootsOp: uint8_t {
INCLUDE_OR_QUERY,
- EXCLUDE_OR_RELEASE,
- RESET_OR_CANCEL,
+ EXCLUDE_OR_CANCEL,
+ RESET_OR_RELEASE,
__INVALID
};
bool is_mutating() const { return (control.roots_op != INCLUDE_OR_QUERY) || !roots.empty() || timeout || expiration; }
bool is_cancel_all() const { return !set_id && is_cancel(); }
- bool excludes_roots() const { return control.roots_op == RESET_OR_CANCEL || (control.roots_op == EXCLUDE_OR_RELEASE && !roots.empty()); }
- bool includes_roots() const { return (control.roots_op == RESET_OR_CANCEL || control.roots_op == INCLUDE_OR_QUERY) && !roots.empty(); }
+ bool excludes_roots() const { return is_exclude() || is_reset(); }
+ bool includes_roots() const { return is_include() || is_reset(); }
bool is_include() const { return control.roots_op == INCLUDE_OR_QUERY && !roots.empty(); }
bool is_query() const { return control.roots_op == INCLUDE_OR_QUERY && roots.empty(); }
- bool is_exclude() const { return control.roots_op == EXCLUDE_OR_RELEASE && !roots.empty(); }
- bool is_release() const { return control.roots_op == EXCLUDE_OR_RELEASE && roots.empty(); }
- bool is_reset() const { return control.roots_op == RESET_OR_CANCEL && !roots.empty(); }
- bool is_cancel() const { return control.roots_op == RESET_OR_CANCEL && roots.empty(); }
+ bool is_exclude() const { return control.roots_op == EXCLUDE_OR_CANCEL && !roots.empty(); }
+ bool is_release() const { return control.roots_op == RESET_OR_RELEASE && roots.empty(); }
+ bool is_reset() const { return control.roots_op == RESET_OR_RELEASE && !roots.empty(); }
+ bool is_cancel() const { return control.roots_op == EXCLUDE_OR_CANCEL && roots.empty(); }
bool is_verbose() const { return control.flags & Flags::VERBOSE; }
bool is_exclusive() const { return control.flags & Flags::EXCLUSIVE; }
switch (control.roots_op) {
case INCLUDE_OR_QUERY:
return false;
- case EXCLUDE_OR_RELEASE:
- return roots.contains(root);
- case RESET_OR_CANCEL:
- return !roots.contains(root);
- default: ceph_abort("unknown roots_op"); return false;
+ case EXCLUDE_OR_CANCEL:
+ return roots.empty() || roots.contains(root);
+ case RESET_OR_RELEASE:
+ return !roots.empty() && !roots.contains(root);
+ default: ceph_abort("unknown roots_op"); return false;
}
}
template <typename R = Roots>
void exclude_roots(R&& roots)
{
- set_roots(EXCLUDE_OR_RELEASE, std::forward<R>(roots));
+ set_roots(EXCLUDE_OR_CANCEL, std::forward<R>(roots));
}
- void release_roots() {
- set_roots(EXCLUDE_OR_RELEASE, {});
+ void release() {
+ set_roots(RESET_OR_RELEASE, {});
}
template <typename R = Roots>
void reset_roots(R&& roots)
{
- set_roots(RESET_OR_CANCEL, std::forward<R>(roots));
+ set_roots(RESET_OR_RELEASE, std::forward<R>(roots));
}
- void cancel_roots()
+ void cancel()
{
- set_roots(RESET_OR_CANCEL, {});
+ set_roots(EXCLUDE_OR_CANCEL, {});
}
template <typename S = std::string>
switch (control.roots_op) {
case INCLUDE_OR_QUERY:
return roots.empty() ? "query" : "include";
- case EXCLUDE_OR_RELEASE:
- return roots.empty() ? "release" : "exclude";
- case RESET_OR_CANCEL:
- return roots.empty() ? "cancel" : "reset";
+ case EXCLUDE_OR_CANCEL:
+ return roots.empty() ? "cancel" : "exclude";
+ case RESET_OR_RELEASE:
+ return roots.empty() ? "release" : "reset";
default:
return "<unknown>";
}
os << "q-req[" << req.op_string();
if (req.set_id) {
- os << " \"" << req.set_id << "\"";
+ os << " \"" << *req.set_id << "\"";
}
if (req.if_version) {
- os << " ?v:" << req.if_version;
+ os << " ?v:" << *req.if_version;
}
if (req.await) {
}
// non-zero result codes are all errors
- dout(10) << "completing request '" << req->request << " with rc: " << -res << dendl;
+ dout(10) << "completing " << req->request << " with rc: " << -res << dendl;
req->complete(-res);
}
done_requests.clear();
return EINVAL;
}
+ dout(20) << request << dendl;
+
const auto db_age = db.get_age();
if (request.is_cancel_all()) {
return !testing::Test::HasFailure();
};
- const auto ops = std::array { QuiesceDbRequest::RootsOp::INCLUDE_OR_QUERY, QuiesceDbRequest::RootsOp::EXCLUDE_OR_RELEASE, QuiesceDbRequest::RootsOp::RESET_OR_CANCEL, QuiesceDbRequest::RootsOp::__INVALID };
+ const auto ops = std::array { QuiesceDbRequest::RootsOp::INCLUDE_OR_QUERY, QuiesceDbRequest::RootsOp::EXCLUDE_OR_CANCEL, QuiesceDbRequest::RootsOp::RESET_OR_RELEASE, QuiesceDbRequest::RootsOp::__INVALID };
const auto strings = nullopt_and_default<std::string>();
const auto versions = nullopt_and_default<QuiesceSetVersion>();
const auto intervals = nullopt_and_default<QuiesceTimeInterval>();
// cancel with no set_id should cancel all active sets
ASSERT_EQ(OK(), run_request([](auto& r) {
- r.control.roots_op = QuiesceDbRequest::RootsOp::RESET_OR_CANCEL;
+ r.cancel();
}));
ASSERT_TRUE(db(mds_gid_t(1)).sets.at("set1").members.at("file:/root4").excluded);
ASSERT_EQ(OK(), run_request([](auto& r) {
r.set_id = "set2";
- r.release_roots();
+ r.release();
}));
ASSERT_EQ(QuiesceState::QS_RELEASING, last_request->response.sets.at("set2").rstate.state);
ASSERT_EQ(OK(), run_request([](auto& r) {
r.set_id = "set1";
r.expiration = sec(100);
- r.timeout = sec(10);
+ r.timeout = sec(100);
r.roots.emplace("root1");
}));
ASSERT_EQ(OK(), run_request([](auto& r) {
r.set_id = "set1";
- r.reset_roots({});
+ r.cancel();
}));
EXPECT_EQ(ERR(ECANCELED), await3.wait_result());
for (int i = 0; i < 2; i++) {
ASSERT_EQ(ERR(EINPROGRESS), run_request([=](auto& r) {
r.set_id = "set1";
- r.release_roots();
+ r.release();
r.await = (expiration*2)/5;
}));
}
// NB: the ETIMEDOUT is the await result, while the set itself should be EXPIRED
EXPECT_EQ(ERR(ETIMEDOUT), run_request([=](auto& r) {
r.set_id = "set1";
- r.release_roots();
+ r.release();
r.await = expiration;
}));
EXPECT_EQ(ERR(EPERM), run_request([](auto& r) {
r.set_id = "set1";
- r.release_roots();
+ r.release();
}));
}
for (auto&& set_id : { "set1", "set2" }) {
ASSERT_EQ(ERR(EPERM), run_request([set_id](auto& r) {
r.set_id = set_id;
- r.release_roots();
+ r.release();
r.await = sec(1);
})) << "bad release-await " << set_id;
}
auto & release_await1 = start_request([](auto &r) {
r.set_id = "set1";
- r.release_roots();
+ r.release();
r.await = sec(100);
});
auto& release_await2 = start_request([](auto& r) {
r.set_id = "set2";
- r.release_roots();
+ r.release();
r.await = sec(100);
});
// we can request release again without any version bump
EXPECT_EQ(OK(), run_request([](auto& r) {
r.set_id = "set1";
- r.release_roots();
+ r.release();
}));
EXPECT_EQ(releasing_v1, last_request->response.sets.at("set1").version );
// we can release-await with a short await timeout
EXPECT_EQ(ERR(EINPROGRESS), run_request([](auto& r) {
r.set_id = "set1";
- r.release_roots();
+ r.release();
r.await = sec(0.1);
}));
// await again
auto& release_await22 = start_request([](auto& r) {
r.set_id = "set2";
- r.release_roots();
+ r.release();
r.await = sec(100);
});
// it should be OK to request release or release-await on a RELEASED set
EXPECT_EQ(OK(), run_request([](auto& r) {
r.set_id = "set1";
- r.release_roots();
+ r.release();
}));
EXPECT_EQ(OK(), run_request([](auto& r) {
r.set_id = "set1";
- r.release_roots();
+ r.release();
r.await = sec(0.1);
}));
// it's invalid to send a release without a set id
EXPECT_EQ(ERR(EINVAL), run_request([](auto& r) {
- r.release_roots();
+ r.release();
}));
}
// release roots
ASSERT_EQ(OK(), run_request([](auto& r) {
r.set_id = "set1";
- r.release_roots();
+ r.release();
}));
EXPECT_EQ(QS_RELEASING, last_request->response.sets.at("set1").rstate.state);
auto &async_release = start_request([](auto& r) {
r.set_id = "set2";
r.await = sec(100);
- r.release_roots();
+ r.release();
});
EXPECT_EQ(NA(), async_release.check_result());
// shouldn't hurt to run release twice for set 1
ASSERT_EQ(OK(), run_request([](auto& r) {
r.set_id = "set1";
- r.release_roots();
+ r.release();
}));
EXPECT_EQ(releasing_v, last_request->response.sets.at("set1").version);
ASSERT_EQ(OK(), run_request([set_id](auto& r) {
r.set_id = set_id;
r.await = sec(100);
- r.release_roots();
+ r.release();
}));
ASSERT_EQ(ERR(EPERM), run_request([set_id](auto& r) {
r.set_id = set_id;