</> MAANG.io

Expert

Design landmark systems in depth, from Dynamo, GFS, Bigtable and Kafka to payments and ads pipelines.

0 of 232 solved 0%

Section 4: A File System That Happens to Lock - API Design (with pushback)

Executive Summary: Clients never see an RPC wire. They link a library that exposes a hierarchical namespace (/ls/<cell>/...) of small nodes: Open returns a handle, whole-file reads and writes (≤ 256 KB) carry an optional content-generation compare-and-set, any node can be locked exclusive or shared, and events report changes. The session and its KeepAlive stay hidden inside the library, where one 12 s lease covers every handle a process holds. Sequencers turn "I hold the lock" into a token that a downstream server can check. Eight error codes make failure visible, and six pushbacks each defend a property the state machine in Section 5 must keep.

The interviewer leans back. "Section 3 says the load is heartbeats. Fine. Now tell me what orders-db actually calls, and I'll ask why for each piece."

You: "The interface looks like a tiny file system, because that's what the four client jobs from Section 1 need: a name, a few bytes, a lock, and a notification. A lock is just a property of a node."

The Client Library Contract

Open(path, intent{read, write, lock, change-acl}, event_mask, lock_delay,
     create{permanent | ephemeral, initial_contents, initial_acl_names}) -> handle
Close(handle)                      Poison(handle)
GetContentsAndStat(handle)  -> (bytes, stat{instance, content_gen, lock_gen, acl_gen, checksum})
GetStat(handle)             -> stat
ReadDir(handle)             -> [child names + stat]
SetContents(handle, bytes, if_content_generation?)   # CAS when the generation is given
SetACL(handle, acl_names)          Delete(handle)
Acquire(handle, mode)              TryAcquire(handle, mode)     Release(handle)
GetSequencer(handle) -> sequencer  SetSequencer(handle, seq)    CheckSequencer(seq) -> ok

Open is the only call that takes a path. Everything after it takes a handle, so the master checks the ACL once at Open and stores the intent on the handle. event_mask subscribes the handle to contents-modified, child-added/removed, lock-acquired, master-failover and handle-invalid events. lock_delay ranges from 0 to 60 s with a default of 30 s, and orders-db passes 0 because every tablet server checks sequencers (Section 9). Ephemeral nodes are deleted when the owning session dies, which is all that group membership needs. Poison makes any outstanding and future calls on the handle fail without closing it, so one thread can cancel another thread's blocked Acquire. Calls are gRPC underneath, but the app never builds a session: the library opens one per process, keeps exactly one KeepAlive in flight (8,300/s across the cell), and turns jeopardy and expiry into events (Section 8).

Quick check before moving on:


Sign in to continue reading

The rest of this lesson is available with a free account. Signing in with Google or Microsoft is free.

Sign in to read the full lesson

Sign in to MAANG.io

Use your Google or Microsoft account — no password to remember.

Continue with Google Continue with Microsoft

Please accept the terms above to continue.