C

struct TSCLIENT_Key
#include <client.h>

A key structure for TStorage records.

Public Members

int32_t cid
int32_t moid
int64_t mid
int64_t cap
int64_t acq
struct TSCLIENT_PayloadType
#include <client.h>

Interface for user-defined payloads.

Each TStorage RecordsSet and Channel has an associated payload type, defined by user by passing a ‘TSCLIENT_PayLoadType’ structure as a ‘payloadType’ parameter to ‘TSCLIENT_RecordsSet_new’ or ‘TSCLIENT_Channel_new’. ‘payloadType’ defines the size of the record with payload (‘size’), offset of the payload within a record (‘offset’), and functions to serialize (‘toBytes’) and deserialize (‘fromBytes’) a single payload structure to/from a bytestream. When communicating with TStorage, the Channel uses these values and functions to send or retrieve Records.

As mentioned above, ‘size’ defines size of each record with payload. This is not to say that variable-sized payloads are not allowed: a payload structure may e.g. contain a pointer to a variable-sized memory area, that is allocated and filled by the ‘fromBytes’ function. This way the payload structure remains constant in size, as it only contains the pointer, but the payload itself may have any size.

But care must be taken in the above case - the library does not know about any additional allocated memory in the payload, so it is the responsibility of the user to free the memory allocated for each payload in any RecordsSets sent to or retrieved from a Channel.

Public Members

size_t size

Size of the record with payload structure in bytes.

A record is composed of a Key and a payload. This is the size of the whole record structure including the key and the payload.

The size may be defined as sizeof(TSCLIENT_Record) to support empty payloads. In this case, records’ keys are the only meaningful data stored in TStorage.

See comments for TSCLIENT_Record.

size_t offset

Offset of the payload structure in an encapsulating Record.

See comments for TSCLIENT_Record.

size_t(* toBytes )(const void *restrict val, void *restrict buffer, size_t size)

Serializes a user-provided payload to a sequence of bytes.

This function is called during sending records via a Channel (i.e. during TSCLIENT_Channel_put and TSCLIENT_Channel_puta). It serializes the user-defined payload structure ‘val’ to a sequence of bytes starting at ‘*buffer’, writing no more than ‘size’ bytes.

If it occurs that the number of bytes needed to serialize ‘val’ is greater than ‘size’, this function may abort the serialization and leave the contents of ‘buffer’ in an undetermined state. This will cause the library to increase the buffer’s size and try again.

It always returns a number of bytes needed to serialize ‘val’ in full.

Param val:

[in] pointer to a user-defined payload structure. May be NULL to indicate empty payload.

Param buffer:

[out] pointer to a buffer to which ‘val’ shall be serialized

Param size:

size of ‘buffer’ in bytes

Return:

Number of bytes needed to serialize ‘val’ (may be 0 if ‘val’ is NULL, i.e. an empty payload).

int(* fromBytes )(void *restrict val, const void *restrict buffer, size_t size)

Deserializes a sequence of bytes into a user-defined payload.

This function is called during receiving records from a Channel (i.e. during TSCLIENT_Channel_get and TSCLIENT_Channel_getStream), once on each retrieved Record. It deserializes a sequence of bytes starting at ‘*buffer’ of length ‘size’, into a user-defined payload structure pointed to by ‘*val’. (The size of the ‘val’ structure is constant for a given payload type.)

This function may allocate additional memory and store pointers to it in the payload structure, but it is then the user’s responsibility to free such allocated memory for all records created during communication via a Channel that uses this payload type.

Should this function fail to deserialize, either because of invalid format of data in ‘*buffer’, or because of a memory allocation error or any other reason - then it should indicate the failure by returning non-zero. This will cause the failed payload to not be included in a resulting RecordsSet, will close the Channel, and cause the get/getStream function to fail with an error.

Failure indication described above is not mandatory. This function may indicate a failure by any other means, e.g. by setting an external variable or putting a special value in the payload ‘*val’ itself - and return 0 to indicate success. This will result in retrieving all records from TStorage and not closing the Channel, and the user may then examine the external variable or payloads of the returned Records to determine which payloads deserialized successfully.

Param val:

[out] pointer to a user-defined payload structure. ‘buffer’ will be deserialized here.

Param buffer:

[in] pointer to bytes to deserialize

Param size:

number of bytes in ‘buffer’ to deserialize. It may be 0 to indicate empty payload.

Return:

Returns 0 on success, or non-0 to indicate an error during deserialization.

struct TSCLIENT_Record
#include <client.h>

A record with a key and a payload.

This structure has no payload field - the payload type is defined by user. The user should define its own record structure that “inherits” from ‘TSCLIENT_Record’, i.e. has ‘TSCLIENT_Record’ as its first element, and a payload structure as its second element, e.g.:

struct MyPayload { int measurementType; float measurementValue; };

struct MyRecord { TSCLIENT_Record base; MyPayload value; };

Then the user should provide the custom record structure’s size, and the payload’s offset within this structure, to a payloadType that would later be passed to a Channel, e.g.:

TSCLIENT_PayLoadType payloadType = { .size = sizeof(struct MyRecord), .offset = offsetof(struct MyRecord, value), .toBytes = (…), .fromBytes = (…) };

A payloadType defined above shall then be passed to each RecordSet and Channel:

TSCLIENT_RecordsSet* recs = TSCLIENT_RecordsSet_new(&payloadType); TSCLIENT_Channel* chan = TSCLIENT_Channel_new(host, port, &payloadType);

Then the user should cast any void pointers obtained from RecordsSets to their own record structure’s pointer (see TSCLIENT_RecordsSet_elements).

Note: If records without payload are desired, then the user does not need to define custom structures and shall just use the TSCLIENT_Record structure as follows:

TSCLIENT_PayLoadType payloadType = { .size = sizeof(TSCLIENT_Record), .offset = sizeof(TSCLIENT_Record), .toBytes = (…), .fromBytes = (…), }

Public Members

TSCLIENT_Key key
file client.h
#include <stddef.h>
#include <stdint.h>
#include <sys/time.h>
#include <time.h>

Defines

TSCLIENT_CID_MIN

Minimum allowed value of TSCLIENT_Key.cid.

TSCLIENT_CID_MAX

Maximum allowed value of TSCLIENT_Key.cid.

TSCLIENT_MID_MIN

Minimum allowed value of TSCLIENT_Key.mid.

TSCLIENT_MID_MAX

Maximum allowed value of TSCLIENT_Key.mid.

TSCLIENT_MOID_MIN

Minimum allowed value of TSCLIENT_Key.moid.

TSCLIENT_MOID_MAX

Maximum allowed value of TSCLIENT_Key.moid.

TSCLIENT_CAP_MIN

Minimum allowed value of TSCLIENT_Key.cap.

TSCLIENT_CAP_MAX

Maximum allowed value of TSCLIENT_Key.cap.

TSCLIENT_ACQ_MIN

Minimum allowed value of TSCLIENT_Key.acq.

TSCLIENT_ACQ_MAX

Maximum allowed value of TSCLIENT_Key.acq.

Typedefs

typedef struct TSCLIENT_Key TSCLIENT_Key

A key structure for TStorage records.

typedef struct TSCLIENT_Record TSCLIENT_Record

A record with a key and a payload.

This structure has no payload field - the payload type is defined by user. The user should define its own record structure that “inherits” from ‘TSCLIENT_Record’, i.e. has ‘TSCLIENT_Record’ as its first element, and a payload structure as its second element, e.g.:

struct MyPayload { int measurementType; float measurementValue; };

struct MyRecord { TSCLIENT_Record base; MyPayload value; };

Then the user should provide the custom record structure’s size, and the payload’s offset within this structure, to a payloadType that would later be passed to a Channel, e.g.:

TSCLIENT_PayLoadType payloadType = { .size = sizeof(struct MyRecord), .offset = offsetof(struct MyRecord, value), .toBytes = (…), .fromBytes = (…) };

A payloadType defined above shall then be passed to each RecordSet and Channel:

TSCLIENT_RecordsSet* recs = TSCLIENT_RecordsSet_new(&payloadType); TSCLIENT_Channel* chan = TSCLIENT_Channel_new(host, port, &payloadType);

Then the user should cast any void pointers obtained from RecordsSets to their own record structure’s pointer (see TSCLIENT_RecordsSet_elements).

Note: If records without payload are desired, then the user does not need to define custom structures and shall just use the TSCLIENT_Record structure as follows:

TSCLIENT_PayLoadType payloadType = { .size = sizeof(TSCLIENT_Record), .offset = sizeof(TSCLIENT_Record), .toBytes = (…), .fromBytes = (…), }

typedef struct TSCLIENT_PayloadType TSCLIENT_PayloadType

Interface for user-defined payloads.

Each TStorage RecordsSet and Channel has an associated payload type, defined by user by passing a ‘TSCLIENT_PayLoadType’ structure as a ‘payloadType’ parameter to ‘TSCLIENT_RecordsSet_new’ or ‘TSCLIENT_Channel_new’. ‘payloadType’ defines the size of the record with payload (‘size’), offset of the payload within a record (‘offset’), and functions to serialize (‘toBytes’) and deserialize (‘fromBytes’) a single payload structure to/from a bytestream. When communicating with TStorage, the Channel uses these values and functions to send or retrieve Records.

As mentioned above, ‘size’ defines size of each record with payload. This is not to say that variable-sized payloads are not allowed: a payload structure may e.g. contain a pointer to a variable-sized memory area, that is allocated and filled by the ‘fromBytes’ function. This way the payload structure remains constant in size, as it only contains the pointer, but the payload itself may have any size.

But care must be taken in the above case - the library does not know about any additional allocated memory in the payload, so it is the responsibility of the user to free the memory allocated for each payload in any RecordsSets sent to or retrieved from a Channel.

typedef struct TSCLIENT_RecordsSet TSCLIENT_RecordsSet

A set or records to put or get from a TStorage Channel.

A RecordsSet holds a number of Records. It has a defined payload type, and all Records inside must have payloads of that type.

This structure may be created by user, or may be a result of a calling ‘TSCLIENT_Channel_get’ or ‘TSCLIENT_Channel_getStream’. It can be passed as input to ‘TSCLIENT_Channel_put’ and ‘TSCLIENT_Channel_puta’.

Caution: if record payloads (as defined by a RecordsSet’s payloadType) contain pointers to additional allocated memory, then it is the user’s responsibility to free such memory on each record inside that RecordsSet.

typedef struct TSCLIENT_Channel TSCLIENT_Channel

A TStorage communications channel.

typedef void (*TSCLIENT_GetCallback)(void *userData, TSCLIENT_RecordsSet *data)

Function called when a TSCLIENT_Channel_getStream fetches records.

The user provides a function of this type as the ‘callback’ parameter when calling ‘TSCLIENT_Channel_getStream’, together with a ‘userData’ parameter which is a user-supplied data structure. This function will then be called every time a set of records is received by the get request.

The function shall process each record in the provided RecordSet ‘data’. Caution 1: if record payloads (as defined in a payloadType passed to a Channel) contain pointers to additional allocated memory, then it is the user’s responsibility to free such memory on each record inside ‘data’ before returning from this function. Caution 2: the function shall not destroy ‘data’ itself.

Param userData:

the value of ‘userData’ provided when calling ‘TSCLIENT_Channel_getStream’, may be whatever the user wishes, even NULL

Param data:

[in] a RecordsSet with records received from TStorage. Its payload type is the same as the payload type of the Channel’s on which ‘TSCLIENT_Channel_getStream’ is being called.

Enums

enum TSCLIENT_ResponseStatus

Possible results of TSCLIENT_* functions.

Values:

enumerator TSCLIENT_RES_OK
enumerator TSCLIENT_RES_ERROR
enumerator TSCLIENT_RES_INVARG
enumerator TSCLIENT_RES_RETRY
enumerator TSCLIENT_RES_TIMEOUT
enumerator TSCLIENT_RES_NOMEM
enumerator TSCLIENT_RES_IOERR
enumerator TSCLIENT_RES_NOPERM
enumerator TSCLIENT_RES_NOIMPL
enumerator TSCLIENT_RES_ABORT
enumerator TSCLIENT_RES_UNAUTHORIZED
enumerator TSCLIENT_RES_INACTIVE
enumerator TSCLIENT_RES_CONTINUE
enumerator TSCLIENT_RES_INTRERROR
enumerator TSCLIENT_RES_CONNRESET
enumerator TSCLIENT_RES_ADDRERROR
enumerator TSCLIENT_RES_CONNERROR
enumerator TSCLIENT_RES_BINDERROR
enumerator TSCLIENT_RES_SOCKERROR
enumerator TSCLIENT_RES_INVPATH
enumerator TSCLIENT_RES_EXIST
enumerator TSCLIENT_RES_NOENT
enumerator TSCLIENT_RES_NOTDIR
enumerator TSCLIENT_RES_BUSY
enumerator TSCLIENT_RES_NOTEMPTY
enumerator TSCLIENT_RES_NOTOPENED
enumerator TSCLIENT_RES_ISDIR
enumerator TSCLIENT_RES_OPENED
enumerator TSCLIENT_RES_CLOSED
enumerator TSCLIENT_RES_NOTSTARTED
enumerator TSCLIENT_RES_RUNNING
enumerator TSCLIENT_RES_ABORTED
enumerator TSCLIENT_RES_REDIR
enumerator TSCLIENT_RES_BADPAYLOAD
enumerator TSCLIENT_RES_MEMORYLIMIT

Functions

time_t TSCLIENT_timestampToUnix(int64_t ts)

Converts a cap/acq timestamp to a Unix timestamp.

Parameters:

ts – a timestamp taken from ‘TSCLIENT_Key.cap’ or ‘.acq’

Returns:

a Unix timestamp, equal to ‘ts’ rounded down to seconds

int64_t TSCLIENT_timestampFromUnix(time_t ts)

Converts a Unix timestamp to a cap/acq timestamp.

Parameters:

ts – a Unix timestamp

Returns:

a timestamp for use in ‘TSCLIENT_Key.cap’ or ‘.acq’

int64_t TSCLIENT_timestampNow(void)

Makes a cap/acq timestamp representing the current time.

Equivalent to:

#include <stddef.h> #include <time.h> return TSCLIENT_TimeStampFromUnix(time(NULL));

Returns:

a timestamp for use in ‘TSCLIENT_Key.cap’ or ‘acq’

void TSCLIENT_Channel_setMemoryLimit(TSCLIENT_Channel *this, size_t size)

Set the Channel’s size limit when getting records.

This function affects the behavior of TSCLIENT_Channel_get and TSCLIENT_Channel_getStream: it sets the upper size limit for data received from TStorage. This includes not only the records in their serialized form, but also other metadata sent by TStorage. In simple terms, this sets the maximum buffer size for received data.

In case of TSCLIENT_Channel_get this means maximum amount of data retrieved from TStorage during the whole function call. In case of TSCLIENT_Channel_getStream this means maximum amount of data retrieved in one “chunk”: getStream getStream will deserialize each chunk into a RecordsSet and pass it to the callback function, before retrieving the next chunk.

If a user wants to records of size N (incl. key), they shall setMemoryLimit to a value greater than N by a certain amount (1 KB is enough), otherwise TSCLIENT_Channel_get and TSCLIENT_Channel_getStream will fail when retrieving that record.

If TSCLIENT_Channel_get receives more data than ‘size’, or if TSCLIENT_Channel_getStream receives a record of size greater than ‘size’, the functions will produce a RecordsSet containing records received up to that point, and will fail with TSCLIENT_RES_MEMORYLIMIT.

Parameters:
  • this – the Channel being configured

  • size – maximum size of received data in bytes

dir tstorage_clients/c
dir tstorage_clients/c/include
dir tstorage_clients/c/include/tstorage-client
dir tstorage_clients