1 package fi.vtt.simantics.procore.internal;
\r
3 import java.util.TreeMap;
\r
5 import org.simantics.db.Metadata;
\r
6 import org.simantics.db.Operation;
\r
7 import org.simantics.db.Resource;
\r
8 import org.simantics.db.VirtualGraph;
\r
9 import org.simantics.db.WriteGraph;
\r
10 import org.simantics.db.common.MetadataUtils;
\r
11 import org.simantics.db.common.exception.DebugException;
\r
12 import org.simantics.db.common.utils.Logger;
\r
13 import org.simantics.db.exception.DatabaseException;
\r
14 import org.simantics.db.exception.ImmutableException;
\r
15 import org.simantics.db.exception.ServiceException;
\r
16 import org.simantics.db.impl.ClusterI;
\r
17 import org.simantics.db.impl.MemWatch;
\r
18 import org.simantics.db.impl.ResourceImpl;
\r
19 import org.simantics.db.impl.VirtualGraphImpl;
\r
20 import org.simantics.db.impl.graph.ReadGraphImpl;
\r
21 import org.simantics.db.impl.graph.WriteGraphImpl;
\r
22 import org.simantics.db.impl.graph.WriteSupport;
\r
23 import org.simantics.db.impl.query.QueryProcessor;
\r
24 import org.simantics.db.impl.query.QuerySupport;
\r
25 import org.simantics.db.procore.cluster.ClusterImpl;
\r
26 import org.simantics.db.procore.protocol.Constants;
\r
27 import org.simantics.db.request.Write;
\r
28 import org.simantics.db.request.WriteOnly;
\r
29 import org.simantics.db.request.WriteResult;
\r
30 import org.simantics.db.request.WriteTraits;
\r
31 import org.simantics.db.service.ByteReader;
\r
33 public class WriteSupportImpl implements WriteSupport {
\r
35 final private SessionImplSocket session;
\r
36 final private QueryProcessor queryProcessor;
\r
37 final private State state;
\r
38 final private QuerySupport querySupport;
\r
39 final private TreeMap<String, byte[]> metadata;
\r
41 WriteSupportImpl(SessionImplSocket session) {
\r
42 this.session = session;
\r
43 this.queryProcessor = session.getQueryProvider2();
\r
44 this.state = session.state;
\r
45 this.querySupport = session.querySupport;
\r
46 this.metadata = new TreeMap<String, byte[]>();
\r
47 assert(this.session != null);
\r
48 assert(this.queryProcessor != null);
\r
49 assert(this.state != null);
\r
50 assert(this.querySupport != null);
\r
54 public void flushCluster() {
\r
55 session.clusterTable.flushCluster(session.graphSession);
\r
56 if(session.defaultClusterSet != null) {
\r
57 long resourceId = session.defaultClusterSet.getResourceId();
\r
58 session.clusterSetsSupport.put(resourceId, Constants.NewClusterId);
\r
63 public void flushCluster(Resource r) {
\r
64 session.clusterStream.reallyFlush();
\r
68 public boolean writeOnly() {
\r
69 return session.writeOnly;
\r
73 public void flush(boolean intermediate) {
\r
75 if (!session.state.isWriteTransaction())
\r
76 throw new IllegalStateException("Can only flush during transaction.");
\r
82 final public void claim(VirtualGraph provider, Resource subject, Resource predicate, Resource object) throws ServiceException {
\r
83 claim(provider, querySupport.getId(subject), querySupport.getId(predicate), querySupport.getId(object));
\r
87 final public void claim(VirtualGraph provider, int subject, int predicate, int object)
\r
88 throws ServiceException {
\r
90 provider = session.getProvider(provider);
\r
92 if (provider != null) {
\r
93 ((VirtualGraphImpl)provider).claim(subject, predicate, object);
\r
94 queryProcessor.updateStatements(subject, predicate);
\r
95 session.clientChanges.claim(subject, predicate, object);
\r
97 claimImpl2(subject, predicate, object);
\r
100 // queryProcessor.acquireWrite(writeState.getGraph());
\r
101 if (provider != null) {
\r
102 ((VirtualGraphImpl)provider).claim(subject, predicate, object);
\r
103 queryProcessor.updateStatements(subject, predicate);
\r
104 session.clientChanges.claim(subject, predicate, object);
\r
106 claimImpl(subject, predicate, object);
\r
108 queryProcessor.releaseWrite(session.writeState.getGraph());
\r
114 public void setValue(VirtualGraph provider, Resource resource, byte[] value) throws ServiceException {
\r
116 provider = session.getProvider(provider);
\r
118 if (provider != null) {
\r
119 ((VirtualGraphImpl)provider).claimValue(((ResourceImpl) resource).id, value, value.length);
\r
120 queryProcessor.updateValue(querySupport.getId(resource));
\r
121 session.clientChanges.claimValue(resource);
\r
124 addSetValue(((ResourceImpl) resource).id, value, value.length);
\r
125 } catch (DatabaseException e) {
\r
126 Logger.defaultLogError(e);
\r
130 if (provider != null) {
\r
131 ((VirtualGraphImpl)provider).claimValue(((ResourceImpl) resource).id, value, value.length);
\r
132 queryProcessor.updateValue(querySupport.getId(resource));
\r
133 session.clientChanges.claimValue(resource);
\r
136 addSetValue(((ResourceImpl) resource).id, value, value.length);
\r
137 } catch (DatabaseException e) {
\r
138 Logger.defaultLogError(e);
\r
141 queryProcessor.releaseWrite(session.writeState.getGraph());
\r
147 public Resource createResource(VirtualGraph provider) throws DatabaseException {
\r
148 if (provider != null) {
\r
149 int newId = ((VirtualGraphImpl)provider).newResource(false);
\r
150 return new ResourceImpl(session.resourceSupport, newId);
\r
152 return session.getNewResource();
\r
157 public Resource createResource(VirtualGraph provider, long clusterId)
\r
158 throws DatabaseException {
\r
159 assert (provider == null);
\r
160 return session.getNewResource(clusterId);
\r
164 public Resource createResource(VirtualGraph provider, Resource clusterSet)
\r
165 throws DatabaseException {
\r
166 assert(provider == null);
\r
167 assert(clusterSet != null);
\r
168 return session.getNewResource(clusterSet);
\r
172 public void createClusterSet(VirtualGraph provider, Resource clusterSet)
\r
173 throws DatabaseException {
\r
174 assert(provider == null);
\r
175 assert(clusterSet != null);
\r
176 session.getNewClusterSet(clusterSet);
\r
180 public boolean hasClusterSet(VirtualGraph dummy, Resource clusterSet)
\r
181 throws ServiceException {
\r
182 return session.containsClusterSet(clusterSet);
\r
186 public Resource setDefaultClusterSet(Resource clusterSet)
\r
187 throws ServiceException {
\r
188 return session.setDefaultClusterSet4NewResource(clusterSet);
\r
191 public void denyValue(VirtualGraph provider, Resource resource) throws ServiceException {
\r
192 provider = session.getProvider(provider);
\r
193 if (null == provider) {
\r
194 int key = ((ResourceImpl)resource).id;
\r
195 ClusterI cluster = session.clusterTable.getClusterByResourceKey(key);
\r
196 if (cluster.getImmutable() && (session.serviceMode & SessionImplSocket.SERVICE_MODE_ALLOW) == 0)
\r
197 if(key != queryProcessor.getRootLibrary())
\r
198 throw new ImmutableException("Trying to modify immutable resource key=" + key);
\r
201 cluster.removeValue(key, session.clusterTranslator);
\r
202 } catch (DatabaseException e) {
\r
203 Logger.defaultLogError(e);
\r
206 queryProcessor.updateValue(key);
\r
207 session.clientChanges.claimValue(resource);
\r
209 ((VirtualGraphImpl)provider).denyValue(((ResourceImpl) resource).id);
\r
210 queryProcessor.updateValue(querySupport.getId(resource));
\r
211 session.clientChanges.claimValue(resource);
\r
214 queryProcessor.releaseWrite(session.writeState.getGraph());
\r
219 public boolean removeStatement(VirtualGraph provider, Resource subject, Resource predicate,
\r
220 Resource object) throws ServiceException {
\r
221 boolean ret = true;
\r
223 if (provider != null) {
\r
224 ((VirtualGraphImpl)provider).deny(querySupport.getId(subject), querySupport.getId(predicate), querySupport.getId(object));
\r
225 queryProcessor.updateStatements(querySupport.getId(subject), querySupport.getId(predicate));
\r
227 ret = removeStatement(querySupport.getId(subject), querySupport.getId(predicate), querySupport.getId(object));
\r
230 if (provider != null) {
\r
231 // queryProcessor.acquireWrite(writeState.getGraph());
\r
232 ((VirtualGraphImpl)provider).deny(querySupport.getId(subject), querySupport.getId(predicate), querySupport.getId(object));
\r
233 queryProcessor.updateStatements(querySupport.getId(subject), querySupport.getId(predicate));
\r
234 queryProcessor.releaseWrite(session.writeState.getGraph());
\r
236 int sid = querySupport.getId(subject);
\r
237 int pid = querySupport.getId(predicate);
\r
238 int oid = querySupport.getId(object);
\r
239 if (sid < 0 || pid < 0 || oid < 0) {
\r
240 // One of the resources is virtual, cannot remove such
\r
241 // statement from persistent storage.
\r
244 // queryProcessor.acquireWrite(writeState.getGraph());
\r
245 ret = removeStatement(sid, pid, oid);
\r
246 queryProcessor.releaseWrite(session.writeState.getGraph());
\r
249 session.clientChanges.deny(subject, predicate, object);
\r
254 public synchronized void performWriteRequest(WriteGraph graph_, Write request) throws DatabaseException {
\r
255 WriteGraphImpl graph = (WriteGraphImpl)graph_;
\r
256 // graph.state.barrier.inc();
\r
258 request.perform(graph);
\r
259 } catch (Throwable t) {
\r
260 t.printStackTrace();
\r
262 // graph.state.barrier.dec();
\r
263 // graph.waitAsync(request);
\r
265 queryProcessor.performDirtyUpdates(graph);
\r
267 // Do not fire metadata listeners for virtual requests
\r
268 if(graph.getProvider() == null) {
\r
269 //session.fireMetadataListeners(graph, session.clientChanges);
\r
270 state.commitAndContinue(graph, session.clusterStream, request);
\r
271 //session.clientChanges = new ClientChangesImpl(session);
\r
274 // graph.state.barrier.assertReady();
\r
279 public synchronized <T> T performWriteRequest(WriteGraph graph_, WriteResult<T> request) throws DatabaseException {
\r
281 WriteGraphImpl graph = (WriteGraphImpl)graph_;
\r
282 // graph.state.barrier.inc();
\r
284 Throwable t = null;
\r
286 result = request.perform(graph);
\r
287 } catch (Throwable t2) {
\r
288 if(DebugException.DEBUG) new DebugException(t2).printStackTrace();
\r
292 // graph.state.barrier.dec();
\r
293 // graph.waitAsync(request);
\r
295 queryProcessor.performDirtyUpdates(graph);
\r
297 // Do not fire metadata listeners for virtual requests
\r
298 if(graph.getProvider() == null) {
\r
299 //session.fireMetadataListeners((WriteGraphImpl)graph, session.clientChanges);
\r
300 state.commitAndContinue(graph, session.clusterStream, request);
\r
301 //session.clientChanges = new ClientChangesImpl(session);
\r
305 if(t instanceof DatabaseException) throw (DatabaseException)t;
\r
306 else throw new DatabaseException(t);
\r
314 public synchronized void performWriteRequest(WriteGraph graph, WriteOnly request) throws DatabaseException {
\r
316 session.acquireWriteOnly();
\r
318 request.perform(graph);
\r
320 ReadGraphImpl impl = (ReadGraphImpl)graph;
\r
322 queryProcessor.performDirtyUpdates(impl);
\r
324 // Do not fire metadata listeners for virtual requests
\r
325 if(graph.getProvider() == null) {
\r
326 //session.fireMetadataListeners(impl, session.clientChanges);
\r
327 state.commitAndContinue(session.writeState.getGraph(), session.clusterStream, request);
\r
328 //session.clientChanges = new ClientChangesImpl(session);
\r
330 session.releaseWriteOnly(impl);
\r
337 if (MemWatch.isLowOnMemory()) {
\r
338 session.clusterTable.gc();
\r
339 queryProcessor.gc(0, Integer.MAX_VALUE);
\r
345 public void claimValue(VirtualGraph provider, Resource resource, byte[] value) throws DatabaseException {
\r
346 claimValue(provider, ((ResourceImpl)resource).id, value, value.length);
\r
350 public void claimValue(VirtualGraph provider, int resource, byte[] value, int length) throws DatabaseException {
\r
352 provider = session.getProvider(provider);
\r
354 if (provider != null) {
\r
355 ((VirtualGraphImpl)provider).claimValue(resource, value, length);
\r
356 queryProcessor.updateValue(resource);
\r
357 session.clientChanges.claimValue(resource);
\r
359 addSetValue(resource, value, length);
\r
362 if (provider != null) {
\r
363 ((VirtualGraphImpl)provider).claimValue(resource, value, length);
\r
364 queryProcessor.updateValue(resource);
\r
365 session.clientChanges.claimValue(resource);
\r
366 queryProcessor.releaseWrite(session.writeState.getGraph());
\r
369 addSetValue(resource, value, length);
\r
370 } catch (DatabaseException e) {
\r
372 } catch (Throwable t) {
\r
373 throw new DatabaseException(t);
\r
375 queryProcessor.releaseWrite(session.writeState.getGraph());
\r
382 public void claimValue(VirtualGraph provider, Resource resource, ByteReader reader, int amount) throws DatabaseException {
\r
383 claimValue(provider, resource, reader.readBytes(null, amount));
\r
387 public <T> void addMetadata(Metadata data) throws ServiceException {
\r
388 MetadataUtils.addMetadata(session, metadata, data);
\r
391 @SuppressWarnings("unchecked")
\r
393 public <T extends Metadata> T getMetadata(Class<T> clazz) throws ServiceException {
\r
394 return MetadataUtils.getMetadata(session, metadata, clazz);
\r
398 public TreeMap<String, byte[]> getMetadata() {
\r
403 public void commitDone(WriteTraits writeTraits, long csid) {
\r
405 if (this.writeTraits == writeTraits) {
\r
406 session.graphSession.undoContext.clear();
\r
407 this.writeTraits = null;
\r
409 // if (null != operation)
\r
410 // operation = null;
\r
413 public int clearMetadata() {
\r
414 int ret = metadata.size();
\r
419 public void clearUndoList(WriteTraits writeTraits) {
\r
420 this.writeTraits = writeTraits;
\r
423 public void startUndo() {
\r
424 session.state.setCombine(false);
\r
426 private WriteTraits writeTraits = null;
\r
427 private void addSetValue(int subject, byte[] value, int length)
\r
428 throws DatabaseException {
\r
430 ClusterI cluster = session.clusterTable.getClusterByResourceKey(subject);
\r
431 if (cluster.getImmutable() && (session.serviceMode & SessionImplSocket.SERVICE_MODE_ALLOW) == 0)
\r
432 if(subject != queryProcessor.getRootLibrary())
\r
433 throw new ImmutableException("Trying to modify immutable resource key=" + subject);
\r
435 ClusterI cluster2 = cluster.setValue(subject, value, length, session.clusterTranslator);
\r
436 if (cluster2 != cluster)
\r
437 session.clusterTable.replaceCluster(cluster2);
\r
439 session.clientChanges.claimValue(subject);
\r
441 if (cluster2.isWriteOnly())
\r
444 queryProcessor.updateValue(subject);
\r
448 final private void claimImpl(int subject, int predicate, int object)
\r
449 throws ServiceException {
\r
451 assert (subject != 0);
\r
452 assert (predicate != 0);
\r
453 assert (object != 0);
\r
455 ClusterImpl cluster = session.clusterTable.getClusterByResourceKey(subject);
\r
456 assert (null != cluster);
\r
457 if (cluster.getImmutable() && (session.serviceMode & SessionImplSocket.SERVICE_MODE_ALLOW) == 0)
\r
458 if(subject != queryProcessor.getRootLibrary())
\r
459 throw new ImmutableException("Trying to modify immutable resource key=" + subject);
\r
461 ClusterI c = cluster.addRelation(subject, predicate, object, session.clusterTranslator);
\r
462 if (null != c && c != cluster)
\r
463 session.clusterTable.replaceCluster(c);
\r
464 } catch (DatabaseException e) {
\r
465 Logger.defaultLogError(e);
\r
466 throw new RuntimeException(e);
\r
468 queryProcessor.updateStatements(subject, predicate);
\r
469 session.clientChanges.claim(subject, predicate, object);
\r
473 final private void claimImpl2(int subject, int predicate, int object) {
\r
475 assert (subject != 0);
\r
476 assert (predicate != 0);
\r
477 assert (object != 0);
\r
479 ClusterI cluster = session.clusterTable.getClusterByResourceKey(subject);
\r
481 ClusterI c = cluster.addRelation(subject, predicate, object, session.clusterTranslator);
\r
482 if (null != c && c != cluster)
\r
483 session.clusterTable.replaceCluster(c);
\r
484 } catch (DatabaseException e) {
\r
485 Logger.defaultLogError(e);
\r
487 if (cluster.isWriteOnly())
\r
489 queryProcessor.updateStatements(subject, predicate);
\r
493 private boolean removeStatement(int subject, int predicate, int object) throws ImmutableException {
\r
495 assert (subject != 0);
\r
496 assert (predicate != 0);
\r
497 assert (object != 0);
\r
499 ClusterI cluster = session.clusterTable.getClusterByResourceKey(subject);
\r
500 assert (null != cluster);
\r
502 if (cluster.getImmutable() && (session.serviceMode & SessionImplSocket.SERVICE_MODE_ALLOW) == 0)
\r
503 if(subject != queryProcessor.getRootLibrary())
\r
504 throw new ImmutableException("Trying to modify immutable resource key=" + subject);
\r
507 cluster.denyRelation(subject, predicate, object, session.clusterTranslator);
\r
508 } catch (DatabaseException e) {
\r
509 Logger.defaultLogError(e);
\r
512 queryProcessor.updateStatements(subject, predicate);
\r