1 // -*- mode:C; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
2 // vim: ts=8 sw=2 smarttab
4 #include "cls/journal/cls_journal_client.h"
5 #include "include/stringify.h"
6 #include "common/Cond.h"
7 #include "test/librados/test.h"
8 #include "gtest/gtest.h"
13 using namespace cls::journal;
15 class TestClsJournal : public ::testing::Test {
18 static void SetUpTestCase() {
19 _pool_name = get_temp_pool_name();
20 ASSERT_EQ("", create_one_pool_pp(_pool_name, _rados));
23 static void TearDownTestCase() {
24 ASSERT_EQ(0, destroy_one_pool_pp(_pool_name, _rados));
27 std::string get_temp_image_name() {
29 return "image" + stringify(_image_number);
32 static std::string _pool_name;
33 static librados::Rados _rados;
34 static uint64_t _image_number;
38 std::string TestClsJournal::_pool_name;
39 librados::Rados TestClsJournal::_rados;
40 uint64_t TestClsJournal::_image_number = 0;
42 TEST_F(TestClsJournal, Create) {
43 librados::IoCtx ioctx;
44 ASSERT_EQ(0, _rados.ioctx_create(_pool_name.c_str(), ioctx));
46 std::string oid = get_temp_image_name();
49 uint8_t splay_width = 2;
50 int64_t pool_id = ioctx.get_id();
51 ASSERT_EQ(0, client::create(ioctx, oid, order, splay_width, pool_id));
54 uint8_t read_splay_width;
57 client::get_immutable_metadata(ioctx, oid, &read_order, &read_splay_width,
58 &read_pool_id, &cond);
59 ASSERT_EQ(0, cond.wait());
60 ASSERT_EQ(order, read_order);
61 ASSERT_EQ(splay_width, read_splay_width);
62 ASSERT_EQ(pool_id, read_pool_id);
65 TEST_F(TestClsJournal, MinimumSet) {
66 librados::IoCtx ioctx;
67 ASSERT_EQ(0, _rados.ioctx_create(_pool_name.c_str(), ioctx));
69 std::string oid = get_temp_image_name();
71 ASSERT_EQ(0, client::create(ioctx, oid, 2, 4, ioctx.get_id()));
73 librados::ObjectWriteOperation op1;
74 client::set_active_set(&op1, 300);
75 ASSERT_EQ(0, ioctx.operate(oid, &op1));
77 uint64_t minimum_set = 123;
78 librados::ObjectWriteOperation op2;
79 client::set_minimum_set(&op2, minimum_set);
80 ASSERT_EQ(0, ioctx.operate(oid, &op2));
83 uint64_t read_minimum_set;
84 uint64_t read_active_set;
85 std::set<cls::journal::Client> read_clients;
86 client::get_mutable_metadata(ioctx, oid, &read_minimum_set, &read_active_set,
87 &read_clients, &cond);
88 ASSERT_EQ(0, cond.wait());
89 ASSERT_EQ(minimum_set, read_minimum_set);
92 TEST_F(TestClsJournal, MinimumSetStale) {
93 librados::IoCtx ioctx;
94 ASSERT_EQ(0, _rados.ioctx_create(_pool_name.c_str(), ioctx));
96 std::string oid = get_temp_image_name();
98 ASSERT_EQ(0, client::create(ioctx, oid, 2, 4, ioctx.get_id()));
100 librados::ObjectWriteOperation op1;
101 client::set_active_set(&op1, 300);
102 ASSERT_EQ(0, ioctx.operate(oid, &op1));
104 uint64_t minimum_set = 123;
105 librados::ObjectWriteOperation op2;
106 client::set_minimum_set(&op2, minimum_set);
107 ASSERT_EQ(0, ioctx.operate(oid, &op2));
109 librados::ObjectWriteOperation op3;
110 client::set_minimum_set(&op3, 1);
111 ASSERT_EQ(-ESTALE, ioctx.operate(oid, &op3));
114 uint64_t read_minimum_set;
115 uint64_t read_active_set;
116 std::set<cls::journal::Client> read_clients;
117 client::get_mutable_metadata(ioctx, oid, &read_minimum_set, &read_active_set,
118 &read_clients, &cond);
119 ASSERT_EQ(0, cond.wait());
120 ASSERT_EQ(minimum_set, read_minimum_set);
123 TEST_F(TestClsJournal, MinimumSetOrderConstraint) {
124 librados::IoCtx ioctx;
125 ASSERT_EQ(0, _rados.ioctx_create(_pool_name.c_str(), ioctx));
127 std::string oid = get_temp_image_name();
129 ASSERT_EQ(0, client::create(ioctx, oid, 2, 4, ioctx.get_id()));
131 librados::ObjectWriteOperation op1;
132 client::set_minimum_set(&op1, 123);
133 ASSERT_EQ(-EINVAL, ioctx.operate(oid, &op1));
136 uint64_t read_minimum_set;
137 uint64_t read_active_set;
138 std::set<cls::journal::Client> read_clients;
139 client::get_mutable_metadata(ioctx, oid, &read_minimum_set, &read_active_set,
140 &read_clients, &cond);
141 ASSERT_EQ(0, cond.wait());
142 ASSERT_EQ(0U, read_minimum_set);
145 TEST_F(TestClsJournal, ActiveSet) {
146 librados::IoCtx ioctx;
147 ASSERT_EQ(0, _rados.ioctx_create(_pool_name.c_str(), ioctx));
149 std::string oid = get_temp_image_name();
151 ASSERT_EQ(0, client::create(ioctx, oid, 2, 4, ioctx.get_id()));
153 uint64_t active_set = 234;
154 librados::ObjectWriteOperation op1;
155 client::set_active_set(&op1, active_set);
156 ASSERT_EQ(0, ioctx.operate(oid, &op1));
159 uint64_t read_minimum_set;
160 uint64_t read_active_set;
161 std::set<cls::journal::Client> read_clients;
162 client::get_mutable_metadata(ioctx, oid, &read_minimum_set, &read_active_set,
163 &read_clients, &cond);
164 ASSERT_EQ(0, cond.wait());
165 ASSERT_EQ(active_set, read_active_set);
168 TEST_F(TestClsJournal, ActiveSetStale) {
169 librados::IoCtx ioctx;
170 ASSERT_EQ(0, _rados.ioctx_create(_pool_name.c_str(), ioctx));
172 std::string oid = get_temp_image_name();
174 ASSERT_EQ(0, client::create(ioctx, oid, 2, 4, ioctx.get_id()));
176 librados::ObjectWriteOperation op1;
177 client::set_active_set(&op1, 345);
178 ASSERT_EQ(0, ioctx.operate(oid, &op1));
180 librados::ObjectWriteOperation op2;
181 client::set_active_set(&op2, 3);
182 ASSERT_EQ(-ESTALE, ioctx.operate(oid, &op2));
185 TEST_F(TestClsJournal, CreateDuplicate) {
186 librados::IoCtx ioctx;
187 ASSERT_EQ(0, _rados.ioctx_create(_pool_name.c_str(), ioctx));
189 std::string oid = get_temp_image_name();
191 ASSERT_EQ(0, client::create(ioctx, oid, 2, 4, ioctx.get_id()));
192 ASSERT_EQ(-EEXIST, client::create(ioctx, oid, 3, 5, ioctx.get_id()));
195 TEST_F(TestClsJournal, GetClient) {
196 librados::IoCtx ioctx;
197 ASSERT_EQ(0, _rados.ioctx_create(_pool_name.c_str(), ioctx));
199 std::string oid = get_temp_image_name();
200 ASSERT_EQ(0, client::create(ioctx, oid, 2, 4, ioctx.get_id()));
203 ASSERT_EQ(-ENOENT, client::get_client(ioctx, oid, "id", &client));
206 data.append(std::string('1', 128));
207 ASSERT_EQ(0, client::client_register(ioctx, oid, "id1", data));
209 ASSERT_EQ(0, client::get_client(ioctx, oid, "id1", &client));
210 Client expected_client("id1", data);
211 ASSERT_EQ(expected_client, client);
214 TEST_F(TestClsJournal, ClientRegister) {
215 librados::IoCtx ioctx;
216 ASSERT_EQ(0, _rados.ioctx_create(_pool_name.c_str(), ioctx));
218 std::string oid = get_temp_image_name();
219 ASSERT_EQ(0, client::create(ioctx, oid, 2, 4, ioctx.get_id()));
221 ASSERT_EQ(0, client::client_register(ioctx, oid, "id1", bufferlist()));
223 std::set<Client> clients;
224 ASSERT_EQ(0, client::client_list(ioctx, oid, &clients));
226 std::set<Client> expected_clients = {Client("id1", bufferlist())};
227 ASSERT_EQ(expected_clients, clients);
230 TEST_F(TestClsJournal, ClientRegisterDuplicate) {
231 librados::IoCtx ioctx;
232 ASSERT_EQ(0, _rados.ioctx_create(_pool_name.c_str(), ioctx));
234 std::string oid = get_temp_image_name();
235 ASSERT_EQ(0, client::create(ioctx, oid, 2, 4, ioctx.get_id()));
237 ASSERT_EQ(0, client::client_register(ioctx, oid, "id1", bufferlist()));
238 ASSERT_EQ(-EEXIST, client::client_register(ioctx, oid, "id1", bufferlist()));
241 TEST_F(TestClsJournal, ClientUpdateData) {
242 librados::IoCtx ioctx;
243 ASSERT_EQ(0, _rados.ioctx_create(_pool_name.c_str(), ioctx));
245 std::string oid = get_temp_image_name();
246 ASSERT_EQ(0, client::create(ioctx, oid, 2, 4, ioctx.get_id()));
248 ASSERT_EQ(-ENOENT, client::client_update_data(ioctx, oid, "id1",
251 ASSERT_EQ(0, client::client_register(ioctx, oid, "id1", bufferlist()));
254 data.append(std::string('1', 128));
255 ASSERT_EQ(0, client::client_update_data(ioctx, oid, "id1", data));
258 ASSERT_EQ(0, client::get_client(ioctx, oid, "id1", &client));
259 Client expected_client("id1", data);
260 ASSERT_EQ(expected_client, client);
263 TEST_F(TestClsJournal, ClientUpdateState) {
264 librados::IoCtx ioctx;
265 ASSERT_EQ(0, _rados.ioctx_create(_pool_name.c_str(), ioctx));
267 std::string oid = get_temp_image_name();
268 ASSERT_EQ(0, client::create(ioctx, oid, 2, 4, ioctx.get_id()));
270 ASSERT_EQ(-ENOENT, client::client_update_state(ioctx, oid, "id1",
271 CLIENT_STATE_DISCONNECTED));
273 ASSERT_EQ(0, client::client_register(ioctx, oid, "id1", bufferlist()));
276 data.append(std::string('1', 128));
277 ASSERT_EQ(0, client::client_update_state(ioctx, oid, "id1",
278 CLIENT_STATE_DISCONNECTED));
281 ASSERT_EQ(0, client::get_client(ioctx, oid, "id1", &client));
282 Client expected_client;
283 expected_client.id = "id1";
284 expected_client.state = CLIENT_STATE_DISCONNECTED;
285 ASSERT_EQ(expected_client, client);
288 TEST_F(TestClsJournal, ClientUnregister) {
289 librados::IoCtx ioctx;
290 ASSERT_EQ(0, _rados.ioctx_create(_pool_name.c_str(), ioctx));
292 std::string oid = get_temp_image_name();
293 ASSERT_EQ(0, client::create(ioctx, oid, 2, 4, ioctx.get_id()));
295 ASSERT_EQ(0, client::client_register(ioctx, oid, "id1", bufferlist()));
296 ASSERT_EQ(0, client::client_unregister(ioctx, oid, "id1"));
299 TEST_F(TestClsJournal, ClientUnregisterDNE) {
300 librados::IoCtx ioctx;
301 ASSERT_EQ(0, _rados.ioctx_create(_pool_name.c_str(), ioctx));
303 std::string oid = get_temp_image_name();
304 ASSERT_EQ(0, client::create(ioctx, oid, 2, 4, ioctx.get_id()));
306 ASSERT_EQ(0, client::client_register(ioctx, oid, "id1", bufferlist()));
307 ASSERT_EQ(0, client::client_unregister(ioctx, oid, "id1"));
308 ASSERT_EQ(-ENOENT, client::client_unregister(ioctx, oid, "id1"));
311 TEST_F(TestClsJournal, ClientUnregisterPruneTags) {
312 librados::IoCtx ioctx;
313 ASSERT_EQ(0, _rados.ioctx_create(_pool_name.c_str(), ioctx));
315 std::string oid = get_temp_image_name();
317 ASSERT_EQ(0, client::create(ioctx, oid, 2, 2, ioctx.get_id()));
318 ASSERT_EQ(0, client::client_register(ioctx, oid, "id1", bufferlist()));
319 ASSERT_EQ(0, client::client_register(ioctx, oid, "id2", bufferlist()));
321 ASSERT_EQ(0, client::tag_create(ioctx, oid, 0, Tag::TAG_CLASS_NEW,
323 ASSERT_EQ(0, client::tag_create(ioctx, oid, 1, Tag::TAG_CLASS_NEW,
326 for (uint32_t i = 2; i <= 96; ++i) {
327 ASSERT_EQ(0, client::tag_create(ioctx, oid, i, 1, bufferlist()));
330 librados::ObjectWriteOperation op1;
331 client::client_commit(&op1, "id1", {{{1, 32, 120}}});
332 ASSERT_EQ(0, ioctx.operate(oid, &op1));
334 ASSERT_EQ(0, client::client_unregister(ioctx, oid, "id2"));
336 std::set<Tag> expected_tags = {{0, 0, {}}};
337 for (uint32_t i = 32; i <= 96; ++i) {
338 expected_tags.insert({i, 1, {}});
341 ASSERT_EQ(0, client::tag_list(ioctx, oid, "id1",
342 boost::optional<uint64_t>(), &tags));
343 ASSERT_EQ(expected_tags, tags);
346 TEST_F(TestClsJournal, ClientCommit) {
347 librados::IoCtx ioctx;
348 ASSERT_EQ(0, _rados.ioctx_create(_pool_name.c_str(), ioctx));
350 std::string oid = get_temp_image_name();
352 ASSERT_EQ(0, client::create(ioctx, oid, 2, 2, ioctx.get_id()));
353 ASSERT_EQ(0, client::client_register(ioctx, oid, "id1", bufferlist()));
355 cls::journal::ObjectPositions object_positions;
357 cls::journal::ObjectPosition(0, 234, 120),
358 cls::journal::ObjectPosition(3, 235, 121)};
359 cls::journal::ObjectSetPosition object_set_position(
362 librados::ObjectWriteOperation op2;
363 client::client_commit(&op2, "id1", object_set_position);
364 ASSERT_EQ(0, ioctx.operate(oid, &op2));
366 std::set<Client> clients;
367 ASSERT_EQ(0, client::client_list(ioctx, oid, &clients));
369 std::set<Client> expected_clients = {
370 Client("id1", bufferlist(), object_set_position)};
371 ASSERT_EQ(expected_clients, clients);
374 TEST_F(TestClsJournal, ClientCommitInvalid) {
375 librados::IoCtx ioctx;
376 ASSERT_EQ(0, _rados.ioctx_create(_pool_name.c_str(), ioctx));
378 std::string oid = get_temp_image_name();
380 ASSERT_EQ(0, client::create(ioctx, oid, 2, 2, ioctx.get_id()));
381 ASSERT_EQ(0, client::client_register(ioctx, oid, "id1", bufferlist()));
383 cls::journal::ObjectPositions object_positions;
385 cls::journal::ObjectPosition(0, 234, 120),
386 cls::journal::ObjectPosition(4, 234, 121),
387 cls::journal::ObjectPosition(5, 235, 121)};
388 cls::journal::ObjectSetPosition object_set_position(
391 librados::ObjectWriteOperation op2;
392 client::client_commit(&op2, "id1", object_set_position);
393 ASSERT_EQ(-EINVAL, ioctx.operate(oid, &op2));
396 TEST_F(TestClsJournal, ClientCommitDNE) {
397 librados::IoCtx ioctx;
398 ASSERT_EQ(0, _rados.ioctx_create(_pool_name.c_str(), ioctx));
400 std::string oid = get_temp_image_name();
402 cls::journal::ObjectSetPosition object_set_position;
404 librados::ObjectWriteOperation op1;
405 client::client_commit(&op1, "id1", object_set_position);
406 ASSERT_EQ(-ENOENT, ioctx.operate(oid, &op1));
409 TEST_F(TestClsJournal, ClientList) {
410 librados::IoCtx ioctx;
411 ASSERT_EQ(0, _rados.ioctx_create(_pool_name.c_str(), ioctx));
413 std::string oid = get_temp_image_name();
415 ASSERT_EQ(0, client::create(ioctx, oid, 12, 5, ioctx.get_id()));
417 std::set<Client> expected_clients;
418 librados::ObjectWriteOperation op1;
419 for (uint32_t i = 0; i < 512; ++i) {
420 std::string id = "id" + stringify(i + 1);
421 expected_clients.insert(Client(id, bufferlist()));
422 client::client_register(&op1, id, bufferlist());
424 ASSERT_EQ(0, ioctx.operate(oid, &op1));
426 std::set<Client> clients;
427 ASSERT_EQ(0, client::client_list(ioctx, oid, &clients));
428 ASSERT_EQ(expected_clients, clients);
431 uint64_t read_minimum_set;
432 uint64_t read_active_set;
433 std::set<cls::journal::Client> read_clients;
434 client::get_mutable_metadata(ioctx, oid, &read_minimum_set, &read_active_set,
435 &read_clients, &cond);
436 ASSERT_EQ(0, cond.wait());
437 ASSERT_EQ(expected_clients, read_clients);
440 TEST_F(TestClsJournal, GetNextTagTid) {
441 librados::IoCtx ioctx;
442 ASSERT_EQ(0, _rados.ioctx_create(_pool_name.c_str(), ioctx));
444 std::string oid = get_temp_image_name();
447 ASSERT_EQ(-ENOENT, client::get_next_tag_tid(ioctx, oid, &tag_tid));
449 ASSERT_EQ(0, client::create(ioctx, oid, 2, 2, ioctx.get_id()));
450 ASSERT_EQ(0, client::client_register(ioctx, oid, "id1", bufferlist()));
452 ASSERT_EQ(0, client::get_next_tag_tid(ioctx, oid, &tag_tid));
453 ASSERT_EQ(0U, tag_tid);
455 ASSERT_EQ(0, client::tag_create(ioctx, oid, 0, Tag::TAG_CLASS_NEW,
457 ASSERT_EQ(0, client::get_next_tag_tid(ioctx, oid, &tag_tid));
458 ASSERT_EQ(1U, tag_tid);
461 TEST_F(TestClsJournal, TagCreate) {
462 librados::IoCtx ioctx;
463 ASSERT_EQ(0, _rados.ioctx_create(_pool_name.c_str(), ioctx));
465 std::string oid = get_temp_image_name();
467 ASSERT_EQ(-ENOENT, client::tag_create(ioctx, oid, 0, Tag::TAG_CLASS_NEW,
470 ASSERT_EQ(0, client::create(ioctx, oid, 2, 2, ioctx.get_id()));
471 ASSERT_EQ(0, client::client_register(ioctx, oid, "id1", bufferlist()));
473 ASSERT_EQ(-ESTALE, client::tag_create(ioctx, oid, 1, Tag::TAG_CLASS_NEW,
475 ASSERT_EQ(-EINVAL, client::tag_create(ioctx, oid, 0, 1, bufferlist()));
477 ASSERT_EQ(0, client::tag_create(ioctx, oid, 0, Tag::TAG_CLASS_NEW,
479 ASSERT_EQ(-EEXIST, client::tag_create(ioctx, oid, 0, Tag::TAG_CLASS_NEW,
481 ASSERT_EQ(0, client::tag_create(ioctx, oid, 1, Tag::TAG_CLASS_NEW,
483 ASSERT_EQ(0, client::tag_create(ioctx, oid, 2, 1, bufferlist()));
485 std::set<Tag> expected_tags = {
486 {0, 0, {}}, {1, 1, {}}, {2, 1, {}}};
488 ASSERT_EQ(0, client::tag_list(ioctx, oid, "id1",
489 boost::optional<uint64_t>(), &tags));
490 ASSERT_EQ(expected_tags, tags);
493 TEST_F(TestClsJournal, TagCreatePrunesTags) {
494 librados::IoCtx ioctx;
495 ASSERT_EQ(0, _rados.ioctx_create(_pool_name.c_str(), ioctx));
497 std::string oid = get_temp_image_name();
499 ASSERT_EQ(0, client::create(ioctx, oid, 2, 2, ioctx.get_id()));
500 ASSERT_EQ(0, client::client_register(ioctx, oid, "id1", bufferlist()));
502 ASSERT_EQ(0, client::tag_create(ioctx, oid, 0, Tag::TAG_CLASS_NEW,
504 ASSERT_EQ(0, client::tag_create(ioctx, oid, 1, Tag::TAG_CLASS_NEW,
506 ASSERT_EQ(0, client::tag_create(ioctx, oid, 2, 1, bufferlist()));
508 librados::ObjectWriteOperation op1;
509 client::client_commit(&op1, "id1", {{{1, 2, 120}}});
510 ASSERT_EQ(0, ioctx.operate(oid, &op1));
512 ASSERT_EQ(0, client::tag_create(ioctx, oid, 3, 0, bufferlist()));
514 std::set<Tag> expected_tags = {
515 {0, 0, {}}, {2, 1, {}}, {3, 0, {}}};
517 ASSERT_EQ(0, client::tag_list(ioctx, oid, "id1",
518 boost::optional<uint64_t>(), &tags));
519 ASSERT_EQ(expected_tags, tags);
522 TEST_F(TestClsJournal, TagList) {
523 librados::IoCtx ioctx;
524 ASSERT_EQ(0, _rados.ioctx_create(_pool_name.c_str(), ioctx));
526 std::string oid = get_temp_image_name();
528 ASSERT_EQ(0, client::create(ioctx, oid, 2, 2, ioctx.get_id()));
529 ASSERT_EQ(0, client::client_register(ioctx, oid, "id1", bufferlist()));
531 std::set<Tag> expected_all_tags;
532 std::set<Tag> expected_filtered_tags;
533 for (uint32_t i = 0; i < 96; ++i) {
534 uint64_t tag_class = Tag::TAG_CLASS_NEW;
536 tag_class = i % 2 == 0 ? 0 : 1;
539 Tag tag(i, i % 2 == 0 ? 0 : 1, bufferlist());
540 expected_all_tags.insert(tag);
542 expected_filtered_tags.insert(tag);
544 ASSERT_EQ(0, client::tag_create(ioctx, oid, i, tag_class,
549 ASSERT_EQ(0, client::tag_list(ioctx, oid, "id1", boost::optional<uint64_t>(),
551 ASSERT_EQ(expected_all_tags, tags);
553 ASSERT_EQ(0, client::tag_list(ioctx, oid, "id1", boost::optional<uint64_t>(0),
555 ASSERT_EQ(expected_filtered_tags, tags);
557 librados::ObjectWriteOperation op1;
558 client::client_commit(&op1, "id1", {{{96, 0, 120}}});
559 ASSERT_EQ(0, ioctx.operate(oid, &op1));
561 ASSERT_EQ(0, client::tag_list(ioctx, oid, "id1", boost::optional<uint64_t>(),
563 ASSERT_EQ(expected_all_tags, tags);
566 TEST_F(TestClsJournal, GuardAppend) {
567 librados::IoCtx ioctx;
568 ASSERT_EQ(0, _rados.ioctx_create(_pool_name.c_str(), ioctx));
570 std::string oid = get_temp_image_name();
573 bl.append("journal entry!");
575 librados::ObjectWriteOperation op1;
577 ASSERT_EQ(0, ioctx.operate(oid, &op1));
579 librados::ObjectWriteOperation op2;
580 client::guard_append(&op2, 1024);
581 ASSERT_EQ(0, ioctx.operate(oid, &op2));
584 TEST_F(TestClsJournal, GuardAppendDNE) {
585 librados::IoCtx ioctx;
586 ASSERT_EQ(0, _rados.ioctx_create(_pool_name.c_str(), ioctx));
588 std::string oid = get_temp_image_name();
590 librados::ObjectWriteOperation op2;
591 client::guard_append(&op2, 1024);
592 ASSERT_EQ(0, ioctx.operate(oid, &op2));
595 TEST_F(TestClsJournal, GuardAppendOverflow) {
596 librados::IoCtx ioctx;
597 ASSERT_EQ(0, _rados.ioctx_create(_pool_name.c_str(), ioctx));
599 std::string oid = get_temp_image_name();
602 bl.append("journal entry!");
604 librados::ObjectWriteOperation op1;
606 ASSERT_EQ(0, ioctx.operate(oid, &op1));
608 librados::ObjectWriteOperation op2;
609 client::guard_append(&op2, 1);
610 ASSERT_EQ(-EOVERFLOW, ioctx.operate(oid, &op2));