1 package org.simantics.datatypes.utils;
3 import gnu.trove.map.hash.TObjectIntHashMap;
5 import java.io.DataInput;
6 import java.io.DataOutput;
7 import java.io.IOException;
8 import java.util.Collection;
9 import java.util.HashMap;
10 import java.util.IdentityHashMap;
11 import java.util.List;
15 import org.simantics.databoard.Bindings;
16 import org.simantics.databoard.accessor.reference.ChildReference;
17 import org.simantics.databoard.binding.Binding;
18 import org.simantics.databoard.binding.error.BindingException;
19 import org.simantics.databoard.binding.error.RuntimeBindingConstructionException;
20 import org.simantics.databoard.binding.impl.BindingPrintContext;
21 import org.simantics.databoard.serialization.RuntimeSerializerConstructionException;
22 import org.simantics.databoard.serialization.Serializer;
23 import org.simantics.databoard.util.IdentityPair;
24 import org.simantics.datatypes.DatatypeResource;
25 import org.simantics.db.ReadGraph;
26 import org.simantics.db.Resource;
27 import org.simantics.db.WriteGraph;
28 import org.simantics.db.common.primitiverequest.RelatedValue;
29 import org.simantics.db.common.procedure.adapter.TransientCacheListener;
30 import org.simantics.db.common.utils.Logger;
31 import org.simantics.db.exception.DatabaseException;
32 import org.simantics.db.service.Bytes;
33 import org.simantics.db.service.SerialisationSupport;
34 import org.simantics.layer0.Layer0;
35 import org.simantics.utils.datastructures.Pair;
37 interface LogContentManager {
39 LogContentBean getContentBean(ReadGraph graph, Resource node) throws DatabaseException;
40 void setContentBean(WriteGraph graph, Resource node, LogContentBean bean) throws DatabaseException;
44 class LogContentBinding extends Binding {
46 private final SerialisationSupport ss;
48 public LogContentBinding(SerialisationSupport ss) {
52 private final Serializer serializer = new Serializer() {
55 public void serialize(DataOutput out, TObjectIntHashMap<Object> identities, Object obj) throws IOException {
56 throw new UnsupportedOperationException();
60 public void serialize(DataOutput out, Object obj) throws IOException {
61 throw new UnsupportedOperationException();
65 public Object deserialize(DataInput in, List<Object> identities)
67 throw new UnsupportedOperationException();
71 public Object deserialize(DataInput in) throws IOException {
72 throw new UnsupportedOperationException();
76 public void deserializeTo(DataInput in, List<Object> identities,
77 Object dst) throws IOException {
78 throw new UnsupportedOperationException();
82 public void deserializeTo(DataInput in, Object dst) throws IOException {
83 throw new UnsupportedOperationException();
87 public void skip(DataInput in, List<Object> identities)
89 throw new UnsupportedOperationException();
93 public void skip(DataInput in) throws IOException {
94 throw new UnsupportedOperationException();
98 public Integer getConstantSize() {
99 throw new UnsupportedOperationException();
103 public int getSize(Object obj, TObjectIntHashMap<Object> identities)
105 throw new UnsupportedOperationException();
109 public int getSize(Object obj) throws IOException {
110 throw new UnsupportedOperationException();
114 public int getMinSize() {
115 throw new UnsupportedOperationException();
118 public byte[] serialize(Object obj) throws IOException {
119 LogContentBean bean = (LogContentBean)obj;
120 int bytes = 1 + 4 + 4 + 8 * bean.stamps.length + 8 * bean.resources.length;
121 byte[] result = new byte[bytes];
122 Bytes.write(result, 0, bean.leaf ? (byte)1 : (byte)0);
124 Bytes.writeLE(result, byteIndex, bean.n);
126 Bytes.writeLE(result, byteIndex, bean.stamps.length);
128 for(long l : bean.stamps) {
129 Bytes.writeLE(result, byteIndex, l);
132 for(PossibleResource pr : bean.resources) {
133 Bytes.writeLE(result, byteIndex, pr.longValue());
139 public Object deserialize(byte[] data) throws IOException {
141 LogContentBean result = new LogContentBean();
145 result.leaf = Bytes.read(data, 0) == 1 ? true : false;
147 result.n = Bytes.readLE4(data, byteIndex);
149 int t = Bytes.readLE4(data, byteIndex);
152 result.stamps = new long[t];
153 result.resources = new PossibleResource[t];
155 for(int i=0;i<t;i++) {
156 result.stamps[i] = Bytes.readLE8(data, byteIndex);
160 for(int i=0;i<t;i++) {
161 result.resources[i] = PossibleResource.read(ss, Bytes.readLE8(data, byteIndex));
165 } catch (DatabaseException e) {
178 public void accept(Visitor1 v, Object obj) {
179 throw new UnsupportedOperationException();
183 public <T> T accept(Visitor<T> v) {
184 throw new UnsupportedOperationException();
188 public boolean isInstance(Object obj) {
189 throw new UnsupportedOperationException();
193 public void readFrom(Binding srcBinding, Object src, Object dst)
194 throws BindingException {
195 throw new UnsupportedOperationException();
199 public void assertInstaceIsValid(Object obj, Set<Object> validInstances)
200 throws BindingException {
201 throw new UnsupportedOperationException();
205 public int deepHashValue(Object value,
206 IdentityHashMap<Object, Object> hashedObjects)
207 throws BindingException {
208 throw new UnsupportedOperationException();
212 public int deepCompare(Object o1, Object o2,
213 Set<IdentityPair<Object, Object>> compareHistory)
214 throws BindingException {
215 throw new UnsupportedOperationException();
219 protected void toString(Object value, BindingPrintContext ctx)
220 throws BindingException {
221 throw new UnsupportedOperationException();
225 public int getComponentCount() {
226 throw new UnsupportedOperationException();
230 public Binding getComponentBinding(int index) {
231 throw new UnsupportedOperationException();
235 public Binding getComponentBinding(ChildReference path) {
236 throw new UnsupportedOperationException();
240 public Serializer serializer() throws RuntimeSerializerConstructionException {
246 final public class LogUtils implements LogContentManager {
248 final public static boolean DEBUG = false;
250 final public Binding CONTENT_BEAN_BINDING;
251 final public DatatypeResource DATA;
253 public LogUtils(ReadGraph graph) throws DatabaseException {
255 CONTENT_BEAN_BINDING = new LogContentBinding(graph.getService(SerialisationSupport.class));
256 DATA = DatatypeResource.getInstance(graph);
257 } catch (RuntimeBindingConstructionException e) {
258 Logger.defaultLogError(e);
259 throw new DatabaseException(e);
263 public Resource create(WriteGraph graph, int t, int stamp) throws DatabaseException {
264 Layer0 L0 = Layer0.getInstance(graph);
265 Resource tree = graph.newResource();
266 graph.claim(tree, L0.InstanceOf, null, DATA.Log);
267 Resource index = createIndexNode(graph, this, stamp, t);
268 graph.claim(tree, DATA.Log_root, DATA.Log_root_Inverse, index);
269 graph.claimLiteral(tree, DATA.Log_t, t, Bindings.INTEGER);
270 Resource leaf = createLeafNode(graph, this, stamp, t);
271 graph.claim(index, DATA.BTreeNode_Content, null, leaf);
272 LogContentBean rContent = getContentBean(graph, index);
274 rContent.stamps[0] = stamp;
275 rContent.resources[0].r = leaf;
276 setContentBean(graph, index, rContent);
280 public void insert(WriteGraph graph, Resource T, int stamp, Resource v) throws DatabaseException {
282 Resource r = getRoot(graph, T);
283 int t = getDegree(graph, T);
284 insertImpl(graph, this, T, r, t, stamp, v);
288 static class BatchContentManager implements LogContentManager {
290 final private LogUtils bu;
292 final Map<Resource, LogContentBean> beans = new HashMap<Resource, LogContentBean>();
294 public BatchContentManager(LogUtils bu) {
299 public LogContentBean getContentBean(ReadGraph graph, Resource node) throws DatabaseException {
300 LogContentBean bean = beans.get(node);
301 if(bean != null) return bean;
302 return bu.getContentBean(graph, node);
306 public void setContentBean(WriteGraph graph, Resource node, LogContentBean bean) throws DatabaseException {
307 beans.put(node, bean);
310 public void apply(WriteGraph graph) throws DatabaseException {
311 for(Map.Entry<Resource, LogContentBean> entry : beans.entrySet()) {
312 bu.setContentBean(graph, entry.getKey(), entry.getValue());
318 public void insertAll(WriteGraph graph, Resource T, Collection<Pair<Integer, Resource>> values) throws DatabaseException {
320 Resource r = getRoot(graph, T);
321 int t = getDegree(graph, T);
322 BatchContentManager cm = new BatchContentManager(this);
323 for(Pair<Integer, Resource> entry : values) {
324 insertImpl(graph, cm, T, r, t, entry.first, entry.second);
331 private void insertImpl(WriteGraph graph, LogContentManager manager, Resource T, Resource r, int t, int k, Resource v) throws DatabaseException {
333 int code = insertImpl2(graph, manager, 0, T, r, t, k, v);
337 LogContentBean rContent = manager.getContentBean(graph, r);
339 if(DEBUG) System.err.println("[insert index code=" + code + "]");
341 Resource newRoot = createIndexNode(graph, manager, k, t);
342 graph.claim(newRoot, DATA.Log_Node_Contains, null, r);
343 setRoot(graph, T, newRoot);
345 LogContentBean nContent = manager.getContentBean(graph, newRoot);
346 nContent.stamps[0] = rContent.stamps[0];
347 nContent.resources[0].r = r;
349 manager.setContentBean(graph, newRoot, nContent);
351 Resource leaf = createLeaf(graph, manager, newRoot, code, k, t);
353 LogContentBean lContent = manager.getContentBean(graph, leaf);
355 lContent.stamps[0] = k;
356 lContent.resources[0].r = v;
358 if(DEBUG) System.err.println("[insert " + k + "]: started a new branch");
360 manager.setContentBean(graph, leaf, lContent);
366 private int insertImpl2(WriteGraph graph, LogContentManager manager, int level, Resource T, Resource r, int t, int k, Resource v) throws DatabaseException {
368 LogContentBean rContent = manager.getContentBean(graph, r);
373 Resource child = rContent.resources[rContent.n-1].r;
374 int code = insertImpl2(graph, manager, level+1, T, child, t, k, v);
378 // Value was inserted successfully
383 // The child was full
386 // We can create a new child
387 Resource leaf = createLeaf(graph, manager, r, code-level-1, k, t);
388 LogContentBean lContent = manager.getContentBean(graph, leaf);
389 lContent.stamps[0] = k;
390 lContent.resources[0].r = v;
392 manager.setContentBean(graph, leaf, lContent);
394 if(DEBUG) System.err.println("[insert " + k + "]: created a fresh leaf");
400 // We are full, let the parent handle this
415 if(DEBUG) System.err.println("[insert " + k + "]: fit into leaf at level " + level);
418 rContent.stamps[rContent.n] = k;
419 rContent.resources[rContent.n].r = v;
421 manager.setContentBean(graph, r, rContent);
435 private Resource createLeaf(WriteGraph graph, LogContentManager manager, Resource r, int code, int stamp, int t) throws DatabaseException {
436 LogContentBean rContent = manager.getContentBean(graph, r);
438 if(DEBUG) System.err.println("[insert leaf code=" + code + "]");
439 Resource result = createLeafNode(graph, manager, stamp, t);
440 graph.claim(r, DATA.Log_Node_Contains, null, result);
441 rContent.stamps[rContent.n] = stamp;
442 rContent.resources[rContent.n].r = result;
444 manager.setContentBean(graph, r, rContent);
447 if(DEBUG) System.err.println("[insert index code=" + code + "]");
448 Resource index = createIndexNode(graph, manager, stamp, t);
449 graph.claim(r, DATA.Log_Node_Contains, null, index);
450 rContent.stamps[rContent.n] = stamp;
451 rContent.resources[rContent.n].r = index;
453 manager.setContentBean(graph, r, rContent);
454 return createLeaf(graph, manager, index, code-1, stamp, t);
458 private Resource createIndexNode(WriteGraph graph, LogContentManager manager, int stamp, int t) throws DatabaseException {
459 Layer0 L0 = Layer0.getInstance(graph);
460 Resource result = graph.newResource();
461 graph.claim(result, L0.InstanceOf, null, DATA.Log_IndexNode);
462 manager.setContentBean(graph, result, LogContentBean.create(t, stamp, false));
466 private Resource createLeafNode(WriteGraph graph, LogContentManager manager, int stamp, int t) throws DatabaseException {
467 Layer0 L0 = Layer0.getInstance(graph);
468 Resource result = graph.newResource();
469 graph.claim(result, L0.InstanceOf, null, DATA.Log_LeafNode);
470 manager.setContentBean(graph, result, LogContentBean.create(t, stamp, true));
474 private Resource getRoot(ReadGraph graph, Resource T) throws DatabaseException {
475 return graph.getPossibleObject(T, DATA.Log_root);
478 private void setRoot(WriteGraph graph, Resource T, Resource r) throws DatabaseException {
479 graph.deny(T, DATA.Log_root);
480 graph.claim(T, DATA.Log_root, r);
483 public void setContentBean(WriteGraph graph, Resource node, LogContentBean bean) throws DatabaseException {
484 graph.claimLiteral(node, DATA.Log_Node_content, DATA.Log_Content, bean, CONTENT_BEAN_BINDING );
487 private int getDegree(ReadGraph graph, Resource tree) throws DatabaseException {
488 return graph.syncRequest(new RelatedValue<Integer>(tree, DATA.Log_t, Bindings.INTEGER), TransientCacheListener.<Integer>instance());
491 public LogContentBean getContentBean(ReadGraph graph, Resource node) throws DatabaseException {
492 return graph.syncRequest(new RelatedValue<LogContentBean>(node, DATA.Log_Node_content, CONTENT_BEAN_BINDING), TransientCacheListener.<LogContentBean>instance());