-package org.simantics.datatypes.utils;\r
-\r
-import gnu.trove.map.hash.TObjectIntHashMap;\r
-\r
-import java.io.DataInput;\r
-import java.io.DataOutput;\r
-import java.io.IOException;\r
-import java.util.Collection;\r
-import java.util.HashMap;\r
-import java.util.IdentityHashMap;\r
-import java.util.List;\r
-import java.util.Map;\r
-import java.util.Set;\r
-\r
-import org.simantics.databoard.Bindings;\r
-import org.simantics.databoard.accessor.reference.ChildReference;\r
-import org.simantics.databoard.binding.Binding;\r
-import org.simantics.databoard.binding.error.BindingException;\r
-import org.simantics.databoard.binding.error.RuntimeBindingConstructionException;\r
-import org.simantics.databoard.binding.impl.BindingPrintContext;\r
-import org.simantics.databoard.serialization.RuntimeSerializerConstructionException;\r
-import org.simantics.databoard.serialization.Serializer;\r
-import org.simantics.databoard.util.IdentityPair;\r
-import org.simantics.datatypes.DatatypeResource;\r
-import org.simantics.db.ReadGraph;\r
-import org.simantics.db.Resource;\r
-import org.simantics.db.WriteGraph;\r
-import org.simantics.db.common.primitiverequest.RelatedValue;\r
-import org.simantics.db.common.procedure.adapter.TransientCacheListener;\r
-import org.simantics.db.common.utils.Logger;\r
-import org.simantics.db.exception.DatabaseException;\r
-import org.simantics.db.service.Bytes;\r
-import org.simantics.db.service.SerialisationSupport;\r
-import org.simantics.layer0.Layer0;\r
-import org.simantics.utils.datastructures.Pair;\r
-\r
-interface LogContentManager {\r
- \r
- LogContentBean getContentBean(ReadGraph graph, Resource node) throws DatabaseException;\r
- void setContentBean(WriteGraph graph, Resource node, LogContentBean bean) throws DatabaseException;\r
- \r
-}\r
-\r
-class LogContentBinding extends Binding {\r
-\r
- private final SerialisationSupport ss;\r
- \r
- public LogContentBinding(SerialisationSupport ss) {\r
- this.ss = ss;\r
- }\r
- \r
- private final Serializer serializer = new Serializer() {\r
-\r
- @Override\r
- public void serialize(DataOutput out, TObjectIntHashMap<Object> identities, Object obj) throws IOException {\r
- throw new UnsupportedOperationException();\r
- }\r
-\r
- @Override\r
- public void serialize(DataOutput out, Object obj) throws IOException {\r
- throw new UnsupportedOperationException();\r
- }\r
-\r
- @Override\r
- public Object deserialize(DataInput in, List<Object> identities)\r
- throws IOException {\r
- throw new UnsupportedOperationException();\r
- }\r
-\r
- @Override\r
- public Object deserialize(DataInput in) throws IOException {\r
- throw new UnsupportedOperationException();\r
- }\r
-\r
- @Override\r
- public void deserializeTo(DataInput in, List<Object> identities,\r
- Object dst) throws IOException {\r
- throw new UnsupportedOperationException();\r
- }\r
-\r
- @Override\r
- public void deserializeTo(DataInput in, Object dst) throws IOException {\r
- throw new UnsupportedOperationException();\r
- }\r
-\r
- @Override\r
- public void skip(DataInput in, List<Object> identities)\r
- throws IOException {\r
- throw new UnsupportedOperationException();\r
- }\r
-\r
- @Override\r
- public void skip(DataInput in) throws IOException {\r
- throw new UnsupportedOperationException();\r
- }\r
-\r
- @Override\r
- public Integer getConstantSize() {\r
- throw new UnsupportedOperationException();\r
- }\r
-\r
- @Override\r
- public int getSize(Object obj, TObjectIntHashMap<Object> identities)\r
- throws IOException {\r
- throw new UnsupportedOperationException();\r
- }\r
-\r
- @Override\r
- public int getSize(Object obj) throws IOException {\r
- throw new UnsupportedOperationException();\r
- }\r
-\r
- @Override\r
- public int getMinSize() {\r
- throw new UnsupportedOperationException();\r
- }\r
- \r
- public byte[] serialize(Object obj) throws IOException {\r
- LogContentBean bean = (LogContentBean)obj;\r
- int bytes = 1 + 4 + 4 + 8 * bean.stamps.length + 8 * bean.resources.length;\r
- byte[] result = new byte[bytes];\r
- Bytes.write(result, 0, bean.leaf ? (byte)1 : (byte)0);\r
- int byteIndex = 1;\r
- Bytes.writeLE(result, byteIndex, bean.n);\r
- byteIndex += 4;\r
- Bytes.writeLE(result, byteIndex, bean.stamps.length);\r
- byteIndex += 4;\r
- for(long l : bean.stamps) {\r
- Bytes.writeLE(result, byteIndex, l);\r
- byteIndex += 8;\r
- }\r
- for(PossibleResource pr : bean.resources) {\r
- Bytes.writeLE(result, byteIndex, pr.longValue());\r
- byteIndex += 8;\r
- }\r
- return result;\r
- }\r
- \r
- public Object deserialize(byte[] data) throws IOException {\r
- \r
- LogContentBean result = new LogContentBean();\r
-\r
- try {\r
- \r
- result.leaf = Bytes.read(data, 0) == 1 ? true : false;\r
- int byteIndex = 1;\r
- result.n = Bytes.readLE4(data, byteIndex);\r
- byteIndex += 4;\r
- int t = Bytes.readLE4(data, byteIndex);\r
- byteIndex += 4;\r
- \r
- result.stamps = new long[t];\r
- result.resources = new PossibleResource[t];\r
- \r
- for(int i=0;i<t;i++) {\r
- result.stamps[i] = Bytes.readLE8(data, byteIndex);\r
- byteIndex += 8;\r
- }\r
- \r
- for(int i=0;i<t;i++) {\r
- result.resources[i] = PossibleResource.read(ss, Bytes.readLE8(data, byteIndex));\r
- byteIndex += 8;\r
- }\r
- \r
- } catch (DatabaseException e) {\r
- \r
- e.printStackTrace();\r
- \r
- }\r
- \r
- return result;\r
- \r
- }\r
- \r
- };\r
- \r
- @Override\r
- public void accept(Visitor1 v, Object obj) {\r
- throw new UnsupportedOperationException();\r
- }\r
-\r
- @Override\r
- public <T> T accept(Visitor<T> v) {\r
- throw new UnsupportedOperationException();\r
- }\r
-\r
- @Override\r
- public boolean isInstance(Object obj) {\r
- throw new UnsupportedOperationException();\r
- }\r
-\r
- @Override\r
- public void readFrom(Binding srcBinding, Object src, Object dst)\r
- throws BindingException {\r
- throw new UnsupportedOperationException();\r
- }\r
-\r
- @Override\r
- public void assertInstaceIsValid(Object obj, Set<Object> validInstances)\r
- throws BindingException {\r
- throw new UnsupportedOperationException();\r
- }\r
-\r
- @Override\r
- public int deepHashValue(Object value,\r
- IdentityHashMap<Object, Object> hashedObjects)\r
- throws BindingException {\r
- throw new UnsupportedOperationException();\r
- }\r
-\r
- @Override\r
- public int deepCompare(Object o1, Object o2,\r
- Set<IdentityPair<Object, Object>> compareHistory)\r
- throws BindingException {\r
- throw new UnsupportedOperationException();\r
- }\r
-\r
- @Override\r
- protected void toString(Object value, BindingPrintContext ctx)\r
- throws BindingException {\r
- throw new UnsupportedOperationException();\r
- }\r
-\r
- @Override\r
- public int getComponentCount() {\r
- throw new UnsupportedOperationException();\r
- }\r
-\r
- @Override\r
- public Binding getComponentBinding(int index) {\r
- throw new UnsupportedOperationException();\r
- }\r
-\r
- @Override\r
- public Binding getComponentBinding(ChildReference path) {\r
- throw new UnsupportedOperationException();\r
- }\r
- \r
- @Override\r
- public Serializer serializer() throws RuntimeSerializerConstructionException {\r
- return serializer;\r
- }\r
- \r
-}\r
-\r
-final public class LogUtils implements LogContentManager {\r
-\r
- final public static boolean DEBUG = false;\r
- \r
- final public Binding CONTENT_BEAN_BINDING;\r
- final public DatatypeResource DATA;\r
- \r
- public LogUtils(ReadGraph graph) throws DatabaseException {\r
- try {\r
- CONTENT_BEAN_BINDING = new LogContentBinding(graph.getService(SerialisationSupport.class));\r
- DATA = DatatypeResource.getInstance(graph);\r
- } catch (RuntimeBindingConstructionException e) {\r
- Logger.defaultLogError(e);\r
- throw new DatabaseException(e);\r
- }\r
- }\r
- \r
- public Resource create(WriteGraph graph, int t, int stamp) throws DatabaseException {\r
- Layer0 L0 = Layer0.getInstance(graph);\r
- Resource tree = graph.newResource();\r
- graph.claim(tree, L0.InstanceOf, null, DATA.Log);\r
- Resource index = createIndexNode(graph, this, stamp, t); \r
- graph.claim(tree, DATA.Log_root, DATA.Log_root_Inverse, index);\r
- graph.claimLiteral(tree, DATA.Log_t, t, Bindings.INTEGER);\r
- Resource leaf = createLeafNode(graph, this, stamp, t);\r
- graph.claim(index, DATA.BTreeNode_Content, null, leaf);\r
- LogContentBean rContent = getContentBean(graph, index);\r
- rContent.n = 1;\r
- rContent.stamps[0] = stamp;\r
- rContent.resources[0].r = leaf;\r
- setContentBean(graph, index, rContent);\r
- return tree;\r
- }\r
-\r
- public void insert(WriteGraph graph, Resource T, int stamp, Resource v) throws DatabaseException {\r
-\r
- Resource r = getRoot(graph, T);\r
- int t = getDegree(graph, T);\r
- insertImpl(graph, this, T, r, t, stamp, v);\r
- \r
- }\r
-\r
- static class BatchContentManager implements LogContentManager {\r
-\r
- final private LogUtils bu;\r
- \r
- final Map<Resource, LogContentBean> beans = new HashMap<Resource, LogContentBean>();\r
- \r
- public BatchContentManager(LogUtils bu) {\r
- this.bu = bu;\r
- }\r
- \r
- @Override\r
- public LogContentBean getContentBean(ReadGraph graph, Resource node) throws DatabaseException {\r
- LogContentBean bean = beans.get(node);\r
- if(bean != null) return bean;\r
- return bu.getContentBean(graph, node);\r
- }\r
-\r
- @Override\r
- public void setContentBean(WriteGraph graph, Resource node, LogContentBean bean) throws DatabaseException {\r
- beans.put(node, bean);\r
- }\r
- \r
- public void apply(WriteGraph graph) throws DatabaseException {\r
- for(Map.Entry<Resource, LogContentBean> entry : beans.entrySet()) {\r
- bu.setContentBean(graph, entry.getKey(), entry.getValue());\r
- }\r
- }\r
- \r
- }\r
- \r
- public void insertAll(WriteGraph graph, Resource T, Collection<Pair<Integer, Resource>> values) throws DatabaseException {\r
-\r
- Resource r = getRoot(graph, T);\r
- int t = getDegree(graph, T);\r
- BatchContentManager cm = new BatchContentManager(this);\r
- for(Pair<Integer, Resource> entry : values) {\r
- insertImpl(graph, cm, T, r, t, entry.first, entry.second);\r
- }\r
- cm.apply(graph);\r
- \r
- }\r
- \r
- // Implementation\r
- private void insertImpl(WriteGraph graph, LogContentManager manager, Resource T, Resource r, int t, int k, Resource v) throws DatabaseException {\r
- \r
- int code = insertImpl2(graph, manager, 0, T, r, t, k, v); \r
- \r
- if(code > 0) {\r
- \r
- LogContentBean rContent = manager.getContentBean(graph, r);\r
- \r
- if(DEBUG) System.err.println("[insert index code=" + code + "]");\r
-\r
- Resource newRoot = createIndexNode(graph, manager, k, t);\r
- graph.claim(newRoot, DATA.Log_Node_Contains, null, r);\r
- setRoot(graph, T, newRoot);\r
- \r
- LogContentBean nContent = manager.getContentBean(graph, newRoot);\r
- nContent.stamps[0] = rContent.stamps[0];\r
- nContent.resources[0].r = r;\r
- nContent.n = 1;\r
- manager.setContentBean(graph, newRoot, nContent);\r
-\r
- Resource leaf = createLeaf(graph, manager, newRoot, code, k, t);\r
- \r
- LogContentBean lContent = manager.getContentBean(graph, leaf);\r
- lContent.n = 1;\r
- lContent.stamps[0] = k;\r
- lContent.resources[0].r = v;\r
-\r
- if(DEBUG) System.err.println("[insert " + k + "]: started a new branch");\r
-\r
- manager.setContentBean(graph, leaf, lContent);\r
-\r
- }\r
- \r
- }\r
-\r
- private int insertImpl2(WriteGraph graph, LogContentManager manager, int level, Resource T, Resource r, int t, int k, Resource v) throws DatabaseException {\r
-\r
- LogContentBean rContent = manager.getContentBean(graph, r);\r
-\r
- // Index\r
- if(!rContent.leaf) {\r
- \r
- Resource child = rContent.resources[rContent.n-1].r;\r
- int code = insertImpl2(graph, manager, level+1, T, child, t, k, v); \r
- \r
- if(code == 0) {\r
- \r
- // Value was inserted successfully\r
- return 0;\r
- \r
- } else {\r
-\r
- // The child was full\r
- if(rContent.n < t) {\r
- \r
- // We can create a new child\r
- Resource leaf = createLeaf(graph, manager, r, code-level-1, k, t);\r
- LogContentBean lContent = manager.getContentBean(graph, leaf);\r
- lContent.stamps[0] = k;\r
- lContent.resources[0].r = v;\r
- lContent.n = 1;\r
- manager.setContentBean(graph, leaf, lContent);\r
- \r
- if(DEBUG) System.err.println("[insert " + k + "]: created a fresh leaf");\r
- \r
- return 0;\r
- \r
- } else {\r
-\r
- // We are full, let the parent handle this\r
- return code;\r
- \r
- }\r
- \r
- \r
- }\r
- \r
- }\r
- \r
- // Leaf\r
- else {\r
-\r
- if(rContent.n < t) {\r
- \r
- if(DEBUG) System.err.println("[insert " + k + "]: fit into leaf at level " + level);\r
- \r
- // Append\r
- rContent.stamps[rContent.n] = k;\r
- rContent.resources[rContent.n].r = v;\r
- rContent.n++;\r
- manager.setContentBean(graph, r, rContent);\r
- return 0;\r
- \r
- } else {\r
-\r
- // This leaf is full\r
- return level;\r
- \r
- }\r
- \r
- }\r
- \r
- }\r
- \r
- private Resource createLeaf(WriteGraph graph, LogContentManager manager, Resource r, int code, int stamp, int t) throws DatabaseException {\r
- LogContentBean rContent = manager.getContentBean(graph, r);\r
- if(code == 0) {\r
- if(DEBUG) System.err.println("[insert leaf code=" + code + "]");\r
- Resource result = createLeafNode(graph, manager, stamp, t);\r
- graph.claim(r, DATA.Log_Node_Contains, null, result);\r
- rContent.stamps[rContent.n] = stamp;\r
- rContent.resources[rContent.n].r = result;\r
- rContent.n++;\r
- manager.setContentBean(graph, r, rContent);\r
- return result;\r
- } else {\r
- if(DEBUG) System.err.println("[insert index code=" + code + "]");\r
- Resource index = createIndexNode(graph, manager, stamp, t);\r
- graph.claim(r, DATA.Log_Node_Contains, null, index);\r
- rContent.stamps[rContent.n] = stamp;\r
- rContent.resources[rContent.n].r = index;\r
- rContent.n++;\r
- manager.setContentBean(graph, r, rContent);\r
- return createLeaf(graph, manager, index, code-1, stamp, t);\r
- }\r
- }\r
- \r
- private Resource createIndexNode(WriteGraph graph, LogContentManager manager, int stamp, int t) throws DatabaseException {\r
- Layer0 L0 = Layer0.getInstance(graph);\r
- Resource result = graph.newResource();\r
- graph.claim(result, L0.InstanceOf, null, DATA.Log_IndexNode);\r
- manager.setContentBean(graph, result, LogContentBean.create(t, stamp, false));\r
- return result;\r
- }\r
-\r
- private Resource createLeafNode(WriteGraph graph, LogContentManager manager, int stamp, int t) throws DatabaseException {\r
- Layer0 L0 = Layer0.getInstance(graph);\r
- Resource result = graph.newResource();\r
- graph.claim(result, L0.InstanceOf, null, DATA.Log_LeafNode);\r
- manager.setContentBean(graph, result, LogContentBean.create(t, stamp, true));\r
- return result;\r
- }\r
- \r
- private Resource getRoot(ReadGraph graph, Resource T) throws DatabaseException {\r
- return graph.getPossibleObject(T, DATA.Log_root);\r
- }\r
- \r
- private void setRoot(WriteGraph graph, Resource T, Resource r) throws DatabaseException {\r
- graph.deny(T, DATA.Log_root);\r
- graph.claim(T, DATA.Log_root, r);\r
- }\r
- \r
- public void setContentBean(WriteGraph graph, Resource node, LogContentBean bean) throws DatabaseException {\r
- graph.claimLiteral(node, DATA.Log_Node_content, DATA.Log_Content, bean, CONTENT_BEAN_BINDING );\r
- }\r
-\r
- private int getDegree(ReadGraph graph, Resource tree) throws DatabaseException {\r
- return graph.syncRequest(new RelatedValue<Integer>(tree, DATA.Log_t, Bindings.INTEGER), TransientCacheListener.<Integer>instance());\r
- }\r
- \r
- public LogContentBean getContentBean(ReadGraph graph, Resource node) throws DatabaseException {\r
- return graph.syncRequest(new RelatedValue<LogContentBean>(node, DATA.Log_Node_content, CONTENT_BEAN_BINDING), TransientCacheListener.<LogContentBean>instance());\r
- }\r
- \r
-}\r
+package org.simantics.datatypes.utils;
+
+import gnu.trove.map.hash.TObjectIntHashMap;
+
+import java.io.DataInput;
+import java.io.DataOutput;
+import java.io.IOException;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.IdentityHashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+import org.simantics.databoard.Bindings;
+import org.simantics.databoard.accessor.reference.ChildReference;
+import org.simantics.databoard.binding.Binding;
+import org.simantics.databoard.binding.error.BindingException;
+import org.simantics.databoard.binding.error.RuntimeBindingConstructionException;
+import org.simantics.databoard.binding.impl.BindingPrintContext;
+import org.simantics.databoard.serialization.RuntimeSerializerConstructionException;
+import org.simantics.databoard.serialization.Serializer;
+import org.simantics.databoard.util.IdentityPair;
+import org.simantics.datatypes.DatatypeResource;
+import org.simantics.db.ReadGraph;
+import org.simantics.db.Resource;
+import org.simantics.db.WriteGraph;
+import org.simantics.db.common.primitiverequest.RelatedValue;
+import org.simantics.db.common.procedure.adapter.TransientCacheListener;
+import org.simantics.db.common.utils.Logger;
+import org.simantics.db.exception.DatabaseException;
+import org.simantics.db.service.Bytes;
+import org.simantics.db.service.SerialisationSupport;
+import org.simantics.layer0.Layer0;
+import org.simantics.utils.datastructures.Pair;
+
+interface LogContentManager {
+
+ LogContentBean getContentBean(ReadGraph graph, Resource node) throws DatabaseException;
+ void setContentBean(WriteGraph graph, Resource node, LogContentBean bean) throws DatabaseException;
+
+}
+
+class LogContentBinding extends Binding {
+
+ private final SerialisationSupport ss;
+
+ public LogContentBinding(SerialisationSupport ss) {
+ this.ss = ss;
+ }
+
+ private final Serializer serializer = new Serializer() {
+
+ @Override
+ public void serialize(DataOutput out, TObjectIntHashMap<Object> identities, Object obj) throws IOException {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public void serialize(DataOutput out, Object obj) throws IOException {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public Object deserialize(DataInput in, List<Object> identities)
+ throws IOException {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public Object deserialize(DataInput in) throws IOException {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public void deserializeTo(DataInput in, List<Object> identities,
+ Object dst) throws IOException {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public void deserializeTo(DataInput in, Object dst) throws IOException {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public void skip(DataInput in, List<Object> identities)
+ throws IOException {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public void skip(DataInput in) throws IOException {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public Integer getConstantSize() {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public int getSize(Object obj, TObjectIntHashMap<Object> identities)
+ throws IOException {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public int getSize(Object obj) throws IOException {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public int getMinSize() {
+ throw new UnsupportedOperationException();
+ }
+
+ public byte[] serialize(Object obj) throws IOException {
+ LogContentBean bean = (LogContentBean)obj;
+ int bytes = 1 + 4 + 4 + 8 * bean.stamps.length + 8 * bean.resources.length;
+ byte[] result = new byte[bytes];
+ Bytes.write(result, 0, bean.leaf ? (byte)1 : (byte)0);
+ int byteIndex = 1;
+ Bytes.writeLE(result, byteIndex, bean.n);
+ byteIndex += 4;
+ Bytes.writeLE(result, byteIndex, bean.stamps.length);
+ byteIndex += 4;
+ for(long l : bean.stamps) {
+ Bytes.writeLE(result, byteIndex, l);
+ byteIndex += 8;
+ }
+ for(PossibleResource pr : bean.resources) {
+ Bytes.writeLE(result, byteIndex, pr.longValue());
+ byteIndex += 8;
+ }
+ return result;
+ }
+
+ public Object deserialize(byte[] data) throws IOException {
+
+ LogContentBean result = new LogContentBean();
+
+ try {
+
+ result.leaf = Bytes.read(data, 0) == 1 ? true : false;
+ int byteIndex = 1;
+ result.n = Bytes.readLE4(data, byteIndex);
+ byteIndex += 4;
+ int t = Bytes.readLE4(data, byteIndex);
+ byteIndex += 4;
+
+ result.stamps = new long[t];
+ result.resources = new PossibleResource[t];
+
+ for(int i=0;i<t;i++) {
+ result.stamps[i] = Bytes.readLE8(data, byteIndex);
+ byteIndex += 8;
+ }
+
+ for(int i=0;i<t;i++) {
+ result.resources[i] = PossibleResource.read(ss, Bytes.readLE8(data, byteIndex));
+ byteIndex += 8;
+ }
+
+ } catch (DatabaseException e) {
+
+ e.printStackTrace();
+
+ }
+
+ return result;
+
+ }
+
+ };
+
+ @Override
+ public void accept(Visitor1 v, Object obj) {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public <T> T accept(Visitor<T> v) {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public boolean isInstance(Object obj) {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public void readFrom(Binding srcBinding, Object src, Object dst)
+ throws BindingException {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public void assertInstaceIsValid(Object obj, Set<Object> validInstances)
+ throws BindingException {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public int deepHashValue(Object value,
+ IdentityHashMap<Object, Object> hashedObjects)
+ throws BindingException {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public int deepCompare(Object o1, Object o2,
+ Set<IdentityPair<Object, Object>> compareHistory)
+ throws BindingException {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ protected void toString(Object value, BindingPrintContext ctx)
+ throws BindingException {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public int getComponentCount() {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public Binding getComponentBinding(int index) {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public Binding getComponentBinding(ChildReference path) {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public Serializer serializer() throws RuntimeSerializerConstructionException {
+ return serializer;
+ }
+
+}
+
+final public class LogUtils implements LogContentManager {
+
+ final public static boolean DEBUG = false;
+
+ final public Binding CONTENT_BEAN_BINDING;
+ final public DatatypeResource DATA;
+
+ public LogUtils(ReadGraph graph) throws DatabaseException {
+ try {
+ CONTENT_BEAN_BINDING = new LogContentBinding(graph.getService(SerialisationSupport.class));
+ DATA = DatatypeResource.getInstance(graph);
+ } catch (RuntimeBindingConstructionException e) {
+ Logger.defaultLogError(e);
+ throw new DatabaseException(e);
+ }
+ }
+
+ public Resource create(WriteGraph graph, int t, int stamp) throws DatabaseException {
+ Layer0 L0 = Layer0.getInstance(graph);
+ Resource tree = graph.newResource();
+ graph.claim(tree, L0.InstanceOf, null, DATA.Log);
+ Resource index = createIndexNode(graph, this, stamp, t);
+ graph.claim(tree, DATA.Log_root, DATA.Log_root_Inverse, index);
+ graph.claimLiteral(tree, DATA.Log_t, t, Bindings.INTEGER);
+ Resource leaf = createLeafNode(graph, this, stamp, t);
+ graph.claim(index, DATA.BTreeNode_Content, null, leaf);
+ LogContentBean rContent = getContentBean(graph, index);
+ rContent.n = 1;
+ rContent.stamps[0] = stamp;
+ rContent.resources[0].r = leaf;
+ setContentBean(graph, index, rContent);
+ return tree;
+ }
+
+ public void insert(WriteGraph graph, Resource T, int stamp, Resource v) throws DatabaseException {
+
+ Resource r = getRoot(graph, T);
+ int t = getDegree(graph, T);
+ insertImpl(graph, this, T, r, t, stamp, v);
+
+ }
+
+ static class BatchContentManager implements LogContentManager {
+
+ final private LogUtils bu;
+
+ final Map<Resource, LogContentBean> beans = new HashMap<Resource, LogContentBean>();
+
+ public BatchContentManager(LogUtils bu) {
+ this.bu = bu;
+ }
+
+ @Override
+ public LogContentBean getContentBean(ReadGraph graph, Resource node) throws DatabaseException {
+ LogContentBean bean = beans.get(node);
+ if(bean != null) return bean;
+ return bu.getContentBean(graph, node);
+ }
+
+ @Override
+ public void setContentBean(WriteGraph graph, Resource node, LogContentBean bean) throws DatabaseException {
+ beans.put(node, bean);
+ }
+
+ public void apply(WriteGraph graph) throws DatabaseException {
+ for(Map.Entry<Resource, LogContentBean> entry : beans.entrySet()) {
+ bu.setContentBean(graph, entry.getKey(), entry.getValue());
+ }
+ }
+
+ }
+
+ public void insertAll(WriteGraph graph, Resource T, Collection<Pair<Integer, Resource>> values) throws DatabaseException {
+
+ Resource r = getRoot(graph, T);
+ int t = getDegree(graph, T);
+ BatchContentManager cm = new BatchContentManager(this);
+ for(Pair<Integer, Resource> entry : values) {
+ insertImpl(graph, cm, T, r, t, entry.first, entry.second);
+ }
+ cm.apply(graph);
+
+ }
+
+ // Implementation
+ private void insertImpl(WriteGraph graph, LogContentManager manager, Resource T, Resource r, int t, int k, Resource v) throws DatabaseException {
+
+ int code = insertImpl2(graph, manager, 0, T, r, t, k, v);
+
+ if(code > 0) {
+
+ LogContentBean rContent = manager.getContentBean(graph, r);
+
+ if(DEBUG) System.err.println("[insert index code=" + code + "]");
+
+ Resource newRoot = createIndexNode(graph, manager, k, t);
+ graph.claim(newRoot, DATA.Log_Node_Contains, null, r);
+ setRoot(graph, T, newRoot);
+
+ LogContentBean nContent = manager.getContentBean(graph, newRoot);
+ nContent.stamps[0] = rContent.stamps[0];
+ nContent.resources[0].r = r;
+ nContent.n = 1;
+ manager.setContentBean(graph, newRoot, nContent);
+
+ Resource leaf = createLeaf(graph, manager, newRoot, code, k, t);
+
+ LogContentBean lContent = manager.getContentBean(graph, leaf);
+ lContent.n = 1;
+ lContent.stamps[0] = k;
+ lContent.resources[0].r = v;
+
+ if(DEBUG) System.err.println("[insert " + k + "]: started a new branch");
+
+ manager.setContentBean(graph, leaf, lContent);
+
+ }
+
+ }
+
+ private int insertImpl2(WriteGraph graph, LogContentManager manager, int level, Resource T, Resource r, int t, int k, Resource v) throws DatabaseException {
+
+ LogContentBean rContent = manager.getContentBean(graph, r);
+
+ // Index
+ if(!rContent.leaf) {
+
+ Resource child = rContent.resources[rContent.n-1].r;
+ int code = insertImpl2(graph, manager, level+1, T, child, t, k, v);
+
+ if(code == 0) {
+
+ // Value was inserted successfully
+ return 0;
+
+ } else {
+
+ // The child was full
+ if(rContent.n < t) {
+
+ // We can create a new child
+ Resource leaf = createLeaf(graph, manager, r, code-level-1, k, t);
+ LogContentBean lContent = manager.getContentBean(graph, leaf);
+ lContent.stamps[0] = k;
+ lContent.resources[0].r = v;
+ lContent.n = 1;
+ manager.setContentBean(graph, leaf, lContent);
+
+ if(DEBUG) System.err.println("[insert " + k + "]: created a fresh leaf");
+
+ return 0;
+
+ } else {
+
+ // We are full, let the parent handle this
+ return code;
+
+ }
+
+
+ }
+
+ }
+
+ // Leaf
+ else {
+
+ if(rContent.n < t) {
+
+ if(DEBUG) System.err.println("[insert " + k + "]: fit into leaf at level " + level);
+
+ // Append
+ rContent.stamps[rContent.n] = k;
+ rContent.resources[rContent.n].r = v;
+ rContent.n++;
+ manager.setContentBean(graph, r, rContent);
+ return 0;
+
+ } else {
+
+ // This leaf is full
+ return level;
+
+ }
+
+ }
+
+ }
+
+ private Resource createLeaf(WriteGraph graph, LogContentManager manager, Resource r, int code, int stamp, int t) throws DatabaseException {
+ LogContentBean rContent = manager.getContentBean(graph, r);
+ if(code == 0) {
+ if(DEBUG) System.err.println("[insert leaf code=" + code + "]");
+ Resource result = createLeafNode(graph, manager, stamp, t);
+ graph.claim(r, DATA.Log_Node_Contains, null, result);
+ rContent.stamps[rContent.n] = stamp;
+ rContent.resources[rContent.n].r = result;
+ rContent.n++;
+ manager.setContentBean(graph, r, rContent);
+ return result;
+ } else {
+ if(DEBUG) System.err.println("[insert index code=" + code + "]");
+ Resource index = createIndexNode(graph, manager, stamp, t);
+ graph.claim(r, DATA.Log_Node_Contains, null, index);
+ rContent.stamps[rContent.n] = stamp;
+ rContent.resources[rContent.n].r = index;
+ rContent.n++;
+ manager.setContentBean(graph, r, rContent);
+ return createLeaf(graph, manager, index, code-1, stamp, t);
+ }
+ }
+
+ private Resource createIndexNode(WriteGraph graph, LogContentManager manager, int stamp, int t) throws DatabaseException {
+ Layer0 L0 = Layer0.getInstance(graph);
+ Resource result = graph.newResource();
+ graph.claim(result, L0.InstanceOf, null, DATA.Log_IndexNode);
+ manager.setContentBean(graph, result, LogContentBean.create(t, stamp, false));
+ return result;
+ }
+
+ private Resource createLeafNode(WriteGraph graph, LogContentManager manager, int stamp, int t) throws DatabaseException {
+ Layer0 L0 = Layer0.getInstance(graph);
+ Resource result = graph.newResource();
+ graph.claim(result, L0.InstanceOf, null, DATA.Log_LeafNode);
+ manager.setContentBean(graph, result, LogContentBean.create(t, stamp, true));
+ return result;
+ }
+
+ private Resource getRoot(ReadGraph graph, Resource T) throws DatabaseException {
+ return graph.getPossibleObject(T, DATA.Log_root);
+ }
+
+ private void setRoot(WriteGraph graph, Resource T, Resource r) throws DatabaseException {
+ graph.deny(T, DATA.Log_root);
+ graph.claim(T, DATA.Log_root, r);
+ }
+
+ public void setContentBean(WriteGraph graph, Resource node, LogContentBean bean) throws DatabaseException {
+ graph.claimLiteral(node, DATA.Log_Node_content, DATA.Log_Content, bean, CONTENT_BEAN_BINDING );
+ }
+
+ private int getDegree(ReadGraph graph, Resource tree) throws DatabaseException {
+ return graph.syncRequest(new RelatedValue<Integer>(tree, DATA.Log_t, Bindings.INTEGER), TransientCacheListener.<Integer>instance());
+ }
+
+ public LogContentBean getContentBean(ReadGraph graph, Resource node) throws DatabaseException {
+ return graph.syncRequest(new RelatedValue<LogContentBean>(node, DATA.Log_Node_content, CONTENT_BEAN_BINDING), TransientCacheListener.<LogContentBean>instance());
+ }
+
+}