#ifndef __SUT_CACHE_H #define __SUT_CACHE_H /******************************************************************************/ /* */ /* X r d S u t C a c h e . 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 "XrdOuc/XrdOucHash.hh" #include "XrdSut/XrdSutCacheEntry.hh" #include "XrdSys/XrdSysPthread.hh" /******************************************************************************/ /* */ /* Class defining the basic memory cache */ /* */ /******************************************************************************/ typedef bool (*XrdSutCacheGet_t)(XrdSutCacheEntry *, void *); typedef struct { long arg1; long arg2; long arg3; long arg4; } XrdSutCacheArg_t; class XrdSutCache { public: XrdSutCache(int psize = 89, int size = 144, int load = 80) : table(psize, size, load) {} virtual ~XrdSutCache() {} XrdSutCacheEntry *Get(const char *tag) { // Get the entry with 'tag'. // If found the entry is returned rd-locked. // If rd-locking fails the status is set to kCE_inactive. // Returns null if not found. XrdSutCacheEntry *cent = 0; // Exclusive access to the table XrdSysMutexHelper raii(mtx); // Look for an entry if (!(cent = table.Find(tag))) { // none found return cent; } // We found an existing entry: // lock until we get the ability to read (another thread may be valudating it) int status = 0; cent->rwmtx.ReadLock( status ); if ( status ) { // A problem occured: fail (set the entry invalid) cent->status = kCE_inactive; } return cent; } 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); int status = 0; cent->rwmtx.WriteLock( status ); if (status) { // 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) int status = 0; cent->rwmtx.ReadLock( status ); if (status) { // A problem occured: fail (set the entry invalid) cent->status = kCE_inactive; return cent; } // 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(); int status = 0; cent->rwmtx.WriteLock( status ); if (status) { // A problem occured: fail (set the entry invalid) cent->status = kCE_inactive; return cent; } } } 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(); } private: XrdSysRecMutex mtx; // Protect access to table XrdOucHash table; // table with content }; #endif