From 4f6de02fc539ad7c73f9a992603ca9dda7cbe1ea Mon Sep 17 00:00:00 2001 From: Andrew Hanushevsky Date: Thu, 3 Mar 2016 05:43:04 -0800 Subject: [PATCH] [Posix] Stage 1: Implement async cache interface. --- src/XrdOuc/XrdOucCache2.hh | 304 +++++++++++++++++++++++++++++++++++++ src/XrdOuc/XrdOucIOVec.hh | 12 ++ 2 files changed, 316 insertions(+) create mode 100644 src/XrdOuc/XrdOucCache2.hh diff --git a/src/XrdOuc/XrdOucCache2.hh b/src/XrdOuc/XrdOucCache2.hh new file mode 100644 index 00000000000..0947d618c0c --- /dev/null +++ b/src/XrdOuc/XrdOucCache2.hh @@ -0,0 +1,304 @@ +#ifndef __XRDOUCCACHE2_HH__ +#define __XRDOUCCACHE2_HH__ +/******************************************************************************/ +/* */ +/* X r d O u c C a c h e 2 . h h */ +/* */ +/* (c) 2016 by the Board of Trustees of the Leland Stanford, Jr., University */ +/* All Rights Reserved */ +/* Produced by Andrew Hanushevsky for Stanford University under contract */ +/* DE-AC02-76-SFO0515 with the Department of Energy */ +/* */ +/* This file is part of the XRootD software suite. */ +/* */ +/* XRootD is free software: you can redistribute it and/or modify it under */ +/* the terms of the GNU Lesser General Public License as published by the */ +/* Free Software Foundation, either version 3 of the License, or (at your */ +/* option) any later version. */ +/* */ +/* XRootD is distributed in the hope that it will be useful, but WITHOUT */ +/* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or */ +/* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public */ +/* License for more details. */ +/* */ +/* You should have received a copy of the GNU Lesser General Public License */ +/* along with XRootD in a file called COPYING.LESSER (LGPL license) and file */ +/* COPYING (GPL license). If not, see . */ +/* */ +/* The copyright holder's institutional names and contributor's names may not */ +/* be used to endorse or promote products derived from this software without */ +/* specific prior written permission of the institution or contributor. */ +/******************************************************************************/ + +#include "XrdOuc/XrdOucCache.hh" + +//----------------------------------------------------------------------------- +//! XrdOucCache2 +//! +//! This class is an extension of the original XrdOucCache class and provides +//! async I/O support, defered open and I/O decoupling. It is loaded as a +//! cache plugin by the POSIX package via the proxy directive +//! +//! pss.cache -2 \ +//! +//! Without the "-2" the original version is loaded. Implementation of a cache +//! is similar between versions (see XrdOucCache.hh for details). The only +//! difference is this version requires additional methods to be implemented +//! and uses an asynchrnous callback mechanism to return the results. +//----------------------------------------------------------------------------- + +/******************************************************************************/ +/* C l a s s X r d O u c C a c h e 2 C B */ +/******************************************************************************/ + +//----------------------------------------------------------------------------- +//! The XrdOucCache2CB defines a callback object that must be used to handle +//! asynchronous operations (e.g. I/O). +//----------------------------------------------------------------------------- + +class XrdOucCache2CB +{ +public: + +//------------------------------------------------------------------------------ +//! Handle result from a previous async operation. +//! +//! @param result is result from a previous operation. Successful results are +//! always values >= 0 while errors are negative values and are +//! always '-errno' indicate the reason for the error. +//------------------------------------------------------------------------------ +virtual +void Done(int result) = 0; + + XrdOucCache2CB() {} +virtual ~XrdOucCache2CB() {} +}; + +/******************************************************************************/ +/* C l a s s X r d O u c C a c h e I O 2 */ +/******************************************************************************/ + +//------------------------------------------------------------------------------ +//! The XrdOucCacheIO2 object is responsible for interacting with the original +//! data source/target. It can be used with or without a front-end cache. It +//! an extension of the XrdOucCacheIO class which defines base methods. +//------------------------------------------------------------------------------ + +class XrdOucCacheIO2 : public virtual XrdOucCacheIO +{ +public: + +//------------------------------------------------------------------------------ +//! Perform an asynchronous file open request. This method is meant to be +//! by the cache layer using the original XrdOucCacheIO2 object passed to +//! Attach() after the cache layer has defered an open request via Prepare(). +//! The file is opened using the original url, oflags, and mode. +//! +//! @param iocb reference to the callback object that receives the result. All +//! results are returned via this object's Done() method. If the +//! caller holds any locks they must be recursive locks as the +//! callback may occur on the calling thread. Done() is passed +//! <0 - Open failed, value is -errno. +//! =0 - Open succeeded. +//------------------------------------------------------------------------------ + +virtual void Open(XrdOucCache2CB &iocb) {iocb.Done(-ENOSYS);} + +//------------------------------------------------------------------------------ +//! Perform an asynchronous read (defaults to synchrnous). +//! +//! @param iocb reference to the callback object that receives the result. All +//! results are returned via this object's Done() method. If the +//! caller holds any locks they must be recursive locks as the +//! callback may occur on the calling thread. Done() is passed +//! < 0 - Read failed, value is -errno. +//! >=0 - Read succeeded, value is number of bytes read. +//! @param buff pointer to the buffer to receive the results. The buffer must +//! remain valid until the callback is invoked. +//! @param offs the offset into the file. +//! @param rlen the number of bytes to read. +//------------------------------------------------------------------------------ + +using XrdOucCacheIO::Read; + +virtual void Read (XrdOucCache2CB &iocb, char *buff, long long offs, int rlen) + {iocb.Done(Read(buff, offs, rlen));} + +//------------------------------------------------------------------------------ +//! Perform an asynchronous vector read (defaults to synchrnous). +//! +//! @param iocb reference to the callback object that receives the result. All +//! results are returned via this object's Done() method. If the +//! caller holds any locks they must be recursive locks as the +//! callback may occur on the calling thread. Done() is passed +//! < 0 - ReadV failed, value is -errno. +//! >=0 - ReadV succeeded, value is number of bytes read. +//! @param readV pointer to a vector of read requests. +//! @param rnum the number of elements in the vector. +//------------------------------------------------------------------------------ + +using XrdOucCacheIO::ReadV; + +virtual void ReadV(XrdOucCache2CB &iocb, const XrdOucIOVec *readV, int rnum) + {iocb.Done(ReadV(readV, rnum));} + +//------------------------------------------------------------------------------ +//! Perform an asynchronous fsync() operation (defaults to synchronous). +//! +//! @param iocb reference to the callback object that receives the result. All +//! results are returned via this object's Done() method. If the +//! caller holds any locks they must be recursive locks as the +//! callback may occur on the calling thread. Done() is passed +//! <0 - Sync failed, value is -errno. +//! =0 - Sync succeeded. +//------------------------------------------------------------------------------ + +using XrdOucCacheIO::Sync; + +virtual void Sync(XrdOucCache2CB &iocb) {iocb.Done(Sync());} + +//------------------------------------------------------------------------------ +//! Perform an asynchronous trunc() operation (defaults to synchrnous). +//! +//! @param iocb reference to the callback object that receives the result. All +//! results are returned via this object's Done() method. If the +//! caller holds any locks they must be recursive locks as the +//! callback may occur on the calling thread. Done() is passsed +//! <0 - Trunc failed, value is -errno. +//! =0 - Trunc succeeded. +//! @param offs the size the file is to have. +//------------------------------------------------------------------------------ + +using XrdOucCacheIO::Trunc; + +virtual void Trunc(XrdOucCache2CB &iocb, long long offs) + {iocb.Done(Trunc(offs));} + +//------------------------------------------------------------------------------ +//! Perform an asynchronous write (defaults to synchronous). +//! +//! @param iocb reference to the callback object that receives the result. All +//! results are returned via this object's Done() method. If the +//! caller holds any locks they must be recursive locks as the +//! callback may occur on the calling thread. +//! < 0 - Write failed, value is -errno. +//! >=0 - Write succeeded, value is number of bytes written. +//! @param buff pointer to the buffer holding the contents. The buffer must +//! remain valid until the callback is invoked. +//! @param offs the offset into the file. +//! @param wlen the number of bytes to write +//------------------------------------------------------------------------------ + +using XrdOucCacheIO::Write; + +virtual void Write(XrdOucCache2CB &iocb, char *buff, long long offs, int wlen) + {iocb.Done(Write(buff, offs, wlen));} + +//------------------------------------------------------------------------------ + +virtual ~XrdOucCacheIO2() {} // Always use Detach() instead of direct delete! +}; + +/******************************************************************************/ +/* C l a s s X r d O u c C a c h e 2 */ +/******************************************************************************/ + +//------------------------------------------------------------------------------ +//! The XrdOucCache2 class is used to define a version 2 cache. In version 2, +//! there can be only one such instance. the cache is associated with one or +//! more XrdOucCacheIO2 objects. Use the Attach() method in this class to +//! create such associations. +//------------------------------------------------------------------------------ + +class XrdOucCache2 : public virtual XrdOucCache +{ +public: + +//------------------------------------------------------------------------------ +//! Obtain a new XrdOucCacheIO2 object that fronts an existing XrdOucCacheIO2 +//! with this cache. Upon success a pointer to a new XrdOucCacheIO2 object is +//! returned and must be used to read and write data with the cache interposed. +//! Upon failure, the original XrdOucCacheIO2 object is returned with errno set. +//! You can continue using the object without any cache. +//! +//! @param ioP Pointer to the current CacheIO2 object used for I/O. +//! @param opts Cache options identical to those defined for XrdOucCache +//! Attach() method. +//! +//! @return Pointer to a new XrdOucCacheIO2 object (success) or the original +//! XrdOucCacheIO2 object (failure) with errno set. +//------------------------------------------------------------------------------ +virtual +XrdOucCacheIO2 *Attach(XrdOucCacheIO2 *ioP, int opts=0) = 0; + +virtual +XrdOucCacheIO *Attach(XrdOucCacheIO *ioP, int opts=0) + {errno = ENOSYS; return ioP;} + +//------------------------------------------------------------------------------ +//! Creates an instance of a version 1 cache. This method is no longer used so +//! we simply define a default for this method here for backward compatability. +//! +//! @return A pointer to an XrdOucCache2 object upon success or a nil pointer +//! with errno set upon failure. +//------------------------------------------------------------------------------ +virtual +XrdOucCache *Create(Parms &Params, XrdOucCacheIO::aprParms *aprP=0) + {return this;} + +//------------------------------------------------------------------------------ +//! Preapare the cache for a file open request. This method is called prior to +//! actually opening a file. This method is meant to allow defering an open +//! request or implementing the full I/O stack in the cache layer. +//! +//! @param url - Pointer to the url about to be opened. +//! @param oflags - Standard Unix open flags (see open(2)). +//! @param mode - Standard mode flags if file is being created. +//! +//! @return <0 Error has occurred, return value is -errno; fail open request. +//! =0 Continue with open() request. +//! >0 Defer open but treat the file as actually being open. Use the +//! XrdOucCacheIO2::Open() method to open the file at a later time. +//------------------------------------------------------------------------------ +virtual +int Prepare(const char *url, int oflags, mode_t mode) + {(void)url; (void)oflags; (void)mode; return 0;} + + XrdOucCache2() {} +virtual ~XrdOucCache2() {} +}; + +/******************************************************************************/ +/* C r e a t i n g C a c h e P l u g - I n s */ +/******************************************************************************/ + +//------------------------------------------------------------------------------ +//! You can create a V2 cache plug-in for those parts of the xrootd system that +//! allow a dynamically selectable cache implementation (e.g. the proxy server +//! plug-in supports cache plug-ins via the pss.cachelib). For the proxy server, +//! it preferentially looks for XrdOucGetCache2() and invokes this function if +//! is exists. Otherwise, it uses the XrdOucGetCache() function (old version 1). +//! +//! Your plug-in must exist in a shared library and have the following extern C +//! function defined whos parameters are: +//! +//! @param Logger Pointer to the logger object that should be used with an +//! instance of XrdSysError to direct messages to a log file. +//! If Logger is null, you should use cerr to output messages. +//! @param Config Pointer to the configuration file name from where you +//! should get additional information. If Config is null, there +//! is no configuration file is present. +//! @param Parms Pointer to any parameters specified after the shared library +//! path. If Parms is null, there are no parameters. +//! @return A usable, fully configured, instance of an XrdOucCache2 +//! object upon success and a null pointer otherwise. This +//! instance is used for all operations defined by methods in +//! XrdOucCache bas class as well as this class. +//! +//! extern "C" +//! { +//! XrdOucCache2 *XrdOucGetCache2(XrdSysLogger *Logger, // Where messages go +//! const char *Config, // Config file used +//! const char *Parms); // Optional parm string +//! } +#endif diff --git a/src/XrdOuc/XrdOucIOVec.hh b/src/XrdOuc/XrdOucIOVec.hh index 10afb78858c..337df2c91e7 100644 --- a/src/XrdOuc/XrdOucIOVec.hh +++ b/src/XrdOuc/XrdOucIOVec.hh @@ -44,4 +44,16 @@ struct XrdOucIOVec int info; // Available for arbitrary use char *data; // Location to read into. }; + +// Add backward compatible constructor to XrdOucIOVec +// +struct XrdOucIOVec2 : public XrdOucIOVec +{ + XrdOucIOVec2(char *buff, long long offs, int sz, int inf=0) + {XrdOucIOVec::offset = offs; + XrdOucIOVec::size = sz; + XrdOucIOVec::info = inf; + XrdOucIOVec::data = buff; + } +}; #endif