source: osm/applications/editors/josm/plugins/imagerycache/src/org/mapdb/EngineWrapper.java@ 29484

Last change on this file since 29484 was 29484, checked in by akks, 11 years ago

JOSM/ImageryCache: updated MapDB (no more deadlocks, Java 1.6 compatible), less crashes, multiple-JOSM support

File size: 12.8 KB
Line 
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
17package org.mapdb;
18
19
20import java.io.IOError;
21import java.io.IOException;
22import java.nio.ByteBuffer;
23import java.util.Arrays;
24import java.util.Iterator;
25import java.util.Queue;
26import java.util.concurrent.ConcurrentLinkedQueue;
27
28
29/**
30 * EngineWrapper adapter. It implements all methods on Engine interface.
31 *
32 * @author Jan Kotek
33 */
34public abstract class EngineWrapper implements Engine{
35
36 private Engine engine;
37
38 protected EngineWrapper(Engine engine){
39 if(engine == null) throw new IllegalArgumentException();
40 this.engine = engine;
41 }
42
43 @Override
44 public <A> long put(A value, Serializer<A> serializer) {
45 return getWrappedEngine().put(value, serializer);
46 }
47
48 @Override
49 public <A> A get(long recid, Serializer<A> serializer) {
50 return getWrappedEngine().get(recid, serializer);
51 }
52
53 @Override
54 public <A> void update(long recid, A value, Serializer<A> serializer) {
55 getWrappedEngine().update(recid, value, serializer);
56 }
57
58 @Override
59 public <A> boolean compareAndSwap(long recid, A expectedOldValue, A newValue, Serializer<A> serializer) {
60 return getWrappedEngine().compareAndSwap(recid, expectedOldValue, newValue, serializer);
61 }
62
63 @Override
64 public <A> void delete(long recid, Serializer<A> serializer) {
65 getWrappedEngine().delete(recid, serializer);
66 }
67
68 @Override
69 public void close() {
70 Engine e = engine;
71 if(e!=null)
72 e.close();
73 engine = null;
74 }
75
76 @Override
77 public boolean isClosed() {
78 return engine==null;
79 }
80
81 @Override
82 public void commit() {
83 getWrappedEngine().commit();
84 }
85
86 @Override
87 public void rollback() {
88 getWrappedEngine().rollback();
89 }
90
91
92 @Override
93 public boolean isReadOnly() {
94 return getWrappedEngine().isReadOnly();
95 }
96
97 @Override
98 public void compact() {
99 getWrappedEngine().compact();
100 }
101
102 /**
103 * Wraps an <code>Engine</code> and throws
104 * <code>UnsupportedOperationException("Read-only")</code>
105 * on any modification attempt.
106 */
107 public static class ReadOnlyEngine extends EngineWrapper {
108
109
110 public ReadOnlyEngine(Engine engine){
111 super(engine);
112 }
113
114 @Override
115 public <A> boolean compareAndSwap(long recid, A expectedOldValue, A newValue, Serializer<A> serializer) {
116 throw new UnsupportedOperationException("Read-only");
117 }
118
119 @Override
120 public <A> long put(A value, Serializer<A> serializer) {
121 throw new UnsupportedOperationException("Read-only");
122 }
123
124 @Override
125 public <A> void update(long recid, A value, Serializer<A> serializer) {
126 throw new UnsupportedOperationException("Read-only");
127 }
128
129 @Override
130 public <A> void delete(long recid, Serializer<A> serializer){
131 throw new UnsupportedOperationException("Read-only");
132 }
133
134
135
136 @Override
137 public void commit() {
138 throw new UnsupportedOperationException("Read-only");
139 }
140
141 @Override
142 public void rollback() {
143 throw new UnsupportedOperationException("Read-only");
144 }
145
146
147 @Override
148 public boolean isReadOnly() {
149 return true;
150 }
151
152 }
153
154 /**
155 * Wrapper which transform binary data. Useful for compression or encryption
156 */
157 public static class ByteTransformEngine extends EngineWrapper {
158
159 //TODO compare and swap
160
161 protected Serializer<byte[]> blockSerializer;
162
163 public ByteTransformEngine(Engine engine, Serializer<byte[]> blockSerializer) {
164 super(engine);
165 this.blockSerializer = blockSerializer;
166 }
167
168 @Override
169 public <A> long put(A value, Serializer<A> serializer) {
170 //serialize to byte array, and pass it down with alternative serializer
171 try {
172 Engine e = getWrappedEngine();
173 Serializer<byte[]> ser = checkClosed(blockSerializer);
174
175 if(value ==null){
176 return e.put(null, ser);
177 }
178
179 DataOutput2 out = new DataOutput2();
180 serializer.serialize(out,value);
181 byte[] b = out.copyBytes();
182
183 return e.put(b, ser);
184 } catch (IOException e) {
185 throw new IOError(e);
186 }
187 }
188
189 @Override
190 public <A> A get(long recid, Serializer<A> serializer) {
191 //get decompressed array
192 try {
193 byte[] b = getWrappedEngine().get(recid, checkClosed(blockSerializer));
194 if(b==null) return null;
195
196 //deserialize
197 DataInput2 in = new DataInput2(ByteBuffer.wrap(b),0);
198
199 return serializer.deserialize(in,b.length);
200 } catch (IOException e) {
201 throw new IOError(e);
202 }
203 }
204
205 @Override
206 public <A> void update(long recid, A value, Serializer<A> serializer) {
207 //serialize to byte array, and pass it down with alternative serializer
208 try {
209 DataOutput2 out = new DataOutput2();
210 serializer.serialize(out,value);
211 byte[] b = out.copyBytes();
212
213 getWrappedEngine().update(recid, b, checkClosed(blockSerializer));
214 } catch (IOException e) {
215 throw new IOError(e);
216 }
217 }
218
219
220 @Override
221 public void close() {
222 super.close();
223 blockSerializer = null;
224 }
225
226
227 }
228
229 public static class DebugEngine extends EngineWrapper{
230
231 //TODO CAS
232
233 final Queue<Record> records = new ConcurrentLinkedQueue<Record>();
234
235
236 protected static final class Record{
237 final long recid;
238 final String desc;
239// final String thread = Thread.currentThread().getName();
240// final Exception stackTrace = new Exception();
241
242 public Record(long recid, String desc) {
243 this.recid = recid;
244 this.desc = desc;
245 }
246 }
247
248 public DebugEngine(Engine engine) {
249 super(engine);
250 }
251
252 @Override
253 public <A> long put(A value, Serializer<A> serializer) {
254 long recid = super.put(value, serializer);
255 records.add(new Record(recid,
256 "INSERT \n val:"+value+"\n ser:"+serializer
257 ));
258 return recid;
259 }
260
261 @Override
262 public <A> A get(long recid, Serializer<A> serializer) {
263 A ret = super.get(recid, serializer);
264 records.add(new Record(recid,
265 "GET \n val:"+ret+"\n ser:"+serializer
266 ));
267 return ret;
268 }
269
270 @Override
271 public <A> void update(long recid, A value, Serializer<A> serializer) {
272 super.update(recid, value, serializer);
273 records.add(new Record(recid,
274 "UPDATE \n val:"+value+"\n ser:"+serializer
275 ));
276
277 }
278
279 @Override
280 public <A> void delete(long recid, Serializer<A> serializer){
281 super.delete(recid,serializer);
282 records.add(new Record(recid,"DEL"));
283 }
284 }
285
286 public Engine getWrappedEngine(){
287 return checkClosed(engine);
288 }
289
290 protected static <V> V checkClosed(V v){
291 if(v==null) throw new IllegalAccessError("DB has been closed");
292 return v;
293 }
294
295
296 /**
297 * check if Record Instances were not modified while in cache.
298 * Usuful to diagnose strange problems with Instance Cache.
299 */
300 public static class ImmutabilityCheckEngine extends EngineWrapper{
301
302 protected static class Item {
303 final Serializer serializer;
304 final Object item;
305 final int oldChecksum;
306
307 public Item(Serializer serializer, Object item) {
308 if(item==null || serializer==null) throw new AssertionError("null");
309 this.serializer = serializer;
310 this.item = item;
311 oldChecksum = checksum();
312 if(oldChecksum!=checksum()) throw new AssertionError("inconsistent serialization");
313 }
314
315 private int checksum(){
316 try {
317 DataOutput2 out = new DataOutput2();
318 serializer.serialize(out, item);
319 byte[] bb = out.copyBytes();
320 return Arrays.hashCode(bb);
321 }catch(IOException e){
322 throw new IOError(e);
323 }
324 }
325
326 void check(){
327 int newChecksum = checksum();
328 if(oldChecksum!=newChecksum) throw new AssertionError("Record instance was modified: \n "+item+"\n "+serializer);
329 }
330 }
331
332 protected LongConcurrentHashMap<Item> items = new LongConcurrentHashMap<Item>();
333
334 protected ImmutabilityCheckEngine(Engine engine) {
335 super(engine);
336 }
337
338 @Override
339 public <A> A get(long recid, Serializer<A> serializer) {
340 Item item = items.get(recid);
341 if(item!=null) item.check();
342 A ret = super.get(recid, serializer);
343 if(ret!=null) items.put(recid, new Item(serializer,ret));
344 return ret;
345 }
346
347 @Override
348 public <A> long put(A value, Serializer<A> serializer) {
349 long ret = super.put(value, serializer);
350 if(value!=null) items.put(ret, new Item(serializer,value));
351 return ret;
352 }
353
354 @Override
355 public <A> void update(long recid, A value, Serializer<A> serializer) {
356 Item item = items.get(recid);
357 if(item!=null) item.check();
358 super.update(recid, value, serializer);
359 if(value!=null) items.put(recid, new Item(serializer,value));
360 }
361
362 @Override
363 public <A> boolean compareAndSwap(long recid, A expectedOldValue, A newValue, Serializer<A> serializer) {
364 Item item = items.get(recid);
365 if(item!=null) item.check();
366 boolean ret = super.compareAndSwap(recid, expectedOldValue, newValue, serializer);
367 if(ret && newValue!=null) items.put(recid, new Item(serializer,item));
368 return ret;
369 }
370
371 @Override
372 public void close() {
373 super.close();
374 for(Iterator<Item> iter = items.valuesIterator(); iter.hasNext();){
375 iter.next().check();
376 }
377 items.clear();
378 }
379 }
380
381
382 /** Engine wrapper with all methods synchronized on global lock, useful to diagnose concurrency issues.*/
383 public static class SynchronizedEngineWrapper extends EngineWrapper{
384
385 protected SynchronizedEngineWrapper(Engine engine) {
386 super(engine);
387 }
388
389 @Override
390 synchronized public <A> long put(A value, Serializer<A> serializer) {
391 return super.put(value, serializer);
392 }
393
394 @Override
395 synchronized public <A> A get(long recid, Serializer<A> serializer) {
396 return super.get(recid, serializer);
397 }
398
399 @Override
400 synchronized public <A> void update(long recid, A value, Serializer<A> serializer) {
401 super.update(recid, value, serializer);
402 }
403
404 @Override
405 synchronized public <A> boolean compareAndSwap(long recid, A expectedOldValue, A newValue, Serializer<A> serializer) {
406 return super.compareAndSwap(recid, expectedOldValue, newValue, serializer);
407 }
408
409 @Override
410 synchronized public <A> void delete(long recid, Serializer<A> serializer) {
411 super.delete(recid, serializer);
412 }
413
414 @Override
415 synchronized public void close() {
416 super.close();
417 }
418
419 @Override
420 synchronized public boolean isClosed() {
421 return super.isClosed();
422 }
423
424 @Override
425 synchronized public void commit() {
426 super.commit();
427 }
428
429 @Override
430 synchronized public void rollback() {
431 super.rollback();
432 }
433
434 @Override
435 synchronized public boolean isReadOnly() {
436 return super.isReadOnly();
437 }
438
439 @Override
440 synchronized public void compact() {
441 super.compact();
442 }
443 }
444
445}
Note: See TracBrowser for help on using the repository browser.