diff options
Diffstat (limited to 'soledad/backends/objectstore.py')
| -rw-r--r-- | soledad/backends/objectstore.py | 135 | 
1 files changed, 135 insertions, 0 deletions
| diff --git a/soledad/backends/objectstore.py b/soledad/backends/objectstore.py new file mode 100644 index 00000000..7c5d1177 --- /dev/null +++ b/soledad/backends/objectstore.py @@ -0,0 +1,135 @@ +""" +Abstract U1DB backend to handle storage using object stores (like CouchDB, for +example. + +Right now, this is only used by CouchDatabase backend, but can also be +extended to implement OpenStack or Amazon S3 storage, for example. +""" + +from u1db.backends.inmemory import ( +    InMemoryDatabase, +    InMemorySyncTarget, +) +from u1db import errors + + +class ObjectStoreDatabase(InMemoryDatabase): +    """ +    A backend for storing u1db data in an object store. +    """ + +    @classmethod +    def open_database(cls, url, create, document_factory=None): +        raise NotImplementedError(cls.open_database) + +    def __init__(self, replica_uid=None, document_factory=None): +        super(ObjectStoreDatabase, self).__init__( +            replica_uid, +            document_factory=document_factory) +        # sync data in memory with data in object store +        if not self._get_doc(self.U1DB_DATA_DOC_ID): +            self._init_u1db_data() +        self._fetch_u1db_data() + +    #------------------------------------------------------------------------- +    # methods from Database +    #------------------------------------------------------------------------- + +    def _set_replica_uid(self, replica_uid): +        super(ObjectStoreDatabase, self)._set_replica_uid(replica_uid) +        self._store_u1db_data() + +    def _put_doc(self, doc): +        raise NotImplementedError(self._put_doc) + +    def _get_doc(self, doc): +        raise NotImplementedError(self._get_doc) + +    def get_all_docs(self, include_deleted=False): +        raise NotImplementedError(self.get_all_docs) + +    def delete_doc(self, doc): +        """Mark a document as deleted.""" +        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_and_update_indexes(old_doc, doc) +        return new_rev + +    # index-related methods + +    def create_index(self, index_name, *index_expressions): +        """ +        Create an named index, which can then be queried for future lookups. +        """ +        raise NotImplementedError(self.create_index) + +    def delete_index(self, index_name): +        """Remove a named index.""" +        super(ObjectStoreDatabase, self).delete_index(index_name) +        self._store_u1db_data() + +    def _replace_conflicts(self, doc, conflicts): +        super(ObjectStoreDatabase, self)._replace_conflicts(doc, conflicts) +        self._store_u1db_data() + +    def _do_set_replica_gen_and_trans_id(self, other_replica_uid, +                                         other_generation, +                                         other_transaction_id): +        super(ObjectStoreDatabase, self)._do_set_replica_gen_and_trans_id( +            other_replica_uid, +            other_generation, +            other_transaction_id) +        self._store_u1db_data() + +    #------------------------------------------------------------------------- +    # implemented methods from CommonBackend +    #------------------------------------------------------------------------- + +    def _put_and_update_indexes(self, old_doc, doc): +        for index in self._indexes.itervalues(): +            if old_doc is not None and not old_doc.is_tombstone(): +                index.remove_json(old_doc.doc_id, old_doc.get_json()) +            if not doc.is_tombstone(): +                index.add_json(doc.doc_id, doc.get_json()) +        trans_id = self._allocate_transaction_id() +        self._put_doc(doc) +        self._transaction_log.append((doc.doc_id, trans_id)) +        self._store_u1db_data() + +    #------------------------------------------------------------------------- +    # methods specific for object stores +    #------------------------------------------------------------------------- + +    U1DB_DATA_DOC_ID = 'u1db_data' + +    def _fetch_u1db_data(self): +        """ +        Fetch u1db configuration data from backend storage. +        """ +        NotImplementedError(self._fetch_u1db_data) + +    def _store_u1db_data(self): +        """ +        Save u1db configuration data on backend storage. +        """ +        NotImplementedError(self._store_u1db_data) + +    def _init_u1db_data(self): +        """ +        Initialize u1db configuration data on backend storage. +        """ +        NotImplementedError(self._init_u1db_data) + + +class ObjectStoreSyncTarget(InMemorySyncTarget): +    pass | 
