#ifndef __SSI_SHMAT__
#define __SSI_SHMAT__
/******************************************************************************/
/* */
/* X r d S s i S h M a t . h h */
/* */
/* (c) 2015 by the Board of Trustees of the Leland Stanford, Jr., University */
/* Produced by Andrew Hanushevsky for Stanford University under contract */
/* DE-AC02-76-SFO0515 with the Department of Energy */
/* */
/* This file is part of the XRootD software suite. */
/* */
/* XRootD is free software: you can redistribute it and/or modify it under */
/* the terms of the GNU Lesser General Public License as published by the */
/* Free Software Foundation, either version 3 of the License, or (at your */
/* option) any later version. */
/* */
/* XRootD is distributed in the hope that it will be useful, but WITHOUT */
/* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or */
/* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public */
/* License for more details. */
/* */
/* You should have received a copy of the GNU Lesser General Public License */
/* along with XRootD in a file called COPYING.LESSER (LGPL license) and file */
/* COPYING (GPL license). If not, see . */
/* */
/* The copyright holder's institutional names and contributor's names may not */
/* be used to endorse or promote products derived from this software without */
/* specific prior written permission of the institution or contributor. */
/******************************************************************************/
#include
#include
//-----------------------------------------------------------------------------
//! This class defines an abstract interface to a generic shared memory table
//! that stores key-value pairs. Since this class a pure abstract any number
//! of implementations may be supplied. The default one is named "XrdSsiShMam".
//-----------------------------------------------------------------------------
class XrdSsiShMat
{
public:
//-----------------------------------------------------------------------------
//! Add an item to the shared memory table.
//!
//! @param newdata Pointer to the data to be added.
//! @param olddata Pointer to the area where the replaced data, if any, is
//! to be placed.
//! @param key The key associated with the data that is to be added.
//! @param hash The hash of the key that is to be used to lookup the key.
//! If the value is zero, an internal hash is computed.
//! @param replace When true, if the key exists, the data associated with the
//! key is replaced. When false, if the key exists, the addition
//! fails with errno set to EEXIST.
//!
//! @return true The addition/replacement succeeded. If the key was actually
//! replaced errno is set to EEXIST else it is set to 0.
//! @return false The addition/replacement failed; errno indicates reason.
//-----------------------------------------------------------------------------
virtual bool AddItem(void *newdata, void *olddata, const char *key,
int hash=0, bool replace=false) = 0;
//-----------------------------------------------------------------------------
//! Attach this object to the shared memory associated with this object at
//! creation time (see New() method). The attach operation waits until the
//! shared memory file is available. At that time, the file is memory mapped.
//!
//! @param tout The maximum number of seconds to wait for the shared
//! memory file to become available. If tout is zero, then
//! the file must be immediately available. If the value is
//! negative then the attach waits as long as needed. When tout
//! is reached the attach fails with errno set to ETIMEDOUT.
//! @param isrw When true the file is mapped to writable memory and allows
//! updates to the table. If false, the shared memory is made
//! read/only and may be significantly faster to access.
//!
//! @return true - The shared memory was attached, the table can be used.
//! @return false - The shared memory could not be attached, errno holds reason.
//-----------------------------------------------------------------------------
virtual bool Attach(int tout, bool isrw=false) = 0;
//-----------------------------------------------------------------------------
//! Create a new shared memory segment and associated file specified at object
//! instantiation (see New() method). Created segments must be made visible to
//! other processes using the Export() method. This allows the table to be
//! preloaded with initial values before the table is made visible.
//!
//! @param parms Create parameters described by CRParms. All uninitialized
//! members in this struct must be specified.
//!
//! @return true - The shared memory was attached, the table can be used.
//! @return false - The shared memory could not be attached, errno holds reason.
//-----------------------------------------------------------------------------
struct CRZParms
{int indexSz; //!< Number of four byte hash table entries to create.
int maxKeys; //!< Maximum number of keys-value pairs expected in table.
int maxKLen; //!< The maximum acceptable key length.
int mode; //!< Filemode for the newly created file.
signed char multW;
//!< 1: Table can have multiple processes writing.
//!< 0: Table has only one process writing.
//!< -1: Use default or, for resize, previous setting.
signed char reUse;
//!< 1: Reuse deleted objects.
//!< 0: Never reuse deleted objects.
//!< -1: Use default or, for resize, previous setting.
char rsvd[6]; //!< Reserved for future options
CRZParms() : indexSz(0), maxKeys(0), maxKLen(0), mode(0640),
multW(-1), reUse(-1)
{memset(rsvd, -1, sizeof(rsvd));}
~CRZParms() {}
};
virtual bool Create(CRZParms &parms) = 0;
//-----------------------------------------------------------------------------
//! Export a newly created table (i.e. see Create()).
//!
//! @return true - The table has been exported and is now visible to others.
//! @return false - The export failed, the errno value describes the reason.
//-----------------------------------------------------------------------------
virtual bool Export() = 0;
//-----------------------------------------------------------------------------
//! Delete an item from the table.
//!
//! @param data Pointer to the area to receive the value of the deleted key.
//! If the pointer is nil, then the key value is not returned.
//! @param key Pointer to the key of length <= MaxKLen.
//! @param hash The hash of the key that is to be used to lookup the key.
//! If the value is zero, an internal hash is computed.
//!
//! @return true - The key and data have been deleted. This is always returned
//! when data is nil.
//! @return false - The key and data either not deleted or the key does not
//! exist and data was not nil. The errno value decribes why.
//! Typical reason: the key was not found (errno == ENOENT).
//-----------------------------------------------------------------------------
virtual bool DelItem(void *data, const char *key, int hash=0) = 0;
//-----------------------------------------------------------------------------
//! Detach the map from the shared memory.
//-----------------------------------------------------------------------------
virtual void Detach() = 0;
//-----------------------------------------------------------------------------
//! Enumerate the keys and assocaited values.
//!
//! @param jar An opaque cookie that tracks progress. It should be
//! initialized to zero and otherwise not touched. The same jar
//! must be used for all successive calls. The jar is deleted
//! when false is returned (also see the next Enumerate method).
//! @param key The pointer variable where the location of the key is
//! returned upon success.
//! @param val The pointer variable where the location f the key values
//! is to be returned upon success.
//!
//! @return true A key and val pointers have been set.
//! Keys are returned in arbitrary order and not all keys may
//! be returned if the map is being actively updated.
//! @return false Key not returned; errno holds the reason. Typically,
//! ENOENT there ae no more keys.
//! Other errors may also be reflected. Whne false is returned
//! the jar is deleted and the pointer to it set to zero.
//-----------------------------------------------------------------------------
virtual bool Enumerate(void *&jar, char *&key, void *&val) = 0;
//-----------------------------------------------------------------------------
//! Terminate an active enumeration. An active enumeration is any enumeration
//! where the previous form of Enumerate() did not return false. Terminating
//! an active enumeration releases all of the enumeration resources allocated.
//!
//! @param jar The opaque cookie initialized by a previous call to
//! Enumerate() requesting the next key-value pair.
//!
//! @return true The enumeration has been terminated and the jar was
//! deleted and the jar pointer is set to zero.
//! Keys are returned in arbitrary order and not all keys may
//! be returned if the map is being actively updated.
//! @return false The jar pointer was zero; no enumeration was active.
//-----------------------------------------------------------------------------
virtual bool Enumerate(void *&jar) = 0;
//-----------------------------------------------------------------------------
//! Return information about the table.
//!
//! @param vname Pointer to the variable name whose value is wanted. A
//! particular implementation may not support all variable and
//! may support variables not listed here. These are for the
//! default implementation unless otherwise noted. They are:
//! hash - name of hash being used.
//! impl - The table implementation being used.
//! indexsz - Number of index entries
//! indexused - Number of index entries in use
//! keys - Number of keys in the bale. keys/indexused is
//! the hash table collision factor
//! keysfree - Number of keys that can still be added
//! maxkeylen - Longest allowed key
//! multw - If table supports multiple writers, else 0
//! reuse - If table allows object reuse, else 0
//! type - Name of the data type in the table.
//! typesz - The number of bytes in the table's data type
//!
//! @param buff - Pointer to the buffer to receive text values.
//! Variables that return text are: hash, impl,
//! and type. A buffer must be supplied in any
//! of these variables are requested. If buff is
//! nill or too small a -1 is returned with errno
//! set to EMSGSIZE.
//!
//! @param blen The length of the buffer.
//!
//! @return >=0 - The variable's value or the length of the text information.
//! @return < 0 - The variable's value could not be returned; errno has the
//! error code describing the reason, typically ENOSYS.
//-----------------------------------------------------------------------------
virtual int Info(const char *vname, char *buff=0, int blen=0) = 0;
//-----------------------------------------------------------------------------
//! Get an item from the table.
//!
//! @param data Pointer to an area to receive the value associated with key.
//! If the pointer is nil, then the key value is not returned.
//! @param key Pointer to the key of length <= MaxKLen.
//! @param hash The hash of the key that is to be used to lookup the key.
//! If the value is zero, an internal hash is computed.
//!
//! @return true - The key was found and if data was not nil, contains the
//! value associated key.
//! @return false - The key not found; errno holds the reason (typically is
//! ENOENT but may be some other reason).
//-----------------------------------------------------------------------------
virtual bool GetItem(void *data, const char *key, int hash=0) = 0;
//-----------------------------------------------------------------------------
//! Instantiate a shared memory object.
//!
//! @param parms The parameters to use when creating the table. Fields are:
//! impl Pointer to the name of the implementation that is
//! desired. The default implementation (XrdSsiShMam)
//! is used if nil. All processes must specify the same
//! implementation that was used to create the table via
//! the Create() method. If specified it must not exceed
//! 63 characters.
//! path Pointer to the file that is backing the table. The
//! path is used to locate the table in memory.
//! typeID A text name of the data type in the table. All
//! processes must specify the same typeID that the
//! table was created with using Create(). Specify text
//! less than 64 characters.
//! typesz The number of bytes occupied by the data type in
//! the table.
//! hashID A 4-characters text name of the hash used in the
//! table represented as an int. All processes must
//! specify the same hashID that the table was created
//! with using Create().
//!
//! @return !0 - Pointer to an instance of an XrdSsiShMat object.
//! @return false - The object could not instantiate because of an error;
//! errno holds the error code explaining why.
//-----------------------------------------------------------------------------
struct NewParms
{const char *impl; //!< Implementation name
const char *path; //!< The path to the backing file for the table
const char *typeID; //!< The name of the type associated with the key
int typeSz; //!< Size of the type in bytes
int hashID; //!< The hash being used (0 means the default)
};
static
XrdSsiShMat *New(NewParms &parms);
//-----------------------------------------------------------------------------
//! Resize a shared memory segment and associated file specified at object
//! instantiation (see New() method). Resizing is implementation specific but
//! may involve creating a new table and exporting it.
//!
//! @param parms Resize parameters. See the CRZParms struct for details. For
//! resize, zero values or unspecified flags use the existing
//! table values.
//!
//! @return true - The shared memory was resized, the table can be used.
//! @return false - The shared memory could not be resized, errno holds reason.
//-----------------------------------------------------------------------------
virtual bool Resize(CRZParms &parms) = 0;
//-----------------------------------------------------------------------------
//! Synchronize all modified pages to the associated backing file.
//!
//! @return true - Operation completed successfully.
//! @return false - Operation failed; errno holds the error code explaining why.
//-----------------------------------------------------------------------------
virtual bool Sync() = 0;
//-----------------------------------------------------------------------------
//! Turn memry synchronization on or off.
//!
//! @param dosync When true, modified table pages are written back to the
//! backing file. The synchronous or async nature of the
//! write is controlled by the second parameter. When false,
//! memory-file synchronization is turned off (initial setting).
//! @param syncdo When true, synchronization is done in the forground. That
//! is, a call triggering a sync will not return until complete.
//! When false, synchronization is done in the background.
//!
//! @return true - Operation completed successfully.
//! @return false - Operation failed; errno holds the error code explaining why.
//-----------------------------------------------------------------------------
virtual bool Sync(bool dosync, bool syncdo=false) = 0;
//-----------------------------------------------------------------------------
//! Set the sync defer queue size.
//!
//! @param synqsz The maximum number of modified pages before flushing.
//!
//! @return true - Operation completed successfully.
//! @return false - Operation failed; errno holds the error code explaining why.
//-----------------------------------------------------------------------------
virtual bool Sync(int synqsz) = 0;
//-----------------------------------------------------------------------------
//! Constructor (arguments the same as for New())
//-----------------------------------------------------------------------------
XrdSsiShMat(NewParms &parms)
: shmImpl(strdup(parms.impl)), shmPath(strdup(parms.path)),
shmType(strdup(parms.typeID)), shmTypeSz(parms.typeSz),
shmHash(parms.hashID)
{}
//-----------------------------------------------------------------------------
//! Destructor. Warning, your destructor should call your own Detach()!
//-----------------------------------------------------------------------------
virtual ~XrdSsiShMat() {if (shmImpl) free(shmImpl);
if (shmPath) free(shmPath);
if (shmType) free(shmType);
}
protected:
char *shmImpl;
char *shmPath;
char *shmType;
int shmTypeSz;
int shmHash;
};
#endif