case CEPH_OSD_OP_WATCH: return "watch";
case CEPH_OSD_OP_COPY_GET: return "copy-get";
+ case CEPH_OSD_OP_COPY_FROM: return "copy-from";
case CEPH_OSD_OP_CLONERANGE: return "clonerange";
case CEPH_OSD_OP_ASSERT_SRC_VERSION: return "assert-src-version";
CEPH_OSD_OP_OMAPRMKEYS = CEPH_OSD_OP_MODE_WR | CEPH_OSD_OP_TYPE_DATA | 24,
CEPH_OSD_OP_OMAP_CMP = CEPH_OSD_OP_MODE_RD | CEPH_OSD_OP_TYPE_DATA | 25,
+ CEPH_OSD_OP_COPY_FROM = CEPH_OSD_OP_MODE_WR | CEPH_OSD_OP_TYPE_DATA | 26,
CEPH_OSD_OP_COPY_GET = CEPH_OSD_OP_MODE_RD | CEPH_OSD_OP_TYPE_DATA | 27,
/** multi **/
struct {
__le64 max; /* max data in reply */
} __attribute__ ((packed)) copy_get;
+ struct {
+ __le64 snapid;
+ __le64 src_version;
+ } __attribute__ ((packed)) copy_from;
};
__le32 payload_len;
} __attribute__ ((packed));
*/
void omap_rm_keys(const std::set<std::string> &to_rm);
+ /**
+ * Copy an object
+ *
+ * Copies an object from another location. The operation is atomic in that
+ * the copy either succeeds in its entirety or fails (e.g., because the
+ * source object was modified while the copy was in progress).
+ *
+ * @param src source object name
+ * @param src_ioctx ioctx for the source object
+ * @param version current version of the source object
+ */
+ void copy_from(const std::string& src, const IoCtx& src_ioctx, uint64_t src_version);
+
friend class IoCtx;
};
IoCtx(IoCtxImpl *io_ctx_impl_);
friend class Rados; // Only Rados can use our private constructor to create IoCtxes.
+ friend class ObjectWriteOperation; // copy_from needs to see our IoCtxImpl
IoCtxImpl *io_ctx_impl;
};
o->omap_rm_keys(to_rm);
}
+void librados::ObjectWriteOperation::copy_from(const std::string& src,
+ const IoCtx& src_ioctx,
+ uint64_t src_version)
+{
+ ::ObjectOperation *o = (::ObjectOperation *)impl;
+ o->copy_from(object_t(src), src_ioctx.io_ctx_impl->snap_seq, src_ioctx.io_ctx_impl->oloc, src_version);
+}
+
void librados::ObjectWriteOperation::tmap_put(const bufferlist &bl)
{
::ObjectOperation *o = (::ObjectOperation *)impl;
break;
case CEPH_OSD_OP_COPY_GET:
out << " max " << op.op.copy_get.max;
+ case CEPH_OSD_OP_COPY_FROM:
+ out << " ver " << op.op.copy_from.src_version;
break;
default:
out << " " << op.op.extent.offset << "~" << op.op.extent.length;
OSDOp& osd_op = add_op(CEPH_OSD_OP_ROLLBACK);
osd_op.op.snap.snapid = snapid;
}
+
+ void copy_from(object_t src, snapid_t snapid, object_locator_t src_oloc, version_t src_version) {
+ OSDOp& osd_op = add_op(CEPH_OSD_OP_COPY_FROM);
+ osd_op.op.copy_from.snapid = snapid;
+ osd_op.op.copy_from.src_version = src_version;
+ ::encode(src, osd_op.indata);
+ ::encode(src_oloc, osd_op.indata);
+ }
};
ASSERT_EQ(0, destroy_one_pool_pp(pool_name, cluster));
}
+TEST(LibRadosMisc, CopyPP) {
+ Rados cluster;
+ std::string pool_name = get_temp_pool_name();
+ ASSERT_EQ("", create_one_pool_pp(pool_name, cluster));
+ IoCtx ioctx;
+ ASSERT_EQ(0, cluster.ioctx_create(pool_name.c_str(), ioctx));
+
+ char buf[64];
+ memset(buf, 0xcc, sizeof(buf));
+ bufferlist bl;
+ bl.append(buf, sizeof(buf));
+
+ ASSERT_EQ(0, ioctx.write_full("foo", bl));
+
+
+ ObjectWriteOperation op;
+ op.copyfrom("foo", ioctx, ioctx.get_last_version());
+
+ ASSERT_EQ(0, ioctx.operate("bar", &op));
+
+ ioctx.close();
+ ASSERT_EQ(0, destroy_one_pool_pp(pool_name, cluster));
+}
+
int main(int argc, char **argv)
{
::testing::InitGoogleTest(&argc, argv);