#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