1 | /*
|
---|
2 | * Copyright (c) 2012 Jan Kotek
|
---|
3 | *
|
---|
4 | * Licensed under the Apache License, Version 2.0 (the "License");
|
---|
5 | * you may not use this file except in compliance with the License.
|
---|
6 | * You may obtain a copy of the License at
|
---|
7 | *
|
---|
8 | * http://www.apache.org/licenses/LICENSE-2.0
|
---|
9 | *
|
---|
10 | * Unless required by applicable law or agreed to in writing, software
|
---|
11 | * distributed under the License is distributed on an "AS IS" BASIS,
|
---|
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
---|
13 | * See the License for the specific language governing permissions and
|
---|
14 | * limitations under the License.
|
---|
15 | */
|
---|
16 |
|
---|
17 | package org.mapdb;
|
---|
18 |
|
---|
19 | /**
|
---|
20 | * Central interface for managing records.
|
---|
21 | * It is primitive key value store, with <code>long</code> keys and object instances values.
|
---|
22 | * It contains basic CRUD operations.
|
---|
23 | * <p/>
|
---|
24 | * MapDB (unlike other DBs) does not use binary <code>byte[]</code> for its values.
|
---|
25 | * Instead it takes object instance with serializer, and manages serialization/deserialization itself.
|
---|
26 | * Integrating serialization into database gives us lot of flexibility.
|
---|
27 | * <p/>
|
---|
28 | * There is {@link Storage} class which implements basic persistence. Most of MapDB features
|
---|
29 | * comes from {@link EngineWrapper}, they are stacked on top of each other
|
---|
30 | * to provide asynchronous writes, instance cache, encryption etc..
|
---|
31 | * <code>Engine</code> stack is very elegant and uniform way to handle additional functionality.
|
---|
32 | * Other DBs need an ORM framework to achieve similar features.
|
---|
33 | * <p/>
|
---|
34 | * In default configuration MapDB runs with this <code>Engine</code> stack:
|
---|
35 | * <pre>
|
---|
36 | * [DISK IO]
|
---|
37 | * StorageJournaled - permament record storage with journaled transactions
|
---|
38 | * AsyncWriteEngine - asynchronous writes to storage
|
---|
39 | * ByteTransformEngine - compression or encryption (optional)
|
---|
40 | * CacheHashTable - instance cache
|
---|
41 | * SnapshotEngine - support for snapshots
|
---|
42 | * [USER API]
|
---|
43 | * </pre>
|
---|
44 | *
|
---|
45 | * <p/>
|
---|
46 | * Engine uses 'recid' to identify records. There is zero error handling in case recid is invalid
|
---|
47 | * (random number or already deleted record). Passing illegal recid may result into anything
|
---|
48 | * (return null, throw EOF or even corrupt store). Engine is considered low-level component
|
---|
49 | * and it is responsibility of upper layers (collections) to ensure recid is consistent.
|
---|
50 | * Lack of error handling is trade of for speed (similar way as manual memory management in C++)
|
---|
51 | * <p/>
|
---|
52 | * Engine must support {@code null} record values. You may insert, update and fetch null records.
|
---|
53 | * Nulls play important role in recid preallocation and asynchronous writes.
|
---|
54 | * <p/>
|
---|
55 | * Recid can be reused after it was deleted. If your application relies on unique being unique,
|
---|
56 | * you should update record with null value, instead of delete.
|
---|
57 | * Null record consumes only 8 bytes in store and is preserved during defragmentation.
|
---|
58 | *
|
---|
59 | * @author Jan Kotek
|
---|
60 | */
|
---|
61 | public interface Engine {
|
---|
62 |
|
---|
63 | long NAME_DIR_RECID = 1;
|
---|
64 | long CLASS_INFO_RECID = 2;
|
---|
65 | long LAST_RESERVED_RECID = 7;
|
---|
66 |
|
---|
67 |
|
---|
68 | /**
|
---|
69 | * Insert new record.
|
---|
70 | *
|
---|
71 | * @param value records to be added
|
---|
72 | * @param serializer used to convert record into/from binary form
|
---|
73 | * @param <A> type of record
|
---|
74 | * @return recid (record identifier) under which record is stored.
|
---|
75 | */
|
---|
76 | <A> long put(A value, Serializer<A> serializer);
|
---|
77 |
|
---|
78 | /**
|
---|
79 | * Get existing record.
|
---|
80 | * <p/>
|
---|
81 | * Recid must be a number returned by 'put' method.
|
---|
82 | * Behaviour for invalid recid (random number or already deleted record)
|
---|
83 | * is not defined, typically it returns null or throws 'EndOfFileException'
|
---|
84 | *
|
---|
85 | * @param recid (record identifier) under which record was persisted
|
---|
86 | * @param serializer used to deserialize record from binary form
|
---|
87 | * @param <A> record type
|
---|
88 | * @return record matching given recid, or null if record is not found under given recid.
|
---|
89 | */
|
---|
90 | <A> A get(long recid, Serializer<A> serializer);
|
---|
91 |
|
---|
92 | /**
|
---|
93 | * Update existing record with new value.
|
---|
94 | * <p/>
|
---|
95 | * Recid must be a number returned by 'put' method.
|
---|
96 | * Behaviour for invalid recid (random number or already deleted record)
|
---|
97 | * is not defined, typically it throws 'EndOfFileException',
|
---|
98 | * but it may also corrupt store.
|
---|
99 | *
|
---|
100 | * @param recid (record identifier) under which record was persisted.
|
---|
101 | * @param value new record value to be stored
|
---|
102 | * @param serializer used to serialize record into binary form
|
---|
103 | * @param <A> record type
|
---|
104 | */
|
---|
105 | <A> void update(long recid, A value, Serializer<A> serializer);
|
---|
106 |
|
---|
107 |
|
---|
108 | /**
|
---|
109 | * Updates existing record in atomic <a href="http://en.wikipedia.org/wiki/Compare-and-swap">(Compare And Swap)</a> manner.
|
---|
110 | * Value is modified only if old value matches expected value. There are three ways to match values, MapDB may use any of them:
|
---|
111 | * <ol>
|
---|
112 | * <li>Equality check <code>oldValue==expectedOldValue</code> when old value is found in instance cache</li>
|
---|
113 | * <li>Deserializing <code>oldValue</code> using <code>serializer</code> and checking <code>oldValue.equals(expectedOldValue)</code></li>
|
---|
114 | * <li>Serializing <code>expectedOldValue</code> using <code>serializer </code> and comparing binary array with already serialized <code>oldValue</code>
|
---|
115 | * </ol>
|
---|
116 | * <p/>
|
---|
117 | * Recid must be a number returned by 'put' method.
|
---|
118 | * Behaviour for invalid recid (random number or already deleted record)
|
---|
119 | * is not defined, typically it throws 'EndOfFileException',
|
---|
120 | * but it may also corrupt store.
|
---|
121 | *
|
---|
122 | * @param recid (record identifier) under which record was persisted.
|
---|
123 | * @param expectedOldValue old value to be compared with existing record
|
---|
124 | * @param newValue to be written if values are matching
|
---|
125 | * @param serializer used to serialize record into binary form
|
---|
126 | * @param <A>
|
---|
127 | * @return true if values matched and newValue was written
|
---|
128 | */
|
---|
129 | <A> boolean compareAndSwap(long recid, A expectedOldValue, A newValue, Serializer<A> serializer);
|
---|
130 |
|
---|
131 | /**
|
---|
132 | * Remove existing record from store/cache
|
---|
133 | *
|
---|
134 | * <p/>
|
---|
135 | * Recid must be a number returned by 'put' method.
|
---|
136 | * Behaviour for invalid recid (random number or already deleted record)
|
---|
137 | * is not defined, typically it throws 'EndOfFileException',
|
---|
138 | * but it may also corrupt store.
|
---|
139 | *
|
---|
140 | * @param recid (record identifier) under which was record persisted
|
---|
141 | * @param serializer which may be used in some circumstances to deserialize and store old object
|
---|
142 | */
|
---|
143 | <A> void delete(long recid, Serializer<A> serializer);
|
---|
144 |
|
---|
145 |
|
---|
146 |
|
---|
147 | /**
|
---|
148 | * Close store/cache. This method must be called before JVM exits to flush all caches and prevent store corruption.
|
---|
149 | * Also it releases resources used by MapDB (disk, memory..).
|
---|
150 | * <p/>
|
---|
151 | * Engine can no longer be used after this method was called. If Engine is used after closing, it may
|
---|
152 | * throw any exception including <code>NullPointerException</code>
|
---|
153 | * </p>
|
---|
154 | * There is an configuration option {@link DBMaker#closeOnJvmShutdown()} which uses shutdown hook to automatically
|
---|
155 | * close Engine when JVM shutdowns.
|
---|
156 | */
|
---|
157 | void close();
|
---|
158 |
|
---|
159 |
|
---|
160 | /**
|
---|
161 | * Checks whether Engine was closed.
|
---|
162 | *
|
---|
163 | * @return true if engine was closed
|
---|
164 | */
|
---|
165 | public boolean isClosed();
|
---|
166 |
|
---|
167 | /**
|
---|
168 | * Makes all changes made since the previous commit/rollback permanent.
|
---|
169 | * In transactional mode (on by default) it means creating journal file and replaying it to storage.
|
---|
170 | * In other modes it may flush disk caches or do nothing at all (check your config options)
|
---|
171 | */
|
---|
172 | void commit();
|
---|
173 |
|
---|
174 | /**
|
---|
175 | * Undoes all changes made in the current transaction.
|
---|
176 | * If transactions are disabled it throws {@link UnsupportedOperationException}.
|
---|
177 | *
|
---|
178 | * @throws UnsupportedOperationException if transactions are disabled
|
---|
179 | */
|
---|
180 | void rollback() throws UnsupportedOperationException;
|
---|
181 |
|
---|
182 | /**
|
---|
183 | * Check if you can write into this Engine. It may be readonly in some cases (snapshot, read-only files).
|
---|
184 | *
|
---|
185 | * @return true if engine is read-only
|
---|
186 | */
|
---|
187 | boolean isReadOnly();
|
---|
188 |
|
---|
189 | void compact();
|
---|
190 | }
|
---|