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 /*                   C l a s s   X r d O u c C a c h e I O                    */
00144 /******************************************************************************/
00145 
00146 /* The XrdOucCacheIO object is responsible for interacting with the original
00147    data source/target. It can be used with or without a front-end cache.
00148 
00149    Six abstract methods are provided FSize(), Path(), Read(), Sync(), Trunc(),
00150    and Write(). You must provide implementations for each as described below.
00151 
00152    Four additional virtual methods are pre-defined: Base(), Detach(), and
00153    Preread() (2x). Normally, there is no need to over-ride these methods.
00154 
00155    Finally, each object carries with it a XrdOucCacheStats object.
00156 */
00157 
00158 class XrdOucCacheIO
00159 {
00160 public:
00161 
00162 // FSize()  returns the current size of the file associated with this object.
00163 
00164 //          Success: size of the file in bytes.
00165 //          Failure: -errno associated with the error.
00166 virtual
00167 long long   FSize() = 0;
00168 
00169 // Path()   returns the path name associated with this object.
00170 //
00171 virtual
00172 const char *Path() = 0;
00173 
00174 // Read()   places Length bytes in Buffer from a data source at Offset.
00175 //          When fronted by a cache, the cache is inspected first.
00176 
00177 //          Success: actual number of bytes placed in Buffer.
00178 //          Failure: -errno associated with the error.
00179 virtual
00180 int         Read (char *Buffer, long long Offset, int Length) = 0;
00181 
00182 // ReadV()  Performs a vector of read requests.  When fronted by a cache,
00183 //          the cache is inspected first.  By batching requests, it provides
00184 //          us the ability to skip expensive network round trips.
00185 //          If any reads fail or return short, the entire operation should
00186 //          fail.
00187 
00188 //          Success: actual number of bytes read.
00189 //          Failure: -errno associated with the read error.
00190 virtual
00191 int         ReadV(const XrdOucIOVec *readV, int n)
00192                  {int nbytes = 0, curCount = 0;
00193                   for (int i=0; i<n; i++)
00194                       {curCount = Read(readV[i].data,
00195                                        readV[i].offset,
00196                                        readV[i].size);
00197                        if (curCount != readV[i].size)
00198                           {if (curCount < 0) return curCount;
00199                            return -ESPIPE;
00200                           }
00201                        nbytes += curCount;
00202                       }
00203                   return nbytes;
00204                  }
00205 
00206 // Sync()   copies any outstanding modified bytes to the target.
00207 
00208 //          Success: return 0.
00209 //          Failure: -errno associated with the error.
00210 virtual
00211 int         Sync() = 0;
00212 
00213 // Trunc()  truncates the file to the specified offset.
00214 
00215 //          Success: return 0.
00216 //          Failure: -errno associated with the error.
00217 virtual
00218 int         Trunc(long long Offset) = 0;
00219 
00220 
00221 // Write()  takes Length bytes in Buffer and writes to a data target at Offset.
00222 //          When fronted by a cache, the cache is updated as well.
00223 
00224 //          Success: actual number of bytes copied from the Buffer.
00225 //          Failure: -errno associated with the error.
00226 virtual
00227 int         Write(char *Buffer, long long Offset, int Length) = 0;
00228 
00229 // Base()   returns the underlying XrdOucCacheIO object being used.
00230 //
00231 virtual XrdOucCacheIO *Base()   {return this;}
00232 
00233 // Detach() detaches the object from the cache. It must be called instead of
00234 //          using the delete operator since CacheIO objects may have multiple
00235 //          outstanding references and actual deletion may need to be defered.
00236 //          Detach() returns the underlying CacheIO object when the last
00237 //          reference has been removed and 0 otherwise. This allows to say
00238 //          something like "delete ioP->Detach()" if you want to make sure you
00239 //          delete the underlying object as well. Alternatively, use the optADB
00240 //          option when attaching a CacheIO object to a cache. This will delete
00241 //          underlying object and always return 0 to avoid a double delete.
00242 //          When not fronted by a cache, Detach() always returns itself. This
00243 //          makes its use consistent whether or not a cache is employed.
00244 //
00245 virtual XrdOucCacheIO *Detach() {return this;}
00246 
00247 
00248 // ioActive() returns true if there is any ongoing IO operation. The function is
00249 //            used in XrdPosixXrootd::Close() to check if destruction od PosixFile
00250 //            has to be done in a separate task. 
00251 virtual bool ioActive() { return false; }
00252 
00253 // Preread() places Length bytes into the cache from a data source at Offset.
00254 //          When there is no cache or the associated cache does not support or
00255 //          allow pre-reads, it's a no-op. Cache placement limits do not apply.
00256 //          To maximize parallelism, Peread() should called *after* obtaining
00257 //          the wanted bytes using Read(). If the cache implementation supports
00258 //          automatic prereads; you can setup parameters on how this should be
00259 //          done using the next the next structure and method. The following
00260 //          options can be specified:
00261 //
00262 static const int SingleUse = 0x0001; // Mark pages for single use
00263 
00264 virtual
00265 void        Preread (long long Offset, int Length, int Opts=0)
00266 {
00267   (void)Offset; (void)Length; (void)Opts;
00268 }
00269 
00270 // The following structure describes automatic preread parameters. These can be
00271 // set at any time for each XrdOucCacheIO object. It can also be specified when
00272 // creating a cache to establish the defaults (see XrdOucCache::Create()).
00273 // Generally, an implementation that supports prereads should disable small
00274 // prereads when minPages or loBound is set to zero; and should disable large
00275 // prereads when maxiRead or maxPages is set to zero. Refer to the actual
00276 // derived class implementation on how the cache handles prereads.
00277 //
00278 struct aprParms
00279       {int   Trigger;   // preread if (rdln < Trigger)        (0 -> pagesize+1)
00280        int   prRecalc;  // Recalc pr efficiency every prRecalc bytes   (0->50M)
00281        int   Reserve4;
00282        short minPages;  // If rdln/pgsz < min,  preread minPages       (0->off)
00283        signed
00284        char  minPerf;   // Minimum auto preread performance required   (0->n/a)
00285        char  Reserve1;
00286 
00287              aprParms() : Trigger(0),  prRecalc(0), Reserve4(0),
00288                           minPages(0), minPerf(90), Reserve1(0)
00289                           {}
00290       };
00291 
00292 virtual
00293 void        Preread(aprParms &Parms) { (void)Parms; }
00294 
00295 //          Here is where the stats about cache and I/O usage reside. There
00296 //          is a summary object in the associated cache as well.
00297 //
00298 XrdOucCacheStats Statistics;
00299 
00300 virtual    ~XrdOucCacheIO() {}  // Always use Detach() instead of direct delete!
00301 };
00302 
00303 /******************************************************************************/
00304 /*                     C l a s s   X r d O u c C a c h e                      */
00305 /******************************************************************************/
00306   
00307 /* The XrdOucCache class is used to define an instance of a cache. There can
00308    be many such instances. Each instance is associated with one or more
00309    XrdOucCacheIO objects. Use the Attach() method in this class to create 
00310    such associations.
00311 */
00312 
00313 class XrdOucCache
00314 {
00315 public:
00316 
00317 /* Attach()   must be called to obtain a new XrdOucCacheIO object that fronts an
00318               existing XrdOucCacheIO object with this cache.
00319               Upon success a pointer to a new XrdOucCacheIO object is returned
00320               and must be used to read and write data with the cache interposed.
00321               Upon failure, the original XrdOucCacheIO object is returned with
00322               errno set. You can continue using the object without any cache.
00323               The following Attach() options are available and, when specified,
00324               override the default options associated with the cache, except for
00325               optRW, optNEW, and optWIN which are valid only for a r/w cache.
00326 */
00327 static const int optADB = 0x1000; // Automatically delete underlying CacheIO
00328 static const int optFIS = 0x0001; // File is   Structured (e.g. root file)
00329 static const int optFIU = 0x0002; // File is Unstructured (e.g. unix file)
00330 static const int optRW  = 0x0004; // File is read/write   (o/w read/only)
00331 static const int optNEW = 0x0014; // File is new -> optRW (o/w read to write)
00332 static const int optWIN = 0x0024; // File is new -> optRW use write-in cache
00333 
00334 virtual
00335 XrdOucCacheIO *Attach(XrdOucCacheIO *ioP, int Options=0) = 0;
00336 
00337 /* isAttached()
00338                Returns the number of CacheIO objects attached to this cache.
00339                Hence, 0 (false) if none and true otherwise.
00340 */
00341 virtual
00342 int            isAttached() {return 0;}
00343 
00344 /* You must first create an instance of a cache using the Create() method.
00345    The Parms structure is used to pass parameters about the cache and should
00346    be filled in with values meaningful to the type of cache being created.
00347    The fields below, while oriented toward a memory cache, are sufficiently
00348    generic to apply to almost any kind of cache. Refer to the actual
00349    implementation in the derived class to see how these values are used.
00350 */
00351 struct Parms
00352       {long long CacheSize; // Size of cache in bytes     (default 100MB)
00353        int       PageSize;  // Size of each page in bytes (default 32KB)
00354        int       Max2Cache; // Largest read to cache      (default PageSize)
00355        int       MaxFiles;  // Maximum number of files    (default 256 or 8K)
00356        int       Options;   // Options as defined below   (default r/o cache)
00357        int       Reserve1;  // Reserved for future use
00358        int       Reserve2;  // Reserved for future use
00359 
00360                  Parms() : CacheSize(104857600), PageSize(32768),
00361                            Max2Cache(0), MaxFiles(0), Options(0),
00362                            Reserve1(0),  Reserve2(0) {}
00363       };
00364 
00365 // Valid option values in Parms::Options
00366 //
00367 static const int
00368 isServer     = 0x0010; // This is server application (as opposed to a user app).
00369                        // Appropriate internal optimizations will be used.
00370 static const int
00371 isStructured = 0x0020; // Optimize for structured files (e.g. root).
00372 
00373 static const int
00374 canPreRead   = 0x0040; // Enable pre-read operations (o/w ignored)
00375 
00376 static const int
00377 logStats     = 0x0080; // Display statistics upon detach
00378 
00379 static const int
00380 Serialized   = 0x0004; // Caller ensures MRSW semantics
00381 
00382 static const int
00383 ioMTSafe     = 0x0008; // CacheIO object is MT-safe
00384 
00385 static const int
00386 Debug        = 0x0003; // Produce some debug messages (levels 0, 1, 2, or 3)
00387 
00388 /* Create()    Creates an instance of a cache using the specified parameters.
00389                You must pass the cache parms and optionally any automatic
00390                pre-read parameters that will be used as future defaults.
00391                Upon success, returns a pointer to the cache. Otherwise, a null
00392                pointer is returned with errno set to indicate the problem.
00393 */
00394 virtual
00395 XrdOucCache   *Create(Parms &Params, XrdOucCacheIO::aprParms *aprP=0) = 0;
00396 
00397 /* The following holds statistics for the cache itself. It is updated as
00398    associated cacheIO objects are deleted and their statistics are added.
00399 */
00400 XrdOucCacheStats Stats;
00401 
00402                XrdOucCache() {}
00403 virtual       ~XrdOucCache() {}
00404 };
00405 
00406 /******************************************************************************/
00407 /*               C r e a t i n g   C a c h e   P l u g - I n s                */
00408 /******************************************************************************/
00409   
00410 /* You can create a cache plug-in for those parts of the xrootd system that
00411    allow a dynamically selectable cache implementation (e.g. the proxy server
00412    plug-in supports cache plug-ins via the pss.cachelib directive).
00413 
00414    Your plug-in must exist in a shared library and have the following extern C
00415    function defined:
00416 
00417    extern "C"
00418    {
00419    XrdOucCache *XrdOucGetCache(XrdSysLogger *Logger, // Where messages go
00420                                const char   *Config, // Config file used
00421                                const char   *Parms); // Optional parm string
00422    }
00423 
00424    When Logger is null, you should use cerr to output messages. Otherwise,
00425                         tie an instance XrdSysError to the passed logger.
00426    When Config is null, no configuration file is present. Otherwise, you need
00427                         additional configuration information you should get it
00428                         from that file in order to support single configuration.
00429    When Parms  is null, no parameter string was specified.
00430 
00431    The call should return an instance of an XrdOucCache object upon success and
00432    a null pointer otherwise. The instance is used to create actual caches using
00433    the object's Create() method.
00434 */
00435 #endif

Generated on 12 Dec 2014 for xrootd by  doxygen 1.4.7