#ifndef __SSI_SHMAP__ #define __SSI_SHMAP__ /******************************************************************************/ /* */ /* X r d S s i S h M a p . 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 #include "XrdSsi/XrdSsiShMat.hh" //----------------------------------------------------------------------------- //! This include file defines a simple key-value store interface using shared //! memory. This allows you to share the map with other processes in read as //! well as read/write mode. See the XrdSsi::ShMap teplated class within. //----------------------------------------------------------------------------- namespace XrdSsi { //----------------------------------------------------------------------------- //! The action parameter that must be passed to the Attach() method. //----------------------------------------------------------------------------- enum ShMap_Access //!< Attach existing map for {ReadOnly = 1, //!< reading ReadWrite = 2 //!< reading & writing }; //----------------------------------------------------------------------------- //! Parameters to pass to Create(). For Resize(&parms) initialize the struct //! as: "ShMap_Parms parms(XrdSsi::ShMap_Parms::ForResize)" so that the default //! values are appropriate for resizing instead of creation. //----------------------------------------------------------------------------- static const int ShMap_4Resize = -1; struct ShMap_Parms {int indexSize; //!< Number of hash table entries to create int maxKeyLen; //!< Maximum key length int maxKeys; //!< Maximum expected keys int mode; //!< Mode setting for the newly created file. int options; //!< Bit or'd ShMop_xxxx options below int reserved; //!< Reserved for future ABI complaint use //----------------------------------------------------------------------------- //! Bit options that may be or'd into he options member above. //----------------------------------------------------------------------------- static const int MultW = 0x88000000; //!< Multiple external writers static const int noMultW = 0x08000000; //!< Opposite (default for Create) static const int ReUse = 0x44000000; //!< Reuse map storage static const int noReUse = 0x04000000; //!< Opposite (default for Create) //----------------------------------------------------------------------------- //! Constructor suitable for Create() //----------------------------------------------------------------------------- ShMap_Parms() : indexSize(16381), maxKeyLen(63), maxKeys(32768), mode(0640), options(0), reserved(0) {} //----------------------------------------------------------------------------- //! Constructor suitable for Resize() (use ShMap_Parms(ForResize)). //----------------------------------------------------------------------------- static const int ForResize = 0; //!< Triggers initialization for Resize ShMap_Parms(int rsz) : indexSize(0), maxKeyLen(0), maxKeys(0), mode(0640), options(0), reserved(rsz) {} //----------------------------------------------------------------------------- //! Destructor //----------------------------------------------------------------------------- ~ShMap_Parms() {} }; //----------------------------------------------------------------------------- //! Options valid for the Sync() method. //----------------------------------------------------------------------------- enum SyncOpt {SyncOff = 0, SyncOn, SyncAll, SyncNow, SyncQSz}; //----------------------------------------------------------------------------- //! Typedef for the optional hash computation function (see constructor) //! //! @param parms Pointer to the key whose hash is to be returned. If nil //! the function should return its 4-character name (e.g. //! {int hash; memcpy(&hash, "c32 ", sizeof(int)); return hash;} //! //! @return Either the hash value of the key or the hash name as an int. //----------------------------------------------------------------------------- typedef int (*ShMap_Hash_t)(const char *key); template class ShMap { public: //----------------------------------------------------------------------------- //! Attach an existing shared memory map. //! //! @param path Pointer to the file that is or will represent the map. //! //! @param access How to attach the map. Specify one of the following: //! ReadOnly - Attach the map strictly for reading. //! ReadWrite - Attach the map in read/write mode. New and //! //! @param tmo How many seconds to wait for the map to appear. It is //! possible that a new map may have not yet been exported, so //! attach will wait for the map to become visible. Specify, //! <0 - wait forever. //! =0 - do not wait at all. //! >0 - wait the specified number seconds and then timeout. //! //! @return true - The shared memory was attached, the map can be used. //! @return false - The shared memory could not be attached, errno holds reason. //----------------------------------------------------------------------------- bool Attach(const char *path, ShMap_Access access, int tmo=-1); //----------------------------------------------------------------------------- //! Create a new r/w shared memory map possibly replacing an existing one upon //! export. New maps must be exported to become visible (see Export()). //! //! This method first creates a temporary map visible only to the creator. This //! allows you to fill the map as needed with minimal overhead. Once this is //! done, call Export() to make the new map visible, possibly replacing an //! any existing version of a map with the same name. //! //! @param parms Reference to the parameters. See the ShMap_Parms struct for //! for details and constructor defaults. Below is a detailed //! explanation of the available options: //! //! MultW - The map has multiple processes writing to it. //! All writers must obtain an exclusive file lock //! before updating the map. No file locks are needed //! ReUse - Allow reuse of storage in the map. Use this if //! the map has many inserts/deletes. If set, r/o //! access will always lock the map file before //! looking at it. Otherwise, there is no need for //! file locks as no item is ever reused. ReUse is //! good when there are few key add/delete cycles. //! //! @return true - The shared memory was attached, the map can be used. //! @return false - The shared memory could not be attached, errno holds reason. //----------------------------------------------------------------------------- bool Create(const char *path, ShMap_Parms &parms); //----------------------------------------------------------------------------- //! Detach the map from the shared memory. //----------------------------------------------------------------------------- void Detach(); //----------------------------------------------------------------------------- //! Export a newly created map (i.e. one that was attached using ShMop_New). //! //! @return true - The map has been exported and is now visible to others. //! @return false - The export failed, the errno value describes the reason. //----------------------------------------------------------------------------- bool Export(); //----------------------------------------------------------------------------- //! Add an item to the map (see the Rep() method for key/data replacement). //! //! @param key pointer to the key of length <= MaxKeySize. //! @param val The associated data to be added to the map. //! //! @return true - The key and data added to the map. //! @return false - The key and data not added, the errno value describes why. //! Typical reason: the key already exists (errno == EEXIST). //----------------------------------------------------------------------------- bool Add(const char *key, T &val); //----------------------------------------------------------------------------- //! Delete an item from the map. //! //! @param key Pointer to the key of length <= MaxKeySize. //! @param valP Pointer to the area to receive the value of the deleted key. //! If the pointer is nil, then the key value is not returned. //! //! @return true - The key and data have been deleted. This is always returned //! when valP is nil. //! @return false - The key and data either not deleted or the key does not //! exist and valP was not nil. The errno value describes why. //! Typical reason: the key was not found (errno == ENOENT). //----------------------------------------------------------------------------- bool Del(const char *key, T *valP=0); //----------------------------------------------------------------------------- //! Enumerate the keys and associated 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. The key is overwritten on the next //! call to Enumerate(); so copy it if you want to keep it. //! @param val The pointer variable where the location of the key value //! is to be returned upon success. The value is overwritten on //! the next call to Enumerate(). Copy it if you want to keep it. //! //! @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. Whene false is returned //! the jar is deleted and the pointer to it set to zero. //----------------------------------------------------------------------------- bool Enumerate(void *&jar, char *&key, T *&val); //----------------------------------------------------------------------------- //! 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() whose enumeration is to be terminated. //! //! @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. //----------------------------------------------------------------------------- bool Enumerate(void *&jar); //----------------------------------------------------------------------------- //! Determine whether or not a key exists in the map. //! //! @param key Pointer to the key of length <= MaxKeySize. //! //! @return true - The key exists. //! @return false - The key does not exist. //----------------------------------------------------------------------------- bool Exists(const char *key); //----------------------------------------------------------------------------- //! Find a key in the map and return its value. //! //! @param key Pointer to the key of length <= MaxKeySize. //! @param val Reference to the area to receive the value of the found key. //! //! @return true - The key found and its value has been returned. //! @return false - The key not found, the errno value describes why. //! Typical reason: the key was not found (errno == ENOENT). //----------------------------------------------------------------------------- bool Get(const char *key, T &val); //----------------------------------------------------------------------------- //! Return information about the map. //! //! @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 map. keys/indexused is //! the hash table collision factor //! keysfree - Number of keys that can still be added //! maxkeylen - Longest allowed key //! multw - If 1 map supports multiple writers, else 0 //! reuse - If 1 map allows object reuse, else 0 //! type - Name of the data type in the table. //! typesz - The number of bytes in the map'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. //! @return < 0 - The variable's value could not be returned; errno has the //! error code describing the reason, typically ENOSYS. //----------------------------------------------------------------------------- int Info(const char *vname, char *buff=0, int blen=0); //----------------------------------------------------------------------------- //! Add to or replace an item in the map. //! //! @param key Pointer to the key of length <= MaxKeySize. //! @param val The associated data to be added to or replaced in the map. //! @param valP Pointer to the area to receive the value of a replaced key. //! If the pointer is nil, then the key value is not returned. //! //! @return true - The key and data added to or replaced in the map. If the //! key was replaced errno is set to EEXIST else it is set to 0. //! @return false - The key and data not added, the errno value describes why. //! Typical reason: the key was too long (errno == ENAMETOOLONG). //----------------------------------------------------------------------------- bool Rep(const char *key, T &val, T *valP=0); //----------------------------------------------------------------------------- //! Resize or change options on an existing map attached in read/write mode. //! The map must have been exported. //! //! @param parms Pointer to the parameters. See the ShMap_Parms struct for //! for details and constructor defaults. A zero value in the //! parameter list uses the existing map value allowing you to //! selectively change the map sizing and options. If a nil //! pointer is passed, the map is simply compressed. //! //! @return true - The shared memory was resized. //! @return false - The shared memory could not be resized, errno holds reason. //----------------------------------------------------------------------------- bool Resize(ShMap_Parms *parms=0); //----------------------------------------------------------------------------- //! Specify how the memory map is synchronized with its backing file. If sync //! is already enabled, calling this method writes back any modified pages //! before effecting any requested changes. //! //! @param dosync Controls how synchronization is done (see SyncOpt enum): //! SyncOff - Turn synchronization off (initial setting). //! SyncOn - Turn synchronization on; pages are written in the //! background (i.e. asynchronously). //! SyncAll - Turn synchronization on; pages are written in the //! foreground(i.e. synchronously). //! SyncNow - Write back any queued pages but otherwise keep //! all other settings the same. //! SyncQSz - Set the queue size specified in the second //! argument. This number of modified pages are //! queued before being written back to disk. No //! other setting in effect are altered. //! @param syncqsz Specifies the defer-writeback queue size. This argument //! is ignored unless SyncQSz has been specified (see above). //! //! @return true - Call ended successfully. //! @return false - Call failed; the errno value describes why. //----------------------------------------------------------------------------- bool Sync(SyncOpt dosync, int syncqsz=256); //----------------------------------------------------------------------------- //! Constructor. First allocate a ShMap object of appropriate type. Then call //! Attach() to attach it to a shared memory segment before calling any other //! method in this class. When through either delete the object. //! //! @param typeName - A text name of the type in the map. Attach() makes sure //! that the map has this type. Specify text < 64 characters. //! Example: XrdSsi::ShMap myMap("int"); //! //! @param hFunc - An optional pointer to to the hash computation function //! to be used. If not specified, a crc32 hash is used. //! //! @param implName - A text name of the map implementation desired. Zero uses //! the default implementation. Currently only the default //! implementation is available. //----------------------------------------------------------------------------- ShMap(const char *typeName, ShMap_Hash_t hFunc=0, const char *implName=0) : shMat(0), hashFunc(hFunc), typeID(strdup(typeName)), implID((implName ? strdup(implName) : 0)) {} //----------------------------------------------------------------------------- //! Destructor //----------------------------------------------------------------------------- ~ShMap() {Detach(); if (typeID) free(typeID); if (implID) free(implID); } private: XrdSsiShMat *shMat; ShMap_Hash_t hashFunc; char *typeID; char *implID; }; } /******************************************************************************/ /* A c t u a l I m p l e m e n t a t i o n */ /******************************************************************************/ #include "XrdSsi/XrdSsiShMap.icc" #endif