PMEMKV_CONFIG(3)

πŸ“¦ version 1.5.0, in ubuntu jammy

πŸ’– PMEMKV_CONFIG β€” like, the whole vibe πŸ’–

Welcome to the pmemkv_config manual page, bestie!! This is part of the PMEMKV Programmer's Manual (yes that's the manual name, it's giving ✨official✨) and it's literally the Configuration API for libpmemkv. Grab a snack, we're doing this. πŸ“


🌸 NAME 🌸

pmemkv_config β€” the Configuration API for libpmemkv, aka the lil clipboard where you write down all your settings before you hand them to pmemkv. πŸ’…


✨ SYNOPSIS ✨

okay so here's the whole lineup, no cap:

#include <libpmemkv.h>

pmemkv_config *pmemkv_config_new(void);
void pmemkv_config_delete(pmemkv_config *config);

int pmemkv_config_put_size(pmemkv_config *config, uint64_t value);
int pmemkv_config_put_path(pmemkv_config *config, const char *value);
int **deprecated** pmemkv_config_put_force_create(pmemkv_config *config,
                               bool value);
int pmemkv_config_put_create_or_error_if_exists(pmemkv_config *config, bool value);
int pmemkv_config_put_create_if_missing(pmemkv_config *config, bool value)
int pmemkv_config_put_comparator(pmemkv_config *config, pmemkv_comparator *comparator);
int pmemkv_config_put_oid(pmemkv_config *config, PMEMoid *oid);

int pmemkv_config_put_data(pmemkv_config *config, const char *key, const void *value,
            size_t value_size);
int pmemkv_config_put_object(pmemkv_config *config, const char *key, void *value,
            void (*deleter)(void *));
int pmemkv_config_put_object_cb(pmemkv_config *config, const char *key, void *value,
                    void *(*getter)(void *), void (*deleter)(void *));
int pmemkv_config_put_uint64(pmemkv_config *config, const char *key, uint64_t value);
int pmemkv_config_put_int64(pmemkv_config *config, const char *key, int64_t value);
int pmemkv_config_put_string(pmemkv_config *config, const char *key, const char *value);

int pmemkv_config_get_data(pmemkv_config *config, const char *key, const void **value,
            size_t *value_size);
int pmemkv_config_get_object(pmemkv_config *config, const char *key, void **value);
int pmemkv_config_get_uint64(pmemkv_config *config, const char *key, uint64_t *value);
int pmemkv_config_get_int64(pmemkv_config *config, const char *key, int64_t *value);
int pmemkv_config_get_string(pmemkv_config *config, const char *key, const char **value);

pmemkv_comparator *pmemkv_comparator_new(pmemkv_compare_function *fn, const char *name,
                             void *arg);
void pmemkv_comparator_delete(pmemkv_comparator *comparator);
🫢 quick heads up: that **deprecated** on pmemkv_config_put_force_create? Yeah, it's deprecated, we're gonna talk about it later, don't @ me.

For the general deets on pmemkv and all the engines you can pick from, go read libpmemkv(7). And for the lowdown on the pmemkv core API, that's libpmemkv(3). iykyk. πŸ“š


part 2 coming right up, don't go anywhere 🌈

✨ DESCRIPTION ✨

okay so bestie, listen πŸ‘‚ β€” a pmemkv database gets configured through a pmemkv_config structure. Think of it like a little purse πŸ‘œ where you stash your settings: it stores mappings of keys (those are null-terminated strings, no cap) to values.

and a value can be any of these cuties:

  • uint64_t
  • int64_t
  • c-style string
  • binary data
  • pointer to an object (with an accompanying deleter function) β€” yes she brings her own cleanup crew πŸ’…

It also delivers methods to store and read configuration items provided by a user. Once the config object is all set (every required parameter in place, nothing missing πŸ™ˆ), it can be passed to the pmemkv_open() method.

Which options a pmemkv database actually needs? That's specific to the engine, bestie β€” every engine has documented all its supported config parameters (please see libpmemkv(7) for the details πŸ‘‘).


🌱 pmemkv_config_new

pmemkv_config *pmemkv_config_new(void);

Creates an instance of configuration for a pmemkv database. On failure, NULL is returned. so if you get NULL, that's not a vibe check you passed 😭

πŸ—‘οΈ pmemkv_config_delete

void pmemkv_config_delete(pmemkv_config *config);

Deletes a pmemkv_config. Should be called ONLY for configs which were not passed to pmemkv_open (because that function moves ownership of the config over to the database β€” she's not yours anymore, periodt πŸ’…).

πŸ“ pmemkv_config_put_size

int pmemkv_config_put_size(pmemkv_config *config, uint64_t value);

Puts a value to a config at key size β€” it's required when creating a new database pool. This function provides type safety for the size parameter. slay πŸ”₯

πŸ›£οΈ pmemkv_config_put_path

int pmemkv_config_put_path(pmemkv_config *config, const char *value);

Puts a value to a config at key path. It's a path to a database file or to a poolset file (see poolset(5) for details), to open or create.

heads up bestie ⚠️ note that when using a poolset file, size should be 0.

This function provides type safety for the path parameter.

πŸ•°οΈ pmemkv_config_put_force_create

int pmemkv_config_put_force_create(pmemkv_config *config, bool value);

It is deprecated and kept for compatibility only 😬 It's an alias for pmemkv_config_put_create_or_error_if_exists β€” use that one instead, fr fr.

πŸ†• pmemkv_config_put_create_or_error_if_exists

int pmemkv_config_put_create_or_error_if_exists(pmemkv_config *config, bool value);

Puts a value to a config at key create_or_error_if_exists. This flag is mutually exclusive with create_if_missing. It works only with engines supporting this flag, and it means:

  • If true: pmemkv creates the pool, unless it exists β€” then it fails πŸ’€
  • If false: pmemkv</p> opens the pool, unless the path does not exist β€” then it fails πŸ’€

False by default.

🐣 pmemkv_config_put_create_if_missing

int pmemkv_config_put_create_if_missing(pmemkv_config *config, bool value);

Puts a value to a config at key create_if_missing. This flag is mutually exclusive with create_or_error_if_exists. It works only with engines supporting this flag, and it means:

  • If true: pmemkv tries to open the pool, and if that doesn't succeed it means there's (most likely) no pool to use β€” so it tries to create it 🫢
  • If false: pmemkv opens the pool, unless the path does not exist β€” then it fails πŸ’€

False by default.

🧠 pmemkv_config_put_comparator

int pmemkv_config_put_comparator(pmemkv_config *config, pmemkv_comparator *comparator);

Puts a comparator object into a config. To create an instance of a pmemkv_comparator object, the pmemkv_comparator_new() function should be used. iykyk ✨

πŸ†” pmemkv_config_put_oid

int pmemkv_config_put_oid(pmemkv_config *config, PMEMoid *oid);

Puts a PMEMoid object into a config (for details see libpmemkv(7)).

πŸ”’ pmemkv_config_put_uint64

int pmemkv_config_put_uint64(pmemkv_config *config, const char *key, uint64_t value);

Puts the uint64_t value to pmemkv_config at key key.

πŸ”’ pmemkv_config_put_int64

int pmemkv_config_put_int64(pmemkv_config *config, const char *key, int64_t value);

Puts the int64_t value to pmemkv_config at key key.

πŸŽ€ pmemkv_config_put_string

int pmemkv_config_put_string(pmemkv_config *config, const char *key, const char *value);

Puts a null-terminated string into pmemkv_config. The string is copied to the config β€” she's keeping a lil' copy for herself, obsessed πŸ’–

🧬 pmemkv_config_put_data

int pmemkv_config_put_data(pmemkv_config *config, const char *key, const void *value, size_t value_size);

Puts a copy of the binary data pointed to by value into pmemkv_config. value_size specifies the size of the data.

πŸ“¦ pmemkv_config_put_object

int pmemkv_config_put_object(pmemkv_config *config, const char *key, void *value, void (*deleter)(void *));

Puts value into pmemkv_config. value can point to an arbitrary object. The deleter parameter specifies the function which will be called for value when the config is destroyed (using pmemkv_config_delete). so like, she'll clean up after herself when the time comes 🧹✨

πŸͺ„ pmemkv_config_put_object_cb

int pmemkv_config_put_object_cb(pmemkv_config *config, const char *key, void *value, void *(*getter)(void *), void (*deleter)(void *));

Extended version of pmemkv_config_put_object. It accepts one additional argument β€” a getter callback. This callback interprets the custom object (value) and returns a pointer which is expected by pmemkv.

Calling pmemkv_config_put_object_cb with getter implemented as:

void *getter(void *arg) { return arg; }

is equivalent to calling pmemkv_config_put_object. same energy, different font πŸ’…

πŸ” pmemkv_config_get_uint64

int pmemkv_config_get_uint64(pmemkv_config *config, const char *key, uint64_t *value);

Gets the value of a config item with key key. The value is copied to the variable pointed to by value.

πŸ” pmemkv_config_get_int64

int pmemkv_config_get_int64(pmemkv_config *config, const char *key, int64_t *value);

Gets the value of a config item with key key. The value is copied to the variable pointed to by value.

πŸŽ€ pmemkv_config_get_string

int pmemkv_config_get_string(pmemkv_config *config, const char *key, const char **value);

Gets a pointer to a null-terminated string. The string is not copied πŸš«πŸ“‹ After a successful call, value points to the string stored in pmemkv_config.

🧬 pmemkv_config_get_data

int pmemkv_config_get_data(pmemkv_config *config, const char *key, const void **value, size_t *value_size);

Gets a pointer to binary data. The data is not copied. After a successful call, *value points to the data stored in pmemkv_config and value_size holds the size of the data.

πŸ“¦ pmemkv_config_get_object

int pmemkv_config_get_object(pmemkv_config *config, const char *key, const void **value);

Gets a pointer to an object. After a successful call, *value points to the object.


🚨 the type-matching rule (do NOT skip this bestie)

Config items stored in pmemkv_config which were put using a specific function can be obtained only using the corresponding pmemkv_config_get_ function β€” for example, config items put using pmemkv_config_put_object can only be obtained using pmemkv_config_get_object. no mix-and-match, she said what she said πŸ’…

The exception from this rule are the functions for uint64 and int64. If a value put by pmemkv_config_put_int64 is in uint64_t range, it can be obtained using pmemkv_config_get_uint64 β€” and vice versa. see, they're flexible like that πŸ¦‹


🧠 pmemkv_comparator_new

pmemkv_comparator *pmemkv_comparator_new(pmemkv_compare_function *fn, const char *name, void *arg);

Creates an instance of a comparator object. Accepts a comparison function fn, name and arg. In case of persistent engines, name is stored within the engine. An attempt to open a database which was created with a different comparator of a different name will fail with PMEMKV_STATUS_COMPARATOR_MISMATCH πŸ’€ arg is saved in the comparator and passed to the comparison function on each invocation.

Neither fn nor name can be NULL. 🚫

fn should perform a three-way comparison. Return values:

  • a negative value if the first key is less than the second one
  • zero if both keys are the same
  • a positive value if the first key is greater than the second one

The comparison function should be thread safe β€” it can be called from multiple threads. no chaotic energy allowed, she multi-tasks responsibly 🧚

On failure, NULL is returned.

πŸ—‘οΈ pmemkv_comparator_delete

void pmemkv_comparator_delete(pmemkv_comparator *comparator);

Removes the comparator object. Should be called ONLY for comparators which were not put to config (because the config takes ownership of the comparator β€” again, she's not yours anymore 😭).


To set a comparator for the database use pmemkv_config_put_object:

pmemkv_comparator *cmp = pmemkv_comparator_new(&compare_fn, "my_comparator", NULL);

pmemkv_config_put_object(cfg, "comparator", cmp, (void (*)(void *)) & pmemkv_comparator_delete);

πŸ’€ ERRORS πŸ’€

Every function, except for pmemkv_config_new() and pmemkv_config_delete(), returns a status. Possible return values are:

  • PMEMKV_STATUS_OK β€” no error, we ate and left no crumbs πŸ”₯
  • PMEMKV_STATUS_UNKNOWN_ERROR β€” unknown error πŸ‘€
  • PMEMKV_STATUS_NOT_FOUND β€” record (or config item) not found πŸ•΅οΈ
  • PMEMKV_STATUS_CONFIG_PARSING_ERROR β€” parsing data to config failed 😭
  • PMEMKV_STATUS_CONFIG_TYPE_ERROR β€” config item has a different type than expected 🚫

πŸŽ€ EXAMPLE πŸŽ€

These cuties are straight out of the examples/pmemkv_config_c directory, so you know they're legit. πŸ’–

🌸 BASIC EXAMPLE 🌸

This one's the classic β€” using the basic config functions to set parameters by what they do, like pmemkv_config_put_path() or pmemkv_config_put_size(). It's giving "I just want my config set up and I don't need it to be fancy." πŸ’…

#include <assert.h>
#include <libpmemkv.h>
#include <libpmemobj/pool_base.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#define ASSERT(expr)                                                                     \
    do {                                                                             \
        if (!(expr))                                                             \
            puts(pmemkv_errormsg());                                         \
        assert(expr);                                                            \
    } while (0)

static const uint64_t SIZE = 1024UL * 1024UL * 1024UL;

int key_length_compare(const char *key1, size_t keybytes1, const char *key2,
               size_t keybytes2, void *arg)
{
    if (keybytes2 < keybytes1)
        return -1;
    else if (keybytes2 > keybytes1)
        return 1;
    else
        return 0;
}

int main(int argc, char *argv[])
{
    if (argc < 2) {
        fprintf(stderr, "Usage: %s file\n", argv[0]);
        exit(1);
    }

    /* Create config */
    pmemkv_config *config = pmemkv_config_new();
    ASSERT(config != NULL);

    /* Add path parameter to config. Meaning of this is dependent on chosen engine.
     *  E.g. if config is used with cmap engine,
     *  it is a path to a database file or to a poolset file. However for
     *  vcmap it is a path to an existing directory */
    int status = pmemkv_config_put_path(config, argv[1]);
    ASSERT(status == PMEMKV_STATUS_OK);

    /* Specifies size of the database */
    status = pmemkv_config_put_size(config, SIZE);
    ASSERT(status == PMEMKV_STATUS_OK);

    /* Specifies value of create_if_missing flag.
     * Alternatively, another flag - 'create_or_error_if_exists' can be set using:
     * `pmemkv_config_put_create_or_error_if_exists`
     * For differences between the two, see manpage libpmemkv(7). */
    status = pmemkv_config_put_create_if_missing(config, true);
    ASSERT(status == PMEMKV_STATUS_OK);

    /* Specifies comparator used by the engine */
    pmemkv_comparator *cmp =
        pmemkv_comparator_new(&key_length_compare, "key_length_compare", NULL);
    ASSERT(cmp != NULL);
    status = pmemkv_config_put_comparator(config, cmp);
    ASSERT(status == PMEMKV_STATUS_OK);

    /* Adds pointer to oid (for details see libpmemkv(7)) to the config */
    PMEMoid oid;
    status = pmemkv_config_put_oid(config, &oid);
    ASSERT(status == PMEMKV_STATUS_OK);

    pmemkv_config_delete(config);

    return 0;
}

πŸ¦‹ TYPE BASED CONFIGURATION EXAMPLE πŸ¦‹

And this one is the glow-up β€” setting and getting data based on the actual data type, like pmemkv_config_put_int64() or pmemkv_config_put_object(). Lowkey obsessed with how tidy this is. ✨

#include <assert.h>
#include <libpmemkv.h>
#include <libpmemkv_json_config.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#define ASSERT(expr)                                                                     \
    do {                                                                             \
        if (!(expr))                                                             \
            puts(pmemkv_errormsg());                                         \
        assert(expr);                                                            \
    } while (0)

/* deleter for int pointer */
void free_int_ptr(void *ptr)
{
    free(ptr);
}

int main()
{
    pmemkv_config *config = pmemkv_config_new();
    ASSERT(config != NULL);

    /* Put int64_t value */
    int status = pmemkv_config_put_int64(config, "size", 1073741824);
    ASSERT(status == PMEMKV_STATUS_OK);

    char buffer[] = "ABC";

    /* Put binary data stored in buffer */
    status = pmemkv_config_put_data(config, "binary", buffer, 3);
    ASSERT(status == PMEMKV_STATUS_OK);

    const void *data;
    size_t data_size;

    /* Get pointer to binary data stored in config */
    status = pmemkv_config_get_data(config, "binary", &data, &data_size);
    ASSERT(status == PMEMKV_STATUS_OK);
    ASSERT(data_size == 3);
    ASSERT(((const char *)data)[0] == 'A');

    int *int_ptr = malloc(sizeof(int));
    ASSERT(int_ptr != NULL);
    *int_ptr = 10;

    /* Put pointer to dynamically allocated object, free_int_ptr is called on
     * pmemkv_config_delete */
    status = pmemkv_config_put_object(config, "int_ptr", int_ptr, &free_int_ptr);
    ASSERT(status == PMEMKV_STATUS_OK);

    int *get_int_ptr;

    /* Get pointer to object stored in config */
    status = pmemkv_config_get_object(config, "int_ptr", (void **)&get_int_ptr);
    ASSERT(status == PMEMKV_STATUS_OK);
    ASSERT(*get_int_ptr == 10);

    pmemkv_config_delete(config);

    pmemkv_config *config_from_json = pmemkv_config_new();
    ASSERT(config_from_json != NULL);

    /* Parse JSON and put all items found into config_from_json */
    status = pmemkv_config_from_json(config_from_json, "{\"path\":\"/dev/shm\",\
         \"size\":1073741824,\
         \"subconfig\":{\
            \"size\":1073741824\
            }\
        }");
    ASSERT(status == PMEMKV_STATUS_OK);

    const char *path;
    status = pmemkv_config_get_string(config_from_json, "path", &path);
    ASSERT(status == PMEMKV_STATUS_OK);
    ASSERT(strcmp(path, "/dev/shm") == 0);

    pmemkv_config *subconfig;

    /* Get pointer to nested configuration "subconfig" */
    status = pmemkv_config_get_object(config_from_json, "subconfig",
                      (void **)&subconfig);
    ASSERT(status == PMEMKV_STATUS_OK);

    size_t sub_size;
    status = pmemkv_config_get_uint64(subconfig, "size", &sub_size);
    ASSERT(status == PMEMKV_STATUS_OK);
    ASSERT(sub_size == 1073741824);

    pmemkv_config_delete(config_from_json);

    return 0;
}

🌈 SEE ALSO 🌈

Go read these next, bestie β€” they're the friend group of this page, fr fr:


And that's a wrap on PMEMKV_CONFIG(3)! 🫢 This one shipped as part of pmemkv version 1.5.0, dated 2022-03-09. Thanks for reading all three parts, you're literally the main character. πŸ‘‘βœ¨πŸ’–

πŸ“¦ where this page comes from