DSMS Deployment with 3 Computers

This guide shows how to run our actively replicated DSMS (with Front End, Sequencer, Replicas, and Replica Managers) using only three physical machines on a local network. We will also demonstrate how to test crash failures.


1. System Overview

We need:

Because we have only 3 physical machines, one of them must host the FE + Sequencer alongside one Replica (and its RM). The other two machines each host a Replica and its RM. That gives us 3 replicas total and a single FE/Sequencer instance. Below is how you can distribute them:

  1. Machine 1:
  2. Machine 2:
  3. Machine 3:
Deployment Diagram
flowchart LR M1(Machine 1) --- M2(Machine 2) M1 --- M3(Machine 3) subgraph M1 [Machine 1] FE(Front End):::fe SQ(Sequencer):::seq RA(Replica A):::replica RMA(RM A):::rm end subgraph M2 [Machine 2] RB(Replica B):::replica RMB(RM B):::rm end subgraph M3 [Machine 3] RC(Replica C):::replica RMC(RM C):::rm end classDef fe fill:#ADE7FF,stroke:#333,stroke-width:1px classDef seq fill:#FFD585,stroke:#333,stroke-width:1px classDef replica fill:#C7FFC7,stroke:#333,stroke-width:1px classDef rm fill:#FFC7C7,stroke:#333,stroke-width:1px

Each block (Replica + RM) can be run as separate processes or combined logic, but they should communicate on the same machine (e.g., via localhost ports).

Machine 1 hosts:

Machine 1 Deployment
flowchart TB subgraph Machine1 [Machine 1] direction TB FE(Front End):::fe SQ(Sequencer):::seq subgraph DSMS_Processes direction TB TOK1(TOK Instance - M1):::replica RMTOK1(RM TOK - M1):::rm LON1(LON Instance - M1):::replica RMLON1(RM LON - M1):::rm NYK1(NYK Instance - M1):::replica RMNYK1(RM NYK - M1):::rm end end %% Arrows for internal communication FE -- requests --> SQ SQ -- seq. msgs --> TOK1 SQ -- seq. msgs --> LON1 SQ -- seq. msgs --> NYK1 %% Replicas -> FE TOK1 -- results --> FE LON1 -- results --> FE NYK1 -- results --> FE %% RM internal signals FE -- crash/fault info --> RMTOK1 FE -- crash/fault info --> RMLON1 FE -- crash/fault info --> RMNYK1 %% Relationship between RM and its instance RMTOK1 -- manages --> TOK1 RMLON1 -- manages --> LON1 RMNYK1 -- manages --> NYK1 classDef fe fill:#ADE7FF,stroke:#333,stroke-width:1px classDef seq fill:#FFD585,stroke:#333,stroke-width:1px classDef replica fill:#C7FFC7,stroke:#333,stroke-width:1px classDef rm fill:#FFC7C7,stroke:#333,stroke-width:1px

Key Points:

Machines 2 and 3 do not host the FE or Sequencer. They only run:

That way, each city code has a replica on Machine 1, 2, and 3. The Sequencer on Machine 1 sends requests to all nine processes (3 per machine).

Machine 2 or 3 Deployment
flowchart TB subgraph MachineX [Machine 2 or Machine 3] direction TB subgraph DSMS_Processes direction TB TOKx(TOK Instance - M2/M3):::replica RMTOKx(RM TOK - M2/M3):::rm LONx(LON Instance - M2/M3):::replica RMLONx(RM LON - M2/M3):::rm NYKx(NYK Instance - M2/M3):::replica RMNYKx(RM NYK - M2/M3):::rm end end %% Arrows from Sequencer (on Machine 1) SQ1(Sequencer - M1):::seq SQ1 -- seq. msgs --> TOKx SQ1 -- seq. msgs --> LONx SQ1 -- seq. msgs --> NYKx %% Replicas -> FE on M1 FE1(Front End - M1):::fe TOKx -- results --> FE1 LONx -- results --> FE1 NYKx -- results --> FE1 %% Crash/fault notifications FE1 -- crash/fault info --> RMTOKx FE1 -- crash/fault info --> RMLONx FE1 -- crash/fault info --> RMNYKx %% RM manages the local instance RMTOKx -- manages --> TOKx RMLONx -- manages --> LONx RMNYKx -- manages --> NYKx classDef fe fill:#ADE7FF,stroke:#333,stroke-width:1px classDef seq fill:#FFD585,stroke:#333,stroke-width:1px classDef replica fill:#C7FFC7,stroke:#333,stroke-width:1px classDef rm fill:#FFC7C7,stroke:#333,stroke-width:1px

Key Points:


Summary

In this final deployment:


2. Running the System and Demonstrating Functionalities

Below is a typical startup order for the system:

  1. Machine 1:
    1. Start the Replica Manager A and the corresponding Replica A.
    2. Start the Sequencer (listening on some port, e.g., 7000).
    3. Start the Front End (listening on another port, e.g., 7100) that clients connect to.
  2. Machine 2:
  3. Machine 3:

Once the system is up, you can point any Admin or Buyer Client to connect to the Front End (on Machine 1). The FE will pass requests to the Sequencer, which multicasts them to all three Replicas in total order.

Runtime Communication Flow
flowchart TB Client --> FE[Front End @ Machine 1] FE --> SQ[Sequencer @ Machine 1] SQ --> RA[Replica A @ Machine 1] SQ --> RB[Replica B @ Machine 2] SQ --> RC[Replica C @ Machine 3] RA --> FE RB --> FE RC --> FE FE -.->|Notify if suspect crash/fault| RM[RM A,B,C]

3. Example Operations to Demonstrate

Your DSMS includes both Admin operations and Buyer operations. Below are the main ones you’ll want to test:

  1. Admin Ops:
  2. Buyer Ops:

When an admin or buyer client runs these operations, they’ll connect to the FE on Machine 1. The FE forwards the request to the Sequencer, which distributes them to all replicas. Each replica returns its local “agreed-upon” result. The FE compares results, detects mismatches or timeouts, and responds to the client.


4. How to Test Crash Failures

This document lists comprehensive test cases to verify your Distributed Share Market System (DSMS) functionality, covering both **normal operations** and **crash scenarios** (process crash). The DSMS includes:

We also show **visual diagrams** depicting where a crash might occur and how the system recovers.


1. Normal Operation Test Cases

Below is a listing of core admin and buyer operations, covering typical edge cases. These assume **all replicas are running** and no process crashes occur.

Test Case ID Operation Scenario Expected Result
T-Admin-01 addShare Admin adds a new share with valid inputs Share is successfully created with correct capacity; success message returned.
T-Admin-02 addShare Admin attempts to add an existing shareID Operation fails with a message “Share already exists.” No new share is created.
T-Admin-03 removeShare Admin removes an existing share Share is removed from the server. Future list or purchase references should fail for that share.
T-Admin-04 removeShare Admin attempts to remove a non-existent shareID Operation returns “Share not found” or similar message.
T-Admin-05 listShareAvailability Admin requests availability for a valid shareType (EQUITY, BONUS, or DIVIDEND) All known shares of that type are returned with capacities from each server city. No error.
T-Buyer-01 purchaseShare Buyer purchases a share with sufficient capacity available Buyer's purchase is recorded, capacity is reduced accordingly. Successful response.
T-Buyer-02 purchaseShare Buyer tries to purchase more than capacity, or shareID doesn’t exist Purchase fails or partial is allocated (depending on logic); an error or partial success message is returned.
T-Buyer-03 getShares Buyer requests their existing holdings All owned shares and quantities from all servers are returned.
T-Buyer-04 sellShare Buyer tries to sell shares they own, less than or equal to the purchased quantity Operation succeeds, capacity goes up on that share. Buyer’s holdings are decreased accordingly.
T-Buyer-05 sellShare Buyer tries to sell a share they do not own Operation fails with error message (e.g., “You do not own this share.”).
T-Buyer-06 swapShares Buyer attempts to swap oldShare for newShare with enough capacity in newShare Old share is removed from the buyer's holdings, new share is allocated. Successful swap message returned.
T-Buyer-07 swapShares Buyer attempts to swap but newShare lacks capacity Swap fails; old share is returned to the buyer’s holdings. Clear error message.

**Note**: For cross-city purchases (if you have that limit of 3 shares across different cities), add an additional test verifying the limit is enforced.


2. Crash Failure Test Cases

In the following scenarios, at least one **replica** is forcibly terminated during or right after a request is broadcast by the Sequencer. We assume your DSMS is in crash-failure tolerance mode (i.e., not the software-fault mode). The system should continue to operate with the remaining replicas.

Test Case ID Crash Point Operation Expected System Behavior
Crash-01 After Sequencer sends an “addShare” request to all replicas,
Replica B is killed before responding
addShare FE receives 2 responses (Replica A and Replica C).
FE times out waiting for B, suspects crash.
FE returns success if A and C results match.
RM(B) restarts or replaces B.
System remains consistent with the new share added.
Crash-02 During “removeShare” broadcast, Replica A’s process is terminated in mid-execution removeShare FE gets responses from B and C.
A never responds => crash suspicion => RMs confirm.
The share is removed on B and C.
Replica A is later restarted or replaced.
Once A is back, it can catch up on missed requests.
Crash-03 Replica C is killed after sending an incorrect partial result for “purchaseShare” (if that partial result arrives, it might be irrelevant in crash mode, but let's say we never trust incomplete data) purchaseShare FE compares responses from A, B, C. If C is killed mid-flight, FE might get no final ack from C.
A and B match => FE proceeds with that result.
FE flags C as crashed. RM(C) restarts C.
The final system state is consistent per A and B.
Crash-04 Replica B is killed before any response for “swapShares” swapShares FE collects responses from A and C. If they match, the swap is successful.
B is restarted later by RM(B).
The buyer’s holdings reflect the swapped share on A and C. B syncs after restart.
Crash-05 Replica A is killed mid “sellShare” operation. FE times out on A’s response sellShare FE obtains matching results from B, C, concludes the sale.
A is flagged for crash; RM(A) restarts it.
Overall capacity is incremented as B and C performed the sale.

In each crash case, once the Replica Manager detects or is notified of the crash, it spins up a new instance (or restarts) so the system returns to having 3 replicas. The FE can respond to requests as soon as it has at least 2 matching responses from the healthy replicas.


3. Visual Diagrams of Crash and Recovery

Below are two sample sequence diagrams illustrating crash scenarios and the subsequent recovery. The first focuses on a crash during an admin operation (e.g., addShare), the second focuses on a buyer operation (e.g., purchaseShare).

Diagram 1: Crash During addShare Operation
sequenceDiagram autonumber participant Admin as Admin Client participant FE as Front End participant S as Sequencer participant R1 as Replica A participant R2 as Replica B (Crashes) participant R3 as Replica C participant RM as Replica Managers Admin->>FE: addShare(shareID, shareType, capacity) FE->>S: "Request from Admin" S->>R1: (seqNo, addShare) S->>R2: (seqNo, addShare) S->>R3: (seqNo, addShare) R1-->>FE: "Success: added share" R3-->>FE: "Success: added share" note over R2: R2 Crashes before responding FE->>FE: Wait for R2 => times out FE->>RM: "Replica B suspected crashed" RM->>R2: Attempt ping => no response RM->>RM: coordinate "Yes, B is down." RM->>R2: "Restart or new instance" FE->>Admin: "Share added successfully"
(2 matching results from A & C) note over R2: Once restarted, R2 can sync state from others

Diagram 2: Crash During purchaseShare Operation
sequenceDiagram autonumber participant Buyer as Buyer Client participant FE as Front End participant S as Sequencer participant R1 as Replica A participant R2 as Replica B participant R3 as Replica C (Crashes) participant RM as Replica Managers Buyer->>FE: purchaseShare(shareID, 10) FE->>S: "Buyer request" S->>R1: (seqNo, purchaseShare) S->>R2: (seqNo, purchaseShare) S->>R3: (seqNo, purchaseShare) R1-->>FE: result "Purchased 10" R2-->>FE: result "Purchased 10" note over R3: R3 crashes during processing FE->>FE: sees 2 matching successful results FE->>Buyer: "Purchase success (10 shares)" FE->>RM: "Replica C is not responding" RM->>R3: ping => fails RM->>R3: restart or spawn new replica note over R3: after restart, sync w/others

4. Additional Observations


Conclusion

The test cases above (normal operations + crash scenarios) will help you verify correctness, robustness, and recovery in your actively replicated DSMS:

  1. Normal Tests: Check that basic admin and buyer operations behave correctly under no failures.
  2. Crash Tests: Forcibly terminate one replica during or just after receiving a request. Confirm the FE obtains matching results from the remaining replicas, and the Replica Manager replaces or restarts the crashed replica.

Together, these tests ensure the DSMS achieves the **high availability** goal under a single crash failure.


5. Minimal Pseudo-code Adjustments for 3 Computers

You can keep the same pseudo-code from the earlier design. The only difference is how you assign host IP addresses and ports to each component. For example:

Machine1_IP = "192.168.0.10"
Machine2_IP = "192.168.0.11"
Machine3_IP = "192.168.0.12"

// On Machine 1
startReplica("A", "192.168.0.10", port=9000)
startRM("A", "192.168.0.10", port=9100)
startSequencer("192.168.0.10", port=7000)
startFrontEnd("192.168.0.10", port=7100, sequencerIP="192.168.0.10", seqPort=7000)

// On Machine 2
startReplica("B", "192.168.0.11", port=9000)
startRM("B", "192.168.0.11", port=9100)

// On Machine 3
startReplica("C", "192.168.0.12", port=9000)
startRM("C", "192.168.0.12", port=9100)

Each replica knows the IP address and ports of the other replicas and the Sequencer. The Front End is the only one the client ever contacts (via 192.168.0.10:7100 in this example).


6. Verifying All Functionalities

After deployment, you can verify:

Confirm each replica’s data (e.g., capacities and buyer records) remain consistent. If you forcibly stop any single replica process (on Machine 2 or Machine 3), the FE should continue returning correct results (via the other two healthy replicas).


Conclusion

By following this setup, you can: