}
}
+ /**
+ * load_then_with_lock
+ *
+ * Takes two functions as arguments -- load_func to be invoked
+ * with an exclusive lock, and func to be invoked under the
+ * lock type specified by the Type template argument.
+ *
+ * Caller must ensure that *this is not already locked, presumably
+ * by invoking load_then_with_lock immediately after construction.
+ *
+ * @param [in] load_func Function to be invoked under excl lock
+ * @param [in] func Function to be invoked after load_func under
+ * lock of type Type.
+ */
+ template<RWState::State Type, typename Func, typename Func2>
+ auto load_then_with_lock(Func &&load_func, Func2 &&func) {
+ class lock_state_t {
+ tri_mutex *lock = nullptr;
+ bool excl = false;
+
+ public:
+ lock_state_t(tri_mutex &lock) : lock(&lock), excl(true) {
+ ceph_assert(lock.try_lock_for_excl());
+ }
+ lock_state_t(lock_state_t &&o) : lock(o.lock), excl(o.excl) {
+ o.lock = nullptr;
+ o.excl = false;
+ }
+ lock_state_t() = delete;
+ lock_state_t &operator=(lock_state_t &&o) = delete;
+ lock_state_t(const lock_state_t &o) = delete;
+ lock_state_t &operator=(const lock_state_t &o) = delete;
+
+ void demote() {
+ ceph_assert(excl);
+ ceph_assert(lock);
+ if constexpr (Type == RWState::RWWRITE) {
+ lock->demote_to_write();
+ } else if constexpr (Type == RWState::RWREAD) {
+ lock->demote_to_read();
+ } else if constexpr (Type == RWState::RWNONE) {
+ lock->unlock_for_excl();
+ }
+ excl = false;
+ }
+
+ ~lock_state_t() {
+ if (!lock)
+ return;
+
+ if constexpr (Type == RWState::RWEXCL) {
+ lock->unlock_for_excl();
+ } else {
+ if (excl) {
+ lock->unlock_for_excl();
+ return;
+ }
+
+ if constexpr (Type == RWState::RWWRITE) {
+ lock->unlock_for_write();
+ } else if constexpr (Type == RWState::RWREAD) {
+ lock->unlock_for_read();
+ }
+ }
+ }
+ };
+
+ return seastar::do_with(
+ lock_state_t{lock},
+ [load_func=std::move(load_func), func=std::move(func)](auto &ls) mutable {
+ return std::invoke(
+ std::move(load_func)
+ ).si_then([func=std::move(func), &ls]() mutable {
+ ls.demote();
+ return std::invoke(std::move(func));
+ });
+ });
+ }
+
bool empty() const {
return !lock.is_acquired();
}
if constexpr (track) {
obc->append_to(obc_set_accessing);
}
- return obc->with_lock<State, IOInterruptCondition>(
- [existed=existed, obc=obc, func=std::move(func), this]() mutable {
- return get_or_load_obc<State>(
- obc, existed
- ).safe_then_interruptible(std::move(func));
- }).finally([FNAME, this, obc=std::move(obc)] {
- DEBUGDPP("released object {}", dpp, obc->get_oid());
- if constexpr (track) {
- obc->remove_from(obc_set_accessing);
- }
- });
+ if (existed) {
+ return obc->with_lock<State, IOInterruptCondition>(
+ [func=std::move(func), obc=ObjectContextRef(obc)] {
+ return std::invoke(std::move(func), obc);
+ }
+ ).finally([FNAME, this, obc=ObjectContextRef(obc)] {
+ DEBUGDPP("released object {}", dpp, obc->get_oid());
+ if constexpr (track) {
+ obc->remove_from(obc_set_accessing);
+ }
+ });
+ } else {
+ return obc->load_then_with_lock<State> (
+ [this, obc=ObjectContextRef(obc)] {
+ return load_obc(obc);
+ },
+ [func=std::move(func), obc=ObjectContextRef(obc)] {
+ return std::invoke(std::move(func), obc);
+ }
+ ).finally([FNAME, this, obc=ObjectContextRef(obc)] {
+ DEBUGDPP("released object {}", dpp, obc->get_oid());
+ if constexpr (track) {
+ obc->remove_from(obc_set_accessing);
+ }
+ });
+ }
}
- ObjectContextLoader::load_obc_iertr::future<ObjectContextRef>
+ ObjectContextLoader::load_obc_iertr::future<>
ObjectContextLoader::load_obc(ObjectContextRef obc)
{
LOG_PREFIX(ObjectContextLoader::load_obc);
return backend.load_metadata(obc->get_oid())
.safe_then_interruptible(
[FNAME, this, obc=std::move(obc)](auto md)
- -> load_obc_ertr::future<ObjectContextRef> {
+ -> load_obc_ertr::future<> {
const hobject_t& oid = md->os.oi.soid;
DEBUGDPP("loaded obs {} for {}", dpp, md->os.oi, oid);
if (oid.is_head()) {
// See set_clone_ssc
obc->set_clone_state(std::move(md->os));
}
- DEBUGDPP("returning obc {} for {}", dpp, obc->obs.oi, obc->obs.oi.soid);
- return load_obc_ertr::make_ready_future<ObjectContextRef>(obc);
+ DEBUGDPP("loaded obc {} for {}", dpp, obc->obs.oi, obc->obs.oi.soid);
+ return seastar::now();
});
}