break;
case 'F': // full
{
- set<snapid_t> old_snaps;
- if (cached_version > 0)
- get_snaps(old_snaps);
-
decode(cached_snaps, p);
decode(cached_pending_update, p);
decode(cached_pending_destroy, p);
- cached_version = m->get_tid();
- // increase destroy_seq if any snapshot gets destroyed.
- if (!old_snaps.empty() && old_snaps != filter(old_snaps))
- destroy_seq++;
+ snapid_t last_created, last_destroyed;
+ decode(last_created, p);
+ decode(last_destroyed, p);
+
+ if (last_created > cached_last_created)
+ cached_last_created = last_created;
+ if (last_destroyed > cached_last_destroyed)
+ cached_last_destroyed = last_destroyed;
+
+ cached_version = m->get_tid();
}
break;
default:
if (!committing_tids.empty()) {
for (auto p = committing_tids.begin();
- p != committing_tids.end() && *p < cached_version; ) {
- if (!cached_pending_update.count(*p) && !cached_pending_destroy.count(*p)) {
+ p != committing_tids.end() && *p <= cached_version; ) {
+ if (cached_pending_update.count(*p)) {
+ if (cached_pending_update[*p].snapid > cached_last_created)
+ cached_last_created = cached_pending_update[*p].snapid;
+ ++p;
+ } else if (cached_pending_destroy.count(*p)) {
+ if (cached_pending_destroy[*p].second > cached_last_destroyed)
+ cached_last_destroyed = cached_pending_destroy[*p].second;
+ ++p;
+ } else {
// pending update/destroy have been committed.
committing_tids.erase(p++);
- } else {
- ++p;
}
}
}
committing_tids.insert(tid);
} else if (cached_pending_update.count(tid)) {
committing_tids.insert(tid);
+ if (cached_pending_update[tid].snapid > cached_last_created)
+ cached_last_created = cached_pending_update[tid].snapid;
} else if (cached_pending_destroy.count(tid)) {
committing_tids.insert(tid);
- destroy_seq++;
+ if (cached_pending_destroy[tid].second > cached_last_destroyed)
+ cached_last_destroyed = cached_pending_destroy[tid].second;
} else if (cached_version > tid) {
// no need to record the tid if it has already been committed.
} else {
class SnapClient : public MDSTableClient {
version_t cached_version;
+ snapid_t cached_last_created, cached_last_destroyed;
map<snapid_t, SnapInfo> cached_snaps;
map<version_t, SnapInfo> cached_pending_update;
map<version_t, pair<snapid_t,snapid_t> > cached_pending_destroy;
map<version_t, std::list<MDSInternalContextBase*> > waiting_for_version;
- uint64_t destroy_seq;
-
uint64_t sync_reqid;
bool synced;
+
public:
explicit SnapClient(MDSRank *m) :
MDSTableClient(m, TABLE_SNAP),
- cached_version(0), destroy_seq(1), sync_reqid(0), synced(false) {}
+ cached_version(0), cached_last_created(0), cached_last_destroyed(0),
+ sync_reqid(0), synced(false) {}
void resend_queries() override;
void handle_query_result(MMDSTableRequest *m) override;
}
version_t get_cached_version() const { return cached_version; }
- uint64_t get_destroy_seq() const { return destroy_seq; }
void refresh(version_t want, MDSInternalContextBase *onfinish);
void sync(MDSInternalContextBase *onfinish);
waiting_for_version[MAX(cached_version, 1)].push_back(c);
}
+ snapid_t get_last_created() const { return cached_last_created; }
+ snapid_t get_last_destroyed() const { return cached_last_destroyed; }
+
void get_snaps(set<snapid_t>& snaps) const;
set<snapid_t> filter(const set<snapid_t>& snaps) const;
const SnapInfo* get_snap_info(snapid_t snapid) const;
max_seq = srnode.seq;
if (srnode.last_created > max_last_created)
max_last_created = srnode.last_created;
- if (srnode.last_destroyed > max_last_destroyed)
- max_last_destroyed = srnode.last_destroyed;
// include my snaps within interval [first,last]
for (auto p = srnode.snaps.lower_bound(first); // first element >= first
void SnapRealm::check_cache() const
{
assert(have_past_parents_open());
- uint64_t destroy_seq = mdcache->mds->snapclient->get_destroy_seq();
+ snapid_t last_destroyed = mdcache->mds->snapclient->get_last_destroyed();
if (cached_seq >= srnode.seq &&
- cached_destroy_seq == destroy_seq)
+ cached_last_destroyed == last_destroyed)
return;
cached_snaps.clear();
cached_snap_context.clear();
cached_last_created = srnode.last_created;
- cached_last_destroyed = srnode.last_destroyed;
cached_seq = srnode.seq;
- cached_destroy_seq = destroy_seq;
+ cached_last_destroyed = last_destroyed;
build_snap_set(cached_snaps, cached_seq, cached_last_created, cached_last_destroyed,
0, CEPH_NOSNAP);
dout(10) << "check_cache rebuilt " << cached_snaps
<< " seq " << srnode.seq
<< " cached_seq " << cached_seq
- << " cached_destroy_seq " << cached_destroy_seq
<< " cached_last_created " << cached_last_created
<< " cached_last_destroyed " << cached_last_destroyed
<< ")" << dendl;
protected:
// cache
mutable snapid_t cached_seq; // max seq over self and all past+present parents.
- mutable uint64_t cached_destroy_seq;
mutable snapid_t cached_last_created; // max last_created over all past+present parents
mutable snapid_t cached_last_destroyed;
mutable set<snapid_t> cached_snaps;
map<client_t, xlist<Capability*>* > client_caps; // to identify clients who need snap notifications
SnapRealm(MDCache *c, CInode *in) :
- cached_destroy_seq(0),
srnode(),
mdcache(c), inode(in),
open(false), parent(0),
if (first_free > last_snap)
last_snap = first_free;
}
+ last_created = last_snap;
+ last_destroyed = last_snap;
version++;
}
info.stamp = snaps[info.snapid].stamp;
} else {
opname = "create";
+ if (info.snapid > last_created)
+ last_created = info.snapid;
}
dout(7) << "commit " << tid << " " << opname << " " << info << dendl;
snaps[info.snapid] = info;
snapid_t seq = pending_destroy[tid].second;
dout(7) << "commit " << tid << " destroy " << sn << " seq " << seq << dendl;
snaps.erase(sn);
+ if (seq > last_destroyed)
+ last_destroyed = seq;
for (const auto p : mds->mdsmap->get_data_pools()) {
need_to_purge[p].insert(sn);
encode(snaps, bl);
encode(pending_update, bl);
encode(pending_destroy, bl);
+ encode(last_created, bl);
+ encode(last_destroyed, bl);
assert(version == tid);
for (auto p : active_clients) {
encode(snaps, reply->bl);
encode(pending_update, reply->bl);
encode(pending_destroy, reply->bl);
+ encode(last_created, reply->bl);
+ encode(last_destroyed, reply->bl);
}
// FIXME: implement incremental change
break;
protected:
MonClient *mon_client = nullptr;
snapid_t last_snap;
+ snapid_t last_created, last_destroyed;
map<snapid_t, SnapInfo> snaps;
map<int, set<snapid_t> > need_to_purge;
version_t last_checked_osdmap;
void encode_server_state(bufferlist& bl) const override {
- ENCODE_START(3, 3, bl);
+ ENCODE_START(4, 3, bl);
encode(last_snap, bl);
encode(snaps, bl);
encode(need_to_purge, bl);
encode(pending_update, bl);
encode(pending_destroy, bl);
encode(pending_noop, bl);
+ encode(last_created, bl);
+ encode(last_destroyed, bl);
ENCODE_FINISH(bl);
}
void decode_server_state(bufferlist::iterator& bl) override {
- DECODE_START_LEGACY_COMPAT_LEN(3, 3, 3, bl);
+ DECODE_START_LEGACY_COMPAT_LEN(4, 3, 3, bl);
decode(last_snap, bl);
decode(snaps, bl);
decode(need_to_purge, bl);
pending_destroy[p->first].first = p->second;
}
decode(pending_noop, bl);
+ if (struct_v >= 4) {
+ decode(last_created, bl);
+ decode(last_destroyed, bl);
+ } else {
+ last_created = last_snap;
+ last_destroyed = last_snap;
+ }
DECODE_FINISH(bl);
}