]> git.proxmox.com Git - ceph.git/blame - ceph/src/mds/SimpleLock.h
update ceph source to reef 18.2.1
[ceph.git] / ceph / src / mds / SimpleLock.h
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
16#ifndef CEPH_SIMPLELOCK_H
17#define CEPH_SIMPLELOCK_H
18
19#include <boost/intrusive_ptr.hpp>
20
21#include "MDSCacheObject.h"
22#include "MDSContext.h"
23
24// -- lock types --
25// see CEPH_LOCK_*
26
7c673cae
FG
27extern "C" {
28#include "locks.h"
29}
30
7c673cae
FG
31#define CAP_ANY 0
32#define CAP_LONER 1
33#define CAP_XLOCKER 2
34
9f95a23c
TL
35struct MDLockCache;
36struct MDLockCacheItem;
37struct MutationImpl;
38typedef boost::intrusive_ptr<MutationImpl> MutationRef;
7c673cae 39
9f95a23c 40struct LockType {
7c673cae
FG
41 explicit LockType(int t) : type(t) {
42 switch (type) {
43 case CEPH_LOCK_DN:
44 case CEPH_LOCK_IAUTH:
45 case CEPH_LOCK_ILINK:
46 case CEPH_LOCK_IXATTR:
47 case CEPH_LOCK_ISNAP:
48 case CEPH_LOCK_IFLOCK:
49 case CEPH_LOCK_IPOLICY:
50 sm = &sm_simplelock;
51 break;
52 case CEPH_LOCK_IDFT:
53 case CEPH_LOCK_INEST:
54 sm = &sm_scatterlock;
55 break;
56 case CEPH_LOCK_IFILE:
57 sm = &sm_filelock;
58 break;
59 case CEPH_LOCK_DVERSION:
60 case CEPH_LOCK_IVERSION:
61 sm = &sm_locallock;
62 break;
63 default:
64 sm = 0;
65 }
66 }
67
9f95a23c
TL
68 int type;
69 const sm_t *sm;
7c673cae
FG
70};
71
72
73class SimpleLock {
74public:
9f95a23c
TL
75 // waiting
76 static const uint64_t WAIT_RD = (1<<0); // to read
77 static const uint64_t WAIT_WR = (1<<1); // to write
78 static const uint64_t WAIT_XLOCK = (1<<2); // to xlock (** dup)
79 static const uint64_t WAIT_STABLE = (1<<2); // for a stable state
80 static const uint64_t WAIT_REMOTEXLOCK = (1<<3); // for a remote xlock
81 static const int WAIT_BITS = 4;
82 static const uint64_t WAIT_ALL = ((1<<WAIT_BITS)-1);
83
11fdf7f2 84 static std::string_view get_state_name(int n) {
7c673cae
FG
85 switch (n) {
86 case LOCK_UNDEF: return "UNDEF";
87 case LOCK_SYNC: return "sync";
88 case LOCK_LOCK: return "lock";
89
90 case LOCK_PREXLOCK: return "prexlock";
91 case LOCK_XLOCK: return "xlock";
92 case LOCK_XLOCKDONE: return "xlockdone";
93 case LOCK_XLOCKSNAP: return "xlocksnap";
94 case LOCK_LOCK_XLOCK: return "lock->xlock";
95
96 case LOCK_SYNC_LOCK: return "sync->lock";
97 case LOCK_LOCK_SYNC: return "lock->sync";
98 case LOCK_REMOTEXLOCK: return "remote_xlock";
99 case LOCK_EXCL: return "excl";
100 case LOCK_EXCL_SYNC: return "excl->sync";
101 case LOCK_EXCL_LOCK: return "excl->lock";
102 case LOCK_SYNC_EXCL: return "sync->excl";
103 case LOCK_LOCK_EXCL: return "lock->excl";
104
105 case LOCK_XSYN: return "xsyn";
106 case LOCK_XSYN_EXCL: return "xsyn->excl";
107 case LOCK_EXCL_XSYN: return "excl->xsyn";
108 case LOCK_XSYN_SYNC: return "xsyn->sync";
b32b8144
FG
109 case LOCK_XSYN_LOCK: return "xsyn->lock";
110 case LOCK_XSYN_MIX: return "xsyn->mix";
7c673cae
FG
111
112 case LOCK_SYNC_MIX: return "sync->mix";
113 case LOCK_SYNC_MIX2: return "sync->mix(2)";
114 case LOCK_LOCK_TSYN: return "lock->tsyn";
115
116 case LOCK_MIX_LOCK: return "mix->lock";
117 case LOCK_MIX_LOCK2: return "mix->lock(2)";
118 case LOCK_MIX: return "mix";
119 case LOCK_MIX_TSYN: return "mix->tsyn";
120
121 case LOCK_TSYN_MIX: return "tsyn->mix";
122 case LOCK_TSYN_LOCK: return "tsyn->lock";
123 case LOCK_TSYN: return "tsyn";
124
125 case LOCK_MIX_SYNC: return "mix->sync";
126 case LOCK_MIX_SYNC2: return "mix->sync(2)";
127 case LOCK_EXCL_MIX: return "excl->mix";
128 case LOCK_MIX_EXCL: return "mix->excl";
129
130 case LOCK_PRE_SCAN: return "*->scan";
131 case LOCK_SCAN: return "scan";
132
133 case LOCK_SNAP_SYNC: return "snap->sync";
134
11fdf7f2 135 default: ceph_abort(); return std::string_view();
7c673cae
FG
136 }
137 }
138
11fdf7f2
TL
139 static std::string_view get_lock_type_name(int t) {
140 switch (t) {
141 case CEPH_LOCK_DN: return "dn";
142 case CEPH_LOCK_DVERSION: return "dversion";
143 case CEPH_LOCK_IVERSION: return "iversion";
144 case CEPH_LOCK_IFILE: return "ifile";
145 case CEPH_LOCK_IAUTH: return "iauth";
146 case CEPH_LOCK_ILINK: return "ilink";
147 case CEPH_LOCK_IDFT: return "idft";
148 case CEPH_LOCK_INEST: return "inest";
149 case CEPH_LOCK_IXATTR: return "ixattr";
150 case CEPH_LOCK_ISNAP: return "isnap";
11fdf7f2
TL
151 case CEPH_LOCK_IFLOCK: return "iflock";
152 case CEPH_LOCK_IPOLICY: return "ipolicy";
9f95a23c 153 default: return "unknown";
11fdf7f2
TL
154 }
155 }
156
157 static std::string_view get_lock_action_name(int a) {
158 switch (a) {
159 case LOCK_AC_SYNC: return "sync";
160 case LOCK_AC_MIX: return "mix";
161 case LOCK_AC_LOCK: return "lock";
162 case LOCK_AC_LOCKFLUSHED: return "lockflushed";
163
164 case LOCK_AC_SYNCACK: return "syncack";
165 case LOCK_AC_MIXACK: return "mixack";
166 case LOCK_AC_LOCKACK: return "lockack";
167
168 case LOCK_AC_REQSCATTER: return "reqscatter";
169 case LOCK_AC_REQUNSCATTER: return "requnscatter";
170 case LOCK_AC_NUDGE: return "nudge";
171 case LOCK_AC_REQRDLOCK: return "reqrdlock";
172 default: return "???";
173 }
174 }
7c673cae 175
9f95a23c
TL
176 SimpleLock(MDSCacheObject *o, LockType *lt) :
177 type(lt),
178 parent(o)
179 {}
180 virtual ~SimpleLock() {}
7c673cae
FG
181
182 client_t get_excl_client() const {
183 return have_more() ? more()->excl_client : -1;
184 }
185 void set_excl_client(client_t c) {
186 if (c < 0 && !have_more())
187 return; // default is -1
188 more()->excl_client = c;
189 }
190
7c673cae
FG
191 virtual bool is_scatterlock() const {
192 return false;
193 }
194 virtual bool is_locallock() const {
195 return false;
196 }
197
198 // parent
199 MDSCacheObject *get_parent() { return parent; }
200 int get_type() const { return type->type; }
201 const sm_t* get_sm() const { return type->sm; }
202
9f95a23c
TL
203 int get_wait_shift() const;
204 int get_cap_shift() const;
205 int get_cap_mask() const;
7c673cae 206
f67539c2 207 void decode_locked_state(const ceph::buffer::list& bl) {
7c673cae
FG
208 parent->decode_lock_state(type->type, bl);
209 }
f67539c2 210 void encode_locked_state(ceph::buffer::list& bl) {
7c673cae
FG
211 parent->encode_lock_state(type->type, bl);
212 }
213 void finish_waiters(uint64_t mask, int r=0) {
214 parent->finish_waiting(mask << get_wait_shift(), r);
215 }
11fdf7f2 216 void take_waiting(uint64_t mask, MDSContext::vec& ls) {
7c673cae
FG
217 parent->take_waiting(mask << get_wait_shift(), ls);
218 }
11fdf7f2 219 void add_waiter(uint64_t mask, MDSContext *c) {
7c673cae
FG
220 parent->add_waiter((mask << get_wait_shift()) | MDSCacheObject::WAIT_ORDERED, c);
221 }
222 bool is_waiter_for(uint64_t mask) const {
223 return parent->is_waiter_for(mask << get_wait_shift());
224 }
9f95a23c
TL
225
226 bool is_cached() const {
227 return state_flags & CACHED;
228 }
229 void add_cache(MDLockCacheItem& item);
230 void remove_cache(MDLockCacheItem& item);
1911f103 231 std::vector<MDLockCache*> get_active_caches();
7c673cae
FG
232
233 // state
234 int get_state() const { return state; }
235 int set_state(int s) {
236 state = s;
237 //assert(!is_stable() || gather_set.size() == 0); // gather should be empty in stable states.
238 return s;
239 }
11fdf7f2
TL
240 void set_state_rejoin(int s, MDSContext::vec& waiters, bool survivor) {
241 ceph_assert(!get_parent()->is_auth());
b32b8144
FG
242
243 // If lock in the replica object was not in SYNC state when auth mds of the object failed.
244 // Auth mds of the object may take xlock on the lock and change the object when replaying
245 // unsafe requests.
246 if (!survivor || state != LOCK_SYNC)
247 mark_need_recover();
248
249 state = s;
250
7c673cae
FG
251 if (is_stable())
252 take_waiting(SimpleLock::WAIT_ALL, waiters);
253 }
254
255 bool is_stable() const {
256 return get_sm()->states[state].next == 0;
257 }
258 bool is_unstable_and_locked() const {
2a845540
TL
259 return (!is_stable() && is_locked());
260 }
261 bool is_locked() const {
7c673cae
FG
262 return is_rdlocked() || is_wrlocked() || is_xlocked();
263 }
264 int get_next_state() {
265 return get_sm()->states[state].next;
266 }
267
7c673cae
FG
268 bool is_sync_and_unlocked() const {
269 return
270 get_state() == LOCK_SYNC &&
271 !is_rdlocked() &&
272 !is_leased() &&
273 !is_wrlocked() &&
274 !is_xlocked();
275 }
276
7c673cae
FG
277 /*
278 bool fw_rdlock_to_auth() {
279 return get_sm()->states[state].can_rdlock == FW;
280 }
281 */
282 bool req_rdlock_from_auth() {
283 return get_sm()->states[state].can_rdlock == REQ;
284 }
285
286 // gather set
f67539c2 287 static std::set<int32_t> empty_gather_set;
7c673cae
FG
288
289 // int32_t: <0 is client, >=0 is MDS rank
f67539c2 290 const std::set<int32_t>& get_gather_set() const {
7c673cae
FG
291 return have_more() ? more()->gather_set : empty_gather_set;
292 }
293
294 void init_gather() {
f67539c2 295 for (const auto& p : parent->get_replicas()) {
181888fb
FG
296 more()->gather_set.insert(p.first);
297 }
7c673cae
FG
298 }
299 bool is_gathering() const {
300 return have_more() && !more()->gather_set.empty();
301 }
302 bool is_gathering(int32_t i) const {
303 return have_more() && more()->gather_set.count(i);
304 }
305 void clear_gather() {
306 if (have_more())
307 more()->gather_set.clear();
308 }
309 void remove_gather(int32_t i) {
310 if (have_more())
311 more()->gather_set.erase(i);
312 }
313
7c673cae
FG
314 virtual bool is_dirty() const { return false; }
315 virtual bool is_stale() const { return false; }
316 virtual bool is_flushing() const { return false; }
317 virtual bool is_flushed() const { return false; }
318 virtual void clear_flushed() { }
319
320 // can_*
321 bool can_lease(client_t client) const {
322 return get_sm()->states[state].can_lease == ANY ||
323 (get_sm()->states[state].can_lease == AUTH && parent->is_auth()) ||
324 (get_sm()->states[state].can_lease == XCL && client >= 0 && get_xlock_by_client() == client);
325 }
326 bool can_read(client_t client) const {
327 return get_sm()->states[state].can_read == ANY ||
328 (get_sm()->states[state].can_read == AUTH && parent->is_auth()) ||
329 (get_sm()->states[state].can_read == XCL && client >= 0 && get_xlock_by_client() == client);
330 }
331 bool can_read_projected(client_t client) const {
332 return get_sm()->states[state].can_read_projected == ANY ||
333 (get_sm()->states[state].can_read_projected == AUTH && parent->is_auth()) ||
334 (get_sm()->states[state].can_read_projected == XCL && client >= 0 && get_xlock_by_client() == client);
335 }
336 bool can_rdlock(client_t client) const {
337 return get_sm()->states[state].can_rdlock == ANY ||
338 (get_sm()->states[state].can_rdlock == AUTH && parent->is_auth()) ||
339 (get_sm()->states[state].can_rdlock == XCL && client >= 0 && get_xlock_by_client() == client);
340 }
341 bool can_wrlock(client_t client) const {
342 return get_sm()->states[state].can_wrlock == ANY ||
343 (get_sm()->states[state].can_wrlock == AUTH && parent->is_auth()) ||
344 (get_sm()->states[state].can_wrlock == XCL && client >= 0 && (get_xlock_by_client() == client ||
345 get_excl_client() == client));
346 }
347 bool can_force_wrlock(client_t client) const {
348 return get_sm()->states[state].can_force_wrlock == ANY ||
349 (get_sm()->states[state].can_force_wrlock == AUTH && parent->is_auth()) ||
350 (get_sm()->states[state].can_force_wrlock == XCL && client >= 0 && (get_xlock_by_client() == client ||
351 get_excl_client() == client));
352 }
353 bool can_xlock(client_t client) const {
354 return get_sm()->states[state].can_xlock == ANY ||
355 (get_sm()->states[state].can_xlock == AUTH && parent->is_auth()) ||
356 (get_sm()->states[state].can_xlock == XCL && client >= 0 && get_xlock_by_client() == client);
357 }
358
359 // rdlock
360 bool is_rdlocked() const { return num_rdlock > 0; }
361 int get_rdlock() {
362 if (!num_rdlock)
363 parent->get(MDSCacheObject::PIN_LOCK);
364 return ++num_rdlock;
365 }
366 int put_rdlock() {
11fdf7f2 367 ceph_assert(num_rdlock>0);
7c673cae
FG
368 --num_rdlock;
369 if (num_rdlock == 0)
370 parent->put(MDSCacheObject::PIN_LOCK);
371 return num_rdlock;
372 }
373 int get_num_rdlocks() const {
374 return num_rdlock;
375 }
376
377 // wrlock
378 void get_wrlock(bool force=false) {
379 //assert(can_wrlock() || force);
380 if (more()->num_wrlock == 0)
381 parent->get(MDSCacheObject::PIN_LOCK);
382 ++more()->num_wrlock;
383 }
384 void put_wrlock() {
385 --more()->num_wrlock;
386 if (more()->num_wrlock == 0) {
387 parent->put(MDSCacheObject::PIN_LOCK);
388 try_clear_more();
389 }
390 }
391 bool is_wrlocked() const {
392 return have_more() && more()->num_wrlock > 0;
393 }
394 int get_num_wrlocks() const {
395 return have_more() ? more()->num_wrlock : 0;
396 }
397
398 // xlock
399 void get_xlock(MutationRef who, client_t client) {
11fdf7f2
TL
400 ceph_assert(get_xlock_by() == MutationRef());
401 ceph_assert(state == LOCK_XLOCK || is_locallock() ||
f67539c2 402 state == LOCK_LOCK /* if we are a peer */);
7c673cae
FG
403 parent->get(MDSCacheObject::PIN_LOCK);
404 more()->num_xlock++;
405 more()->xlock_by = who;
406 more()->xlock_by_client = client;
407 }
408 void set_xlock_done() {
11fdf7f2
TL
409 ceph_assert(more()->xlock_by);
410 ceph_assert(state == LOCK_XLOCK || is_locallock() ||
f67539c2 411 state == LOCK_LOCK /* if we are a peer */);
7c673cae
FG
412 if (!is_locallock())
413 state = LOCK_XLOCKDONE;
414 more()->xlock_by.reset();
415 }
416 void put_xlock() {
11fdf7f2 417 ceph_assert(state == LOCK_XLOCK || state == LOCK_XLOCKDONE ||
a8e16298 418 state == LOCK_XLOCKSNAP || state == LOCK_LOCK_XLOCK ||
f67539c2 419 state == LOCK_LOCK || /* if we are a leader of a peer */
aee94f69 420 state == LOCK_PREXLOCK || state == LOCK_SYNC ||
a8e16298 421 is_locallock());
7c673cae
FG
422 --more()->num_xlock;
423 parent->put(MDSCacheObject::PIN_LOCK);
424 if (more()->num_xlock == 0) {
425 more()->xlock_by.reset();
426 more()->xlock_by_client = -1;
427 try_clear_more();
428 }
429 }
430 bool is_xlocked() const {
431 return have_more() && more()->num_xlock > 0;
432 }
433 int get_num_xlocks() const {
434 return have_more() ? more()->num_xlock : 0;
435 }
436 client_t get_xlock_by_client() const {
437 return have_more() ? more()->xlock_by_client : -1;
438 }
439 bool is_xlocked_by_client(client_t c) const {
440 return have_more() ? more()->xlock_by_client == c : false;
441 }
442 MutationRef get_xlock_by() const {
443 return have_more() ? more()->xlock_by : MutationRef();
444 }
445
446 // lease
b32b8144
FG
447 bool is_leased() const {
448 return state_flags & LEASED;
449 }
7c673cae 450 void get_client_lease() {
11fdf7f2 451 ceph_assert(!is_leased());
b32b8144 452 state_flags |= LEASED;
7c673cae
FG
453 }
454 void put_client_lease() {
11fdf7f2 455 ceph_assert(is_leased());
b32b8144 456 state_flags &= ~LEASED;
7c673cae
FG
457 }
458
b32b8144
FG
459 bool needs_recover() const {
460 return state_flags & NEED_RECOVER;
461 }
462 void mark_need_recover() {
463 state_flags |= NEED_RECOVER;
464 }
465 void clear_need_recover() {
466 state_flags &= ~NEED_RECOVER;
7c673cae
FG
467 }
468
469 // encode/decode
f67539c2 470 void encode(ceph::buffer::list& bl) const {
7c673cae 471 ENCODE_START(2, 2, bl);
11fdf7f2 472 encode(state, bl);
7c673cae 473 if (have_more())
11fdf7f2 474 encode(more()->gather_set, bl);
7c673cae 475 else
11fdf7f2 476 encode(empty_gather_set, bl);
7c673cae
FG
477 ENCODE_FINISH(bl);
478 }
f67539c2 479 void decode(ceph::buffer::list::const_iterator& p) {
7c673cae 480 DECODE_START(2, p);
11fdf7f2 481 decode(state, p);
f67539c2 482 std::set<__s32> g;
11fdf7f2 483 decode(g, p);
7c673cae
FG
484 if (!g.empty())
485 more()->gather_set.swap(g);
486 DECODE_FINISH(p);
487 }
f67539c2 488 void encode_state_for_replica(ceph::buffer::list& bl) const {
7c673cae 489 __s16 s = get_replica_state();
11fdf7f2
TL
490 using ceph::encode;
491 encode(s, bl);
7c673cae 492 }
f67539c2 493 void decode_state(ceph::buffer::list::const_iterator& p, bool is_new=true) {
11fdf7f2 494 using ceph::decode;
7c673cae 495 __s16 s;
11fdf7f2 496 decode(s, p);
7c673cae
FG
497 if (is_new)
498 state = s;
499 }
f67539c2 500 void decode_state_rejoin(ceph::buffer::list::const_iterator& p, MDSContext::vec& waiters, bool survivor) {
7c673cae 501 __s16 s;
11fdf7f2
TL
502 using ceph::decode;
503 decode(s, p);
b32b8144 504 set_state_rejoin(s, waiters, survivor);
7c673cae
FG
505 }
506
7c673cae
FG
507 // caps
508 bool is_loner_mode() const {
509 return get_sm()->states[state].loner;
510 }
511 int gcaps_allowed_ever() const {
512 return parent->is_auth() ? get_sm()->allowed_ever_auth : get_sm()->allowed_ever_replica;
513 }
514 int gcaps_allowed(int who, int s=-1) const {
515 if (s < 0) s = state;
516 if (parent->is_auth()) {
517 if (get_xlock_by_client() >= 0 && who == CAP_XLOCKER)
518 return get_sm()->states[s].xlocker_caps | get_sm()->states[s].caps; // xlocker always gets more
519 else if (is_loner_mode() && who == CAP_ANY)
520 return get_sm()->states[s].caps;
521 else
522 return get_sm()->states[s].loner_caps | get_sm()->states[s].caps; // loner always gets more
523 } else
524 return get_sm()->states[s].replica_caps;
525 }
526 int gcaps_careful() const {
527 if (get_num_wrlocks())
528 return get_sm()->careful;
529 return 0;
530 }
531
7c673cae
FG
532 int gcaps_xlocker_mask(client_t client) const {
533 if (client == get_xlock_by_client())
534 return type->type == CEPH_LOCK_IFILE ? 0xf : (CEPH_CAP_GSHARED|CEPH_CAP_GEXCL);
535 return 0;
536 }
537
538 // simplelock specifics
539 int get_replica_state() const {
540 return get_sm()->states[state].replica_state;
541 }
542 void export_twiddle() {
543 clear_gather();
544 state = get_replica_state();
545 }
546
7c673cae
FG
547 bool remove_replica(int from) {
548 if (is_gathering(from)) {
549 remove_gather(from);
550 if (!is_gathering())
551 return true;
552 }
553 return false;
554 }
555 bool do_import(int from, int to) {
556 if (!is_stable()) {
557 remove_gather(from);
558 remove_gather(to);
559 if (!is_gathering())
560 return true;
561 }
562 if (!is_stable() && !is_gathering())
563 return true;
564 return false;
565 }
566
f67539c2 567 void _print(std::ostream& out) const {
7c673cae
FG
568 out << get_lock_type_name(get_type()) << " ";
569 out << get_state_name(get_state());
570 if (!get_gather_set().empty())
571 out << " g=" << get_gather_set();
b32b8144
FG
572 if (is_leased())
573 out << " l";
7c673cae
FG
574 if (is_rdlocked())
575 out << " r=" << get_num_rdlocks();
576 if (is_wrlocked())
577 out << " w=" << get_num_wrlocks();
578 if (is_xlocked()) {
579 out << " x=" << get_num_xlocks();
580 if (get_xlock_by())
581 out << " by " << get_xlock_by();
582 }
583 /*if (is_stable())
584 out << " stable";
585 else
586 out << " unstable";
587 */
588 }
589
590 /**
591 * Write bare values (caller must be in an object section)
592 * to formatter, or nothing if is_sync_and_unlocked.
593 */
f67539c2 594 void dump(ceph::Formatter *f) const;
7c673cae 595
f67539c2 596 virtual void print(std::ostream& out) const {
7c673cae
FG
597 out << "(";
598 _print(out);
599 out << ")";
600 }
9f95a23c
TL
601
602 LockType *type;
603
604protected:
605 // parent (what i lock)
606 MDSCacheObject *parent;
607
608 // lock state
609 __s16 state = LOCK_SYNC;
610 __s16 state_flags = 0;
611
612 enum {
613 LEASED = 1 << 0,
614 NEED_RECOVER = 1 << 1,
615 CACHED = 1 << 2,
616 };
617
618private:
619 // XXX not in mempool
620 struct unstable_bits_t {
621 unstable_bits_t();
622
623 bool empty() {
624 return
625 gather_set.empty() &&
626 num_wrlock == 0 &&
627 num_xlock == 0 &&
628 xlock_by.get() == NULL &&
629 xlock_by_client == -1 &&
630 excl_client == -1 &&
631 lock_caches.empty();
632 }
633
f67539c2 634 std::set<__s32> gather_set; // auth+rep. >= 0 is mds, < 0 is client
9f95a23c
TL
635
636 // local state
637 int num_wrlock = 0, num_xlock = 0;
638 MutationRef xlock_by;
639 client_t xlock_by_client = -1;
640 client_t excl_client = -1;
641
642 elist<MDLockCacheItem*> lock_caches;
643 };
644
645 bool have_more() const { return _unstable ? true : false; }
646 unstable_bits_t *more() const {
647 if (!_unstable)
648 _unstable.reset(new unstable_bits_t);
649 return _unstable.get();
650 }
651 void try_clear_more() {
652 if (_unstable && _unstable->empty()) {
653 _unstable.reset();
654 }
655 }
656
657 int num_rdlock = 0;
658
659 mutable std::unique_ptr<unstable_bits_t> _unstable;
7c673cae
FG
660};
661WRITE_CLASS_ENCODER(SimpleLock)
662
f67539c2 663inline std::ostream& operator<<(std::ostream& out, const SimpleLock& l)
7c673cae
FG
664{
665 l.print(out);
666 return out;
667}
7c673cae 668#endif