File indexing completed on 2025-01-18 10:15:41
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019
0020
0021
0022
0023
0024
0025
0026
0027
0028
0029
0030 #include <cerrno>
0031 #include <cstring>
0032
0033
0034
0035
0036
0037 extern unsigned long XrdOucHashVal(const char *KeyVal);
0038
0039
0040
0041
0042
0043 template<class T>
0044 XrdOucHash<T>::XrdOucHash(int psize, int csize, int load)
0045 {
0046 prevtablesize = psize;
0047 hashtablesize = csize;
0048 hashload = load;
0049 hashmax = (csize * load) / 100;
0050 hashnum = 0;
0051 hashtable = (XrdOucHash_Item<T> **)
0052 malloc( (size_t)(csize*sizeof(XrdOucHash_Item<T> *)) );
0053 memset((void *)hashtable, 0, (size_t)(csize*sizeof(XrdOucHash_Item<T> *)));
0054 }
0055
0056
0057
0058
0059
0060 template<class T>
0061 T *XrdOucHash<T>::Add(const char *KeyVal, T *KeyData, const int LifeTime,
0062 XrdOucHash_Options opt)
0063 {
0064 unsigned long khash = XrdOucHashVal(KeyVal);
0065 int hent;
0066 time_t lifetime, KeyTime=0;
0067 XrdOucHash_Item<T> *hip, *newhip, *prevhip;
0068
0069
0070
0071
0072
0073 hent = khash % hashtablesize;
0074 if ((hip = hashtable[hent]) && (hip = Search(hip, khash, KeyVal, &prevhip)))
0075 {if (opt & Hash_count)
0076 {hip->Update(hip->Count()+1,
0077 (LifeTime || hip->Time() ? LifeTime + time(0) : 0) );}
0078 if (!(opt & Hash_replace)
0079 && ((lifetime=hip->Time())==0||lifetime>=time(0))) return hip->Data();
0080 Remove(hent, hip, prevhip);
0081 } else {
0082
0083
0084 if (hashnum >= hashmax) {Expand(); hent = khash % hashtablesize;}
0085 }
0086
0087
0088
0089 if (LifeTime) KeyTime = LifeTime + time(0);
0090 if ( !(newhip = new XrdOucHash_Item<T>(khash, KeyVal, KeyData, KeyTime,
0091 hashtable[hent], opt)) ) throw ENOMEM;
0092 hashtable[hent] = newhip;
0093 hashnum++;
0094 return (T *)0;
0095 }
0096
0097
0098
0099
0100
0101 template<class T>
0102 T *XrdOucHash<T>::Apply(int (*func)(const char *, T *, void *), void *Arg)
0103 {
0104 int i, rc;
0105 time_t lifetime;
0106 XrdOucHash_Item<T> *hip, *prevhip, *nexthip;
0107
0108
0109
0110
0111 for (i = 0; i < hashtablesize; i++)
0112 {hip = hashtable[i]; prevhip = 0;
0113 while(hip)
0114 {nexthip = hip->Next();
0115 if ((lifetime = hip->Time()) && lifetime < time(0)) rc = -1;
0116 else if ( (rc = (*func)(hip->Key(), hip->Data(), Arg)) > 0 )
0117 return hip->Data();
0118 if (rc < 0)
0119 {delete hip;
0120 if (prevhip) prevhip->SetNext(nexthip);
0121 else hashtable[i] = nexthip;
0122 hashnum--;
0123 }
0124 else prevhip = hip;
0125 hip = nexthip;
0126 }
0127 }
0128 return (T *)0;
0129 }
0130
0131
0132
0133
0134
0135 template<class T>
0136 int XrdOucHash<T>::Del(const char *KeyVal, XrdOucHash_Options)
0137 {
0138 unsigned long khash = XrdOucHashVal(KeyVal);
0139 int hent, cnt;
0140 XrdOucHash_Item<T> *hip, *phip, *thip;
0141
0142
0143
0144 hent = khash % hashtablesize;
0145 if (!(thip = hashtable[hent])) return -ENOENT;
0146 if (!( hip = Search(thip, khash, KeyVal, &phip) ) ) return -ENOENT;
0147
0148
0149
0150 if ((cnt = hip->Count()) <= 0) Remove(hent, hip, phip);
0151 else hip->Update(cnt-1, 0);
0152 return 0;
0153 }
0154
0155
0156
0157
0158
0159 template<class T>
0160 T *XrdOucHash<T>::Find(const char *KeyVal, time_t *KeyTime)
0161 {
0162 unsigned long khash = XrdOucHashVal(KeyVal);
0163 int kent;
0164 time_t lifetime = 0;
0165 XrdOucHash_Item<T> *phip, *hip;
0166
0167
0168
0169 kent = khash%hashtablesize;
0170
0171
0172
0173 if ((hip = hashtable[kent]))
0174 if ((hip = Search(hip, khash, KeyVal, &phip)))
0175 if ( (lifetime = hip->Time()) && lifetime < time(0) )
0176 {Remove(kent, hip, phip);
0177 if (KeyTime) *KeyTime = (time_t)0;
0178 return (T *)0;
0179 }
0180
0181
0182
0183 if (KeyTime) *KeyTime = lifetime;
0184 if (hip) return hip->Data();
0185 return (T *)0;
0186 }
0187
0188
0189
0190
0191
0192 template<class T>
0193 void XrdOucHash<T>::Purge()
0194 {
0195 int i;
0196 XrdOucHash_Item<T> *hip, *nexthip;
0197
0198
0199
0200 for (i = 0; i < hashtablesize; i++)
0201 {hip = hashtable[i]; hashtable[i] = 0;
0202 while(hip)
0203 {nexthip = hip->Next();
0204 delete hip;
0205 hip = nexthip;
0206 }
0207 }
0208 hashnum = 0;
0209 }
0210
0211
0212
0213
0214
0215
0216
0217
0218
0219 template<class T>
0220 void XrdOucHash<T>::Expand()
0221 {
0222 int newsize, newent, i;
0223 size_t memlen;
0224 XrdOucHash_Item<T> **newtab, *hip, *nexthip;
0225
0226
0227
0228 newsize = prevtablesize +hashtablesize;
0229
0230
0231
0232 memlen = (size_t)(newsize*sizeof(XrdOucHash_Item<T> *));
0233 if (!(newtab = (XrdOucHash_Item<T> **) malloc(memlen))) throw ENOMEM;
0234 memset((void *)newtab, 0, memlen);
0235
0236
0237
0238 for (i = 0; i < hashtablesize; i++)
0239 {hip = hashtable[i];
0240 while(hip)
0241 {nexthip = hip->Next();
0242 newent = (hip->Hash()) % newsize;
0243 hip->SetNext(newtab[newent]);
0244 newtab[newent] = hip;
0245 hip = nexthip;
0246 }
0247 }
0248
0249
0250
0251 free((void *)hashtable);
0252 hashtable = newtab;
0253 prevtablesize = hashtablesize;
0254 hashtablesize = newsize;
0255
0256
0257
0258 hashmax = static_cast<int>((static_cast<long long>(newsize)*hashload)/100);
0259 }
0260
0261
0262
0263
0264
0265 template<class T>
0266 void XrdOucHash<T>::Remove(int kent, XrdOucHash_Item<T> *hip,
0267 XrdOucHash_Item<T> *phip)
0268 {
0269 if (phip) phip->SetNext(hip->Next());
0270 else hashtable[kent] = hip->Next();
0271 delete hip;
0272 hashnum--;
0273 }
0274
0275
0276
0277
0278
0279 template<class T>
0280 XrdOucHash_Item<T> *XrdOucHash<T>::Search(XrdOucHash_Item<T> *hip,
0281 const unsigned long khash,
0282 const char *kval,
0283 XrdOucHash_Item<T> **pitem)
0284 {
0285 XrdOucHash_Item<T> *prevp = 0;
0286
0287
0288
0289 while(hip && !hip->Same(khash, kval))
0290 {prevp = hip;
0291 hip = hip->Next();
0292 }
0293 if (pitem) *pitem = prevp;
0294 return hip;
0295 }