From aef4a21f2e22a6d1564093ead96accd7f08313e5 Mon Sep 17 00:00:00 2001 From: Gerardo Ganis Date: Thu, 18 May 2017 14:11:57 +0200 Subject: [PATCH] xrdsut: new XrdSutCache based on XrdOucHash Uses XrdSutCacheEntry, based on XrdSutPFEntry and a RW lock --- src/XrdSut/XrdSutCache.cc | 808 --------------------------------- src/XrdSut/XrdSutCache.hh | 161 ++++--- src/XrdSut/XrdSutCacheEntry.cc | 184 ++++++++ src/XrdSut/XrdSutCacheEntry.hh | 129 ++++++ 4 files changed, 392 insertions(+), 890 deletions(-) delete mode 100644 src/XrdSut/XrdSutCache.cc create mode 100644 src/XrdSut/XrdSutCacheEntry.cc create mode 100644 src/XrdSut/XrdSutCacheEntry.hh diff --git a/src/XrdSut/XrdSutCache.cc b/src/XrdSut/XrdSutCache.cc deleted file mode 100644 index 9a108468fd1..00000000000 --- a/src/XrdSut/XrdSutCache.cc +++ /dev/null @@ -1,808 +0,0 @@ -/******************************************************************************/ -/* */ -/* X r d S u t C a c h e . c c */ -/* */ -/* (c) 2004 by the Board of Trustees of the Leland Stanford, Jr., University */ -/* Produced by Gerri Ganis for CERN */ -/* */ -/* This file is part of the XRootD software suite. */ -/* */ -/* XRootD is free software: you can redistribute it and/or modify it under */ -/* the terms of the GNU Lesser General Public License as published by the */ -/* Free Software Foundation, either version 3 of the License, or (at your */ -/* option) any later version. */ -/* */ -/* XRootD is distributed in the hope that it will be useful, but WITHOUT */ -/* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or */ -/* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public */ -/* License for more details. */ -/* */ -/* You should have received a copy of the GNU Lesser General Public License */ -/* along with XRootD in a file called COPYING.LESSER (LGPL license) and file */ -/* COPYING (GPL license). If not, see . */ -/* */ -/* The copyright holder's institutional names and contributor's names may not */ -/* be used to endorse or promote products derived from this software without */ -/* specific prior written permission of the institution or contributor. */ -/******************************************************************************/ - -#include -#include -#include -#include -#include -#include - -#include "XrdSut/XrdSutCache.hh" -#include "XrdSut/XrdSutPFile.hh" -#include "XrdSut/XrdSutTrace.hh" -#include "XrdSut/XrdSutAux.hh" -#include "XrdSys/XrdSysTimer.hh" - -/******************************************************************************/ -/* */ -/* For caching temporary information during the authentication handshake */ -/* */ -/******************************************************************************/ - -//__________________________________________________________________ -XrdSutCache::~XrdSutCache() -{ - // Destructor - - // We are destroying the cache - rwlock.WriteLock(); - - // Cleanup content - while (cachemx > -1) { - if (cachent[cachemx]) { - delete cachent[cachemx]; - cachent[cachemx] = 0; - } - cachemx--; - } - // Cleanup table - if (cachent) - delete[] cachent; - - // Done - rwlock.UnLock(); -} - -//__________________________________________________________________ -int XrdSutCache::Init(int capacity, bool lock) -{ - // Initialize the cache to hold up to capacity entries. - // Later on, capacity is double each time more space is needed. - // Return 0 if ok, -1 otherwise - EPNAME("Cache::Init"); - - // Lock for writing - if (lock) rwlock.WriteLock(); - - // Nothing to do if already done - if (isinit) { - if (lock) rwlock.UnLock(); - return 0; - } - - // Make sure capacity makes sense; use a default, if not - capacity = (capacity > 0) ? capacity : 100; - - // Allocate - cachent = new XrdSutPFEntry *[capacity]; - if (cachent) { - for (int i = 0; i < capacity; i++) { cachent[i] = 0; } - cachesz = capacity; - DEBUG("cache allocated for "<pfeMutex.CondLock()) - {urRef.Set(&(pfEnt->pfeMutex)); - return pfEnt; - } - } else return pfEnt; - isg.UnLock(); - XrdSysTimer::Wait(retryMSW); - if (Rehash() != 0) - {DEBUG("problems rehashing"); - return (XrdSutPFEntry *)0 ; - } - isg.Lock(&rwlock, 1); - } - - // Nothing found - return (XrdSutPFEntry *)0 ; -} - -//__________________________________________________________________ -XrdSutPFEntry *XrdSutCache::Get(const char *ID, bool *wild) -{ - - // Look in the hash first - kXR_int32 *ie = hashtable.Find(ID); - if (ie && *ie >= 0 && *ie < cachesz) { - // Return the associated entry - return cachent[*ie]; - } - - // If wild cards allowed search sequentially - if (wild) { - XrdOucString sid(ID); - int i = 0, match = 0, nmmax = 0, iref = -1; - for (; i <= cachemx; i++) { - if (cachent[i]) { - match = sid.matches(cachent[i]->name); - if (match > nmmax) { - nmmax = match; - iref = i; - } - } - } - if (iref > -1) { - *wild = 1; - return cachent[iref]; - } - } - - // Nothing found - return (XrdSutPFEntry *)0 ; -} - -//__________________________________________________________________ -XrdSutPFEntry *XrdSutCache::Add(XrdSutCacheRef &urRef, const char *ID, bool force) -{ - // Add an entry with ID in cache - // Cache buffer is re-allocated with double size, if needed - // Hash is updated - EPNAME("Cache::Add"); - - // - // IF ID is undefined, do nothing - if (!ID || !strlen(ID)) { - DEBUG("empty ID !"); - return (XrdSutPFEntry *)0 ; - } - - // - // If an entry already exists, return it - XrdSutPFEntry *ent = Get(urRef, ID); - if (ent) - return ent; - - // Lock for writing - XrdSysRWLockHelper isg(rwlock, 0); - - // - // Make sure there enough space for a new entry - if (cachemx == cachesz - 1) { - // - // Duplicate buffer - XrdSutPFEntry **newcache = new XrdSutPFEntry *[2*cachesz]; - if (!newcache) { - DEBUG("could not extend cache to size: "<<(2*cachesz)); - return (XrdSutPFEntry *)0 ; - } - // Update info - cachesz *= 2; - // - // Copy existing valid entries, calculating real size - int i = 0, nmx = 0; - for (; i <= cachemx; i++) { - if (cachent[i]) { - newcache[nmx] = cachent[i]; - nmx++; - } - } - // update size - cachemx = nmx - 1; - // - // Reset new entries - for (i = cachemx + 1; i <= cachemx; i++) { - newcache[i] = 0; - } - // - // Cleanup and reassign - delete[] cachent; - cachent = newcache; - // - // Force rehash in this case - force = 1; - } - // - // The next free - int pos = cachemx + 1; - - // - // Add new entry - cachent[pos] = new XrdSutPFEntry(ID); - if (cachent[pos]) { - cachemx = pos; - } else { - DEBUG("could not allocate space for new cache entry"); - return (XrdSutPFEntry *)0 ; - } - // Update time stamp - utime = (kXR_int32)time(0); - - // Rebuild hash table - if (Rehash(force, 0) != 0) { - DEBUG("problems re-hashing"); - return (XrdSutPFEntry *)0 ; - } - - // We are done (we can lock the entry without a wait) - urRef.Lock(&(cachent[pos]->pfeMutex)); - return cachent[pos]; -} - -//__________________________________________________________________ -bool XrdSutCache::Remove(const char *ID, int opt) -{ - // If opt==1 remove entry with name matching exactly ID from cache - // If opt==0 all entries with names starting with ID are removed - // Return 1 if ok, 0 otherwise - EPNAME("Cache::Remove"); - - // - // IF ID is undefined, do nothing - if (!ID || !strlen(ID)) { - DEBUG("empty ID !"); - return 0 ; - } - - // Lock for writing - XrdSysRWLockHelper isg(rwlock, 0); - - if (Rehash(0, 0) != 0) { - DEBUG("problems rehashing"); - return 0 ; - } - - bool found = 0; - if (opt == 1) { - int pos = -1; - // Look in the hash first - kXR_int32 *ie = hashtable.Find(ID); - if (*ie >= 0 && *ie < cachesz) { - // Return the associated entry - pos = *ie; - } - - // - // Check if pos makes sense - if (cachent[pos] && !strcmp(cachent[pos]->name,ID)) { - if (!Delete(cachent[pos])) DEBUG("Delete defered for " <= 0; i--) { - if (cachent[i]) { - if (!strncmp(cachent[i]->name,ID,strlen(ID))) { - if (!Delete(cachent[i])) DEBUG("Delete defered for " <next)) - {nTot++; - if (dQ->pfEnt->pfeMutex.CondLock()) - {pQ->next = dQ->next; - dQ->pfEnt->pfeMutex.UnLock(); - delete dQ; - dTot++; - } else pQ = dQ; - } - if (nTot) DEBUG("Defered delete " <pfeMutex.CondLock()) - {pfEnt->pfeMutex.UnLock(); - delete pfEnt; - return true; - } - -// Defer the delete as someone still has a reference to the entry -// - pfDefer.next = new pfQ(pfDefer.next, pfEnt); - return false; -} - -//__________________________________________________________________ -int XrdSutCache::Trim(int lifet) -{ - // Remove entries older then lifet seconds. If lifet <=0, compare - // to lifetime, which can be set with SetValidity(). - // Return number of entries removed - - // Lock for writing - EPNAME("Cache::Trim"); - XrdSysRWLockHelper isg(rwlock, 0); - - // - // Make sure lifet makes sense; if not, use internal default - lifet = (lifet > 0) ? lifet : lifetime; - - // - // Reference time - int reftime = time(0) - lifet; - - // Loop over entries - int i = cachemx, nrm = 0; - for (; i >= 0; i--) { - if (cachent[i] && cachent[i]->mtime < reftime) { - if (!Delete(cachent[i])) - DEBUG("Delete defered for " <name); - cachent[i] = 0; - nrm++; - } - if (i == cachemx) { - if (!cachent[i]) - cachemx--; - } - } - - // We are done - return nrm; -} - -//__________________________________________________________________ -int XrdSutCache::Reset(int newsz, bool lock) -{ - // Remove all existing entries. - // If newsz > -1, set new capacity to newsz, reallocating if needed - // Return 0 if ok, -1 if problems reallocating. - EPNAME("Cache::Reset"); - - // Lock for writing - if (lock) rwlock.WriteLock(); - - // Loop over entries - int i = cachemx; - for (; i >= 0; i--) { - if (cachent[i]) { - if (!Delete(cachent[i])) - DEBUG("Delete defered for " <name); - cachent[i] = 0; - } - } - - int rc = 0; - // Reallocate, if requested - if (newsz > -1 && newsz != cachesz) { - delete[] cachent; - cachent = 0; - cachesz = 0; - cachemx = -1; - isinit = 0; - rc = Init(newsz, 0); - } - - // Unlock - if (lock) rwlock.UnLock(); - - // We are done - return rc; -} - -//________________________________________________________________ -void XrdSutCache::Dump(const char *msg) -{ - // Dump content of the cache - EPNAME("Cache::Dump"); - - PRINT("//-----------------------------------------------------"); - PRINT("//"); - if (msg && strlen(msg) > 0) { - PRINT("// "< 0) { - - XrdSutPFEntry *ent = 0; - int i = 0, nn = 0; - for (; i <= cachemx; i++) { - - // get entry - if ((ent = cachent[i])) { - - char smt[20] = {0}; - XrdSutTimeString(ent->mtime,smt); - - nn++; - PRINT("// #:"<status<<" cn:"<cnt - <<" buf:"<buf1.len<<","<buf2.len<<"," - <buf3.len<<","<buf4.len<<" mod:"<name); - } - - } - PRINT("//"); - } - PRINT("//-----------------------------------------------------"); -} - -//__________________________________________________________________ -int XrdSutCache::Load(const char *pfn) -{ - // Initialize the cache from the content of a file of PF entries - // Return 0 if ok, -1 otherwise - EPNAME("Cache::Load"); - - // Make sure file name is defined - if (!pfn) { - DEBUG("invalid input file name"); - return -1; - } - - // Check if file exists and if it has been modified since last load - struct stat st; - if (stat(pfn,&st) == -1) { - DEBUG("cannot stat file (errno: "< -1 && utime > st.st_mtime) { - DEBUG("cached information for file "< 0 && ne < header.entries) { - // - // read index entry - if (ff.ReadInd(nxtofs, ind) < 0) { - DEBUG("problems reading index entry "); - ff.Close(); - return -1; - } - - // If active ... - if (ind.entofs > 0) { - - // Read entry out - XrdSutPFEntry ent; - if (ff.ReadEnt(ind.entofs, ent) < 0) { - ff.Close(); - return -1; - } - - // Copy for the cache - XrdSutPFEntry *cent = new XrdSutPFEntry(ent); - - if (cent) { - // Set the id - cent->SetName(ind.name); - - // Fill the array - cachent[ne] = cent; - - // Count - ne++; - - } else { - DEBUG("problems duplicating entry for cache"); - ff.Close(); - return -1; - } - } - - // Go to next - nxtofs = ind.nxtofs; - } - cachemx = ne-1; - if (nxtofs > 0) - DEBUG("WARNING: inconsistent number of entries: possible file corruption"); - - // Update the time stamp - utime = (kXR_int32)time(0); - - // Save file name - pfile = pfn; - - // Close the file - ff.Close(); - - DEBUG("PF file "<= utime && !force) { - TRACE(Dump, "hash table is up-to-date"); - if (lock) rwlock.UnLock(); - return 0; - } - - // Clean up the hash table - hashtable.Purge(); - - kXR_int32 i = 0, nht = 0; - for (; i <= cachemx; i++) { - if (cachent[i]) { - // Fill the hash table - kXR_int32 *key = new kXR_int32(i); - if (key) { - TRACE(Dump, "Adding ID: "<name<<"; key: "<<*key); - hashtable.Add(cachent[i]->name,key); - nht++; - } - } - } - // Update modification time - htmtime = (kXR_int32)time(0); - - // Unlock - if (lock) rwlock.UnLock(); - - DEBUG("Hash table updated (found "<name, ent)) < 0) { - ff.Close(); - return -1; - } - // - // Write (update) only if older that cache or not found - if (nr == 0 || cachent[i]->mtime > ent.mtime) { - if (ff.WriteEntry(*cachent[i]) < 0) { - ff.Close(); - return -1; - } - nfs++; - } - } - } - - // Close the file - ff.Close(); - - // Update the time stamp (to avoid fake loads later on) - utime = (kXR_int32)time(0); - - // Save file name - if (pfile.length() <= 0) - pfile = pfn; - - DEBUG("Cache flushed to file "< -1 && utime > st.st_mtime) { - DEBUG("cached information for file "<UnLock(); - else return; - } - Mutex->Lock(); - mtx = Mutex; - }; - -inline void Set(XrdSysMutex *Mutex) - {if (mtx) {if (mtx != Mutex) mtx->UnLock(); - else return; - } - mtx = Mutex; - }; - -inline void UnLock() {if (mtx) {mtx->UnLock(); mtx = 0;}} - - XrdSutCacheRef() : mtx(0) {} - - ~XrdSutCacheRef() {if (mtx) UnLock();} -protected: -XrdSysMutex *mtx; -}; - -class XrdSutCache -{ -private: - XrdSysRWLock rwlock; // Access synchronizator - int cachesz; // Number of entries allocated - int cachemx; // Largest Index of allocated entries - XrdSutPFEntry **cachent; // Pointers to filled entries - kXR_int32 utime; // time at which was last updated - int lifetime; // lifetime (in secs) of the cache info - XrdOucHash hashtable; // Reflects the file index structure - kXR_int32 htmtime; // time at which hash table was last rebuild - XrdOucString pfile; // file name (if loaded from file) - bool isinit; // true if already initialized - - XrdSutPFEntry *Get(const char *ID, bool *wild); - bool Delete(XrdSutPFEntry *pfEnt); - - static const int maxTries = 100; // Max time to try getting a lock - static const int retryMSW = 300; // Milliseconds to wait to get lock +typedef bool (*XrdSutCacheGet_t)(XrdSutCacheEntry *, void *); +typedef struct { + long arg1; + long arg2; + long arg3; + long arg4; +} XrdSutCacheArg_t; +class XrdSutCache { public: - XrdSutCache() { cachemx = -1; cachesz = 0; cachent = 0; lifetime = 300; - utime = -1; htmtime = -1; pfile = ""; isinit = 0; } - virtual ~XrdSutCache(); - - // Status - int Entries() const { return (cachemx+1); } - bool Empty() const { return (cachemx == -1); } + XrdSutCache(int psize = 89, int size = 144, int load = 80) : table(psize, size, load) {} + virtual ~XrdSutCache() {} + + + XrdSutCacheEntry *Get(const char *tag, bool &rdlock, XrdSutCacheGet_t condition = 0, void *arg = 0) { + // Get or create the entry with 'tag'. + // New entries are always returned write-locked. + // The status of existing ones depends on condition: if condition is undefined or if applied + // to the entry with arguments 'arg' returns true, the entry is returned read-locked. + // Otherwise a write-lock is attempted on the entry: if unsuccessful (another thread is modifing + // the entry) the entry is read-locked. + // The status of the lock is returned in rdlock (true if read-locked). + rdlock = false; + XrdSutCacheEntry *cent = 0; + + // Exclusive access to the table + XrdSysMutexHelper raii(mtx); + + // Look for an entry + if (!(cent = table.Find(tag))) { + // If none, create a new one and write-lock for validation + cent = new XrdSutCacheEntry(tag); + if (cent->rwmtx.WriteLock()) { + // A problem occured: delete the entry and fail + delete cent; + return (XrdSutCacheEntry *)0; + } + // Register it in the table + table.Add(tag, cent); + return cent; + } + + // We found an existing entry: + // lock until we get the ability to read (another thread may be valudating it) + if (cent->rwmtx.ReadLock()) { + // A problem occured: fail (do not touch the entry) + return (XrdSutCacheEntry *)0; + } + + // Check-it by apply the condition, if required + if (condition) { + if ((*condition)(cent, arg)) { + // Good and valid entry + rdlock = true; + } else { + // Invalid entry: unlock and write-lock to be able to validate it + cent->rwmtx.UnLock(); + if (cent->rwmtx.WriteLock()) { + // A problem occured: fail (do not touch the entry) + return (XrdSutCacheEntry *)0; + } + } + } else { + // Good and valid entry + rdlock = true; + } + // We are done: return read-locked so we can use it until we need it + return cent; + } + + inline int Num() { return table.Num(); } + inline void Reset() { return table.Purge(); } - // Initialization methods - int Init(int capacity = 100, bool lock = 1); - int Reset(int newsz = -1, bool lock = 1); - int Load(const char *pfname); // build cache of a pwd file - int Flush(const char *pfname = 0); // flush content to pwd file - int Refresh(); // refresh content from source file - int Rehash(bool force = 0, bool lock = 1); // (re)build hash table - void SetLifetime(int lifet = 300) { lifetime = lifet; } - - // Cache management - XrdSutPFEntry *Get(int i) const { return (i<=cachemx) ? cachent[i] : - (XrdSutPFEntry *)0; } - XrdSutPFEntry *Get(XrdSutCacheRef &urRef, const char *ID, bool *wild = 0); - XrdSutPFEntry *Add(XrdSutCacheRef &urRef, const char *ID, bool force = 0); - bool Remove(const char *ID, int opt = 1); - int Trim(int lifet = 0); - - // For debug purposes - void Dump(const char *msg= 0); +private: + XrdSysRecMutex mtx; // Protect access to table + XrdOucHash table; // table with content }; #endif - diff --git a/src/XrdSut/XrdSutCacheEntry.cc b/src/XrdSut/XrdSutCacheEntry.cc new file mode 100644 index 00000000000..64707c5d781 --- /dev/null +++ b/src/XrdSut/XrdSutCacheEntry.cc @@ -0,0 +1,184 @@ +/******************************************************************************/ +/* */ +/* X r d S u t C a c h e E n t r y . c c */ +/* */ +/* (c) 2012 by the Board of Trustees of the Leland Stanford, Jr., University */ +/* Produced by Gerri Ganis for CERN */ +/* */ +/* This file is part of the XRootD software suite. */ +/* */ +/* XRootD is free software: you can redistribute it and/or modify it under */ +/* the terms of the GNU Lesser General Public License as published by the */ +/* Free Software Foundation, either version 3 of the License, or (at your */ +/* option) any later version. */ +/* */ +/* XRootD is distributed in the hope that it will be useful, but WITHOUT */ +/* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or */ +/* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public */ +/* License for more details. */ +/* */ +/* You should have received a copy of the GNU Lesser General Public License */ +/* along with XRootD in a file called COPYING.LESSER (LGPL license) and file */ +/* COPYING (GPL license). If not, see . */ +/* */ +/* The copyright holder's institutional names and contributor's names may not */ +/* be used to endorse or promote products derived from this software without */ +/* specific prior written permission of the institution or contributor. */ +/******************************************************************************/ + +#include +#include +#include + +#include "XrdSutAux.hh" +#include "XrdSutCacheEntry.hh" + +//__________________________________________________________________ +XrdSutCacheEntryBuf::XrdSutCacheEntryBuf(char *b, kXR_int32 l) +{ + // Constructor + + len = 0; + buf = 0; + if (b) { + buf = b; + len = l; + } +} + +//__________________________________________________________________ +XrdSutCacheEntryBuf::XrdSutCacheEntryBuf(const XrdSutCacheEntryBuf &b) +{ + //Copy constructor + + buf = 0; + len = 0; + if (b.buf) { + buf = new char[b.len]; + if (buf) { + memcpy(buf,b.buf,b.len); + len = b.len; + } + } +} + +//__________________________________________________________________ +void XrdSutCacheEntryBuf::SetBuf(const char *b, kXR_int32 l) +{ + // Set the buffer + + len = 0; + if (buf) { + delete[] buf; + buf = 0; + } + if (b && l > 0) { + buf = new char[l]; + if (buf) { + memcpy(buf,b,l); + len = l; + } + } +} + +//____________________________________________________________________ +XrdSutCacheEntry::XrdSutCacheEntry(const char *n, short st, short cn, + kXR_int32 mt) +{ + // Constructor + + name = 0; + status = st; + cnt = cn; + mtime = (mt > 0) ? mt : (kXR_int32)time(0); + if (n) { + name = new char[strlen(n)+1]; + if (name) + strcpy(name,n); + } +} + +//_____________________________________________________________________ +XrdSutCacheEntry::XrdSutCacheEntry(const XrdSutCacheEntry &e) : buf1(e.buf1), + buf2(e.buf2), buf3(e.buf3), buf4(e.buf4) +{ + // Copy constructor + + name = 0; + status = e.status; + cnt = e.cnt; + mtime = e.mtime; + if (e.name) { + name = new char[strlen(e.name)+1]; + if (name) + strcpy(name,e.name); + } +} + +//____________________________________________________________________ +void XrdSutCacheEntry::Reset() +{ + // Resetting entry + + if (name) + delete[] name; + name = 0; + status = 0; + cnt = 0; + mtime = (kXR_int32)time(0); + buf1.SetBuf(); + buf2.SetBuf(); + buf3.SetBuf(); + buf4.SetBuf(); +} + +//_____________________________________________________________________ +void XrdSutCacheEntry::SetName(const char *n) +{ + // Set the name + + if (name) { + delete[] name; + name = 0; + } + if (n) { + name = new char[strlen(n)+1]; + if (name) + strcpy(name,n); + } +} + +//_____________________________________________________________________ +char *XrdSutCacheEntry::AsString() const +{ + // Return a string with serialized information + // For print purposes + // The output string points to a static buffer, so it must + // not be deleted by the caller + static char pbuf[2048]; + + char smt[20] = {0}; + XrdSutTimeString(mtime,smt); + + sprintf(pbuf,"st:%d cn:%d buf:%d,%d,%d,%d modified:%s name:%s", + status,cnt,buf1.len,buf2.len,buf3.len,buf4.len,smt,name); + + return pbuf; +} + +//______________________________________________________________________________ +XrdSutCacheEntry& XrdSutCacheEntry::operator=(const XrdSutCacheEntry &e) +{ + // Assign entry e to local entry. + + SetName(name); + status = e.status; + cnt = e.cnt; // counter + mtime = e.mtime; // time of last modification / creation + buf1.SetBuf(e.buf1.buf); + buf2.SetBuf(e.buf2.buf); + buf3.SetBuf(e.buf3.buf); + buf4.SetBuf(e.buf4.buf); + + return (*this); +} diff --git a/src/XrdSut/XrdSutCacheEntry.hh b/src/XrdSut/XrdSutCacheEntry.hh new file mode 100644 index 00000000000..099ca34ac7e --- /dev/null +++ b/src/XrdSut/XrdSutCacheEntry.hh @@ -0,0 +1,129 @@ +#ifndef __SUT_CACHEENTRY_H +#define __SUT_CACHEENTRY_H +/******************************************************************************/ +/* */ +/* X r d S u t C a c h e E n t r y . h h */ +/* */ +/* (c) 2005 by the Board of Trustees of the Leland Stanford, Jr., University */ +/* Produced by Gerri Ganis for CERN */ +/* */ +/* This file is part of the XRootD software suite. */ +/* */ +/* XRootD is free software: you can redistribute it and/or modify it under */ +/* the terms of the GNU Lesser General Public License as published by the */ +/* Free Software Foundation, either version 3 of the License, or (at your */ +/* option) any later version. */ +/* */ +/* XRootD is distributed in the hope that it will be useful, but WITHOUT */ +/* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or */ +/* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public */ +/* License for more details. */ +/* */ +/* You should have received a copy of the GNU Lesser General Public License */ +/* along with XRootD in a file called COPYING.LESSER (LGPL license) and file */ +/* COPYING (GPL license). If not, see . */ +/* */ +/* The copyright holder's institutional names and contributor's names may not */ +/* be used to endorse or promote products derived from this software without */ +/* specific prior written permission of the institution or contributor. */ +/******************************************************************************/ + +#include "XProtocol/XProtocol.hh" +#include "XrdSys/XrdSysPthread.hh" + +/******************************************************************************/ +/* */ +/* Class defining the basic cache entry */ +/* */ +/******************************************************************************/ + +enum kCEntryStatus { + kCE_inactive = -2, // -2 inactive: eliminated at next trim + kCE_disabled, // -1 disabled, cannot be enabled + kCE_allowed, // 0 empty creds, can be enabled + kCE_expired, // 1 enabled, creds to be changed at next used + kCE_ok, // 2 enabled and OK + kCE_special // 3 special (non-creds) entry +}; + +// +// Buffer used internally by XrdGCEntry +// +class XrdSutCacheEntryBuf { +public: + char *buf; + kXR_int32 len; + XrdSutCacheEntryBuf(char *b = 0, kXR_int32 l = 0); + XrdSutCacheEntryBuf(const XrdSutCacheEntryBuf &b); + + virtual ~XrdSutCacheEntryBuf() { if (len > 0 && buf) delete[] buf; } + + void SetBuf(const char *b = 0, kXR_int32 l = 0); +}; + +// +// Generic cache entry: it stores a +// +// name +// status 2 bytes +// cnt 2 bytes +// mtime 4 bytes +// buf1, buf2, buf3, buf4 +// +// The buffers are generic buffers to store bufferized info +// +class XrdSutCacheEntry { +public: + char *name; + short status; + short cnt; // counter + kXR_int32 mtime; // time of last modification / creation + XrdSutCacheEntryBuf buf1; + XrdSutCacheEntryBuf buf2; + XrdSutCacheEntryBuf buf3; + XrdSutCacheEntryBuf buf4; + XrdSysRWLock rwmtx; // Locked when reference is outstanding + XrdSutCacheEntry(const char *n = 0, short st = 0, short cn = 0, + kXR_int32 mt = 0); + XrdSutCacheEntry(const XrdSutCacheEntry &e); + virtual ~XrdSutCacheEntry() { if (name) delete[] name; } + kXR_int32 Length() const { return (buf1.len + buf2.len + 2*sizeof(short) + + buf3.len + buf4.len + 5*sizeof(kXR_int32)); } + void Reset(); + void SetName(const char *n = 0); + char *AsString() const; + + XrdSutCacheEntry &operator=(const XrdSutCacheEntry &pfe); +}; + +class XrdSutCERef +{ +public: + +inline void ReadLock(XrdSysRWLock *lock = 0) + { if (lock) Set(lock); + rwlock->ReadLock(); + }; + +inline void WriteLock(XrdSysRWLock *lock = 0) + { if (lock) Set(lock); + rwlock->WriteLock(); + }; + +inline void Set(XrdSysRWLock *lock) + {if (rwlock) {if (rwlock != lock) rwlock->UnLock(); + else return; + } + rwlock = lock; + }; + +inline void UnLock(bool reset = true) {if (rwlock) {rwlock->UnLock(); if (reset) rwlock = 0; }} + + XrdSutCERef() : rwlock(0) {} + + ~XrdSutCERef() {if (rwlock) UnLock(); rwlock = 0; } +protected: +XrdSysRWLock *rwlock; +}; + +#endif