source: osm/applications/editors/josm/plugins/imagerycache/src/org/mapdb/TxMaker.java@ 29363

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

JOSM/ImageryCache: Initial commit

File size: 5.4 KB
Line 
1package org.mapdb;
2
3import java.util.LinkedHashSet;
4import java.util.Set;
5
6/**
7 * Transaction factory
8 *
9 * @author Jan Kotek
10 */
11public class TxMaker {
12
13 protected static final Fun.Tuple2<Object, Serializer> DELETED = new Fun.Tuple2(null, Serializer.STRING_SERIALIZER);
14
15 protected Engine engine;
16
17 protected final Object lock = new Object();
18
19 protected final LongMap<TxEngine> globalMod = new LongHashMap<TxEngine>();
20
21
22 public TxMaker(Engine engine) {
23 if(engine==null) throw new IllegalArgumentException();
24 this.engine = engine;
25 }
26
27
28 public DB makeTx(){
29 return new DB(new TxEngine(engine));
30 }
31
32 public void close() {
33 if(engine==null)
34 engine.close();
35 }
36
37 /**
38 * Executes given block withing single transaction.
39 * If block throws {@code TxRollbackException} execution is repeated until it does not fail.
40 *
41 * @param txBlock
42 */
43 public void execute(TxBlock txBlock) {
44 for(;;){
45 DB tx = makeTx();
46 try{
47 txBlock.tx(tx);
48 if(!tx.isClosed())
49 tx.commit();
50 return;
51 }catch(TxRollbackException e){
52 //failed, so try again
53 }
54 }
55 }
56
57 protected class TxEngine extends EngineWrapper{
58
59 protected LongMap<Fun.Tuple2<?, Serializer>> modItems =
60 new LongHashMap<Fun.Tuple2<?, Serializer>>();
61
62 protected Set<Long> newItems = new LinkedHashSet<Long>();
63
64
65 protected TxEngine(Engine engine) {
66 super(engine);
67 }
68
69 @Override
70 public <A> long put(A value, Serializer<A> serializer) {
71 if(isClosed()) throw new IllegalAccessError("already closed");
72 synchronized (lock){
73 long recid = engine.put(Utils.EMPTY_STRING, Serializer.EMPTY_SERIALIZER);
74 newItems.add(recid);
75 modItems.put(recid, Fun.t2(value, (Serializer)serializer));
76 globalMod.put(recid, TxEngine.this);
77 return recid;
78 }
79 }
80
81 @Override
82 public <A> A get(long recid, Serializer<A> serializer) {
83 if(isClosed()) throw new IllegalAccessError("already closed");
84 synchronized (lock){
85 Fun.Tuple2 t = modItems.get(recid);
86 if(t!=null){
87 return (A) t.a;
88 //TODO compare serializers?
89 }else{
90 return super.get(recid, serializer);
91 }
92 }
93 }
94
95 @Override
96 public <A> void update(long recid, A value, Serializer<A> serializer) {
97 if(isClosed()) throw new IllegalAccessError("already closed");
98 synchronized (lock){
99 TxEngine other = globalMod.get(recid);
100 if(other!=null && other!=TxEngine.this) {
101 rollback();
102 throw new TxRollbackException();
103 }
104 modItems.put(recid, new Fun.Tuple2(value, serializer));
105 globalMod.put(recid, TxEngine.this);
106 }
107
108 }
109
110 @Override
111 public <A> boolean compareAndSwap(long recid, A expectedOldValue, A newValue, Serializer<A> serializer) {
112 if(isClosed()) throw new IllegalAccessError("already closed");
113 throw new IllegalAccessError("Compare and Swap not supported in Tx mode");
114 }
115
116 @Override
117 public <A> void delete(long recid, Serializer<A> serializer){
118 if(isClosed()) throw new IllegalAccessError("already closed");
119 synchronized (lock){
120 TxEngine other = globalMod.get(recid);
121 if(other!=null && other!=TxEngine.this) {
122 rollback();
123 throw new TxRollbackException();
124 }
125 modItems.put(recid, DELETED);
126 globalMod.put(recid, TxEngine.this);
127 }
128 }
129
130 @Override
131 public void commit() {
132 synchronized (lock){
133 //remove locally modified items from global list
134 LongMap.LongMapIterator<Fun.Tuple2<?, Serializer>> iter = modItems.longMapIterator();
135 while(iter.moveToNext()){
136 TxEngine other = globalMod.remove(iter.key());
137 if(other!=TxEngine.this) throw new InternalError();
138 Fun.Tuple2<?, Serializer> t = iter.value();
139 engine.update(iter.key(), t.a, t.b);
140 }
141 modItems = null;
142 newItems = null;
143
144 engine.commit();
145 }
146
147 }
148
149 @Override
150 public void rollback() {
151 synchronized (lock){
152 //remove locally modified items from global list
153 LongMap.LongMapIterator iter = modItems.longMapIterator();
154 while(iter.moveToNext()){
155 TxEngine other = globalMod.remove(iter.key());
156 if(other!=TxEngine.this) throw new InternalError();
157 }
158 //delete preallocated items
159 for(long recid:newItems){
160 engine.delete(recid, Serializer.EMPTY_SERIALIZER);
161 }
162 modItems = null;
163 newItems = null;
164 }
165
166 }
167
168 @Override
169 public void close() {
170 rollback();
171 }
172 }
173
174
175}
Note: See TracBrowser for help on using the repository browser.