]> gerrit.simantics Code Review - simantics/platform.git/blob - bundles/org.simantics.db.procore/src/fi/vtt/simantics/procore/internal/WriteSupportImpl.java
4b3bf37a5789831d494d490f6cb0b4ca6d55d1fa
[simantics/platform.git] / bundles / org.simantics.db.procore / src / fi / vtt / simantics / procore / internal / WriteSupportImpl.java
1 package fi.vtt.simantics.procore.internal;
2
3 import java.util.TreeMap;
4
5 import org.simantics.db.Metadata;
6 import org.simantics.db.Operation;
7 import org.simantics.db.Resource;
8 import org.simantics.db.VirtualGraph;
9 import org.simantics.db.WriteGraph;
10 import org.simantics.db.common.MetadataUtils;
11 import org.simantics.db.common.exception.DebugException;
12 import org.simantics.db.common.utils.Logger;
13 import org.simantics.db.exception.DatabaseException;
14 import org.simantics.db.exception.ImmutableException;
15 import org.simantics.db.exception.ServiceException;
16 import org.simantics.db.impl.ClusterI;
17 import org.simantics.db.impl.MemWatch;
18 import org.simantics.db.impl.ResourceImpl;
19 import org.simantics.db.impl.VirtualGraphImpl;
20 import org.simantics.db.impl.graph.ReadGraphImpl;
21 import org.simantics.db.impl.graph.WriteGraphImpl;
22 import org.simantics.db.impl.graph.WriteSupport;
23 import org.simantics.db.impl.query.QueryProcessor;
24 import org.simantics.db.impl.query.QuerySupport;
25 import org.simantics.db.procore.cluster.ClusterImpl;
26 import org.simantics.db.procore.protocol.Constants;
27 import org.simantics.db.request.Write;
28 import org.simantics.db.request.WriteOnly;
29 import org.simantics.db.request.WriteResult;
30 import org.simantics.db.request.WriteTraits;
31 import org.simantics.db.service.ByteReader;
32
33 public class WriteSupportImpl implements WriteSupport {
34
35     final private SessionImplSocket session;
36     final private QueryProcessor queryProcessor;
37     final private State state;
38     final private QuerySupport querySupport;
39     final private TreeMap<String, byte[]> metadata;
40     
41     WriteSupportImpl(SessionImplSocket session) {
42         this.session = session;
43         this.queryProcessor = session.getQueryProvider2();
44         this.state = session.state;
45         this.querySupport = session.querySupport;
46         this.metadata = new TreeMap<String, byte[]>();
47         assert(this.session != null);
48         assert(this.queryProcessor != null);
49         assert(this.state != null);
50         assert(this.querySupport != null);
51     }
52     
53     @Override
54     public void flushCluster() {
55         session.clusterTable.flushCluster(session.graphSession);
56         if(session.defaultClusterSet != null) {
57             long resourceId = session.defaultClusterSet.getResourceId();
58             session.clusterSetsSupport.put(resourceId, Constants.NewClusterId);
59         }
60     }
61
62     @Override
63     public void flushCluster(Resource r) {
64         session.clusterStream.reallyFlush();
65     }
66
67     @Override
68     public boolean writeOnly() {
69         return session.writeOnly;
70     }
71
72     @Override
73     public void flush(boolean intermediate) {
74
75         if (!session.state.isWriteTransaction())
76             throw new IllegalStateException("Can only flush during transaction.");
77
78         gc();
79         
80     }
81     
82     final public void claim(VirtualGraph provider, Resource subject, Resource predicate, Resource object) throws ServiceException {
83         claim(provider, querySupport.getId(subject), querySupport.getId(predicate), querySupport.getId(object));
84     }
85
86     @Override
87     final public void claim(VirtualGraph provider, int subject, int predicate, int object)
88     throws ServiceException {
89
90         provider = session.getProvider(provider); 
91         if (writeOnly()) {
92             if (provider != null) {
93                 ((VirtualGraphImpl)provider).claim(subject, predicate, object);
94                 queryProcessor.updateStatements(subject, predicate);
95                 session.clientChanges.claim(subject, predicate, object);
96             } else {
97                 claimImpl2(subject, predicate, object);
98             }
99         } else {
100 //            queryProcessor.acquireWrite(writeState.getGraph());
101             if (provider != null) {
102                 ((VirtualGraphImpl)provider).claim(subject, predicate, object);
103                 queryProcessor.updateStatements(subject, predicate);
104                 session.clientChanges.claim(subject, predicate, object);
105             } else {
106                 claimImpl(subject, predicate, object);
107             }
108             queryProcessor.releaseWrite(session.writeState.getGraph());
109         }
110         
111     }
112     
113     @Override
114     public void setValue(VirtualGraph provider, Resource resource, byte[] value) throws ServiceException {
115
116         provider = session.getProvider(provider);
117         if (writeOnly()) {
118             if (provider != null) {
119                 ((VirtualGraphImpl)provider).claimValue(((ResourceImpl) resource).id, value, value.length);
120                 queryProcessor.updateValue(querySupport.getId(resource));
121                 session.clientChanges.claimValue(resource);
122             } else {
123                 try {
124                     addSetValue(((ResourceImpl) resource).id, value, value.length);
125                 } catch (DatabaseException e) {
126                     Logger.defaultLogError(e);
127                 }
128             }
129         } else {
130             if (provider != null) {
131                 ((VirtualGraphImpl)provider).claimValue(((ResourceImpl) resource).id, value, value.length);
132                 queryProcessor.updateValue(querySupport.getId(resource));
133                 session.clientChanges.claimValue(resource);
134             } else {
135                 try {
136                     addSetValue(((ResourceImpl) resource).id, value, value.length);
137                 } catch (DatabaseException e) {
138                     Logger.defaultLogError(e);
139                 }
140             }
141             queryProcessor.releaseWrite(session.writeState.getGraph());
142         }
143
144     }
145
146     @Override
147     public Resource createResource(VirtualGraph provider) throws DatabaseException {
148         if (provider != null) {
149             int newId = ((VirtualGraphImpl)provider).newResource(false);
150             return new ResourceImpl(session.resourceSupport, newId);
151         } else {
152             return session.getNewResource();
153         }
154     }
155
156     @Override
157     public Resource createResource(VirtualGraph provider, long clusterId)
158     throws DatabaseException {
159         assert (provider == null);
160         return session.getNewResource(clusterId);
161     }
162
163     @Override
164     public Resource createResource(VirtualGraph provider, Resource clusterSet)
165     throws DatabaseException {
166         assert(provider == null);
167         assert(clusterSet != null);
168         return session.getNewResource(clusterSet);
169     }
170
171     @Override
172     public void createClusterSet(VirtualGraph provider, Resource clusterSet)
173     throws DatabaseException {
174         assert(provider == null);
175         assert(clusterSet != null);
176         session.getNewClusterSet(clusterSet);
177     }
178
179     @Override
180     public boolean hasClusterSet(VirtualGraph dummy, Resource clusterSet)
181     throws ServiceException {
182         return session.containsClusterSet(clusterSet);
183     }
184
185     @Override
186     public Resource setDefaultClusterSet(Resource clusterSet)
187     throws ServiceException {
188         return session.setDefaultClusterSet4NewResource(clusterSet);
189     }
190     @Override
191     public void denyValue(VirtualGraph provider, Resource resource) throws ServiceException {
192         provider = session.getProvider(provider);
193         if (null == provider) {
194             int key = ((ResourceImpl)resource).id;
195             ClusterI cluster = session.clusterTable.getClusterByResourceKey(key);
196             if (cluster.getImmutable() && (session.serviceMode & SessionImplSocket.SERVICE_MODE_ALLOW) == 0)
197                 if(key != queryProcessor.getRootLibrary())
198                         throw new ImmutableException("Trying to modify immutable resource key=" + key);
199
200             try { 
201                 cluster.removeValue(key, session.clusterTranslator);
202             } catch (DatabaseException e) {
203                 Logger.defaultLogError(e);
204                 return;
205             }
206             queryProcessor.updateValue(key);
207             session.clientChanges.claimValue(resource);
208         } else {
209             ((VirtualGraphImpl)provider).denyValue(((ResourceImpl) resource).id);
210             queryProcessor.updateValue(querySupport.getId(resource));
211             session.clientChanges.claimValue(resource);
212         }
213         if (!writeOnly())
214             queryProcessor.releaseWrite(session.writeState.getGraph());
215     }
216
217
218     @Override
219     public boolean removeStatement(VirtualGraph provider, Resource subject, Resource predicate,
220             Resource object) throws ServiceException {
221         boolean ret = true;
222         if (writeOnly()) {
223             if (provider != null) {
224                 ((VirtualGraphImpl)provider).deny(querySupport.getId(subject), querySupport.getId(predicate), querySupport.getId(object));
225                 queryProcessor.updateStatements(querySupport.getId(subject), querySupport.getId(predicate));
226             } else {
227                 ret = removeStatement(querySupport.getId(subject), querySupport.getId(predicate), querySupport.getId(object));
228             }
229         } else {
230             if (provider != null) {
231 //                queryProcessor.acquireWrite(writeState.getGraph());
232                 ((VirtualGraphImpl)provider).deny(querySupport.getId(subject), querySupport.getId(predicate), querySupport.getId(object));
233                 queryProcessor.updateStatements(querySupport.getId(subject), querySupport.getId(predicate));
234                 queryProcessor.releaseWrite(session.writeState.getGraph());
235             } else {
236                 int sid = querySupport.getId(subject);
237                 int pid = querySupport.getId(predicate);
238                 int oid = querySupport.getId(object);
239                 if (sid < 0 || pid < 0 || oid < 0) {
240                     // One of the resources is virtual, cannot remove such
241                     // statement from persistent storage.
242                     return false;
243                 }
244 //                queryProcessor.acquireWrite(writeState.getGraph());
245                 ret = removeStatement(sid, pid, oid);
246                 queryProcessor.releaseWrite(session.writeState.getGraph());
247             }
248         }
249         session.clientChanges.deny(subject, predicate, object);
250         return ret;
251     }
252     
253     @Override
254     public synchronized void performWriteRequest(WriteGraph graph_, Write request) throws DatabaseException {
255         WriteGraphImpl graph = (WriteGraphImpl)graph_;
256 //        graph.state.barrier.inc();
257         try {
258             request.perform(graph);
259         } catch (Throwable t) {
260             t.printStackTrace();
261         }
262 //        graph.state.barrier.dec();
263 //        graph.waitAsync(request);
264         
265         queryProcessor.performDirtyUpdates(graph);
266         
267         // Do not fire metadata listeners for virtual requests
268         if(graph.getProvider() == null) {
269             //session.fireMetadataListeners(graph, session.clientChanges);
270             state.commitAndContinue(graph, session.clusterStream, request);
271             //session.clientChanges = new ClientChangesImpl(session);
272         }
273
274 //        graph.state.barrier.assertReady();
275         
276     }
277     
278     @Override
279     public synchronized <T> T performWriteRequest(WriteGraph graph_, WriteResult<T> request) throws DatabaseException {
280
281         WriteGraphImpl graph = (WriteGraphImpl)graph_;
282 //        graph.state.barrier.inc();
283         T result = null;
284         Throwable t = null;
285         try {
286             result = request.perform(graph);
287         } catch (Throwable t2) {
288             if(DebugException.DEBUG) new DebugException(t2).printStackTrace();
289             t = t2;
290         }
291         
292 //        graph.state.barrier.dec();
293 //        graph.waitAsync(request);
294         
295         queryProcessor.performDirtyUpdates(graph);
296
297         // Do not fire metadata listeners for virtual requests
298         if(graph.getProvider() == null) {
299             //session.fireMetadataListeners((WriteGraphImpl)graph, session.clientChanges);
300             state.commitAndContinue(graph, session.clusterStream, request);
301             //session.clientChanges = new ClientChangesImpl(session);
302         }
303         
304         if(t != null) {
305             if(t instanceof DatabaseException) throw (DatabaseException)t;
306             else throw new DatabaseException(t);
307         }
308         
309         return result;
310         
311     }
312
313     @Override
314     public synchronized void performWriteRequest(WriteGraph graph, WriteOnly request) throws DatabaseException {
315
316         session.acquireWriteOnly();
317         
318         request.perform(graph);
319         
320         ReadGraphImpl impl = (ReadGraphImpl)graph;
321         
322         queryProcessor.performDirtyUpdates(impl);
323
324         // Do not fire metadata listeners for virtual requests
325         if(graph.getProvider() == null) {
326             //session.fireMetadataListeners(impl, session.clientChanges);
327             state.commitAndContinue(session.writeState.getGraph(), session.clusterStream, request);
328             //session.clientChanges = new ClientChangesImpl(session);
329         }        
330         session.releaseWriteOnly(impl);
331         
332     }
333
334     
335     @Override
336     public void gc() {
337         if (MemWatch.isLowOnMemory()) {
338             session.clusterTable.gc();
339             queryProcessor.gc(0, Integer.MAX_VALUE);
340             System.gc();
341         }
342     }
343     
344     @Override
345     public void claimValue(VirtualGraph provider, Resource resource, byte[] value) throws DatabaseException {
346         claimValue(provider, ((ResourceImpl)resource).id, value, value.length);
347     }
348
349     @Override
350     public void claimValue(VirtualGraph provider, int resource, byte[] value, int length) throws DatabaseException {
351
352         provider = session.getProvider(provider);
353         if (writeOnly()) {
354             if (provider != null) {
355                 ((VirtualGraphImpl)provider).claimValue(resource, value, length);
356                 queryProcessor.updateValue(resource);
357                 session.clientChanges.claimValue(resource);
358             } else {
359                 addSetValue(resource, value, length);
360             }
361         } else {
362             if (provider != null) {
363                 ((VirtualGraphImpl)provider).claimValue(resource, value, length);
364                 queryProcessor.updateValue(resource);
365                 session.clientChanges.claimValue(resource);
366                 queryProcessor.releaseWrite(session.writeState.getGraph());
367             } else {
368                 try {
369                     addSetValue(resource, value, length);
370                 } catch (DatabaseException e) {
371                     throw e;
372                 } catch (Throwable t) {
373                     throw new DatabaseException(t);
374                 } finally {
375                     queryProcessor.releaseWrite(session.writeState.getGraph());
376                 }
377             }
378         }
379     }
380     
381     @Override
382     public void claimValue(VirtualGraph provider, Resource resource, ByteReader reader, int amount) throws DatabaseException {
383         claimValue(provider, resource, reader.readBytes(null, amount));
384     }
385
386     @Override
387     public <T> void addMetadata(Metadata data) throws ServiceException {
388         MetadataUtils.addMetadata(session, metadata, data);
389     }
390
391     @SuppressWarnings("unchecked")
392     @Override
393     public <T extends Metadata> T getMetadata(Class<T> clazz) throws ServiceException {
394         return MetadataUtils.getMetadata(session, metadata, clazz);
395     }
396
397     @Override
398     public TreeMap<String, byte[]> getMetadata() {
399         return metadata;
400     }
401
402     @Override
403     public void commitDone(WriteTraits writeTraits, long csid) {
404         metadata.clear();
405         if (this.writeTraits == writeTraits) {
406             session.graphSession.undoContext.clear();
407             this.writeTraits = null;
408         }
409 //        if (null != operation)
410 //            operation = null;
411     }
412     @Override
413     public int clearMetadata() {
414         int ret = metadata.size();
415         metadata.clear();
416         return ret;
417     }
418     @Override
419     public void clearUndoList(WriteTraits writeTraits) {
420         this.writeTraits = writeTraits;
421     }
422     @Override
423     public void startUndo() {
424         session.state.setCombine(false);
425     }
426     private WriteTraits writeTraits = null;
427     private void addSetValue(int subject, byte[] value, int length)
428     throws DatabaseException {
429
430         ClusterI cluster = session.clusterTable.getClusterByResourceKey(subject);
431         if (cluster.getImmutable() && (session.serviceMode & SessionImplSocket.SERVICE_MODE_ALLOW) == 0)
432                 if(subject != queryProcessor.getRootLibrary())
433                         throw new ImmutableException("Trying to modify immutable resource key=" + subject);
434         
435         ClusterI cluster2 = cluster.setValue(subject, value, length, session.clusterTranslator);
436         if (cluster2 != cluster)
437             session.clusterTable.replaceCluster(cluster2);
438         
439         session.clientChanges.claimValue(subject);
440         
441         if (cluster2.isWriteOnly())
442             return;
443
444         queryProcessor.updateValue(subject);
445
446     }
447
448     final private void claimImpl(int subject, int predicate, int object)
449     throws ServiceException {
450
451         assert (subject != 0);
452         assert (predicate != 0);
453         assert (object != 0);
454
455         ClusterImpl cluster = session.clusterTable.getClusterByResourceKey(subject);
456         assert (null != cluster);
457         if (cluster.getImmutable() && (session.serviceMode & SessionImplSocket.SERVICE_MODE_ALLOW) == 0)
458                 if(subject != queryProcessor.getRootLibrary())
459                         throw new ImmutableException("Trying to modify immutable resource key=" + subject);
460         try {
461             ClusterI c = cluster.addRelation(subject, predicate, object, session.clusterTranslator);
462             if (null != c && c != cluster)
463                 session.clusterTable.replaceCluster(c);
464         } catch (DatabaseException e) {
465             Logger.defaultLogError(e);
466             throw new RuntimeException(e);
467         }
468         queryProcessor.updateStatements(subject, predicate);
469         session.clientChanges.claim(subject, predicate, object);
470
471     }
472
473     final private void claimImpl2(int subject, int predicate, int object) {
474         
475         assert (subject != 0);
476         assert (predicate != 0);
477         assert (object != 0);
478
479         ClusterI cluster = session.clusterTable.getClusterByResourceKey(subject);
480         try {
481             ClusterI c = cluster.addRelation(subject, predicate, object, session.clusterTranslator);
482             if (null != c && c != cluster)
483                 session.clusterTable.replaceCluster(c);
484         } catch (DatabaseException e) {
485             Logger.defaultLogError(e);
486         }
487         if (cluster.isWriteOnly())
488             return;
489         queryProcessor.updateStatements(subject, predicate);
490
491     }
492     
493     private boolean removeStatement(int subject, int predicate, int object) throws ImmutableException {
494
495         assert (subject != 0);
496         assert (predicate != 0);
497         assert (object != 0);
498
499         ClusterI cluster = session.clusterTable.getClusterByResourceKey(subject);
500         assert (null != cluster);
501
502         if (cluster.getImmutable() && (session.serviceMode & SessionImplSocket.SERVICE_MODE_ALLOW) == 0)
503                 if(subject != queryProcessor.getRootLibrary())
504                         throw new ImmutableException("Trying to modify immutable resource key=" + subject);
505
506         try {
507             cluster.denyRelation(subject, predicate, object, session.clusterTranslator);
508         } catch (DatabaseException e) {
509             Logger.defaultLogError(e);
510             return false;
511         }
512         queryProcessor.updateStatements(subject, predicate);
513         return true;
514
515     }
516     
517 }