i != miter->second.end();
++i) {
dout(10) << __func__ << ": checking missing_loc " << *i << dendl;
- boost::optional<const pg_missing_t &> m =
- get_parent()->maybe_get_shard_missing(*i);
+ auto m = get_parent()->maybe_get_shard_missing(*i);
if (m) {
assert(!(*m).is_missing(hoid));
}
pg->lock();
fout << *pg << std::endl;
- std::map<hobject_t, pg_missing_t::item, hobject_t::BitwiseComparator>::const_iterator mend =
+ std::map<hobject_t, pg_missing_item, hobject_t::BitwiseComparator>::const_iterator mend =
pg->pg_log.get_missing().get_items().end();
- std::map<hobject_t, pg_missing_t::item, hobject_t::BitwiseComparator>::const_iterator mi =
+ std::map<hobject_t, pg_missing_item, hobject_t::BitwiseComparator>::const_iterator mi =
pg->pg_log.get_missing().get_items().begin();
for (; mi != mend; ++mi) {
fout << mi->first << " -> " << mi->second << std::endl;
dout(10) << " peer osd." << from << " now " << oinfo << " " << omissing << dendl;
might_have_unfound.insert(from);
- for (map<hobject_t, pg_missing_t::item, hobject_t::ComparatorWithDefault>::const_iterator i =
+ for (map<hobject_t, pg_missing_item, hobject_t::ComparatorWithDefault>::const_iterator i =
omissing.get_items().begin();
i != omissing.get_items().end();
++i) {
{
dout(10) << __func__ << ": adding sources in batch " << sources.size() << dendl;
unsigned loop = 0;
- for (map<hobject_t, pg_missing_t::item, hobject_t::ComparatorWithDefault>::const_iterator i = needs_recovery_map.begin();
+ for (map<hobject_t, pg_missing_item, hobject_t::ComparatorWithDefault>::const_iterator i = needs_recovery_map.begin();
i != needs_recovery_map.end();
++i) {
if (handle && ++loop >= g_conf->osd_loop_before_reset_tphandle) {
bool found_missing = false;
unsigned loop = 0;
// found items?
- for (map<hobject_t,pg_missing_t::item, hobject_t::ComparatorWithDefault>::const_iterator p = needs_recovery_map.begin();
+ for (map<hobject_t,pg_missing_item, hobject_t::ComparatorWithDefault>::const_iterator p = needs_recovery_map.begin();
p != needs_recovery_map.end();
++p) {
const hobject_t &soid(p->first);
void PG::discover_all_missing(map<int, map<spg_t,pg_query_t> > &query_map)
{
- const pg_missing_t &missing = pg_log.get_missing();
+ auto &missing = pg_log.get_missing();
assert(have_unfound());
dout(10) << __func__ << " "
{
assert(is_primary());
- const pg_missing_t &missing = pg_log.get_missing();
+ auto &missing = pg_log.get_missing();
if (missing.num_missing()) {
dout(10) << __func__ << " primary has " << missing.num_missing()
info.last_epoch_started = activation_epoch;
}
- const pg_missing_t &missing = pg_log.get_missing();
+ auto &missing = pg_log.get_missing();
if (is_primary()) {
last_update_ondisk = info.last_update;
ghobject_t pgmeta_oid;
class MissingLoc {
- map<hobject_t, pg_missing_t::item, hobject_t::BitwiseComparator> needs_recovery_map;
+ map<hobject_t, pg_missing_item, hobject_t::BitwiseComparator> needs_recovery_map;
map<hobject_t, set<pg_shard_t>, hobject_t::BitwiseComparator > missing_loc;
set<pg_shard_t> missing_loc_sources;
PG *pg;
bool needs_recovery(
const hobject_t &hoid,
eversion_t *v = 0) const {
- map<hobject_t, pg_missing_t::item, hobject_t::BitwiseComparator>::const_iterator i =
+ map<hobject_t, pg_missing_item, hobject_t::BitwiseComparator>::const_iterator i =
needs_recovery_map.find(hoid);
if (i == needs_recovery_map.end())
return false;
const set<pg_shard_t> &acting) const;
uint64_t num_unfound() const {
uint64_t ret = 0;
- for (map<hobject_t, pg_missing_t::item, hobject_t::BitwiseComparator>::const_iterator i =
+ for (map<hobject_t, pg_missing_item, hobject_t::BitwiseComparator>::const_iterator i =
needs_recovery_map.begin();
i != needs_recovery_map.end();
++i) {
missing_loc[hoid].erase(location);
}
void add_active_missing(const pg_missing_t &missing) {
- for (map<hobject_t, pg_missing_t::item, hobject_t::BitwiseComparator>::const_iterator i =
+ for (map<hobject_t, pg_missing_item, hobject_t::BitwiseComparator>::const_iterator i =
missing.get_items().begin();
i != missing.get_items().end();
++i) {
- map<hobject_t, pg_missing_t::item, hobject_t::BitwiseComparator>::const_iterator j =
+ map<hobject_t, pg_missing_item, hobject_t::BitwiseComparator>::const_iterator j =
needs_recovery_map.find(i->first);
if (j == needs_recovery_map.end()) {
needs_recovery_map.insert(*i);
}
void add_missing(const hobject_t &hoid, eversion_t need, eversion_t have) {
- needs_recovery_map[hoid] = pg_missing_t::item(need, have);
+ needs_recovery_map[hoid] = pg_missing_item(need, have);
}
void revise_need(const hobject_t &hoid, eversion_t need) {
assert(needs_recovery(hoid));
const map<pg_shard_t, pg_missing_t> &pmissing,
const map<pg_shard_t, pg_info_t> &pinfo) {
recovered(hoid);
- boost::optional<pg_missing_t::item> item;
+ boost::optional<pg_missing_item> item;
auto miter = missing.get_items().find(hoid);
if (miter != missing.get_items().end()) {
item = miter->second;
const map<hobject_t, set<pg_shard_t>, hobject_t::BitwiseComparator> &get_missing_locs() const {
return missing_loc;
}
- const map<hobject_t, pg_missing_t::item, hobject_t::BitwiseComparator> &get_needs_recovery() const {
+ const map<hobject_t, pg_missing_item, hobject_t::BitwiseComparator> &get_needs_recovery() const {
return needs_recovery_map;
}
} missing_loc;
virtual const map<hobject_t, set<pg_shard_t>, hobject_t::BitwiseComparator> &get_missing_loc_shards()
const = 0;
- virtual const pg_missing_t &get_local_missing() const = 0;
+ virtual const pg_missing_tracker_t &get_local_missing() const = 0;
virtual const map<pg_shard_t, pg_missing_t> &get_shard_missing()
const = 0;
- virtual boost::optional<const pg_missing_t &> maybe_get_shard_missing(
+ virtual boost::optional<const pg_missing_const_i &> maybe_get_shard_missing(
pg_shard_t peer) const {
if (peer == primary_shard()) {
return get_local_missing();
map<pg_shard_t, pg_missing_t>::const_iterator i =
get_shard_missing().find(peer);
if (i == get_shard_missing().end()) {
- return boost::optional<const pg_missing_t &>();
+ return boost::optional<const pg_missing_const_i &>();
} else {
return i->second;
}
}
}
- virtual const pg_missing_t &get_shard_missing(pg_shard_t peer) const {
- boost::optional<const pg_missing_t &> m = maybe_get_shard_missing(peer);
+ virtual const pg_missing_const_i &get_shard_missing(pg_shard_t peer) const {
+ auto m = maybe_get_shard_missing(peer);
assert(m);
return *m;
}
we will send the peer enough log to arrive at the same state.
*/
- for (map<hobject_t, pg_missing_t::item, hobject_t::BitwiseComparator>::const_iterator i = omissing.get_items().begin();
+ for (map<hobject_t, pg_missing_item, hobject_t::BitwiseComparator>::const_iterator i = omissing.get_items().begin();
i != omissing.get_items().end();
++i) {
dout(20) << " before missing " << i->first << " need " << i->second.need
// The logs must overlap.
assert(log.head >= olog.tail && olog.head >= log.tail);
- for (map<hobject_t, pg_missing_t::item, hobject_t::BitwiseComparator>::const_iterator i = missing.get_items().begin();
+ for (map<hobject_t, pg_missing_item, hobject_t::BitwiseComparator>::const_iterator i = missing.get_items().begin();
i != missing.get_items().end();
++i) {
dout(20) << "pg_missing_t sobject: " << i->first << dendl;
//////////////////// data members ////////////////////
map<eversion_t, hobject_t> divergent_priors;
- pg_missing_t missing;
+
+ pg_missing_tracker_t missing;
IndexedLog log;
eversion_t dirty_to; ///< must clear/writeout all keys <= dirty_to
//////////////////// get or set missing ////////////////////
- const pg_missing_t& get_missing() const { return missing; }
+ const pg_missing_tracker_t& get_missing() const { return missing; }
void resort_missing(bool sort_bitwise) {
missing.resort(sort_bitwise);
}
}
f->dump_int("num_missing", missing.num_missing());
f->dump_int("num_unfound", get_num_unfound());
- const map<hobject_t, pg_missing_t::item, hobject_t::BitwiseComparator> &needs_recovery_map =
+ const map<hobject_t, pg_missing_item, hobject_t::BitwiseComparator> &needs_recovery_map =
missing_loc.get_needs_recovery();
- map<hobject_t, pg_missing_t::item, hobject_t::BitwiseComparator>::const_iterator p =
+ map<hobject_t, pg_missing_item, hobject_t::BitwiseComparator>::const_iterator p =
needs_recovery_map.upper_bound(offset);
{
f->open_array_section("objects");
// ensure sort order is correct
pg_log.resort_missing(get_sort_bitwise());
- map<hobject_t, pg_missing_t::item, hobject_t::ComparatorWithDefault>::const_iterator missing_iter =
+ map<hobject_t, pg_missing_item, hobject_t::ComparatorWithDefault>::const_iterator missing_iter =
pg_log.get_missing().get_items().lower_bound(current);
vector<hobject_t>::iterator ls_iter = sentries.begin();
hobject_t _max = hobject_t::get_max();
// ensure sort order is correct
pg_log.resort_missing(get_sort_bitwise());
- map<hobject_t, pg_missing_t::item, hobject_t::ComparatorWithDefault>::const_iterator missing_iter =
+ map<hobject_t, pg_missing_item, hobject_t::ComparatorWithDefault>::const_iterator missing_iter =
pg_log.get_missing().get_items().lower_bound(current);
vector<hobject_t>::iterator ls_iter = sentries.begin();
hobject_t _max = hobject_t::get_max();
list<pg_log_entry_t> log_entries;
utime_t mtime = ceph_clock_now(cct);
- map<hobject_t, pg_missing_t::item, hobject_t::ComparatorWithDefault>::const_iterator m =
+ map<hobject_t, pg_missing_item, hobject_t::ComparatorWithDefault>::const_iterator m =
missing_loc.get_needs_recovery().begin();
- map<hobject_t, pg_missing_t::item, hobject_t::ComparatorWithDefault>::const_iterator mend =
+ map<hobject_t, pg_missing_item, hobject_t::ComparatorWithDefault>::const_iterator mend =
missing_loc.get_needs_recovery().end();
ObcLockManager manager;
latest = 0;
soid = p->second;
}
- const pg_missing_t::item& item = missing.get_items().find(p->second)->second;
+ const pg_missing_item& item = missing.get_items().find(p->second)->second;
++p;
hobject_t head = soid;
}
dout(10) << __func__ << ": recover_object_replicas(" << soid << ")" << dendl;
- map<hobject_t,pg_missing_t::item, hobject_t::ComparatorWithDefault>::const_iterator r = m.get_items().find(soid);
+ map<hobject_t,pg_missing_item, hobject_t::ComparatorWithDefault>::const_iterator r = m.get_items().find(soid);
started += prep_object_replica_pushes(soid, r->second.need,
h);
}
return peer_info;
}
using PGBackend::Listener::get_shard_info;
- const pg_missing_t &get_local_missing() const {
+ const pg_missing_tracker_t &get_local_missing() const {
return pg_log.get_missing();
}
const PGLog &get_log() const {
return out;
}
-
// -- pg_missing_t --
-void pg_missing_t::resort(bool sort_bitwise)
-{
- if (missing.key_comp().bitwise != sort_bitwise) {
- map<hobject_t, item, hobject_t::ComparatorWithDefault> tmp;
- tmp.swap(missing);
- missing = map<hobject_t, item, hobject_t::ComparatorWithDefault>(
- hobject_t::ComparatorWithDefault(sort_bitwise));
- missing.insert(tmp.begin(), tmp.end());
- }
-}
-
-void pg_missing_t::encode(bufferlist &bl) const
-{
- ENCODE_START(3, 2, bl);
- ::encode(missing, bl);
- ENCODE_FINISH(bl);
-}
-
-void pg_missing_t::decode(bufferlist::iterator &bl, int64_t pool)
-{
- DECODE_START_LEGACY_COMPAT_LEN(3, 2, 2, bl);
- ::decode(missing, bl);
- DECODE_FINISH(bl);
-
- if (struct_v < 3) {
- // Handle hobject_t upgrade
- map<hobject_t, item, hobject_t::ComparatorWithDefault> tmp;
- for (map<hobject_t, item, hobject_t::ComparatorWithDefault>::iterator i = missing.begin();
- i != missing.end();
- ) {
- if (!i->first.is_max() && i->first.pool == -1) {
- hobject_t to_insert(i->first);
- to_insert.pool = pool;
- tmp[to_insert] = i->second;
- missing.erase(i++);
- } else {
- ++i;
- }
- }
- missing.insert(tmp.begin(), tmp.end());
- }
-
- for (map<hobject_t,item, hobject_t::ComparatorWithDefault>::iterator it = missing.begin();
- it != missing.end();
- ++it)
- rmissing[it->second.need.version] = it->first;
-}
-
-void pg_missing_t::dump(Formatter *f) const
-{
- f->open_array_section("missing");
- for (map<hobject_t,item, hobject_t::ComparatorWithDefault>::const_iterator p = missing.begin(); p != missing.end(); ++p) {
- f->open_object_section("item");
- f->dump_stream("object") << p->first;
- p->second.dump(f);
- f->close_section();
- }
- f->close_section();
-}
-
-void pg_missing_t::generate_test_instances(list<pg_missing_t*>& o)
-{
- o.push_back(new pg_missing_t);
- o.push_back(new pg_missing_t);
- o.back()->add(hobject_t(object_t("foo"), "foo", 123, 456, 0, ""), eversion_t(5, 6), eversion_t(5, 1));
-}
-
-ostream& operator<<(ostream& out, const pg_missing_t::item& i)
+ostream& operator<<(ostream& out, const pg_missing_item& i)
{
out << i.need;
if (i.have != eversion_t())
return out;
}
-ostream& operator<<(ostream& out, const pg_missing_t& missing)
-{
- out << "missing(" << missing.num_missing();
- //if (missing.num_lost()) out << ", " << missing.num_lost() << " lost";
- out << ")";
- return out;
-}
-
-
-unsigned int pg_missing_t::num_missing() const
-{
- return missing.size();
-}
-
-bool pg_missing_t::have_missing() const
-{
- return !missing.empty();
-}
-
-void pg_missing_t::swap(pg_missing_t& o)
-{
- missing.swap(o.missing);
- rmissing.swap(o.rmissing);
-}
-
-bool pg_missing_t::is_missing(const hobject_t& oid) const
-{
- return (missing.find(oid) != missing.end());
-}
-
-bool pg_missing_t::is_missing(const hobject_t& oid, eversion_t v) const
-{
- map<hobject_t, item, hobject_t::ComparatorWithDefault>::const_iterator m = missing.find(oid);
- if (m == missing.end())
- return false;
- const pg_missing_t::item &item(m->second);
- if (item.need > v)
- return false;
- return true;
-}
-
-eversion_t pg_missing_t::have_old(const hobject_t& oid) const
-{
- map<hobject_t, item, hobject_t::ComparatorWithDefault>::const_iterator m = missing.find(oid);
- if (m == missing.end())
- return eversion_t();
- const pg_missing_t::item &item(m->second);
- return item.have;
-}
-
-/*
- * this needs to be called in log order as we extend the log. it
- * assumes missing is accurate up through the previous log entry.
- */
-void pg_missing_t::add_next_event(const pg_log_entry_t& e)
-{
- if (e.is_update()) {
- map<hobject_t, item, hobject_t::ComparatorWithDefault>::iterator missing_it;
- missing_it = missing.find(e.soid);
- bool is_missing_divergent_item = missing_it != missing.end();
- if (e.prior_version == eversion_t() || e.is_clone()) {
- // new object.
- if (is_missing_divergent_item) { // use iterator
- rmissing.erase((missing_it->second).need.version);
- missing_it->second = item(e.version, eversion_t()); // .have = nil
- } else // create new element in missing map
- missing[e.soid] = item(e.version, eversion_t()); // .have = nil
- } else if (is_missing_divergent_item) {
- // already missing (prior).
- rmissing.erase((missing_it->second).need.version);
- (missing_it->second).need = e.version; // leave .have unchanged.
- } else if (e.is_backlog()) {
- // May not have prior version
- assert(0 == "these don't exist anymore");
- } else {
- // not missing, we must have prior_version (if any)
- assert(!is_missing_divergent_item);
- missing[e.soid] = item(e.version, e.prior_version);
- }
- rmissing[e.version.version] = e.soid;
- } else if (e.is_delete()) {
- rm(e.soid, e.version);
- }
-}
-
-void pg_missing_t::revise_need(hobject_t oid, eversion_t need)
-{
- if (missing.count(oid)) {
- rmissing.erase(missing[oid].need.version);
- missing[oid].need = need; // no not adjust .have
- } else {
- missing[oid] = item(need, eversion_t());
- }
- rmissing[need.version] = oid;
-}
-
-void pg_missing_t::revise_have(hobject_t oid, eversion_t have)
-{
- if (missing.count(oid)) {
- missing[oid].have = have;
- }
-}
-
-void pg_missing_t::add(const hobject_t& oid, eversion_t need, eversion_t have)
-{
- missing[oid] = item(need, have);
- rmissing[need.version] = oid;
-}
-
-void pg_missing_t::rm(const hobject_t& oid, eversion_t v)
-{
- std::map<hobject_t, pg_missing_t::item, hobject_t::ComparatorWithDefault>::iterator p = missing.find(oid);
- if (p != missing.end() && p->second.need <= v)
- rm(p);
-}
-
-void pg_missing_t::rm(std::map<hobject_t, pg_missing_t::item, hobject_t::ComparatorWithDefault>::const_iterator m)
-{
- rmissing.erase(m->second.need.version);
- missing.erase(m);
-}
-
-void pg_missing_t::got(const hobject_t& oid, eversion_t v)
-{
- std::map<hobject_t, pg_missing_t::item, hobject_t::ComparatorWithDefault>::iterator p = missing.find(oid);
- assert(p != missing.end());
- assert(p->second.need <= v);
- got(p);
-}
-
-void pg_missing_t::got(std::map<hobject_t, pg_missing_t::item, hobject_t::ComparatorWithDefault>::iterator m)
-{
- rmissing.erase(m->second.need.version);
- missing.erase(m);
-}
-
-void pg_missing_t::split_into(
- pg_t child_pgid,
- unsigned split_bits,
- pg_missing_t *omissing)
-{
- unsigned mask = ~((~0)<<split_bits);
- for (map<hobject_t, item, hobject_t::ComparatorWithDefault>::iterator i = missing.begin();
- i != missing.end();
- ) {
- if ((i->first.get_hash() & mask) == child_pgid.m_seed) {
- omissing->add(i->first, i->second.need, i->second.have);
- rm(i++);
- } else {
- ++i;
- }
- }
-}
-
// -- object_copy_cursor_t --
void object_copy_cursor_t::encode(bufferlist& bl) const
* kept in memory, as a supplement to pg_log_t
* also used to pass missing info in messages.
*/
-class pg_missing_t {
+struct pg_missing_item {
+ eversion_t need, have;
+ pg_missing_item() {}
+ explicit pg_missing_item(eversion_t n) : need(n) {} // have no old version
+ pg_missing_item(eversion_t n, eversion_t h) : need(n), have(h) {}
+
+ void encode(bufferlist& bl) const {
+ ::encode(need, bl);
+ ::encode(have, bl);
+ }
+ void decode(bufferlist::iterator& bl) {
+ ::decode(need, bl);
+ ::decode(have, bl);
+ }
+ void dump(Formatter *f) const {
+ f->dump_stream("need") << need;
+ f->dump_stream("have") << have;
+ }
+ static void generate_test_instances(list<pg_missing_item*>& o) {
+ o.push_back(new pg_missing_item);
+ o.push_back(new pg_missing_item);
+ o.back()->need = eversion_t(1, 2);
+ o.back()->have = eversion_t(1, 1);
+ }
+ bool operator==(const pg_missing_item &rhs) const {
+ return need == rhs.need && have == rhs.have;
+ }
+ bool operator!=(const pg_missing_item &rhs) const {
+ return !(*this == rhs);
+ }
+};
+WRITE_CLASS_ENCODER(pg_missing_item)
+ostream& operator<<(ostream& out, const pg_missing_item &item);
+
+class pg_missing_const_i {
public:
- struct item {
- eversion_t need, have;
- item() {}
- explicit item(eversion_t n) : need(n) {} // have no old version
- item(eversion_t n, eversion_t h) : need(n), have(h) {}
-
- void encode(bufferlist& bl) const {
- ::encode(need, bl);
- ::encode(have, bl);
- }
- void decode(bufferlist::iterator& bl) {
- ::decode(need, bl);
- ::decode(have, bl);
- }
- void dump(Formatter *f) const {
- f->dump_stream("need") << need;
- f->dump_stream("have") << have;
- }
- static void generate_test_instances(list<item*>& o) {
- o.push_back(new item);
- o.push_back(new item);
- o.back()->need = eversion_t(1, 2);
- o.back()->have = eversion_t(1, 1);
+ virtual const map<hobject_t, pg_missing_item, hobject_t::ComparatorWithDefault> &
+ get_items() const = 0;
+ virtual const map<version_t, hobject_t> &get_rmissing() const = 0;
+ virtual unsigned int num_missing() const = 0;
+ virtual bool have_missing() const = 0;
+ virtual bool is_missing(const hobject_t& oid) const = 0;
+ virtual bool is_missing(const hobject_t& oid, eversion_t v) const = 0;
+ virtual eversion_t have_old(const hobject_t& oid) const = 0;
+ virtual ~pg_missing_const_i() {}
+};
+
+
+template <bool Track>
+class ChangeTracker {
+public:
+ void changed(const hobject_t &obj) {}
+ template <typename F>
+ void get_changed(F &&f) const {}
+ void flush() {}
+ void clean() {
+ return true;
+ }
+};
+template <>
+class ChangeTracker<true> {
+ set<hobject_t, hobject_t::BitwiseComparator> _changed;
+public:
+ void changed(const hobject_t &obj) {
+ _changed.insert(obj);
+ }
+ template <typename F>
+ void get_changed(F &&f) {
+ for (auto const &i: _changed) {
+ f(i);
}
- };
- WRITE_CLASS_ENCODER(item)
+ }
+ void flush() {
+ _changed.clear();
+ }
+ bool clean() const {
+ return _changed.empty();
+ }
+};
-private:
+template <bool TrackChanges>
+class pg_missing_set : public pg_missing_const_i {
+ using item = pg_missing_item;
map<hobject_t, item, hobject_t::ComparatorWithDefault> missing; // oid -> (need v, have v)
map<version_t, hobject_t> rmissing; // v -> oid
+ ChangeTracker<TrackChanges> tracker;
public:
- const map<hobject_t, item, hobject_t::ComparatorWithDefault> &get_items() const {
+ pg_missing_set() = default;
+
+ template <typename missing_type>
+ pg_missing_set(const missing_type &m) :
+ missing(m.get_items()), rmissing(m.get_rmissing()) {
+ static_assert(
+ !TrackChanges,
+ "Cannot copy construct into tracker pg_missing object");
+ }
+
+ const map<hobject_t, item, hobject_t::ComparatorWithDefault> &get_items() const override {
return missing;
}
- const map<version_t, hobject_t> &get_rmissing() const {
+ const map<version_t, hobject_t> &get_rmissing() const override {
return rmissing;
}
- unsigned int num_missing() const;
- bool have_missing() const;
- bool is_missing(const hobject_t& oid) const;
- bool is_missing(const hobject_t& oid, eversion_t v) const;
- eversion_t have_old(const hobject_t& oid) const;
-
- void swap(pg_missing_t& o);
- void add_next_event(const pg_log_entry_t& e);
- void revise_need(hobject_t oid, eversion_t need);
- void revise_have(hobject_t oid, eversion_t have);
- void add(const hobject_t& oid, eversion_t need, eversion_t have);
- void rm(const hobject_t& oid, eversion_t v);
- void rm(std::map<hobject_t, pg_missing_t::item, hobject_t::ComparatorWithDefault>::const_iterator m);
- void got(const hobject_t& oid, eversion_t v);
- void got(std::map<hobject_t, pg_missing_t::item, hobject_t::ComparatorWithDefault>::const_iterator m);
- void split_into(pg_t child_pgid, unsigned split_bits, pg_missing_t *omissing);
+ unsigned int num_missing() const override {
+ return missing.size();
+ }
+ bool have_missing() const override {
+ return !missing.empty();
+ }
+ bool is_missing(const hobject_t& oid) const override {
+ return (missing.find(oid) != missing.end());
+ }
+ bool is_missing(const hobject_t& oid, eversion_t v) const override {
+ map<hobject_t, item, hobject_t::ComparatorWithDefault>::const_iterator m =
+ missing.find(oid);
+ if (m == missing.end())
+ return false;
+ const item &item(m->second);
+ if (item.need > v)
+ return false;
+ return true;
+ }
+ eversion_t have_old(const hobject_t& oid) const override {
+ map<hobject_t, item, hobject_t::ComparatorWithDefault>::const_iterator m =
+ missing.find(oid);
+ if (m == missing.end())
+ return eversion_t();
+ const item &item(m->second);
+ return item.have;
+ }
+
+ void swap(pg_missing_set& o) {
+ for (auto &&i: missing)
+ tracker.changed(i.first);
+ missing.swap(o.missing);
+ rmissing.swap(o.rmissing);
+ for (auto &&i: missing)
+ tracker.changed(i.first);
+ }
+
+ /*
+ * this needs to be called in log order as we extend the log. it
+ * assumes missing is accurate up through the previous log entry.
+ */
+ void add_next_event(const pg_log_entry_t& e) {
+ if (e.is_update()) {
+ map<hobject_t, item, hobject_t::ComparatorWithDefault>::iterator missing_it;
+ missing_it = missing.find(e.soid);
+ bool is_missing_divergent_item = missing_it != missing.end();
+ if (e.prior_version == eversion_t() || e.is_clone()) {
+ // new object.
+ if (is_missing_divergent_item) { // use iterator
+ rmissing.erase((missing_it->second).need.version);
+ missing_it->second = item(e.version, eversion_t()); // .have = nil
+ } else // create new element in missing map
+ missing[e.soid] = item(e.version, eversion_t()); // .have = nil
+ } else if (is_missing_divergent_item) {
+ // already missing (prior).
+ rmissing.erase((missing_it->second).need.version);
+ (missing_it->second).need = e.version; // leave .have unchanged.
+ } else if (e.is_backlog()) {
+ // May not have prior version
+ assert(0 == "these don't exist anymore");
+ } else {
+ // not missing, we must have prior_version (if any)
+ assert(!is_missing_divergent_item);
+ missing[e.soid] = item(e.version, e.prior_version);
+ }
+ rmissing[e.version.version] = e.soid;
+ } else if (e.is_delete()) {
+ rm(e.soid, e.version);
+ }
+
+ tracker.changed(e.soid);
+ }
+
+ void revise_need(hobject_t oid, eversion_t need) {
+ if (missing.count(oid)) {
+ rmissing.erase(missing[oid].need.version);
+ missing[oid].need = need; // no not adjust .have
+ } else {
+ missing[oid] = item(need, eversion_t());
+ }
+ rmissing[need.version] = oid;
+
+ tracker.changed(oid);
+ }
+
+ void revise_have(hobject_t oid, eversion_t have) {
+ if (missing.count(oid)) {
+ tracker.changed(oid);
+ missing[oid].have = have;
+ }
+ }
+
+ void add(const hobject_t& oid, eversion_t need, eversion_t have) {
+ missing[oid] = item(need, have);
+ rmissing[need.version] = oid;
+ tracker.changed(oid);
+ }
+
+ void rm(const hobject_t& oid, eversion_t v) {
+ std::map<hobject_t, item, hobject_t::ComparatorWithDefault>::iterator p = missing.find(oid);
+ if (p != missing.end() && p->second.need <= v)
+ rm(p);
+ }
+
+ void rm(std::map<hobject_t, item, hobject_t::ComparatorWithDefault>::const_iterator m) {
+ tracker.changed(m->first);
+ rmissing.erase(m->second.need.version);
+ missing.erase(m);
+ }
+
+ void got(const hobject_t& oid, eversion_t v) {
+ std::map<hobject_t, item, hobject_t::ComparatorWithDefault>::iterator p = missing.find(oid);
+ assert(p != missing.end());
+ assert(p->second.need <= v);
+ got(p);
+ }
+
+ void got(std::map<hobject_t, item, hobject_t::ComparatorWithDefault>::const_iterator m) {
+ tracker.changed(m->first);
+ rmissing.erase(m->second.need.version);
+ missing.erase(m);
+ }
+
+ void split_into(
+ pg_t child_pgid,
+ unsigned split_bits,
+ pg_missing_set *omissing) {
+ unsigned mask = ~((~0)<<split_bits);
+ for (map<hobject_t, item, hobject_t::ComparatorWithDefault>::iterator i = missing.begin();
+ i != missing.end();
+ ) {
+ if ((i->first.get_hash() & mask) == child_pgid.m_seed) {
+ omissing->add(i->first, i->second.need, i->second.have);
+ rm(i++);
+ } else {
+ ++i;
+ }
+ }
+ }
void clear() {
+ for (auto const &i: missing)
+ tracker.changed(i.first);
missing.clear();
rmissing.clear();
}
- void resort(bool sort_bitwise);
+ void resort(bool sort_bitwise) {
+ if (missing.key_comp().bitwise != sort_bitwise) {
+ map<hobject_t, item, hobject_t::ComparatorWithDefault> tmp;
+ tmp.swap(missing);
+ missing = map<hobject_t, item, hobject_t::ComparatorWithDefault>(
+ hobject_t::ComparatorWithDefault(sort_bitwise));
+ missing.insert(tmp.begin(), tmp.end());
+ }
+ }
- void encode(bufferlist &bl) const;
- void decode(bufferlist::iterator &bl, int64_t pool = -1);
- void dump(Formatter *f) const;
- static void generate_test_instances(list<pg_missing_t*>& o);
+ void encode(bufferlist &bl) const {
+ ENCODE_START(3, 2, bl);
+ ::encode(missing, bl);
+ ENCODE_FINISH(bl);
+ }
+ void decode(bufferlist::iterator &bl, int64_t pool = -1) {
+ for (auto const &i: missing)
+ tracker.changed(i.first);
+ DECODE_START_LEGACY_COMPAT_LEN(3, 2, 2, bl);
+ ::decode(missing, bl);
+ DECODE_FINISH(bl);
+
+ if (struct_v < 3) {
+ // Handle hobject_t upgrade
+ map<hobject_t, item, hobject_t::ComparatorWithDefault> tmp;
+ for (map<hobject_t, item, hobject_t::ComparatorWithDefault>::iterator i =
+ missing.begin();
+ i != missing.end();
+ ) {
+ if (!i->first.is_max() && i->first.pool == -1) {
+ hobject_t to_insert(i->first);
+ to_insert.pool = pool;
+ tmp[to_insert] = i->second;
+ missing.erase(i++);
+ } else {
+ ++i;
+ }
+ }
+ missing.insert(tmp.begin(), tmp.end());
+ }
+
+ for (map<hobject_t,item, hobject_t::ComparatorWithDefault>::iterator it =
+ missing.begin();
+ it != missing.end();
+ ++it)
+ rmissing[it->second.need.version] = it->first;
+ for (auto const &i: missing)
+ tracker.changed(i.first);
+ }
+ void dump(Formatter *f) const {
+ f->open_array_section("missing");
+ for (map<hobject_t,item, hobject_t::ComparatorWithDefault>::const_iterator p =
+ missing.begin(); p != missing.end(); ++p) {
+ f->open_object_section("item");
+ f->dump_stream("object") << p->first;
+ p->second.dump(f);
+ f->close_section();
+ }
+ f->close_section();
+ }
+ static void generate_test_instances(list<pg_missing_set*>& o) {
+ o.push_back(new pg_missing_set);
+ o.push_back(new pg_missing_set);
+ o.back()->add(
+ hobject_t(object_t("foo"), "foo", 123, 456, 0, ""),
+ eversion_t(5, 6), eversion_t(5, 1));
+ }
+ template <typename F>
+ std::enable_if<TrackChanges, void> get_changed (F &&f) const {
+ tracker.get_changed(f);
+ }
+ template <typename F>
+ std::enable_if<TrackChanges, void> flush() {
+ tracker.flush();
+ }
+ template <typename F>
+ std::enable_if<TrackChanges, bool> clean() const {
+ return tracker.clean();
+ }
};
-WRITE_CLASS_ENCODER(pg_missing_t::item)
-WRITE_CLASS_ENCODER(pg_missing_t)
+template <bool TrackChanges>
+void encode(
+ const pg_missing_set<TrackChanges> &c, bufferlist &bl, uint64_t features=0) {
+ ENCODE_DUMP_PRE();
+ c.encode(bl);
+ ENCODE_DUMP_POST(cl);
+}
+template <bool TrackChanges>
+void decode(pg_missing_set<TrackChanges> &c, bufferlist::iterator &p) {
+ c.decode(p);
+}
+template <bool TrackChanges>
+ostream& operator<<(ostream& out, const pg_missing_set<TrackChanges> &missing)
+{
+ out << "missing(" << missing.num_missing();
+ //if (missing.num_lost()) out << ", " << missing.num_lost() << " lost";
+ out << ")";
+ return out;
+}
+
+using pg_missing_t = pg_missing_set<false>;
+using pg_missing_tracker_t = pg_missing_set<true>;
-ostream& operator<<(ostream& out, const pg_missing_t::item& i);
-ostream& operator<<(ostream& out, const pg_missing_t& missing);
/**
* pg list objects response format
TYPE_FEATUREFUL(pg_query_t)
TYPE(pg_log_entry_t)
TYPE(pg_log_t)
-TYPE(pg_missing_t::item)
+TYPE(pg_missing_item)
TYPE(pg_missing_t)
TYPE(pg_ls_response_t)
TYPE(pg_nls_response_t)
missing.rm(oid, eversion_t(epoch * 2,20));
EXPECT_FALSE(missing.is_missing(oid));
}
- // void pg_missing_t::rm(const std::map<hobject_t, pg_missing_t::item>::iterator &m)
+ // void pg_missing_t::rm(const std::map<hobject_t, pg_missing_item>::iterator &m)
{
hobject_t oid(object_t("objname"), "key", 123, 456, 0, "");
pg_missing_t missing;
missing.got(oid, eversion_t(epoch * 2,20));
EXPECT_FALSE(missing.is_missing(oid));
}
- // void pg_missing_t::got(const std::map<hobject_t, pg_missing_t::item>::iterator &m)
+ // void pg_missing_t::got(const std::map<hobject_t, pg_missing_item>::iterator &m)
{
hobject_t oid(object_t("objname"), "key", 123, 456, 0, "");
pg_missing_t missing;