00001 #ifndef __OUC_RASH__ 00002 #define __OUC_RASH__ 00003 /******************************************************************************/ 00004 /* */ 00005 /* X r d O u c R a s h . h h */ 00006 /* */ 00007 /* (c) 2005 by the Board of Trustees of the Leland Stanford, Jr., University */ 00008 /* Produced by Andrew Hanushevsky for Stanford University under contract */ 00009 /* DE-AC02-76-SFO0515 with the Department of Energy */ 00010 /* */ 00011 /* This file is part of the XRootD software suite. */ 00012 /* */ 00013 /* XRootD is free software: you can redistribute it and/or modify it under */ 00014 /* the terms of the GNU Lesser General Public License as published by the */ 00015 /* Free Software Foundation, either version 3 of the License, or (at your */ 00016 /* option) any later version. */ 00017 /* */ 00018 /* XRootD is distributed in the hope that it will be useful, but WITHOUT */ 00019 /* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or */ 00020 /* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public */ 00021 /* License for more details. */ 00022 /* */ 00023 /* You should have received a copy of the GNU Lesser General Public License */ 00024 /* along with XRootD in a file called COPYING.LESSER (LGPL license) and file */ 00025 /* COPYING (GPL license). If not, see <http://www.gnu.org/licenses/>. */ 00026 /* */ 00027 /* The copyright holder's institutional names and contributor's names may not */ 00028 /* be used to endorse or promote products derived from this software without */ 00029 /* specific prior written permission of the institution or contributor. */ 00030 /******************************************************************************/ 00031 00032 // This templated class implements a radix tree to remap binary quantities using 00033 // a hash-like <key,Value> interface. Define the object as: 00034 00035 // XrdOucRash<key_type, value_type> myobject; 00036 00037 // Where: key_type is the binary type of the key (short, int, long, long long) 00038 // value_type is the binary type of the value (one of the types above). 00039 00040 // The binary types may be signed or unsigned. Use the methods defined in 00041 // class XrdOucRash to Add(), Del(), Find(), and Rep() items in the table. 00042 // Use Apply() to scan through all of the items in the table and Purge() to 00043 // remove all items in the table (indices are not removed). Several options 00044 // exist to manage the items (see individual methods and XrdOucRash_Options). 00045 00046 // Warning! This class is not MT-safe and should be protected by an external 00047 // mutex when used in a multi-threaded environment. 00048 00049 #include <sys/types.h> 00050 #include <time.h> 00051 00052 enum XrdOucRash_Options {Rash_default = 0x0000, 00053 Rash_replace = 0x0002, 00054 Rash_count = 0x0004 00055 }; 00056 00057 template<typename K, typename V> 00058 class XrdOucRash_Item 00059 { 00060 public: 00061 int Count() {return keycount;} 00062 00063 V *Data() {return &keydata;} 00064 00065 K Key() {return keyval;} 00066 00067 time_t Time() {return keytime;} 00068 00069 void Update(int newcount, time_t newtime) 00070 {keycount = newcount; 00071 if (newtime) keytime = newtime; 00072 } 00073 00074 void Set(V &keyData, time_t newtime) 00075 {keydata = keyData; 00076 keytime = newtime; 00077 } 00078 00079 XrdOucRash_Item(K &KeyVal, 00080 V &KeyData, 00081 time_t KeyTime) 00082 {keyval = KeyVal; 00083 keydata = KeyData; 00084 keytime = KeyTime; 00085 keycount= 0; 00086 } 00087 00088 ~XrdOucRash_Item() {} 00089 00090 private: 00091 00092 K keyval; 00093 V keydata; 00094 time_t keytime; 00095 int keycount; 00096 }; 00097 00098 template<typename K, typename V> 00099 class XrdOucRash_Tent 00100 { 00101 public: 00102 XrdOucRash_Tent<K,V> *Table; 00103 XrdOucRash_Item<K,V> *Item; 00104 00105 XrdOucRash_Tent() {Table = 0; Item = 0;} 00106 ~XrdOucRash_Tent() {if (Table) delete[] Table; 00107 if (Item) delete(Item); 00108 } 00109 }; 00110 00111 template<typename K, typename V> 00112 class XrdOucRash 00113 { 00114 public: 00115 00116 // Add() adds a new item to the table. If it exists and repl = 0 then the old 00117 // entry is returned and the new data is not added. Otherwise the current 00118 // entry is replaced (see Rep()) and 0 is returned. If we have no memory 00119 // to add the new entry, an ENOMEM exception is thrown. The 00120 // LifeTime value is the number of seconds this entry is to be considered 00121 // valid. When the time has passed, the entry may be deleted. A value 00122 // of zero, keeps the entry until explicitly deleted. The Hash_count 00123 // option keeps track of duplicate key entries for Del. Thus the key must 00124 // be deleted as many times as it is added before it is physically deleted. 00125 // 00126 V *Add(K KeyVal, V &KeyData, time_t LifeTime=0, 00127 XrdOucRash_Options opt=Rash_default); 00128 00129 // Del() deletes the item from the table. If it doesn't exist, it returns 00130 // -ENOENT. If it was deleted it returns 0. If it was created with 00131 // Rash_Count then the count is decremented and count+1 is returned. 00132 // 00133 int Del(K KeyVal); 00134 00135 // Find() simply looks up an entry in the cache. It can optionally return the 00136 // lifetime associated with the entry. If the 00137 // 00138 V *Find(K KeyVal, time_t *KeyTime=0); 00139 00140 // Num() returns the number of items in the table 00141 // 00142 int Num() {return rashnum;} 00143 00144 // Purge() simply deletes all of the appendages to the table. 00145 // 00146 void Purge(); 00147 00148 // Rep() is simply Add() that allows replacement. 00149 // 00150 V *Rep(K KeyVal, V &KeyData, const int LifeTime=0, 00151 XrdOucRash_Options opt=Rash_default) 00152 {return Add(KeyVal, KeyData, LifeTime, 00153 (XrdOucRash_Options)(opt | Rash_replace));} 00154 00155 // Apply() applies the specified function to every item in the table. The 00156 // first argument is the key value, the second is the associated data, 00157 // the third argument is whatever is the passed in void *variable, The 00158 // following actions occur for values returned by the applied function: 00159 // <0 - The table item is deleted. 00160 // =0 - The next table item is processed. 00161 // >0 - Processing stops and the address of item is returned. 00162 // 00163 V *Apply(int (*func)(K, V, void *), void *Arg) 00164 {return Apply(rashTable, func, Arg);} 00165 00166 XrdOucRash() {rashnum = 0;} 00167 ~XrdOucRash() {Purge();} 00168 00169 private: 00170 V *Apply(XrdOucRash_Tent<K,V> *tab, 00171 int (*func)(K, V, void *), void *Arg); 00172 XrdOucRash_Item<K,V> *Lookup(K theKey, XrdOucRash_Tent<K,V> **tloc); 00173 void Insert(K theKey, XrdOucRash_Item<K,V> *theItem); 00174 unsigned long long key2ull(K theKey); 00175 00176 XrdOucRash_Tent<K,V> rashTable[16]; 00177 int rashnum; 00178 }; 00179 00180 /******************************************************************************/ 00181 /* A c t u a l I m p l e m e n t a t i o n */ 00182 /******************************************************************************/ 00183 00184 #include "XrdOuc/XrdOucRash.icc" 00185 #endif