]> git.proxmox.com Git - ceph.git/blob - ceph/src/test/librados/c_write_operations.cc
update sources to 12.2.2
[ceph.git] / ceph / src / test / librados / c_write_operations.cc
1 // Tests for the C API coverage of atomic write operations
2
3 #include <errno.h>
4 #include "include/err.h"
5 #include "include/rados/librados.h"
6 #include "test/librados/test.h"
7 #include "gtest/gtest.h"
8
9 TEST(LibradosCWriteOps, NewDelete) {
10 rados_write_op_t op = rados_create_write_op();
11 ASSERT_TRUE(op);
12 rados_release_write_op(op);
13 }
14
15 TEST(LibRadosCWriteOps, assertExists) {
16 rados_t cluster;
17 rados_ioctx_t ioctx;
18 std::string pool_name = get_temp_pool_name();
19 ASSERT_EQ("", create_one_pool(pool_name, &cluster));
20 rados_ioctx_create(cluster, pool_name.c_str(), &ioctx);
21
22 rados_write_op_t op = rados_create_write_op();
23 ASSERT_TRUE(op);
24 rados_write_op_assert_exists(op);
25
26 // -2, ENOENT
27 ASSERT_EQ(-2, rados_write_op_operate(op, ioctx, "test", NULL, 0));
28 rados_release_write_op(op);
29
30 rados_write_op_t op2 = rados_create_write_op();
31 ASSERT_TRUE(op2);
32 rados_write_op_assert_exists(op2);
33
34 rados_completion_t completion;
35 ASSERT_EQ(0, rados_aio_create_completion(NULL, NULL, NULL, &completion));
36 ASSERT_EQ(0, rados_aio_write_op_operate(op2, ioctx, completion, "test", NULL, 0));
37 rados_aio_wait_for_complete(completion);
38 ASSERT_EQ(-2, rados_aio_get_return_value(completion));
39 rados_aio_release(completion);
40
41 rados_ioctx_destroy(ioctx);
42 rados_release_write_op(op2);
43 ASSERT_EQ(0, destroy_one_pool(pool_name, &cluster));
44 }
45
46 TEST(LibRadosCWriteOps, WriteOpAssertVersion) {
47 rados_t cluster;
48 rados_ioctx_t ioctx;
49 std::string pool_name = get_temp_pool_name();
50 ASSERT_EQ("", create_one_pool(pool_name, &cluster));
51 rados_ioctx_create(cluster, pool_name.c_str(), &ioctx);
52
53 rados_write_op_t op = rados_create_write_op();
54 ASSERT_TRUE(op);
55 rados_write_op_create(op, LIBRADOS_CREATE_EXCLUSIVE, NULL);
56 ASSERT_EQ(0, rados_write_op_operate(op, ioctx, "test", NULL, 0));
57 rados_release_write_op(op);
58
59 // Write to the object a second time to guarantee that its
60 // version number is greater than 0
61 op = rados_create_write_op();
62 ASSERT_TRUE(op);
63 rados_write_op_write_full(op, "hi", 2);
64 ASSERT_EQ(0, rados_write_op_operate(op, ioctx, "test", NULL, 0));
65 rados_release_write_op(op);
66
67 uint64_t v = rados_get_last_version(ioctx);
68
69 op = rados_create_write_op();
70 ASSERT_TRUE(op);
71 rados_write_op_assert_version(op, v+1);
72 ASSERT_EQ(-EOVERFLOW, rados_write_op_operate(op, ioctx, "test", NULL, 0));
73 rados_release_write_op(op);
74
75 op = rados_create_write_op();
76 ASSERT_TRUE(op);
77 rados_write_op_assert_version(op, v-1);
78 ASSERT_EQ(-ERANGE, rados_write_op_operate(op, ioctx, "test", NULL, 0));
79 rados_release_write_op(op);
80
81 op = rados_create_write_op();
82 ASSERT_TRUE(op);
83 rados_write_op_assert_version(op, v);
84 ASSERT_EQ(0, rados_write_op_operate(op, ioctx, "test", NULL, 0));
85 rados_release_write_op(op);
86
87 rados_ioctx_destroy(ioctx);
88 ASSERT_EQ(0, destroy_one_pool(pool_name, &cluster));
89 }
90
91 TEST(LibRadosCWriteOps, Xattrs) {
92 rados_t cluster;
93 rados_ioctx_t ioctx;
94 std::string pool_name = get_temp_pool_name();
95 ASSERT_EQ("", create_one_pool(pool_name, &cluster));
96 rados_ioctx_create(cluster, pool_name.c_str(), &ioctx);
97
98 // Create an object with an xattr
99 rados_write_op_t op = rados_create_write_op();
100 ASSERT_TRUE(op);
101 rados_write_op_create(op, LIBRADOS_CREATE_EXCLUSIVE, NULL);
102 rados_write_op_setxattr(op, "key", "value", 5);
103 ASSERT_EQ(0, rados_write_op_operate(op, ioctx, "test", NULL, 0));
104 rados_release_write_op(op);
105
106 // Check that xattr exists, if it does, delete it.
107 op = rados_create_write_op();
108 ASSERT_TRUE(op);
109 rados_write_op_create(op, LIBRADOS_CREATE_IDEMPOTENT, NULL);
110 rados_write_op_cmpxattr(op, "key", LIBRADOS_CMPXATTR_OP_EQ, "value", 5);
111 rados_write_op_rmxattr(op, "key");
112 ASSERT_EQ(0, rados_write_op_operate(op, ioctx, "test", NULL, 0));
113 rados_release_write_op(op);
114
115 // Check the xattr exits, if it does, add it again (will fail) with -125
116 // (ECANCELED)
117 op = rados_create_write_op();
118 ASSERT_TRUE(op);
119 rados_write_op_cmpxattr(op, "key", LIBRADOS_CMPXATTR_OP_EQ, "value", 5);
120 rados_write_op_setxattr(op, "key", "value", 5);
121 ASSERT_EQ(-ECANCELED, rados_write_op_operate(op, ioctx, "test", NULL, 0));
122
123 rados_release_write_op(op);
124 rados_ioctx_destroy(ioctx);
125 ASSERT_EQ(0, destroy_one_pool(pool_name, &cluster));
126 }
127
128 TEST(LibRadosCWriteOps, Write) {
129 rados_t cluster;
130 rados_ioctx_t ioctx;
131 std::string pool_name = get_temp_pool_name();
132 ASSERT_EQ("", create_one_pool(pool_name, &cluster));
133 rados_ioctx_create(cluster, pool_name.c_str(), &ioctx);
134
135 // Create an object, write and write full to it
136 rados_write_op_t op = rados_create_write_op();
137 ASSERT_TRUE(op);
138 rados_write_op_create(op, LIBRADOS_CREATE_EXCLUSIVE, NULL);
139 rados_write_op_write(op, "four", 4, 0);
140 rados_write_op_write_full(op, "hi", 2);
141 ASSERT_EQ(0, rados_write_op_operate(op, ioctx, "test", NULL, 0));
142 char hi[4];
143 ASSERT_EQ(2, rados_read(ioctx, "test", hi, 4, 0));
144 rados_release_write_op(op);
145
146 //create write op with iohint
147 op = rados_create_write_op();
148 ASSERT_TRUE(op);
149 rados_write_op_write_full(op, "ceph", 4);
150 rados_write_op_set_flags(op, LIBRADOS_OP_FLAG_FADVISE_NOCACHE);
151 ASSERT_EQ(0, rados_write_op_operate(op, ioctx, "test", NULL, 0));
152 ASSERT_EQ(4, rados_read(ioctx, "test", hi, 4, 0));
153 rados_release_write_op(op);
154
155 // Truncate and append
156 op = rados_create_write_op();
157 ASSERT_TRUE(op);
158 rados_write_op_truncate(op, 1);
159 rados_write_op_append(op, "hi", 2);
160 ASSERT_EQ(0, rados_write_op_operate(op, ioctx, "test", NULL, 0));
161 ASSERT_EQ(3, rados_read(ioctx, "test", hi, 4, 0));
162 rados_release_write_op(op);
163
164 // zero and remove
165 op = rados_create_write_op();
166 ASSERT_TRUE(op);
167 rados_write_op_zero(op, 0, 3);
168 rados_write_op_remove(op);
169 ASSERT_EQ(0, rados_write_op_operate(op, ioctx, "test", NULL, 0));
170 // ENOENT
171 ASSERT_EQ(-2, rados_read(ioctx, "test", hi, 4, 0));
172 rados_release_write_op(op);
173
174 rados_ioctx_destroy(ioctx);
175 ASSERT_EQ(0, destroy_one_pool(pool_name, &cluster));
176 }
177
178 TEST(LibRadosCWriteOps, Exec) {
179 rados_t cluster;
180 rados_ioctx_t ioctx;
181 std::string pool_name = get_temp_pool_name();
182 ASSERT_EQ("", create_one_pool(pool_name, &cluster));
183 rados_ioctx_create(cluster, pool_name.c_str(), &ioctx);
184
185 int rval = 1;
186 rados_write_op_t op = rados_create_write_op();
187 rados_write_op_exec(op, "hello", "record_hello", "test", 4, &rval);
188 ASSERT_EQ(0, rados_write_op_operate(op, ioctx, "test", NULL, 0));
189 rados_release_write_op(op);
190 ASSERT_EQ(0, rval);
191
192 char hi[100];
193 ASSERT_EQ(12, rados_read(ioctx, "test", hi, 100, 0));
194 hi[12] = '\0';
195 ASSERT_EQ(0, strcmp("Hello, test!", hi));
196
197 rados_ioctx_destroy(ioctx);
198 ASSERT_EQ(0, destroy_one_pool(pool_name, &cluster));
199 }
200
201 TEST(LibRadosCWriteOps, WriteSame) {
202 rados_t cluster;
203 rados_ioctx_t ioctx;
204 std::string pool_name = get_temp_pool_name();
205 ASSERT_EQ("", create_one_pool(pool_name, &cluster));
206 rados_ioctx_create(cluster, pool_name.c_str(), &ioctx);
207
208 // Create an object, write to it using writesame
209 rados_write_op_t op = rados_create_write_op();
210 ASSERT_TRUE(op);
211 rados_write_op_create(op, LIBRADOS_CREATE_EXCLUSIVE, NULL);
212 rados_write_op_writesame(op, "four", 4, 4 * 4, 0);
213 ASSERT_EQ(0, rados_write_op_operate(op, ioctx, "test", NULL, 0));
214 char hi[4 * 4];
215 ASSERT_EQ(sizeof(hi), static_cast<std::size_t>(
216 rados_read(ioctx, "test", hi,sizeof(hi), 0)));
217 rados_release_write_op(op);
218 ASSERT_EQ(0, memcmp("fourfourfourfour", hi, sizeof(hi)));
219
220 // cleanup
221 op = rados_create_write_op();
222 ASSERT_TRUE(op);
223 rados_write_op_remove(op);
224 ASSERT_EQ(0, rados_write_op_operate(op, ioctx, "test", NULL, 0));
225 rados_release_write_op(op);
226
227 rados_ioctx_destroy(ioctx);
228 ASSERT_EQ(0, destroy_one_pool(pool_name, &cluster));
229 }
230
231 TEST(LibRadosCWriteOps, CmpExt) {
232 rados_t cluster;
233 rados_ioctx_t ioctx;
234 std::string pool_name = get_temp_pool_name();
235 ASSERT_EQ("", create_one_pool(pool_name, &cluster));
236 rados_ioctx_create(cluster, pool_name.c_str(), &ioctx);
237
238 // create an object, write to it using writesame
239 rados_write_op_t op = rados_create_write_op();
240 ASSERT_TRUE(op);
241 rados_write_op_create(op, LIBRADOS_CREATE_EXCLUSIVE, NULL);
242 rados_write_op_write(op, "four", 4, 0);
243 ASSERT_EQ(0, rados_write_op_operate(op, ioctx, "test", NULL, 0));
244 rados_release_write_op(op);
245 char hi[4];
246 ASSERT_EQ(sizeof(hi), static_cast<std::size_t>(rados_read(ioctx, "test", hi, sizeof(hi), 0)));
247 ASSERT_EQ(0, memcmp("four", hi, sizeof(hi)));
248
249 // compare and overwrite on (expected) match
250 int val = 0;
251 op = rados_create_write_op();
252 ASSERT_TRUE(op);
253 rados_write_op_cmpext(op, "four", 4, 0, &val);
254 rados_write_op_write(op, "five", 4, 0);
255 ASSERT_EQ(0, rados_write_op_operate(op, ioctx, "test", NULL, 0));
256 ASSERT_EQ(0, val);
257 rados_release_write_op(op);
258 ASSERT_EQ(sizeof(hi), static_cast<std::size_t>(rados_read(ioctx, "test", hi, sizeof(hi), 0)));
259 ASSERT_EQ(0, memcmp("five", hi, sizeof(hi)));
260
261 // compare and bail before write due to mismatch
262 val = 0;
263 op = rados_create_write_op();
264 ASSERT_TRUE(op);
265 rados_write_op_cmpext(op, "four", 4, 0, &val);
266 rados_write_op_write(op, "six ", 4, 0);
267 ASSERT_EQ(-MAX_ERRNO - 1, rados_write_op_operate(op, ioctx, "test", NULL, 0));
268
269 ASSERT_EQ(-MAX_ERRNO - 1, val);
270
271 // cleanup
272 op = rados_create_write_op();
273 ASSERT_TRUE(op);
274 rados_write_op_remove(op);
275 ASSERT_EQ(0, rados_write_op_operate(op, ioctx, "test", NULL, 0));
276
277 rados_ioctx_destroy(ioctx);
278 ASSERT_EQ(0, destroy_one_pool(pool_name, &cluster));
279 }