Mooncake/docs/source/design/tent/cpp-api.md

21 KiB

TENT C++ API Reference

Overview

This page summarizes the C++ APIs in mooncake-transfer-engine/tent/include/tent/transfer_engine.h. It follows the same structure as the Transfer Engine API documentation.

For conceptual background, see TENT Overview.

Prerequisites and API modes

  • Build with -DUSE_TENT=ON to enable TENT.
  • TENT provides two API surfaces:
    • TENT-native API (documented below).
    • TE-compatible API via the compatibility shim (set MC_USE_TENT=1). For TE-compatible API, see TE C++ API Reference

Core APIs vs Advanced APIs

  • Core APIs form the minimal path to move data: create the engine, register memory, open segments, submit transfers, and query status.
  • Advanced APIs are optional; they help with segment export/import, notifications, and engine introspection.

Key Differences from Transfer Engine

TENT redesigns the API surface based on different design goals. The following table summarizes the key differences and the rationale behind them.

Aspect Transfer Engine (TE) TENT Rationale
Initialization Two-step: constructor + init(metadata_conn_string, server_name, ...) Single-step: constructor with Config object or config file path Simplifies initialization; centralizes configuration in a single place
Transport Management Manual: installTransport(), uninstallTransport(), getTransport() Removed from public API TENT performs dynamic transport selection at runtime; applications should not manage transports directly
Memory Allocation Not provided; users allocate memory externally allocateLocalMemory() / freeLocalMemory() Provides integrated memory management with automatic registration
Memory Registration registerLocalMemory(addr, len, location, remote_accessible, update_metadata) registerLocalMemory(addr, size, Permission) or MemoryOptions Cleaner semantics; Permission replaces boolean flags; metadata updates are internal
Segment Discovery Via metadata service; manual cache sync with syncSegmentCache() Internal control plane (metadata type = p2p or central); no manual sync Simplifies metadata management; discovery handled inside runtime
Error Handling Mixed: some APIs return int, others return Status Consistent: all APIs return Status Uniform error handling across the API
Topology/Introspection Exposed: getLocalTopology(), getMetadata(), checkOverlap(), etc. Internalized; not exposed TENT handles topology and path selection internally; reduces API complexity

Design Philosophy

  1. Declarative over Imperative: Applications describe what data to move, not how to move it. Transport selection, path optimization, and failure handling are delegated to the TENT runtime.

  2. Single Initialization: Instead of a two-phase constructor + init() pattern, TENT uses configuration objects that fully describe the engine state at construction time.

  3. Internal Metadata Management: TENT does not expose metadata internals (TransferMetadata, Topology). Segment discovery is handled by the control plane (P2P or central), and the cache is managed automatically.

  4. Consistent Error Model: All TENT APIs return Status objects, eliminating the mixed int / Status return types in TE.

API Mapping: TE to TENT

For users migrating from Transfer Engine, the following table shows how TE APIs map to TENT APIs. TENT provides a backward-compatible shim (MC_USE_TENT=1) that allows existing TE code to run on the TENT runtime.

Transfer Engine API TENT API Notes
Initialization
TransferEngine(auto_discover) TransferEngine() TENT ignores auto_discover; discovery is always automatic
init(conn_string, server_name, ip, port) Constructor with Config Config sets metadata_type, metadata_servers, local_segment_name
freeEngine() Destructor Resources released automatically on destruction
Transport
installTransport(proto, args) Not available Transport selection is internal to TENT
uninstallTransport(proto) Not available
getTransport(proto) Not available
Memory
registerLocalMemory(addr, len, location, remote_accessible, update_metadata) registerLocalMemory(addr, size, MemoryOptions) MemoryOptions.location replaces location; MemoryOptions.perm replaces remote_accessible
unregisterLocalMemory(addr, update_metadata) unregisterLocalMemory(addr) Metadata update is internal
registerLocalMemoryBatch(buffer_list, location) registerLocalMemory(addr_list, size_list, MemoryOptions) Batch API uses vectors instead of BufferEntry
unregisterLocalMemoryBatch(addr_list) unregisterLocalMemory(addr_list)
Not available allocateLocalMemory(addr, size, location) TENT-only: allocates and registers in one call
Not available freeLocalMemory(addr) TENT-only: frees allocated memory
Segment
openSegment(segment_name) → returns handle openSegment(handle, segment_name) → via output param Return style differs; Status indicates success/failure
closeSegment(handle) closeSegment(handle) Same semantics
removeLocalSegment(segment_name) Not available Segment lifecycle managed internally
CheckSegmentStatus(sid) Not available Status checking is internal
syncSegmentCache(segment_name) Not available Cache sync is automatic
Not available exportLocalSegment(shared_handle) Declared in TENT API but currently not implemented
Not available importRemoteSegment(handle, shared_handle) Declared in TENT API but currently not implemented
getSegmentInfo(handle, info) getSegmentInfo(handle, info) Same semantics
Batch & Transfer
allocateBatchID(batch_size) allocateBatch(batch_size) Renamed
freeBatchID(batch_id) freeBatch(batch_id) Renamed
submitTransfer(batch_id, entries) submitTransfer(batch_id, request_list) TransferRequestRequest
submitTransferWithNotify(batch_id, entries, notify_msg) submitTransfer(batch_id, request_list, notifi) Unified API with optional notification
getTransferStatus(batch_id, task_id, status) getTransferStatus(batch_id, task_id, status) Same
getBatchTransferStatus(batch_id, status) getTransferStatus(batch_id, status) Overloaded; single TransferStatus output = overall status
Not available getTransferStatus(batch_id, status_list) TENT-only: get all task statuses at once
Notification
sendNotifyByID(target_id, notify_msg) sendNotification(target_id, notifi) Renamed; uses Notification struct
sendNotifyByName(remote_agent, notify_msg) openSegment() + sendNotification() TENT requires explicit segment handle
getNotifies(notifies) receiveNotification(notifi_list) Renamed; uses Notification struct
Introspection
getLocalIpAndPort() getRpcServerAddress() + getRpcServerPort() Split into two methods
getRpcPort() getRpcServerPort() Same
getMetadata() Not available Metadata internals not exposed
getLocalTopology() Not available Topology internals not exposed
checkOverlap(addr, length) Not available
setAutoDiscover(auto_discover) Not available Always enabled (ignored under MC_USE_TENT)
setWhitelistFilters(filters) Not available Configure via Config
numContexts() Not available
Not available available() TENT-only: check if engine initialized successfully
Not available getSegmentName() TENT-only: get local segment name

Using the Backward-Compatible Shim

Existing Transfer Engine code can run on TENT by setting the environment variable:

export MC_USE_TENT=1

When this variable is set, the mooncake::TransferEngine class internally delegates to mooncake::tent::TransferEngine. Most TE APIs are translated automatically. APIs that have no TENT equivalent (e.g., installTransport, getMetadata) become no-ops or return placeholder values.

Core APIs

Core Usage Path (C++)

Most integrations follow a short, repeatable path: create the engine, register local memory, open a target segment, submit a batch transfer, poll status, and finally free resources. A minimal example is shown below.

#include "tent/transfer_engine.h"

using mooncake::tent::TransferEngine;
using mooncake::tent::Request;
using mooncake::tent::TransferStatus;
using mooncake::tent::SegmentID;
using mooncake::tent::BatchID;

// Create engine (loads config from default path or environment)
TransferEngine engine;
if (!engine.available()) {
    // handle initialization failure
}

// Allocate and register local memory
void* local_addr = nullptr;
size_t length = 1024 * 1024;  // 1MB
engine.allocateLocalMemory(&local_addr, length, "cuda:0");

// Open remote segment
SegmentID remote_segment;
engine.openSegment(remote_segment, "remote_node");

// Prepare transfer request
Request req{};
req.opcode = Request::WRITE;
req.source = local_addr;
req.target_id = remote_segment;
req.target_offset = 0;
req.length = length;

// Allocate batch and submit transfer
BatchID batch = engine.allocateBatch(1);
engine.submitTransfer(batch, {req});

// Poll for completion
TransferStatus status;
do {
    engine.getTransferStatus(batch, status);
} while (status.s == mooncake::tent::PENDING);

// Cleanup
engine.freeBatch(batch);
engine.closeSegment(remote_segment);
engine.freeLocalMemory(local_addr);

Constructors

TransferEngine();
TransferEngine(const std::string config_path);
TransferEngine(std::shared_ptr<Config> config);

Constructs a TENT Transfer Engine instance.

  • Default constructor: Loads configuration from the default path or environment variables.
  • config_path: Path to a JSON configuration file.
  • config: A pre-constructed Config object for programmatic configuration.

The engine is ready to use after construction if available() returns true.

Types

Request

The core API provided by TENT is submitting a group of asynchronous Request tasks through the submitTransfer interface, and querying their status through the getTransferStatus interface.

struct Request {
    enum OpCode { READ, WRITE };
    OpCode opcode;
    void* source;
    SegmentID target_id;
    uint64_t target_offset;
    size_t length;
};
  • opcode: READ copies data from <target_id, target_offset> to source; WRITE copies data from source to <target_id, target_offset>.
  • source: Local buffer address, must be registered via registerLocalMemory or allocated via allocateLocalMemory.
  • target_id: Segment ID obtained from openSegment.
  • target_offset: Offset within the target segment.
  • length: Number of bytes to transfer.

TransferStatus

enum TransferStatusEnum {
    INITIAL,    // Not yet started
    PENDING,    // Transfer in progress
    INVALID,    // Invalid parameters
    CANCELED,   // Transfer canceled
    COMPLETED,  // Transfer completed successfully
    TIMEOUT,    // Transfer timed out
    FAILED      // Transfer failed
};

struct TransferStatus {
    TransferStatusEnum s;
    size_t transferred_bytes;
};
  • s: Current status of the transfer.
  • transferred_bytes: Number of bytes successfully transferred (lower bound).

Data Transfer

TransferEngine::allocateBatch

BatchID allocateBatch(size_t batch_size);

Allocates a BatchID that can hold up to batch_size transfer requests.

  • batch_size: Maximum number of requests that can be submitted under this batch.
  • Return value: A valid BatchID on success.

TransferEngine::submitTransfer

Status submitTransfer(BatchID batch_id,
                      const std::vector<Request>& request_list);

Submits transfer requests to the specified batch. Requests are executed asynchronously.

  • batch_id: The batch to submit requests to.
  • request_list: Vector of Request objects.
  • Return value: Status::OK() on success; otherwise a non-OK status.

TransferEngine::getTransferStatus

// Get status of a single task
Status getTransferStatus(BatchID batch_id, size_t task_id,
                         TransferStatus& status);

// Get status of all tasks in a batch
Status getTransferStatus(BatchID batch_id,
                         std::vector<TransferStatus>& status_list);

// Get overall batch status
Status getTransferStatus(BatchID batch_id, TransferStatus& overall_status);

Queries the status of transfer requests.

  • batch_id: The batch to query.
  • task_id: Index of the specific task (for single-task query).
  • status / status_list / overall_status: Output parameter(s) for status.
  • Return value: Status::OK() on success; otherwise a non-OK status.

TransferEngine::freeBatch

Status freeBatch(BatchID batch_id);

Releases a batch. All transfers in the batch must be completed before calling this.

  • batch_id: The batch to release.
  • Return value: Status::OK() on success; otherwise a non-OK status.

Memory Management

TransferEngine::allocateLocalMemory

Status allocateLocalMemory(void** addr, size_t size,
                           Location location = kWildcardLocation);

// Advanced version with MemoryOptions
Status allocateLocalMemory(void** addr, size_t size,
                           MemoryOptions& options);

Allocates memory that is automatically registered for transfers.

  • addr: Output pointer to the allocated memory.
  • size: Size in bytes to allocate.
  • location: Device location hint (e.g., "cuda:0", "cpu:0", or "*" for auto-detect).
  • options: Advanced options including location, permission, and transport type.
  • Return value: Status::OK() on success; otherwise a non-OK status.

TransferEngine::freeLocalMemory

Status freeLocalMemory(void* addr);

Frees memory previously allocated with allocateLocalMemory.

  • addr: Pointer to the memory to free.
  • Return value: Status::OK() on success; otherwise a non-OK status.

TransferEngine::registerLocalMemory

Status registerLocalMemory(void* addr, size_t size,
                           Permission permission = kGlobalReadWrite);

// Batch registration
Status registerLocalMemory(std::vector<void*> addr_list,
                           std::vector<size_t> size_list,
                           Permission permission = kGlobalReadWrite);

// Advanced version with MemoryOptions
Status registerLocalMemory(void* addr, size_t size, MemoryOptions& options);

Registers externally allocated memory for use in transfers.

  • addr: Starting address of the memory region.
  • size: Size in bytes.
  • permission: Access permission (kLocalReadWrite, kGlobalReadOnly, kGlobalReadWrite).
  • addr_list / size_list: For batch registration of multiple buffers.
  • options: Advanced options for fine-grained control.
  • Return value: Status::OK() on success; otherwise a non-OK status.

TransferEngine::unregisterLocalMemory

Status unregisterLocalMemory(void* addr, size_t size = 0);

// Batch unregistration
Status unregisterLocalMemory(std::vector<void*> addr_list,
                             std::vector<size_t> size_list = {});

Unregisters previously registered memory.

  • addr: Starting address of the memory region.
  • size: Size in bytes (optional, can be 0 if the engine tracks it).
  • Return value: Status::OK() on success; otherwise a non-OK status.

Segment Management

TransferEngine::openSegment

Status openSegment(SegmentID& handle, const std::string& segment_name);

Opens a segment by name and returns a handle for use in transfers.

  • handle: Output parameter for the segment ID.
  • segment_name: Name of the segment to open (typically the remote node name).
  • Return value: Status::OK() on success; otherwise a non-OK status.

TransferEngine::closeSegment

Status closeSegment(SegmentID handle);

Closes a previously opened segment.

  • handle: The segment ID to close.
  • Return value: Status::OK() on success; otherwise a non-OK status.

TransferEngine::getSegmentInfo

Status getSegmentInfo(SegmentID handle, SegmentInfo& info);

Retrieves information about a segment.

  • handle: The segment ID.
  • info: Output parameter containing segment details (type, buffers).
  • Return value: Status::OK() on success; otherwise a non-OK status.

Advanced APIs

These APIs are optional; use them for segment export/import, notifications, or engine introspection.

Segment Export and Import

Reserved for future use. These APIs are declared but currently return Status::NotImplemented.

TransferEngine::exportLocalSegment

Status exportLocalSegment(std::string& shared_handle);

Exports the local segment as a shareable handle string.

  • shared_handle: Output string that can be passed to remote nodes.
  • Return value: Currently returns Status::NotImplemented.
  • Typical use: Share segment information through an external channel (e.g., gRPC, Redis).

TransferEngine::importRemoteSegment

Status importRemoteSegment(SegmentID& handle,
                           const std::string& shared_handle);

Imports a remote segment from a shared handle string.

  • handle: Output segment ID.
  • shared_handle: The handle string obtained from exportLocalSegment on the remote side.
  • Return value: Currently returns Status::NotImplemented.

Notifications

TENT supports lightweight notifications to coordinate data movement between nodes.

TransferEngine::submitTransfer (with notification)

Status submitTransfer(BatchID batch_id,
                      const std::vector<Request>& request_list,
                      const Notification& notifi);

Submits transfers and sends a notification upon completion.

  • notifi: A {name, msg} payload delivered to the receiver when the transfer completes.
  • Typical use: Signal that transferred data is ready for consumption.

TransferEngine::sendNotification

Status sendNotification(SegmentID target_id, const Notification& notifi);

Sends a notification to a specific segment without data transfer.

  • target_id: The segment to notify.
  • notifi: The notification payload.
  • Return value: Status::OK() on success; otherwise a non-OK status.

TransferEngine::receiveNotification

Status receiveNotification(std::vector<Notification>& notifi_list);

Receives pending notifications from peers.

  • notifi_list: Output vector of received notifications.
  • Return value: Status::OK() on success; otherwise a non-OK status.
  • Typical use: Polling loop to trigger follow-up actions on received data.

Engine Introspection

TransferEngine::available

bool available() const;

Returns true if the engine was initialized successfully and is ready for use.

TransferEngine::getSegmentName

const std::string getSegmentName() const;

Returns the local segment name (node identifier).

TransferEngine::getRpcServerAddress

const std::string getRpcServerAddress() const;

Returns the RPC server address for this engine instance.

TransferEngine::getRpcServerPort

uint16_t getRpcServerPort() const;

Returns the RPC server port for this engine instance.

Type Reference

Permission

enum Permission {
    kLocalReadWrite,   // Only local access
    kGlobalReadOnly,   // Remote read access
    kGlobalReadWrite,  // Remote read/write access
};

Location

using Location = std::string;
const static std::string kWildcardLocation = "*";

Location strings identify device affinity: "cpu:0", "cuda:0", "cuda:1", etc. Use "*" for automatic detection.

TransportType

enum TransportType {
    RDMA = 0,
    MNNVL,
    SHM,
    NVLINK,
    GDS,
    IOURING,
    TCP,
    AscendDirect,
    UNSPEC
};

Transport types used internally by TENT. Applications typically do not need to specify these directly.

MemoryOptions

struct MemoryOptions {
    Location location = kWildcardLocation;
    Permission perm = kGlobalReadWrite;
    TransportType type = UNSPEC;
    std::string shm_path = "";
    size_t shm_offset = 0;
    bool internal = false;
};

Advanced options for memory allocation and registration.

SegmentInfo

struct SegmentInfo {
    enum Type { Memory, File };
    struct Buffer {
        uint64_t base, length;
        Location location;
    };
    Type type;
    std::vector<Buffer> buffers;
};

Information about a segment, including its type and registered buffers.

Notification

struct Notification {
    std::string name;
    std::string msg;
};

Lightweight notification payload for coordination between nodes.

Status

The Status class is used for error handling throughout the API. Key methods:

bool ok() const;           // Returns true if operation succeeded
std::string ToString() const;  // Human-readable error description

// Common status factory methods
static Status OK();
static Status InvalidArgument(std::string_view msg);
static Status InternalError(std::string_view msg);
// ... and more