]>
Commit | Line | Data |
---|---|---|
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 |
29 | using namespace std; |
30 | using namespace librados; | |
7c673cae FG |
31 | using namespace rados::cls::lock; |
32 | ||
33 | void 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 | ||
61 | void 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 |
66 | bool 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 |
83 | TEST(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 | ||
178 | TEST(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 | ||
239 | TEST(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 | ||
275 | TEST(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 | ||
297 | TEST(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 | ||
324 | TEST(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 | ||
364 | TEST(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 | |
415 | TEST(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 | ||
481 | TEST(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 | ||
528 | TEST(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 | ||
560 | TEST(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 | } |