Removed contact application support prints
[simantics/platform.git] / bundles / org.simantics.db.procore / src / org / simantics / db / procore / cluster / ClusterChangeSet.java
1 /*******************************************************************************
2  * Copyright (c) 2007, 2010 Association for Decentralized Information Management
3  * in Industry THTH ry.
4  * All rights reserved. This program and the accompanying materials
5  * are made available under the terms of the Eclipse Public License v1.0
6  * which accompanies this distribution, and is available at
7  * http://www.eclipse.org/legal/epl-v10.html
8  *
9  * Contributors:
10  *     VTT Technical Research Centre of Finland - initial API and implementation
11  *******************************************************************************/
12 package org.simantics.db.procore.cluster;
13
14 import java.util.Vector;
15
16 import org.simantics.db.exception.InternalException;
17 import org.simantics.db.exception.RuntimeDatabaseException;
18 import org.simantics.db.procore.cluster.CCSParser.ReferenceType;
19 import org.simantics.db.procore.cluster.CCSParser.StmEnum;
20 import org.simantics.db.service.ClusterUID;
21
22 public class ClusterChangeSet implements ClusterChangeSetI {
23     static interface IteratorI {
24     }
25     static private final boolean DEBUG = false;
26     static private final int HEADER_SIZE = 20;
27     private final int version;
28     private final ClusterUID clusterUID;
29     private final byte[] bytes;
30
31     public static ClusterChangeSetI create(byte[] rawData, String compressionCodec)
32     throws InternalException {
33         
34         // TODO: Find maybe a better way to do this
35         byte[] bytes;
36         if (compressionCodec.equals("LZ4")) {
37             LZ4.DecompressStruct data = LZ4.decompress(rawData);
38             bytes = data.bytes;
39         } else if (compressionCodec.equals("FLZ")) {
40             FastLZ.DecompressStruct data = FastLZ.decompress(rawData);
41             bytes = data.bytes;
42         } else {
43             throw new RuntimeDatabaseException("No compressionCodec given!");
44         }
45         return new ClusterChangeSet(bytes);
46     }
47     @Override
48     public String toString() {
49         return "cid=" + clusterUID + " len=" + bytes.length; 
50     }
51     private ClusterChangeSet(byte[] abytes) {
52         this.bytes = abytes;
53         if (bytes.length < HEADER_SIZE + 4)
54             throw new RuntimeDatabaseException("Cluster change must contain header and size. length=" + bytes.length);
55         version = CCSParser.getInt(bytes, 0);
56         if (version <1 || version > 2)
57             throw new RuntimeDatabaseException("Unsupported cluster change set version=" + version);
58         clusterUID = ClusterUID.make(abytes, 4);
59         if (ClusterUID.Null.equals(clusterUID))
60             throw new RuntimeDatabaseException("Cluster uid can not be null.");
61         if (DEBUG)
62             System.out.println("DEBUG: Cluster uid=" + clusterUID);
63         int p = HEADER_SIZE;
64         int size = CCSParser.getInt(bytes, p);
65         if (2 == version) {
66             System.out.println("Cluster change set version=2 is not supported. skipping...");
67             return;
68         }
69         for (; size > 0; size = CCSParser.getInt(bytes, p)) {
70             mBlocks.push_back(new ClusterChangeSetBlock(p+=4, size, bytes));
71             p += size; // skip block data
72         } 
73     }
74     @Override
75     public ClusterUID getClusterUID() {
76         return clusterUID;
77     }
78     private boolean updateRequired() {
79         return false;
80     }
81     private void update() {
82     }
83     @Override
84     public void getNextOperation(Operation ar) {
85         Iterator pIterator = null;
86         if (null == ar.iterator) {
87             if (updateRequired())
88                 this.update();
89             int N = mBlocks.size();
90             if (0 ==  N) {
91                 ar.type = OperationEnum.EndOf;
92                 return;
93             }
94             pIterator = new Iterator(N-1);
95             ar.iterator = pIterator;
96         } else
97             pIterator = (Iterator)ar.iterator;
98         if (pIterator.block > pIterator.lastBlock) {
99             ar.type = OperationEnum.EndOf;
100             ar.iterator = null;
101             return;
102         } else if (pIterator.offset >= mBlocks.get(pIterator.block).size) {
103             ++pIterator.block;
104             pIterator.foreignTable.init();
105             pIterator.offset = 0;
106             if (pIterator.block > pIterator.lastBlock) {
107                 ar.type = OperationEnum.EndOf;
108                 ar.iterator = null;
109                 return;
110             }
111         }
112         if (pIterator.offset >= mBlocks.get(pIterator.block).size) {
113             ++pIterator.block;
114             pIterator.foreignTable.init();
115             pIterator.offset = 0;
116             if (pIterator.block > pIterator.lastBlock) {
117                 ar.type = OperationEnum.EndOf;
118                 ar.iterator = null;
119                 return;
120             }
121         }
122         ClusterChangeSetBlock r = mBlocks.get(pIterator.block);
123         int inc = next(ar, pIterator, r.bytes, r.offset + pIterator.offset, r.offset + r.size);
124         if (inc <= 0) {
125             if (inc < 0)
126                 System.out.println("Iterarto offset increment is negative!");
127             ar.type = OperationEnum.EndOf;
128             ar.iterator = null;
129         } else
130             pIterator.offset += inc;
131     }
132     private int next(Operation ar, Iterator pIterator, byte[] bytes, int ab, int ae) {
133         CCSParser.Args args = new CCSParser.Args(clusterUID, pIterator.foreignTable, ar);
134         final int pe = ae;
135         final int pb = ab;
136         int p = pb;
137         if (p < pe) {
138             if (DEBUG)
139                 System.out.println("CCS.next offset=" + p);
140             short ri = 0; // resource index
141             short kraa = (short)(bytes[p] & 0xFF); 
142             switch (kraa) {
143                 case 0: case 1: case 2: case 3:
144                     //0x000000?? add - ri12 + pi14 + oi14 = 40 / 8 = 5
145                     p = CCSParser.parseStm(StmEnum.Add, args, bytes, p, 2, ReferenceType.Local, ReferenceType.Local);
146                     break;
147                 case 4: case 5: case 6: case 7:
148                     //0x000001?? rem - ri12 + pi14 + oi14 = 40 / 8 = 5
149                     p = CCSParser.parseStm(StmEnum.Remove, args, bytes, p, 2, ReferenceType.Local, ReferenceType.Local);
150                     break;
151                 case 8: case 9: case 10: case 11:
152                     //0x000010?? add - ri12 + pi14 + oc62 = 88 / 8 = 11
153                     p = CCSParser.parseStm(StmEnum.Add, args, bytes, p, 2, ReferenceType.Local, ReferenceType.ForeignLong);
154                     break;
155                 case 12: case 13: case 14: case 15:
156                     //0x000011?? rem - ri12 + pi14 + oc62 = 88 / 8 = 11
157                     p = CCSParser.parseStm(StmEnum.Remove, args, bytes, p, 2, ReferenceType.Local, ReferenceType.ForeignLong);
158                     break;
159                 case 16: case 17: case 18: case 19:
160                     //0x000100?? add - ri12 + pc62 + oi14 = 88 / 8 = 11
161                     p = CCSParser.parseStm(StmEnum.Add, args, bytes, p, 2, ReferenceType.ForeignLong, ReferenceType.Local);
162                     break;
163                 case 20: case 21: case 22: case 23:
164                     //0x000101?? rem - ri12 + pc62 + oi14 = 88 / 8 = 11
165                     p = CCSParser.parseStm(StmEnum.Remove, args, bytes, p, 2, ReferenceType.ForeignLong, ReferenceType.Local);
166                     break;
167                 case 24: case 25: case 26: case 27:
168                     //0x000110?? add - ri12 + pc62 + oc62 = 136 / 8 = 17
169                     p = CCSParser.parseStm(StmEnum.Add, args, bytes, p, 2, ReferenceType.ForeignLong, ReferenceType.ForeignLong);
170                     break;
171                 case 28: case 29: case 30: case 31:
172                     //0x000111?? rem - ri12 + pc62 + oc62 = 136 / 8 = 17
173                     p = CCSParser.parseStm(StmEnum.Remove, args, bytes, p, 2, ReferenceType.ForeignLong, ReferenceType.ForeignLong);
174                     break;
175                 case 32: case 33: case 34: case 35:
176                 case 36: case 37: case 38: case 39:
177                 case 40: case 41: case 42: case 43:
178                 case 44: case 45: case 46: case 47: case 48:
179                     //0x0010???? rem - ri10 + pr08 + oi14 = 32 / 8 = 4
180                     p = CCSParser.parseStm(StmEnum.Remove, args, bytes, p, 4, ReferenceType.ForeignShort, ReferenceType.Local);
181                     break;
182                 case 49:
183                     //0x00110001 rem - ri14 + pi14 + pr08 + pad4 = 40 / 8 = 5
184                     p = CCSParser.parseStm(StmEnum.Remove, args, bytes, p, 0, ReferenceType.Local, ReferenceType.ForeignShort);
185                     break;
186                 case 50:
187                     //0x00110010 rem - ri14 + pr08 + oc62 + pad4 = 88 / 8 = 11
188                     p = CCSParser.parseStm(StmEnum.Remove, args, bytes, p, 0, ReferenceType.ForeignShort, ReferenceType.ForeignLong);
189                     break;
190                 case 51:
191                     //0x00110011 rem - ri14 + pc62 + or08 + pad4 = 88 / 8 = 11
192                     p = CCSParser.parseStm(StmEnum.Remove, args, bytes, p, 0, ReferenceType.ForeignLong, ReferenceType.ForeignShort);
193                     break;
194                 case 52: //0x00110100 cre - ri14 + pad2 = 16 / 8 = 2
195                     ri = CCSParser.getShort(bytes, p+1);
196                     if (DEBUG)
197                         System.out.println("Creating resource r=" + ri + " rc=" + clusterUID);
198                     args.createResource(ri);
199                     p += 3;
200                     break;
201                 case 53: {
202                     //0x00110101 set - ri14 + sz18 = 32 / 8 = 4 + sz * bytes
203                     int t = CCSParser.getInt(bytes, p + 1);
204                     ri = (short)(t & 0x3FFF); 
205                     int s = t >>> 14;
206                     args.setValue(ri, bytes, p + 5, s);
207                     p += 5 + s;
208                     break; }
209                 case 54: //0x00110110 del - ri14 + pad2 = 16 / 8 = 2
210                     ri = CCSParser.getShort(bytes, p+1);
211                     args.deleteValue(ri);
212                     p += 3;
213                     break;
214                 case 55: {
215                     //0x00110111 mod - ri14 + of58 + sz16  = 88 / 8 = 11 + sz * bytes
216                     ri = CCSParser.getShort(bytes, p+1);
217                     ri &= (1<<14)-1; // mask top 2 bits
218                     long vo = CCSParser.getLongN(bytes, p+3, 7); // get low 7 bytes
219                     vo |= (long)(bytes[p+2] & 0xC0) << (56-6); // add the top 2 bits
220                     p += 10;
221                     int vsize = CCSParser.getShort(bytes, p);
222                     if (vsize < 0)
223                         vsize += 65536;
224                     p += 2;
225                     if (DEBUG)
226                         System.out.println("Modifying value r=" + ri + " rc=" + args.clusterUID +
227                         " value offset=" + vo + " size=" + vsize);
228                     if (pe - p < vsize)
229                         throw new RuntimeException("Illegal size=" + vsize + " limit=" + (pe - p));
230                     args.modifyValue(ri, vo, vsize, bytes, p);
231                     p += vsize;
232                     break; }
233                 case 56: case 57: case 58: case 59:
234                 case 60: case 61: case 62: case 63: {
235                     //0x00111??? set - ri14 + sz2 = 16 / 8 = 2 + sz * bytes;
236                     byte s = (byte)(bytes[p] & 0x7);
237                     s <<= 2;
238                     ri = CCSParser.getShort(bytes, p+1);
239                     ri &= 0x3FFF; 
240                     byte t = bytes[p + 2];
241                     s |= (t &0xFF) >> 6;
242                     args.setValue(ri, bytes, p + 3, s);
243                     p += 3 + s;
244                     break; }
245                 case 64: case 65: case 66: case 67:
246                 case 68: case 69: case 70: case 71:
247                 case 72: case 73: case 74: case 75:
248                 case 76: case 77: case 78: case 79:
249                 case 80: case 81: case 82: case 83:
250                 case 84: case 85: case 86: case 87:
251                 case 88: case 89: case 90: case 91:
252                 case 92: case 93: case 94: case 95:
253                 case 96: case 97: case 98: case 99:
254                 case 100: case 101: case 102: case 103:
255                 case 104: case 105: case 106: case 107:
256                 case 108: case 109: case 110: case 111:
257                 case 112: case 113: case 114: case 115:
258                 case 116: case 117: case 118: case 119:
259                 case 120: case 121: case 122: case 123:
260                 case 124: case 125: case 126: case 127:
261                     //0x01?????? add - ri08 + pr08 + or08 = 24 / 8 = 3
262                     p = CCSParser.parseStm(StmEnum.Add, args, bytes, p, 6, ReferenceType.ForeignShort, ReferenceType.ForeignShort);
263                     break;
264                 case 128: case 129: case 130: case 131:
265                 case 132: case 133: case 134: case 135:
266                 case 136: case 137: case 138: case 139:
267                 case 140: case 141: case 142: case 143:
268                 case 144: case 145: case 146: case 147:
269                 case 148: case 149: case 150: case 151:
270                 case 152: case 153: case 154: case 155:
271                 case 156: case 157: case 158: case 159:
272                 case 160: case 161: case 162: case 163:
273                 case 164: case 165: case 166: case 167:
274                 case 168: case 169: case 170: case 171:
275                 case 172: case 173: case 174: case 175:
276                 case 176: case 177: case 178: case 179:
277                 case 180: case 181: case 182: case 183:
278                 case 184: case 185: case 186: case 187:
279                 case 188: case 189: case 190:case 191:
280                     //0x10?????? rem - ri08 + pr08 + or08 = 24 / 8 = 3
281                     p = CCSParser.parseStm(StmEnum.Remove, args, bytes, p, 6, ReferenceType.ForeignShort, ReferenceType.ForeignShort);
282                     break;
283                 case 192: case 193: case 194: case 195:
284                 case 196: case 197: case 198: case 199:
285                 case 200: case 201: case 202: case 203:
286                 case 204: case 205: case 206: case 207:
287                     //0x1100???? add - ri10 + pi14 + pr08 = 32 / 8 = 4
288                     p = CCSParser.parseStm(StmEnum.Add, args, bytes, p, 4, ReferenceType.Local, ReferenceType.ForeignShort);
289                     break;
290                 case 208: case 209: case 210: case 211:
291                 case 212: case 213: case 214: case 215:
292                 case 216: case 217: case 218: case 219:
293                 case 220: case 221: case 222: case 223:
294                     //0x1101???? add - ri10 + pr08 + oi14 = 32 / 8 = 4
295                     p = CCSParser.parseStm(StmEnum.Add, args, bytes, p, 4, ReferenceType.ForeignShort, ReferenceType.Local);
296                     break;
297                 case 224: case 225: case 226: case 227:
298                 case 228: case 229: case 230: case 231:
299                 case 232: case 233: case 234: case 235:
300                 case 236: case 237: case 238: case 239:
301                     //0x1110???? add - ri10 + pr08 + oc62 = 80 / 8 = 10 
302                     p = CCSParser.parseStm(StmEnum.Add, args, bytes, p, 4, ReferenceType.ForeignShort, ReferenceType.ForeignLong);
303                     break;
304                 case 240: case 241: case 242: case 243:
305                 case 244: case 245: case 246: case 247:
306                 case 248: case 249: case 250: case 251:
307                 case 252: case 253: case 254: case 255:
308                     //0x1111???? add - ri10 + pc62 + or08 = 80 / 8 = 10 
309                     p = CCSParser.parseStm(StmEnum.Add, args, bytes, p, 4, ReferenceType.ForeignLong, ReferenceType.ForeignShort);
310                     break;
311                 default:
312                     throw new RuntimeException("Internal error in cluster stream (v=" + kraa + ")");
313             }
314         }
315         return p - pb;
316     }
317     private static class ClusterChangeSetBlock {
318         ClusterChangeSetBlock(int offset, int size, byte[] bytes) {
319             this.bytes = bytes;
320             this.offset = offset;
321             this.size = size;
322         }
323         byte[] bytes;
324         int offset;
325         int size;
326     }
327     private static class Blocks {
328         Blocks() {
329             mBlocks = new Vector<ClusterChangeSetBlock>();
330             mBlocks.ensureCapacity(BLOCK_INCREMENT);
331         }
332         int size() {
333             return mBlocks.size();
334         }
335         void push_back(ClusterChangeSetBlock ar) {
336             if (mBlocks.size() == mBlocks.capacity())
337                 mBlocks.ensureCapacity(mBlocks.size() + BLOCK_INCREMENT);
338             mBlocks.add(ar);
339         }
340         ClusterChangeSetBlock get(int i) {
341             return mBlocks.get(i);
342         }
343         // How many block elements are allocated when out of space.
344         private static final int BLOCK_INCREMENT = 10;
345         private Vector<ClusterChangeSetBlock> mBlocks;
346     }
347     private static class Iterator implements IteratorI {
348         Iterator(int lastBlock) {
349             this.lastBlock = lastBlock;
350             this.foreignTable = new CCSParser.ForeignTable(); 
351         }
352         int lastBlock;
353         int block;
354         int offset;
355         CCSParser.ForeignTable foreignTable;
356     }
357     private Blocks mBlocks = new Blocks();
358 }