]> git.apps.os.sepia.ceph.com Git - ceph.git/commitdiff
mon: Monitor: tolerate GV duplicates during conversion
authorJoao Eduardo Luis <joao.luis@inktank.com>
Mon, 13 May 2013 14:36:59 +0000 (15:36 +0100)
committerSage Weil <sage@inktank.com>
Mon, 13 May 2013 18:40:53 +0000 (11:40 -0700)
Fixes: #4974
Signed-off-by: Joao Eduardo Luis <joao.luis@inktank.com>
(cherry picked from commit ba05b16ee2b6e25141f2ab88265a1cf92dcd493c)

src/mon/Monitor.cc
src/mon/Monitor.h

index 56cd291cd24ae8035bfd04b23870502ecffc25f4..3c40ad38085265655e7f1bb452f2ee976dcbfc3d 100644 (file)
@@ -4404,23 +4404,54 @@ void Monitor::StoreConverter::_convert_machines(string machine)
       dout(20) << __func__ << " " << machine
               << " ver " << ver << " -> " << gv << dendl;
 
+      MonitorDBStore::Transaction paxos_tx;
+
       if (gvs.count(gv) == 0) {
-       gvs.insert(gv);
+        gvs.insert(gv);
       } else {
        dout(0) << __func__ << " " << machine
                << " gv " << gv << " already exists"
                << dendl;
-       assert(0 == "Duplicate GV -- something is wrong!");
+
+        // Duplicates aren't supposed to happen, but an old bug introduced
+       // them and the mds state machine wasn't ever trimmed, so many users
+       // will see them.  So we'll just merge them all in one
+        // single paxos version.
+        // We know that they are either from another paxos machine or
+        // they are from the same paxos machine but their version is
+        // lower than ours -- given that we are iterating all versions
+        // from the lowest to the highest, duh!
+        // We'll just append our stuff to the existing paxos transaction
+        // as if nothing had happened.
+
+        // Just make sure we are correct. This shouldn't take long and
+        // should never be triggered!
+        set<pair<string,version_t> >& s = gv_map[gv];
+        for (set<pair<string,version_t> >::iterator it = s.begin();
+             it != s.end(); ++it) {
+          if (it->first == machine)
+            assert(it->second + 1 == ver);
+        }
+
+        bufferlist paxos_bl;
+        int r = db->get("paxos", gv, paxos_bl);
+        assert(r >= 0);
+        paxos_tx.append_from_encoded(paxos_bl);
       }
+      gv_map[gv].insert(make_pair(machine,ver));
 
       bufferlist tx_bl;
       tx.encode(tx_bl);
-      tx.put("paxos", gv, tx_bl);
+      paxos_tx.append_from_encoded(tx_bl);
+      bufferlist paxos_bl;
+      paxos_tx.encode(paxos_bl);
+      tx.put("paxos", gv, paxos_bl);
     }
     db->apply_transaction(tx);
   }
 
   version_t lc = db->get(machine, "last_committed");
+  dout(20) << __func__ << " lc " << lc << " last_committed " << last_committed << dendl;
   assert(lc == last_committed);
 
   MonitorDBStore::Transaction tx;
index c06d2fbb54e3d1a3f430006505a1e74dd1315554..57da2aba539c614dfd3808980a07e7539df5564a 100644 (file)
@@ -1450,6 +1450,8 @@ public:
     boost::scoped_ptr<MonitorStore> store;
 
     set<version_t> gvs;
+    map<version_t, set<pair<string,version_t> > > gv_map;
+
     version_t highest_last_pn;
     version_t highest_accepted_pn;