1 // -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
2 // vim: ts=8 sw=2 smarttab
4 * Ceph - scalable distributed file system
6 * Copyright (C) 2004-2006 Sage Weil <sage@newdream.net>
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.
16 #ifndef CEPH_SCATTERLOCK_H
17 #define CEPH_SCATTERLOCK_H
19 #include "SimpleLock.h"
21 class ScatterLock : public SimpleLock {
26 xlist<ScatterLock*>::item item_updated;
29 explicit more_bits_t(ScatterLock *lock) :
37 !item_updated.is_on_list();
42 bool have_more() const { return _more ? true : false; }
43 void try_clear_more() {
44 if (_more && _more->empty()) {
51 _more = new more_bits_t(this);
55 enum flag_values { // flag values for more_bits_t state
56 SCATTER_WANTED = 1 << 0,
57 UNSCATTER_WANTED = 1 << 1,
61 REJOIN_MIX = 1 << 5, // no rdlock until the recovering mds become active
65 ScatterLock(MDSCacheObject *o, LockType *lt) :
66 SimpleLock(o, lt), _more(NULL)
68 ~ScatterLock() override {
70 _more->item_updated.remove_myself(); // FIXME this should happen sooner, i think...
75 bool is_scatterlock() const override {
79 bool is_sync_and_unlocked() const {
81 SimpleLock::is_sync_and_unlocked() &&
86 bool can_scatter_pin(client_t loner) {
88 LOCK : NOT okay because it can MIX and force replicas to journal something
89 TSYN : also not okay for same reason
92 MIX : okay, replica can stall before sending AC_SYNCACK
93 SYNC : okay, replica can stall before sending AC_MIXACK or AC_LOCKACK
96 get_state() == LOCK_SYNC ||
97 get_state() == LOCK_MIX;
100 void set_xlock_snap_sync(MDSInternalContextBase *c)
102 assert(get_type() == CEPH_LOCK_IFILE);
103 assert(state == LOCK_XLOCK || state == LOCK_XLOCKDONE);
104 state = LOCK_XLOCKSNAP;
105 add_waiter(WAIT_STABLE, c);
108 xlist<ScatterLock*>::item *get_updated_item() { return &more()->item_updated; }
110 utime_t get_update_stamp() {
111 return more()->update_stamp;
114 void set_update_stamp(utime_t t) { more()->update_stamp = t; }
116 void set_scatter_wanted() {
117 more()->state_flags |= SCATTER_WANTED;
119 void set_unscatter_wanted() {
120 more()->state_flags |= UNSCATTER_WANTED;
122 void clear_scatter_wanted() {
124 _more->state_flags &= ~SCATTER_WANTED;
127 void clear_unscatter_wanted() {
129 _more->state_flags &= ~UNSCATTER_WANTED;
132 bool get_scatter_wanted() const {
133 return have_more() ? _more->state_flags & SCATTER_WANTED : false;
135 bool get_unscatter_wanted() const {
136 return have_more() ? _more->state_flags & UNSCATTER_WANTED : false;
139 bool is_dirty() const override {
140 return have_more() ? _more->state_flags & DIRTY : false;
142 bool is_flushing() const override {
143 return have_more() ? _more->state_flags & FLUSHING: false;
145 bool is_flushed() const override {
146 return have_more() ? _more->state_flags & FLUSHED: false;
148 bool is_dirty_or_flushing() const {
149 return have_more() ? (is_dirty() || is_flushing()) : false;
151 bool is_rejoin_mix() const {
152 return have_more() ? _more->state_flags & REJOIN_MIX : false;
158 parent->get(MDSCacheObject::PIN_DIRTYSCATTERED);
168 void finish_flush() {
173 parent->put(MDSCacheObject::PIN_DIRTYSCATTERED);
174 parent->clear_dirty_scattered(get_type());
178 void remove_dirty() {
182 void clear_flushed() override {
184 _more->state_flags &= ~FLUSHED;
189 void clear_rejoin_mix() {
191 _more->state_flags &= ~REJOIN_MIX;
196 void set_last_scatter(utime_t t) { more()->last_scatter = t; }
197 utime_t get_last_scatter() {
198 return more()->last_scatter;
201 void infer_state_from_strong_rejoin(int rstate, bool locktoo) {
202 if (rstate == LOCK_MIX ||
203 rstate == LOCK_MIX_LOCK || // replica still has wrlocks?
204 rstate == LOCK_MIX_SYNC)
206 else if (locktoo && rstate == LOCK_LOCK)
210 void encode_state_for_rejoin(bufferlist& bl, int rep) {
211 __s16 s = get_replica_state();
212 if (is_gathering(rep)) {
213 // the recovering mds may hold rejoined wrlocks
214 if (state == LOCK_MIX_SYNC)
220 if (s == LOCK_MIX || s == LOCK_MIX_LOCK || s == LOCK_MIX_SYNC)
221 more()->state_flags |= REJOIN_MIX;
226 void decode_state_rejoin(bufferlist::iterator& p, list<MDSInternalContextBase*>& waiters) {
227 SimpleLock::decode_state_rejoin(p, waiters);
234 bool remove_replica(int from, bool rejoin) {
236 (state == LOCK_MIX ||
237 state == LOCK_MIX_SYNC ||
238 state == LOCK_MIX_LOCK2 ||
239 state == LOCK_MIX_TSYN ||
240 state == LOCK_MIX_EXCL))
242 return SimpleLock::remove_replica(from);
245 void print(ostream& out) const override {
254 if (get_scatter_wanted())
255 out << " scatter_wanted";
260 void set_flushing() {
261 more()->state_flags |= FLUSHING;
263 void clear_flushing() {
265 _more->state_flags &= ~FLUSHING;
269 more()->state_flags |= FLUSHED;
272 more()->state_flags |= DIRTY;
276 _more->state_flags &= ~DIRTY;