]> git-server-git.apps.pok.os.sepia.ceph.com Git - ceph.git/commitdiff
ceph-kvstore-tool: copy one leveldb store to some other place 732/head
authorJoao Eduardo Luis <joao.luis@inktank.com>
Sun, 13 Oct 2013 12:45:43 +0000 (13:45 +0100)
committerJoao Eduardo Luis <joao.luis@inktank.com>
Wed, 16 Oct 2013 20:25:06 +0000 (21:25 +0100)
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>
src/tools/ceph-kvstore-tool.cc

index ffd462bbabd1d530d47cdcf0cd5e7b363ab4ec98..e07391d5c5107642b2e894e5da39890564ad14d6 100644 (file)
 #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;