]> gerrit.simantics Code Review - simantics/platform.git/blob - bundles/org.simantics.simulator.toolkit.db/src/org/simantics/simulator/toolkit/db/StandardSessionManager.java
Fixed Acorn deadlock during snapshotting
[simantics/platform.git] / bundles / org.simantics.simulator.toolkit.db / src / org / simantics / simulator / toolkit / db / StandardSessionManager.java
1 package org.simantics.simulator.toolkit.db;
2
3 import java.util.Collection;
4 import java.util.concurrent.ConcurrentHashMap;
5
6 import org.simantics.db.ReadGraph;
7 import org.simantics.db.WriteGraph;
8 import org.simantics.db.common.request.ParametrizedPrimitiveRead;
9 import org.simantics.db.exception.DatabaseException;
10 import org.simantics.db.layer0.variable.NodeSupport;
11 import org.simantics.db.procedure.Listener;
12 import org.simantics.simulator.toolkit.StandardNodeManagerSupport;
13 import org.simantics.simulator.toolkit.StandardRealm;
14
15 public abstract class StandardSessionManager<Node, Engine extends StandardNodeManagerSupport<Node>> {
16
17     private ConcurrentHashMap<String, Listener<StandardRealm<Node,Engine>>> realmListeners = new ConcurrentHashMap<>();
18     private ConcurrentHashMap<String, StandardRealm<Node,Engine>> REALMS = new ConcurrentHashMap<>(); 
19     private ConcurrentHashMap<String, NodeSupport<Node>> SUPPORTS = new ConcurrentHashMap<>(); 
20
21     // Accessing Realms should be done over ParametrizedPrimitveRead for the
22     // case if a realm is destroyed and new one is created with the same id than
23     // the previously deleted one for the listeners to get discarded and new
24     // registered
25     private class RealmRequest extends ParametrizedPrimitiveRead<String, StandardRealm<Node, Engine>> {
26
27         public RealmRequest(String parameter) {
28             super(parameter);
29         }
30
31         @Override
32         public void register(ReadGraph graph, Listener<StandardRealm<Node, Engine>> procedure) {
33             StandardRealm<Node, Engine> realm = REALMS.get(parameter);
34             if (realm == null) {
35                 try {
36                     realm = createRealmInner(graph, parameter);
37                 } catch (DatabaseException e) {
38                     e.printStackTrace();
39                 }
40             }
41
42             if(procedure.isDisposed()) {
43                 procedure.execute(realm);
44                 return;
45             }
46
47             Listener<StandardRealm<Node,Engine>> existing = getOrDisposeListener(parameter);
48             assert(existing == null);
49             realmListeners.put(parameter, procedure);
50             procedure.execute(realm);
51         }
52
53         private StandardRealm<Node,Engine> createRealmInner(ReadGraph graph, String id) throws DatabaseException {
54             Engine engine = createEngine(graph, id);
55             StandardRealm<Node,Engine> realm = createRealm(engine, id);
56             modifyRealms(id, realm);
57             return realm;
58         }
59     }
60
61     protected StandardSessionManager() {
62     }
63
64     private Listener<StandardRealm<Node,Engine>> getOrDisposeListener(String key) {
65         Listener<StandardRealm<Node,Engine>> listener = realmListeners.get(key);
66         if(listener != null) {
67             if(listener.isDisposed()) {
68                 realmListeners.remove(key);
69             } else {
70                 return listener;
71             }
72         }
73         return null;
74     }
75
76     private void modifyRealms(String key, StandardRealm<Node,Engine> realm) {
77         if(realm != null) {
78             REALMS.put(key, realm);
79         } else {
80             StandardRealm<Node, Engine> removedRealm = REALMS.remove(key);
81             if (removedRealm != null)
82                 removedRealm.close();
83         }
84         Listener<StandardRealm<Node,Engine>> listener = getOrDisposeListener(key);
85         if(listener != null) {
86             listener.execute(realm);
87         }
88     }
89
90     public NodeSupport<Node> getOrCreateNodeSupport(ReadGraph graph, String id) throws DatabaseException {
91         synchronized(SUPPORTS) {
92             NodeSupport<Node> result = SUPPORTS.get(id);
93             if(result == null) {
94                 StandardRealm<Node,Engine> realm = getOrCreateRealm(graph, id);
95                 result = new NodeSupport<Node>(realm.getNodeManager());
96                 SUPPORTS.put(id, result);
97             }
98             return result;
99         }
100     }
101
102     public StandardRealm<Node,Engine> getOrCreateRealm(ReadGraph graph, String id) throws DatabaseException {
103         synchronized(REALMS) {
104             return graph.syncRequest(new RealmRequest(id));
105         }
106     }
107
108     protected abstract Engine createEngine(ReadGraph graph, String id) throws DatabaseException;
109     protected abstract StandardRealm<Node,Engine> createRealm(Engine engine, String id);
110
111     public void removeRealm(WriteGraph graph, String id) throws DatabaseException {
112         modifyRealms(id, null);
113         // remove listeners from this realm
114         realmListeners.remove(id);
115         // if node support has been created remove it as well
116         NodeSupport<Node> support = SUPPORTS.remove(id);
117         if (support != null)
118             support.dispose();
119     }
120
121     public Collection<String> getRealms() {
122         return REALMS.keySet();
123     }
124 }