summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSage Weil <sage@inktank.com>2013-10-16 13:35:07 -0700
committerSage Weil <sage@inktank.com>2013-10-16 13:35:07 -0700
commitd1547d222315e83543edccb68fd7b623e08322de (patch)
tree9a2145f1884223626695e7b7deb8a78ec01bf489
parent64fa5cbe87a7f956f36125c7dc2d1a360024b95d (diff)
parentfd6e2b86188845e6c115d65a5cfaeb60f57c6a3a (diff)
downloadceph-d1547d222315e83543edccb68fd7b623e08322de.tar.gz
Merge pull request #732 from ceph/wip-kvstore-tool
tools: ceph-kvstore-tool: Access & manipulate leveldb store using the KeyValueDB interface Reviewed-by: Sage Weil <sage@inktank.com>
-rw-r--r--src/test/Makefile.am5
-rw-r--r--src/tools/Makefile.am6
-rw-r--r--src/tools/ceph-kvstore-tool.cc (renamed from src/test/ObjectMap/test_store_tool/test_store_tool.cc)128
3 files changed, 125 insertions, 14 deletions
diff --git a/src/test/Makefile.am b/src/test/Makefile.am
index 59b4d89e930..84a228f1d4b 100644
--- a/src/test/Makefile.am
+++ b/src/test/Makefile.am
@@ -856,11 +856,6 @@ ceph_test_keyvaluedb_iterators_LDADD = $(LIBOS) $(UNITTEST_LDADD) $(CEPH_GLOBAL)
ceph_test_keyvaluedb_iterators_CXXFLAGS = $(UNITTEST_CXXFLAGS)
bin_DEBUGPROGRAMS += ceph_test_keyvaluedb_iterators
-ceph_test_store_tool_SOURCES = test/ObjectMap/test_store_tool/test_store_tool.cc
-ceph_test_store_tool_LDADD = $(LIBOS) $(CEPH_GLOBAL)
-ceph_test_store_tool_CXXFLAGS = $(UNITTEST_CXXFLAGS)
-bin_DEBUGPROGRAMS += ceph_test_store_tool
-
ceph_test_cfuse_cache_invalidate_SOURCES = test/test_cfuse_cache_invalidate.cc
bin_DEBUGPROGRAMS += ceph_test_cfuse_cache_invalidate
diff --git a/src/tools/Makefile.am b/src/tools/Makefile.am
index 4b8da77951a..89417014dd4 100644
--- a/src/tools/Makefile.am
+++ b/src/tools/Makefile.am
@@ -6,6 +6,12 @@ ceph_monstore_tool_SOURCES = tools/ceph-monstore-tool.cc
ceph_monstore_tool_LDADD = $(LIBOS) $(CEPH_GLOBAL) -lboost_program_options
bin_DEBUGPROGRAMS += ceph-monstore-tool
+ceph_kvstore_tool_SOURCES = tools/ceph-kvstore-tool.cc
+ceph_kvstore_tool_LDADD = $(LIBOS) $(CEPH_GLOBAL)
+ceph_kvstore_tool_CXXFLAGS = $(UNITTEST_CXXFLAGS)
+bin_DEBUGPROGRAMS += ceph-kvstore-tool
+
+
ceph_filestore_dump_SOURCES = tools/ceph-filestore-dump.cc
ceph_filestore_dump_LDADD = $(LIBOSD) $(LIBOS) $(CEPH_GLOBAL) -lboost_program_options
if LINUX
diff --git a/src/test/ObjectMap/test_store_tool/test_store_tool.cc b/src/tools/ceph-kvstore-tool.cc
index 8fcf3f30e82..e07391d5c51 100644
--- a/src/test/ObjectMap/test_store_tool/test_store_tool.cc
+++ b/src/tools/ceph-kvstore-tool.cc
@@ -25,21 +25,25 @@
#include "common/safe_io.h"
#include "common/config.h"
#include "common/strtol.h"
+#include "include/stringify.h"
using namespace std;
class StoreTool
{
boost::scoped_ptr<KeyValueDB> db;
+ string store_path;
public:
- StoreTool(const string &path) {
- LevelDBStore *db_ptr = new LevelDBStore(g_ceph_context, path);
+ StoreTool(const string &path) : store_path(path) {
+ LevelDBStore *db_ptr = new LevelDBStore(g_ceph_context, store_path);
assert(!db_ptr->open(std::cerr));
db.reset(db_ptr);
}
- void list(const string &prefix, const bool do_crc) {
+ uint32_t traverse(const string &prefix,
+ const bool do_crc,
+ ostream *out) {
KeyValueDB::WholeSpaceIterator iter = db->get_iterator();
if (prefix.empty())
@@ -47,18 +51,36 @@ class StoreTool
else
iter->seek_to_first(prefix);
+ uint32_t crc = -1;
+
while (iter->valid()) {
pair<string,string> rk = iter->raw_key();
if (!prefix.empty() && (rk.first != prefix))
- break;
+ break;
- std::cout << rk.first << ":" << rk.second;
+ if (out)
+ *out << rk.first << ":" << rk.second;
if (do_crc) {
- std::cout << " (" << iter->value().crc32c(0) << ")";
+ bufferlist bl;
+ bl.append(rk.first);
+ bl.append(rk.second);
+ bl.append(iter->value());
+
+ crc = bl.crc32c(crc);
+ if (out) {
+ *out << " (" << bl.crc32c(0) << ")";
+ }
}
- std::cout << std::endl;
+ if (out)
+ *out << std::endl;
iter->next();
}
+
+ return crc;
+ }
+
+ void list(const string &prefix, const bool do_crc) {
+ traverse(prefix, do_crc, &std::cout);
}
bool exists(const string &prefix) {
@@ -118,6 +140,70 @@ class StoreTool
return (ret == 0);
}
+
+ int copy_store_to(const string &other_path, const int num_keys_per_tx) {
+
+ if (num_keys_per_tx <= 0) {
+ std::cerr << "must specify a number of keys/tx > 0" << std::endl;
+ return -EINVAL;
+ }
+
+ // open or create a leveldb store at @p other_path
+ LevelDBStore other(g_ceph_context, other_path);
+ int err = other.create_and_open(std::cerr);
+ if (err < 0)
+ return err;
+
+ KeyValueDB::WholeSpaceIterator it = db->get_iterator();
+ it->seek_to_first();
+ uint64_t total_keys = 0;
+ uint64_t total_size = 0;
+ uint64_t total_txs = 0;
+
+ utime_t started_at = ceph_clock_now(g_ceph_context);
+
+ do {
+ int num_keys = 0;
+
+ KeyValueDB::Transaction tx = other.get_transaction();
+
+
+ while (it->valid() && num_keys < num_keys_per_tx) {
+ pair<string,string> k = it->raw_key();
+ bufferlist v = it->value();
+ tx->set(k.first, k.second, v);
+
+ num_keys ++;
+ total_size += v.length();
+
+ it->next();
+ }
+
+ total_txs ++;
+ total_keys += num_keys;
+
+ if (num_keys > 0)
+ other.submit_transaction_sync(tx);
+
+ utime_t cur_duration = ceph_clock_now(g_ceph_context) - started_at;
+ std::cout << "ts = " << cur_duration << "s, copied " << total_keys
+ << " keys so far (" << stringify(si_t(total_size)) << ")"
+ << std::endl;
+
+ } while (it->valid());
+
+ utime_t time_taken = ceph_clock_now(g_ceph_context) - started_at;
+
+ std::cout << "summary:" << std::endl;
+ std::cout << " copied " << total_keys << " keys" << std::endl;
+ std::cout << " used " << total_txs << " transactions" << std::endl;
+ std::cout << " total size " << stringify(si_t(total_size)) << std::endl;
+ std::cout << " from '" << store_path << "' to '" << other_path << "'"
+ << std::endl;
+ std::cout << " duration " << time_taken << " seconds" << std::endl;
+
+ return 0;
+ }
};
void usage(const char *pname)
@@ -132,6 +218,8 @@ void usage(const char *pname)
<< " crc <prefix> <key>\n"
<< " get-size\n"
<< " set <prefix> <key> [ver <N>|in <file>]\n"
+ << " store-copy <path> [num-keys-per-tx]\n"
+ << " store-crc <path>\n"
<< std::endl;
}
@@ -155,8 +243,6 @@ int main(int argc, const char *argv[])
string path(args[0]);
string cmd(args[1]);
- std::cout << "path: " << path << " cmd " << cmd << std::endl;
-
StoreTool st(path);
if (cmd == "list" || cmd == "list-crc") {
@@ -260,6 +346,30 @@ int main(int argc, const char *argv[])
<< prefix << "," << key << ")" << std::endl;
return 1;
}
+ } else if (cmd == "store-copy") {
+ int num_keys_per_tx = 128; // magic number that just feels right.
+ if (argc < 4) {
+ usage(argv[0]);
+ return 1;
+ } else if (argc > 4) {
+ string err;
+ num_keys_per_tx = strict_strtol(argv[4], 10, &err);
+ if (!err.empty()) {
+ std::cerr << "invalid num_keys_per_tx: " << err << std::endl;
+ return 1;
+ }
+ }
+
+ int ret = st.copy_store_to(argv[3], num_keys_per_tx);
+ if (ret < 0) {
+ std::cerr << "error copying store to path '" << argv[3]
+ << "': " << cpp_strerror(ret) << std::endl;
+ return 1;
+ }
+
+ } else if (cmd == "store-crc") {
+ uint32_t crc = st.traverse(string(), true, NULL);
+ std::cout << "store at '" << path << "' crc " << crc << std::endl;
} else {
std::cerr << "Unrecognized command: " << cmd << std::endl;