diff options
Diffstat (limited to 'src/osd/object_state.h')
-rw-r--r-- | src/osd/object_state.h | 190 |
1 files changed, 190 insertions, 0 deletions
diff --git a/src/osd/object_state.h b/src/osd/object_state.h new file mode 100644 index 000000000..31987d2a4 --- /dev/null +++ b/src/osd/object_state.h @@ -0,0 +1,190 @@ +// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*- +// vim: ts=8 sw=2 smarttab + +#pragma once + +#include "osd_types.h" + +struct ObjectState { + object_info_t oi; + bool exists; ///< the stored object exists (i.e., we will remember the object_info_t) + + ObjectState() : exists(false) {} + + ObjectState(const object_info_t &oi_, bool exists_) + : oi(oi_), exists(exists_) {} + ObjectState(object_info_t &&oi_, bool exists_) + : oi(std::move(oi_)), exists(exists_) {} + ObjectState(const hobject_t &obj) : oi(obj), exists(false) {} +}; + +struct RWState { + enum State { + RWNONE, + RWREAD, + RWWRITE, + RWEXCL, + }; + static const char *get_state_name(State s) { + switch (s) { + case RWNONE: return "none"; + case RWREAD: return "read"; + case RWWRITE: return "write"; + case RWEXCL: return "excl"; + default: return "???"; + } + } + const char *get_state_name() const { + return get_state_name(state); + } + + int count; ///< number of readers or writers + int waiters = 0; ///< number waiting + + State state:4; ///< rw state + /// if set, restart backfill when we can get a read lock + bool recovery_read_marker:1; + /// if set, requeue snaptrim on lock release + bool snaptrimmer_write_marker:1; + + RWState() + : count(0), + state(RWNONE), + recovery_read_marker(false), + snaptrimmer_write_marker(false) + {} + + /// this function adjusts the counts if necessary + bool get_read_lock() { + // don't starve anybody! + if (waiters > 0) { + return false; + } + switch (state) { + case RWNONE: + ceph_assert(count == 0); + state = RWREAD; + // fall through + case RWREAD: + count++; + return true; + case RWWRITE: + return false; + case RWEXCL: + return false; + default: + ceph_abort_msg("unhandled case"); + return false; + } + } + + bool get_write_lock(bool greedy=false) { + if (!greedy) { + // don't starve anybody! + if (waiters > 0 || + recovery_read_marker) { + return false; + } + } + switch (state) { + case RWNONE: + ceph_assert(count == 0); + state = RWWRITE; + // fall through + case RWWRITE: + count++; + return true; + case RWREAD: + return false; + case RWEXCL: + return false; + default: + ceph_abort_msg("unhandled case"); + return false; + } + } + bool get_excl_lock() { + switch (state) { + case RWNONE: + ceph_assert(count == 0); + state = RWEXCL; + count = 1; + return true; + case RWWRITE: + return false; + case RWREAD: + return false; + case RWEXCL: + return false; + default: + ceph_abort_msg("unhandled case"); + return false; + } + } + /// same as get_write_lock, but ignore starvation + bool take_write_lock() { + if (state == RWWRITE) { + count++; + return true; + } + return get_write_lock(); + } + bool dec() { + ceph_assert(count > 0); + count--; + if (count == 0) { + state = RWNONE; + return true; + } else { + return false; + } + } + bool put_read() { + ceph_assert(state == RWREAD); + return dec(); + } + bool put_write() { + ceph_assert(state == RWWRITE); + return dec(); + } + bool put_excl() { + ceph_assert(state == RWEXCL); + return dec(); + } + void inc_waiters() { + ++waiters; + } + void release_waiters() { + waiters = 0; + } + void dec_waiters(int count) { + ceph_assert(waiters >= count); + waiters -= count; + } + bool empty() const { return state == RWNONE; } + + bool get_snaptrimmer_write(bool mark_if_unsuccessful) { + if (get_write_lock()) { + return true; + } else { + if (mark_if_unsuccessful) + snaptrimmer_write_marker = true; + return false; + } + } + bool get_recovery_read() { + recovery_read_marker = true; + if (get_read_lock()) { + return true; + } + return false; + } +}; + +inline std::ostream& operator<<(std::ostream& out, const RWState& rw) +{ + return out << "rwstate(" << rw.get_state_name() + << " n=" << rw.count + << " w=" << rw.waiters + << ")"; +} |