Two-Phase Locking (2PL) for isolation + Two-Phase Commit (2PC) for atomicity. These solve different problems: 2PL controls concurrent access during a transaction, 2PC ensures all-or-nothing commit across servers.
accounts: map[string]Account
Account:
committedBalance int
lockState:
mode: UNLOCKED | READ | WRITE
holders: []TransactionID // for read locks (multiple allowed)
holder: TransactionID // for write lock (exclusive)
waitQueue: []WaitEntry // blocked transactions + their requested mode
tentativeWrites: map[TransactionID]map[AccountName]int
Tentative writes are invisible to other transactions. A transaction reads its own write buffer first; if no entry, falls back to committedBalance.
Transaction:
id: TransactionID
timestamp: int64 // assigned at BEGIN, used for wound-wait
participants: []ServerID // servers contacted so far (grows dynamically)
clientConn: net.Conn
- Read lock (BALANCE): shared — multiple transactions can hold simultaneously
- Write lock (DEPOSIT/WITHDRAW): exclusive — one holder at a time
- Locks are held until the transaction commits or aborts (strict 2PL)
- This prevents dirty reads: T2 cannot read uncommitted writes from T1
- Check account's lock state
- If compatible (e.g., read + read), grant immediately
- If incompatible, apply wound-wait (see below)
Each transaction receives a timestamp at BEGIN. Lower timestamp = older.
| Scenario | Action |
|---|---|
| Older T1 wants lock held by younger T2 | T1 wounds T2 (T2 is aborted) |
| Younger T2 wants lock held by older T1 | T2 waits |
This ensures waiting only goes in one direction (younger→older), making cycles impossible.
No timeouts are used (per spec requirement).
- The server holding the lock sends
ABORTEDback to the wounded transaction's coordinator - The wounded transaction's coordinator sends
ABORTto all servers in its participant list - Each server clears tentative writes and releases all locks held by that transaction
The client connects to a randomly selected server as coordinator. The client only ever talks to the coordinator.
The coordinator:
- Routes each command to the correct branch server (by account prefix)
- Maintains the participant list (set of servers contacted, grows per command)
- Handles
COMMITandABORTby running 2PC or broadcasting abort - For accounts on its own branch: calls local function directly (no network hop)
Coordinator sends PREPARE to all participants.
Each participant:
- Checks that all accounts written during the transaction have non-negative balances
- Votes
YESorNO
If any participant votes NO, coordinator sends ABORT to all and replies ABORTED to client.
If all votes are YES:
- Coordinator sends
COMMITto all participants - Each participant applies tentative writes to committed balances, releases all locks
- Coordinator replies
COMMIT OKto client - Each server prints balances of all non-zero accounts after committing
If any vote is NO:
- Coordinator sends
ABORTto all participants - Each participant clears tentative writes, releases all locks
- Coordinator replies
ABORTEDto client
Triggered by: user ABORT command, NOT FOUND on BALANCE/WITHDRAW, wound-wait, or negative balance at commit.
Steps:
- Coordinator sends
ABORTto all servers in participant list - Each server: delete tentative write buffer for transaction, release all locks
- Coordinator replies
ABORTEDto client
Coordinator ↔ participant communication over TCP. Each message is a line of text (newline-delimited) for simplicity.
Request format (coordinator → participant):
<txn_id> <command> [args...]
e.g.: tx42 DEPOSIT foo 10
tx42 BALANCE foo
tx42 PREPARE
tx42 COMMIT
tx42 ABORT
Response format (participant → coordinator):
OK [value] — success, optional value for BALANCE
ABORTED — transaction aborted (wound, not found, etc.)
YES / NO — prepare vote
- Server data structures (account store, lock table, write buffers)
- Lock acquisition/release + wound-wait logic
- Single-server transactions (coordinator = participant, no forwarding)
- Cross-server forwarding (coordinator routes to remote participants)
- 2PC at commit
- Client (parse stdin, connect to random server, print responses)