From: Kim Vandry Date: Sat, 31 Jan 2015 06:00:31 +0000 (+0900) Subject: librados: expose rados_{read|write}_op_assert_version() in C X-Git-Tag: v0.93~96^2~1 X-Git-Url: http://git-server-git.apps.pok.os.sepia.ceph.com/?a=commitdiff_plain;h=ac161bf38b15840c75bf20fa6427292afa8e8ab1;p=ceph.git librados: expose rados_{read|write}_op_assert_version() in C Previously, assert_version was only available in the C++ interface. Signed-off-by: Kim Vandry --- diff --git a/src/include/rados/librados.h b/src/include/rados/librados.h index 67113dd3471..745aa978f9f 100644 --- a/src/include/rados/librados.h +++ b/src/include/rados/librados.h @@ -261,6 +261,8 @@ struct rados_cluster_stat_t { * - Object map key/value pairs: rados_write_op_omap_set(), * rados_write_op_omap_rm_keys(), rados_write_op_omap_clear(), * rados_write_op_omap_cmp() + * - Object properties: rados_write_op_assert_exists(), + * rados_write_op_assert_version() * - Creating objects: rados_write_op_create() * - IO on objects: rados_write_op_append(), rados_write_op_write(), rados_write_op_zero * rados_write_op_write_full(), rados_write_op_remove, rados_write_op_truncate(), @@ -281,7 +283,8 @@ typedef void *rados_write_op_t; * - Object map key/value pairs: rados_read_op_omap_get_vals(), * rados_read_op_omap_get_keys(), rados_read_op_omap_get_vals_by_keys(), * rados_read_op_omap_cmp() - * - Object properties: rados_read_op_stat(), rados_read_op_assert_exists() + * - Object properties: rados_read_op_stat(), rados_read_op_assert_exists(), + * rados_read_op_assert_version() * - IO on objects: rados_read_op_read() * - Custom operations: rados_read_op_exec(), rados_read_op_exec_user_buf() * - Request properties: rados_read_op_set_flags() @@ -2204,6 +2207,21 @@ CEPH_RADOS_API void rados_write_op_set_flags(rados_write_op_t write_op, */ CEPH_RADOS_API void rados_write_op_assert_exists(rados_write_op_t write_op); +/** + * Ensure that the object exists and that its internal version + * number is equal to "ver" before writing. "ver" should be a + * version number previously obtained with rados_get_last_version(). + * - If the object's version is greater than the asserted version + * then rados_write_op_operate will return -ERANGE instead of + * executing the op. + * - If the object's version is less than the asserted version + * then rados_write_op_operate will return -EOVERFLOW instead + * of executing the op. + * @param write_op operation to add this action to + * @param ver object version number + */ +CEPH_RADOS_API void rados_write_op_assert_version(rados_write_op_t write_op, uint64_t ver); + /** * Ensure that given xattr satisfies comparison. * If the comparison is not satisfied, the return code of the @@ -2448,6 +2466,21 @@ CEPH_RADOS_API void rados_read_op_set_flags(rados_read_op_t read_op, int flags); */ CEPH_RADOS_API void rados_read_op_assert_exists(rados_read_op_t read_op); +/** + * Ensure that the object exists and that its internal version + * number is equal to "ver" before reading. "ver" should be a + * version number previously obtained with rados_get_last_version(). + * - If the object's version is greater than the asserted version + * then rados_read_op_operate will return -ERANGE instead of + * executing the op. + * - If the object's version is less than the asserted version + * then rados_read_op_operate will return -EOVERFLOW instead + * of executing the op. + * @param read_op operation to add this action to + * @param ver object version number + */ +CEPH_RADOS_API void rados_read_op_assert_version(rados_read_op_t write_op, uint64_t ver); + /** * Ensure that the an xattr satisfies a comparison * If the comparison is not satisfied, the return code of the diff --git a/src/librados/librados.cc b/src/librados/librados.cc index bdcc4c37369..2cdb8b4fdab 100644 --- a/src/librados/librados.cc +++ b/src/librados/librados.cc @@ -4125,6 +4125,13 @@ extern "C" void rados_write_op_set_flags(rados_write_op_t write_op, int flags) tracepoint(librados, rados_write_op_set_flags_exit); } +extern "C" void rados_write_op_assert_version(rados_write_op_t write_op, uint64_t ver) +{ + tracepoint(librados, rados_write_op_assert_version_enter, write_op); + ((::ObjectOperation *)write_op)->assert_version(ver); + tracepoint(librados, rados_write_op_assert_version_exit); +} + extern "C" void rados_write_op_assert_exists(rados_write_op_t write_op) { tracepoint(librados, rados_write_op_assert_exists_enter, write_op); @@ -4380,6 +4387,13 @@ extern "C" void rados_read_op_set_flags(rados_read_op_t read_op, int flags) tracepoint(librados, rados_read_op_set_flags_exit); } +extern "C" void rados_read_op_assert_version(rados_read_op_t read_op, uint64_t ver) +{ + tracepoint(librados, rados_read_op_assert_version_enter, read_op); + ((::ObjectOperation *)read_op)->assert_version(ver); + tracepoint(librados, rados_read_op_assert_version_exit); +} + extern "C" void rados_read_op_assert_exists(rados_read_op_t read_op) { tracepoint(librados, rados_read_op_assert_exists_enter, read_op); diff --git a/src/test/librados/c_read_operations.cc b/src/test/librados/c_read_operations.cc index da5f93783ff..9b577471bab 100644 --- a/src/test/librados/c_read_operations.cc +++ b/src/test/librados/c_read_operations.cc @@ -170,6 +170,31 @@ TEST_F(CReadOpsTest, AssertExists) { remove_object(); } +TEST_F(CReadOpsTest, AssertVersion) { + write_object(); + // Write to the object a second time to guarantee that its + // version number is greater than 0 + write_object(); + uint64_t v = rados_get_last_version(ioctx); + + rados_read_op_t op = rados_create_read_op(); + rados_read_op_assert_version(op, v+1); + ASSERT_EQ(-EOVERFLOW, rados_read_op_operate(op, ioctx, obj, 0)); + rados_release_read_op(op); + + op = rados_create_read_op(); + rados_read_op_assert_version(op, v-1); + ASSERT_EQ(-ERANGE, rados_read_op_operate(op, ioctx, obj, 0)); + rados_release_read_op(op); + + op = rados_create_read_op(); + rados_read_op_assert_version(op, v); + ASSERT_EQ(0, rados_read_op_operate(op, ioctx, obj, 0)); + rados_release_read_op(op); + + remove_object(); +} + TEST_F(CReadOpsTest, CmpXattr) { write_object(); diff --git a/src/test/librados/c_write_operations.cc b/src/test/librados/c_write_operations.cc index 7e1dc73df76..37c7450888d 100644 --- a/src/test/librados/c_write_operations.cc +++ b/src/test/librados/c_write_operations.cc @@ -1,5 +1,6 @@ // Tests for the C API coverage of atomic write operations +#include #include "include/rados/librados.h" #include "test/librados/test.h" #include "gtest/gtest.h" @@ -41,6 +42,51 @@ TEST(LibRadosCWriteOps, assertExists) { ASSERT_EQ(0, destroy_one_pool(pool_name, &cluster)); } +TEST(LibRadosCWriteOps, WriteOpAssertVersion) { + rados_t cluster; + rados_ioctx_t ioctx; + std::string pool_name = get_temp_pool_name(); + ASSERT_EQ("", create_one_pool(pool_name, &cluster)); + rados_ioctx_create(cluster, pool_name.c_str(), &ioctx); + + rados_write_op_t op = rados_create_write_op(); + ASSERT_TRUE(op); + rados_write_op_create(op, LIBRADOS_CREATE_EXCLUSIVE, NULL); + ASSERT_EQ(0, rados_write_op_operate(op, ioctx, "test", NULL, 0)); + rados_release_write_op(op); + + // Write to the object a second time to guarantee that its + // version number is greater than 0 + op = rados_create_write_op(); + ASSERT_TRUE(op); + rados_write_op_write_full(op, "hi", 2); + ASSERT_EQ(0, rados_write_op_operate(op, ioctx, "test", NULL, 0)); + rados_release_write_op(op); + + uint64_t v = rados_get_last_version(ioctx); + + op = rados_create_write_op(); + ASSERT_TRUE(op); + rados_write_op_assert_version(op, v+1); + ASSERT_EQ(-EOVERFLOW, rados_write_op_operate(op, ioctx, "test", NULL, 0)); + rados_release_write_op(op); + + op = rados_create_write_op(); + ASSERT_TRUE(op); + rados_write_op_assert_version(op, v-1); + ASSERT_EQ(-ERANGE, rados_write_op_operate(op, ioctx, "test", NULL, 0)); + rados_release_write_op(op); + + op = rados_create_write_op(); + ASSERT_TRUE(op); + rados_write_op_assert_version(op, v); + ASSERT_EQ(0, rados_write_op_operate(op, ioctx, "test", NULL, 0)); + rados_release_write_op(op); + + rados_ioctx_destroy(ioctx); + ASSERT_EQ(0, destroy_one_pool(pool_name, &cluster)); +} + TEST(LibRadosCWriteOps, Xattrs) { rados_t cluster; rados_ioctx_t ioctx;