//------------------------------------------------------------------------------ // Copyright (c) 2011-2014 by European Organization for Nuclear Research (CERN) // Author: Lukasz Janyst //------------------------------------------------------------------------------ // 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_STATE_HANDLER_HH__ #define __XRD_CL_FILE_STATE_HANDLER_HH__ #include "XrdCl/XrdClXRootDResponses.hh" #include "XrdCl/XrdClPostMasterInterfaces.hh" #include "XrdCl/XrdClFileSystem.hh" #include "XrdCl/XrdClMessageUtils.hh" #include "XrdSys/XrdSysPthread.hh" #include "XrdCl/XrdClLocalFileHandler.hh" #include #include #include namespace XrdCl { class ResponseHandlerHolder; class Message; //---------------------------------------------------------------------------- //! Handle the stateful operations //---------------------------------------------------------------------------- class FileStateHandler { public: //------------------------------------------------------------------------ //! State of the file //------------------------------------------------------------------------ enum FileStatus { Closed, //!< The file is closed Opened, //!< Opening has succeeded Error, //!< Opening has failed Recovering, //!< Recovering from an error OpenInProgress, //!< Opening is in progress CloseInProgress //!< Closing operation is in progress }; //------------------------------------------------------------------------ //! Constructor //------------------------------------------------------------------------ FileStateHandler(); //------------------------------------------------------------------------ //! Constructor //! //! @param useVirtRedirector if true Metalink files will be treated //! as a VirtualRedirectors //------------------------------------------------------------------------ FileStateHandler( bool useVirtRedirector ); //------------------------------------------------------------------------ //! Destructor //------------------------------------------------------------------------ ~FileStateHandler(); //------------------------------------------------------------------------ //! Open the file pointed to by the given URL //! //! @param url url of the file to be opened //! @param flags OpenFlags::Flags //! @param mode Access::Mode for new files, 0 otherwise //! @param handler handler to be notified about the status of the operation //! @param timeout timeout value, if 0 the environment default will be //! used //! @return status of the operation //------------------------------------------------------------------------ XRootDStatus Open( const std::string &url, uint16_t flags, uint16_t mode, ResponseHandler *handler, uint16_t timeout = 0 ); //------------------------------------------------------------------------ //! Close the file object //! //! @param handler handler to be notified about the status of the operation //! @param timeout timeout value, if 0 the environment default will be //! used //! @return status of the operation //------------------------------------------------------------------------ XRootDStatus Close( ResponseHandler *handler, uint16_t timeout = 0 ); //------------------------------------------------------------------------ //! Obtain status information for this file - async //! //! @param force do not use the cached information, force re-stating //! @param handler handler to be notified when the response arrives, //! the response parameter will hold a StatInfo object //! if the procedure is successful //! @param timeout timeout value, if 0 the environment default will //! be used //! @return status of the operation //------------------------------------------------------------------------ XRootDStatus Stat( bool force, ResponseHandler *handler, uint16_t timeout = 0 ); //------------------------------------------------------------------------ //! Read a data chunk at a given offset - sync //! //! @param offset offset from the beginning of the file //! @param size number of bytes to be read //! @param buffer a pointer to a buffer big enough to hold the data //! or 0 if the buffer should be allocated by the system //! @param handler handler to be notified when the response arrives, //! the response parameter will hold a buffer object if //! the procedure was successful, if a preallocated //! buffer was specified then the buffer object will //! "wrap" this buffer //! @param timeout timeout value, if 0 the environment default will be //! used //! @return status of the operation //------------------------------------------------------------------------ XRootDStatus Read( uint64_t offset, uint32_t size, void *buffer, ResponseHandler *handler, uint16_t timeout = 0 ); //------------------------------------------------------------------------ //! Write a data chunk at a given offset - async //! //! @param offset offset from the beginning of the file //! @param size number of bytes to be written //! @param buffer a pointer to the buffer holding the data to be written //! @param handler handler to be notified when the response arrives //! @param timeout timeout value, if 0 the environment default will be //! used //! @return status of the operation //------------------------------------------------------------------------ XRootDStatus Write( uint64_t offset, uint32_t size, const void *buffer, ResponseHandler *handler, uint16_t timeout = 0 ); //------------------------------------------------------------------------ //! Commit all pending disk writes - async //! //! @param handler handler to be notified when the response arrives //! @param timeout timeout value, if 0 the environment default will be //! used //! @return status of the operation //------------------------------------------------------------------------ XRootDStatus Sync( ResponseHandler *handler, uint16_t timeout = 0 ); //------------------------------------------------------------------------ //! Truncate the file to a particular size - async //! //! @param size desired size of the file //! @param handler handler to be notified when the response arrives //! @param timeout timeout value, if 0 the environment default will be //! used //! @return status of the operation //------------------------------------------------------------------------ XRootDStatus Truncate( uint64_t size, ResponseHandler *handler, uint16_t timeout = 0 ); //------------------------------------------------------------------------ //! Read scattered data chunks in one operation - async //! //! @param chunks list of the chunks to be read //! @param buffer a pointer to a buffer big enough to hold the data //! @param handler handler to be notified when the response arrives //! @param timeout timeout value, if 0 then the environment default //! will be used //! @return status of the operation //------------------------------------------------------------------------ XRootDStatus VectorRead( const ChunkList &chunks, void *buffer, ResponseHandler *handler, uint16_t timeout = 0 ); //------------------------------------------------------------------------ //! Write scattered data chunks in one operation - async //! //! @param chunks list of the chunks to be read //! @param handler handler to be notified when the response arrives //! @param timeout timeout value, if 0 then the environment default //! will be used //! @return status of the operation //------------------------------------------------------------------------ XRootDStatus VectorWrite( const ChunkList &chunks, ResponseHandler *handler, uint16_t timeout = 0 ); //------------------------------------------------------------------------ //! Write scattered buffers in one operation - async //! //! @param offset offset from the beginning of the file //! @param iov list of the buffers to be written //! @param iovcnt number of buffers //! @param handler handler to be notified when the response arrives //! @param timeout timeout value, if 0 then the environment default //! will be used //! @return status of the operation //------------------------------------------------------------------------ XRootDStatus WriteV( uint64_t offset, const struct iovec *iov, int iovcnt, ResponseHandler *handler, uint16_t timeout = 0 ); //------------------------------------------------------------------------ //! Performs a custom operation on an open file, server implementation //! dependent - async //! //! @param arg query argument //! @param handler handler to be notified when the response arrives, //! the response parameter will hold a Buffer object //! if the procedure is successful //! @param timeout timeout value, if 0 the environment default will //! be used //! @return status of the operation //------------------------------------------------------------------------ XRootDStatus Fcntl( const Buffer &arg, ResponseHandler *handler, uint16_t timeout = 0 ); //------------------------------------------------------------------------ //! Get access token to a file - async //! //! @param handler handler to be notified when the response arrives, //! the response parameter will hold a Buffer object //! if the procedure is successful //! @param timeout timeout value, if 0 the environment default will //! be used //! @return status of the operation //------------------------------------------------------------------------ XRootDStatus Visa( ResponseHandler *handler, uint16_t timeout = 0 ); //------------------------------------------------------------------------ //! Process the results of the opening operation //------------------------------------------------------------------------ void OnOpen( const XRootDStatus *status, const OpenInfo *openInfo, const HostList *hostList ); //------------------------------------------------------------------------ //! Process the results of the closing operation //------------------------------------------------------------------------ void OnClose( const XRootDStatus *status ); //------------------------------------------------------------------------ //! Handle an error while sending a stateful message //------------------------------------------------------------------------ void OnStateError( XRootDStatus *status, Message *message, ResponseHandler *userHandler, MessageSendParams &sendParams ); //------------------------------------------------------------------------ //! Handle stateful redirect //------------------------------------------------------------------------ void OnStateRedirection( const std::string &redirectUrl, Message *message, ResponseHandler *userHandler, MessageSendParams &sendParams ); //------------------------------------------------------------------------ //! Handle stateful response //------------------------------------------------------------------------ void OnStateResponse( XRootDStatus *status, Message *message, AnyObject *response, HostList *hostList ); //------------------------------------------------------------------------ //! Check if the file is open //------------------------------------------------------------------------ bool IsOpen() const; //------------------------------------------------------------------------ //! Set file property //! //! @see File::GetProperty for propert list //------------------------------------------------------------------------ bool SetProperty( const std::string &name, const std::string &value ); //------------------------------------------------------------------------ //! Get file property //! //! @see File::SetProperty for property list //------------------------------------------------------------------------ bool GetProperty( const std::string &name, std::string &value ) const; //------------------------------------------------------------------------ //! Lock the internal lock //------------------------------------------------------------------------ void Lock() { pMutex.Lock(); } //------------------------------------------------------------------------ //! Unlock the internal lock //------------------------------------------------------------------------ void UnLock() { pMutex.UnLock(); } //------------------------------------------------------------------------ //! Tick //------------------------------------------------------------------------ void Tick( time_t now ); //------------------------------------------------------------------------ //! Declare timeout on requests being recovered //------------------------------------------------------------------------ void TimeOutRequests( time_t now ); //------------------------------------------------------------------------ //! Called in the child process after the fork //------------------------------------------------------------------------ void AfterForkChild(); private: //------------------------------------------------------------------------ // Helper for queuing messages //------------------------------------------------------------------------ struct RequestData { RequestData(): request(0), handler(0) {} RequestData( Message *r, ResponseHandler *h, const MessageSendParams &p ): request(r), handler(h), params(p) {} Message *request; ResponseHandler *handler; MessageSendParams params; }; typedef std::list RequestList; //------------------------------------------------------------------------ //! Send a message to a host or put it in the recovery queue //------------------------------------------------------------------------ Status SendOrQueue( const URL &url, Message *msg, ResponseHandler *handler, MessageSendParams &sendParams ); //------------------------------------------------------------------------ //! Check if the stateful error is recoverable //------------------------------------------------------------------------ bool IsRecoverable( const XRootDStatus &stataus ) const; //------------------------------------------------------------------------ //! Recover a message //! //! @param rd request data associated with the message //! @param callbackOnFailure should the current handler be called back //! if the recovery procedure fails //------------------------------------------------------------------------ Status RecoverMessage( RequestData rd, bool callbackOnFailure = true ); //------------------------------------------------------------------------ //! Run the recovery procedure if appropriate //------------------------------------------------------------------------ Status RunRecovery(); //------------------------------------------------------------------------ // Send a close and ignore the response //------------------------------------------------------------------------ Status SendClose( uint16_t timeout ); //------------------------------------------------------------------------ //! Check if the file is open for read only //------------------------------------------------------------------------ bool IsReadOnly() const; //------------------------------------------------------------------------ //! Re-open the current file at a given server //------------------------------------------------------------------------ Status ReOpenFileAtServer( const URL &url, uint16_t timeout ); //------------------------------------------------------------------------ //! Fail a message //------------------------------------------------------------------------ void FailMessage( RequestData rd, XRootDStatus status ); //------------------------------------------------------------------------ //! Fail queued messages //------------------------------------------------------------------------ void FailQueuedMessages( XRootDStatus status ); //------------------------------------------------------------------------ //! Re-send queued messages //------------------------------------------------------------------------ void ReSendQueuedMessages(); //------------------------------------------------------------------------ //! Re-write file handle //------------------------------------------------------------------------ void ReWriteFileHandle( Message *msg ); //------------------------------------------------------------------------ //! Reset monitoring vars //------------------------------------------------------------------------ void ResetMonitoringVars() { pOpenTime.tv_sec = 0; pOpenTime.tv_usec = 0; pRBytes = 0; pVRBytes = 0; pWBytes = 0; pVSegs = 0; pRCount = 0; pVRCount = 0; pWCount = 0; pCloseReason = Status(); } //------------------------------------------------------------------------ //! Dispatch monitoring information on close //------------------------------------------------------------------------ void MonitorClose( const XRootDStatus *status ); //------------------------------------------------------------------------ //! Issues request: //! - if the request is for a Metalink a redirect is generated //! - if the request is for a local file, it will be passed to //! LocalFileHandler //! - otherwise vanilla XRootD request will be sent //------------------------------------------------------------------------ XRootDStatus IssueRequest( const URL &url, Message *msg, ResponseHandler *handler, MessageSendParams &sendParams ); mutable XrdSysMutex pMutex; FileStatus pFileState; XRootDStatus pStatus; StatInfo *pStatInfo; URL *pFileUrl; URL *pDataServer; URL *pLoadBalancer; URL *pStateRedirect; uint8_t *pFileHandle; uint16_t pOpenMode; uint16_t pOpenFlags; RequestList pToBeRecovered; std::set pInTheFly; uint64_t pSessionId; bool pDoRecoverRead; bool pDoRecoverWrite; bool pFollowRedirects; bool pUseVirtRedirector; //------------------------------------------------------------------------ // Monitoring variables //------------------------------------------------------------------------ timeval pOpenTime; uint64_t pRBytes; uint64_t pVRBytes; uint64_t pWBytes; uint64_t pVWBytes; uint64_t pVSegs; uint64_t pRCount; uint64_t pVRCount; uint64_t pWCount; uint64_t pVWCount; XRootDStatus pCloseReason; //------------------------------------------------------------------------ // Holds the OpenHanlder used to issue reopen // (there is only only OpenHandler reopening a file at a time) //------------------------------------------------------------------------ ResponseHandlerHolder *pReOpenHandler; //------------------------------------------------------------------------ // Responsible for file:// operations on the local filesystem //------------------------------------------------------------------------ LocalFileHandler *pLFileHandler; }; } #endif // __XRD_CL_FILE_STATE_HANDLER_HH__