Repository navigation
Expand file tree
/
Copy pathEngine.java
More file actions
235 lines (205 loc) · 9.34 KB
/
Copy pathEngine.java
File metadata and controls
235 lines (205 loc) · 9.34 KB
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
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
/*
* Copyright (c) 2012 Jan Kotek
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.mapdb;
import java.io.Closeable;
/**
* Centerpiece for record management, `Engine` is simple key value store.
* Engine is low-level interface and is not meant to be used directly
* by user. For most operations user should use {@link DB} class.
*
* In this store key is primitive `long` number, typically pointer to index table.
* Value is class instance. To turn value into/from binary form serializer is
* required as extra argument for most operations.
*
* Unlike other DBs MapDB does not expect user to (de)serialize data before
* they are passed as arguments. Instead MapDB controls (de)serialization itself.
* This gives DB a lot of flexibility: for example instances may be held in
* cache to minimise number of deserializations, or modified instance can
* be placed into queue and asynchronously written on background thread.
*
* There is {@link Store} subinterface for raw persistence
* Most of MapDB features comes from {@link EngineWrapper}s, which are stacked on
* top of each other to provide asynchronous writes, instance cache, encryption etc..
* `Engine` stack is very elegant and uniform way to handle additional functionality.
* Other DBs need an ORM framework to achieve similar features.
* In default configuration MapDB runs with this `Engine` stack:
*
* * **DISK** - raw file or memory
* * {@link org.mapdb.StoreWAL} - permanent record store with transactions
* * {@link org.mapdb.Caches.HashTable} - instance cache
* * **USER** - {@link DB} and collections
*
* TODO document more examples of Engine wrappers
*
* Engine uses `recid` to identify records. There is zero error handling in case recid is invalid
* (random number or already deleted record). Passing illegal recid may result into anything
* (return null, throw EOF or even corrupt store). Engine is considered low-level component
* and it is responsibility of upper layers (collections) to ensure recid is consistent.
* Lack of error handling is trade of for speed (similar way as manual memory management in C++)
* <p/>
* Engine must support `null` record values. You may insert, update and fetch null records.
* Nulls play important role in recid preallocation and asynchronous writes.
* <p/>
* Recid can be reused after it was deleted. If your application relies on unique being unique,
* you should update record with null value, instead of delete.
* Null record consumes only 8 bytes in store and is preserved during defragmentation.
*
* @author Jan Kotek
*/
public interface Engine extends Closeable {
long CATALOG_RECID = 1;
long CLASS_INFO_RECID = 2;
long CHECK_RECORD = 3;
long LAST_RESERVED_RECID = 7;
/**
* Preallocates recid for not yet created record. It does not insert any data into it.
* @return new recid
*/
long preallocate();
/**
* Preallocates recids for not yet created record. It does not insert any data into it.
* This is done in batch of given size (determied by size of array in argument)
* @param recids array to put result into
*/
void preallocate(long[] recids);
/**
* Insert new record.
*
* @param value records to be added
* @param serializer used to convert record into/from binary form
* @return recid (record identifier) under which record is stored.
*/
<A> long put(A value, Serializer<A> serializer);
/**
* Get existing record.
* <p/>
* Recid must be a number returned by 'put' method.
* Behaviour for invalid recid (random number or already deleted record)
* is not defined, typically it returns null or throws 'EndOfFileException'
*
* @param recid (record identifier) under which record was persisted
* @param serializer used to deserialize record from binary form
* @return record matching given recid, or null if record is not found under given recid.
*/
<A> A get(long recid, Serializer<A> serializer);
/**
* Update existing record with new value.
* <p/>
* Recid must be a number returned by 'put' method.
* Behaviour for invalid recid (random number or already deleted record)
* is not defined, typically it throws 'EndOfFileException',
* but it may also corrupt store.
*
* @param recid (record identifier) under which record was persisted.
* @param value new record value to be stored
* @param serializer used to serialize record into binary form
*/
<A> void update(long recid, A value, Serializer<A> serializer);
/**
* Updates existing record in atomic <a href="http://en.wikipedia.org/wiki/Compare-and-swap">(Compare And Swap)</a> manner.
* Value is modified only if old value matches expected value. There are three ways to match values, MapDB may use any of them:
* <ol>
* <li>Equality check <code>oldValue==expectedOldValue</code> when old value is found in instance cache</li>
* <li>Deserializing <code>oldValue</code> using <code>serializer</code> and checking <code>oldValue.equals(expectedOldValue)</code></li>
* <li>Serializing <code>expectedOldValue</code> using <code>serializer </code> and comparing binary array with already serialized <code>oldValue</code>
* </ol>
* <p/>
* Recid must be a number returned by 'put' method.
* Behaviour for invalid recid (random number or already deleted record)
* is not defined, typically it throws 'EndOfFileException',
* but it may also corrupt store.
*
* @param recid (record identifier) under which record was persisted.
* @param expectedOldValue old value to be compared with existing record
* @param newValue to be written if values are matching
* @param serializer used to serialize record into binary form
* @return true if values matched and newValue was written
*/
<A> boolean compareAndSwap(long recid, A expectedOldValue, A newValue, Serializer<A> serializer);
/**
* Remove existing record from store/cache
*
* <p/>
* Recid must be a number returned by 'put' method.
* Behaviour for invalid recid (random number or already deleted record)
* is not defined, typically it throws 'EndOfFileException',
* but it may also corrupt store.
*
* @param recid (record identifier) under which was record persisted
* @param serializer which may be used in some circumstances to deserialize and store old object
*/
<A> void delete(long recid, Serializer<A> serializer);
/**
* Close store/cache. This method must be called before JVM exits to flush all caches and prevent store corruption.
* Also it releases resources used by MapDB (disk, memory..).
* <p/>
* Engine can no longer be used after this method was called. If Engine is used after closing, it may
* throw any exception including <code>NullPointerException</code>
* </p>
* There is an configuration option {@link DBMaker#closeOnJvmShutdown()} which uses shutdown hook to automatically
* close Engine when JVM shutdowns.
*/
void close();
/**
* Checks whether Engine was closed.
*
* @return true if engine was closed
*/
public boolean isClosed();
/**
* Makes all changes made since the previous commit/rollback permanent.
* In transactional mode (on by default) it means creating journal file and replaying it to storage.
* In other modes it may flush disk caches or do nothing at all (check your config options)
*/
void commit();
/**
* Undoes all changes made in the current transaction.
* If transactions are disabled it throws {@link UnsupportedOperationException}.
*
* @throws UnsupportedOperationException if transactions are disabled
*/
void rollback() throws UnsupportedOperationException;
/**
* Check if you can write into this Engine. It may be readonly in some cases (snapshot, read-only files).
*
* @return true if engine is read-only
*/
boolean isReadOnly();
/** @return true if engine supports rollback*/
boolean canRollback();
/** @return true if engine can create read-only snapshots*/
boolean canSnapshot();
/**
* Returns read-only snapshot of data in Engine.
*
* @see EngineWrapper#canSnapshot()
* @throws UnsupportedOperationException if snapshots are not supported/enabled
*/
Engine snapshot() throws UnsupportedOperationException;
/** clears any underlying cache */
void clearCache();
void compact();
/**
* Returns default serializer associated with this engine.
* The default serializer will be moved from Engine into DB, so it is deprecated now and
* this method will be removed.
*
*/
@Deprecated
SerializerPojo getSerializerPojo();
void closeListenerRegister(Runnable closeListener);
void closeListenerUnregister(Runnable closeListener);
}