Programming in C
Sample Program
In order to help understand a lot of the description below, you can download the wordfreq.c sample program, with a reference input file and corresponding reference output file and compile it. Here are some copy pastable instructions. The diff exit code should be zero, as the files should be identical. For the following example, you will need to use the bash shell, have git, diff and a C compiler (gcc here) installed.
mkdir test
cd test
git clone https://gitlab.com/YottaDB/DB/YDBTest
source /usr/local/etc/ydb_env_set
gcc `pkg-config --cflags yottadb` wordfreq.c `pkg-config --libs yottadb` -o wordfreq
./wordfreq < YDBTest/simpleapi/outref/wordfreq_input.txt > wordfreq.out
diff wordfreq.out YDBTest/simpleapi/outref/wordfreq_output.txt
echo $?
Symbolic Constants
The libyottadb.h
file defines several symbolic constants, which are one of the following types:
Function Return Codes, which in turn are one of:
Normal Return Codes
Error Return Codes
Limits
Other
Symbolic constants all fit within the range of a C int
.
Function Return Codes
Return codes from calls to YottaDB are usually of type int
and occasionally other types. Normal return codes are non-negative (greater than or equal to zero); error return codes are negative.
Normal Return Codes
Symbolic constants for normal return codes have YDB_
prefixes other than YDB_ERR_
.
YDB_LOCK_TIMEOUT
This return code from lock acquisition functions indicates that the specified timeout was reached without the requested locks being acquired.
YDB_OK
This the standard return code of all functions following successful execution.
YDB_TP_RESTART
Return code to YottaDB from an application function that implements a transaction to indicate that it wishes YottaDB to restart the transaction, or by a YottaDB function invoked within a transaction to its caller that the database engine has detected that it will be unable to commit the transaction and will need to restart. Application code designed to be executed within a transaction should be written to recognize this return code and in turn perform any cleanup required and return to the YottaDB ydb_tp_s() / ydb_tp_st() invocation from which it was called. See Transaction Processing for a discussion of restarts.
YDB_TP_ROLLBACK
Return code to YottaDB from an application function that implements a transaction, and in turn returned to the caller indicating that the transaction was not committed.
Error Return Codes
Symbolic constants for error codes returned by calls to YottaDB are prefixed with YDB_ERR_
and are all less than zero. The symbolic constants below are not a complete list of all error messages that YottaDB functions can return — error return codes can indicate system errors and database errors, not just application errors. A process that receives a negative return code, including one not listed here, can call ydb_get_s() / ydb_get_st() to get the value of $zstatus.
Error messages can be raised by the YottaDB runtime system or by the underlying operating system.
A full set of YottaDB error messages and numbers is in the YottaDB Messages and Recovery Procedures Manual.
Linux error messages are described in Linux documentation, e.g. errno.
Remember that the error codes returned by YottaDB functions are the negated numeric values of the error codes above.
YDB_ERR_CALLINAFTERXIT
A YottaDB function was called after ydb_exit()
was called.
YDB_ERR_FATALERROR1
A fatal error occurred. The process is generating a core dump and terminating. As a process cannot receive a fatal error code, this error appears in the syslog.
YDB_ERR_FATALERROR2
A fatal error occurred. The process is terminating without generating a core dump. As a process cannot receive a fatal error code, this error appears in the syslog.
YDB_ERR_GVUNDEF
No value exists at a requested global variable node.
YDB_ERR_INVNAMECOUNT
A namecount
parameter has an invalid value.
YDB_ERR_INSUFFSUBS
A call to ydb_node_next_s() / ydb_node_next_st() or ydb_node_previous_s() / ydb_node_previous_st() did not provide enough parameters for the return values. Note that as the number of parameters is a count, when array subscripts start at 0, an array subscript of n corresponds to n+1 parameters.
YDB_ERR_INVSTRLEN
A buffer provided by the caller is not long enough for a string to be returned, or the length of a string passed as a parameter exceeds YDB_MAX_STR
. In the event the return code is YDB_ERR_INVSTRLEN
and if *xyz
is a ydb_buffer_t
structure whose xyz->len_alloc
indicates insufficient space, then xyz->len_used
is set to the size required of a sufficiently large buffer. In this case the len_used
field of a ydb_buffer_t
structure is greater than the len_alloc
field, and the caller is responsible for correcting the xyz->len_used
field.
YDB_ERR_INVSVN
A special variable name provided by the caller is invalid.
YDB_ERR_INVVARNAME
A variable name provided by the caller is invalid.
YDB_ERR_KEY2BIG
The length of a global variable name and subscripts exceeds the limit configured for the database region to which it is mapped.
YDB_ERR_LVUNDEF
No value exists at a requested local variable node.
YDB_ERR_MAXNRSUBSCRIPTS
The number of subscripts specified in the call exceeds YDB_MAX_SUBS
.
YDB_ERR_MINNRSUBSCRIPTS
The number of subscripts cannot be negative.
YDB_ERR_NAMECOUNT2HI
The number of variable names specified to ydb_delete_excl_s() / ydb_delete_excl_st() or ydb_tp_s() / ydb_tp_st() exceeded the YDB_MAX_NAMES
.
YDB_ERR_NODEEND
In the event a call to ydb_node_next_s() / ydb_node_next_st(), ydb_node_previous_s() / ydb_node_previous_st(), ydb_subscript_next_s() / ydb_subscript_next_st(), or ydb_subscript_previous_s() / ydb_subscript_previous_st() wish to report that there no further nodes/subscripts in their traversals, they return this value.
YDB_NOTOK
ydb_file_name_to_id() / ydb_file_name_to_id_t() was called with a NULL pointer to a filename.
YDB_ERR_NUMOFLOW
A ydb_incr_s() / ydb_incr_st() operation resulted in a numeric overflow.
YDB_ERR_PARAMINVALID
A parameter provided by the caller is invalid.
YDB_ERR_SIMPLEAPINEST
An attempt was made to nest Simple API calls, which cannot be nested.
YDB_ERR_SUBSARRAYNULL
The subs_used
parameter of a function is greater than zero, but the subsarray
parameter is a NULL pointer.
YDB_ERR_SVNOSET
The application inappropriately attempted to modify the value of an intrinsic special variable such as an attempt to modify $trestart
using ydb_set_s() / ydb_set_st().
YDB_ERR_TIME2LONG
This return code indicates that a value greater than YDB_MAX_TIME_NSEC
was specified for a time duration.
YDB_ERR_TPTIMEOUT
This return code from ydb_tp_s() / ydb_tp_st() indicates that the transaction took too long to commit.
YDB_ERR_UNIMPLOP
An operation that is not supported for an intrinsic special variable – of the Simple API functions only ydb_get_s() / ydb_get_st() and ydb_set_s() / ydb_set_st() are supported – was attempted on an intrinsic special variable.
YDB_ERR_VARNAME2LONG
A variable name length exceeds YottaDB's limit.
Limits
Symbolic constants for limits are prefixed with YDB_MAX_
or YDB_MIN_
.
YDB_MAX_IDENT
The maximum space in bytes required to store a complete variable name, not including the preceding caret for a global variable. Therefore, when allocating space for a string to hold a global variable name, add 1 for the caret.
YDB_MAX_M_LINE_LEN
The maximum M source code line length, in bytes.
YDB_MAX_NAMES
The maximum number of variable names that can be passed to ydb_delete_excl_s() / ydb_delete_excl_st() or ydb_tp_s() / ydb_tp_st().
YDB_MAX_STR
The maximum length of a string (or blob) in bytes. A caller to ydb_get_s() / ydb_get_st() whose *ret_value
parameter provides a buffer of YDB_MAX_STR
will never get a YDB_ERR_INVSTRLEN
error.
YDB_MAX_SUBS
The maximum number of subscripts for a local or global variable.
YDB_MAX_TIME_NSEC
The maximum value in nanoseconds that an application can instruct libyottab to wait, e.g., until the process is able to acquire locks it needs before timing out, or for ydb_hiber_start(). Note that even if timer resolution is in nanoseconds, the accuracy is always determined by the underlying hardware and operating system, as well as factors such as system load.
YDB_MAX_YDBERR
The absolute (positive) value of any YottaDB function error return code. If the absolute value of an error return code is greater than YDB_MAX_YDBERR
, then it is an error code from elsewhere, e.g. errno. Also, see YDB_IS_YDBERR()
.
YDB_MIN_YDBERR
The absolute (positive) value of any YottaDB function error return code. If the absolute value of an error return code is less than YDB_MIN_YDBERR
, then it is an error code from elsewhere, e.g. errno. Also, see YDB_IS_YDBERR()
.
Severity
Symbolic constants for the severities of message numbers in return codes and $zstatus
are prefixed with YDB_SEVERITY_
.
YDB_SEVERITY_ERROR
The number corresponds to an error from which the process can recover.
YDB_SEVERITY_FATAL
The number corresponds to an error that terminated the process.
YDB_SEVERITY_INFORMATIONAL
The number corresponds to an informational message.
YDB_SEVERITY_SUCCESS
The number corresponds to the successful completion of a requested operation.
YDB_SEVERITY_WARNING
The number corresponds to a warning, i.e., it indicates a possible problem.
Other
Other symbolic constants have a prefix of YDB_
.
YDB_DEL_NODE and YDB_DEL_TREE
As values of the deltype
parameter, these values indicate to ydb_delete_s() / ydb_delete_st() whether to delete an entire subtree or just the node at the root, leaving the subtree intact.
YDB_NOTTP
As a value of the tptoken
parameter of the Simple API multi-threaded functions – those ending in _st()
, indicates that the caller is not within a transaction.
Data Structures & Type Definitions
ydb_buffer_t
ydb_buffer_t
is a descriptor for a string [1] value, and consists of the following fields:
buf_addr
— pointer to anunsigned char
, the starting address of a string.len_alloc
andlen_used
— fields of typeunsigned int
where:len_alloc
is the number of bytes allocated to store the string,len_used
is the length in bytes of the currently stored string, andlen_alloc
≥len_used
except when a YDB_ERR_INVSTRLEN occurs.
ydb_string_t
ydb_string_t
is a descriptor for a string provided for compatibility with existing code, and consists of the following fields:
address
— pointer to anunsigned char
, the starting address of a string.length
— the length of the string starting at theaddress
field.
ydb_tpfnptr_t
ydb_tpfnptr_t
is a pointer to a function which returns an integer, with one parameter, a pointer to an arbitrary structure:
typedef int (*ydb_tpfnptr_t)(void *tpfnparm);
ydb_tp2fnptr_t
ydb_tp2fnptr_t
is a pointer to a function which returns an integer, with three parameters, a tptoken
, a *errstr
pointer, and a pointer to an arbitrary structure:
typedef int (*ydb_tp2fnptr_t)(uint64_t tptoken, ydb_buffer_t *errstr, void *tpfnparm)
Functions to implement transaction processing logic for single-threaded applications are referenced by ydb_tpfnptr_t
and functions to implement transaction processing logic for multi-threaded applications are referenced by ydb_tp2fnptr_t
.
Macros
YDB_ASSERT(x)
Conditionally include this macro in code for debugging and testing purposes. If x
is non-zero, it prints an error message on stderr
and generates a core file by calling ydb_fork_n_core().
YDB_BUFFER_IS_SAME(buffer1, buffer2)
Use this macro to test whether the memory locations (strings) pointed to by two ydb_buffer_t
structures have the same content, returning FALSE
(0) if they differ and a non-zero value if the contents are identical.
YDB_COPY_BUFFER_TO_BUFFER(source, destination, done)
Use this macro to copy the memory locations (strings) pointed to by source
to the memory locations pointed to by destination
and set:
destination->len_used
tosource->len_used
; anddone
toTRUE
ifdestination->len_alloc
≥source->len_used
and the underlyingmemcpy()
completed successfully, andFALSE
otherwise.
YDB_COPY_LITERAL_TO_BUFFER(literal, buffer, done)
Use this macro to copy a literal string to previously allocated memory referenced by a ydb_buffer_t
structure (for example, to set an initial subscript to sequence through nodes). It sets:
buffer->len_used
to the size of the literal; anddone
toTRUE
ifbuffer->len_alloc
≥ the size of the literal excluding its terminating null byte and the underlyingmemcpy()
completed successfully, andFALSE
otherwise.
YDB_COPY_STRING_TO_BUFFER(string, buffer, done)
Use this macro to copy a null-terminated string to previously allocated memory referenced by a ydb_buffer_t
structure. This macro requires the code to also #include <string.h>
. It sets:
buffer->len_used
to the size of the copied string; anddone
toTRUE
ifbuffer->len_alloc
≥ the size of the string to be copied and the underlyingmemcpy()
completed successfully, andFALSE
otherwise.
YDB_FREE_BUFFER(BUFFERP)
Use this macro to free the buffer malloced using YDB_MALLOC_BUFFER
.
free() call is used on
BUFFERP->buf_addr
.
YDB_LITERAL_TO_BUFFER(literal, buffer)
Use this macro to set a ydb_buffer_t
structure to refer to a literal (such as a variable name). With a string literal, and a pointer to a ydb_buffer_t
structure, set:
buffer->buf_addr
to the address ofliteral
; andbuffer->len_used
andbuffer->len_alloc
to the length ofliteral
excluding the terminating null byte.
YDB_IS_YDBERR(msgnum)
Returns TRUE if the absolute value of msgnum
lies between YDB_MIN_YDBERR
and YDB_MAX_YDBERR
.
YDB_MALLOC_BUFFER(BUFFERP,LEN)
Use this macro to to allocate a buffer using malloc()
of length LEN and assign it to an already allocated ydb_buffer_t
structure.
BUFFERP->buf_addr
is set to the malloced buffer.BUFFERP->len_alloc
is set to the malloced length.BUFFERP->len_used
is set to 0.
YDB_SEVERITY(msgnum, severity)
The error return code from a function indicates both the nature of an error as well as its severity. For message msgnum
, the variable severity
is set to one of the YDB_SEVERITY_*
symbolic constants. YDB_SEVERITY()
is only meaningful for error return codes and not other numbers. Use YDB_IS_YDBERR()
to determine whether a return code is a YottaDB error return code.
HASH128_STATE_INIT(hash128_state_t *state, ydb_uint8 addl_seed)
Use this macro to initialize a variable in order to compute a 128-bit MurMurHash using ydb_mmrhash_128_ingest() / ydb_mmrhash_128_result().
Example:
// Initialize state struct
HASH128_STATE_INIT(hash_state, 0);
YDB_STRING_TO_BUFFER
Sets a ydb_buffer_t
structure
to point to an existing null-terminated C string, i.e.,
#define YDB_STRING_TO_BUFFER(STRING, BUFFERP) \
{ \
(BUFFERP)->buf_addr = STRING; \
(BUFFERP)->len_used = (BUFFERP)->len_alloc = strlen(STRING); \
}
YottaDB functions are divided into:
Simple API — a core set of functions that provides easy-to-use access to the major features of YottaDB.
Comprehensive API — a more elaborate set of functions for specialized or optimized access to additional functionality within
libyottadb.so
that YottaDB itself uses. The Comprehensive API is a project for the future.Utility Functions — Functions useful to a C application using YottaDB.
Simple API
As all subscripts and node data passed to YottaDB using the Simple API are strings, use the sprintf()
and atoi()/strtoul()
family of functions to convert between numeric values and strings which are Canonical Numbers.
Note that all parameters passed to Simple API functions must be properly allocated and initialized where needed prior to the function call, including return values. This also specifically includes all members of ydb_buffer_t
structs for parameters containing input values, but only buf_addr
and len_alloc
members for return values. To facilitate initialization of the ydb_buffer_t
members, you may find the YDB_MALLOC_BUFFER
macro helpful for heap allocations.
To allow the YottaDB Simple API functions to handle a variable tree whose nodes have varying numbers of subscripts, the actual number of subscripts is itself passed as a parameter. In the prototypes of functions, parameters of the form:
ydb_buffer_t *varname
refers to the name of a variable;int subs_used
andint *subs_used
refer to an actual number of subscripts; andydb_buffer_t *subsarray
refers to an array ofydb_buffer_t
structures used to pass subscripts whose actual number is defined bysubs_used
or*subs_used
parameters.
To pass an intrinsic special variable, or unsubscripted local or global variable, subs_used
should be zero and *subsarray
should be NULL.
Caveat: Specifying a subs_used
that exceeds the actual number of parameters passed in *subsarray
will almost certainly result in an unpleasant bug that is difficult to troubleshoot.
Functions specific to the YottaDB Simple API for single-threaded applications end in _s()
and those for multi-threaded applications end in _st()
, with the latter functions typically differing from their counterparts of the former type with two additional parameters, tptoken
, and errstr
. The discussion in Threads provides more detailed information.
ydb_data_s() / ydb_data_st()
int ydb_data_s(ydb_buffer_t *varname,
int subs_used,
ydb_buffer_t *subsarray,
unsigned int *ret_value);
int ydb_data_st(uint64_t tptoken,
ydb_buffer_t *errstr,
ydb_buffer_t *varname,
int subs_used,
ydb_buffer_t *subsarray,
unsigned int *ret_value);
In the location pointed to by ret_value
, ydb_data_s()
and ydb_data_st()
return the following information about the local or global variable node identified by *varname
, subs_used
and *subsarray
.
0 — There is neither a value nor a subtree, i.e., it is undefined.
1 — There is a value, but no subtree
10 — There is no value, but there is a subtree.
11 — There are both a value and a subtree.
It is an error to call ydb_data_s()
or ydb_data_st()
on an intrinsic special variable; doing so results in the YDB_ERR_UNIMPLOP
error. ydb_data_s() / ydb_data_st()
returns:
YDB_OK
; or
The error YDB_ERR_PARAMINVALID
is returned when
ret_value
is NULLlen_alloc
<len_used
or thelen_used
is non-zero andbuf_addr
is NULL in at least one subscript, insubsarray
.
Please see the Simple API introduction for details about parameter allocation.
ydb_delete_s() / ydb_delete_st()
int ydb_delete_s(ydb_buffer_t *varname,
int subs_used,
ydb_buffer_t *subsarray,
int deltype);
int ydb_delete_st(uint64_t tptoken,
ydb_buffer_t *errstr,
ydb_buffer_t *varname,
int subs_used,
ydb_buffer_t *subsarray,
int deltype);
Delete nodes in the local or global variable tree or subtree specified. A value of YDB_DEL_NODE
or YDB_DEL_TREE
for deltype
specifies whether to delete just the node at the root, leaving the (sub)tree intact, or to delete the node as well as the (sub)tree.
Intrinsic special variables cannot be deleted.
ydb_delete_s()
and ydb_delete_st()
return YDB_OK
, a YDB_ERR_UNIMPLOP
if deltype
is neither YDB_DEL_NODE
nor YDB_DEL_TREE
, YDB_ERR_PARAMINVALID
is returned when len_alloc
< len_used
or the len_used
is non-zero and buf_addr
is NULL in at least one subscript in subsarray
, or another error return code.
YDB_OK
;YDB_ERR_UNIMPLOP
ifdeltype
is neitherYDB_DEL_NODE
norYDB_DEL_TREE
; oranother error return code.
Please see the Simple API introduction for details about parameter allocation.
ydb_delete_excl_s() / ydb_delete_excl_st()
int ydb_delete_excl_s(int namecount,
ydb_buffer_t *varnames);
int ydb_delete_excl_st(uint64_t tptoken,
ydb_buffer_t *errstr,
int namecount, ydb_buffer_t *varnames);
ydb_delete_excl_s()
and ydb_delete_excl_st()
delete the trees of all local variables except those in the *varnames
array. It is an error for *varnames
to include a global or intrinsic special variable.
In the special case where namecount
is zero, ydb_delete_excl_s()
and ydb_delete_excl_st()
delete all local variables. In this case, the varnames
parameter is ignored so any value can be passed in for that parameter but we recommend that applications pass a NULL
value.
If your application mixes M and non M code, and you wish to use ydb_delete_excl_s()
to delete local variables that are aliases, formal parameters, or actual parameters passed by reference, make sure you understand what (sub)trees are being deleted. This warning does not apply to applications that do not include M code.
ydb_delete_excl_s()
and ydb_delete_excl_st()
return YDB_OK
, YDB_ERR_NAMECOUNT2HI
if more than YDB_MAX_NAMES
are specified, or another error return code. YDB_ERR_PARAMINVALID
is returned when len_alloc
< len_used
or the len_used
is non-zero and buf_addr
is NULL in at least one variable name in varnames
.
Note that specifying a larger value for namecount
than the number of variable names actually provided in *varnames
can result in a buffer overflow.
Please see the Simple API introduction for details about parameter allocation.
ydb_get_s() / ydb_get_st()
int ydb_get_s(ydb_buffer_t *varname,
int subs_used,
ydb_buffer_t *subsarray,
ydb_buffer_t *ret_value);
int ydb_get_st(uint64_t tptoken,
ydb_buffer_t *errstr,
ydb_buffer_t *varname,
int subs_used,
ydb_buffer_t *subsarray,
ydb_buffer_t *ret_value);
To the user-allocated location pointed to by ret_value->buf_addr
, ydb_get_s()
and ydb_get_st()
copy the value of the specified node or intrinsic special variable, setting ret_value->len_used
on both normal and error returns (the latter case as long as the data exists). Return values are:
YDB_OK
for a normal return;YDB_ERR_GVUNDEF
,YDB_ERR_INVSVN
, orYDB_ERR_LVUNDEF
as appropriate if no such variable or node exists;YDB_ERR_INVSTRLEN
ifret_value->len_alloc
is insufficient for the value at the node;YDB_ERR_PARAMINVALID
whenret_value
is NULL orret_value->buf_addr
is NULL and the return value has a non-zerolen_used
; orlen_alloc
<len_used
or thelen_used
is non-zero andbuf_addr
is NULL in at least one subscript insubsarray
; oranother applicable error return code.
Notes:
In the unlikely event an application wishes to know the length of the value at a node, but not access the data, it can call
ydb_get_s()
orydb_get_st()
and provide an output buffer (retvalue->len_alloc
) with a length of zero, since even in the case of aYDB_ERR_INVSTRLEN
error,retvalue->len_used
is set.Within a transaction implemented by ydb_tp_s() / ydb_tp_st() application code observes stable data at global variable nodes because YottaDB Transaction Processing ensures ACID properties, restarting the transaction if a value changes.
Outside a transaction, a global variable node can potentially be changed by another, concurrent, process between the time that a process calls ydb_data_s() / ydb_data_st() to ascertain the existence of the data and a subsequent call to ydb_get_s() / ydb_get_st() to get that data. A caller of ydb_get_s() / ydb_get_st() to access a global variable node should code in anticipation of a potential
YDB_ERR_GVUNDEF
, unless it is known from application design that this cannot happen.
Please see the Simple API introduction for details about parameter allocation.
ydb_incr_s() / ydb_incr_st()
int ydb_incr_s(ydb_buffer_t *varname,
int subs_used,
ydb_buffer_t *subsarray,
ydb_buffer_t *increment,
ydb_buffer_t *ret_value);
int ydb_incr_st(uint64_t tptoken,
ydb_buffer_t *errstr,
ydb_buffer_t *varname,
int subs_used,
ydb_buffer_t *subsarray,
ydb_buffer_t *increment,
ydb_buffer_t *ret_value);
ydb_incr_s()
and ydb_incr_st()
atomically:
convert the value in the specified node to a number if it is not one already, using a zero value if the node does not exist;
increment it by the value specified by
*increment
, converting the value to a number if it is not a canonical number, defaulting to 1 if the parameter is NULL; andstore the value as a canonical number in
*ret_value
.
Return values:
The normal return value is
YDB_OK
.If the atomic increment results in a numeric overflow, the function returns a
YDB_ERR_NUMOFLOW
error; in this case, the value in the node is untouched and that in*ret_value
is unreliable.YDB_ERR_INVSTRLEN
ifret_value->len_alloc
is insufficient for the result. As with ydb_get_s() / ydb_get_st(), in this caseret_value->len_used
is set to the required length.Other errors return the corresponding error return code.
Notes:
Intrinsic special variables cannot be atomically incremented, and an attempt to do so returns the
YDB_ERR_UNIMPLOP
error.The value of the empty string coerced to a numeric value is 0.
Please see the Simple API introduction for details about parameter allocation.
ydb_lock_s() / ydb_lock_st()
int ydb_lock_s(unsigned long long timeout_nsec,
int namecount[,
[ydb_buffer_t *varname,
int subs_used,
ydb_buffer_t *subsarray], ...]);
int ydb_lock_st(uint64_t tptoken,
ydb_buffer_t *errstr,
unsigned long long timeout_nsec,
int namecount[,
[ydb_buffer_t *varname,
int subs_used,
ydb_buffer_t *subsarray], ...]);
namecount
is the number of variable names in the call.
Release any locks held by the process, and attempt to acquire all the requested locks. Except in the case of an error, the release is unconditional. On return, the function will have acquired all requested locks or none of them. If no locks are requested (namecount
is zero), the function releases all locks and returns YDB_OK
.
timeout_nsec
specifies a time in nanoseconds that the function waits to acquire the requested locks. If timeout_nsec
is zero, the function makes exactly one attempt to acquire the locks
Return values:
If all requested locks are successfully acquired, the function returns
YDB_OK
.If it is not able to acquire all requested locks in the specified time, it acquires no locks, returning with a
YDB_LOCK_TIMEOUT
return value.If the requested
timeout_nsec
exceedsYDB_MAX_TIME_NSEC
, the function immediately returnsYDB_ERR_TIME2LONG
.YDB_ERR_PARAMINVALID
is returned whenlen_alloc
<len_used
or thelen_used
is non-zero andbuf_addr
is NULL in at least one subscript insubsarray
.In other cases, the function returns an error return code.
Please see the Simple API introduction for details about parameter allocation.
ydb_lock_decr_s() / ydb_lock_decr_st()
int ydb_lock_decr_s(ydb_buffer_t *varname,
int subs_used,
ydb_buffer_t *subsarray);
int ydb_lock_decr_st(uint64_t tptoken,
ydb_buffer_t *errstr,
ydb_buffer_t *varname,
int subs_used,
ydb_buffer_t *subsarray);
Decrements the count of the specified lock held by the process. As noted in the Concepts section, a lock whose count goes from 1 to 0 is released. A lock whose name is specified, but which the process does not hold, is ignored.
As releasing a lock cannot fail, the function returns YDB_OK
, unless there is an error such as an invalid name that results in the return of an error code such as YDB_ERR_INVVARNAME
. Errors result in an appropriate error return code. YDB_ERR_PARAMINVALID
is returned when len_alloc
< len_used
or the len_used
is non-zero and buf_addr
is NULL in at least one subscript in subsarray
.
Please see the Simple API introduction for details about parameter allocation.
ydb_lock_incr_s() / ydb_lock_incr_st()
int ydb_lock_incr_s(unsigned long long timeout_nsec,
ydb_buffer_t *varname,
int subs_used,
ydb_buffer_t *subsarray);
int ydb_lock_incr_st(uint64_t tptoken,
ydb_buffer_t *errstr,
unsigned long long timeout_nsec,
ydb_buffer_t *varname,
int subs_used,
ydb_buffer_t *subsarray);
Without releasing any locks held by the process attempt to acquire the requested lock, incrementing it if already held.
timeout_nsec
specifies a time in nanoseconds that the function waits to acquire the requested locks. If timeout_nsec
is zero, the function makes exactly one attempt to acquire the locks
Return values:
If all requested locks are successfully acquired, the function returns
YDB_OK
.If it is not able to acquire all requested locks in the specified time, it acquires no locks, returning with a
YDB_LOCK_TIMEOUT
return value.If the requested
timeout_nsec
exceedsYDB_MAX_TIME_NSEC
, the function immediately returnsYDB_ERR_TIME2LONG
.YDB_ERR_PARAMINVALID
is returned whenlen_alloc
<len_used
or thelen_used
is non-zero andbuf_addr
is NULL in at least one subscript insubsarray
.In other cases, the function returns an error return code.
Please see the Simple API introduction for details about parameter allocation.
ydb_node_next_s() / ydb_node_next_st()
int ydb_node_next_s(ydb_buffer_t *varname,
int subs_used,
ydb_buffer_t *subsarray,
int *ret_subs_used,
ydb_buffer_t *ret_subsarray);
int ydb_node_next_st(uint64_t tptoken,
ydb_buffer_t *errstr,
ydb_buffer_t *varname,
int subs_used,
ydb_buffer_t *subsarray,
int *ret_subs_used,
ydb_buffer_t *ret_subsarray);
ydb_node_next_s()
and ydb_node_next_st()
facilitate traversal of a local or global variable tree. As the number of subscripts can differ between the input node of the call and the output node reported by the call *ret_subs_used
is an input as well as an output parameter:
On input,
*ret_subs_used
specifies the number of elements allocated for returning the subscripts of the next node.On normal output (
YDB_OK
return code),*ret_subs_used
contains the actual number of subscripts returned. See below for error return codes
Return values of ydb_node_next_s()
and ydb_node_next_st()
are:
YDB_OK
with the next node, if there is one, changing*ret_subs_used
and*ret_subsarray
parameters to those of the next node. If there is no next node (i.e., the input node is the last),*ret_subs_used
on output isYDB_NODE_END
.YDB_ERR_INSUFFSUBS
if*ret_subs_used
specifies insufficient parameters to return the subscript. In this case*ret_subs_used
reports the actual number of subscripts required.YDB_ERR_INVSTRLEN
if one of theydb_buffer_t
structures pointed to by*ret_subsarray
does not have enough space for the subscript. In this case,*ret_subs_used
is the index into the*ret_subsarray
array with the error, and thelen_used
field of that structure specifies the size required.YDB_ERR_NODEEND
to indicate that that there are no more nodes. In this case,*ret_subs_used
is unchanged.YDB_ERR_PARAMINVALID
ifret_subs_used
is NULL orret_subsarray
is NULL or one of theydb_buffer_t
structures pointed to by*ret_subsarray
has a NULL buf_addr. In the last case,*ret_subs_used
is the index into the*ret_subsarray
array with the NULL buf_addr.Another error return code, in which case the application should consider the values of
*ret_subs_used
and the*ret_subsarray
to be undefined.
Please see the Simple API introduction for details about parameter allocation.
ydb_node_previous_s() / ydb_node_previous_st()
int ydb_node_previous_s(ydb_buffer_t *varname,
int subs_used,
ydb_buffer_t *subsarray,
int *ret_subs_used,
ydb_buffer_t *ret_subsarray);
int ydb_node_previous_st(uint64_t tptoken,
ydb_buffer_t *errstr,
ydb_buffer_t *varname,
int subs_used,
ydb_buffer_t *subsarray,
int *ret_subs_used,
ydb_buffer_t *ret_subsarray);
Analogous to ydb_node_next_s() / ydb_node_next_st(), ydb_node_previous_s()
and ydb_node_previous_st()
facilitate reverse traversal of a local or global variable tree, except that ydb_node_previous_s()
and ydb_node_previous_st()
search for and report the predecessor node. Unlike ydb_node_next_s() / ydb_node_next_st(), *ret_subs_used
can be zero if the previous node is the unsubscripted root.
Return values of ydb_node_previous_s()
and ydb_node_previous_st()
are:
YDB_OK
with the previous node, if there is one, changing*ret_subs_used
and*ret_subsarray
parameters to those of the previous node.YDB_ERR_INSUFFSUBS
if*ret_subs_used
specifies insufficient parameters to return the subscript. In this case*ret_subs_used
reports the actual number of subscripts required.YDB_ERR_INVSTRLEN
if one of theydb_buffer_t
structures pointed to by*ret_subsarray
does not have enough space for the subscript. In this case,*ret_subs_used
is the index into the*ret_subsarray
array with the error, and thelen_used
field of that structure specifies the size required.YDB_ERR_NODEEND
to indicate that that there are no more nodes. In this case,*ret_subs_used
is unchanged.YDB_ERR_PARAMINVALID
ifret_subs_used
is NULL orret_subsarray
is NULL or one of theydb_buffer_t
structures pointed to by*ret_subsarray
has a NULL buf_addr. In the last case,*ret_subs_used
is the index into the*ret_subsarray
array with the NULL buf_addr.Another error return code, in which case the application should consider the values of
*ret_subs_used
and the*ret_subsarray
to be undefined.
Please see the Simple API introduction for details about parameter allocation.
ydb_set_s() / ydb_set_st()
int ydb_set_s(ydb_buffer_t *varname,
int subs_used,
ydb_buffer_t *subsarray,
ydb_buffer_t *value);
int ydb_set_st(uint64_t tptoken,
ydb_buffer_t *errstr,
ydb_buffer_t *varname,
int subs_used,
ydb_buffer_t *subsarray,
ydb_buffer_t *value);
ydb_set_s()
and ydb_set_st()
copy the value->len_used
bytes at value->buf_addr
as the value of the specified node or intrinsic special variable specified. A NULL value
parameter is treated as equivalent to one that points to a ydb_buffer_t
specifying an empty string. Return values are:
YDB_OK
for a normal return;YDB_ERR_INVSVN
if no such intrinsic special variable exists;YDB_ERR_PARAMINVALID
whenlen_alloc
<len_used
or thelen_used
is non-zero andbuf_addr
is NULL in at least one subscript insubsarray
orincrement
; oranother applicable error return code.
Please see the Simple API introduction for details about parameter allocation.
ydb_str2zwr_s() / ydb_str2zwr_st()
int ydb_str2zwr_s(ydb_buffer_t *str, ydb_buffer_t *zwr);
int ydb_str2zwr_st(uint64_t tptoken,
ydb_buffer_t *errstr,
ydb_buffer_t *str, ydb_buffer_t *zwr);
In the buffer referenced by *zwr
, ydb_str2zwr_s()
and ydb_str2zwr_st()
provide the zwrite formatted version of the string pointed to by *str
, returning:
YDB_OK
;YDB_ERR_INVSTRLEN
if the*zwr
buffer is not long enough;YDB_ERR_PARAMINVALID
ifzwr
is NULL orzwr->buf_addr
is NULL and the return value has a non-zerolen_used
; oranother applicable error return code.
Please see the Simple API introduction for details about parameter allocation.
ydb_subscript_next_s() / ydb_subscript_next_st()
int ydb_subscript_next_s(ydb_buffer_t *varname,
int subs_used,
ydb_buffer_t *subsarray,
ydb_buffer_t *ret_value);
int ydb_subscript_next_st(uint64_t tptoken,
ydb_buffer_t *errstr,
ydb_buffer_t *varname,
int subs_used,
ydb_buffer_t *subsarray,
ydb_buffer_t *ret_value);
ydb_subscript_next_s()
and ydb_subscript_next_st()
provide a primitive for implementing traversal of a tree by searching for the next subscript at the level specified by subs_used
, i.e., the next subscript after the one referred to by subsarray[subs_used-1].buf_addr
. A node need not exist at the subscripted variable name provided as input to the function. If subsarray[subs_used-1].len_used
is zero, ret_value->buf_addr
points to first node at that level with a subscript that is not the empty string. ydb_subscript_next_s()
and ydb_subscript_next_st()
return:
YDB_OK
, in which caseret_value->buf_addr
points to the value of that next subscript;YDB_ERR_NODEEND
when there are no more subscripts at that level, in which case*ret_value
is unchanged;YDB_ERR_PARAMINVALID
whenret_value
is NULL;ret_value->buf_addr
is NULL and the return value has a non-zerolen_used
; orlen_alloc
<len_used
or thelen_used
is non-zero andbuf_addr
is NULL in at least one subscript insubsarray
or another error return code.
In the special case where subs_used
is zero, and the function returns YDB_OK
, ret_value->buf_addr
points to the next local or global variable name, with YDB_ERR_NODEEND
indicating an end to the traversal.
Please see the Simple API introduction for details about parameter allocation.
ydb_subscript_previous_s() / ydb_subscript_previous_st()
int ydb_subscript_previous_s(ydb_buffer_t *varname,
int subs_used,
ydb_buffer_t *subsarray,
ydb_buffer_t *ret_value);
int ydb_subscript_previous_st(uint64_t tptoken,
ydb_buffer_t *errstr,
ydb_buffer_t *varname,
int subs_used,
ydb_buffer_t *subsarray,
ydb_buffer_t *ret_value);
ydb_subscript_previous_s()
and ydb_subscript_previous_st()
provide a primitive for implementing reverse traversal of a tree by searching for the previous subscript at the level specified by subs_used
. i.e. the subscript preceding the one referred to by subsarray[subs_used-1].buf_addr
. A node need not exist at the subscripted variable name provided as input to the function. If subsarray[subs_used-1].len_used
is zero, ret_value->buf_addr
points to last node at that level with a subscript that is not the empty string. ydb_subscript_previous_s()
and ydb_subscript_previous_st()
return:
YDB_OK
, in which caseret_value->buf_addr
points to the value of that previous subscript;YDB_ERR_NODEEND
when there are no more subscripts at that level, in which case*ret_value
is unchanged;YDB_ERR_PARAMINVALID
whenret_value
is NULL;ret_value->buf_addr
is NULL and the return value has a non-zerolen_used
; orlen_alloc
<len_used
or thelen_used
is non-zero andbuf_addr
is NULL in at least one subscript insubsarray
or another error return code.
In the special case where subs_used
is zero, and the function returns YDB_OK
, ret_value->buf_addr
points to the previous local or global variable name, with YDB_ERR_NODEEND
indicating an end to the traversal.
Please see the Simple API introduction for details about parameter allocation.
ydb_tp_s() / ydb_tp_st()
int ydb_tp_s(ydb_tpfnptr_t tpfn,
void *tpfnparm,
const char *transid,
int namecount,
ydb_buffer_t *varnames);
int ydb_tp_st(uint64_t tptoken,
ydb_buffer_t *errstr,
ydb_tp2fnptr_t tpfn,
void *tpfnparm,
const char *transid,
int namecount,
ydb_buffer_t *varnames);
ydb_tp_s()
and ydp_tp_st()
call the function referenced by tpfn
passing it tpfnparm
as a parameter. Additionally, ydb_tp_st()
also generates a new tptoken
that it passes as a parameter to the function referenced by its tpfn
parameter.
As discussed under Transaction Processing, a function implementing transaction processing logic should use the intrinsic special variable $trestart
to manage any externally visible action (which YottaDB recommends against, but which may be unavoidable). The function referenced by tpfn
should return one of the following:
YDB_OK
— application logic indicates that the transaction can be committed (the YottaDB engine may still decide that a restart is required to ensure ACID transaction properties) as discussed under Transaction Processing.YDB_TP_RESTART
— application logic indicates that the transaction should restart.YDB_TP_ROLLBACK
— application logic indicates that the transaction should not be committed.YDB_ERR_PARAMINVALID
whenlen_alloc
<len_used
or thelen_used
is non-zero andbuf_addr
is NULL in at least one variable name invarnames
.An error return code returned by a YottaDB function called by the function. This case is treated the same way as if YDB_TP_ROLLBACK was returned (i.e. the application indicates that this transaction should not be committed).
transid
is a string, up to the first 8 bytes of which are recorded in the commit record of journal files for database regions participating in the transaction. If not NULL or the empty string, a case-insensitive value of "BA"
or "BATCH"
indicates that at transaction commit, YottaDB need not ensure Durability (it always ensures Atomicity, Consistency, and Isolation). Use of this value may improve latency and throughput for those applications where an alternative mechanism (such as a checkpoint) provides acceptable Durability. If a transaction that is not flagged as "BATCH"
follows one or more transactions so flagged, Durability of the later transaction ensures Durability of the the earlier "BATCH"
transaction(s).
If namecount>0
, varnames[i]
where 0≤i<namecount
specifies local variable names whose values are restored to their original values when the transaction is restarted. In the special case where namecount=1
and varnames[0]
provides the value "*"
, all local variables are restored on a restart. It is an error for a varnames
to include a global or intrinsic special variable.
A top level ydb_tp_s()
and ydb_tp_st()
can return:
YDB_OK
;YDB_TP_ROLLBACK
;YDB_ERR_TPTIMEOUT
(see Transaction Processing); oran error return code, including
YDB_ERR_NAMECOUNT2HI
.
A ydb_tp_s()
or ydb_tp_st()
call that is within another transaction (i.e., a nested transaction) can also return YDB_TP_RESTART
to its caller. [2]
An enclosing transaction can result not just from another
ydb_tp_s()
or ydb_tp_st()
higher in the stack,
but also (for single-threaded applications) from an M
tstart
command as well as a database trigger resulting
from a ydb_delete_s() / ydb_delete_st(), or ydb_set_s() / ydb_set_st().
Note
If the transaction logic receives a YDB_TP_RESTART
from a YottaDB function that it calls, it must return that value to the calling ydb_tp_s()
or ydb_tp_st()
. Failure to do so could result in application level data inconsistencies and hard to debug application code.
Please see the Simple API introduction for details about parameter allocation.
ydb_zwr2str_s() / ydb_zwr2str_st()
int ydb_zwr2str_s(ydb_buffer_t *zwr, ydb_buffer_t *str);
int ydb_zwr2str_st(uint64_t tptoken,
ydb_buffer_t *errstr,
ydb_buffer_t *zwr, ydb_buffer_t *str);
In the buffer referenced by *str
, ydb_zwr2str_s()
and ydb_zwr2str_st()
provide the string described by the zwrite formatted string pointed to by *zwr
, returning
YDB_OK
(withstr->len_used
set to zero if the zwrite formatted string has an error);YDB_ERR_INVSTRLEN
error if the*str
buffer is not long enough;YDB_ERR_PARAMINVALID
either if the*str
buffer is NULL or the return value contains a non-zerolen_used
and thestr->buf_addr
is NULL.
Please see the Simple API introduction for details about parameter allocation.
Comprehensive API
The Comprehensive API is a project for the future.
YottaDB C to M APIs
YottaDB C code has the ability to call M code. This allows you to reuse existing M mcode written previously, as well as write code in M that may be easier to write than writing the same code in C, then call it from C from your application.
The C API needs a small text file called a "call-in table" that maps typed C
parameters to the typeless M code. This call-in table can be set as an
environment variable ydb_ci
, or it can be set from the C code at
runtime.
Here's a listing of these APIs. The APIs ending with _t are for use from threaded applications. The discussion in Threads provides more detailed information. See the Programmers Guide Call-In Interface for full description as well as a compilable example.
API |
Description |
---|---|
|
The most common API to use. Call an M function by its name in a call-in table. |
|
|
|
This opens a call-in table in a specific file. |
|
This switches to a call-in table just opened above. You can have multiple call-in tables open at the same time and switch between them. |
Utility Functions
Utility functions are functions that are not core to YottaDB functionality, but which are useful to application code.
Utility functions whose names end in _t()
are for use by multi-threaded applications, and those which do not are for single-threaded applications. The discussion in Threads provides more detailed information.
ydb_hiber_start() and ydb_hiber_start_wait_any() are for use only with the SimpleAPI and not with the threaded Simple API.
ydb_exit(), ydb_fork_n_core(), and ydb_init() do not have separate variants for single- and multi-threaded applications and are suitable for both.
ydb_call_variadic_plist_func()
int ydb_call_variadic_plist_func(ydb_vplist_func cgfunc, gparam_list *cvplist)
ydb_call_variadic_plist_func
allows a language wrapper to make pseudo variadic calls to routines if the wrapper doesn't support variadic calls. Since some variadic calls are required to interface properly with YottaDB interfaces (e.g., ydb_ci()
, ydb_cip
, and ydb_lock_st()
etc.) this routine is needed. The return value is the same as the return value from the function. For example, if ydb_call_variadic_plist_func()
is used to call ydb_cip()
then a 0
return value indicates successful completion.
The ydb_vplist_func
type is defined as follows:
typedef uintptr_t (*ydb_vplist_func)();
The gparam_list
type is defined as follows:
typedef struct gparam_list_struct
{
intptr_t n; /* Count of parameter/arguments */
void *arg[MAX_GPARAM_LIST_ARGS]; /* Parameter/argument array */
} gparam_list;
The first field n
is the count of valid parameters, which can have a maximum value of MAX_GPARAM_LIST_ARGS (currently 36).
To use ydb_call_variadic_plist_func()
, the cvplist
array needs to be filled in. Each element in the array is sized to hold a pointer. The arg
array holds all of the parameters (a maximum of 36 entries at this time) to be passed to the function. If a parameter does not fit as a single element, multiple elements can be used but this must be done in accordance with the calling API of the particular system.
Note
On a 32 bit machine, each argument is only 32 bits wide. To pass a 64 bit value like a ydb_double_t
in a portable way, you should instead pass a pointer to it using ydb_double_t *
. For this reason, ydb_double_t
and ydb_int64_t
have been disabled on 32 bit machines, but you can still use ydb_double_t*
and ydb_int64_t*
Note
Third-party language wrappers that use ydb_call_variadic_plist_func() to implement call-ins need to respect the limitations of the calling convention (ABI), as not all types can be passed via ydb_call_variadic_plist_func(). For example, some ABIs pass floating point types in FPU registers rather than in a memory array, or cannot pass 64-bit types in one parameter slot, so these types cannot be passed to ydb_call_variadic_plist_func(). It is always safe to pass and return these types as pointer types like ydb_double_t*
and ydb_int64_t*
. If desired, the language wrapper can automatically translate the user's call-in table from ydb_float_t
and ydb_int64_t
types to ydb_float_t*
and ydb_int64_t*
types, as the called M code will be the same.
ydb_child_init()
YottaDB r1.22 and before required the use of a function ydb_child_init()
immediately after a fork()
to avoid database damage and other possible side-effects.
Effective YottaDB r1.24, this function is not needed. It gets automatically invoked by YottaDB as needed. Any existing usages of this function in an application can be safely removed assuming YottaDB r1.24 or later is in use.
ydb_eintr_handler() / ydb_eintr_handler_t()
int ydb_eintr_handler(void)
int ydb_eintr_handler_t(uint64_t tptoken, ydb_buffer_t *errstr)
ydb_eintr_handler()
needs to be invoked by a SimpleAPI application whenever a system call that it invokes (e.g. accept()
, select()
) returns an error with errno set to EINTR
(this usually means a signal interrupted the system call). This ensures that YottaDB takes appropriate action corresponding to the interrupting signal in a timely fashion. For example, if the signal SIGTERM
was sent externally to this SimpleAPI application process, the appropriate action is to terminate the process as soon as a safe/logical point is reached.
Note that not invoking ydb_eintr_handler()
as part of an EINTR
situation can cause the SimpleAPI application to behave unexpectedly. For example, in the SIGTERM
case, the process would not terminate how ever many signals are sent.
ydb_eintr_handler_t()
is very similar to ydb_eintr_handler()
except that it needs to be invoked by a SimpleThreadAPI application.
ydb_exit()
int ydb_exit(void)
When a caller no longer wishes to use YottaDB, a call to ydb_exit()
cleans up the process connection/access to all databases and cleans up its data structures. Therafter, any attempt to call a YottaDB function produces a YDB_ERR_CALLINAFTERXIT
error.
Note that:
a typical application should not need to call
ydb_exit()
, but should instead just terminate with a call toexit()
which will perform any cleanup needed by YottaDB; andcalling
ydb_exit()
before calling any other YottaDB function does nothing, i.e., it is a no-op.
ydb_exit()
returns YDB_OK
on success, and a positive non-zero value on error. If ydb_exit()
has already been called, later calls to ydb_exit()
in the same process return YDB_OK
with no further action, since all resources related to YottaDB are already cleaned up by the first call.
If an external call attempts to call ydb_exit()
, a YDB_ERR_INVYDBEXIT
error is returned, since YottaDB is required to remain operational even after the external call returns. For information about this error, see INVYDBEXIT in the Messages and Recovery Procedures guide.
ydb_exit()
can be used with both the Simple API and threaded Simple API.
ydb_file_id_free() / ydb_file_id_free_t()
int ydb_file_id_free(ydb_fileid_ptr_t fileid)
int ydb_file_id_free_t(uint64_t tptoken,
ydb_buffer_t *errstr, ydb_fileid_ptr_t fileid)
Releases the memory used by a fileid
structure previously generated by ydb_file_name_to_id() / ydb_file_name_to_id_t(). Calling the function twice for the same pointer, unless it has been returned a second time by a different ydb_file_name_to_id() / ydb_file_name_to_id_t() is an application error with undefined consequences.
A PARAMINVALID
error is issued if the input fileid
parameter is NULL.
Please see the Simple API introduction for details about parameter allocation.
ydb_file_is_identical() / ydb_file_is_identical_t()
int ydb_file_is_identical(ydb_fileid_ptr_t fileid1,
ydb_fileid_ptr_t fileid2)
int ydb_file_is_identical_t(uint64_t tptoken,
ydb_buffer_t *errstr,
ydb_fileid_ptr_t fileid1,
ydb_fileid_ptr_t fileid2)
Given two pointers to fileid
structures (see ydb_file_name_to_id() / ydb_file_name_to_id_t()), ydb_file_is_identical()
and ydb_file_is_identical_t()
return YDB_OK if the two fileid
structures are the same file and YDB_NOTOK otherwise.
A PARAMINVALID
error is issued if the input fileid
parameter is NULL.
Please see the Simple API introduction for details about parameter allocation.
ydb_file_name_to_id() / ydb_file_name_to_id_t()
int ydb_file_name_to_id(ydb_string_t *filename,
ydb_fileid_ptr_t *fileid)
int ydb_file_name_to_id_t(uint64_t tptoken,
ydb_buffer_t *errstr,
ydb_string_t *filename,
ydb_fileid_ptr_t *fileid)
As a file is potentially reachable through different paths, and application code may need to check whether two paths do indeed lead to the same file, YottaDB provides a mechanism to do so. Provided with a path to a file, YottaDB creates an internal structure called a fileid
that uniquely identifies the file if such a structure does not already exist for that file, and provides the caller with a pointer to that structure. The layout and contents of the fileid structure are opaque to the caller, which must not modify the pointer or the structure it points to.
When the fileid
structure for a file is no longer needed, an application should call ydb_file_id_free() / ydb_file_id_free_t() to release the structure and avoid a memory leak.
ydb_file_name_to_id()
and ydb_file_name_to_id_t()
return YDB_OK
, or an error return code.
A PARAMINVALID
error is issued if the input filename
or fileid
parameter is NULL.
Please see the Simple API introduction for details about parameter allocation.
ydb_fork_n_core()
void ydb_fork_n_core(void)
A core is a snapshot of a process, to help debug application code, for example to troubleshoot an out-of-design condition. When a process executes ydb_fork_n_core()
, it forks. The child process sends itself a signal to generate a core and terminate. On termination of the child process, the parent process continues execution. Note that depending on the nature of the condition necessitating a core, an exit()
may well be the right action for the parent process. An exit()
call will drive YottaDB exit handlers to perform clean shutdown of databases and devices the process has open.
The content, location, and naming of cores is managed by the operating system – see man 5 core
for details. We recommend that you set kernel.core_uses_pid
to 1 to make it easier to identify and track cores. As cores will likely contain protected confidential information, you must ensure appropriate configuration and management of cores.
In a multi-threaded environment, only the thread that executes ydb_fork_n_core()
or ydb_fork_n_core()
survives in the child and is dumped.
ydb_fork_n_core()
can be used with both the Simple API and threaded Simple API.
ydb_free()
void ydb_free(void *ptr)
Releases memory previously allocated by ydb_malloc(). Passing ydb_free()
a pointer not previously provided to the application by ydb_malloc() can result in unpredictable behavior. The signature of ydb_free()
matches that of the POSIX free()
call.
ydb_free()
should not be used in multiple threads in multi-threaded programs. (See the Threads section for details). However, the YDB_FREE_BUFFER
macro is safe to use in multiple threads.
ydb_hiber_start()
int ydb_hiber_start(unsigned long long sleep_nsec)
The process or thread sleeps for the time in nanoseconds specified by sleep_nsec
. If a value greater than YDB_MAX_TIME_NSEC
is specified, ydb_hiber_start()
immediately returns with a YDB_ERR_TIME2LONG
error; otherwise they return YDB_OK
after the elapsed time.
ydb_hiber_start()
should not be used in multiple threads in multi-threaded programs. (See the Threads section for details).
ydb_hiber_start_wait_any()
int ydb_hiber_start_wait_any(unsigned long long sleep_nsec)
The process or thread sleeps for the time in nanoseconds specified by sleep_nsec
or until it receives a signal. If a value greater than YDB_MAX_TIME_NSEC
is specified, ydb_hiber_start_wait_any()
immediately returns with a YDB_ERR_TIME2LONG
error; otherwise they return YDB_OK
after the elapsed time or when the wait is terminated by a signal.
ydb_hiber_start_wait_any()
should not be used in multiple threads in multi-threaded programs. (See the Threads section for details).
ydb_init()
int ydb_init(void)
ydb_init()
initializes the YottaDB runtime environment. As YottaDB automatically initializes the runtime on the first call to its API or first M code invocation, there is usually no need to explicitly call ydb_init()
. The exception is when an application wishes to set its own signal handlers (see Signals): ydb_init()
sets signal handlers, and in case an application wishes to set its own signal handlers for signals not used by YottaDB, it can call ydb_init()
before setting its signal handlers.
ydb_init()
returns YDB_OK
on success, and a positive non-zero value otherwise. On failure, the error message text corresponding to the non-zero return value can be obtained by immediately calling ydb_zstatus()
.
If ydb_init()
has already been called, later calls to ydb_init()
in the same process return YDB_OK
with no further action, since the YottaDB runtime has already been initialized.
ydb_init()
can be used with both the Simple API and threaded Simple API.
ydb_malloc()
void *ydb_malloc(size_t size)
With a signature matching that of the POSIX malloc()
call, ydb_malloc()
returns an address to a block of memory of the requested size, or NULL if it is unable to satisfy the request. ydb_malloc()
uses a buddy system, and provides debugging functionality under the control of the environment variable ydb_dbglvl
whose values are a mask as described in gtmdbglvl.h.
ydb_malloc()
should not be used in multiple threads in multi-threaded programs. (See the Threads section for details). However, the YDB_MALLOC_BUFFER
macro is safe to use in multiple threads.
ydb_message() / ydb_message_t()
int ydb_message(int errnum, ydb_buffer_t *msg_buff)
int ydb_message_t(uint64_t tptoken, ydb_buffer_t *errstr,
int errnum, ydb_buffer_t *msg_buff)
The functions return the error message text template for the error number specified by errnum
.
If
errnum
does not correspond to an error that YottaDB recognizes, the return the errorYDB_ERR_UNKNOWNSYSERR
, leaving the structures referenced bymsg_buff
unaltered.Otherwise, if the length of the text exceeds
msg_buff->len_alloc
they return the errorYDB_ERR_INVSTRLEN
. In this casemsg_buff->len_used
is greater thanmsg_buff->len_alloc
.Otherwise, if
msg_buff->buf_addr
is NULL, they return the errorYDB_ERR_PARAMINVALID
.Otherwise, the copy the text to the buffer specified by
msg_buff->buf_addr
, setmsg_buff->len_used
to its length, and returnYDB_OK
.
Please see the Simple API introduction for details about parameter allocation.
ydb_mmrhash_32()
void ydb_mmrhash_32(const void *key, int len, uint4 seed, uint4 *out4);
This function returns in *out4
the 32-bit (4-byte) MurmurHash of len
bytes at *key
.
Please see the Simple API introduction for details about parameter allocation.
ydb_mmrhash_128()
void ydb_mmrhash_128(const void *key, int len, uint4 seed, ydb_uint16 *out);
This function returns in *out
the 128-bit (16-byte) MurmurHash of len
bytes at *key
.
Please see the Simple API introduction for details about parameter allocation.
ydb_mmrhash_128_ingest() / ydb_mmrhash_128_result()
void ydb_mmrhash_128_ingest(hash128_state_t *state, const void *key, int len);
void ydb_mmrhash_128_result(hash128_state_t *state, uint4 addl_seed, ydb_uint16 *out);
These functions enable users to get a MurmurHash through a series of incremental operations.
The sequence is to first initialize the "state" variable using the HASH128_STATE_INIT(hash128_state_t *state, ydb_uint8 addl_seed) macro, then call ydb_mmrhash_128_ingest()
one or more times and finally call ydb_mmrhash_128_result()
to obtain the final hash value. "key" points to the input character array (of length "len") for the hash. "addl_seed" can either be the last four bytes of the input, or at the application's discretion, an additional seed or salt. An example is to set it to the sum of the "len" values passed in across all calls to ydb_mmrhash_128_ingest
before ydb_mmrhash_128_result
is called. "out" points to the structure holding the 16-byte hash result.
Example:
// Initialize state struct
HASH128_STATE_INIT(hash_state, 0);
// Create keys/strings to ingest
char *key1 = "ifembu8r308j243h5g3h84t7yf23h0h";
char *key2 = "ougoh2408rh2fhe08yh2ti8rhhrguo2r3huocdiWEN23";
// Add keys to hash
ydb_mmrhash_128_ingest(&hash_state, (void*)key1, strlen(key1));
ydb_mmrhash_128_ingest(&hash_state, (void*)key2, strlen(key2));
// Produce result
ydb_mmrhash_128_result(hash_state, 0, &hash);
Please see the Simple API introduction for details about parameter allocation.
ydb_mmrhash_128_hex()
void ydb_mmrhash_128_hex(const ydb_uint16 *hash, unsigned char *out);
This function returns a hex formatted representation of a 16-byte hash value. As the function does no checking, if *out
is not at least 32 bytes, a buffer overflow can occur, potentially with unpleasant consequences such as abnormal process termination with a SIG-11, or worse.
Example:
char out[16];
ydb_mmrhash_128_hex(&hash, out);
Please see the Simple API introduction for details about parameter allocation.
ydb_mmrhash_128_bytes()
void ydb_mmrhash_128_bytes(const ydb_uint16 *hash, unsigned char *out);
This function converts the 16-byte hash stored in a "ydb_uint16" structure (2 8-byte integers) into a byte array "out" of 16 characters. It is also internally used by ydb_mmrhash_128_hex().
Example:
char out[16];
ydb_mmrhash_128_bytes(&hash, out);
Please see the Simple API introduction for details about parameter allocation.
ydb_stdout_stderr_adjust() / ydb_stdout_stderr_adjust_t()
int ydb_stdout_stderr_adjust(void)
int ydb_stdout_stderr_adjust_t(uint64 tptoken,
ydb_buffer_t *errstr)
The functions check whether stdout (file descriptor 1) and stderr (file descriptor 2) are the same file, and if so, route stderr writes to stdout instead. This ensures that output appears in the order in which it was written; otherwise owing to IO buffering, output can appear in an order different from that in which it was written. Application code which mixes C and M code, and which explicitly redirects stdout or stderr (e.g., using dup2()
), should call one of these functions as soon as possible after the redirection. ydb_stdout_stderr_adjust()
and ydb_stdout_stderr_adjust_t()
return YDB_OK
.
Please see the Simple API introduction for details about parameter allocation.
ydb_thread_is_main()
int ydb_thread_is_main(void)
The functions return YDB_OK
if the thread is the main thread of the process, and another value if the thread is not. YottaDB recommends against application code that requires use of these functions, which exist only to provide backward compatibility to a specific application code base (see discussion under Threads).
ydb_timer_cancel() / ydb_timer_cancel_t()
void ydb_timer_cancel(intptr_t timer_id)
void ydb_timer_cancel_t(uint64_t tptoken,
ydb_buffer_t *errstr, intptr_t timer_id)
Cancel a timer identified by timer_id
and previously started with ydb_timer_start() / ydb_timer_start_t().
Please see the Simple API introduction for details about parameter allocation.
ydb_timer_start() / ydb_timer_start_t()
typedef void (*ydb_funcptr_retvoid_t)(intptr_t timer_id,
unsigned int handler_data_len,
char *handler_data);
int ydb_timer_start(intptr_t timer_id,
unsigned long long limit_nsec,
ydb_funcptr_retvoid_t handler,
unsigned int handler_data_len,
char *handler_data);
int ydb_timer_start_t(uint64_t tptoken,
ydb_buffer_t *errstr,
intptr_t timer_id,
unsigned long long limit_nsec,
ydb_funcptr_retvoid_t handler,
unsigned int handler_data_len,
char *handler_data);
Start a timer. Unless canceled, when the timer expires, ydb_timer_start()
and ydb_timer_start_t()
invoke a handler function, providing that function with input data.
timer_id
is an identifier for the the timer. It is the responsibility of application code to ensure that timer_id
is different from those of any other active / pending timers.
limit_nsec
is the minimum number of nanoseconds before the timer expires and invokes the handler function. Owing to overhead and system load, the actual time will almost always be greater than this value.
handler
is a pointer to the function to be called when the timer expires.
handler_data
is a pointer to the data to be passed to handler
and handler_data_len
is the length of the data at *handler_data
. Note that the data it points to must be on the heap rather than on the stack, as the stack frame may no longer be valid when the timer expires.
If the requested timeout_nsec
exceeds YDB_MAX_TIME_NSEC
, the functions return YDB_ERR_TIME2LONG
; otherwise they return YDB_OK
.
Please see the Simple API introduction for details about parameter allocation.
Calling M Routines
M routines can be called from C with the following functions which are described in the M Programmers Guide:
Historically, the predecessors of the functions to call M routines returned positive return codes. In order to maintain backward compatibility, values returned by the above are positive values, whereas YottaDB Error Return Codes are negative. For example, to return an invalid string length (YDB_ERR_INVSTRLEN), the ydb_ci*()
functions return -YDB_ERR_INVSTRLEN
, which is a positve value because YDB_ERR_STRLEN
is a negative value.
Effective release r1.30. ydb_zstatus()
returns an int
.