xrootd
XrdOucCache.hh
Go to the documentation of this file.
1 #ifndef __XRDOUCCACHE_HH__
2 #define __XRDOUCCACHE_HH__
3 /******************************************************************************/
4 /* */
5 /* X r d O u c C a c h e . h h */
6 /* */
7 /* (c) 2011 by the Board of Trustees of the Leland Stanford, Jr., University */
8 /* All Rights Reserved */
9 /* Produced by Andrew Hanushevsky for Stanford University under contract */
10 /* DE-AC02-76-SFO0515 with the Department of Energy */
11 /* */
12 /* This file is part of the XRootD software suite. */
13 /* */
14 /* XRootD is free software: you can redistribute it and/or modify it under */
15 /* the terms of the GNU Lesser General Public License as published by the */
16 /* Free Software Foundation, either version 3 of the License, or (at your */
17 /* option) any later version. */
18 /* */
19 /* XRootD is distributed in the hope that it will be useful, but WITHOUT */
20 /* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or */
21 /* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public */
22 /* License for more details. */
23 /* */
24 /* You should have received a copy of the GNU Lesser General Public License */
25 /* along with XRootD in a file called COPYING.LESSER (LGPL license) and file */
26 /* COPYING (GPL license). If not, see <http://www.gnu.org/licenses/>. */
27 /* */
28 /* The copyright holder's institutional names and contributor's names may not */
29 /* be used to endorse or promote products derived from this software without */
30 /* specific prior written permission of the institution or contributor. */
31 /******************************************************************************/
32 
33 #include "XrdOuc/XrdOucIOVec.hh"
34 #include "XrdSys/XrdSysPthread.hh"
35 
36 /* The classes defined here can be used to implement a general cache for
37  data from an arbitrary source (e.g. files, sockets, etc); as follows:
38 
39  1. Create an instance of XrdOucCacheIO. This object is used to actually
40  bring in missing data into the cache or write out dirty cache pages.
41  There can be many instances of this class, as needed. However, make sure
42  that there is a 1-to-1 unique correspondence between data and its CacheIO
43  object. Violating this may cause the same data to be cached multiple
44  times and if the cache is writable the data may be inconsistent!
45 
46  2. Create an instance of XrdOucCache. You can specify various cache
47  handling parameters (see the class definition). You can also define
48  additional instances if you want more than one cache. The specific cache
49  you create will be defined by an implementation that derives from these
50  classes. For instance, an implementation of a memory cache is defined
51  in "XrdOucCacheDram.hh".
52 
53  3. Use the Attach() method in XrdOucCache to attach your XrdOucCacheIO
54  object with a cache instance. The method returns a remanufactured
55  XrdOucCacheIO object that interposes the cache in front of the original
56  XrdOucCacheIO. This allows you to transparently use the cache.
57 
58  4. When finished using the remanufactured XrdOucCacheIO object, use its
59  Detach() method to remove the association from the cache. Other actions
60  are defined by the actual implementation. For instance XrdOucCacheDram
61  also releases any assigned cache pages, writes out any dirty pages, and
62  may optionally delete the object when all references have been removed.
63 
64  5. You may delete cache instances as well. Just be sure that no associations
65  still exist using the XrdOucCache::isAttached() method. Otherwise, the
66  cache destructor will wait until all attached objects are detached.
67 
68  Example:
69  class physIO : public XrdOucCacheIO {...}; // Define required methods
70  class xCache : public XrdOucCache {...}; // The cache implementation
71  XrdOucCache::Parms myParms; // Set any desired parameters
72  XrdOucCache *myCache;
73  XrdOucCacheIO *cacheIO;
74  xCache theCache; // Implementation instance
75 
76  myCache = theCache.Create(myParms); // Create a cache instance
77  cacheIO = myCache->Attach(physIO); // Interpose the cache
78 
79  // Use cacheIO (fronted by myCache) instead of physIO. When done...
80 
81  delete cacheIO->Detach(); // Deletes cacheIO and physIO
82 */
83 
84 /******************************************************************************/
85 /* C l a s s X r d O u c C a c h e S t a t s */
86 /******************************************************************************/
87 
88 /* The XrdOucCacheStats object holds statistics on cache usage. It is available
89  in for each XrdOucCacheIO and each XrdOucCache object. The former usually
90  identifies a specific file while the latter provides summary information.
91 */
92 
94 {
95 public:
96 long long BytesPead; // Bytes read via preread (not included in BytesRead)
97 long long BytesRead; // Total number of bytes read into the cache
98 long long BytesGet; // Number of bytes delivered from the cache
99 long long BytesPass; // Number of bytes read but not cached
100 long long BytesWrite; // Total number of bytes written from the cache
101 long long BytesPut; // Number of bytes updated in the cache
102 int Hits; // Number of times wanted data was in the cache
103 int Miss; // Number of times wanted data was *not* in the cache
104 int HitsPR; // Number of pages wanted data was just preread
105 int MissPR; // Number of pages wanted data was just read
106 
107 inline void Get(XrdOucCacheStats &Dst)
108  {sMutex.Lock();
109  Dst.BytesRead = BytesPead; Dst.BytesGet = BytesRead;
110  Dst.BytesPass = BytesPass;
111  Dst.BytesWrite = BytesWrite; Dst.BytesPut = BytesPut;
112  Dst.Hits = Hits; Dst.Miss = Miss;
113  Dst.HitsPR = HitsPR; Dst.MissPR = MissPR;
114  sMutex.UnLock();
115  }
116 
117 inline void Add(XrdOucCacheStats &Src)
118  {sMutex.Lock();
119  BytesRead += Src.BytesPead; BytesGet += Src.BytesRead;
120  BytesPass += Src.BytesPass;
121  BytesWrite += Src.BytesWrite; BytesPut += Src.BytesPut;
122  Hits += Src.Hits; Miss += Src.Miss;
123  HitsPR += Src.HitsPR; MissPR += Src.MissPR;
124  sMutex.UnLock();
125  }
126 
127 inline void Add(long long &Dest, int &Val)
128  {sMutex.Lock(); Dest += Val; sMutex.UnLock();}
129 
130 inline void Lock() {sMutex.Lock();}
131 inline void UnLock() {sMutex.UnLock();}
132 
133  XrdOucCacheStats() : BytesPead(0), BytesRead(0), BytesGet(0),
134  BytesPass(0), BytesWrite(0), BytesPut(0),
135  Hits(0), Miss(0),
136  HitsPR(0), MissPR(0) {}
138 private:
140 };
141 
142 /******************************************************************************/
143 /* C l a s s X r d O u c C a c h e I O */
144 /******************************************************************************/
145 
146 /* The XrdOucCacheIO object is responsible for interacting with the original
147  data source/target. It can be used with or without a front-end cache.
148 
149  Six abstract methods are provided FSize(), Path(), Read(), Sync(), Trunc(),
150  and Write(). You must provide implementations for each as described below.
151 
152  Four additional virtual methods are pre-defined: Base(), Detach(), and
153  Preread() (2x). Normally, there is no need to over-ride these methods.
154 
155  Finally, each object carries with it a XrdOucCacheStats object.
156 */
157 
159 {
160 public:
161 
162 // FSize() returns the current size of the file associated with this object.
163 
164 // Success: size of the file in bytes.
165 // Failure: -errno associated with the error.
166 virtual
167 long long FSize() = 0;
168 
169 // Path() returns the path name associated with this object.
170 //
171 virtual
172 const char *Path() = 0;
173 
174 // Read() places Length bytes in Buffer from a data source at Offset.
175 // When fronted by a cache, the cache is inspected first.
176 
177 // Success: actual number of bytes placed in Buffer.
178 // Failure: -errno associated with the error.
179 virtual
180 int Read (char *Buffer, long long Offset, int Length) = 0;
181 
182 // ReadV() Performs a vector of read requests. When fronted by a cache,
183 // the cache is inspected first. By batching requests, it provides
184 // us the ability to skip expensive network round trips.
185 // If any reads fail or return short, the entire operation should
186 // fail.
187 
188 // Success: actual number of bytes read.
189 // Failure: -errno associated with the read error.
190 virtual
191 int ReadV(const XrdOucIOVec *readV, int n)
192  {int nbytes = 0, curCount = 0;
193  for (int i=0; i<n; i++)
194  {curCount = Read(readV[i].data,
195  readV[i].offset,
196  readV[i].size);
197  if (curCount != readV[i].size)
198  {if (curCount < 0) return curCount;
199  return -ESPIPE;
200  }
201  nbytes += curCount;
202  }
203  return nbytes;
204  }
205 
206 // Sync() copies any outstanding modified bytes to the target.
207 
208 // Success: return 0.
209 // Failure: -errno associated with the error.
210 virtual
211 int Sync() = 0;
212 
213 // Trunc() truncates the file to the specified offset.
214 
215 // Success: return 0.
216 // Failure: -errno associated with the error.
217 virtual
218 int Trunc(long long Offset) = 0;
219 
220 
221 // Write() takes Length bytes in Buffer and writes to a data target at Offset.
222 // When fronted by a cache, the cache is updated as well.
223 
224 // Success: actual number of bytes copied from the Buffer.
225 // Failure: -errno associated with the error.
226 virtual
227 int Write(char *Buffer, long long Offset, int Length) = 0;
228 
229 // Base() returns the underlying XrdOucCacheIO object being used.
230 //
231 virtual XrdOucCacheIO *Base() {return this;}
232 
233 // Detach() detaches the object from the cache. It must be called instead of
234 // using the delete operator since CacheIO objects may have multiple
235 // outstanding references and actual deletion may need to be defered.
236 // Detach() returns the underlying CacheIO object when the last
237 // reference has been removed and 0 otherwise. This allows to say
238 // something like "delete ioP->Detach()" if you want to make sure you
239 // delete the underlying object as well. Alternatively, use the optADB
240 // option when attaching a CacheIO object to a cache. This will delete
241 // underlying object and always return 0 to avoid a double delete.
242 // When not fronted by a cache, Detach() always returns itself. This
243 // makes its use consistent whether or not a cache is employed.
244 //
245 virtual XrdOucCacheIO *Detach() {return this;}
246 
247 
248 // ioActive() returns true if there is any ongoing IO operation. The function is
249 // used in XrdPosixXrootd::Close() to check if destruction od PosixFile
250 // has to be done in a separate task.
251 virtual bool ioActive() { return false; }
252 
253 // Preread() places Length bytes into the cache from a data source at Offset.
254 // When there is no cache or the associated cache does not support or
255 // allow pre-reads, it's a no-op. Cache placement limits do not apply.
256 // To maximize parallelism, Peread() should called *after* obtaining
257 // the wanted bytes using Read(). If the cache implementation supports
258 // automatic prereads; you can setup parameters on how this should be
259 // done using the next the next structure and method. The following
260 // options can be specified:
261 //
262 static const int SingleUse = 0x0001; // Mark pages for single use
263 
264 virtual
265 void Preread (long long Offset, int Length, int Opts=0)
266 {
267  (void)Offset; (void)Length; (void)Opts;
268 }
269 
270 // The following structure describes automatic preread parameters. These can be
271 // set at any time for each XrdOucCacheIO object. It can also be specified when
272 // creating a cache to establish the defaults (see XrdOucCache::Create()).
273 // Generally, an implementation that supports prereads should disable small
274 // prereads when minPages or loBound is set to zero; and should disable large
275 // prereads when maxiRead or maxPages is set to zero. Refer to the actual
276 // derived class implementation on how the cache handles prereads.
277 //
278 struct aprParms
279  {int Trigger; // preread if (rdln < Trigger) (0 -> pagesize+1)
280  int prRecalc; // Recalc pr efficiency every prRecalc bytes (0->50M)
281  int Reserve4;
282  short minPages; // If rdln/pgsz < min, preread minPages (0->off)
283  signed
284  char minPerf; // Minimum auto preread performance required (0->n/a)
285  char Reserve1;
286 
287  aprParms() : Trigger(0), prRecalc(0), Reserve4(0),
288  minPages(0), minPerf(90), Reserve1(0)
289  {}
290  };
291 
292 virtual
293 void Preread(aprParms &Parms) { (void)Parms; }
294 
295 // Here is where the stats about cache and I/O usage reside. There
296 // is a summary object in the associated cache as well.
297 //
299 
300 virtual ~XrdOucCacheIO() {} // Always use Detach() instead of direct delete!
301 };
302 
303 /******************************************************************************/
304 /* C l a s s X r d O u c C a c h e */
305 /******************************************************************************/
306 
307 /* The XrdOucCache class is used to define an instance of a cache. There can
308  be many such instances. Each instance is associated with one or more
309  XrdOucCacheIO objects. Use the Attach() method in this class to create
310  such associations.
311 */
312 
314 {
315 public:
316 
317 /* Attach() must be called to obtain a new XrdOucCacheIO object that fronts an
318  existing XrdOucCacheIO object with this cache.
319  Upon success a pointer to a new XrdOucCacheIO object is returned
320  and must be used to read and write data with the cache interposed.
321  Upon failure, the original XrdOucCacheIO object is returned with
322  errno set. You can continue using the object without any cache.
323  The following Attach() options are available and, when specified,
324  override the default options associated with the cache, except for
325  optRW, optNEW, and optWIN which are valid only for a r/w cache.
326 */
327 static const int optADB = 0x1000; // Automatically delete underlying CacheIO
328 static const int optFIS = 0x0001; // File is Structured (e.g. root file)
329 static const int optFIU = 0x0002; // File is Unstructured (e.g. unix file)
330 static const int optRW = 0x0004; // File is read/write (o/w read/only)
331 static const int optNEW = 0x0014; // File is new -> optRW (o/w read to write)
332 static const int optWIN = 0x0024; // File is new -> optRW use write-in cache
333 
334 virtual
335 XrdOucCacheIO *Attach(XrdOucCacheIO *ioP, int Options=0) = 0;
336 
337 /* isAttached()
338  Returns the number of CacheIO objects attached to this cache.
339  Hence, 0 (false) if none and true otherwise.
340 */
341 virtual
342 int isAttached() {return 0;}
343 
344 /* You must first create an instance of a cache using the Create() method.
345  The Parms structure is used to pass parameters about the cache and should
346  be filled in with values meaningful to the type of cache being created.
347  The fields below, while oriented toward a memory cache, are sufficiently
348  generic to apply to almost any kind of cache. Refer to the actual
349  implementation in the derived class to see how these values are used.
350 */
351 struct Parms
352  {long long CacheSize; // Size of cache in bytes (default 100MB)
353  int PageSize; // Size of each page in bytes (default 32KB)
354  int Max2Cache; // Largest read to cache (default PageSize)
355  int MaxFiles; // Maximum number of files (default 256 or 8K)
356  int Options; // Options as defined below (default r/o cache)
357  int Reserve1; // Reserved for future use
358  int Reserve2; // Reserved for future use
359 
360  Parms() : CacheSize(104857600), PageSize(32768),
361  Max2Cache(0), MaxFiles(0), Options(0),
362  Reserve1(0), Reserve2(0) {}
363  };
364 
365 // Valid option values in Parms::Options
366 //
367 static const int
368 isServer = 0x0010; // This is server application (as opposed to a user app).
369  // Appropriate internal optimizations will be used.
370 static const int
371 isStructured = 0x0020; // Optimize for structured files (e.g. root).
372 
373 static const int
374 canPreRead = 0x0040; // Enable pre-read operations (o/w ignored)
375 
376 static const int
377 logStats = 0x0080; // Display statistics upon detach
378 
379 static const int
380 Serialized = 0x0004; // Caller ensures MRSW semantics
381 
382 static const int
383 ioMTSafe = 0x0008; // CacheIO object is MT-safe
384 
385 static const int
386 Debug = 0x0003; // Produce some debug messages (levels 0, 1, 2, or 3)
387 
388 /* Create() Creates an instance of a cache using the specified parameters.
389  You must pass the cache parms and optionally any automatic
390  pre-read parameters that will be used as future defaults.
391  Upon success, returns a pointer to the cache. Otherwise, a null
392  pointer is returned with errno set to indicate the problem.
393 */
394 virtual
395 XrdOucCache *Create(Parms &Params, XrdOucCacheIO::aprParms *aprP=0) = 0;
396 
397 
398 // Propagate Unlink client request from posix layer to cache.
399 virtual
400 int Unlink(const char* /*path*/) { return 0; }
401 
402 // Propagate Rmdir client request from posix layer to cache.
403 virtual
404 int Rmdir(const char* /*path*/) { return 0; }
405 
406 // Propagate Rename client request from posix layer to cache.
407 virtual
408 int Rename(const char* /*path*/, const char* /*newPath*/) { return 0; }
409 
410 // Propagate Truncate client request from posix layer to cache.
411 virtual
412 int Truncate(const char* /*path*/, off_t /*size*/) { return 0; }
413 
414 /* The following holds statistics for the cache itself. It is updated as
415  associated cacheIO objects are deleted and their statistics are added.
416 */
418 
420 virtual ~XrdOucCache() {}
421 };
422 
423 /******************************************************************************/
424 /* C r e a t i n g C a c h e P l u g - I n s */
425 /******************************************************************************/
426 
427 /* You can create a cache plug-in for those parts of the xrootd system that
428  allow a dynamically selectable cache implementation (e.g. the proxy server
429  plug-in supports cache plug-ins via the pss.cachelib directive).
430 
431  Your plug-in must exist in a shared library and have the following extern C
432  function defined:
433 
434  extern "C"
435  {
436  XrdOucCache *XrdOucGetCache(XrdSysLogger *Logger, // Where messages go
437  const char *Config, // Config file used
438  const char *Parms); // Optional parm string
439  }
440 
441  When Logger is null, you should use cerr to output messages. Otherwise,
442  tie an instance XrdSysError to the passed logger.
443  When Config is null, no configuration file is present. Otherwise, you need
444  additional configuration information you should get it
445  from that file in order to support single configuration.
446  When Parms is null, no parameter string was specified.
447 
448  The call should return an instance of an XrdOucCache object upon success and
449  a null pointer otherwise. The instance is used to create actual caches using
450  the object's Create() method.
451 */
452 #endif
XrdOucCacheStats()
Definition: XrdOucCache.hh:133
virtual XrdOucCacheIO * Base()
Definition: XrdOucCache.hh:231
long long BytesPass
Definition: XrdOucCache.hh:99
virtual XrdOucCacheIO * Attach(XrdOucCacheIO *ioP, int Options=0)=0
virtual void Preread(aprParms &Parms)
Definition: XrdOucCache.hh:293
Parms()
Definition: XrdOucCache.hh:360
static const int ioMTSafe
Definition: XrdOucCache.hh:383
static const int Debug
Definition: XrdOucCache.hh:386
~XrdOucCacheStats()
Definition: XrdOucCache.hh:137
static const int isStructured
Definition: XrdOucCache.hh:371
static const int SingleUse
Definition: XrdOucCache.hh:262
aprParms()
Definition: XrdOucCache.hh:287
virtual int Truncate(const char *, off_t)
Definition: XrdOucCache.hh:412
XrdOucCache()
Definition: XrdOucCache.hh:419
static const int logStats
Definition: XrdOucCache.hh:377
Definition: XrdOucCache.hh:158
virtual int Read(char *Buffer, long long Offset, int Length)=0
int Reserve2
Definition: XrdOucCache.hh:358
virtual int Rmdir(const char *)
Definition: XrdOucCache.hh:404
static const int optNEW
Definition: XrdOucCache.hh:331
void Add(XrdOucCacheStats &Src)
Definition: XrdOucCache.hh:117
virtual int Trunc(long long Offset)=0
int Max2Cache
Definition: XrdOucCache.hh:354
int MaxFiles
Definition: XrdOucCache.hh:355
virtual int Write(char *Buffer, long long Offset, int Length)=0
long long BytesGet
Definition: XrdOucCache.hh:98
XrdOucCacheStats Stats
Definition: XrdOucCache.hh:417
int Options
Definition: XrdOucCache.hh:356
void Get(XrdOucCacheStats &Dst)
Definition: XrdOucCache.hh:107
short minPages
Definition: XrdOucCache.hh:282
static const int optFIU
Definition: XrdOucCache.hh:329
Definition: XrdSysPthread.hh:140
long long BytesRead
Definition: XrdOucCache.hh:97
int Hits
Definition: XrdOucCache.hh:102
Definition: XrdOucCache.hh:313
int Miss
Definition: XrdOucCache.hh:103
static const int optFIS
Definition: XrdOucCache.hh:328
virtual const char * Path()=0
virtual int Rename(const char *, const char *)
Definition: XrdOucCache.hh:408
virtual int ReadV(const XrdOucIOVec *readV, int n)
Definition: XrdOucCache.hh:191
int HitsPR
Definition: XrdOucCache.hh:104
Definition: XrdOucIOVec.hh:40
int Reserve4
Definition: XrdOucCache.hh:281
long long BytesPut
Definition: XrdOucCache.hh:101
virtual ~XrdOucCacheIO()
Definition: XrdOucCache.hh:300
long long CacheSize
Definition: XrdOucCache.hh:352
Definition: XrdOucCache.hh:278
static const int optADB
Definition: XrdOucCache.hh:327
static const int canPreRead
Definition: XrdOucCache.hh:374
static const int isServer
Definition: XrdOucCache.hh:368
virtual bool ioActive()
Definition: XrdOucCache.hh:251
int PageSize
Definition: XrdOucCache.hh:353
virtual int Unlink(const char *)
Definition: XrdOucCache.hh:400
char Reserve1
Definition: XrdOucCache.hh:285
virtual XrdOucCacheIO * Detach()
Definition: XrdOucCache.hh:245
void Lock()
Definition: XrdSysPthread.hh:149
long long BytesPead
Definition: XrdOucCache.hh:96
int Reserve1
Definition: XrdOucCache.hh:357
virtual int isAttached()
Definition: XrdOucCache.hh:342
virtual int Sync()=0
int Trigger
Definition: XrdOucCache.hh:279
int MissPR
Definition: XrdOucCache.hh:105
void UnLock()
Definition: XrdOucCache.hh:131
XrdSysMutex sMutex
Definition: XrdOucCache.hh:139
static const int optWIN
Definition: XrdOucCache.hh:332
void Lock()
Definition: XrdOucCache.hh:130
static const int optRW
Definition: XrdOucCache.hh:330
long long BytesWrite
Definition: XrdOucCache.hh:100
Definition: XrdOucCache.hh:93
virtual ~XrdOucCache()
Definition: XrdOucCache.hh:420
virtual void Preread(long long Offset, int Length, int Opts=0)
Definition: XrdOucCache.hh:265
virtual long long FSize()=0
Definition: XrdOucCache.hh:351
void UnLock()
Definition: XrdSysPthread.hh:151
int prRecalc
Definition: XrdOucCache.hh:280
void Add(long long &Dest, int &Val)
Definition: XrdOucCache.hh:127
signed char minPerf
Definition: XrdOucCache.hh:284
virtual XrdOucCache * Create(Parms &Params, XrdOucCacheIO::aprParms *aprP=0)=0
static const int Serialized
Definition: XrdOucCache.hh:380
XrdOucCacheStats Statistics
Definition: XrdOucCache.hh:298