1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
|
"""
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
from u1db import errors
class ObjectStore(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(ObjectStore, 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(ObjectStore, 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(ObjectStore, self).delete_index(index_name)
self._store_u1db_data()
def _replace_conflicts(self, doc, conflicts):
super(ObjectStore, 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(ObjectStore, 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)
|