.\" Automatically generated by Pandoc 2.9.2.1 .\" .TH "VMEMCACHE" "3" "2020-11-20" "PMDK - " "PMDK Programmer's Manual" .hy .\" Copyright 2018-2020, Intel Corporation .\" .\" Redistribution and use in source and binary forms, with or without .\" modification, are permitted provided that the following conditions .\" are met: .\" .\" * Redistributions of source code must retain the above copyright .\" notice, this list of conditions and the following disclaimer. .\" .\" * Redistributions in binary form must reproduce the above copyright .\" notice, this list of conditions and the following disclaimer in .\" the documentation and/or other materials provided with the .\" distribution. .\" .\" * Neither the name of the copyright holder nor the names of its .\" contributors may be used to endorse or promote products derived .\" from this software without specific prior written permission. .\" .\" THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS .\" "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT .\" LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR .\" A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT .\" OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, .\" SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT .\" LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, .\" DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY .\" THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT .\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE .\" OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. .SH NAME .PP \f[B]vmemcache\f[R] - buffer-based LRU cache .SH SYNOPSIS .IP .nf \f[C] #include VMEMcache *vmemcache_new(); void vmemcache_delete(VMEMcache *cache); int vmemcache_set_eviction_policy(VMEMcache *cache, enum vmemcache_repl_p repl_p); int vmemcache_set_size(VMEMcache *cache, size_t size); int vmemcache_set_extent_size(VMEMcache *cache, size_t extent_size); int vmemcache_add(VMEMcache *cache, const char *path); void vmemcache_callback_on_evict(VMEMcache *cache, vmemcache_on_evict *evict, void *arg); void vmemcache_callback_on_miss(VMEMcache *cache, vmemcache_on_miss *miss, void *arg); ssize_t vmemcache_get(VMEMcache *cache, const void *key, size_t key_size, void *vbuf, size_t vbufsize, size_t offset, size_t *vsize); int vmemcache_put(VMEMcache *cache, const void *key, size_t key_size, const void *value, size_t value_size); int vmemcache_exists(VMEMcache *cache, const void *key, size_t key_size); int vmemcache_evict(VMEMcache *cache, const void *key, size_t ksize); int vmemcache_get_stat(VMEMcache *cache, enum vmemcache_statistic stat, void *value, size_t value_size); const char *vmemcache_errormsg(void); \f[R] .fi .SH DESCRIPTION .PP \f[B]libvmemcache\f[R] is a volatile key-value store optimized for operating on NVDIMM based space, although it can work with any filesystem, stored in memory (tmpfs) or, less performant, on some kind of a disk. .SS Creation .TP \f[B]\f[CB]VMEMcache *vmemcache_new();\f[B]\f[R] Creates an empty unconfigured vmemcache instance. .TP \f[B]\f[CB]int vmemcache_set_size(VMEMcache *cache, size_t size);\f[B]\f[R] Sets the size of the cache; it will be rounded \f[B]up\f[R] towards a whole page size alignment (4KB on x86). .TP \f[B]\f[CB]int vmemcache_set_extent_size(VMEMcache *cache, size_t extent_size);\f[B]\f[R] Sets block size of the cache \[en] 256 bytes minimum, strongly recommended to be a multiple of 64 bytes. If the cache is backed by a non byte-addressable medium, the extent size should be 4096 (or a multiple) or performance will greatly suffer. .TP \f[B]\f[CB]int vmemcache_set_eviction_policy(VMEMcache *cache, enum vmemcache_repl_p repl_p);\f[B]\f[R] Sets what should happen on a put into a full cache. .RS .IP \[bu] 2 \f[B]VMEMCACHE_REPLACEMENT_NONE\f[R]: manual eviction only - puts into a full cache will fail .IP \[bu] 2 \f[B]VMEMCACHE_REPLACEMENT_LRU\f[R]: least recently accessed entry will be evicted to make space when needed .RE .TP \f[B]\f[CB]int vmemcache_add(VMEMcache *cache, const char *path);\f[B]\f[R] Associate the cache with a backing medium in the given \f[I]path\f[R], which may be: .RS .IP \[bu] 2 a \f[C]/dev/dax\f[R] device .IP \[bu] 2 a directory on a regular filesystem (which may or may not be mounted with -o dax, either on persistent memory or any other backing storage) .RE .TP \f[B]\f[CB]void vmemcache_delete(VMEMcache *cache);\f[B]\f[R] Frees any structures associated with the cache. .SS Use .TP \f[B]\f[CB]ssize_t vmemcache_get(VMEMcache *cache, const void *key, size_t key_size, void *vbuf, size_t vbufsize, size_t offset, size_t *vsize);\f[B]\f[R] Searches for an entry with the given \f[I]key\f[R]; it doesn\[cq]t have to be zero-terminated or be text - any sequence of bytes of length \f[I]key_size\f[R] is okay. If found, the entry\[cq]s value is copied to \f[I]vbuf\f[R] that has space for \f[I]vbufsize\f[R] bytes, optionally skipping \f[I]offset\f[R] bytes at the start. No matter if the copy was truncated or not, its true size is stored into \f[I]vsize\f[R]; \f[I]vsize\f[R] remains unmodified if the key was not found. .RS .PP Return value is number of bytes successfully copied, or -1 on error. In particular, if there\[cq]s no entry for the given \f[I]key\f[R] in the cache, the errno will be ENOENT. .RE .TP \f[B]\f[CB]int vmemcache_put(VMEMcache *cache, const void *key, size_t key_size, const void *value, size_t value_size);\f[B]\f[R] Inserts the given key:value pair into the cache. Returns 0 on success, -1 on error. Inserting a key that already exists will fail with EEXIST. .TP \f[B]\f[CB]int vmemcache_exists(VMEMcache *cache, const void *key, size_t key_size, size_t *vsize);\f[B]\f[R] Searches for an entry with the given \f[I]key\f[R], and returns 1 if found, 0 if not found, and -1 if search couldn\[cq]t be performed. The size of the found entry is stored into \f[I]vsize\f[R]; \f[I]vsize\f[R] remains unmodified if the key was not found. This function does not impact the replacement policy or statistics. .TP \f[B]\f[CB]int vmemcache_evict(VMEMcache *cache, const void *key, size_t ksize);\f[B]\f[R] Removes the given key from the cache. If \f[I]key\f[R] is null and there is a replacement policy set, the oldest entry will be removed. Returns 0 if an entry has been evicted, -1 otherwise. .SS Callbacks .PP You can register a hook to be called during eviction or after a cache miss, using \f[B]vmemcache_callback_on_evict()\f[R] or \f[B]vmemcache_callback_on_miss()\f[R], respectively: .PP \f[C]void vmemcache_callback_on_evict(VMEMcache *cache, vmemcache_on_evict *evict, void *arg);\f[R] .PP \f[C]void vmemcache_callback_on_miss(VMEMcache *cache, vmemcache_on_miss *miss, void *arg);\f[R] .PP The extra \f[I]arg\f[R] will be passed to your function. .PP A hook to be called during eviction has to have the following signature: .TP \f[B]\f[CB]void vmemcache_on_evict(VMEMcache *cache, const void *key, size_t key_size, void *arg);\f[B]\f[R] Called when an entry is being removed from the cache. The eviction can\[cq]t be prevented, but until the callback returns, the entry remains available for queries. The thread that triggered the eviction is blocked in the meantime. .PP A hook to be called after a cache miss has to have the following signature: .TP \f[B]\f[CB]void vmemcache_on_miss(VMEMcache *cache, const void *key, size_t key_size, void *arg);\f[B]\f[R] Called when a \f[I]get\f[R] query fails, to provide an opportunity to insert the missing key. If the callback calls \f[I]put\f[R] for that specific key, the \f[I]get\f[R] will return its value, even if it did not fit into the cache. .SS Misc .TP \f[B]\f[CB]int vmemcache_get_stat(VMEMcache *cache, enum vmemcache_statistic stat, void *value, size_t value_size);\f[B]\f[R] Obtains a piece of statistics about the cache. The \f[I]stat\f[R] may be: .RS .IP \[bu] 2 \f[B]VMEMCACHE_STAT_PUT\f[R] \[en] count of puts .IP \[bu] 2 \f[B]VMEMCACHE_STAT_GET\f[R] \[en] count of gets .IP \[bu] 2 \f[B]VMEMCACHE_STAT_HIT\f[R] \[en] count of gets that were served from the cache .IP \[bu] 2 \f[B]VMEMCACHE_STAT_MISS\f[R] \[en] count of gets that were not present in the cache .IP \[bu] 2 \f[B]VMEMCACHE_STAT_EVICT\f[R] \[en] count of evictions .IP \[bu] 2 \f[B]VMEMCACHE_STAT_ENTRIES\f[R] \[en] \f[I]current\f[R] number of cache entries (key:value pairs) .IP \[bu] 2 \f[B]VMEMCACHE_STAT_DRAM_SIZE_USED\f[R] \[en] current amount of DRAM used .IP \[bu] 2 \f[B]VMEMCACHE_STAT_POOL_SIZE_USED\f[R] \[en] current usage of data pool .IP \[bu] 2 \f[B]VMEMCACHE_STAT_HEAP_ENTRIES\f[R] \[en] current number of discontiguous unused regions (ie, free space fragmentation) .RE .PP Statistics are enabled by default. They can be disabled at the compile time of the vmemcache library if the \f[B]STATS_ENABLED\f[R] CMake option is set to OFF. .TP \f[B]\f[CB]const char *vmemcache_errormsg(void);\f[B]\f[R] Retrieves a human-friendly description of the last error. .SS Errors .PP On an error, a machine-usable description is passed in \f[C]errno\f[R]. It may be: .IP \[bu] 2 \f[B]EINVAL\f[R] \[en] nonsensical/invalid parameter .IP \[bu] 2 \f[B]ENOMEM\f[R] \[en] out of DRAM .IP \[bu] 2 \f[B]EEXIST\f[R] \[en] (put) entry for that key already exists .IP \[bu] 2 \f[B]ENOENT\f[R] \[en] (evict, get) no entry for that key .IP \[bu] 2 \f[B]ESRCH\f[R] \[en] (evict) could not find an evictable entry .IP \[bu] 2 \f[B]EAGAIN\f[R] \[en] (evict) an entry was used and could not be evicted, please try again .IP \[bu] 2 \f[B]ENOSPC\f[R] \[en] (create, put) not enough space in the memory pool