MaruServer Architecture¶
The MaruServer is a metadata-only server that coordinates CXL memory allocation and KV metadata across clients. It never directly accesses KV data — all actual reads and writes happen through CXL shared memory by the clients themselves.
Responsibilities:
CXL memory allocation and deallocation (via the resource manager)
KV metadata management (key → region, offset, length)
Brokering KV location information between clients
1. Component Structure¶
flowchart TB
subgraph Server["MaruServer"]
RpcServer["RpcServer<br/>Message dispatch"]
MaruServer["MaruServer<br/>Atomic coordination<br/>Business logic"]
KVManager["KVManager<br/>Key → location<br/>Ref counting"]
AllocMgr["AllocationManager<br/>Region lifecycle<br/>Deferred freeing"]
ShmClient["MaruShmClient<br/>(alloc/free only)"]
RpcServer -->|"dispatch"| MaruServer
MaruServer -->|"KV metadata"| KVManager
MaruServer -->|"memory allocation"| AllocMgr
AllocMgr -->|"RPC"| ShmClient
end
Clients["MaruHandler #1..N"]
Clients <-->|"ZMQ RPC"| RpcServer
RM["Maru Resource Manager"]
ShmClient <-->|"alloc / free"| RM
style RpcServer fill:#e3f2fd,stroke:#1565c0
style MaruServer fill:#e8f5e9,stroke:#4a9
style KVManager fill:#fff3e0,stroke:#e65100
style AllocMgr fill:#fce4ec,stroke:#c62828
RpcServer accepts incoming ZeroMQ messages, dispatches to the appropriate MaruServer method, and returns the serialized response.
MaruServer is the central coordinator. It holds references to both KVManager and AllocationManager, and guarantees atomicity of cross-manager operations such as registering a KV entry and incrementing its region’s reference count.
KVManager maintains a key-to-location mapping, where each entry records the region ID, offset, and length of a stored KV pair. Duplicate key registrations are handled idempotently.
AllocationManager tracks all CXL memory allocations with records that include the owner instance, a KV reference count, and a connection flag. It communicates with the Resource Manager to perform physical allocation and deallocation.
2. Allocation Management¶
Each allocation is tracked with an AllocationInfo that records the owning client, the number of KV entries referencing the region, and whether the owner is still connected.
The allocation lifecycle uses deferred freeing: a region is only physically freed when both the owner has disconnected and no KV entries reference it. This prevents premature deallocation while readers still depend on the data.
stateDiagram-v2
[*] --> Active: allocate(instance_id, size)
state Active {
[*] --> Connected
Connected: owner_connected=True
Connected: kv_ref_count >= 0
}
Active --> Deferred: release() / disconnect_client()
state Deferred {
[*] --> Waiting
Waiting: owner_connected=False
Waiting: kv_ref_count > 0
}
Active --> Freed: release() + kv_ref_count==0
Deferred --> Freed: decrement_kv_ref() → kv_ref_count==0
state Freed {
[*] --> Done
Done: Physical memory returned
Done: Allocation record removed
}
Freed --> [*]
When a client calls return_alloc or disconnects, the allocation’s owner_connected flag is set to false. If the KV reference count is already zero, the region is freed immediately. Otherwise, it enters the deferred state and is freed later when the last KV entry referencing it is deleted.
3. KV Registry¶
KVManager stores a mapping from string keys to location records containing the region ID, offset within the region, and data length.
When a new key is registered, an entry is created and the allocation’s KV reference count is incremented. If the key already exists, the registration is treated as idempotent — no new entry is created.
When a key is deleted, the entry is removed and the allocation’s KV reference count is decremented. This may trigger deferred freeing if the region’s owner has already disconnected.
4. Cross-Manager Coordination¶
MaruServer ensures atomicity between KVManager and AllocationManager by executing paired operations as a single atomic unit.
For register_kv, the server registers the key and increments the region’s KV reference count atomically. Without this, a concurrent return_alloc could free the region between registration and reference count increment, creating a dangling KV entry.
For delete_kv, the server deletes the key and decrements the reference count atomically. If this brings the count to zero and the owner has disconnected, the allocation is freed immediately.
For lookup_kv, the server reads the KV entry and retrieves the corresponding handle atomically, ensuring the allocation cannot be freed between the two reads.
5. RPC Interface¶
The server exposes the following message types:
MessageType |
Operation |
|---|---|
|
Allocate a new CXL region for a client |
|
Release ownership of a region |
|
List all active allocations |
|
Register a KV entry at a given location |
|
Look up a KV entry’s location and handle |
|
Check whether a key exists |
|
Delete a KV entry |
|
Batch register multiple KV entries |
|
Batch look up multiple keys |
|
Batch check existence of multiple keys |
|
Retrieve server statistics |
|
Connection health check |
|
Reserved — initial client-server handshake |
|
Reserved — graceful server shutdown |
Batch operations allow clients to reduce RPC round-trips when operating on multiple keys.