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