1 package fi.vtt.simantics.procore.internal;
3 import java.util.TreeMap;
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;
33 public class WriteSupportImpl implements WriteSupport {
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;
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);
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);
63 public void flushCluster(Resource r) {
64 session.clusterStream.reallyFlush();
68 public boolean writeOnly() {
69 return session.writeOnly;
73 public void flush(boolean intermediate) {
75 if (!session.state.isWriteTransaction())
76 throw new IllegalStateException("Can only flush during transaction.");
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));
87 final public void claim(VirtualGraph provider, int subject, int predicate, int object)
88 throws ServiceException {
90 provider = session.getProvider(provider);
92 if (provider != null) {
93 ((VirtualGraphImpl)provider).claim(subject, predicate, object);
94 queryProcessor.updateStatements(subject, predicate);
95 session.clientChanges.claim(subject, predicate, object);
97 claimImpl2(subject, predicate, object);
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);
106 claimImpl(subject, predicate, object);
108 queryProcessor.releaseWrite(session.writeState.getGraph());
114 public void setValue(VirtualGraph provider, Resource resource, byte[] value) throws ServiceException {
116 provider = session.getProvider(provider);
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);
124 addSetValue(((ResourceImpl) resource).id, value, value.length);
125 } catch (DatabaseException e) {
126 Logger.defaultLogError(e);
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);
136 addSetValue(((ResourceImpl) resource).id, value, value.length);
137 } catch (DatabaseException e) {
138 Logger.defaultLogError(e);
141 queryProcessor.releaseWrite(session.writeState.getGraph());
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);
152 return session.getNewResource();
157 public Resource createResource(VirtualGraph provider, long clusterId)
158 throws DatabaseException {
159 assert (provider == null);
160 return session.getNewResource(clusterId);
164 public Resource createResource(VirtualGraph provider, Resource clusterSet)
165 throws DatabaseException {
166 assert(provider == null);
167 assert(clusterSet != null);
168 return session.getNewResource(clusterSet);
172 public void createClusterSet(VirtualGraph provider, Resource clusterSet)
173 throws DatabaseException {
174 assert(provider == null);
175 assert(clusterSet != null);
176 session.getNewClusterSet(clusterSet);
180 public boolean hasClusterSet(VirtualGraph dummy, Resource clusterSet)
181 throws ServiceException {
182 return session.containsClusterSet(clusterSet);
186 public Resource setDefaultClusterSet(Resource clusterSet)
187 throws ServiceException {
188 return session.setDefaultClusterSet4NewResource(clusterSet);
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);
201 cluster.removeValue(key, session.clusterTranslator);
202 } catch (DatabaseException e) {
203 Logger.defaultLogError(e);
206 queryProcessor.updateValue(key);
207 session.clientChanges.claimValue(resource);
209 ((VirtualGraphImpl)provider).denyValue(((ResourceImpl) resource).id);
210 queryProcessor.updateValue(querySupport.getId(resource));
211 session.clientChanges.claimValue(resource);
214 queryProcessor.releaseWrite(session.writeState.getGraph());
219 public boolean removeStatement(VirtualGraph provider, Resource subject, Resource predicate,
220 Resource object) throws ServiceException {
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));
227 ret = removeStatement(querySupport.getId(subject), querySupport.getId(predicate), querySupport.getId(object));
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());
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.
244 // queryProcessor.acquireWrite(writeState.getGraph());
245 ret = removeStatement(sid, pid, oid);
246 queryProcessor.releaseWrite(session.writeState.getGraph());
249 session.clientChanges.deny(subject, predicate, object);
254 public synchronized void performWriteRequest(WriteGraph graph_, Write request) throws DatabaseException {
255 WriteGraphImpl graph = (WriteGraphImpl)graph_;
256 // graph.state.barrier.inc();
258 request.perform(graph);
259 } catch (Throwable t) {
262 // graph.state.barrier.dec();
263 // graph.waitAsync(request);
265 queryProcessor.performDirtyUpdates(graph);
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);
274 // graph.state.barrier.assertReady();
279 public synchronized <T> T performWriteRequest(WriteGraph graph_, WriteResult<T> request) throws DatabaseException {
281 WriteGraphImpl graph = (WriteGraphImpl)graph_;
282 // graph.state.barrier.inc();
286 result = request.perform(graph);
287 } catch (Throwable t2) {
288 if(DebugException.DEBUG) new DebugException(t2).printStackTrace();
292 // graph.state.barrier.dec();
293 // graph.waitAsync(request);
295 queryProcessor.performDirtyUpdates(graph);
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);
305 if(t instanceof DatabaseException) throw (DatabaseException)t;
306 else throw new DatabaseException(t);
314 public synchronized void performWriteRequest(WriteGraph graph, WriteOnly request) throws DatabaseException {
316 session.acquireWriteOnly();
318 request.perform(graph);
320 ReadGraphImpl impl = (ReadGraphImpl)graph;
322 queryProcessor.performDirtyUpdates(impl);
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);
330 session.releaseWriteOnly(impl);
337 if (MemWatch.isLowOnMemory()) {
338 session.clusterTable.gc();
339 queryProcessor.gc(0, Integer.MAX_VALUE);
345 public void claimValue(VirtualGraph provider, Resource resource, byte[] value) throws DatabaseException {
346 claimValue(provider, ((ResourceImpl)resource).id, value, value.length);
350 public void claimValue(VirtualGraph provider, int resource, byte[] value, int length) throws DatabaseException {
352 provider = session.getProvider(provider);
354 if (provider != null) {
355 ((VirtualGraphImpl)provider).claimValue(resource, value, length);
356 queryProcessor.updateValue(resource);
357 session.clientChanges.claimValue(resource);
359 addSetValue(resource, value, length);
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());
369 addSetValue(resource, value, length);
370 } catch (DatabaseException e) {
372 } catch (Throwable t) {
373 throw new DatabaseException(t);
375 queryProcessor.releaseWrite(session.writeState.getGraph());
382 public void claimValue(VirtualGraph provider, Resource resource, ByteReader reader, int amount) throws DatabaseException {
383 claimValue(provider, resource, reader.readBytes(null, amount));
387 public <T> void addMetadata(Metadata data) throws ServiceException {
388 MetadataUtils.addMetadata(session, metadata, data);
391 @SuppressWarnings("unchecked")
393 public <T extends Metadata> T getMetadata(Class<T> clazz) throws ServiceException {
394 return MetadataUtils.getMetadata(session, metadata, clazz);
398 public TreeMap<String, byte[]> getMetadata() {
403 public void commitDone(WriteTraits writeTraits, long csid) {
405 if (this.writeTraits == writeTraits) {
406 session.graphSession.undoContext.clear();
407 this.writeTraits = null;
409 // if (null != operation)
413 public int clearMetadata() {
414 int ret = metadata.size();
419 public void clearUndoList(WriteTraits writeTraits) {
420 this.writeTraits = writeTraits;
423 public void startUndo() {
424 session.state.setCombine(false);
426 private WriteTraits writeTraits = null;
427 private void addSetValue(int subject, byte[] value, int length)
428 throws DatabaseException {
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);
435 ClusterI cluster2 = cluster.setValue(subject, value, length, session.clusterTranslator);
436 if (cluster2 != cluster)
437 session.clusterTable.replaceCluster(cluster2);
439 session.clientChanges.claimValue(subject);
441 if (cluster2.isWriteOnly())
444 queryProcessor.updateValue(subject);
448 final private void claimImpl(int subject, int predicate, int object)
449 throws ServiceException {
451 assert (subject != 0);
452 assert (predicate != 0);
453 assert (object != 0);
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);
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);
468 queryProcessor.updateStatements(subject, predicate);
469 session.clientChanges.claim(subject, predicate, object);
473 final private void claimImpl2(int subject, int predicate, int object) {
475 assert (subject != 0);
476 assert (predicate != 0);
477 assert (object != 0);
479 ClusterI cluster = session.clusterTable.getClusterByResourceKey(subject);
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);
487 if (cluster.isWriteOnly())
489 queryProcessor.updateStatements(subject, predicate);
493 private boolean removeStatement(int subject, int predicate, int object) throws ImmutableException {
495 assert (subject != 0);
496 assert (predicate != 0);
497 assert (object != 0);
499 ClusterI cluster = session.clusterTable.getClusterByResourceKey(subject);
500 assert (null != cluster);
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);
507 cluster.denyRelation(subject, predicate, object, session.clusterTranslator);
508 } catch (DatabaseException e) {
509 Logger.defaultLogError(e);
512 queryProcessor.updateStatements(subject, predicate);