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 /* All Rights Reserved. See XrdInfo.cc for complete License Terms */ 00009 /* Produced by Andrew Hanushevsky for Stanford University under contract */ 00010 /* DE-AC03-76-SFO0515 with the Department of Energy */ 00011 /******************************************************************************/ 00012 00013 // $Id: XrdOucRash.hh 22437 2008-03-04 14:35:16Z rdm $ 00014 00015 // This templated class implements a radix tree to remap binary quantities using 00016 // a hash-like <key,Value> interface. Define the object as: 00017 00018 // XrdOucRash<key_type, value_type> myobject; 00019 00020 // Where: key_type is the binary type of the key (short, int, long, long long) 00021 // value_type is the binary type of the value (one of the types above). 00022 00023 // The binary types may be signed or unsigned. Use the methods defined in 00024 // class XrdOucRash to Add(), Del(), Find(), and Rep() items in the table. 00025 // Use Apply() to scan through all of the items in the table and Purge() to 00026 // remove all items in the table (indices are not removed). Several options 00027 // exist to manage the items (see individual methods and XrdOucRash_Options). 00028 00029 // Warning! This class is not MT-safe and should be protected by an external 00030 // mutex when used in a multi-threaded environment. 00031 00032 #include <sys/types.h> 00033 #include <time.h> 00034 00035 enum XrdOucRash_Options {Rash_default = 0x0000, 00036 Rash_replace = 0x0002, 00037 Rash_count = 0x0004 00038 }; 00039 00040 template<typename K, typename V> 00041 class XrdOucRash_Item 00042 { 00043 public: 00044 int Count() {return keycount;} 00045 00046 V *Data() {return &keydata;} 00047 00048 K Key() {return keyval;} 00049 00050 time_t Time() {return keytime;} 00051 00052 void Update(int newcount, time_t newtime) 00053 {keycount = newcount; 00054 if (newtime) keytime = newtime; 00055 } 00056 00057 void Set(V &keyData, time_t newtime) 00058 {keydata = keyData; 00059 keytime = newtime; 00060 } 00061 00062 XrdOucRash_Item(K &KeyVal, 00063 V &KeyData, 00064 time_t KeyTime) 00065 {keyval = KeyVal; 00066 keydata = KeyData; 00067 keytime = KeyTime; 00068 keycount= 0; 00069 } 00070 00071 ~XrdOucRash_Item() {} 00072 00073 private: 00074 00075 K keyval; 00076 V keydata; 00077 time_t keytime; 00078 int keycount; 00079 }; 00080 00081 template<typename K, typename V> 00082 class XrdOucRash_Tent 00083 { 00084 public: 00085 XrdOucRash_Tent<K,V> *Table; 00086 XrdOucRash_Item<K,V> *Item; 00087 00088 XrdOucRash_Tent() {Table = 0; Item = 0;} 00089 ~XrdOucRash_Tent() {if (Table) delete[] Table; 00090 if (Item) delete(Item); 00091 } 00092 }; 00093 00094 template<typename K, typename V> 00095 class XrdOucRash 00096 { 00097 public: 00098 00099 // Add() adds a new item to the table. If it exists and repl = 0 then the old 00100 // entry is returned and the new data is not added. Otherwise the current 00101 // entry is replaced (see Rep()) and 0 is returned. If we have no memory 00102 // to add the new entry, an ENOMEM exception is thrown. The 00103 // LifeTime value is the number of seconds this entry is to be considered 00104 // valid. When the time has passed, the entry may be deleted. A value 00105 // of zero, keeps the entry until explicitly deleted. The Hash_count 00106 // option keeps track of duplicate key entries for Del. Thus the key must 00107 // be deleted as many times as it is added before it is physically deleted. 00108 // 00109 V *Add(K KeyVal, V &KeyData, time_t LifeTime=0, 00110 XrdOucRash_Options opt=Rash_default); 00111 00112 // Del() deletes the item from the table. If it doesn't exist, it returns 00113 // -ENOENT. If it was deleted it returns 0. If it was created with 00114 // Rash_Count then the count is decremented and count+1 is returned. 00115 // 00116 int Del(K KeyVal); 00117 00118 // Find() simply looks up an entry in the cache. It can optionally return the 00119 // lifetime associated with the entry. If the 00120 // 00121 V *Find(K KeyVal, time_t *KeyTime=0); 00122 00123 // Num() returns the number of items in the table 00124 // 00125 int Num() {return rashnum;} 00126 00127 // Purge() simply deletes all of the appendages to the table. 00128 // 00129 void Purge(); 00130 00131 // Rep() is simply Add() that allows replacement. 00132 // 00133 V *Rep(K KeyVal, V &KeyData, const int LifeTime=0, 00134 XrdOucRash_Options opt=Rash_default) 00135 {return Add(KeyVal, KeyData, LifeTime, 00136 (XrdOucRash_Options)(opt | Rash_replace));} 00137 00138 // Apply() applies the specified function to every item in the table. The 00139 // first argument is the key value, the second is the associated data, 00140 // the third argument is whatever is the passed in void *variable, The 00141 // following actions occur for values returned by the applied function: 00142 // <0 - The table item is deleted. 00143 // =0 - The next table item is processed. 00144 // >0 - Processing stops and the address of item is returned. 00145 // 00146 V *Apply(int (*func)(K, V, void *), void *Arg) 00147 {return Apply(rashTable, func, Arg);} 00148 00149 XrdOucRash() {rashnum = 0;} 00150 ~XrdOucRash() {Purge();} 00151 00152 private: 00153 V *Apply(XrdOucRash_Tent<K,V> *tab, 00154 int (*func)(K, V, void *), void *Arg); 00155 XrdOucRash_Item<K,V> *Lookup(K theKey, XrdOucRash_Tent<K,V> **tloc); 00156 void Insert(K theKey, XrdOucRash_Item<K,V> *theItem); 00157 unsigned long long key2ull(K theKey); 00158 00159 XrdOucRash_Tent<K,V> rashTable[16]; 00160 int rashnum; 00161 }; 00162 00163 /******************************************************************************/ 00164 /* A c t u a l I m p l e m e n t a t i o n */ 00165 /******************************************************************************/ 00166 00167 #include "XrdOuc/XrdOucRash.icc" 00168 #endif