Fix some bugs when testing opensds ansible
[stor4nfv.git] / src / ceph / src / test / cls_lock / test_cls_lock.cc
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
23 #include "test/librados/test.h"
24 #include "gtest/gtest.h"
25
26 using namespace librados;
27
28 #include "cls/lock/cls_lock_client.h"
29 #include "cls/lock/cls_lock_ops.h"
30
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 {
36   ClsLockType lock_type = LOCK_NONE;
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
66 TEST(ClsLock, TestMultiLocking) {
67   Rados cluster;
68   std::string pool_name = get_temp_pool_name();
69   ASSERT_EQ("", create_one_pool_pp(pool_name, cluster));
70   IoCtx ioctx;
71   cluster.ioctx_create(pool_name.c_str(), ioctx);
72   ClsLockType lock_type_shared = LOCK_SHARED;
73   ClsLockType lock_type_exclusive = LOCK_EXCLUSIVE;
74
75
76   Rados cluster2;
77   IoCtx ioctx2;
78   ASSERT_EQ("", connect_cluster_pp(cluster2));
79   cluster2.ioctx_create(pool_name.c_str(), ioctx2);
80
81   string oid = "foo";
82   bufferlist bl;
83   string lock_name = "mylock";
84
85   ASSERT_EQ(0, ioctx.write(oid, bl, bl.length(), 0));
86
87   Lock l(lock_name);
88
89   /* test lock object */
90
91   ASSERT_EQ(0, l.lock_exclusive(&ioctx, oid));
92
93   /* test exclusive lock */
94   ASSERT_EQ(-EEXIST, l.lock_exclusive(&ioctx, oid));
95
96   /* test idempotency */
97   l.set_renew(true);
98   ASSERT_EQ(0, l.lock_exclusive(&ioctx, oid));
99
100   l.set_renew(false);
101
102   /* test second client */
103   Lock l2(lock_name);
104   ASSERT_EQ(-EBUSY, l2.lock_exclusive(&ioctx2, oid));
105   ASSERT_EQ(-EBUSY, l2.lock_shared(&ioctx2, oid));
106
107   list<string> locks;
108   ASSERT_EQ(0, list_locks(&ioctx, oid, &locks));
109
110   ASSERT_EQ(1, (int)locks.size());
111   list<string>::iterator iter = locks.begin();
112   map<locker_id_t, locker_info_t> lockers;
113   lock_info(&ioctx, oid, *iter, lockers, &lock_type_exclusive, NULL);
114
115   ASSERT_EQ(1, (int)lockers.size());
116
117   /* test unlock */
118   ASSERT_EQ(0, l.unlock(&ioctx, oid));
119   locks.clear();
120   ASSERT_EQ(0, list_locks(&ioctx, oid, &locks));
121
122   /* test shared lock */
123   ASSERT_EQ(0, l2.lock_shared(&ioctx2, oid));
124   ASSERT_EQ(0, l.lock_shared(&ioctx, oid));
125
126   locks.clear();
127   ASSERT_EQ(0, list_locks(&ioctx, oid, &locks));
128   ASSERT_EQ(1, (int)locks.size());
129   iter = locks.begin();
130   lock_info(&ioctx, oid, *iter, lockers, &lock_type_shared, NULL);
131   ASSERT_EQ(2, (int)lockers.size());
132
133   /* test break locks */
134   entity_name_t name = entity_name_t::CLIENT(cluster.get_instance_id());
135   entity_name_t name2 = entity_name_t::CLIENT(cluster2.get_instance_id());
136
137   l2.break_lock(&ioctx2, oid, name);
138   lock_info(&ioctx, oid, *iter, lockers);
139   ASSERT_EQ(1, (int)lockers.size());
140   map<locker_id_t, locker_info_t>::iterator liter = lockers.begin();
141   const locker_id_t& id = liter->first;
142   ASSERT_EQ(name2, id.locker);
143
144   /* test lock tag */
145   Lock l_tag(lock_name);
146   l_tag.set_tag("non-default tag");
147   ASSERT_EQ(-EBUSY, l_tag.lock_shared(&ioctx, oid));
148
149
150   /* test modify description */
151   string description = "new description";
152   l.set_description(description);
153   ASSERT_EQ(0, l.lock_shared(&ioctx, oid));
154
155   ASSERT_EQ(0, destroy_one_pool_pp(pool_name, cluster));
156 }
157
158 TEST(ClsLock, TestMeta) {
159   Rados cluster;
160   std::string pool_name = get_temp_pool_name();
161   ASSERT_EQ("", create_one_pool_pp(pool_name, cluster));
162   IoCtx ioctx;
163   cluster.ioctx_create(pool_name.c_str(), ioctx);
164
165
166   Rados cluster2;
167   IoCtx ioctx2;
168   ASSERT_EQ("", connect_cluster_pp(cluster2));
169   cluster2.ioctx_create(pool_name.c_str(), ioctx2);
170
171   string oid = "foo";
172   bufferlist bl;
173   string lock_name = "mylock";
174
175   ASSERT_EQ(0, ioctx.write(oid, bl, bl.length(), 0));
176
177   Lock l(lock_name);
178   ASSERT_EQ(0, l.lock_shared(&ioctx, oid));
179
180   /* test lock tag */
181   Lock l_tag(lock_name);
182   l_tag.set_tag("non-default tag");
183   ASSERT_EQ(-EBUSY, l_tag.lock_shared(&ioctx2, oid));
184
185
186   ASSERT_EQ(0, l.unlock(&ioctx, oid));
187
188   /* test description */
189   Lock l2(lock_name);
190   string description = "new description";
191   l2.set_description(description);
192   ASSERT_EQ(0, l2.lock_shared(&ioctx2, oid));
193
194   map<locker_id_t, locker_info_t> lockers;
195   lock_info(&ioctx, oid, lock_name, lockers, NULL, NULL);
196   ASSERT_EQ(1, (int)lockers.size());
197
198   map<locker_id_t, locker_info_t>::iterator iter = lockers.begin();
199   locker_info_t locker = iter->second;
200   ASSERT_EQ("new description", locker.description);
201
202   ASSERT_EQ(0, l2.unlock(&ioctx2, oid));
203
204   /* check new tag */
205   string new_tag = "new_tag";
206   l.set_tag(new_tag);
207   l.set_renew(true);
208   ASSERT_EQ(0, l.lock_exclusive(&ioctx, oid));
209   lock_info(&ioctx, oid, lock_name, lockers, NULL, &new_tag);
210   ASSERT_EQ(1, (int)lockers.size());
211   l.set_tag("");
212   ASSERT_EQ(-EBUSY, l.lock_exclusive(&ioctx, oid));
213   l.set_tag(new_tag);
214   ASSERT_EQ(0, l.lock_exclusive(&ioctx, oid));
215
216   ASSERT_EQ(0, destroy_one_pool_pp(pool_name, cluster));
217 }
218
219 TEST(ClsLock, TestCookie) {
220   Rados cluster;
221   std::string pool_name = get_temp_pool_name();
222   ASSERT_EQ("", create_one_pool_pp(pool_name, cluster));
223   IoCtx ioctx;
224   cluster.ioctx_create(pool_name.c_str(), ioctx);
225
226   string oid = "foo";
227   string lock_name = "mylock";
228   Lock l(lock_name);
229
230   ASSERT_EQ(0, l.lock_exclusive(&ioctx, oid));
231
232   /* new cookie */
233   string cookie = "new cookie";
234   l.set_cookie(cookie);
235   ASSERT_EQ(-EBUSY, l.lock_exclusive(&ioctx, oid));
236   ASSERT_EQ(-ENOENT, l.unlock(&ioctx, oid));
237   l.set_cookie("");
238   ASSERT_EQ(0, l.unlock(&ioctx, oid));
239
240   map<locker_id_t, locker_info_t> lockers;
241   lock_info(&ioctx, oid, lock_name, lockers);
242   ASSERT_EQ(0, (int)lockers.size());
243
244   l.set_cookie(cookie);
245   ASSERT_EQ(0, l.lock_shared(&ioctx, oid));
246   l.set_cookie("");
247   ASSERT_EQ(0, l.lock_shared(&ioctx, oid));
248
249   lock_info(&ioctx, oid, lock_name, lockers);
250   ASSERT_EQ(2, (int)lockers.size());
251
252   ASSERT_EQ(0, destroy_one_pool_pp(pool_name, cluster));
253 }
254
255 TEST(ClsLock, TestMultipleLocks) {
256   Rados cluster;
257   std::string pool_name = get_temp_pool_name();
258   ASSERT_EQ("", create_one_pool_pp(pool_name, cluster));
259   IoCtx ioctx;
260   cluster.ioctx_create(pool_name.c_str(), ioctx);
261
262   string oid = "foo";
263   Lock l("lock1");
264   ASSERT_EQ(0, l.lock_exclusive(&ioctx, oid));
265
266   Lock l2("lock2");
267   ASSERT_EQ(0, l2.lock_exclusive(&ioctx, oid));
268
269   list<string> locks;
270   ASSERT_EQ(0, list_locks(&ioctx, oid, &locks));
271
272   ASSERT_EQ(2, (int)locks.size());
273
274   ASSERT_EQ(0, destroy_one_pool_pp(pool_name, cluster));
275 }
276
277 TEST(ClsLock, TestLockDuration) {
278   Rados cluster;
279   std::string pool_name = get_temp_pool_name();
280   ASSERT_EQ("", create_one_pool_pp(pool_name, cluster));
281   IoCtx ioctx;
282   cluster.ioctx_create(pool_name.c_str(), ioctx);
283
284   string oid = "foo";
285   Lock l("lock");
286   utime_t dur(5, 0);
287   l.set_duration(dur);
288   utime_t start = ceph_clock_now();
289   ASSERT_EQ(0, l.lock_exclusive(&ioctx, oid));
290   int r = l.lock_exclusive(&ioctx, oid);
291   if (r == 0) {
292     // it's possible to get success if we were just really slow...
293     ASSERT_TRUE(ceph_clock_now() > start + dur);
294   } else {
295     ASSERT_EQ(-EEXIST, r);
296   }
297
298   sleep(dur.sec());
299   ASSERT_EQ(0, l.lock_exclusive(&ioctx, oid));
300
301   ASSERT_EQ(0, destroy_one_pool_pp(pool_name, cluster));
302 }
303
304 TEST(ClsLock, TestAssertLocked) {
305   Rados cluster;
306   std::string pool_name = get_temp_pool_name();
307   ASSERT_EQ("", create_one_pool_pp(pool_name, cluster));
308   IoCtx ioctx;
309   cluster.ioctx_create(pool_name.c_str(), ioctx);
310
311   string oid = "foo";
312   Lock l("lock1");
313   ASSERT_EQ(0, l.lock_exclusive(&ioctx, oid));
314
315   librados::ObjectWriteOperation op1;
316   l.assert_locked_exclusive(&op1);
317   ASSERT_EQ(0, ioctx.operate(oid, &op1));
318
319   librados::ObjectWriteOperation op2;
320   l.assert_locked_shared(&op2);
321   ASSERT_EQ(-EBUSY, ioctx.operate(oid, &op2));
322
323   l.set_tag("tag");
324   librados::ObjectWriteOperation op3;
325   l.assert_locked_exclusive(&op3);
326   ASSERT_EQ(-EBUSY, ioctx.operate(oid, &op3));
327   l.set_tag("");
328
329   l.set_cookie("cookie");
330   librados::ObjectWriteOperation op4;
331   l.assert_locked_exclusive(&op4);
332   ASSERT_EQ(-EBUSY, ioctx.operate(oid, &op4));
333   l.set_cookie("");
334
335   ASSERT_EQ(0, l.unlock(&ioctx, oid));
336
337   librados::ObjectWriteOperation op5;
338   l.assert_locked_exclusive(&op5);
339   ASSERT_EQ(-EBUSY, ioctx.operate(oid, &op5));
340
341   ASSERT_EQ(0, destroy_one_pool_pp(pool_name, cluster));
342 }
343
344 TEST(ClsLock, TestSetCookie) {
345   Rados cluster;
346   std::string pool_name = get_temp_pool_name();
347   ASSERT_EQ("", create_one_pool_pp(pool_name, cluster));
348   IoCtx ioctx;
349   cluster.ioctx_create(pool_name.c_str(), ioctx);
350
351   string oid = "foo";
352   string name = "name";
353   string tag = "tag";
354   string cookie = "cookie";
355   string new_cookie = "new cookie";
356   librados::ObjectWriteOperation op1;
357   set_cookie(&op1, name, LOCK_SHARED, cookie, tag, new_cookie);
358   ASSERT_EQ(-ENOENT, ioctx.operate(oid, &op1));
359
360   librados::ObjectWriteOperation op2;
361   lock(&op2, name, LOCK_SHARED, cookie, tag, "", utime_t{}, 0);
362   ASSERT_EQ(0, ioctx.operate(oid, &op2));
363
364   librados::ObjectWriteOperation op3;
365   lock(&op3, name, LOCK_SHARED, "cookie 2", tag, "", utime_t{}, 0);
366   ASSERT_EQ(0, ioctx.operate(oid, &op3));
367
368   librados::ObjectWriteOperation op4;
369   set_cookie(&op4, name, LOCK_SHARED, cookie, tag, cookie);
370   ASSERT_EQ(-EBUSY, ioctx.operate(oid, &op4));
371
372   librados::ObjectWriteOperation op5;
373   set_cookie(&op5, name, LOCK_SHARED, cookie, "wrong tag", new_cookie);
374   ASSERT_EQ(-EBUSY, ioctx.operate(oid, &op5));
375
376   librados::ObjectWriteOperation op6;
377   set_cookie(&op6, name, LOCK_SHARED, "wrong cookie", tag, new_cookie);
378   ASSERT_EQ(-EBUSY, ioctx.operate(oid, &op6));
379
380   librados::ObjectWriteOperation op7;
381   set_cookie(&op7, name, LOCK_EXCLUSIVE, cookie, tag, new_cookie);
382   ASSERT_EQ(-EBUSY, ioctx.operate(oid, &op7));
383
384   librados::ObjectWriteOperation op8;
385   set_cookie(&op8, name, LOCK_SHARED, cookie, tag, "cookie 2");
386   ASSERT_EQ(-EBUSY, ioctx.operate(oid, &op8));
387
388   librados::ObjectWriteOperation op9;
389   set_cookie(&op9, name, LOCK_SHARED, cookie, tag, new_cookie);
390   ASSERT_EQ(0, ioctx.operate(oid, &op9));
391
392   ASSERT_EQ(0, destroy_one_pool_pp(pool_name, cluster));
393 }