00001 /******************************************************************************/ 00002 /* */ 00003 /* X r d C m s K e y . c c */ 00004 /* */ 00005 /* (c) 2007 by the Board of Trustees of the Leland Stanford, Jr., University */ 00006 /* All Rights Reserved */ 00007 /* Produced by Andrew Hanushevsky for Stanford University under contract */ 00008 /* DE-AC02-76-SFO0515 with the Department of Energy */ 00009 /******************************************************************************/ 00010 00011 // $Id: XrdCmsKey.cc 30949 2009-11-02 16:37:58Z ganis $ 00012 00013 const char *XrdCmsKeyCVSID = "$Id: XrdCmsKey.cc 30949 2009-11-02 16:37:58Z ganis $"; 00014 00015 #include <errno.h> 00016 #include <string.h> 00017 00018 #include "XrdCms/XrdCmsKey.hh" 00019 #include "XrdCms/XrdCmsTrace.hh" 00020 #include "XrdOuc/XrdOucCRC.hh" 00021 #include "XrdSys/XrdSysError.hh" 00022 00023 using namespace XrdCms; 00024 00025 /******************************************************************************/ 00026 /* C l a s s X r d C m s K e y */ 00027 /******************************************************************************/ 00028 /******************************************************************************/ 00029 /* public s e t H a s h */ 00030 /******************************************************************************/ 00031 00032 void XrdCmsKey::setHash() 00033 { 00034 if (!Len) Len = strlen(Val); 00035 if (!(Hash = XrdOucCRC::CRC32((const unsigned char *)Val, Len))) Hash = 1; 00036 } 00037 00038 /******************************************************************************/ 00039 /* C l a s s X r d C m s K e y I t e m */ 00040 /******************************************************************************/ 00041 /******************************************************************************/ 00042 /* S t a t i c D a t a */ 00043 /******************************************************************************/ 00044 00045 XrdCmsKeyItem *XrdCmsKeyItem::TockTable[TickRate] = {0}; 00046 XrdCmsKeyItem *XrdCmsKeyItem::Free = 0; 00047 int XrdCmsKeyItem::numFree = 0; 00048 int XrdCmsKeyItem::numHave = 0; 00049 int XrdCmsKeyItem::numNull = 0; 00050 00051 /******************************************************************************/ 00052 /* static public A l l o c */ 00053 /******************************************************************************/ 00054 00055 XrdCmsKeyItem *XrdCmsKeyItem::Alloc(unsigned int theTock) 00056 { 00057 XrdCmsKeyItem *kP; 00058 00059 // Try to allocate an existing item or replenish the list 00060 // 00061 do {if ((kP = Free)) 00062 {Free = kP->Next; 00063 numFree--; 00064 theTock &= TickMask; 00065 kP->Key.TOD = theTock; 00066 kP->Key.TODRef = TockTable[theTock]; 00067 TockTable[theTock] = kP; 00068 if (!(kP->Key.Ref++)) kP->Key.Ref = 1; 00069 kP->Loc.roPend = kP->Loc.rwPend = 0; 00070 return kP; 00071 } 00072 numNull++; 00073 } while(Replenish()); 00074 00075 // We failed 00076 // 00077 Say.Emsg("Key", ENOMEM, "create key item"); 00078 return (XrdCmsKeyItem *)0; 00079 } 00080 00081 /******************************************************************************/ 00082 /* public R e c y c l e */ 00083 /******************************************************************************/ 00084 00085 void XrdCmsKeyItem::Recycle() 00086 { 00087 static char *noKey = (char *)""; 00088 00089 // Clear up data areas 00090 // 00091 if (Key.Val && Key.Val != noKey) {free(Key.Val); Key.Val = noKey;} 00092 Key.Ref++; Key.Hash = 0; 00093 00094 // Put entry on the free list 00095 // 00096 Next = Free; Free = this; 00097 numFree++; 00098 } 00099 00100 /******************************************************************************/ 00101 /* public R e l o a d */ 00102 /******************************************************************************/ 00103 00104 void XrdCmsKeyItem::Reload() 00105 { 00106 Key.TOD &= static_cast<unsigned char>(TickMask); 00107 Key.TODRef = TockTable[Key.TOD]; 00108 TockTable[Key.TOD] = this; 00109 } 00110 00111 /******************************************************************************/ 00112 /* static public R e p l e n i s h */ 00113 /******************************************************************************/ 00114 00115 int XrdCmsKeyItem::Replenish() 00116 { 00117 EPNAME("Replenish"); 00118 XrdCmsKeyItem *kP; 00119 int i; 00120 00121 // Allocate a quantum of free elements and chain them into the free list 00122 // 00123 if (!(kP = new XrdCmsKeyItem[minAlloc])) return 0; 00124 DEBUG("old free " <<numFree <<" + " <<minAlloc <<" = " <<numHave+minAlloc); 00125 00126 // We would do this in an initializer but that causes problems when alloacting 00127 // temporary items on the stack. So, manually put these on the free list. 00128 // 00129 i = minAlloc; 00130 while(i--) {kP->Next = Free; Free = kP; kP++;} 00131 00132 // Return the number we have free 00133 // 00134 numHave += minAlloc; 00135 numFree += minAlloc; 00136 return numFree; 00137 } 00138 00139 /******************************************************************************/ 00140 /* static public S t a t s */ 00141 /******************************************************************************/ 00142 00143 void XrdCmsKeyItem::Stats(int &isAlloc, int &isFree, int &wasNull) 00144 { 00145 00146 isAlloc = numHave; 00147 isFree = numFree; 00148 wasNull = numNull; 00149 numNull = 0; 00150 } 00151 00152 /******************************************************************************/ 00153 /* static public U n l o a d */ 00154 /******************************************************************************/ 00155 00156 XrdCmsKeyItem *XrdCmsKeyItem::Unload(unsigned int theTock) 00157 { 00158 XrdCmsKeyItem myItem, *nP, *pP = &myItem; 00159 00160 // Remove all entries from the indicated list. If any entries have been 00161 // reassigned to a different list, move them to the right list. Otherwise, 00162 // make the entry unfindable by clearing the hash code. Since item recycling 00163 // requires knowing the hash code, we save it elsewhere in the object. 00164 // 00165 theTock &= TickMask; 00166 myItem.Key.TODRef = TockTable[theTock]; TockTable[theTock] = 0; 00167 while((nP = pP->Key.TODRef)) 00168 if (nP->Key.TOD == theTock) 00169 {nP->Loc.HashSave = nP->Key.Hash; nP->Key.Hash = 0; pP = nP;} 00170 else {pP->Key.TODRef = nP->Key.TODRef; 00171 nP->Key.TODRef = TockTable[nP->Key.TOD]; 00172 TockTable[nP->Key.TOD] = nP; 00173 } 00174 return myItem.Key.TODRef; 00175 } 00176 00177 /******************************************************************************/ 00178 00179 XrdCmsKeyItem *XrdCmsKeyItem::Unload(XrdCmsKeyItem *theItem) 00180 { 00181 XrdCmsKeyItem *kP, *pP = 0; 00182 unsigned int theTock = theItem->Key.TOD & TickMask; 00183 00184 // Remove the entry from the right list 00185 // 00186 kP = TockTable[theTock]; 00187 while(kP && kP != theItem) {pP = kP; kP = kP->Key.TODRef;} 00188 if (kP) 00189 {if (pP) pP->Key.TODRef = kP->Key.TODRef; 00190 else TockTable[theTock] = kP->Key.TODRef; 00191 kP->Loc.HashSave = kP->Key.Hash; kP->Key.Hash = 0; 00192 } 00193 return kP; 00194 }