42 channel(0), callBack(0), readEnabled(false), writeEnabled(false),
43 readTimeout(0), writeTimeout(0)
45 XrdSys::IOEvents::Channel *channel;
46 XrdSys::IOEvents::CallBack *callBack;
69 DisableControl() : pFlags( 0 ), pCnd( 0 ) { }
76 void DisableCallBack()
78 const int flags = pFlags.fetch_or( kWantDisable );
79 if( !(flags & kIdSet) )
return;
80 if( !(flags & kRunningCallBack) )
return;
81 XrdSysCondVarHelper lck( pCnd );
83 while( !(pFlags.load() & kDisabled) ) pCnd.Wait();
94 pFlags.fetch_and( ~kIdSet );
97 std::atomic<int> pFlags;
102 SocketCallBack( XrdCl::Socket *sock, XrdCl::SocketHandler *sh ):
103 pSocket( sock ), pHandler( sh )
105 pControl = std::make_shared<DisableControl>();
108 virtual ~SocketCallBack() {};
110 virtual bool Event( XrdSys::IOEvents::Channel *chP,
114 using namespace XrdCl;
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;
122 Log *log = DefaultEnv::GetLog();
125 log->
Dump( PollerMsg,
"%s Got an event: %s",
126 pSocket->GetName().c_str(),
127 SocketHandler::EventTypeToString( ev ).c_str() );
130 int flags = pControl->pFlags.fetch_or( kRunningCallBack );
131 if( !( flags & kIdSet ) )
133 XrdSysCondVarHelper lck( pControl->pCnd );
135 flags = pControl->pFlags.fetch_or( kIdSet );
137 if( flags & kWantDisable )
139 XrdSysCondVarHelper lck( pControl->pCnd );
140 pControl->pFlags &= ~kRunningCallBack;
141 pControl->pFlags |= kDisabled;
142 pControl->pCnd.Broadcast();
150 auto control = pControl;
151 pHandler->Event( ev, pSocket );
153 flags = control->pFlags.fetch_and( ~kRunningCallBack );
154 if( flags & kWantDisable )
156 XrdSysCondVarHelper lck( control->pCnd );
157 control->pFlags |= kDisabled;
158 control->pCnd.Broadcast();
164 std::shared_ptr<DisableControl> GetControl()
170 XrdCl::Socket *pSocket;
171 XrdCl::SocketHandler *pHandler;
172 std::shared_ptr<DisableControl> pControl;
195 SocketMap::iterator it;
196 for( it = pSocketMap.begin(); it != pSocketMap.end(); ++it )
198 PollerHelper *helper = (PollerHelper*)it->second;
199 if( helper->channel ) helper->channel->
Delete();
200 delete helper->callBack;
219 log->
Debug(
PollerMsg,
"Creating and starting the built-in poller..." );
222 const char *errMsg = 0;
224 for(
int i = 0; i < pNbPoller; ++i )
229 log->
Error(
PollerMsg,
"Unable to create the internal poller object: "
233 pPollerPool.push_back( poller );
236 pNext = pPollerPool.begin();
244 SocketMap::iterator it;
245 for( it = pSocketMap.begin(); it != pSocketMap.end(); ++it )
247 PollerHelper *helper = (PollerHelper*)it->second;
248 Socket *socket = it->first;
251 auto *scb =
static_cast<SocketCallBack*
>( helper->callBack );
254 auto dc = scb->GetControl();
255 if( dc ) dc->Restart();
260 if( helper->readEnabled )
263 helper->readTimeout, &errMsg );
267 "while re-starting %s (%s)",
XrdSysE2T( errno ), errMsg );
273 if( helper->writeEnabled )
276 helper->writeTimeout, &errMsg );
280 "while re-starting %s (%s)",
XrdSysE2T( errno ), errMsg );
301 if( pPollerPool.empty() )
303 log->
Debug(
PollerMsg,
"Stopping a poller that has not been started" );
307 while( !pPollerPool.empty() )
310 if( *pNext == poller )
311 pNext = pPollerPool.begin();
312 pPollerPool.pop_back();
314 if( !poller )
continue;
319 scopedLock.
Lock( &pMutex );
321 pNext = pPollerPool.end();
324 SocketMap::iterator it;
325 const char *errMsg = 0;
327 for( it = pSocketMap.begin(); it != pSocketMap.end(); ++it )
329 PollerHelper *helper = (PollerHelper*)it->second;
330 if( !helper->channel )
continue;
334 Socket *socket = it->first;
335 log->
Error(
PollerMsg,
"%s Unable to disable write notifications: %s",
336 socket->
GetName().c_str(), errMsg );
338 helper->channel->
Delete();
363 log->
Error(
PollerMsg,
"Socket is not in a state valid for polling" );
367 log->
Debug(
PollerMsg,
"Adding socket %p to the poller", (
void*)socket );
372 SocketMap::const_iterator it = pSocketMap.find( socket );
373 if( it != pSocketMap.end() )
387 log->
Error(
PollerMsg,
"No poller available, can not add socket" );
391 PollerHelper *helper =
new PollerHelper();
392 helper->callBack = new ::SocketCallBack( socket, handler );
402 pSocketMap[socket] = helper;
415 SocketMap::iterator it = pSocketMap.find( socket );
416 if( it == pSocketMap.end() )
419 PollerHelper *helper = (PollerHelper*)it->second;
420 if( !helper )
return;
423 SocketCallBack *scb =
dynamic_cast<SocketCallBack*
>( cb );
425 auto dc = scb->GetControl();
427 dc->DisableCallBack();
442 SocketMap::iterator it = pSocketMap.find( socket );
443 if( it == pSocketMap.end() )
450 UnregisterFromPoller( socket );
455 PollerHelper *helper = (PollerHelper*)it->second;
456 pSocketMap.erase( it );
459 if( helper->channel )
465 log->
Error(
PollerMsg,
"%s Unable to disable write notifications: %s",
466 socket->
GetName().c_str(), errMsg );
469 helper->channel->
Delete();
471 delete helper->callBack;
488 log->
Error(
PollerMsg,
"Invalid socket, read events unavailable" );
496 SocketMap::const_iterator it = pSocketMap.find( socket );
497 if( it == pSocketMap.end() )
504 PollerHelper *helper = (PollerHelper*)it->second;
512 if( helper->readEnabled )
514 helper->readTimeout = timeout;
516 log->
Dump(
PollerMsg,
"%s Enable read notifications, timeout: %lld",
517 socket->
GetName().c_str(), (
long long)timeout );
526 log->
Error(
PollerMsg,
"%s Unable to enable read notifications: %s",
527 socket->
GetName().c_str(), errMsg );
531 helper->readEnabled =
true;
539 if( !helper->readEnabled )
551 log->
Error(
PollerMsg,
"%s Unable to disable read notifications: %s",
552 socket->
GetName().c_str(), errMsg );
556 helper->readEnabled =
false;
573 log->
Error(
PollerMsg,
"Invalid socket, write events unavailable" );
581 SocketMap::const_iterator it = pSocketMap.find( socket );
582 if( it == pSocketMap.end() )
589 PollerHelper *helper = (PollerHelper*)it->second;
597 if( helper->writeEnabled )
600 helper->writeTimeout = timeout;
602 log->
Dump(
PollerMsg,
"%s Enable write notifications, timeout: %lld",
603 socket->
GetName().c_str(), (
long long)timeout );
612 log->
Error(
PollerMsg,
"%s Unable to enable write notifications: %s",
613 socket->
GetName().c_str(), errMsg );
617 helper->writeEnabled =
true;
625 if( !helper->writeEnabled )
636 log->
Error(
PollerMsg,
"%s Unable to disable write notifications: %s",
637 socket->
GetName().c_str(), errMsg );
641 helper->writeEnabled =
false;
652 SocketMap::iterator it = pSocketMap.find( socket );
653 return it != pSocketMap.end();
661 if( pPollerPool.empty() )
return 0;
663 PollerPool::iterator ret = pNext;
665 if( pNext == pPollerPool.end() )
666 pNext = pPollerPool.begin();
675 PollerMap::iterator itr = pPollerMap.find( socket->
GetFD() );
677 if( itr == pPollerMap.end() )
681 pPollerMap[socket->
GetFD()] = poller;
688 void PollerBuiltIn::UnregisterFromPoller(
const Socket *socket )
690 PollerMap::iterator itr = pPollerMap.find( socket->
GetFD() );
691 if( itr == pPollerMap.end() )
return;
692 pPollerMap.erase( itr );
695 XrdSys::IOEvents::Poller* PollerBuiltIn::GetPoller(
const Socket * socket)
697 PollerMap::iterator itr = pPollerMap.find( socket->
GetFD() );
698 if( itr == pPollerMap.end() )
return 0;
705 int PollerBuiltIn::GetNbPollerInit()
709 env->
GetInt(
"ParallelEvtLoop", ret);
const char * XrdSysE2T(int errcode)
static Log * GetLog()
Get default log.
static Env * GetEnv()
Get default client environment.
bool GetInt(const std::string &key, int &value)
void Error(uint64_t topic, const char *format,...)
Report an error.
LogLevel GetLevel() const
Get the log level.
void Warning(uint64_t topic, const char *format,...)
Report a warning.
void Dump(uint64_t topic, const char *format,...)
Print a dump message.
void Debug(uint64_t topic, const char *format,...)
Print a debug message.
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.
std::string GetName() const
Get the string representation of the socket.
@ Connected
The socket is connected.
@ Connecting
The connection process is in progress.
int GetFD() const
Get the file descriptor.
SocketStatus GetStatus() const
Get the socket status.
void Lock(XrdSysMutex *Mutex)
static int Same(pthread_t t1, pthread_t t2)
static pthread_t ID(void)
@ allEvents
All of the above.
@ writeEvents
Write and Write Timeouts.
@ readEvents
Read and Read Timeouts.
bool Enable(int events, int timeout=0, const char **eText=0)
bool Disable(int events, const char **eText=0)
static Poller * Create(int &eNum, const char **eTxt=0, int crOpts=0)
const int DefaultParallelEvtLoop