XRootD
XrdClSIDManager.cc
Go to the documentation of this file.
1 //------------------------------------------------------------------------------
2 // Copyright (c) 2011-2012 by European Organization for Nuclear Research (CERN)
3 // Author: Lukasz Janyst <ljanyst@cern.ch>
4 //------------------------------------------------------------------------------
5 // XRootD is free software: you can redistribute it and/or modify
6 // it under the terms of the GNU Lesser General Public License as published by
7 // the Free Software Foundation, either version 3 of the License, or
8 // (at your option) any later version.
9 //
10 // XRootD is distributed in the hope that it will be useful,
11 // but WITHOUT ANY WARRANTY; without even the implied warranty of
12 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 // GNU General Public License for more details.
14 //
15 // You should have received a copy of the GNU Lesser General Public License
16 // along with XRootD. If not, see <http://www.gnu.org/licenses/>.
17 //------------------------------------------------------------------------------
18 
19 #include "XrdCl/XrdClSIDManager.hh"
20 
21 #include <algorithm>
22 
23 namespace XrdCl
24 {
26  {
27  //----------------------------------------------------------------------
28  // We could also use a nifty counter but this is simpler and will do!
29  //----------------------------------------------------------------------
30  static SIDMgrPool *instance = new SIDMgrPool();
31  return *instance;
32  }
33  //----------------------------------------------------------------------------
34  // Allocate a SID
35  //---------------------------------------------------------------------------
36  Status SIDManager::AllocateSID( uint8_t sid[2] )
37  {
38  XrdSysMutexHelper scopedLock( pMutex );
39 
40  uint16_t allocSID = 1;
41 
42  //--------------------------------------------------------------------------
43  // Get a SID from the list of free SIDs if it's not empty
44  //--------------------------------------------------------------------------
45  if( !pFreeSIDs.empty() )
46  {
47  allocSID = pFreeSIDs.front();
48  pFreeSIDs.pop_front();
49  }
50  //--------------------------------------------------------------------------
51  // Allocate a new SID if possible
52  //--------------------------------------------------------------------------
53  else
54  {
55  if( pSIDCeiling == 0xffff )
56  return Status( stError, errNoMoreFreeSIDs );
57  allocSID = pSIDCeiling++;
58  }
59 
60  memcpy( sid, &allocSID, 2 );
61  pAllocTime[allocSID] = time(0);
62  return Status();
63  }
64 
65  //----------------------------------------------------------------------------
66  // Release the SID that is no longer needed
67  //----------------------------------------------------------------------------
68  void SIDManager::ReleaseSID( uint8_t sid[2] )
69  {
70  XrdSysMutexHelper scopedLock( pMutex );
71  uint16_t relSID = 0;
72  memcpy( &relSID, sid, 2 );
73  pFreeSIDs.push_back( relSID );
74  pAllocTime.erase( relSID );
75  }
76 
77  //----------------------------------------------------------------------------
78  // Register a SID of a request that timed out
79  //----------------------------------------------------------------------------
80  void SIDManager::TimeOutSID( uint8_t sid[2] )
81  {
82  XrdSysMutexHelper scopedLock( pMutex );
83  uint16_t tiSID = 0;
84  memcpy( &tiSID, sid, 2 );
85  pTimeOutSIDs.insert( tiSID );
86  pAllocTime.erase( tiSID );
87  }
88 
89  //----------------------------------------------------------------------------
90  // Check if any SID was allocated at or before a given time
91  //----------------------------------------------------------------------------
92  bool SIDManager::IsAnySIDOldAs( const time_t tlim ) const
93  {
94  XrdSysMutexHelper scopedLock( pMutex );
95  return std::any_of( pAllocTime.begin(), pAllocTime.end(),
96  [tlim](const auto& p)
97  {
98  return p.second <= tlim;
99  } );
100  }
101 
102  //----------------------------------------------------------------------------
103  // Check if a SID is timed out
104  //----------------------------------------------------------------------------
105  bool SIDManager::IsTimedOut( uint8_t sid[2] )
106  {
107  XrdSysMutexHelper scopedLock( pMutex );
108  uint16_t tiSID = 0;
109  memcpy( &tiSID, sid, 2 );
110  std::set<uint16_t>::iterator it = pTimeOutSIDs.find( tiSID );
111  if( it != pTimeOutSIDs.end() )
112  return true;
113  return false;
114  }
115 
116  //----------------------------------------------------------------------------
117  // Release a timed out SID
118  //-----------------------------------------------------------------------------
119  void SIDManager::ReleaseTimedOut( uint8_t sid[2] )
120  {
121  XrdSysMutexHelper scopedLock( pMutex );
122  uint16_t tiSID = 0;
123  memcpy( &tiSID, sid, 2 );
124  pTimeOutSIDs.erase( tiSID );
125  pFreeSIDs.push_back( tiSID );
126  }
127 
128  //------------------------------------------------------------------------
129  // Release all timed out SIDs
130  //------------------------------------------------------------------------
132  {
133  XrdSysMutexHelper scopedLock( pMutex );
134  std::set<uint16_t>::iterator it;
135  for( it = pTimeOutSIDs.begin(); it != pTimeOutSIDs.end(); ++it )
136  pFreeSIDs.push_back( *it );
137  pTimeOutSIDs.clear();
138  }
139 
140  //----------------------------------------------------------------------------
141  // Get number of allocated SIDs
142  //----------------------------------------------------------------------------
144  {
145  XrdSysMutexHelper scopedLock( pMutex );
146  return pSIDCeiling - pFreeSIDs.size() - pTimeOutSIDs.size() - 1;
147  }
148 
149  //----------------------------------------------------------------------------
150  // Returns a pointer to the SIDManager object
151  //----------------------------------------------------------------------------
152  std::shared_ptr<SIDManager> SIDMgrPool::GetSIDMgr( const URL &url )
153  {
154  //--------------------------------------------------------------------------
155  // Look for an instance of SID manager in the pool
156  //--------------------------------------------------------------------------
157  XrdSysMutexHelper lck1( mtx );
158  SIDManager *mgr = 0;
159  auto itr = pool.find( url.GetChannelId() );
160  if( itr == pool.end() )
161  {
162  mgr = new SIDManager();
163  pool[url.GetChannelId()] = mgr;
164  }
165  else mgr = itr->second;
166 
167  //--------------------------------------------------------------------------
168  // Update the reference counter
169  //--------------------------------------------------------------------------
170  XrdSysMutexHelper lck2( mgr->pMutex );
171  ++mgr->pRefCount;
172 
173  //--------------------------------------------------------------------------
174  // Create a shared pointer that will recycle the SID manager
175  //--------------------------------------------------------------------------
176  RecycleSidMgr deleter;
177  std::shared_ptr<SIDManager> ptr( mgr, deleter );
178 
179  return ptr;
180  }
181 
183  {
184  //--------------------------------------------------------------------------
185  // Lock the pool, we need to do it in the same order as in 'GetSIDMgr'
186  //--------------------------------------------------------------------------
187  XrdSysMutexHelper lck1( mtx );
188 
189  //--------------------------------------------------------------------------
190  // Lock the SID manager object
191  //--------------------------------------------------------------------------
192  XrdSysMutexHelper lck2( mgr->pMutex );
193  --mgr->pRefCount;
194 
195  if( !mgr->pRefCount )
196  {
197  //------------------------------------------------------------------------
198  // Remove the SID manager from the pool
199  //------------------------------------------------------------------------
200  auto itr = pool.begin();
201  for( ; itr != pool.end() ; ++itr )
202  if( itr->second == mgr )
203  {
204  pool.erase( itr );
205  break;
206  }
207 
208  lck2.UnLock();
209  delete mgr;
210  }
211  }
212 }
Handle XRootD stream IDs.
void ReleaseTimedOut(uint8_t sid[2])
Release a timed out SID.
uint16_t GetNumberOfAllocatedSIDs() const
Number of allocated streams.
void TimeOutSID(uint8_t sid[2])
Register a SID of a request that timed out.
bool IsAnySIDOldAs(const time_t tlim) const
Check if any SID was allocated at or before a given time.
bool IsTimedOut(uint8_t sid[2])
Check if a SID is timed out.
Status AllocateSID(uint8_t sid[2])
void ReleaseAllTimedOut()
Release all timed out SIDs.
void ReleaseSID(uint8_t sid[2])
Release the SID that is no longer needed.
Pool of SID manager objects.
static SIDMgrPool & Instance()
void Recycle(SIDManager *mgr)
std::shared_ptr< SIDManager > GetSIDMgr(const URL &url)
URL representation.
Definition: XrdClURL.hh:31
std::string GetChannelId() const
Definition: XrdClURL.cc:512
const uint16_t stError
An error occurred that could potentially be retried.
Definition: XrdClStatus.hh:32
const uint16_t errNoMoreFreeSIDs
Definition: XrdClStatus.hh:97
Procedure execution status.
Definition: XrdClStatus.hh:115