]> git-server-git.apps.pok.os.sepia.ceph.com Git - ceph.git/commitdiff
rados: add whole-object 'clonedata' command 180/head
authorSage Weil <sage@inktank.com>
Mon, 6 May 2013 23:45:12 +0000 (16:45 -0700)
committerSage Weil <sage@inktank.com>
Mon, 6 May 2013 23:45:12 +0000 (16:45 -0700)
Clone the data stream from one object to another.

Signed-off-by: Sage Weil <sage@inktank.com>
doc/man/8/rados.rst
qa/workunits/rados/clone.sh [new file with mode: 0755]
src/rados.cc

index e12f2da646a0466a04f66f4619034eb6da6f83e2..687ea807435ebc2c621ab44c10bc73ac6e104e0a 100644 (file)
@@ -87,11 +87,14 @@ Pool specific commands
 :command:`lssnap`
   List snapshots for given pool.
 
+:command:`clonedata` *srcname* *dstname* --object-locator *key*
+  Clone object byte data from *srcname* to *dstname*.  Both objects must be stored with the locator key *key* (usually either *srcname* or *dstname*).  Object attributes and omap keys are not copied or cloned.
+
 :command:`mksnap` *foo*
   Create pool snapshot named *foo*.
 
 :command:`rmsnap` *foo*
-  Remove pool snapshot names *foo*.
+  Remove pool snapshot named *foo*.
 
 :command:`bench` *seconds* *mode* [ -b *objsize* ] [ -t *threads* ]
   Benchmark for seconds. The mode can be write or read. The default
diff --git a/qa/workunits/rados/clone.sh b/qa/workunits/rados/clone.sh
new file mode 100755 (executable)
index 0000000..281e89f
--- /dev/null
@@ -0,0 +1,13 @@
+#!/bin/sh -x
+
+set -e
+
+rados -p data rm foo || true
+rados -p data put foo.tmp /etc/passwd --object-locator foo
+rados -p data clonedata foo.tmp foo --object-locator foo
+rados -p data get foo /tmp/foo
+cmp /tmp/foo /etc/passwd
+rados -p data rm foo.tmp --object-locator foo
+rados -p data rm foo
+
+echo OK
\ No newline at end of file
index 9af6a2c823afc05c505a4f1b0051f56351738913..8d06d2fa59305299a14244c778291b72069ee149 100644 (file)
@@ -72,6 +72,7 @@ void usage(ostream& out)
 "   create <obj-name> [category]     create object\n"
 "   rm <obj-name> ...                remove object(s)\n"
 "   cp <obj-name> [target-obj]       copy object\n"
+"   clonedata <src-obj> <dst-obj>    clone object data\n"
 "   listxattr <obj-name>\n"
 "   getxattr <obj-name> attr\n"
 "   setxattr <obj-name> attr val\n"
@@ -301,6 +302,26 @@ err:
   return ret;
 }
 
+static int do_clone_data(IoCtx& io_ctx, const char *objname, IoCtx& target_ctx, const char *target_obj)
+{
+  string oid(objname);
+
+  // get size
+  uint64_t size;
+  int r = target_ctx.stat(oid, &size, NULL);
+  if (r < 0)
+    return r;
+
+  librados::ObjectWriteOperation write_op;
+  string target_oid(target_obj);
+
+  /* reset data stream only */
+  write_op.create(false);
+  write_op.truncate(0);
+  write_op.clone_range(0, oid, 0, size);
+  return target_ctx.operate(target_oid, &write_op);
+}
+
 static int do_copy_pool(Rados& rados, const char *src_pool, const char *target_pool)
 {
   IoCtx src_ctx, target_ctx;
@@ -1682,7 +1703,49 @@ static int rados_tool_common(const std::map < std::string, std::string > &opts,
       return 1;
     }
   }
-  else if (strcmp(nargs[0], "rm") == 0) {
+  else if (strcmp(nargs[0], "clonedata") == 0) {
+    if (!pool_name)
+      usage_exit();
+
+    if (nargs.size() < 2 || nargs.size() > 3)
+      usage_exit();
+
+    const char *target = target_pool_name;
+    if (!target)
+      target = pool_name;
+
+    const char *target_obj;
+    if (nargs.size() < 3) {
+      if (strcmp(target, pool_name) == 0) {
+        cerr << "cannot copy object into itself" << std::endl;
+        return 1;
+      }
+      target_obj = nargs[1];
+    } else {
+      target_obj = nargs[2];
+    }
+
+    // open io context.
+    IoCtx target_ctx;
+    ret = rados.ioctx_create(target, target_ctx);
+    if (ret < 0) {
+      cerr << "error opening target pool " << target << ": "
+           << strerror_r(-ret, buf, sizeof(buf)) << std::endl;
+      return 1;
+    }
+    if (oloc.size()) {
+      target_ctx.locator_set_key(oloc);
+    } else {
+      cerr << "must specify locator for clone" << std::endl;
+      return 1;
+    }
+
+    ret = do_clone_data(io_ctx, nargs[1], target_ctx, target_obj);
+    if (ret < 0) {
+      cerr << "error cloning " << pool_name << "/" << nargs[1] << " => " << target << "/" << target_obj << ": " << strerror_r(-ret, buf, sizeof(buf)) << std::endl;
+      return 1;
+    }
+  } else if (strcmp(nargs[0], "rm") == 0) {
     if (!pool_name || nargs.size() < 2)
       usage_exit();
     vector<const char *>::iterator iter = nargs.begin();