]> gerrit.simantics Code Review - simantics/platform.git/blob - bundles/org.simantics.acorn/src/org/simantics/acorn/lru/ClusterLRU.java
Merge remote-tracking branch 'origin/svn' commit 96bb7ef9cbe42d82eb58306
[simantics/platform.git] / bundles / org.simantics.acorn / src / org / simantics / acorn / lru / ClusterLRU.java
1 package org.simantics.acorn.lru;
2
3 import java.nio.file.Path;
4 import java.util.concurrent.atomic.AtomicBoolean;
5 import java.util.concurrent.atomic.AtomicInteger;
6
7 import org.simantics.acorn.ClusterManager;
8 import org.simantics.acorn.cluster.ClusterImpl;
9 import org.simantics.acorn.internal.BijectionMap;
10 import org.simantics.db.common.utils.Logger;
11 import org.simantics.db.exception.ClusterDoesNotExistException;
12 import org.simantics.db.exception.DatabaseException;
13 import org.simantics.db.impl.ClusterBase;
14 import org.simantics.db.impl.ClusterI;
15 import org.simantics.db.service.ClusterUID;
16
17 import gnu.trove.TIntIntHashMap;
18
19 public class ClusterLRU extends LRU<ClusterUID, ClusterInfo> {
20
21         final private BijectionMap<ClusterUID, Integer> clusterMapping = new BijectionMap<ClusterUID, Integer>();
22         final private ClusterManager manager;
23         
24         public ClusterLRU(ClusterManager manager, String identifier, Path writeDir) {
25                 
26                 super(identifier, writeDir);
27                 this.manager = manager;
28                 
29                 clusterMapping.map(ClusterUID.make(0,2), clusterMapping.size() + 1);
30
31         }
32
33         public ClusterInfo getOrCreate(ClusterUID uid, boolean makeIfNull) {
34                 
35                 try {
36                         
37                         acquireMutex();
38                         
39                         ClusterInfo info = get(uid);
40
41                         if (info == null) {
42                                 
43                                 if(!makeIfNull) throw new IllegalStateException("Asked for an existing cluster " + uid + " that was not found.");
44
45                                 Integer clusterKey = clusterMapping.getRight(uid);
46                                 if (clusterKey == null) {
47                                         clusterKey = clusterMapping.size() + 1;
48                                         clusterMapping.map(uid, clusterKey);
49                                 }
50
51                                 info = new ClusterInfo(manager, this, ClusterImpl.make(manager.support,
52                                                 uid, clusterKey, manager.support));
53
54                         }
55
56                         return info;
57                         
58                 } catch (Throwable t) {
59                         throw new IllegalStateException(t);
60                 } finally {
61                         
62                         releaseMutex();
63                         
64                 }
65                 
66         }
67
68         /*
69          * This method waits - we have no locks here
70          */
71         public void ensureUpdates(ClusterUID uid) throws DatabaseException {
72
73                 ClusterInfo info = getWithoutMutex(uid);
74                 if(info == null)
75                     throw new ClusterDoesNotExistException("Asked a cluster which does not exist: " + uid);
76                 info.waitForUpdates();
77                 
78         }
79
80         public ClusterInfo get(ClusterUID uid, boolean makeIfNull, boolean ensureUpdates) throws DatabaseException {
81
82                 if (ensureUpdates) {
83                     try {
84                         ensureUpdates(uid);
85                     } catch (ClusterDoesNotExistException e) {
86                         if (makeIfNull) {
87                             Logger.defaultLogError("For debug purposes, creating cluster which does not exist", e);
88                         } else {
89                             throw e;
90                         }
91                     }
92                 }
93                 return getOrCreate(uid, makeIfNull);
94         }
95         
96         public ClusterInfo get(ClusterUID uid, boolean makeIfNull) throws DatabaseException {
97                 return get(uid, makeIfNull, true);
98                 
99         }
100
101         public int getResourceKey(ClusterUID uid, int index) {
102
103                 if(VERIFY) verifyAccess();
104
105                 Integer i = clusterMapping.getRight(uid);
106                 if (i == null) {
107                         i = clusterMapping.size() + 1;
108                         clusterMapping.map(uid, i);
109                 }
110                 return (i << 12) + index;
111
112         }
113
114         public int getResourceKeyWithoutMutex(ClusterUID uid, int index) {
115                 
116                 acquireMutex();
117                 try {
118                         return getResourceKey(uid, index);
119                 } catch (Throwable t) {
120                         throw new IllegalStateException(t);
121                 } finally {
122                         releaseMutex();
123                 }
124                 
125         }
126
127         public int createClusterKeyByClusterUID(ClusterUID uid) {
128                 
129                 if(VERIFY) verifyAccess();
130                 
131                 Integer i = clusterMapping.getRight(uid);
132                 if (i == null) {
133                         i = clusterMapping.size() + 1;
134                         clusterMapping.map(uid, i);
135                 }
136                 return i;
137                 
138         }
139
140         public ClusterBase getClusterByClusterUIDOrMake(ClusterUID uid) throws DatabaseException {
141                 
142                 if(VERIFY) verifyAccess();
143                 
144                 int key = createClusterKeyByClusterUID(uid);
145                 return getClusterByClusterKey(key);
146                 
147         }
148
149         public int getClusterKeyByClusterUIDOrMake(ClusterUID clusterUID) {
150
151                 if(VERIFY) verifyAccess();
152
153                 return createClusterKeyByClusterUID(clusterUID);
154                         
155         }
156         
157         public int getClusterKeyByClusterUIDOrMakeWithoutMutex(ClusterUID clusterUID) {
158                 acquireMutex();
159                 try {
160                         return getClusterKeyByClusterUIDOrMake(clusterUID);
161                 } catch (Throwable t) {
162                         throw new IllegalStateException(t);
163                 } finally {
164                         releaseMutex();
165                 }
166         }
167
168         public ClusterBase getClusterByClusterKey(int clusterKey) throws DatabaseException {
169                 
170                 if(VERIFY) verifyAccess();
171                 
172                 ClusterUID uid = clusterMapping.getLeft(clusterKey);
173                 ClusterInfo info = get(uid, true);
174                 info.acquireMutex();
175                 try {
176                         return info.getCluster();
177                 } catch (Throwable t) {
178                         throw new IllegalStateException(t);
179                 } finally {
180                         info.releaseMutex();
181                 }
182                 
183         }
184
185         public ClusterUID getClusterUIDByResourceKey(int resourceKey)
186                         throws DatabaseException {
187                 
188                 if(VERIFY) verifyAccess();
189                 
190                 int clusterKey = resourceKey >> 12;
191                 return clusterMapping.getLeft(clusterKey);
192                 
193         }
194         
195         public ClusterUID getClusterUIDByResourceKeyWithoutMutex(int resourceKey) throws DatabaseException {
196                 acquireMutex();
197                 try {
198                         return getClusterUIDByResourceKey(resourceKey);
199                 } catch (Throwable t) {
200                         throw new IllegalStateException(t);
201                 } finally {
202                         releaseMutex();
203                 }
204         }
205
206         @SuppressWarnings("unchecked")
207         public <T extends ClusterI> T getClusterByClusterUIDOrMakeProxy(ClusterUID uid) throws DatabaseException {
208                 return (T) getClusterByClusterUIDOrMake(uid);
209         }
210
211         @SuppressWarnings("unchecked")
212         public <T extends ClusterI> T getClusterProxyByResourceKey(int resourceKey) throws DatabaseException {
213                 
214                 if(VERIFY) verifyAccess();
215
216                 return (T) getClusterByClusterKey(resourceKey >> 12);
217                 
218         }
219
220         public int getClusterKeyByUID(long id1, long id2) throws DatabaseException {
221                 
222                 if(VERIFY) verifyAccess();
223
224                 return getClusterKeyByClusterUIDOrMake(ClusterUID.make(id1, id2));
225                 
226         }
227         
228         public int getClusterKeyByUIDWithoutMutex(long id1, long id2) throws DatabaseException {
229
230                 acquireMutex();
231                 try {
232                         return getClusterKeyByClusterUIDOrMake(ClusterUID.make(id1, id2));
233                 } catch (Throwable t) {
234                         throw new IllegalStateException(t);
235                 } finally {
236                         releaseMutex();
237                 }
238
239         }
240
241         
242         public static void main(String[] args) throws Exception {
243                 
244                 long start = System.nanoTime();
245                 
246                 final TIntIntHashMap map = new TIntIntHashMap(0, 0.9f);
247
248                 AtomicInteger counter = new AtomicInteger(0);
249                 AtomicBoolean written = new AtomicBoolean(false);
250                 
251                 //final Semaphore ws = new Semaphore(1);
252                 
253                 Thread write = new Thread() {
254                         
255                         @Override
256                         public void run() {
257                                 try {
258                                         for(int i=0;i<100000000;i++) {
259                                                 synchronized(map) {
260 //                                              ws.acquire();
261                                                 map.put(i, i);
262 //                                              ws.release();
263                                                 }
264                                                 //if((i & 0xfffff) == 0) System.err.println("Write " + i);
265                                                 counter.incrementAndGet();
266                                         }
267                                         written.set(true);
268                                 } catch (Throwable e) {
269                                         e.printStackTrace();
270                                 }
271                         }
272                         
273                 };
274                 write.start();
275                 
276                 Thread read = new Thread() {
277                         
278                         @Override
279                         public void run() {
280                                 try {
281                                         while(!written.get()) {
282                                                 double r = Math.random();
283                                                 double max = counter.get();
284                                                 int key = (int)(max*r);
285                                                 int value = map.get(key);
286                                                 if(key != value) {
287                                                         //System.err.println("Read failed " + key + " vs. " + value);
288                                                         //ws.acquire();
289                                                         synchronized(map) {
290                                                                 value = map.get(key);
291                                                                 if(key != value) {
292                                                                         System.err.println("Read failed for real " + key + " vs. " + value);
293                                                                 }
294                                                                 //ws.release();
295                                                         }
296                                                 }
297                                                 //if((key & 0xfffff) == 0) System.err.println("Read " + key);
298                                         }
299                                 } catch (Throwable e) {
300                                         e.printStackTrace();
301                                 }
302                         }
303                         
304                 };
305                 read.start();
306                 
307                 write.join();
308                 read.join();
309                 
310                 long duration = System.nanoTime() - start;
311                 System.err.println("took " + 1e-9*duration + "s.");
312                 
313         }
314         
315 }