SAPI reference¶
This page is the reference for the SAPI client libraries: the methods available in each language and the fields of each configuration object.
For how to use these methods, see Connect with SAPI, Query data with SAPI, and Publish data with SAPI.
Methods¶
SAPI exposes the same set of operations in each language, with naming that follows the language's conventions. The C library uses free functions that take a handle; the others use methods on a client object (Kxs in C# and Java, SAPI in Python).
| Operation | C | C# | Java | Python |
|---|---|---|---|---|
| Connect | sapiConnect |
Connect |
connect |
connect |
| Disconnect | sapiDisconnect |
Disconnect |
disconnect |
disconnect |
| Call an API | sapiExecute |
Execute |
execute |
execute |
| Register a publisher | sapiRegisterPublisher |
RegisterPublisher |
registerPublisher |
register_publisher |
| Publish a message | sapiPublish |
Publish |
publish |
publish |
| Unregister a publisher | sapiUnregisterPublisher |
UnregisterPublisher |
unregisterPublisher |
unregister_publisher |
| Register a queue listener | sapiRegisterQueueListener |
RegisterQueueListener |
registerQueueListener |
register_queue_listener |
| Unregister a queue listener | sapiUnregisterQueueListener |
UnregisterQueueListener |
unregisterQueueListener |
unregister_queue_listener |
| Acknowledge a queue message | sapiAckQueue |
AckQueue |
ackQueueMessage |
ack_queue |
| Register a log handler | sapiRegisterLogHandler |
RegisterLogHandler |
Not needed. See Logging and events in Java. | register_log_handler |
| Set log levels | sapiSetLogLevels |
SetLogLevels |
Not available | Not available |
| Get the event handler | sapiEventHandler |
GetSapiEvents |
addEventListener. See Logging and events in Java. |
events property |
| Get the TCP endpoint | sapiGetTcpEndpoint |
GetTcpEndpoint |
getTcpEndpoint |
get_tcp_endpoint |
| Free a response object | sapiFreeKxsResponse |
Not applicable | Not applicable | Not applicable |
| Free a configuration object | sapiFreeSAPIConfig |
Not applicable | Not applicable | Not applicable |
Logging and events in Java¶
Java has no log handler call. SAPI routes the native log lines into SLF4J loggers named com.kx.sapi.c.*, so you control them through your logging configuration.
Java delivers the three connection events as SapiEvent objects to listeners that you register with addEventListener. The events are GW_CONNECTED, GWS_CONNECTED, and RP_CONNECTED. The method is protected, so to use it you subclass Kxs. See Connection event callbacks.
The other languages expose the same three events: one Gateway connected, all Gateways connected, and the response server connected. In C, sapiEventHandler returns a structure of three wait handles, and C# mirrors it with GetSapiEvents. In Python, the events property holds three threading.Event objects.
Method signatures¶
KxsHandle sapiConnect(SAPIConfig *config, KxsResponse *response);
void sapiDisconnect(KxsHandle handle);
bool sapiExecute(KxsHandle handle, char *apiName, K request, K header,
bool deserializeResponse, SAPIRetryPolicy *retryPolicy,
KxsResponse *response);
TopicHandle sapiRegisterPublisher(KxsHandle handle, char *topicName,
KxsResponse *response);
bool sapiPublish(TopicHandle handle, short msgType, K data, K header,
SAPIRetryPolicy *retryPolicy, KxsResponse *response);
bool sapiUnregisterPublisher(KxsHandle handle, TopicHandle topicHandle,
KxsResponse *response);
bool sapiRegisterQueueListener(KxsHandle handle, char *queue,
SAPIQueueHandler handler, SAPIAckMode ackMode,
int workers, KxsResponse *response);
bool sapiUnregisterQueueListener(KxsHandle handle, char *queue,
KxsResponse *response);
bool sapiAckQueue(KxsHandle handle, char *queue, long long id);
bool SAPIQueueHandler(KxsHandle handle, char *queue, long long id,
KxsResponse *response);
void sapiRegisterLogHandler(LogHandler callback);
void sapiSetLogLevels(short traceLevel, short debugLevel, short infoLevel,
short warnLevel, short errorLevel, short fatalLevel);
SAPIEvents *sapiEventHandler(KxsHandle handle);
bool sapiGetTcpEndpoint(KxsHandle handle, char *sb, int len);
void sapiFreeKxsResponse(KxsResponse *response);
void sapiFreeSAPIConfig(SAPIConfig *config);
bool Connect(SapiConfig config, KxsResponse kxsResponse = null);
void Disconnect();
bool Execute(string apiName, c.Dict request = null, c.Dict header = null,
bool deserializeResponse = true, RetryPolicy retryPolicy = null,
KxsResponse kxsResponse = null);
IntPtr RegisterPublisher(string topic, KxsResponse kxsResponse = null);
bool Publish(IntPtr topicHandle, short msgType, object data,
c.Dict header = null, RetryPolicy retryPolicy = null,
KxsResponse kxsResponse = null);
void UnregisterPublisher(IntPtr topicHandle, KxsResponse kxsResponse = null);
bool RegisterQueueListener(string queue,
Func<IntPtr, string, int, KxsResponse, bool> handler,
short ackMode, KxsResponse kxsResponse = null);
bool UnregisterQueueListener(string queue, KxsResponse kxsResponse = null);
static bool AckQueue(IntPtr client, string queue, long id);
static void RegisterLogHandler(Action<int, string, string> logMessageHandler);
static void SetLogLevels(short traceLevel, short debugLevel, short infoLevel,
short warnLevel, short errorLevel, short fatalLevel);
Events.Events GetSapiEvents();
string GetTcpEndpoint();
boolean connect(SapiConfig sapiConfig, KxsResponse kxsResponse);
void disconnect();
boolean execute(String apiName, c.Dict params, c.Dict header,
RetryPolicy retryPolicy, KxsResponse kxsResponse);
long registerPublisher(String topic, KxsResponse kxsResponse);
boolean publish(long topicHandle, short msgType, Object data,
c.Dict header, KxsResponse response);
boolean publish(long topicHandle, short msgType, Object data, c.Dict header,
RetryPolicy retryPolicy, KxsResponse kxsResponse);
boolean unregisterPublisher(long topicHandle, KxsResponse kxsResponse);
boolean registerQueueListener(String queue, KxsQueueListener listener,
AckMode ackMode, KxsResponse response);
boolean unregisterQueueListener(String queue, KxsResponse response);
boolean ackQueueMessage(String queue, long messageId);
String getTcpEndpoint();
connect(config: SAPIConfig, response: Optional[KxsResponse] = None) -> bool
disconnect() -> None
execute(req_corr: int, api_name: str, request: pykx.Dictionary,
header: Optional[pykx.Dictionary] = None,
retry_policy: Optional[SAPIRetryPolicy] = None,
response: Optional[KxsResponse] = None) -> bool
register_publisher(topic_name: str,
response: Optional[KxsResponse] = None) -> TopicHandle
publish(topic_handle: TopicHandle, req_corr: int, msg_type: int,
payload: pykx.Dictionary, header: Optional[pykx.Dictionary] = None,
retry_policy: Optional[SAPIRetryPolicy] = None,
response: KxsResponse = None) -> bool
unregister_publisher(topic_handle: TopicHandle,
response: Optional[KxsResponse] = None) -> bool
register_queue_listener(queue: str, handler: QueueHandler,
ack_mode: SAPIAckMode, workers: int,
response: KxsResponse) -> bool
unregister_queue_listener(queue: str, response: KxsResponse) -> bool
ack_queue(queue: str, queue_id: int) -> bool
register_log_handler(callback: LogHandler) -> None
get_tcp_endpoint(buf_len: int = 512) -> str
Differences between the languages¶
- Request correlator. Python's
executeandpublishtake areq_corrparameter. Pass0to have SAPI generate the correlator, which is the normal value. SAPI uses any non-zero value as supplied, so you can set your own to find a request in the client and server logs. The C serialized entry points take the same argument. In Java, set thereqCorrkey in the header dictionary instead. C and C# always generate the correlator. - Queue listener workers.
register_queue_listenerin Python andsapiRegisterQueueListenerin C require aworkersargument, which has no default. It's the number of messages that the client asks the queue to keep in flight for that listener at once. Use1unless the handler is slow and the queue is deep. It's not the same asmqWorkersCountin the configuration, which sizes the shared thread pool that processes queue messages. C# and Java don't expose it and always pass1. - Publish without a retry policy. The Java
publishoverload without a retry policy passesnull. A publish with no retry policy is asynchronous: the call returns success as soon as the client accepts the message. See Choose synchronous or asynchronous publishing. - Unregistering a publisher in C#.
UnregisterPublisherreturnsvoid, while the other languages return a boolean. Pass a response object to see the outcome.
Configuration objects¶
The configuration object is the same structure in every language, with per-language naming. The fields that differ by more than capitalization are:
| Purpose | C and Python | C# | Java |
|---|---|---|---|
| Discovery endpoints | discoverySvcHosts |
DiscoveryHosts |
discoveryHosts |
| Service classes of interest | scs |
ServiceClasses |
scs |
| Build information | build |
Build |
buildInfo |
| Network interface addresses | addrs |
Addresses |
addrs |
| Event callbacks | sapiCallbacks |
Not applicable. See Connection event callbacks. | Not applicable. See Connection event callbacks. |
| Gateway worker threads | gwWorkersCount |
GWWorkerThreadCount |
gwWorkersCount |
| RP worker threads | rpWorkersCount |
RPWorkerThreadCount |
rpWorkersCount |
| MQ worker threads | mqWorkersCount |
MQWorkerThreadCount |
mqWorkersCount |
| Publish worker threads | pubWorkersCount |
PublishWorkerThreadCount |
pubWorkersCount |
| Discovery worker threads | dsWorkersCount |
DSWorkerThreadCount |
dsWorkersCount |
| TLS settings | tls |
Tls |
tls (set with setTLS) |
| Socket options | socketConfig |
SocketConfig |
socketConfig |
| RT settings | rtConfig |
RtConfig |
rtConfig |
In C, every array field has a companion count field — discoverySvcHostsCount, listenHostsCount, advertiseHostsCount, gatewayHostsCount, scsCount, and addrsCount — which you must set to the number of entries in the array. The Python library also accepts the Count fields. The C# and Java libraries take arrays and derive the count.
Connection configuration fields¶
The field names below use the C and Python spelling.
| Field | Type | Description |
|---|---|---|
discoverySvcHosts |
string list | Addresses and ports of the Discovery service — the qetcd process on KX Sensors nodes. |
gatewayHosts |
string list | Addresses and ports of Gateway processes. Setting this disables Discovery. |
username |
string | KX Sensors user name. |
password |
string | Password. |
instanceName |
string | Name for this client. Appears in the SAPI header of every request and in server-side logs. Defaults to a generated unique value. |
listenHosts |
string list | Addresses that the client binds its listening socket to, for inbound connections. Defaults to ["0.0.0.0"]. Set it if the default bind is wrong for the host. |
listenPorts |
string | Port range to accept inbound connections on, for example 8000-8010. |
advertiseHosts |
string list | Addresses that the client sends to Discovery so that the server can connect back. Set it when the bind address isn't reachable from the server. No default. |
advertisePorts |
string | Ports advertised to the server as accepting inbound connections. |
udpPort |
int | Set by the client. SAPI overwrites it with the client's actual listening port when it sets up the socket, then sends it to Discovery. Don't set it. Defaults to 0. |
addrs |
string list | Set by the client. SAPI fills it in from its own listening endpoint and sends it to Discovery. Don't set it. |
connTimeout |
int | Timeout in milliseconds for a Gateway connection to succeed. -1 waits indefinitely. In Java, 0 uses the native default of 30 seconds. |
bridgeTimeout |
int | Reserved. SAPI doesn't enforce it. Available in C and Java. In Java, 0 uses the native default of 60 seconds. |
gatewayStrategy |
short | Strategy for choosing the destination Gateway. Round-robin is the default and the only strategy that works, so don't set it. |
scs |
string list | Unused. SAPI copies and logs the value but doesn't act on it. Defaults to ["/reg/GW/"]. |
domain |
string | Sent to Discovery as domain on the client's registration record. Leave the default unless your deployment team tells you otherwise. Defaults to an empty string. |
serviceClass |
string | Sent to Discovery as svcClass on the client's registration record. The default, EXT, marks the process as an external client. Leave the default unless your deployment team tells you otherwise. |
family |
string | Sent to Discovery as family on the client's registration record. Leave the default unless your deployment team tells you otherwise. Defaults to an empty string. |
version |
int | Set by the client. SAPI sends it to Discovery as the registration revision. Don't set it. Defaults to 0. |
build |
string | Build information. |
useTLS |
bool | Whether to use TLS for connections to remote processes. |
tls |
SAPITLS |
TLS settings. See TLS fields. |
retryPolicy |
SAPIRetryPolicy |
Default retry policy. Null means no retries. See Retry policy fields. |
socketConfig |
SAPISocketConfig |
Socket options. See Socket option fields. |
rtConfig |
SAPIRTConfig |
RT settings. See RT configuration fields. |
sapiCallbacks |
SAPICallbacks |
Called on connection events. See Connection event callbacks. |
gwWorkersCount |
short | No effect. SAPI logs the value, but the Gateway pool always has one worker. Defaults to 3. |
rpWorkersCount |
short | Size of the pool that handles query responses. Defaults to 6. |
mqWorkersCount |
short | Size of the pool that runs queue listener callbacks. Defaults to 3. |
pubWorkersCount |
short | No effect. SAPI never reads it. Defaults to 3. |
dsWorkersCount |
short | No effect. SAPI never reads it. Defaults to 1. |
reqMaxPending |
int | Maximum number of outstanding requests and pending publishes. When the limit is reached, the call fails with -1, unless reqMaxPendingBlock is true. Set it if the application needs more calls in flight. Defaults to 10000. |
reqMaxPendingBlock |
bool | Whether a call waits, instead of failing, when reqMaxPending is reached. Defaults to false. |
sapiProtocol |
byte | Set by each language binding. Don't set it. The library sends it in every request header as clientProtocol, and uses it to decide whether queue messages must be serialized for a managed language. The values are 0x02 for C, 0x04 for Java, and 0x05 for C# and Python. |
Retry policy fields¶
| Field | Type | Description |
|---|---|---|
maxAttempts |
unsigned int | Maximum number of attempts before the operation fails. |
timeout |
unsigned int | Timeout for a single attempt, in milliseconds. |
retryInterval |
unsigned int | Interval between attempts, in milliseconds. |
retryScaling |
float | Multiplier applied to the interval after each attempt. Must be 1 or greater. |
The C# constructor takes the fields in the order maxAttempts, timeout, retryInterval, retryScaling; the Java constructor takes the same order. See Retry failed calls.
Socket option fields¶
| Field | Type | Description |
|---|---|---|
socRoundTripTime |
int | Expected maximum round-trip time to the server, in milliseconds. |
socSendRate |
int | Expected send rate per connection, in bytes per second. |
socReceiveRate |
int | Expected receive rate per connection, in bytes per second. |
The C# field names are SocketRoundTripTime, SocketSendRate, and SocketReceiveRate.
TLS fields¶
| Field | Type | Description |
|---|---|---|
CA |
string | CA certificate, as a string. |
CAFile |
string | Path to a file holding the CA certificate. Overrides CA. |
cert |
string | Client certificate, as a string. |
certFile |
string | Path to a file holding the client certificate. Overrides cert. |
key |
string | Certificate key, as a string. |
keyFile |
string | Path to a file holding the certificate key. Overrides key. |
verifyClient |
bool | Verify the certificate presented on inbound connections. |
verifyServer |
bool | Verify the certificate presented on outbound connections. |
The C# field names are capitalized: CA, CAFile, Cert, CertFile, Key, KeyFile, VerifyClient, VerifyServer. See Encrypt the connection with TLS.
RT configuration fields¶
These fields configure the RT layer that carries published messages. Most clients set only a few of them, usually rtDir and dedupId.
When configUrl is empty, SAPI writes its own RT configuration file under configPath, named <instance>_<topic>, and fills it with the feed endpoints that it gets from Discovery. SAPI also appends the instance name and topic to rtDir, so each publisher gets its own log directory.
| Field | Type | Description | Default |
|---|---|---|---|
useBridge |
bool | Whether to use a bridge connection instead of persisting messages to a local disk. | |
rtDir |
string | Base directory for RT logs. SAPI appends the instance name and topic to it. | /tmp/rt on Linux, c:/Temp/rt on Windows |
configPath |
string | Directory where SAPI writes the RT configuration file that it generates. Used when configUrl isn't set. |
|
caInfoFile |
string | Path to a CA certificate bundle. | Empty string |
dedupId |
string | Label that tells publishers apart. It doesn't deduplicate messages. See Deduplication. | None |
logLevel |
string | General log level: info, warn, err, or off. |
info |
consoleLogLevel |
string | Console log level: info, warn, err, or off. |
err |
replFileLogLevel |
string | Replicator file log level: trace, debug, info, warn, error, fatal, or off. |
off |
replConsoleLogLevel |
string | Replicator console log level, same values as replFileLogLevel. |
err |
connTimeout |
int | RT connection timeout, in milliseconds. | 2000 |
configMaxAge |
int | Maximum age of configuration details, in milliseconds. | 300000 |
fetchConfigSleep |
int | Delay between configuration reads, in milliseconds. | 5000 |
localPersistencePeriod |
int | Local data persistence period, in milliseconds. | 600000 |
rtFlushTimeoutSecs |
int | Timeout, in seconds, for flushing local logs to the server on close. -1 means no timeout. A value of 0 from a language binding keeps the default. |
No timeout |
rtLogSizeSoftCap |
int | Soft cap on the size of an RT log file, in bytes. 0 uses the RT SDK's default roll behavior. |
0 |
rtLogSizeHardCap |
int | Hard cap on the size of an RT log file, in bytes. 0 uses the RT SDK's default roll behavior, which rolls at 1 GB. |
0 |
deleteFiles |
int | Whether to delete RT log files. | 0 |
truncateArchived |
int | Whether archived RT log files are truncated automatically. | 1 |
Advanced RT fields¶
SAPI passes these fields to the RT SDK unchanged. Leave them unset unless the RT team tells you otherwise. SAPI doesn't derive stream, endPoints, rtPort, prefix, or clientName from Discovery; it leaves them empty.
| Field | Type | Description | Default |
|---|---|---|---|
configUrl |
string | URL or file that supplies the RT endpoints. Set it only when you supply endpoints by hand instead of using Discovery. | None |
clientName |
string | RT client identifier. | |
prefix |
string | Prefix for RT resources. | |
stream |
string | RT stream identifier. | |
endPoints |
string | RT endpoint identifiers. | |
rtPort |
string | RT port number. | |
restPortStart |
int | Port on which to start the RT REST server. | 0 |
clientType |
string | RT client type. SAPI publishes only, so leave it as pub. |
pub |
The RT SDK also has subscriber fields (logPosition, pauseThreshold, and exchangeArchived). They have no effect in SAPI, which has no subscribe call.
The Java field names are rtDir, caInfoFile, and rtFlushTimeoutSecs; the C# names are capitalized, with Dir for the log directory, CaInfoFile for the CA bundle, and FlushTimeoutSecs for the flush timeout. The Python name for the CA bundle is CAInfoFile.
Response object fields¶
| Field | Type | Description |
|---|---|---|
reqCorr |
long | Request correlator. |
queueTm |
int | Queue time, in milliseconds. |
svcTm |
int | Service time, in milliseconds. |
rc |
short | Response code. 0 indicates success. |
ac |
short | Application code. |
ai |
string or object | Application information. |
header |
dictionary | Response header. |
payload |
object | Response payload. |
In C, ai, header, and payload each have a companion length field: aiLen, headerLen, and payloadLen. Call sapiFreeKxsResponse to release a response object in C.
The type of ai was reverted to Object to match v2 behavior, which may require small changes in clients written against an earlier v3 release. See Release notes.
Connection event callbacks¶
SAPI raises three connection events. Each language exposes them differently.
| Event | Message passed to the handler |
|---|---|
| Gateway connected | The Gateway's process name. |
| All Gateways connected | An empty string. |
| Response connection accepted | The remote IP address. |
Every handler is optional. Each event also signals a matching wait object, for code that prefers to wait instead of register a handler.
No event fires when a Gateway or response connection is lost. The client reconnects on its own and raises the Gateway connected event again when the Gateway returns, so the only signals your application gets are a failed query in the meantime and the reconnect event afterwards.
Fill in a SAPICallbacks structure and set it on config->sapiCallbacks before you call sapiConnect. The handler type is void handler(const char *msg, const void *opt), where opt is the client handle.
| Field | Invoked when |
|---|---|
gwConnectedEvent |
A Gateway connection is established. |
gwsConnectedEvent |
All Gateways have at least one connection established. |
rpConnectedEvent |
A response connection is accepted. |
To wait instead, use the semaphores in the structure that sapiEventHandler(handle) returns.
Subscribe to the .NET events GwConnected, GwsConnected, and RpConnected on the object that GetSapiEvents() returns. The handler receives a SapiEventsArgs with a Message string.
kxs.GetSapiEvents().GwConnected += (sender, args) => Console.WriteLine(args.Message);
Don't use the public SapiCallbacks class or its IntPtr fields. Connect overwrites them.
Java has no function pointers. Implement the one-method EventListener interface, handle(SapiEvent). Read event.getEventType(), which is GW_CONNECTED, GWS_CONNECTED, or RP_CONNECTED, and event.getMessage(). Register the listener with addEventListener(type, listener).
addEventListener is protected, so your application has to subclass Kxs.
Java listeners see only reconnections. The two Gateway events raised during the initial connect are dropped, because the Kxs object isn't registered until connect returns.
Pass SAPICallbacks(gwConnectedEvent=..., gwsConnectedEvent=..., rpConnectedEvent=...) as config.sapiCallbacks. Each handler is a callable that takes (msg, opt).
If you supply none, the library sets the three threading.Event objects on kxs.events, so you can wait on them instead, for example kxs.events.gwConnected.
Threads and timing¶
In C, C# and Python, the Gateway callbacks run inline on that Gateway's communication worker thread, and the response connection callback runs on the listening thread. A slow handler stalls that thread. Record the event or signal another thread, and return at once. Don't block in a handler, and don't call back into SAPI from one.
Java hands listeners to an executor, so a Java listener can do real work.
The Gateway events fire while connect is still blocking. In C, C# and Python, the callback runs before connect returns.
Acknowledgement modes¶
SAPIAckMode sets how a queue listener acknowledges messages.
| Value | Numeric | Behavior |
|---|---|---|
SAPI_ACK_UNKNOWN |
Not yet set. | |
SAPI_ACK_AUTO |
1 | The message is acknowledged automatically when the queue handler returns true. |
SAPI_ACK_CLIENT |
2 | The client must acknowledge explicitly. |
SAPI_ACK_NONE |
3 | No acknowledgement is sent. The server treats the message as acknowledged when it sends it. |
In C# the mode is passed as a short; in Java it is the AckMode enum with values AUTO, CLIENT, and NONE. For the server side of message queues, see Publish and subscribe to a message queue.
Generate enumeration files¶
KX Sensors uses enumerations and flags for the numeric codes that a client exchanges with the server, such as return codes, application codes, log levels, service classes, and your application's own message types. The generator writes those codes as named constants, so each client language uses the same names as the server.
Which sets you need depends on your application. Every client needs the return and application codes, and the SAPI library already ships those in sapidefns.h and its Java and C# counterparts. The generated files add the application-specific sets.
Generate the files from the server rather than hand-writing them, so they stay in step with the deployment's configuration.
- Connect to the target environment over SSH and switch to the KX Sensors user.
- Start a q console with the enumeration generation console:
mc enumGen - Load the export library:
li`kxsSapiExport -
Generate the files:
.flagsenums.writeAll[]The log message
Writing export files to:shows the resolved output path. By default that is thesapisubdirectory of the environment's miscellaneous data directory (${MISC}/sapi), which you can change with thesapiExportDirsystem parameter. Each language has its own subdirectory, for examplejava/Flags.javaandjava/Enum.java. -
Exit the console with
\\. - Copy the generated files from that directory to your development machine.
The generator produces files for Java, C#, C++, C, and PL/SQL. It doesn't produce Python files, and the Python library ships no generated constants.
In C#, the Kx.SapiCS.Enum.dll assembly ships with the library so that example code compiles. Replace it with enumerations generated on your own server before you run against a real deployment.
Regenerate after an upgrade¶
The generated files are a snapshot, stamped with the environment version and the generation time. The client never checks that version. After any upgrade that adds, removes, or renumbers a flag or enumeration, regenerate the files and rebuild your client.
SAPI gives no error if the files are stale. The client sends the old numbers, which the server may map to a different or illegal value, and it can't name new codes that it receives.