virtual int create_and_open(std::ostream &out) = 0;
virtual void close() { }
+ /// Try to repair K/V database. leveldb and rocksdb require that database must be not opened.
+ virtual int repair(std::ostream &out) { return 0; }
+
virtual Transaction get_transaction() = 0;
virtual int submit_transaction(Transaction) = 0;
virtual int submit_transaction_sync(Transaction t) {
return 0;
}
-int LevelDBStore::do_open(ostream &out, bool create_if_missing)
+int LevelDBStore::load_leveldb_options(bool create_if_missing, leveldb::Options &ldoptions)
{
- leveldb::Options ldoptions;
-
if (options.write_buffer_size)
ldoptions.write_buffer_size = options.write_buffer_size;
if (options.max_open_files)
leveldb::Env *env = leveldb::Env::Default();
env->NewLogger(options.log_file, &ldoptions.info_log);
}
+ return 0;
+}
+
+int LevelDBStore::do_open(ostream &out, bool create_if_missing)
+{
+ leveldb::Options ldoptions;
+ int r = load_leveldb_options(create_if_missing, ldoptions);
+ if (r) {
+ dout(1) << "load leveldb options failed" << dendl;
+ return r;
+ }
leveldb::DB *_db;
leveldb::Status status = leveldb::DB::Open(ldoptions, path, &_db);
cct->get_perfcounters_collection()->remove(logger);
}
+int LevelDBStore::repair(std::ostream &out)
+{
+ leveldb::Options ldoptions;
+ int r = load_leveldb_options(false, ldoptions);
+ if (r) {
+ dout(1) << "load leveldb options failed" << dendl;
+ out << "load leveldb options failed" << std::endl;
+ return r;
+ }
+ leveldb::Status status = leveldb::RepairDB(path, ldoptions);
+ if (status.ok()) {
+ return 0;
+ } else {
+ out << "repair leveldb failed : " << status.ToString() << std::endl;
+ return 1;
+ }
+}
+
int LevelDBStore::submit_transaction(KeyValueDB::Transaction t)
{
utime_t start = ceph_clock_now();
#endif
boost::scoped_ptr<leveldb::DB> db;
+ int load_leveldb_options(bool create_if_missing, leveldb::Options &opts);
int do_open(ostream &out, bool create_if_missing);
// manage async compactions
{
return logger;
}
+ int repair(std::ostream &out) override;
class LevelDBTransactionImpl : public KeyValueDB::TransactionImpl {
public:
return do_open(out, true);
}
-int RocksDBStore::do_open(ostream &out, bool create_if_missing)
+int RocksDBStore::load_rocksdb_options(bool create_if_missing, rocksdb::Options& opt)
{
- rocksdb::Options opt;
rocksdb::Status status;
if (options_str.length()) {
<< dendl;
opt.merge_operator.reset(new MergeOperatorRouter(*this));
+
+ return 0;
+}
+
+int RocksDBStore::do_open(ostream &out, bool create_if_missing)
+{
+ rocksdb::Options opt;
+ int r = load_rocksdb_options(create_if_missing, opt);
+ if (r) {
+ dout(1) << __func__ << " load rocksdb options failed" << dendl;
+ return r;
+ }
+ rocksdb::Status status;
status = rocksdb::DB::Open(opt, path, &db);
if (!status.ok()) {
derr << status.ToString() << dendl;
cct->get_perfcounters_collection()->remove(logger);
}
+int RocksDBStore::repair(std::ostream &out)
+{
+ rocksdb::Options opt;
+ int r = load_rocksdb_options(false, opt);
+ if (r) {
+ dout(1) << __func__ << " load rocksdb options failed" << dendl;
+ out << "load rocksdb options failed" << std::endl;
+ return r;
+ }
+ rocksdb::Status status = rocksdb::RepairDB(path, opt);
+ if (status.ok()) {
+ return 0;
+ } else {
+ out << "repair rocksdb failed : " << status.ToString() << std::endl;
+ return 1;
+ }
+}
+
void RocksDBStore::split_stats(const std::string &s, char delim, std::vector<std::string> &elems) {
std::stringstream ss;
ss.str(s);
bool set_cache_flag = false;
int do_open(ostream &out, bool create_if_missing);
+ int load_rocksdb_options(bool create_if_missing, rocksdb::Options& opt);
// manage async compactions
Mutex compact_queue_lock;
void close() override;
+ int repair(std::ostream &out) override;
void split_stats(const std::string &s, char delim, std::vector<std::string> &elems);
void get_statistics(Formatter *f) override;
}
-int BlueStore::_open_db(bool create)
+int BlueStore::_open_db(bool create, bool to_repair_db)
{
int r;
assert(!db);
if (kv_backend == "rocksdb")
options = cct->_conf->bluestore_rocksdb_options;
db->init(options);
+ if (to_repair_db)
+ return 0;
if (create)
r = db->create_and_open(err);
else
}
}
-int BlueStore::_mount(bool kv_only)
+int BlueStore::_mount(bool kv_only, bool open_db)
{
dout(1) << __func__ << " path " << path << dendl;
if (r < 0)
goto out_fsid;
- r = _open_db(false);
+ r = _open_db(false, !open_db);
if (r < 0)
goto out_bdev;
int _open_bdev(bool create);
void _close_bdev();
- int _open_db(bool create);
+ /*
+ * @warning to_repair_db means that we open this db to repair it, will not
+ * hold the rocksdb's file lock.
+ */
+ int _open_db(bool create, bool to_repair_db=false);
void _close_db();
int _open_fm(bool create);
void _close_fm();
bool test_mount_in_use() override;
private:
- int _mount(bool kv_only);
+ int _mount(bool kv_only, bool open_db=true);
public:
int mount() override {
return _mount(false);
}
int umount() override;
- int start_kv_only(KeyValueDB **pdb) {
- int r = _mount(true);
+ int start_kv_only(KeyValueDB **pdb, bool open_db=true) {
+ int r = _mount(true, open_db);
if (r < 0)
return r;
*pdb = db;
ceph-osd
ceph-dencoder
ceph-objectstore-tool
+ ceph-kvstore-tool
ceph-monstore-tool
osdmaptool
ceph_example
--- /dev/null
+ $ ceph-kvstore-tool --help
+ Usage: ceph-kvstore-tool <leveldb|rocksdb|bluestore-kv> <store path> command [args...]
+
+ Commands:
+ list [prefix]
+ list-crc [prefix]
+ exists <prefix> [key]
+ get <prefix> <key> [out <file>]
+ crc <prefix> <key>
+ get-size [<prefix> <key>]
+ set <prefix> <key> [ver <N>|in <file>]
+ rm <prefix> <key>
+ rm-prefix <prefix>
+ store-copy <path> [num-keys-per-tx]
+ store-crc <path>
+ compact
+ compact-prefix <prefix>
+ compact-range <prefix> <start> <end>
+ repair
+
+ [1]
endif(WITH_TESTS)
endif(WITH_LIBCEPHFS)
-if(WITH_TESTS)
add_executable(ceph-kvstore-tool ceph_kvstore_tool.cc)
target_link_libraries(ceph-kvstore-tool os global)
install(TARGETS ceph-kvstore-tool DESTINATION bin)
-endif(WITH_TESTS)
set(ceph_conf_srcs ceph_conf.cc)
add_executable(ceph-conf ${ceph_conf_srcs})
string store_path;
public:
- StoreTool(string type, const string &path) : store_path(path) {
+ StoreTool(string type, const string &path, bool need_open_db=true) : store_path(path) {
KeyValueDB *db_ptr;
if (type == "bluestore-kv") {
#ifdef HAVE_LIBAIO
// note: we'll leak this! the only user is ceph-kvstore-tool and
// we don't care.
- bluestore.reset(new BlueStore(g_ceph_context, path));
+ bluestore.reset(new BlueStore(g_ceph_context, path, need_open_db));
int r = bluestore->start_kv_only(&db_ptr);
if (r < 0) {
exit(1);
#endif
} else {
db_ptr = KeyValueDB::create(g_ceph_context, type, path);
- int r = db_ptr->open(std::cerr);
- if (r < 0) {
- cerr << "failed to open type " << type << " path " << path << ": "
- << cpp_strerror(r) << std::endl;
- exit(1);
+ if (need_open_db) {
+ int r = db_ptr->open(std::cerr);
+ if (r < 0) {
+ cerr << "failed to open type " << type << " path " << path << ": "
+ << cpp_strerror(r) << std::endl;
+ exit(1);
+ }
+ db = db_ptr;
}
}
- db = db_ptr;
}
~StoreTool() {
void compact_range(string prefix, string start, string end) {
db->compact_range(prefix, start, end);
}
+
+ int repair() {
+ return db->repair(std::cout);
+ }
};
void usage(const char *pname)
<< " compact\n"
<< " compact-prefix <prefix>\n"
<< " compact-range <prefix> <start> <end>\n"
+ << " repair\n"
<< std::endl;
}
string path(args[1]);
string cmd(args[2]);
- StoreTool st(type, path);
+ bool need_open_db = (cmd != "repair");
+ StoreTool st(type, path, need_open_db);
- if (cmd == "list" || cmd == "list-crc") {
+ if (cmd == "repair") {
+ int ret = st.repair();
+ if (!ret) {
+ std::cout << "repair kvstore successfully" << std::endl;
+ } else {
+ std::cout << "repair kvstore failed" << std::endl;
+ }
+ return ret;
+ } else if (cmd == "list" || cmd == "list-crc") {
string prefix;
if (argc > 4)
prefix = url_unescape(argv[4]);