diff options
| -rw-r--r-- | client/src/leap/soledad/client/api.py | 20 | ||||
| -rw-r--r-- | client/src/leap/soledad/client/sqlcipher.py | 8 | 
2 files changed, 19 insertions, 9 deletions
| diff --git a/client/src/leap/soledad/client/api.py b/client/src/leap/soledad/client/api.py index 9000029f..633c07d0 100644 --- a/client/src/leap/soledad/client/api.py +++ b/client/src/leap/soledad/client/api.py @@ -41,13 +41,14 @@ except ImportError:  from itertools import chain  from StringIO import StringIO +from collections import defaultdict  from u1db.remote import http_client  from u1db.remote.ssl_match_hostname import match_hostname  from zope.interface import implements  from leap.common.config import get_path_prefix  from leap.common.plugins import collect_plugins -from twisted.internet import defer +from twisted.internet.defer import DeferredLock  from leap.soledad.common import SHARED_DB_NAME  from leap.soledad.common import soledad_assert @@ -114,6 +115,7 @@ class Soledad(object):      local_db_file_name = 'soledad.u1db'      secrets_file_name = "soledad.json"      default_prefix = os.path.join(get_path_prefix(), 'leap', 'soledad') +    _syncing_lock = defaultdict(DeferredLock)      def __init__(self, uuid, passphrase, secrets_path, local_db_path,                   server_url, cert_file, shared_db=None, @@ -200,7 +202,6 @@ class Soledad(object):          self._crypto = SoledadCrypto(self._secrets.remote_storage_secret)          self._init_u1db_sqlcipher_backend() -        self.sync_lock = defer.DeferredLock()          if syncable:              self._init_u1db_syncer() @@ -671,7 +672,7 @@ class Soledad(object):          # -----------------------------------------------------------------          sync_url = urlparse.urljoin(self._server_url, 'user-%s' % self.uuid) -        d = self.sync_lock.run(lambda: self._dbsyncer.sync( +        d = self.syncing_lock.run(lambda: self._dbsyncer.sync(              sync_url,              creds=self._creds,              defer_decryption=defer_decryption)) @@ -706,6 +707,17 @@ class Soledad(object):          return d      @property +    def syncing_lock(self): +        """ +        Class based lock to ensure consistency on concurrent calls to sync. +        Each lock is based on the path of db file. + +        :return: DeferredLock based on this instance path of db file +        :rtype: DeferredLock +        """ +        return self._syncing_lock[self._local_db_path] + +    @property      def syncing(self):          """          Return wether Soledad is currently synchronizing with the server. @@ -713,7 +725,7 @@ class Soledad(object):          :return: Wether Soledad is currently synchronizing with the server.          :rtype: bool          """ -        return self.sync_lock.locked +        return self.syncing_lock.locked      def _set_token(self, token):          """ diff --git a/client/src/leap/soledad/client/sqlcipher.py b/client/src/leap/soledad/client/sqlcipher.py index 249ffb1a..6a4fa01a 100644 --- a/client/src/leap/soledad/client/sqlcipher.py +++ b/client/src/leap/soledad/client/sqlcipher.py @@ -420,11 +420,6 @@ class SQLCipherU1DBSync(SQLCipherDatabase):      """      ENCRYPT_LOOP_PERIOD = 1 -    """ -    A dictionary that hold locks which avoid multiple sync attempts from the -    same database replica. -    """ -      def __init__(self, opts, soledad_crypto, replica_uid, cert_file,                   defer_encryption=False, sync_db=None, sync_enc_pool=None): @@ -513,6 +508,9 @@ class SQLCipherU1DBSync(SQLCipherDatabase):          changes, we should add a thread-safe condition to ensure the db is          ready before using it. +        This method is atomic, with atomicity guaranteed by caller. Each +        caller should implement a locking mechanism to ensure atomicity. +          :param url: The url of the target replica to sync with.          :type url: str          :param creds: optional dictionary giving credentials to authorize the | 
