From 7aee1e34baeafcc12d44c304bac7fb6fcf3be562 Mon Sep 17 00:00:00 2001 From: drebs Date: Thu, 27 Dec 2012 11:09:39 -0200 Subject: Fix imports and namespaces --- src/leap/soledad/backends/couch.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src/leap/soledad/backends/couch.py') diff --git a/src/leap/soledad/backends/couch.py b/src/leap/soledad/backends/couch.py index ed356fdd..101dd4ea 100644 --- a/src/leap/soledad/backends/couch.py +++ b/src/leap/soledad/backends/couch.py @@ -2,8 +2,8 @@ from u1db import errors from u1db.remote.http_target import HTTPSyncTarget from couchdb.client import Server, Document from couchdb.http import ResourceNotFound -from soledad.backends.objectstore import ObjectStore -from soledad.backends.leap import LeapDocument +from leap.soledad.backends.objectstore import ObjectStore +from leap.soledad.backends.leap_backend import LeapDocument try: import simplejson as json -- cgit v1.2.3 From 9175349330a205f2c799a02722469cc86efd33db Mon Sep 17 00:00:00 2001 From: drebs Date: Tue, 8 Jan 2013 16:12:41 -0200 Subject: Refactor and details of ObjectStore and CouchDatabase --- src/leap/soledad/backends/couch.py | 26 ++++++++++++++++++++++---- 1 file changed, 22 insertions(+), 4 deletions(-) (limited to 'src/leap/soledad/backends/couch.py') diff --git a/src/leap/soledad/backends/couch.py b/src/leap/soledad/backends/couch.py index 101dd4ea..8603a36b 100644 --- a/src/leap/soledad/backends/couch.py +++ b/src/leap/soledad/backends/couch.py @@ -14,7 +14,7 @@ except ImportError: class CouchDatabase(ObjectStore): """A U1DB implementation that uses Couch as its persistence layer.""" - def __init__(self, url, database, full_commit=True, session=None): + def __init__(self, url, database, replica_uid=None, full_commit=True, session=None): """Create a new Couch data container.""" self._url = url self._full_commit = full_commit @@ -22,6 +22,7 @@ class CouchDatabase(ObjectStore): self._server = Server(url=self._url, full_commit=self._full_commit, session=self._session) + self._dbname = database # this will ensure that transaction and sync logs exist and are # up-to-date. self.set_document_factory(LeapDocument) @@ -30,7 +31,7 @@ class CouchDatabase(ObjectStore): except ResourceNotFound: self._server.create(database) self._database = self._server[database] - super(CouchDatabase, self).__init__() + super(CouchDatabase, self).__init__(replica_uid=replica_uid) #------------------------------------------------------------------------- # implemented methods from Database @@ -84,7 +85,15 @@ class CouchDatabase(ObjectStore): return CouchSyncTarget(self) def close(self): - raise NotImplementedError(self.close) + # TODO: fix this method so the connection is properly closed and + # test_close (+tearDown, which deletes the db) works without problems. + self._url = None + self._full_commit = None + self._session = None + #self._server = None + self._database = None + return True + def sync(self, url, creds=None, autocreate=True): from u1db.sync import Synchronizer @@ -100,11 +109,20 @@ class CouchDatabase(ObjectStore): self._replica_uid = content['replica_uid'] self._couch_rev = cdoc['_rev'] + def _set_u1db_data(self): + doc = self._factory(doc_id=self.U1DB_DATA_DOC_ID) + doc.content = { 'transaction_log' : self._transaction_log.log, + 'sync_log' : self._sync_log.log, + 'replica_uid' : self._replica_uid, + '_rev' : self._couch_rev} + self._put_doc(doc) + #------------------------------------------------------------------------- # Couch specific methods #------------------------------------------------------------------------- - # no specific methods so far. + def delete_database(self): + del(self._server[self._dbname]) class CouchSyncTarget(HTTPSyncTarget): -- cgit v1.2.3 From 9b7728b80027f35c013a449b884235cf8eac503c Mon Sep 17 00:00:00 2001 From: drebs Date: Wed, 9 Jan 2013 11:46:58 -0200 Subject: CouchDatabase passes u1db LocalDatabaseTests. --- src/leap/soledad/backends/couch.py | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) (limited to 'src/leap/soledad/backends/couch.py') diff --git a/src/leap/soledad/backends/couch.py b/src/leap/soledad/backends/couch.py index 8603a36b..14021737 100644 --- a/src/leap/soledad/backends/couch.py +++ b/src/leap/soledad/backends/couch.py @@ -58,6 +58,8 @@ class CouchDatabase(ObjectStore): generation = self._get_generation() results = [] for doc_id in self._database: + if doc_id == self.U1DB_DATA_DOC_ID: + continue doc = self._get_doc(doc_id) if doc.content is None and not include_deleted: continue @@ -106,13 +108,15 @@ class CouchDatabase(ObjectStore): content = json.loads(cdoc['u1db_json']) self._sync_log.log = content['sync_log'] self._transaction_log.log = content['transaction_log'] + self._conflict_log.log = content['conflict_log'] self._replica_uid = content['replica_uid'] self._couch_rev = cdoc['_rev'] def _set_u1db_data(self): doc = self._factory(doc_id=self.U1DB_DATA_DOC_ID) - doc.content = { 'transaction_log' : self._transaction_log.log, - 'sync_log' : self._sync_log.log, + doc.content = { 'sync_log' : self._sync_log.log, + 'transaction_log' : self._transaction_log.log, + 'conflict_log' : self._conflict_log.log, 'replica_uid' : self._replica_uid, '_rev' : self._couch_rev} self._put_doc(doc) -- cgit v1.2.3 From 8909a16a12c17098ae8d5ecd31af6765b543622c Mon Sep 17 00:00:00 2001 From: drebs Date: Thu, 10 Jan 2013 13:18:48 -0200 Subject: CouchDatabase passes all relevant u1db tests. --- src/leap/soledad/backends/couch.py | 34 ++++++++++++++++++++++++++++------ 1 file changed, 28 insertions(+), 6 deletions(-) (limited to 'src/leap/soledad/backends/couch.py') diff --git a/src/leap/soledad/backends/couch.py b/src/leap/soledad/backends/couch.py index 14021737..f071cfad 100644 --- a/src/leap/soledad/backends/couch.py +++ b/src/leap/soledad/backends/couch.py @@ -1,6 +1,8 @@ +import uuid +from base64 import b64encode, b64decode from u1db import errors from u1db.remote.http_target import HTTPSyncTarget -from couchdb.client import Server, Document +from couchdb.client import Server, Document as CouchDocument from couchdb.http import ResourceNotFound from leap.soledad.backends.objectstore import ObjectStore from leap.soledad.backends.leap_backend import LeapDocument @@ -46,7 +48,13 @@ class CouchDatabase(ObjectStore): cdoc = self._database.get(doc_id) if cdoc is None: return None - doc = self._factory(doc_id=doc_id, rev=cdoc['u1db_rev']) + has_conflicts = False + if check_for_conflicts: + has_conflicts = self._has_conflicts(doc_id) + doc = self._factory( + doc_id=doc_id, + rev=cdoc['u1db_rev'], + has_conflicts=has_conflicts) if cdoc['u1db_json'] is not None: doc.content = json.loads(cdoc['u1db_json']) else: @@ -60,7 +68,7 @@ class CouchDatabase(ObjectStore): for doc_id in self._database: if doc_id == self.U1DB_DATA_DOC_ID: continue - doc = self._get_doc(doc_id) + doc = self._get_doc(doc_id, check_for_conflicts=True) if doc.content is None and not include_deleted: continue results.append(doc) @@ -68,7 +76,7 @@ class CouchDatabase(ObjectStore): def _put_doc(self, doc): # prepare couch's Document - cdoc = Document() + cdoc = CouchDocument() cdoc['_id'] = doc.doc_id # we have to guarantee that couch's _rev is cosistent old_cdoc = self._database.get(doc.doc_id) @@ -81,6 +89,7 @@ class CouchDatabase(ObjectStore): cdoc['u1db_json'] = doc.get_json() else: cdoc['u1db_json'] = None + # save doc in db self._database.save(cdoc) def get_sync_target(self): @@ -103,12 +112,22 @@ class CouchDatabase(ObjectStore): return Synchronizer(self, CouchSyncTarget(url, creds=creds)).sync( autocreate=autocreate) + def _initialize(self): + if self._replica_uid is None: + self._replica_uid = uuid.uuid4().hex + doc = self._factory(doc_id=self.U1DB_DATA_DOC_ID) + doc.content = { 'sync_log' : [], + 'transaction_log' : [], + 'conflict_log' : b64encode(json.dumps([])), + 'replica_uid' : self._replica_uid } + self._put_doc(doc) + def _get_u1db_data(self): cdoc = self._database.get(self.U1DB_DATA_DOC_ID) content = json.loads(cdoc['u1db_json']) self._sync_log.log = content['sync_log'] self._transaction_log.log = content['transaction_log'] - self._conflict_log.log = content['conflict_log'] + self._conflict_log.log = json.loads(b64decode(content['conflict_log'])) self._replica_uid = content['replica_uid'] self._couch_rev = cdoc['_rev'] @@ -116,7 +135,10 @@ class CouchDatabase(ObjectStore): doc = self._factory(doc_id=self.U1DB_DATA_DOC_ID) doc.content = { 'sync_log' : self._sync_log.log, 'transaction_log' : self._transaction_log.log, - 'conflict_log' : self._conflict_log.log, + # Here, the b64 encode ensures that document content + # does not cause strange behaviour in couchdb because + # of encoding. + 'conflict_log' : b64encode(json.dumps(self._conflict_log.log)), 'replica_uid' : self._replica_uid, '_rev' : self._couch_rev} self._put_doc(doc) -- cgit v1.2.3 From 7c3b6c5c0fa7a8bd1e15a302bfe0d30e347316be Mon Sep 17 00:00:00 2001 From: drebs Date: Mon, 14 Jan 2013 13:23:44 -0200 Subject: CouchSyncTarget works as a LocalSyncTarget. --- src/leap/soledad/backends/couch.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'src/leap/soledad/backends/couch.py') diff --git a/src/leap/soledad/backends/couch.py b/src/leap/soledad/backends/couch.py index f071cfad..5cde4805 100644 --- a/src/leap/soledad/backends/couch.py +++ b/src/leap/soledad/backends/couch.py @@ -1,7 +1,8 @@ +import sys import uuid from base64 import b64encode, b64decode from u1db import errors -from u1db.remote.http_target import HTTPSyncTarget +from u1db.sync import LocalSyncTarget from couchdb.client import Server, Document as CouchDocument from couchdb.http import ResourceNotFound from leap.soledad.backends.objectstore import ObjectStore @@ -108,7 +109,6 @@ class CouchDatabase(ObjectStore): def sync(self, url, creds=None, autocreate=True): from u1db.sync import Synchronizer - from u1db.remote.http_target import CouchSyncTarget return Synchronizer(self, CouchSyncTarget(url, creds=creds)).sync( autocreate=autocreate) @@ -150,7 +150,8 @@ class CouchDatabase(ObjectStore): def delete_database(self): del(self._server[self._dbname]) -class CouchSyncTarget(HTTPSyncTarget): + +class CouchSyncTarget(LocalSyncTarget): def get_sync_info(self, source_replica_uid): source_gen, source_trans_id = self._db._get_replica_gen_and_trans_id( @@ -168,4 +169,3 @@ class CouchSyncTarget(HTTPSyncTarget): source_replica_uid, source_replica_generation, source_replica_transaction_id) - -- cgit v1.2.3 From e83572610574e8d3d96c0117fdb45764ffbeb538 Mon Sep 17 00:00:00 2001 From: drebs Date: Wed, 16 Jan 2013 09:55:27 -0200 Subject: Fix copy_database for couch tests. --- src/leap/soledad/backends/couch.py | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) (limited to 'src/leap/soledad/backends/couch.py') diff --git a/src/leap/soledad/backends/couch.py b/src/leap/soledad/backends/couch.py index 5cde4805..78026af8 100644 --- a/src/leap/soledad/backends/couch.py +++ b/src/leap/soledad/backends/couch.py @@ -41,10 +41,8 @@ class CouchDatabase(ObjectStore): #------------------------------------------------------------------------- def _get_doc(self, doc_id, check_for_conflicts=False): - """Get just the document content, without fancy handling. - - Conflicts do not happen on server side, so there's no need to check - for them. + """ + Get just the document content, without fancy handling. """ cdoc = self._database.get(doc_id) if cdoc is None: -- cgit v1.2.3