]> gerrit.simantics Code Review - simantics/platform.git/blob - 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
1 package org.simantics.datatypes.utils;
2
3 import gnu.trove.map.hash.TObjectIntHashMap;
4
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;
12 import java.util.Map;
13 import java.util.Set;
14
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;
36
37 interface LogContentManager {
38         
39         LogContentBean getContentBean(ReadGraph graph, Resource node) throws DatabaseException;
40         void setContentBean(WriteGraph graph, Resource node, LogContentBean bean) throws DatabaseException;
41         
42 }
43
44 class LogContentBinding extends Binding {
45
46         private final SerialisationSupport ss;
47         
48         public LogContentBinding(SerialisationSupport ss) {
49                 this.ss = ss;
50         }
51         
52         private final Serializer serializer = new Serializer() {
53
54                 @Override
55                 public void serialize(DataOutput out, TObjectIntHashMap<Object> identities, Object obj) throws IOException {
56                         throw new UnsupportedOperationException();
57                 }
58
59                 @Override
60                 public void serialize(DataOutput out, Object obj) throws IOException {
61                         throw new UnsupportedOperationException();
62                 }
63
64                 @Override
65                 public Object deserialize(DataInput in, List<Object> identities)
66                                 throws IOException {
67                         throw new UnsupportedOperationException();
68                 }
69
70                 @Override
71                 public Object deserialize(DataInput in) throws IOException {
72                         throw new UnsupportedOperationException();
73                 }
74
75                 @Override
76                 public void deserializeTo(DataInput in, List<Object> identities,
77                                 Object dst) throws IOException {
78                         throw new UnsupportedOperationException();
79                 }
80
81                 @Override
82                 public void deserializeTo(DataInput in, Object dst) throws IOException {
83                         throw new UnsupportedOperationException();
84                 }
85
86                 @Override
87                 public void skip(DataInput in, List<Object> identities)
88                                 throws IOException {
89                         throw new UnsupportedOperationException();
90                 }
91
92                 @Override
93                 public void skip(DataInput in) throws IOException {
94                         throw new UnsupportedOperationException();
95                 }
96
97                 @Override
98                 public Integer getConstantSize() {
99                         throw new UnsupportedOperationException();
100                 }
101
102                 @Override
103                 public int getSize(Object obj, TObjectIntHashMap<Object> identities)
104                                 throws IOException {
105                         throw new UnsupportedOperationException();
106                 }
107
108                 @Override
109                 public int getSize(Object obj) throws IOException {
110                         throw new UnsupportedOperationException();
111                 }
112
113                 @Override
114                 public int getMinSize() {
115                         throw new UnsupportedOperationException();
116                 }
117                 
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);
123                         int byteIndex = 1;
124                         Bytes.writeLE(result, byteIndex, bean.n);
125                         byteIndex += 4;
126                         Bytes.writeLE(result, byteIndex, bean.stamps.length);
127                         byteIndex += 4;
128                         for(long l : bean.stamps) {
129                                 Bytes.writeLE(result, byteIndex, l);
130                                 byteIndex += 8;
131                         }
132                         for(PossibleResource pr : bean.resources) {
133                                 Bytes.writeLE(result, byteIndex, pr.longValue());
134                                 byteIndex += 8;
135                         }
136                         return result;
137                 }
138                 
139                 public Object deserialize(byte[] data) throws IOException {
140                         
141                         LogContentBean result = new LogContentBean();
142
143                         try {
144                         
145                                 result.leaf = Bytes.read(data, 0) == 1 ? true : false;
146                                 int byteIndex = 1;
147                                 result.n = Bytes.readLE4(data, byteIndex);
148                                 byteIndex += 4;
149                                 int t =  Bytes.readLE4(data, byteIndex);
150                                 byteIndex += 4;
151                                 
152                                 result.stamps = new long[t];
153                                 result.resources = new PossibleResource[t];
154                                 
155                                 for(int i=0;i<t;i++) {
156                                         result.stamps[i] = Bytes.readLE8(data, byteIndex);
157                                         byteIndex += 8;
158                                 }
159                                 
160                                 for(int i=0;i<t;i++) {
161                                         result.resources[i] = PossibleResource.read(ss, Bytes.readLE8(data, byteIndex));
162                                         byteIndex += 8;
163                                 }
164         
165                         } catch (DatabaseException e) {
166                         
167                                 e.printStackTrace();
168                                 
169                         }
170                         
171                         return result;
172                         
173                 }
174                 
175         };
176         
177         @Override
178         public void accept(Visitor1 v, Object obj) {
179                 throw new UnsupportedOperationException();
180         }
181
182         @Override
183         public <T> T accept(Visitor<T> v) {
184                 throw new UnsupportedOperationException();
185         }
186
187         @Override
188         public boolean isInstance(Object obj) {
189                 throw new UnsupportedOperationException();
190         }
191
192         @Override
193         public void readFrom(Binding srcBinding, Object src, Object dst)
194                         throws BindingException {
195                 throw new UnsupportedOperationException();
196         }
197
198         @Override
199         public void assertInstaceIsValid(Object obj, Set<Object> validInstances)
200                         throws BindingException {
201                 throw new UnsupportedOperationException();
202         }
203
204         @Override
205         public int deepHashValue(Object value,
206                         IdentityHashMap<Object, Object> hashedObjects)
207                         throws BindingException {
208                 throw new UnsupportedOperationException();
209         }
210
211         @Override
212         public int deepCompare(Object o1, Object o2,
213                         Set<IdentityPair<Object, Object>> compareHistory)
214                         throws BindingException {
215                 throw new UnsupportedOperationException();
216         }
217
218         @Override
219         protected void toString(Object value, BindingPrintContext ctx)
220                         throws BindingException {
221                 throw new UnsupportedOperationException();
222         }
223
224         @Override
225         public int getComponentCount() {
226                 throw new UnsupportedOperationException();
227         }
228
229         @Override
230         public Binding getComponentBinding(int index) {
231                 throw new UnsupportedOperationException();
232         }
233
234         @Override
235         public Binding getComponentBinding(ChildReference path) {
236                 throw new UnsupportedOperationException();
237         }
238         
239         @Override
240         public Serializer serializer() throws RuntimeSerializerConstructionException {
241                 return serializer;
242         }
243         
244 }
245
246 final public class LogUtils implements LogContentManager {
247
248         final public static boolean DEBUG = false;
249         
250         final public Binding CONTENT_BEAN_BINDING;
251         final public DatatypeResource DATA;
252         
253         public LogUtils(ReadGraph graph) throws DatabaseException {
254                 try {
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);
260                 }
261         }
262         
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);
273                 rContent.n = 1;
274                 rContent.stamps[0] = stamp;
275                 rContent.resources[0].r = leaf;
276                 setContentBean(graph, index, rContent);
277                 return tree;
278         }
279
280         public void insert(WriteGraph graph, Resource T, int stamp, Resource v) throws DatabaseException {
281
282                 Resource r = getRoot(graph, T);
283                 int t = getDegree(graph, T);
284                 insertImpl(graph, this, T, r, t, stamp, v);
285                 
286         }
287
288         static class BatchContentManager implements LogContentManager {
289
290                 final private LogUtils bu;
291                 
292                 final Map<Resource, LogContentBean> beans = new HashMap<Resource, LogContentBean>();
293                 
294                 public BatchContentManager(LogUtils bu) {
295                         this.bu = bu;
296                 }
297                 
298                 @Override
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);
303                 }
304
305                 @Override
306                 public void setContentBean(WriteGraph graph, Resource node, LogContentBean bean) throws DatabaseException {
307                         beans.put(node, bean);
308                 }
309                 
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());
313                         }
314                 }
315                 
316         }
317         
318         public void insertAll(WriteGraph graph, Resource T, Collection<Pair<Integer, Resource>> values) throws DatabaseException {
319
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);
325                 }
326                 cm.apply(graph);
327                 
328         }
329         
330         // Implementation
331         private void insertImpl(WriteGraph graph, LogContentManager manager, Resource T, Resource r, int t, int k, Resource v) throws DatabaseException {
332                 
333                 int code = insertImpl2(graph, manager, 0, T, r, t, k, v); 
334                 
335                 if(code > 0) {
336                         
337                         LogContentBean rContent = manager.getContentBean(graph, r);
338                         
339                         if(DEBUG) System.err.println("[insert index code=" + code + "]");
340
341                         Resource newRoot = createIndexNode(graph, manager, k, t);
342                         graph.claim(newRoot, DATA.Log_Node_Contains, null, r);
343                         setRoot(graph, T, newRoot);
344                         
345                         LogContentBean nContent = manager.getContentBean(graph, newRoot);
346                         nContent.stamps[0] = rContent.stamps[0];
347                         nContent.resources[0].r = r;
348                         nContent.n = 1;
349                         manager.setContentBean(graph, newRoot, nContent);
350
351                         Resource leaf = createLeaf(graph, manager, newRoot, code, k, t);
352                         
353                         LogContentBean lContent = manager.getContentBean(graph, leaf);
354                         lContent.n = 1;
355                         lContent.stamps[0] = k;
356                         lContent.resources[0].r = v;
357
358                         if(DEBUG) System.err.println("[insert " + k + "]: started a new branch");
359
360                         manager.setContentBean(graph, leaf, lContent);
361
362                 }
363                 
364         }
365
366         private int insertImpl2(WriteGraph graph, LogContentManager manager, int level, Resource T, Resource r, int t, int k, Resource v) throws DatabaseException {
367
368                 LogContentBean rContent = manager.getContentBean(graph, r);
369
370                 // Index
371                 if(!rContent.leaf) {
372                         
373                         Resource child = rContent.resources[rContent.n-1].r;
374                         int code = insertImpl2(graph, manager, level+1, T, child, t, k, v); 
375                         
376                         if(code == 0) {
377                                 
378                                 // Value was inserted successfully
379                                 return 0;
380                                 
381                         } else {
382
383                                 // The child was full
384                                 if(rContent.n < t) {
385                                         
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;
391                                         lContent.n = 1;
392                                         manager.setContentBean(graph, leaf, lContent);
393                                         
394                                         if(DEBUG) System.err.println("[insert " + k + "]: created a fresh leaf");
395                                         
396                                         return 0;
397                                         
398                                 } else {
399
400                                         // We are full, let the parent handle this
401                                         return code;
402                                         
403                                 }
404                                 
405                                 
406                         }
407                         
408                 }
409                 
410                 // Leaf
411                 else {
412
413                         if(rContent.n < t) {
414                                 
415                                 if(DEBUG) System.err.println("[insert " + k + "]: fit into leaf at level " + level);
416                                 
417                                 // Append
418                                 rContent.stamps[rContent.n] = k;
419                                 rContent.resources[rContent.n].r = v;
420                                 rContent.n++;
421                                 manager.setContentBean(graph, r, rContent);
422                                 return 0;
423                                 
424                         } else {
425
426                                 // This leaf is full
427                                 return level;
428                                 
429                         }
430                         
431                 }
432                 
433         }
434         
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);
437                 if(code == 0) {
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;
443                         rContent.n++;
444                         manager.setContentBean(graph, r, rContent);
445                         return result;
446                 } else {
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;
452                         rContent.n++;
453                         manager.setContentBean(graph, r, rContent);
454                         return createLeaf(graph, manager, index, code-1, stamp, t);
455                 }
456         }
457         
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));
463                 return result;
464         }
465
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));
471                 return result;
472         }
473         
474         private Resource getRoot(ReadGraph graph, Resource T) throws DatabaseException {
475                 return graph.getPossibleObject(T, DATA.Log_root);
476         }
477         
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);
481         }
482         
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 );
485         }
486
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());
489         }
490         
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());
493         }
494         
495 }