00001 #ifndef __SUT_CACHE_H 00002 #define __SUT_CACHE_H 00003 /******************************************************************************/ 00004 /* */ 00005 /* X r d S u t C a c h e . h h */ 00006 /* */ 00007 /* (c) 2005 by the Board of Trustees of the Leland Stanford, Jr., University */ 00008 /* Produced by Gerri Ganis for CERN */ 00009 /* */ 00010 /* This file is part of the XRootD software suite. */ 00011 /* */ 00012 /* XRootD is free software: you can redistribute it and/or modify it under */ 00013 /* the terms of the GNU Lesser General Public License as published by the */ 00014 /* Free Software Foundation, either version 3 of the License, or (at your */ 00015 /* option) any later version. */ 00016 /* */ 00017 /* XRootD is distributed in the hope that it will be useful, but WITHOUT */ 00018 /* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or */ 00019 /* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public */ 00020 /* License for more details. */ 00021 /* */ 00022 /* You should have received a copy of the GNU Lesser General Public License */ 00023 /* along with XRootD in a file called COPYING.LESSER (LGPL license) and file */ 00024 /* COPYING (GPL license). If not, see <http://www.gnu.org/licenses/>. */ 00025 /* */ 00026 /* The copyright holder's institutional names and contributor's names may not */ 00027 /* be used to endorse or promote products derived from this software without */ 00028 /* specific prior written permission of the institution or contributor. */ 00029 /******************************************************************************/ 00030 00031 #include "XrdOuc/XrdOucHash.hh" 00032 #include "XrdSut/XrdSutCacheEntry.hh" 00033 #include "XrdSys/XrdSysPthread.hh" 00034 00035 /******************************************************************************/ 00036 /* */ 00037 /* Class defining the basic memory cache */ 00038 /* */ 00039 /******************************************************************************/ 00040 00041 typedef bool (*XrdSutCacheGet_t)(XrdSutCacheEntry *, void *); 00042 typedef struct { 00043 long arg1; 00044 long arg2; 00045 long arg3; 00046 long arg4; 00047 } XrdSutCacheArg_t; 00048 00049 class XrdSutCache { 00050 public: 00051 XrdSutCache(int psize = 89, int size = 144, int load = 80) : table(psize, size, load) {} 00052 virtual ~XrdSutCache() {} 00053 00054 XrdSutCacheEntry *Get(const char *tag) { 00055 // Get the entry with 'tag'. 00056 // If found the entry is returned rd-locked. 00057 // If rd-locking fails the status is set to kCE_inactive. 00058 // Returns null if not found. 00059 00060 XrdSutCacheEntry *cent = 0; 00061 00062 // Exclusive access to the table 00063 XrdSysMutexHelper raii(mtx); 00064 00065 // Look for an entry 00066 if (!(cent = table.Find(tag))) { 00067 // none found 00068 return cent; 00069 } 00070 00071 // We found an existing entry: 00072 // lock until we get the ability to read (another thread may be valudating it) 00073 int status = 0; 00074 cent->rwmtx.ReadLock( status ); 00075 if ( status ) { 00076 // A problem occured: fail (set the entry invalid) 00077 cent->status = kCE_inactive; 00078 } 00079 return cent; 00080 } 00081 00082 XrdSutCacheEntry *Get(const char *tag, bool &rdlock, XrdSutCacheGet_t condition = 0, void *arg = 0) { 00083 // Get or create the entry with 'tag'. 00084 // New entries are always returned write-locked. 00085 // The status of existing ones depends on condition: if condition is undefined or if applied 00086 // to the entry with arguments 'arg' returns true, the entry is returned read-locked. 00087 // Otherwise a write-lock is attempted on the entry: if unsuccessful (another thread is modifing 00088 // the entry) the entry is read-locked. 00089 // The status of the lock is returned in rdlock (true if read-locked). 00090 rdlock = false; 00091 XrdSutCacheEntry *cent = 0; 00092 00093 // Exclusive access to the table 00094 XrdSysMutexHelper raii(mtx); 00095 00096 // Look for an entry 00097 if (!(cent = table.Find(tag))) { 00098 // If none, create a new one and write-lock for validation 00099 cent = new XrdSutCacheEntry(tag); 00100 int status = 0; 00101 cent->rwmtx.WriteLock( status ); 00102 if (status) { 00103 // A problem occured: delete the entry and fail 00104 delete cent; 00105 return (XrdSutCacheEntry *)0; 00106 } 00107 // Register it in the table 00108 table.Add(tag, cent); 00109 return cent; 00110 } 00111 00112 // We found an existing entry: 00113 // lock until we get the ability to read (another thread may be valudating it) 00114 int status = 0; 00115 cent->rwmtx.ReadLock( status ); 00116 if (status) { 00117 // A problem occured: fail (set the entry invalid) 00118 cent->status = kCE_inactive; 00119 return cent; 00120 } 00121 00122 // Check-it by apply the condition, if required 00123 if (condition) { 00124 if ((*condition)(cent, arg)) { 00125 // Good and valid entry 00126 rdlock = true; 00127 } else { 00128 // Invalid entry: unlock and write-lock to be able to validate it 00129 cent->rwmtx.UnLock(); 00130 int status = 0; 00131 cent->rwmtx.WriteLock( status ); 00132 if (status) { 00133 // A problem occured: fail (set the entry invalid) 00134 cent->status = kCE_inactive; 00135 return cent; 00136 } 00137 } 00138 } else { 00139 // Good and valid entry 00140 rdlock = true; 00141 } 00142 // We are done: return read-locked so we can use it until we need it 00143 return cent; 00144 } 00145 00146 inline int Num() { return table.Num(); } 00147 inline void Reset() { return table.Purge(); } 00148 00149 private: 00150 XrdSysRecMutex mtx; // Protect access to table 00151 XrdOucHash<XrdSutCacheEntry> table; // table with content 00152 }; 00153 00154 #endif