summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJoao Eduardo Luis <joao.luis@inktank.com>2013-10-13 13:45:43 +0100
committerJoao Eduardo Luis <joao.luis@inktank.com>2013-10-16 21:25:06 +0100
commitfd6e2b86188845e6c115d65a5cfaeb60f57c6a3a (patch)
tree702efdbfcda9d3e4e656ac35417fc3ced9764d21
parent85914b27e67879e5d5b8f05c569919155b690d4f (diff)
downloadceph-fd6e2b86188845e6c115d65a5cfaeb60f57c6a3a.tar.gz
ceph-kvstore-tool: copy one leveldb store to some other place
Iterates over the provided source store's keys and copies them to the provided destination store. Signed-off-by: Joao Eduardo Luis <joao.luis@inktank.com>
-rw-r--r--src/tools/ceph-kvstore-tool.cc94
1 files changed, 90 insertions, 4 deletions
diff --git a/src/tools/ceph-kvstore-tool.cc b/src/tools/ceph-kvstore-tool.cc
index ffd462bbabd..e07391d5c51 100644
--- a/src/tools/ceph-kvstore-tool.cc
+++ b/src/tools/ceph-kvstore-tool.cc
@@ -25,16 +25,18 @@
#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);
}
@@ -138,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)
@@ -152,6 +218,7 @@ 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;
}
@@ -176,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") {
@@ -281,6 +346,27 @@ 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;