]> gerrit.simantics Code Review - simantics/platform.git/blobdiff - bundles/org.simantics.datatypes/src/org/simantics/datatypes/utils/LogUtils.java
Fixed all line endings of the repository
[simantics/platform.git] / bundles / org.simantics.datatypes / src / org / simantics / datatypes / utils / LogUtils.java
index 3950518c191e685775a99f532d281c364446c9cb..dbe62fc80b38fe284b130a29a345f3ee1f47a910 100644 (file)
-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());
+       }
+       
+}