Docs · Context Transfer Engine
Context Transfer Engine API reference.
Signatures below are taken from context-transfer-engine/core/include/clio_cte/core/core_client.h, the Python bindings in context-transfer-engine/wrapper/python/core_bindings.cc, and the parser in context-transfer-engine/core/src/core_config.cc. Types are abbreviated: Future is clio::run::Future, PoolQuery is clio::run::PoolQuery, u32 and u64 are clio::run::u32 and clio::run::u64.
- Namespace
- clio::cte::core
- Header
- clio_cte/core/core_client.h
- Python
- clio_cte_core_ext
- Module name
- clio_cte_core
Initialization
bool clio::run::CLIO_INIT(clio::run::RuntimeMode mode, bool default_with_runtime = false, bool is_restart = false);
bool clio::cte::core::CLIO_CTE_CLIENT_INIT(const std::string &config_path = "",
const PoolQuery &pool_query = PoolQuery::Dynamic());
#define CLIO_CTE_CLIENT /* clio::cte::core::Client * bound by CLIO_CTE_CLIENT_INIT */RuntimeModeiskClient,kServerorkRuntime.CLIO_CTE_CLIENT_INITbinds the shared client to pool 512.0 (kCtePoolId), or to the pool named by theCLIO_CTE_POOLenvironment variable asmajor.minor. A malformed value is logged and ignored.Client()uses the default pool;Client(const PoolId &)addresses any pool that speaks the core interface.
C++: Tag
A thin wrapper over the shared client for one tag. The blocking put from a private buffer defaults the score to 1.0. The asynchronous and shared-memory forms default to -1.0, which keeps the blob's existing score.
class Tag {
public:
explicit Tag(const std::string &tag_name); // GetOrCreateTag
explicit Tag(const TagId &tag_id); // wrap an existing id, no RPC
void PutBlob(const std::string &blob_name, const char *data, size_t data_size,
size_t off = 0, float score = 1.0f, const Context &context = Context());
void PutBlob(const std::string &blob_name, const ctp::ipc::ShmPtr<> &data, size_t data_size,
size_t off = 0, float score = -1.0f, const Context &context = Context());
Future<PutBlobTask> AsyncPutBlob(const std::string &blob_name, const char *data, size_t data_size,
size_t off = 0, float score = -1.0f, const Context &context = Context());
Future<PutBlobTask> AsyncPutBlob(const std::string &blob_name, const ctp::ipc::ShmPtr<> &data,
size_t data_size, size_t off = 0, float score = -1.0f, const Context &context = Context());
void GetBlob(const std::string &blob_name, char *data, size_t data_size, size_t off = 0);
void GetBlob(const std::string &blob_name, ctp::ipc::ShmPtr<> data, size_t data_size, size_t off = 0);
Future<GetBlobTask> AsyncGetBlob(const std::string &blob_name, char *data, size_t data_size, size_t off = 0);
float GetBlobScore(const std::string &blob_name);
u64 GetBlobSize(const std::string &blob_name);
std::vector<std::string> GetContainedBlobs();
void ReorganizeBlob(const std::string &blob_name, float new_score);
const TagId &GetTagId() const;
};- The blocking
PutBlob(const char *)throws on a non-zero return code. The private-buffer forms need no shared-memory management; theShmPtrforms take a buffer fromCLIO_IPC->AllocateBufferthat the caller keeps alive until the task completes. - A private-buffer
AsyncGetBlobserved from the shared-memory cache returns an empty future:Wait()returns at once and the future must not be dereferenced. OtherwiseGetReturnCode()is 0 on success afterWait().
C++: Client
Every verb is asynchronous. Results live on the task after Wait(): return_code_ or GetReturnCode() is 0 on success; tag_id_ for GetOrCreateTag; size_ for GetBlobSize; results_ for TagQuery, SemanticSearch and TemporalSearch; parallel tag_names_ and blob_names_ for BlobQuery; blob_names_ for GetContainedBlobs; entries_ for PollTelemetryLog; target_names_ for ListTargets.
Tags
Future<GetOrCreateTagTask<CreateParams>> AsyncGetOrCreateTag(const std::string &tag_name,
const TagId &tag_id = TagId::GetNull(), const PoolQuery &pool_query = PoolQuery::Dynamic());
Future<GetOrCreateTagTask<CreateParams>> AsyncGetOrCreateTag(const std::string &tag_name,
const clio::run::PoolId &fault_pool_id, const std::string &fault_pool_name, const std::string &fault_params,
const TagId &tag_id = TagId::GetNull(), const PoolQuery &pool_query = PoolQuery::Dynamic());
Future<DelTagTask> AsyncDelTag(const TagId &tag_id, const PoolQuery &pool_query = PoolQuery::Dynamic());
Future<DelTagTask> AsyncDelTag(const std::string &tag_name, const PoolQuery &pool_query = PoolQuery::Dynamic(),
bool posix_unlink = false);
Future<RenameTagTask> AsyncRenameTag(const std::string &old_name, const std::string &new_name,
const TagId &tag_id = TagId::GetNull(), const PoolQuery &pool_query = PoolQuery::Broadcast());
Future<SyncTagTask> AsyncSyncTag(const TagId &tag_id, const PoolQuery &pool_query = PoolQuery::Broadcast(),
int min_persistence = -1);
Future<GetContainedBlobsTask> AsyncGetContainedBlobs(const TagId &tag_id,
const PoolQuery &pool_query = PoolQuery::Dynamic());The second AsyncGetOrCreateTag registers another pool as the tag's fault handler: a get of a blob the tag does not hold is dispatched to that pool with fault_params in the context. The Context Assimilation Engine and the paged vectors' Copy use it.
Blobs
Future<PutBlobTask> AsyncPutBlob(const TagId &tag_id, const std::string &blob_name,
u64 offset, u64 size, const char *priv_data, float score = -1.0f,
const Context &context = Context(), u32 flags = 0, const PoolQuery &pool_query = PoolQuery::Dynamic());
Future<PutBlobTask> AsyncPutBlob(const TagId &tag_id, const std::string &blob_name,
u64 offset, u64 size, ctp::ipc::ShmPtr<> blob_data, float score = -1.0f,
const Context &context = Context(), u32 flags = 0, const PoolQuery &pool_query = PoolQuery::Dynamic());
int AsyncPutBlobDefer(const TagId &tag_id, const std::string &blob_name, u64 offset, u64 size,
const char *priv_data, float score = -1.0f, const Context &context = Context(), u32 flags = 0,
const PoolQuery &pool_query = PoolQuery::Dynamic(), u64 max_inflight_bytes = 0);
static u64 AwaitPutsUntilSpace(u64 max_inflight_bytes, u64 max_inflight_count = std::numeric_limits<u64>::max());
static u64 DeferErrorCount();
Future<GetBlobTask> AsyncGetBlob(const TagId &tag_id, const std::string &blob_name,
u64 offset, u64 size, u32 flags, char *priv_data,
const PoolQuery &pool_query = PoolQuery::Dynamic(), const Context &context = Context());
Future<GetBlobTask> AsyncGetBlob(const TagId &tag_id, const std::string &blob_name,
u64 offset, u64 size, u32 flags, ctp::ipc::ShmPtr<> blob_data,
const PoolQuery &pool_query = PoolQuery::Dynamic(), const Context &context = Context());
Future<GetBlobTask> AsyncGetBlobDefer(const TagId &tag_id, const std::string &blob_name,
u64 offset, u64 size, char *priv_data, u32 flags = 0,
const PoolQuery &pool_query = PoolQuery::Dynamic(), const Context &context = Context());
Future<DelBlobTask> AsyncDelBlob(const TagId &tag_id, const std::string &blob_name,
const PoolQuery &pool_query = PoolQuery::Dynamic(), u32 del_flags = 0);
Future<TruncateBlobTask> AsyncTruncateBlob(const TagId &tag_id, const std::string &blob_name, u64 new_size,
const PoolQuery &pool_query = PoolQuery::Dynamic());
Future<GetBlobSizeTask> AsyncGetBlobSize(const TagId &tag_id, const std::string &blob_name,
const PoolQuery &pool_query = PoolQuery::Dynamic(), int replica = 0);
Future<GetBlobScoreTask> AsyncGetBlobScore(const TagId &tag_id, const std::string &blob_name,
const PoolQuery &pool_query = PoolQuery::Dynamic());
Future<ReorganizeBlobTask> AsyncReorganizeBlob(const TagId &tag_id, const std::string &blob_name, float new_score,
const PoolQuery &pool_query = PoolQuery::Dynamic(), int replica = 0);
Future<EvictTask> AsyncEvict(float min_tier_score, u64 bytes,
const PoolQuery &pool_query = PoolQuery::Broadcast(), u32 droppable_only = 0);Context flags: kNoFault suppresses fault-handler dispatch for one operation; kPutIfAbsent fails with kPutExistsRc when the blob exists; kPutIfVersion applies the put only at the expected content version and fails with a version-mismatch code otherwise. A deferred put returns 0 when submitted. The private-buffer AsyncGetBlob has three paths: a copy out of the shared-memory cache with no task (the future is empty), a direct read when the caller is inside the runtime, and client staging.
Queries and telemetry
Future<TagQueryTask> AsyncTagQuery(const std::string &tag_regex, u32 max_tags = 0,
const PoolQuery &pool_query = PoolQuery::Broadcast());
Future<BlobQueryTask> AsyncBlobQuery(const std::string &tag_regex, const std::string &blob_regex,
u32 max_blobs = 0, const PoolQuery &pool_query = PoolQuery::Broadcast());
Future<SemanticSearchTask> AsyncSemanticSearch(const std::string &tag_regex, const std::string &blob_regex,
const std::string &query_text, u32 k = 10, const PoolQuery &pool_query = PoolQuery::Broadcast());
Future<TemporalSearchTask> AsyncTemporalSearch(const std::string &tag_regex, const std::string &blob_regex,
Timestamp time_begin = 0, Timestamp time_end = 0, u32 max_entries = 0,
const PoolQuery &pool_query = PoolQuery::Broadcast());
Future<PollTelemetryLogTask> AsyncPollTelemetryLog(std::uint64_t minimum_logical_time,
const PoolQuery &pool_query = PoolQuery::Dynamic());
Future<ListTargetsTask> AsyncListTargets(const PoolQuery &pool_query = PoolQuery::Dynamic());Patterns are matched against the whole name with std::regex_match. SemanticSearchResult has tag_id_, blob_name_ and score_; TemporalSearchResult has tag_id_, blob_name_ and last_modified_. Timestamp is a u64 of nanoseconds on std::chrono::steady_clock (see the note on the usage page). SemanticSearch is answered by the indexer module, so the client must be bound to it.
Pool queries
PoolQuery::Dynamic(): route to the owner of the tag or blob. The default for data operations.PoolQuery::Broadcast(): every container answers and the runtime merges. The default for queries, RenameTag, SyncTag and Evict.PoolQuery::Local(): only this node.
Python: clio_cte_core_ext
The module binds the same client. Payloads are bytes, every blocking call releases the GIL, and asynchronous calls return a Future. The Python module reference lists every call with its arguments, defaults and return value. In short:
- Setup:
clio_init(mode, default_with_runtime=False, is_restart=False),initialize_cte(config_path, pool_query),get_cte_client(). - Tag:
Tag(tag_name)orTag(tag_id);PutBlob(blob_name, data, off=0),GetBlob(blob_name, data_size, off=0),GetBlobScore,GetBlobSize,GetContainedBlobs,ReorganizeBlob(blob_name, new_score),GetTagId. - Client, blocking:
TagQuery,BlobQuery,SemanticSearch,TemporalSearch,ReorganizeBlob,DelBlob,PollTelemetryLog,RegisterTarget. - Client, asynchronous:
AsyncGetOrCreateTag,AsyncPutBlob,AsyncPutBlobIfAbsent,AsyncPutBlobIfVersion,AsyncGetBlob,AsyncGetBlobVersioned,AsyncGetBlobDefer,AsyncPutBlobDefer(returns anint),AwaitPutsUntilSpace,DeferErrorCount,AsyncGetBlobSize,AsyncGetContainedBlobs,AsyncDelBlob,AsyncReorganizeBlob,AsyncTagQuery,AsyncBlobQuery,AsyncSemanticSearch,AsyncTemporalSearch,AsyncPollTelemetryLog,AsyncRegisterTarget,AsyncGetCapacity,AsyncListTargets,AsyncStatTargets,AsyncGetTargetInfo. - Types:
UniqueId(the tag id),PoolQuery,Future,SemanticSearchResult,TemporalSearchResult,CteTelemetry,CapacityInfo,TargetInfo, and the enumsRuntimeMode,BdevType(kFile,kRam) andCteOp.
Environment variables
CLIO_CTE_POOL: pool the shared CTE client binds to, asmajor.minor. Default 512.0.CLIO_WITH_RUNTIME:0attaches to a running runtime,1starts one in the process. Overrides thedefault_with_runtimeargument ofCLIO_INITandclio_init.CLIO_SERVER_CONF: path of the runtime configuration file. Unset means~/.clio/clio.yaml, then built-in defaults.CLIO_WAIT_SERVER: seconds a client waits for the runtime to answer beforeclio_initgives up. Default 30.CLIO_BIND_ADDR,CLIO_SERVER_ADDR: the address the runtime binds and the address clients connect to. On Windows set both to127.0.0.1.
Compose YAML: clio_cte_core
The CTE is one entry in the runtime's compose list. Sizes accept suffixes k to p (powers of 1024). This is the default file's entry with comments removed; the module page adds the behavior behind each key.
compose:
- mod_name: clio_cte_core
pool_name: cte_main
pool_query: local
pool_id: "512.0"
storage:
- path: "ram::cte_ram_tier1"
bdev_type: "ram"
capacity_limit: "0g"
score: 1.0
- path: "${CLIO_STORAGE_ROOT}/cte_disk_tier.dat"
bdev_type: "file"
capacity_limit: "10GB"
score: 0.2
persistence_level: "temporary"
performance:
metadata_log_path: "${CLIO_STORAGE_ROOT}/cte_metadata_log"
transaction_log_capacity: "32MB"
dpe:
dpe_type: "max_bw"
targets:
neighborhood: 1
default_target_timeout_ms: 30000
poll_period_ms: 5000storage (list)
path:ram::<name>for memory tiers, a file path for file tiers, a URL fors3andgcs. Required unless binding to an existing pool.bdev_type:file,ram,hbm,pinned,noop,s3orgcs.capacity_limit: size string.0is valid only forramand means 80% of system DRAM. A file tier grows lazily up to this cap.score: 0.0 to 1.0. Absent means automatic scoring from measured bandwidth.persistence_level:volatile(default),temporaryorlong_term. Only a tier above volatile can hold the durable copy a flush or SyncTag asks for.growth_unit: lazy-growth step of a file tier, default 1 GB.existing_pool_id,existing_pool_module: bind an already composed pool, such asclio_safe_bdev, as a tier instead of creating a block device. The module name is for logging only.
performance
metadata_log_path: directory for the metadata write-ahead log and snapshots. Empty disables metadata durability.transaction_log_capacity: WAL capacity, default 32 MB.flush_metadata_period_ms(5000),flush_data_period_ms(10000),flush_data_min_persistence(1).fsync_mode:durable(default) ordeferred.stat_targets_period_ms(1000, valid 10 to 60000),max_concurrent_operations(64).
targets
neighborhood: nodes, in ring order, a container registers persistent targets from. Built-in default 4; the shipped file sets 1.default_target_timeout_ms(30000),poll_period_ms(5000).failover_to_successor(false): route a dead owner's blobs to the first live successor.
dpe and organizer
dpe.dpe_type:max_bw(default),round_robinorrandom.organizer:none(default),frecency,grayscott,cyclic,scatterorhotset.organizer_tasks(1) andorganizer_period_ms(5000) size and pace the periodic rescoring.
Where to go next
- Python module reference: every
clio_cte_core_extcall. - Usage: the same calls in task order with examples.
- CTE core module and CTE design: behavior and internals.