Skip to content

Commit

Permalink
BSN: Allow concurrent reads to consistency DB
Browse files Browse the repository at this point in the history
Allow concurrent reads to the consistency DB since the
database lock the block was originally protecting against
is gone.

Closes-Bug: #1357102
Change-Id: I1618b4046e995c796757e723f99288e486683339
(cherry picked from commit b09c995)
  • Loading branch information
kevinbenton committed Sep 16, 2014
1 parent 2820410 commit b5e3c9a
Show file tree
Hide file tree
Showing 2 changed files with 11 additions and 30 deletions.
39 changes: 11 additions & 28 deletions neutron/plugins/bigswitch/db/consistency_db.py
Expand Up @@ -14,18 +14,13 @@
# under the License.
import sqlalchemy as sa

from neutron.common import exceptions
from neutron.db import api as db
from neutron.db import model_base
from neutron.openstack.common import log as logging

LOG = logging.getLogger(__name__)


class MultipleReadForUpdateCalls(exceptions.NeutronException):
message = _("Only one read_for_update call may be made at a time.")


class ConsistencyHash(model_base.BASEV2):
'''
A simple table to store the latest consistency hash
Expand All @@ -41,47 +36,35 @@ class ConsistencyHash(model_base.BASEV2):

class HashHandler(object):
'''
A wrapper object to keep track of the session and hold the SQL
lock between the read and the update to prevent other servers
from reading the hash during a transaction.
A wrapper object to keep track of the session between the read
and the update operations.
'''
def __init__(self, context=None, hash_id='1'):
self.hash_id = hash_id
self.session = db.get_session() if not context else context.session
self.hash_db_obj = None
self.transaction = None

def read_for_update(self):
if self.transaction:
raise MultipleReadForUpdateCalls()
self.transaction = self.session.begin(subtransactions=True)
# REVISIT(kevinbenton): locking here with the DB is prone to deadlocks
# in various multi-REST-call scenarios (router intfs, flips, etc).
# Since it doesn't work in Galera deployments anyway, another sync
# mechanism will have to be introduced to prevent inefficient double
# syncs in HA deployments.
res = (self.session.query(ConsistencyHash).
filter_by(hash_id=self.hash_id).first())
with self.session.begin(subtransactions=True):
res = (self.session.query(ConsistencyHash).
filter_by(hash_id=self.hash_id).first())
if not res:
return ''
self.hash_db_obj = res
return res.hash

def put_hash(self, hash):
hash = hash or ''
if not self.transaction:
self.transaction = self.session.begin(subtransactions=True)
if self.hash_db_obj is not None:
self.hash_db_obj.hash = hash
else:
conhash = ConsistencyHash(hash_id=self.hash_id, hash=hash)
self.session.merge(conhash)
self.close_update_session()
with self.session.begin(subtransactions=True):
if self.hash_db_obj is not None:
self.hash_db_obj.hash = hash
else:
conhash = ConsistencyHash(hash_id=self.hash_id, hash=hash)
self.session.merge(conhash)
LOG.debug(_("Consistency hash for group %(hash_id)s updated "
"to %(hash)s"), {'hash_id': self.hash_id, 'hash': hash})

def close_update_session(self):
if not self.transaction:
return
self.transaction.commit()
self.transaction = None
2 changes: 0 additions & 2 deletions neutron/plugins/bigswitch/servermanager.py
Expand Up @@ -197,8 +197,6 @@ def rest_call(self, action, resource, data='', headers={}, timeout=False,
except ValueError:
# response was not JSON, ignore the exception
pass
else:
hash_handler.close_update_session()
ret = (response.status, response.reason, respstr, respdata)
except httplib.HTTPException:
# If we were using a cached connection, try again with a new one.
Expand Down

0 comments on commit b5e3c9a

Please sign in to comment.