bes Updated for version 3.21.1
The Backend Server (BES) is the lower two tiers of the Hyrax data server
BESDapFunctionResponseCache Class Reference

Cache the results from server functions. More...

#include <BESDapFunctionResponseCache.h>

Inheritance diagram for BESDapFunctionResponseCache:
Inheritance graph
Collaboration diagram for BESDapFunctionResponseCache:
Collaboration graph

Public Member Functions

bool cache_enabled () const
 
virtual bool cache_too_big (unsigned long long current_size) const
 look at the cache size; is it too large? Look at the cache size and see if it is too big.
 
virtual bool can_be_cached (libdap::DDS *dds, const std::string &constraint)
 
virtual bool create_and_lock (const std::string &target, int &fd)
 Create a file in the cache and lock it for write access.
 
void disable ()
 Disable the cache.
 
void dump (std::ostream &strm) const override
 dumps information about this object
 
void enable ()
 Enable the cache.
 
virtual void exclusive_to_shared_lock (int fd)
 Transfer from an exclusive lock to a shared lock.
 
std::string get_cache_directory () const
 
virtual std::string get_cache_file_name (const std::string &src, bool mangle=true)
 
std::string get_cache_file_prefix () const
 
virtual unsigned long long get_cache_size ()
 Get the cache size.
 
virtual bool get_exclusive_lock (const std::string &target, int &fd)
 
virtual bool get_exclusive_lock_nb (const std::string &target, int &fd)
 
virtual libdap::DDS * get_or_cache_dataset (libdap::DDS *dds, const std::string &constraint)
 Return a DDS loaded with data that can be serialized back to a client.
 
virtual bool get_read_lock (const std::string &target, int &fd)
 Get a read-only lock on the file if it exists.
 
void initialize (const std::string &cache_dir, const std::string &prefix, unsigned long long size)
 Initialize an instance of FileLockingCache.
 
bool is_unlimited () const
 Is this cache allowed to store as much as it wants?
 
virtual void purge_file (const std::string &file)
 Purge a single file from the cache.
 
virtual void unlock_and_close (const std::string &target)
 
virtual void update_and_purge (const std::string &new_file)
 Purge files from the cache.
 
virtual unsigned long long update_cache_info (const std::string &target)
 Update the cache info file to include 'target'.
 

Static Public Member Functions

static bool dir_exists (const std::string &dir)
 
static string get_cache_dir_from_config ()
 
static string get_cache_prefix_from_config ()
 
static unsigned long get_cache_size_from_config ()
 
Get the singleton instance

Get an instance of the BESDapFunctionResponseCache object. This class is a singleton, so the first call to any of three 'get_instance()' methods makes an instance and subsequent calls return a pointer to that instance.

Note
If the cache_dir parameter is null, this will return null for the pointer to the singleton and caching is disabled.
Parameters
cache_dir_keyKey to use to get the value of the cache directory. If this is the empty stirng, return null right away.
prefix_keyKey for the item/file prefix. Each file added to the cache uses this as a prefix so cached items can be easily identified when /tmp is used for the cache.
size_keyHow big should the cache be, in megabytes
Returns
A pointer to a BESDapFunctionResponseCache object
static BESDapFunctionResponseCacheget_instance (const std::string &cache_dir, const std::string &prefix, unsigned long long size)
 
static BESDapFunctionResponseCacheget_instance ()
 

Static Public Attributes

static const std::string PATH_KEY = "DAP.FunctionResponseCache.path"
 
static const std::string PREFIX_KEY = "DAP.FunctionResponseCache.prefix"
 
static const std::string SIZE_KEY = "DAP.FunctionResponseCache.size"
 

Protected Member Functions

 BESDapFunctionResponseCache (const std::string &cache_dir, const std::string &prefix, unsigned long long size)
 Protected constructor that takes as arguments keys to the cache directory, file prefix, and size of the cache to be looked up a configuration file.
 

Friends

class FunctionResponseCacheTest
 
class StoredResultTest
 

Detailed Description

Cache the results from server functions.

Serve-side functions build new datasets and can be quite large. This code caches those results so that when clients ask for a suite of responses from the function calls, the computations are run only once (in the best case) and subsequent requests for data or metadata are satisfied using information in this case.

Note
Cache entry collisions: This cache must hold objects that are identified by the combination of a dataset and a constraint expression. The CE can be quite large and contain a number of 'special' characters like '()' and so on. Instead of building cache IDs using a simple concatenation of the dataset and CE, we use the C++ std::hash class to generate a hash code. However, it's possible that two different dataset/CE combinations will have the same hash values. We use a simple collision resolution system where a suffix is appended to the hash value. After a number of collisions, we give up and simply do not cache the response (providing no worse performance than if the cache did not exist - but currently we throw an exception - see load_from_cache and the constant 'max_collisions').
Cache entry format: The cache uses a specially formated 'response object' that is more efficient to read and write than a typical DAP2 or DAP4 response object. DAP2 serializes data using network byte order while the cache uses native machine order. DAP4 computes checksums; the cache does not. In addition, each cache entry contains the resource id as its first line so that the correct entry can be identified.
Author
ndp, jhrg

Definition at line 72 of file BESDapFunctionResponseCache.h.

Constructor & Destructor Documentation

◆ BESDapFunctionResponseCache()

BESDapFunctionResponseCache::BESDapFunctionResponseCache ( const std::string & cache_dir,
const std::string & prefix,
unsigned long long size )
inlineprotected

Protected constructor that takes as arguments keys to the cache directory, file prefix, and size of the cache to be looked up a configuration file.

The keys specified are looked up in the specified keys object. If not found or not set correctly then an exception is thrown. I.E., if the cache directory is empty, the size is zero, or the prefix is empty.

Parameters
cache_dir_keykey to look up in the keys file to find cache dir
prefix_keykey to look up in the keys file to find the cache prefix
size_keykey to look up in the keys file to find the cache size (in MBytes)
Exceptions
BESSyntaxUserErrorif keys not set, cache dir or prefix empty, size is 0, or if cache dir does not exist.

Definition at line 123 of file BESDapFunctionResponseCache.h.

◆ ~BESDapFunctionResponseCache()

virtual BESDapFunctionResponseCache::~BESDapFunctionResponseCache ( )
inlinevirtual

Definition at line 137 of file BESDapFunctionResponseCache.h.

Member Function Documentation

◆ cache_enabled()

bool BESFileLockingCache::cache_enabled ( ) const
inlineinherited
Returns
Is this cache enabled?

Definition at line 200 of file BESFileLockingCache.h.

◆ cache_too_big()

bool BESFileLockingCache::cache_too_big ( unsigned long long current_size) const
virtualinherited

look at the cache size; is it too large? Look at the cache size and see if it is too big.

Returns
True if the size is too big, false otherwise.

Definition at line 817 of file BESFileLockingCache.cc.

◆ can_be_cached()

bool BESDapFunctionResponseCache::can_be_cached ( libdap::DDS * dds,
const std::string & constraint )
virtual

Definition at line 270 of file BESDapFunctionResponseCache.cc.

◆ create_and_lock()

bool BESFileLockingCache::create_and_lock ( const std::string & target,
int & fd )
virtualinherited

Create a file in the cache and lock it for write access.

If the file does not exist, make it, open it for read-write access and get an exclusive lock on it. The locking operation blocks, although that should never happen.

Parameters
targetThe name of the file to make/open/lock
fdValue-result param that holds the file descriptor of the opened file
Returns
True if the operation was successful, false otherwise. This method will return false if the file already existed (the file won't be locked and the descriptor reference is undefined - but likely -1).
Exceptions
BESBESInternalErrorif any error except EEXIST is returned by open(2) or if fcntl(2) returns an error.

Definition at line 625 of file BESFileLockingCache.cc.

◆ dir_exists()

bool BESFileLockingCache::dir_exists ( const std::string & dir)
staticinherited

Does the directory exist?

Note
This is a static method, so it can be called from other static methods like those that build instances of singletons.
Parameters
dirThe pathname to test.
Returns
True if the directory exists, false otherwise

Definition at line 1190 of file BESFileLockingCache.cc.

◆ disable()

void BESFileLockingCache::disable ( )
inlineinherited

Disable the cache.

Definition at line 205 of file BESFileLockingCache.h.

◆ dump()

void BESFileLockingCache::dump ( std::ostream & strm) const
overridevirtualinherited

dumps information about this object

Displays the pointer value of this instance along with information about this cache.

Parameters
strmC++ i/o stream to dump the information to

Implements BESObj.

Definition at line 1205 of file BESFileLockingCache.cc.

◆ enable()

void BESFileLockingCache::enable ( )
inlineinherited

Enable the cache.

Definition at line 210 of file BESFileLockingCache.h.

◆ exclusive_to_shared_lock()

void BESFileLockingCache::exclusive_to_shared_lock ( int fd)
virtualinherited

Transfer from an exclusive lock to a shared lock.

If the file has an exclusive write lock on it, change that to a shared read lock. This is an atomic operation. If the call to fcntl(2) is protected by locking the cache, a dead lock will result given typical use of this class. This method exists to help with the situation where one process has the cache locked and is blocking on a shared read lock for a file that a second process has locked exclusively (for writing). By changing the exclusive lock to a shared lock, the first process can get its shared lock and then release the cache.

Parameters
fdThe file descriptor that is exclusively locked and which, on exit, will have a shared lock.

Definition at line 660 of file BESFileLockingCache.cc.

◆ get_cache_dir_from_config()

string BESDapFunctionResponseCache::get_cache_dir_from_config ( )
static

Definition at line 132 of file BESDapFunctionResponseCache.cc.

◆ get_cache_directory()

std::string BESFileLockingCache::get_cache_directory ( ) const
inlineinherited
Returns
The directory used for the an instance of BESFileLockingCache

Definition at line 191 of file BESFileLockingCache.h.

◆ get_cache_file_name()

string BESFileLockingCache::get_cache_file_name ( const std::string & src,
bool mangle = true )
virtualinherited

Returns the fully qualified file system path name for the cache file associated with this particular cache resource. This does not look in the cache to see if the fle is present, it just returns the name that will (or is) be used once/if the file is added to the cache.

Note
Names are mangled: ALl occurrences of the characters '<', '>', '=', ',', '/', '(', ')', '"', ''', ':', '?', and ' ' are replaced with the '#' character.
Parameters
srcThe source name to (or in the) cache
mangleIf True, assume the name is a file pathname and mangle it. If false, do not mangle the name (assume the caller has sent a suitable string) but do turn the string into a pathname located in the cache directory with the cache prefix. The 'mangle' param is true by default.

Reimplemented in BESUncompressCache.

Definition at line 472 of file BESFileLockingCache.cc.

◆ get_cache_file_prefix()

std::string BESFileLockingCache::get_cache_file_prefix ( ) const
inlineinherited
Returns
The prefix used for items in an instance of BESFileLockingCache

Definition at line 186 of file BESFileLockingCache.h.

◆ get_cache_prefix_from_config()

string BESDapFunctionResponseCache::get_cache_prefix_from_config ( )
static

Definition at line 117 of file BESDapFunctionResponseCache.cc.

◆ get_cache_size()

unsigned long long BESFileLockingCache::get_cache_size ( )
virtualinherited

Get the cache size.

Read the size information from the cache info file and return it. This methods locks the cache.

Returns
The size of the cache.

Definition at line 829 of file BESFileLockingCache.cc.

◆ get_cache_size_from_config()

unsigned long BESDapFunctionResponseCache::get_cache_size_from_config ( )
static

Definition at line 101 of file BESDapFunctionResponseCache.cc.

◆ get_exclusive_lock()

bool BESFileLockingCache::get_exclusive_lock ( const std::string & target,
int & ref_fd )
virtualinherited

A blocking call to get an exclusive (write) lock on a file in the cache. Because this cache uses per-process advisory locking, it's possible to call this several times from within a single process and get a lock each time.

Note
This is used only by the purge_file() method.
Parameters
file_nameName of the file to lock
ref_fdReturn value parameter that holds the file descriptor that is locked.
Returns
Return false if the file does not exist, otherwise block until the lock is acquired and then return true.
Exceptions
BESInternalErroris thrown on any condition other than the file not existing

Definition at line 1079 of file BESFileLockingCache.cc.

◆ get_exclusive_lock_nb()

bool BESFileLockingCache::get_exclusive_lock_nb ( const std::string & target,
int & ref_fd )
virtualinherited

A non-blocking call to get an exclusive (write) lock on a file in the cache. Because this cache uses per-process advisory locking, it's possible to call this several times from within a single process and get a lock each time.

Note
This is used only by the update_and_purge() method.
Parameters
file_nameName of the file to lock
ref_fdReturn value parameter that holds the file descriptor that is locked.
Returns
Return false if the file does not exist or the non-blocking lock acquisition fails, otherwise the lock is acquired and then return true.
Exceptions
BESInternalErroris thrown on any condition other than the file not existing or the lock being unavailable.

Definition at line 920 of file BESFileLockingCache.cc.

◆ get_instance() [1/2]

BESDapFunctionResponseCache * BESDapFunctionResponseCache::get_instance ( )
static

Definition at line 193 of file BESDapFunctionResponseCache.cc.

◆ get_instance() [2/2]

BESDapFunctionResponseCache * BESDapFunctionResponseCache::get_instance ( const std::string & cache_dir,
const std::string & prefix,
unsigned long long size )
static

Definition at line 164 of file BESDapFunctionResponseCache.cc.

◆ get_or_cache_dataset()

DDS * BESDapFunctionResponseCache::get_or_cache_dataset ( libdap::DDS * dds,
const std::string & constraint )
virtual

Return a DDS loaded with data that can be serialized back to a client.

Given a DDS and a DAP2 constraint expression that contains only projection function calls, either pull a cached DDS* that is the result of evaluating those functions, or evaluate, cache and return the result. This is the main API cacll for this class.

Note
This method controls the cache lock, ensuring that the cache is unlocked when it returns.
The code that evaluates the function expression (when needed) could be sped up by using a thread to handle the process of writing the DDS to the cache, but this will be complicated until we have shared pointers (because the DDS* could be deleted while the cache code is still writing it).
Parameters
dds
constraint
eval
Returns

Definition at line 320 of file BESDapFunctionResponseCache.cc.

◆ get_read_lock()

bool BESFileLockingCache::get_read_lock ( const std::string & target,
int & fd )
virtualinherited

Get a read-only lock on the file if it exists.

Try to get a read-only lock on the file, blocking until we can get it. If the file does not exist, return false.

Note
If this code returns false, that means the file did not exist in the cache at the time of the test. by the time the caller gets the result, the file may have been added to the cache by another process.
Parameters
targetThe path of the cached file
fdA value-result parameter set to the locked cached file. Undefined if the file could not be locked for read access.
Returns
true if the file is in the cache and has been locked, false if the file is/was not in the cache.
Exceptions
Errorif the attempt to get the (shared) lock failed for any reason other than that the file does/did not exist.

Definition at line 565 of file BESFileLockingCache.cc.

◆ initialize()

void BESFileLockingCache::initialize ( const std::string & cache_dir,
const std::string & prefix,
unsigned long long size )
inherited

Initialize an instance of FileLockingCache.

Initialize and instance of FileLockingCache using the passed values for the cache directory, item prefix and max cache size. This will ignore the value of enable_cache() (but will correctly (re)set it based on the directory, ..., values). This provides a way for clients to re-initialize caches on the fly.

Parameters
cache_dirThe directory into which the cache files will be written.
prefixThe prefix that will be added to each cache file.
sizeThe size of the cache in MBytes
Exceptions
BESInternalErrorIf the cache_dir does not exist or is not writable. size is 0, or if cache dir does not exist.
BESErrorIf the parameters (directory, ...) are invalid.

Definition at line 259 of file BESFileLockingCache.cc.

◆ is_unlimited()

bool BESFileLockingCache::is_unlimited ( ) const
inlineinherited

Is this cache allowed to store as much as it wants?

If the size of the cache is zero bytes, then it is allowed to grow with out bounds.

Returns
True if the cache is unlimited in size, false if values will be purged after a preset size is exceeded.

Definition at line 181 of file BESFileLockingCache.h.

◆ purge_file()

void BESFileLockingCache::purge_file ( const std::string & file)
virtualinherited

Purge a single file from the cache.

Purge a single file from the cache. The file might be old, etc., and need to be removed. Don't use this to shrink the cache when it gets too big, use update_and_purge() instead since that file optimizes accesses to the cache control file for several changes in a row.

Parameters
fileThe name of the file to purge.

Definition at line 1125 of file BESFileLockingCache.cc.

◆ unlock_and_close()

void BESFileLockingCache::unlock_and_close ( const std::string & target)
virtualinherited

Get an exclusive lock on the 'cache info' file. The 'cache info' file is used to control certain cache actions, ensuring that they are atomic. These include making sure that the create_and_lock() and read_and_lock() operations are atomic as well as the purge and related operations.

Note
This is intended to be used internally only but might be useful in some settings. Unlock the named file.

This does not do any name mangling; it just closes and unlocks whatever is named (or throws BESBESInternalError if the file cannot be closed). If the file was opened more than once, all descriptors are closed. If you need to close a specific descriptor, use the other version of unlock_and_close().

Note
This method assumes that the file was opened/locked using one of read_and_lock() or create_and_lock(). Those methods record the name/file- descriptor pairs so that the files can be properly closed and locks released.
Parameters
file_nameThe name of the file to unlock.
Exceptions
BESBESInternalError

Definition at line 745 of file BESFileLockingCache.cc.

◆ update_and_purge()

void BESFileLockingCache::update_and_purge ( const std::string & new_file)
virtualinherited

Purge files from the cache.

Purge files, oldest to newest, if the current size of the cache exceeds the size of the cache specified in the constructor. This method uses an exclusive lock on the cache for the duration of the purge process.

Note
If the cache size in bytes is zero, calling this method has no affect (the cache is unlimited in size). Other public methods like update_cache_info() and get_cache_size() still work, however.
Parameters
new_fileDo not delete this file. The name of a file this process just added to the cache. Using fcntl(2) locking there is no way this process can detect its own lock, so the shared read lock on the new file won't keep this process from deleting it (but will keep other processes from deleting it).

Definition at line 977 of file BESFileLockingCache.cc.

◆ update_cache_info()

unsigned long long BESFileLockingCache::update_cache_info ( const std::string & target)
virtualinherited

Update the cache info file to include 'target'.

Add the size of the named file to the total cache size recorded in the cache info file. The cache info file is exclusively locked by this method for its duration. This updates the cache info file and returns the new size.

Parameters
targetThe name of the file
Returns
The new size of the cache

Definition at line 769 of file BESFileLockingCache.cc.

Friends And Related Symbol Documentation

◆ FunctionResponseCacheTest

friend class FunctionResponseCacheTest
friend

Definition at line 105 of file BESDapFunctionResponseCache.h.

◆ StoredResultTest

friend class StoredResultTest
friend

Definition at line 106 of file BESDapFunctionResponseCache.h.

Member Data Documentation

◆ PATH_KEY

const string BESDapFunctionResponseCache::PATH_KEY = "DAP.FunctionResponseCache.path"
static

Definition at line 129 of file BESDapFunctionResponseCache.h.

◆ PREFIX_KEY

const string BESDapFunctionResponseCache::PREFIX_KEY = "DAP.FunctionResponseCache.prefix"
static

Definition at line 130 of file BESDapFunctionResponseCache.h.

◆ SIZE_KEY

const string BESDapFunctionResponseCache::SIZE_KEY = "DAP.FunctionResponseCache.size"
static

Definition at line 131 of file BESDapFunctionResponseCache.h.


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