1 package org.simantics.acorn.internal;
3 import java.util.Arrays;
4 import java.util.HashMap;
7 import org.simantics.acorn.ClusterManager;
8 import org.simantics.acorn.internal.ClusterStream.ClusterEnum;
9 import org.simantics.acorn.internal.ClusterStream.Data;
10 import org.simantics.acorn.internal.ClusterStream.StmEnum;
11 import org.simantics.db.exception.DatabaseException;
12 import org.simantics.db.service.Bytes;
13 import org.simantics.db.service.ClusterUID;
15 abstract public class ClusterUpdateProcessorBase {
17 public final static boolean DEBUG = false;
19 final protected ClusterManager manager;
20 final public byte[] bytes;
22 final private int len;
23 final private ClusterUID uid;
24 final private int clusterKey;
25 final public int version;
27 final Map<ClusterUID, Integer> clusterKeyCache = new HashMap<ClusterUID, Integer>();
29 public int getResourceKey(ClusterUID uid, int index) {
30 Integer match = clusterKeyCache.get(uid);
31 if(match != null) return match+index;
32 int key = manager.getResourceKeyWitoutMutex(uid, 0);
33 clusterKeyCache.put(uid, key);
38 public ClusterUpdateProcessorBase(ClusterManager client, byte[] operations) throws DatabaseException {
39 this.manager = client;
40 this.bytes = operations;
41 this.len = Bytes.readLE4(bytes, 0)+4; // whatta?
42 version = Bytes.readLE4(bytes, 4);
43 long cuid1 = Bytes.readLE8(bytes, 8);
44 long cuid2 = Bytes.readLE8(bytes, 16);
45 uid = ClusterUID.make(cuid1, cuid2);
47 client.clusterLRU.acquireMutex();
49 clusterKey = client.clusterLRU.getClusterKeyByUID(cuid1, cuid2) << 12;
50 } catch (Throwable t) {
51 throw new IllegalStateException(t);
53 client.clusterLRU.releaseMutex();
57 public ClusterUID getClusterUID() {
61 private void processCreate() {
62 int r = Bytes.readLE2(bytes, pos);
64 if(DEBUG) System.err.println("DEBUG: New ri=" + r + " offset=" + (pos-3-24));
67 } catch (DatabaseException e) {
73 private void processDelete() {
75 int ri = Bytes.readLE2(bytes, pos);
78 if(DEBUG) System.err.println("DEBUG: Delete " + ri);
82 } catch (DatabaseException e) {
88 private void processModify(int op) {
90 int ri = Bytes.readLE2(bytes, pos);
92 long offset = Bytes.readLE7(bytes, pos);
94 int size = Bytes.readLE2(bytes, pos);
97 offset += (ri>>14) << 56;
101 throw new IllegalStateException();
103 throw new IllegalStateException();
105 throw new IllegalStateException();
107 if(DEBUG) System.err.println("DEBUG: Modify " + ri + " " + offset + " " + size + " offset=" + (pos-1-24) + " " + Arrays.toString(Arrays.copyOf(valueBuffer,size)));
110 modify(clusterKey + ri, offset, size, bytes, pos);
111 } catch (DatabaseException e) {
119 private void processSet(int op) {
121 int s = Bytes.readLE4(bytes, pos);
122 int length = (s >> 14);
124 throw new IllegalStateException();
128 System.arraycopy(bytes, pos, valueBuffer, 0, length);
131 if(DEBUG) System.err.println("DEBUG: Set " + r + " " + length + " offset=" + (pos-1-24) + " " + Arrays.toString(Arrays.copyOf(valueBuffer,length)));
134 set(clusterKey+r, valueBuffer, length);
135 } catch (DatabaseException e) {
141 byte[] valueBuffer = new byte[65536];
143 private void processSetShort(int op) {
145 int s = Bytes.readLE2(bytes, pos);
146 int length = ((op&7)<<2) + (s >> 14);
148 throw new IllegalStateException();
150 throw new IllegalStateException();
153 if(DEBUG) System.err.println("DEBUG: SetShort " + r + " " + length + " offset=" + (pos-1-24) + " " + Arrays.toString(Arrays.copyOf(valueBuffer,length)));
156 System.arraycopy(bytes, pos, valueBuffer, 0, length);
160 set(clusterKey+r, valueBuffer, length);
161 } catch (DatabaseException e) {
167 private void processStatementResource(ClusterEnum enu, int pOrO) {
168 if(ClusterEnum.ForeignShort == enu) {
169 int fs = bytes[pos++]&0xff;
170 foreignRefs[pOrO] = fs;
171 } else if(ClusterEnum.Local == enu) {
172 int lo = bytes[pos++]&0xff;
175 long l1 = Bytes.readLE8(bytes, pos);
177 long l2 = Bytes.readLE8(bytes, pos);
179 ClusterUID cuid = ClusterUID.make(l1, l2);
180 foreignClusters[foreignPos] = cuid;
181 int lo = bytes[pos++]&0xff;
182 foreignIndices[foreignPos] = lo;
183 foreignRefs[pOrO] = foreignPos;
189 ClusterUID[] foreignClusters = new ClusterUID[256];
190 int[] foreignIndices = new int[256];
192 int lows[] = new int[2];
193 int foreignRefs[] = new int[2];
195 private void processStatement(int op, StmEnum stmEnum, ClusterEnum p, ClusterEnum o) {
197 int curPos = pos-1-24;
199 processStatementResource(p, 0);
200 processStatementResource(o, 1);
202 int ri = bytes[pos++]&0xff;
206 ClusterUID puid = uid;
207 ClusterUID ouid = puid;
209 if(ClusterEnum.ForeignShort == p && ClusterEnum.ForeignShort == o) {
210 ri |= (op&0x3F) << 8;
212 Data data = ClusterEnum.getData(stmEnum, p, o);
213 // data.left is the amount of bytes in last two bytes
214 if(data.bytes == 0) {
215 ri = ri | ((op&0x3F)<<8);
218 int opBits = data.bits;
219 int extraBits = 6-opBits;
220 if(data.bytes == 1) {
221 extra = bytes[pos++]&0xff;
222 int high = extra >> extraBits;
223 if(ClusterEnum.ForeignShort == p) {
224 oi = lows[1] + (high<<8);
226 pi = lows[0] + (high<<8);
229 extra = Bytes.readLE2(bytes, pos);
231 int high1 = (extra >> extraBits)&((1<<6)-1);
232 int high2 = (extra >> (extraBits+6))&((1<<6)-1);
233 if(ClusterEnum.ForeignShort == p) {
234 oi = lows[1] + (high1<<8);
236 pi = lows[0] + (high1<<8);
237 oi = lows[1] + (high2<<8);
240 ri = ri | ((extra&((1<<extraBits)-1))<<8) | ((op&((1<<opBits)-1))<<(8+extraBits));
245 if(ClusterEnum.ForeignLong == p) {
246 int ref = foreignRefs[0];
247 foreignIndices[ref] = pi;
248 puid = foreignClusters[ref];
250 if(ClusterEnum.ForeignLong == o) {
251 int ref = foreignRefs[1];
252 foreignIndices[ref] = oi;
253 ouid = foreignClusters[ref];
256 if(ClusterEnum.ForeignShort == p) {
257 int ref = foreignRefs[0];
258 pi = foreignIndices[ref];
259 puid = foreignClusters[ref];
261 if(ClusterEnum.ForeignShort == o) {
262 int ref = foreignRefs[1];
263 oi = foreignIndices[ref];
264 ouid = foreignClusters[ref];
268 throw new IllegalStateException();
270 throw new IllegalStateException();
272 throw new IllegalStateException();
274 throw new IllegalStateException();
276 throw new IllegalStateException();
278 throw new IllegalStateException();
280 if(StmEnum.Add == stmEnum) {
283 System.err.println("DEBUG: ClusterChange " + uid + ": Add ri=" + ri + " pi=" + pi + " oi=" + oi + " pc=" + puid + " oc=" + ouid + " offset=" + curPos + " " + p.ordinal + " " + o.ordinal);
285 int predicateKey = getResourceKey(puid, pi);
286 int objectKey = getResourceKey(ouid, oi);
288 claim(clusterKey+ri, predicateKey, objectKey, puid, ouid);
289 } catch (DatabaseException e) {
296 System.err.println("DEBUG: ClusterChange " + uid + ": Rem ri=" + ri + " pi=" + pi + " oi=" + oi + " pc=" + puid + " oc=" + ouid + " offset=" + curPos + " " + p.ordinal + " " + o.ordinal);
298 int predicateKey = getResourceKey(puid, pi);
299 int objectKey = getResourceKey(ouid, oi);
301 deny(clusterKey+ri, predicateKey, objectKey, puid, ouid);
302 } catch (DatabaseException e) {
310 public void process() {
314 if(DEBUG) System.err.println("DEBUG: process " + uid + " " + len);
316 // op resolution for statement operation:
322 // 3 first bits (000)
323 // op: 000000 | r12-13
324 // op: 000001 | r12-13
325 // op: 000010 | r12-13
326 // op: 000011 | r12-13
327 // op: 000100 | r12-13
328 // op: 000101 | r12-13
329 // op: 000110 | r12-13
330 // op: 000111 | r12-13
347 int op = bytes[pos++]&0xff;
349 // common prefix: 0011
353 processStatement(op, StmEnum.Remove, ClusterEnum.Local, ClusterEnum.ForeignShort);
356 processStatement(op, StmEnum.Remove, ClusterEnum.ForeignShort, ClusterEnum.ForeignLong);
359 processStatement(op, StmEnum.Remove, ClusterEnum.ForeignLong, ClusterEnum.ForeignShort);
361 // 52 = 32+16+4 = 00110100
365 // 53 = 32+16+4+1 = 00110101
369 // 54 = 32+16+4+2 = 00110110
373 // 55 = 32+16+4+2+1 = 00110111
379 int bits6 = ((int)op)&0xC0;
383 processStatement(op, StmEnum.Add, ClusterEnum.ForeignShort, ClusterEnum.ForeignShort);
386 processStatement(op, StmEnum.Remove, ClusterEnum.ForeignShort, ClusterEnum.ForeignShort);
390 int bits5 = ((int)op)&0xE0;
393 int bits2 = (((int)op)&0xFC) >> 2;
401 processStatement(op, StmEnum.Add, ClusterEnum.Local, ClusterEnum.Local);
404 processStatement(op, StmEnum.Remove, ClusterEnum.Local, ClusterEnum.Local);
407 processStatement(op, StmEnum.Add, ClusterEnum.Local, ClusterEnum.ForeignLong);
410 processStatement(op, StmEnum.Remove, ClusterEnum.Local, ClusterEnum.ForeignLong);
413 processStatement(op, StmEnum.Add, ClusterEnum.ForeignLong, ClusterEnum.Local);
416 processStatement(op, StmEnum.Remove, ClusterEnum.ForeignLong, ClusterEnum.Local);
419 processStatement(op, StmEnum.Add, ClusterEnum.ForeignLong, ClusterEnum.ForeignLong);
422 processStatement(op, StmEnum.Remove, ClusterEnum.ForeignLong, ClusterEnum.ForeignLong);
430 // 4 low bits of payload
432 int bits4 = (((int)op)&0xF0)>>4;
435 processStatement(op, StmEnum.Add, ClusterEnum.Local, ClusterEnum.ForeignShort);
438 processStatement(op, StmEnum.Add, ClusterEnum.ForeignShort, ClusterEnum.Local);
441 processStatement(op, StmEnum.Add, ClusterEnum.ForeignShort, ClusterEnum.ForeignLong);
444 processStatement(op, StmEnum.Add, ClusterEnum.ForeignLong, ClusterEnum.ForeignShort);
447 processStatement(op, StmEnum.Remove, ClusterEnum.ForeignShort, ClusterEnum.Local);
450 int bits3 = (((int)op)&0xF8)>>3;
467 abstract void create() throws DatabaseException;
468 abstract void delete(int resourceIndex) throws DatabaseException;
469 abstract void modify(int resourceKey, long offset, int size, byte[] bytes, int pos) throws DatabaseException;
470 abstract void set(int resourceKey, byte[] bytes, int length) throws DatabaseException;
472 abstract void claim(int resourceKey, int predicateKey, int objectKey, ClusterUID puid, ClusterUID ouid) throws DatabaseException;
473 abstract void deny(int resourceKey, int predicateKey, int objectKey, ClusterUID puid, ClusterUID ouid) throws DatabaseException;