summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorVictor Shyba <victor.shyba@gmail.com>2015-10-20 15:31:09 -0300
committerVictor Shyba <victor.shyba@gmail.com>2015-11-03 12:41:37 -0300
commit9830bd00964a1c83cfc92151446adda6f14fbc54 (patch)
tree4a606f9a82ce63886b71a0a06775d34cac10709a
parentf0b96af943dcb6c8cde4f6d4280186d78c78096c (diff)
[refactor] CouchDocument is now ServerDocument
As SoledadBackend is intended to be database agnostic, a new generic document is now used instead of the old one made for CouchDB. The only attribute that really relates to couch was couch_rev, removed on this commit as it can be set on CouchDatabase implementation when needed.
-rw-r--r--common/src/leap/soledad/common/backend.py43
-rw-r--r--common/src/leap/soledad/common/couch/__init__.py24
-rw-r--r--common/src/leap/soledad/common/document.py25
-rw-r--r--common/src/leap/soledad/common/tests/test_couch.py6
-rw-r--r--scripts/profiling/mail/mx.py5
5 files changed, 44 insertions, 59 deletions
diff --git a/common/src/leap/soledad/common/backend.py b/common/src/leap/soledad/common/backend.py
index cb37b4ac..1cbf3d57 100644
--- a/common/src/leap/soledad/common/backend.py
+++ b/common/src/leap/soledad/common/backend.py
@@ -29,7 +29,7 @@ from u1db.errors import (
)
from u1db.backends import CommonBackend
from u1db.backends import CommonSyncTarget
-from leap.soledad.common.document import CouchDocument
+from leap.soledad.common.document import ServerDocument
class SoledadBackend(CommonBackend):
@@ -48,7 +48,7 @@ class SoledadBackend(CommonBackend):
:type replica_uid: str
"""
# save params
- self._factory = CouchDocument
+ self._factory = ServerDocument
self._real_replica_uid = None
self._cache = None
self._dbname = database._dbname
@@ -83,7 +83,7 @@ class SoledadBackend(CommonBackend):
def delete_database(self):
"""
- Delete a U1DB CouchDB database.
+ Delete a U1DB database.
"""
self._database.delete_database()
@@ -221,7 +221,7 @@ class SoledadBackend(CommonBackend):
:type check_for_conflicts: bool
:return: The document.
- :rtype: CouchDocument
+ :rtype: ServerDocument
"""
return self._database._get_doc(doc_id, check_for_conflicts)
@@ -237,7 +237,7 @@ class SoledadBackend(CommonBackend):
:type include_deleted: bool
:return: A document object.
- :rtype: CouchDocument.
+ :rtype: ServerDocument.
"""
doc = self._get_doc(doc_id, check_for_conflicts=True)
if doc is None:
@@ -255,25 +255,25 @@ class SoledadBackend(CommonBackend):
documents will not be included in the results.
:type include_deleted: bool
- :return: (generation, [CouchDocument])
+ :return: (generation, [ServerDocument])
The current generation of the database, followed by a list of all
the documents in the database.
- :rtype: (int, [CouchDocument])
+ :rtype: (int, [ServerDocument])
"""
return self._database.get_all_docs(include_deleted)
def _put_doc(self, old_doc, doc):
"""
- Put the document in the Couch backend database.
+ Put the document in the backend database.
Note that C{old_doc} must have been fetched with the parameter
C{check_for_conflicts} equal to True, so we can properly update the
new document using the conflict information from the old one.
:param old_doc: The old document version.
- :type old_doc: CouchDocument
+ :type old_doc: ServerDocument
:param doc: The document to be put.
- :type doc: CouchDocument
+ :type doc: ServerDocument
"""
last_transaction =\
self._database.save_document(old_doc, doc,
@@ -348,7 +348,7 @@ class SoledadBackend(CommonBackend):
This will also set doc.content to None.
:param doc: The document to mark as deleted.
- :type doc: CouchDocument.
+ :type doc: ServerDocument.
:raise DocumentDoesNotExist: Raised if the document does not
exist.
@@ -372,20 +372,17 @@ class SoledadBackend(CommonBackend):
self._put_doc(old_doc, doc)
return new_rev
- def get_doc_conflicts(self, doc_id, couch_rev=None):
+ def get_doc_conflicts(self, doc_id):
"""
Get the conflicted versions of a document.
- If the C{couch_rev} parameter is not None, conflicts for a specific
- document's couch revision are returned.
-
- :param couch_rev: The couch document revision.
- :type couch_rev: str
+ :param doc_id: The document id.
+ :type doc_id: str
:return: A list of conflicted versions of the document.
:rtype: list
"""
- return self._database.get_doc_conflicts(doc_id, couch_rev)
+ return self._database.get_doc_conflicts(doc_id)
def _get_replica_gen_and_trans_id(self, other_replica_uid):
"""
@@ -478,7 +475,7 @@ class SoledadBackend(CommonBackend):
Add a conflict and force a document put.
:param doc: The document to be put.
- :type doc: CouchDocument
+ :type doc: ServerDocument
"""
my_doc = self._get_doc(doc.doc_id)
self._prune_conflicts(doc, vectorclock.VectorClockRev(doc.rev))
@@ -499,7 +496,7 @@ class SoledadBackend(CommonBackend):
the time you GET_DOC_CONFLICTS until the point where you RESOLVE)
:param doc: A Document with the new content to be inserted.
- :type doc: CouchDocument
+ :type doc: ServerDocument
:param conflicted_doc_revs: A list of revisions that the new content
supersedes.
:type conflicted_doc_revs: [str]
@@ -564,7 +561,7 @@ class SoledadBackend(CommonBackend):
remote copy is never updated again.)
:param doc: A document object
- :type doc: CouchDocument
+ :type doc: ServerDocument
:param save_conflict: If this document is a conflict, do you want to
save it as a conflict, or just ignore it.
:type save_conflict: bool
@@ -596,7 +593,7 @@ class SoledadBackend(CommonBackend):
'converged', at_gen is the insertion/current generation.
:rtype: (str, int)
"""
- if not isinstance(doc, CouchDocument):
+ if not isinstance(doc, ServerDocument):
doc = self._factory(doc.doc_id, doc.rev, doc.get_json())
my_doc = self._get_doc(doc.doc_id, check_for_conflicts=True)
if my_doc:
@@ -636,7 +633,7 @@ class SoledadBackend(CommonBackend):
Originally in u1db.CommonBackend
:param doc: The document to have conflicts pruned.
- :type doc: CouchDocument
+ :type doc: ServerDocument
:param doc_vcr: A vector clock representing the current document's
revision.
:type doc_vcr: u1db.vectorclock.VectorClock
diff --git a/common/src/leap/soledad/common/couch/__init__.py b/common/src/leap/soledad/common/couch/__init__.py
index 727f033f..1780cecd 100644
--- a/common/src/leap/soledad/common/couch/__init__.py
+++ b/common/src/leap/soledad/common/couch/__init__.py
@@ -1,5 +1,5 @@
# -*- coding: utf-8 -*-
-# couch.py
+# __init__.py
# Copyright (C) 2013 LEAP
#
# This program is free software: you can redistribute it and/or modify
@@ -54,7 +54,7 @@ from leap.soledad.common import ddocs
from leap.soledad.common.errors import raise_server_error
from leap.soledad.common.errors import raise_missing_design_doc_error
from leap.soledad.common.errors import InvalidURLError
-from leap.soledad.common.document import CouchDocument
+from leap.soledad.common.document import ServerDocument
from leap.soledad.common.backend import SoledadBackend
@@ -78,8 +78,8 @@ def list_users_dbs(couch_url):
return users
-# monkey-patch the u1db http app to use CouchDocument
-http_app.Document = CouchDocument
+# monkey-patch the u1db http app to use ServerDocument
+http_app.Document = ServerDocument
@contextmanager
@@ -254,10 +254,10 @@ class CouchDatabase(object):
documents will not be included in the results.
:type include_deleted: bool
- :return: (generation, [CouchDocument])
+ :return: (generation, [ServerDocument])
The current generation of the database, followed by a list of all
the documents in the database.
- :rtype: (int, [CouchDocument])
+ :rtype: (int, [ServerDocument])
"""
generation, _ = self._get_generation_info()
@@ -316,7 +316,7 @@ class CouchDatabase(object):
:type check_for_conflicts: bool
:return: The document.
- :rtype: CouchDocument
+ :rtype: ServerDocument
"""
# get document with all attachments (u1db content and eventual
# conflicts)
@@ -333,7 +333,7 @@ class CouchDatabase(object):
# restrict to u1db documents
if 'u1db_rev' not in result:
return None
- doc = CouchDocument(doc_id, result['u1db_rev'])
+ doc = ServerDocument(doc_id, result['u1db_rev'])
# set contents or make tombstone
if '_attachments' not in result \
or 'u1db_content' not in result['_attachments']:
@@ -368,7 +368,7 @@ class CouchDatabase(object):
"""
conflicts = []
for doc_rev, content in attached_conflicts:
- doc = CouchDocument(doc_id, doc_rev)
+ doc = ServerDocument(doc_id, doc_rev)
if content is None:
doc.make_tombstone()
else:
@@ -652,9 +652,9 @@ class CouchDatabase(object):
new document using the conflict information from the old one.
:param old_doc: The old document version.
- :type old_doc: CouchDocument
+ :type old_doc: ServerDocument
:param doc: The document to be put.
- :type doc: CouchDocument
+ :type doc: ServerDocument
:raise RevisionConflict: Raised when trying to update a document but
couch revisions mismatch.
@@ -712,7 +712,7 @@ class CouchDatabase(object):
'_attachments': attachments,
}
# if we are updating a doc we have to add the couch doc revision
- if old_doc is not None:
+ if old_doc is not None and hasattr(old_doc, 'couch_rev'):
couch_doc['_rev'] = old_doc.couch_rev
# prepare the multipart PUT
buf = StringIO()
diff --git a/common/src/leap/soledad/common/document.py b/common/src/leap/soledad/common/document.py
index 05458906..20510544 100644
--- a/common/src/leap/soledad/common/document.py
+++ b/common/src/leap/soledad/common/document.py
@@ -110,18 +110,17 @@ class SoledadDocument(Document):
doc="Wrapper to ensure `doc.rev` is always returned as bytes.")
-class CouchDocument(SoledadDocument):
+class ServerDocument(SoledadDocument):
"""
- This is the document used for maintaining the Couch backend.
+ This is the document used by server to hold conflicts and transactions
+ on a database.
- A CouchDocument can fetch and manipulate conflicts and also holds a
- reference to the couch document revision. This data is used to ensure an
- atomic and consistent update of the database.
+ The goal is to ensure an atomic and consistent update of the database.
"""
def __init__(self, doc_id=None, rev=None, json='{}', has_conflicts=False):
"""
- Container for handling a document that is stored in couch backend.
+ Container for handling a document that stored on server.
:param doc_id: The unique document identifier.
:type doc_id: str
@@ -133,7 +132,6 @@ class CouchDocument(SoledadDocument):
:type has_conflicts: bool
"""
SoledadDocument.__init__(self, doc_id, rev, json, has_conflicts)
- self.couch_rev = None
self.transactions = None
self._conflicts = None
@@ -142,7 +140,7 @@ class CouchDocument(SoledadDocument):
Get the conflicted versions of the document.
:return: The conflicted versions of the document.
- :rtype: [CouchDocument]
+ :rtype: [ServerDocument]
"""
return self._conflicts or []
@@ -161,7 +159,7 @@ class CouchDocument(SoledadDocument):
Add a conflict to this document.
:param doc: The conflicted version to be added.
- :type doc: CouchDocument
+ :type doc: Document
"""
if self._conflicts is None:
raise Exception("Fetch conflicts first!")
@@ -181,12 +179,3 @@ class CouchDocument(SoledadDocument):
lambda doc: doc.rev not in conflict_revs,
self._conflicts)
self.has_conflicts = len(self._conflicts) > 0
-
- def update(self, new_doc):
- # update info
- self.rev = new_doc.rev
- if new_doc.is_tombstone():
- self.is_tombstone()
- else:
- self.content = new_doc.content
- self.has_conflicts = new_doc.has_conflicts
diff --git a/common/src/leap/soledad/common/tests/test_couch.py b/common/src/leap/soledad/common/tests/test_couch.py
index 1634d30c..01f0587b 100644
--- a/common/src/leap/soledad/common/tests/test_couch.py
+++ b/common/src/leap/soledad/common/tests/test_couch.py
@@ -36,7 +36,7 @@ from u1db import SyncTarget
from u1db import vectorclock
from leap.soledad.common import couch
-from leap.soledad.common import backend
+from leap.soledad.common.document import ServerDocument
from leap.soledad.common import errors
from leap.soledad.common.tests import u1db_tests as tests
@@ -47,8 +47,6 @@ from leap.soledad.common.tests.util import sync_via_synchronizer
from leap.soledad.common.tests.u1db_tests import test_backends
from leap.soledad.common.tests.u1db_tests import DatabaseBaseTests
-from u1db.backends.inmemory import InMemoryIndex
-
# -----------------------------------------------------------------------------
# The following tests come from `u1db.tests.test_common_backend`.
@@ -134,7 +132,7 @@ def copy_couch_database_for_test(test, db):
def make_document_for_test(test, doc_id, rev, content, has_conflicts=False):
- return couch.CouchDocument(
+ return ServerDocument(
doc_id, rev, content, has_conflicts=has_conflicts)
diff --git a/scripts/profiling/mail/mx.py b/scripts/profiling/mail/mx.py
index b6a1e5cf..55084a40 100644
--- a/scripts/profiling/mail/mx.py
+++ b/scripts/profiling/mail/mx.py
@@ -5,7 +5,7 @@ import timeit
from leap.keymanager import openpgp
-from leap.soledad.common.couch import CouchDocument
+from leap.soledad.common.document import ServerDocument
from leap.soledad.common.crypto import (
EncryptionSchemes,
ENC_JSON_KEY,
@@ -47,7 +47,7 @@ def get_enc_json(pubkey, message):
def get_new_doc(enc_json):
- doc = CouchDocument(doc_id=str(uuid.uuid4()))
+ doc = ServerDocument(doc_id=str(uuid.uuid4()))
doc.content = {
'incoming': True,
ENC_SCHEME_KEY: EncryptionSchemes.PUBKEY,
@@ -71,6 +71,7 @@ def put_lots_of_messages(db, number):
log("Populating database with %d encrypted messages... "
% number, line_break=False)
pubkey = get_pubkey()
+
def _put_one_message():
put_one_message(pubkey, db)
time = timeit.timeit(_put_one_message, number=number)