rados: add whole-object 'clonedata' command

Clone the data stream from one object to another.

Signed-off-by: Sage Weil <sage@inktank.com>
This commit is contained in:
Sage Weil 2013-05-06 16:45:12 -07:00
parent bd36e78f72
commit c693ba5732
3 changed files with 81 additions and 2 deletions

View 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

13
qa/workunits/rados/clone.sh Executable file
View File

@ -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

View 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();