diff options
| author | Paul Buetow <paul@buetow.org> | 2008-05-17 14:55:16 +0000 |
|---|---|---|
| committer | Paul Buetow <paul@buetow.org> | 2008-05-17 14:55:16 +0000 |
| commit | 271949bf140359dd97cbee9ef927ee9280c9f31f (patch) | |
| tree | 31cd0e175401d2041e23128402c235eb6d2e3117 | |
| parent | 5a0924146201bc577ca170952a21a42464ac7c71 (diff) | |
Vectortimestamps work
Better representation of Lamporttimestamps
BerkelyTimeProtocol
M trunk/ROADMAP
M trunk/sources/prefs/VSPrefs.java
M trunk/sources/prefs/VSDefaultPrefs.java
M trunk/sources/simulator/VSMain.java
M trunk/sources/simulator/VSSimulation.java
M trunk/sources/simulator/VSSimulationPanel.java
M trunk/sources/utils/VSFrame.java
M trunk/sources/utils/VSClassLoader.java
M trunk/sources/utils/VSInfoArea.java
M trunk/sources/protocols/BroadcastSturmProtocol.java
M trunk/sources/protocols/ExternalTimeSyncProtocol.java
M trunk/sources/protocols/RegisteredProtocols.java
M trunk/sources/protocols/PingPongProtocol.java
M trunk/sources/protocols/InternalTimeSyncProtocol.java
M trunk/sources/protocols/VSProtocol.java
M trunk/sources/protocols/DummyProtocol.java
A trunk/sources/protocols/BerkelyTimeProtocol.java
M trunk/sources/core/VSLamport.java
M trunk/sources/core/VSProcess.java
A trunk/sources/core/VSTime.java
A trunk/sources/core/VSVectorTime.java
M trunk/sources/core/VSTask.java
M trunk/sources/core/VSMessage.java
M trunk/sources/editors/VSEditor.java
M trunk/sources/editors/VSProtocolEditor.java
M trunk/sources/editors/VSSimulationEditor.java
M trunk/sources/editors/VSEditorFrame.java
M trunk/sources/editors/VSProcessEditor.java
28 files changed, 475 insertions, 136 deletions
@@ -1,8 +1,15 @@ +DONE: +Vectortimestamps work +Better representation of Lamporttimestamps +BerkelyTimeProtocol + +TODO: + Prozesse manuell abstuerzen lassen Prozesse duerfen wiederbelebt werden + Prozess Quick Panel: Uhrabweichung / Geschwindigkeit direkt einstellen koennen Event Manager (Prozessabstuerze genau vorprogrammieren) -Vektorzeitstempel Himmelobjekt Ganze simulationseinstellungen abspeichern/laden koennen @@ -10,9 +17,11 @@ Systemschnitte? Middleware-Schicht? Weitere Optimierungen: Linienobjekte von nicht aendernden Linien erzeugen! JTree Editor +Systemschnitte + +Create schedules from Protocols Protocols: - Berkely Alpgorithmus zur interenen Synchronisierung ReliableMulticast Ein-Phasen Commit Protokoll Zwei-Phasen Commit Protokoll diff --git a/sources/core/VSLamport.java b/sources/core/VSLamport.java index 157aaae..4c4707f 100644 --- a/sources/core/VSLamport.java +++ b/sources/core/VSLamport.java @@ -1,19 +1,23 @@ package core; -public class VSLamport { - private long time; +public class VSLamport implements VSTime { + private long globalTime; private long lamportTime; - public VSLamport(long time, long lamportTime) { - this.time = time; + public VSLamport(long globalTime, long lamportTime) { + this.globalTime = globalTime; this.lamportTime = lamportTime; } - public long getTime() { - return time; + public long getGlobalTime() { + return globalTime; } public long getLamportTime() { return lamportTime; } + + public String toString() { + return "(" + lamportTime + ")"; + } } diff --git a/sources/core/VSMessage.java b/sources/core/VSMessage.java index b3c1d31..466fc4d 100644 --- a/sources/core/VSMessage.java +++ b/sources/core/VSMessage.java @@ -10,6 +10,7 @@ public class VSMessage extends VSPrefs implements VSEvent { private long messageID; private static long messageCounter; private long lamportTime; + private VSVectorTime vectorTime; public VSMessage(String protocolClassname) { this.protocolClassname = protocolClassname; @@ -31,6 +32,7 @@ public class VSMessage extends VSPrefs implements VSEvent { public void setSendingProcess(VSProcess sendingProcess) { this.sendingProcess = sendingProcess; lamportTime = sendingProcess.getLamportTime(); + vectorTime = sendingProcess.getVectorTime().getCopy(); } public VSProcess getSendingProcess() { @@ -41,6 +43,10 @@ public class VSMessage extends VSPrefs implements VSEvent { return lamportTime; } + public VSVectorTime getVectorTime() { + return vectorTime; + } + public String toString() { return "ID: " + messageID; } diff --git a/sources/core/VSProcess.java b/sources/core/VSProcess.java index bb65959..c9002ca 100644 --- a/sources/core/VSProcess.java +++ b/sources/core/VSProcess.java @@ -24,15 +24,15 @@ public final class VSProcess extends VSPrefs { private boolean timeModified; private double clockOffset; private float clockVariance; - private int num; private int processID; private long globalTime; private long localTime; private static int processCounter; private boolean isCrashed; private long lamportTime; - private ArrayList<VSLamport> lamportTimestamps; - private ArrayList<Integer> vectorTimestamps; + private ArrayList<VSLamport> lamportTimeHistory; + private VSVectorTime vectorTime; + private ArrayList<VSVectorTime> vectorTimeHistory; /* 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 @@ -79,16 +79,13 @@ public final class VSProcess extends VSPrefs { private static final String DEFAULT_STRING_VALUE_KEYS[] = { }; - public VSProcess(VSPrefs prefs, VSSimulationPanel simulationPanel, VSLogging logging, int num) { + public VSProcess(VSPrefs prefs, VSSimulationPanel simulationPanel, VSLogging logging) { this.prefs = prefs; this.simulationPanel = simulationPanel; this.logging = logging; - this.num = num; - this.random = new VSRandom(processID+processCounter); - this.lamportTimestamps = new ArrayList<VSLamport>(); - this.vectorTimestamps = new ArrayList<Integer>(); - setLamportTime(0); + random = new VSRandom(processID+processCounter); + initTimeFormats(); setObject("protocols", new ArrayList<VSProtocol>()); isPaused = true; @@ -110,6 +107,31 @@ public final class VSProcess extends VSPrefs { createRandomCrashTask(); } + private void initTimeFormats() { + lamportTime = 0; + lamportTimeHistory = new ArrayList<VSLamport>(); + + vectorTime = new VSVectorTime(0); + vectorTimeHistory = new ArrayList<VSVectorTime>(); + + final int numProcesses = simulationPanel.getNumProcesses(); + for (int i = 0; i < numProcesses; ++i) + vectorTime.add(new Long(0)); + } + + private void resetTimeFormats() { + lamportTime = 0; + lamportTimeHistory.clear(); + + vectorTime = new VSVectorTime(0); + vectorTimeHistory.clear(); + + final int numProcesses = simulationPanel.getNumProcesses(); + for (int i = numProcesses; i > 0; --i) + vectorTime.add(new Long(0)); + } + + /** * Called from the VSProcessEditor, after finishing editing! */ @@ -178,9 +200,6 @@ public final class VSProcess extends VSPrefs { localTime = 0; globalTime = 0; clockOffset = 0; - lamportTime = 0; - lamportTimestamps.clear(); - vectorTimestamps.clear(); if (objectExists("protocols.registered")) { Object protocolsObj = getObject("protocols.registered"); @@ -193,6 +212,7 @@ public final class VSProcess extends VSPrefs { setCurrentColor(getColor("process.default")); createRandomCrashTask(); + resetTimeFormats(); } private void createRandomCrashTask() { @@ -277,10 +297,6 @@ public final class VSProcess extends VSPrefs { return crashedColor; } - public int getNum() { - return num; - } - public synchronized boolean timeModified() { return timeModified; } @@ -362,40 +378,83 @@ public final class VSProcess extends VSPrefs { return isPaused; } + public void increaseLamportTime() { + setLamportTime(getLamportTime()+1); + } + + public void updateLamportTime(long time) { + final long lamportTime = getLamportTime() + 1; + + if (time > lamportTime) + setLamportTime(time); + else + setLamportTime(lamportTime); + } + public synchronized long getLamportTime() { return lamportTime; } public synchronized void setLamportTime(long lamportTime) { this.lamportTime = lamportTime; - lamportTimestamps.add(new VSLamport(globalTime, lamportTime)); + lamportTimeHistory.add(new VSLamport(globalTime, lamportTime)); } - public synchronized VSLamport[] getLamportArray() { - final int size = lamportTimestamps.size(); - final VSLamport[] arr = new VSLamport[size]; + public synchronized VSTime[] getLamportTimeArray() { + final int size = lamportTimeHistory.size(); + final VSTime[] arr = new VSLamport[size]; for (int i = 0; i < size; ++i) - arr[i] = lamportTimestamps.get(i); + arr[i] = (VSTime) lamportTimeHistory.get(i); return arr; } - public synchronized int[] getVectorTime() { - final int size = vectorTimestamps.size(); - final int[] arr = new int[size]; + public synchronized void increaseVectorTime() { + vectorTime.set(processID-1, new Long(vectorTime.get(processID-1).longValue()+1)); + vectorTime.setGlobalTime(globalTime); + vectorTimeHistory.add(vectorTime.getCopy()); + } + + public synchronized void updateVectorTime(VSVectorTime vectorTimeUpdate) { + final int size = vectorTime.size(); + + for (int i = 0; i < size; ++i) { + if (i == processID-1) + vectorTime.set(i, new Long(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()); + } + + public synchronized VSVectorTime getVectorTime() { + return vectorTime; + } + + public synchronized VSTime[] getVectorTimeArray() { + final int size = vectorTimeHistory.size(); + final VSTime[] arr = new VSTime[size]; for (int i = 0; i < size; ++i) - arr[i] = vectorTimestamps.get(i); + arr[i] = (VSTime) vectorTimeHistory.get(i); return arr; } - public void sendMessage(VSMessage message) { - logg(prefs.getString("lang.message.sent") + "; " - + prefs.getString("lang.protocol") + ": " + message.getProtocolName() + "; " - + prefs.getString("lang.message") + " " + message.toStringFull()); + StringBuffer buffer = new StringBuffer(); + buffer.append(prefs.getString("lang.message.sent")); + buffer.append("; "); + buffer.append(prefs.getString("lang.protocol")); + buffer.append(": " + message.getProtocolName()); + buffer.append("; "); + buffer.append(prefs.getString("lang.message")); + buffer.append(" "); + buffer.append(message.toStringFull()); + logg(buffer.toString()); simulationPanel.sendMessage(message); } @@ -412,20 +471,39 @@ public final class VSProcess extends VSPrefs { } public String toString() { - return - prefs.getString("lang.process.id") + ": " - + getProcessID() + "; " - + prefs.getString("lang.process.time.local") + ": " - + VSTools.getTimeString(getTime()) - + "; Lamport: " + lamportTime; + 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(); } public String toStringFull() { - return toString() + "; paused: " + isPaused + "; crashed: " + isCrashed + "; crashTask: " + randomCrashTask; + 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(); } public boolean equals(VSProcess process) { - return process.getNum() == getNum(); + return process.getProcessID() == processID; } public VSSimulationPanel getSimulationPanel() { diff --git a/sources/core/VSTask.java b/sources/core/VSTask.java index 43b0265..26b2485 100644 --- a/sources/core/VSTask.java +++ b/sources/core/VSTask.java @@ -84,13 +84,8 @@ public class VSTask implements Comparable { final String protocolName = message.getProtocolName(); final String protocolClassname = message.getProtocolClassname(); - final long recvLamportTime = message.getLamportTime() + 1; - final long lamportTime = process.getLamportTime() + 1; - - if (recvLamportTime > lamportTime) - process.setLamportTime(recvLamportTime); - else - process.setLamportTime(lamportTime); + process.updateLamportTime(message.getLamportTime()+1); + process.updateVectorTime(message.getVectorTime()); Object protocolObj; @@ -120,10 +115,6 @@ public class VSTask implements Comparable { private void onProcessEventStart() { final VSProcessEvent processEvent = (VSProcessEvent) event; processEvent.onStart(process); - /* - if (process.isCrashed()) - process.setLamportTime(process.getLamportTime()-1); - */ } public long getTaskTime() { diff --git a/sources/core/VSTime.java b/sources/core/VSTime.java new file mode 100644 index 0000000..f35c0dd --- /dev/null +++ b/sources/core/VSTime.java @@ -0,0 +1,6 @@ +package core; + +public interface VSTime { + public long getGlobalTime(); + public String toString(); +} diff --git a/sources/core/VSVectorTime.java b/sources/core/VSVectorTime.java new file mode 100644 index 0000000..70a62a2 --- /dev/null +++ b/sources/core/VSVectorTime.java @@ -0,0 +1,52 @@ +package core; + +import java.util.ArrayList; + +public class VSVectorTime extends ArrayList<Long> implements VSTime { + /* Only needed for painting in the painting panel */ + private long globalTime; + + public VSVectorTime(long globalTime) { + this.globalTime = globalTime; + } + + 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; + } + + public void setGlobalTime(long globalTime) { + this.globalTime = globalTime; + } + + public long getGlobalTime() { + return globalTime; + } + + 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; + } + + 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(); + } +} diff --git a/sources/editors/VSEditor.java b/sources/editors/VSEditor.java index 074bfd4..a81300d 100644 --- a/sources/editors/VSEditor.java +++ b/sources/editors/VSEditor.java @@ -38,14 +38,14 @@ abstract class VSEditor implements ActionListener { protected Insets insets = new Insets(0, 0, 0, 0); public VSEditor(VSPrefs prefs, VSPrefs prefsToEdit) { - initialize(prefs, prefsToEdit, SIMULATION_PREFERENCES); + init(prefs, prefsToEdit, SIMULATION_PREFERENCES); } public VSEditor(VSPrefs prefs, VSPrefs prefsToEdit, int prefsCategory) { - initialize(prefs, prefsToEdit, prefsCategory); + init(prefs, prefsToEdit, prefsCategory); } - private void initialize(VSPrefs prefs, VSPrefs prefsToEdit, int prefsCategory) { + private void init(VSPrefs prefs, VSPrefs prefsToEdit, int prefsCategory) { this.prefs = prefs; this.prefsToEdit = prefsToEdit; this.prefsCategory = prefsCategory; diff --git a/sources/editors/VSEditorFrame.java b/sources/editors/VSEditorFrame.java index b9c14c6..1276e5b 100644 --- a/sources/editors/VSEditorFrame.java +++ b/sources/editors/VSEditorFrame.java @@ -19,16 +19,16 @@ public abstract class VSEditorFrame extends VSEditor { public VSEditorFrame(VSPrefs prefs, Component relativeTo, VSPrefs prefsToEdit, String title) { super(prefs, prefsToEdit); frame = new VSFrame(title, relativeTo); - initialize(); + init(); } public VSEditorFrame(VSPrefs prefs, Component relativeTo, VSPrefs prefsToEdit, String title, int prefsCategory) { super(prefs, prefsToEdit, prefsCategory); frame = new VSFrame(title, relativeTo); - initialize(); + init(); } - private void initialize() { + private void init() { frame.setJMenuBar(createJMenuBar()); frame.setContentPane(createContentPane()); frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE); @@ -198,7 +198,7 @@ public abstract class VSEditorFrame extends VSEditor { if (ret == JFileChooser.APPROVE_OPTION) { File file = fileChooser.getSelectedFile(); - prefsToEdit = prefs = VSDefaultPrefs.initialize(file.getName()); + prefsToEdit = prefs = VSDefaultPrefs.init(file.getName()); resetEditPanel(); } diff --git a/sources/editors/VSProcessEditor.java b/sources/editors/VSProcessEditor.java index ecd495d..158295a 100644 --- a/sources/editors/VSProcessEditor.java +++ b/sources/editors/VSProcessEditor.java @@ -24,7 +24,7 @@ public class VSProcessEditor extends VSEditorFrame { this.process = process; - initialize(); + init(); } public VSProcessEditor(VSPrefs prefs, Component relativeTo, VSProcess process, int prefsCategory) { @@ -35,10 +35,10 @@ public class VSProcessEditor extends VSEditorFrame { this.process = process; - initialize(); + init(); } - private void initialize() { + private void init() { super.infoArea.setText(prefs.getString("lang.prefs.process.info!")); getFrame().disposeWithParent(); createButtonPanel(); @@ -92,10 +92,8 @@ public class VSProcessEditor extends VSEditorFrame { else return; } else { - protocol = RegisteredProtocols.getProtocolInstanceByName(protocolName); + protocol = RegisteredProtocols.getProtocolInstanceByName(protocolName, process); process.setObject(protocolClassname, protocol); - protocol.setProcess(process); - protocol.setVSPrefs(prefs); } new VSProtocolEditor(prefs, frame, protocol); } diff --git a/sources/editors/VSProtocolEditor.java b/sources/editors/VSProtocolEditor.java index b347498..7a0961c 100644 --- a/sources/editors/VSProtocolEditor.java +++ b/sources/editors/VSProtocolEditor.java @@ -32,14 +32,14 @@ public class VSProtocolEditor extends VSEditorFrame { this.protocol = protocol; this.taskManager = protocol.getProcess().getSimulationPanel().getTaskManager(); - initialize(); + init(); } - private void initialize() { + private void init() { super.getFrame().disposeWithParent(); super.infoArea.setText(prefs.getString("lang.prefs.protocol.info!")); - initializeTaskManagerEditor(clientTaskManagerEditorPanel); - initlializeClientServerCheckboxes(); + initTaskManagerEditor(clientTaskManagerEditorPanel); + initClientServerCheckboxes(); createButtonPanel(); } @@ -129,7 +129,7 @@ public class VSProtocolEditor extends VSEditorFrame { return panel; } - private void initlializeClientServerCheckboxes() { + private void initClientServerCheckboxes() { final String protocolName = protocol.getProtocolName(); final VSProcess process = protocol.getProcess(); @@ -140,7 +140,7 @@ public class VSProtocolEditor extends VSEditorFrame { } - private void initializeTaskManagerEditor(JPanel panel) { + private void initTaskManagerEditor(JPanel panel) { clientComboBox = new JComboBox(); deleteButton = new JButton(prefs.getString("lang.remove")); takeOverButton = new JButton(prefs.getString("lang.takeover")); diff --git a/sources/editors/VSSimulationEditor.java b/sources/editors/VSSimulationEditor.java index c455d64..31d40d8 100644 --- a/sources/editors/VSSimulationEditor.java +++ b/sources/editors/VSSimulationEditor.java @@ -20,7 +20,7 @@ public class VSSimulationEditor extends VSEditorFrame { + " - " + prefs.getString("lang.prefs")); startNewVSSimulation = true; - initialize(); + init(); } public VSSimulationEditor(VSPrefs prefs, Component relativeTo, int prefsCategory) { @@ -30,10 +30,10 @@ public class VSSimulationEditor extends VSEditorFrame { prefsCategory); startNewVSSimulation = false; - initialize(); + init(); } - private void initialize() { + private void init() { super.infoArea.setText(prefs.getString("lang.prefs.info!")); } diff --git a/sources/prefs/VSDefaultPrefs.java b/sources/prefs/VSDefaultPrefs.java index b985e8c..dac1b5c 100644 --- a/sources/prefs/VSDefaultPrefs.java +++ b/sources/prefs/VSDefaultPrefs.java @@ -5,11 +5,11 @@ import java.awt.event.KeyEvent; import java.io.*; public class VSDefaultPrefs extends VSPrefs { - public static VSPrefs initialize() { - return initialize(VSPrefs.PREFERENCES_FILENAME); + public static VSPrefs init() { + return init(VSPrefs.PREFERENCES_FILENAME); } - public static VSPrefs initialize(String fileName) { + public static VSPrefs init(String fileName) { File file = new File(fileName); VSPrefs prefs = null; @@ -40,7 +40,8 @@ public class VSDefaultPrefs extends VSPrefs { public void fillDefaultStrings() { /* Internal prefs */ - initString("lang.time.lamport", "Lamport"); + initString("lang.time.vector", "Vektorzeit"); + initString("lang.time.lamport", "Lamportzeit"); initString("lang.message.sent", "Nachricht versendet"); initString("lang.logging.active", "Logging"); initString("lang.message", "Nachricht"); @@ -141,7 +142,7 @@ public class VSDefaultPrefs extends VSPrefs { initIntegerUnit("window.prefs.xsize", 400, "X-Grösse des Einstellungsfensters", 550, 3200, "px"); initIntegerUnit("window.prefs.ysize", 650, "Y-Grösse des Einstellungsfensters", 640, 2400, "px"); - initIntegerUnit("window.loggsize", 350, "Y-Grösse des Loggingfensters", 100, 1000, "px"); + initIntegerUnit("window.loggsize", 300, "Y-Grösse des Loggingfensters", 100, 1000, "px"); initIntegerUnit("window.splitsize", 180, null, 100, 1000, "px"); initIntegerUnit("window.xsize", 1024, "X-Grösse des Hauptfensters", 800, 3200, "px"); initIntegerUnit("window.ysize", 768, "Y-Grösse des Hauptfensters", 600, 2400, "px"); diff --git a/sources/prefs/VSPrefs.java b/sources/prefs/VSPrefs.java index 9da4808..be9aea6 100644 --- a/sources/prefs/VSPrefs.java +++ b/sources/prefs/VSPrefs.java @@ -520,6 +520,13 @@ public abstract class VSPrefs implements Serializable { descr += key + "=" + getInteger(key) + "; "; } + set = getLongKeySet(); + if (set.size() > 0) { + descr += LONG_PREFIX; + for (String key : set) + descr += key + "=" + getLong(key) + "; "; + } + set = getFloatKeySet(); if (set.size() > 0) { descr += FLOAT_PREFIX; diff --git a/sources/protocols/BerkelyTimeProtocol.java b/sources/protocols/BerkelyTimeProtocol.java new file mode 100644 index 0000000..ea81cba --- /dev/null +++ b/sources/protocols/BerkelyTimeProtocol.java @@ -0,0 +1,126 @@ +package protocols; + +import prefs.VSPrefs; +import core.VSMessage; + +import java.util.HashMap; + +public class BerkelyTimeProtocol extends VSProtocol { + /* Berkely Server variables */ + + /* Integer: Process ID, Long: Local time of the process */ + private HashMap<Integer,Long> processTimes = new HashMap<Integer,Long>(); + /* Integer: Process ID, Long: Time of receiving the response from the process */ + private HashMap<Integer,Long> recvTimes = new HashMap<Integer,Long>(); + /* Integer: Process ID, Long: Calculated process times (using the RTT) */ + private HashMap<Integer,Long> realTimesRTT = new HashMap<Integer,Long>(); + /* Time the request/response has started */ + private long requestTime; + + /* Berkely Client vairables */ + + protected void onInit() { + setProtocolClassname(getClass().toString()); + + /* Those prefs are editable through the VSProtocol VSEditor GUI. t_min and t_max in milliseconds */ + setInteger("numProcesses", getNumProcesses()-1); + } + + protected void onClientReset() { + processTimes.clear(); + recvTimes.clear(); + realTimesRTT.clear(); + } + + protected void onClientStart() { + requestTime = process.getTime(); + VSMessage message = new VSMessage(getProtocolClassname()); + message.setBoolean("isRequest", true); + sendMessage(message); + } + + protected void onClientRecv(VSMessage recvMessage) { + /* Ignore all protocol messages which are not a response message, e.g. itself */ + if (!recvMessage.getBoolean("isResponse")) + return; + + Integer processID = new Integer(recvMessage.getInteger("processID")); + Long time = new Long(recvMessage.getLong("time")); + + processTimes.put(processID, time); + recvTimes.put(processID, new Long(process.getTime())); + + /* All processes have comitted the response */ + if (processTimes.size() == getInteger("numProcesses")) { + long avgTime = calculateAverageTime(); + /* Set the local's process time to the new avg reference time */ + process.setTime(avgTime); + /* Tell all other processes what to do in order to justify their times */ + sendJustifyRequests(avgTime); + /* Start "clean" next time */ + onClientReset(); + } + } + + /** + * Calculate the new average time + */ + private long calculateAverageTime() { + long sum = 0; + for (Integer processID : processTimes.keySet()) { + Long localTime = processTimes.get(processID); + Long recvTime = recvTimes.get(processID); + long rtt = recvTime.longValue() - requestTime; + long realProcessTime = localTime + (long) (rtt / 2); + realTimesRTT.put(processID, new Long(realProcessTime)); + sum += realProcessTime; + } + /* Include the time of the local process */ + sum += process.getTime(); + return (long) sum / (1 + getInteger("numProcesses")); + } + + /** + * Sends to all clients a value to justify their local clocks + */ + private void sendJustifyRequests(long avgTime) { + for (Integer processID : processTimes.keySet()) { + long realProcessTime = realTimesRTT.get(processID).longValue(); + long diff = avgTime - realProcessTime; + VSMessage message = new VSMessage(getProtocolClassname()); + message.setBoolean("isJustify", true); + message.setLong("timeDiff", diff); + message.setInteger("receiverProcessID", processID); + sendMessage(message); + } + } + + protected void onServerReset() { + } + + protected void onServerRecv(VSMessage recvMessage) { + if (recvMessage.getBoolean("isRequest")) { + VSMessage message = new VSMessage(getProtocolClassname()); + message.setInteger("processID", process.getProcessID()); + message.setLong("time", process.getTime()); + message.setBoolean("isResponse", true); + sendMessage(message); + + } else if (recvMessage.getBoolean("isJustify")) { + /* Check if it's "my" justify message */ + if (recvMessage.getInteger("receiverProcessID") != process.getProcessID()) + return; + + long timeDiff = recvMessage.getLong("timeDiff"); + long recvTime = process.getTime(); + long newTime = process.getTime() + timeDiff; + logg("Neue Zeit: " + newTime); + + process.setTime(newTime); + } + } + + public String toString() { + return super.toString(); + } +} diff --git a/sources/protocols/BroadcastSturmProtocol.java b/sources/protocols/BroadcastSturmProtocol.java index 3940e5f..6ce95e8 100644 --- a/sources/protocols/BroadcastSturmProtocol.java +++ b/sources/protocols/BroadcastSturmProtocol.java @@ -9,7 +9,7 @@ public class BroadcastSturmProtocol extends VSProtocol { private ArrayList<VSMessage> sentMessages; private static int broadcastCount; - public BroadcastSturmProtocol() { + protected void onInit() { setProtocolClassname(getClass().toString()); sentMessages = new ArrayList<VSMessage>(); } diff --git a/sources/protocols/DummyProtocol.java b/sources/protocols/DummyProtocol.java index 8c9009c..9a531e1 100644 --- a/sources/protocols/DummyProtocol.java +++ b/sources/protocols/DummyProtocol.java @@ -3,7 +3,7 @@ package protocols; import core.VSMessage; public class DummyProtocol extends VSProtocol { - public DummyProtocol() { + protected void onInit() { setProtocolClassname(getClass().toString()); } diff --git a/sources/protocols/ExternalTimeSyncProtocol.java b/sources/protocols/ExternalTimeSyncProtocol.java index 33a60ad..b6ee73f 100644 --- a/sources/protocols/ExternalTimeSyncProtocol.java +++ b/sources/protocols/ExternalTimeSyncProtocol.java @@ -7,7 +7,7 @@ public class ExternalTimeSyncProtocol extends VSProtocol { private long requestTime; private boolean waitingForResponse; - public ExternalTimeSyncProtocol() { + protected void onInit() { setProtocolClassname(getClass().toString()); } diff --git a/sources/protocols/InternalTimeSyncProtocol.java b/sources/protocols/InternalTimeSyncProtocol.java index 48b57e0..961cf65 100644 --- a/sources/protocols/InternalTimeSyncProtocol.java +++ b/sources/protocols/InternalTimeSyncProtocol.java @@ -6,7 +6,7 @@ import core.VSMessage; public class InternalTimeSyncProtocol extends VSProtocol { private boolean waitingForResponse; - public InternalTimeSyncProtocol() { + protected void onInit() { setProtocolClassname(getClass().toString()); /* Those prefs are editable through the VSProtocol VSEditor GUI. t_min and t_max in milliseconds */ diff --git a/sources/protocols/PingPongProtocol.java b/sources/protocols/PingPongProtocol.java index 6244b9a..ee54a3c 100644 --- a/sources/protocols/PingPongProtocol.java +++ b/sources/protocols/PingPongProtocol.java @@ -7,7 +7,7 @@ public class PingPongProtocol extends VSProtocol { private int clientCounter; private int serverCounter; - public PingPongProtocol() { + protected void onInit() { setProtocolClassname(getClass().toString()); } @@ -16,7 +16,6 @@ public class PingPongProtocol extends VSProtocol { } protected void onClientStart() { - VSMessage message = new VSMessage(getProtocolClassname()); message.setBoolean("fromClient", true); message.setInteger("counter", ++clientCounter); diff --git a/sources/protocols/RegisteredProtocols.java b/sources/protocols/RegisteredProtocols.java index 542d686..b08bb87 100644 --- a/sources/protocols/RegisteredProtocols.java +++ b/sources/protocols/RegisteredProtocols.java @@ -11,7 +11,7 @@ public final class RegisteredProtocols { private static HashMap<String,String> protocolNames; private static VSPrefs prefs; - public static void initialize(VSPrefs prefs_) { + public static void init(VSPrefs prefs_) { prefs = prefs_; protocolNames = new HashMap<String, String>(); protocolClassnames = new HashMap<String, String>(); @@ -21,6 +21,7 @@ public final class RegisteredProtocols { registerProtocol("protocols.ExternalTimeSyncProtocol"); registerProtocol("protocols.InternalTimeSyncProtocol"); registerProtocol("protocols.BroadcastSturmProtocol"); + registerProtocol("protocols.BerkelyTimeProtocol"); } public static Vector<String> getProtocolNames() { @@ -43,12 +44,15 @@ public final class RegisteredProtocols { return protocolNames.get(protocolClassname); } - public static VSProtocol getProtocolInstanceByName(String protocolName) { + public static VSProtocol getProtocolInstanceByName(String protocolName, VSProcess process) { final String protocolClassname = protocolClassnames.get(protocolName); final Object protocolObj = new VSClassLoader().newInstance(protocolClassname); - if (protocolObj instanceof VSProtocol) - return (VSProtocol) protocolObj; + if (protocolObj instanceof VSProtocol) { + VSProtocol protocol = (VSProtocol) protocolObj; + protocol.init(process); + return protocol; + } return null; } diff --git a/sources/protocols/VSProtocol.java b/sources/protocols/VSProtocol.java index b66f034..4f34195 100644 --- a/sources/protocols/VSProtocol.java +++ b/sources/protocols/VSProtocol.java @@ -11,9 +11,12 @@ abstract public class VSProtocol extends VSPrefs implements VSEvent { private boolean isClient; protected VSProcess process; private boolean currentContextIsServer; - private boolean lamportIncreased; - public VSProtocol() { + public void init(VSProcess process) { + this.process = process; + this.prefs = process.getPrefs(); + + onInit(); } protected final void setProtocolClassname(String protocolClassname) { @@ -36,7 +39,8 @@ abstract public class VSProtocol extends VSPrefs implements VSEvent { } protected void sendMessage(VSMessage message) { - process.setLamportTime(process.getLamportTime()+1); + process.increaseLamportTime(); + process.increaseVectorTime(); message.setSendingProcess(process); process.sendMessage(message); } @@ -75,14 +79,6 @@ abstract public class VSProtocol extends VSPrefs implements VSEvent { this.isClient = isClient; } - public final void setVSPrefs(VSPrefs prefs) { - this.prefs = prefs; - } - - public final void setProcess(VSProcess process) { - this.process = process; - } - public void reset() { if (isServer) { currentContextIsServer = true; @@ -95,6 +91,7 @@ abstract public class VSProtocol extends VSPrefs implements VSEvent { } } + abstract protected void onInit(); abstract protected void onClientStart(); abstract protected void onClientReset(); abstract protected void onClientRecv(VSMessage message); @@ -110,6 +107,10 @@ abstract public class VSProtocol extends VSPrefs implements VSEvent { return protocol.getID() == getID(); } + protected int getNumProcesses() { + return process.getSimulationPanel().getNumProcesses(); + } + public String toString() { String type = new String(); diff --git a/sources/simulator/VSMain.java b/sources/simulator/VSMain.java index 9280eeb..db64092 100644 --- a/sources/simulator/VSMain.java +++ b/sources/simulator/VSMain.java @@ -10,14 +10,14 @@ import protocols.*; public class VSMain { public VSMain(VSPrefs prefs) { - initialize(prefs, null); + init(prefs, null); } public VSMain(VSPrefs prefs, Component relativeTo) { - initialize(prefs, relativeTo); + init(prefs, relativeTo); } - private void initialize(VSPrefs prefs, Component relativeTo) { + private void init(VSPrefs prefs, Component relativeTo) { new VSSimulationEditor(prefs, relativeTo); } @@ -27,8 +27,8 @@ public class VSMain { UIManager.getCrossPlatformLookAndFeelClassName()); } catch (Exception e) { } - VSPrefs prefs = VSDefaultPrefs.initialize(); - RegisteredProtocols.initialize(prefs); + VSPrefs prefs = VSDefaultPrefs.init(); + RegisteredProtocols.init(prefs); new VSMain(prefs); } } diff --git a/sources/simulator/VSSimulation.java b/sources/simulator/VSSimulation.java index 2bc90d8..89ffd7c 100644 --- a/sources/simulator/VSSimulation.java +++ b/sources/simulator/VSSimulation.java @@ -23,6 +23,8 @@ public class VSSimulation extends VSFrame implements ActionListener { private VSPrefs prefs; private boolean hasStarted = false; private VSLogging logging; + private JCheckBox lamportActiveCheckBox; + private JCheckBox vectorTimeActiveCheckBox; public VSSimulation (VSPrefs prefs, Component relativeTo) { super(prefs.getString("name"), relativeTo); @@ -193,17 +195,32 @@ public class VSSimulation extends VSFrame implements ActionListener { }); toolsPanel.add(loggingActiveCheckBox); - JCheckBox lamportActiveCheckBox = new JCheckBox(prefs.getString("lang.time.lamport")); + lamportActiveCheckBox = new JCheckBox(prefs.getString("lang.time.lamport")); lamportActiveCheckBox.setSelected(false); lamportActiveCheckBox.addChangeListener(new ChangeListener() { public void stateChanged(ChangeEvent ce) { AbstractButton abstractButton = (AbstractButton) ce.getSource(); ButtonModel buttonModel = abstractButton.getModel(); simulationPanel.showLamport(buttonModel.isSelected()); + if (buttonModel.isSelected()) + vectorTimeActiveCheckBox.setSelected(false); } }); toolsPanel.add(lamportActiveCheckBox); + vectorTimeActiveCheckBox = new JCheckBox(prefs.getString("lang.time.vector")); + vectorTimeActiveCheckBox.setSelected(false); + vectorTimeActiveCheckBox.addChangeListener(new ChangeListener() { + public void stateChanged(ChangeEvent ce) { + AbstractButton abstractButton = (AbstractButton) ce.getSource(); + ButtonModel buttonModel = abstractButton.getModel(); + simulationPanel.showVectorTime(buttonModel.isSelected()); + if (buttonModel.isSelected()) + lamportActiveCheckBox.setSelected(false); + } + }); + toolsPanel.add(vectorTimeActiveCheckBox); + return toolsPanel; } @@ -252,7 +269,7 @@ public class VSSimulation extends VSFrame implements ActionListener { dispose(); } else if (source.getText().equals(prefs.getString("lang.new"))) { - new VSMain(VSDefaultPrefs.initialize(), VSSimulation.this); + new VSMain(VSDefaultPrefs.init(), VSSimulation.this); } else if (source.getText().equals(prefs.getString("lang.about"))) { new VSAbout(prefs, VSSimulation.this); diff --git a/sources/simulator/VSSimulationPanel.java b/sources/simulator/VSSimulationPanel.java index f0d3d75..89fd0ad 100644 --- a/sources/simulator/VSSimulationPanel.java +++ b/sources/simulator/VSSimulationPanel.java @@ -26,6 +26,7 @@ public class VSSimulationPanel extends JPanel implements Runnable, MouseMotionLi private volatile boolean isFinished = false; private volatile boolean isResetted = false; private volatile boolean showLamport = false; + private volatile boolean showVectorTime = false; private volatile long pauseTime; private volatile long startTime; private volatile long time; @@ -39,9 +40,10 @@ public class VSSimulationPanel extends JPanel implements Runnable, MouseMotionLi private static final int SEPLINE_WIDTH = 2; private static final int XOFFSET = 50; private static final int YOFFSET = 30; - private static final int YOUTER_SPACEING = 10; + private static final int YOUTER_SPACEING = 15; private static final int YSEPLINE_SPACEING = 20; private static final int TEXT_SPACEING = 10; + private static final int ROW_HEIGHT = 14; /* Constats, which have to get calculated once after start */ private Color processlineColor; @@ -226,7 +228,7 @@ public class VSSimulationPanel extends JPanel implements Runnable, MouseMotionLi } public VSProcess createProcess(int i) { - VSProcess process = new VSProcess(prefs, this, logging, i+1); + VSProcess process = new VSProcess(prefs, this, logging); processes.add(process); logging.logg(prefs.getString("lang.process.new") + "; " + process); @@ -293,24 +295,52 @@ public class VSSimulationPanel extends JPanel implements Runnable, MouseMotionLi g.drawLine(xPos, yStart, xPos, yEnd); g.drawString(localTime+"ms", xPos + 2, yStart + TEXT_SPACEING); - if (showLamport) { - int last = -1; - final int distance = 20; - final VSLamport[] lamportStamps = process.getLamportArray(); - for (VSLamport lamport : lamportStamps) { - int xPos_ = (int) getTimeXPosition(lamport.getTime()); - if (last >= 0) { - int diff = xPos_ - last; - if (diff < distance) - xPos_ += distance - diff; + if (showLamport) + paintTime(g, process.getLamportTimeArray(), process, yStart, 25); + else if (showVectorTime) + paintTime(g, process.getVectorTimeArray(), process, yStart, 20 * numProcesses); + + for (int i = 0; i < 5; ++i) + yPoints[i] += paintProcessesOffset; + } + } + + private void paintTime(final Graphics2D g, final VSTime times[], final VSProcess process, + final int yStart, final int distance) { + + final int lastPos[] = { -1, -1, -1, -1 }; + + for (VSTime time : times) { + int xPos = (int) getTimeXPosition(time.getGlobalTime()); + int bestRow[] = { -1, -1 }; + + for (int i = 0; i < 4; ++i) { + if (lastPos[i] != -1) { + int diff = xPos - lastPos[i]; + if (diff > distance) { + bestRow[0] = i; + bestRow[1] = -1; + break; + } else if (bestRow[0] == -1) { + bestRow[0] = i; + bestRow[1] = diff; + } else if (diff > bestRow[1]) { + bestRow[0] = i; + bestRow[1] = diff; } - g.drawString(""+lamport.getLamportTime(), xPos_ + 2, yStart + 3 * TEXT_SPACEING); - last = xPos_; + } else { + bestRow[0] = i; + bestRow[1] = -1; + break; } } - for (int i = 0; i < 5; ++i) - yPoints[i] += paintProcessesOffset; + final int row = bestRow[0]; + if (bestRow[1] != -1) + xPos += distance - bestRow[1]; + + g.drawString(time.toString(), xPos + 2, yStart + 3 * TEXT_SPACEING + row * ROW_HEIGHT); + lastPos[row] = xPos; } } @@ -324,7 +354,8 @@ public class VSSimulationPanel extends JPanel implements Runnable, MouseMotionLi final int xStringPos = paintSecondlinesLine[0] - 5; g.drawString(i+"s", xStringPos, paintSecondlinesYStringPos1); - g.drawString(i+"s", xStringPos, paintSecondlinesYStringPos2); + if (!showVectorTime && !showLamport) + g.drawString(i+"s", xStringPos, paintSecondlinesYStringPos2); } if (i > paintSecondlinesSeconds) { @@ -529,6 +560,11 @@ public class VSSimulationPanel extends JPanel implements Runnable, MouseMotionLi repaint(); } + public void showVectorTime(boolean showVectorTime) { + this.showVectorTime = showVectorTime; + repaint(); + } + public void sendMessage(VSMessage message) { VSTask task = null; VSProcess sendingProcess = message.getSendingProcess(); @@ -554,7 +590,7 @@ public class VSSimulationPanel extends JPanel implements Runnable, MouseMotionLi synchronized (messageLines) { messageLines.add(new VSMessageLine(receiverProcess, sendingProcess.getGlobalTime(), deliverTime, outageTime, - sendingProcess.getNum(), receiverProcess.getNum())); + sendingProcess.getProcessID(), receiverProcess.getProcessID())); } } } diff --git a/sources/utils/VSClassLoader.java b/sources/utils/VSClassLoader.java index 7d9fdf3..8470f53 100644 --- a/sources/utils/VSClassLoader.java +++ b/sources/utils/VSClassLoader.java @@ -1,15 +1,19 @@ package utils; import java.util.*; +import java.lang.reflect.*; import prefs.*; +import core.*; public class VSClassLoader extends ClassLoader { public Object newInstance(String classname) { Object object = null; try { - object = loadClass(classname, true).newInstance(); + object = super.loadClass(classname, true).newInstance(); + //Constructor constructors[] = theClass.getConstructors(); + //object = constructors[0].newInstance(process); } catch (Exception e) { System.out.println(e); diff --git a/sources/utils/VSFrame.java b/sources/utils/VSFrame.java index 2725729..9bd70a9 100644 --- a/sources/utils/VSFrame.java +++ b/sources/utils/VSFrame.java @@ -12,15 +12,15 @@ public class VSFrame extends JFrame { public VSFrame(String title, Component parent) { super(title); - initialize(parent); + init(parent); } public VSFrame(String title) { super(title); - initialize(null); + init(null); } - private void initialize(Component parent) { + private void init(Component parent) { this.parent = parent; this.dispose = false; diff --git a/sources/utils/VSInfoArea.java b/sources/utils/VSInfoArea.java index 9d3600e..c1afd42 100644 --- a/sources/utils/VSInfoArea.java +++ b/sources/utils/VSInfoArea.java @@ -6,15 +6,15 @@ import javax.swing.border.*; public class VSInfoArea extends JTextPane { public VSInfoArea() { - initialize(); + init(); } public VSInfoArea(String text) { setText(text); - initialize(); + init(); } - private void initialize() { + private void init() { setOpaque(false); setBorder(null); setFocusable(false); |
