diff options
Diffstat (limited to 'src/leap')
| -rw-r--r-- | src/leap/soledad/__init__.py | 2 | ||||
| -rw-r--r-- | src/leap/soledad/backends/objectstore.py | 153 | ||||
| -rw-r--r-- | src/leap/soledad/backends/openstack.py | 143 | 
3 files changed, 157 insertions, 141 deletions
diff --git a/src/leap/soledad/__init__.py b/src/leap/soledad/__init__.py index 7f742a89..78f1f768 100644 --- a/src/leap/soledad/__init__.py +++ b/src/leap/soledad/__init__.py @@ -44,7 +44,7 @@ class GPGWrapper():  #---------------------------------------------------------------------------- -# u1db Transaction and Sync logs as JSON structures. +# u1db Transaction and Sync logs.  #----------------------------------------------------------------------------  class SimpleLog(object): diff --git a/src/leap/soledad/backends/objectstore.py b/src/leap/soledad/backends/objectstore.py new file mode 100644 index 00000000..e36df72d --- /dev/null +++ b/src/leap/soledad/backends/objectstore.py @@ -0,0 +1,153 @@ +from u1db.backends import CommonBackend + + +class ObjectStore(CommonBackend): + +    def __init__(self): +        self._sync_log = SyncLog() +        self._transaction_log = TransactionLog() + +    #------------------------------------------------------------------------- +    # implemented methods from Database +    #------------------------------------------------------------------------- + +    def set_document_factory(self, factory): +        self._factory = factory + +    def set_document_size_limit(self, limit): +        raise NotImplementedError(self.set_document_size_limit) + +    def whats_changed(self, old_generation=0): +        self._get_u1db_data() +        return self._transaction_log.whats_changed(old_generation) + +    def get_doc(self, doc_id, include_deleted=False): +        doc = self._get_doc(doc_id, check_for_conflicts=True) +        if doc is None: +            return None +        if doc.is_tombstone() and not include_deleted: +            return None +        return doc + +    def delete_doc(self, doc): +        old_doc = self._get_doc(doc.doc_id, check_for_conflicts=True) +        if old_doc is None: +            raise errors.DocumentDoesNotExist +        if old_doc.rev != doc.rev: +            raise errors.RevisionConflict() +        if old_doc.is_tombstone(): +            raise errors.DocumentAlreadyDeleted +        if old_doc.has_conflicts: +            raise errors.ConflictedDoc() +        new_rev = self._allocate_doc_rev(doc.rev) +        doc.rev = new_rev +        doc.make_tombstone() +        self._put_doc(olddoc) +        return new_rev + +    # start of index-related methods: these are not supported by this backend. + +    def create_index(self, index_name, *index_expressions): +        return False + +    def delete_index(self, index_name): +        return False + +    def list_indexes(self): +        return [] + +    def get_from_index(self, index_name, *key_values): +        return [] + +    def get_range_from_index(self, index_name, start_value=None, +                             end_value=None): +        return [] + +    def get_index_keys(self, index_name): +        return [] + +    # end of index-related methods: these are not supported by this backend. + +    def get_doc_conflicts(self, doc_id): +        return [] + +    def resolve_doc(self, doc, conflicted_doc_revs): +        raise NotImplementedError(self.resolve_doc) + +    def _get_replica_gen_and_trans_id(self, other_replica_uid): +        self._get_u1db_data() +        return self._sync_log.get_replica_gen_and_trans_id(other_replica_uid) + +    def _set_replica_gen_and_trans_id(self, other_replica_uid, +                                      other_generation, other_transaction_id): +        self._get_u1db_data() +        self._sync_log.set_replica_gen_and_trans_id(other_replica_uid, +                                                    other_generation, +                                                    other_transaction_id) +        self._set_u1db_data() + +    #------------------------------------------------------------------------- +    # implemented methods from CommonBackend +    #------------------------------------------------------------------------- + +    def _get_generation(self): +        self._get_u1db_data() +        return self._transaction_log.get_generation() + +    def _get_generation_info(self): +        self._get_u1db_data() +        return self._transaction_log.get_generation_info() + +    def _has_conflicts(self, doc_id): +        # Documents never have conflicts on server. +        return False + +    def _put_and_update_indexes(self, doc_id, old_doc, new_rev, content): +        raise NotImplementedError(self._put_and_update_indexes) + + +    def _get_trans_id_for_gen(self, generation): +        self._get_u1db_data() +        trans_id = self._transaction_log.get_trans_id_for_gen(generation) +        if trans_id is None: +            raise errors.InvalidGeneration +        return trans_id + +    def _ensure_u1db_data(self): +        """ +        Guarantee that u1db data exists in store. +        """ +        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'] + +    def _is_initialized(self): +        """ +        Verify if u1db data exists in store. +        """ +        if not self._get_doc('u1db_data'): +            return False +        return True + +    def _initialize(self): +        """ +        Create u1db data object in store. +        """ +        content = { 'transaction_log' : [], +                    'sync_log' : [] } +        doc = self.create_doc('u1db_data', content) + +    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 _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) + + diff --git a/src/leap/soledad/backends/openstack.py b/src/leap/soledad/backends/openstack.py index 6c971485..f8563d81 100644 --- a/src/leap/soledad/backends/openstack.py +++ b/src/leap/soledad/backends/openstack.py @@ -1,15 +1,16 @@ -from leap import *  from u1db import errors  from u1db.backends import CommonBackend  from u1db.remote.http_target import HTTPSyncTarget  from swiftclient import client +from soledad.backends.objectstore import ObjectStore -class OpenStackDatabase(CommonBackend): +class OpenStackDatabase(ObjectStore):      """A U1DB implementation that uses OpenStack as its persistence layer."""      def __init__(self, auth_url, user, auth_key, container):          """Create a new OpenStack data container.""" +        super(OpenStackDatabase, self)          self._auth_url = auth_url          self._user = user          self._auth_key = auth_key @@ -24,16 +25,6 @@ class OpenStackDatabase(CommonBackend):      # implemented methods from Database      #------------------------------------------------------------------------- -    def set_document_factory(self, factory): -        self._factory = factory - -    def set_document_size_limit(self, limit): -        raise NotImplementedError(self.set_document_size_limit) - -    def whats_changed(self, old_generation=0): -        self._get_u1db_data() -        return self._transaction_log.whats_changed(old_generation) -      def _get_doc(self, doc_id, check_for_conflicts=False):          """Get just the document content, without fancy handling. @@ -47,14 +38,6 @@ class OpenStackDatabase(CommonBackend):          except swiftclient.ClientException:              return None -    def get_doc(self, doc_id, include_deleted=False): -        doc = self._get_doc(doc_id, check_for_conflicts=True) -        if doc is None: -            return None -        if doc.is_tombstone() and not include_deleted: -            return None -        return doc -      def get_all_docs(self, include_deleted=False):          """Get all documents from the database."""          generation = self._get_generation() @@ -84,51 +67,6 @@ class OpenStackDatabase(CommonBackend):          self._set_u1db_data()          return new_rev -    def delete_doc(self, doc): -        old_doc = self._get_doc(doc.doc_id, check_for_conflicts=True) -        if old_doc is None: -            raise errors.DocumentDoesNotExist -        if old_doc.rev != doc.rev: -            raise errors.RevisionConflict() -        if old_doc.is_tombstone(): -            raise errors.DocumentAlreadyDeleted -        if old_doc.has_conflicts: -            raise errors.ConflictedDoc() -        new_rev = self._allocate_doc_rev(doc.rev) -        doc.rev = new_rev -        doc.make_tombstone() -        self._put_doc(olddoc) -        return new_rev - -    # start of index-related methods: these are not supported by this backend. - -    def create_index(self, index_name, *index_expressions): -        return False - -    def delete_index(self, index_name): -        return False - -    def list_indexes(self): -        return [] - -    def get_from_index(self, index_name, *key_values): -        return [] - -    def get_range_from_index(self, index_name, start_value=None, -                             end_value=None): -        return [] - -    def get_index_keys(self, index_name): -        return [] - -    # end of index-related methods: these are not supported by this backend. - -    def get_doc_conflicts(self, doc_id): -        return [] - -    def resolve_doc(self, doc, conflicted_doc_revs): -        raise NotImplementedError(self.resolve_doc) -      def get_sync_target(self):          return OpenStackSyncTarget(self) @@ -141,89 +79,14 @@ class OpenStackDatabase(CommonBackend):          return Synchronizer(self, OpenStackSyncTarget(url, creds=creds)).sync(              autocreate=autocreate) -    def _get_replica_gen_and_trans_id(self, other_replica_uid): -        self._get_u1db_data() -        return self._sync_log.get_replica_gen_and_trans_id(other_replica_uid) - -    def _set_replica_gen_and_trans_id(self, other_replica_uid, -                                      other_generation, other_transaction_id): -        self._get_u1db_data() -        self._sync_log.set_replica_gen_and_trans_id(other_replica_uid, -                                                    other_generation, -                                                    other_transaction_id) -        self._set_u1db_data() - -    #------------------------------------------------------------------------- -    # implemented methods from CommonBackend -    #------------------------------------------------------------------------- - -    def _get_generation(self): -        self._get_u1db_data() -        return self._transaction_log.get_generation() - -    def _get_generation_info(self): -        self._get_u1db_data() -        return self._transaction_log.get_generation_info() - -    def _has_conflicts(self, doc_id): -        # Documents never have conflicts on server. -        return False - -    def _put_and_update_indexes(self, doc_id, old_doc, new_rev, content): -        raise NotImplementedError(self._put_and_update_indexes) - - -    def _get_trans_id_for_gen(self, generation): -        self._get_u1db_data() -        trans_id = self._transaction_log.get_trans_id_for_gen(generation) -        if trans_id is None: -            raise errors.InvalidGeneration -        return trans_id -      #-------------------------------------------------------------------------      # OpenStack specific methods      #------------------------------------------------------------------------- -    def _ensure_u1db_data(self): -        """ -        Guarantee that u1db data exists in store. -        """ -        if self._is_initialized(): -            return -        self._initialize() - -    def _is_initialized(self): -        """ -        Verify if u1db data exists in store. -        """ -        if not self._get_doc('u1db_data'): -            return False -        return True - -    def _initialize(self): -        """ -        Create u1db data object in store. -        """ -        content = { 'transaction_log' : [], -                    'sync_log' : [] } -        doc = self.create_doc('u1db_data', content) -      def _get_auth(self):          self._url, self._auth_token = self._connection.get_auth()          return self._url, self.auth_token -    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 _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) - -  class OpenStackSyncTarget(HTTPSyncTarget):      def get_sync_info(self, source_replica_uid):  | 
