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 "XrdSys/XrdSysPthread.hh"
00034   
00035 /* The classes defined here can be used to implement a general cache for
00036    data from an arbitrary source (e.g. files, sockets, etc); as follows:
00037 
00038    1. Create an instance of XrdOucCacheIO. This object is used to actually
00039       bring in missing data into the cache or write out dirty cache pages.
00040       There can be many instances of this class, as needed. However, make sure
00041       that there is a 1-to-1 unique correspondence between data and its CacheIO
00042       object. Violating this may cause the same data to be cached multiple
00043       times and if the cache is writable the data may be inconsistent!
00044 
00045    2. Create an instance of XrdOucCache. You can specify various cache
00046       handling parameters (see the class definition). You can also define
00047       additional instances if you want more than one cache. The specific cache
00048       you create will be defined by an implementation that derives from these
00049       classes. For instance, an implementation of a memory cache is defined
00050       in "XrdOucCacheDram.hh".
00051 
00052    3. Use the Attach() method in XrdOucCache to attach your XrdOucCacheIO
00053       object with a cache instance. The method returns a remanufactured
00054       XrdOucCacheIO object that interposes the cache in front of the original
00055       XrdOucCacheIO. This allows you to transparently use the cache.
00056 
00057    4. When finished using the remanufactured XrdOucCacheIO object, use its
00058       Detach() method to remove the association from the cache. Other actions
00059       are defined by the actual implementation. For instance XrdOucCacheDram
00060       also releases any assigned cache pages, writes out any dirty pages, and
00061       may optionally delete the object when all references have been removed.
00062 
00063    5. You may delete cache instances as well. Just be sure that no associations
00064       still exist using the XrdOucCache::isAttached() method. Otherwise, the
00065       cache destructor will wait until all attached objects are detached.
00066 
00067    Example:
00068       class physIO : public XrdOucCacheIO {...}; // Define required methods
00069       class xCache : public XrdOucCache   {...}; // The cache implementation
00070       XrdOucCache::Parms myParms;                // Set any desired parameters
00071       XrdOucCache   *myCache;
00072       XrdOucCacheIO *cacheIO;
00073       xCache         theCache;                   // Implementation instance
00074 
00075       myCache = theCache.Create(myParms);        // Create a cache instance
00076       cacheIO = myCache->Attach(physIO);         // Interpose the cache
00077 
00078       // Use cacheIO (fronted by myCache) instead of physIO. When done...
00079 
00080       delete cacheIO->Detach();                  // Deletes cacheIO and physIO
00081 */
00082   
00083 /******************************************************************************/
00084 /*                C l a s s   X r d O u c C a c h e S t a t s                 */
00085 /******************************************************************************/
00086   
00087 /* The XrdOucCacheStats object holds statistics on cache usage. It is available
00088    in for each XrdOucCacheIO and each XrdOucCache object. The former usually
00089    identifies a specific file while the latter provides summary information.
00090 */
00091 
00092 class XrdOucCacheStats
00093 {
00094 public:
00095 long long    BytesPead;  // Bytes read via preread (not included in BytesRead)
00096 long long    BytesRead;  // Total number of bytes read into the cache
00097 long long    BytesGet;   // Number of bytes delivered from the cache
00098 long long    BytesPass;  // Number of bytes read but not cached
00099 long long    BytesWrite; // Total number of bytes written from the cache
00100 long long    BytesPut;   // Number of bytes updated in the cache
00101 int          Hits;       // Number of times wanted data was in the cache
00102 int          Miss;       // Number of times wanted data was *not* in the cache
00103 int          HitsPR;     // Number of pages wanted data was just preread
00104 int          MissPR;     // Number of pages wanted data was just    read
00105 
00106 inline void Get(XrdOucCacheStats &Dst)
00107                {sMutex.Lock();
00108                 Dst.BytesRead   = BytesPead;  Dst.BytesGet    = BytesRead;
00109                 Dst.BytesPass   = BytesPass;
00110                 Dst.BytesWrite  = BytesWrite; Dst.BytesPut    = BytesPut;
00111                 Dst.Hits        = Hits;       Dst.Miss        = Miss;
00112                 Dst.HitsPR      = HitsPR;     Dst.MissPR      = MissPR;
00113                 sMutex.UnLock();
00114                }
00115 
00116 inline void Add(XrdOucCacheStats &Src)
00117                {sMutex.Lock();
00118                 BytesRead  += Src.BytesPead;  BytesGet   += Src.BytesRead;
00119                 BytesPass  += Src.BytesPass;
00120                 BytesWrite += Src.BytesWrite; BytesPut   += Src.BytesPut;
00121                 Hits       += Src.Hits;       Miss       += Src.Miss;
00122                 HitsPR     += Src.HitsPR;     MissPR     += Src.MissPR;
00123                 sMutex.UnLock();
00124                }
00125 
00126 inline void  Add(long long &Dest, int &Val)
00127                 {sMutex.Lock(); Dest += Val; sMutex.UnLock();}
00128 
00129 inline void  Lock()   {sMutex.Lock();}
00130 inline void  UnLock() {sMutex.UnLock();}
00131 
00132              XrdOucCacheStats() : BytesPead(0), BytesRead(0),  BytesGet(0),
00133                                   BytesPass(0), BytesWrite(0), BytesPut(0),
00134                                   Hits(0),      Miss(0),
00135                                   HitsPR(0),    MissPR(0) {}
00136             ~XrdOucCacheStats() {}
00137 private:
00138 XrdSysMutex sMutex;
00139 };
00140 
00141 /******************************************************************************/
00142 /*                   C l a s s   X r d O u c C a c h e I O                    */
00143 /******************************************************************************/
00144 
00145 /* The XrdOucCacheIO object is responsible for interacting with the original
00146    data source/target. It can be used with or without a front-end cache.
00147 
00148    Six abstract methods are provided FSize(), Path(), Read(), Sync(), Trunc(),
00149    and Write(). You must provide implementations for each as described below.
00150 
00151    Four additional virtual methods are pre-defined: Base(), Detach(), and
00152    Preread() (2x). Normally, there is no need to over-ride these methods.
00153 
00154    Finally, each object carries with it a XrdOucCacheStats object.
00155 */
00156 
00157 class XrdOucCacheIO
00158 {
00159 public:
00160 
00161 // FSize()  returns the current size of the file associated with this object.
00162 
00163 //          Success: size of the file in bytes.
00164 //          Failure: -errno associated with the error.
00165 virtual
00166 long long   FSize() = 0;
00167 
00168 // Path()   returns the path name associated with this object.
00169 //
00170 virtual
00171 const char *Path() = 0;
00172 
00173 // Read()   places Length bytes in Buffer from a data source at Offset.
00174 //          When fronted by a cache, the cache is inspected first.
00175 
00176 //          Success: actual number of bytes placed in Buffer.
00177 //          Failure: -errno associated with the error.
00178 virtual
00179 int         Read (char *Buffer, long long Offset, int Length) = 0;
00180 
00181 // Sync()   copies any outstanding modified bytes to the target.
00182 
00183 //          Success: return 0.
00184 //          Failure: -errno associated with the error.
00185 virtual
00186 int         Sync() = 0;
00187 
00188 // Trunc()  truncates the file to the specified offset.
00189 
00190 //          Success: return 0.
00191 //          Failure: -errno associated with the error.
00192 virtual
00193 int         Trunc(long long Offset) = 0;
00194 
00195 
00196 // Write()  takes Length bytes in Buffer and writes to a data target at Offset.
00197 //          When fronted by a cache, the cache is updated as well.
00198 
00199 //          Success: actual number of bytes copied from the Buffer.
00200 //          Failure: -errno associated with the error.
00201 virtual
00202 int         Write(char *Buffer, long long Offset, int Length) = 0;
00203 
00204 // Base()   returns the underlying XrdOucCacheIO object being used.
00205 //
00206 virtual XrdOucCacheIO *Base()   {return this;}
00207 
00208 // Detach() detaches the object from the cache. It must be called instead of
00209 //          using the delete operator since CacheIO objects may have multiple
00210 //          outstanding references and actual deletion may need to be defered.
00211 //          Detach() returns the underlying CacheIO object when the last
00212 //          reference has been removed and 0 otherwise. This allows to say
00213 //          something like "delete ioP->Detach()" if you want to make sure you
00214 //          delete the underlying object as well. Alternatively, use the optADB
00215 //          option when attaching a CacheIO object to a cache. This will delete
00216 //          underlying object and always return 0 to avoid a double delete.
00217 //          When not fronted by a cache, Detach() always returns itself. This
00218 //          makes its use consistent whether or not a cache is employed.
00219 //
00220 virtual XrdOucCacheIO *Detach() {return this;}
00221 
00222 // Preread() places Length bytes into the cache from a data source at Offset.
00223 //          When there is no cache or the associated cache does not support or
00224 //          allow pre-reads, it's a no-op. Cache placement limits do not apply.
00225 //          To maximize parallelism, Peread() should called *after* obtaining
00226 //          the wanted bytes using Read(). If the cache implementation supports
00227 //          automatic prereads; you can setup parameters on how this should be
00228 //          done using the next the next structure and method. The following
00229 //          options can be specified:
00230 //
00231 static const int SingleUse = 0x0001; // Mark pages for single use
00232 
00233 virtual
00234 void        Preread (long long Offset, int Length, int Opts=0) {}
00235 
00236 // The following structure describes automatic preread parameters. These can be
00237 // set at any time for each XrdOucCacheIO object. It can also be specified when
00238 // creating a cache to establish the defaults (see XrdOucCache::Create()).
00239 // Generally, an implementation that supports prereads should disable small
00240 // prereads when minPages or loBound is set to zero; and should disable large
00241 // prereads when maxiRead or maxPages is set to zero. Refer to the actual
00242 // derived class implementation on how the cache handles prereads.
00243 //
00244 struct aprParms
00245       {int   Trigger;   // preread if (rdln < Trigger)        (0 -> pagesize+1)
00246        int   prRecalc;  // Recalc pr efficiency every prRecalc bytes   (0->50M)
00247        int   Reserve4;
00248        short minPages;  // If rdln/pgsz < min,  preread minPages       (0->off)
00249        char  minPerf;   // Minimum auto preread performance required   (0->n/a)
00250        char  Reserve1;
00251 
00252              aprParms() : Trigger(0),  prRecalc(0), Reserve4(0),
00253                           minPages(0), minPerf(90), Reserve1(0)
00254                           {}
00255       };
00256 
00257 virtual
00258 void        Preread(aprParms &Parms) {}
00259 
00260 //          Here is where the stats about cache and I/O usage reside. There
00261 //          is a summary object in the associated cache as well.
00262 //
00263 XrdOucCacheStats Statistics;
00264 
00265 virtual    ~XrdOucCacheIO() {}  // Always use Detach() instead of direct delete!
00266 };
00267 
00268 /******************************************************************************/
00269 /*                     C l a s s   X r d O u c C a c h e                      */
00270 /******************************************************************************/
00271   
00272 /* The XrdOucCache class is used to define an instance of a cache. There can
00273    be many such instances. Each instance is associated with one or more
00274    XrdOucCacheIO objects. Use the Attach() method in this class to create 
00275    such associations.
00276 */
00277 
00278 class XrdOucCache
00279 {
00280 public:
00281 
00282 /* Attach()   must be called to obtain a new XrdOucCacheIO object that fronts an
00283               existing XrdOucCacheIO object with this cache.
00284               Upon success a pointer to a new XrdOucCacheIO object is returned
00285               and must be used to read and write data with the cache interposed.
00286               Upon failure, the original XrdOucCacheIO object is returned with
00287               errno set. You can continue using the object without any cache.
00288               The following Attach() options are available and, when specified,
00289               override the default options associated with the cache, except for
00290               optRW, optNEW, and optWIN which are valid only for a r/w cache.
00291 */
00292 static const int optADB = 0x1000; // Automatically delete underlying CacheIO
00293 static const int optFIS = 0x0001; // File is   Structured (e.g. root file)
00294 static const int optFIU = 0x0002; // File is Unstructured (e.g. unix file)
00295 static const int optRW  = 0x0004; // File is read/write   (o/w read/only)
00296 static const int optNEW = 0x0014; // File is new -> optRW (o/w read to write)
00297 static const int optWIN = 0x0024; // File is new -> optRW use write-in cache
00298 
00299 virtual
00300 XrdOucCacheIO *Attach(XrdOucCacheIO *ioP, int Options=0) = 0;
00301 
00302 /* isAttached()
00303                Returns the number of CacheIO objects attached to this cache.
00304                Hence, 0 (false) if none and true otherwise.
00305 */
00306 virtual
00307 int            isAttached() {return 0;}
00308 
00309 /* You must first create an instance of a cache using the Create() method.
00310    The Parms structure is used to pass parameters about the cache and should
00311    be filled in with values meaningful to the type of cache being created.
00312    The fields below, while oriented toward a memory cache, are sufficiently
00313    generic to apply to almost any kind of cache. Refer to the actual
00314    implementation in the derived class to see how these values are used.
00315 */
00316 struct Parms
00317       {long long CacheSize; // Size of cache in bytes     (default 100MB)
00318        int       PageSize;  // Size of each page in bytes (default 32KB)
00319        int       Max2Cache; // Largest read to cache      (default PageSize)
00320        int       MaxFiles;  // Maximum number of files    (default 256 or 8K)
00321        int       Options;   // Options as defined below   (default r/o cache)
00322        int       Reserve1;  // Reserved for future use
00323        int       Reserve2;  // Reserved for future use
00324 
00325                  Parms() : CacheSize(104857600), PageSize(32768),
00326                            Max2Cache(0), MaxFiles(0), Options(0),
00327                            Reserve1(0),  Reserve2(0) {}
00328       };
00329 
00330 // Valid option values in Parms::Options
00331 //
00332 static const int
00333 isServer     = 0x0010; // This is server application (as opposed to a user app).
00334                        // Appropriate internal optimizations will be used.
00335 static const int
00336 isStructured = 0x0020; // Optimize for structured files (e.g. root).
00337 
00338 static const int
00339 canPreRead   = 0x0040; // Enable pre-read operations (o/w ignored)
00340 
00341 static const int
00342 logStats     = 0x0080; // Display statistics upon detach
00343 
00344 static const int
00345 Serialized   = 0x0004; // Caller ensures MRSW semantics
00346 
00347 static const int
00348 ioMTSafe     = 0x0008; // CacheIO object is MT-safe
00349 
00350 static const int
00351 Debug        = 0x0003; // Produce some debug messages (levels 0, 1, 2, or 3)
00352 
00353 /* Create()    Creates an instance of a cache using the specified parameters.
00354                You must pass the cache parms and optionally any automatic
00355                pre-read parameters that will be used as future defaults.
00356                Upon success, returns a pointer to the cache. Otherwise, a null
00357                pointer is returned with errno set to indicate the problem.
00358 */
00359 virtual
00360 XrdOucCache   *Create(Parms &Params, XrdOucCacheIO::aprParms *aprP=0) = 0;
00361 
00362 /* The following holds statistics for the cache itself. It is updated as
00363    associated cacheIO objects are deleted and their statistics are added.
00364 */
00365 XrdOucCacheStats Stats;
00366 
00367                XrdOucCache() {}
00368 virtual       ~XrdOucCache() {}
00369 };
00370 
00371 /******************************************************************************/
00372 /*               C r e a t i n g   C a c h e   P l u g - I n s                */
00373 /******************************************************************************/
00374   
00375 /* You can create a cache plug-in for those parts of the xrootd system that
00376    allow a dynamically selectable cache implementation (e.g. the proxy server
00377    plug-in supports cache plug-ins via the pss.cachelib directive).
00378 
00379    Your plug-in must exist in a shared library and have the following extern C
00380    function defined:
00381 
00382    extern "C"
00383    {
00384    XrdOucCache *XrdOucGetCache(XrdSysLogger *Logger, // Where messages go
00385                                const char   *Config, // Config file used
00386                                const char   *Parms); // Optional parm string
00387    }
00388 
00389    When Logger is null, you should use cerr to output messages. Otherwise,
00390                         tie an instance XrdSysError to the passed logger.
00391    When Config is null, no configuration file is present. Otherwise, you need
00392                         additional configuration information you should get it
00393                         from that file in order to support single configuration.
00394    When Parms  is null, no parameter string was specified.
00395 
00396    The call should return an instance of an XrdOucCache object upon success and
00397    a null pointer otherwise. The instance is used to create actual caches using
00398    the object's Create() method.
00399 */
00400 #endif

Generated on 27 Jul 2013 for xrootd by  doxygen 1.4.7