1 package org.simantics.acorn.lru;
3 import java.nio.file.Path;
4 import java.util.concurrent.atomic.AtomicBoolean;
5 import java.util.concurrent.atomic.AtomicInteger;
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;
17 import gnu.trove.TIntIntHashMap;
19 public class ClusterLRU extends LRU<ClusterUID, ClusterInfo> {
21 final private BijectionMap<ClusterUID, Integer> clusterMapping = new BijectionMap<ClusterUID, Integer>();
22 final private ClusterManager manager;
24 public ClusterLRU(ClusterManager manager, String identifier, Path writeDir) {
26 super(identifier, writeDir);
27 this.manager = manager;
29 clusterMapping.map(ClusterUID.make(0,2), clusterMapping.size() + 1);
33 public ClusterInfo getOrCreate(ClusterUID uid, boolean makeIfNull) {
39 ClusterInfo info = get(uid);
43 if(!makeIfNull) throw new IllegalStateException("Asked for an existing cluster " + uid + " that was not found.");
45 Integer clusterKey = clusterMapping.getRight(uid);
46 if (clusterKey == null) {
47 clusterKey = clusterMapping.size() + 1;
48 clusterMapping.map(uid, clusterKey);
51 info = new ClusterInfo(manager, this, ClusterImpl.make(manager.support,
52 uid, clusterKey, manager.support));
58 } catch (Throwable t) {
59 throw new IllegalStateException(t);
69 * This method waits - we have no locks here
71 public void ensureUpdates(ClusterUID uid) throws DatabaseException {
73 ClusterInfo info = getWithoutMutex(uid);
75 throw new ClusterDoesNotExistException("Asked a cluster which does not exist: " + uid);
76 info.waitForUpdates();
80 public ClusterInfo get(ClusterUID uid, boolean makeIfNull, boolean ensureUpdates) throws DatabaseException {
85 } catch (ClusterDoesNotExistException e) {
87 Logger.defaultLogError("For debug purposes, creating cluster which does not exist", e);
93 return getOrCreate(uid, makeIfNull);
96 public ClusterInfo get(ClusterUID uid, boolean makeIfNull) throws DatabaseException {
97 return get(uid, makeIfNull, true);
101 public int getResourceKey(ClusterUID uid, int index) {
103 if(VERIFY) verifyAccess();
105 Integer i = clusterMapping.getRight(uid);
107 i = clusterMapping.size() + 1;
108 clusterMapping.map(uid, i);
110 return (i << 12) + index;
114 public int getResourceKeyWithoutMutex(ClusterUID uid, int index) {
118 return getResourceKey(uid, index);
119 } catch (Throwable t) {
120 throw new IllegalStateException(t);
127 public int createClusterKeyByClusterUID(ClusterUID uid) {
129 if(VERIFY) verifyAccess();
131 Integer i = clusterMapping.getRight(uid);
133 i = clusterMapping.size() + 1;
134 clusterMapping.map(uid, i);
140 public ClusterBase getClusterByClusterUIDOrMake(ClusterUID uid) throws DatabaseException {
142 if(VERIFY) verifyAccess();
144 int key = createClusterKeyByClusterUID(uid);
145 return getClusterByClusterKey(key);
149 public int getClusterKeyByClusterUIDOrMake(ClusterUID clusterUID) {
151 if(VERIFY) verifyAccess();
153 return createClusterKeyByClusterUID(clusterUID);
157 public int getClusterKeyByClusterUIDOrMakeWithoutMutex(ClusterUID clusterUID) {
160 return getClusterKeyByClusterUIDOrMake(clusterUID);
161 } catch (Throwable t) {
162 throw new IllegalStateException(t);
168 public ClusterBase getClusterByClusterKey(int clusterKey) throws DatabaseException {
170 if(VERIFY) verifyAccess();
172 ClusterUID uid = clusterMapping.getLeft(clusterKey);
173 ClusterInfo info = get(uid, true);
176 return info.getCluster();
177 } catch (Throwable t) {
178 throw new IllegalStateException(t);
185 public ClusterUID getClusterUIDByResourceKey(int resourceKey)
186 throws DatabaseException {
188 if(VERIFY) verifyAccess();
190 int clusterKey = resourceKey >> 12;
191 return clusterMapping.getLeft(clusterKey);
195 public ClusterUID getClusterUIDByResourceKeyWithoutMutex(int resourceKey) throws DatabaseException {
198 return getClusterUIDByResourceKey(resourceKey);
199 } catch (Throwable t) {
200 throw new IllegalStateException(t);
206 @SuppressWarnings("unchecked")
207 public <T extends ClusterI> T getClusterByClusterUIDOrMakeProxy(ClusterUID uid) throws DatabaseException {
208 return (T) getClusterByClusterUIDOrMake(uid);
211 @SuppressWarnings("unchecked")
212 public <T extends ClusterI> T getClusterProxyByResourceKey(int resourceKey) throws DatabaseException {
214 if(VERIFY) verifyAccess();
216 return (T) getClusterByClusterKey(resourceKey >> 12);
220 public int getClusterKeyByUID(long id1, long id2) throws DatabaseException {
222 if(VERIFY) verifyAccess();
224 return getClusterKeyByClusterUIDOrMake(ClusterUID.make(id1, id2));
228 public int getClusterKeyByUIDWithoutMutex(long id1, long id2) throws DatabaseException {
232 return getClusterKeyByClusterUIDOrMake(ClusterUID.make(id1, id2));
233 } catch (Throwable t) {
234 throw new IllegalStateException(t);
242 public static void main(String[] args) throws Exception {
244 long start = System.nanoTime();
246 final TIntIntHashMap map = new TIntIntHashMap(0, 0.9f);
248 AtomicInteger counter = new AtomicInteger(0);
249 AtomicBoolean written = new AtomicBoolean(false);
251 //final Semaphore ws = new Semaphore(1);
253 Thread write = new Thread() {
258 for(int i=0;i<100000000;i++) {
264 //if((i & 0xfffff) == 0) System.err.println("Write " + i);
265 counter.incrementAndGet();
268 } catch (Throwable e) {
276 Thread read = new Thread() {
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);
287 //System.err.println("Read failed " + key + " vs. " + value);
290 value = map.get(key);
292 System.err.println("Read failed for real " + key + " vs. " + value);
297 //if((key & 0xfffff) == 0) System.err.println("Read " + key);
299 } catch (Throwable e) {
310 long duration = System.nanoTime() - start;
311 System.err.println("took " + 1e-9*duration + "s.");