XrdOucCache.hh

Go to the documentation of this file.
00001 #ifndef __XRDOUCCACHE_HH__
00002 #define __XRDOUCCACHE_HH__
00003 /******************************************************************************/
00004 /*                                                                            */
00005 /*                        X r d O u c C a c h e . h h                         */
00006 /*                                                                            */
00007 /* (c) 2011 by the Board of Trustees of the Leland Stanford, Jr., University  */
00008 /*                            All Rights Reserved                             */
00009 /*   Produced by Andrew Hanushevsky for Stanford University under contract    */
00010 /*              DE-AC02-76-SFO0515 with the Department of Energy              */
00011 /*                                                                            */
00012 /* This file is part of the XRootD software suite.                            */
00013 /*                                                                            */
00014 /* XRootD is free software: you can redistribute it and/or modify it under    */
00015 /* the terms of the GNU Lesser General Public License as published by the     */
00016 /* Free Software Foundation, either version 3 of the License, or (at your     */
00017 /* option) any later version.                                                 */
00018 /*                                                                            */
00019 /* XRootD is distributed in the hope that it will be useful, but WITHOUT      */
00020 /* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or      */
00021 /* FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public       */
00022 /* License for more details.                                                  */
00023 /*                                                                            */
00024 /* You should have received a copy of the GNU Lesser General Public License   */
00025 /* along with XRootD in a file called COPYING.LESSER (LGPL license) and file  */
00026 /* COPYING (GPL license).  If not, see <http://www.gnu.org/licenses/>.        */
00027 /*                                                                            */
00028 /* The copyright holder's institutional names and contributor's names may not */
00029 /* be used to endorse or promote products derived from this software without  */
00030 /* specific prior written permission of the institution or contributor.       */
00031 /******************************************************************************/
00032 
00033 #include "XrdOuc/XrdOucIOVec.hh"
00034 #include "XrdSys/XrdSysPthread.hh"
00035 
00036 /* The classes defined here can be used to implement a general cache for
00037    data from an arbitrary source (e.g. files, sockets, etc); as follows:
00038 
00039    1. Create an instance of XrdOucCacheIO. This object is used to actually
00040       bring in missing data into the cache or write out dirty cache pages.
00041       There can be many instances of this class, as needed. However, make sure
00042       that there is a 1-to-1 unique correspondence between data and its CacheIO
00043       object. Violating this may cause the same data to be cached multiple
00044       times and if the cache is writable the data may be inconsistent!
00045 
00046    2. Create an instance of XrdOucCache. You can specify various cache
00047       handling parameters (see the class definition). You can also define
00048       additional instances if you want more than one cache. The specific cache
00049       you create will be defined by an implementation that derives from these
00050       classes. For instance, an implementation of a memory cache is defined
00051       in "XrdOucCacheDram.hh".
00052 
00053    3. Use the Attach() method in XrdOucCache to attach your XrdOucCacheIO
00054       object with a cache instance. The method returns a remanufactured
00055       XrdOucCacheIO object that interposes the cache in front of the original
00056       XrdOucCacheIO. This allows you to transparently use the cache.
00057 
00058    4. When finished using the remanufactured XrdOucCacheIO object, use its
00059       Detach() method to remove the association from the cache. Other actions
00060       are defined by the actual implementation. For instance XrdOucCacheDram
00061       also releases any assigned cache pages, writes out any dirty pages, and
00062       may optionally delete the object when all references have been removed.
00063 
00064    5. You may delete cache instances as well. Just be sure that no associations
00065       still exist using the XrdOucCache::isAttached() method. Otherwise, the
00066       cache destructor will wait until all attached objects are detached.
00067 
00068    Example:
00069       class physIO : public XrdOucCacheIO {...}; // Define required methods
00070       class xCache : public XrdOucCache   {...}; // The cache implementation
00071       XrdOucCache::Parms myParms;                // Set any desired parameters
00072       XrdOucCache   *myCache;
00073       XrdOucCacheIO *cacheIO;
00074       xCache         theCache;                   // Implementation instance
00075 
00076       myCache = theCache.Create(myParms);        // Create a cache instance
00077       cacheIO = myCache->Attach(physIO);         // Interpose the cache
00078 
00079       // Use cacheIO (fronted by myCache) instead of physIO. When done...
00080 
00081       delete cacheIO->Detach();                  // Deletes cacheIO and physIO
00082 */
00083   
00084 /******************************************************************************/
00085 /*                C l a s s   X r d O u c C a c h e S t a t s                 */
00086 /******************************************************************************/
00087   
00088 /* The XrdOucCacheStats object holds statistics on cache usage. It is available
00089    in for each XrdOucCacheIO and each XrdOucCache object. The former usually
00090    identifies a specific file while the latter provides summary information.
00091 */
00092 
00093 class XrdOucCacheStats
00094 {
00095 public:
00096 long long    BytesPead;  // Bytes read via preread (not included in BytesRead)
00097 long long    BytesRead;  // Total number of bytes read into the cache
00098 long long    BytesGet;   // Number of bytes delivered from the cache
00099 long long    BytesPass;  // Number of bytes read but not cached
00100 long long    BytesWrite; // Total number of bytes written from the cache
00101 long long    BytesPut;   // Number of bytes updated in the cache
00102 int          Hits;       // Number of times wanted data was in the cache
00103 int          Miss;       // Number of times wanted data was *not* in the cache
00104 int          HitsPR;     // Number of pages wanted data was just preread
00105 int          MissPR;     // Number of pages wanted data was just    read
00106 
00107 inline void Get(XrdOucCacheStats &Dst)
00108                {sMutex.Lock();
00109                 Dst.BytesRead   = BytesPead;  Dst.BytesGet    = BytesRead;
00110                 Dst.BytesPass   = BytesPass;
00111                 Dst.BytesWrite  = BytesWrite; Dst.BytesPut    = BytesPut;
00112                 Dst.Hits        = Hits;       Dst.Miss        = Miss;
00113                 Dst.HitsPR      = HitsPR;     Dst.MissPR      = MissPR;
00114                 sMutex.UnLock();
00115                }
00116 
00117 inline void Add(XrdOucCacheStats &Src)
00118                {sMutex.Lock();
00119                 BytesRead  += Src.BytesPead;  BytesGet   += Src.BytesRead;
00120                 BytesPass  += Src.BytesPass;
00121                 BytesWrite += Src.BytesWrite; BytesPut   += Src.BytesPut;
00122                 Hits       += Src.Hits;       Miss       += Src.Miss;
00123                 HitsPR     += Src.HitsPR;     MissPR     += Src.MissPR;
00124                 sMutex.UnLock();
00125                }
00126 
00127 inline void  Add(long long &Dest, int &Val)
00128                 {sMutex.Lock(); Dest += Val; sMutex.UnLock();}
00129 
00130 inline void  Lock()   {sMutex.Lock();}
00131 inline void  UnLock() {sMutex.UnLock();}
00132 
00133              XrdOucCacheStats() : BytesPead(0), BytesRead(0),  BytesGet(0),
00134                                   BytesPass(0), BytesWrite(0), BytesPut(0),
00135                                   Hits(0),      Miss(0),
00136                                   HitsPR(0),    MissPR(0) {}
00137             ~XrdOucCacheStats() {}
00138 private:
00139 XrdSysMutex sMutex;
00140 };
00141 
00142 /******************************************************************************/
00143 /*                       X r d O u c C a c h e I O C B                        */
00144 /******************************************************************************/
00145 
00146 //-----------------------------------------------------------------------------
00149 //-----------------------------------------------------------------------------
00150 
00151 class XrdOucCacheIOCB
00152 {
00153 public:
00154 
00155 //------------------------------------------------------------------------------
00161 //------------------------------------------------------------------------------
00162 virtual
00163 void     Done(int result) = 0;
00164 
00165          XrdOucCacheIOCB() {}
00166 virtual ~XrdOucCacheIOCB() {}
00167 };
00168 
00169 /******************************************************************************/
00170 /*                   C l a s s   X r d O u c C a c h e I O                    */
00171 /******************************************************************************/
00172 
00173 /* The XrdOucCacheIO object is responsible for interacting with the original
00174    data source/target. It can be used with or without a front-end cache.
00175 
00176    Six abstract methods are provided FSize(), Path(), Read(), Sync(), Trunc(),
00177    and Write(). You must provide implementations for each as described below.
00178 
00179    Four additional virtual methods are pre-defined: Base(), Detach(), and
00180    Preread() (2x). Normally, there is no need to over-ride these methods.
00181 
00182    Finally, each object carries with it a XrdOucCacheStats object.
00183 */
00184 
00185 class XrdOucCacheIO
00186 {
00187 public:
00188 
00189 // FSize()  returns the current size of the file associated with this object.
00190 
00191 //          Success: size of the file in bytes.
00192 //          Failure: -errno associated with the error.
00193 virtual
00194 long long   FSize() = 0;
00195 
00196 // Path()   returns the path name associated with this object.
00197 //
00198 virtual
00199 const char *Path() = 0;
00200 
00201 // Read()   places Length bytes in Buffer from a data source at Offset.
00202 //          When fronted by a cache, the cache is inspected first.
00203 
00204 //          Success: actual number of bytes placed in Buffer.
00205 //          Failure: -errno associated with the error.
00206 virtual
00207 int         Read (char *Buffer, long long Offset, int Length) = 0;
00208 
00209 // ReadV()  Performs a vector of read requests.  When fronted by a cache,
00210 //          the cache is inspected first.  By batching requests, it provides
00211 //          us the ability to skip expensive network round trips.
00212 //          If any reads fail or return short, the entire operation should
00213 //          fail.
00214 
00215 //          Success: actual number of bytes read.
00216 //          Failure: -errno associated with the read error.
00217 virtual
00218 int         ReadV(const XrdOucIOVec *readV, int n)
00219                  {int nbytes = 0, curCount = 0;
00220                   for (int i=0; i<n; i++)
00221                       {curCount = Read(readV[i].data,
00222                                        readV[i].offset,
00223                                        readV[i].size);
00224                        if (curCount != readV[i].size)
00225                           {if (curCount < 0) return curCount;
00226                            return -ESPIPE;
00227                           }
00228                        nbytes += curCount;
00229                       }
00230                   return nbytes;
00231                  }
00232 
00233 // Sync()   copies any outstanding modified bytes to the target.
00234 
00235 //          Success: return 0.
00236 //          Failure: -errno associated with the error.
00237 virtual
00238 int         Sync() = 0;
00239 
00240 // Trunc()  truncates the file to the specified offset.
00241 
00242 //          Success: return 0.
00243 //          Failure: -errno associated with the error.
00244 virtual
00245 int         Trunc(long long Offset) = 0;
00246 
00247 
00248 // Write()  takes Length bytes in Buffer and writes to a data target at Offset.
00249 //          When fronted by a cache, the cache is updated as well.
00250 
00251 //          Success: actual number of bytes copied from the Buffer.
00252 //          Failure: -errno associated with the error.
00253 virtual
00254 int         Write(char *Buffer, long long Offset, int Length) = 0;
00255 
00256 // Base()   returns the underlying XrdOucCacheIO object being used.
00257 //
00258 virtual XrdOucCacheIO *Base()   {return this;}
00259 
00260 // Detach() detaches the object from the cache. It must be called instead of
00261 //          using the delete operator since CacheIO objects may have multiple
00262 //          outstanding references and actual deletion may need to be defered.
00263 //          Detach() returns the underlying CacheIO object when the last
00264 //          reference has been removed and 0 otherwise. This allows to say
00265 //          something like "delete ioP->Detach()" if you want to make sure you
00266 //          delete the underlying object as well. Alternatively, use the optADB
00267 //          option when attaching a CacheIO object to a cache. This will delete
00268 //          underlying object and always return 0 to avoid a double delete.
00269 //          When not fronted by a cache, Detach() always returns itself. This
00270 //          makes its use consistent whether or not a cache is employed.
00271 //
00272 virtual XrdOucCacheIO *Detach() {return this;}
00273 
00274 
00275 // ioActive() returns true if there is any ongoing IO operation. The function is
00276 //            used in XrdPosixXrootd::Close() to check if destruction od PosixFile
00277 //            has to be done in a separate task. 
00278 virtual bool ioActive() { return false; }
00279 
00280 // Preread() places Length bytes into the cache from a data source at Offset.
00281 //          When there is no cache or the associated cache does not support or
00282 //          allow pre-reads, it's a no-op. Cache placement limits do not apply.
00283 //          To maximize parallelism, Peread() should called *after* obtaining
00284 //          the wanted bytes using Read(). If the cache implementation supports
00285 //          automatic prereads; you can setup parameters on how this should be
00286 //          done using the next the next structure and method. The following
00287 //          options can be specified:
00288 //
00289 static const int SingleUse = 0x0001; // Mark pages for single use
00290 
00291 virtual
00292 void        Preread (long long Offset, int Length, int Opts=0)
00293 {
00294   (void)Offset; (void)Length; (void)Opts;
00295 }
00296 
00297 // The following structure describes automatic preread parameters. These can be
00298 // set at any time for each XrdOucCacheIO object. It can also be specified when
00299 // creating a cache to establish the defaults (see XrdOucCache::Create()).
00300 // Generally, an implementation that supports prereads should disable small
00301 // prereads when minPages or loBound is set to zero; and should disable large
00302 // prereads when maxiRead or maxPages is set to zero. Refer to the actual
00303 // derived class implementation on how the cache handles prereads.
00304 //
00305 struct aprParms
00306       {int   Trigger;   // preread if (rdln < Trigger)        (0 -> pagesize+1)
00307        int   prRecalc;  // Recalc pr efficiency every prRecalc bytes   (0->50M)
00308        int   Reserve4;
00309        short minPages;  // If rdln/pgsz < min,  preread minPages       (0->off)
00310        signed
00311        char  minPerf;   // Minimum auto preread performance required   (0->n/a)
00312        char  Reserve1;
00313 
00314              aprParms() : Trigger(0),  prRecalc(0), Reserve4(0),
00315                           minPages(0), minPerf(90), Reserve1(0)
00316                           {}
00317       };
00318 
00319 virtual
00320 void        Preread(aprParms &Parms) { (void)Parms; }
00321 
00322 //          Here is where the stats about cache and I/O usage reside. There
00323 //          is a summary object in the associated cache as well.
00324 //
00325 XrdOucCacheStats Statistics;
00326 
00327 virtual    ~XrdOucCacheIO() {}  // Always use Detach() instead of direct delete!
00328 };
00329 
00330 /******************************************************************************/
00331 /*                     C l a s s   X r d O u c C a c h e                      */
00332 /******************************************************************************/
00333   
00334 /* The XrdOucCache class is used to define an instance of a cache. There can
00335    be many such instances. Each instance is associated with one or more
00336    XrdOucCacheIO objects. Use the Attach() method in this class to create 
00337    such associations.
00338 */
00339 
00340 class XrdOucCache
00341 {
00342 public:
00343 
00344 /* Attach()   must be called to obtain a new XrdOucCacheIO object that fronts an
00345               existing XrdOucCacheIO object with this cache.
00346               Upon success a pointer to a new XrdOucCacheIO object is returned
00347               and must be used to read and write data with the cache interposed.
00348               Upon failure, the original XrdOucCacheIO object is returned with
00349               errno set. You can continue using the object without any cache.
00350               The following Attach() options are available and, when specified,
00351               override the default options associated with the cache, except for
00352               optRW, optNEW, and optWIN which are valid only for a r/w cache.
00353 */
00354 static const int optADB = 0x1000; // Automatically delete underlying CacheIO
00355 static const int optFIS = 0x0001; // File is   Structured (e.g. root file)
00356 static const int optFIU = 0x0002; // File is Unstructured (e.g. unix file)
00357 static const int optRW  = 0x0004; // File is read/write   (o/w read/only)
00358 static const int optNEW = 0x0014; // File is new -> optRW (o/w read to write)
00359 static const int optWIN = 0x0024; // File is new -> optRW use write-in cache
00360 
00361 virtual
00362 XrdOucCacheIO *Attach(XrdOucCacheIO *ioP, int Options=0) = 0;
00363 
00364 /* isAttached()
00365                Returns the number of CacheIO objects attached to this cache.
00366                Hence, 0 (false) if none and true otherwise.
00367 */
00368 virtual
00369 int            isAttached() {return 0;}
00370 
00371 /* You must first create an instance of a cache using the Create() method.
00372    The Parms structure is used to pass parameters about the cache and should
00373    be filled in with values meaningful to the type of cache being created.
00374    The fields below, while oriented toward a memory cache, are sufficiently
00375    generic to apply to almost any kind of cache. Refer to the actual
00376    implementation in the derived class to see how these values are used.
00377 */
00378 struct Parms
00379       {long long CacheSize; // Size of cache in bytes     (default 100MB)
00380        int       PageSize;  // Size of each page in bytes (default 32KB)
00381        int       Max2Cache; // Largest read to cache      (default PageSize)
00382        int       MaxFiles;  // Maximum number of files    (default 256 or 8K)
00383        int       Options;   // Options as defined below   (default r/o cache)
00384        int       Reserve1;  // Reserved for future use
00385        int       Reserve2;  // Reserved for future use
00386 
00387                  Parms() : CacheSize(104857600), PageSize(32768),
00388                            Max2Cache(0), MaxFiles(0), Options(0),
00389                            Reserve1(0),  Reserve2(0) {}
00390       };
00391 
00392 // Valid option values in Parms::Options
00393 //
00394 static const int
00395 isServer     = 0x0010; // This is server application (as opposed to a user app).
00396                        // Appropriate internal optimizations will be used.
00397 static const int
00398 isStructured = 0x0020; // Optimize for structured files (e.g. root).
00399 
00400 static const int
00401 canPreRead   = 0x0040; // Enable pre-read operations (o/w ignored)
00402 
00403 static const int
00404 logStats     = 0x0080; // Display statistics upon detach
00405 
00406 static const int
00407 Serialized   = 0x0004; // Caller ensures MRSW semantics
00408 
00409 static const int
00410 ioMTSafe     = 0x0008; // CacheIO object is MT-safe
00411 
00412 static const int
00413 Debug        = 0x0003; // Produce some debug messages (levels 0, 1, 2, or 3)
00414 
00415 /* Create()    Creates an instance of a cache using the specified parameters.
00416                You must pass the cache parms and optionally any automatic
00417                pre-read parameters that will be used as future defaults.
00418                Upon success, returns a pointer to the cache. Otherwise, a null
00419                pointer is returned with errno set to indicate the problem.
00420 */
00421 virtual
00422 XrdOucCache   *Create(Parms &Params, XrdOucCacheIO::aprParms *aprP=0) = 0;
00423 
00424 
00425 // Propagate  Unlink client request from posix layer to cache.
00426 virtual
00427 int           Unlink(const char* /*path*/) { return 0; }    
00428 
00429 // Propagate  Rmdir client request from posix layer to cache.
00430 virtual
00431 int           Rmdir(const char* /*path*/) { return 0; }      
00432 
00433 // Propagate  Rename client request from posix layer to cache.
00434 virtual
00435 int           Rename(const char* /*path*/, const char* /*newPath*/) { return 0; }                
00436 
00437 // Propagate  Truncate client request from posix layer to cache.
00438 virtual
00439 int           Truncate(const char* /*path*/, off_t /*size*/) { return 0; }    
00440 
00441 /* The following holds statistics for the cache itself. It is updated as
00442    associated cacheIO objects are deleted and their statistics are added.
00443 */
00444 XrdOucCacheStats Stats;
00445 
00446                XrdOucCache() {}
00447 virtual       ~XrdOucCache() {}
00448 };
00449 
00450 /******************************************************************************/
00451 /*               C r e a t i n g   C a c h e   P l u g - I n s                */
00452 /******************************************************************************/
00453   
00454 /* You can create a cache plug-in for those parts of the xrootd system that
00455    allow a dynamically selectable cache implementation (e.g. the proxy server
00456    plug-in supports cache plug-ins via the pss.cachelib directive).
00457 
00458    Your plug-in must exist in a shared library and have the following extern C
00459    function defined:
00460 
00461    extern "C"
00462    {
00463    XrdOucCache *XrdOucGetCache(XrdSysLogger *Logger, // Where messages go
00464                                const char   *Config, // Config file used
00465                                const char   *Parms); // Optional parm string
00466    }
00467 
00468    When Logger is null, you should use cerr to output messages. Otherwise,
00469                         tie an instance XrdSysError to the passed logger.
00470    When Config is null, no configuration file is present. Otherwise, you need
00471                         additional configuration information you should get it
00472                         from that file in order to support single configuration.
00473    When Parms  is null, no parameter string was specified.
00474 
00475    The call should return an instance of an XrdOucCache object upon success and
00476    a null pointer otherwise. The instance is used to create actual caches using
00477    the object's Create() method.
00478 */
00479 #endif

Generated on 13 Mar 2017 for xrootd by  doxygen 1.4.7