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.exception.DatabaseException;
12 import org.simantics.db.exception.ImmutableException;
13 import org.simantics.db.exception.ServiceException;
14 import org.simantics.db.impl.ClusterI;
15 import org.simantics.db.impl.MemWatch;
16 import org.simantics.db.impl.ResourceImpl;
17 import org.simantics.db.impl.VirtualGraphImpl;
18 import org.simantics.db.impl.graph.ReadGraphImpl;
19 import org.simantics.db.impl.graph.WriteGraphImpl;
20 import org.simantics.db.impl.graph.WriteSupport;
21 import org.simantics.db.impl.query.QueryProcessor;
22 import org.simantics.db.impl.query.QuerySupport;
23 import org.simantics.db.procore.cluster.ClusterImpl;
24 import org.simantics.db.procore.protocol.Constants;
25 import org.simantics.db.request.Write;
26 import org.simantics.db.request.WriteOnly;
27 import org.simantics.db.request.WriteResult;
28 import org.simantics.db.request.WriteTraits;
29 import org.simantics.db.service.ByteReader;
30 import org.slf4j.Logger;
31 import org.slf4j.LoggerFactory;
33 public class WriteSupportImpl implements WriteSupport {
35 private static final Logger LOGGER = LoggerFactory.getLogger(WriteSupportImpl.class);
37 final private SessionImplSocket session;
38 final private QueryProcessor queryProcessor;
39 final private State state;
40 final private QuerySupport querySupport;
41 final private TreeMap<String, byte[]> metadata;
43 WriteSupportImpl(SessionImplSocket session) {
44 this.session = session;
45 this.queryProcessor = session.getQueryProvider2();
46 this.state = session.state;
47 this.querySupport = session.querySupport;
48 this.metadata = new TreeMap<String, byte[]>();
49 assert(this.session != null);
50 assert(this.queryProcessor != null);
51 assert(this.state != null);
52 assert(this.querySupport != null);
56 public void flushCluster() {
57 session.clusterTable.flushCluster(session.graphSession);
58 if(session.defaultClusterSet != null) {
59 long resourceId = session.defaultClusterSet.getResourceId();
60 session.clusterSetsSupport.put(resourceId, Constants.NewClusterId);
65 public void flushCluster(Resource r) {
66 session.clusterStream.reallyFlush();
70 public boolean writeOnly() {
71 return session.writeOnly;
75 public void flush(boolean intermediate) {
77 if (!session.state.isWriteTransaction())
78 throw new IllegalStateException("Can only flush during transaction.");
84 final public void claim(VirtualGraph provider, Resource subject, Resource predicate, Resource object) throws ServiceException {
85 claim(provider, querySupport.getId(subject), querySupport.getId(predicate), querySupport.getId(object));
89 final public void claim(VirtualGraph provider, int subject, int predicate, int object)
90 throws ServiceException {
92 provider = session.getProvider(provider);
94 if (provider != null) {
95 ((VirtualGraphImpl)provider).claim(subject, predicate, object);
96 queryProcessor.updateStatements(subject, predicate);
97 session.clientChanges.claim(subject, predicate, object);
99 claimImpl2(subject, predicate, object);
102 // queryProcessor.acquireWrite(writeState.getGraph());
103 if (provider != null) {
104 ((VirtualGraphImpl)provider).claim(subject, predicate, object);
105 queryProcessor.updateStatements(subject, predicate);
106 session.clientChanges.claim(subject, predicate, object);
108 claimImpl(subject, predicate, object);
110 queryProcessor.releaseWrite(session.writeState.getGraph());
116 public void setValue(VirtualGraph provider, Resource resource, byte[] value) throws ServiceException {
118 provider = session.getProvider(provider);
120 if (provider != null) {
121 ((VirtualGraphImpl)provider).claimValue(((ResourceImpl) resource).id, value, value.length);
122 queryProcessor.updateValue(querySupport.getId(resource));
123 session.clientChanges.claimValue(resource);
126 addSetValue(((ResourceImpl) resource).id, value, value.length);
127 } catch (DatabaseException e) {
128 LOGGER.error("writeOnly setValue({}, {}, byte[{}]) failed", provider, resource, value.length, e);
132 if (provider != null) {
133 ((VirtualGraphImpl)provider).claimValue(((ResourceImpl) resource).id, value, value.length);
134 queryProcessor.updateValue(querySupport.getId(resource));
135 session.clientChanges.claimValue(resource);
138 addSetValue(((ResourceImpl) resource).id, value, value.length);
139 } catch (DatabaseException e) {
140 LOGGER.error("setValue({}, {}, byte[{}]) failed", provider, resource, value.length, e);
143 queryProcessor.releaseWrite(session.writeState.getGraph());
149 public Resource createResource(VirtualGraph provider) throws DatabaseException {
150 if (provider != null) {
151 int newId = ((VirtualGraphImpl)provider).newResource(false);
152 return new ResourceImpl(session.resourceSupport, newId);
154 return session.getNewResource();
159 public Resource createResource(VirtualGraph provider, long clusterId)
160 throws DatabaseException {
161 assert (provider == null);
162 return session.getNewResource(clusterId);
166 public Resource createResource(VirtualGraph provider, Resource clusterSet)
167 throws DatabaseException {
168 assert(provider == null);
169 assert(clusterSet != null);
170 return session.getNewResource(clusterSet);
174 public void createClusterSet(VirtualGraph provider, Resource clusterSet)
175 throws DatabaseException {
176 assert(provider == null);
177 assert(clusterSet != null);
178 session.getNewClusterSet(clusterSet);
182 public boolean hasClusterSet(VirtualGraph dummy, Resource clusterSet)
183 throws ServiceException {
184 return session.containsClusterSet(clusterSet);
188 public Resource setDefaultClusterSet(Resource clusterSet)
189 throws ServiceException {
190 return session.setDefaultClusterSet4NewResource(clusterSet);
193 public void denyValue(VirtualGraph provider, Resource resource) throws ServiceException {
194 provider = session.getProvider(provider);
195 if (null == provider) {
196 int key = ((ResourceImpl)resource).id;
197 ClusterI cluster = session.clusterTable.getClusterByResourceKey(key);
198 if (cluster.getImmutable() && (session.serviceMode & SessionImplSocket.SERVICE_MODE_ALLOW) == 0)
199 if(key != queryProcessor.getRootLibrary())
200 throw new ImmutableException("Trying to modify immutable resource key=" + key);
203 cluster.removeValue(key, session.clusterTranslator);
204 } catch (DatabaseException e) {
205 LOGGER.error("denyValue({}, {}) failed", provider, resource, e);
208 queryProcessor.updateValue(key);
209 session.clientChanges.claimValue(resource);
211 ((VirtualGraphImpl)provider).denyValue(((ResourceImpl) resource).id);
212 queryProcessor.updateValue(querySupport.getId(resource));
213 session.clientChanges.claimValue(resource);
216 queryProcessor.releaseWrite(session.writeState.getGraph());
221 public boolean removeStatement(VirtualGraph provider, Resource subject, Resource predicate,
222 Resource object) throws ServiceException {
225 if (provider != null) {
226 ((VirtualGraphImpl)provider).deny(querySupport.getId(subject), querySupport.getId(predicate), querySupport.getId(object));
227 queryProcessor.updateStatements(querySupport.getId(subject), querySupport.getId(predicate));
229 ret = removeStatement(querySupport.getId(subject), querySupport.getId(predicate), querySupport.getId(object));
232 if (provider != null) {
233 // queryProcessor.acquireWrite(writeState.getGraph());
234 ((VirtualGraphImpl)provider).deny(querySupport.getId(subject), querySupport.getId(predicate), querySupport.getId(object));
235 queryProcessor.updateStatements(querySupport.getId(subject), querySupport.getId(predicate));
236 queryProcessor.releaseWrite(session.writeState.getGraph());
238 int sid = querySupport.getId(subject);
239 int pid = querySupport.getId(predicate);
240 int oid = querySupport.getId(object);
241 if (sid < 0 || pid < 0 || oid < 0) {
242 // One of the resources is virtual, cannot remove such
243 // statement from persistent storage.
246 // queryProcessor.acquireWrite(writeState.getGraph());
247 ret = removeStatement(sid, pid, oid);
248 queryProcessor.releaseWrite(session.writeState.getGraph());
251 session.clientChanges.deny(subject, predicate, object);
256 public synchronized void performWriteRequest(WriteGraph graph_, Write request) throws DatabaseException {
257 WriteGraphImpl graph = (WriteGraphImpl)graph_;
258 // graph.state.barrier.inc();
260 request.perform(graph);
261 } catch (Throwable t) {
264 // graph.state.barrier.dec();
265 // graph.waitAsync(request);
267 queryProcessor.propagateChangesInQueryCache(graph);
269 // Do not fire metadata listeners for virtual requests
270 if(graph.getProvider() == null) {
271 //session.fireMetadataListeners(graph, session.clientChanges);
272 state.commitAndContinue(graph, session.clusterStream, request);
273 //session.clientChanges = new ClientChangesImpl(session);
276 // graph.state.barrier.assertReady();
281 public synchronized <T> T performWriteRequest(WriteGraph graph_, WriteResult<T> request) throws DatabaseException {
283 WriteGraphImpl graph = (WriteGraphImpl)graph_;
284 // graph.state.barrier.inc();
288 result = request.perform(graph);
289 } catch (Throwable t2) {
290 if(DebugException.DEBUG) new DebugException(t2).printStackTrace();
294 // graph.state.barrier.dec();
295 // graph.waitAsync(request);
297 queryProcessor.propagateChangesInQueryCache(graph);
299 // Do not fire metadata listeners for virtual requests
300 if(graph.getProvider() == null) {
301 //session.fireMetadataListeners((WriteGraphImpl)graph, session.clientChanges);
302 state.commitAndContinue(graph, session.clusterStream, request);
303 //session.clientChanges = new ClientChangesImpl(session);
307 if(t instanceof DatabaseException) throw (DatabaseException)t;
308 else throw new DatabaseException(t);
316 public synchronized void performWriteRequest(WriteGraph graph, WriteOnly request) throws DatabaseException {
318 session.acquireWriteOnly();
320 request.perform(graph);
322 ReadGraphImpl impl = (ReadGraphImpl)graph;
324 queryProcessor.propagateChangesInQueryCache(impl);
326 // Do not fire metadata listeners for virtual requests
327 if(graph.getProvider() == null) {
328 //session.fireMetadataListeners(impl, session.clientChanges);
329 state.commitAndContinue(session.writeState.getGraph(), session.clusterStream, request);
330 //session.clientChanges = new ClientChangesImpl(session);
332 session.releaseWriteOnly(impl);
339 if (MemWatch.isLowOnMemory()) {
340 session.clusterTable.gc();
341 queryProcessor.gc(0, Integer.MAX_VALUE);
347 public void claimValue(VirtualGraph provider, Resource resource, byte[] value) throws DatabaseException {
348 claimValue(provider, ((ResourceImpl)resource).id, value, value.length);
352 public void claimValue(VirtualGraph provider, int resource, byte[] value, int length) throws DatabaseException {
354 provider = session.getProvider(provider);
356 if (provider != null) {
357 ((VirtualGraphImpl)provider).claimValue(resource, value, length);
358 queryProcessor.updateValue(resource);
359 session.clientChanges.claimValue(resource);
361 addSetValue(resource, value, length);
364 if (provider != null) {
365 ((VirtualGraphImpl)provider).claimValue(resource, value, length);
366 queryProcessor.updateValue(resource);
367 session.clientChanges.claimValue(resource);
368 queryProcessor.releaseWrite(session.writeState.getGraph());
371 addSetValue(resource, value, length);
372 } catch (DatabaseException e) {
374 } catch (Throwable t) {
375 throw new DatabaseException(t);
377 queryProcessor.releaseWrite(session.writeState.getGraph());
384 public void claimValue(VirtualGraph provider, Resource resource, ByteReader reader, int amount) throws DatabaseException {
385 claimValue(provider, resource, reader.readBytes(null, amount));
389 public <T> void addMetadata(Metadata data) throws ServiceException {
390 MetadataUtils.addMetadata(session, metadata, data);
394 public <T extends Metadata> T getMetadata(Class<T> clazz) throws ServiceException {
395 return MetadataUtils.getMetadata(session, metadata, clazz);
399 public TreeMap<String, byte[]> getMetadata() {
404 public void commitDone(WriteTraits writeTraits, long csid) {
406 if (this.writeTraits == writeTraits) {
407 session.graphSession.undoContext.clear();
408 this.writeTraits = null;
410 // if (null != operation)
414 public int clearMetadata() {
415 int ret = metadata.size();
420 public void clearUndoList(WriteTraits writeTraits) {
421 this.writeTraits = writeTraits;
424 public void startUndo() {
425 session.state.setCombine(false);
427 private WriteTraits writeTraits = null;
428 private void addSetValue(int subject, byte[] value, int length)
429 throws DatabaseException {
431 ClusterI cluster = session.clusterTable.getClusterByResourceKey(subject);
432 if (cluster.getImmutable() && (session.serviceMode & SessionImplSocket.SERVICE_MODE_ALLOW) == 0)
433 if(subject != queryProcessor.getRootLibrary())
434 throw new ImmutableException("Trying to modify immutable resource key=" + subject);
436 ClusterI cluster2 = cluster.setValue(subject, value, length, session.clusterTranslator);
437 if (cluster2 != cluster)
438 session.clusterTable.replaceCluster(cluster2);
440 session.clientChanges.claimValue(subject);
442 if (cluster2.isWriteOnly())
445 queryProcessor.updateValue(subject);
449 final private void claimImpl(int subject, int predicate, int object)
450 throws ServiceException {
452 assert (subject != 0);
453 assert (predicate != 0);
454 assert (object != 0);
456 ClusterImpl cluster = session.clusterTable.getClusterByResourceKey(subject);
457 assert (null != cluster);
458 if (cluster.getImmutable() && (session.serviceMode & SessionImplSocket.SERVICE_MODE_ALLOW) == 0)
459 if(subject != queryProcessor.getRootLibrary())
460 throw new ImmutableException("Trying to modify immutable resource key=" + subject);
462 ClusterI c = cluster.addRelation(subject, predicate, object, session.clusterTranslator);
463 if (null != c && c != cluster)
464 session.clusterTable.replaceCluster(c);
465 } catch (DatabaseException e) {
466 LOGGER.error("claimImpl({}, {}, {}) failed", subject, predicate, object, e);
467 throw new RuntimeException(e);
469 queryProcessor.updateStatements(subject, predicate);
470 session.clientChanges.claim(subject, predicate, object);
474 final private void claimImpl2(int subject, int predicate, int object) {
476 assert (subject != 0);
477 assert (predicate != 0);
478 assert (object != 0);
480 ClusterI cluster = session.clusterTable.getClusterByResourceKey(subject);
482 ClusterI c = cluster.addRelation(subject, predicate, object, session.clusterTranslator);
483 if (null != c && c != cluster)
484 session.clusterTable.replaceCluster(c);
485 } catch (DatabaseException e) {
486 LOGGER.error("claimImpl2({}, {}, {}) failed", subject, predicate, object, e);
488 if (cluster.isWriteOnly())
490 queryProcessor.updateStatements(subject, predicate);
494 private boolean removeStatement(int subject, int predicate, int object) throws ImmutableException {
496 assert (subject != 0);
497 assert (predicate != 0);
498 assert (object != 0);
500 ClusterI cluster = session.clusterTable.getClusterByResourceKey(subject);
501 assert (null != cluster);
503 if (cluster.getImmutable() && (session.serviceMode & SessionImplSocket.SERVICE_MODE_ALLOW) == 0)
504 if(subject != queryProcessor.getRootLibrary())
505 throw new ImmutableException("Trying to modify immutable resource key=" + subject);
508 cluster.denyRelation(subject, predicate, object, session.clusterTranslator);
509 } catch (DatabaseException e) {
510 LOGGER.error("removeStatement({}, {}, {}) failed", subject, predicate, object, e);
513 queryProcessor.updateStatements(subject, predicate);