]> gerrit.simantics Code Review - simantics/platform.git/blob - bundles/org.simantics.acorn/src/org/simantics/acorn/internal/ClusterUpdateProcessorBase.java
Merge remote-tracking branch 'origin/svn'
[simantics/platform.git] / bundles / org.simantics.acorn / src / org / simantics / acorn / internal / ClusterUpdateProcessorBase.java
1 package org.simantics.acorn.internal;
2
3 import java.util.Arrays;
4 import java.util.HashMap;
5 import java.util.Map;
6
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;
14
15 abstract public class ClusterUpdateProcessorBase {
16         
17         public final static boolean DEBUG = false;
18
19         final protected ClusterManager manager;
20         final public byte[] bytes;
21         private int pos = 0;
22         final private int len;
23         final private ClusterUID uid;
24         final private int clusterKey;
25         final public int version;
26         
27         final Map<ClusterUID, Integer> clusterKeyCache = new HashMap<ClusterUID, Integer>();
28         
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);
34                 return key+index;
35         }
36         
37         
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);
46                 pos = 24;
47                 client.clusterLRU.acquireMutex();
48                 try {
49                         clusterKey = client.clusterLRU.getClusterKeyByUID(cuid1, cuid2) << 12;
50                 } catch (Throwable t) {
51                         throw new IllegalStateException(t);
52                 } finally {
53                         client.clusterLRU.releaseMutex();
54                 }
55         }
56         
57         public ClusterUID getClusterUID() {
58                 return uid;
59         }
60         
61         private void processCreate() {
62                 int r = Bytes.readLE2(bytes, pos);
63                 pos+=2;
64                 if(DEBUG) System.err.println("DEBUG: New ri=" + r + " offset=" + (pos-3-24));
65                 try {
66                         create();
67                 } catch (DatabaseException e) {
68                         e.printStackTrace();
69                 }
70                 
71         }
72         
73         private void processDelete() {
74                 
75                 int ri = Bytes.readLE2(bytes, pos);
76                 pos += 2;
77                 
78                 if(DEBUG) System.err.println("DEBUG: Delete " + ri);
79                 
80                 try {
81                         delete(ri);
82                 } catch (DatabaseException e) {
83                         e.printStackTrace();
84                 }
85                 
86         }
87
88         private void processModify(int op) {
89                 
90                 int ri = Bytes.readLE2(bytes, pos);
91                 pos+=2;
92                 long offset = Bytes.readLE7(bytes, pos);
93                 pos+=7;
94                 int size = Bytes.readLE2(bytes, pos);
95                 pos+=2;
96                 
97                 offset += (ri>>14) << 56;
98                 ri = ri & 0x3FFF;
99                 
100                 if(size < 0)
101                         throw new IllegalStateException();
102                 if(ri < 1)
103                         throw new IllegalStateException();
104                 if(ri > 4095)
105                         throw new IllegalStateException();
106                 
107                 if(DEBUG) System.err.println("DEBUG: Modify " + ri + " " + offset + " " + size + " offset=" + (pos-1-24) + " " + Arrays.toString(Arrays.copyOf(valueBuffer,size)));
108
109                 try {
110                         modify(clusterKey + ri, offset, size, bytes, pos);
111                 } catch (DatabaseException e) {
112                         e.printStackTrace();
113                 }
114
115                 pos += size;
116                 
117         }
118
119         private void processSet(int op) {
120                 
121                 int s = Bytes.readLE4(bytes, pos);
122                 int length = (s >> 14);
123                 if(length < 1)
124                         throw new IllegalStateException();
125                 int r = s & 0x3FFF;
126                 
127                 pos += 4;
128                 System.arraycopy(bytes, pos, valueBuffer, 0, length);
129                 pos += length;
130
131                 if(DEBUG) System.err.println("DEBUG: Set " + r + " " + length + " offset=" + (pos-1-24) + " " + Arrays.toString(Arrays.copyOf(valueBuffer,length)));
132
133                 try {
134                         set(clusterKey+r, valueBuffer, length);
135                 } catch (DatabaseException e) {
136                         e.printStackTrace();
137                 }
138                 
139         }
140
141         byte[] valueBuffer = new byte[65536];
142         
143         private void processSetShort(int op) {
144                 
145                 int s = Bytes.readLE2(bytes, pos);
146                 int length = ((op&7)<<2) + (s >> 14);
147                 if(length < 1)
148                         throw new IllegalStateException();
149                 if(length > 31)
150                         throw new IllegalStateException();
151                 int r = s & 0x3FFF;
152                 
153                 if(DEBUG) System.err.println("DEBUG: SetShort " + r + " " + length + " offset=" + (pos-1-24) + " " + Arrays.toString(Arrays.copyOf(valueBuffer,length)));
154                 pos += 2;
155
156                 System.arraycopy(bytes, pos, valueBuffer, 0, length);
157                 pos += length;
158                 
159                 try {
160                         set(clusterKey+r, valueBuffer, length);
161                 } catch (DatabaseException e) {
162                         e.printStackTrace();
163                 }
164                 
165         }
166
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;
173                         lows[pOrO] = lo;
174                 } else {
175                         long l1 = Bytes.readLE8(bytes, pos);
176                         pos += 8;
177                         long l2 = Bytes.readLE8(bytes, pos);
178                         pos += 8;
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;
184                         foreignPos++;
185                         lows[pOrO] = lo;
186                 }
187         }
188         
189         ClusterUID[] foreignClusters = new ClusterUID[256];
190         int[] foreignIndices = new int[256];
191         int foreignPos = 0;
192         int lows[] = new int[2];
193         int foreignRefs[] = new int[2];
194         
195         private void processStatement(int op, StmEnum stmEnum, ClusterEnum p, ClusterEnum o) {
196
197                 int curPos = pos-1-24;
198                 
199                 processStatementResource(p, 0);
200                 processStatementResource(o, 1);
201
202                 int ri = bytes[pos++]&0xff;
203                 int pi = 0;
204                 int oi = 0;
205                 
206                 ClusterUID puid = uid;
207                 ClusterUID ouid = puid;
208                 
209                 if(ClusterEnum.ForeignShort == p && ClusterEnum.ForeignShort == o) {
210                         ri |= (op&0x3F) << 8;
211                 } else {
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); 
216                         } else {
217                                 int extra = 0;
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);
225                                         } else {
226                                                 pi = lows[0] + (high<<8);
227                                         }
228                                 } else {
229                                         extra = Bytes.readLE2(bytes, pos);
230                                         pos += 2;
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);
235                                         } else {
236                                                 pi = lows[0] + (high1<<8);
237                                                 oi = lows[1] + (high2<<8);
238                                         }
239                                 }
240                                 ri = ri | ((extra&((1<<extraBits)-1))<<8) | ((op&((1<<opBits)-1))<<(8+extraBits)); 
241                         }
242                 }
243
244                 // Set foreigns
245                 if(ClusterEnum.ForeignLong == p) {
246                         int ref = foreignRefs[0];
247                         foreignIndices[ref] = pi;
248                         puid = foreignClusters[ref];
249                 }
250                 if(ClusterEnum.ForeignLong == o) {
251                         int ref = foreignRefs[1];
252                         foreignIndices[ref] = oi;
253                         ouid = foreignClusters[ref]; 
254                 }
255                 // Get foreigns
256                 if(ClusterEnum.ForeignShort == p) {
257                         int ref = foreignRefs[0];
258                         pi = foreignIndices[ref];
259                         puid = foreignClusters[ref]; 
260                 }
261                 if(ClusterEnum.ForeignShort == o) {
262                         int ref = foreignRefs[1];
263                         oi = foreignIndices[ref];
264                         ouid = foreignClusters[ref]; 
265                 }
266
267                 if(ri < 1)
268                         throw new IllegalStateException();
269                 if(pi < 1)
270                         throw new IllegalStateException();
271                 if(oi < 1)
272                         throw new IllegalStateException();
273                 if(ri > 4095)
274                         throw new IllegalStateException();
275                 if(pi > 4095)
276                         throw new IllegalStateException();
277                 if(oi > 4095)
278                         throw new IllegalStateException();
279
280                 if(StmEnum.Add == stmEnum) {
281                         
282                         if(DEBUG)
283                 System.err.println("DEBUG: ClusterChange " + uid + ": Add ri=" + ri + " pi=" + pi + " oi=" + oi + " pc=" + puid + " oc=" + ouid + " offset=" + curPos + " " + p.ordinal + " " + o.ordinal);
284             
285                         int predicateKey = getResourceKey(puid, pi);
286                         int objectKey = getResourceKey(ouid, oi);       
287                         try {
288                                 claim(clusterKey+ri, predicateKey, objectKey, puid, ouid);
289                         } catch (DatabaseException e) {
290                                 e.printStackTrace();
291                         }
292                         
293                 } else {
294                         
295                         if(DEBUG)
296                 System.err.println("DEBUG: ClusterChange " + uid + ": Rem ri=" + ri + " pi=" + pi + " oi=" + oi + " pc=" + puid + " oc=" + ouid + " offset=" + curPos + " " + p.ordinal + " " + o.ordinal);
297             
298                         int predicateKey = getResourceKey(puid, pi);
299                         int objectKey = getResourceKey(ouid, oi);
300                         try {
301                                 deny(clusterKey+ri, predicateKey, objectKey, puid, ouid);
302                         } catch (DatabaseException e) {
303                                 e.printStackTrace();
304                         }
305                         
306                 }
307                 
308         }
309
310         public void process() {
311                 
312                 foreignPos = 0;
313
314                 if(DEBUG) System.err.println("DEBUG: process " + uid + " " + len);
315                 
316                 // op resolution for statement operation:
317                 
318                 // 2 first bits
319                 // op: 01 | r8-13
320                 // op: 10 | r8-13
321
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 
331
332                 // 4 first bits
333                 // op: 1100 | r10-13
334                 // op: 1101 | r10-13 
335                 // op: 1110 | r10-13 
336                 // op: 1111 | r10-13
337                 // op: 0010 | r10-13
338                 
339                 // 6 bits
340                 // op: 00110001 = 49
341                 // op: 00110010 = 50
342                 // op: 00110011 = 51
343                 // other: 0011xxxx
344                 
345                 while(pos < len) {
346                 
347                         int op = bytes[pos++]&0xff;
348                         
349                         // common prefix: 0011
350                         switch(op) {
351                         
352                         case 49:
353                                 processStatement(op, StmEnum.Remove, ClusterEnum.Local, ClusterEnum.ForeignShort);
354                                 break;
355                         case 50:
356                                 processStatement(op, StmEnum.Remove, ClusterEnum.ForeignShort, ClusterEnum.ForeignLong);
357                                 break;
358                         case 51:
359                                 processStatement(op, StmEnum.Remove, ClusterEnum.ForeignLong, ClusterEnum.ForeignShort);
360                                 break;
361                         // 52 = 32+16+4 = 00110100
362                         case 52:
363                                 processCreate();
364                                 break;
365                         // 53 = 32+16+4+1 = 00110101
366                         case 53:
367                                 processSet(op);
368                                 break;
369                         // 54 = 32+16+4+2 = 00110110
370                         case 54:
371                                 processDelete();
372                                 break;
373                         // 55 = 32+16+4+2+1 = 00110111
374                         case 55:
375                                 processModify(op);
376                                 break;
377                         default:
378                                 
379                                 int bits6 = ((int)op)&0xC0;
380                                 switch(bits6) {
381                                 
382                                 case 0x40:
383                                         processStatement(op, StmEnum.Add, ClusterEnum.ForeignShort, ClusterEnum.ForeignShort);
384                                         break;
385                                 case 0x80:
386                                         processStatement(op, StmEnum.Remove, ClusterEnum.ForeignShort, ClusterEnum.ForeignShort);
387                                         break;
388                                 default:
389
390                                         int bits5 = ((int)op)&0xE0;
391                                         if(bits5 == 0) {
392
393                                                 int bits2 = (((int)op)&0xFC) >> 2;      
394                                                 
395                                                 // 3 top bits are 0
396                                                 // 6 bits of op
397                                                 
398                                                 switch(bits2) {
399
400                                                 case 0:
401                                                         processStatement(op, StmEnum.Add, ClusterEnum.Local, ClusterEnum.Local);
402                                                         break;
403                                                 case 1:
404                                                         processStatement(op, StmEnum.Remove, ClusterEnum.Local, ClusterEnum.Local);
405                                                         break;
406                                                 case 2:
407                                                         processStatement(op, StmEnum.Add, ClusterEnum.Local, ClusterEnum.ForeignLong);
408                                                         break;
409                                                 case 3:
410                                                         processStatement(op, StmEnum.Remove, ClusterEnum.Local, ClusterEnum.ForeignLong);
411                                                         break;
412                                                 case 4:
413                                                         processStatement(op, StmEnum.Add, ClusterEnum.ForeignLong, ClusterEnum.Local);
414                                                         break;
415                                                 case 5:
416                                                         processStatement(op, StmEnum.Remove, ClusterEnum.ForeignLong, ClusterEnum.Local);
417                                                         break;
418                                                 case 6:
419                                                         processStatement(op, StmEnum.Add, ClusterEnum.ForeignLong, ClusterEnum.ForeignLong);
420                                                         break;
421                                                 case 7:
422                                                         processStatement(op, StmEnum.Remove, ClusterEnum.ForeignLong, ClusterEnum.ForeignLong);
423                                                         break;
424                                                 
425                                                 }
426
427                                         } else {
428
429                                                 // 4 top bits of op
430                                                 // 4 low bits of payload
431
432                                                 int bits4 = (((int)op)&0xF0)>>4;
433                                                 switch(bits4) {
434                                                 case 0b1100:
435                                                         processStatement(op, StmEnum.Add, ClusterEnum.Local, ClusterEnum.ForeignShort);
436                                                         break;
437                                                 case 0b1101:
438                                                         processStatement(op, StmEnum.Add, ClusterEnum.ForeignShort, ClusterEnum.Local);
439                                                         break;
440                                                 case 0b1110:
441                                                         processStatement(op, StmEnum.Add, ClusterEnum.ForeignShort, ClusterEnum.ForeignLong);
442                                                         break;
443                                                 case 0b1111:
444                                                         processStatement(op, StmEnum.Add, ClusterEnum.ForeignLong, ClusterEnum.ForeignShort);
445                                                         break;
446                                                 case 0b0010:
447                                                         processStatement(op, StmEnum.Remove, ClusterEnum.ForeignShort, ClusterEnum.Local);
448                                                         break;
449                                                 case 0b0011:
450                                                         int bits3 = (((int)op)&0xF8)>>3;
451                                                         if(bits3 == 7)
452                                                                 processSetShort(op);
453                                                         break;
454                                                 }
455
456                                         }
457                                 
458                                 }
459                                 
460                         }
461                         
462                 }
463                 
464         }
465         
466         
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;
471         
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;
474         
475 }