XRootD
XrdClPollerBuiltIn.cc
Go to the documentation of this file.
1 //------------------------------------------------------------------------------
2 // Copyright (c) 2011-2014 by European Organization for Nuclear Research (CERN)
3 // Author: Lukasz Janyst <ljanyst@cern.ch>
4 //------------------------------------------------------------------------------
5 // This file is part of the XRootD software suite.
6 //
7 // XRootD is free software: you can redistribute it and/or modify
8 // it under the terms of the GNU Lesser General Public License as published by
9 // the Free Software Foundation, either version 3 of the License, or
10 // (at your option) any later version.
11 //
12 // XRootD is distributed in the hope that it will be useful,
13 // but WITHOUT ANY WARRANTY; without even the implied warranty of
14 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 // GNU General Public License for more details.
16 //
17 // You should have received a copy of the GNU Lesser General Public License
18 // along with XRootD. If not, see <http://www.gnu.org/licenses/>.
19 //
20 // In applying this licence, CERN does not waive the privileges and immunities
21 // granted to it by virtue of its status as an Intergovernmental Organization
22 // or submit itself to any jurisdiction.
23 //------------------------------------------------------------------------------
24 
26 #include "XrdCl/XrdClLog.hh"
27 #include "XrdCl/XrdClDefaultEnv.hh"
28 #include "XrdCl/XrdClConstants.hh"
29 #include "XrdCl/XrdClSocket.hh"
30 #include "XrdCl/XrdClOptimizers.hh"
31 #include "XrdSys/XrdSysE2T.hh"
32 #include "XrdSys/XrdSysIOEvents.hh"
33 
34 namespace
35 {
36  //----------------------------------------------------------------------------
37  // A helper struct passed to the callback as a custom arg
38  //----------------------------------------------------------------------------
39  struct PollerHelper
40  {
41  PollerHelper():
42  channel(0), callBack(0), readEnabled(false), writeEnabled(false),
43  readTimeout(0), writeTimeout(0)
44  {}
47  bool readEnabled;
48  bool writeEnabled;
49  time_t readTimeout;
50  time_t writeTimeout;
51  };
52 
53  //----------------------------------------------------------------------------
54  // Call back implementation
55  //----------------------------------------------------------------------------
56  class SocketCallBack: public XrdSys::IOEvents::CallBack
57  {
58  public:
59  enum CallBackFlags
60  {
61  kRunningCallBack = 1,
62  kIdSet = 2,
63  kWantDisable = 4,
64  kDisabled = 8
65  };
66 
67  struct DisableControl
68  {
69  DisableControl() : pFlags( 0 ), pCnd( 0 ) { }
70  ~DisableControl() { }
71 
72  //------------------------------------------------------------------------
73  // Want to disable further callbacks. If callback is currently running
74  // in a different thread from our caller, wait until callback finishes.
75  //------------------------------------------------------------------------
76  void DisableCallBack()
77  {
78  const int flags = pFlags.fetch_or( kWantDisable );
79  if( !(flags & kIdSet) ) return;
80  if( !(flags & kRunningCallBack) ) return;
81  XrdSysCondVarHelper lck( pCnd );
82  if( XrdSysThread::Same( XrdSysThread::ID(), pSelfId ) ) return;
83  while( !(pFlags.load() & kDisabled) ) pCnd.Wait();
84  }
85 
86  //--------------------------------------------------------------------
87  // In case the poller is started with existing SocketCallBacks (e.g.
88  // after a fork) we are called before reestablishing callbacks. We
89  // should reset flags, e.g. kIdSet so that pSelfId of new callback
90  // thread is recorded on the first of the new callbacks.
91  //--------------------------------------------------------------------
92  void Restart()
93  {
94  pFlags.fetch_and( ~kIdSet );
95  }
96 
97  std::atomic<int> pFlags;
98  XrdSysCondVar pCnd;
99  pthread_t pSelfId;
100  };
101 
102  SocketCallBack( XrdCl::Socket *sock, XrdCl::SocketHandler *sh ):
103  pSocket( sock ), pHandler( sh )
104  {
105  pControl = std::make_shared<DisableControl>();
106  }
107 
108  virtual ~SocketCallBack() {};
109 
110  virtual bool Event( XrdSys::IOEvents::Channel *chP,
111  void *cbArg,
112  int evFlags )
113  {
114  using namespace XrdCl;
115  uint8_t ev = 0;
116 
117  if( evFlags & ReadyToRead ) ev |= SocketHandler::ReadyToRead;
118  if( evFlags & ReadTimeOut ) ev |= SocketHandler::ReadTimeOut;
119  if( evFlags & ReadyToWrite ) ev |= SocketHandler::ReadyToWrite;
120  if( evFlags & WriteTimeOut ) ev |= SocketHandler::WriteTimeOut;
121 
122  Log *log = DefaultEnv::GetLog();
123  if( unlikely(log->GetLevel() >= Log::DumpMsg) )
124  {
125  log->Dump( PollerMsg, "%s Got an event: %s",
126  pSocket->GetName().c_str(),
127  SocketHandler::EventTypeToString( ev ).c_str() );
128  }
129 
130  int flags = pControl->pFlags.fetch_or( kRunningCallBack );
131  if( !( flags & kIdSet ) )
132  {
133  XrdSysCondVarHelper lck( pControl->pCnd );
134  pControl->pSelfId = XrdSysThread::ID();
135  flags = pControl->pFlags.fetch_or( kIdSet );
136  }
137  if( flags & kWantDisable )
138  {
139  XrdSysCondVarHelper lck( pControl->pCnd );
140  pControl->pFlags &= ~kRunningCallBack;
141  pControl->pFlags |= kDisabled;
142  pControl->pCnd.Broadcast();
143  return false;
144  }
145 
146  //----------------------------------------------------------------------
147  // If the event handler calls RemoveSocket for itself this object may
148  // be destroyed during the Event call.
149  //----------------------------------------------------------------------
150  auto control = pControl;
151  pHandler->Event( ev, pSocket );
152 
153  flags = control->pFlags.fetch_and( ~kRunningCallBack );
154  if( flags & kWantDisable )
155  {
156  XrdSysCondVarHelper lck( control->pCnd );
157  control->pFlags |= kDisabled;
158  control->pCnd.Broadcast();
159  return false;
160  }
161  return true;
162  }
163 
164  std::shared_ptr<DisableControl> GetControl()
165  {
166  return pControl;
167  }
168 
169  private:
170  XrdCl::Socket *pSocket;
171  XrdCl::SocketHandler *pHandler;
172  std::shared_ptr<DisableControl> pControl;
173  };
174 }
175 
176 
177 namespace XrdCl
178 {
179  //----------------------------------------------------------------------------
180  // Initialize the poller
181  //----------------------------------------------------------------------------
183  {
184  return true;
185  }
186 
187  //----------------------------------------------------------------------------
188  // Finalize the poller
189  //----------------------------------------------------------------------------
191  {
192  //--------------------------------------------------------------------------
193  // Clean up the channels
194  //--------------------------------------------------------------------------
195  SocketMap::iterator it;
196  for( it = pSocketMap.begin(); it != pSocketMap.end(); ++it )
197  {
198  PollerHelper *helper = (PollerHelper*)it->second;
199  if( helper->channel ) helper->channel->Delete();
200  delete helper->callBack;
201  delete helper;
202  }
203  pSocketMap.clear();
204 
205  return true;
206  }
207 
208  //------------------------------------------------------------------------
209  // Start polling
210  //------------------------------------------------------------------------
212  {
213  //--------------------------------------------------------------------------
214  // Start the poller
215  //--------------------------------------------------------------------------
216  using namespace XrdSys;
217 
218  Log *log = DefaultEnv::GetLog();
219  log->Debug( PollerMsg, "Creating and starting the built-in poller..." );
220  XrdSysMutexHelper scopedLock( pMutex );
221  int errNum = 0;
222  const char *errMsg = 0;
223 
224  for( int i = 0; i < pNbPoller; ++i )
225  {
226  XrdSys::IOEvents::Poller* poller = IOEvents::Poller::Create( errNum, &errMsg );
227  if( !poller )
228  {
229  log->Error( PollerMsg, "Unable to create the internal poller object: "
230  "%s (%s)", XrdSysE2T( errno ), errMsg );
231  return false;
232  }
233  pPollerPool.push_back( poller );
234  }
235 
236  pNext = pPollerPool.begin();
237 
238  log->Debug( PollerMsg, "Using %d poller threads", pNbPoller );
239 
240  //--------------------------------------------------------------------------
241  // Check if we have any descriptors to reinsert from the last time we
242  // were started
243  //--------------------------------------------------------------------------
244  SocketMap::iterator it;
245  for( it = pSocketMap.begin(); it != pSocketMap.end(); ++it )
246  {
247  PollerHelper *helper = (PollerHelper*)it->second;
248  Socket *socket = it->first;
249 
250  // static cast for the downcast as we're sure it's a SocketCallBack
251  auto *scb = static_cast<SocketCallBack*>( helper->callBack );
252  if( scb )
253  {
254  auto dc = scb->GetControl();
255  if( dc ) dc->Restart();
256  }
257 
258  helper->channel = new IOEvents::Channel( RegisterAndGetPoller( socket ), socket->GetFD(),
259  helper->callBack );
260  if( helper->readEnabled )
261  {
262  bool status = helper->channel->Enable( IOEvents::Channel::readEvents,
263  helper->readTimeout, &errMsg );
264  if( !status )
265  {
266  log->Error( PollerMsg, "Unable to enable read notifications "
267  "while re-starting %s (%s)", XrdSysE2T( errno ), errMsg );
268 
269  return false;
270  }
271  }
272 
273  if( helper->writeEnabled )
274  {
275  bool status = helper->channel->Enable( IOEvents::Channel::writeEvents,
276  helper->writeTimeout, &errMsg );
277  if( !status )
278  {
279  log->Error( PollerMsg, "Unable to enable write notifications "
280  "while re-starting %s (%s)", XrdSysE2T( errno ), errMsg );
281 
282  return false;
283  }
284  }
285  }
286  return true;
287  }
288 
289  //------------------------------------------------------------------------
290  // Stop polling
291  //------------------------------------------------------------------------
293  {
294  using namespace XrdSys::IOEvents;
295 
296  Log *log = DefaultEnv::GetLog();
297  log->Debug( PollerMsg, "Stopping the poller..." );
298 
299  XrdSysMutexHelper scopedLock( pMutex );
300 
301  if( pPollerPool.empty() )
302  {
303  log->Debug( PollerMsg, "Stopping a poller that has not been started" );
304  return true;
305  }
306 
307  while( !pPollerPool.empty() )
308  {
309  XrdSys::IOEvents::Poller *poller = pPollerPool.back();
310  if( *pNext == poller )
311  pNext = pPollerPool.begin();
312  pPollerPool.pop_back();
313 
314  if( !poller ) continue;
315 
316  scopedLock.UnLock();
317  poller->Stop();
318  delete poller;
319  scopedLock.Lock( &pMutex );
320  }
321  pNext = pPollerPool.end();
322  pPollerMap.clear();
323 
324  SocketMap::iterator it;
325  const char *errMsg = 0;
326 
327  for( it = pSocketMap.begin(); it != pSocketMap.end(); ++it )
328  {
329  PollerHelper *helper = (PollerHelper*)it->second;
330  if( !helper->channel ) continue;
331  bool status = helper->channel->Disable( Channel::allEvents, &errMsg );
332  if( !status )
333  {
334  Socket *socket = it->first;
335  log->Error( PollerMsg, "%s Unable to disable write notifications: %s",
336  socket->GetName().c_str(), errMsg );
337  }
338  helper->channel->Delete();
339  helper->channel = 0;
340  }
341 
342  return true;
343  }
344 
345  //------------------------------------------------------------------------
346  // Add socket to the polling queue
347  //------------------------------------------------------------------------
349  SocketHandler *handler )
350  {
351  Log *log = DefaultEnv::GetLog();
352  XrdSysMutexHelper scopedLock( pMutex );
353 
354  if( !socket )
355  {
356  log->Error( PollerMsg, "Invalid socket, impossible to poll" );
357  return false;
358  }
359 
360  if( socket->GetStatus() != Socket::Connected &&
361  socket->GetStatus() != Socket::Connecting )
362  {
363  log->Error( PollerMsg, "Socket is not in a state valid for polling" );
364  return false;
365  }
366 
367  log->Debug( PollerMsg, "Adding socket %p to the poller", (void*)socket );
368 
369  //--------------------------------------------------------------------------
370  // Check if the socket is already registered
371  //--------------------------------------------------------------------------
372  SocketMap::const_iterator it = pSocketMap.find( socket );
373  if( it != pSocketMap.end() )
374  {
375  log->Warning( PollerMsg, "%s Already registered with this poller",
376  socket->GetName().c_str() );
377  return false;
378  }
379 
380  //--------------------------------------------------------------------------
381  // Create the socket helper
382  //--------------------------------------------------------------------------
383  XrdSys::IOEvents::Poller* poller = RegisterAndGetPoller( socket );
384 
385  if( !poller )
386  {
387  log->Error( PollerMsg, "No poller available, can not add socket" );
388  return false;
389  }
390 
391  PollerHelper *helper = new PollerHelper();
392  helper->callBack = new ::SocketCallBack( socket, handler );
393 
394  if( poller )
395  {
396  helper->channel = new XrdSys::IOEvents::Channel( poller,
397  socket->GetFD(),
398  helper->callBack );
399  }
400 
401  handler->Initialize( this );
402  pSocketMap[socket] = helper;
403  return true;
404  }
405 
406  //----------------------------------------------------------------------------
407  // This disables further callbacks to the socket's handler from the poller
408  // thread. Will wait until any current callback completes (unless our caller
409  // is the same thread). We do not yet remove the socket from the poller.
410  // Removal may still block until the relevant poller thread can run.
411  //----------------------------------------------------------------------------
413  {
414  XrdSysMutexHelper scopedLock( pMutex );
415  SocketMap::iterator it = pSocketMap.find( socket );
416  if( it == pSocketMap.end() )
417  return;
418 
419  PollerHelper *helper = (PollerHelper*)it->second;
420  if( !helper ) return;
421  XrdSys::IOEvents::CallBack *cb = helper->callBack;
422  if( !cb ) return;
423  SocketCallBack *scb = dynamic_cast<SocketCallBack*>( cb );
424  if( !scb ) return;
425  auto dc = scb->GetControl();
426  scopedLock.UnLock();
427  dc->DisableCallBack();
428  }
429 
430  //------------------------------------------------------------------------
431  // Remove the socket
432  //------------------------------------------------------------------------
434  {
435  using namespace XrdSys::IOEvents;
436  Log *log = DefaultEnv::GetLog();
437 
438  //--------------------------------------------------------------------------
439  // Find the right socket
440  //--------------------------------------------------------------------------
441  XrdSysMutexHelper scopedLock( pMutex );
442  SocketMap::iterator it = pSocketMap.find( socket );
443  if( it == pSocketMap.end() )
444  return true;
445 
446  log->Debug( PollerMsg, "%s Removing socket from the poller",
447  socket->GetName().c_str() );
448 
449  // unregister from the poller it's currently associated with
450  UnregisterFromPoller( socket );
451 
452  //--------------------------------------------------------------------------
453  // Remove the socket
454  //--------------------------------------------------------------------------
455  PollerHelper *helper = (PollerHelper*)it->second;
456  pSocketMap.erase( it );
457  scopedLock.UnLock();
458 
459  if( helper->channel )
460  {
461  const char *errMsg;
462  bool status = helper->channel->Disable( Channel::allEvents, &errMsg );
463  if( !status )
464  {
465  log->Error( PollerMsg, "%s Unable to disable write notifications: %s",
466  socket->GetName().c_str(), errMsg );
467  return false;
468  }
469  helper->channel->Delete();
470  }
471  delete helper->callBack;
472  delete helper;
473  return true;
474  }
475 
476  //----------------------------------------------------------------------------
477  // Notify the handler about read events
478  //----------------------------------------------------------------------------
480  bool notify,
481  time_t timeout )
482  {
483  using namespace XrdSys::IOEvents;
484  Log *log = DefaultEnv::GetLog();
485 
486  if( !socket )
487  {
488  log->Error( PollerMsg, "Invalid socket, read events unavailable" );
489  return false;
490  }
491 
492  //--------------------------------------------------------------------------
493  // Check if the socket is registered
494  //--------------------------------------------------------------------------
495  XrdSysMutexHelper scopedLock( pMutex );
496  SocketMap::const_iterator it = pSocketMap.find( socket );
497  if( it == pSocketMap.end() )
498  {
499  log->Warning( PollerMsg, "%s Socket is not registered",
500  socket->GetName().c_str() );
501  return false;
502  }
503 
504  PollerHelper *helper = (PollerHelper*)it->second;
505  XrdSys::IOEvents::Poller *poller = GetPoller( socket );
506 
507  //--------------------------------------------------------------------------
508  // Enable read notifications
509  //--------------------------------------------------------------------------
510  if( notify )
511  {
512  if( helper->readEnabled )
513  return true;
514  helper->readTimeout = timeout;
515 
516  log->Dump( PollerMsg, "%s Enable read notifications, timeout: %lld",
517  socket->GetName().c_str(), (long long)timeout );
518 
519  if( poller )
520  {
521  const char *errMsg;
522  bool status = helper->channel->Enable( Channel::readEvents, timeout,
523  &errMsg );
524  if( !status )
525  {
526  log->Error( PollerMsg, "%s Unable to enable read notifications: %s",
527  socket->GetName().c_str(), errMsg );
528  return false;
529  }
530  }
531  helper->readEnabled = true;
532  }
533 
534  //--------------------------------------------------------------------------
535  // Disable read notifications
536  //--------------------------------------------------------------------------
537  else
538  {
539  if( !helper->readEnabled )
540  return true;
541 
542  log->Dump( PollerMsg, "%s Disable read notifications",
543  socket->GetName().c_str() );
544 
545  if( poller )
546  {
547  const char *errMsg;
548  bool status = helper->channel->Disable( Channel::readEvents, &errMsg );
549  if( !status )
550  {
551  log->Error( PollerMsg, "%s Unable to disable read notifications: %s",
552  socket->GetName().c_str(), errMsg );
553  return false;
554  }
555  }
556  helper->readEnabled = false;
557  }
558  return true;
559  }
560 
561  //----------------------------------------------------------------------------
562  // Notify the handler about write events
563  //----------------------------------------------------------------------------
565  bool notify,
566  time_t timeout )
567  {
568  using namespace XrdSys::IOEvents;
569  Log *log = DefaultEnv::GetLog();
570 
571  if( !socket )
572  {
573  log->Error( PollerMsg, "Invalid socket, write events unavailable" );
574  return false;
575  }
576 
577  //--------------------------------------------------------------------------
578  // Check if the socket is registered
579  //--------------------------------------------------------------------------
580  XrdSysMutexHelper scopedLock( pMutex );
581  SocketMap::const_iterator it = pSocketMap.find( socket );
582  if( it == pSocketMap.end() )
583  {
584  log->Warning( PollerMsg, "%s Socket is not registered",
585  socket->GetName().c_str() );
586  return false;
587  }
588 
589  PollerHelper *helper = (PollerHelper*)it->second;
590  XrdSys::IOEvents::Poller *poller = GetPoller( socket );
591 
592  //--------------------------------------------------------------------------
593  // Enable write notifications
594  //--------------------------------------------------------------------------
595  if( notify )
596  {
597  if( helper->writeEnabled )
598  return true;
599 
600  helper->writeTimeout = timeout;
601 
602  log->Dump( PollerMsg, "%s Enable write notifications, timeout: %lld",
603  socket->GetName().c_str(), (long long)timeout );
604 
605  if( poller )
606  {
607  const char *errMsg;
608  bool status = helper->channel->Enable( Channel::writeEvents, timeout,
609  &errMsg );
610  if( !status )
611  {
612  log->Error( PollerMsg, "%s Unable to enable write notifications: %s",
613  socket->GetName().c_str(), errMsg );
614  return false;
615  }
616  }
617  helper->writeEnabled = true;
618  }
619 
620  //--------------------------------------------------------------------------
621  // Disable read notifications
622  //--------------------------------------------------------------------------
623  else
624  {
625  if( !helper->writeEnabled )
626  return true;
627 
628  log->Dump( PollerMsg, "%s Disable write notifications",
629  socket->GetName().c_str() );
630  if( poller )
631  {
632  const char *errMsg;
633  bool status = helper->channel->Disable( Channel::writeEvents, &errMsg );
634  if( !status )
635  {
636  log->Error( PollerMsg, "%s Unable to disable write notifications: %s",
637  socket->GetName().c_str(), errMsg );
638  return false;
639  }
640  }
641  helper->writeEnabled = false;
642  }
643  return true;
644  }
645 
646  //----------------------------------------------------------------------------
647  // Check whether the socket is registered with the poller
648  //----------------------------------------------------------------------------
650  {
651  XrdSysMutexHelper scopedLock( pMutex );
652  SocketMap::iterator it = pSocketMap.find( socket );
653  return it != pSocketMap.end();
654  }
655 
656  //----------------------------------------------------------------------------
657  // Return poller threads in round-robin fashion
658  //----------------------------------------------------------------------------
659  XrdSys::IOEvents::Poller* PollerBuiltIn::GetNextPoller()
660  {
661  if( pPollerPool.empty() ) return 0;
662 
663  PollerPool::iterator ret = pNext;
664  ++pNext;
665  if( pNext == pPollerPool.end() )
666  pNext = pPollerPool.begin();
667  return *ret;
668  }
669 
670  //----------------------------------------------------------------------------
671  // Return the poller associated with the respective channel
672  //----------------------------------------------------------------------------
673  XrdSys::IOEvents::Poller* PollerBuiltIn::RegisterAndGetPoller(const Socket * socket)
674  {
675  PollerMap::iterator itr = pPollerMap.find( socket->GetFD() );
676 
677  if( itr == pPollerMap.end() )
678  {
679  XrdSys::IOEvents::Poller* poller = GetNextPoller();
680  if( poller )
681  pPollerMap[socket->GetFD()] = poller;
682  return poller;
683  }
684 
685  return itr->second;
686  }
687 
688  void PollerBuiltIn::UnregisterFromPoller( const Socket *socket )
689  {
690  PollerMap::iterator itr = pPollerMap.find( socket->GetFD() );
691  if( itr == pPollerMap.end() ) return;
692  pPollerMap.erase( itr );
693  }
694 
695  XrdSys::IOEvents::Poller* PollerBuiltIn::GetPoller(const Socket * socket)
696  {
697  PollerMap::iterator itr = pPollerMap.find( socket->GetFD() );
698  if( itr == pPollerMap.end() ) return 0;
699  return itr->second;
700  }
701 
702  //----------------------------------------------------------------------------
703  // Get the initial value for pNbPoller
704  //----------------------------------------------------------------------------
705  int PollerBuiltIn::GetNbPollerInit()
706  {
707  Env * env = DefaultEnv::GetEnv();
709  env->GetInt("ParallelEvtLoop", ret);
710  return ret;
711  }
712 }
#define unlikely(x)
bool Create
const char * XrdSysE2T(int errcode)
Definition: XrdSysE2T.cc:104
static Log * GetLog()
Get default log.
static Env * GetEnv()
Get default client environment.
bool GetInt(const std::string &key, int &value)
Definition: XrdClEnv.cc:115
Handle diagnostics.
Definition: XrdClLog.hh:101
void Error(uint64_t topic, const char *format,...)
Report an error.
Definition: XrdClLog.cc:231
LogLevel GetLevel() const
Get the log level.
Definition: XrdClLog.hh:258
void Warning(uint64_t topic, const char *format,...)
Report a warning.
Definition: XrdClLog.cc:248
void Dump(uint64_t topic, const char *format,...)
Print a dump message.
Definition: XrdClLog.cc:299
void Debug(uint64_t topic, const char *format,...)
Print a debug message.
Definition: XrdClLog.cc:282
virtual bool AddSocket(Socket *socket, SocketHandler *handler)
virtual bool EnableReadNotification(Socket *socket, bool notify, time_t timeout=60)
virtual bool RemoveSocket(Socket *socket)
Remove the socket.
virtual bool Stop()
Stop polling.
virtual void ShutdownEvents(Socket *socket)
virtual bool EnableWriteNotification(Socket *socket, bool notify, time_t timeout=60)
virtual bool IsRegistered(Socket *socket)
Check whether the socket is registered with the poller.
virtual bool Finalize()
Finalize the poller.
virtual bool Initialize()
Initialize the poller.
virtual bool Start()
Start polling.
virtual void Initialize(Poller *)
Initializer.
Definition: XrdClPoller.hh:56
A network socket.
Definition: XrdClSocket.hh:43
std::string GetName() const
Get the string representation of the socket.
Definition: XrdClSocket.cc:672
@ Connected
The socket is connected.
Definition: XrdClSocket.hh:51
@ Connecting
The connection process is in progress.
Definition: XrdClSocket.hh:52
int GetFD() const
Get the file descriptor.
Definition: XrdClSocket.hh:214
SocketStatus GetStatus() const
Get the socket status.
Definition: XrdClSocket.hh:125
void Lock(XrdSysMutex *Mutex)
static int Same(pthread_t t1, pthread_t t2)
static pthread_t ID(void)
virtual bool Event(Channel *chP, void *cbArg, int evFlags)=0
const uint64_t PollerMsg
const int DefaultParallelEvtLoop