});
}
+ template<RWState::State State>
+ ObjectContextLoader::load_obc_iertr::future<>
+ ObjectContextLoader::with_head_and_clone_obc(
+ hobject_t oid,
+ with_both_obc_func_t&& func)
+ {
+ LOG_PREFIX(ObjectContextLoader::with_head_and_clone_obc);
+ assert(!oid.is_head());
+ return with_obc<RWState::RWREAD>(
+ oid.get_head(),
+ [FNAME, oid, func=std::move(func), this](auto head) mutable
+ -> load_obc_iertr::future<> {
+ if (!head->obs.exists) {
+ ERRORDPP("head doesn't exist for object {}", dpp, head->obs.oi.soid);
+ return load_obc_iertr::future<>{
+ crimson::ct_error::enoent::make()
+ };
+ }
+ auto coid = resolve_oid(head->get_head_ss(), oid);
+ if (!coid) {
+ ERRORDPP("clone {} not found", dpp, oid);
+ return load_obc_iertr::future<>{
+ crimson::ct_error::enoent::make()
+ };
+ }
+ auto [clone, existed] = obc_registry.get_cached_obc(*coid);
+ return clone->template with_lock<State, IOInterruptCondition>(
+ [existed=existed, clone=std::move(clone),
+ func=std::move(func), head=std::move(head), this]()
+ -> load_obc_iertr::future<> {
+ auto loaded = get_or_load_obc<State>(clone, existed);
+ return loaded.safe_then_interruptible(
+ [func = std::move(func), head=std::move(head)](auto clone) {
+ return std::move(func)(std::move(head), std::move(clone));
+ });
+ });
+ });
+ }
+
template<RWState::State State>
ObjectContextLoader::load_obc_iertr::future<>
ObjectContextLoader::with_obc(hobject_t oid,
template ObjectContextLoader::load_obc_iertr::future<>
ObjectContextLoader::with_obc<RWState::RWEXCL>(hobject_t,
with_obc_func_t&&);
+
+ template ObjectContextLoader::load_obc_iertr::future<>
+ ObjectContextLoader::with_head_and_clone_obc<RWState::RWWRITE>(
+ hobject_t,
+ with_both_obc_func_t&&);
}
using with_obc_func_t =
std::function<load_obc_iertr::future<> (ObjectContextRef)>;
+ using with_both_obc_func_t =
+ std::function<load_obc_iertr::future<> (ObjectContextRef, ObjectContextRef)>;
+
template<RWState::State State>
load_obc_iertr::future<> with_obc(hobject_t oid,
with_obc_func_t&& func);
hobject_t oid,
with_obc_func_t&& func);
+ // Use this variant in the case where both the head
+ // object *and* the matching clone object are being used
+ // in func.
+ template<RWState::State State>
+ load_obc_iertr::future<> with_head_and_clone_obc(
+ hobject_t oid,
+ with_both_obc_func_t&& func);
+
template<RWState::State State>
load_obc_iertr::future<> with_head_obc(ObjectContextRef obc,
bool existed,
}).then_interruptible([this] {
logger().debug("{}: getting obc for {}", *this, coid);
// end of commonality
- // with_cone_obc lock both clone's and head's obcs
- return pg->obc_loader.with_clone_obc<RWState::RWWRITE>(coid, [this](auto clone_obc) {
+ // with_head_and_clone_obc lock both clone's and head's obcs
+ return pg->obc_loader.with_head_and_clone_obc<RWState::RWWRITE>(
+ coid,
+ [this](auto head_obc, auto clone_obc) {
logger().debug("{}: got clone_obc={}", *this, fmt::ptr(clone_obc.get()));
return enter_stage<interruptor>(
pp().process
- ).then_interruptible([this, clone_obc=std::move(clone_obc)]() mutable {
+ ).then_interruptible(
+ [this,clone_obc=std::move(clone_obc), head_obc=std::move(head_obc)]() mutable {
logger().debug("{}: processing clone_obc={}", *this, fmt::ptr(clone_obc.get()));
return remove_or_update(
- clone_obc, clone_obc->head
+ clone_obc, head_obc
).safe_then_unpack_interruptible([clone_obc, this]
(auto&& txn, auto&& log_entries) mutable {
auto [submitted, all_completed] = pg->submit_transaction(