cerr << "object_info: " << objb.oi << std::endl;
}
- // XXX: Should we be checking for WHITEOUT or LOST in objb.oi.flags and skip?
+ // NOTE: we include whiteouts, lost, etc.
ret = write_section(TYPE_OBJECT_BEGIN, objb, file_fd);
if (ret < 0)
return 0;
}
-int get_attrs(ObjectStore *store, coll_t coll, ghobject_t hoid,
- ObjectStore::Transaction *t, bufferlist &bl,
- OSDriver &driver, SnapMapper &snap_mapper)
+int get_attrs(
+ ObjectStore *store, coll_t coll, ghobject_t hoid,
+ ObjectStore::Transaction *t, bufferlist &bl,
+ OSDriver &driver, SnapMapper &snap_mapper,
+ const ghobject_t& last_head,
+ const set<ghobject_t>& last_clones)
{
bufferlist::iterator ebliter = bl.begin();
attr_section as;
// This could have been handled in the caller if we didn't need to
// support exports that didn't include object_info_t in object_begin.
- if (hoid.hobj.snap < CEPH_MAXSNAP && hoid.generation == ghobject_t::NO_GEN) {
- map<string,bufferlist>::iterator mi = as.data.find(OI_ATTR);
- if (mi != as.data.end()) {
- object_info_t oi(mi->second);
-
- if (debug)
- cerr << "object_info " << oi << std::endl;
-
- OSDriver::OSTransaction _t(driver.get_transaction(t));
- set<snapid_t> oi_snaps(oi.legacy_snaps.begin(), oi.legacy_snaps.end());
- snap_mapper.add_oid(hoid.hobj, oi_snaps, &_t);
+ if (hoid.generation == ghobject_t::NO_GEN) {
+ if (hoid.hobj.snap < CEPH_MAXSNAP) {
+ map<string,bufferlist>::iterator mi = as.data.find(OI_ATTR);
+ if (mi != as.data.end()) {
+ object_info_t oi(mi->second);
+
+ if (debug)
+ cerr << "object_info " << oi << std::endl;
+
+ OSDriver::OSTransaction _t(driver.get_transaction(t));
+ set<snapid_t> oi_snaps(oi.legacy_snaps.begin(), oi.legacy_snaps.end());
+ if (!oi_snaps.empty()) {
+ if (debug)
+ cerr << "\tsetting legacy snaps " << oi_snaps << std::endl;
+ snap_mapper.add_oid(hoid.hobj, oi_snaps, &_t);
+ }
+ }
+ } else {
+ if (hoid == last_head) {
+ map<string,bufferlist>::iterator mi = as.data.find(SS_ATTR);
+ if (mi != as.data.end()) {
+ SnapSet snapset;
+ auto p = mi->second.begin();
+ snapset.decode(p);
+ cout << "snapset " << snapset << std::endl;
+ if (!snapset.is_legacy()) {
+ for (auto& p : snapset.clone_snaps) {
+ hobject_t clone = hoid.hobj;
+ clone.snap = p.first;
+ set<snapid_t> snaps(p.second.begin(), p.second.end());
+ if (debug)
+ cerr << "\tsetting " << clone << " snaps " << snaps << std::endl;
+ OSDriver::OSTransaction _t(driver.get_transaction(t));
+ assert(!snaps.empty());
+ snap_mapper.add_oid(clone, snaps, &_t);
+ }
+ }
+ } else {
+ cerr << "missing SS_ATTR on " << hoid << std::endl;
+ }
+ }
}
}
int ObjectStoreTool::get_object(ObjectStore *store, coll_t coll,
bufferlist &bl, OSDMap &curmap,
bool *skipped_objects,
- ObjectStore::Sequencer &osr)
+ ObjectStore::Sequencer &osr,
+ ghobject_t *last_head,
+ set<ghobject_t> *last_clones)
{
ObjectStore::Transaction tran;
ObjectStore::Transaction *t = &tran;
cout << "Write " << ob.hoid << std::endl;
+ // manage snap collection
+ if (ob.hoid.hobj.is_snap()) {
+ ghobject_t head = ob.hoid;
+ head.hobj = head.hobj.get_head();
+ if (head == *last_head) {
+ last_clones->insert(ob.hoid);
+ } else {
+ *last_head = head;
+ last_clones->clear();
+ }
+ last_clones->insert(ob.hoid);
+ }
+
bufferlist ebl;
bool done = false;
while(!done) {
break;
case TYPE_ATTRS:
if (dry_run) break;
- ret = get_attrs(store, coll, ob.hoid, t, ebl, driver, mapper);
+ ret = get_attrs(store, coll, ob.hoid, t, ebl, driver, mapper,
+ *last_head, *last_clones);
if (ret) return ret;
break;
case TYPE_OMAP_HDR:
bool done = false;
bool found_metadata = false;
metadata_section ms;
+ ghobject_t last_head;
+ set<ghobject_t> last_clones;
while(!done) {
ret = read_section(&type, &ebl);
if (ret)
}
switch(type) {
case TYPE_OBJECT_BEGIN:
- ret = get_object(store, coll, ebl, curmap, &skipped_objects, osr);
+ ret = get_object(store, coll, ebl, curmap, &skipped_objects, osr,
+ &last_head, &last_clones);
if (ret) return ret;
break;
case TYPE_PG_METADATA: