1#if defined(HAVE_CONFIG_H)
7#include <sys/resource.h>
20#define RESIPROCATE_SUBSYSTEM Subsystem::TRANSPORT
34 DebugLog(<<
"ConnectionManager::ConnectionManager() called ");
47ConnectionManager::closeConnections()
49 while (!mAddrMap.empty())
51 delete mAddrMap.begin()->second;
60 IdMap::iterator i = mIdMap.find(addr.
mFlowKey);
61 if (i != mIdMap.end())
63 if(i->second->who() == addr)
71 <<
" exists, but does not match the destination. FD -> "
72 << i->second->who() <<
", tuple -> " << addr);
86 AddrMap::iterator i = mAddrMap.find(addr);
87 if (i != mAddrMap.end())
89 DebugLog(<<
"Found connection for tuple "<< addr );
93 DebugLog(<<
"Could not find a connection for " << addr);
102 IdMap::const_iterator i = mIdMap.find(addr.
mFlowKey);
103 if (i != mIdMap.end())
105 if(i->second->who()==addr)
113 <<
" exists, but does not match the destination. FD -> "
114 << i->second->who() <<
", tuple -> " << addr);
123 AddrMap::const_iterator i = mAddrMap.find(addr);
124 if (i != mAddrMap.end())
126 DebugLog(<<
"Found connection for tuple "<< addr );
130 DebugLog(<<
"Could not find a connection for " << addr);
141 i != mReadHead->
end(); ++i)
143 fdset.
setRead((*i)->getSocket());
148 i != mWriteHead->
end(); ++i)
156ConnectionManager::addToWritable(
Connection* conn)
169ConnectionManager::removeFromWritable(
Connection* conn)
178 conn->ConnectionWriteList::remove();
183ConnectionManager::addConnection(
Connection* connection)
187 DebugLog (<<
"ConnectionManager::addConnection() " << connection->
mWho.
mFlowKey <<
":" << connection->
who() <<
", totalConnections=" << mIdMap.size());
189 mAddrMap[connection->
who()] = connection;
194 connection->mPollItemHandle = mPollGrp->
addPollItem(
215ConnectionManager::removeConnection(
Connection* connection)
217 DebugLog (<<
"ConnectionManager::removeConnection()");
220 mAddrMap.erase(connection->
mWho);
224 mPollGrp->
delPollItem(connection->mPollItemHandle);
229 connection->ConnectionReadList::remove();
230 connection->ConnectionWriteList::remove();
233 connection->FlowTimerLruList::remove();
237 connection->ConnectionLruList::remove();
244ConnectionManager::gc(
uint64_t relThreshold,
unsigned int maxToRemove)
247 uint64_t threshold = curTimeMs > relThreshold ? curTimeMs - relThreshold : 0;
249 DebugLog(<<
"recycling connections not used in last " << relThreshold/1000.0 <<
" seconds");
252 unsigned int numRemoved = 0;
254 i != mLRUHead->
end() &&
255 (maxToRemove == 0 || numRemoved != maxToRemove);)
257 if ((*i)->whenLastUsed() < threshold)
260 InfoLog(<<
"recycling connection: " << discard <<
" " << discard->
getSocket());
274 if(mFlowTimerLRUHead->
begin() != mFlowTimerLRUHead->
end())
277 threshold = curTimeMs > flowTimerPeriodMs ? curTimeMs - flowTimerPeriodMs : 0;
279 i2 != mFlowTimerLRUHead->
end() &&
280 (maxToRemove == 0 || numRemoved != maxToRemove);)
282 if ((*i2)->whenLastUsed() < threshold)
285 InfoLog(<<
"recycling flow-timer enabled connection: " << discard <<
" " << discard->
getSocket());
301 DebugLog(<<
"MinimumGcHeadroom not yet implemented on Windows (requires getrlimit())");
304 if(getrlimit(RLIMIT_NOFILE, &rlim) != 0)
306 ErrLog(<<
"Call to getrlimit() for RLIMIT_NOFILE failed: " <<
strError(errno));
310 rlim_t& soft_limit = rlim.rlim_cur;
311 AddrMap::size_type conn_count = mAddrMap.size();
312 AddrMap::size_type headroom = soft_limit - conn_count;
313 DebugLog(<<
"GC headroom check: soft_limit = " << soft_limit <<
", managed connection count = " << conn_count <<
", headroom = " << headroom <<
", minimum headroom = " <<
MinimumGcHeadroom);
316 WarningLog(<<
"actual headroom = " << headroom <<
", MinimumGcHeadroom = " <<
MinimumGcHeadroom <<
", garbage collector making extra effort to reclaim file descriptors");
318 unsigned int remainder = gcWithTarget(mustRemove);
319 numRemoved += (mustRemove - remainder);
322 ErrLog(<<
"No more stream connections to close, something else must be eating file descriptors, limit too low or MinimumGcHeadroom too high");
332ConnectionManager::gcWithTarget(
unsigned int target)
339 if(i == mLRUHead->
end())
341 if(i2 == mFlowTimerLRUHead->
end())
343 WarningLog(<<
"No more stream connections to close, remaining target = " << target);
351 if (i2 == mFlowTimerLRUHead->
end() ||
352 (*i)->whenLastUsed() < (*i2)->whenLastUsed())
373ConnectionManager::touch(
Connection* connection)
378 connection->FlowTimerLruList::remove();
379 mFlowTimerLRUHead->
push_back(connection);
383 connection->ConnectionLruList::remove();
389ConnectionManager::moveToFlowTimerLru(
Connection *connection)
391 connection->ConnectionLruList::remove();
392 mFlowTimerLRUHead->
push_back(connection);
402 writeIter != mWriteHead->
end(); )
417 delete currConnection;
423 int errNumSize =
sizeof(errNum);
424 getsockopt(currConnection->
getSocket(), SOL_SOCKET, SO_ERROR, (
char *)&errNum, (socklen_t *)&errNumSize);
425 InfoLog(<<
"Exception writing to socket " << currConnection->
getSocket() <<
" code: " << errNum <<
"; closing connection");
426 delete currConnection;
432 readIter != mReadHead->
end(); )
452 int errNumSize =
sizeof(errNum);
453 getsockopt(currConnection->
getSocket(), SOL_SOCKET, SO_ERROR, (
char *)&errNum, (socklen_t *)&errNumSize);
454 InfoLog(<<
"Exception reading from socket " << currConnection->
getSocket() <<
" code: " << errNum <<
"; closing connection");
455 delete currConnection;
473 for (AddrMap::const_iterator it = mAddrMap.begin(); it != mAddrMap.end(); it++)
475 it->second->invokeAfterSocketCreationFunc();
#define WarningLog(args_)
#define resip_assert(x)
This file needs to work for both C and C++ code.
static bool EnableAgressiveGc
Enable Agressive Connection Garbage Collection to have resip perform garbage collection on every new ...
Connection * findConnection(const Tuple &tuple)
may return 0
void buildFdSet(FdSet &fdset)
void process(FdSet &fdset)
void setPollGrp(FdPollGrp *grp)
populate the fdset againt the read and write lists
static uint64_t MinimumGcAge
connection must have no inbound traffic for greater than this time (in ms) before it is garbage colle...
virtual void invokeAfterSocketCreationFunc() const
static uint64_t MinimumGcHeadroom
If the difference between the number of permitted FDs (reported by periodic calls to getrlimit()) and...
Connection implements, via sockets, ConnectionBase for managed connections.
bool performWrites(unsigned int max=0)
Call performWrite() repeatedly, until either the send queue is exhausted, the write() call fails (pro...
virtual bool hasDataToRead()
always true – always add to fdset as read ready
bool performReads(unsigned int max=0)
Call read() repeatedly, until an error occurs (because the fd is not ready to read,...
bool isFlowTimerEnabled()
virtual FdPollItemHandle addPollItem(Socket sock, FdPollEventMask newMask, FdPollItemIf *item)=0
virtual void delPollItem(FdPollItemHandle handle)=0
virtual void modPollItem(FdPollItemHandle handle, FdPollEventMask newMask)=0
Object-oriented wrapper for your platform's file-descriptor set.
bool readyToWrite(Socket fd)
bool readyToRead(Socket fd)
void setExcept(Socket fd)
bool hasException(Socket fd)
static unsigned int getFlowTimerSeconds()
static unsigned int getFlowTimerGracePeriodSeconds()
static uint64_t getTimeMs()
Returns the current clock time in milliseconds.
Represents a network address.
bool onlyUseExistingConnection
FlowKey mFlowKey
This is a (largely) opaque key that subclasses of Transport will use to help record/find flows.
dcm! – add UnusedChecking(_enum) below;
std::string strError(int err)
unsigned __int64 uint64_t