From 2dcc079b131cca04e3a59ded5ee1214318eb96e1 Mon Sep 17 00:00:00 2001
From: Julien Muchembled <jm@nexedi.com>
Date: Sat, 4 Jan 2014 17:01:15 +0100
Subject: [PATCH] client: do never reconnect to master if already connected

---
 neo/client/app.py             | 19 +++++++++----------
 neo/client/handlers/master.py |  1 -
 2 files changed, 9 insertions(+), 11 deletions(-)

diff --git a/neo/client/app.py b/neo/client/app.py
index 5ac1b407..85d7dc03 100644
--- a/neo/client/app.py
+++ b/neo/client/app.py
@@ -107,11 +107,9 @@ class Application(object):
         # _cache_lock is used for the client cache
         self._cache_lock_acquire = lock.acquire
         self._cache_lock_release = lock.release
-        lock = Lock()
         # _connecting_to_master_node is used to prevent simultaneous master
         # node connection attemps
-        self._connecting_to_master_node_acquire = lock.acquire
-        self._connecting_to_master_node_release = lock.release
+        self._connecting_to_master_node = Lock()
         # _nm ensure exclusive access to the node manager
         lock = Lock()
         self._nm_acquire = lock.acquire
@@ -231,15 +229,16 @@ class Application(object):
 
     def _getMasterConnection(self):
         """ Connect to the primary master node on demand """
-        # acquire the lock to allow only one thread to connect to the primary
+        # For performance reasons, get 'master_conn' without locking.
         result = self.master_conn
         if result is None:
-            self._connecting_to_master_node_acquire()
-            try:
-                self.new_oid_list = []
-                result = self._connectToPrimaryNode()
-            finally:
-                self._connecting_to_master_node_release()
+            # If not connected, 'master_conn' must be tested again while we have
+            # the lock, to avoid concurrent threads reconnecting.
+            with self._connecting_to_master_node:
+                result = self.master_conn
+                if result is None:
+                    self.new_oid_list = []
+                    result = self.master_conn = self._connectToPrimaryNode()
         return result
 
     def getPartitionTable(self):
diff --git a/neo/client/handlers/master.py b/neo/client/handlers/master.py
index 83756cd0..e269fa4f 100644
--- a/neo/client/handlers/master.py
+++ b/neo/client/handlers/master.py
@@ -80,7 +80,6 @@ class PrimaryBootstrapHandler(AnswerBaseHandler):
 
         # Always create partition table
         app.pt = PartitionTable(num_partitions, num_replicas)
-        app.master_conn = conn
 
     def answerPartitionTable(self, conn, ptid, row_list):
         assert row_list
-- 
2.30.9