Previously, assert_version was only available in the C++ interface.
Signed-off-by: Kim Vandry <vandry@TZoNE.ORG>
* - 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(),
* - 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()
*/
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
*/
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
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);
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);
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();
// Tests for the C API coverage of atomic write operations
+#include <errno.h>
#include "include/rados/librados.h"
#include "test/librados/test.h"
#include "gtest/gtest.h"
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;