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