void Codec20::writeExpirationParams(transport::Transport& t,uint64_t lifespan, uint64_t maxIdle) const { uint32_t lInt= (uint32_t) lifespan; uint32_t mInt= (uint32_t) maxIdle; if ( lInt != lifespan) throw HotRodClientException("lifespan exceed 32bit integer"); if ( mInt != maxIdle) throw HotRodClientException("maxIdle exceed 32bit integer"); t.writeVInt(lInt); t.writeVInt(mInt); }
void ConnectionPool::invalidateObject(const InetSocketAddress& key, TcpTransport* val) { sys::ScopedLock<sys::Mutex> l(lock); bool maxTotalReached = hasReachedMaxTotal(); if (val != NULL) { // Remove from busy queue std::map<InetSocketAddress, TransportQueuePtr>::iterator busyIt = busy.find(key); if (busyIt == busy.end()) { throw HotRodClientException("No busy queue for address!"); } busyIt->second->remove(val); totalActive--; if (maxTotalReached && !allocationQueue.empty()) { InetSocketAddress keyToAllocate = allocationQueue.front(); allocationQueue.pop(); //front does not remove it... //we need to allocate a new connection for other key. idle[keyToAllocate]->push(&factory->makeObject(keyToAllocate)); totalIdle++; } // Destroy object factory->destroyObject(key, *val); } }
void ConnectionPool::invalidateObject(const InetSocketAddress& key, TcpTransport* val) { sys::ScopedLock<sys::Mutex> l(lock); if (val != NULL) { // Remove from busy queue std::map<InetSocketAddress, TransportQueuePtr>::iterator busyIt = busy.find(key); if (busyIt == busy.end()) { throw HotRodClientException("No busy queue for address!"); } busyIt->second->remove(val); // Destroy object factory->destroyObject(key, *val); // Add new transport to idle queue std::map<InetSocketAddress, TransportQueuePtr>::iterator idleIt = idle.find(key); if (idleIt == idle.end()) { throw HotRodClientException("No idle queue for address!"); } idleIt->second->push(&factory->makeObject(key)); } }
TcpTransport& ConnectionPool::borrowObject(const InetSocketAddress& key) { 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 = 0; 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() < (size_t) 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; }
void Codec20::checkForErrorsInResponseStatus(Transport& transport, HeaderParams& params, uint8_t status) const { try { switch (status) { case HotRodConstants::INVALID_MAGIC_OR_MESSAGE_ID_STATUS: case HotRodConstants::REQUEST_PARSING_ERROR_STATUS: case HotRodConstants::UNKNOWN_COMMAND_STATUS: case HotRodConstants::SERVER_ERROR_STATUS: case HotRodConstants::COMMAND_TIMEOUT_STATUS: case HotRodConstants::UNKNOWN_VERSION_STATUS: { // If error, the body of the message just contains a message std::string msgFromServer = transport.readString(); if (msgFromServer.find("SuspectException") != std::string::npos || msgFromServer.find("SuspectedException") != std::string::npos) { // Handle both Infinispan's and JGroups' suspicions // TODO: This will be better handled with its own status id in version 2 of protocol throw RemoteNodeSuspectException(msgFromServer, params.messageId, status); } else { throw HotRodClientException(msgFromServer); //, params.messageId, status); } } default: { throw InternalException("Unknown status: " + status); } } } catch (const Exception &) { // Some operations require invalidating the transport switch (status) { case HotRodConstants::INVALID_MAGIC_OR_MESSAGE_ID_STATUS: case HotRodConstants::REQUEST_PARSING_ERROR_STATUS: case HotRodConstants::UNKNOWN_COMMAND_STATUS: case HotRodConstants::UNKNOWN_VERSION_STATUS: { transport.invalidate(); } } throw; } }
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; }