]> git.proxmox.com Git - ceph.git/blame - ceph/src/test/cls_lock/test_cls_lock.cc
update ceph source to reef 18.1.2
[ceph.git] / ceph / src / test / cls_lock / test_cls_lock.cc
CommitLineData
7c673cae
FG
1// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
2// vim: ts=8 sw=2 smarttab
3/*
4 * Ceph - scalable distributed file system
5 *
6 * Copyright (C) 2004-2006 Sage Weil <sage@newdream.net>
7 *
8 * This is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Lesser General Public
10 * License version 2.1, as published by the Free Software
11 * Foundation. See file COPYING.
12 *
13 */
14
15#include <iostream>
16#include <errno.h>
17
18#include "include/types.h"
19#include "common/Clock.h"
20#include "msg/msg_types.h"
21#include "include/rados/librados.hpp"
22
11fdf7f2 23#include "test/librados/test_cxx.h"
7c673cae
FG
24#include "gtest/gtest.h"
25
7c673cae
FG
26#include "cls/lock/cls_lock_client.h"
27#include "cls/lock/cls_lock_ops.h"
28
20effc67
TL
29using namespace std;
30using namespace librados;
7c673cae
FG
31using namespace rados::cls::lock;
32
33void lock_info(IoCtx *ioctx, string& oid, string& name, map<locker_id_t, locker_info_t>& lockers,
34 ClsLockType *assert_type, string *assert_tag)
35{
f67539c2 36 ClsLockType lock_type = ClsLockType::NONE;
7c673cae
FG
37 string tag;
38 lockers.clear();
39 ASSERT_EQ(0, get_lock_info(ioctx, oid, name, &lockers, &lock_type, &tag));
40 cout << "lock: " << name << std::endl;
41 cout << " lock_type: " << cls_lock_type_str(lock_type) << std::endl;
42 cout << " tag: " << tag << std::endl;
43 cout << " lockers:" << std::endl;
44
45 if (assert_type) {
46 ASSERT_EQ(*assert_type, lock_type);
47 }
48
49 if (assert_tag) {
50 ASSERT_EQ(*assert_tag, tag);
51 }
52
53 map<locker_id_t, locker_info_t>::iterator liter;
54 for (liter = lockers.begin(); liter != lockers.end(); ++liter) {
55 const locker_id_t& locker = liter->first;
56 cout << " " << locker.locker << " expiration=" << liter->second.expiration
57 << " addr=" << liter->second.addr << " cookie=" << locker.cookie << std::endl;
58 }
59}
60
61void lock_info(IoCtx *ioctx, string& oid, string& name, map<locker_id_t, locker_info_t>& lockers)
62{
63 lock_info(ioctx, oid, name, lockers, NULL, NULL);
64}
65
1e59de90
TL
66bool lock_expired(IoCtx *ioctx, string& oid, string& name)
67{
68 ClsLockType lock_type = ClsLockType::NONE;
69 string tag;
70 map<locker_id_t, locker_info_t> lockers;
71 if (0 == get_lock_info(ioctx, oid, name, &lockers, &lock_type, &tag))
72 return false;
73 utime_t now = ceph_clock_now();
74 map<locker_id_t, locker_info_t>::iterator liter;
75 for (liter = lockers.begin(); liter != lockers.end(); ++liter) {
76 if (liter->second.expiration > now)
77 return false;
78 }
79
80 return true;
81}
82
7c673cae
FG
83TEST(ClsLock, TestMultiLocking) {
84 Rados cluster;
85 std::string pool_name = get_temp_pool_name();
86 ASSERT_EQ("", create_one_pool_pp(pool_name, cluster));
87 IoCtx ioctx;
88 cluster.ioctx_create(pool_name.c_str(), ioctx);
f67539c2
TL
89 ClsLockType lock_type_shared = ClsLockType::SHARED;
90 ClsLockType lock_type_exclusive = ClsLockType::EXCLUSIVE;
7c673cae
FG
91
92
93 Rados cluster2;
94 IoCtx ioctx2;
95 ASSERT_EQ("", connect_cluster_pp(cluster2));
96 cluster2.ioctx_create(pool_name.c_str(), ioctx2);
97
98 string oid = "foo";
99 bufferlist bl;
100 string lock_name = "mylock";
101
102 ASSERT_EQ(0, ioctx.write(oid, bl, bl.length(), 0));
103
104 Lock l(lock_name);
11fdf7f2
TL
105 // we set the duration, so the log output contains a locker with a
106 // non-zero expiration time
107 l.set_duration(utime_t(120, 0));
7c673cae
FG
108
109 /* test lock object */
110
111 ASSERT_EQ(0, l.lock_exclusive(&ioctx, oid));
112
113 /* test exclusive lock */
114 ASSERT_EQ(-EEXIST, l.lock_exclusive(&ioctx, oid));
115
116 /* test idempotency */
f64942e4 117 l.set_may_renew(true);
7c673cae
FG
118 ASSERT_EQ(0, l.lock_exclusive(&ioctx, oid));
119
f64942e4 120 l.set_may_renew(false);
7c673cae
FG
121
122 /* test second client */
123 Lock l2(lock_name);
124 ASSERT_EQ(-EBUSY, l2.lock_exclusive(&ioctx2, oid));
125 ASSERT_EQ(-EBUSY, l2.lock_shared(&ioctx2, oid));
126
127 list<string> locks;
128 ASSERT_EQ(0, list_locks(&ioctx, oid, &locks));
129
130 ASSERT_EQ(1, (int)locks.size());
131 list<string>::iterator iter = locks.begin();
132 map<locker_id_t, locker_info_t> lockers;
133 lock_info(&ioctx, oid, *iter, lockers, &lock_type_exclusive, NULL);
134
135 ASSERT_EQ(1, (int)lockers.size());
136
137 /* test unlock */
138 ASSERT_EQ(0, l.unlock(&ioctx, oid));
139 locks.clear();
140 ASSERT_EQ(0, list_locks(&ioctx, oid, &locks));
141
142 /* test shared lock */
143 ASSERT_EQ(0, l2.lock_shared(&ioctx2, oid));
144 ASSERT_EQ(0, l.lock_shared(&ioctx, oid));
145
146 locks.clear();
147 ASSERT_EQ(0, list_locks(&ioctx, oid, &locks));
148 ASSERT_EQ(1, (int)locks.size());
149 iter = locks.begin();
150 lock_info(&ioctx, oid, *iter, lockers, &lock_type_shared, NULL);
151 ASSERT_EQ(2, (int)lockers.size());
152
153 /* test break locks */
154 entity_name_t name = entity_name_t::CLIENT(cluster.get_instance_id());
155 entity_name_t name2 = entity_name_t::CLIENT(cluster2.get_instance_id());
156
157 l2.break_lock(&ioctx2, oid, name);
158 lock_info(&ioctx, oid, *iter, lockers);
159 ASSERT_EQ(1, (int)lockers.size());
160 map<locker_id_t, locker_info_t>::iterator liter = lockers.begin();
161 const locker_id_t& id = liter->first;
162 ASSERT_EQ(name2, id.locker);
163
164 /* test lock tag */
165 Lock l_tag(lock_name);
166 l_tag.set_tag("non-default tag");
167 ASSERT_EQ(-EBUSY, l_tag.lock_shared(&ioctx, oid));
168
169
170 /* test modify description */
171 string description = "new description";
172 l.set_description(description);
173 ASSERT_EQ(0, l.lock_shared(&ioctx, oid));
174
175 ASSERT_EQ(0, destroy_one_pool_pp(pool_name, cluster));
176}
177
178TEST(ClsLock, TestMeta) {
179 Rados cluster;
180 std::string pool_name = get_temp_pool_name();
181 ASSERT_EQ("", create_one_pool_pp(pool_name, cluster));
182 IoCtx ioctx;
183 cluster.ioctx_create(pool_name.c_str(), ioctx);
184
185
186 Rados cluster2;
187 IoCtx ioctx2;
188 ASSERT_EQ("", connect_cluster_pp(cluster2));
189 cluster2.ioctx_create(pool_name.c_str(), ioctx2);
190
191 string oid = "foo";
192 bufferlist bl;
193 string lock_name = "mylock";
194
195 ASSERT_EQ(0, ioctx.write(oid, bl, bl.length(), 0));
196
197 Lock l(lock_name);
198 ASSERT_EQ(0, l.lock_shared(&ioctx, oid));
199
200 /* test lock tag */
201 Lock l_tag(lock_name);
202 l_tag.set_tag("non-default tag");
203 ASSERT_EQ(-EBUSY, l_tag.lock_shared(&ioctx2, oid));
204
205
206 ASSERT_EQ(0, l.unlock(&ioctx, oid));
207
208 /* test description */
209 Lock l2(lock_name);
210 string description = "new description";
211 l2.set_description(description);
212 ASSERT_EQ(0, l2.lock_shared(&ioctx2, oid));
213
214 map<locker_id_t, locker_info_t> lockers;
215 lock_info(&ioctx, oid, lock_name, lockers, NULL, NULL);
216 ASSERT_EQ(1, (int)lockers.size());
217
218 map<locker_id_t, locker_info_t>::iterator iter = lockers.begin();
219 locker_info_t locker = iter->second;
220 ASSERT_EQ("new description", locker.description);
221
222 ASSERT_EQ(0, l2.unlock(&ioctx2, oid));
223
224 /* check new tag */
225 string new_tag = "new_tag";
226 l.set_tag(new_tag);
f64942e4 227 l.set_may_renew(true);
7c673cae
FG
228 ASSERT_EQ(0, l.lock_exclusive(&ioctx, oid));
229 lock_info(&ioctx, oid, lock_name, lockers, NULL, &new_tag);
230 ASSERT_EQ(1, (int)lockers.size());
231 l.set_tag("");
232 ASSERT_EQ(-EBUSY, l.lock_exclusive(&ioctx, oid));
233 l.set_tag(new_tag);
234 ASSERT_EQ(0, l.lock_exclusive(&ioctx, oid));
235
236 ASSERT_EQ(0, destroy_one_pool_pp(pool_name, cluster));
237}
238
239TEST(ClsLock, TestCookie) {
240 Rados cluster;
241 std::string pool_name = get_temp_pool_name();
242 ASSERT_EQ("", create_one_pool_pp(pool_name, cluster));
243 IoCtx ioctx;
244 cluster.ioctx_create(pool_name.c_str(), ioctx);
245
246 string oid = "foo";
247 string lock_name = "mylock";
248 Lock l(lock_name);
249
250 ASSERT_EQ(0, l.lock_exclusive(&ioctx, oid));
251
252 /* new cookie */
253 string cookie = "new cookie";
254 l.set_cookie(cookie);
255 ASSERT_EQ(-EBUSY, l.lock_exclusive(&ioctx, oid));
256 ASSERT_EQ(-ENOENT, l.unlock(&ioctx, oid));
257 l.set_cookie("");
258 ASSERT_EQ(0, l.unlock(&ioctx, oid));
259
260 map<locker_id_t, locker_info_t> lockers;
261 lock_info(&ioctx, oid, lock_name, lockers);
262 ASSERT_EQ(0, (int)lockers.size());
263
264 l.set_cookie(cookie);
265 ASSERT_EQ(0, l.lock_shared(&ioctx, oid));
266 l.set_cookie("");
267 ASSERT_EQ(0, l.lock_shared(&ioctx, oid));
268
269 lock_info(&ioctx, oid, lock_name, lockers);
270 ASSERT_EQ(2, (int)lockers.size());
271
272 ASSERT_EQ(0, destroy_one_pool_pp(pool_name, cluster));
273}
274
275TEST(ClsLock, TestMultipleLocks) {
276 Rados cluster;
277 std::string pool_name = get_temp_pool_name();
278 ASSERT_EQ("", create_one_pool_pp(pool_name, cluster));
279 IoCtx ioctx;
280 cluster.ioctx_create(pool_name.c_str(), ioctx);
281
282 string oid = "foo";
283 Lock l("lock1");
284 ASSERT_EQ(0, l.lock_exclusive(&ioctx, oid));
285
286 Lock l2("lock2");
287 ASSERT_EQ(0, l2.lock_exclusive(&ioctx, oid));
288
289 list<string> locks;
290 ASSERT_EQ(0, list_locks(&ioctx, oid, &locks));
291
292 ASSERT_EQ(2, (int)locks.size());
293
294 ASSERT_EQ(0, destroy_one_pool_pp(pool_name, cluster));
295}
296
297TEST(ClsLock, TestLockDuration) {
298 Rados cluster;
299 std::string pool_name = get_temp_pool_name();
300 ASSERT_EQ("", create_one_pool_pp(pool_name, cluster));
301 IoCtx ioctx;
302 cluster.ioctx_create(pool_name.c_str(), ioctx);
303
304 string oid = "foo";
305 Lock l("lock");
306 utime_t dur(5, 0);
307 l.set_duration(dur);
308 utime_t start = ceph_clock_now();
309 ASSERT_EQ(0, l.lock_exclusive(&ioctx, oid));
310 int r = l.lock_exclusive(&ioctx, oid);
311 if (r == 0) {
312 // it's possible to get success if we were just really slow...
313 ASSERT_TRUE(ceph_clock_now() > start + dur);
314 } else {
315 ASSERT_EQ(-EEXIST, r);
316 }
317
318 sleep(dur.sec());
319 ASSERT_EQ(0, l.lock_exclusive(&ioctx, oid));
320
321 ASSERT_EQ(0, destroy_one_pool_pp(pool_name, cluster));
322}
323
324TEST(ClsLock, TestAssertLocked) {
325 Rados cluster;
326 std::string pool_name = get_temp_pool_name();
327 ASSERT_EQ("", create_one_pool_pp(pool_name, cluster));
328 IoCtx ioctx;
329 cluster.ioctx_create(pool_name.c_str(), ioctx);
330
331 string oid = "foo";
332 Lock l("lock1");
333 ASSERT_EQ(0, l.lock_exclusive(&ioctx, oid));
334
335 librados::ObjectWriteOperation op1;
336 l.assert_locked_exclusive(&op1);
337 ASSERT_EQ(0, ioctx.operate(oid, &op1));
338
339 librados::ObjectWriteOperation op2;
340 l.assert_locked_shared(&op2);
341 ASSERT_EQ(-EBUSY, ioctx.operate(oid, &op2));
342
343 l.set_tag("tag");
344 librados::ObjectWriteOperation op3;
345 l.assert_locked_exclusive(&op3);
346 ASSERT_EQ(-EBUSY, ioctx.operate(oid, &op3));
347 l.set_tag("");
348
349 l.set_cookie("cookie");
350 librados::ObjectWriteOperation op4;
351 l.assert_locked_exclusive(&op4);
352 ASSERT_EQ(-EBUSY, ioctx.operate(oid, &op4));
353 l.set_cookie("");
354
355 ASSERT_EQ(0, l.unlock(&ioctx, oid));
356
357 librados::ObjectWriteOperation op5;
358 l.assert_locked_exclusive(&op5);
359 ASSERT_EQ(-EBUSY, ioctx.operate(oid, &op5));
360
361 ASSERT_EQ(0, destroy_one_pool_pp(pool_name, cluster));
362}
363
364TEST(ClsLock, TestSetCookie) {
365 Rados cluster;
366 std::string pool_name = get_temp_pool_name();
367 ASSERT_EQ("", create_one_pool_pp(pool_name, cluster));
368 IoCtx ioctx;
369 cluster.ioctx_create(pool_name.c_str(), ioctx);
370
371 string oid = "foo";
372 string name = "name";
373 string tag = "tag";
374 string cookie = "cookie";
375 string new_cookie = "new cookie";
376 librados::ObjectWriteOperation op1;
f67539c2 377 set_cookie(&op1, name, ClsLockType::SHARED, cookie, tag, new_cookie);
7c673cae
FG
378 ASSERT_EQ(-ENOENT, ioctx.operate(oid, &op1));
379
380 librados::ObjectWriteOperation op2;
f67539c2 381 lock(&op2, name, ClsLockType::SHARED, cookie, tag, "", utime_t{}, 0);
7c673cae
FG
382 ASSERT_EQ(0, ioctx.operate(oid, &op2));
383
384 librados::ObjectWriteOperation op3;
f67539c2 385 lock(&op3, name, ClsLockType::SHARED, "cookie 2", tag, "", utime_t{}, 0);
7c673cae
FG
386 ASSERT_EQ(0, ioctx.operate(oid, &op3));
387
388 librados::ObjectWriteOperation op4;
f67539c2 389 set_cookie(&op4, name, ClsLockType::SHARED, cookie, tag, cookie);
7c673cae
FG
390 ASSERT_EQ(-EBUSY, ioctx.operate(oid, &op4));
391
392 librados::ObjectWriteOperation op5;
f67539c2 393 set_cookie(&op5, name, ClsLockType::SHARED, cookie, "wrong tag", new_cookie);
7c673cae
FG
394 ASSERT_EQ(-EBUSY, ioctx.operate(oid, &op5));
395
396 librados::ObjectWriteOperation op6;
f67539c2 397 set_cookie(&op6, name, ClsLockType::SHARED, "wrong cookie", tag, new_cookie);
7c673cae
FG
398 ASSERT_EQ(-EBUSY, ioctx.operate(oid, &op6));
399
400 librados::ObjectWriteOperation op7;
f67539c2 401 set_cookie(&op7, name, ClsLockType::EXCLUSIVE, cookie, tag, new_cookie);
7c673cae
FG
402 ASSERT_EQ(-EBUSY, ioctx.operate(oid, &op7));
403
404 librados::ObjectWriteOperation op8;
f67539c2 405 set_cookie(&op8, name, ClsLockType::SHARED, cookie, tag, "cookie 2");
7c673cae
FG
406 ASSERT_EQ(-EBUSY, ioctx.operate(oid, &op8));
407
408 librados::ObjectWriteOperation op9;
f67539c2 409 set_cookie(&op9, name, ClsLockType::SHARED, cookie, tag, new_cookie);
7c673cae
FG
410 ASSERT_EQ(0, ioctx.operate(oid, &op9));
411
412 ASSERT_EQ(0, destroy_one_pool_pp(pool_name, cluster));
413}
f64942e4
AA
414
415TEST(ClsLock, TestRenew) {
416 Rados cluster;
417 std::string pool_name = get_temp_pool_name();
418 ASSERT_EQ("", create_one_pool_pp(pool_name, cluster));
419 IoCtx ioctx;
420 cluster.ioctx_create(pool_name.c_str(), ioctx);
421
422 bufferlist bl;
423
424 string oid1 = "foo1";
425 string lock_name1 = "mylock1";
426
427 ASSERT_EQ(0, ioctx.write(oid1, bl, bl.length(), 0));
428
429 Lock l1(lock_name1);
430 utime_t lock_duration1(5, 0);
431 l1.set_duration(lock_duration1);
432
433 ASSERT_EQ(0, l1.lock_exclusive(&ioctx, oid1));
434 l1.set_may_renew(true);
435 sleep(2);
436 ASSERT_EQ(0, l1.lock_exclusive(&ioctx, oid1));
437 sleep(7);
438 ASSERT_EQ(0, l1.lock_exclusive(&ioctx, oid1)) <<
439 "when a cls_lock is set to may_renew, a relock after expiration "
440 "should still work";
441 ASSERT_EQ(0, l1.unlock(&ioctx, oid1));
442
443 // ***********************************************
444
445 string oid2 = "foo2";
446 string lock_name2 = "mylock2";
447
448 ASSERT_EQ(0, ioctx.write(oid2, bl, bl.length(), 0));
449
450 Lock l2(lock_name2);
451 utime_t lock_duration2(5, 0);
452 l2.set_duration(lock_duration2);
453
454 ASSERT_EQ(0, l2.lock_exclusive(&ioctx, oid2));
455 l2.set_must_renew(true);
456 sleep(2);
457 ASSERT_EQ(0, l2.lock_exclusive(&ioctx, oid2));
458 sleep(7);
459 ASSERT_EQ(-ENOENT, l2.lock_exclusive(&ioctx, oid2)) <<
460 "when a cls_lock is set to must_renew, a relock after expiration "
461 "should fail";
462 ASSERT_EQ(-ENOENT, l2.unlock(&ioctx, oid2));
463
464 // ***********************************************
465
466 string oid3 = "foo3";
467 string lock_name3 = "mylock3";
468
469 ASSERT_EQ(0, ioctx.write(oid3, bl, bl.length(), 0));
470
471 Lock l3(lock_name3);
472 l3.set_duration(utime_t(5, 0));
473 l3.set_must_renew(true);
474
475 ASSERT_EQ(-ENOENT, l3.lock_exclusive(&ioctx, oid3)) <<
476 "unable to create a lock with must_renew";
477
478 ASSERT_EQ(0, destroy_one_pool_pp(pool_name, cluster));
479}
480
481TEST(ClsLock, TestExclusiveEphemeralBasic) {
482 Rados cluster;
483 std::string pool_name = get_temp_pool_name();
484 ASSERT_EQ("", create_one_pool_pp(pool_name, cluster));
485 IoCtx ioctx;
486 cluster.ioctx_create(pool_name.c_str(), ioctx);
487
488 bufferlist bl;
489
490 string oid1 = "foo1";
491 string oid2 = "foo2";
492 string lock_name1 = "mylock1";
493 string lock_name2 = "mylock2";
494
495 Lock l1(lock_name1);
496 l1.set_duration(utime_t(5, 0));
497
498 uint64_t size;
499 time_t mod_time;
500
501 l1.set_may_renew(true);
502 ASSERT_EQ(0, l1.lock_exclusive_ephemeral(&ioctx, oid1));
503 ASSERT_EQ(0, ioctx.stat(oid1, &size, &mod_time));
504 sleep(2);
1e59de90
TL
505 int r1 = l1.unlock(&ioctx, oid1);
506 EXPECT_TRUE(r1 == 0 || ((r1 == -ENOENT) && (lock_expired(&ioctx, oid1, lock_name1))))
507 << "unlock should return 0 or -ENOENT return: " << r1;
f64942e4
AA
508 ASSERT_EQ(-ENOENT, ioctx.stat(oid1, &size, &mod_time));
509
510 // ***********************************************
511
512 Lock l2(lock_name2);
513 utime_t lock_duration2(5, 0);
514 l2.set_duration(utime_t(5, 0));
515
516 ASSERT_EQ(0, l2.lock_exclusive(&ioctx, oid2));
517 ASSERT_EQ(0, ioctx.stat(oid2, &size, &mod_time));
518 sleep(2);
1e59de90
TL
519 int r2 = l2.unlock(&ioctx, oid2);
520 EXPECT_TRUE(r2 == 0 || ((r2 == -ENOENT) && (lock_expired(&ioctx, oid2, lock_name2))))
521 << "unlock should return 0 or -ENOENT return: " << r2;
f64942e4
AA
522 ASSERT_EQ(0, ioctx.stat(oid2, &size, &mod_time));
523
524 ASSERT_EQ(0, destroy_one_pool_pp(pool_name, cluster));
525}
526
527
528TEST(ClsLock, TestExclusiveEphemeralStealEphemeral) {
529 Rados cluster;
530 std::string pool_name = get_temp_pool_name();
531 ASSERT_EQ("", create_one_pool_pp(pool_name, cluster));
532 IoCtx ioctx;
533 cluster.ioctx_create(pool_name.c_str(), ioctx);
534
535 bufferlist bl;
536
537 string oid1 = "foo1";
538 string lock_name1 = "mylock1";
539
540 Lock l1(lock_name1);
541 l1.set_duration(utime_t(3, 0));
542
543 ASSERT_EQ(0, l1.lock_exclusive_ephemeral(&ioctx, oid1));
544 sleep(4);
545
546 // l1 is expired, l2 can take; l2 is also exclusive_ephemeral
547 Lock l2(lock_name1);
548 l2.set_duration(utime_t(3, 0));
549 ASSERT_EQ(0, l2.lock_exclusive_ephemeral(&ioctx, oid1));
550 sleep(1);
551 ASSERT_EQ(0, l2.unlock(&ioctx, oid1));
552
553 // l2 cannot unlock its expired lock
554 ASSERT_EQ(-ENOENT, l1.unlock(&ioctx, oid1));
555
556 ASSERT_EQ(0, destroy_one_pool_pp(pool_name, cluster));
557}
558
559
560TEST(ClsLock, TestExclusiveEphemeralStealExclusive) {
561 Rados cluster;
562 std::string pool_name = get_temp_pool_name();
563 ASSERT_EQ("", create_one_pool_pp(pool_name, cluster));
564 IoCtx ioctx;
565 cluster.ioctx_create(pool_name.c_str(), ioctx);
566
567 bufferlist bl;
568
569 string oid1 = "foo1";
570 string lock_name1 = "mylock1";
571
572 Lock l1(lock_name1);
573 l1.set_duration(utime_t(3, 0));
574
575 ASSERT_EQ(0, l1.lock_exclusive_ephemeral(&ioctx, oid1));
576 sleep(4);
577
578 // l1 is expired, l2 can take; l2 is exclusive (but not ephemeral)
579 Lock l2(lock_name1);
580 l2.set_duration(utime_t(3, 0));
581 ASSERT_EQ(0, l2.lock_exclusive(&ioctx, oid1));
582 sleep(1);
583 ASSERT_EQ(0, l2.unlock(&ioctx, oid1));
584
585 // l2 cannot unlock its expired lock
586 ASSERT_EQ(-ENOENT, l1.unlock(&ioctx, oid1));
587
588 ASSERT_EQ(0, destroy_one_pool_pp(pool_name, cluster));
589}