Ref head; // Ref defined as part of ceph::common::intrusive_lru_base
ObjectState obs;
std::optional<SnapSet> ss;
- bool loaded : 1;
// the watch / notify machinery rather stays away from the hot and
// frequented paths. std::map is used mostly because of developer's
// convenience.
using watch_key_t = std::pair<uint64_t, entity_name_t>;
std::map<watch_key_t, seastar::shared_ptr<crimson::osd::Watch>> watchers;
- ObjectContext(const hobject_t &hoid) : obs(hoid), loaded(false) {}
+ ObjectContext(hobject_t hoid) : obs(std::move(hoid)) {}
const hobject_t &get_oid() const {
return obs.oi.soid;
return get_oid().is_head();
}
+ Ref get_head_obc() const {
+ return head;
+ }
+
+ hobject_t get_head_oid() const {
+ return get_oid().get_head();
+ }
+
const SnapSet &get_ro_ss() const {
if (is_head()) {
ceph_assert(ss);
ceph_assert(is_head());
obs = std::move(_obs);
ss = std::move(_ss);
- loaded = true;
}
void set_clone_state(ObjectState &&_obs, Ref &&_head) {
ceph_assert(!is_head());
obs = std::move(_obs);
head = _head;
- loaded = true;
}
/// pass the provided exception to any waiting consumers of this ObjectContext
});
}
+ boost::intrusive::list_member_hook<> list_hook;
+ uint64_t list_link_cnt = 0;
+
public:
- template<RWState::State Type, typename Func>
+
+ template <typename ListType>
+ void append_to(ListType& list) {
+ if (list_link_cnt++ == 0) {
+ list.push_back(*this);
+ }
+ }
+
+ template <typename ListType>
+ void remove_from(ListType&& list) {
+ assert(list_link_cnt > 0);
+ if (--list_link_cnt == 0) {
+ list.erase(std::decay_t<ListType>::s_iterator_to(*this));
+ }
+ }
+
+ using obc_accessing_option_t = boost::intrusive::member_hook<
+ ObjectContext,
+ boost::intrusive::list_member_hook<>,
+ &ObjectContext::list_hook>;
+
+ template<RWState::State Type, typename InterruptCond = void, typename Func>
auto with_lock(Func&& func) {
- switch (Type) {
- case RWState::RWWRITE:
- return _with_lock(lock.for_write(), std::forward<Func>(func));
- case RWState::RWREAD:
- return _with_lock(lock.for_read(), std::forward<Func>(func));
- case RWState::RWEXCL:
- return _with_lock(lock.for_excl(), std::forward<Func>(func));
- case RWState::RWNONE:
- return seastar::futurize_invoke(std::forward<Func>(func));
- default:
- assert(0 == "noop");
+ if constexpr (!std::is_void_v<InterruptCond>) {
+ auto wrapper = ::crimson::interruptible::interruptor<InterruptCond>::wrap_function(std::forward<Func>(func));
+ switch (Type) {
+ case RWState::RWWRITE:
+ return _with_lock(lock.for_write(), std::move(wrapper));
+ case RWState::RWREAD:
+ return _with_lock(lock.for_read(), std::move(wrapper));
+ case RWState::RWEXCL:
+ return _with_lock(lock.for_excl(), std::move(wrapper));
+ case RWState::RWNONE:
+ return seastar::futurize_invoke(std::move(wrapper));
+ default:
+ assert(0 == "noop");
+ }
+ } else {
+ switch (Type) {
+ case RWState::RWWRITE:
+ return _with_lock(lock.for_write(), std::forward<Func>(func));
+ case RWState::RWREAD:
+ return _with_lock(lock.for_read(), std::forward<Func>(func));
+ case RWState::RWEXCL:
+ return _with_lock(lock.for_excl(), std::forward<Func>(func));
+ case RWState::RWNONE:
+ return seastar::futurize_invoke(std::forward<Func>(func));
+ default:
+ assert(0 == "noop");
+ }
}
}
- template<RWState::State Type, typename Func>
+ template<RWState::State Type, typename InterruptCond = void, typename Func>
auto with_promoted_lock(Func&& func) {
- switch (Type) {
- case RWState::RWWRITE:
- return _with_lock(lock.excl_from_write(), std::forward<Func>(func));
- case RWState::RWREAD:
- return _with_lock(lock.excl_from_read(), std::forward<Func>(func));
- case RWState::RWEXCL:
- return _with_lock(lock.excl_from_excl(), std::forward<Func>(func));
- case RWState::RWNONE:
- return _with_lock(lock.for_excl(), std::forward<Func>(func));
- default:
- assert(0 == "noop");
+ if constexpr (!std::is_void_v<InterruptCond>) {
+ auto wrapper = ::crimson::interruptible::interruptor<InterruptCond>::wrap_function(std::forward<Func>(func));
+ switch (Type) {
+ case RWState::RWWRITE:
+ return _with_lock(lock.excl_from_write(), std::move(wrapper));
+ case RWState::RWREAD:
+ return _with_lock(lock.excl_from_read(), std::move(wrapper));
+ case RWState::RWEXCL:
+ return _with_lock(lock.excl_from_excl(), std::move(wrapper));
+ case RWState::RWNONE:
+ return _with_lock(lock.for_excl(), std::move(wrapper));
+ default:
+ assert(0 == "noop");
+ }
+ } else {
+ switch (Type) {
+ case RWState::RWWRITE:
+ return _with_lock(lock.excl_from_write(), std::forward<Func>(func));
+ case RWState::RWREAD:
+ return _with_lock(lock.excl_from_read(), std::forward<Func>(func));
+ case RWState::RWEXCL:
+ return _with_lock(lock.excl_from_excl(), std::forward<Func>(func));
+ case RWState::RWNONE:
+ return _with_lock(lock.for_excl(), std::forward<Func>(func));
+ default:
+ assert(0 == "noop");
+ }
}
}
public:
ObjectContextRegistry(crimson::common::ConfigProxy &conf);
+ ~ObjectContextRegistry();
std::pair<ObjectContextRef, bool> get_cached_obc(const hobject_t &hoid) {
return obc_lru.get_or_create(hoid);