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.DataInput;
16 import java.io.DataOutput;
18 import java.io.FileInputStream;
19 import java.io.FileOutputStream;
20 import java.io.IOException;
21 import java.io.InputStream;
22 import java.io.OutputStream;
23 import java.nio.ByteBuffer;
24 import java.nio.channels.FileChannel;
25 import java.util.ArrayList;
26 import java.util.HashSet;
27 import java.util.IdentityHashMap;
28 import java.util.List;
30 import java.util.TreeMap;
31 import java.util.UUID;
33 import org.eclipse.core.runtime.Platform;
34 import org.simantics.databoard.Bindings;
35 import org.simantics.databoard.accessor.Accessor;
36 import org.simantics.databoard.accessor.reference.ChildReference;
37 import org.simantics.databoard.binding.Binding;
38 import org.simantics.databoard.binding.error.BindingConstructionException;
39 import org.simantics.databoard.binding.impl.BindingPrintContext;
40 import org.simantics.databoard.serialization.SerializationException;
41 import org.simantics.databoard.serialization.Serializer;
42 import org.simantics.databoard.type.Datatype;
43 import org.simantics.databoard.util.IdentityPair;
44 import org.simantics.databoard.util.binary.RandomAccessBinary;
45 import org.simantics.db.Metadata;
46 import org.simantics.db.ReadGraph;
47 import org.simantics.db.Resource;
48 import org.simantics.db.Session;
49 import org.simantics.db.Statement;
50 import org.simantics.db.VirtualGraph;
51 import org.simantics.db.WriteGraph;
52 import org.simantics.db.WriteOnlyGraph;
53 import org.simantics.db.common.MetadataUtils;
54 import org.simantics.db.common.request.WriteOnlyRequest;
55 import org.simantics.db.common.utils.Logger;
56 import org.simantics.db.exception.BindingException;
57 import org.simantics.db.exception.ClusterSetExistException;
58 import org.simantics.db.exception.DatabaseException;
59 import org.simantics.db.exception.ManyObjectsForFunctionalRelationException;
60 import org.simantics.db.exception.NoSingleResultException;
61 import org.simantics.db.exception.ResourceNotFoundException;
62 import org.simantics.db.exception.ServiceException;
63 import org.simantics.db.impl.DebugPolicy;
64 import org.simantics.db.impl.ResourceImpl;
65 import org.simantics.db.request.DelayedWrite;
66 import org.simantics.db.request.WriteOnly;
67 import org.simantics.db.request.WriteResult;
68 import org.simantics.db.request.WriteTraits;
69 import org.simantics.db.service.ByteReader;
70 import org.simantics.db.service.ClusteringSupport;
71 import org.simantics.db.service.TransferableGraphSupport;
72 import org.simantics.db.service.XSupport;
73 import org.simantics.layer0.Layer0;
74 import org.simantics.utils.datastructures.MapList;
76 import gnu.trove.list.array.TIntArrayList;
77 import gnu.trove.map.hash.TIntIntHashMap;
78 import gnu.trove.map.hash.TObjectIntHashMap;
81 * Write graph implementation that does not modify the database
82 * immediately but with an explicit commit method. All read operations
83 * return results based on the old graph.
85 public class DelayedWriteGraph extends ReadGraphImpl implements WriteGraph, ByteReader {
87 private static final boolean DEBUG = false;
88 public static int BUFFER = 65536;
90 static class Haxx extends Binding {
92 static final Serializer serializer = new Serializer() {
94 public byte[] serialize(Object obj) throws SerializationException {
99 public void serialize(DataOutput out,
100 TObjectIntHashMap<Object> identities, Object obj)
102 throw new Error("Not supported.");
106 public void serialize(DataOutput out, Object obj)
108 throw new Error("Not supported.");
112 public Object deserialize(DataInput in, List<Object> identities)
114 throw new Error("Not supported.");
118 public Object deserialize(DataInput in) throws IOException {
119 throw new Error("Not supported.");
123 public void deserializeTo(DataInput in, List<Object> identities,
124 Object obj) throws IOException {
125 throw new Error("Not supported.");
129 public void deserializeTo(DataInput in, Object obj)
131 throw new Error("Not supported.");
135 public void skip(DataInput in, List<Object> identities)
137 throw new Error("Not supported.");
141 public void skip(DataInput in) throws IOException {
142 throw new Error("Not supported.");
146 public Integer getConstantSize() {
147 throw new Error("Not supported.");
151 public int getSize(Object obj, TObjectIntHashMap<Object> identities)
153 throw new Error("Not supported.");
157 public int getSize(Object obj) throws IOException {
158 throw new Error("Not supported.");
162 public int getMinSize() {
163 throw new Error("Not supported.");
169 public Serializer serializer() {
174 public void accept(Visitor1 v, Object obj) {
175 throw new Error("Not supported.");
179 public <T> T accept(Visitor<T> v) {
180 throw new Error("Not supported.");
184 public boolean isInstance(Object obj) {
185 throw new Error("Not supported.");
189 public void assertInstaceIsValid(Object obj, Set<Object> validInstances)
190 throws org.simantics.databoard.binding.error.BindingException {
191 throw new Error("Not supported.");
195 public int deepHashValue(Object value,
196 IdentityHashMap<Object, Object> hashedObjects)
197 throws org.simantics.databoard.binding.error.BindingException {
198 throw new Error("Not supported.");
202 public int deepCompare(Object o1, Object o2,
203 Set<IdentityPair<Object, Object>> compareHistory)
204 throws org.simantics.databoard.binding.error.BindingException {
205 throw new Error("Not supported.");
209 public void readFrom(Binding srcBinding, Object src, Object dst)
210 throws org.simantics.databoard.binding.error.BindingException {
211 throw new Error("Not supported.");
215 public Object readFromTry(Binding srcBinding, Object src, Object dst)
216 throws org.simantics.databoard.binding.error.BindingException {
217 throw new Error("Not supported.");
221 protected void toString(Object value, BindingPrintContext ctx) throws org.simantics.databoard.binding.error.BindingException {
222 throw new Error("Not supported.");
226 public int getComponentCount() {
227 throw new Error("Not supported.");
231 public Binding getComponentBinding(int index) {
232 throw new Error("Not supported.");
236 public Binding getComponentBinding(ChildReference path) {
237 throw new Error("Not supported.");
242 private static final Haxx haxx = new Haxx();
244 private final int TERM = 0;
245 private final int CLAIM = 1;
246 private final int CLAIM_NOINVERSE = 2;
247 private final int CLAIM_VALUE_B = 4;
248 private final int DENY = 5;
249 private final int DENY_VALUE = 6;
250 private final int COMMIT_AND_CONTINUE = 7;
252 static class ClusterSet {
253 public Resource resource;
255 ids = new TIntArrayList();
258 ClusterSet(boolean old, Resource r) {
259 ids = new TIntArrayList();
266 private TIntArrayList ids;
267 private final boolean old; // true if
273 public File tempFile;
274 public FileOutputStream out;
275 public ArrayList<Resource> idToResource = new ArrayList<Resource>();
276 public TIntIntHashMap externalToId = new TIntIntHashMap();
277 public ArrayList<Binding> idToBinding = new ArrayList<Binding>();
278 public TObjectIntHashMap<Binding> bindingToId = new TObjectIntHashMap<Binding>();
279 public Set<Resource> clusterSets = new HashSet<Resource>();
280 public Set<Resource> clusterSetsForExistingResources = new HashSet<Resource>();
281 public int clusterCount = 0;
282 public long defaultCluster;
283 public Resource defaultClusterSet;
284 public int statementCount = 0;
285 public int valueCount = 0;
286 public int fileCount = 0;
289 public State writeState;
290 public TreeMap<String,byte[]> metadata = new TreeMap<String,byte[]>();
294 public static Resource convertDelayedResource(Resource r) {
295 if (r instanceof InternalResource) {
296 InternalResource ri = (InternalResource)r;
301 private static class InternalResource implements Resource {
305 Resource resource = null;
306 Resource clusterSet = null;
308 public InternalResource(int id, long clusterId) {
310 this.clusterId = clusterId;
313 public InternalResource(int id, Resource clusterSet) {
315 this.clusterSet = clusterSet;
319 public long getResourceId() {
320 throw new UnsupportedOperationException();
324 public Resource get() {
329 public boolean isPersistent() {
334 public int compareTo(Resource o) {
335 if(o instanceof InternalResource) {
336 return Integer.compare(id, ((InternalResource)o).id);
343 public int hashCode() {
344 final int prime = 31;
346 result = prime * result + id;
351 public int getThreadHash() {
356 public boolean equals(Object obj) {
361 if (!(obj instanceof InternalResource))
363 InternalResource other = (InternalResource) obj;
371 public boolean equalsResource(Resource other) {
372 return equals(other);
375 public String toString() {
376 StringBuilder sb = new StringBuilder(32);
377 if(DebugPolicy.VERBOSE) {
378 sb.append("[delayed id=");
386 return sb.toString();
390 private int getId(Resource resource) {
391 if(resource instanceof InternalResource)
392 return ((InternalResource)resource).id;
394 ResourceImpl r = (ResourceImpl)resource;
395 int id = writeState.externalToId.get(r.id);
399 id = writeState.idToResource.size();
400 writeState.idToResource.add(resource);
401 writeState.externalToId.put(r.id, id);
407 private Resource getResource(int id) {
408 return writeState.idToResource.get(id);
411 private int getBindingId(Binding binding) {
412 if(writeState.bindingToId.contains(binding))
413 return writeState.bindingToId.get(binding);
415 int id = writeState.idToBinding.size();
416 writeState.idToBinding.add(binding);
417 writeState.bindingToId.put(binding, id);
422 public DelayedWriteGraph(ReadGraph g) throws IOException {
423 super((ReadGraphImpl)g);
424 writeState = new State();
425 session = g.getSession();
426 b = Layer0.getInstance(g);
427 writeState.defaultCluster = newCluster();
430 public DelayedWriteGraph(ReadGraph g, State state) {
431 super((ReadGraphImpl)g);
432 session = g.getSession();
433 b = Layer0.getInstance(g);
434 this.writeState = state;
437 public DelayedWriteGraph newSync() {
438 return new DelayedWriteGraph(this, writeState);
442 public void claim(Resource subject, Resource predicate, Resource object)
443 throws ServiceException {
444 assert(subject != null);
445 assert(predicate != null);
446 assert(object != null);
448 Resource inverse = getPossibleInverse(predicate);
449 claim(subject, predicate, inverse, object);
453 public void addLiteral(Resource resource, Resource predicate, Resource inverse, Resource type, Object value,
454 Binding binding) throws BindingException,
455 ManyObjectsForFunctionalRelationException, ServiceException {
456 Resource valueResource = newResource();
457 claimValue(valueResource, value, binding);
458 claim(valueResource, b.InstanceOf, null, type);
459 claim(resource, predicate, inverse, valueResource);
463 public void addLiteral(Resource resource, Resource predicate,
464 Resource inverse, Object value, Binding binding)
465 throws BindingException, ManyObjectsForFunctionalRelationException,
468 Resource type = getType(value);
470 Resource literal = newResource();
472 Resource dataType = newResource();
473 claim(dataType, b.InstanceOf, null, b.DataType);
474 claimValue(dataType, binding.type(), DATA_TYPE_BINDING_INTERNAL);
475 claim(literal, b.HasDataType, null, dataType);
476 claim(literal, b.InstanceOf, null, type);
477 claimValue(literal, value, binding);
478 claim(resource, predicate, inverse, literal);
480 addLiteral(resource, predicate, inverse, type, value, binding);
486 public <T extends Accessor> T newLiteral(Resource resource, Resource predicate, Datatype datatype, Object initialValue)
487 throws DatabaseException {
489 throw new UnsupportedOperationException();
494 public RandomAccessBinary createRandomAccessBinary (Resource resource, Resource predicate, Datatype datatype, Object initialValue) throws DatabaseException {
495 throw new UnsupportedOperationException();
499 public RandomAccessBinary createRandomAccessBinary(Resource resource, Datatype datatype, Object initialValue) throws DatabaseException {
500 throw new UnsupportedOperationException();
504 public void claimLiteral(Resource resource, Resource predicate, Object value) throws ManyObjectsForFunctionalRelationException, ServiceException {
507 Binding b = Bindings.getBinding(value.getClass());
508 claimLiteral(resource, predicate, value, b);
509 } catch (BindingConstructionException e) {
510 throw new IllegalArgumentException(e);
511 } catch (BindingException e) {
512 throw new IllegalArgumentException(e);
518 public void claimLiteral(Resource resource, Resource predicate, Object value, Binding binding) throws BindingException,
519 ManyObjectsForFunctionalRelationException, ServiceException {
521 Statement valueStatement = null;
522 if(!(resource instanceof InternalResource)) valueStatement = getPossibleStatement(resource, predicate);
524 if(valueStatement != null && resource.equals(valueStatement.getSubject())) {
526 claimValue(valueStatement.getObject(), value, binding);
530 Resource type = getType(value);
531 Resource literal = newResource();
534 Resource dataType = newResource();
535 claim(dataType, b.InstanceOf, null, b.DataType);
536 claimValue(dataType, binding.type(), DATA_TYPE_BINDING_INTERNAL);
537 claim(literal, b.HasDataType, dataType);
539 claim(literal, b.InstanceOf, null, type);
540 claimValue(literal, value, binding);
541 claim(resource, predicate, literal);
548 public void claimLiteral(Resource resource, Resource predicate,
549 Resource inverse, Resource type, Object value)
550 throws BindingException, ManyObjectsForFunctionalRelationException,
554 Binding b = Bindings.getBinding(value.getClass());
555 claimLiteral(resource, predicate, inverse, type, value, b);
556 } catch (BindingConstructionException e) {
557 throw new IllegalArgumentException(e);
558 } catch (BindingException e) {
559 throw new IllegalArgumentException(e);
565 public void claimLiteral(Resource resource, Resource predicate,
566 Resource inverse, Resource type, Object value, Binding binding)
567 throws BindingException, ManyObjectsForFunctionalRelationException,
570 Statement valueStatement = (resource instanceof InternalResource) ? null : getPossibleStatement(resource, predicate);
572 if(valueStatement != null && resource.equals(valueStatement.getSubject())) {
574 claimValue(valueStatement.getObject(), value, binding);
578 Resource valueResource = newResource();
579 claim(valueResource, b.InstanceOf, null, type);
580 claim(resource, predicate, inverse, valueResource);
581 claimValue(valueResource, value, binding);
588 public void claimLiteral(Resource resource, Resource predicate,
589 Resource type, Object value) throws BindingException,
590 ManyObjectsForFunctionalRelationException, ServiceException {
593 Binding b = Bindings.getBinding(value.getClass());
594 claimLiteral(resource, predicate, type, value, b);
595 } catch (BindingConstructionException e) {
596 throw new IllegalArgumentException(e);
597 } catch (BindingException e) {
598 throw new IllegalArgumentException(e);
604 public void claimLiteral(Resource resource, Resource predicate,
605 Resource type, Object value, Binding binding)
606 throws BindingException, ManyObjectsForFunctionalRelationException,
610 Resource inverse = getSingleObject(predicate, b.InverseOf);
611 claimLiteral(resource, predicate, inverse, type, value, binding);
612 } catch (NoSingleResultException e) {
613 throw new ServiceException(e);
619 public void deny(Resource subject) throws ServiceException {
620 assert(subject != null);
621 if(!(subject instanceof InternalResource)) {
623 for (Statement statement : getStatements(subject, b.IsWeaklyRelatedTo)) {
626 } catch (ManyObjectsForFunctionalRelationException e) {
627 throw new ServiceException(e);
633 public void deny(Resource subject, Resource predicate)
634 throws ServiceException {
635 assert(subject != null);
636 if(!(subject instanceof InternalResource)) {
637 for (Resource object : getObjects(subject, predicate)) {
638 deny(subject, predicate, object);
644 public void deny(Resource subject, Resource predicate, Resource object) throws ServiceException {
645 denyStatement(subject, predicate, object);
649 public void denyStatement(Resource subject, Resource predicate, Resource object) throws ServiceException {
650 deny(subject, predicate, getPossibleInverse(predicate), object);
654 public void deny(Statement statement) throws ServiceException {
655 Resource predicate = statement.getPredicate();
656 deny(statement.getSubject(), predicate, getPossibleInverse(predicate), statement.getObject());
660 public void denyValue(Resource resource, Resource predicate)
661 throws ManyObjectsForFunctionalRelationException, ServiceException {
662 assert(resource != null);
663 assert(predicate != null);
665 if(!(resource instanceof InternalResource)) {
666 Statement valueStatement = getPossibleStatement(resource, predicate);
668 if (valueStatement != null && !valueStatement.isAsserted(resource)) {
669 Resource value = valueStatement.getObject();
676 public Resource newResource() throws ServiceException {
677 if(writeState.defaultClusterSet != null) return newResource(writeState.defaultClusterSet);
678 else return newResource(writeState.defaultCluster);
682 public Resource newResource(long clusterId) throws ServiceException {
683 int id = writeState.idToResource.size();
684 InternalResource ret = new InternalResource(id, clusterId);
685 writeState.idToResource.add(ret);
690 public Resource newResource(Resource clusterSet) throws ServiceException {
692 if ((clusterSet instanceof InternalResource)) {
693 if(!writeState.clusterSets.contains(clusterSet))
694 throw new ClusterSetExistException("Cluster set does not exist. Resource=" + clusterSet);
696 WriteSupport ws = session.getService(WriteSupport.class);
697 if (!ws.hasClusterSet(null, clusterSet))
698 if(!writeState.clusterSetsForExistingResources.contains(clusterSet))
699 throw new ClusterSetExistException("Cluster set does not exist. Resource=" + clusterSet);
702 int id = writeState.idToResource.size();
703 InternalResource ret = new InternalResource(id, clusterSet);
704 writeState.idToResource.add(ret);
709 public void newClusterSet(Resource clusterSet) throws ServiceException {
711 System.out.println("new cluster set=" + clusterSet);
712 boolean existingResource = !(clusterSet instanceof InternalResource);
713 if (existingResource) {
714 WriteSupport ws = session.getService(WriteSupport.class);
715 if (ws.hasClusterSet(null, clusterSet))
716 throw new ClusterSetExistException("Cluster set exist already. Resource=" + clusterSet);
717 writeState.clusterSetsForExistingResources.add(clusterSet);
719 if(!writeState.clusterSets.add(clusterSet))
720 throw new ClusterSetExistException("Cluster set exist already. Resource=" + clusterSet);
724 public Resource setClusterSet4NewResource(Resource clusterSet)
725 throws ServiceException {
726 Resource existing = writeState.defaultClusterSet;
727 writeState.defaultClusterSet = clusterSet;
732 public void claim(Resource subject, Resource predicate, Resource inverse,
733 Resource object) throws ServiceException {
734 assert(subject != null);
735 assert(predicate != null);
736 assert(object != null);
738 if(inverse != null && !(subject.equals(object) && inverse.equals(predicate))) {
740 writeInt(getId(subject));
741 writeInt(getId(predicate));
742 writeInt(getId(inverse));
743 writeInt(getId(object));
745 writeByte(CLAIM_NOINVERSE);
746 writeInt(getId(subject));
747 writeInt(getId(predicate));
748 writeInt(getId(object));
750 } catch(Exception e) {
751 throw new ServiceException(e);
756 public void deny(Resource subject, Resource predicate, Resource inverse,
757 Resource object) throws ServiceException {
758 assert(subject != null);
759 assert(predicate != null);
760 assert(object != null);
763 writeInt(getId(subject));
764 writeInt(getId(predicate));
765 if(inverse != null) writeInt(getId(inverse));
767 writeInt(getId(object));
768 } catch(Exception e) {
769 throw new ServiceException(e);
774 public void deny(Resource subject, Resource predicate, Resource inverse,
775 Resource object, VirtualGraph graph) throws ServiceException {
776 throw new UnsupportedOperationException();
780 public void claimValue(Resource resource, Object value)
781 throws ServiceException {
783 Binding binding = Bindings.getBinding(value.getClass());
784 claimValue(resource, value, binding);
785 } catch (BindingConstructionException e) {
786 throw new ServiceException(e);
791 public void claimValue(Resource resource, Object value, Binding binding)
792 throws ServiceException {
795 writeByte(CLAIM_VALUE_B);
796 writeInt(getId(resource));
797 Serializer serializer = binding.serializer();
798 int size = serializer.getSize(value);
800 serializer.serialize(new OutputStream() {
803 public void write(int b) throws IOException {
809 } catch(IOException e) {
810 Logger.defaultLogError(e);
811 throw new ServiceException(e);
816 public void denyValue(Resource resource) throws ServiceException {
817 writeByte(DENY_VALUE);
818 writeInt(getId(resource));
822 public void denyValue(Resource resource, VirtualGraph graph) throws ServiceException {
823 throw new UnsupportedOperationException();
827 public void flushCluster() throws ServiceException {
828 writeState.defaultCluster = newCluster();
832 public void flushCluster(Resource r) throws ServiceException {
833 throw new ServiceException("Operation flushCluster(" + r + " not implemented.");
836 private FileChannel channel;
837 byte[] bytes = new byte[BUFFER];
838 byte[] buffer = new byte[BUFFER];
839 ByteBuffer bb = ByteBuffer.wrap(bytes);
842 private void writeReset(int size) {
849 if(writeState.tempFile == null) {
851 File workspace = Platform.getLocation().toFile();
852 File temp = new File(workspace, "tempFiles");
855 File base = new File(temp, "delayed");
857 writeState.tempFile = new File(base, UUID.randomUUID().toString());
858 writeState.out = new FileOutputStream(writeState.tempFile);
859 channel = writeState.out.getChannel();
863 for (int got=0;got < size;) {
864 int n = channel.write(bb);
866 new Exception().printStackTrace();
871 } catch (IOException e) {
876 private void reset() {
880 for(int got=0; got < BUFFER;) {
881 int n = channel.read(bb);
886 } catch (IOException e) {
891 private void writeInt(int i) {
892 if(byteIndex < (BUFFER-4)) {
893 bytes[byteIndex++] = (byte)(i&0xff);
894 bytes[byteIndex++] = (byte)((i>>>8)&0xff);
895 bytes[byteIndex++] = (byte)((i>>>16)&0xff);
896 bytes[byteIndex++] = (byte)((i>>>24)&0xff);
897 if (byteIndex == BUFFER)
900 int has = BUFFER-byteIndex;
901 if(has == 0) writeReset(BUFFER);
902 bytes[byteIndex++] = (byte)(i&0xff);
903 if(has == 1) writeReset(BUFFER);
904 bytes[byteIndex++] = (byte)((i>>>8)&0xff);
905 if(has == 2) writeReset(BUFFER);
906 bytes[byteIndex++] = (byte)((i>>>16)&0xff);
907 if(has == 3) writeReset(BUFFER);
908 bytes[byteIndex++] = (byte)((i>>>24)&0xff);
909 if(has == 4) writeReset(BUFFER);
913 private int readInt() {
914 if(byteIndex < (BUFFER-4)) {
916 ((bytes[byteIndex++] & 0xff) |
917 ((bytes[byteIndex++] & 0xff)<<8) |
918 ((bytes[byteIndex++] & 0xff)<<16) |
919 ((bytes[byteIndex++] & 0xff)<<24));
922 int has = BUFFER-byteIndex;
924 if(has == 0) reset();
925 result = (int)(bytes[byteIndex++] & 0xff);
926 if(has == 1) reset();
927 result |= (int)((bytes[byteIndex++] & 0xff) <<8);
928 if(has == 2) reset();
929 result |= (int)((bytes[byteIndex++] & 0xff) <<16);
930 if(has == 3) reset();
931 result |= (int)((bytes[byteIndex++] & 0xff) <<24);
932 if(has == 4) reset();
937 private byte readByte() {
938 byte result = bytes[byteIndex++];
939 if(byteIndex == BUFFER) reset();
943 private void writeByte(int b) {
944 bytes[byteIndex++] = (byte)b;
945 if(byteIndex == BUFFER) writeReset(BUFFER);
948 private void writeBytes(byte[] data) {
949 int has = BUFFER-byteIndex;
950 int amount = data.length;
952 System.arraycopy(data, 0, bytes, byteIndex, amount);
955 System.arraycopy(data, 0, bytes, byteIndex, has);
957 ByteBuffer bb2 = ByteBuffer.wrap(data);
961 } catch (IOException e) {
967 public byte[] readBytes(int amount) {
968 return readBytes(buffer, amount);
971 public byte[] readBytes(byte[] result, int amount) {
972 if(result == null) result = new byte[amount];
973 int has = BUFFER-byteIndex;
975 System.arraycopy(bytes, byteIndex, result, 0, amount);
978 System.arraycopy(bytes, byteIndex, result, 0, has);
979 ByteBuffer bb2 = ByteBuffer.wrap(result);
981 for(int got=has;got<amount;)
983 got += channel.read(bb2);
985 new Exception().printStackTrace();
989 } catch (IOException e) {
997 public void commit(final WriteOnlyGraph w, final WriteTraits traits) throws ServiceException {
998 writeState.bindingToId = null;
999 writeState.externalToId = null;
1004 writeReset(byteIndex);
1006 channel.force(false);
1007 writeState.out.close();
1009 FileInputStream fs = new FileInputStream(writeState.tempFile);
1010 channel = fs.getChannel();
1012 } catch (IOException e) {
1013 throw new ServiceException(e);
1016 w.getMetadata().putAll(metadata);
1018 TransferableGraphSupport tgs = w.getService(TransferableGraphSupport.class);
1020 // First create all resources defined by clusterId
1021 MapList<Long,InternalResource> clusterAssignment = new MapList<Long,InternalResource>();
1022 for(Resource r : writeState.idToResource) {
1023 if(r instanceof InternalResource) {
1024 InternalResource ir = (InternalResource)r;
1025 if(ir.clusterId < 0) {
1027 System.out.println("ASSIGN CLUSTER " + ir + " => " + ir.clusterId);
1028 clusterAssignment.add(ir.clusterId, ir);
1029 } else if(ir.clusterId > 0) {
1031 System.out.println("-CREATED RESOURCE WITH EXISTING CLUSTER ID: " + ir);
1032 ir.resource = w.newResource(ir.clusterId);
1033 writeState.idToResource.set(ir.id, ir.resource);
1034 if (writeState.clusterSets.contains(ir)) {
1035 w.newClusterSet(ir.resource);
1037 System.out.println("--CREATED NEW INTERNAL RESOURCE CLUSTER SET: " + ir.resource);
1044 for(Long clusterKey : clusterAssignment.getKeys()) {
1046 System.out.println("CREATE LOGICAL CLUSTER: " + clusterKey);
1048 for(InternalResource ir : clusterAssignment.getValuesUnsafe(clusterKey)) {
1050 System.out.println("-CREATED RESOURCE: " + ir);
1051 ir.resource = w.newResource();
1052 writeState.idToResource.set(ir.id, ir.resource);
1053 if (writeState.clusterSets.contains(ir)) {
1054 w.newClusterSet(ir.resource);
1056 System.out.println("--CREATED NEW INTERNAL RESOURCE CLUSTER SET: " + ir.resource);
1061 // Create cluster sets for all existing resources (not InternalResource)
1062 // before proceeding to create resources.
1063 for(Resource existingResource : writeState.clusterSetsForExistingResources) {
1064 w.newClusterSet(existingResource);
1066 System.out.println("CREATED NEW CLUSTER SET: " + existingResource);
1069 // Then create all resources defined by cluster set
1070 for(Resource r : writeState.idToResource) {
1071 if(r instanceof InternalResource) {
1072 InternalResource ir = (InternalResource)r;
1073 Resource clusterSet = ir.clusterSet;
1075 if (clusterSet != null) {
1077 System.out.println("NEW RESOURCE " + ir + " for cluster set " + clusterSet);
1078 if(clusterSet instanceof InternalResource) {
1079 ir.resource = w.newResource(((InternalResource)clusterSet).resource);
1081 ir.resource = w.newResource(clusterSet);
1084 System.out.println(" => " + ir.resource);
1085 writeState.idToResource.set(ir.id, ir.resource);
1086 if(writeState.clusterSets.contains(ir)) {
1088 System.out.println(" ==> NEW CLUSTER SET");
1089 w.newClusterSet(ir.resource);
1101 byte method = readByte();
1107 writeState.statementCount += 2;
1108 Resource subject = getResource(readInt());
1109 Resource predicate = getResource(readInt());
1110 Resource inverse = getResource(readInt());
1111 Resource object = getResource(readInt());
1112 w.claim(subject, predicate, inverse, object);
1114 case CLAIM_NOINVERSE: {
1115 ++writeState.statementCount;
1116 Resource subject = getResource(readInt());
1117 Resource predicate = getResource(readInt());
1118 Resource object = getResource(readInt());
1119 w.claim(subject, predicate, null, object);
1122 Resource subject = getResource(readInt());
1123 Resource predicate = getResource(readInt());
1124 int inv = readInt();
1125 Resource inverse = null;
1126 if(inv > 0) inverse = getResource(inv);
1127 Resource object = getResource(readInt());
1128 if(!subject.isPersistent() || !object.isPersistent()) {
1129 VirtualGraph statementProvider1 = processor.getProvider(subject, predicate, object);
1131 VirtualGraph statementProvider2 = processor.getProvider(object, inverse, subject);
1132 if(statementProvider2 != null)
1133 w.deny(object, inverse, null, subject, statementProvider2);
1135 if(statementProvider1 != null)
1136 w.deny(subject, predicate, null, object, statementProvider1);
1138 w.deny(subject, predicate, inverse, object, null);
1142 Resource subject = getResource(readInt());
1143 if(!subject.isPersistent()) {
1144 VirtualGraph provider = processor.getValueProvider(subject);
1145 if(provider != null)
1146 w.denyValue(subject, provider);
1148 w.denyValue(subject);
1151 case CLAIM_VALUE_B: {
1152 ++writeState.valueCount;
1153 Resource resource = getResource(readInt());
1154 int len = readInt();
1155 tgs.setValue(w, resource, null, this, len);
1156 // byte[] bytes = readBytes(len);
1157 // tgs.setValue(resource, null, bytes);
1159 case COMMIT_AND_CONTINUE: {
1160 XSupport xs = w.getService(XSupport.class);
1161 xs.commitAndContinue(w, traits);
1165 } catch(Exception e) {
1166 if(e instanceof ServiceException)
1167 throw (ServiceException)e;
1169 throw new ServiceException(e);
1174 } catch (IOException e) {
1175 throw new ServiceException(e);
1178 // System.out.println("Resources: " + state.resourceCount);
1179 // System.out.println("Statements: " + state.statementCount);
1180 // System.out.println("Values: " + state.valueCount);
1183 private Resource getType(Object value) {
1184 Class<?> clazz = value.getClass();
1186 clazz == Float.class ? b.Float
1187 : clazz == Double.class ? b.Double
1188 : clazz == Integer.class ? b.Integer
1189 : clazz == String.class ? b.String
1190 : clazz == Boolean.class ? b.Boolean
1191 : clazz == Byte.class ? b.Byte
1192 : clazz == Long.class ? b.Long
1193 : clazz == float[].class ? b.FloatArray
1194 : clazz == double[].class ? b.DoubleArray
1195 : clazz == int[].class ? b.IntegerArray
1196 : clazz == String[].class ? b.StringArray
1197 : clazz == boolean[].class ? b.BooleanArray
1198 : clazz == byte[].class ? b.ByteArray
1199 : clazz == long[].class ? b.LongArray
1205 public long newCluster() {
1206 return -1 - (++writeState.clusterCount);
1209 public long getDefaultCluster() {
1210 return writeState.defaultCluster;
1213 public void setDefaultCluster(long cluster) {
1214 writeState.defaultCluster = cluster;
1218 public void syncRequest(final DelayedWrite request) throws DatabaseException {
1222 final DelayedWriteGraph dwg = new DelayedWriteGraph(this);
1223 request.perform(dwg);
1225 syncRequest(new WriteOnlyRequest() {
1228 public void perform(WriteOnlyGraph graph) throws DatabaseException {
1229 dwg.commit(graph, request);
1234 } catch (DatabaseException e) {
1238 } catch (Throwable e) {
1240 throw new DatabaseException(e);
1249 public void syncRequest(WriteOnly request) throws DatabaseException {
1251 Resource defaultClusterSet = setClusterSet4NewResource(null);
1254 WriteSupport ws = session.getService(WriteSupport.class);
1255 ws.performWriteRequest(this, request);
1256 } catch (DatabaseException e) {
1258 } catch (Throwable t) {
1259 throw new DatabaseException(t);
1261 setClusterSet4NewResource(defaultClusterSet);
1266 @SuppressWarnings("unchecked")
1268 public <T> T getService(Class<T> api) {
1270 if(ClusteringSupport.class == api) {
1272 final ClusteringSupport support = (ClusteringSupport)super.getService(api);
1274 return (T)new ClusteringSupport() {
1277 public Resource getResourceByIndexAndCluster(int resourceIndex, long clusterId)
1278 throws DatabaseException, ResourceNotFoundException {
1279 return support.getResourceByIndexAndCluster(resourceIndex, clusterId);
1283 public Resource getResourceByKey(int resourceKey) throws ResourceNotFoundException {
1284 return support.getResourceByKey(resourceKey);
1288 public int getNumberOfResources(long clusterId)
1289 throws DatabaseException {
1290 return support.getNumberOfResources(clusterId);
1294 public long getCluster(Resource r) {
1295 return support.getCluster(r);
1299 public long createCluster() {
1300 return newCluster();
1304 public boolean isClusterSet(Resource r) throws DatabaseException {
1305 return support.isClusterSet(r);
1309 public Resource getClusterSetOfCluster(Resource r) throws DatabaseException {
1310 return support.getClusterSetOfCluster(r);
1314 public Resource getClusterSetOfCluster(long cluster) throws DatabaseException {
1315 return support.getClusterSetOfCluster(cluster);
1320 } else if (TransferableGraphSupport.class == api) {
1322 final TransferableGraphSupport parentSupport = session.getService(TransferableGraphSupport.class);
1324 return (T)new TransferableGraphSupport() {
1327 public void setValue(WriteOnlyGraph graph, Resource resource, VirtualGraph provider, byte[] raw) {
1328 writeByte(CLAIM_VALUE_B);
1329 writeInt(getId(resource));
1330 writeInt(raw.length);
1332 writeInt(getBindingId(haxx));
1336 public void setValue(WriteOnlyGraph graph, Resource resource, VirtualGraph provider, ByteReader reader, int amount)
1337 throws DatabaseException {
1338 writeByte(CLAIM_VALUE_B);
1339 writeInt(getId(resource));
1341 writeBytes(reader.readBytes(null, amount));
1342 writeInt(getBindingId(haxx));
1346 public byte[] getValue(ReadGraph graph, Resource resource) {
1347 return parentSupport.getValue(graph, resource);
1351 public InputStream getValueStream(ReadGraph graph, Resource resource) {
1352 return parentSupport.getValueStream(graph, resource);
1359 return super.getService(api);
1364 public <T> void addMetadata(Metadata data) throws ServiceException {
1365 MetadataUtils.addMetadata(session, metadata, data);
1368 public void addCommitAndContinue() {
1369 writeByte(COMMIT_AND_CONTINUE);
1373 public <T extends Metadata> T getMetadata(Class<T> clazz) throws ServiceException {
1374 return MetadataUtils.getMetadata(session, metadata, clazz);
1378 public TreeMap<String, byte[]> getMetadata() {
1382 public <T> T syncRequest(WriteResult<T> request) throws DatabaseException {
1384 return request.perform(this);
1389 public VirtualGraph getProvider() {
1394 public void clearUndoList(WriteTraits writeTraits) {
1395 WriteSupport ws = session.getService(WriteSupport.class);
1397 ws.clearUndoList(writeTraits);
1401 public void markUndoPoint() {
1402 // TODO Auto-generated method stub
1407 public <T> T getPossibleRelatedValue(final Resource subject, final Resource relation, final Binding binding)
1408 throws ManyObjectsForFunctionalRelationException, BindingException, ServiceException {
1409 if(!(subject instanceof InternalResource)) {
1410 return super.getPossibleRelatedValue(subject, relation, binding);
1417 final public Resource getPossibleObject(final Resource subject, final Resource relation)
1418 throws ManyObjectsForFunctionalRelationException, ServiceException {
1419 if(!(subject instanceof InternalResource)) {
1420 return super.getPossibleObject(subject, relation);