bool ConnectionPool::tryRemoveIdle() { //first, if we find an idle queue with more the minIdle connection, we destroy one of them. //otherwise, we try to destroy and connection from the longer idle queue. const int minIdle = configuration.getMinIdle(); do { const InetSocketAddress* keyToRemove = NULL; int longerQueueSize = 0; for (std::map<InetSocketAddress, TransportQueuePtr>::iterator it = idle.begin(); it != idle.end(); ++it) { TransportQueuePtr idleQ = it->second; if (minIdle > 0 && (int) idleQ->size() > minIdle) { keyToRemove = &it->first; break; } else if ((int) idleQ->size() > longerQueueSize) { keyToRemove = &it->first; longerQueueSize = idleQ->size(); } } if (keyToRemove != NULL) { TcpTransport* t = NULL; if (idle[*keyToRemove]->poll(t)) { //in case of concurrent removal, avoid blocking factory->destroyObject(*keyToRemove, *t); totalIdle--; return true; } } else { return false; } } while (true); }
void ConnectionPool::clear(const InetSocketAddress& key) { sys::ScopedLock<sys::Mutex> l(lock); TransportQueuePtr idleQ = idle[key]; totalIdle -= idleQ->size(); clear(key, idleQ); idle.erase(key); }
int ConnectionPool::calculateMinIdleGrow(const InetSocketAddress& key) { TransportQueuePtr idleQ = idle[key]; int grown = configuration.getMinIdle() - idleQ->size(); //Note: if we need to check maxActive, uncomment the code above /*if (configuration.getMaxActive() > 0) { int growLimit = std::max(0, configuration.getMaxActive() - (int) busy[key]->size() - (int) idleQ->size()); grown = std::min(grown, growLimit); }*/ if (configuration.getMaxTotal() > 0) { int growLimit = std::max(0, configuration.getMaxTotal() - totalIdle - totalActive); grown = std::min(grown, growLimit); } return grown; }
TcpTransport& ConnectionPool::borrowObject(const InetSocketAddress& key) { if (closed) { throw new HotRodClientException("Pool is closed"); } if (!idle.count(key) || !busy.count(key)) { throw new HotRodClientException("Pool is closed"); } TransportQueuePtr idleQ = idle[key]; TransportQueuePtr busyQ = busy[key]; // See if an object is readily available TcpTransport* obj; bool ok = idleQ->poll(obj); for (;;) { if (ok) { // Check if the object is still valid, if not destroy it if (configuration.isTestOnBorrow() && !factory->validateObject(key, *obj)) { factory->destroyObject(key, *obj); ok = false; } // We have a valid object if (ok) { busyQ->push(obj); break; } } // See if we can create a new one if (busyQ->size() < configuration.getMaxActive()) { obj = &factory->makeObject(key); } else { // Wait for an object to become idle obj = idleQ->pop(); } ok = true; } factory->activateObject(key, *obj); return *obj; }
TcpTransport& ConnectionPool::borrowObject(const InetSocketAddress& key) { sys::ScopedLock<sys::Mutex> l(lock); if (closed) { throw HotRodClientException("Pool is closed"); } if (!idle.count(key) || !busy.count(key)) { throw HotRodClientException("Pool has no idle or no busy transports."); } TransportQueuePtr idleQ = idle[key]; TransportQueuePtr busyQ = busy[key]; // See if an object is readily available TcpTransport* obj = NULL; bool ok = idleQ->poll(obj); if (ok) { totalIdle--; } for (;;) { if (ok) { // Check if the object is still valid, if not destroy it if (configuration.isTestOnBorrow() && !factory->validateObject(key, *obj)) { factory->destroyObject(key, *obj); ok = false; } // We have a valid object if (ok) { busyQ->push(obj); totalActive++; break; } } // See if we can create a new one if (idleQ->size() == 0 && //the idle queue is empty (configuration.getMaxActive() < 0 || busyQ->size() < (size_t) configuration.getMaxActive()) && //max active not reached! !hasReachedMaxTotal()) { obj = &factory->makeObject(key); } else if (hasReachedMaxTotal()) { //max total reached. try to destroy a existing idle connection. if not possible, wait until some other connection is available. if (tryRemoveIdle()) { //removal successful. obj = &factory->makeObject(key); } else { allocationQueue.push(key); { sys::ScopedUnlock<sys::Mutex> u(lock); obj = idleQ->pop(); } totalIdle--; } } else { // Wait for an object to become idle { sys::ScopedUnlock<sys::Mutex> u(lock); obj = idleQ->pop(); } totalIdle--; } ok = true; } factory->activateObject(key, *obj); return *obj; }
void ConnectionPool::clear(const InetSocketAddress& key, TransportQueuePtr queue) { while (queue->size() > 0) { TcpTransport* transport = queue->pop(); factory->destroyObject(key, *transport); } }