From c3b95267b24d843897b04d6d6a16f62dc8cf1ed2 Mon Sep 17 00:00:00 2001 From: Paul Buetow Date: Fri, 20 Jun 2025 19:47:04 +0300 Subject: Add comprehensive architecture documentation MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Create ARCHITECTURE.md with system overview, component diagrams, and design patterns - Add DEVELOPER_GUIDE.md for creating new protocols and events - Add TIMESTAMP_EVENTS_GUIDE.md for timestamp-triggered event system - Include PlantUML diagrams for technical architecture - Document event-driven design and protocol framework - Add sequence diagrams for key workflows - Include best practices and common patterns - Update README with links to new documentation 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude --- README.md | 10 + docs/ARCHITECTURE.md | 397 +++++++++++++++++++++++++++++ docs/DEVELOPER_GUIDE.md | 537 ++++++++++++++++++++++++++++++++++++++++ docs/TIMESTAMP_EVENTS_GUIDE.md | 293 ++++++++++++++++++++++ docs/architecture-diagrams.puml | 390 +++++++++++++++++++++++++++++ 5 files changed, 1627 insertions(+) create mode 100644 docs/ARCHITECTURE.md create mode 100644 docs/DEVELOPER_GUIDE.md create mode 100644 docs/TIMESTAMP_EVENTS_GUIDE.md create mode 100644 docs/architecture-diagrams.puml diff --git a/README.md b/README.md index 8d872fc..c0332d0 100644 --- a/README.md +++ b/README.md @@ -228,11 +228,21 @@ ds-sim/ │ │ └── utils/ # Utilities and helpers │ └── resources/ # Configuration files ├── docs/ # Documentation +│ ├── ARCHITECTURE.md # System architecture and design +│ ├── DEVELOPER_GUIDE.md # Guide for extending DS-Sim +│ └── TIMESTAMP_EVENTS_GUIDE.md # Timestamp event system ├── saved-simulations/ # Example simulation files ├── scripts/ # Development scripts └── pom.xml # Maven configuration ``` +## Documentation + +- **[Architecture Guide](docs/ARCHITECTURE.md)** - System design, components, and diagrams +- **[Developer Guide](docs/DEVELOPER_GUIDE.md)** - How to create new protocols and events +- **[Timestamp Events Guide](docs/TIMESTAMP_EVENTS_GUIDE.md)** - Using timestamp-triggered events +- **[CLAUDE.md](CLAUDE.md)** - Build commands and project overview + ## Contributing 1. Fork the repository diff --git a/docs/ARCHITECTURE.md b/docs/ARCHITECTURE.md new file mode 100644 index 0000000..f222850 --- /dev/null +++ b/docs/ARCHITECTURE.md @@ -0,0 +1,397 @@ +# DS-Sim Architecture Documentation + +## Table of Contents +1. [Overview](#overview) +2. [Core Architecture](#core-architecture) +3. [Event-Driven Design](#event-driven-design) +4. [Protocol Framework](#protocol-framework) +5. [Time Management](#time-management) +6. [Message System](#message-system) +7. [Component Diagrams](#component-diagrams) +8. [Sequence Diagrams](#sequence-diagrams) + +## Overview + +DS-Sim is an event-driven distributed systems simulator built with Java. It provides a visual environment for simulating and understanding distributed algorithms, protocols, and time synchronization mechanisms. + +### Key Design Principles +- **Event-Driven Architecture**: All actions are modeled as events +- **Pluggable Protocols**: Easy to add new distributed algorithms +- **Visual Feedback**: Real-time visualization of process states and messages +- **Time Simulation**: Support for logical clocks and clock drift + +## Core Architecture + +### Layer Diagram +``` +┌─────────────────────────────────────────────────────────────┐ +│ User Interface Layer │ +│ VSSimulatorFrame, VSSimulator, VSSimulatorVisualization │ +├─────────────────────────────────────────────────────────────┤ +│ Protocol Layer │ +│ VSAbstractProtocol, Protocol Implementations │ +├─────────────────────────────────────────────────────────────┤ +│ Event System Layer │ +│ VSAbstractEvent, VSTask, VSTaskManager │ +├─────────────────────────────────────────────────────────────┤ +│ Core Process Layer │ +│ VSAbstractProcess, VSInternalProcess, VSMessage │ +├─────────────────────────────────────────────────────────────┤ +│ Infrastructure Layer │ +│ Time Management, Serialization, Utilities │ +└─────────────────────────────────────────────────────────────┘ +``` + +### Component Overview + +```mermaid +graph TB + subgraph UI[User Interface] + Frame[VSSimulatorFrame] + Sim[VSSimulator] + Viz[VSSimulatorVisualization] + end + + subgraph Core[Core Components] + TM[VSTaskManager] + IP[VSInternalProcess] + Msg[VSMessage] + end + + subgraph Events[Event System] + AE[VSAbstractEvent] + Task[VSTask] + RE[VSRegisteredEvents] + end + + subgraph Protocols[Protocols] + AP[VSAbstractProtocol] + PP[PingPongProtocol] + BC[BroadcastProtocol] + TC[TwoPhaseCommit] + end + + Frame --> Sim + Sim --> Viz + Viz --> TM + TM --> Task + Task --> AE + IP --> Msg + AP --> AE + PP --> AP + BC --> AP + TC --> AP +``` + +## Event-Driven Design + +The simulator operates on an event-driven model where all actions are encapsulated as events that are scheduled and executed by the task manager. + +### Event Hierarchy + +```mermaid +classDiagram + class VSAbstractEvent { + <> + +onInit() + +onStart() + +getClassname() + +isInternalEvent() + +shouldIncreaseTimestamps() + } + + class VSAbstractProtocol { + <> + +onServerInit() + +onClientInit() + +onServerRecv() + +onClientRecv() + +sendMessage() + } + + class VSProcessCrashEvent { + +onStart() + } + + class VSMessageReceiveEvent { + +onStart() + } + + class VSTimestampTriggeredEvent { + <> + +checkCondition() + +onTimestampReached() + } + + VSAbstractEvent <|-- VSAbstractProtocol + VSAbstractEvent <|-- VSProcessCrashEvent + VSAbstractEvent <|-- VSMessageReceiveEvent + VSAbstractEvent <|-- VSTimestampTriggeredEvent +``` + +### Event Lifecycle + +1. **Creation**: Events are created with specific parameters +2. **Initialization**: `onInit()` is called once when first added +3. **Scheduling**: Events are wrapped in `VSTask` with execution time +4. **Execution**: `onStart()` is called when scheduled time arrives +5. **Completion**: Event completes or schedules new events + +## Protocol Framework + +Protocols implement distributed algorithms and define client-server communication patterns. + +### Protocol Structure + +```mermaid +stateDiagram-v2 + [*] --> Uninitialized + Uninitialized --> ServerInit: isServer + Uninitialized --> ClientInit: isClient + + ServerInit --> ServerReady + ClientInit --> ClientReady + + ServerReady --> ServerStart: hasOnServerStart + ClientReady --> ClientStart: !hasOnServerStart + + ServerReady --> ServerRecv: receive message + ClientReady --> ClientRecv: receive message + + ServerReady --> ServerSchedule: scheduled event + ClientReady --> ClientSchedule: scheduled event +``` + +### Protocol Implementation Pattern + +```java +public class MyProtocol extends VSAbstractProtocol { + public MyProtocol() { + super(HAS_ON_SERVER_START); // or HAS_ON_CLIENT_START + } + + // Server-side methods + public void onServerInit() { /* Initialize server state */ } + public void onServerStart() { /* Server begins protocol */ } + public void onServerRecv(VSMessage msg) { /* Handle client message */ } + public void onServerSchedule() { /* Periodic server action */ } + + // Client-side methods + public void onClientInit() { /* Initialize client state */ } + public void onClientStart() { /* Client begins protocol */ } + public void onClientRecv(VSMessage msg) { /* Handle server message */ } + public void onClientSchedule() { /* Periodic client action */ } +} +``` + +## Time Management + +The simulator supports multiple time representations for distributed systems research. + +### Time Types + +```mermaid +graph LR + subgraph Time System + GT[Global Time
Simulation Clock] + LT[Local Time
Process Clock] + LAM[Lamport Time
Logical Clock] + VT[Vector Time
Vector Clock] + end + + GT --> LT + LT --> LAM + LT --> VT +``` + +### Clock Synchronization + +- **Global Time**: Absolute simulation time (milliseconds) +- **Local Time**: Process time with configurable drift +- **Lamport Time**: Increments on events and messages +- **Vector Time**: Array of logical times for each process + +### Clock Drift Simulation + +``` +Local Time = Global Time + Accumulated Drift +Drift Rate = Clock Variance (e.g., -0.1 to +0.1) +``` + +## Message System + +Messages in DS-Sim carry protocol data between processes with automatic timestamp management. + +### Message Flow + +```mermaid +sequenceDiagram + participant P1 as Process 1 + participant TM as TaskManager + participant Net as Network Sim + participant P2 as Process 2 + + P1->>P1: Increase timestamps + P1->>TM: Create send task + TM->>Net: Schedule with delay + Net->>TM: Create receive task + TM->>P2: Deliver message + P2->>P2: Update timestamps + P2->>P2: Process message +``` + +### Message Properties + +- **Sender/Receiver**: Process IDs +- **Protocol**: Associated protocol class +- **Timestamps**: Lamport and vector times +- **Payload**: Serializable data +- **Type**: Server or client message + +## Component Diagrams + +### Task Management System + +```mermaid +graph TB + subgraph TaskManager + PQ[Priority Queue
Time-ordered tasks] + GL[Global Tasks
Simulation time] + LL[Local Tasks
Process time] + end + + subgraph Task Execution + Run[runTasks
Main loop] + Exec[Execute task] + Update[Update times] + end + + PQ --> Run + Run --> Exec + Exec --> Update + Update --> PQ +``` + +### Process Architecture + +```mermaid +classDiagram + class VSAbstractProcess { + <> + #localTime: long + #globalTime: long + #lamportTime: long + #vectorTime: VSVectorTime + +increaseTime() + +sendMessage() + } + + class VSInternalProcess { + -clockVariance: float + -clockOffset: double + -vectorClockMonitor: VSVectorClockMonitor + +syncTime(globalTime) + +highlightOn() + +crash() + +recover() + } + + VSAbstractProcess <|-- VSInternalProcess +``` + +## Sequence Diagrams + +### Protocol Initialization + +```mermaid +sequenceDiagram + participant UI as User Interface + participant Reg as VSRegisteredEvents + participant Proto as Protocol + participant Proc as Process + + UI->>Reg: Select protocol + Reg->>Proto: Create instance + Proto->>Proc: Set process + Proc->>Proto: isServer(true/false) + Proto->>Proto: onServerInit/onClientInit + Proto->>UI: Ready +``` + +### Event Processing Loop + +```mermaid +sequenceDiagram + participant Viz as Visualization + participant TM as TaskManager + participant Task as VSTask + participant Event as Event + participant Proc as Process + + loop Simulation Loop + Viz->>TM: runTasks(currentTime) + TM->>TM: Get ready tasks + TM->>Task: run() + Task->>Event: onStart() + Event->>Proc: Update state + Event->>TM: Schedule new tasks + end +``` + +### Two-Phase Commit Example + +```mermaid +sequenceDiagram + participant Coord as Coordinator + participant P1 as Process 1 + participant P2 as Process 2 + + Coord->>P1: VOTE_REQUEST + Coord->>P2: VOTE_REQUEST + P1->>Coord: VOTE_YES + P2->>Coord: VOTE_YES + Coord->>Coord: All votes YES + Coord->>P1: GLOBAL_COMMIT + Coord->>P2: GLOBAL_COMMIT + P1->>Coord: ACK + P2->>Coord: ACK +``` + +## Adding New Components + +### Creating a New Event + +1. Extend `VSAbstractEvent` +2. Implement `onInit()` and `onStart()` +3. Register in `VSRegisteredEvents.init()` + +### Creating a New Protocol + +1. Extend `VSAbstractProtocol` +2. Implement required abstract methods +3. Choose `HAS_ON_SERVER_START` or `HAS_ON_CLIENT_START` +4. Register in `VSRegisteredEvents.init()` + +### Creating Timestamp-Triggered Events + +1. Extend `VSTimestampTriggeredEvent` +2. Implement `onTimestampReached()` +3. Configure trigger conditions +4. Register with process monitor + +## Design Patterns Used + +- **Template Method**: Protocol base class defines structure +- **Observer**: Event system for loose coupling +- **Strategy**: Pluggable protocols and events +- **Factory**: Event creation through registry +- **Singleton**: Global registries and managers +- **Command**: Events encapsulate actions + +## Future Architecture Improvements + +1. **GUI Separation**: Extract UI from business logic +2. **Dependency Injection**: Remove static registries +3. **Event Bus**: Decouple component communication +4. **Plugin System**: Dynamic protocol loading +5. **Reactive Streams**: Modern async event handling \ No newline at end of file diff --git a/docs/DEVELOPER_GUIDE.md b/docs/DEVELOPER_GUIDE.md new file mode 100644 index 0000000..ed0f8e1 --- /dev/null +++ b/docs/DEVELOPER_GUIDE.md @@ -0,0 +1,537 @@ +# DS-Sim Developer Guide + +This guide explains how to extend DS-Sim with new protocols, events, and features. + +## Table of Contents +1. [Creating a New Protocol](#creating-a-new-protocol) +2. [Creating Custom Events](#creating-custom-events) +3. [Working with Time and Timestamps](#working-with-time-and-timestamps) +4. [Message Passing](#message-passing) +5. [Testing Your Components](#testing-your-components) +6. [Best Practices](#best-practices) + +## Creating a New Protocol + +### Step 1: Understand the Protocol Framework + +All protocols extend `VSAbstractProtocol` and must implement both server and client sides, even if one side does nothing. The framework supports two initialization patterns: + +- **Server-initiated**: Protocol starts from server side (`HAS_ON_SERVER_START = true`) +- **Client-initiated**: Protocol starts from client side (`HAS_ON_CLIENT_START = false`) + +### Step 2: Create Your Protocol Class + +```java +package protocols.implementations; + +import core.VSMessage; +import protocols.VSAbstractProtocol; + +public class VSMyProtocol extends VSAbstractProtocol { + + // Protocol-specific constants + private static final String MSG_REQUEST = "REQUEST"; + private static final String MSG_RESPONSE = "RESPONSE"; + + // State variables (separate for client/server) + private int serverState; + private int clientState; + + public VSMyProtocol() { + // true = server starts, false = client starts + super(HAS_ON_SERVER_START); + } + + // Server-side implementation + @Override + public void onServerInit() { + // Initialize server state + serverState = 0; + // Set any server preferences + setBoolean("myprotocol.server.enabled", true); + } + + @Override + public void onServerStart() { + // Server initiates the protocol + VSMessage msg = new VSMessage(); + msg.setString("type", MSG_REQUEST); + msg.setInteger("value", 42); + sendMessage(msg); // Broadcasts to all clients + } + + @Override + public void onServerRecv(VSMessage message) { + // Handle messages from clients + String type = message.getString("type"); + if (MSG_RESPONSE.equals(type)) { + int clientId = message.getSenderNum(); + int value = message.getInteger("value"); + process.log("Received response from client " + clientId + ": " + value); + } + } + + @Override + public void onServerSchedule() { + // Called when a scheduled server event fires + // Schedule periodic actions using scheduleAt(time) + } + + @Override + public void onServerReset() { + // Clean up server state + serverState = 0; + } + + // Client-side implementation + @Override + public void onClientInit() { + // Initialize client state + clientState = 0; + setBoolean("myprotocol.client.autorespond", true); + } + + @Override + public void onClientStart() { + // Only called if HAS_ON_CLIENT_START = false + } + + @Override + public void onClientRecv(VSMessage message) { + // Handle messages from server + String type = message.getString("type"); + if (MSG_REQUEST.equals(type)) { + int value = message.getInteger("value"); + + // Process the request + clientState = value * 2; + + // Send response + VSMessage response = new VSMessage(); + response.setString("type", MSG_RESPONSE); + response.setInteger("value", clientState); + sendMessage(response); + } + } + + @Override + public void onClientSchedule() { + // Called when a scheduled client event fires + } + + @Override + public void onClientReset() { + // Clean up client state + clientState = 0; + } +} +``` + +### Step 3: Register Your Protocol + +Add your protocol to `VSRegisteredEvents.init()`: + +```java +public static void init(VSPrefs prefs_) { + // ... existing registrations ... + registerEvent("protocols.implementations.VSMyProtocol"); +} +``` + +### Step 4: Protocol Communication Patterns + +#### Broadcast (Server to All Clients) +```java +// In server code +VSMessage msg = new VSMessage(); +sendMessage(msg); // Automatically sent to all clients +``` + +#### Unicast (Client to Server) +```java +// In client code +VSMessage msg = new VSMessage(); +sendMessage(msg); // Automatically sent to server only +``` + +#### Selective Send (Server to Specific Client) +```java +// In server code - requires custom handling +VSMessage msg = new VSMessage(); +msg.setInteger("targetClient", 2); // Custom field +sendMessage(msg); // Clients must filter +``` + +### Step 5: Using Scheduled Events + +```java +// Schedule a task to run at local time 1000 +scheduleAt(1000); + +// This will trigger onServerSchedule() or onClientSchedule() +@Override +public void onServerSchedule() { + // Periodic action + process.log("Scheduled event triggered"); + + // Reschedule for next interval + long nextTime = process.getTime() + 500; + scheduleAt(nextTime); +} +``` + +## Creating Custom Events + +### Basic Event + +```java +package events.implementations; + +import events.VSAbstractEvent; + +public class VSMyEvent extends VSAbstractEvent { + + private String eventData; + + @Override + public void onInit() { + // Called once when event is first created + setClassname(getClass().getName()); + eventData = getString("myevent.data", "default"); + } + + @Override + public void onStart() { + // Called when event executes + process.log("MyEvent executing with data: " + eventData); + + // Optionally schedule another event + VSMyEvent nextEvent = new VSMyEvent(); + VSTask task = new VSTask( + process.getTime() + 100, // When to execute + process, // Which process + nextEvent, // What event + VSTask.LOCAL // LOCAL or GLOBAL time + ); + // Add task through simulator + } + + @Override + protected String createShortname(String savedShortname) { + return "MyEvent"; + } +} +``` + +### Copyable Event + +```java +public class VSCopyableMyEvent extends VSAbstractEvent implements VSCopyableEvent { + + private int counter; + + @Override + public void initCopy(VSAbstractEvent copy) { + if (copy instanceof VSCopyableMyEvent) { + VSCopyableMyEvent myCopy = (VSCopyableMyEvent) copy; + myCopy.counter = this.counter; + } + } + + // ... rest of implementation +} +``` + +### Timestamp-Triggered Event + +```java +public class VSCustomTimestampEvent extends VSTimestampTriggeredEvent { + + public VSCustomTimestampEvent() { + // Trigger when Lamport time >= 50 + super(50, ComparisonOperator.GREATER_EQUAL); + } + + @Override + protected void onTimestampReached() { + // This fires when condition is met + process.log("Lamport time reached 50!"); + + // Highlight process + if (process instanceof VSInternalProcess) { + ((VSInternalProcess) process).highlightOn(); + } + } +} +``` + +## Working with Time and Timestamps + +### Time Types in DS-Sim + +1. **Global Time**: Simulation-wide clock (milliseconds) +2. **Local Time**: Per-process clock with drift +3. **Lamport Time**: Logical timestamp for ordering +4. **Vector Time**: Vector clock for causality + +### Accessing Time Values + +```java +// In a protocol or event +long globalTime = process.getGlobalTime(); +long localTime = process.getTime(); // Local time +long lamportTime = process.getLamportTime(); +VSVectorTime vectorTime = process.getVectorTime(); + +// Increase timestamps (done automatically for messages) +process.increaseLamportTime(); +process.increaseVectorTime(); +``` + +### Clock Drift Simulation + +```java +// In VSInternalProcess configuration +setFloat("process.clock.variance", 0.1f); // 10% drift +``` + +## Message Passing + +### Message Structure + +```java +// Creating a message +VSMessage msg = new VSMessage(); + +// Set data - supports various types +msg.setString("type", "REQUEST"); +msg.setInteger("sequence", 42); +msg.setBoolean("urgent", true); +msg.setFloat("value", 3.14f); +msg.setLong("timestamp", System.currentTimeMillis()); + +// Get data +String type = msg.getString("type"); +int seq = msg.getInteger("sequence", 0); // With default +``` + +### Message Metadata + +```java +// In receiver +int sender = message.getSenderNum(); +int receiver = message.getReceiverNum(); +VSLamportTime msgLamport = message.getLamportTime(); +VSVectorTime msgVector = message.getVectorTime(); +``` + +### Complex Data in Messages + +```java +// For complex data, convert to string +JSONObject data = new JSONObject(); +data.put("items", new JSONArray(items)); +msg.setString("data", data.toString()); + +// Or implement custom serialization +msg.setInteger("arraySize", array.length); +for (int i = 0; i < array.length; i++) { + msg.setInteger("array_" + i, array[i]); +} +``` + +## Testing Your Components + +### Unit Testing a Protocol + +```java +@Test +public void testProtocolServerInit() { + // Setup + VSPrefs prefs = new VSPrefs(); + VSInternalProcess process = mock(VSInternalProcess.class); + when(process.getNum()).thenReturn(0); + + // Create protocol + VSMyProtocol protocol = new VSMyProtocol(); + protocol.setProcess(process); + protocol.setPrefs(prefs); + protocol.isServer(true); + + // Test initialization + protocol.onInit(); + + // Verify state + assertTrue(prefs.getBoolean("myprotocol.server.enabled")); +} + +@Test +public void testMessageHandling() { + // Setup protocol and process + VSMyProtocol protocol = new VSMyProtocol(); + protocol.setProcess(mockProcess); + protocol.isClient(true); + protocol.onInit(); + + // Create test message + VSMessage msg = new VSMessage(); + msg.setString("type", "REQUEST"); + msg.setInteger("value", 10); + + // Test message handling + protocol.onClientRecv(msg); + + // Verify response was sent + verify(mockProcess).sendMessage(any(VSMessage.class)); +} +``` + +### Integration Testing + +```java +@Test +public void testProtocolIntegration() { + // Create simulator components + VSSimulatorVisualization viz = new VSSimulatorVisualization(); + VSTaskManager taskManager = new VSTaskManager(viz); + + // Create processes + VSInternalProcess server = createProcess(0, viz); + VSInternalProcess client1 = createProcess(1, viz); + VSInternalProcess client2 = createProcess(2, viz); + + // Setup protocol on all processes + setupProtocol(server, true, false); // server + setupProtocol(client1, false, true); // client + setupProtocol(client2, false, true); // client + + // Run simulation steps + for (int i = 0; i < 10; i++) { + taskManager.runTasks(i * 100); + } + + // Verify expected behavior + // Check logs, state changes, etc. +} +``` + +## Best Practices + +### 1. State Management + +- Keep server and client state separate +- Use preferences (VSPrefs) for configurable values +- Reset state properly in onReset methods + +### 2. Error Handling + +```java +@Override +public void onServerRecv(VSMessage message) { + try { + String type = message.getString("type"); + if (type == null) { + process.log("Warning: Received message without type"); + return; + } + // Process message + } catch (Exception e) { + VSErrorHandler.handle(e, "Error processing message"); + } +} +``` + +### 3. Logging + +```java +// Use process.log for important events +process.log("Protocol started"); + +// Add context to logs +process.log(String.format("Received %s from process %d", + msgType, message.getSenderNum())); + +// Debug logging +if (getBoolean("debug.verbose")) { + process.log("Debug: " + detailedInfo); +} +``` + +### 4. Performance Considerations + +- Avoid scheduling too many events +- Use appropriate time types (LOCAL vs GLOBAL) +- Clean up completed tasks and state +- Be mindful of message size + +### 5. Protocol Design + +- Document message types and formats +- Handle missing or malformed messages gracefully +- Consider network failures and timeouts +- Test with various numbers of processes + +### 6. Code Organization + +``` +protocols/implementations/ +├── VSMyProtocol.java # Main protocol implementation +├── messages/ # Message type constants +│ └── MyProtocolMessages.java +└── state/ # Complex state management + └── MyProtocolState.java +``` + +## Common Patterns + +### Request-Response Pattern + +```java +// Server sends request with ID +msg.setInteger("requestId", nextRequestId++); +pendingRequests.put(requestId, new RequestInfo()); + +// Client echoes ID in response +response.setInteger("requestId", message.getInteger("requestId")); + +// Server matches response to request +int requestId = message.getInteger("requestId"); +RequestInfo info = pendingRequests.remove(requestId); +``` + +### Timeout Handling + +```java +// Schedule timeout when sending request +long timeout = process.getTime() + 5000; +scheduleAt(timeout); +markTimeout(timeout, requestId); + +// In onSchedule, check for timeouts +if (isTimeout(process.getTime())) { + handleTimeout(); +} +``` + +### State Machine Implementation + +```java +enum ProtocolState { + INIT, WAITING, PROCESSING, DONE +} + +private ProtocolState state = ProtocolState.INIT; + +@Override +public void onServerRecv(VSMessage message) { + switch (state) { + case INIT: + handleInit(message); + break; + case WAITING: + handleWaiting(message); + break; + // etc. + } +} +``` \ No newline at end of file diff --git a/docs/TIMESTAMP_EVENTS_GUIDE.md b/docs/TIMESTAMP_EVENTS_GUIDE.md new file mode 100644 index 0000000..67ba2c0 --- /dev/null +++ b/docs/TIMESTAMP_EVENTS_GUIDE.md @@ -0,0 +1,293 @@ +# Timestamp-Triggered Events Guide + +This guide explains how to use DS-Sim's timestamp-triggered event system to create events that fire based on logical time conditions. + +## Overview + +Timestamp-triggered events allow you to: +- Fire events when Lamport timestamps reach specific values +- Trigger actions based on vector clock conditions +- Create complex temporal conditions for distributed algorithms +- Visualize causality and ordering in distributed systems + +## Event Types + +### 1. VSLamportTimestampEvent + +Triggers based on Lamport logical clock conditions. + +```java +// Fire when Lamport time reaches exactly 100 +VSLamportTimestampEvent event1 = new VSLamportTimestampEvent( + 100, ComparisonOperator.EQUAL, "Reached checkpoint" +); + +// Fire when Lamport time exceeds 50 +VSLamportTimestampEvent event2 = new VSLamportTimestampEvent( + 50, ComparisonOperator.GREATER_THAN, "Passed threshold" +); + +// With custom action +VSLamportTimestampEvent event3 = new VSLamportTimestampEvent( + 200, ComparisonOperator.GREATER_EQUAL, "Major milestone", + () -> { + System.out.println("Milestone reached!"); + // Custom logic here + } +); +``` + +### 2. VSVectorTimestampEvent + +Triggers based on vector clock conditions. + +```java +// Create target vector time [10, 5, 8] +VSVectorTime targetVector = new VSVectorTime(3); +targetVector.set(0, 10); +targetVector.set(1, 5); +targetVector.set(2, 8); + +// Fire when vector time equals target +VSVectorTimestampEvent event1 = new VSVectorTimestampEvent( + targetVector, ComparisonOperator.EQUAL, "Vectors synchronized" +); + +// Fire when current vector >= target (happens-before relation) +VSVectorTimestampEvent event2 = new VSVectorTimestampEvent( + targetVector, ComparisonOperator.GREATER_EQUAL, "Causality met" +); +``` + +### 3. VSTimestampMonitorEvent + +Monitors multiple timestamp conditions simultaneously. + +```java +VSTimestampMonitorEvent monitor = new VSTimestampMonitorEvent(); + +// Add multiple Lamport conditions +monitor.addLamportEvent(new VSLamportTimestampEvent( + 10, ComparisonOperator.EQUAL, "Early checkpoint" +)); +monitor.addLamportEvent(new VSLamportTimestampEvent( + 50, ComparisonOperator.GREATER_THAN, "Mid checkpoint" +)); + +// Add vector conditions +monitor.addVectorEvent(new VSVectorTimestampEvent( + targetVector, ComparisonOperator.EQUAL, "Vector match" +)); +``` + +## Comparison Operators + +| Operator | Symbol | Description | Example | +|----------|--------|-------------|---------| +| EQUAL | == | Exact match | Lamport == 100 | +| GREATER_THAN | > | Strictly greater | Lamport > 50 | +| LESS_THAN | < | Strictly less | Lamport < 30 | +| GREATER_EQUAL | >= | Greater or equal | Lamport >= 75 | +| LESS_EQUAL | <= | Less or equal | Lamport <= 25 | + +## Vector Clock Comparisons + +Vector clock comparisons follow the happens-before relation: + +- **Equal**: All components are equal +- **Greater**: v1 >= v2 in all components AND v1 > v2 in at least one +- **Less**: v2 > v1 (inverse of greater) +- **Concurrent**: Neither v1 > v2 nor v2 > v1 + +## Usage Examples + +### Example 1: Debugging Protocol Synchronization + +```java +// In your protocol initialization +public void onServerInit() { + // Fire when all clients have caught up + VSVectorTime syncPoint = new VSVectorTime(getNumProcesses()); + for (int i = 0; i < getNumProcesses(); i++) { + syncPoint.set(i, 10); // All processes at time 10 + } + + VSVectorTimestampEvent syncEvent = new VSVectorTimestampEvent( + syncPoint, ComparisonOperator.GREATER_EQUAL, + "All processes synchronized" + ); + + // Register with process + VSInternalProcess internal = (VSInternalProcess) process; + internal.getVectorClockMonitor().registerVectorEvent(syncEvent); +} +``` + +### Example 2: Phased Protocol Execution + +```java +public class PhasedProtocol extends VSAbstractProtocol { + + @Override + public void onServerInit() { + // Phase 1: Initialization (Lamport 0-20) + schedulePhase(20, "Phase 1 complete", this::startPhase2); + + // Phase 2: Data exchange (Lamport 21-50) + schedulePhase(50, "Phase 2 complete", this::startPhase3); + + // Phase 3: Finalization (Lamport > 50) + schedulePhase(100, "Protocol complete", this::finishProtocol); + } + + private void schedulePhase(long timestamp, String desc, Runnable action) { + VSLamportTimestampEvent phase = new VSLamportTimestampEvent( + timestamp, ComparisonOperator.GREATER_EQUAL, desc, action + ); + + // Add to process's task manager + VSTask task = new VSTask(0, process, phase, VSTask.LOCAL); + // ... add task to manager + } +} +``` + +### Example 3: Detecting Causality Violations + +```java +// Monitor for out-of-order message delivery +VSTimestampMonitorEvent causalityMonitor = new VSTimestampMonitorEvent() { + @Override + protected void onTimestampReached() { + // Check if vector times indicate causality violation + VSVectorTime current = process.getVectorTime(); + VSVectorTime expected = getExpectedVector(); + + if (!isValidCausalOrder(current, expected)) { + process.log("WARNING: Causality violation detected!"); + highlightProcess(); + } + } +}; +``` + +### Example 4: Performance Benchmarking + +```java +// Measure time to reach consensus +long startGlobal = process.getGlobalTime(); + +VSLamportTimestampEvent consensusReached = new VSLamportTimestampEvent( + CONSENSUS_LAMPORT_TIME, + ComparisonOperator.EQUAL, + "Consensus reached", + () -> { + long elapsed = process.getGlobalTime() - startGlobal; + process.log("Consensus took " + elapsed + "ms global time"); + process.log("Lamport time: " + process.getLamportTime()); + } +); +``` + +## Implementation Details + +### Registration and Monitoring + +1. **Process Registration**: Events are registered with the process +2. **Continuous Monitoring**: Vector events are checked on every vector clock update +3. **One-Time Trigger**: Events fire only once when condition is first met +4. **No Retroactive Firing**: Events won't fire if condition was already true + +### Memory Considerations + +- Events are kept in memory until triggered +- Use `reset()` to reuse events +- Remove completed events to free memory +- Vector clock monitors have O(n) checking cost + +### Visual Feedback + +```java +@Override +protected void onTimestampReached() { + VSInternalProcess internal = (VSInternalProcess) process; + + // Highlight process + internal.highlightOn(); + + // Log event + internal.log("Timestamp event: " + getActionDescription()); + + // Change process color temporarily + scheduleColorReset(internal, 2000); // Reset after 2 seconds +} +``` + +## Best Practices + +1. **Use Descriptive Names**: Make event descriptions clear +2. **Avoid Tight Conditions**: Use >= instead of == when possible +3. **Consider Clock Drift**: Local clocks may not advance uniformly +4. **Test Edge Cases**: Test with 1, 2, and many processes +5. **Clean Up**: Remove or reset events after use + +## Troubleshooting + +### Event Not Firing + +1. Check operator logic (>= vs >) +2. Verify timestamp is actually increasing +3. Ensure event is properly registered +4. Check `hasTriggered` flag hasn't been set + +### Multiple Firings + +- Events fire only once by design +- Use `reset()` to allow re-firing +- Create new events for repeated conditions + +### Performance Issues + +- Limit number of active monitors +- Use Lamport events when possible (faster than vector) +- Consider sampling instead of continuous monitoring + +## Advanced Usage + +### Custom Timestamp Events + +```java +public class ComplexTimestampEvent extends VSTimestampTriggeredEvent { + + @Override + protected boolean checkCondition(VSInternalProcess process) { + // Custom complex condition + long lamport = process.getLamportTime(); + VSVectorTime vector = process.getVectorTime(); + + // Example: Fire when Lamport > 50 AND vector[0] > vector[1] + return lamport > 50 && + vector.get(0) > vector.get(1); + } + + @Override + protected void onTimestampReached() { + process.log("Complex condition met!"); + } +} +``` + +### Chaining Events + +```java +VSLamportTimestampEvent phase1 = new VSLamportTimestampEvent( + 50, ComparisonOperator.EQUAL, "Phase 1", + () -> { + // Phase 1 complete, schedule phase 2 + VSLamportTimestampEvent phase2 = new VSLamportTimestampEvent( + 100, ComparisonOperator.EQUAL, "Phase 2" + ); + // Register phase2... + } +); +``` \ No newline at end of file diff --git a/docs/architecture-diagrams.puml b/docs/architecture-diagrams.puml new file mode 100644 index 0000000..e9b675b --- /dev/null +++ b/docs/architecture-diagrams.puml @@ -0,0 +1,390 @@ +@startuml DS-Sim Core Architecture + +!define RECTANGLE class + +package "User Interface Layer" { + RECTANGLE VSSimulatorFrame { + - menuBar: JMenuBar + - simulator: VSSimulator + + createSimulator() + + showAboutDialog() + } + + RECTANGLE VSSimulator { + - simulatorVisualization: VSSimulatorVisualization + - taskManager: VSTaskManager + - logingArea: JTextArea + + reset() + + play() + + pause() + } + + RECTANGLE VSSimulatorVisualization { + - processes: List + - globalTime: long + - isPaused: boolean + + paintComponent(Graphics) + + run() + + addProcess() + } +} + +package "Event System" { + abstract RECTANGLE VSAbstractEvent { + # process: VSAbstractProcess + # prefs: VSPrefs + + {abstract} onInit() + + {abstract} onStart() + + isInternalEvent(): boolean + + shouldIncreaseTimestamps(): boolean + + getEventPriority(): int + } + + RECTANGLE VSTask { + - time: long + - process: VSAbstractProcess + - event: VSAbstractEvent + - timeType: int + + run() + + compareTo(VSTask): int + } + + RECTANGLE VSTaskManager { + - tasks: VSPriorityQueue + - simulatorVisualization: VSSimulatorVisualization + + addTask(VSTask) + + runTasks(long) + + removeAllTasks() + } + + RECTANGLE VSRegisteredEvents { + {static} - eventClassnamesByNames: Map + {static} - eventShortnamesByClassnames: Map + {static} + init(VSPrefs) + {static} + registerEvent(String) + {static} + createEventInstance(String) + } +} + +package "Core Process" { + abstract RECTANGLE VSAbstractProcess { + # processNum: int + # localTime: long + # globalTime: long + # lamportTime: long + # vectorTime: VSVectorTime + + increaseTime() + + increaseLamportTime() + + increaseVectorTime() + + sendMessage(VSMessage) + } + + RECTANGLE VSInternalProcess { + - clockVariance: float + - clockOffset: double + - vectorClockMonitor: VSVectorClockMonitor + - crashed: boolean + + syncTime(long) + + crash() + + recover() + + highlightOn() + } + + RECTANGLE VSMessage { + - senderNum: int + - receiverNum: int + - protocolClassname: String + - lamportTime: VSLamportTime + - vectorTime: VSVectorTime + + getName(): String + + isServerMessage(): boolean + } +} + +package "Protocol Framework" { + abstract RECTANGLE VSAbstractProtocol { + - isServer: boolean + - isClient: boolean + - hasOnServerStart: boolean + + {abstract} onServerInit() + + {abstract} onClientInit() + + {abstract} onServerRecv(VSMessage) + + {abstract} onClientRecv(VSMessage) + + sendMessage(VSMessage) + + scheduleAt(long) + } + + RECTANGLE VSPingPongProtocol { + + onServerInit() + + onServerRecv(VSMessage) + + onClientInit() + + onClientRecv(VSMessage) + } + + RECTANGLE VSTwoPhaseCommitProtocol { + - phase: Phase + - votes: Map + + onServerInit() + + onServerRecv(VSMessage) + + onClientInit() + + onClientRecv(VSMessage) + } +} + +package "Time Management" { + interface VSTime { + + getGlobalTime(): long + + toString(): String + } + + RECTANGLE VSLamportTime { + - lamportTime: long + - globalTime: long + + increase() + + update(VSLamportTime) + } + + RECTANGLE VSVectorTime { + - vector: long[] + - globalTime: long + + increase(int) + + update(VSVectorTime) + + getCopy(): VSVectorTime + } +} + +' Relationships +VSSimulatorFrame --> VSSimulator +VSSimulator --> VSSimulatorVisualization +VSSimulator --> VSTaskManager +VSSimulatorVisualization --> VSInternalProcess +VSTaskManager --> VSTask +VSTask --> VSAbstractEvent +VSInternalProcess --|> VSAbstractProcess +VSAbstractProtocol --|> VSAbstractEvent +VSPingPongProtocol --|> VSAbstractProtocol +VSTwoPhaseCommitProtocol --|> VSAbstractProtocol +VSLamportTime ..|> VSTime +VSVectorTime ..|> VSTime +VSInternalProcess --> VSMessage +VSAbstractProtocol --> VSMessage + +@enduml + +@startuml Event Processing Sequence + +participant "VSSimulatorVisualization" as Viz +participant "VSTaskManager" as TM +participant "VSTask" as Task +participant "VSAbstractEvent" as Event +participant "VSInternalProcess" as Process + +activate Viz + +loop Simulation Loop + Viz -> Viz: Thread.sleep(timestep) + Viz -> Process: syncTime(globalTime) + activate Process + Process -> Process: Update local time with drift + deactivate Process + + Viz -> TM: runTasks(globalTime) + activate TM + + loop For each ready task + TM -> Task: time <= currentTime? + activate Task + + alt Task is ready + Task -> Event: onStart() + activate Event + + alt Event increases timestamps + Event -> Process: increaseLamportTime() + Event -> Process: increaseVectorTime() + end + + Event -> Event: Execute event logic + Event -> TM: May schedule new tasks + + deactivate Event + end + + deactivate Task + end + + deactivate TM +end + +deactivate Viz + +@enduml + +@startuml Protocol Message Flow + +participant "Client Process" as Client +participant "Client Protocol" as CP +participant "Network Simulation" as Net +participant "Server Protocol" as SP +participant "Server Process" as Server + +activate Client +Client -> CP: Protocol action triggered +activate CP + +CP -> CP: onClientStart() +CP -> Client: increaseLamportTime() +CP -> Client: increaseVectorTime() +CP -> Net: sendMessage(request) + +deactivate CP +deactivate Client + +activate Net +Net -> Net: Calculate network delay +Net -> Net: Schedule receive task +Net -> SP: onMessageRecvStart(request) +deactivate Net + +activate SP +activate Server + +SP -> SP: isRelevantMessage()? +SP -> SP: onServerRecv(request) +SP -> Server: Process request +SP -> Server: increaseLamportTime() +SP -> Server: increaseVectorTime() +SP -> Net: sendMessage(response) + +deactivate SP +deactivate Server + +activate Net +Net -> Net: Calculate network delay +Net -> Net: Schedule receive task +Net -> CP: onMessageRecvStart(response) +deactivate Net + +activate CP +activate Client + +CP -> CP: onClientRecv(response) +CP -> Client: Update timestamps from message +CP -> Client: Process response + +deactivate CP +deactivate Client + +@enduml + +@startuml Timestamp Triggered Events + +class VSTimestampTriggeredEvent { + # timestampType: TimestampType + # operator: ComparisonOperator + # hasTriggered: boolean + # targetLamportTime: long + # targetVectorTime: VSVectorTime + + checkCondition(VSInternalProcess): boolean + + {abstract} onTimestampReached() +} + +class VSLamportTimestampEvent { + - actionDescription: String + - customAction: Runnable + + onTimestampReached() +} + +class VSVectorTimestampEvent { + - processIndex: int + - actionDescription: String + + onTimestampReached() +} + +class VSTimestampMonitorEvent { + - lamportEvents: List + - vectorEvents: List + + addLamportEvent(event) + + addVectorEvent(event) + + onStart() +} + +class VSVectorClockMonitor { + - process: VSInternalProcess + - vectorEvents: List + + registerVectorEvent(event) + + checkVectorEvents() +} + +VSTimestampTriggeredEvent <|-- VSLamportTimestampEvent +VSTimestampTriggeredEvent <|-- VSVectorTimestampEvent +VSAbstractEvent <|-- VSTimestampTriggeredEvent +VSAbstractEvent <|-- VSTimestampMonitorEvent +VSInternalProcess --> VSVectorClockMonitor +VSVectorClockMonitor --> VSVectorTimestampEvent + +note top of VSTimestampTriggeredEvent + Triggers when timestamp conditions are met: + - EQUAL: timestamp == target + - GREATER_THAN: timestamp > target + - LESS_THAN: timestamp < target + - GREATER_EQUAL: timestamp >= target + - LESS_EQUAL: timestamp <= target +end note + +@enduml + +@startuml Task Scheduling and Execution + +participant "User Action" as User +participant "VSAbstractProtocol" as Protocol +participant "VSTaskManager" as TM +participant "VSPriorityQueue" as Queue +participant "VSTask" as Task + +activate User +User -> Protocol: scheduleAt(time) +activate Protocol + +Protocol -> Protocol: Create VSProtocolScheduleEvent +Protocol -> Task: new VSTask(time, process, event) +activate Task + +Protocol -> TM: addTask(task) +activate TM + +TM -> Queue: add(task) +activate Queue +Queue -> Queue: Sort by time +deactivate Queue + +deactivate TM +deactivate Task +deactivate Protocol +deactivate User + +... Time passes ... + +activate TM +TM -> TM: runTasks(currentTime) +TM -> Queue: peek() +activate Queue + +loop While task.time <= currentTime + Queue -> Task: remove() + Task -> Task: run() + activate Task + + Task -> Protocol: onServerSchedule() or onClientSchedule() + activate Protocol + Protocol -> Protocol: Execute scheduled logic + Protocol -> TM: May schedule more tasks + deactivate Protocol + + deactivate Task +end + +deactivate Queue +deactivate TM + +@enduml \ No newline at end of file -- cgit v1.2.3