PooledConnection* ConnectionPool::getOrDefault(const char* policyName, LMREG::CppTable* params) { if(!m_settings.empty()) { return this->get(policyName, params); } { PooledConnection* cnn = NULL; JG_S::KAutoThreadMutex mx(m_mx); ConnectionSetting* cnnSetting = m_settings.defaultConnection(); if(!cnnSetting) return NULL; ConnectionList& lst = m_cnnMap[m_settings.defaultName()]; cnn = lst.pop_front(); if(!cnn) { cnn = PooledConnection::Alloc(); cnn->reset(); cnn->m_setting = cnnSetting; } if(!cnn->keepAlive()) { this->release(cnn); return NULL; } return cnn; } }
void BloomfilterConnectionPool::recycleConnectionPool() { pthread_mutex_lock(&mutex_connectionpool); if (connections.empty()) { pthread_mutex_unlock(&mutex_connectionpool); return; } PooledConnection* pConn = NULL; for (int i = 0; i < connections.size(); i++) { pConn = connections.at(i); if (!pConn->isBusy()) { delete pConn->getConnection(); delete pConn; } else { delete pConn; } } connections.clear(); pthread_mutex_unlock(&mutex_connectionpool); return; }
//刷新连接池中所有的连接对象 void MySQLConnectionPool::refreshConnections() { // 确保连接池己创新存在 pthread_mutex_lock(&mutex_connectionpool); if (connections.empty()) { pthread_mutex_unlock(&mutex_connectionpool); return; } PooledConnection *pConn = NULL; for(int i =0 ; i<connections.size(); i++) { // 获得一个连接对象 pConn = connections.at(i); // 如果对象忙则等 5 秒 ,5 秒后直接刷新 if (pConn->isBusy()) { wait(5000); // 等 5 秒 } // 关闭此连接,用一个新的连接代替它。 closeConnection(pConn->getConnection()); pConn->setConnection(newConnection()); pConn->setBusy(false); } pthread_mutex_unlock(&mutex_connectionpool); }
//关闭连接池中所有的连接,并清空连接池 void MySQLConnectionPool::closeConnectionPool() { // 确保连接池存在,如果不存在,返回 pthread_mutex_lock(&mutex_connectionpool); if (connections.empty()) { pthread_mutex_unlock(&mutex_connectionpool); return; } PooledConnection *pConn = NULL; for(int i = 0 ; i < connections.size(); i++){ pConn = connections.at(i); // 如果忙,等 5 秒 if (pConn->isBusy()) { wait(5000); // 等 5 秒 } //5 秒后直接关闭它 closeConnection(pConn->getConnection()); // 从连接池向量中删除它 delete pConn; connections.erase(connections.begin()+i); } pthread_mutex_unlock(&mutex_connectionpool); // 置连接池为空 connections.clear(); }
void ServerPool::InitConnections() { debug("Initializing connections in ServerPool"); m_iMaxLevel = 0; for (Servers::iterator it = m_Servers.begin(); it != m_Servers.end(); it++) { NewsServer* pNewsServer = *it; if (m_iMaxLevel < pNewsServer->GetLevel()) { m_iMaxLevel = pNewsServer->GetLevel(); } for (int i = 0; i < pNewsServer->GetMaxConnections(); i++) { PooledConnection* pConnection = new PooledConnection(pNewsServer); pConnection->SetTimeout(m_iTimeout); m_Connections.push_back(pConnection); } } for (int iLevel = 0; iLevel <= m_iMaxLevel; iLevel++) { int iMaxConnectionsForLevel = 0; for (Servers::iterator it = m_Servers.begin(); it != m_Servers.end(); it++) { NewsServer* pNewsServer = *it; if (iLevel == pNewsServer->GetLevel()) { iMaxConnectionsForLevel += pNewsServer->GetMaxConnections(); } } m_Levels.push_back(iMaxConnectionsForLevel); } }
PooledConnection* ConnectionPool::get(const char* policyName, LMREG::CppTable* params) { PooledConnection* cnn = NULL; { JG_S::KAutoThreadMutex mx(m_mx); ConnectionSetting* cnnSetting = (ConnectionSetting*)m_settings.callPolicy(policyName, *params); if(!cnnSetting) return NULL; const char* cnnName = cnnSetting->m_name.c_str(); ConnectionList& lst = m_cnnMap[cnnName]; cnn = lst.pop_front(); if(!cnn) { cnn = PooledConnection::Alloc(); cnn->reset(); cnn->m_setting = cnnSetting; } } if(!cnn->keepAlive()) { this->release(cnn); return NULL; } return cnn; }
NNTPConnection* ServerPool::GetConnection(int iLevel) { PooledConnection* pConnection = NULL; m_mutexConnections.Lock(); if (m_Levels[iLevel] > 0) { for (Connections::iterator it = m_Connections.begin(); it != m_Connections.end(); it++) { PooledConnection* pConnection1 = *it; if (!pConnection1->GetInUse() && pConnection1->GetNewsServer()->GetLevel() == iLevel) { // free connection found, take it! pConnection = pConnection1; pConnection->SetInUse(true); break; } } m_Levels[iLevel]--; if (!pConnection) { error("ServerPool: internal error, no free connection found, but there should be one"); } } m_mutexConnections.Unlock(); return pConnection; }
void ConnectionPool::Execute() { while(!m_stopDesired) { time_t nowTime = time(NULL); if(!m_conf_lua_file.empty() && nowTime >= m_nextLoadTime) { time_t lastModify = JG_F::KFileUtil::GetLastModified(m_conf_lua_file.c_str()); if(lastModify != m_lastModifiedTime) { PoolSettings::ConnectionSettingArray cpy(m_settings.m_settings); if(!m_settings.reload(m_conf_lua_file.c_str())) { Log(LOG_WARN, "warn: fail reload pool setting file '%s', recover", m_conf_lua_file.c_str()); m_settings.m_settings = cpy; } m_lastModifiedTime = lastModify; } m_nextLoadTime = nowTime + 10; } if(nowTime > m_nextCheckIdleTime) { JG_S::KAutoThreadMutex mx(m_mx); ConnectionMap::iterator it = m_cnnMap.begin(), ite = m_cnnMap.end(); for(; it != ite; it++) { ConnectionList tmp; ConnectionList& lst = it->second; PooledConnection* cnn; while(cnn = lst.pop_front()) { if(cnn->isExpire(nowTime)) { Log(LOG_DEBUG, "debug: %s expire, abandon", cnn->toString().c_str()); cnn->destroy(); } else { tmp.push_back(cnn); } } while(cnn = tmp.pop_front()) { lst.push_back(cnn); } } m_nextCheckIdleTime = nowTime + 30; } msleep(100); } }
void ServerPool::InitConnections() { debug("Initializing connections in ServerPool"); m_mutexConnections.Lock(); NormalizeLevels(); m_Levels.clear(); for (Servers::iterator it = m_SortedServers.begin(); it != m_SortedServers.end(); it++) { NewsServer* pNewsServer = *it; pNewsServer->SetBlockTime(0); int iNormLevel = pNewsServer->GetNormLevel(); if (pNewsServer->GetNormLevel() > -1) { if ((int)m_Levels.size() <= iNormLevel) { m_Levels.push_back(0); } if (pNewsServer->GetActive()) { int iConnections = 0; for (Connections::iterator it = m_Connections.begin(); it != m_Connections.end(); it++) { PooledConnection* pConnection = *it; if (pConnection->GetNewsServer() == pNewsServer) { iConnections++; } } for (int i = iConnections; i < pNewsServer->GetMaxConnections(); i++) { PooledConnection* pConnection = new PooledConnection(pNewsServer); pConnection->SetTimeout(m_iTimeout); m_Connections.push_back(pConnection); iConnections++; } m_Levels[iNormLevel] += iConnections; } } } m_iGeneration++; m_mutexConnections.Unlock(); }
void ConnectionPool::finalize() { this->stop(); JG_S::KAutoThreadMutex mx(m_mx); ConnectionMap::iterator it = m_cnnMap.begin(); ConnectionMap::iterator ite = m_cnnMap.end(); for(; it!=ite; it++) { ConnectionList& lst = it->second; PooledConnection* cnn; while(cnn = lst.pop_front(), cnn) cnn->destroy(); } m_cnnMap.clear(); }
ServClient* BloomfilterConnectionPool::findFreeConnection() { ServClient * conn = NULL; PooledConnection *pConn = NULL; for(int i = 0 ;i<connections.size(); i++) { pConn = connections.at(i); if (!pConn->isBusy()) { conn = pConn->getConnection(); pConn->setBusy(true); break; } } return conn; }
void MySQLConnectionPool::Destroy() { pthread_mutex_lock(&mutex_connectionpool); if (connections.empty()) { pthread_mutex_unlock(&mutex_connectionpool); return; } PooledConnection *pConn = NULL; // 遍历连接池中的所有连接,找到这个要返回的连接对象 for (int i= 0 ; i < connections.size() ; i++) { pConn =connections.at(i); closeConnection(pConn->getConnection()); } connections.clear(); pthread_mutex_unlock(&mutex_connectionpool); }
void BloomfilterConnectionPool::returnConnection(ServClient * conn) { pthread_mutex_lock(&mutex_connectionpool); if (connections.empty()) { pthread_mutex_unlock(&mutex_connectionpool); return; } PooledConnection* pConn = NULL; for (int i = 0; i < connections.size(); i++) { pConn = connections.at(i); if (conn == pConn->getConnection()) { pConn->setBusy(false); break; } } pthread_mutex_unlock(&mutex_connectionpool); }
//此函数返回一个数据库连接到连接池中,并把此连接置为空闲。 void MySQLConnectionPool::returnConnection(sql::Connection *conn) { pthread_mutex_lock(&mutex_connectionpool); if (connections.empty()) { pthread_mutex_unlock(&mutex_connectionpool); return; } PooledConnection *pConn = NULL; // 遍历连接池中的所有连接,找到这个要返回的连接对象 for (int i= 0 ; i < connections.size() ; i++) { pConn =connections.at(i); // 先找到连接池中的要返回的连接对象 if (conn == pConn->getConnection()) { // 找到了 , 设置此连接为空闲状态 pConn->setBusy(false); break; } } pthread_mutex_unlock(&mutex_connectionpool); }
void ServerPool::LogDebugInfo() { info(" ---------- ServerPool"); info(" Max-Level: %i", m_iMaxNormLevel); m_mutexConnections.Lock(); time_t tCurTime = time(NULL); info(" Servers: %i", m_Servers.size()); for (Servers::iterator it = m_Servers.begin(); it != m_Servers.end(); it++) { NewsServer* pNewsServer = *it; info(" %i) %s (%s): Level=%i, NormLevel=%i, BlockSec=%i", pNewsServer->GetID(), pNewsServer->GetName(), pNewsServer->GetHost(), pNewsServer->GetLevel(), pNewsServer->GetNormLevel(), pNewsServer->GetBlockTime() && pNewsServer->GetBlockTime() + m_iRetryInterval > tCurTime ? pNewsServer->GetBlockTime() + m_iRetryInterval - tCurTime : 0); } info(" Levels: %i", m_Levels.size()); int index = 0; for (Levels::iterator it = m_Levels.begin(); it != m_Levels.end(); it++, index++) { int iSize = *it; info(" %i: Free connections=%i", index, iSize); } info(" Connections: %i", m_Connections.size()); for (Connections::iterator it = m_Connections.begin(); it != m_Connections.end(); it++) { PooledConnection* pConnection = *it; info(" %i) %s (%s): Level=%i, NormLevel=%i, InUse:%i", pConnection->GetNewsServer()->GetID(), pConnection->GetNewsServer()->GetName(), pConnection->GetNewsServer()->GetHost(), pConnection->GetNewsServer()->GetLevel(), pConnection->GetNewsServer()->GetNormLevel(), (int)pConnection->GetInUse()); } m_mutexConnections.Unlock(); }
//查找连接池中所有的连接,查找一个可用的数据库连接 sql::Connection * MySQLConnectionPool::findFreeConnection() { sql::Connection * conn = NULL; PooledConnection *pConn = NULL; // 获得连接池向量中所有的对象 for(int i = 0 ;i<connections.size(); i++) { pConn = connections.at(i); if (!pConn->isBusy()) { // 如果此对象不忙,则获得它的数据库连接并把它设为忙 conn = pConn->getConnection(); // 测试此连接是否可用 if (!testConnection(conn)) { // 如果此连接不可再用了,则创建一个新的连接, // 并替换此不可用的连接对象,如果创建失败,返回 null try { conn = newConnection(); } catch(...) { return NULL; } if (conn) { pConn->setConnection(conn); pConn->setBusy(true); } else { return NULL; } } else { pConn->setBusy(true); } break; // 己经找到一个可用的连接,退出 } } //mysql_query( mysql, "SET NAMES" gbk"" ); return conn;// 返回找到到的可用连接 }
void ServerPool::CloseUnusedConnections() { m_mutexConnections.Lock(); time_t curtime = ::time(NULL); for (Connections::iterator it = m_Connections.begin(); it != m_Connections.end(); it++) { PooledConnection* pConnection = *it; if (!pConnection->GetInUse() && pConnection->GetStatus() == Connection::csConnected) { int tdiff = (int)(curtime - pConnection->GetFreeTime()); if (tdiff > CONNECTION_HOLD_SECODNS) { debug("Closing unused connection to %s", pConnection->GetHost()); pConnection->Disconnect(); } } } m_mutexConnections.Unlock(); }
void ServerPool::CloseUnusedConnections() { m_mutexConnections.Lock(); time_t curtime = ::time(NULL); // close and free all connections of servers which were disabled since the last check int i = 0; for (Connections::iterator it = m_Connections.begin(); it != m_Connections.end(); ) { PooledConnection* pConnection = *it; bool bDeleted = false; if (!pConnection->GetInUse() && (pConnection->GetNewsServer()->GetNormLevel() == -1 || !pConnection->GetNewsServer()->GetActive())) { debug("Closing (and deleting) unused connection to server%i", pConnection->GetNewsServer()->GetID()); if (pConnection->GetStatus() == Connection::csConnected) { pConnection->Disconnect(); } delete pConnection; m_Connections.erase(it); it = m_Connections.begin() + i; bDeleted = true; } if (!bDeleted) { it++; i++; } } // close all opened connections on levels not having any in-use connections for (int iLevel = 0; iLevel <= m_iMaxNormLevel; iLevel++) { // check if we have in-use connections on the level bool bHasInUseConnections = false; int iInactiveTime = 0; for (Connections::iterator it = m_Connections.begin(); it != m_Connections.end(); it++) { PooledConnection* pConnection = *it; if (pConnection->GetNewsServer()->GetNormLevel() == iLevel) { if (pConnection->GetInUse()) { bHasInUseConnections = true; break; } else { int tdiff = (int)(curtime - pConnection->GetFreeTime()); if (tdiff > iInactiveTime) { iInactiveTime = tdiff; } } } } // if there are no in-use connections on the level and the hold time out has // expired - close all connections of the level. if (!bHasInUseConnections && iInactiveTime > CONNECTION_HOLD_SECODNS) { for (Connections::iterator it = m_Connections.begin(); it != m_Connections.end(); it++) { PooledConnection* pConnection = *it; if (pConnection->GetNewsServer()->GetNormLevel() == iLevel && pConnection->GetStatus() == Connection::csConnected) { debug("Closing (and keeping) unused connection to server%i", pConnection->GetNewsServer()->GetID()); pConnection->Disconnect(); } } } } m_mutexConnections.Unlock(); }
NNTPConnection* ServerPool::GetConnection(int iLevel, NewsServer* pWantServer, Servers* pIgnoreServers) { PooledConnection* pConnection = NULL; m_mutexConnections.Lock(); time_t tCurTime = time(NULL); if (iLevel < (int)m_Levels.size() && m_Levels[iLevel] > 0) { Connections candidates; candidates.reserve(m_Connections.size()); for (Connections::iterator it = m_Connections.begin(); it != m_Connections.end(); it++) { PooledConnection* pCandidateConnection = *it; NewsServer* pCandidateServer = pCandidateConnection->GetNewsServer(); if (!pCandidateConnection->GetInUse() && pCandidateServer->GetActive() && pCandidateServer->GetNormLevel() == iLevel && (!pWantServer || pCandidateServer == pWantServer || (pWantServer->GetGroup() > 0 && pWantServer->GetGroup() == pCandidateServer->GetGroup())) && (pCandidateConnection->GetStatus() == Connection::csConnected || !pCandidateServer->GetBlockTime() || pCandidateServer->GetBlockTime() + m_iRetryInterval <= tCurTime || pCandidateServer->GetBlockTime() > tCurTime)) { // free connection found, check if it's not from the server which should be ignored bool bUseConnection = true; if (pIgnoreServers && !pWantServer) { for (Servers::iterator it = pIgnoreServers->begin(); it != pIgnoreServers->end(); it++) { NewsServer* pIgnoreServer = *it; if (pIgnoreServer == pCandidateServer || (pIgnoreServer->GetGroup() > 0 && pIgnoreServer->GetGroup() == pCandidateServer->GetGroup() && pIgnoreServer->GetNormLevel() == pCandidateServer->GetNormLevel())) { bUseConnection = false; break; } } } pCandidateServer->SetBlockTime(0); if (bUseConnection) { candidates.push_back(pCandidateConnection); } } } if (!candidates.empty()) { // Peeking a random free connection. This is better than taking the first // available connection because provides better distribution across news servers, // especially when one of servers becomes unavailable or doesn't have requested articles. int iRandomIndex = rand() % candidates.size(); pConnection = candidates[iRandomIndex]; pConnection->SetInUse(true); } if (pConnection) { m_Levels[iLevel]--; } } m_mutexConnections.Unlock(); return pConnection; }
void BloomfilterConnectionPool::closeConnectionPool() { #if 0 pthread_mutex_lock(&mutex_closepool); if (isClosing == 1) { while (isClosing == 1) { pthread_mutex_unlock(&mutex_closepool); //sleep(5); pthread_mutex_lock(&mutex_closepool); } pthread_mutex_unlock(&mutex_closepool); return; } isClosing = 1; pthread_mutex_unlock(&mutex_closepool); #endif pthread_mutex_lock(&mutex_connectionpool); if (connections.empty()) { pthread_mutex_unlock(&mutex_connectionpool); #if 0 pthread_mutex_lock(&mutex_closepool); isClosing = 0; pthread_mutex_unlock(&mutex_closepool); #endif return; } PooledConnection* pConn = NULL; int ret = connections.size(); for (int i = 0; i < connections.size(); i++) { pConn = connections.at(i); #if 0 while (pConn->isBusy()) { // 等50秒时间有点长,是为了防止dump时,阻塞了client的请求。找时间优化一下对这个地方的处理。 //wait(5); } #endif //delete pConn->getConnection(); if (!pConn->isBusy()) { delete pConn->getConnection(); delete pConn; } else { delete pConn; } // connections.erase(connections.begin()+i); } connections.clear(); pthread_mutex_unlock(&mutex_connectionpool); //printf("close executed unlock\n"); #if 0 pthread_mutex_lock(&mutex_closepool); isClosing = 0; pthread_mutex_unlock(&mutex_closepool); #endif }