const SequencerPosition *spos=0 ///< [in] Sequencer
) { return 0; }
- virtual int check(std::ostream &out) { return 0; }
+ virtual int check(std::ostream &out, bool repair = false) { return 0; }
typedef KeyValueDB::GenericIteratorImpl ObjectMapIteratorImpl;
typedef ceph::shared_ptr<ObjectMapIteratorImpl> ObjectMapIterator;
}
}
-int DBObjectMap::check(std::ostream &out)
+int DBObjectMap::check(std::ostream &out, bool repair)
{
int errors = 0;
map<uint64_t, uint64_t> parent_to_num_children;
complete_iter->next()) {
if (prev && prev >= complete_iter->key()) {
out << "Bad complete for " << header.oid << std::endl;
- errors++;
complete_error = true;
break;
}
prev = string(complete_iter->value().c_str(), complete_iter->value().length() - 1);
}
if (complete_error) {
- out << "Complete mapping:" << std::endl;
+ out << "Complete mapping for " << header.seq << " :" << std::endl;
for (complete_iter->seek_to_first(); complete_iter->valid();
complete_iter->next()) {
out << complete_iter->key() << " -> " << string(complete_iter->value().c_str(), complete_iter->value().length() - 1) << std::endl;
}
+ if (repair) {
+ KeyValueDB::Transaction t = db->get_transaction();
+ t->rmkeys_by_prefix(USER_PREFIX + header_key(header.seq) + COMPLETE_PREFIX);
+ db->submit_transaction(t);
+ out << "Cleared complete mapping to repair" << std::endl;
+ } else {
+ errors++; // Only count when not repaired
+ }
}
if (header.parent == 0)
state.v = 2;
state.seq = 1;
}
+ ostringstream ss;
+ int errors = check(ss, true);
+ if (errors) {
+ dout(5) << ss.str() << dendl;
+ return -EINVAL;
+ }
dout(20) << "(init)dbobjectmap: seq is " << state.seq << dendl;
return 0;
}
int upgrade_to_v2();
/// Consistency check, debug, there must be no parallel writes
- int check(std::ostream &out) override;
+ int check(std::ostream &out, bool repair = false) override;
/// Ensure that all previous operations are durable
int sync(const ghobject_t *oid=0, const SequencerPosition *spos=0) override;
("debug", "Additional debug output from DBObjectMap")
("oid", po::value<string>(&oid), "Restrict to this object id when dumping objects")
("command", po::value<string>(&cmd),
- "command arg is one of [dump-raw-keys, dump-raw-key-vals, dump-objects, dump-objects-with-keys, check, dump-headers], mandatory")
+ "command arg is one of [dump-raw-keys, dump-raw-key-vals, dump-objects, dump-objects-with-keys, check, dump-headers, repair], mandatory")
;
po::positional_options_description p;
p.add("command", 1);
std::cerr << "Output: " << out.str() << std::endl;
goto done;
}
+ // We don't call omap.init() here because it will repair
+ // the DBObjectMap which we might want to examine for diagnostic
+ // reasons. Instead use --command repair.
r = 0;
j->value().hexdump(std::cout);
}
}
- } else if (cmd == "check") {
- r = omap.check(std::cout);
+ } else if (cmd == "check" || cmd == "repair") {
+ bool repair = (cmd == "repair");
+ r = omap.check(std::cout, repair);
if (r > 0) {
std::cerr << "check got " << r << " error(s)" << std::endl;
r = 1;
goto done;
}
- std::cout << "check succeeded" << std::endl;
+ std::cout << (repair ? "repair" : "check") << " succeeded" << std::endl;
} else if (cmd == "dump-headers") {
vector<DBObjectMap::_Header> headers;
r = omap.list_object_headers(&headers);