DBATS
DataBase of Aggregated Time Series
Data Structures | Macros | Typedefs | Enumerations | Functions | Variables
dbats.h File Reference

DBATS API header file. More...

Data Structures

struct  dbats_bundle_info
 Time series bundle parameters (read only). More...
 
struct  dbats_config
 Configuration parameters (read only). More...
 
union  dbats_value
 A value stored in a DBATS database. More...
 

Macros

#define DBATS_DB_VERSION   11
 Version of db format written by this API.
 
#define DBATS_KEYLEN   1024
 max length of key name
 
#define DBATS_KEY_IS_PREFIX   0x80000000
 keyid describes a node, not a key
 
#define dbats_abort_snap(snap)   (dbats_abort_snap)(__FILE__, __LINE__, snap)
 Abort a transaction begun by dbats_select_snap(), undoing all changes made during the transaction and releasing any associated database locks and other resources. More...
 
Flags
#define DBATS_CREATE   0x0001
 create object if it doesn't exist
 
#define DBATS_PRELOAD   0x0004
 load fragments when snapshot is selected
 
#define DBATS_READONLY   0x0008
 don't allow writing
 
#define DBATS_UNCOMPRESSED   0x0010
 don't compress written time series data
 
#define DBATS_EXCLUSIVE   0x0020
 obtain exclusive lock on whole db
 
#define DBATS_NO_TXN   0x0040
 don't use transactions (fast but unsafe)
 
#define DBATS_UPDATABLE   0x0080
 allow updates to existing values
 
#define DBATS_GLOB   0x0200
 (internal use)
 
#define DBATS_DELETE   0x0400
 (internal use)
 

Typedefs

typedef struct dbats_handler dbats_handler
 Opaque handle for a DBATS db.
 
typedef struct dbats_snapshot dbats_snapshot
 Opaque handle for a DBATS snapshot.
 
typedef struct dbats_keyid_iterator dbats_keyid_iterator
 Opaque handle for iterating over keys by id.
 
typedef struct dbats_keytree_iterator dbats_keytree_iterator
 Opaque handle for iterating over keys by name.
 

Enumerations

enum  dbats_agg_func {
  DBATS_AGG_NONE = -1, DBATS_AGG_DATA, DBATS_AGG_MIN, DBATS_AGG_MAX,
  DBATS_AGG_AVG, DBATS_AGG_LAST, DBATS_AGG_SUM, DBATS_AGG_N
}
 Aggregation function identifiers. More...
 

Functions

int dbats_open (dbats_handler **handlerp, const char *path, uint16_t values_per_entry, uint32_t period, uint32_t flags, int mode)
 Open an existing or new DBATS database. More...
 
int dbats_commit_open (dbats_handler *handler)
 Commit the transaction started by dbats_open(). More...
 
int dbats_abort_open (dbats_handler *handler)
 Abort a transaction begun by dbats_open(), undoing all changes made during the transaction and releasing any associated database locks and other resources. More...
 
int dbats_close (dbats_handler *handler)
 Close a database opened by dbats_open(). More...
 
int dbats_aggregate (dbats_handler *handler, enum dbats_agg_func func, int steps)
 Defines an aggregate. More...
 
enum dbats_agg_func dbats_find_agg_func (const char *name)
 Look up an aggregate function by name (case insensitive). More...
 
int dbats_get_start_time (dbats_handler *handler, dbats_snapshot *snap, int bid, uint32_t *start)
 Get the earliest timestamp in a time series bundle. More...
 
int dbats_get_end_time (dbats_handler *handler, dbats_snapshot *snap, int bid, uint32_t *end)
 Get the latest timestamp in a time series bundle. More...
 
int dbats_series_limit (dbats_handler *handler, int bid, int keep)
 Configure the number of data points to keep for each time series of a bundle. More...
 
void dbats_set_userdata (dbats_handler *handler, void *data)
 Store arbitrary user-defined data on a dbats_handler. More...
 
void * dbats_get_userdata (dbats_handler *handler)
 Retreive user-defined data from a dbats_handler. More...
 
int dbats_best_bundle (dbats_handler *handler, enum dbats_agg_func func, uint32_t start, uint32_t end, int max_points, int exclude)
 Find a bundle covering a time range. More...
 
uint32_t dbats_normalize_time (const dbats_handler *handler, int bid, uint32_t *t)
 Round a time value down to a multiple of a bundle's period. More...
 
int dbats_select_snap (dbats_handler *handler, dbats_snapshot **snapp, uint32_t time_value, uint32_t flags)
 Create a "snapshot", that is, a working copy of a fixed point in time that can be manipulated with dbats_get(), dbats_set(), etc. More...
 
int dbats_commit_snap (dbats_snapshot *snap)
 Commit the transaction started by dbats_select_snap(). More...
 
int dbats_get_key_id (dbats_handler *handler, dbats_snapshot *snap, const char *key, uint32_t *key_id_p, uint32_t flags)
 Get the id of a new or existing key. More...
 
int dbats_bulk_get_key_id (dbats_handler *handler, dbats_snapshot *snap, uint32_t *n_keys_p, const char *const *keys, uint32_t *key_ids, uint32_t flags)
 Get the ids of a large number of new or existing keys. More...
 
int dbats_get_key_name (dbats_handler *handler, dbats_snapshot *snap, uint32_t key_id, char *namebuf)
 Get the name of an existing key. More...
 
int dbats_delete_keys (dbats_handler *dh, const char *pattern)
 For each metric key that matches pattern, delete the key and all its data. More...
 
int dbats_set (dbats_snapshot *snap, uint32_t key_id, const dbats_value *valuep)
 Write a value to the primary time series for the specified key and snapshot (time). More...
 
int dbats_set_by_key (dbats_snapshot *snap, const char *key, const dbats_value *valuep, int flags)
 Write a value to the primary time series for the specified key and the time selected by dbats_select_snap(). More...
 
int dbats_get (dbats_snapshot *snap, uint32_t key_id, const dbats_value **valuepp, int bid)
 Read an entry (array of dbats_value) from the database for the specified bundle id and key and the time selected by dbats_select_snap(). More...
 
int dbats_get_by_key (dbats_snapshot *snap, const char *key, const dbats_value **valuepp, int bid)
 Read an array of dbats_values from the database for the specified bundle id and key and the time selected by dbats_select_snap(). More...
 
int dbats_num_keys (dbats_handler *handler, uint32_t *num_keys)
 Get the number of keys in the database. More...
 
int dbats_glob_keyname_start (dbats_handler *handler, dbats_snapshot *snap, dbats_keytree_iterator **dkip, const char *pattern)
 Prepare to iterate over the list of keys and keytree nodes that match pattern, ordered by name. More...
 
int dbats_glob_keyname_next (dbats_keytree_iterator *dki, uint32_t *key_id_p, char *namebuf)
 Get the next key id and key name in the sequence started by dbats_glob_keyname_start(). More...
 
int dbats_glob_keyname_end (dbats_keytree_iterator *dki)
 End the sequence started by dbats_glob_keyname_start(). More...
 
int dbats_walk_keyid_start (dbats_handler *handler, dbats_snapshot *snap, dbats_keyid_iterator **dkip)
 Prepare to iterate over the list of keys ordered by id (which is the same order the keys were defined). More...
 
int dbats_walk_keyid_next (dbats_keyid_iterator *dki, uint32_t *key_id_p, char *namebuf)
 Get the next key id and key name in the sequence started by dbats_walk_keyid_start(). More...
 
int dbats_walk_keyid_end (dbats_keyid_iterator *dki)
 End the sequence started by dbats_walk_keyid_start(). More...
 
const dbats_configdbats_get_config (dbats_handler *handler)
 Get configuration parameters from a DBATS database. More...
 
const dbats_bundle_infodbats_get_bundle_info (dbats_handler *handler, int bid)
 Get time series parameters from a DBATS database. More...
 
void dbats_stat_print (const dbats_handler *handler)
 

Variables

const char * dbats_agg_func_label []
 Labels for aggregation functions (e.g. dbats_agg_func_label[DBATS_AGG_MIN] is "min")
 

signal handling convenience functions

int dbats_caught_signal
 The last signal caught by the DBATS signal handler, or 0 if no signal has been caught.
 
void dbats_catch_signal (int sig)
 If signal sig is currently handled by SIG_DFL, change it to a DBATS signal handler that sets dbats_caught_signal. More...
 
void dbats_catch_signals (void)
 Shorthand for calling dbats_catch_signal() on the following signals that are normally fatal: SIGINT, SIGHUP, SIGTERM, and SIGPIPE.
 
void dbats_restore_signal (int sig)
 If signal sig was configured with dbats_catch_signal(), reset it to SIG_DFL. More...
 
void dbats_deliver_signal (void)
 If any signal configured with dbats_catch_signal() has been caught since the handler was set, restore the SIG_DFL handler and raise the signal. More...
 

Detailed Description

DBATS API header file.

DBATS is a database for storing millions of similar time series and aggregating them by time. A DBATS time series is a sequence of data entries measured at regular time intervals. A set of similar time series with the same period and entry size is a "bundle". Each time series in a bundle is identified by a user-defined string key and an automatically assigned integer key id. The primary bundle stores the original raw data. Additional "aggregate" bundles can be defined that merge sub-sequences of data points for a key in the primary bundle into single data points for the same key in the aggregate bundle.

Typical usage:

Functions that return an int will return one of the following types of values:

If multiple snapshots (in different processes or threads) are accessing the same DBATS database concurrently, the writers may deadlock. When this happens, one or more operations will be cancelled so that another may proceed. The cancelled operations will return DB_LOCK_DEADLOCK. After a function in a transaction returns DB_LOCK_DEADLOCK, no other dbats calls are allowed on that dbats_snapshot (or dbats_handler) until dbats_abort_snap() (or dbats_abort_open()) is called to clean up the cancelled transaction. When an operation needs to be cancelled, one with the lowest priority is preferred. There are three priority categories; from lowest to highest, they are: read only; writable, but haven't yet called dbats_set(); writable, and have called dbats_set(). Within the two writable categories, priority depends on timestamp, so that inserts of "live" data have higher priority than inserts of historic data.

Although this API will not prevent you from opening two snapshots for writing within a single thread, doing so is not recommended since it may lead to an unbreakable deadlock.

Macro Definition Documentation

#define dbats_abort_snap (   snap)    (dbats_abort_snap)(__FILE__, __LINE__, snap)

Abort a transaction begun by dbats_select_snap(), undoing all changes made during the transaction and releasing any associated database locks and other resources.

After calling this function, the snapshot is no longer valid.

Parameters
[in]snapA dbats_snapshot created by dbats_select_snap().
Returns
0 for success, nonzero for error.

Enumeration Type Documentation

Aggregation function identifiers.

Enumerator
DBATS_AGG_NONE 

unknown

DBATS_AGG_DATA 

primary data value (not an aggregate)

DBATS_AGG_MIN 

minimum value

DBATS_AGG_MAX 

maximum value

DBATS_AGG_AVG 

average of values (double)

DBATS_AGG_LAST 

last value (i.e., with greatest timestamp)

DBATS_AGG_SUM 

sum of values (capped at 2e64-1)

Function Documentation

int dbats_abort_open ( dbats_handler handler)

Abort a transaction begun by dbats_open(), undoing all changes made during the transaction and releasing any associated database locks and other resources.

After calling this function, the dbats_handler is no longer valid.

Parameters
[in]handlerA dbats_handler created by dbats_open().
Returns
0 for success, nonzero for error.
int dbats_aggregate ( dbats_handler handler,
enum dbats_agg_func  func,
int  steps 
)

Defines an aggregate.

Should be called after opening a database with dbats_open() but before dbats_commit_open(), and before any other process has written data to the database. Values for DBATS_AGG_AVG are stored as dbats_value.d; all other aggregates are stored as dbats_value.u64.

For example, given a primary data bundle with a period of 60s (1 minute), dbats_aggregate(handler, DBATS_AGG_MAX, 120) will define an aggregate bundle that tracks the maximum value seen in each sub-sequence of 120 primary values (2 hours).

Parameters
[in]handlerA dbats_handler created by dbats_open().
[in]funca dbats_agg_func indicating which aggregation function to apply to the data points.
[in]stepsnumber of primary data points to include in an aggregate point
Returns
0 for success, nonzero for error.
int dbats_best_bundle ( dbats_handler handler,
enum dbats_agg_func  func,
uint32_t  start,
uint32_t  end,
int  max_points,
int  exclude 
)

Find a bundle covering a time range.

Find the bundle that best covers the time range starting at start. Only the primary bundle (0) and bundles with aggregation function func are considered.

  • If one bundle covers significantly less of the time range than another, the one with better coverage is preferred.
  • In the event of a tie above, if either bundle has more than max_points points, the bundle with fewer points is preferred.
  • In the event of a tie above, if neither bundle has more than max_points points, the bundle with more points is preferred.

Note that it is possible for the selected bundle to have more than max_points points if there is no other bundle that covers as much of the time range.

Parameters
[in]handlerA dbats_handler created by dbats_open().
[in]funcaggregation function
[in]startbeginning of the time range
[in]endend of the time range
[in]max_pointsmaximum number of data points wanted. If max_points is 0, it is treated as infinite.
[in]excludethe first sample should or should not include the from value if exclude is 0 or 1, respectively.
Returns
the bundle id of the best bundle
int dbats_bulk_get_key_id ( dbats_handler handler,
dbats_snapshot snap,
uint32_t *  n_keys_p,
const char *const *  keys,
uint32_t *  key_ids,
uint32_t  flags 
)

Get the ids of a large number of new or existing keys.

The keys must already exist unless the DBATS_CREATE flag is given. When creating a large number (> 20000) of keys, it is recommended to do so outside of a transaction to avoid excessive locking (this function will create keys in efficiently-sized batches and use its own transactions).

Parameters
[in]handlerA dbats_handler created by dbats_open().
[in]snapA dbats_snapshot created by dbats_select_snap().
[in,out]*n_keys_pOn input, should point to an integer containing the number of keys in the keys array. On output, that integer will contain the number of ids written into key_ids. If this function returns 0, the output value of *n_keys_p will equal the input value; otherwise, the output value may be anywhere between 0 and the input value, indicating the number of keys that were successfully looked up or created before the error occurred.
[in]keysan array of key names
[out]key_idsan array of uint32_t where the ids for keys will be written.
[in]flagsa bitwise-OR combination of any of the following:
  • DBATS_CREATE - create any key that does not already exist.
Returns
0 for success, DB_NOTFOUND if any key does not exist and DBATS_CREATE flag was not set, or other nonzero value for error.
void dbats_catch_signal ( int  sig)

If signal sig is currently handled by SIG_DFL, change it to a DBATS signal handler that sets dbats_caught_signal.

Parameters
[in]sigthe signal to handle
int dbats_close ( dbats_handler handler)

Close a database opened by dbats_open().

All snapshots must be committed or aborted before calling dbats_close().

Parameters
[in]handlerA dbats_handler created by dbats_open().
Returns
0 for success, nonzero for error.
int dbats_commit_open ( dbats_handler handler)

Commit the transaction started by dbats_open().

This will flush any pending writes to the database and release any associated database locks and other resources. If the database was created in this transaction, no other processes will be able to access the database until dbats_commit_open() is called.

Parameters
[in]handlerA dbats_handler created by dbats_open().
Returns
  • 0 for success;
  • DB_LOCK_DEADLOCK if the operation was cancelled to resolve a deadlock;
  • other nonzero value for other errors.
int dbats_commit_snap ( dbats_snapshot snap)

Commit the transaction started by dbats_select_snap().

This will flush any pending writes to the database and release any associated database locks and other resources. Any data points that fall outside the limit set by dbats_series_limit() will be deleted. After calling this function, the snapshot is no longer valid.

Parameters
[in]snapA dbats_snapshot created by dbats_select_snap().
Returns
  • 0 for success;
  • DB_LOCK_DEADLOCK if the operation was cancelled to resolve a deadlock;
  • other nonzero value for other errors.
int dbats_delete_keys ( dbats_handler dh,
const char *  pattern 
)

For each metric key that matches pattern, delete the key and all its data.

There must not be a snapshot open when this function is called.

Parameters
[in]handlerA dbats_handler created by dbats_open().
[in]patternA fileglob-like pattern as described under dbats_glob_keyname_start().
Returns
0 for success, EINVAL if the pattern is invalid, or other nonzero value for other error.
void dbats_deliver_signal ( void  )

If any signal configured with dbats_catch_signal() has been caught since the handler was set, restore the SIG_DFL handler and raise the signal.

This is useful after cleanly aborting transactions and closing the database, to exit the process with the same status that would have occurred if the signal had not been caught.

enum dbats_agg_func dbats_find_agg_func ( const char *  name)

Look up an aggregate function by name (case insensitive).

Parameters
[in]namethe name of an aggregate function
Returns
the dbats_agg_func function id, or DBATS_AGG_NONE if no match is found
int dbats_get ( dbats_snapshot snap,
uint32_t  key_id,
const dbats_value **  valuepp,
int  bid 
)

Read an entry (array of dbats_value) from the database for the specified bundle id and key and the time selected by dbats_select_snap().

Parameters
[in]snapA dbats_snapshot created by dbats_select_snap().
[in]key_idthe id of the key.
[out]valueppthe address of a dbats_value*; after the call, *valuepp will point to an array of values_per_entry dbats_values read from the database.
[in]bidbundle id (0 for the primary bundle).
Returns
  • 0 for success;
  • DB_NOTFOUND if the key does not exist;
  • DB_LOCK_DEADLOCK if the operation was cancelled to resolve a deadlock;
  • other nonzero value for other errors.
const dbats_bundle_info* dbats_get_bundle_info ( dbats_handler handler,
int  bid 
)

Get time series parameters from a DBATS database.

Parameters
[in]handlerA dbats_handler created by dbats_open().
[in]bidThe id of the time series bundle (0 for the primary bundle).
Returns
pointer to a dbats_bundle_info describing the bundle specified by bid.
int dbats_get_by_key ( dbats_snapshot snap,
const char *  key,
const dbats_value **  valuepp,
int  bid 
)

Read an array of dbats_values from the database for the specified bundle id and key and the time selected by dbats_select_snap().

Equivalent to dbats_get_key_id() followed by dbats_get(). Note that dbats_get() is significantly faster if you already know the key_id.

Parameters
[in]snapA dbats_snapshot created by dbats_select_snap().
[in]keythe name of the key.
[out]valueppthe address of a dbats_value*; after the call, *valuepp will point to an array of values_per_entry dbats_values read from the database.
[in]bidbundle id (0 for the primary bundle).
Returns
  • 0 for success;
  • DB_NOTFOUND if the key does not exist;
  • DB_LOCK_DEADLOCK if the operation was cancelled to resolve a deadlock;
  • other nonzero value for other errors.
const dbats_config* dbats_get_config ( dbats_handler handler)

Get configuration parameters from a DBATS database.

Parameters
[in]handlerA dbats_handler created by dbats_open().
Returns
pointer to a dbats_config containing configuration parameters.
int dbats_get_end_time ( dbats_handler handler,
dbats_snapshot snap,
int  bid,
uint32_t *  end 
)

Get the latest timestamp in a time series bundle.

At least one key in the bundle will have a value at the end time.

Parameters
[in]handlerA dbats_handler created by dbats_open().
[in]snapA dbats_snapshot created by dbats_select_snap().
[in]bidbundle id (0 for the primary bundle).
[out]endA pointer to a uint32_t that will be filled in with the time of the latest entry in the bundle, or 0 if an error occurred.
Returns
0 for success, DB_NOTFOUND if the bundle is empty, or other nonzero value for error.
int dbats_get_key_id ( dbats_handler handler,
dbats_snapshot snap,
const char *  key,
uint32_t *  key_id_p,
uint32_t  flags 
)

Get the id of a new or existing key.

The key must already exist unless the DBATS_CREATE flag is given. When getting or creating multiple keys, it is faster to do it with dbats_bulk_get_key_id().

Parameters
[in]handlerA dbats_handler created by dbats_open().
[in]snapA dbats_snapshot created by dbats_select_snap().
[in]keythe name of the key.
[out]key_id_pa pointer to a uint32_t where the id for key will be written.
[in]flagsa bitwise-OR combination of any of the following:
  • DBATS_CREATE - create the key if it does not already exist.
Returns
0 for success, DB_NOTFOUND if the key does not exist and DBATS_CREATE flag was not set, or other nonzero value for error.
int dbats_get_key_name ( dbats_handler handler,
dbats_snapshot snap,
uint32_t  key_id,
char *  namebuf 
)

Get the name of an existing key.

Parameters
[in]handlerA dbats_handler created by dbats_open().
[in]snapA dbats_snapshot created by dbats_select_snap().
[in]key_idthe id of the key.
[out]namebufa pointer to an array of at least DBATS_KEYLEN characters where the key's name will be written.
Returns
0 for success, nonzero for error.
int dbats_get_start_time ( dbats_handler handler,
dbats_snapshot snap,
int  bid,
uint32_t *  start 
)

Get the earliest timestamp in a time series bundle.

At least one key in the bundle will have a value at the start time.

Parameters
[in]handlerA dbats_handler created by dbats_open().
[in]snapA dbats_snapshot created by dbats_select_snap().
[in]bidbundle id (0 for the primary bundle).
[out]startA pointer to a uint32_t that will be filled in with the time of the earliest entry in the bundle, or 0 if an error occurred.
Returns
0 for success, DB_NOTFOUND if the bundle is empty, or other nonzero value for error.
void* dbats_get_userdata ( dbats_handler handler)

Retreive user-defined data from a dbats_handler.

Parameters
[in]handlerA dbats_handler created by dbats_open().
Returns
the pointer stored by dbats_set_userdata().
int dbats_glob_keyname_end ( dbats_keytree_iterator dki)

End the sequence started by dbats_glob_keyname_start().

Parameters
[in]dkiA dbats_keytree_iterator created by dbats_glob_keyname_start().
Returns
0 for success, nonzero for error.
int dbats_glob_keyname_next ( dbats_keytree_iterator dki,
uint32_t *  key_id_p,
char *  namebuf 
)

Get the next key id and key name in the sequence started by dbats_glob_keyname_start().

Parameters
[in]dkiA dbats_keytree_iterator created by dbats_glob_keyname_start().
[out]key_id_pA pointer to a uint32_t where the key_id will be written. If (keyid & DBATS_KEY_IS_PREFIX) is true, the result describes a keytree node; otherwise, it describes a keytree leaf (i.e., an actual key).
[out]namebufa pointer to an array of at least DBATS_KEYLEN characters where the key's name will be written, or NULL if you do not need the name.
Returns
  • 0 for success;
  • DB_NOTFOUND if there are no more matching keys;
  • other nonzero value for error.
int dbats_glob_keyname_start ( dbats_handler handler,
dbats_snapshot snap,
dbats_keytree_iterator **  dkip,
const char *  pattern 
)

Prepare to iterate over the list of keys and keytree nodes that match pattern, ordered by name.

If pattern is NULL, all keys (but not nodes) will be iterated over. Otherwise, keys and nodes matching the pattern will be iterated over. The pattern is similar to shell filename globbing, except that hierarchical components are separated by '.' instead of '/'.

  • * matches any zero or more characters (except '.')
  • ? matches any one character (except '.')
  • [...] matches any one character in the character class (except '.')
    • A leading '^' negates the character class
    • Two characters separated by '-' matches any ASCII character between the two characters, inclusive
  • {...} matches any one string of characters in the comma-separated list of strings
  • Any other character matches itself.
  • Any special character can have its special meaning removed by preceeding it with '\'.

Example:

1 dbats_handler *handler;
2 dbats_snapshot *snap;
3 dbats_keytree_iterator *dki;
4 int rc;
5 uint32_t keyid;
6 char name[DBATS_KEYLEN];
7 ...
8 rc = dbats_glob_keyname_start(handler, snap, &dki, "*.*.uniq_*_ip");
9 if (rc != 0) goto error_handling;
10 while (dbats_glob_keyname_next(dki, &keyid, name) == 0 && !dbats_caught_signal) {
11  if (keyid & DBATS_KEY_IS_PREFIX) {
12  // do something with node described by keyid and name
13  } else {
14  // do something with key described by keyid and name
15  }
16 }
17 dbats_glob_keyname_end(dki);

If snap is not NULL, the operations will occur within snap's transaction; otherwise, if handler's transaction has not been closed, they will occur within handler's transaction; otherwise, this function will begin a new transaction which will be committed by dbats_glob_keyname_end().

Parameters
[in]handlerA dbats_handler created by dbats_open().
[in]snapA dbats_snapshot created by dbats_select_snap().
[out]dkipthe address of a dbats_keytree_iterator*; after the call, *dkip will contain a pointer that must be passed to subsequent calls of dbats_glob_keyname_next() and dbats_glob_keyname_end().
[in]patternA fileglob-like pattern
Returns
0 for success, or EINVAL if the pattern is invalid.
uint32_t dbats_normalize_time ( const dbats_handler handler,
int  bid,
uint32_t *  t 
)

Round a time value down to a multiple of a bundle's period.

Parameters
[in]handlerA dbats_handler created by dbats_open().
[in]bidbundle id (0 for the primary bundle).
[in,out]ta unix time value (seconds since 1970-01-01 00:00:00 UTC, without leap seconds). Value will be rounded down to the nearest multiple of the data period, counting from 00:00 on the first Sunday of 1970, UTC.
Returns
the rounded time value (*t)
int dbats_num_keys ( dbats_handler handler,
uint32_t *  num_keys 
)

Get the number of keys in the database.

Parameters
[in]handlerA dbats_handler created by dbats_open().
[out]num_keysA pointer to a uint32_t that will be filled in with the number of keys in the databasse.
Returns
0 for success, nonzero for error.
int dbats_open ( dbats_handler **  handlerp,
const char *  path,
uint16_t  values_per_entry,
uint32_t  period,
uint32_t  flags,
int  mode 
)

Open an existing or new DBATS database.

Some configuration parameters can be set only when creating a database; when opening an existing database, those parameters will be silently ignored. By default, the database will allow reading data values and inserting new data values, but not updating existing data values.

If dbats_open() succeeds, the process should not call dbats_open() again with the same path until the former handle is closed with dbats_close().

Opening a database also starts a transaction that can be used to configure the database. When configuration is complete, you must call dbats_commit_open() to commit the transaction. Before calling dbats_commit_open():

  • if the database is newly created, no other processes will be able to access the database
  • multiple threads should not attempt to use the dbats_handler concurrently
  • dbats_select_snap() is not allowed

After dbats_commit_open(), any number of threads may call dbats_select_snap() on the dbats_handler.

Parameters
[out]handlerpthe address of a dbats_handler*; after the call, *handlerp will contain a pointer that must be passed to subsequent calls on this database.
[in]pathpath of an existing directory containing a DBATS database or a nonexistant directory in which to create a new DBATS database.
[in]values_per_entrynumber of dbats_values in the array read by dbats_get() or written by dbats_set() (ignored unless creating a new database).
[in]periodthe number of seconds between primary data values (ignored unless creating a new database).
[in]flagsa bitwise-OR combination of any of the following:
  • DBATS_CREATE - create the database if it doesn't already exist
  • DBATS_READONLY - do not allow writing to the database (improves performance)
  • DBATS_UNCOMPRESSED - do not compress written time series data
  • DBATS_EXCLUSIVE - do not allow any other process to access the database
  • DBATS_NO_TXN - do not use transactions (faster, but may corrupt the database if other processes or threads try to access the database or if the process exits uncleanly)
  • DBATS_UPDATABLE - allow updates to existing values
[in]modepermissions for files created by this function (as defined by open(2)) and modified by the process's umask. A value of 0 is treated as 0644. (This function will automatically add write permission to certain transaction and locking related files as needed to allow read-only access.)
Returns
  • 0 for success;
  • EINVAL if a parameter was invalid;
  • ENOMEM if out of memory;
  • ENOENT if the directory specified by path does not exist and flags did not contain DBATS_CREATE, or if the directory does exist but does not contain a valid database after waiting several seconds;
  • DB_VERSION_MISMATCH if the version of the BDB library or DBATS library is not compatible with that used to create the database;
  • other nonzero value for other errors.
void dbats_restore_signal ( int  sig)

If signal sig was configured with dbats_catch_signal(), reset it to SIG_DFL.

Parameters
[in]sigthe signal to handle
int dbats_select_snap ( dbats_handler handler,
dbats_snapshot **  snapp,
uint32_t  time_value,
uint32_t  flags 
)

Create a "snapshot", that is, a working copy of a fixed point in time that can be manipulated with dbats_get(), dbats_set(), etc.

All operations on this snapshot take place within a transaction; that is, they will not be visible to other processes/threads until they are committed with dbats_commit_snap(), or they can be undone with dbats_abort_snap(). If this function fails for any reason, it returns nonzero without beginning a transaction. If multiple snapshots are being used to write to the database in parallel (in other processes or threads), this function may block until those other snapshots complete their transactions. If a deadlock occurs within this function, it will automatically retry, up to a limit; if this limit is reached, this function will return DB_LOCK_DEADLOCK without beginning a transaction (so dbats_abort_snap() is not needed).

Parameters
[in]handlerA dbats_handler created by dbats_open().
[out]snappthe address of a dbats_snapshot*; after the call, *snapp will contain a pointer that must be passed to subsequent function calls.
[in]time_valuethe desired time, which will be rounded down by dbats_normalize_time().
[in]flagsa bitwise-OR combination of any of the following:
  • DBATS_READONLY - do not allow writing to this snapshot, even if the db was opened for writing (improves performance)
  • DBATS_PRELOAD - load data immediately instead of waiting until it's needed (if you're going to load all the data eventually, this flag can reduce the chances of deadlock)
Returns
  • 0 for success;
  • EINVAL if the database was not opened with DBATS_READONLY and the selected time is outside the keep limit set by dbats_series_limit();
  • DB_LOCK_DEADLOCK if the operation was cancelled to resolve a deadlock;
  • other nonzero value for other errors.
int dbats_series_limit ( dbats_handler handler,
int  bid,
int  keep 
)

Configure the number of data points to keep for each time series of a bundle.

When a transaction started by dbats_select_snap() is committed, any data points that are keep periods or more older than the latest point ever set (for any key) will be deleted. Once a point is deleted for being outside the limit, it can not be set again, even if the limit is changed. The limit for the primary data bundle (bid 0) can not be smaller than the number of steps in the largest aggregate.

For example, if a bundle with period 60s has a keep limit of 1440, values more than 1 day older than the last timestamp set for any key in the bundle will be deleted. If the bundle contains data for keys "foo" and "bar", and a new value for "foo" is set for 15:37:00 today, then (as soon as that transaction is committed) all values for both "foo" and "bar" up to 15:36:00 yesterday will be deleted.

Parameters
[in]handlerA dbats_handler created by dbats_open().
[in]bidbundle id (0 for the primary bundle).
[in]keepThe number of data points to keep in each time series of the bundle, or 0 to keep all points.
Returns
  • 0 for success;
  • DB_NOTFOUND if bid does not refer to a valid bundle;
  • EINVAL if the limit is too small;
  • other nonzero value for other errors.
int dbats_set ( dbats_snapshot snap,
uint32_t  key_id,
const dbats_value valuep 
)

Write a value to the primary time series for the specified key and snapshot (time).

All aggregate values whose time ranges contain this primary data point will also be updated. Note that values are not guaranteed to be safely stored in the database until dbats_commit_snap() is called and returns successfully. In particular, when multiple processes are writing to the database, there is a non-negligible probability of losing data due to deadlock in dbats_set() or dbats_commit_snap(). You are advised to hold on to a copy of your original data until dbats_commit_snap() succeeds, so that you can repeat dbats_select_snap() and dbats_set() if needed.

Parameters
[in]snapA dbats_snapshot created by dbats_select_snap().
[in]key_idthe id of the key.
[in]valuepa pointer to an array of values_per_entry dbats_value to be written to the database. Each dbats_value.u64 should contain a value.
Returns
  • 0 for success;
  • EPERM if the handler is not open or was opened with DBATS_READONLY;
  • DB_KEYEXIST if a value already exists for the given time and key, and handler was not opened with DBATS_UPDATABLE;
  • ENOSYS if a value already exists for the given time and key, and an aggregate depending on the value has the function DBATS_AGG_MIN or DBATS_AGG_MAX;
  • DB_LOCK_DEADLOCK if the operation was cancelled to resolve a deadlock;
  • other nonzero value for other errors.
int dbats_set_by_key ( dbats_snapshot snap,
const char *  key,
const dbats_value valuep,
int  flags 
)

Write a value to the primary time series for the specified key and the time selected by dbats_select_snap().

Equivalent to dbats_get_key_id (handler, key, &key_id, flags) followed by dbats_set (handler, key_id, valuep). Note that dbats_set() is much faster than dbats_set_by_key() if you know the key_id already.

Parameters
[in]snapA dbats_snapshot created by dbats_select_snap().
[in]keythe name of the key.
[in]valuepa pointer to an array of values_per_entry dbats_values to be written to the database.
[in]flagsa bitwise-OR combination of any of the following:
  • DBATS_CREATE - create the key if it does not already exist.
Returns
  • 0 for success;
  • EPERM if the handler is not open or was opened with DBATS_READONLY;
  • DB_NOTFOUND if the key does not exist and DBATS_CREATE flag was not set;
  • EEXIST if a value already exists for the given time and key, and handler was not opened with DBATS_UPDATABLE;
  • DB_LOCK_DEADLOCK if the operation was cancelled to resolve a deadlock;
  • other nonzero value for other errors.
void dbats_set_userdata ( dbats_handler handler,
void *  data 
)

Store arbitrary user-defined data on a dbats_handler.

Parameters
[in]handlerA dbats_handler created by dbats_open().
[in]dataa pointer to store on dbats_handler.
int dbats_walk_keyid_end ( dbats_keyid_iterator dki)

End the sequence started by dbats_walk_keyid_start().

Parameters
[in]dkiA dbats_keyid_iterator created by dbats_walk_keyid_start().
Returns
0 for success, nonzero for error.
int dbats_walk_keyid_next ( dbats_keyid_iterator dki,
uint32_t *  key_id_p,
char *  namebuf 
)

Get the next key id and key name in the sequence started by dbats_walk_keyid_start().

Parameters
[in]dkiA dbats_keyid_iterator created by dbats_walk_keyid_start().
[out]key_id_pA pointer to a uint32_t where the key_id will be written.
[out]namebufa pointer to an array of at least DBATS_KEYLEN characters where the key's name will be written, or NULL if you do not need the name.
Returns
  • 0 for success;
  • DB_NOTFOUND if there are no more keys;
  • other nonzero value for error.
int dbats_walk_keyid_start ( dbats_handler handler,
dbats_snapshot snap,
dbats_keyid_iterator **  dkip 
)

Prepare to iterate over the list of keys ordered by id (which is the same order the keys were defined).

If snap is not NULL, the operations will occur within snap's transaction; otherwise they will occur within handler's transaction. You must call dbats_walk_keyid_end() before committing the transaction.

Example:

1 dbats_handler *handler;
2 dbats_snapshot *snap;
3 dbats_keyid_iterator *dki;
4 int rc;
5 uint32_t keyid;
6 char name[DBATS_KEYLEN];
7 ...
8 rc = dbats_walk_keyid_start(handler, snap, &dki);
9 if (rc != 0) goto error_handling;
10 while (dbats_walk_keyid_next(dki, &keyid, name) == 0 && !dbats_caught_signal) {
11  // do something with keyid and/or name
12 }
13 dbats_walk_keyid_end(dki);
Parameters
[in]handlerA dbats_handler created by dbats_open().
[in]snapA dbats_snapshot created by dbats_select_snap().
[out]dkipthe address of a dbats_keyid_iterator*; after the call, *dkip will contain a pointer that must be passed to subsequent calls of dbats_walk_keyid_next() and dbats_walk_keyid_end().
Returns
0 for success, nonzero for error.