//------------------------------------------------------------------------------ // Copyright (c) 2011-2017 by European Organization for Nuclear Research (CERN) // Author: Krzysztof Jamrog , // Michal Simon //------------------------------------------------------------------------------ // 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 General Public License for more details. // // You should have received a copy of the GNU Lesser General Public License // along with XRootD. If not, see . // // In applying this licence, CERN does not waive the privileges and immunities // granted to it by virtue of its status as an Intergovernmental Organization // or submit itself to any jurisdiction. //------------------------------------------------------------------------------ #ifndef __XRD_CL_FILE_OPERATIONS_HH__ #define __XRD_CL_FILE_OPERATIONS_HH__ #include "XrdCl/XrdClFile.hh" #include "XrdCl/XrdClOperations.hh" #include "XrdCl/XrdClOperationHandlers.hh" namespace XrdCl { //---------------------------------------------------------------------------- //! Base class for all file releated operations //! //! @arg Derived : the class that derives from this template (CRTP) //! @arg HasHndl : true if operation has a handler, false otherwise //! @arg Args : operation arguments //---------------------------------------------------------------------------- template class Derived, bool HasHndl, typename Response, typename ... Arguments> class FileOperation: public ConcreteOperation { template class, bool, typename, typename ...> friend class FileOperation; public: //------------------------------------------------------------------------ //! Constructor //! //! @param f : file on which the operation will be performed //! @param args : file operation arguments //------------------------------------------------------------------------ FileOperation( File *f, Arguments... args): ConcreteOperation( std::move( args )... ), file(f) { } //------------------------------------------------------------------------ //! Constructor //! //! @param f : file on which the operation will be performed //! @param args : file operation arguments //------------------------------------------------------------------------ FileOperation( File &f, Arguments... args): FileOperation( &f, std::move( args )... ) { } //------------------------------------------------------------------------ //! Move constructor from other states //! //! @arg from : state from which the object is being converted //! //! @param op : the object that is being converted //------------------------------------------------------------------------ template FileOperation( FileOperation && op ) : ConcreteOperation( std::move( op ) ), file( op.file ) { } //------------------------------------------------------------------------ //! Destructor //------------------------------------------------------------------------ virtual ~FileOperation() { } protected: //------------------------------------------------------------------------ //! The file object itself //------------------------------------------------------------------------ File *file; }; //---------------------------------------------------------------------------- //! Open operation (@see FileOperation) //---------------------------------------------------------------------------- template class OpenImpl: public FileOperation, Arg, Arg, Arg> { //------------------------------------------------------------------------ //! Helper for extending the operator>> capabilities. //! //! In addition to standard overloads for std::function adds: //! - void( XRootDStatus&, StatInfo& ) //! - void( XRootDStatus&, StatInfo&, OperationContext& ) //------------------------------------------------------------------------ struct ExResp : public Resp { //-------------------------------------------------------------------- //! Constructor //! //! @param file : the underlying XrdCl::File object //-------------------------------------------------------------------- ExResp( XrdCl::File &file ): file( file ) { } //-------------------------------------------------------------------- //! A factory method //! //! @param func : the function/functor/lambda that should be wrapped //! @return : ResponseHandler instance //-------------------------------------------------------------------- inline ResponseHandler* Create( std::function func ) { return new ExOpenFuncWrapper( this->file, func ); } //-------------------------------------------------------------------- //! Make other overloads of Create visible //-------------------------------------------------------------------- using Resp::Create; //-------------------------------------------------------------------- //! The underlying XrdCl::File object //-------------------------------------------------------------------- XrdCl::File &file; }; public: //------------------------------------------------------------------------ //! Constructor (@see FileOperation) //------------------------------------------------------------------------ OpenImpl( File *f, Arg url, Arg flags, Arg mode = Access::None ) : FileOperation, Arg, Arg, Arg>( f, std::move( url ), std::move( flags ), std::move( mode ) ) { } //------------------------------------------------------------------------ //! Constructor (@see FileOperation) //------------------------------------------------------------------------ OpenImpl( File &f, Arg url, Arg flags, Arg mode = Access::None ) : FileOperation, Arg, Arg, Arg>( &f, std::move( url ), std::move( flags ), std::move( mode ) ) { } //------------------------------------------------------------------------ //! Move constructor from other states //! //! @arg from : state from which the object is being converted //! //! @param op : the object that is being converted //------------------------------------------------------------------------ template OpenImpl( OpenImpl && open ) : FileOperation, Arg, Arg, Arg>( std::move( open ) ) { } //------------------------------------------------------------------------ //! Argument indexes in the args tuple //------------------------------------------------------------------------ enum { UrlArg, FlagsArg, ModeArg }; //------------------------------------------------------------------------ //! Overload of operator>> defined in ConcreteOperation, we're adding //! additional capabilities by using ExResp factory (@see ExResp). //! //! @param func : function/functor/lambda //------------------------------------------------------------------------ template OpenImpl operator>>( Hdlr &&hdlr ) { // check if the resulting handler should be owned by us or by the user, // if the user passed us directly a ResponseHandler it's owned by the // user, otherwise we need to wrap the argument in a handler and in this // case the resulting handler will be owned by us constexpr bool own = !IsResponseHandler::value; ExResp factory( *this->file ); return this->StreamImpl( factory.Create( hdlr ), own ); } //------------------------------------------------------------------------ //! @return : name of the operation (@see Operation) //------------------------------------------------------------------------ std::string ToString() { return "Open"; } protected: //------------------------------------------------------------------------ //! RunImpl operation (@see Operation) //! //! @param params : container with parameters forwarded from //! previous operation //! @return : status of the operation //------------------------------------------------------------------------ XRootDStatus RunImpl() { try { std::string url = std::get( this->args ).Get(); OpenFlags::Flags flags = std::get( this->args ).Get(); Access::Mode mode = std::get( this->args ).Get(); return this->file->Open( url, flags, mode, this->handler.get() ); } catch( const PipelineException& ex ) { return ex.GetError(); } catch( const std::exception& ex ) { return XRootDStatus( stError, ex.what() ); } } }; typedef OpenImpl Open; //---------------------------------------------------------------------------- //! Read operation (@see FileOperation) //---------------------------------------------------------------------------- template class ReadImpl: public FileOperation, Arg, Arg, Arg> { public: //------------------------------------------------------------------------ //! Inherit constructors from FileOperation (@see FileOperation) //------------------------------------------------------------------------ using FileOperation, Arg, Arg, Arg>::FileOperation; //------------------------------------------------------------------------ //! Argument indexes in the args tuple //------------------------------------------------------------------------ enum { OffsetArg, SizeArg, BufferArg }; //------------------------------------------------------------------------ //! @return : name of the operation (@see Operation) //------------------------------------------------------------------------ std::string ToString() { return "Read"; } protected: //------------------------------------------------------------------------ //! RunImpl operation (@see Operation) //! //! @param params : container with parameters forwarded from //! previous operation //! @return : status of the operation //------------------------------------------------------------------------ XRootDStatus RunImpl() { try { uint64_t offset = std::get( this->args ).Get(); uint32_t size = std::get( this->args ).Get(); void *buffer = std::get( this->args ).Get(); return this->file->Read( offset, size, buffer, this->handler.get() ); } catch( const PipelineException& ex ) { return ex.GetError(); } catch( const std::exception& ex ) { return XRootDStatus( stError, ex.what() ); } } }; typedef ReadImpl Read; //---------------------------------------------------------------------------- //! Close operation (@see FileOperation) //---------------------------------------------------------------------------- template class CloseImpl: public FileOperation> { public: //------------------------------------------------------------------------ //! Inherit constructors from FileOperation (@see FileOperation) //------------------------------------------------------------------------ using FileOperation>::FileOperation; //------------------------------------------------------------------------ //! @return : name of the operation (@see Operation) //------------------------------------------------------------------------ std::string ToString() { return "Close"; } protected: //------------------------------------------------------------------------ //! RunImpl operation (@see Operation) //! //! @param params : container with parameters forwarded from //! previous operation //! @return : status of the operation //------------------------------------------------------------------------ XRootDStatus RunImpl() { return this->file->Close( this->handler.get() ); } }; typedef CloseImpl Close; //---------------------------------------------------------------------------- //! Stat operation (@see FileOperation) //---------------------------------------------------------------------------- template class StatImpl: public FileOperation, Arg> { public: //------------------------------------------------------------------------ //! Inherit constructors from FileOperation (@see FileOperation) //------------------------------------------------------------------------ using FileOperation, Arg>::FileOperation; //------------------------------------------------------------------------ //! Argument indexes in the args tuple //------------------------------------------------------------------------ enum { ForceArg }; //------------------------------------------------------------------------ //! @return : name of the operation (@see Operation) //------------------------------------------------------------------------ std::string ToString() { return "Stat"; } protected: //------------------------------------------------------------------------ //! RunImpl operation (@see Operation) //! //! @param params : container with parameters forwarded from //! previous operation //! @return : status of the operation //------------------------------------------------------------------------ XRootDStatus RunImpl() { try { bool force = std::get( this->args ).Get(); return this->file->Stat( force, this->handler.get() ); } catch( const PipelineException& ex ) { return ex.GetError(); } catch( const std::exception& ex ) { return XRootDStatus( stError, ex.what() ); } } }; //---------------------------------------------------------------------------- //! Factory for creating StatImpl objects (as there is another Stat in //! FileSystem there would be a clash of typenames). //---------------------------------------------------------------------------- StatImpl Stat( File *file, Arg force ) { return StatImpl( file, std::move( force ) ); } //---------------------------------------------------------------------------- //! Factory for creating StatImpl objects (as there is another Stat in //! FileSystem there would be a clash of typenames). //---------------------------------------------------------------------------- StatImpl Stat( File &file, Arg force ) { return StatImpl( file, std::move( force ) ); } //---------------------------------------------------------------------------- //! Write operation (@see FileOperation) //---------------------------------------------------------------------------- template class WriteImpl: public FileOperation, Arg, Arg, Arg> { public: //------------------------------------------------------------------------ //! Inherit constructors from FileOperation (@see FileOperation) //------------------------------------------------------------------------ using FileOperation, Arg, Arg, Arg>::FileOperation; //------------------------------------------------------------------------ //! Argument indexes in the args tuple //------------------------------------------------------------------------ enum { OffsetArg, SizeArg, BufferArg }; //------------------------------------------------------------------------ //! @return : name of the operation (@see Operation) //------------------------------------------------------------------------ std::string ToString() { return "Write"; } protected: //------------------------------------------------------------------------ //! RunImpl operation (@see Operation) //! //! @param params : container with parameters forwarded from //! previous operation //! @return : status of the operation //------------------------------------------------------------------------ XRootDStatus RunImpl() { try { uint64_t offset = std::get( this->args ).Get(); uint32_t size = std::get( this->args ).Get(); void *buffer = std::get( this->args ).Get(); return this->file->Write( offset, size, buffer, this->handler.get() ); } catch( const PipelineException& ex ) { return ex.GetError(); } catch( const std::exception& ex ) { return XRootDStatus( stError, ex.what() ); } } }; typedef WriteImpl Write; //---------------------------------------------------------------------------- //! Sync operation (@see FileOperation) //---------------------------------------------------------------------------- template class SyncImpl: public FileOperation> { public: //------------------------------------------------------------------------ //! Inherit constructors from FileOperation (@see FileOperation) //------------------------------------------------------------------------ using FileOperation>::FileOperation; //------------------------------------------------------------------------ //! @return : name of the operation (@see Operation) //------------------------------------------------------------------------ std::string ToString() { return "Sync"; } protected: //------------------------------------------------------------------------ //! RunImpl operation (@see Operation) //! //! @param params : container with parameters forwarded from //! previous operation //! @return : status of the operation //------------------------------------------------------------------------ XRootDStatus RunImpl() { return this->file->Sync( this->handler.get() ); } }; typedef SyncImpl Sync; //---------------------------------------------------------------------------- //! Truncate operation (@see FileOperation) //---------------------------------------------------------------------------- template class TruncateImpl: public FileOperation, Arg> { public: //------------------------------------------------------------------------ //! Inherit constructors from FileOperation (@see FileOperation) //------------------------------------------------------------------------ using FileOperation, Arg>::FileOperation; //------------------------------------------------------------------------ //! Argument indexes in the args tuple //------------------------------------------------------------------------ enum { SizeArg }; //------------------------------------------------------------------------ //! @return : name of the operation (@see Operation) //------------------------------------------------------------------------ std::string ToString() { return "Truncate"; } protected: //------------------------------------------------------------------------ //! RunImpl operation (@see Operation) //! //! @param params : container with parameters forwarded from //! previous operation //! @return : status of the operation //------------------------------------------------------------------------ XRootDStatus RunImpl() { try { uint64_t size = std::get( this->args ).Get(); return this->file->Truncate( size, this->handler.get() ); } catch( const PipelineException& ex ) { return ex.GetError(); } catch( const std::exception& ex ) { return XRootDStatus( stError, ex.what() ); } } }; //---------------------------------------------------------------------------- //! Factory for creating TruncateImpl objects (as there is another Stat in //! FileSystem there would be a clash of typenames). //---------------------------------------------------------------------------- TruncateImpl Truncate( File *file, Arg size ) { return TruncateImpl( file, std::move( size ) ); } //---------------------------------------------------------------------------- //! Factory for creating TruncateImpl objects (as there is another Stat in //! FileSystem there would be a clash of typenames). //---------------------------------------------------------------------------- TruncateImpl Truncate( File &file, Arg size ) { return TruncateImpl( file, std::move( size ) ); } //---------------------------------------------------------------------------- //! VectorRead operation (@see FileOperation) //---------------------------------------------------------------------------- template class VectorReadImpl: public FileOperation, Arg, Arg> { public: //------------------------------------------------------------------------ //! Inherit constructors from FileOperation (@see FileOperation) //------------------------------------------------------------------------ using FileOperation, Arg, Arg>::FileOperation; //------------------------------------------------------------------------ //! Argument indexes in the args tuple //------------------------------------------------------------------------ enum { ChunksArg, BufferArg }; //------------------------------------------------------------------------ //! @return : name of the operation (@see Operation) //------------------------------------------------------------------------ std::string ToString() { return "VectorRead"; } protected: //------------------------------------------------------------------------ //! RunImpl operation (@see Operation) //! //! @param params : container with parameters forwarded from //! previous operation //! @return : status of the operation //------------------------------------------------------------------------ XRootDStatus RunImpl() { try { ChunkList chunks( std::get( this->args ).Get() ); void *buffer = std::get( this->args ).Get(); return this->file->VectorRead( chunks, buffer, this->handler.get() ); } catch( const PipelineException& ex ) { return ex.GetError(); } catch( const std::exception& ex ) { return XRootDStatus( stError, ex.what() ); } } }; typedef VectorReadImpl VectorRead; //---------------------------------------------------------------------------- //! VectorWrite operation (@see FileOperation) //---------------------------------------------------------------------------- template class VectorWriteImpl: public FileOperation, Arg> { public: //------------------------------------------------------------------------ //! Inherit constructors from FileOperation (@see FileOperation) //------------------------------------------------------------------------ using FileOperation, Arg>::FileOperation; //------------------------------------------------------------------------ //! Argument indexes in the args tuple //------------------------------------------------------------------------ enum { ChunksArg }; //------------------------------------------------------------------------ //! @return : name of the operation (@see Operation) //------------------------------------------------------------------------ std::string ToString() { return "VectorWrite"; } protected: //------------------------------------------------------------------------ //! RunImpl operation (@see Operation) //! //! @param params : container with parameters forwarded from //! previous operation //! @return : status of the operation //------------------------------------------------------------------------ XRootDStatus RunImpl() { try { const ChunkList chunks( std::get( this->args ).Get() ); return this->file->VectorWrite( chunks, this->handler.get() ); } catch( const PipelineException& ex ) { return ex.GetError(); } catch( const std::exception& ex ) { return XRootDStatus( stError, ex.what() ); } } }; typedef VectorWriteImpl VectorWrite; //---------------------------------------------------------------------------- //! WriteV operation (@see FileOperation) //---------------------------------------------------------------------------- template class WriteVImpl: public FileOperation, Arg, Arg, Arg> { public: //------------------------------------------------------------------------ //! Inherit constructors from FileOperation (@see FileOperation) //------------------------------------------------------------------------ using FileOperation, Arg, Arg, Arg>::FileOperation; //------------------------------------------------------------------------ //! Argument indexes in the args tuple //------------------------------------------------------------------------ enum { OffsetArg, IovArg, IovcntArg }; //------------------------------------------------------------------------ //! @return : name of the operation (@see Operation) //------------------------------------------------------------------------ std::string ToString() { return "WriteV"; } protected: //------------------------------------------------------------------------ //! RunImpl operation (@see Operation) //! //! @param params : container with parameters forwarded from //! previous operation //! @return : status of the operation //------------------------------------------------------------------------ XRootDStatus RunImpl() { try { uint64_t offset = std::get( this->args ).Get(); const struct iovec *iov = std::get( this->args ).Get(); int iovcnt = std::get( this->args ).Get(); return this->file->WriteV( offset, iov, iovcnt, this->handler.get() ); } catch( const PipelineException& ex ) { return ex.GetError(); } catch( const std::exception& ex ) { return XRootDStatus( stError, ex.what() ); } } }; typedef WriteVImpl WriteV; //---------------------------------------------------------------------------- //! Fcntl operation (@see FileOperation) //---------------------------------------------------------------------------- template class FcntlImpl: public FileOperation, Arg> { public: //------------------------------------------------------------------------ //! Inherit constructors from FileOperation (@see FileOperation) //------------------------------------------------------------------------ using FileOperation, Arg>::FileOperation; //------------------------------------------------------------------------ //! Argument indexes in the args tuple //------------------------------------------------------------------------ enum { BufferArg }; //------------------------------------------------------------------------ //! @return : name of the operation (@see Operation) //------------------------------------------------------------------------ std::string ToString() { return "Fcntl"; } protected: //------------------------------------------------------------------------ //! RunImpl operation (@see Operation) //! //! @param params : container with parameters forwarded from //! previous operation //! @return : status of the operation //------------------------------------------------------------------------ XRootDStatus RunImpl() { try { Buffer arg( std::get( this->args ).Get() ); return this->file->Fcntl( arg, this->handler.get() ); } catch( const PipelineException& ex ) { return ex.GetError(); } catch( const std::exception& ex ) { return XRootDStatus( stError, ex.what() ); } } }; typedef FcntlImpl Fcntl; //---------------------------------------------------------------------------- //! Visa operation (@see FileOperation) //---------------------------------------------------------------------------- template class VisaImpl: public FileOperation> { public: //------------------------------------------------------------------------ //! Inherit constructors from FileOperation (@see FileOperation) //------------------------------------------------------------------------ using FileOperation>::FileOperation; //------------------------------------------------------------------------ //! @return : name of the operation (@see Operation) //------------------------------------------------------------------------ std::string ToString() { return "Visa"; } protected: //------------------------------------------------------------------------ //! RunImpl operation (@see Operation) //! //! @param params : container with parameters forwarded from //! previous operation //! @return : status of the operation //------------------------------------------------------------------------ XRootDStatus RunImpl() { return this->file->Visa( this->handler.get() ); } }; typedef VisaImpl Visa; } #endif // __XRD_CL_FILE_OPERATIONS_HH__