
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.
While the most common use of YDB_TP_TROLLBACK is to terminate transactions in case of errors, it is useful for testing and "what-if" scenarios, since it can be used to exercise application code that updates global variables. The global variable updates are visible to code within the process, but not to other processes. This is accomplished by invoking or driving application code from within a transaction initiated by the code driving the test or evaluating the "what-if" scenario. Once the test or "what-if" scenario is complete, the outer driver code returns with a YDB_TP_ROLLBACK, leaving the database unmodified by the code.
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_allocandlen_used- fields of typeunsigned intwhere:len_allocis the number of bytes allocated to store the string,len_usedis the length in bytes of the currently stored string, andlen_alloc≥len_usedexcept 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 theaddressfield.
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_usedtosource->len_used; anddonetoTRUEifdestination->len_alloc≥source->len_usedand the underlyingmemcpy()completed successfully, andFALSEotherwise.
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_usedto the size of the literal; anddonetoTRUEifbuffer->len_alloc≥ the size of the literal excluding its terminating null byte and the underlyingmemcpy()completed successfully, andFALSEotherwise.
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_usedto the size of the copied string; anddonetoTRUEifbuffer->len_alloc≥ the size of the string to be copied and the underlyingmemcpy()completed successfully, andFALSEotherwise.
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_addrto the address ofliteral; andbuffer->len_usedandbuffer->len_allocto the length ofliteralexcluding 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_addris set to the malloced buffer.BUFFERP->len_allocis set to the malloced length.BUFFERP->len_usedis 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.sothat 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 *varnamerefers to the name of a variable;int subs_usedandint *subs_usedrefer to an actual number of subscripts; andydb_buffer_t *subsarrayrefers to an array ofydb_buffer_tstructures used to pass subscripts whose actual number is defined bysubs_usedor*subs_usedparameters.
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_valueis NULLlen_alloc<len_usedor thelen_usedis non-zero andbuf_addris 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_UNIMPLOPifdeltypeis neitherYDB_DEL_NODEnorYDB_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_OKfor a normal return;YDB_ERR_GVUNDEF,YDB_ERR_INVSVN, orYDB_ERR_LVUNDEFas appropriate if no such variable or node exists;YDB_ERR_INVSTRLENifret_value->len_allocis insufficient for the value at the node;YDB_ERR_PARAMINVALIDwhenret_valueis NULL orret_value->buf_addris NULL and the return value has a non-zerolen_used; orlen_alloc<len_usedor thelen_usedis non-zero andbuf_addris 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_INVSTRLENerror,retvalue->len_usedis 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_NUMOFLOWerror; in this case, the value in the node is untouched and that in*ret_valueis unreliable.YDB_ERR_INVSTRLENifret_value->len_allocis insufficient for the result. As with ydb_get_s() / ydb_get_st(), in this caseret_value->len_usedis 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_UNIMPLOPerror.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_TIMEOUTreturn value.If the requested
timeout_nsecexceedsYDB_MAX_TIME_NSEC, the function immediately returnsYDB_ERR_TIME2LONG.YDB_ERR_PARAMINVALIDis returned whenlen_alloc<len_usedor thelen_usedis non-zero andbuf_addris 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_TIMEOUTreturn value.If the requested
timeout_nsecexceedsYDB_MAX_TIME_NSEC, the function immediately returnsYDB_ERR_TIME2LONG.YDB_ERR_PARAMINVALIDis returned whenlen_alloc<len_usedor thelen_usedis non-zero andbuf_addris 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_usedspecifies the number of elements allocated for returning the subscripts of the next node.On normal output (
YDB_OKreturn code),*ret_subs_usedcontains 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_OKwith the next node, if there is one, changing*ret_subs_usedand*ret_subsarrayparameters to those of the next node.YDB_ERR_INSUFFSUBSif*ret_subs_usedspecifies insufficient parameters to return the subscript. In this case*ret_subs_usedreports the actual number of subscripts required.YDB_ERR_INVSTRLENif one of theydb_buffer_tstructures pointed to by*ret_subsarraydoes not have enough space for the subscript. In this case,*ret_subs_usedis the index into the*ret_subsarrayarray with the error, and thelen_usedfield of that structure specifies the size required.YDB_ERR_NODEENDto indicate that that there are no more nodes. In this case,*ret_subs_usedis unchanged.YDB_ERR_PARAMINVALIDifret_subs_usedis NULL orret_subsarrayis NULL or one of theydb_buffer_tstructures pointed to by*ret_subsarrayhas a NULL buf_addr. In the last case,*ret_subs_usedis the index into the*ret_subsarrayarray with the NULL buf_addr.Another error return code, in which case the application should consider the values of
*ret_subs_usedand the*ret_subsarrayto 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_OKwith the previous node, if there is one, changing*ret_subs_usedand*ret_subsarrayparameters to those of the previous node.YDB_ERR_INSUFFSUBSif*ret_subs_usedspecifies insufficient parameters to return the subscript. In this case*ret_subs_usedreports the actual number of subscripts required.YDB_ERR_INVSTRLENif one of theydb_buffer_tstructures pointed to by*ret_subsarraydoes not have enough space for the subscript. In this case,*ret_subs_usedis the index into the*ret_subsarrayarray with the error, and thelen_usedfield of that structure specifies the size required.YDB_ERR_NODEENDto indicate that that there are no more nodes. In this case,*ret_subs_usedis unchanged.YDB_ERR_PARAMINVALIDifret_subs_usedis NULL orret_subsarrayis NULL or one of theydb_buffer_tstructures pointed to by*ret_subsarrayhas a NULL buf_addr. In the last case,*ret_subs_usedis the index into the*ret_subsarrayarray with the NULL buf_addr.Another error return code, in which case the application should consider the values of
*ret_subs_usedand the*ret_subsarrayto 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_OKfor a normal return;YDB_ERR_INVSVNif no such intrinsic special variable exists;YDB_ERR_PARAMINVALIDwhenlen_alloc<len_usedor thelen_usedis non-zero andbuf_addris NULL in at least one subscript insubsarray; 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_INVSTRLENif the*zwrbuffer is not long enough;YDB_ERR_PARAMINVALIDifzwris NULL orzwr->buf_addris 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_addrpoints to the value of that next subscript;YDB_ERR_NODEENDwhen there are no more subscripts at that level, in which case*ret_valueis unchanged;YDB_ERR_PARAMINVALIDwhenret_valueis NULL;ret_value->buf_addris NULL and the return value has a non-zerolen_used; orlen_alloc<len_usedor thelen_usedis non-zero andbuf_addris 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_addrpoints to the value of that previous subscript;YDB_ERR_NODEENDwhen there are no more subscripts at that level, in which case*ret_valueis unchanged;YDB_ERR_PARAMINVALIDwhenret_valueis NULL;ret_value->buf_addris NULL and the return value has a non-zerolen_used; orlen_alloc<len_usedor thelen_usedis non-zero andbuf_addris 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_PARAMINVALIDwhenlen_alloc<len_usedor thelen_usedis non-zero andbuf_addris 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_usedset to zero if the zwrite formatted string has an error);YDB_ERR_INVSTRLENerror if the*strbuffer is not long enough;YDB_ERR_PARAMINVALIDeither if the*strbuffer is NULL or the return value contains a non-zerolen_usedand thestr->buf_addris 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
errnumdoes not correspond to an error that YottaDB recognizes, the return the errorYDB_ERR_UNKNOWNSYSERR, leaving the structures referenced bymsg_buffunaltered.Otherwise, if the length of the text exceeds
msg_buff->len_allocthey return the errorYDB_ERR_INVSTRLEN. In this casemsg_buff->len_usedis greater thanmsg_buff->len_alloc.Otherwise, if
msg_buff->buf_addris NULL, they return the errorYDB_ERR_PARAMINVALID.Otherwise, the copy the text to the buffer specified by
msg_buff->buf_addr, setmsg_buff->len_usedto 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 positive value because YDB_ERR_INVSTRLEN is a negative value.
Effective release r1.30. ydb_zstatus() returns an int.