summaryrefslogtreecommitdiff
path: root/src/main/java/core
diff options
context:
space:
mode:
authorPaul Buetow <paul@buetow.org>2025-06-06 08:02:52 +0300
committerPaul Buetow <paul@buetow.org>2025-06-06 08:02:52 +0300
commit1d99762c7965d351510cfb5e08eac25e48d96038 (patch)
treef469493e911878ab9055ccf0494211bf9015922d /src/main/java/core
parent4d35597bd92607c4d194686e20b125044506c79a (diff)
Modernize project structure, update Maven config, move sources, add logging config, update README and .gitignore
Diffstat (limited to 'src/main/java/core')
-rw-r--r--src/main/java/core/VSAbstractProcess.java738
-rw-r--r--src/main/java/core/VSInternalProcess.java435
-rw-r--r--src/main/java/core/VSMessage.java182
-rw-r--r--src/main/java/core/VSMessageStub.java30
-rw-r--r--src/main/java/core/VSTask.java503
-rw-r--r--src/main/java/core/VSTaskManager.java562
-rw-r--r--src/main/java/core/time/VSLamportTime.java50
-rw-r--r--src/main/java/core/time/VSTime.java22
-rw-r--r--src/main/java/core/time/VSVectorTime.java96
9 files changed, 2618 insertions, 0 deletions
diff --git a/src/main/java/core/VSAbstractProcess.java b/src/main/java/core/VSAbstractProcess.java
new file mode 100644
index 0000000..78e7844
--- /dev/null
+++ b/src/main/java/core/VSAbstractProcess.java
@@ -0,0 +1,738 @@
+package core;
+
+import java.awt.Color;
+import java.io.IOException;
+import java.io.ObjectInputStream;
+import java.io.ObjectOutputStream;
+import java.util.ArrayList;
+
+import core.time.VSLamportTime;
+import core.time.VSTime;
+import core.time.VSVectorTime;
+import prefs.VSPrefs;
+import prefs.VSSerializablePrefs;
+import protocols.VSAbstractProtocol;
+import serialize.VSSerialize;
+import simulator.VSLogging;
+import simulator.VSSimulatorVisualization;
+import utils.VSPriorityQueue;
+import utils.VSRandom;
+import utils.VSTools;
+
+/**
+ * The class VSAbstractProcess, an object of this class represents a process
+ * of a simulator.
+ *
+ * @author Paul C. Buetow
+ */
+public abstract class VSAbstractProcess extends VSSerializablePrefs {
+ /** The data serialization id. */
+ protected static final long serialVersionUID = 1L;
+
+ /** The protocols to reset if the simulator is over or the reset
+ * button has been pressed.
+ */
+ protected ArrayList<VSAbstractProtocol> protocolsToReset;
+
+ /** The crash history. represents all crashes of the process using the
+ * global simulator time.
+ */
+ protected ArrayList<Long> crashHistory;
+
+ /** The lamport time history. */
+ protected ArrayList<VSLamportTime> lamportTimeHistory;
+
+ /** The vector time history. */
+ protected ArrayList<VSVectorTime> vectorTimeHistory;
+
+ /** The color used if the process has crashed. */
+ protected Color crashedColor;;
+
+ /** The process' current color. */
+ protected Color currentColor;
+
+ /** A temp. color. For internal usage. */
+ protected Color tmpColor;
+
+ /** The loging object. */
+ protected VSLogging loging;
+
+ /** The simulator's default prefs. */
+ protected VSPrefs prefs;
+
+ /** The random generator of the process. */
+ protected VSRandom random;
+
+ /** The simulator canvas. */
+ protected VSSimulatorVisualization simulatorVisualization;
+
+ /** The random crash task. May be null if there is no such random task. */
+ protected VSTask randomCrashTask;
+
+ /** The vector time. */
+ protected VSVectorTime vectorTime;
+
+ /** The tasks of the process. DO ONLY MANIPULATE THIS OBJECT WITHIN THE
+ * VSTaskManager CLASS! OTHERWISE THE SYNCHRONIZATION IS WRONG! Use the
+ * VSAbstractProcess.getTasks() method to get a reference to this object
+ * within the VSTaskManager! */
+ protected VSPriorityQueue<VSTask> tasks;
+
+ /** The process has crashed. But may be working again. */
+ protected boolean hasCrashed;
+
+ /** The process has started. But may be paused or crashed.. */
+ protected boolean hasStarted;
+
+ /** The process is crashed. */
+ protected boolean isCrashed;
+
+ /** The process is highlighted. */
+ protected boolean isHighlighted;
+
+ /** The process is paused. */
+ protected boolean isPaused;
+
+ /** The time has been modified in a task. Needed by the task manager to
+ * calculate correct offsets.
+ */
+ protected boolean timeModified;
+
+ /** The clock offset. Used by the task manager and also by the process'
+ * clock variance.
+ */
+ protected double clockOffset;
+
+ /** The clock variance. */
+ protected float clockVariance;
+
+ /** The process id. */
+ protected int processID;
+
+ /** The process num. It is different to the process id. It represents the
+ * array index of there the process is stored at.
+ */
+ protected int processNum;
+
+ /** The global time. */
+ protected long globalTime;
+
+ /** The lamport time. */
+ protected long lamportTime;
+
+ /** The local time. */
+ protected long localTime;
+
+ /** The Constant DEFAULT_INTEGER_VALUE_KEYS.
+ * This array contains all Integer prefs of the process which should show
+ * up in the prefs menu! All keys which dont start with "sim." only show
+ * up in the extended prefs menu!
+ */
+ protected static final String DEFAULT_INTEGER_VALUE_KEYS[] = {
+ "process.prob.crash",
+ "message.prob.outage",
+ };
+
+ /** The Constant DEFAULT_LONG_VALUE_KEYS.
+ * This array contains all Long prefs of the process which should show
+ * up in the prefs menu! All keys which dont start with "sim." only show
+ * up in the extended prefs menu!
+ */
+ protected static final String DEFAULT_LONG_VALUE_KEYS[] = {
+ "message.sendingtime.min",
+ "message.sendingtime.max",
+ };
+
+ /** The Constant DEFAULT_FLOAT_VALUE_KEYS.
+ * This array contains all Float prefs of the process which should show
+ * up in the prefs menu! All keys which dont start with "sim." only show
+ * up in the extended prefs menu!
+ */
+ protected static final String DEFAULT_FLOAT_VALUE_KEYS[] = {
+ "process.clock.variance",
+ };
+
+ /** The Constant DEFAULT_COLOR_VALUE_KEYS.
+ * This array contains all Color prefs of the process which should show
+ * up in the prefs menu! All keys which dont start with "sim." only show
+ * up in the extended prefs menu!
+ */
+ protected static final String DEFAULT_COLOR_VALUE_KEYS[] = {
+ "col.process.default",
+ "col.process.running",
+ "col.process.stopped",
+ "col.process.highlight",
+ "col.process.crashed",
+ };
+
+ /** The Constant DEFAULT_STRING_VALUE_KEYS.
+ * This array contains all String prefs of the process which should show
+ * up in the prefs menu! All keys which dont start with "sim." only show
+ * up in the extended prefs menu!
+ */
+ protected static final String DEFAULT_STRING_VALUE_KEYS[] = {
+ };
+
+ /**
+ * Instantiates a new process.
+ *
+ * @param prefs the simulator's default prefs
+ * @param processNum the process num
+ * @param simulatorVisualization the simulator canvas
+ * @param loging the loging object
+ */
+ public VSAbstractProcess(VSPrefs prefs, int processNum,
+ VSSimulatorVisualization simulatorVisualization,
+ VSLogging loging) {
+ init(prefs, processNum, simulatorVisualization, loging);
+ }
+
+ /**
+ * Inits a the process.
+ *
+ * @param prefs the simulator's default prefs
+ * @param processNum the process num
+ * @param simulatorVisualization the simulator canvas
+ * @param loging the loging object
+ */
+ protected void init(VSPrefs prefs, int processNum,
+ VSSimulatorVisualization simulatorVisualization,
+ VSLogging loging) {
+ /* May be not null if called from deserialization */
+ if (this.protocolsToReset == null)
+ this.protocolsToReset = new ArrayList<VSAbstractProtocol>();
+
+ this.processNum = processNum;
+ this.prefs = prefs;
+ this.simulatorVisualization = simulatorVisualization;
+ this.loging = loging;
+
+ processID = simulatorVisualization.processIDCount();
+ random = new VSRandom(processID*processNum+processID+processNum);
+ tasks = new VSPriorityQueue<VSTask>();
+
+ initTimeFormats();
+
+ isPaused = true;
+
+ /* Create the super.VSPrefs with it's default prefs */
+ fillWithDefaults();
+
+ /* Make local copys in order to have more performance */
+ clockVariance = getFloat("process.clock.variance");
+ currentColor = getColor("col.process.default");
+ crashedColor = getColor("col.process.crashed");
+
+ /* Make additional process settings editable through GUI */
+ initLong("process.localtime", localTime,
+ prefs.getString("lang.process.time.local"), "ms");
+
+ createRandomCrashTask_();
+ }
+
+ /**
+ * Inits the time formats. E.g. lamport and vector time stamps.
+ */
+ protected void initTimeFormats() {
+ lamportTime = 0;
+ lamportTimeHistory = new ArrayList<VSLamportTime>();
+
+ vectorTime = new VSVectorTime(0);
+ vectorTimeHistory = new ArrayList<VSVectorTime>();
+ crashHistory = new ArrayList<Long>();
+
+ final int numProcesses = simulatorVisualization.getNumProcesses();
+ for (int i = 0; i < numProcesses; ++i)
+ vectorTime.add(Long.valueOf(0));
+ }
+
+ /**
+ * Reset time formats. E.g. lamport and vector time stamps.
+ */
+ protected void resetTimeFormats() {
+ lamportTime = 0;
+ lamportTimeHistory.clear();
+
+ vectorTime = new VSVectorTime(0);
+ vectorTimeHistory.clear();
+ crashHistory.clear();
+
+ final int numProcesses = simulatorVisualization.getNumProcesses();
+ for (int i = numProcesses; i > 0; --i)
+ vectorTime.add(Long.valueOf(0));
+ }
+
+ /**
+ * Creates a random percentage 0..100 using the process' own pseudo
+ * random number generator object of the VSRandom class.
+ *
+ * @return A random percentage 0..100.
+ */
+ public synchronized int getRandomPercentage() {
+ return random.nextInt() % 101;
+ }
+
+ /**
+ * Adds the clock offset. This method is used by the task manager. The
+ * clock offset identifies if the local time of the process has changed and
+ * how much..
+ *
+ * @param add the clock offset to add.
+ */
+ protected synchronized void addClockOffset(long add) {
+ this.clockOffset += add;
+ }
+
+ /**
+ * Gets the process id.
+ *
+ * @return the process id
+ */
+ public synchronized int getProcessID() {
+ return processID;
+ }
+
+ /**
+ * Gets the process num. The num is different to the process id. It
+ * represents the array index of there the process is stored at.
+ *
+ * @return the process num
+ */
+ public synchronized int getProcessNum() {
+ return processNum;
+ }
+
+ /**
+ * Sets the process id.
+ *
+ * @param processID the new process id
+ */
+ public synchronized void setProcessID(int processID) {
+ this.processID = processID;
+ }
+
+ /**
+ * Gets the process' local time.
+ *
+ * @return the process' local time
+ */
+ public synchronized long getTime() {
+ return localTime;
+ }
+
+ /**
+ * Sets the process' local time.
+ *
+ * @param time the new local time of the process.
+ */
+ public synchronized void setTime(final long time) {
+ if (time >= 0)
+ this.localTime = time;
+ else
+ this.localTime = 0;
+
+ this.timeModified = true;
+ }
+
+ /**
+ * Checks if the process is crashed.
+ *
+ * @return true, if is crashed
+ */
+ public synchronized boolean isCrashed() {
+ return isCrashed;
+ }
+
+ /**
+ * Sets if the process is crashed.
+ *
+ * @param isCrashed true if the process is crashed.
+ */
+ public synchronized void isCrashed(boolean isCrashed) {
+ this.isCrashed = isCrashed;
+ crashHistory.add(Long.valueOf(globalTime));
+ if (!hasCrashed)
+ hasCrashed = true;
+ }
+
+ /**
+ * Checks if the process has crashed. The difference to isCrashed is,
+ * that the process may be fully functional again after crashing. This
+ * method is needed by the simulator canvas in order to see if it should
+ * paint 'crashed areas' using the crash history of this process.
+ *
+ * @return true, if yes
+ */
+ public synchronized boolean hasCrashed() {
+ return hasCrashed;
+ }
+
+ /**
+ * Gets the global time.
+ *
+ * @return the global time
+ */
+ public synchronized long getGlobalTime() {
+ return globalTime;
+ }
+
+ /**
+ * Gets the clock variance.
+ *
+ * @return the clock variance
+ */
+ public synchronized float getClockVariance() {
+ return clockVariance;
+ }
+
+ /**
+ * Sets the clock variance.
+ *
+ * @param clockVariance the new clock variance
+ */
+ public synchronized void setClockVariance(float clockVariance) {
+ /* If negative, only allow < 1 prefs */
+ if (clockVariance < 0) {
+ int part = (int) -clockVariance;
+ if (part > 0) {
+ this.clockVariance = 0;
+ return;
+ }
+ }
+
+ this.clockVariance = clockVariance;
+ }
+
+ /**
+ * Gets the a random crash time.
+ *
+ * @return the a random crash time. It will be -1 if the process will not
+ * crash at all randomly!
+ */
+ protected long getARandomCrashTime() {
+ /* Check if the process will crash or not */
+ if (getRandomPercentage() < getInteger("process.prob.crash")) {
+ /* Calculate the random crash time! */
+ final long crashTime =
+ random.nextLong(simulatorVisualization.getUntilTime()+1) %
+ simulatorVisualization.getUntilTime();
+ return crashTime;
+ }
+
+ /* No crash */
+ return -1;
+ }
+
+ /**
+ * Increases the process' lamport time.
+ */
+ public synchronized void increaseLamportTime() {
+ setLamportTime(getLamportTime()+1);
+ }
+
+ /**
+ * Updates the process' lamport time.
+ *
+ * @param time the lamport time to use as its update reference.
+ */
+ public synchronized void updateLamportTime(long time) {
+ final long lamportTime = getLamportTime() + 1;
+
+ if (time > lamportTime)
+ setLamportTime(time);
+ else
+ setLamportTime(lamportTime);
+ }
+
+ /**
+ * Gets the lamport time.
+ *
+ * @return the lamport time.
+ */
+ public synchronized long getLamportTime() {
+ return lamportTime;
+ }
+
+ /**
+ * Sets the lamport time.
+ *
+ * @param lamportTime the new lamport time
+ */
+ public synchronized void setLamportTime(long lamportTime) {
+ this.lamportTime = lamportTime;
+ lamportTimeHistory.add(new VSLamportTime(globalTime, lamportTime));
+ }
+
+ /**
+ * Gets the lamport time history as an array.
+ *
+ * @return the lamport time history array
+ */
+ public synchronized VSTime[] getLamportTimeArray() {
+ final int size = lamportTimeHistory.size();
+ final VSTime[] arr = new VSLamportTime[size];
+
+ for (int i = 0; i < size; ++i)
+ arr[i] = (VSTime) lamportTimeHistory.get(i);
+
+ return arr;
+ }
+
+ /**
+ * Increases the vector and the lamport time by 1 each if
+ * sim.update.vectortime.all/sim.update.lamporttime.all are set
+ * to true.
+ */
+ public void increaseVectorAndLamportTimeIfAll() {
+ if (prefs.getBoolean("sim.update.lamporttime.all"))
+ increaseLamportTime();
+
+ if (prefs.getBoolean("sim.update.vectortime.all"))
+ increaseVectorTime();
+ }
+
+ /**
+ * Increases the vector time by 1.
+ */
+ public synchronized void increaseVectorTime() {
+ vectorTime.set(processNum,
+ Long.valueOf(vectorTime.get(processNum).longValue()+1));
+ vectorTime.setGlobalTime(globalTime);
+ vectorTimeHistory.add(vectorTime.getCopy());
+ }
+
+ /**
+ * Updates the vector time.
+ *
+ * @param vectorTimeUpdate the vector time of the other process to use for
+ * the update
+ */
+ public synchronized void updateVectorTime(VSVectorTime vectorTimeUpdate) {
+ final int size = vectorTime.size();
+
+ for (int i = 0; i < size; ++i) {
+ if (i == processNum)
+ vectorTime.set(i, Long.valueOf(vectorTime.get(i).longValue()+1));
+ else if (vectorTimeUpdate.get(i) > vectorTime.get(i))
+ vectorTime.set(i, vectorTimeUpdate.get(i));
+ }
+
+ vectorTime.setGlobalTime(globalTime);
+ vectorTimeHistory.add(vectorTime.getCopy());
+ }
+
+ /**
+ * Gets the vector time.
+ *
+ * @return the vector time
+ */
+ public synchronized VSVectorTime getVectorTime() {
+ return vectorTime;
+ }
+
+ /**
+ * Gets the vector time history as an array.
+ *
+ * @return the vector time history array
+ */
+ public synchronized VSTime[] getVectorTimeArray() {
+ final int size = vectorTimeHistory.size();
+ final VSTime[] arr = new VSTime[size];
+
+ for (int i = 0; i < size; ++i)
+ arr[i] = (VSTime) vectorTimeHistory.get(i);
+
+ return arr;
+ }
+
+ /**
+ * Gets the crash history array.
+ *
+ * @return the crash history array
+ */
+ public synchronized Long[] getCrashHistoryArray() {
+ final int size = crashHistory.size();
+ final Long[] arr = new Long[size];
+
+ for (int i = 0; i < size; ++i)
+ arr[i] = crashHistory.get(i);
+
+ return arr;
+ }
+
+ /**
+ * Logg a message to the loging area.
+ *
+ * @param message the message to log
+ */
+ public void log(String message) {
+ loging.log(toString() + "; " + message, globalTime);
+ }
+
+ /* (non-Javadoc)
+ * @see prefs.VSPrefs#fillWithDefaults()
+ */
+ public void fillWithDefaults() {
+ prefs.copyIntegers(this, DEFAULT_INTEGER_VALUE_KEYS);
+ prefs.copyLongs(this, DEFAULT_LONG_VALUE_KEYS);
+ prefs.copyFloats(this, DEFAULT_FLOAT_VALUE_KEYS);
+ prefs.copyColors(this, DEFAULT_COLOR_VALUE_KEYS);
+ prefs.copyStrings(this, DEFAULT_STRING_VALUE_KEYS);
+ }
+
+ /* (non-Javadoc)
+ * @see prefs.VSPrefs#toString()
+ */
+ public synchronized String toString() {
+ StringBuffer buffer = new StringBuffer();
+ buffer.append(prefs.getString("lang.process.id"));
+ buffer.append(": ");
+ buffer.append(getProcessID());
+ buffer.append("; ");
+ buffer.append(prefs.getString("lang.process.time.local"));
+ buffer.append(": ");
+ buffer.append(VSTools.getTimeString(getTime()));
+ buffer.append("; ");
+ buffer.append(prefs.getString("lang.time.lamport"));
+ buffer.append(": ");
+ buffer.append(lamportTime);
+ buffer.append("; ");
+ buffer.append(prefs.getString("lang.time.vector"));
+ buffer.append(": ");
+ buffer.append(vectorTime);
+ return buffer.toString();
+ }
+
+ /**
+ * The extended string representation of the process object.
+ *
+ * @return the extended string representation
+ */
+ public synchronized String toStringFull() {
+ StringBuffer buffer = new StringBuffer();
+ buffer.append(toString());
+ buffer.append("; paused: ");
+ buffer.append(isPaused);
+ buffer.append("; crashed: ");
+ buffer.append(isCrashed);
+ buffer.append("; crashTask: ");
+ buffer.append(randomCrashTask);
+ return buffer.toString();
+ }
+
+ /**
+ * Equals. Checks, if both processes have the same process num.
+ *
+ * @param process the process to compare to
+ *
+ * @return true, if both processes are the same (same processNum).
+ */
+ public boolean equals(VSAbstractProcess process) {
+ return process.getProcessNum() == processNum;
+ }
+
+ /**
+ * Gets the simulator's default prefs.
+ *
+ * @return the default prefs
+ */
+ public VSPrefs getPrefs() {
+ return prefs;
+ }
+
+ /* (non-Javadoc)
+ * @see serialize.VSSerializable#serialize(serialize.VSSerialize,
+ * java.io.ObjectOutputStream)
+ */
+ public synchronized void serialize(VSSerialize serialize,
+ ObjectOutputStream objectOutputStream)
+ throws IOException {
+ super.serialize(serialize, objectOutputStream);
+
+ if (VSSerialize.DEBUG)
+ System.out.println("Serializing: VSAbstractProcess (num: "
+ + processNum
+ + "; id: " + processID + ")");
+
+ /** For later backwards compatibility, to add more stuff */
+ objectOutputStream.writeObject(Boolean.valueOf(false));
+
+ objectOutputStream.writeObject(Integer.valueOf(processID));
+ objectOutputStream.writeObject(Integer.valueOf(protocolsToReset.size()));
+ for (VSAbstractProtocol protocol : protocolsToReset) {
+ objectOutputStream.writeObject(protocol.getClassname());
+ protocol.serialize(serialize, objectOutputStream);
+ }
+
+ /** For later backwards compatibility, to add more stuff */
+ objectOutputStream.writeObject(Boolean.valueOf(false));
+ }
+
+ /* (non-Javadoc)
+ * @see serialize.VSSerializable#deserialize(serialize.VSSerialize,
+ * java.io.ObjectInputStream)
+ */
+ public synchronized void deserialize(VSSerialize serialize,
+ ObjectInputStream objectInputStream)
+ throws IOException, ClassNotFoundException {
+ super.deserialize(serialize, objectInputStream);
+
+ /* Bugfix, being compatible with old versions */
+ super.deleteLong("process.localTime");
+
+ updateFromPrefs_();
+
+ if (VSSerialize.DEBUG)
+ System.out.println("Deserializing: VSAbstractProcess");
+
+ /** For later backwards compatibility, to add more stuff */
+ objectInputStream.readObject();
+
+ this.processID = ((Integer)
+ objectInputStream.readObject()).intValue();
+ int numProtocols = ((Integer)
+ objectInputStream.readObject()).intValue();
+
+ for (int i = 0; i < numProtocols; ++i) {
+ String protocolClassname = (String) objectInputStream.readObject();
+ VSAbstractProtocol protocol = getProtocolObject_(protocolClassname);
+ protocol.deserialize(serialize, objectInputStream);
+ }
+
+ localTime = 0;
+ setLong("process.localtime", localTime);
+
+ /** For later backwards compatibility, to add more stuff */
+ objectInputStream.readObject();
+
+ serialize.setObject(processNum, "process", this);
+ }
+
+ /**
+ * Sets the current color.
+ *
+ * @param newColor the new current color
+ */
+ protected void setCurrentColor(Color newColor) {
+ if (isHighlighted)
+ tmpColor = newColor;
+ else
+ currentColor = newColor;
+ }
+
+ /* (non-Javadoc)
+ * @see core.VSInternalMessage#updateFromPrefs()
+ */
+ protected abstract void updateFromPrefs_();
+
+ /* (non-Javadoc)
+ * @see core.VSInternalMessage#createRandomCrashTask()
+ */
+ protected abstract void createRandomCrashTask_();
+
+ /* (non-Javadoc)
+ * @see core.VSInternalMessage#getProtocolObjekt(java.util.String)
+ */
+ protected abstract VSAbstractProtocol getProtocolObject_(
+ String protocolClassname);
+}
diff --git a/src/main/java/core/VSInternalProcess.java b/src/main/java/core/VSInternalProcess.java
new file mode 100644
index 0000000..81cc3fd
--- /dev/null
+++ b/src/main/java/core/VSInternalProcess.java
@@ -0,0 +1,435 @@
+package core;
+
+import java.awt.Color;
+
+import core.time.VSVectorTime;
+import events.VSAbstractEvent;
+import events.VSRegisteredEvents;
+import events.implementations.VSProcessCrashEvent;
+import prefs.VSPrefs;
+import protocols.VSAbstractProtocol;
+import simulator.VSLogging;
+import simulator.VSSimulatorVisualization;
+import utils.VSPriorityQueue;
+
+/**
+ * The class VSInternalProcess, an object of this class represents a process
+ * of a simulator.
+ *
+ * @author Paul C. Buetow
+ */
+public class VSInternalProcess extends VSAbstractProcess {
+ /**
+ * Instantiates a new process.
+ *
+ * @param prefs the simulator's default prefs
+ * @param processNum the process num
+ * @param simulatorVisualization the simulator canvas
+ * @param loging the loging object
+ */
+ public VSInternalProcess(VSPrefs prefs, int processNum,
+ VSSimulatorVisualization simulatorVisualization,
+ VSLogging loging) {
+ super(prefs, processNum, simulatorVisualization, loging);
+ }
+
+ /**
+ * Called from the VSProcessEditor, after finishing editing! This makes
+ * sure that the VSInternalProcess object is using the up to date prefs!
+ */
+ public synchronized void updateFromPrefs() {
+ setClockVariance(getFloat("process.clock.variance"));
+ setLocalTime(getLong("process.localtime"));
+ crashedColor = getColor("col.process.crashed");
+ createRandomCrashTask();
+ }
+
+ /**
+ * Called from the VSProcessEditor, before starting editing! This makes
+ * sure that the editor edits the up to date prefs of the process!
+ */
+ public synchronized void updatePrefs() {
+ setFloat("process.clock.variance", getClockVariance());
+ setLong("process.localtime", getTime());
+ }
+
+ /**
+ * Syncs the process' time. This method is using the clockOffset and
+ * clockVariance variables. This method is called repeatedly from the
+ * VSSimulatorVisualization in order to update the process' local and global
+ * time values.
+ *
+ * @param globalTime the global time.
+ */
+ public synchronized void syncTime(final long globalTime) {
+ final long currentGlobalTimestep = globalTime - this.globalTime;
+ this.globalTime = globalTime;
+
+ localTime += currentGlobalTimestep;
+ clockOffset += currentGlobalTimestep * (double) clockVariance;
+
+ while (clockOffset >= 1) {
+ clockOffset -= 1;
+ ++localTime;
+ }
+
+ while (clockOffset <= -1) {
+ clockOffset += 1;
+ --localTime;
+ }
+
+ /* We do not want a negative time */
+ if (localTime < 0)
+ localTime = 0;
+ }
+
+ /**
+ * Highlights the process.
+ */
+ public synchronized void highlightOn() {
+ tmpColor = currentColor;
+ currentColor = getColor("col.process.highlight");
+ isHighlighted = true;
+ }
+
+ /**
+ * Unhighlights the process.
+ */
+ public synchronized void highlightOff() {
+ currentColor = tmpColor;
+ isHighlighted = false;
+ }
+
+ /**
+ * Resets the process.
+ */
+ public synchronized void reset() {
+ isPaused = true;
+ isCrashed = false;
+ hasCrashed = false;
+ localTime = 0;
+ globalTime = 0;
+ clockOffset = 0;
+
+ for (VSAbstractProtocol protocol : protocolsToReset)
+ protocol.reset();
+
+ setCurrentColor(getColor("col.process.default"));
+ resetTimeFormats();
+ }
+
+ /**
+ * Creates the random crash task. The crash task will be created only if
+ * the process is not crashed atm. and if
+ * VSInternalProcess.getARandomCrashTime() * returns a non-negative value.
+ * The random crash task uses the simulaion's global time for its
+ * scheduling.
+ */
+ public synchronized void createRandomCrashTask() {
+ if (!isCrashed) {
+ VSTaskManager taskManager = simulatorVisualization.getTaskManager();
+ long crashTime = getARandomCrashTime();
+
+ if (crashTime < 0)
+ return;
+
+ if (randomCrashTask != null)
+ taskManager.removeTask(randomCrashTask);
+
+ if (crashTime >= getGlobalTime()) {
+ VSAbstractEvent event = new VSProcessCrashEvent();
+ randomCrashTask = new VSTask(crashTime, this, event,
+ VSTask.GLOBAL);
+ taskManager.addTask(randomCrashTask);
+
+ } else {
+ randomCrashTask = null;
+ }
+ }
+ }
+
+ /**
+ * Creates a random percentage 0..100 using the process' own pseudo
+ * random number generator object of the VSRandom class.
+ *
+ * @return A random percentage 0..100.
+ */
+ public synchronized int getRandomPercentage() {
+ return random.nextInt() % 101;
+ }
+
+ /**
+ * Adds the clock offset. This method is used by the task manager. The
+ * clock offset identifies if the local time of the process has changed and
+ * how much..
+ *
+ * @param add the clock offset to add.
+ */
+ public synchronized void addClockOffset(long add) {
+ this.clockOffset += add;
+ }
+
+ /**
+ * The process' state is 'play'. Called by the simulator canvas.
+ */
+ public synchronized void play() {
+ isPaused = false;
+ setCurrentColor(getColor("col.process.running"));
+ }
+
+ /**
+ * The process' state is 'pause'. Called by the simulator canvas.
+ */
+ public synchronized void pause() {
+ isPaused = true;
+ setCurrentColor(getColor("col.process.stopped"));
+ }
+
+ /**
+ * The process' state is 'Finish'. Called by the simulator canvas.
+ */
+ public synchronized void finish() {
+ isPaused = true;
+ setCurrentColor(getColor("col.process.default"));
+ }
+
+ /**
+ * Gets the current process' color.
+ *
+ * @return the current color of the process.
+ */
+ public synchronized Color getColor() {
+ return currentColor;
+ }
+
+ /**
+ * Gets the color of this process if it's crashed.
+ *
+ * @return the crashed color
+ */
+ public synchronized Color getCrashedColor() {
+ return crashedColor;
+ }
+
+ /**
+ * Checks if the time has been modified. by a task.
+ * This mehod is needed by the task manager in order to add a clock offset
+ * to the process object.
+ *
+ * @return true, if yes
+ */
+ public synchronized boolean timeModified() {
+ return timeModified;
+ }
+
+ /**
+ * Sets if the time has been modified by a task.
+ *
+ * @param timeModified true, if it has been modified.
+ */
+ public synchronized void timeModified(boolean timeModified) {
+ this.timeModified = timeModified;
+ }
+
+ /**
+ * Sets the global time.
+ *
+ * @param globalTime the new global time
+ */
+ public synchronized void setGlobalTime(final long globalTime) {
+ this.globalTime = globalTime >= 0 ? globalTime : 0;
+ }
+
+ /* Gets the duration time of a message to send.
+ *
+ * @return the duration time
+ */
+ public synchronized long getDurationTime() {
+ final long maxDurationTime = getLong("message.sendingtime.max");
+ final long minDurationTime = getLong("message.sendingtime.min");
+
+ if (maxDurationTime <= minDurationTime)
+ return minDurationTime;
+
+ final int diff = (int) (maxDurationTime - minDurationTime);
+
+ /* Integer overflow */
+ if (diff <= 0)
+ return minDurationTime;
+
+ return minDurationTime + random.nextInt(diff+1);
+ }
+
+ /**
+ * Gets the a random message outage time.
+ *
+ * @param durationTime the duration time
+ *
+ * @return the a random message outage time. It will be -1 if the message
+ * will not get lost at all.
+ */
+ public synchronized long getARandomMessageOutageTime(long durationTime,
+ VSInternalProcess receiverProcess) {
+ int percentage = (int) ((getInteger("message.prob.outage") +
+ receiverProcess.getInteger(
+ "message.prob.outage")) / 2);
+
+ /* Check if the message will have an outage or not */
+ if (getRandomPercentage() < percentage) {
+
+ /* Calculate the random outage time! */
+ long outageTime = globalTime + random.nextLong(durationTime+1) %
+ simulatorVisualization.getUntilTime();
+
+ return outageTime;
+ }
+
+ /* No outage */
+ return -1;
+ }
+
+ /**
+ * Gets the random crash task.
+ *
+ * @return the random crash task
+ */
+ public synchronized VSTask getCrashTask() {
+ return randomCrashTask;
+ }
+
+ /**
+ * Checks if the process is paused.
+ *
+ * @return true, if is paused
+ */
+ public synchronized boolean isPaused() {
+ return isPaused;
+ }
+
+ /**
+ * Called by a task if the process sends a message.
+ *
+ * @param message the message to send.
+ */
+ public synchronized void sendMessage(VSMessage message) {
+ StringBuffer buffer = new StringBuffer();
+ buffer.append(prefs.getString("lang.message.sent"));
+ buffer.append("; ");
+ buffer.append(message.toStringFull());
+ log(buffer.toString());
+ simulatorVisualization.sendMessage(message);
+ }
+
+ /**
+ * Gets the simulator canvas.
+ *
+ * @return the simulator canvas
+ */
+ public VSSimulatorVisualization getSimulatorCanvas() {
+ return simulatorVisualization;
+ }
+
+ /**
+ * Removes the process at the specified index. Called by the simulator
+ * canvas if a process has been removed from the simulator. Needed in
+ * order to update the vector time and the local processNum.
+ *
+ * @param index the index the process has to get removed.
+ */
+ public synchronized void removedAProcessAtIndex(int index) {
+ if (index < processNum)
+ --processNum;
+
+ vectorTime.remove(index);
+ for (VSVectorTime vectorTime : vectorTimeHistory)
+ vectorTime.remove(index);
+ }
+
+ /**
+ * Added a process. Needed in order to update the vector time's size.
+ * Called by the simulator canvas if a process has been added to the
+ * simulator.
+ */
+ public synchronized void addedAProcess() {
+ vectorTime.add(Long.valueOf(0));
+ for (VSVectorTime vectorTime : vectorTimeHistory)
+ vectorTime.add(Long.valueOf(0));
+ }
+
+ /**
+ * Gets the tasks of the process.
+ *
+ * @return The tasks
+ */
+ public VSPriorityQueue<VSTask> getTasks() {
+ return tasks;
+ }
+
+ /**
+ * Sets the tasks of the process.
+ *
+ * @param tasks The tasks
+ */
+ public void setTasks(VSPriorityQueue<VSTask> tasks) {
+ this.tasks = tasks;
+ }
+
+ /**
+ * Gets the protocol object.
+ *
+ * @param protocolClassname the protocol classname
+ *
+ * @return the protocol object
+ */
+ public synchronized VSAbstractProtocol getProtocolObject(
+ String protocolClassname) {
+ VSAbstractProtocol protocol = null;
+
+ if (!objectExists(protocolClassname)) {
+ protocol = (VSAbstractProtocol)
+ VSRegisteredEvents.createEventInstanceByClassname(
+ protocolClassname, this);
+
+ setObject(protocolClassname, protocol);
+ protocolsToReset.add(protocol);
+
+ } else {
+ protocol = (VSAbstractProtocol) getObject(protocolClassname);
+ }
+
+ return protocol;
+ }
+
+ /**
+ * Sets the local time.
+ *
+ * @param localTime the new local time.
+ */
+ public synchronized void setLocalTime(final long localTime) {
+ if (localTime >= 0)
+ this.localTime = localTime;
+ else
+ this.localTime = 0;
+ }
+
+ /* (non-Javadoc)
+ * @see core.VSInternalMessage#updateFromPrefs()
+ */
+ protected void updateFromPrefs_() {
+ updateFromPrefs();
+ }
+
+ /* (non-Javadoc)
+ * @see core.VSInternalMessage#createRandomCrashTask()
+ */
+ protected void createRandomCrashTask_() {
+ createRandomCrashTask();
+ }
+
+ /* (non-Javadoc)
+ * @see core.VSInternalMessage#getProtocolObjekt(java.util.String)
+ */
+ protected VSAbstractProtocol getProtocolObject_(String protocolClassname) {
+ return getProtocolObject(protocolClassname);
+ }
+}
diff --git a/src/main/java/core/VSMessage.java b/src/main/java/core/VSMessage.java
new file mode 100644
index 0000000..a7b48e6
--- /dev/null
+++ b/src/main/java/core/VSMessage.java
@@ -0,0 +1,182 @@
+package core;
+
+import core.time.VSVectorTime;
+import events.VSRegisteredEvents;
+import prefs.VSPrefs;
+
+/**
+ * An object of this class represents a message which is sent from one process
+ * to another process in the simulator.
+ *
+ * @author Paul C. Buetow
+ */
+public class VSMessage extends VSPrefs {
+ /** The constant IS_SERVER_MESSAGE. */
+ public static final boolean IS_SERVER_MESSAGE = true;
+
+ /** The constant IS_CLIENT_MESSAGE. */
+ public static final boolean IS_CLIENT_MESSAGE = false;
+
+ /** true, if the message has been sent from a server. false, if the message
+ * has been sent from a client.
+ */
+ private boolean isServerMessage;
+
+ /** Each message belongs to a specific protocol. This variable defined the
+ * class name of the protocol being used.
+ */
+ private String protocolClassname;
+
+ /** The default application preferences. */
+ private VSPrefs prefs;
+
+ /** A reference to the process who sent this message. */
+ private VSInternalProcess sendingProcess;
+
+ /** The vector time of the sending process after sending. The receiver
+ * process will use this vector time in order to update the local vector
+ * time.
+ */
+ private VSVectorTime vectorTime;
+
+ /** The lamport time of the sending process after sending. The receiver
+ * process will use this lamport time in order to update the local vector
+ * time.
+ */
+ private long lamportTime;
+
+ /** Each message has its own unique ID. The ID will show up in the loging
+ * window of the simulator
+ */
+ private long messageID;
+
+ /** This counter is used in order to generate unique message ID's. */
+ private static long messageCounter;
+
+ /**
+ * The constructor of the message. Creates a new message object.
+ */
+ public VSMessage() {
+ this.messageID = ++messageCounter;
+ }
+
+ /**
+ * Initializes the message.
+ *
+ * @param process The sending process of this message.
+ * @param protocolClassname The classname of the protocol this message.
+ * @param isServerMessage Sets if the message has been sent by a server.
+ */
+ void init(VSInternalProcess process, String protocolClassname,
+ boolean isServerMessage) {
+ this.sendingProcess = process;
+ this.protocolClassname = protocolClassname;
+ this.isServerMessage = isServerMessage;
+ this.prefs = process.getPrefs();
+
+ lamportTime = sendingProcess.getLamportTime();
+ vectorTime = sendingProcess.getVectorTime().getCopy();
+ }
+
+ /**
+ * Gets the protocol name of the message.
+ *
+ * @return The protocol name of the message.
+ */
+ public String getName() {
+ return VSRegisteredEvents.getNameByClassname(getProtocolClassname());
+ }
+
+ /**
+ * Gets the protocol classname.
+ *
+ * @return The protocol classname of the message.
+ */
+ public String getProtocolClassname() {
+ return protocolClassname;
+ }
+
+ /**
+ * Gets the message id.
+ *
+ * @return The id of the message.
+ */
+ public long getMessageID() {
+ return messageID;
+ }
+
+ /**
+ * Gets a reference of the sending process.
+ *
+ * @return The process which sent this message.
+ */
+ public VSAbstractProcess getSendingProcess() {
+ return sendingProcess;
+ }
+
+ /**
+ * Gets the lamport time.
+ *
+ * @return The lamport time of the sending process.
+ */
+ public long getLamportTime() {
+ return lamportTime;
+ }
+
+ /**
+ * Gets the vector time.
+ *
+ * @return The vector time of the sending process.
+ */
+ public VSVectorTime getVectorTime() {
+ return vectorTime;
+ }
+
+ /**
+ * Checks if the message has been sent by a server or a client.
+ *
+ * @return true, if the message has been sent by a server. false, if the
+ * message has been sent by a client.
+ */
+ public boolean isServerMessage() {
+ return isServerMessage;
+ }
+
+ /* (non-Javadoc)
+ * @see prefs.VSPrefs#toString()
+ */
+ public String toString() {
+ StringBuffer buffer = new StringBuffer();
+
+ buffer.append("ID: ");
+ buffer.append(messageID);
+ buffer.append("; ");
+ buffer.append(prefs.getString("lang.protocol"));
+ buffer.append(": ");
+ buffer.append(VSRegisteredEvents.getShortnameByClassname(
+ getProtocolClassname()));
+
+ return buffer.toString();
+ }
+
+ /**
+ * Extended string representation of the message object.
+ *
+ * @return Extended string representation of the message object.
+ */
+ public String toStringFull() {
+ return toString() + "; " + super.toString();
+ }
+
+ /**
+ * Compares two messages.
+ *
+ * @param message The message to compare with.
+ *
+ * @return true, if the messages have the same id. Otherwise false.
+ */
+ public boolean equals(VSMessage message) {
+ return messageID == message.getMessageID();
+ }
+}
+
diff --git a/src/main/java/core/VSMessageStub.java b/src/main/java/core/VSMessageStub.java
new file mode 100644
index 0000000..95a515b
--- /dev/null
+++ b/src/main/java/core/VSMessageStub.java
@@ -0,0 +1,30 @@
+package core;
+
+/**
+ * An object of this class represents a message stub. A message stub allows
+ * to run the init method on a VSMessage object. The init method should be
+ * hidden by the protocol programming API.
+ *
+ * @author Paul C. Buetow
+ */
+public class VSMessageStub {
+ /** The message */
+ private VSMessage message;
+
+ /**
+ * The constructor of the message stub. Creates a new message stub object.
+ *
+ * @param message the message
+ */
+ public VSMessageStub(VSMessage message) {
+ this.message = message;
+ }
+
+ /* (non-Javadoc)
+ * @see core.VSMessage#init(VSInternalProcess, java.util.String, boolean)
+ */
+ public void init(VSInternalProcess process, String protocolClassname,
+ boolean isServerMessage) {
+ message.init(process, protocolClassname, isServerMessage);
+ }
+}
diff --git a/src/main/java/core/VSTask.java b/src/main/java/core/VSTask.java
new file mode 100644
index 0000000..54d7ff1
--- /dev/null
+++ b/src/main/java/core/VSTask.java
@@ -0,0 +1,503 @@
+package core;
+
+import java.io.IOException;
+import java.io.ObjectInputStream;
+import java.io.ObjectOutputStream;
+
+import events.VSAbstractEvent;
+import events.VSRegisteredEvents;
+import events.implementations.VSProcessCrashEvent;
+import events.implementations.VSProcessRecoverEvent;
+import events.internal.VSAbstractInternalEvent;
+import events.internal.VSMessageReceiveEvent;
+import events.internal.VSProtocolEvent;
+import exceptions.VSEventNotCopyableException;
+import prefs.VSPrefs;
+import protocols.VSAbstractProtocol;
+//import utils.*;
+import serialize.VSNotSerializable;
+import serialize.VSSerializable;
+import serialize.VSSerialize;
+
+/**
+ * The class VSTask, an object of this class represents a task to do or done.
+ * All tasks are managed by the task manager. There are local and global timed
+ * tasks. Local timed tasks are being fullfilled if the process' local time is
+ * reached. Global timed tasks are being fullfilled if the simulator's time is
+ * reached.
+ *
+ * @author Paul C. Buetow
+ */
+public class VSTask implements Comparable<Object>, VSSerializable {
+ /** The Constant LOCAL. Used for the constructor if it's a local timed
+ * task.
+ */
+ public final static boolean LOCAL = true;
+
+ /** The Constant GLOBAL. Used for the constructor if it's a global timed
+ * task.
+ */
+ public final static boolean GLOBAL = false;
+
+ /** The task time. */
+ private long taskTime;
+
+ /** The event which takes plase if the task time matches. */
+ private VSAbstractEvent event;
+
+ /** The process to run the task at. */
+ private VSInternalProcess process;
+
+ /** The simulator's default prefs. */
+ private VSPrefs prefs;
+
+ /** The task is programmed. The task will be still in the task manager
+ * after reset.
+ */
+ private boolean isProgrammed;
+
+ /** The task is global timed. If set to true, its local timed. */
+ private boolean isGlobalTimed;
+
+ /** The task counter. Needed for the unique task numbers. */
+ private static int taskCounter;
+
+ /** The task number. */
+ private int taskNum;
+
+ /**
+ * Instantiates a new task.
+ *
+ * @param taskTime the task time
+ * @param process the process
+ * @param event the event
+ * @param isLocal the taks is local timed
+ */
+ public VSTask(long taskTime, VSInternalProcess process,
+ VSAbstractEvent event,
+ boolean isLocal) {
+ init(taskTime, process, event, isLocal);
+ }
+
+ /**
+ * Instantiates a new task, it's a copy constructor.
+ *
+ * @param task the task to copy
+ */
+ public VSTask(VSTask task) {
+ VSAbstractEvent event = task.getEvent();
+
+ try {
+ // Use the copy of the event object
+ event = event.getCopy();
+
+ } catch (VSEventNotCopyableException e) {
+ // Use the original event object
+ }
+
+ init(task.getTaskTime(),
+ task.getProcess(),
+ event,
+ !task.isGlobalTimed());
+ }
+
+ /**
+ * Instantiates a new task during a deserialization.
+ *
+ * @param serialize the serialize object
+ * @param objectInputStream The input stream
+ */
+ public VSTask(VSSerialize serialize, ObjectInputStream objectInputStream)
+ throws IOException, ClassNotFoundException {
+ deserialize(serialize, objectInputStream);
+ }
+
+ /**
+ * Inits the task
+ *
+ * @param taskTime the task time
+ * @param process the process
+ * @param event the event
+ * @param isLocal the taks is local timed
+ */
+ private void init(long taskTime, VSInternalProcess process,
+ VSAbstractEvent event, boolean isLocal) {
+ this.process = process;
+ this.taskTime = taskTime > 0 ? taskTime : 0;
+ /* May be not null if called from deserialization */
+ if (this.event == null)
+ this.event = event;
+ this.prefs = process.getPrefs();
+ this.isGlobalTimed = !isLocal;
+ this.taskNum = ++taskCounter;
+ }
+
+ /**
+ * Gets the task num.
+ *
+ * @return the task num
+ */
+ public int getTaskNum() {
+ return taskNum;
+ }
+
+ /**
+ * Sets if the task is programmed.
+ *
+ * @param isProgrammed true, if the task is programmed
+ */
+ public void isProgrammed(boolean isProgrammed) {
+ this.isProgrammed = isProgrammed;
+ }
+
+ /**
+ * Checks if the task is programmed.
+ *
+ * @return true, if the task is programmed
+ */
+ public boolean isProgrammed() {
+ return isProgrammed;
+ }
+
+ /**
+ * Checks if the task is using an "internal event".
+ *
+ * @return true, if the task is using an internal event
+ */
+ public boolean hasInternalEvent() {
+ return event instanceof VSAbstractInternalEvent;
+ }
+
+ /**
+ * Checks if the task should not get serialized.
+ *
+ * @return true, if the task should not get serialized
+ */
+ public boolean hasNotSerializableEvent() {
+ return event instanceof VSNotSerializable;
+ }
+
+ /**
+ * Checks if the task is a message receive event.
+ *
+ * @return true, if it is a message receive event
+ */
+ public boolean hasMessageReceiveEvent() {
+ return event instanceof VSMessageReceiveEvent;
+ }
+
+ /**
+ * Checks if the task is a process recover event.
+ *
+ * @return true, if it is a process recover event
+ */
+ public boolean hasProcessRecoverEvent() {
+ return event instanceof VSProcessRecoverEvent;
+ }
+
+ /**
+ * Checks if the task belongs to the specified protocol object.
+ *
+ * @param protocol the protocol object to check against.
+ *
+ * @return true, if it's a task using the protocol object.
+ */
+ public boolean isProtocol(VSAbstractProtocol protocol) {
+ if (event instanceof VSAbstractProtocol)
+ return ((VSAbstractProtocol) event).equals(protocol);
+
+ return false;
+ }
+
+ /**
+ * Checks if the task's time is over.
+ *
+ * @return true, if it's over
+ */
+ public boolean timeOver() {
+ if (isGlobalTimed)
+ return taskTime < process.getGlobalTime();
+
+ return taskTime < process.getTime();
+ }
+
+ /**
+ * Checks if the task equals to another task.
+ *
+ * @param task the task to compare to
+ *
+ * @return true, if equal (the task nums equal)
+ */
+ public boolean equals(VSTask task) {
+ return taskNum == task.getTaskNum();
+ }
+
+ /**
+ * Checks if the task belongs to the specified process.
+ *
+ * @param process the process to check against
+ *
+ * @return true, if the task is using the process
+ */
+ public boolean isProcess(VSInternalProcess process) {
+ return this.process.equals(process);
+ }
+
+ /**
+ * Checks if the task is global timed.
+ *
+ * @return true, if the taks is global timed
+ */
+ public boolean isGlobalTimed() {
+ return isGlobalTimed;
+ }
+
+ /**
+ * Gets the process.
+ *
+ * @return the process of the event
+ */
+ public VSInternalProcess getProcess() {
+ return process;
+ }
+
+ /**
+ * Runs the task.
+ */
+ public void run() {
+ if (event.getProcess() == null)
+ event.init(process);
+
+ if (!(event instanceof VSMessageReceiveEvent)
+ && !(event instanceof VSAbstractProtocol))
+ process.increaseVectorAndLamportTimeIfAll();
+
+ event.onStart();
+ }
+
+ /**
+ * Gets the task time.
+ *
+ * @return the task time
+ */
+ public long getTaskTime() {
+ return taskTime;
+ }
+
+ /**
+ * Sets the task time.
+ *
+ * @param taskTime the task time
+ */
+ public void setTaskTime(long taskTime) {
+ this.taskTime = taskTime;
+ }
+
+ /**
+ * Sets the process.
+ *
+ * @param process the process
+ */
+ public void setProcess(VSInternalProcess process) {
+ /* Only do it if the process differs */
+ if (!this.process.equals(process)) {
+ this.process = process;
+
+ try {
+ // Use the copy of the event object
+ event = event.getCopy(process);
+
+ } catch (VSEventNotCopyableException e) {
+ if (event instanceof VSAbstractProtocol) {
+ String eventShortname = event.getShortname();
+ event = process.getProtocolObject(event.getClassname());
+ event.setShortname(eventShortname);
+ } else {
+ System.out.println(e);
+ }
+ }
+ }
+ }
+
+ /**
+ * Gets the event.
+ *
+ * @return the event
+ */
+ public VSAbstractEvent getEvent() {
+ return event;
+ }
+
+ /*
+ private void log(String message) {
+ process.log(message);
+ }
+ */
+
+ /* (non-Javadoc)
+ * @see java.lang.Object#toString()
+ */
+ public String toString() {
+ StringBuffer buffer = new StringBuffer();
+
+ buffer.append(prefs.getString("lang.task"));
+ buffer.append(" ");
+ buffer.append(getTaskTime());
+ buffer.append(event.toString());
+ buffer.append("; PID: ");
+ buffer.append(process.getProcessID());
+ /*
+ if (isProgrammed()) {
+ buffer.append("; Programmed");
+ }
+ */
+
+ return buffer.toString();
+ }
+
+ /* (non-Javadoc)
+ * @see java.lang.Comparable#compareTo(java.lang.Object)
+ */
+ public int compareTo(Object object) {
+ if (object instanceof VSTask) {
+ final VSTask task = (VSTask) object;
+
+ if (taskTime < task.getTaskTime())
+ return -1;
+
+ else if (taskTime > task.getTaskTime())
+ return 1;
+
+ VSAbstractEvent event2 = task.getEvent();
+
+ /* If it's a recovering, it should get handled very first */
+ boolean a = event instanceof VSProcessRecoverEvent;
+ boolean b = event2 instanceof VSProcessRecoverEvent;
+
+ if (a && b)
+ return 0;
+
+ if (a)
+ return -1;
+
+ if (b)
+ return 1;
+
+ /* If it's a crash, it should get handled second first */
+ a = event instanceof VSProcessCrashEvent;
+ b = event2 instanceof VSProcessCrashEvent;
+
+ if (a && b)
+ return 0;
+
+ if (a)
+ return -1;
+
+ if (b)
+ return 1;
+
+ /* If it's a VSProtocolEvent, it should get handled third */
+ a = event instanceof VSProtocolEvent;
+ b = event2 instanceof VSProtocolEvent;
+
+ if (a && b)
+ return 0;
+
+ if (a)
+ return -1;
+
+ if (b)
+ return 1;
+
+ String shortname = event.getShortname();
+ String shortname2 = event2.getShortname();
+
+ /* One of those may be null if an VSAbstractEvent object has not
+ been initialized yet */
+ if (shortname == null || shortname2 == null)
+ return 0;
+
+ return shortname.compareTo(shortname2);
+ }
+
+ return 0;
+ }
+
+ /* (non-Javadoc)
+ * @see serialize.VSSerializable#serialize(serialize.VSSerialize,
+ * java.io.ObjectOutputStream)
+ */
+ public synchronized void serialize(VSSerialize serialize,
+ ObjectOutputStream objectOutputStream)
+ throws IOException {
+ /** For later backwards compatibility, to add more stuff */
+ objectOutputStream.writeObject(Boolean.valueOf(false));
+
+ objectOutputStream.writeObject(Integer.valueOf(process.getProcessNum()));
+
+ if (event.getClassname() == null)
+ event.init(process);
+
+ if (VSSerialize.DEBUG)
+ System.out.println("Serializing: " + event.getClassname());
+
+ objectOutputStream.writeObject(event.getClassname());
+ objectOutputStream.writeObject(Integer.valueOf(event.getID()));
+ event.serialize(serialize, objectOutputStream);
+ objectOutputStream.writeObject(Integer.valueOf(taskNum));
+ objectOutputStream.writeObject(Long.valueOf(taskTime));
+ objectOutputStream.writeObject(Boolean.valueOf(isGlobalTimed));
+ objectOutputStream.writeObject(Boolean.valueOf(isProgrammed));
+
+ /** For later backwards compatibility, to add more stuff */
+ objectOutputStream.writeObject(Boolean.valueOf(false));
+ }
+
+ /* (non-Javadoc)
+ * @see serialize.VSSerializable#deserialize(serialize.VSSerialize,
+ * java.io.ObjectInputStream)
+ */
+ public synchronized void deserialize(VSSerialize serialize,
+ ObjectInputStream objectInputStream)
+ throws IOException, ClassNotFoundException {
+ if (VSSerialize.DEBUG)
+ System.out.println("Deserializing: VSTask");
+
+ /** For later backwards compatibility, to add more stuff */
+ objectInputStream.readObject();
+
+ int processNum = ((Integer) objectInputStream.readObject()).intValue();
+ VSInternalProcess process = (VSInternalProcess)
+ serialize.getObject(processNum, "process");
+
+ String eventClassname = (String) objectInputStream.readObject();
+ int eventID = ((Integer) objectInputStream.readObject()).intValue();
+
+ VSAbstractEvent event = null;
+
+ if (serialize.objectExists(eventID, "event")) {
+ event = (VSAbstractEvent) serialize.getObject(eventID, "event");
+
+ } else {
+ event = VSRegisteredEvents.
+ createEventInstanceByClassname(eventClassname, process);
+
+ serialize.setObject(eventID, "event", event);
+ }
+
+ event.deserialize(serialize, objectInputStream);
+
+ int taskNum = ((Integer) objectInputStream.readObject()).intValue();
+ long taskTime = ((Long) objectInputStream.readObject()).longValue();
+ Boolean isGlobalTimed = (Boolean) objectInputStream.readObject();
+ Boolean isProgrammed = (Boolean) objectInputStream.readObject();
+
+ serialize.setObject(taskNum, "task", this);
+ init(taskTime, process, event, !isGlobalTimed.booleanValue());
+ this.isProgrammed = isProgrammed.booleanValue();
+
+ /** For later backwards compatibility, to add more stuff */
+ objectInputStream.readObject();
+ }
+}
+
diff --git a/src/main/java/core/VSTaskManager.java b/src/main/java/core/VSTaskManager.java
new file mode 100644
index 0000000..6aa10d0
--- /dev/null
+++ b/src/main/java/core/VSTaskManager.java
@@ -0,0 +1,562 @@
+package core;
+
+import java.io.IOException;
+import java.io.ObjectInputStream;
+import java.io.ObjectOutputStream;
+import java.util.ArrayList;
+import java.util.LinkedList;
+import java.util.PriorityQueue;
+
+import prefs.VSPrefs;
+import serialize.VSSerializable;
+import serialize.VSSerialize;
+import simulator.VSSimulatorVisualization;
+import utils.VSPriorityQueue;
+
+/**
+ * The class VSTaskManager, it is responsible that all tasks will get
+ * fullfilled in the correct order. Please also read the javadoc of the VSTask
+ * class. It describes the difference between local and global timed tasks.
+ *
+ * @author Paul C. Buetow
+ */
+public class VSTaskManager implements VSSerializable {
+ /** The simulator canvas. */
+ private VSSimulatorVisualization simulatorVisualization;
+
+ /** The global tasks. */
+ private PriorityQueue<VSTask> globalTasks;
+
+ /** The fullfilled programmed tasks. */
+ private LinkedList<VSTask> fullfilledProgrammedTasks;
+
+ /** The Constant PROGRAMMED. */
+ public final static boolean PROGRAMMED = true;
+
+ /** The Constant ONLY_ONCE. */
+ public final static boolean ONLY_ONCE = false;
+
+ /** The simulator's default prefs. */
+ private VSPrefs prefs;
+
+ /**
+ * Instantiates a new task manager object.
+ *
+ * @param prefs the simulator's default prefs
+ * @param simulatorVisualization the simulator canvas
+ */
+ public VSTaskManager(VSPrefs prefs,
+ VSSimulatorVisualization simulatorVisualization) {
+ init(prefs, simulatorVisualization);
+ }
+
+ /**
+ * Inits the task manager.
+ *
+ * @param prefs the simulator's default prefs
+ * @param simulatorVisualization the simulator canvas
+ */
+ private void init(VSPrefs prefs,
+ VSSimulatorVisualization simulatorVisualization) {
+ this.prefs = prefs;
+ this.simulatorVisualization = simulatorVisualization;
+
+ /* May be not null if called from deserialization */
+ if (globalTasks == null)
+ this.globalTasks = new PriorityQueue<VSTask>();
+
+ this.fullfilledProgrammedTasks = new LinkedList<VSTask>();
+ }
+
+ /**
+ * Run tasks. This method gets called by the simulator canvas repeatedly.
+ * Almost all simulator actions take place in this method.
+ *
+ * @param step the step
+ * @param offset the offset
+ * @param lastGlobalTime the last global time
+ */
+ public synchronized void runTasks(long step, long offset,
+ long lastGlobalTime) {
+ VSTask task = null;
+ long localTime;
+ long offsetTime;
+ long taskTime;
+ long globalTime;
+ final long globalOffsetTime = lastGlobalTime + step;
+ boolean redo;
+ ArrayList<VSInternalProcess> processes =
+ simulatorVisualization.getProcesses();
+
+ do {
+ redo = false;
+
+ /* Run tasks which have for its schedule the global time */
+ while (globalTasks.size() != 0) {
+ task = globalTasks.peek();
+ VSInternalProcess process = task.getProcess();
+ localTime = process.getTime();
+ offsetTime = localTime + step;
+ taskTime = task.getTaskTime();
+ globalTime = process.getGlobalTime();
+
+ if (globalOffsetTime < taskTime)
+ break;
+
+ globalTasks.poll();
+ redo = true;
+
+ if (process.isCrashed() && !task.hasProcessRecoverEvent()) {
+ if (task.isProgrammed())
+ fullfilledProgrammedTasks.add(task);
+ continue;
+ }
+
+ if (globalOffsetTime == taskTime) {
+ process.setGlobalTime(globalOffsetTime);
+ process.setLocalTime(offsetTime);
+ process.timeModified(false);
+ task.run();
+ process.setGlobalTime(globalTime);
+ if (process.isCrashed())
+ process.addClockOffset(step);
+ if (process.timeModified())
+ process.addClockOffset(process.getTime()-offsetTime);
+ process.setLocalTime(localTime);
+
+ } else { /* if (globalOffsetTime > taskTime) */
+ final long diff = globalOffsetTime - taskTime;
+ if (globalOffsetTime - diff < lastGlobalTime)
+ process.setGlobalTime(lastGlobalTime);
+ else
+ process.setGlobalTime(globalOffsetTime - diff);
+ process.setLocalTime(offsetTime - diff);
+ process.timeModified(false);
+ task.run();
+ process.setGlobalTime(globalTime);
+ if (process.isCrashed())
+ process.addClockOffset(step);
+ if (process.timeModified())
+ process.addClockOffset(process.getTime()-
+ (offsetTime-diff));
+ process.setLocalTime(localTime);
+ }
+
+ if (task.isProgrammed())
+ fullfilledProgrammedTasks.add(task);
+ }
+
+ synchronized (processes) {
+ for (VSInternalProcess process : processes) {
+ PriorityQueue<VSTask> tasks = process.getTasks();
+
+ /* Run tasks which have for its schedule the local
+ process times */
+ while (tasks.size() != 0) {
+ task = tasks.peek();
+ process = task.getProcess();
+ localTime = process.getTime();
+ offsetTime = localTime + step;
+ taskTime = task.getTaskTime();
+ globalTime = process.getGlobalTime();
+
+ if (offsetTime < taskTime)
+ break;
+
+ tasks.poll();
+ redo = true;
+
+ if (process.isCrashed() &&
+ !task.hasProcessRecoverEvent()) {
+ if (task.isProgrammed())
+ fullfilledProgrammedTasks.add(task);
+ continue;
+ }
+
+ if (offsetTime == taskTime) {
+ process.setGlobalTime(globalOffsetTime);
+ process.setLocalTime(offsetTime);
+ process.timeModified(false);
+ task.run();
+ process.setGlobalTime(globalTime);
+ if (process.timeModified())
+ process.addClockOffset(process.getTime()-
+ offsetTime);
+ process.setLocalTime(localTime);
+
+ } else { /* if (offsetTime > taskTime) */
+ final long diff = offsetTime - taskTime;
+ if (globalOffsetTime - diff < lastGlobalTime)
+ process.setGlobalTime(lastGlobalTime);
+ else
+ process.setGlobalTime(globalOffsetTime-
+ diff);
+ process.setLocalTime(offsetTime - diff);
+ process.timeModified(false);
+ task.run();
+ process.setGlobalTime(globalTime);
+ if (process.timeModified())
+ process.addClockOffset(process.getTime()-
+ (offsetTime-diff));
+ process.setLocalTime(localTime);
+ }
+
+ if (task.isProgrammed())
+ fullfilledProgrammedTasks.add(task);
+ }
+ }
+ }
+
+ } while (redo);
+ }
+
+ /**
+ * Resets the task manager.
+ */
+ public synchronized void reset() {
+ ArrayList<VSInternalProcess> processes =
+ simulatorVisualization.getProcesses();
+ PriorityQueue<VSTask> tmp = null;
+
+ synchronized (processes) {
+ for (VSInternalProcess process : processes) {
+ tmp = process.getTasks();
+ process.setTasks(new VSPriorityQueue<VSTask>());
+
+ for (VSTask task : tmp) {
+ if (task.isProgrammed())
+ insert(task);
+ }
+ }
+ }
+
+ tmp = globalTasks;
+ globalTasks = new PriorityQueue<VSTask>();
+
+ while (fullfilledProgrammedTasks.size() != 0)
+ insert(fullfilledProgrammedTasks.removeFirst());
+
+ while (tmp.size() != 0) {
+ VSTask task = tmp.poll();
+ if (task.isProgrammed())
+ insert(task);
+ }
+ }
+
+ /**
+ * Inserts a task. Only for internal usage. Use the add methods instead.
+ * This method checks if the task to insert is a global or a local timed
+ * task. And it also checks if the task's time is over already.
+ *
+ * @param task the task to insert
+ */
+ private synchronized void insert(VSTask task) {
+ if (task.timeOver()) {
+ if (task.isProgrammed())
+ fullfilledProgrammedTasks.addLast(task);
+
+ } else if (task.isGlobalTimed()) {
+ globalTasks.add(task);
+
+ } else {
+ task.getProcess().getTasks().add(task);
+ }
+ }
+
+ /**
+ * Adds a task.
+ *
+ * @param task the task to add
+ */
+ public synchronized void addTask(VSTask task) {
+ addTask(task, VSTaskManager.ONLY_ONCE);
+ }
+
+ /**
+ * Adds a task.
+ *
+ * @param task the task to add
+ * @param isProgrammed true, if the task is programmed
+ */
+ public synchronized void addTask(VSTask task, boolean isProgrammed) {
+ task.isProgrammed(isProgrammed);
+ insert(task);
+ }
+
+ /**
+ * Removes a task.
+ *
+ * @param task the task to remove
+ *
+ * @return true, if the task has been removed with success
+ */
+ public synchronized boolean removeTask(VSTask task) {
+ if (fullfilledProgrammedTasks.remove(task)) {
+ return true;
+
+ } else if (task.isGlobalTimed() && globalTasks.remove(task)) {
+ return true;
+
+ } else if (!task.isGlobalTimed()) {
+ if (task.getProcess().getTasks().remove(task))
+ return true;
+ }
+
+ return false;
+ }
+
+ /**
+ * Removes several tasks.
+ *
+ * @param tasks the tasks to remove
+ */
+ public synchronized void removeAllTasks(ArrayList<VSTask> tasks) {
+ for (VSTask task : tasks)
+ removeTask(task);
+ }
+
+ /**
+ * Removes the tasks of the specified process.
+ *
+ * @param process the process to remove the tasks of
+ */
+ public synchronized void removeTasksOf(VSInternalProcess process) {
+ ArrayList<VSTask> removeThose = new ArrayList<VSTask>();
+
+ for (VSTask task : fullfilledProgrammedTasks)
+ if (task.isProcess(process))
+ removeThose.add(task);
+
+ for (VSTask task : removeThose)
+ fullfilledProgrammedTasks.remove(task);
+
+ removeThose.clear();
+
+ for (VSTask task : globalTasks)
+ if (task.isProcess(process))
+ removeThose.add(task);
+
+ for (VSTask task : removeThose)
+ globalTasks.remove(task);
+
+ process.getTasks().clear();
+ }
+
+ /**
+ * Gets the local timed tasks.
+ *
+ * @return the local timed tasks
+ */
+ public synchronized ArrayList<VSTask> getLocalTasks() {
+ ArrayList<VSTask> localTasks = new ArrayList<VSTask>();
+ ArrayList<VSInternalProcess> processes =
+ simulatorVisualization.getProcesses();
+
+ for (VSTask task : fullfilledProgrammedTasks)
+ if (!task.isGlobalTimed())
+ localTasks.add(task);
+
+ synchronized (processes) {
+ for (VSInternalProcess process : processes) {
+ VSPriorityQueue<VSTask> tasks = process.getTasks();
+ for (VSTask task : tasks)
+ localTasks.add(task);
+ }
+ }
+
+ return localTasks;
+ }
+
+ /**
+ * Gets the global timed tasks.
+ *
+ * @return the global timed tasks
+ */
+ public synchronized ArrayList<VSTask> getGlobalTasks() {
+ ArrayList<VSTask> globalTasks = new ArrayList<VSTask>();
+
+ for (VSTask task : fullfilledProgrammedTasks)
+ if (task.isGlobalTimed())
+ globalTasks.add(task);
+
+ for (VSTask task : this.globalTasks)
+ if (task.isProgrammed())
+ globalTasks.add(task);
+
+ return globalTasks;
+ }
+
+ /**
+ * Gets the local timed tasks of a specific process.
+ *
+ * @param process the process to get the local timed tasks of
+ *
+ * @return the local tasks of the specified process
+ */
+ public synchronized ArrayList<VSTask> getProcessLocalTasks(
+ VSInternalProcess process) {
+ ArrayList<VSTask> processTasks = new ArrayList<VSTask>();
+ VSPriorityQueue<VSTask> tasks = process.getTasks();
+
+ for (VSTask task : fullfilledProgrammedTasks)
+ if (!task.isGlobalTimed() && task.isProcess(process) &&
+ task.isProgrammed())
+ processTasks.add(task);
+
+ for (VSTask task : tasks)
+ if (task.isProgrammed())
+ processTasks.add(task);
+
+ return processTasks;
+ }
+
+ /**
+ * Gets the global timed tasks of a specific process.
+ *
+ * @param process the process to get the local timed tasks of
+ *
+ * @return the global timed tasks of the specified process
+ */
+ public synchronized ArrayList<VSTask> getProcessGlobalTasks(
+ VSInternalProcess process) {
+ ArrayList<VSTask> processTasks = new ArrayList<VSTask>();
+
+ for (VSTask task : fullfilledProgrammedTasks)
+ if (task.isGlobalTimed() && task.isProcess(process) &&
+ task.isProgrammed())
+ processTasks.add(task);
+
+ for (VSTask task : globalTasks)
+ if (task.isProcess(process) && task.isProgrammed())
+ processTasks.add(task);
+
+ return processTasks;
+ }
+
+ /* (non-Javadoc)
+ * @see java.lang.Object#toString()
+ */
+ public synchronized String toString() {
+ StringBuffer buffer = new StringBuffer();
+
+ buffer.append(prefs.getString("lang.task.manager"));
+ buffer.append(" (");
+ buffer.append(prefs.getString("lang.tasks.fullfilled"));
+ buffer.append(": ");
+
+ for (VSTask task : fullfilledProgrammedTasks) {
+ buffer.append(task);
+ buffer.append("; ");
+ }
+
+ buffer.append(prefs.getString("lang.tasks.global"));
+ buffer.append(": ");
+
+ for (VSTask task : globalTasks) {
+ buffer.append(task);
+ buffer.append("; ");
+ }
+
+ buffer.append(prefs.getString("lang.tasks.local"));
+ buffer.append(": ");
+
+ ArrayList<VSInternalProcess> processes =
+ simulatorVisualization.getProcesses();
+ synchronized (processes) {
+ for (VSInternalProcess process : processes) {
+ VSPriorityQueue<VSTask> tasks = process.getTasks();
+ for (VSTask task : tasks) {
+ buffer.append(task);
+ buffer.append("; ");
+ }
+ }
+ }
+
+ String descr = buffer.toString();
+
+ if (descr.endsWith("; "))
+ return descr.substring(0, descr.length()-2) + ")";
+
+ return descr + ")";
+ }
+
+ /* (non-Javadoc)
+ * @see serialize.VSSerializable#serialize(serialize.VSSerialize,
+ * java.io.ObjectOutputStream)
+ */
+ public synchronized void serialize(VSSerialize serialize,
+ ObjectOutputStream objectOutputStream)
+ throws IOException {
+ /** For later backwards compatibility, to add more stuff */
+ objectOutputStream.writeObject(Boolean.valueOf(false));
+
+ ArrayList<VSTask> serializeThoseTasks = new ArrayList<VSTask>();
+
+ for (VSTask task : fullfilledProgrammedTasks) {
+ if (!task.hasNotSerializableEvent())
+ serializeThoseTasks.add(task);
+ }
+
+ for (VSTask task : globalTasks) {
+ if (!task.hasNotSerializableEvent())
+ serializeThoseTasks.add(task);
+ }
+
+ ArrayList<VSInternalProcess> processes =
+ simulatorVisualization.getProcesses();
+
+ synchronized (processes) {
+ for (VSInternalProcess process : processes) {
+ VSPriorityQueue<VSTask> localTasks = process.getTasks();
+ for (VSTask task : localTasks) {
+ if (!task.hasNotSerializableEvent())
+ serializeThoseTasks.add(task);
+ }
+ }
+ }
+
+ objectOutputStream.writeObject(
+ Integer.valueOf(serializeThoseTasks.size()));
+ for (VSTask task : serializeThoseTasks)
+ task.serialize(serialize, objectOutputStream);
+
+ /** For later backwards compatibility, to add more stuff */
+ objectOutputStream.writeObject(Boolean.valueOf(false));
+ }
+
+ /* (non-Javadoc)
+ * @see serialize.VSSerializable#deserialize(serialize.VSSerialize,
+ * java.io.ObjectInputStream)
+ */
+ public synchronized void deserialize(VSSerialize serialize,
+ ObjectInputStream objectInputStream)
+ throws IOException, ClassNotFoundException {
+ if (VSSerialize.DEBUG)
+ System.out.println("Deserializing: VSTaskManager");
+
+ /** For later backwards compatibility, to add more stuff */
+ objectInputStream.readObject();
+
+ globalTasks.clear();
+
+ ArrayList<VSInternalProcess> processes =
+ simulatorVisualization.getProcesses();
+ synchronized (processes) {
+ for (VSInternalProcess process : processes)
+ process.getTasks().clear();
+ }
+
+ int numTasks = ((Integer) objectInputStream.readObject()).intValue();
+
+ if (VSSerialize.DEBUG)
+ System.out.println("Num of tasks: " + numTasks);
+
+ for (int i = 0; i < numTasks; ++i) {
+ VSTask task = new VSTask(serialize, objectInputStream);
+ addTask(task, task.isProgrammed());
+ }
+
+ /** For later backwards compatibility, to add more stuff */
+ objectInputStream.readObject();
+ }
+}
diff --git a/src/main/java/core/time/VSLamportTime.java b/src/main/java/core/time/VSLamportTime.java
new file mode 100644
index 0000000..be1226b
--- /dev/null
+++ b/src/main/java/core/time/VSLamportTime.java
@@ -0,0 +1,50 @@
+package core.time;
+
+/**
+ * The class VSLamportTime, defines how the lamport timestamps are represented.
+ *
+ * @author Paul C. Buetow
+ */
+public class VSLamportTime implements VSTime {
+ /** Specified the global time of the lamport timestamp. It's used for
+ * correct painting position in the simulator canvas paint area.
+ */
+ private long globalTime;
+
+ /** Specified the process' local lamport time. */
+ private long lamportTime;
+
+ /**
+ * A simple constructor.
+ *
+ * @param globalTime The global time.
+ * @param lamportTime The local lamport time.
+ */
+ public VSLamportTime(long globalTime, long lamportTime) {
+ this.globalTime = globalTime;
+ this.lamportTime = lamportTime;
+ }
+
+ /* (non-Javadoc)
+ * @see core.time.VSTime#getGlobalTime()
+ */
+ public long getGlobalTime() {
+ return globalTime;
+ }
+
+ /**
+ * Gets the lamport time.
+ *
+ * @return The process' local lamport time
+ */
+ public long getLamportTime() {
+ return lamportTime;
+ }
+
+ /* (non-Javadoc)
+ * @see core.time.VSTime#toString()
+ */
+ public String toString() {
+ return "(" + lamportTime + ")";
+ }
+}
diff --git a/src/main/java/core/time/VSTime.java b/src/main/java/core/time/VSTime.java
new file mode 100644
index 0000000..d46e0e4
--- /dev/null
+++ b/src/main/java/core/time/VSTime.java
@@ -0,0 +1,22 @@
+package core.time;
+
+/**
+ * This interface is a guidline for general time format classes.
+ *
+ * @author Paul C. Buetow
+ */
+public interface VSTime {
+ /**
+ * Gets the global time.
+ *
+ * @return The global time
+ */
+ public long getGlobalTime();
+
+ /**
+ * Returns a string representation.
+ *
+ * @return The representation of the implementing object as a string
+ */
+ public String toString();
+}
diff --git a/src/main/java/core/time/VSVectorTime.java b/src/main/java/core/time/VSVectorTime.java
new file mode 100644
index 0000000..4e63b3c
--- /dev/null
+++ b/src/main/java/core/time/VSVectorTime.java
@@ -0,0 +1,96 @@
+package core.time;
+
+import java.util.ArrayList;
+
+/**
+ * The class VSVectorTime, defined how the vector timestamps are represented.
+ *
+ * @author Paul C. Buetow
+ */
+public class VSVectorTime extends ArrayList<Long> implements VSTime {
+ /** The serial version uid */
+ private static final long serialVersionUID = 1L;
+
+ /** The global time. */
+ private long globalTime;
+
+ /**
+ * Instantiates a new vector time.
+ *
+ * @param globalTime the global time
+ */
+ public VSVectorTime(long globalTime) {
+ this.globalTime = globalTime;
+ }
+
+ /**
+ * To long array.
+ *
+ * @return the long[]
+ */
+ public long[] toLongArray() {
+ final int size = super.size();
+ final long[] arr = new long[size];
+
+ for (int i = 0; i < size; ++i)
+ arr[i] = super.get(i).longValue();
+
+ return arr;
+ }
+
+ /**
+ * Sets the global time.
+ *
+ * @param globalTime the new global time
+ */
+ public void setGlobalTime(long globalTime) {
+ this.globalTime = globalTime;
+ }
+
+ /* (non-Javadoc)
+ * @see core.time.VSTime#getGlobalTime()
+ */
+ public long getGlobalTime() {
+ return globalTime;
+ }
+
+ /**
+ * Gets the copy.
+ *
+ * @return the copy
+ */
+ public VSVectorTime getCopy() {
+ final VSVectorTime vectorTime = new VSVectorTime(globalTime);
+ final int size = super.size();
+
+ for (int i = 0; i < size; ++i)
+ vectorTime.add(super.get(i));
+
+ return vectorTime;
+ }
+
+ /* (non-Javadoc)
+ * @see java.util.AbstractCollection#toString()
+ */
+ public String toString() {
+ final int size = super.size();
+ final StringBuffer buffer = new StringBuffer();
+ buffer.append("(");
+
+ for (int i = 0; i < size-1; ++i)
+ buffer.append(super.get(i)+",");
+ buffer.append(super.get(size-1)+")");
+
+ return buffer.toString();
+ }
+
+ /* (non-Javadoc)
+ * @see java.util.ArrayList#get(int)
+ */
+ public Long get(int index) {
+ if (index >= super.size())
+ return Long.valueOf(0);
+
+ return super.get(index);
+ }
+}