Date: Wednesday, February 28, 2007 @ 10:53:27
Author: gilles
Path: /cvsroot/carob/carob
Modified: include/ControllerPool.hpp (1.14 -> 1.15) src/ControllerPool.cpp
(1.22 -> 1.23)
Now keeping controller pools 10seconds before deleting them
Cleaned-up remaining debug code
Fixes CAROB-132
----------------------------+
include/ControllerPool.hpp | 19 +++++++++--
src/ControllerPool.cpp | 70 +++++++++++++++++++++++++++++++------------
2 files changed, 67 insertions(+), 22 deletions(-)
Index: carob/include/ControllerPool.hpp
diff -u carob/include/ControllerPool.hpp:1.14
carob/include/ControllerPool.hpp:1.15
--- carob/include/ControllerPool.hpp:1.14 Thu Feb 8 12:28:12 2007
+++ carob/include/ControllerPool.hpp Wed Feb 28 10:53:27 2007
@@ -211,7 +211,11 @@
* Tells the pool that one of its 'user' (ie. connection) doesn't use it
* anymore, and return the new number of references
*/
- int removeRef() { ref_counter--; return ref_counter;
}
+ int removeRef();
+ /** Retrieves the number of references left on this instance */
+ int getRefCount() { return ref_counter; }
+ /** Returns the last time the number of references was decreased to zero */
+ int64_t getLastTimeZeroRef() { return
last_time_zero_ref; }
/** Up-to-date list of controllers that respond to pings */
std::vector<ControllerAndVdbState> alive_controllers;
/** Mutex on alive controllers */
@@ -221,15 +225,16 @@
AbstractControllerPool();
AbstractControllerPool(AbstractControllerPool&);
AbstractControllerPool& operator=(AbstractControllerPool&);
-
/** Controller watcher thread */
ControllerWatcher* watcher_ptr;
/** Associated pthread */
pthread_t watcher_thread;
/** Callback for controller failures and come backs */
SocketKillerCallback* callback_ptr;
- /** references counter managed by controller pool manager */
+ /** References counter managed by controller pool manager */
int ref_counter;
+ /** Last time this instance saw its ref_counter decreased to zero */
+ int64_t last_time_zero_ref;
};
/**
@@ -293,6 +298,8 @@
bool operator()(const PoolIndex& pi1, const PoolIndex& pi2) const;
};
+/** Number of milliseconds to wait before deleting a pool that is not used */
+#define POOL_TIMEOUT_IN_MS 10000 /* 10s */
/**
* Holds a list of controller pools, that are indexed by their policy and list
* of controllers. Permits to have only one instance of ControllerPool for the
@@ -329,6 +336,12 @@
*/
static void freePool(AbstractControllerPool* pool);
protected:
+ /**
+ * Walks through the pool map to look for pools that can be deleted, ie.
+ * a pool that is not used anymore and that been freed at least
POOL_TIMEOUTms
+ * ago
+ */
+ static void tryTocleanUpPools();
private:
/** To manage pool map concurrent accesses */
static CriticalSection pool_map_CS;
Index: carob/src/ControllerPool.cpp
diff -u carob/src/ControllerPool.cpp:1.22 carob/src/ControllerPool.cpp:1.23
--- carob/src/ControllerPool.cpp:1.22 Mon Feb 26 18:28:23 2007
+++ carob/src/ControllerPool.cpp Wed Feb 28 10:53:27 2007
@@ -173,6 +173,14 @@
return sRet;
}
+int AbstractControllerPool::removeRef()
+{
+ ref_counter--;
+ if (ref_counter < 1)
+ last_time_zero_ref = currentTimeMillis();
+ return ref_counter;
+}
+
////////////////////////////////////////////////////////////////////////////////
// ROUND ROBIN POLICY
////////////////////////////////////////////////////////////////////////////////
@@ -184,21 +192,12 @@
index(-1)
{
}
-#include <iostream>
-using namespace std;
+
ControllerInfo RoundRobinControllerPool::getController()
throw (NoMoreControllerException, UnexpectedException)
{
const wchar_t fctName[] = L"RoundRobinControllerPool::getController";
LockScope ls(&pool_CS);
-/* if (alive_controllers.empty())
- throw NoMoreControllerException(L"All controllers down");
- index = (index + 1) % alive_controllers.size();
- if (isDebugEnabled())
- logDebug(fctName, L"Selected controller[" + toUserString(index) + L"]:"
- + static_cast<wstring>(alive_controllers[index]));
- return alive_controllers[index].controller;
-*/
int nbOfControllers = alive_controllers.size();
if (nbOfControllers == 0)
throw NoMoreControllerException(L"All controllers down");
@@ -224,7 +223,6 @@
if (index >= nbOfControllers)
index = 0;
nbTested++;
-cout<<"index = "<<index<<endl;
ctrl = alive_controllers[index];
}
// all controllers tested, no more available
@@ -298,6 +296,7 @@
logDebug(fctName, L"Reusing pool \""
+ static_cast<wstring>(*(pool->second)) + L"\"");
pool->second->addRef();
+ tryTocleanUpPools();
return *(pool->second);
}
// if the pool was not found, let's create a new one
@@ -308,16 +307,47 @@
new_pool = new RoundRobinControllerPool(ctrls, pingDelayInMs,
controllerTimeoutInMs);
break;
default:
+ tryTocleanUpPools();
throw DriverException(L"Unsupported connection policy #" +
toUserString(static_cast<int>(cp)));
}
new_pool->addRef();
pool_map[idx] = static_cast<AbstractControllerPool*>(new_pool);
if (isDebugEnabled())
logDebug(fctName, L"Creating new pool \"" +
static_cast<wstring>(*new_pool) + L"\"");
+ tryTocleanUpPools();
return *new_pool;
}
/*static*/
+void ControllerPoolManager::tryTocleanUpPools()
+{
+ const wchar_t fctName[] = L"ControllerPoolManager::tryTocleanUpPools";
+ LockScope ls(&pool_map_CS);
+ for (std::map<PoolIndex, AbstractControllerPool*, ltPoolIndex>::iterator iter
+ = pool_map.begin(); iter != pool_map.end();)
+ {
+ if (iter->second->getRefCount() == 0)
+ {
+ if ((currentTimeMillis() - POOL_TIMEOUT_IN_MS) >
iter->second->getLastTimeZeroRef())
+ {
+ std::map<PoolIndex, AbstractControllerPool*, ltPoolIndex>::iterator
toRemove = iter;
+ if (isInfoEnabled())
+ logInfo(fctName, L"Pool \"" + static_cast<wstring>(*toRemove->second)
+ + L"\" freed " +
toWString(static_cast<int64_t>(currentTimeMillis()-toRemove->second->getLastTimeZeroRef()))
+ + L"ms ago - Deleting it");
+ iter++;
+ delete toRemove->second;
+ pool_map.erase(toRemove);
+ }
+ else
+ iter++;
+ }
+ else
+ iter++;
+ }
+}
+
+/*static*/
void ControllerPoolManager::freePool(AbstractControllerPool* pool)
{
const wchar_t fctName[] = L"ControllerPoolManager::freePool";
@@ -328,24 +358,24 @@
return;
}
LockScope ls(&pool_map_CS);
- for (std::map<PoolIndex, AbstractControllerPool*, ltPoolIndex>::iterator iter
- = pool_map.begin(); iter != pool_map.end(); iter++)
+ std::map<PoolIndex, AbstractControllerPool*, ltPoolIndex>::iterator iter =
pool_map.begin();
+ while (iter != pool_map.end())
{
if (iter->second == pool)
{
- if (pool->removeRef() == 0)
+ if (iter->second->removeRef() == 0)
{
if (isDebugEnabled())
logDebug(fctName, L"No more references to pool \""
- + static_cast<wstring>(*pool) + L"\" - deleting it");
- pool_map.erase(iter); // don't mind about iter, we won't use it anymore
- delete pool;
+ + static_cast<wstring>(*iter->second) + L"\" - keeping it at
least "
+ + toWString(POOL_TIMEOUT_IN_MS) + L" ms");
}
- return;
+ break; // pool found, stop search
}
+ iter++;
}
// No match => log error and continue
- if (isErrorEnabled())
+ if (iter == pool_map.end() && isErrorEnabled())
{
wstring msg(L"Pool " + static_cast<wstring>(*pool)
+ L" not found in pool map! Map contains ");
@@ -356,4 +386,6 @@
}
logError(fctName, msg);
}
+ // look for pools to delete
+ tryTocleanUpPools();
}
_______________________________________________
Carob-commits mailing list
[email protected]
https://forge.continuent.org/mailman/listinfo/carob-commits