summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--docs/storage.md52
1 files changed, 40 insertions, 12 deletions
diff --git a/docs/storage.md b/docs/storage.md
index f1de2db..794a739 100644
--- a/docs/storage.md
+++ b/docs/storage.md
@@ -33,7 +33,9 @@ A entity is uniquely identified by:
33The additional revision identifies a specific instance/version of the entity. 33The additional revision identifies a specific instance/version of the entity.
34 34
35Uri Scheme: 35Uri Scheme:
36 akonadi://resource/id:revision 36```
37akonadi://resource/id:revision
38```
37 39
38## Store Entities 40## Store Entities
39Each entity can be as normalized/denormalized as useful. It is not necessary to have a solution that fits everything. 41Each entity can be as normalized/denormalized as useful. It is not necessary to have a solution that fits everything.
@@ -64,7 +66,7 @@ Event {
64} 66}
65``` 67```
66 68
67Of course any combination of the two can be used, including duplicating data into individual properties while keeping the complete struct intact. The question then becomes though which copy is used for conflict resolution (perhaps this would result in more problems than it solves). 69Of course any combination of the two can be used, including duplicating data into individual properties while keeping the complete struct intact.
68 70
69#### Optional Properties 71#### Optional Properties
70For each domain type, we want to define a set of required and a set of optional properties. The required properties are the minimum bar for each resource, and are required in order for applications to work as expected. Optional properties may only be shown by the UI if actually supported by the backend. 72For each domain type, we want to define a set of required and a set of optional properties. The required properties are the minimum bar for each resource, and are required in order for applications to work as expected. Optional properties may only be shown by the UI if actually supported by the backend.
@@ -79,18 +81,22 @@ The advantage of this is that a resource only needs to specify a minimal set of
79Each entity-value in the key-value store consists of the following individual buffers: 81Each entity-value in the key-value store consists of the following individual buffers:
80 82
81* Metadata: metadata that is required for every entity (revision, ....) 83* Metadata: metadata that is required for every entity (revision, ....)
82* Resource: the buffer defined by the resource (synchronized properties, values that help for synchronization such as remoteId's) 84* Local: default storage buffer that is domain-type specific.
83* Local-only: default storage buffer that is domain-type specific. 85* Resource: the buffer defined by the resource (additional properties, values that help for synchronization)
84 86
85## Database 87## Database
86### Storage Layout 88### Database Layout
87Storage is split up in multiple named databases that reside in the same database environment. 89Storage is split up in multiple named databases that reside in the same database environment.
88 90
89``` 91```
90 $DATADIR/storage/$RESOURCE_IDENTIFIER/$BUFFERTYPE.main 92 $DATADIR/storage/$RESOURCE_IDENTIFIER/
91 $BUFFERTYPE.index.$INDEXTYPE
92``` 93```
93 94
95* $BUFFERTYPE.main: The primary store for a type
96* $BUFFERTYPE.index.$PROPERTY: Secondary indexes
97* revisionType: Allows to lookup the type by revision to find the correct primary or secondary db's.
98* revisions: Allows to lookup the entity id by revision
99
94The resource can be effectively removed from disk (besides configuration), 100The resource can be effectively removed from disk (besides configuration),
95by deleting the directories matching `$RESOURCE_IDENTIFIER*` and everything they contain. 101by deleting the directories matching `$RESOURCE_IDENTIFIER*` and everything they contain.
96 102
@@ -100,9 +106,25 @@ by deleting the directories matching `$RESOURCE_IDENTIFIER*` and everything they
100### Revisions 106### Revisions
101Every operation (create/delete/modify), leads to a new revision. The revision is an ever increasing number for the complete store. 107Every operation (create/delete/modify), leads to a new revision. The revision is an ever increasing number for the complete store.
102 108
109Each entity is stored with a key consisting of its id and the revision. This way it is possible to lookup older revision.
110
111Removing an entity simply results in a new revision of the entitiy recording the removal.
112
113Secondary indexes always refer to the latest revision.
114
103#### Design Considerations 115#### Design Considerations
104By having one revision for the complete store instead of one per type, the change replay always works across all types. This is especially important in the write-back mechanism that replays the changes to the source. 116By having one revision for the complete store instead of one per type, the change replay always works across all types. This is especially important in the write-back mechanism that replays the changes to the source.
105 117
118### Revision cleanup
119Because the store would grow infinitely, old revisions need to be removed.
120The resource maintains a "lower bound revision", which is the lowest revision of any change-replaying component (such as clients and write-back).
121For all lower revisions the cleanup will remove any revision that:
122
123* is a delete command (the revision is no longer existing)
124* has a newer revision for the same entity (the revision is outdated)
125
126By doing cleanups continously, we avoid keeping outdated data.
127
106### BLOB properties 128### BLOB properties
107Files are used to handle opaque large properties that should not end up in memory. BLOB properties are in their nature never queriable (extract parts of it to other properties if indexes are required). 129Files are used to handle opaque large properties that should not end up in memory. BLOB properties are in their nature never queriable (extract parts of it to other properties if indexes are required).
108 130
@@ -110,7 +132,7 @@ For reading:
110 132
111Resources... 133Resources...
112 134
113* store the file in $DATADIR/storage/$RESOURCE_IDENTIFIER_files/ 135* store the file in $DATADIR/storage/$RESOURCE_IDENTIFIER.files/
114* store the filename in the blob property. 136* store the filename in the blob property.
115* delete the file when the corresponding entity is deleted. 137* delete the file when the corresponding entity is deleted.
116 138
@@ -132,7 +154,7 @@ Clients..
132 154
133Resources.. 155Resources..
134 156
135* move the file to $DATADIR/storage/$RESOURCE_IDENTIFIER_files/ 157* move the file to $DATADIR/storage/$RESOURCE_IDENTIFIER.files/
136* store the new path in the entity 158* store the new path in the entity
137 159
138#### Design Considerations 160#### Design Considerations
@@ -145,7 +167,7 @@ Using regular files as the interface has the advantages:
145The copy is necessary to guarantee that the file remains for the client/resource even if the resource removes the file on it's side as part of a sync. 167The copy is necessary to guarantee that the file remains for the client/resource even if the resource removes the file on it's side as part of a sync.
146The copy could be optimized by using hardlinks, which is not a portable solution though. For some next-gen copy-on-write filesystems copying is a very cheap operation. 168The copy could be optimized by using hardlinks, which is not a portable solution though. For some next-gen copy-on-write filesystems copying is a very cheap operation.
147 169
148### Database choice 170## Database choice
149By design we're interested in key-value stores or perhaps document databases. This is because a fixed schema is not useful for this design, which makes 171By design we're interested in key-value stores or perhaps document databases. This is because a fixed schema is not useful for this design, which makes
150SQL not very useful (it would just be a very slow key-value store). While document databases would allow for indexes on certain properties (which is something we need), we did not yet find any contenders that looked like they would be useful for this system. 172SQL not very useful (it would just be a very slow key-value store). While document databases would allow for indexes on certain properties (which is something we need), we did not yet find any contenders that looked like they would be useful for this system.
151 173
@@ -216,9 +238,10 @@ Other useful properties:
216 * reading about 30% the speed of lmdb 238 * reading about 30% the speed of lmdb
217 * slow writes with transactions 239 * slow writes with transactions
218 240
219## Indexes 241### Result
242LMDB was chosen as one of the few contenders that are embeddable and have true multi process support. It also outperformed unqllite significantly, although its write performance and disk usage aren't ideal.
220 243
221### Index Choice 244### Indexes
222Additionally to the primary store, indexes are required for efficient lookups. 245Additionally to the primary store, indexes are required for efficient lookups.
223 246
224Since indexes always need to be updated they directly affect how fast we can write data. While reading only a subset of the available indexes is typically used, so a slow index doesn't affect all quries. 247Since indexes always need to be updated they directly affect how fast we can write data. While reading only a subset of the available indexes is typically used, so a slow index doesn't affect all quries.
@@ -245,6 +268,11 @@ Since indexes always need to be updated they directly affect how fast we can wri
245 * fast full text searching 268 * fast full text searching
246 * MVCC concurrency 269 * MVCC concurrency
247 270
271### Result
272For regular secondary indexes LMDB is used as well, because it's sufficient for key lookups, and by using the same database, we can store the indexed data directly in the same transaction.
273
274No solution for full-text indexes has been chosen yet. Baloo implements a fulltext index on top of LMDB though.
275
248## Useful Resources 276## Useful Resources
249* LMDB 277* LMDB
250 * Wikipedia for a good overview: <https://en.wikipedia.org/wiki/Lightning_Memory-Mapped_Database> 278 * Wikipedia for a good overview: <https://en.wikipedia.org/wiki/Lightning_Memory-Mapped_Database>