1 /*******************************************************************************
2 * Copyright (c) 2007, 2010 Association for Decentralized Information Management
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
10 * VTT Technical Research Centre of Finland - initial API and implementation
11 *******************************************************************************/
12 package fi.vtt.simantics.procore.internal;
14 import java.util.ArrayList;
16 import org.simantics.db.common.utils.Logger;
17 import org.simantics.db.exception.DatabaseException;
18 import org.simantics.db.service.ClusterUID;
20 final public class ClusterStream {
22 // public static long duration2 = 0;
24 public static final boolean DEBUG = false;
25 public static final byte NULL_OPERATION = 0;
26 public static final byte CREATE_OPERATION = 1;
27 public static final byte SET_OPERATION = 4;
28 public static final byte MODI_OPERATION = 6;
29 public static final byte KILL_OPERATION = 7;
31 public GraphSession graphSession;
32 final SessionImplSocket session;
33 // private int flushCount = 0;
34 final private boolean alwaysOff;
36 private int acceptedStamp;
37 private boolean dirty = false;
38 // final private ArrayList<ClusterChange> clusterChanges = new ArrayList<ClusterChange>();
40 final ClusterChangeManager changes = new ClusterChangeManager();
42 // final TLongObjectHashMap<ClusterChange> clusterChanges = new TLongObjectHashMap<ClusterChange>();
44 // private final Change lastChange = new Change();
45 ClusterStream(SessionImplSocket session, GraphSession graphSession,
47 this.session = session;
48 this.graphSession = graphSession;
49 this.alwaysOff = alwaysOff;
61 void setOff(boolean value) {
73 void createResource(ClusterChange cc, short operationIndex, ClusterUID clusterUID) {
77 assert (0 != operationIndex);
78 assert (!ClusterUID.Null.equals(clusterUID));
80 System.out.println("DEBUG: Created resource index=" + operationIndex + " cluster=" + clusterUID);
81 cc.createResource(operationIndex);
84 final void addStatementIndex(Change change, int key, ClusterUID clusterUID, byte op) {
88 assert (null != change);
89 assert (!ClusterUID.Null.equals(clusterUID));
90 change.addStatementIndex(key, clusterUID, op);
93 void addStatement(ClusterChange cc, Change change) {
97 assert (null != change);
101 void cancelStatement(Change change) {
104 assert (null != change);
108 void removeStatement(ClusterChange cc, Change change) {
112 assert (null != change);
113 cc.addChange(change);
116 void cancelValue(Change change) {
119 assert (null != change);
123 void removeValue(ClusterChange cc, Change change) {
127 assert (null != change);
128 cc.addChange(change);
131 void setValue(ClusterChange cc, Change change, long clusterId, byte[] bytes, int length) {
135 assert (null != change);
136 // ClusterChange cc = getClusterChange(clusterId);
137 cc.setValue(change, bytes, length);
140 void modiValue(ClusterChange cc, Change change, long clusterId,
141 long voffset, int length, byte[] bytes, int offset) {
143 assert (null != change);
144 cc.modiValue(change, voffset, length, bytes, offset);
147 void undoValueEx(ClusterChange cc, Change change, int resourceIndex) {
148 cc.undoValueEx(resourceIndex);
150 void setImmutable(ClusterChange cc, Change change, boolean immutable) {
153 cc.setImmutable(immutable);
155 void setDeleted(ClusterChange cc, Change change, boolean deleted) {
158 cc.setDeleted(deleted);
160 public void corruptCluster(ClusterChange cc, long clusterId)
161 throws DatabaseException {
165 System.out.println("ClusterStream.corrupt cid=" + clusterId + ".");
181 void flush(ClusterUID clusterUID) {
184 ArrayList<ClusterChange> ccs = new ArrayList<ClusterChange>();
185 for(ClusterChange cc : changes.get()) {
186 if(cc.clusterUID.equals(clusterUID)) {
187 if (cc.flush(graphSession, cc.clusterUID)) {
189 if (stamp == acceptedStamp)
192 Logger.defaultLogError("Failed to flush ClusterStream. cluster=" + clusterUID);
200 * @return true if the stream has accepted all changes
202 public boolean reallyFlush() {
203 // Last possibility to mark clusters immutable before write only clusters are gone
204 session.handleCreatedClusters();
205 // These shall be requested from server
206 session.clusterTable.removeWriteOnlyClusters();
207 if (!off && changes.size() > 0) {
208 for(ClusterChange cc : changes.get()) {
209 if (cc.flush(graphSession, cc.clusterUID))
210 if (stamp == acceptedStamp)
216 return hasAcceptedAllChanges();
220 * Clear all changes and set stream status to empty.
222 public void clear() {
224 acceptedStamp = stamp;
228 private boolean hasAcceptedAllChanges() {
229 return stamp == acceptedStamp;
233 acceptedStamp = stamp;
238 static class DebugInfo {
259 void add(DebugInfo di) {
262 nPartly += di.nPartly;
263 nForeign += di.nForeign;
264 sForeign += di.sForeign;
265 nValues += di.nValues;
266 sValues += di.sValues;
271 public String toString() {
272 return "val=" + nValues + " stm=" + nStms + " loc=" + nLocal
273 + " par=" + nPartly + " ful=" + nForeign + " for="
274 + sForeign + " vat=" + sValues + " tot=" + tot;
279 Add(0, (byte) 0), Remove(1, (byte) 0x20);
280 StmEnum(int ordinal, byte mask) {
281 this.ordinal = ordinal;
293 final static class Data {
295 final byte mask; // or mask for operation code (don't care bits are zero)
296 final short bits; // how many bits are reserved for resource index (0,2,4,6)
299 Data(int mask, int bits, ClusterEnum a, ClusterEnum b) {
300 this.mask = (byte) (mask << bits);
301 this.bits = (short) bits;
302 this.bytes = bytes(bits, a, b);
305 private static int bytes(int bits, ClusterEnum a, ClusterEnum b) {
307 if (a != ClusterEnum.ForeignShort) {
310 if (b != ClusterEnum.ForeignShort) {
313 int bytes = left >>> 3;
323 Local(0), ForeignShort(1), ForeignLong(2);
326 ClusterEnum(int ordinal) {
327 this.ordinal = ordinal;
330 static Data[][][] maps = new Data[2][3][3];
332 maps[StmEnum.Add.ordinal][Local.ordinal][Local.ordinal] = new Data(
334 maps[StmEnum.Add.ordinal][Local.ordinal][ForeignShort.ordinal] = new Data(
335 12, 4, Local, ForeignShort);
336 maps[StmEnum.Add.ordinal][Local.ordinal][ForeignLong.ordinal] = new Data(
337 2, 2, Local, ForeignLong);
338 maps[StmEnum.Add.ordinal][ForeignShort.ordinal][Local.ordinal] = new Data(
339 13, 4, ForeignShort, Local);
340 maps[StmEnum.Add.ordinal][ForeignShort.ordinal][ForeignShort.ordinal] = new Data(
341 1, 6, ForeignShort, ForeignShort);
342 maps[StmEnum.Add.ordinal][ForeignShort.ordinal][ForeignLong.ordinal] = new Data(
343 14, 4, ForeignShort, ForeignLong);
344 maps[StmEnum.Add.ordinal][ForeignLong.ordinal][Local.ordinal] = new Data(
345 4, 2, ForeignLong, Local);
346 maps[StmEnum.Add.ordinal][ForeignLong.ordinal][ForeignShort.ordinal] = new Data(
347 15, 4, ForeignLong, ForeignShort);
348 maps[StmEnum.Add.ordinal][ForeignLong.ordinal][ForeignLong.ordinal] = new Data(
349 6, 2, ForeignLong, ForeignLong);
351 maps[StmEnum.Remove.ordinal][Local.ordinal][Local.ordinal] = new Data(
353 maps[StmEnum.Remove.ordinal][Local.ordinal][ForeignShort.ordinal] = new Data(
354 49, 0, Local, ForeignShort);
355 maps[StmEnum.Remove.ordinal][Local.ordinal][ForeignLong.ordinal] = new Data(
356 3, 2, Local, ForeignLong);
357 maps[StmEnum.Remove.ordinal][ForeignShort.ordinal][Local.ordinal] = new Data(
358 2, 4, ForeignShort, Local);
359 maps[StmEnum.Remove.ordinal][ForeignShort.ordinal][ForeignShort.ordinal] = new Data(
360 2, 6, ForeignShort, ForeignShort);
361 maps[StmEnum.Remove.ordinal][ForeignShort.ordinal][ForeignLong.ordinal] = new Data(
362 50, 0, ForeignShort, ForeignLong);
363 maps[StmEnum.Remove.ordinal][ForeignLong.ordinal][Local.ordinal] = new Data(
364 5, 2, ForeignLong, Local);
365 maps[StmEnum.Remove.ordinal][ForeignLong.ordinal][ForeignShort.ordinal] = new Data(
366 51, 0, ForeignLong, ForeignShort);
367 maps[StmEnum.Remove.ordinal][ForeignLong.ordinal][ForeignLong.ordinal] = new Data(
368 7, 2, ForeignLong, ForeignLong);
371 static Data getData(StmEnum s, ClusterEnum a, ClusterEnum b) {
372 return maps[s.ordinal][a.ordinal][b.ordinal];
373 // return maps.get(s).get(a).get(b);
378 Create((byte) 52), Set((byte) 53), SetShort((byte) 56), Delete(
379 (byte) 54), Modify((byte) 55);
384 public byte getOrMask() {