+++ /dev/null
-// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
-// vim: ts=8 sw=2 smarttab
-/*
- * Ceph - scalable distributed file system
- *
- * Copyright (C) 2004-2006 Sage Weil <sage@newdream.net>
- *
- * This is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License version 2.1, as published by the Free Software
- * Foundation. See file COPYING.
- *
- */
-
-
-#ifndef CEPH_SCATTERLOCK_H
-#define CEPH_SCATTERLOCK_H
-
-#include "SimpleLock.h"
-
-class ScatterLock : public SimpleLock {
-
- struct more_bits_t {
- int state_flags;
- utime_t last_scatter;
- xlist<ScatterLock*>::item item_updated;
- utime_t update_stamp;
-
- explicit more_bits_t(ScatterLock *lock) :
- state_flags(0),
- item_updated(lock)
- {}
-
- bool empty() const {
- return
- !state_flags &&
- !item_updated.is_on_list();
- }
- };
- more_bits_t *_more;
-
- bool have_more() const { return _more ? true : false; }
- void try_clear_more() {
- if (_more && _more->empty()) {
- delete _more;
- _more = NULL;
- }
- }
- more_bits_t *more() {
- if (!_more)
- _more = new more_bits_t(this);
- return _more;
- }
-
- enum flag_values { // flag values for more_bits_t state
- SCATTER_WANTED = 1 << 0,
- UNSCATTER_WANTED = 1 << 1,
- DIRTY = 1 << 2,
- FLUSHING = 1 << 3,
- FLUSHED = 1 << 4,
- REJOIN_MIX = 1 << 5, // no rdlock until the recovering mds become active
- };
-
-public:
- ScatterLock(MDSCacheObject *o, LockType *lt) :
- SimpleLock(o, lt), _more(NULL)
- {}
- ~ScatterLock() override {
- if (_more) {
- _more->item_updated.remove_myself(); // FIXME this should happen sooner, i think...
- delete _more;
- }
- }
-
- bool is_scatterlock() const override {
- return true;
- }
-
- bool is_sync_and_unlocked() const {
- return
- SimpleLock::is_sync_and_unlocked() &&
- !is_dirty() &&
- !is_flushing();
- }
-
- bool can_scatter_pin(client_t loner) {
- /*
- LOCK : NOT okay because it can MIX and force replicas to journal something
- TSYN : also not okay for same reason
- EXCL : also not okay
-
- MIX : okay, replica can stall before sending AC_SYNCACK
- SYNC : okay, replica can stall before sending AC_MIXACK or AC_LOCKACK
- */
- return
- get_state() == LOCK_SYNC ||
- get_state() == LOCK_MIX;
- }
-
- void set_xlock_snap_sync(MDSInternalContextBase *c)
- {
- assert(get_type() == CEPH_LOCK_IFILE);
- assert(state == LOCK_XLOCK || state == LOCK_XLOCKDONE);
- state = LOCK_XLOCKSNAP;
- add_waiter(WAIT_STABLE, c);
- }
-
- xlist<ScatterLock*>::item *get_updated_item() { return &more()->item_updated; }
-
- utime_t get_update_stamp() {
- return more()->update_stamp;
- }
-
- void set_update_stamp(utime_t t) { more()->update_stamp = t; }
-
- void set_scatter_wanted() {
- more()->state_flags |= SCATTER_WANTED;
- }
- void set_unscatter_wanted() {
- more()->state_flags |= UNSCATTER_WANTED;
- }
- void clear_scatter_wanted() {
- if (have_more())
- _more->state_flags &= ~SCATTER_WANTED;
- try_clear_more();
- }
- void clear_unscatter_wanted() {
- if (have_more())
- _more->state_flags &= ~UNSCATTER_WANTED;
- try_clear_more();
- }
- bool get_scatter_wanted() const {
- return have_more() ? _more->state_flags & SCATTER_WANTED : false;
- }
- bool get_unscatter_wanted() const {
- return have_more() ? _more->state_flags & UNSCATTER_WANTED : false;
- }
-
- bool is_dirty() const override {
- return have_more() ? _more->state_flags & DIRTY : false;
- }
- bool is_flushing() const override {
- return have_more() ? _more->state_flags & FLUSHING: false;
- }
- bool is_flushed() const override {
- return have_more() ? _more->state_flags & FLUSHED: false;
- }
- bool is_dirty_or_flushing() const {
- return have_more() ? (is_dirty() || is_flushing()) : false;
- }
- bool is_rejoin_mix() const {
- return have_more() ? _more->state_flags & REJOIN_MIX : false;
- }
-
- void mark_dirty() {
- if (!is_dirty()) {
- if (!is_flushing())
- parent->get(MDSCacheObject::PIN_DIRTYSCATTERED);
- set_dirty();
- }
- }
- void start_flush() {
- if (is_dirty()) {
- set_flushing();
- clear_dirty();
- }
- }
- void finish_flush() {
- if (is_flushing()) {
- clear_flushing();
- set_flushed();
- if (!is_dirty()) {
- parent->put(MDSCacheObject::PIN_DIRTYSCATTERED);
- parent->clear_dirty_scattered(get_type());
- }
- }
- }
- void remove_dirty() {
- start_flush();
- finish_flush();
- }
- void clear_flushed() override {
- if (have_more()) {
- _more->state_flags &= ~FLUSHED;
- try_clear_more();
- }
- }
-
- void clear_rejoin_mix() {
- if (have_more()) {
- _more->state_flags &= ~REJOIN_MIX;
- try_clear_more();
- }
- }
-
- void set_last_scatter(utime_t t) { more()->last_scatter = t; }
- utime_t get_last_scatter() {
- return more()->last_scatter;
- }
-
- void infer_state_from_strong_rejoin(int rstate, bool locktoo) {
- if (rstate == LOCK_MIX ||
- rstate == LOCK_MIX_LOCK || // replica still has wrlocks?
- rstate == LOCK_MIX_SYNC)
- state = LOCK_MIX;
- else if (locktoo && rstate == LOCK_LOCK)
- state = LOCK_LOCK;
- }
-
- void encode_state_for_rejoin(bufferlist& bl, int rep) {
- __s16 s = get_replica_state();
- if (is_gathering(rep)) {
- // the recovering mds may hold rejoined wrlocks
- if (state == LOCK_MIX_SYNC)
- s = LOCK_MIX_SYNC;
- else
- s = LOCK_MIX_LOCK;
- }
-
- if (s == LOCK_MIX || s == LOCK_MIX_LOCK || s == LOCK_MIX_SYNC)
- more()->state_flags |= REJOIN_MIX;
-
- ::encode(s, bl);
- }
-
- void decode_state_rejoin(bufferlist::iterator& p, list<MDSInternalContextBase*>& waiters) {
- SimpleLock::decode_state_rejoin(p, waiters);
- if (is_flushing()) {
- set_dirty();
- clear_flushing();
- }
- }
-
- bool remove_replica(int from, bool rejoin) {
- if (rejoin &&
- (state == LOCK_MIX ||
- state == LOCK_MIX_SYNC ||
- state == LOCK_MIX_LOCK2 ||
- state == LOCK_MIX_TSYN ||
- state == LOCK_MIX_EXCL))
- return false;
- return SimpleLock::remove_replica(from);
- }
-
- void print(ostream& out) const override {
- out << "(";
- _print(out);
- if (is_dirty())
- out << " dirty";
- if (is_flushing())
- out << " flushing";
- if (is_flushed())
- out << " flushed";
- if (get_scatter_wanted())
- out << " scatter_wanted";
- out << ")";
- }
-
-private:
- void set_flushing() {
- more()->state_flags |= FLUSHING;
- }
- void clear_flushing() {
- if (have_more()) {
- _more->state_flags &= ~FLUSHING;
- }
- }
- void set_flushed() {
- more()->state_flags |= FLUSHED;
- }
- void set_dirty() {
- more()->state_flags |= DIRTY;
- }
- void clear_dirty() {
- if (have_more()) {
- _more->state_flags &= ~DIRTY;
- }
- }
-};
-
-#endif