1 package fi.vtt.simantics.procore.internal;
3 import java.util.TreeMap;
5 import org.simantics.db.Metadata;
6 import org.simantics.db.Resource;
7 import org.simantics.db.VirtualGraph;
8 import org.simantics.db.WriteGraph;
9 import org.simantics.db.common.MetadataUtils;
10 import org.simantics.db.common.exception.DebugException;
11 import org.simantics.db.common.utils.Logger;
12 import org.simantics.db.exception.DatabaseException;
13 import org.simantics.db.exception.ImmutableException;
14 import org.simantics.db.exception.ServiceException;
15 import org.simantics.db.impl.ClusterI;
16 import org.simantics.db.impl.MemWatch;
17 import org.simantics.db.impl.ResourceImpl;
18 import org.simantics.db.impl.VirtualGraphImpl;
19 import org.simantics.db.impl.graph.ReadGraphImpl;
20 import org.simantics.db.impl.graph.WriteGraphImpl;
21 import org.simantics.db.impl.graph.WriteSupport;
22 import org.simantics.db.impl.query.QueryProcessor;
23 import org.simantics.db.impl.query.QuerySupport;
24 import org.simantics.db.procore.cluster.ClusterImpl;
25 import org.simantics.db.procore.protocol.Constants;
26 import org.simantics.db.request.Write;
27 import org.simantics.db.request.WriteOnly;
28 import org.simantics.db.request.WriteResult;
29 import org.simantics.db.request.WriteTraits;
30 import org.simantics.db.service.ByteReader;
32 public class WriteSupportImpl implements WriteSupport {
34 final private SessionImplSocket session;
35 final private QueryProcessor queryProcessor;
36 final private State state;
37 final private QuerySupport querySupport;
38 final private TreeMap<String, byte[]> metadata;
40 WriteSupportImpl(SessionImplSocket session) {
41 this.session = session;
42 this.queryProcessor = session.getQueryProvider2();
43 this.state = session.state;
44 this.querySupport = session.querySupport;
45 this.metadata = new TreeMap<String, byte[]>();
46 assert(this.session != null);
47 assert(this.queryProcessor != null);
48 assert(this.state != null);
49 assert(this.querySupport != null);
53 public void flushCluster() {
54 session.clusterTable.flushCluster(session.graphSession);
55 if(session.defaultClusterSet != null) {
56 long resourceId = session.defaultClusterSet.getResourceId();
57 session.clusterSetsSupport.put(resourceId, Constants.NewClusterId);
62 public void flushCluster(Resource r) {
63 session.clusterStream.reallyFlush();
67 public boolean writeOnly() {
68 return session.writeOnly;
72 public void flush(boolean intermediate) {
74 if (!session.state.isWriteTransaction())
75 throw new IllegalStateException("Can only flush during transaction.");
81 final public void claim(VirtualGraph provider, Resource subject, Resource predicate, Resource object) throws ServiceException {
82 claim(provider, querySupport.getId(subject), querySupport.getId(predicate), querySupport.getId(object));
86 final public void claim(VirtualGraph provider, int subject, int predicate, int object)
87 throws ServiceException {
89 provider = session.getProvider(provider);
91 if (provider != null) {
92 ((VirtualGraphImpl)provider).claim(subject, predicate, object);
93 queryProcessor.updateStatements(subject, predicate);
94 session.clientChanges.claim(subject, predicate, object);
96 claimImpl2(subject, predicate, object);
99 // queryProcessor.acquireWrite(writeState.getGraph());
100 if (provider != null) {
101 ((VirtualGraphImpl)provider).claim(subject, predicate, object);
102 queryProcessor.updateStatements(subject, predicate);
103 session.clientChanges.claim(subject, predicate, object);
105 claimImpl(subject, predicate, object);
107 queryProcessor.releaseWrite(session.writeState.getGraph());
113 public void setValue(VirtualGraph provider, Resource resource, byte[] value) throws ServiceException {
115 provider = session.getProvider(provider);
117 if (provider != null) {
118 ((VirtualGraphImpl)provider).claimValue(((ResourceImpl) resource).id, value, value.length);
119 queryProcessor.updateValue(querySupport.getId(resource));
120 session.clientChanges.claimValue(resource);
123 addSetValue(((ResourceImpl) resource).id, value, value.length);
124 } catch (DatabaseException e) {
125 Logger.defaultLogError(e);
129 if (provider != null) {
130 ((VirtualGraphImpl)provider).claimValue(((ResourceImpl) resource).id, value, value.length);
131 queryProcessor.updateValue(querySupport.getId(resource));
132 session.clientChanges.claimValue(resource);
135 addSetValue(((ResourceImpl) resource).id, value, value.length);
136 } catch (DatabaseException e) {
137 Logger.defaultLogError(e);
140 queryProcessor.releaseWrite(session.writeState.getGraph());
146 public Resource createResource(VirtualGraph provider) throws DatabaseException {
147 if (provider != null) {
148 int newId = ((VirtualGraphImpl)provider).newResource(false);
149 return new ResourceImpl(session.resourceSupport, newId);
151 return session.getNewResource();
156 public Resource createResource(VirtualGraph provider, long clusterId)
157 throws DatabaseException {
158 assert (provider == null);
159 return session.getNewResource(clusterId);
163 public Resource createResource(VirtualGraph provider, Resource clusterSet)
164 throws DatabaseException {
165 assert(provider == null);
166 assert(clusterSet != null);
167 return session.getNewResource(clusterSet);
171 public void createClusterSet(VirtualGraph provider, Resource clusterSet)
172 throws DatabaseException {
173 assert(provider == null);
174 assert(clusterSet != null);
175 session.getNewClusterSet(clusterSet);
179 public boolean hasClusterSet(VirtualGraph dummy, Resource clusterSet)
180 throws ServiceException {
181 return session.containsClusterSet(clusterSet);
185 public Resource setDefaultClusterSet(Resource clusterSet)
186 throws ServiceException {
187 return session.setDefaultClusterSet4NewResource(clusterSet);
190 public void denyValue(VirtualGraph provider, Resource resource) throws ServiceException {
191 provider = session.getProvider(provider);
192 if (null == provider) {
193 int key = ((ResourceImpl)resource).id;
194 ClusterI cluster = session.clusterTable.getClusterByResourceKey(key);
195 if (cluster.getImmutable() && (session.serviceMode & SessionImplSocket.SERVICE_MODE_ALLOW) == 0)
196 if(key != queryProcessor.getRootLibrary())
197 throw new ImmutableException("Trying to modify immutable resource key=" + key);
200 cluster.removeValue(key, session.clusterTranslator);
201 } catch (DatabaseException e) {
202 Logger.defaultLogError(e);
205 queryProcessor.updateValue(key);
206 session.clientChanges.claimValue(resource);
208 ((VirtualGraphImpl)provider).denyValue(((ResourceImpl) resource).id);
209 queryProcessor.updateValue(querySupport.getId(resource));
210 session.clientChanges.claimValue(resource);
213 queryProcessor.releaseWrite(session.writeState.getGraph());
218 public boolean removeStatement(VirtualGraph provider, Resource subject, Resource predicate,
219 Resource object) throws ServiceException {
222 if (provider != null) {
223 ((VirtualGraphImpl)provider).deny(querySupport.getId(subject), querySupport.getId(predicate), querySupport.getId(object));
224 queryProcessor.updateStatements(querySupport.getId(subject), querySupport.getId(predicate));
226 ret = removeStatement(querySupport.getId(subject), querySupport.getId(predicate), querySupport.getId(object));
229 if (provider != null) {
230 // queryProcessor.acquireWrite(writeState.getGraph());
231 ((VirtualGraphImpl)provider).deny(querySupport.getId(subject), querySupport.getId(predicate), querySupport.getId(object));
232 queryProcessor.updateStatements(querySupport.getId(subject), querySupport.getId(predicate));
233 queryProcessor.releaseWrite(session.writeState.getGraph());
235 int sid = querySupport.getId(subject);
236 int pid = querySupport.getId(predicate);
237 int oid = querySupport.getId(object);
238 if (sid < 0 || pid < 0 || oid < 0) {
239 // One of the resources is virtual, cannot remove such
240 // statement from persistent storage.
243 // queryProcessor.acquireWrite(writeState.getGraph());
244 ret = removeStatement(sid, pid, oid);
245 queryProcessor.releaseWrite(session.writeState.getGraph());
248 session.clientChanges.deny(subject, predicate, object);
253 public synchronized void performWriteRequest(WriteGraph graph_, Write request) throws DatabaseException {
254 WriteGraphImpl graph = (WriteGraphImpl)graph_;
255 // graph.state.barrier.inc();
257 request.perform(graph);
258 } catch (Throwable t) {
261 // graph.state.barrier.dec();
262 // graph.waitAsync(request);
264 queryProcessor.propagateChangesInQueryCache(graph);
266 // Do not fire metadata listeners for virtual requests
267 if(graph.getProvider() == null) {
268 //session.fireMetadataListeners(graph, session.clientChanges);
269 state.commitAndContinue(graph, session.clusterStream, request);
270 //session.clientChanges = new ClientChangesImpl(session);
273 // graph.state.barrier.assertReady();
278 public synchronized <T> T performWriteRequest(WriteGraph graph_, WriteResult<T> request) throws DatabaseException {
280 WriteGraphImpl graph = (WriteGraphImpl)graph_;
281 // graph.state.barrier.inc();
285 result = request.perform(graph);
286 } catch (Throwable t2) {
287 if(DebugException.DEBUG) new DebugException(t2).printStackTrace();
291 // graph.state.barrier.dec();
292 // graph.waitAsync(request);
294 queryProcessor.propagateChangesInQueryCache(graph);
296 // Do not fire metadata listeners for virtual requests
297 if(graph.getProvider() == null) {
298 //session.fireMetadataListeners((WriteGraphImpl)graph, session.clientChanges);
299 state.commitAndContinue(graph, session.clusterStream, request);
300 //session.clientChanges = new ClientChangesImpl(session);
304 if(t instanceof DatabaseException) throw (DatabaseException)t;
305 else throw new DatabaseException(t);
313 public synchronized void performWriteRequest(WriteGraph graph, WriteOnly request) throws DatabaseException {
315 session.acquireWriteOnly();
317 request.perform(graph);
319 ReadGraphImpl impl = (ReadGraphImpl)graph;
321 queryProcessor.propagateChangesInQueryCache(impl);
323 // Do not fire metadata listeners for virtual requests
324 if(graph.getProvider() == null) {
325 //session.fireMetadataListeners(impl, session.clientChanges);
326 state.commitAndContinue(session.writeState.getGraph(), session.clusterStream, request);
327 //session.clientChanges = new ClientChangesImpl(session);
329 session.releaseWriteOnly(impl);
336 if (MemWatch.isLowOnMemory()) {
337 session.clusterTable.gc();
338 queryProcessor.gc(0, Integer.MAX_VALUE);
344 public void claimValue(VirtualGraph provider, Resource resource, byte[] value) throws DatabaseException {
345 claimValue(provider, ((ResourceImpl)resource).id, value, value.length);
349 public void claimValue(VirtualGraph provider, int resource, byte[] value, int length) throws DatabaseException {
351 provider = session.getProvider(provider);
353 if (provider != null) {
354 ((VirtualGraphImpl)provider).claimValue(resource, value, length);
355 queryProcessor.updateValue(resource);
356 session.clientChanges.claimValue(resource);
358 addSetValue(resource, value, length);
361 if (provider != null) {
362 ((VirtualGraphImpl)provider).claimValue(resource, value, length);
363 queryProcessor.updateValue(resource);
364 session.clientChanges.claimValue(resource);
365 queryProcessor.releaseWrite(session.writeState.getGraph());
368 addSetValue(resource, value, length);
369 } catch (DatabaseException e) {
371 } catch (Throwable t) {
372 throw new DatabaseException(t);
374 queryProcessor.releaseWrite(session.writeState.getGraph());
381 public void claimValue(VirtualGraph provider, Resource resource, ByteReader reader, int amount) throws DatabaseException {
382 claimValue(provider, resource, reader.readBytes(null, amount));
386 public <T> void addMetadata(Metadata data) throws ServiceException {
387 MetadataUtils.addMetadata(session, metadata, data);
391 public <T extends Metadata> T getMetadata(Class<T> clazz) throws ServiceException {
392 return MetadataUtils.getMetadata(session, metadata, clazz);
396 public TreeMap<String, byte[]> getMetadata() {
401 public void commitDone(WriteTraits writeTraits, long csid) {
403 if (this.writeTraits == writeTraits) {
404 session.graphSession.undoContext.clear();
405 this.writeTraits = null;
407 // if (null != operation)
411 public int clearMetadata() {
412 int ret = metadata.size();
417 public void clearUndoList(WriteTraits writeTraits) {
418 this.writeTraits = writeTraits;
421 public void startUndo() {
422 session.state.setCombine(false);
424 private WriteTraits writeTraits = null;
425 private void addSetValue(int subject, byte[] value, int length)
426 throws DatabaseException {
428 ClusterI cluster = session.clusterTable.getClusterByResourceKey(subject);
429 if (cluster.getImmutable() && (session.serviceMode & SessionImplSocket.SERVICE_MODE_ALLOW) == 0)
430 if(subject != queryProcessor.getRootLibrary())
431 throw new ImmutableException("Trying to modify immutable resource key=" + subject);
433 ClusterI cluster2 = cluster.setValue(subject, value, length, session.clusterTranslator);
434 if (cluster2 != cluster)
435 session.clusterTable.replaceCluster(cluster2);
437 session.clientChanges.claimValue(subject);
439 if (cluster2.isWriteOnly())
442 queryProcessor.updateValue(subject);
446 final private void claimImpl(int subject, int predicate, int object)
447 throws ServiceException {
449 assert (subject != 0);
450 assert (predicate != 0);
451 assert (object != 0);
453 ClusterImpl cluster = session.clusterTable.getClusterByResourceKey(subject);
454 assert (null != cluster);
455 if (cluster.getImmutable() && (session.serviceMode & SessionImplSocket.SERVICE_MODE_ALLOW) == 0)
456 if(subject != queryProcessor.getRootLibrary())
457 throw new ImmutableException("Trying to modify immutable resource key=" + subject);
459 ClusterI c = cluster.addRelation(subject, predicate, object, session.clusterTranslator);
460 if (null != c && c != cluster)
461 session.clusterTable.replaceCluster(c);
462 } catch (DatabaseException e) {
463 Logger.defaultLogError(e);
464 throw new RuntimeException(e);
466 queryProcessor.updateStatements(subject, predicate);
467 session.clientChanges.claim(subject, predicate, object);
471 final private void claimImpl2(int subject, int predicate, int object) {
473 assert (subject != 0);
474 assert (predicate != 0);
475 assert (object != 0);
477 ClusterI cluster = session.clusterTable.getClusterByResourceKey(subject);
479 ClusterI c = cluster.addRelation(subject, predicate, object, session.clusterTranslator);
480 if (null != c && c != cluster)
481 session.clusterTable.replaceCluster(c);
482 } catch (DatabaseException e) {
483 Logger.defaultLogError(e);
485 if (cluster.isWriteOnly())
487 queryProcessor.updateStatements(subject, predicate);
491 private boolean removeStatement(int subject, int predicate, int object) throws ImmutableException {
493 assert (subject != 0);
494 assert (predicate != 0);
495 assert (object != 0);
497 ClusterI cluster = session.clusterTable.getClusterByResourceKey(subject);
498 assert (null != cluster);
500 if (cluster.getImmutable() && (session.serviceMode & SessionImplSocket.SERVICE_MODE_ALLOW) == 0)
501 if(subject != queryProcessor.getRootLibrary())
502 throw new ImmutableException("Trying to modify immutable resource key=" + subject);
505 cluster.denyRelation(subject, predicate, object, session.clusterTranslator);
506 } catch (DatabaseException e) {
507 Logger.defaultLogError(e);
510 queryProcessor.updateStatements(subject, predicate);