summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--client/src/leap/soledad/client/api.py8
-rw-r--r--client/src/leap/soledad/client/sqlcipher.py51
-rw-r--r--common/src/leap/soledad/common/tests/test_couch_operations_atomicity.py33
-rw-r--r--common/src/leap/soledad/common/tests/test_server.py2
-rw-r--r--common/src/leap/soledad/common/tests/test_soledad.py2
-rw-r--r--common/src/leap/soledad/common/tests/util.py4
6 files changed, 31 insertions, 69 deletions
diff --git a/client/src/leap/soledad/client/api.py b/client/src/leap/soledad/client/api.py
index 5ba93721..9000029f 100644
--- a/client/src/leap/soledad/client/api.py
+++ b/client/src/leap/soledad/client/api.py
@@ -47,6 +47,7 @@ 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 leap.soledad.common import SHARED_DB_NAME
from leap.soledad.common import soledad_assert
@@ -199,6 +200,7 @@ 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()
@@ -669,10 +671,10 @@ class Soledad(object):
# -----------------------------------------------------------------
sync_url = urlparse.urljoin(self._server_url, 'user-%s' % self.uuid)
- d = self._dbsyncer.sync(
+ d = self.sync_lock.run(lambda: self._dbsyncer.sync(
sync_url,
creds=self._creds,
- defer_decryption=defer_decryption)
+ defer_decryption=defer_decryption))
def _sync_callback(local_gen):
self._last_received_docs = docs = self._dbsyncer.received_docs
@@ -711,7 +713,7 @@ class Soledad(object):
:return: Wether Soledad is currently synchronizing with the server.
:rtype: bool
"""
- return self._dbsyncer.syncing
+ return self.sync_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 a76a35b7..249ffb1a 100644
--- a/client/src/leap/soledad/client/sqlcipher.py
+++ b/client/src/leap/soledad/client/sqlcipher.py
@@ -43,7 +43,6 @@ handled by Soledad should be created by SQLCipher >= 2.0.
"""
import logging
import os
-import threading
import json
import u1db
@@ -51,8 +50,6 @@ from u1db import errors as u1db_errors
from u1db.backends import sqlite_backend
from hashlib import sha256
-from contextlib import contextmanager
-from collections import defaultdict
from functools import partial
from pysqlcipher import dbapi2 as sqlcipher_dbapi2
@@ -427,7 +424,6 @@ class SQLCipherU1DBSync(SQLCipherDatabase):
A dictionary that hold locks which avoid multiple sync attempts from the
same database replica.
"""
- syncing_lock = defaultdict(threading.Lock)
def __init__(self, opts, soledad_crypto, replica_uid, cert_file,
defer_encryption=False, sync_db=None, sync_enc_pool=None):
@@ -532,46 +528,17 @@ class SQLCipherU1DBSync(SQLCipherDatabase):
before the synchronisation was performed.
:rtype: Deferred
"""
- # the following context manager blocks until the syncing lock can be
- # acquired.
- with self._syncer(url, creds=creds) as syncer:
+ syncer = self._get_syncer(url, creds=creds)
- def _record_received_docs(result):
- # beware, closure. syncer is in scope.
- self.received_docs = syncer.received_docs
- return result
+ def _record_received_docs(result):
+ # beware, closure. syncer is in scope.
+ self.received_docs = syncer.received_docs
+ return result
- # XXX could mark the critical section here...
- d = syncer.sync(defer_decryption=defer_decryption)
- d.addCallback(_record_received_docs)
- return d
-
- @contextmanager
- def _syncer(self, url, creds=None):
- """
- Accesor for synchronizer.
-
- As we reuse the same synchronizer for every sync, there can be only
- one instance synchronizing the same database replica at the same time.
- Because of that, this method blocks until the syncing lock can be
- acquired.
-
- :param creds: optional dictionary giving credentials to authorize the
- operation with the server.
- :type creds: dict
- """
- with self.syncing_lock[self._path]:
- syncer = self._get_syncer(url, creds=creds)
- yield syncer
-
- @property
- def syncing(self):
- lock = self.syncing_lock[self._path]
- acquired_lock = lock.acquire(False)
- if acquired_lock is False:
- return True
- lock.release()
- return False
+ # XXX could mark the critical section here...
+ d = syncer.sync(defer_decryption=defer_decryption)
+ d.addCallback(_record_received_docs)
+ return d
def _get_syncer(self, url, creds=None):
"""
diff --git a/common/src/leap/soledad/common/tests/test_couch_operations_atomicity.py b/common/src/leap/soledad/common/tests/test_couch_operations_atomicity.py
index 8f7af8c9..be36ddee 100644
--- a/common/src/leap/soledad/common/tests/test_couch_operations_atomicity.py
+++ b/common/src/leap/soledad/common/tests/test_couch_operations_atomicity.py
@@ -96,6 +96,7 @@ class CouchAtomicityTestCase(CouchDBTestCase, TestCaseWithServer):
replica_uid='replica',
ensure_ddocs=True)
self.tempdir = tempfile.mkdtemp(prefix="leap_tests-")
+ self.startTwistedServer()
def tearDown(self):
self.db.delete_database()
@@ -164,7 +165,6 @@ class CouchAtomicityTestCase(CouchDBTestCase, TestCaseWithServer):
"""
Assert that the sync_log increases accordingly with sequential syncs.
"""
- self.startServer()
sol = self._soledad_instance(
auth_token='auth-token',
server_url=self.getURL())
@@ -321,8 +321,6 @@ class CouchAtomicityTestCase(CouchDBTestCase, TestCaseWithServer):
"""
docs = []
- self.startServer()
-
sol = self._soledad_instance(
auth_token='auth-token',
server_url=self.getURL())
@@ -357,6 +355,7 @@ class CouchAtomicityTestCase(CouchDBTestCase, TestCaseWithServer):
return d
+ @defer.inlineCallbacks
def test_concurrent_syncs_do_not_fail(self):
"""
Assert that concurrent attempts to sync end up being executed
@@ -364,8 +363,6 @@ class CouchAtomicityTestCase(CouchDBTestCase, TestCaseWithServer):
"""
docs = []
- self.startServer()
-
sol = self._soledad_instance(
auth_token='auth-token',
server_url=self.getURL())
@@ -374,21 +371,15 @@ class CouchAtomicityTestCase(CouchDBTestCase, TestCaseWithServer):
for i in xrange(0, REPEAT_TIMES):
d = sol.create_doc({})
d.addCallback(lambda doc: docs.append(doc.doc_id))
- d.addCallback(lambda _: sol.sync())
+ d.addCallback(sol.sync)
deferreds.append(d)
+ yield defer.gatherResults(deferreds, consumeErrors=True)
- def _assert_logs(results):
- transaction_log = self.db._get_transaction_log()
- self.assertEqual(REPEAT_TIMES, len(transaction_log))
- # assert all documents are in the remote log
- self.assertEqual(REPEAT_TIMES, len(docs))
- for doc_id in docs:
- self.assertEqual(
- 1,
- len(filter(lambda t: t[0] == doc_id, transaction_log)))
-
- d = defer.gatherResults(deferreds)
- d.addCallback(_assert_logs)
- d.addCallback(lambda _: sol.close())
-
- return d
+ transaction_log = self.db._get_transaction_log()
+ self.assertEqual(REPEAT_TIMES, len(transaction_log))
+ # assert all documents are in the remote log
+ self.assertEqual(REPEAT_TIMES, len(docs))
+ for doc_id in docs:
+ self.assertEqual(
+ 1,
+ len(filter(lambda t: t[0] == doc_id, transaction_log)))
diff --git a/common/src/leap/soledad/common/tests/test_server.py b/common/src/leap/soledad/common/tests/test_server.py
index 848b68e9..17827486 100644
--- a/common/src/leap/soledad/common/tests/test_server.py
+++ b/common/src/leap/soledad/common/tests/test_server.py
@@ -347,7 +347,7 @@ class EncryptedSyncTestCase(
Test the complete syncing chain between two soledad dbs using a
Soledad server backed by a couch database.
"""
- self.startServer()
+ self.startTwistedServer()
user = 'user-' + uuid4().hex
# instantiate soledad and create a document
diff --git a/common/src/leap/soledad/common/tests/test_soledad.py b/common/src/leap/soledad/common/tests/test_soledad.py
index 8c791672..1217b763 100644
--- a/common/src/leap/soledad/common/tests/test_soledad.py
+++ b/common/src/leap/soledad/common/tests/test_soledad.py
@@ -361,7 +361,7 @@ class SoledadSignalingTestCase(BaseSoledadTest):
def _assert_done_data_sync_signal_emitted(results):
# assert the signal has been emitted
- soledad.client.signal.assert_called_with(
+ soledad.client.events.emit.assert_called_with(
catalog.SOLEDAD_DONE_DATA_SYNC,
ADDRESS,
)
diff --git a/common/src/leap/soledad/common/tests/util.py b/common/src/leap/soledad/common/tests/util.py
index df405010..9800078d 100644
--- a/common/src/leap/soledad/common/tests/util.py
+++ b/common/src/leap/soledad/common/tests/util.py
@@ -275,7 +275,7 @@ class BaseSoledadTest(BaseLeapTest, MockedSharedDBTest):
MockSharedDB = self.get_default_shared_mock(
_put_doc_side_effect)
- return Soledad(
+ soledad = Soledad(
user,
passphrase,
secrets_path=os.path.join(
@@ -287,6 +287,8 @@ class BaseSoledadTest(BaseLeapTest, MockedSharedDBTest):
defer_encryption=self.defer_sync_encryption,
shared_db=MockSharedDB(),
auth_token=auth_token)
+ self.addCleanup(soledad.close)
+ return soledad
def assertGetEncryptedDoc(
self, db, doc_id, doc_rev, content, has_conflicts):