.\" Automatically generated by Pandoc 2.9.2.1 .\" .TH "PMEMKV" "3" "2021-07-26" "PMEMKV - pmemkv version 1.5.0-rc1" "PMEMKV Programmer's Manual" .hy .\" SPDX-License-Identifier: BSD-3-Clause .\" Copyright 2019-2021, Intel Corporation .SH NAME .PP \f[B]pmemkv\f[R] - Key/Value Datastore for Persistent Memory .SH SYNOPSIS .IP .nf \f[C] #include typedef int pmemkv_get_kv_callback(const char *key, size_t keybytes, const char *value, size_t valuebytes, void *arg); typedef void pmemkv_get_v_callback(const char *value, size_t valuebytes, void *arg); int pmemkv_open(const char *engine, pmemkv_config *config, pmemkv_db **db); void pmemkv_close(pmemkv_db *kv); int pmemkv_count_all(pmemkv_db *db, size_t *cnt); int pmemkv_count_above(pmemkv_db *db, const char *k, size_t kb, size_t *cnt); int pmemkv_count_below(pmemkv_db *db, const char *k, size_t kb, size_t *cnt); int pmemkv_count_between(pmemkv_db *db, const char *k1, size_t kb1, const char *k2, size_t kb2, size_t *cnt); int pmemkv_get_all(pmemkv_db *db, pmemkv_get_kv_callback *c, void *arg); int pmemkv_get_above(pmemkv_db *db, const char *k, size_t kb, pmemkv_get_kv_callback *c, void *arg); int pmemkv_get_below(pmemkv_db *db, const char *k, size_t kb, pmemkv_get_kv_callback *c, void *arg); int pmemkv_get_between(pmemkv_db *db, const char *k1, size_t kb1, const char *k2, size_t kb2, pmemkv_get_kv_callback *c, void *arg); int pmemkv_exists(pmemkv_db *db, const char *k, size_t kb); int pmemkv_get(pmemkv_db *db, const char *k, size_t kb, pmemkv_get_v_callback *c, void *arg); int pmemkv_get_copy(pmemkv_db *db, const char *k, size_t kb, char *buffer, size_t buffer_size, size_t *value_size); int pmemkv_put(pmemkv_db *db, const char *k, size_t kb, const char *v, size_t vb); int pmemkv_remove(pmemkv_db *db, const char *k, size_t kb); int pmemkv_defrag(pmemkv_db *db, double start_percent, double amount_percent); const char *pmemkv_errormsg(void); \f[R] .fi .PP For pmemkv configuration API description see \f[B]libpmemkv_config\f[R](3). For pmemkv iterator API description see \f[B]libpmemkv_iterator\f[R](3). For general pmemkv information, engine descriptions and bindings details see \f[B]libpmemkv\f[R](7). .SH DESCRIPTION .PP Keys and values stored in a pmemkv database can be arbitrary binary data and can contain multiple null characters. Every function which accepts key expects \f[C]const char *k\f[R] pointer to data and its size as \f[C]size_t\f[R]. .PP Some of the functions (mainly range-query API) are not guaranteed to be implemented by all engines. If an engine does not support a certain function, it will return PMEMKV_STATUS_NOT_SUPPORTED. .PP Note: There are no explicit upper_bound/lower_bound functions. If you want to obtain an element(s) above or below the selected key, you can use pmemkv_get_above() or pmemkv_get_below(). See descriptions of these functions for details. .TP \f[B]\f[CB]int pmemkv_open(const char *engine, pmemkv_config *config, pmemkv_db **db);\f[B]\f[R] Opens the pmemkv database and stores a pointer to a \f[I]pmemkv_db\f[R] instance in \f[C]*db\f[R]. The \f[C]engine\f[R] parameter specifies the engine name (see \f[B]libpmemkv\f[R](7) for the list of available engines). The \f[C]config\f[R] parameter specifies configuration (see \f[B]libpmemkv_config\f[R](3) for details). Pmemkv takes ownership of the config parameter - this means that pmemkv_config_delete() must NOT be called after open (successful or failed). .TP \f[B]\f[CB]void pmemkv_close(pmemkv_db *kv);\f[B]\f[R] Closes pmemkv database. .TP \f[B]\f[CB]int pmemkv_count_all(pmemkv_db *db, size_t *cnt);\f[B]\f[R] Stores in \f[C]*cnt\f[R] the number of records in \f[C]db\f[R]. .TP \f[B]\f[CB]int pmemkv_count_above(pmemkv_db *db, const char *k, size_t kb, size_t *cnt);\f[B]\f[R] Stores in \f[C]*cnt\f[R] the number of records in \f[C]db\f[R] whose keys are greater than the key \f[C]k\f[R] of length \f[C]kb\f[R]. Order of the elements is specified by a comparator (see \f[B]libpmemkv\f[R](7)). .TP \f[B]\f[CB]int pmemkv_count_below(pmemkv_db *db, const char *k, size_t kb, size_t *cnt);\f[B]\f[R] Stores in \f[C]*cnt\f[R] the number of records in \f[C]db\f[R] whose keys are less than the key \f[C]k\f[R] of length \f[C]kb\f[R]. Order of the elements is specified by a comparator (see \f[B]libpmemkv\f[R](7)). .TP \f[B]\f[CB]int pmemkv_count_between(pmemkv_db *db, const char *k1, size_t kb1, const char *k2, size_t kb2, size_t *cnt);\f[B]\f[R] Stores in \f[C]*cnt\f[R] the number of records in \f[C]db\f[R] whose keys are greater than key \f[C]k1\f[R] (of length \f[C]kb1\f[R]) and less than key \f[C]k2\f[R] (of length \f[C]kb2\f[R]). Order of the elements is specified by a comparator (see \f[B]libpmemkv\f[R](7)). .TP \f[B]\f[CB]int pmemkv_get_all(pmemkv_db *db, pmemkv_get_kv_callback *c, void *arg);\f[B]\f[R] Executes function \f[C]c\f[R] for every record stored in \f[C]db\f[R]. Arguments passed to the function are: pointer to a key, size of the key, pointer to a value, size of the value and \f[C]arg\f[R] specified by the user. Function \f[C]c\f[R] can stop iteration by returning non-zero value. In that case \f[I]pmemkv_get_all()\f[R] returns PMEMKV_STATUS_STOPPED_BY_CB. Returning 0 continues iteration. Order of the elements is specified by a comparator (see \f[B]libpmemkv\f[R](7)). .TP \f[B]\f[CB]int pmemkv_get_above(pmemkv_db *db, const char *k, size_t kb, pmemkv_get_kv_callback *c, void *arg);\f[B]\f[R] Executes function \f[C]c\f[R] for every record stored in \f[C]db\f[R] whose keys are greater than key \f[C]k\f[R] (of length \f[C]kb\f[R]). Arguments passed to \f[C]c\f[R] are: pointer to a key, size of the key, pointer to a value, size of the value and \f[C]arg\f[R] specified by the user. Function \f[C]c\f[R] can stop iteration by returning non-zero value. In that case \f[I]pmemkv_get_above()\f[R] returns PMEMKV_STATUS_STOPPED_BY_CB. Returning 0 continues iteration. Order of the elements is specified by a comparator (see \f[B]libpmemkv\f[R](7)). .TP \f[B]\f[CB]int pmemkv_get_below(pmemkv_db *db, const char *k, size_t kb, pmemkv_get_kv_callback *c, void *arg);\f[B]\f[R] Executes function \f[C]c\f[R] for every record stored in \f[C]db\f[R] whose keys are less than key \f[C]k\f[R] (of length \f[C]kb\f[R]). Arguments passed to \f[C]c\f[R] are: pointer to a key, size of the key, pointer to a value, size of the value and \f[C]arg\f[R] specified by the user. Function \f[C]c\f[R] can stop iteration by returning non-zero value. In that case \f[I]pmemkv_get_below()\f[R] returns PMEMKV_STATUS_STOPPED_BY_CB. Returning 0 continues iteration. Order of the elements is specified by a comparator (see \f[B]libpmemkv\f[R](7)). .TP \f[B]\f[CB]int pmemkv_get_between(pmemkv_db *db, const char *k1, size_t kb1, const char *k2, size_t kb2, pmemkv_get_kv_callback *c, void *arg);\f[B]\f[R] Executes function \f[C]c\f[R] for every record stored in \f[C]db\f[R] whose keys are greater than key \f[C]k1\f[R] (of length \f[C]kb1\f[R]) and less than key \f[C]k2\f[R] (of length \f[C]kb2\f[R]). Arguments passed to \f[C]c\f[R] are: pointer to a key, size of the key, pointer to a value, size of the value and \f[C]arg\f[R] specified by the user. Function \f[C]c\f[R] can stop iteration by returning non-zero value. In that case \f[I]pmemkv_get_between()\f[R] returns PMEMKV_STATUS_STOPPED_BY_CB. Returning 0 continues iteration. Order of the elements is specified by a comparator (see \f[B]libpmemkv\f[R](7)). .TP \f[B]\f[CB]int pmemkv_exists(pmemkv_db *db, const char *k, size_t kb);\f[B]\f[R] Checks existence of record with key \f[C]k\f[R] of length \f[C]kb\f[R]. If record is present PMEMKV_STATUS_OK is returned, otherwise PMEMKV_STATUS_NOT_FOUND is returned. Other possible return values are described in the \f[I]ERRORS\f[R] section. .TP \f[B]\f[CB]int pmemkv_get(pmemkv_db *db, const char *k, size_t kb, pmemkv_get_v_callback *c, void *arg);\f[B]\f[R] Executes function \f[C]c\f[R] on record with key \f[C]k\f[R] (of length \f[C]kb\f[R]). If record is present and no error occurred the function returns PMEMKV_STATUS_OK. If record does not exist PMEMKV_STATUS_NOT_FOUND is returned. Other possible return values are described in the \f[I]ERRORS\f[R] section. Function \f[C]c\f[R] is called with the following parameters: pointer to a value, size of the value and \f[C]arg\f[R] specified by the user. \f[C]Value\f[R] points to the location where data is actually stored (no copy occurs). This function is guaranteed to be implemented by all engines. .TP \f[B]\f[CB]int pmemkv_get_copy(pmemkv_db *db, const char *k, size_t kb, char *buffer, size_t buffer_size, size_t *value_size);\f[B]\f[R] Copies value of record with key \f[C]k\f[R] of length \f[C]kb\f[R] to user provided buffer. \f[C]buffer\f[R] points to the value buffer, \f[C]buffer_size\f[R] specifies its size and \f[C]*value_size\f[R] is filled in by this function. If the value doesn\[cq]t fit in the provided buffer then this function returns PMEMKV_STATUS_UNKNOWN_ERROR. Otherwise, in absence of any errors, PMEMKV_STATUS_OK is returned. Other possible return values are described in the \f[I]ERRORS\f[R] section. This function is guaranteed to be implemented by all engines. .TP \f[B]\f[CB]int pmemkv_put(pmemkv_db *db, const char *k, size_t kb, const char *v, size_t vb);\f[B]\f[R] Inserts a key-value pair into pmemkv database. \f[C]kb\f[R] is the length of key \f[C]k\f[R] and \f[C]vb\f[R] is the length of value \f[C]v\f[R]. When this function returns, caller is free to reuse both buffers. This function is guaranteed to be implemented by all engines. .TP \f[B]\f[CB]int pmemkv_remove(pmemkv_db *db, const char *k, size_t kb);\f[B]\f[R] Removes record with key \f[C]k\f[R] of length \f[C]kb\f[R]. This function is guaranteed to be implemented by all engines. .TP \f[B]\f[CB]int pmemkv_defrag(pmemkv_db *db, double start_percent, double amount_percent);\f[B]\f[R] Defragments approximately `amount_percent' percent of elements in the database starting from `start_percent' percent of elements. .TP \f[B]\f[CB]const char *pmemkv_errormsg(void);\f[B]\f[R] Returns a human readable string describing the last error. .SS ERRORS .PP Each function, except for \f[I]pmemkv_close()\f[R] and \f[I]pmemkv_errormsg()\f[R], returns one of the following status codes: .IP \[bu] 2 \f[B]PMEMKV_STATUS_OK\f[R] \[en] no error .IP \[bu] 2 \f[B]PMEMKV_STATUS_UNKNOWN_ERROR\f[R] \[en] unknown error .IP \[bu] 2 \f[B]PMEMKV_STATUS_NOT_FOUND\f[R] \[en] record not found .IP \[bu] 2 \f[B]PMEMKV_STATUS_NOT_SUPPORTED\f[R] \[en] function is not implemented by current engine .IP \[bu] 2 \f[B]PMEMKV_STATUS_INVALID_ARGUMENT\f[R] \[en] argument to function has wrong value .IP \[bu] 2 \f[B]PMEMKV_STATUS_CONFIG_PARSING_ERROR\f[R] \[en] parsing data to config failed .IP \[bu] 2 \f[B]PMEMKV_STATUS_CONFIG_TYPE_ERROR\f[R] \[en] config item has different type than expected .IP \[bu] 2 \f[B]PMEMKV_STATUS_STOPPED_BY_CB\f[R] \[en] iteration was stopped by user\[cq]s callback .IP \[bu] 2 \f[B]PMEMKV_STATUS_OUT_OF_MEMORY\f[R] \[en] operation failed because there is not enough memory (or space on the device) .IP \[bu] 2 \f[B]PMEMKV_STATUS_WRONG_ENGINE_NAME\f[R] \[en] engine name does not match any available engine .IP \[bu] 2 \f[B]PMEMKV_STATUS_TRANSACTION_SCOPE_ERROR\f[R] \[en] an error with the scope of the libpmemobj transaction .IP \[bu] 2 \f[B]PMEMKV_STATUS_DEFRAG_ERROR\f[R] \[en] the defragmentation process failed (possibly in the middle of a run) .PP Status returned from a function can change in a future version of a library to a more specific one. For example, if a function returns PMEMKV_STATUS_UNKNOWN_ERROR, it is possible that in future versions it will return PMEMKV_STATUS_INVALID_ARGUMENT. Recommended way to check for an error is to compare status with PMEMKV_STATUS_OK. .SH EXAMPLE .PP The following example is taken from \f[C]examples/pmemkv_basic_c\f[R] directory. .PP Basic pmemkv usage in C: .IP .nf \f[C] #include #include #include #include #include #define ASSERT(expr) \[rs] do { \[rs] if (!(expr)) \[rs] puts(pmemkv_errormsg()); \[rs] assert(expr); \[rs] } while (0) #define LOG(msg) puts(msg) #define MAX_VAL_LEN 64 static const uint64_t SIZE = 1024UL * 1024UL * 1024UL; int get_kv_callback(const char *k, size_t kb, const char *value, size_t value_bytes, void *arg) { printf(\[dq] visited: %s\[rs]n\[dq], k); return 0; } int main(int argc, char *argv[]) { if (argc < 2) { fprintf(stderr, \[dq]Usage: %s file\[rs]n\[dq], argv[0]); exit(1); } /* See libpmemkv_config(3) for more detailed example of config creation */ LOG(\[dq]Creating config\[dq]); pmemkv_config *cfg = pmemkv_config_new(); ASSERT(cfg != NULL); int s = pmemkv_config_put_path(cfg, argv[1]); ASSERT(s == PMEMKV_STATUS_OK); s = pmemkv_config_put_size(cfg, SIZE); ASSERT(s == PMEMKV_STATUS_OK); s = pmemkv_config_put_create_if_missing(cfg, true); ASSERT(s == PMEMKV_STATUS_OK); /* Alternatively create_or_error_if_exists flag can be set, to fail if file exists * For differences between the two flags, see manpage libpmemkv(7). */ /* s = pmemkv_config_put_create_or_error_if_exists(cfg, true); */ LOG(\[dq]Opening pmemkv database with \[aq]cmap\[aq] engine\[dq]); pmemkv_db *db = NULL; s = pmemkv_open(\[dq]cmap\[dq], cfg, &db); ASSERT(s == PMEMKV_STATUS_OK); ASSERT(db != NULL); LOG(\[dq]Putting new key\[dq]); const char *key1 = \[dq]key1\[dq]; const char *value1 = \[dq]value1\[dq]; s = pmemkv_put(db, key1, strlen(key1), value1, strlen(value1)); ASSERT(s == PMEMKV_STATUS_OK); size_t cnt; s = pmemkv_count_all(db, &cnt); ASSERT(s == PMEMKV_STATUS_OK); ASSERT(cnt == 1); LOG(\[dq]Reading key back\[dq]); char val[MAX_VAL_LEN]; s = pmemkv_get_copy(db, key1, strlen(key1), val, MAX_VAL_LEN, NULL); ASSERT(s == PMEMKV_STATUS_OK); ASSERT(!strcmp(val, \[dq]value1\[dq])); LOG(\[dq]Iterating existing keys\[dq]); const char *key2 = \[dq]key2\[dq]; const char *value2 = \[dq]value2\[dq]; const char *key3 = \[dq]key3\[dq]; const char *value3 = \[dq]value3\[dq]; pmemkv_put(db, key2, strlen(key2), value2, strlen(value2)); pmemkv_put(db, key3, strlen(key3), value3, strlen(value3)); pmemkv_get_all(db, &get_kv_callback, NULL); LOG(\[dq]Removing existing key\[dq]); s = pmemkv_remove(db, key1, strlen(key1)); ASSERT(s == PMEMKV_STATUS_OK); ASSERT(pmemkv_exists(db, key1, strlen(key1)) == PMEMKV_STATUS_NOT_FOUND); LOG(\[dq]Defragmenting the database\[dq]); s = pmemkv_defrag(db, 0, 100); ASSERT(s == PMEMKV_STATUS_OK); LOG(\[dq]Closing database\[dq]); pmemkv_close(db); return 0; } \f[R] .fi .SS Common usage mistake .PP Common mistake in pmemkv API usage (especially when using C++ API) is to dereference pointer to the data stored in pmemkv outside of a callback function scope. .IP .nf \f[C] std::string value; const char* ptr; size_t sz; kv->get(\[dq]key1\[dq], [&](string_view v) { /* Save pointer to the data to use it later outside of a callback scope */ ptr = v.data(); sz = v.size(); }); kv->remove(\[dq]key\[dq]); /* ERROR! * Using this pointer outside of a callback function may cause access to some random data * or a segmentation fault. At that point, ptr should be considered as invalid. */ value.append(ptr, sz); \f[R] .fi .SH SEE ALSO .PP \f[B]libpmemkv\f[R](7), \f[B]libpmemkv_config\f[R](3), \f[B]libpmemkv_iterator\f[R](3) and \f[B]\f[R]