diff options
Diffstat (limited to 'src/tools/ceph-kvstore-tool.cc')
-rw-r--r-- | src/tools/ceph-kvstore-tool.cc | 94 |
1 files changed, 90 insertions, 4 deletions
diff --git a/src/tools/ceph-kvstore-tool.cc b/src/tools/ceph-kvstore-tool.cc index 5b4fdb73b93..9c5254f4cb5 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); } @@ -133,6 +135,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) @@ -147,6 +213,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; } @@ -171,8 +238,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") { @@ -276,6 +341,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; |