1 /*******************************************************************************
2 * Copyright (c) 2007, 2010 Association for Decentralized Information Management
4 * All rights reserved. This program and the accompanying materials
5 * are made available under the terms of the Eclipse Public License v1.0
6 * which accompanies this distribution, and is available at
7 * http://www.eclipse.org/legal/epl-v10.html
10 * VTT Technical Research Centre of Finland - initial API and implementation
11 *******************************************************************************/
12 package org.simantics.db.impl.graph;
15 import java.io.Closeable;
17 import java.io.FileInputStream;
18 import java.io.FileOutputStream;
19 import java.io.IOException;
20 import java.io.InputStream;
21 import java.io.OutputStream;
22 import java.nio.ByteBuffer;
23 import java.nio.channels.FileChannel;
24 import java.nio.file.Files;
25 import java.util.ArrayList;
26 import java.util.HashSet;
28 import java.util.TreeMap;
29 import java.util.UUID;
31 import org.eclipse.core.runtime.Platform;
32 import org.simantics.databoard.Bindings;
33 import org.simantics.databoard.accessor.Accessor;
34 import org.simantics.databoard.binding.Binding;
35 import org.simantics.databoard.binding.error.BindingConstructionException;
36 import org.simantics.databoard.serialization.Serializer;
37 import org.simantics.databoard.type.Datatype;
38 import org.simantics.databoard.util.binary.RandomAccessBinary;
39 import org.simantics.db.Metadata;
40 import org.simantics.db.ReadGraph;
41 import org.simantics.db.Resource;
42 import org.simantics.db.Session;
43 import org.simantics.db.Statement;
44 import org.simantics.db.VirtualGraph;
45 import org.simantics.db.WriteGraph;
46 import org.simantics.db.WriteOnlyGraph;
47 import org.simantics.db.common.MetadataUtils;
48 import org.simantics.db.common.request.WriteOnlyRequest;
49 import org.simantics.db.common.utils.Logger;
50 import org.simantics.db.exception.BindingException;
51 import org.simantics.db.exception.ClusterSetExistException;
52 import org.simantics.db.exception.DatabaseException;
53 import org.simantics.db.exception.ManyObjectsForFunctionalRelationException;
54 import org.simantics.db.exception.NoSingleResultException;
55 import org.simantics.db.exception.ResourceNotFoundException;
56 import org.simantics.db.exception.ServiceException;
57 import org.simantics.db.impl.DebugPolicy;
58 import org.simantics.db.impl.ResourceImpl;
59 import org.simantics.db.request.DelayedWrite;
60 import org.simantics.db.request.WriteOnly;
61 import org.simantics.db.request.WriteResult;
62 import org.simantics.db.request.WriteTraits;
63 import org.simantics.db.service.ByteReader;
64 import org.simantics.db.service.ClusteringSupport;
65 import org.simantics.db.service.TransferableGraphSupport;
66 import org.simantics.db.service.XSupport;
67 import org.simantics.layer0.Layer0;
68 import org.simantics.utils.datastructures.MapList;
70 import gnu.trove.map.hash.TIntIntHashMap;
71 import gnu.trove.map.hash.TObjectIntHashMap;
74 * Write graph implementation that does not modify the database
75 * immediately but with an explicit commit method. All read operations
76 * return results based on the old graph.
78 public class DelayedWriteGraph extends ReadGraphImpl implements WriteGraph, ByteReader, Closeable {
80 private static final boolean DEBUG = false;
81 private static final int BUFFER_SIZE = 512*1024;
83 private static final PassthroughSerializerBinding PASSTHROUGH = new PassthroughSerializerBinding();
85 private final int TERM = 0;
86 private final int CLAIM = 1;
87 private final int CLAIM_NOINVERSE = 2;
88 private final int CLAIM_VALUE_B = 4;
89 private final int DENY = 5;
90 private final int DENY_VALUE = 6;
91 private final int COMMIT_AND_CONTINUE = 7;
93 private static class State {
95 public FileOutputStream out;
96 public FileInputStream in;
97 public ArrayList<Resource> idToResource = new ArrayList<Resource>();
98 public TIntIntHashMap externalToId = new TIntIntHashMap();
99 public ArrayList<Binding> idToBinding = new ArrayList<Binding>();
100 public TObjectIntHashMap<Binding> bindingToId = new TObjectIntHashMap<Binding>();
101 public Set<Resource> clusterSets = new HashSet<Resource>();
102 public Set<Resource> clusterSetsForExistingResources = new HashSet<Resource>();
103 public int clusterCount = 0;
104 public long defaultCluster;
105 public Resource defaultClusterSet;
106 public int statementCount = 0;
107 public int valueCount = 0;
108 public int fileCount = 0;
111 private State writeState;
112 private TreeMap<String,byte[]> metadata = new TreeMap<String,byte[]>();
114 private FileChannel channel;
115 private byte[] bytes = new byte[BUFFER_SIZE];
116 private ByteBuffer bb = ByteBuffer.wrap(bytes);
117 private int byteIndex = 0;
120 private Session session;
122 public static Resource convertDelayedResource(Resource r) {
123 if (r instanceof InternalResource)
124 return ((InternalResource) r).resource;
128 private static class InternalResource implements Resource {
132 Resource resource = null;
133 Resource clusterSet = null;
135 public InternalResource(int id, long clusterId) {
137 this.clusterId = clusterId;
140 public InternalResource(int id, Resource clusterSet) {
142 this.clusterSet = clusterSet;
146 public long getResourceId() {
147 throw new UnsupportedOperationException();
151 public Resource get() {
156 public boolean isPersistent() {
161 public int compareTo(Resource o) {
162 if(o instanceof InternalResource)
163 return Integer.compare(id, ((InternalResource)o).id);
168 public int hashCode() {
169 final int prime = 31;
171 result = prime * result + id;
176 public int getThreadHash() {
181 public boolean equals(Object obj) {
186 if (!(obj instanceof InternalResource))
188 InternalResource other = (InternalResource) obj;
195 public boolean equalsResource(Resource other) {
196 return equals(other);
200 public String toString() {
201 StringBuilder sb = new StringBuilder(32);
202 if(DebugPolicy.VERBOSE) {
203 sb.append("[delayed id=");
211 return sb.toString();
215 private int getId(Resource resource) {
216 if(resource instanceof InternalResource)
217 return ((InternalResource)resource).id;
219 ResourceImpl r = (ResourceImpl)resource;
220 int id = writeState.externalToId.get(r.id);
224 id = writeState.idToResource.size();
225 writeState.idToResource.add(resource);
226 writeState.externalToId.put(r.id, id);
232 private Resource getResource(int id) {
233 return writeState.idToResource.get(id);
236 private int getBindingId(Binding binding) {
237 if(writeState.bindingToId.contains(binding))
238 return writeState.bindingToId.get(binding);
240 int id = writeState.idToBinding.size();
241 writeState.idToBinding.add(binding);
242 writeState.bindingToId.put(binding, id);
247 public DelayedWriteGraph(ReadGraph g) throws IOException {
248 super((ReadGraphImpl)g);
249 writeState = new State();
250 session = g.getSession();
251 b = Layer0.getInstance(g);
252 writeState.defaultCluster = newCluster();
255 public DelayedWriteGraph(ReadGraph g, State state) {
256 super((ReadGraphImpl)g);
257 session = g.getSession();
258 b = Layer0.getInstance(g);
259 this.writeState = state;
262 public DelayedWriteGraph newSync() {
263 return new DelayedWriteGraph(this, writeState);
267 public void claim(Resource subject, Resource predicate, Resource object)
268 throws ServiceException {
269 assert(subject != null);
270 assert(predicate != null);
271 assert(object != null);
273 Resource inverse = getPossibleInverse(predicate);
274 claim(subject, predicate, inverse, object);
278 public void addLiteral(Resource resource, Resource predicate, Resource inverse, Resource type, Object value,
279 Binding binding) throws BindingException,
280 ManyObjectsForFunctionalRelationException, ServiceException {
281 Resource valueResource = newResource();
282 claimValue(valueResource, value, binding);
283 claim(valueResource, b.InstanceOf, null, type);
284 claim(resource, predicate, inverse, valueResource);
288 public void addLiteral(Resource resource, Resource predicate,
289 Resource inverse, Object value, Binding binding)
290 throws BindingException, ManyObjectsForFunctionalRelationException,
293 Resource type = getType(value);
295 Resource literal = newResource();
297 Resource dataType = newResource();
298 claim(dataType, b.InstanceOf, null, b.DataType);
299 claimValue(dataType, binding.type(), DATA_TYPE_BINDING_INTERNAL);
300 claim(literal, b.HasDataType, null, dataType);
301 claim(literal, b.InstanceOf, null, type);
302 claimValue(literal, value, binding);
303 claim(resource, predicate, inverse, literal);
305 addLiteral(resource, predicate, inverse, type, value, binding);
311 public <T extends Accessor> T newLiteral(Resource resource, Resource predicate, Datatype datatype, Object initialValue)
312 throws DatabaseException {
314 throw new UnsupportedOperationException();
319 public RandomAccessBinary createRandomAccessBinary (Resource resource, Resource predicate, Datatype datatype, Object initialValue) throws DatabaseException {
320 throw new UnsupportedOperationException();
324 public RandomAccessBinary createRandomAccessBinary(Resource resource, Datatype datatype, Object initialValue) throws DatabaseException {
325 throw new UnsupportedOperationException();
329 public void claimLiteral(Resource resource, Resource predicate, Object value) throws ManyObjectsForFunctionalRelationException, ServiceException {
332 Binding b = Bindings.getBinding(value.getClass());
333 claimLiteral(resource, predicate, value, b);
334 } catch (BindingConstructionException e) {
335 throw new IllegalArgumentException(e);
336 } catch (BindingException e) {
337 throw new IllegalArgumentException(e);
343 public void claimLiteral(Resource resource, Resource predicate, Object value, Binding binding) throws BindingException,
344 ManyObjectsForFunctionalRelationException, ServiceException {
346 Statement valueStatement = null;
347 if(!(resource instanceof InternalResource)) valueStatement = getPossibleStatement(resource, predicate);
349 if(valueStatement != null && resource.equals(valueStatement.getSubject())) {
351 claimValue(valueStatement.getObject(), value, binding);
355 Resource type = getType(value);
356 Resource literal = newResource();
359 Resource dataType = newResource();
360 claim(dataType, b.InstanceOf, null, b.DataType);
361 claimValue(dataType, binding.type(), DATA_TYPE_BINDING_INTERNAL);
362 claim(literal, b.HasDataType, dataType);
364 claim(literal, b.InstanceOf, null, type);
365 claimValue(literal, value, binding);
366 claim(resource, predicate, literal);
373 public void claimLiteral(Resource resource, Resource predicate,
374 Resource inverse, Resource type, Object value)
375 throws BindingException, ManyObjectsForFunctionalRelationException,
379 Binding b = Bindings.getBinding(value.getClass());
380 claimLiteral(resource, predicate, inverse, type, value, b);
381 } catch (BindingConstructionException e) {
382 throw new IllegalArgumentException(e);
383 } catch (BindingException e) {
384 throw new IllegalArgumentException(e);
390 public void claimLiteral(Resource resource, Resource predicate,
391 Resource inverse, Resource type, Object value, Binding binding)
392 throws BindingException, ManyObjectsForFunctionalRelationException,
395 Statement valueStatement = (resource instanceof InternalResource) ? null : getPossibleStatement(resource, predicate);
397 if(valueStatement != null && resource.equals(valueStatement.getSubject())) {
399 claimValue(valueStatement.getObject(), value, binding);
403 Resource valueResource = newResource();
404 claim(valueResource, b.InstanceOf, null, type);
405 claim(resource, predicate, inverse, valueResource);
406 claimValue(valueResource, value, binding);
413 public void claimLiteral(Resource resource, Resource predicate,
414 Resource type, Object value) throws BindingException,
415 ManyObjectsForFunctionalRelationException, ServiceException {
418 Binding b = Bindings.getBinding(value.getClass());
419 claimLiteral(resource, predicate, type, value, b);
420 } catch (BindingConstructionException e) {
421 throw new IllegalArgumentException(e);
422 } catch (BindingException e) {
423 throw new IllegalArgumentException(e);
429 public void claimLiteral(Resource resource, Resource predicate,
430 Resource type, Object value, Binding binding)
431 throws BindingException, ManyObjectsForFunctionalRelationException,
435 Resource inverse = getSingleObject(predicate, b.InverseOf);
436 claimLiteral(resource, predicate, inverse, type, value, binding);
437 } catch (NoSingleResultException e) {
438 throw new ServiceException(e);
444 public void deny(Resource subject) throws ServiceException {
445 assert(subject != null);
446 if(!(subject instanceof InternalResource)) {
448 for (Statement statement : getStatements(subject, b.IsWeaklyRelatedTo)) {
451 } catch (ManyObjectsForFunctionalRelationException e) {
452 throw new ServiceException(e);
458 public void deny(Resource subject, Resource predicate)
459 throws ServiceException {
460 assert(subject != null);
461 if(!(subject instanceof InternalResource)) {
462 for (Resource object : getObjects(subject, predicate)) {
463 deny(subject, predicate, object);
469 public void deny(Resource subject, Resource predicate, Resource object) throws ServiceException {
470 denyStatement(subject, predicate, object);
474 public void denyStatement(Resource subject, Resource predicate, Resource object) throws ServiceException {
475 deny(subject, predicate, getPossibleInverse(predicate), object);
479 public void deny(Statement statement) throws ServiceException {
480 Resource predicate = statement.getPredicate();
481 deny(statement.getSubject(), predicate, getPossibleInverse(predicate), statement.getObject());
485 public void denyValue(Resource resource, Resource predicate)
486 throws ManyObjectsForFunctionalRelationException, ServiceException {
487 assert(resource != null);
488 assert(predicate != null);
490 if(!(resource instanceof InternalResource)) {
491 Statement valueStatement = getPossibleStatement(resource, predicate);
493 if (valueStatement != null && !valueStatement.isAsserted(resource)) {
494 Resource value = valueStatement.getObject();
501 public Resource newResource() throws ServiceException {
502 if(writeState.defaultClusterSet != null) return newResource(writeState.defaultClusterSet);
503 else return newResource(writeState.defaultCluster);
507 public Resource newResource(long clusterId) throws ServiceException {
508 int id = writeState.idToResource.size();
509 InternalResource ret = new InternalResource(id, clusterId);
510 writeState.idToResource.add(ret);
515 public Resource newResource(Resource clusterSet) throws ServiceException {
517 if ((clusterSet instanceof InternalResource)) {
518 if(!writeState.clusterSets.contains(clusterSet))
519 throw new ClusterSetExistException("Cluster set does not exist. Resource=" + clusterSet);
521 WriteSupport ws = session.getService(WriteSupport.class);
522 if (!ws.hasClusterSet(null, clusterSet))
523 if(!writeState.clusterSetsForExistingResources.contains(clusterSet))
524 throw new ClusterSetExistException("Cluster set does not exist. Resource=" + clusterSet);
527 int id = writeState.idToResource.size();
528 InternalResource ret = new InternalResource(id, clusterSet);
529 writeState.idToResource.add(ret);
534 public void newClusterSet(Resource clusterSet) throws ServiceException {
536 System.out.println("new cluster set=" + clusterSet);
537 boolean existingResource = !(clusterSet instanceof InternalResource);
538 if (existingResource) {
539 WriteSupport ws = session.getService(WriteSupport.class);
540 if (ws.hasClusterSet(null, clusterSet))
541 throw new ClusterSetExistException("Cluster set exist already. Resource=" + clusterSet);
542 writeState.clusterSetsForExistingResources.add(clusterSet);
544 if(!writeState.clusterSets.add(clusterSet))
545 throw new ClusterSetExistException("Cluster set exist already. Resource=" + clusterSet);
549 public Resource setClusterSet4NewResource(Resource clusterSet)
550 throws ServiceException {
551 Resource existing = writeState.defaultClusterSet;
552 writeState.defaultClusterSet = clusterSet;
557 public void claim(Resource subject, Resource predicate, Resource inverse,
558 Resource object) throws ServiceException {
559 assert(subject != null);
560 assert(predicate != null);
561 assert(object != null);
563 if(inverse != null && !(subject.equals(object) && inverse.equals(predicate))) {
565 writeInt(getId(subject));
566 writeInt(getId(predicate));
567 writeInt(getId(inverse));
568 writeInt(getId(object));
570 writeByte(CLAIM_NOINVERSE);
571 writeInt(getId(subject));
572 writeInt(getId(predicate));
573 writeInt(getId(object));
575 } catch(Exception e) {
576 throw new ServiceException(e);
581 public void deny(Resource subject, Resource predicate, Resource inverse,
582 Resource object) throws ServiceException {
583 assert(subject != null);
584 assert(predicate != null);
585 assert(object != null);
588 writeInt(getId(subject));
589 writeInt(getId(predicate));
590 if(inverse != null) writeInt(getId(inverse));
592 writeInt(getId(object));
593 } catch(Exception e) {
594 throw new ServiceException(e);
599 public void deny(Resource subject, Resource predicate, Resource inverse,
600 Resource object, VirtualGraph graph) throws ServiceException {
601 throw new UnsupportedOperationException();
605 public void claimValue(Resource resource, Object value)
606 throws ServiceException {
608 Binding binding = Bindings.getBinding(value.getClass());
609 claimValue(resource, value, binding);
610 } catch (BindingConstructionException e) {
611 throw new ServiceException(e);
615 private OutputStream valueWriter = new OutputStream() {
617 public void write(int b) throws IOException {
623 public void claimValue(Resource resource, Object value, Binding binding)
624 throws ServiceException {
627 writeByte(CLAIM_VALUE_B);
628 writeInt(getId(resource));
629 Serializer serializer = binding.serializer();
630 int size = serializer.getSize(value);
632 serializer.serialize(valueWriter, value);
634 } catch(IOException e) {
635 Logger.defaultLogError(e);
636 throw new ServiceException(e);
641 public void denyValue(Resource resource) throws ServiceException {
642 writeByte(DENY_VALUE);
643 writeInt(getId(resource));
647 public void denyValue(Resource resource, VirtualGraph graph) throws ServiceException {
648 throw new UnsupportedOperationException();
652 public void flushCluster() throws ServiceException {
653 writeState.defaultCluster = newCluster();
657 public void flushCluster(Resource r) throws ServiceException {
658 throw new ServiceException("Operation flushCluster(" + r + " not implemented.");
661 private void writeReset(int size) {
666 if (writeState.tempFile == null) {
667 File workspace = Platform.getLocation().toFile();
668 File temp = new File(workspace, "tempFiles");
669 File base = new File(temp, "delayed");
670 Files.createDirectories(base.toPath());
671 writeState.tempFile = new File(base, UUID.randomUUID().toString());
672 writeState.out = new FileOutputStream(writeState.tempFile);
673 channel = writeState.out.getChannel();
676 for (int got=0;got < size;) {
677 int n = channel.write(bb);
679 Logger.defaultLogError(new Exception("FileChannel.write returned " + n));
684 } catch (IOException e) {
685 Logger.defaultLogError("Failed to write buffer of " + size + " bytes to temporary file " + writeState.tempFile, e);
689 private void reset() {
692 if (channel != null) {
694 for(int got=0; got < BUFFER_SIZE;) {
695 int n = channel.read(bb);
700 } catch (IOException e) {
701 Logger.defaultLogError("FileChannel.read failed", e);
706 private void writeInt(int i) {
707 if(byteIndex < (BUFFER_SIZE-4)) {
708 bytes[byteIndex++] = (byte)(i&0xff);
709 bytes[byteIndex++] = (byte)((i>>>8)&0xff);
710 bytes[byteIndex++] = (byte)((i>>>16)&0xff);
711 bytes[byteIndex++] = (byte)((i>>>24)&0xff);
712 if (byteIndex == BUFFER_SIZE)
713 writeReset(BUFFER_SIZE);
715 int has = BUFFER_SIZE-byteIndex;
716 if(has == 0) writeReset(BUFFER_SIZE);
717 bytes[byteIndex++] = (byte)(i&0xff);
718 if(has == 1) writeReset(BUFFER_SIZE);
719 bytes[byteIndex++] = (byte)((i>>>8)&0xff);
720 if(has == 2) writeReset(BUFFER_SIZE);
721 bytes[byteIndex++] = (byte)((i>>>16)&0xff);
722 if(has == 3) writeReset(BUFFER_SIZE);
723 bytes[byteIndex++] = (byte)((i>>>24)&0xff);
724 if(has == 4) writeReset(BUFFER_SIZE);
728 private int readInt() {
729 if(byteIndex < (BUFFER_SIZE-4)) {
731 ((bytes[byteIndex++] & 0xff) |
732 ((bytes[byteIndex++] & 0xff)<<8) |
733 ((bytes[byteIndex++] & 0xff)<<16) |
734 ((bytes[byteIndex++] & 0xff)<<24));
737 int has = BUFFER_SIZE-byteIndex;
739 if(has == 0) reset();
740 result = (int)(bytes[byteIndex++] & 0xff);
741 if(has == 1) reset();
742 result |= (int)((bytes[byteIndex++] & 0xff) <<8);
743 if(has == 2) reset();
744 result |= (int)((bytes[byteIndex++] & 0xff) <<16);
745 if(has == 3) reset();
746 result |= (int)((bytes[byteIndex++] & 0xff) <<24);
747 if(has == 4) reset();
752 private byte readByte() {
753 byte result = bytes[byteIndex++];
754 if(byteIndex == BUFFER_SIZE) reset();
758 private void writeByte(int b) {
759 bytes[byteIndex++] = (byte)b;
760 if(byteIndex == BUFFER_SIZE) writeReset(BUFFER_SIZE);
763 private void writeBytes(byte[] data) {
764 int has = BUFFER_SIZE-byteIndex;
765 int amount = data.length;
767 System.arraycopy(data, 0, bytes, byteIndex, amount);
770 System.arraycopy(data, 0, bytes, byteIndex, has);
771 writeReset(BUFFER_SIZE);
772 ByteBuffer bb2 = ByteBuffer.wrap(data);
776 } catch (IOException e) {
777 Logger.defaultLogError("FileChannel.write failed", e);
782 public byte[] readBytes(byte[] result, int amount) {
783 if(result == null) result = new byte[amount];
784 int has = BUFFER_SIZE-byteIndex;
786 System.arraycopy(bytes, byteIndex, result, 0, amount);
789 System.arraycopy(bytes, byteIndex, result, 0, has);
790 ByteBuffer bb2 = ByteBuffer.wrap(result);
792 for(int got=has;got<amount;)
794 got += channel.read(bb2);
796 // End-of-stream, why log this?
799 } catch (IOException e) {
800 Logger.defaultLogError("FileChannel.read failed", e);
807 public void commit(final WriteOnlyGraph w, final WriteTraits traits) throws ServiceException {
808 writeState.bindingToId = null;
809 writeState.externalToId = null;
812 if (writeState.out != null) {
813 // Flush current buffer to file only if backing file has already
814 // been taken into use.
816 writeReset(byteIndex);
818 try (OutputStream out = writeState.out) {
819 channel.force(false);
820 } catch (IOException e) {
821 throw new ServiceException(e);
823 writeState.out = null;
827 writeState.in = new FileInputStream(writeState.tempFile);
828 channel = writeState.in.getChannel();
829 } catch (IOException e) {
830 throw new ServiceException(e);
834 w.getMetadata().putAll(metadata);
836 TransferableGraphSupport tgs = w.getService(TransferableGraphSupport.class);
838 // First create all resources defined by clusterId
839 MapList<Long,InternalResource> clusterAssignment = new MapList<Long,InternalResource>();
840 for(Resource r : writeState.idToResource) {
841 if(r instanceof InternalResource) {
842 InternalResource ir = (InternalResource)r;
843 if(ir.clusterId < 0) {
845 System.out.println("ASSIGN CLUSTER " + ir + " => " + ir.clusterId);
846 clusterAssignment.add(ir.clusterId, ir);
847 } else if(ir.clusterId > 0) {
849 System.out.println("-CREATED RESOURCE WITH EXISTING CLUSTER ID: " + ir);
850 ir.resource = w.newResource(ir.clusterId);
851 writeState.idToResource.set(ir.id, ir.resource);
852 if (writeState.clusterSets.contains(ir)) {
853 w.newClusterSet(ir.resource);
855 System.out.println("--CREATED NEW INTERNAL RESOURCE CLUSTER SET: " + ir.resource);
862 for(Long clusterKey : clusterAssignment.getKeys()) {
864 System.out.println("CREATE LOGICAL CLUSTER: " + clusterKey);
866 for(InternalResource ir : clusterAssignment.getValuesUnsafe(clusterKey)) {
868 System.out.println("-CREATED RESOURCE: " + ir);
869 ir.resource = w.newResource();
870 writeState.idToResource.set(ir.id, ir.resource);
871 if (writeState.clusterSets.contains(ir)) {
872 w.newClusterSet(ir.resource);
874 System.out.println("--CREATED NEW INTERNAL RESOURCE CLUSTER SET: " + ir.resource);
879 // Create cluster sets for all existing resources (not InternalResource)
880 // before proceeding to create resources.
881 for(Resource existingResource : writeState.clusterSetsForExistingResources) {
882 w.newClusterSet(existingResource);
884 System.out.println("CREATED NEW CLUSTER SET: " + existingResource);
887 // Then create all resources defined by cluster set
888 for(Resource r : writeState.idToResource) {
889 if(r instanceof InternalResource) {
890 InternalResource ir = (InternalResource)r;
891 Resource clusterSet = ir.clusterSet;
893 if (clusterSet != null) {
895 System.out.println("NEW RESOURCE " + ir + " for cluster set " + clusterSet);
896 if(clusterSet instanceof InternalResource) {
897 ir.resource = w.newResource(((InternalResource)clusterSet).resource);
899 ir.resource = w.newResource(clusterSet);
902 System.out.println(" => " + ir.resource);
903 writeState.idToResource.set(ir.id, ir.resource);
904 if(writeState.clusterSets.contains(ir)) {
906 System.out.println(" ==> NEW CLUSTER SET");
907 w.newClusterSet(ir.resource);
915 bb.limit(BUFFER_SIZE);
919 byte method = readByte();
923 System.out.println("Resources: " + writeState.idToResource.size());
924 System.out.println("Statements: " + writeState.statementCount);
925 System.out.println("Values: " + writeState.valueCount);
926 System.out.println("Files: " + writeState.fileCount);
927 System.out.println("Clusters: " + writeState.clusterCount);
932 writeState.statementCount += 2;
933 Resource subject = getResource(readInt());
934 Resource predicate = getResource(readInt());
935 Resource inverse = getResource(readInt());
936 Resource object = getResource(readInt());
937 w.claim(subject, predicate, inverse, object);
939 case CLAIM_NOINVERSE: {
940 ++writeState.statementCount;
941 Resource subject = getResource(readInt());
942 Resource predicate = getResource(readInt());
943 Resource object = getResource(readInt());
944 w.claim(subject, predicate, null, object);
947 Resource subject = getResource(readInt());
948 Resource predicate = getResource(readInt());
950 Resource inverse = null;
951 if(inv > 0) inverse = getResource(inv);
952 Resource object = getResource(readInt());
953 if(!subject.isPersistent() || !object.isPersistent()) {
954 VirtualGraph statementProvider1 = processor.getProvider(subject, predicate, object);
956 VirtualGraph statementProvider2 = processor.getProvider(object, inverse, subject);
957 if(statementProvider2 != null)
958 w.deny(object, inverse, null, subject, statementProvider2);
960 if(statementProvider1 != null)
961 w.deny(subject, predicate, null, object, statementProvider1);
963 w.deny(subject, predicate, inverse, object, null);
967 Resource subject = getResource(readInt());
968 if(!subject.isPersistent()) {
969 VirtualGraph provider = processor.getValueProvider(subject);
971 w.denyValue(subject, provider);
973 w.denyValue(subject);
976 case CLAIM_VALUE_B: {
977 ++writeState.valueCount;
978 Resource resource = getResource(readInt());
980 tgs.setValue(w, resource, null, this, len);
982 case COMMIT_AND_CONTINUE: {
983 XSupport xs = w.getService(XSupport.class);
984 xs.commitAndContinue(w, traits);
988 } catch(Exception e) {
989 if(e instanceof ServiceException)
990 throw (ServiceException)e;
992 throw new ServiceException(e);
995 if (writeState.in != null) {
996 try (InputStream in = writeState.in) {
997 } catch (IOException e) {
998 throw new ServiceException(e);
1000 writeState.in = null;
1001 writeState.tempFile.delete();
1007 private Resource getType(Object value) {
1008 Class<?> clazz = value.getClass();
1010 clazz == Float.class ? b.Float
1011 : clazz == Double.class ? b.Double
1012 : clazz == Integer.class ? b.Integer
1013 : clazz == String.class ? b.String
1014 : clazz == Boolean.class ? b.Boolean
1015 : clazz == Byte.class ? b.Byte
1016 : clazz == Long.class ? b.Long
1017 : clazz == float[].class ? b.FloatArray
1018 : clazz == double[].class ? b.DoubleArray
1019 : clazz == int[].class ? b.IntegerArray
1020 : clazz == String[].class ? b.StringArray
1021 : clazz == boolean[].class ? b.BooleanArray
1022 : clazz == byte[].class ? b.ByteArray
1023 : clazz == long[].class ? b.LongArray
1029 public long newCluster() {
1030 return -1 - (++writeState.clusterCount);
1033 public long getDefaultCluster() {
1034 return writeState.defaultCluster;
1037 public void setDefaultCluster(long cluster) {
1038 writeState.defaultCluster = cluster;
1042 public void syncRequest(final DelayedWrite request) throws DatabaseException {
1046 final DelayedWriteGraph dwg = new DelayedWriteGraph(this);
1047 request.perform(dwg);
1049 syncRequest(new WriteOnlyRequest() {
1052 public void perform(WriteOnlyGraph graph) throws DatabaseException {
1053 dwg.commit(graph, request);
1058 } catch (DatabaseException e) {
1062 } catch (Throwable e) {
1064 throw new DatabaseException(e);
1072 public void syncRequest(WriteOnly request) throws DatabaseException {
1074 Resource defaultClusterSet = setClusterSet4NewResource(null);
1077 WriteSupport ws = session.getService(WriteSupport.class);
1078 ws.performWriteRequest(this, request);
1079 } catch (DatabaseException e) {
1081 } catch (Throwable t) {
1082 throw new DatabaseException(t);
1084 setClusterSet4NewResource(defaultClusterSet);
1089 @SuppressWarnings("unchecked")
1091 public <T> T getService(Class<T> api) {
1093 if(ClusteringSupport.class == api) {
1095 final ClusteringSupport support = (ClusteringSupport)super.getService(api);
1097 return (T)new ClusteringSupport() {
1100 public Resource getResourceByIndexAndCluster(int resourceIndex, long clusterId)
1101 throws DatabaseException, ResourceNotFoundException {
1102 return support.getResourceByIndexAndCluster(resourceIndex, clusterId);
1106 public Resource getResourceByKey(int resourceKey) throws ResourceNotFoundException {
1107 return support.getResourceByKey(resourceKey);
1111 public int getNumberOfResources(long clusterId)
1112 throws DatabaseException {
1113 return support.getNumberOfResources(clusterId);
1117 public long getCluster(Resource r) {
1118 return support.getCluster(r);
1122 public long createCluster() {
1123 return newCluster();
1127 public boolean isClusterSet(Resource r) throws DatabaseException {
1128 return support.isClusterSet(r);
1132 public Resource getClusterSetOfCluster(Resource r) throws DatabaseException {
1133 return support.getClusterSetOfCluster(r);
1137 public Resource getClusterSetOfCluster(long cluster) throws DatabaseException {
1138 return support.getClusterSetOfCluster(cluster);
1143 } else if (TransferableGraphSupport.class == api) {
1145 final TransferableGraphSupport parentSupport = session.getService(TransferableGraphSupport.class);
1147 return (T)new TransferableGraphSupport() {
1150 public void setValue(WriteOnlyGraph graph, Resource resource, VirtualGraph provider, byte[] raw) {
1151 writeByte(CLAIM_VALUE_B);
1152 writeInt(getId(resource));
1153 writeInt(raw.length);
1155 writeInt(getBindingId(PASSTHROUGH));
1159 public void setValue(WriteOnlyGraph graph, Resource resource, VirtualGraph provider, ByteReader reader, int amount)
1160 throws DatabaseException {
1161 writeByte(CLAIM_VALUE_B);
1162 writeInt(getId(resource));
1164 writeBytes(reader.readBytes(null, amount));
1165 writeInt(getBindingId(PASSTHROUGH));
1169 public byte[] getValue(ReadGraph graph, Resource resource) {
1170 return parentSupport.getValue(graph, resource);
1174 public InputStream getValueStream(ReadGraph graph, Resource resource) {
1175 return parentSupport.getValueStream(graph, resource);
1182 return super.getService(api);
1187 public <T> void addMetadata(Metadata data) throws ServiceException {
1188 MetadataUtils.addMetadata(session, metadata, data);
1191 public void addCommitAndContinue() {
1192 writeByte(COMMIT_AND_CONTINUE);
1196 public <T extends Metadata> T getMetadata(Class<T> clazz) throws ServiceException {
1197 return MetadataUtils.getMetadata(session, metadata, clazz);
1201 public TreeMap<String, byte[]> getMetadata() {
1205 public <T> T syncRequest(WriteResult<T> request) throws DatabaseException {
1207 return request.perform(this);
1212 public VirtualGraph getProvider() {
1217 public void clearUndoList(WriteTraits writeTraits) {
1218 WriteSupport ws = session.getService(WriteSupport.class);
1220 ws.clearUndoList(writeTraits);
1224 public void markUndoPoint() {
1225 // TODO Auto-generated method stub
1230 public <T> T getPossibleRelatedValue(final Resource subject, final Resource relation, final Binding binding)
1231 throws ManyObjectsForFunctionalRelationException, BindingException, ServiceException {
1232 if(!(subject instanceof InternalResource)) {
1233 return super.getPossibleRelatedValue(subject, relation, binding);
1240 final public Resource getPossibleObject(final Resource subject, final Resource relation)
1241 throws ManyObjectsForFunctionalRelationException, ServiceException {
1242 if(!(subject instanceof InternalResource)) {
1243 return super.getPossibleObject(subject, relation);
1249 public void close() {
1250 if (writeState.out != null) {
1251 try (OutputStream out = writeState.out) {
1252 } catch (IOException e) {
1253 Logger.defaultLogError("Failed to close delayed write graph temporary commit output stream", e);
1255 writeState.out = null;
1258 if (writeState.in != null) {
1259 try (InputStream in = writeState.in) {
1260 } catch (IOException e) {
1261 Logger.defaultLogError("Failed to close delayed write graph temporary commit input stream", e);
1263 writeState.in = null;
1266 if (writeState.tempFile != null) {
1267 writeState.tempFile.delete();
1268 writeState.tempFile = null;