diff --git a/src/XrdCl/XrdClChannel.cc b/src/XrdCl/XrdClChannel.cc index 0433cfcf929..5fb11536358 100644 --- a/src/XrdCl/XrdClChannel.cc +++ b/src/XrdCl/XrdClChannel.cc @@ -35,6 +35,7 @@ #include "XrdSys/XrdSysPthread.hh" #include +#include namespace { @@ -245,7 +246,9 @@ namespace XrdCl int timeoutResolution = DefaultTimeoutResolution; env->GetInt( "TimeoutResolution", timeoutResolution ); - pTransport->InitializeChannel( pChannelData ); + XRootDTransport *xrdTransport = dynamic_cast( pTransport ); + if( !xrdTransport ) throw std::logic_error( "Expected XRootD transport!" ); + xrdTransport->InitializeChannel( url, pChannelData ); uint16_t numStreams = transport->StreamNumber( pChannelData ); log->Debug( PostMasterMsg, "Creating new channel to: %s %d stream(s)", url.GetHostId().c_str(), numStreams ); diff --git a/src/XrdCl/XrdClMessageUtils.cc b/src/XrdCl/XrdClMessageUtils.cc index de2a3481a42..8cfbcc3b6fd 100644 --- a/src/XrdCl/XrdClMessageUtils.cc +++ b/src/XrdCl/XrdClMessageUtils.cc @@ -57,23 +57,12 @@ namespace XrdCl log->Dump( XRootDMsg, "[%s] Sending message %s", url.GetHostId().c_str(), msg->GetDescription().c_str() ); - - AnyObject sidMgrObj; - SIDManager *sidMgr = 0; - st = postMaster->QueryTransport( url, XRootDQuery::SIDManager, - sidMgrObj ); - - if( !st.IsOK() ) - { - log->Error( XRootDMsg, "[%s] Unable to get stream id manager", - url.GetHostId().c_str() ); - return st; - } - sidMgrObj.Get( sidMgr ); - + //-------------------------------------------------------------------------- + // Get an instance of SID manager object + //-------------------------------------------------------------------------- + std::shared_ptr sidMgr( SIDMgrPool::Instance().GetSIDMgr( url ) ); ClientRequestHdr *req = (ClientRequestHdr*)msg->GetBuffer(); - //-------------------------------------------------------------------------- // Allocate the SID and marshall the message //-------------------------------------------------------------------------- diff --git a/src/XrdCl/XrdClSIDManager.cc b/src/XrdCl/XrdClSIDManager.cc index dd6903d3344..148415a8680 100644 --- a/src/XrdCl/XrdClSIDManager.cc +++ b/src/XrdCl/XrdClSIDManager.cc @@ -119,4 +119,65 @@ namespace XrdCl XrdSysMutexHelper scopedLock( pMutex ); return pSIDCeiling - pFreeSIDs.size() - pTimeOutSIDs.size() - 1; } + + //---------------------------------------------------------------------------- + // Returns a pointer to the SIDManager object + //---------------------------------------------------------------------------- + std::shared_ptr SIDMgrPool::GetSIDMgr( const URL &url ) + { + //-------------------------------------------------------------------------- + // Look for an instance of SID manager in the pool + //-------------------------------------------------------------------------- + XrdSysMutexHelper lck1( mtx ); + SIDManager *mgr = 0; + auto itr = pool.find( url.GetHostId() ); + if( itr == pool.end() ) + { + mgr = new SIDManager(); + pool[url.GetHostId()] = mgr; + } + else mgr = itr->second; + + //-------------------------------------------------------------------------- + // Update the reference counter + //-------------------------------------------------------------------------- + XrdSysMutexHelper lck2( mgr->pMutex ); + ++mgr->pRefCount; + + //-------------------------------------------------------------------------- + // Create a shared pointer that will recycle the SID manager + //-------------------------------------------------------------------------- + RecycleSidMgr deleter; + std::shared_ptr ptr( mgr, deleter ); + + return std::move( ptr ); + } + + void SIDMgrPool::Recycle( SIDManager *mgr ) + { + //-------------------------------------------------------------------------- + // Lock the pool, we need to do it in the same order as in 'GetSIDMgr' + //-------------------------------------------------------------------------- + XrdSysMutexHelper lck1( mtx ); + + //-------------------------------------------------------------------------- + // Lock the SID manager object + //-------------------------------------------------------------------------- + XrdSysMutexHelper lck2( mgr->pMutex ); + --mgr->pRefCount; + + if( !mgr->pRefCount ) + { + //------------------------------------------------------------------------ + // Remove the SID manager from the pool + //------------------------------------------------------------------------ + auto itr = pool.begin(); + for( ; itr != pool.end() ; ++itr ) + if( itr->second == mgr ) break; + pool.erase( itr ); + + lck2.UnLock(); + delete mgr; + } + } } diff --git a/src/XrdCl/XrdClSIDManager.hh b/src/XrdCl/XrdClSIDManager.hh index 59239345adf..6acd2e553ae 100644 --- a/src/XrdCl/XrdClSIDManager.hh +++ b/src/XrdCl/XrdClSIDManager.hh @@ -21,23 +21,41 @@ #include #include +#include +#include +#include #include #include "XrdSys/XrdSysPthread.hh" #include "XrdCl/XrdClStatus.hh" +#include "XrdCl/XrdClURL.hh" namespace XrdCl { + //---------------------------------------------------------------------------- + // We need the forward declaration for the friendship to work properly + //---------------------------------------------------------------------------- + class SIDMgrPool; + //---------------------------------------------------------------------------- //! Handle XRootD stream IDs //---------------------------------------------------------------------------- class SIDManager { - public: + friend class SIDMgrPool; + + private: //------------------------------------------------------------------------ //! Constructor //------------------------------------------------------------------------ - SIDManager(): pSIDCeiling(1) {} + SIDManager(): pSIDCeiling(1), pRefCount(0) { } + + //------------------------------------------------------------------------ + //! Destructor + //------------------------------------------------------------------------ + ~SIDManager() { } + + public: //------------------------------------------------------------------------ //! Allocate a SID @@ -91,6 +109,78 @@ namespace XrdCl std::set pTimeOutSIDs; uint16_t pSIDCeiling; mutable XrdSysMutex pMutex; + mutable size_t pRefCount; + }; + + //---------------------------------------------------------------------------- + //! Pool of SID manager objects + //---------------------------------------------------------------------------- + class SIDMgrPool + { + public: + + //------------------------------------------------------------------------ + //! @return : instance of SIDMgrPool + //------------------------------------------------------------------------ + static SIDMgrPool& Instance() + { + //---------------------------------------------------------------------- + // We could also use a nifty counter but this is simpler and will do! + //---------------------------------------------------------------------- + static SIDMgrPool *instance = new SIDMgrPool(); + return *instance; + } + + //------------------------------------------------------------------------ + //! Destructor + //------------------------------------------------------------------------ + ~SIDMgrPool() { } + + //------------------------------------------------------------------------ + //! @param url : URL for which we need a SIDManager + //! @return : a shared pointer to SIDManager object, the pointer has + // a custom deleter that will return the object to the pool + //------------------------------------------------------------------------ + std::shared_ptr GetSIDMgr( const URL &url ); + + //------------------------------------------------------------------------ + //! @param mgr : the SIDManager object to be recycled + //------------------------------------------------------------------------ + void Recycle( SIDManager *mgr ); + + private: + + //------------------------------------------------------------------------ + //! A functional object for handling the deletion of SIDManager objects + //------------------------------------------------------------------------ + struct RecycleSidMgr + { + inline void operator()( SIDManager *mgr ) + { + SIDMgrPool &pool = SIDMgrPool::Instance(); + pool.Recycle( mgr ); + } + }; + + //------------------------------------------------------------------------ + //! Constructor + //------------------------------------------------------------------------ + SIDMgrPool() { } + + //------------------------------------------------------------------------ + //! Deleted constructors + //------------------------------------------------------------------------ + SIDMgrPool( const SIDMgrPool& ) = delete; + SIDMgrPool( SIDMgrPool&& ) = delete; + + //------------------------------------------------------------------------ + //! Deleted assigment operators + //------------------------------------------------------------------------ + SIDMgrPool& operator=( const SIDMgrPool& ) = delete; + SIDMgrPool& operator=( SIDMgrPool&& ) = delete; + + XrdSysMutex mtx; + std::unordered_map pool; }; } diff --git a/src/XrdCl/XrdClXRootDMsgHandler.cc b/src/XrdCl/XrdClXRootDMsgHandler.cc index 57e9880c296..e1314c1da58 100644 --- a/src/XrdCl/XrdClXRootDMsgHandler.cc +++ b/src/XrdCl/XrdClXRootDMsgHandler.cc @@ -2076,20 +2076,8 @@ namespace XrdCl // file and in this case there is no SID) if( !url.IsLocalFile() ) { - AnyObject sidMgrObj; - Status st = pPostMaster->QueryTransport( url, XRootDQuery::SIDManager, - sidMgrObj ); - if( !st.IsOK() ) - { - log->Error( XRootDMsg, "[%s] Impossible to send message %s.", - pUrl.GetHostId().c_str(), - pRequest->GetDescription().c_str() ); - return st; - } - sidMgrObj.Get( pSidMgr ); - - // and finally allocate new stream id - st = pSidMgr->AllocateSID( req->streamid ); + pSidMgr = SIDMgrPool::Instance().GetSIDMgr( url ); + Status st = pSidMgr->AllocateSID( req->streamid ); if( !st.IsOK() ) { log->Error( XRootDMsg, "[%s] Impossible to send message %s.", diff --git a/src/XrdCl/XrdClXRootDMsgHandler.hh b/src/XrdCl/XrdClXRootDMsgHandler.hh index bc78680c75b..fb5bed4cea9 100644 --- a/src/XrdCl/XrdClXRootDMsgHandler.hh +++ b/src/XrdCl/XrdClXRootDMsgHandler.hh @@ -119,11 +119,11 @@ namespace XrdCl //! @param sidMgr the sid manager used to allocate SID for the initial //! message //------------------------------------------------------------------------ - XRootDMsgHandler( Message *msg, - ResponseHandler *respHandler, - const URL *url, - SIDManager *sidMgr, - LocalFileHandler *lFileHandler): + XRootDMsgHandler( Message *msg, + ResponseHandler *respHandler, + const URL *url, + std::shared_ptr sidMgr, + LocalFileHandler *lFileHandler): pRequest( msg ), pResponse( 0 ), pResponseHandler( respHandler ), @@ -205,7 +205,6 @@ namespace XrdCl pResponse = reinterpret_cast( 0xDEADBEEF ); pResponseHandler = reinterpret_cast( 0xDEADBEEF ); pPostMaster = reinterpret_cast( 0xDEADBEEF ); - pSidMgr = reinterpret_cast( 0xDEADBEEF ); pLFileHandler = reinterpret_cast( 0xDEADBEEF ); pHosts = reinterpret_cast( 0xDEADBEEF ); pChunkList = reinterpret_cast( 0xDEADBEEF ); @@ -544,7 +543,7 @@ namespace XrdCl URL pUrl; URL *pEffectiveDataServerUrl; PostMaster *pPostMaster; - SIDManager *pSidMgr; + std::shared_ptr pSidMgr; LocalFileHandler *pLFileHandler; Status pStatus; Status pLastError; diff --git a/src/XrdCl/XrdClXRootDTransport.cc b/src/XrdCl/XrdClXRootDTransport.cc index 35bcc333627..3c212dbe328 100644 --- a/src/XrdCl/XrdClXRootDTransport.cc +++ b/src/XrdCl/XrdClXRootDTransport.cc @@ -51,6 +51,7 @@ #include #include #include +#include #if __cplusplus >= 201103L #include @@ -192,11 +193,10 @@ namespace XrdCl //-------------------------------------------------------------------------- // Constructor //-------------------------------------------------------------------------- - XRootDChannelInfo(): + XRootDChannelInfo( const URL &url ): serverFlags(0), protocolVersion(0), firstLogIn(true), - sidManager(0), authBuffer(0), authProtocol(0), authParams(0), @@ -208,7 +208,7 @@ namespace XrdCl protRespSize(0), strmSelector(0) { - sidManager = new SIDManager(); + sidManager = SIDMgrPool::Instance().GetSIDMgr( url.GetHostId() ); memset( sessionId, 0, 16 ); memset( oldSessionId, 0, 16 ); } @@ -218,7 +218,6 @@ namespace XrdCl //-------------------------------------------------------------------------- ~XRootDChannelInfo() { - delete sidManager; delete [] authBuffer; delete strmSelector; } @@ -233,7 +232,7 @@ namespace XrdCl uint8_t sessionId[16]; uint8_t oldSessionId[16]; bool firstLogIn; - SIDManager *sidManager; + std::shared_ptr sidManager; char *authBuffer; XrdSecProtocol *authProtocol; XrdSecParameters *authParams; @@ -350,7 +349,12 @@ namespace XrdCl //---------------------------------------------------------------------------- void XRootDTransport::InitializeChannel( AnyObject &channelData ) { - XRootDChannelInfo *info = new XRootDChannelInfo(); + throw std::logic_error( "InitializeChannel: deprecated interface!" ); + } + + void XRootDTransport::InitializeChannel( const URL &url, AnyObject &channelData ) + { + XRootDChannelInfo *info = new XRootDChannelInfo( url ); XrdSysMutexHelper scopedLock( info->mutex ); channelData.Set( info ); @@ -1184,13 +1188,6 @@ namespace XrdCl result.Set( new std::string( info->authProtocolName ), false ); return Status(); - //------------------------------------------------------------------------ - // SID Manager object - //------------------------------------------------------------------------ - case XRootDQuery::SIDManager: - result.Set( info->sidManager, false ); - return Status(); - //------------------------------------------------------------------------ // Server flags //------------------------------------------------------------------------ diff --git a/src/XrdCl/XrdClXRootDTransport.hh b/src/XrdCl/XrdClXRootDTransport.hh index 50e7a8f830f..4382b75dbcd 100644 --- a/src/XrdCl/XrdClXRootDTransport.hh +++ b/src/XrdCl/XrdClXRootDTransport.hh @@ -43,7 +43,6 @@ namespace XrdCl //---------------------------------------------------------------------------- struct XRootDQuery { - static const uint16_t SIDManager = 1001; //!< returns the SIDManager object static const uint16_t ServerFlags = 1002; //!< returns server flags static const uint16_t ProtocolVersion = 1003; //!< returns the protocol version }; @@ -93,7 +92,8 @@ namespace XrdCl //------------------------------------------------------------------------ //! Initialize channel //------------------------------------------------------------------------ - virtual void InitializeChannel( AnyObject &channelData ); + virtual void InitializeChannel( AnyObject &channelData ); //< we keep this as we need to implement the abstract method + virtual void InitializeChannel( const URL &url, AnyObject &channelData ); //------------------------------------------------------------------------ //! Finalize channel