summaryrefslogtreecommitdiff
path: root/src/leap/soledad
diff options
context:
space:
mode:
authordrebs <drebs@leap.se>2012-12-10 18:39:56 -0200
committerdrebs <drebs@leap.se>2012-12-10 18:39:56 -0200
commit002d2bfdbc4ca62733478524ec588cf0aa9f9383 (patch)
tree307bdabb393626205374e1cfccfd705bedd09525 /src/leap/soledad
parent817d4a1dab5cfce6228593ad61951e1593777eeb (diff)
CouchDB backend can put and get objects.
Diffstat (limited to 'src/leap/soledad')
-rw-r--r--src/leap/soledad/backends/couch.py (renamed from src/leap/soledad/backends/couchdb.py)52
-rw-r--r--src/leap/soledad/backends/leap.py1
-rw-r--r--src/leap/soledad/backends/objectstore.py43
-rw-r--r--src/leap/soledad/backends/openstack.py2
-rw-r--r--src/leap/soledad/tests/test_couchdb.py19
5 files changed, 80 insertions, 37 deletions
diff --git a/src/leap/soledad/backends/couchdb.py b/src/leap/soledad/backends/couch.py
index 89b713f9..5586ea9c 100644
--- a/src/leap/soledad/backends/couchdb.py
+++ b/src/leap/soledad/backends/couch.py
@@ -1,7 +1,9 @@
from u1db import errors
from u1db.remote.http_target import HTTPSyncTarget
-from couchdb import *
+from couchdb.client import Server, Document
+from couchdb.http import ResourceNotFound
from soledad.backends.objectstore import ObjectStore
+from soledad.backends.leap import LeapDocument
class CouchDatabase(ObjectStore):
@@ -12,13 +14,18 @@ class CouchDatabase(ObjectStore):
self._url = url
self._full_commit = full_commit
self._session = session
- self._server = couchdb.Server(url=self._url,
- full_commit=self._full_commit,
- session=self._session)
+ self._server = Server(url=self._url,
+ full_commit=self._full_commit,
+ session=self._session)
# this will ensure that transaction and sync logs exist and are
# up-to-date.
- super(CouchDatabase, self)
- self._database = self._server[database]
+ self.set_document_factory(LeapDocument)
+ try:
+ self._database = self._server[database]
+ except ResourceNotFound:
+ self._server.create(database)
+ self._database = self._server[database]
+ super(CouchDatabase, self).__init__()
#-------------------------------------------------------------------------
# implemented methods from Database
@@ -31,13 +38,14 @@ class CouchDatabase(ObjectStore):
for them.
"""
cdoc = self._database.get(doc_id)
- if cdoc is not None:
- content = {}
- for key, value in content:
- if not key in ['_id', '_rev', '_u1db_rev']:
- content[key] = value
- doc = self._factory(doc_id=doc_id, rev=cdoc['_u1db_rev'])
- doc.content = content
+ if cdoc is None:
+ return None
+ content = {}
+ for (key, value) in cdoc.items():
+ if key not in ['_id', '_rev', 'u1db_rev']:
+ content[key] = value
+ doc = self._factory(doc_id=doc_id, rev=cdoc['u1db_rev'])
+ doc.content = content
return doc
def get_all_docs(self, include_deleted=False):
@@ -51,12 +59,15 @@ class CouchDatabase(ObjectStore):
results.append(doc)
return (generation, results)
- def _put_doc(self, doc, new_rev):
+ def _put_doc(self, doc):
# map u1db metadata to couch
content = doc.content
- content['_id'] = doc.doc_id
- content['_u1db_rev'] = new_rev
- self._database.save(doc.content)
+ cdoc = Document()
+ cdoc['_id'] = doc.doc_id
+ cdoc['u1db_rev'] = doc.rev
+ for (key, value) in content.items():
+ cdoc[key] = value
+ self._database.save(cdoc)
def get_sync_target(self):
return CouchSyncTarget(self)
@@ -70,6 +81,13 @@ class CouchDatabase(ObjectStore):
return Synchronizer(self, CouchSyncTarget(url, creds=creds)).sync(
autocreate=autocreate)
+ def _get_u1db_data(self):
+ cdoc = self._database.get(self.U1DB_DATA_DOC_ID)
+ self._sync_log.log = cdoc['sync_log']
+ self._transaction_log.log = cdoc['transaction_log']
+ self._replica_uid = cdoc['replica_uid']
+ self._couch_rev = cdoc['_rev']
+
#-------------------------------------------------------------------------
# Couch specific methods
#-------------------------------------------------------------------------
diff --git a/src/leap/soledad/backends/leap.py b/src/leap/soledad/backends/leap.py
index 2c815632..ce00c8f3 100644
--- a/src/leap/soledad/backends/leap.py
+++ b/src/leap/soledad/backends/leap.py
@@ -7,6 +7,7 @@ from u1db import Document
from u1db.remote.http_target import HTTPSyncTarget
from u1db.remote.http_database import HTTPDatabase
import base64
+from soledad import GPGWrapper
class NoDefaultKey(Exception):
diff --git a/src/leap/soledad/backends/objectstore.py b/src/leap/soledad/backends/objectstore.py
index d9ab7cbd..5bd864c8 100644
--- a/src/leap/soledad/backends/objectstore.py
+++ b/src/leap/soledad/backends/objectstore.py
@@ -1,5 +1,7 @@
+import uuid
from u1db.backends import CommonBackend
from soledad import SyncLog, TransactionLog
+from soledad.backends.leap import LeapDocument
class ObjectStore(CommonBackend):
@@ -45,15 +47,14 @@ class ObjectStore(CommonBackend):
self._check_doc_id(doc.doc_id)
self._check_doc_size(doc)
# put the document
- new_rev = self._allocate_doc_rev(doc.rev)
- self._put_doc(doc, new_rev)
- doc.rev = new_rev
+ doc.rev = self._allocate_doc_rev(doc.rev)
+ self._put_doc(doc)
# update u1db generation and logs
new_gen = self._get_generation() + 1
trans_id = self._allocate_transaction_id()
self._transaction_log.append((new_gen, doc.doc_id, trans_id))
self._set_u1db_data()
- return new_rev
+ return doc.rev
def delete_doc(self, doc):
old_doc = self._get_doc(doc.doc_id, check_for_conflicts=True)
@@ -145,15 +146,16 @@ class ObjectStore(CommonBackend):
"""
if not self._is_initialized():
self._initialize()
- u1db_data = self._get_doc('u1db_data')
- self._sync_log.log = u1db_data.content['sync_log']
- self._transaction_log.log = u1db_data.content['transaction_log']
+ self._get_u1db_data()
+
+ U1DB_DATA_DOC_ID = 'u1db_data'
def _is_initialized(self):
"""
Verify if u1db data exists in store.
"""
- if not self._get_doc('u1db_data'):
+ doc = self._get_doc(self.U1DB_DATA_DOC_ID)
+ if not self._get_doc(self.U1DB_DATA_DOC_ID):
return False
return True
@@ -161,19 +163,22 @@ class ObjectStore(CommonBackend):
"""
Create u1db data object in store.
"""
- content = { 'transaction_log' : [],
- 'sync_log' : [] }
- doc = self.create_doc('u1db_data', content)
+ self._replica_uid = uuid.uuid4().hex
+ doc = self._factory(doc_id=self.U1DB_DATA_DOC_ID)
+ doc.content = { 'transaction_log' : [],
+ 'sync_log' : [],
+ 'replica_uid' : self._replica_uid }
+ self._put_doc(doc)
- def _get_u1db_data(self):
- data = self.get_doc('u1db_data').content
- self._transaction_log = data['transaction_log']
- self._sync_log = data['sync_log']
+ def _get_u1db_data(self, u1db_data_doc_id):
+ NotImplementedError(self._get_u1db_data)
def _set_u1db_data(self):
- doc = self._factory('u1db_data')
- doc.content = { 'transaction_log' : self._transaction_log,
- 'sync_log' : self._sync_log }
- self.put_doc(doc)
+ 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)
diff --git a/src/leap/soledad/backends/openstack.py b/src/leap/soledad/backends/openstack.py
index 5f2a2771..c027231c 100644
--- a/src/leap/soledad/backends/openstack.py
+++ b/src/leap/soledad/backends/openstack.py
@@ -17,7 +17,7 @@ class OpenStackDatabase(ObjectStore):
self._auth_key)
self._get_auth()
# this will ensure transaction and sync logs exist and are up-to-date.
- super(OpenStackDatabase, self)
+ super(OpenStackDatabase, self).__init__()
#-------------------------------------------------------------------------
# implemented methods from Database
diff --git a/src/leap/soledad/tests/test_couchdb.py b/src/leap/soledad/tests/test_couchdb.py
new file mode 100644
index 00000000..58285086
--- /dev/null
+++ b/src/leap/soledad/tests/test_couchdb.py
@@ -0,0 +1,19 @@
+import unittest
+from soledad.backends.couch import CouchDatabase
+
+class CouchTestCase(unittest.TestCase):
+
+ def setUp(self):
+ self._db = CouchDatabase('http://localhost:5984', 'u1db_tests')
+
+ def test_create_get(self):
+ doc1 = self._db.create_doc({"key": "value"}, doc_id="testdoc")
+ doc2 = self._db.get_doc('testdoc')
+ self.assertEqual(doc1, doc2, 'error storing/retrieving document.')
+ self.assertEqual(self._db._get_generation(), 1)
+
+ def tearDown(self):
+ self._db._server.delete('u1db_tests')
+
+if __name__ == '__main__':
+ unittest.main()