]> git.apps.os.sepia.ceph.com Git - ceph.git/commitdiff
mon/Paxos: WRITING != WRITING_PREVIOUS
authorSage Weil <sage@redhat.com>
Mon, 25 Aug 2014 04:01:07 +0000 (21:01 -0700)
committerSage Weil <sage@redhat.com>
Wed, 27 Aug 2014 21:36:08 +0000 (14:36 -0700)
This distinction is important: the update-previous state should not be
writeable, as reflected by PaxosService::is_writeable().

Signed-off-by: Sage Weil <sage@redhat.com>
src/mon/Monitor.cc
src/mon/Paxos.cc
src/mon/Paxos.h
src/mon/PaxosService.cc

index f9327ef9e2a6bd00f07057739e75a2d9a2e68ea4..ced69a5b0966232dbdd3443d350c8b618fdd0b6d 100644 (file)
@@ -781,7 +781,7 @@ void Monitor::shutdown()
 
 void Monitor::bootstrap()
 {
-  if (paxos->is_writing()) {
+  if (paxos->is_writing() || paxos->is_writing_previous()) {
     dout(10) << "bootstrap flushing pending write" << dendl;
     lock.Unlock();
     store->flush();
@@ -2387,7 +2387,7 @@ void Monitor::handle_command(MMonCommand *m)
   }
 
   if (prefix == "scrub") {
-    while (paxos->is_writing()) {
+    while (paxos->is_writing() || paxos->is_writing_previous()) {
       lock.Unlock();
       store->flush();
       lock.Lock();
index c85beaabbf41a2fcb90d1a8b9091766b1f4007a3..e5208527055e47694acf32fc4f3998476f96859f 100644 (file)
@@ -796,7 +796,8 @@ void Paxos::accept_timeout()
   dout(1) << "accept timeout, calling fresh election" << dendl;
   accept_timeout_event = 0;
   assert(mon->is_leader());
-  assert(is_updating() || is_updating_previous() || is_writing());
+  assert(is_updating() || is_updating_previous() || is_writing() ||
+        is_writing_previous());
   logger->inc(l_paxos_accept_timeout);
   mon->bootstrap();
 }
@@ -839,7 +840,12 @@ void Paxos::commit_start()
 
   get_store()->queue_transaction(t, new C_Committed(this));
 
-  state = STATE_WRITING;
+  if (is_updating_previous())
+    state = STATE_WRITING_PREVIOUS;
+  else if (is_updating())
+    state = STATE_WRITING;
+  else
+    assert(0);
 }
 
 void Paxos::commit_finish()
@@ -889,7 +895,7 @@ void Paxos::commit_finish()
   // WRITING -> REFRESH
   // among other things, this lets do_refresh() -> mon->bootstrap() know
   // it doesn't need to flush the store queue
-  assert(state == STATE_WRITING);
+  assert(is_writing() || is_writing_previous());
   state = STATE_REFRESH;
 
   if (do_refresh()) {
@@ -1339,7 +1345,7 @@ void Paxos::restart()
   cancel_events();
   new_value.clear();
 
-  if (is_writing()) {
+  if (is_writing() || is_writing_previous()) {
     dout(10) << __func__ << " flushing" << dendl;
     mon->lock.Unlock();
     mon->store->flush();
index aa591de7658e0e5dd35d98f0b4361dce5b2e38eb..dcba45805b0cff6cb0657e0dabc6332057fea35f 100644 (file)
@@ -228,6 +228,10 @@ public:
      * writeable.
      */
     STATE_WRITING,
+    /*
+     * Leader/Peon is writing a new commit from a previous round.
+     */
+    STATE_WRITING_PREVIOUS,
     // leader: refresh following a commit
     STATE_REFRESH,
   };
@@ -253,6 +257,8 @@ public:
       return "updating-previous";
     case STATE_WRITING:
       return "writing";
+    case STATE_WRITING_PREVIOUS:
+      return "writing-previous";
     case STATE_REFRESH:
       return "refresh";
     default:
@@ -298,6 +304,9 @@ public:
   /// @return 'true' if we are writing an update to disk
   bool is_writing() const { return state == STATE_WRITING; }
 
+  /// @return 'true' if we are writing an update-previous to disk
+  bool is_writing_previous() const { return state == STATE_WRITING_PREVIOUS; }
+
   /// @return 'true' if we are refreshing an update just committed
   bool is_refresh() const { return state == STATE_REFRESH; }
 
index aba8c959a94da4c089e1db3540ed196fce4b4cf4..92257209565f821521ba7fb3725fa4c46ef86da9 100644 (file)
@@ -53,7 +53,8 @@ bool PaxosService::dispatch(PaxosServiceMessage *m)
   // make sure the client is still connected.  note that a proxied
   // connection will be disconnected with a null message; don't drop
   // those.  also ignore loopback (e.g., log) messages.
-  if (!m->get_connection()->is_connected() &&
+  if (m->get_connection() &&
+      !m->get_connection()->is_connected() &&
       m->get_connection() != mon->con_self &&
       m->get_connection()->get_messenger() != NULL) {
     dout(10) << " discarding message from disconnected client "