#ifndef __OOUC_HASH__ #define __OOUC_HASH__ /******************************************************************************/ /* */ /* X r d O u c H a s h . h h */ /* */ /* (c) 2004 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 #include /* Hash_data_is_key - The key and data are the same so when an item is added the data pointer is set to the key address. Hash_replace - When adding an item, any existing item is replaced. Hash_count - The number of deletion requests must equal the number of additions before the item is actually deleted. Hash_keep - When the item is added, the key is not duplicated and when the item is deleted, the key *and* data are not deleted. Hash_dofree - When an item is deleted the data is released using free() instead of delete(). Hash_keepdata - Works like Hash_keep but only applies to the data object. When adding the entry, the key is strdup'd and when deleting an entry, the key is freed. */ enum XrdOucHash_Options {Hash_default = 0x0000, Hash_data_is_key = 0x0001, Hash_replace = 0x0002, Hash_count = 0x0004, Hash_keep = 0x0008, Hash_dofree = 0x0010, Hash_keepdata = 0x0020 }; template class XrdOucHash_Item { public: int Count() {return keycount;} T *Data() {return keydata;} unsigned long Hash() {return keyhash;} const char *Key() {return keyval;} XrdOucHash_Item *Next() {return next;} time_t Time() {return keytime;} void Update(int newcount, time_t newtime) {keycount = newcount; if (newtime) keytime = newtime; } int Same(const unsigned long KeyHash, const char *KeyVal) {return keyhash == KeyHash && !strcmp(keyval, KeyVal);} void SetNext(XrdOucHash_Item *item) {next = item;} XrdOucHash_Item(unsigned long KeyHash, const char *KeyVal, T *KeyData, time_t KeyTime, XrdOucHash_Item *KeyNext, XrdOucHash_Options KeyOpts) {keyhash = KeyHash; if (KeyOpts & Hash_keep) keyval = KeyVal; else keyval = strdup(KeyVal); if (KeyOpts & Hash_data_is_key) keydata = (T *)keyval; else keydata = KeyData; keytime = KeyTime; entopts = KeyOpts; next = KeyNext; keycount= 0; } ~XrdOucHash_Item() {if (!(entopts & Hash_keep)) {if (keydata && keydata != (T *)keyval && !(entopts & Hash_keepdata)) {if (entopts & Hash_dofree) free(keydata); else delete keydata; } if (keyval) free((void *)keyval); } keydata = 0; keyval = 0; keycount = 0; } private: XrdOucHash_Item *next; const char *keyval; unsigned long keyhash; T *keydata; time_t keytime; int keycount; XrdOucHash_Options entopts; }; template class XrdOucHash { public: // Add() adds a new item to the hash. If it exists and repl = 0 then the old // entry is returned and the new data is not added. Otherwise the current // entry is replaced (see Rep()) and 0 is returned. If we have no memory // to add the new entry, an ENOMEM exception is thrown. The // LifeTime value is the number of seconds this entry is to be considered // valid. When the time has passed, the entry may be deleted. A value // of zero, keeps the entry until explicitly deleted. A special feature // allows the data to be associated with the key to be the actual key // using the Hash_data_is_key option. In this case, KeyData is ignored. // The Hash_count option keeps track of duplicate key entries for Del. // T *Add(const char *KeyVal, T *KeyData, const int LifeTime=0, XrdOucHash_Options opt=Hash_default); // Del() deletes the item from the hash. If it doesn't exist, it returns // -ENOENT. Otherwise 0 is returned. If the Hash_count option is specified // tyhen the entry is only deleted when the entry count is below 0. // int Del(const char *KeyVal, XrdOucHash_Options opt = Hash_default); // Find() simply looks up an entry in the cache. It can optionally return the // lifetime associated with the entry. If the // T *Find(const char *KeyVal, time_t *KeyTime=0); // Num() returns the number of items in the hash table // int Num() {return hashnum;} // Purge() simply deletes all of the appendages to the table. // void Purge(); // Rep() is simply Add() that allows replacement. // T *Rep(const char *KeyVal, T *KeyData, const int LifeTime=0, XrdOucHash_Options opt=Hash_default) {return Add(KeyVal, KeyData, LifeTime, (XrdOucHash_Options)(opt | Hash_replace));} // Apply() applies the specified function to every item in the hash. The // first argument is the key value, the second is the associated data, // the third argument is whatever is the passed in void *variable, The // following actions occur for values returned by the applied function: // <0 - The hash table item is deleted. // =0 - The next hash table item is processed. // >0 - Processing stops and the hash table item is returned. // T *Apply(int (*func)(const char *, T *, void *), void *Arg); // When allocateing a new hash, specify the required starting size. Make // sure that the previous number is the correct Fibonocci antecedent. The // series is simply n[j] = n[j-1] + n[j-2]. // XrdOucHash(int psize = 89, int size=144, int load=80); ~XrdOucHash() {if (hashtable) {Purge(); free(hashtable); hashtable = 0;}} private: void Remove(int kent, XrdOucHash_Item *hip, XrdOucHash_Item *phip); XrdOucHash_Item *Search(XrdOucHash_Item *hip, const unsigned long khash, const char *kval, XrdOucHash_Item **phip=0); unsigned long HashVal(const char *KeyVal); void Expand(); XrdOucHash_Item **hashtable; int prevtablesize; int hashtablesize; int hashnum; int hashmax; int hashload; }; /******************************************************************************/ /* A c t u a l I m p l e m e n t a t i o n */ /******************************************************************************/ #include "XrdOuc/XrdOucHash.icc" #endif