DB client state gets corrupted
[simantics/platform.git] / bundles / org.simantics.db.procore / src / fi / vtt / simantics / procore / internal / ClusterBuilderImpl2.java
1 package fi.vtt.simantics.procore.internal;
2
3 import org.simantics.db.Resource;
4 import org.simantics.db.WriteOnlyGraph;
5 import org.simantics.db.exception.DatabaseException;
6 import org.simantics.db.exception.RuntimeDatabaseException;
7 import org.simantics.db.impl.ClusterSupport;
8 import org.simantics.db.impl.ClusterTraitsBase;
9 import org.simantics.db.impl.ResourceImpl;
10 import org.simantics.db.impl.graph.WriteGraphImpl;
11 import org.simantics.db.procore.cluster.ClusterImpl;
12 import org.simantics.db.service.ClusterBuilder2;
13 import org.simantics.db.service.SerialisationSupport;
14
15 import fi.vtt.simantics.procore.internal.SessionImplSocket.WriteOnlySupport;
16
17 public class ClusterBuilderImpl2 implements ClusterBuilder2 {
18
19     final private ClusterSupport cs;
20     final private SerialisationSupport ss;
21     final private ClusterStream stream;
22     final private WriteOnlySupport support;
23     final private ClusterImpl[] clusterArray;
24     private boolean allowImmutables;
25     
26     ClusterBuilderImpl2(SessionImplSocket session, boolean allowImmutables) {
27
28         WriteState<?> state = session.writeState;
29         if(state != null) {
30             WriteGraphImpl graph = state.getGraph();
31             support = (WriteOnlySupport)graph.writeSupport;
32             stream = support.stream;
33         } else {
34             support = null;
35             stream = null;
36         }
37         
38         this.ss = session.getService(SerialisationSupport.class);
39         this.clusterArray = session.clusterTable.getClusterArray();
40         this.cs = session.getService(ClusterSupport.class);
41         this.allowImmutables = allowImmutables;
42         
43     }
44
45     ClusterBuilderImpl2(SessionImplSocket session) {
46         this(session, false);
47     }
48
49     @Override
50     public void newCluster() throws DatabaseException {
51         support.flushCluster();
52     }
53
54     @Override
55     public void selectCluster(long cluster) throws DatabaseException {
56         support.selectCluster(cluster);
57     }
58     
59     @Override
60     public void newCluster(int setHandle) throws DatabaseException {
61         support.setDefaultClusterSet(resource(setHandle));
62         support.flushCluster();
63     }
64     
65     @Override
66     public void createClusterSet(int resource) throws DatabaseException {
67         support.createClusterSet(null, resource(resource));
68     }
69     
70     @Override
71     public int newResource() throws DatabaseException {
72         Resource result = support.createResource(null); 
73         return handle(result);
74     }
75
76     @Override
77     public int newResource(int set) throws DatabaseException {
78         Resource result = support.createResource(null, resource(set));
79         return ss.getTransientId(result);
80     }
81     
82     @Override
83     public int resource(Resource res) throws DatabaseException {
84         ResourceImpl r = (ResourceImpl)res;
85         int clusterKey = ClusterTraitsBase.getClusterKeyFromResourceKeyNoThrow(r.id);
86         ClusterImpl cluster = clusterArray[clusterKey];
87         if(cluster.cc == null) cluster.cc = new ClusterChange(stream, cluster);
88         return r.id;
89     }
90
91     @Override
92     public void addStatement(WriteOnlyGraph graph, int subject, int predicate, int object) throws DatabaseException {
93         int clusterKey = ClusterTraitsBase.getClusterKeyFromResourceKeyNoThrow(subject);
94         ClusterImpl cluster = clusterArray[clusterKey];
95         if(!cluster.isLoaded()) cluster = (ClusterImpl)cs.getClusterByResourceKey(subject);
96         if(cluster.isWriteOnly()) addStatement(cluster, subject, predicate, object);
97         else {
98             WriteGraphImpl impl = (WriteGraphImpl)graph;
99             if(!cluster.getImmutable() || allowImmutables)
100                 impl.writeSupport.claim(graph.getProvider(), subject, predicate, object);
101         }
102     }
103     
104     private void addStatement(ClusterImpl cluster, int resourceKey, int predicate, int object) {
105         
106         if(cluster.getImmutable()) return;
107         
108         Change change = cluster.change;
109         change.addStatementIndex0(resourceKey, ClusterChange.ADD_OPERATION);
110         applyPredicate(cluster, predicate);
111         applyObject(cluster, object);
112         cluster.cc.addChange(change);
113         
114     }
115     
116     public void applyPredicate(ClusterImpl impl, int predicate) {
117         
118         int clusterKey = ClusterTraitsBase.getClusterKeyFromResourceKeyNoThrow(predicate);
119         ClusterImpl cluster = clusterArray[clusterKey]; 
120         
121         impl.change.addStatementIndex1(predicate, cluster.clusterUID, (byte)0, impl.foreignLookup);
122         
123     }
124
125     public void applyObject(ClusterImpl impl, int object) {
126
127         int clusterKey = ClusterTraitsBase.getClusterKeyFromResourceKeyNoThrow(object);
128         ClusterImpl cluster = clusterArray[clusterKey]; 
129         
130         impl.change.addStatementIndex2(object, cluster.clusterUID, (byte)0, impl.foreignLookup);
131         
132     }
133
134     @Override
135     public Resource resource(int key) {
136         try {
137             return ss.getResource(key);
138         } catch (DatabaseException e) {
139             throw new RuntimeDatabaseException(e);
140         }
141     }
142     
143     @Override
144     public int handle(Resource r) {
145         return ((ResourceImpl)r).id;
146     }
147
148     byte[] buffer = new byte[65536];
149     int bufferOffset = 0;
150     int valueSubject = 0;
151     int valueOffset = 0;
152     
153     @Override
154     public void beginValue(int subject) {
155         valueSubject = subject;
156         bufferOffset = 0;
157         valueOffset = 0;
158     }
159         
160     @Override
161     public void appendValue(int byteValue) throws DatabaseException {
162         buffer[bufferOffset++] = (byte)byteValue;
163         if(bufferOffset == 65536) {
164             int clusterKey = ClusterTraitsBase.getClusterKeyFromResourceKeyNoThrow(valueSubject);
165             ClusterImpl cluster = clusterArray[clusterKey]; 
166             cluster.modiValueEx(valueSubject, valueOffset, 65536, buffer, 0, cs);
167             bufferOffset = 0;
168             valueOffset += 65536;
169         }
170     }
171
172     @Override
173     public void endValue() throws DatabaseException {
174         if(bufferOffset > 0) {
175             int clusterKey = ClusterTraitsBase.getClusterKeyFromResourceKeyNoThrow(valueSubject);
176             ClusterImpl cluster = clusterArray[clusterKey]; 
177             if(valueOffset == 0) {
178                 if(cluster.isWriteOnly()) cluster.cc.setValue((short)(valueSubject & 0xFFF), buffer, bufferOffset);
179                 else {
180                     support.claimValue(null, valueSubject, buffer, bufferOffset);
181                 }
182             } else {
183                 cluster.modiValueEx(valueSubject, valueOffset, bufferOffset, buffer, 0, cs);
184             }
185         }
186     }
187     
188 }