]> gerrit.simantics Code Review - simantics/platform.git/blob - bundles/org.simantics.db.procore/src/fi/vtt/simantics/procore/internal/ClusterStream.java
Sync git svn branch with SVN repository r33249.
[simantics/platform.git] / bundles / org.simantics.db.procore / src / fi / vtt / simantics / procore / internal / ClusterStream.java
1 /*******************************************************************************\r
2  * Copyright (c) 2007, 2010 Association for Decentralized Information Management\r
3  * in Industry THTH ry.\r
4  * All rights reserved. This program and the accompanying materials\r
5  * are made available under the terms of the Eclipse Public License v1.0\r
6  * which accompanies this distribution, and is available at\r
7  * http://www.eclipse.org/legal/epl-v10.html\r
8  *\r
9  * Contributors:\r
10  *     VTT Technical Research Centre of Finland - initial API and implementation\r
11  *******************************************************************************/\r
12 package fi.vtt.simantics.procore.internal;\r
13 \r
14 import java.util.ArrayList;\r
15 \r
16 import org.simantics.db.common.utils.Logger;\r
17 import org.simantics.db.exception.DatabaseException;\r
18 import org.simantics.db.service.ClusterUID;\r
19 \r
20 final public class ClusterStream {\r
21 \r
22     // public static long duration2 = 0;\r
23 \r
24     public static final boolean DEBUG = false;\r
25     public static final byte NULL_OPERATION = 0;\r
26     public static final byte CREATE_OPERATION = 1;\r
27     public static final byte SET_OPERATION = 4;\r
28     public static final byte MODI_OPERATION = 6;\r
29     public static final byte KILL_OPERATION = 7;\r
30     boolean off = false;\r
31     public GraphSession graphSession;\r
32     final SessionImplSocket session;\r
33 //    private int flushCount = 0;\r
34     final private boolean alwaysOff;\r
35     private int stamp;\r
36     private int acceptedStamp;\r
37     private boolean dirty = false;\r
38 //    final private ArrayList<ClusterChange> clusterChanges = new ArrayList<ClusterChange>();\r
39 \r
40     final ClusterChangeManager changes = new ClusterChangeManager();\r
41 \r
42 //    final TLongObjectHashMap<ClusterChange> clusterChanges = new TLongObjectHashMap<ClusterChange>();\r
43 \r
44     // private final Change lastChange = new Change();\r
45     ClusterStream(SessionImplSocket session, GraphSession graphSession,\r
46             boolean alwaysOff) {\r
47         this.session = session;\r
48         this.graphSession = graphSession;\r
49         this.alwaysOff = alwaysOff;\r
50     }\r
51 \r
52 \r
53     boolean isDirty() {\r
54         return dirty;\r
55     }\r
56 \r
57     void markDirty() {\r
58         dirty = true;\r
59     }\r
60 \r
61     void setOff(boolean value) {\r
62         if (alwaysOff) {\r
63             off = true;\r
64         } else {\r
65             off = value;\r
66         }\r
67     }\r
68 \r
69     boolean getOff() {\r
70         return off;\r
71     }\r
72 \r
73     void createResource(ClusterChange cc, short operationIndex, ClusterUID clusterUID) {\r
74         if (off)\r
75             return;\r
76         assert (null != cc);\r
77         assert (0 != operationIndex);\r
78         assert (!ClusterUID.Null.equals(clusterUID));\r
79         if (DEBUG)\r
80             System.out.println("DEBUG: Created resource index=" + operationIndex + " cluster=" + clusterUID);\r
81         cc.createResource(operationIndex);\r
82     }\r
83 \r
84     final void addStatementIndex(Change change, int key, ClusterUID clusterUID, byte op) {\r
85         if (off)\r
86             return;\r
87         assert (key > 0);\r
88         assert (null != change);\r
89         assert (!ClusterUID.Null.equals(clusterUID));\r
90         change.addStatementIndex(key, clusterUID, op);\r
91     }\r
92 \r
93     void addStatement(ClusterChange cc, Change change) {\r
94         if (off)\r
95             return;\r
96         assert (null != cc);\r
97         assert (null != change);\r
98         cc.addChange(change);\r
99     }\r
100 \r
101     void cancelStatement(Change change) {\r
102         if (off)\r
103             return;\r
104         assert (null != change);\r
105         change.init();\r
106     }\r
107 \r
108     void removeStatement(ClusterChange cc, Change change) {\r
109         if (off)\r
110             return;\r
111         assert (null != cc);\r
112         assert (null != change);\r
113         cc.addChange(change);\r
114     }\r
115 \r
116     void cancelValue(Change change) {\r
117         if (off)\r
118             return;\r
119         assert (null != change);\r
120         change.init();\r
121     }\r
122 \r
123     void removeValue(ClusterChange cc, Change change) {\r
124         if (off)\r
125             return;\r
126         assert (null != cc);\r
127         assert (null != change);\r
128         cc.addChange(change);\r
129     }\r
130 \r
131     void setValue(ClusterChange cc, Change change, long clusterId, byte[] bytes, int length) {\r
132         if (off)\r
133             return;\r
134         assert (null != cc);\r
135         assert (null != change);\r
136         // ClusterChange cc = getClusterChange(clusterId);\r
137         cc.setValue(change, bytes, length);\r
138     }\r
139 \r
140     void modiValue(ClusterChange cc, Change change, long clusterId,\r
141             long voffset, int length, byte[] bytes, int offset) {\r
142         assert (null != cc);\r
143         assert (null != change);\r
144         cc.modiValue(change, voffset, length, bytes, offset);\r
145     }\r
146 \r
147     void undoValueEx(ClusterChange cc, Change change, int resourceIndex) {\r
148         cc.undoValueEx(resourceIndex);\r
149     }\r
150     void setImmutable(ClusterChange cc, Change change, boolean immutable) {\r
151         if (off)\r
152             return;\r
153         cc.setImmutable(immutable);\r
154     }\r
155     void setDeleted(ClusterChange cc, Change change, boolean deleted) {\r
156         if (off)\r
157             return;\r
158         cc.setDeleted(deleted);\r
159     }\r
160     public void corruptCluster(ClusterChange cc, long clusterId)\r
161             throws DatabaseException {\r
162         if (off)\r
163             return;\r
164         if (DEBUG)\r
165             System.out.println("ClusterStream.corrupt cid=" + clusterId + ".");\r
166         assert (null != cc);\r
167         cc.corrupt();\r
168     }\r
169 \r
170     int getStamp() {\r
171         return stamp;\r
172     }\r
173 \r
174     void flush() {\r
175         if (off)\r
176             return;\r
177 //        flushCount++;\r
178         return;\r
179     }\r
180 \r
181     void flush(ClusterUID clusterUID) {\r
182         if (off)\r
183             return;\r
184         ArrayList<ClusterChange> ccs = new ArrayList<ClusterChange>();\r
185         for(ClusterChange cc : changes.get()) {\r
186             if(cc.clusterUID.equals(clusterUID)) {\r
187                 if (cc.flush(graphSession, cc.clusterUID)) {\r
188                     ccs.add(cc);\r
189                     if (stamp == acceptedStamp)\r
190                         ++stamp;\r
191                 } else {\r
192                     Logger.defaultLogError("Failed to flush ClusterStream. cluster=" + clusterUID);\r
193                 }\r
194             }\r
195         }\r
196         changes.remove(ccs);\r
197     }\r
198 \r
199     /**\r
200      * @return true if the stream has accepted all changes\r
201      */\r
202     public boolean reallyFlush() {\r
203         // Last possibility to mark clusters immutable before write only clusters are gone\r
204         session.handleCreatedClusters();\r
205         // These shall be requested from server\r
206         session.clusterTable.removeWriteOnlyClusters();\r
207         if (!off && changes.size() > 0) {\r
208             for(ClusterChange cc : changes.get()) {\r
209                 if (cc.flush(graphSession, cc.clusterUID))\r
210                     if (stamp == acceptedStamp)\r
211                         ++stamp;\r
212             }\r
213             changes.clear();\r
214         }\r
215         dirty = false;\r
216         return hasAcceptedAllChanges();\r
217     }\r
218 \r
219     /**\r
220      * Clear all changes and set stream status to empty.\r
221      */\r
222     public void clear() {\r
223         changes.clear();\r
224         acceptedStamp = stamp;\r
225         dirty = false;\r
226     }\r
227 \r
228     private boolean hasAcceptedAllChanges() {\r
229         return stamp == acceptedStamp;\r
230     }\r
231 \r
232     void accept() {\r
233         acceptedStamp = stamp;\r
234     }\r
235 \r
236 \r
237 \r
238     static class DebugInfo {\r
239         long nStms;\r
240         long nLocal;\r
241         long nPartly;\r
242         long nForeign;\r
243         long nValues;\r
244         long sValues;\r
245         long sForeign;\r
246         long tot;\r
247 \r
248         void clear() {\r
249             nStms = 0;\r
250             nLocal = 0;\r
251             nPartly = 0;\r
252             nForeign = 0;\r
253             sForeign = 0;\r
254             nValues = 0;\r
255             sValues = 0;\r
256             tot = 0;\r
257         }\r
258 \r
259         void add(DebugInfo di) {\r
260             nStms += di.nStms;\r
261             nLocal += di.nLocal;\r
262             nPartly += di.nPartly;\r
263             nForeign += di.nForeign;\r
264             sForeign += di.sForeign;\r
265             nValues += di.nValues;\r
266             sValues += di.sValues;\r
267             tot += di.tot;\r
268         }\r
269 \r
270         @Override\r
271         public String toString() {\r
272             return "val=" + nValues + " stm=" + nStms + " loc=" + nLocal\r
273                     + " par=" + nPartly + " ful=" + nForeign + " for="\r
274                     + sForeign + " vat=" + sValues + " tot=" + tot;\r
275         }\r
276     }\r
277 \r
278     enum StmEnum {\r
279         Add(0, (byte) 0), Remove(1, (byte) 0x20);\r
280         StmEnum(int ordinal, byte mask) {\r
281             this.ordinal = ordinal;\r
282             this.mask = mask;\r
283         }\r
284 \r
285         public int ordinal;\r
286         private byte mask;\r
287 \r
288         byte getOrMask() {\r
289             return mask;\r
290         }\r
291     }\r
292 \r
293     final static class Data {\r
294 \r
295         final byte mask; // or mask for operation code (don't care bits are zero)\r
296         final short bits; // how many bits are reserved for resource index (0,2,4,6)\r
297         final int bytes;\r
298 \r
299         Data(int mask, int bits, ClusterEnum a, ClusterEnum b) {\r
300             this.mask = (byte) (mask << bits);\r
301             this.bits = (short) bits;\r
302             this.bytes = bytes(bits, a, b);\r
303         }\r
304 \r
305         private static int bytes(int bits, ClusterEnum a, ClusterEnum b) {\r
306             int left = 6 - bits;\r
307             if (a != ClusterEnum.ForeignShort) {\r
308                 left += 6;\r
309             }\r
310             if (b != ClusterEnum.ForeignShort) {\r
311                 left += 6;\r
312             }\r
313             int bytes = left >>> 3;\r
314             if ((left & 7) != 0)\r
315                 bytes++;\r
316             return bytes;\r
317         }\r
318 \r
319 \r
320     }\r
321 \r
322     enum ClusterEnum {\r
323         Local(0), ForeignShort(1), ForeignLong(2);\r
324         public int ordinal;\r
325 \r
326         ClusterEnum(int ordinal) {\r
327             this.ordinal = ordinal;\r
328         }\r
329 \r
330         static Data[][][] maps = new Data[2][3][3];\r
331         static {\r
332             maps[StmEnum.Add.ordinal][Local.ordinal][Local.ordinal] = new Data(\r
333                     0, 2, Local, Local);\r
334             maps[StmEnum.Add.ordinal][Local.ordinal][ForeignShort.ordinal] = new Data(\r
335                     12, 4, Local, ForeignShort);\r
336             maps[StmEnum.Add.ordinal][Local.ordinal][ForeignLong.ordinal] = new Data(\r
337                     2, 2, Local, ForeignLong);\r
338             maps[StmEnum.Add.ordinal][ForeignShort.ordinal][Local.ordinal] = new Data(\r
339                     13, 4, ForeignShort, Local);\r
340             maps[StmEnum.Add.ordinal][ForeignShort.ordinal][ForeignShort.ordinal] = new Data(\r
341                     1, 6, ForeignShort, ForeignShort);\r
342             maps[StmEnum.Add.ordinal][ForeignShort.ordinal][ForeignLong.ordinal] = new Data(\r
343                     14, 4, ForeignShort, ForeignLong);\r
344             maps[StmEnum.Add.ordinal][ForeignLong.ordinal][Local.ordinal] = new Data(\r
345                     4, 2, ForeignLong, Local);\r
346             maps[StmEnum.Add.ordinal][ForeignLong.ordinal][ForeignShort.ordinal] = new Data(\r
347                     15, 4, ForeignLong, ForeignShort);\r
348             maps[StmEnum.Add.ordinal][ForeignLong.ordinal][ForeignLong.ordinal] = new Data(\r
349                     6, 2, ForeignLong, ForeignLong);\r
350 \r
351             maps[StmEnum.Remove.ordinal][Local.ordinal][Local.ordinal] = new Data(\r
352                     1, 2, Local, Local);\r
353             maps[StmEnum.Remove.ordinal][Local.ordinal][ForeignShort.ordinal] = new Data(\r
354                     49, 0, Local, ForeignShort);\r
355             maps[StmEnum.Remove.ordinal][Local.ordinal][ForeignLong.ordinal] = new Data(\r
356                     3, 2, Local, ForeignLong);\r
357             maps[StmEnum.Remove.ordinal][ForeignShort.ordinal][Local.ordinal] = new Data(\r
358                     2, 4, ForeignShort, Local);\r
359             maps[StmEnum.Remove.ordinal][ForeignShort.ordinal][ForeignShort.ordinal] = new Data(\r
360                     2, 6, ForeignShort, ForeignShort);\r
361             maps[StmEnum.Remove.ordinal][ForeignShort.ordinal][ForeignLong.ordinal] = new Data(\r
362                     50, 0, ForeignShort, ForeignLong);\r
363             maps[StmEnum.Remove.ordinal][ForeignLong.ordinal][Local.ordinal] = new Data(\r
364                     5, 2, ForeignLong, Local);\r
365             maps[StmEnum.Remove.ordinal][ForeignLong.ordinal][ForeignShort.ordinal] = new Data(\r
366                     51, 0, ForeignLong, ForeignShort);\r
367             maps[StmEnum.Remove.ordinal][ForeignLong.ordinal][ForeignLong.ordinal] = new Data(\r
368                     7, 2, ForeignLong, ForeignLong);\r
369         }\r
370 \r
371         static Data getData(StmEnum s, ClusterEnum a, ClusterEnum b) {\r
372             return maps[s.ordinal][a.ordinal][b.ordinal];\r
373             // return maps.get(s).get(a).get(b);\r
374         }\r
375     }\r
376 \r
377     enum OpEnum {\r
378         Create((byte) 52), Set((byte) 53), SetShort((byte) 56), Delete(\r
379                 (byte) 54), Modify((byte) 55);\r
380         OpEnum(byte mask) {\r
381             this.mask = mask;\r
382         }\r
383 \r
384         public byte getOrMask() {\r
385             return mask;\r
386         }\r
387 \r
388         private byte mask;\r
389     }\r
390 }\r