persistent-cache-cpp
core::PersistentStringCache Class Reference

A cache of key-value pairs with persistent storage. More...

#include <core/persistent_string_cache.h>

Classes

struct  Data
 Simple pair of value and metadata. More...
 

Public Types

typedef std::unique_ptr< PersistentStringCacheUPtr
 

Public Member Functions

Copy and Assignment

Cache instances are not copyable, but can be moved.

Note
The constructors are private. Use one of the open() static member functions to create or open a cache.
 PersistentStringCache (PersistentStringCache const &)=delete
 
PersistentStringCacheoperator= (PersistentStringCache const &)=delete
 
 PersistentStringCache (PersistentStringCache &&)
 
PersistentStringCacheoperator= (PersistentStringCache &&)
 
 ~PersistentStringCache ()
 
Accessors
Optional< std::string > get (std::string const &key) const
 Returns the value of an entry in the cache, provided the entry has not expired.
 
Optional< Dataget_data (std::string const &key) const
 Returns the data for an entry in the cache, provided the entry has not expired.
 
Optional< std::string > get_metadata (std::string const &key) const
 Returns the metadata for an entry in the cache, provided the entry has not expired.
 
bool contains_key (std::string const &key) const
 Tests if an (unexpired) entry is in the cache.
 
int64_t size () const noexcept
 Returns the number of entries in the cache.
 
int64_t size_in_bytes () const noexcept
 Returns the number of bytes consumed by entries in the cache.
 
int64_t max_size_in_bytes () const noexcept
 Returns the maximum size of the cache in bytes.
 
int64_t disk_size_in_bytes () const
 Returns an estimate of the disk space consumed by the cache.
 
CacheDiscardPolicy discard_policy () const noexcept
 Returns the discard policy of the cache.
 
PersistentCacheStats stats () const
 Returns statistics for the cache.
 

Static Public Member Functions

Creation Methods
static UPtr open (std::string const &cache_path, int64_t max_size_in_bytes, CacheDiscardPolicy policy)
 Creates or opens a PersistentStringCache.
 
static UPtr open (std::string const &cache_path)
 Opens an existing PersistentStringCache.
 

Modifiers

typedef std::function< void(std::string const &key, PersistentStringCache &cache)> Loader
 Function called by the cache to load an entry after a cache miss.
 
bool put (std::string const &key, std::string const &value, std::chrono::time_point< std::chrono::system_clock > expiry_time=std::chrono::system_clock::time_point())
 Adds or updates an entry.
 
bool put (std::string const &key, char const *value, int64_t size, std::chrono::time_point< std::chrono::system_clock > expiry_time=std::chrono::system_clock::time_point())
 Adds or updates an entry.
 
bool put (std::string const &key, std::string const &value, std::string const &metadata, std::chrono::time_point< std::chrono::system_clock > expiry_time=std::chrono::system_clock::time_point())
 Adds or updates an entry and its metadata.
 
bool put (std::string const &key, char const *value, int64_t value_size, char const *metadata, int64_t metadata_size, std::chrono::time_point< std::chrono::system_clock > expiry_time=std::chrono::system_clock::time_point())
 Adds or updates an entry and its metadata.
 
Optional< std::string > get_or_put (std::string const &key, Loader const &load_func)
 Atomically retrieves or stores a cache entry.
 
Optional< Dataget_or_put_data (std::string const &key, Loader const &load_func)
 Atomically retrieves or stores a cache entry.
 
bool put_metadata (std::string const &key, std::string const &metadata)
 Adds or replaces the metadata for an entry.
 
bool put_metadata (std::string const &key, char const *metadata, int64_t size)
 Adds or replaces the metadata for an entry.
 
Optional< std::string > take (std::string const &key)
 Removes an entry and returns its value.
 
Optional< Datatake_data (std::string const &key)
 Removes an entry and returns its value and metadata.
 
bool invalidate (std::string const &key)
 Removes an entry and its associated metadata (if any).
 
void invalidate (std::vector< std::string > const &keys)
 Atomically removes the specified entries from the cache.
 
template<typename It >
void invalidate (It begin, It end)
 Atomically removes the specified entries from the cache.
 
void invalidate (std::initializer_list< std::string > const &keys)
 Atomically removes the specified entries from the cache.
 
void invalidate ()
 Deletes all entries from the cache.
 
bool touch (std::string const &key, std::chrono::time_point< std::chrono::system_clock > expiry_time=std::chrono::system_clock::time_point())
 Updates the access time of an entry.
 
void clear_stats ()
 Resets all statistics counters.
 
void resize (int64_t size_in_bytes)
 Changes the maximum size of the cache.
 
void trim_to (int64_t used_size_in_bytes)
 Expires entries.
 
void compact ()
 Compacts the database.
 

Monitoring cache activity

The cache allows you to register one or more callback functions that are called when the cache contents change.

Note
Callback functions are called by the application thread that triggered the corresponding event.
Warning
Do not invoke operations on the cache from within a callback function. Doing so has undefined behavior.
typedef std::function< void(std::string const &key, CacheEvent ev, PersistentCacheStats const &stats)> EventCallback
 The type of a handler function.
 
void set_handler (CacheEvent events, EventCallback cb)
 Installs a handler for one or more events.
 

Detailed Description

A cache of key-value pairs with persistent storage.

PersistentStringCache provides a cache of string key-value pairs with a backing store. It is intended for caching arbitrary (possibly large) amounts of data, such as might be needed by a web browser cache.

See Overview for a more detailed description.

Usage example

Typical use looks something like this:

// Open cache or create it if it does not exist.
// Look for an entry. If it doesn't exist, add it.
string key = "some_key";
auto value = c->get(key);
if (value)
{
cout << *value << endl;
}
else
{
string v = "some value";
c->put(key, v);
}
static UPtr open(std::string const &cache_path, int64_t max_size_in_bytes, CacheDiscardPolicy policy)
Creates or opens a PersistentStringCache.
@ lru_only
Evict in LRU order.

Member Typedef Documentation

◆ EventCallback

typedef std::function<void(std::string const& key, CacheEvent ev, PersistentCacheStats const& stats)> core::PersistentStringCache::EventCallback

The type of a handler function.

Note
Callback functions are called by the application thread that triggered the corresponding event.
Warning
Do not invoke operations on the cache from within a callback function. Doing so has undefined behavior.
Parameters
keyThe key of the entry.
evThe event type.
statsThe cache statistics. Note that the stats parameter reflects the state of the cache after the corresponding event. For example, for a Put event, stats.size_in_bytes() includes the size of the added entry.

◆ Loader

typedef std::function<void(std::string const& key, PersistentStringCache& cache)> core::PersistentStringCache::Loader

Function called by the cache to load an entry after a cache miss.

◆ UPtr

Convenience typedef for the return type of open().

Constructor & Destructor Documentation

◆ PersistentStringCache() [1/2]

core::PersistentStringCache::PersistentStringCache ( PersistentStringCache const &  )
delete

◆ PersistentStringCache() [2/2]

core::PersistentStringCache::PersistentStringCache ( PersistentStringCache &&  )

◆ ~PersistentStringCache()

core::PersistentStringCache::~PersistentStringCache ( )

Destroys the instance.

Member Function Documentation

◆ clear_stats()

void core::PersistentStringCache::clear_stats ( )

Resets all statistics counters.

◆ compact()

void core::PersistentStringCache::compact ( )

Compacts the database.

This operation compacts the database to consume as little disk space as possible. Note that this operation can be slow. (Compacting a 100 MB cache can take around ten seconds on a machine with a spinning-platter disk.)

◆ contains_key()

bool core::PersistentStringCache::contains_key ( std::string const &  key) const

Tests if an (unexpired) entry is in the cache.

Parameters
keyThe key for the entry.
Returns
true if the entry is in the cache; false otherwise.
Exceptions
invalid_argumentkey is the empty string.
Note
This operation does not update the access time of the entry.
See also
touch()

◆ discard_policy()

CacheDiscardPolicy core::PersistentStringCache::discard_policy ( ) const
noexcept

Returns the discard policy of the cache.

Returns
The discard policy (lru_only or lru_ttl).

◆ disk_size_in_bytes()

int64_t core::PersistentStringCache::disk_size_in_bytes ( ) const

Returns an estimate of the disk space consumed by the cache.

Returns
The approximate number of bytes used by the cache on disk.
Note
The returned size may be smaller than the eventual size if there are updates to the cache that have not yet been written to disk.

◆ get()

Optional< std::string > core::PersistentStringCache::get ( std::string const &  key) const

Returns the value of an entry in the cache, provided the entry has not expired.

Parameters
keyThe key for the entry.
Returns
A null value if the entry could not be retrieved; the value of the entry, otherwise.
Exceptions
invalid_argumentkey is the empty string.
Note
This operation updates the access time of the entry.

◆ get_data()

Optional< Data > core::PersistentStringCache::get_data ( std::string const &  key) const

Returns the data for an entry in the cache, provided the entry has not expired.

Parameters
keyThe key for the entry.
Returns
A null value if the entry could not be retrieved; the data of the entry, otherwise. If no metadata exists, Data::metadata is set to the empty string.
Exceptions
invalid_argumentkey is the empty string.
Note
This operation updates the access time of the entry.

◆ get_metadata()

Optional< std::string > core::PersistentStringCache::get_metadata ( std::string const &  key) const

Returns the metadata for an entry in the cache, provided the entry has not expired.

Parameters
keyThe key for the entry.
Returns
A null value if the entry could not be retrieved; the metadata of the entry, otherwise.
Exceptions
invalid_argumentkey is the empty string.
Note
This operation does not update the access time of the entry.
See also
touch()

◆ get_or_put()

Optional< std::string > core::PersistentStringCache::get_or_put ( std::string const &  key,
Loader const &  load_func 
)

Atomically retrieves or stores a cache entry.

get_or_put attempts to retrieve the value of a (non-expired) entry. If the entry can be found, it returns its value. Otherwise, it calls load_func, which is expected to add the entry to the cache. If the load function succeeds in adding the entry, the value added by the load function is returned. The load function is called by the application thread.

Returns
A null value if the entry could not be retrieved or loaded; the value of the entry, otherwise.
Exceptions
runtime_errorThe load function threw an exception.
Note
The load function must (synchronously) call one of the overloaded put methods to add a new entry for the provided key. Calling any other method on the cache from within the load function causes undefined behavior.
Warning
This operation holds a lock on the cache while the load function runs. This means that, if multiple threads call into the cache, they will be blocked for the duration of the load function.

◆ get_or_put_data()

Optional< Data > core::PersistentStringCache::get_or_put_data ( std::string const &  key,
Loader const &  load_func 
)

Atomically retrieves or stores a cache entry.

get_or_put attempts to retrieve the value and metadata of a (non-expired) entry. If the entry can be found, it returns its data. Otherwise, it calls load_func, which is expected to add the entry to the cache. If the load function succeeds in adding the entry, the data added by the load function is returned. The load function is called by the application thread.

Returns
A null value if the entry could not be retrieved or loaded; the value and metadata of the entry, otherwise.
Exceptions
runtime_errorThe load function threw an exception.
Note
The load function must (synchronously) call one of the overloaded put methods to add a new entry for the provided key. Calling any other method on the cache from within the load function causes undefined behavior.
Warning
This operation holds a lock on the cache while the load function runs. This means that, if multiple threads call into the cache, they will be blocked for the duration of the load function.

◆ invalidate() [1/5]

void core::PersistentStringCache::invalidate ( )

Deletes all entries from the cache.

This operation completely empties the cache.

Note
Clearing the cache also resets the statistics counters.
See also
clear_stats()

◆ invalidate() [2/5]

template<typename It >
void core::PersistentStringCache::invalidate ( It  begin,
It  end 
)
inline

Atomically removes the specified entries from the cache.

Parameters
beginIterator to the first key for the entries to be removed.
endIterator to the one-beyond-the-last key for the entries to be removed.

If the iterator range is empty, this operation is a no-op. If one or more keys are empty or specify non-existent entries, they are ignored.

◆ invalidate() [3/5]

void core::PersistentStringCache::invalidate ( std::initializer_list< std::string > const &  keys)

Atomically removes the specified entries from the cache.

Parameters
keysThe keys for the entries to be removed. If keys is empty, this operation is a no-op. If one or more keys are empty or specify non-existent entries, they are ignored.

◆ invalidate() [4/5]

bool core::PersistentStringCache::invalidate ( std::string const &  key)

Removes an entry and its associated metadata (if any).

If a (non-expired) entry with the given key can be found, it is removed from the cache.

Returns
true if the entry was removed; false if the entry could not be found or was expired.
Exceptions
invalid_argumentkey is the empty string.

◆ invalidate() [5/5]

void core::PersistentStringCache::invalidate ( std::vector< std::string > const &  keys)

Atomically removes the specified entries from the cache.

Parameters
keysA vector of keys for the entries to be removed. If the vector is empty, this operation is a no-op. If one or more keys are empty or specify non-existent entries, they are ignored.

◆ max_size_in_bytes()

int64_t core::PersistentStringCache::max_size_in_bytes ( ) const
noexcept

Returns the maximum size of the cache in bytes.

Returns
The maximum number of bytes that can be stored in the cache.
See also
resize()

◆ open() [1/2]

static UPtr core::PersistentStringCache::open ( std::string const &  cache_path)
static

Opens an existing PersistentStringCache.

Parameters
cache_pathThe path to a directory containing the existing cache.
Returns
A unique_ptr to the instance.

◆ open() [2/2]

static UPtr core::PersistentStringCache::open ( std::string const &  cache_path,
int64_t  max_size_in_bytes,
CacheDiscardPolicy  policy 
)
static

Creates or opens a PersistentStringCache.

If no cache exists on disk, it will be created; otherwise, the pre-existing cache contents are used.

An existing cache can be opened only if max_size_in_bytes and policy have the same values they had when the cache was last closed.

Parameters
cache_pathThe path to a directory in which to store the cache. The contents of this directory are exlusively owned by the cache; do not create additional files or directories there. The directory need not exist when creating a new cache.
max_size_in_bytesThe maximum size in bytes for the cache.
policyThe discard policy for the cache (lru_only or lru_ttl). The discard policy cannot be changed once a cache has been created.

The size of an entry is the sum of the sizes of its key, value, and metadata. The maximum size of the cache is the sum of the sizes of all its entries.

Returns
A unique_ptr to the instance.
Exceptions
invalid_argumentmax_size_in_bytes is < 1.
logic_errormax_size_in_bytes or policy do not match the settings of a pre-existing cache.

◆ operator=() [1/2]

PersistentStringCache & core::PersistentStringCache::operator= ( PersistentStringCache &&  )

◆ operator=() [2/2]

PersistentStringCache & core::PersistentStringCache::operator= ( PersistentStringCache const &  )
delete

◆ put() [1/4]

bool core::PersistentStringCache::put ( std::string const &  key,
char const *  value,
int64_t  size,
std::chrono::time_point< std::chrono::system_clock >  expiry_time = std::chrono::system_clock::time_point() 
)

Adds or updates an entry.

Note
This overload is provided to avoid the need to construct a string value.

If an entry with the given key does not exist in the cache, it is added (possibly evicting a number of expired and/or older entries). If the entry still exists (whether expired or not), it is updated with the new value (and possibly expiry time).

This operation deletes any metadata associated with the entry.

Returns
true if the entry was added or updated. false if the policy is lru_ttl and expiry_time is in the past.
Parameters
keyThe key of the entry.
valueA pointer to the first byte of the value.
sizeThe size of the value in bytes.
expiry_timeThe time at which the entry expires.
Exceptions
invalid_argumentkey is the empty string.
invalid_argumentvalue is nullptr.
invalid_argumentsize is negative.
logic_errorThe size of the entry exceeds the maximum cache size.
logic_errorThe cache policy is lru_only and a non-infinite expiry time was provided.

◆ put() [2/4]

bool core::PersistentStringCache::put ( std::string const &  key,
char const *  value,
int64_t  value_size,
char const *  metadata,
int64_t  metadata_size,
std::chrono::time_point< std::chrono::system_clock >  expiry_time = std::chrono::system_clock::time_point() 
)

Adds or updates an entry and its metadata.

Note
This overload is provided to avoid the need to construct strings for the value and metadata.

If an entry with the given key does not exist in the cache, it is added (possibly evicting a number of expired and/or older entries). If the entry still exists (whether expired or not), it is updated with the new value and metadata (and possibly expiry time).

Returns
true if the entry was added or updated. false if the policy is lru_ttl and expiry_time is in the past.
Parameters
keyThe key of the entry.
valueA pointer to the first byte of the value.
value_sizeThe size of the value in bytes.
metadataA pointer to the first byte of the metadata.
metadata_sizeThe size of the metadata in bytes.
expiry_timeThe time at which the entry expires.
Exceptions
invalid_argumentkey is the empty string.
logic_errorThe sum of sizes of the entry and metadata exceeds the maximum cache size.
logic_errorThe cache policy is lru_only and a non-infinite expiry time was provided.

◆ put() [3/4]

bool core::PersistentStringCache::put ( std::string const &  key,
std::string const &  value,
std::chrono::time_point< std::chrono::system_clock >  expiry_time = std::chrono::system_clock::time_point() 
)

Adds or updates an entry.

If an entry with the given key does not exist in the cache, it is added (possibly evicting a number of expired and/or older entries). If the entry still exists (whether expired or not), it is updated with the new value (and possibly expiry time).

This operation deletes any metadata associated with the entry.

Returns
true if the entry was added or updated. false if the policy is lru_ttl and expiry_time is in the past.
Exceptions
invalid_argumentkey is the empty string.
logic_errorThe size of the entry exceeds the maximum cache size.
logic_errorThe cache policy is lru_only and a non-infinite expiry time was provided.

◆ put() [4/4]

bool core::PersistentStringCache::put ( std::string const &  key,
std::string const &  value,
std::string const &  metadata,
std::chrono::time_point< std::chrono::system_clock >  expiry_time = std::chrono::system_clock::time_point() 
)

Adds or updates an entry and its metadata.

If an entry with the given key does not exist in the cache, it is added (possibly evicting a number of expired and/or older entries). If the entry still exists (whether expired or not), it is updated with the new value and metadata (and possibly expiry time).

Returns
true if the entry was added or updated. false if the policy is lru_ttl and expiry_time is in the past.
Exceptions
invalid_argumentkey is the empty string.
logic_errorThe sum of sizes of the entry and metadata exceeds the maximum cache size.
logic_errorThe cache policy is lru_only and a non-infinite expiry time was provided.

◆ put_metadata() [1/2]

bool core::PersistentStringCache::put_metadata ( std::string const &  key,
char const *  metadata,
int64_t  size 
)

Adds or replaces the metadata for an entry.

Note
This overload is provided to avoid the need to construct a string for the metadata.

If a (non-expired) entry with the given key exists in the cache, its metadata is set to the provided value, replacing any previous metadata.

Parameters
keyThe key of the entry.
metadataA pointer to the first byte of the metadata.
sizeThe size of the metadata in bytes.
Returns
true if the metadata was added or updated. false if the entry could not be found or was expired.
Exceptions
invalid_argumentkey is the empty string.
invalid_argumentmetadata is nullptr.
invalid_argumentsize is negative.
logic_errorThe new size of the entry would exceed the maximum cache size.
Note
This operation does not update the access time of the entry.
See also
touch()

◆ put_metadata() [2/2]

bool core::PersistentStringCache::put_metadata ( std::string const &  key,
std::string const &  metadata 
)

Adds or replaces the metadata for an entry.

If a (non-expired) entry with the given key exists in the cache, its metadata is set to the provided value, replacing any previous metadata.

Returns
true if the metadata was added or updated. false if the entry could not be found or was expired.
Exceptions
invalid_argumentkey is the empty string.
logic_errorThe new size of the entry would exceed the maximum cache size.
Note
This operation does not update the access time of the entry.
See also
touch()

◆ resize()

void core::PersistentStringCache::resize ( int64_t  size_in_bytes)

Changes the maximum size of the cache.

If size_in_bytes is greater or equal to max_size_in_bytes(), the cache size is set to size_in_bytes.

If size_in_bytes is less than max_size_in_bytes(), the cache discards existing entries until the size falls to (or below) size_in_bytes and sets the cache size to the new value.

Exceptions
invalid_argumentsize_in_bytes is < 1
Note
If the new size is less than the current size, this operation compacts the database to use the smallest possible amount of disk space.

◆ set_handler()

void core::PersistentStringCache::set_handler ( CacheEvent  events,
EventCallback  cb 
)

Installs a handler for one or more events.

Parameters
eventsA bitwise OR of the event types for which to install the handler. To install a handler for all events, you can use core::AllCacheEvents.
cbThe handler to install. To cancel an existing handler, pass nullptr.

For example, to install a handler for get and put events, you could use:

auto cache = PersistentStringCache::open("my_cache");
auto handler = [](string const& key, CacheEvent event, PersistentCacheStats const& stats)
{
// ...
};
cache->set_handler(CacheEvent::get | CacheEvent::put, handler);
Class that provides (read-only) access to cache statistics and settings.
Definition persistent_cache_stats.h:43
PersistentCacheStats stats() const
Returns statistics for the cache.
CacheEvent
Event types that can be monitored.
Definition cache_events.h:39
@ put
An entry was added by a call to put() or get_or_put().
@ get
An entry was returned by a call to get(), get_or_put(), take(), or take_data().
See also
CacheEvent

◆ size()

int64_t core::PersistentStringCache::size ( ) const
noexcept

Returns the number of entries in the cache.

Returns
The total number of entries in the cache.
Note
The returned count includes possibly expired entries.

◆ size_in_bytes()

int64_t core::PersistentStringCache::size_in_bytes ( ) const
noexcept

Returns the number of bytes consumed by entries in the cache.

Returns
The total number of bytes in the cache.
Note
The returned size includes possibly expired entries.

◆ stats()

PersistentCacheStats core::PersistentStringCache::stats ( ) const

Returns statistics for the cache.

The returned statistics are persistent and are restored the next time an existing cache is opened. Call clear_stats() to explicitly reset the statistics counters and time stamps to zero.

Returns
An object that provides accessors to statistics and settings.
See also
clear_stats()

◆ take()

Optional< std::string > core::PersistentStringCache::take ( std::string const &  key)

Removes an entry and returns its value.

If a (non-expired) entry with the given key can be found, it is removed from the cache and its value returned.

Returns
A null value if the entry could not be found; the value of the entry, otherwise.
Exceptions
invalid_argumentkey is the empty string.

◆ take_data()

Optional< Data > core::PersistentStringCache::take_data ( std::string const &  key)

Removes an entry and returns its value and metadata.

If a (non-expired) entry with the given key can be found, it is removed from the cache and its data returned. If no metadata exists, Data::metadata is set to the empty string.

Returns
A null value if the entry could not be retrieved; the value and metadata of the entry, otherwise.
Exceptions
invalid_argumentkey is the empty string.

◆ touch()

bool core::PersistentStringCache::touch ( std::string const &  key,
std::chrono::time_point< std::chrono::system_clock >  expiry_time = std::chrono::system_clock::time_point() 
)

Updates the access time of an entry.

If the entry specified by key is still in the cache (whether expired or not), it is marked as the most-recently used entry. If the policy is lru_ttl, the entry's expiry time is updated with the specified time (infinite expiry by default).

Returns
true if the entry was updated; false if the entry could not be found or expiry_time is in the past.
Exceptions
invalid_argumentkey is the empty string.
logic_errorkey is the empty string.
logic_errorThe cache policy is lru_only and a non-infinite expiry time was provided.

◆ trim_to()

void core::PersistentStringCache::trim_to ( int64_t  used_size_in_bytes)

Expires entries.

Expires entries using the cache's expiration policy until the cache size falls to or below used_size_in_bytes. If used_size_in_bytes is less than the current cache size, this operation is a no-op.

Exceptions
invalid_argumentused_size_in_bytes is < 0
logic_errorused_size_in_bytes is > max_size_in_bytes().

The documentation for this class was generated from the following file: