Date: Monday, December 11, 2006 @ 19:14:45
Author: gilles
Path: /cvsroot/carob/carob
Modified: include/Connection.hpp (1.75 -> 1.76) include/ControllerPool.hpp
(1.9 -> 1.10) include/ControllerStateChangedCallback.hpp (1.3 ->
1.4) src/Connection.cpp (1.98 -> 1.99) src/ControllerInfo.cpp
(1.5 -> 1.6) src/ControllerPool.cpp (1.14 -> 1.15)
src/ControllerStateChangedCallback.cpp (1.4 -> 1.5)
Put getController() and connect() together inside a ControllerPool-locked block
to avoid concurrent
controller add or delete during connection initConnection is now called
initConnectionToNextController
and holds this synchronized block
Fixed leak when ControllerInfo::connect() fails: the socket pointer was not
deleted. Had to create a
'unregister socket' function in controller pool and callback to avoid double
destructions
--------------------------------------------+
include/Connection.hpp | 12 +++++---
include/ControllerPool.hpp | 17 +++++++++++-
include/ControllerStateChangedCallback.hpp | 7 ++++-
src/Connection.cpp | 37 ++++++++++++++-------------
src/ControllerInfo.cpp | 17 ++++++++++--
src/ControllerPool.cpp | 7 +++++
src/ControllerStateChangedCallback.cpp | 21 +++++++++++++++
7 files changed, 92 insertions(+), 26 deletions(-)
Index: carob/include/Connection.hpp
diff -u carob/include/Connection.hpp:1.75 carob/include/Connection.hpp:1.76
--- carob/include/Connection.hpp:1.75 Thu Nov 30 17:47:49 2006
+++ carob/include/Connection.hpp Mon Dec 11 19:14:45 2006
@@ -147,7 +147,8 @@
* Creates a new connection and connects to a controller with the given
* parameters
* @param prms controller, base, user, etc. to use for connecting
- * @throw DriverException if the ConnectPolicy given in parameters is unknown
+ * @throw DriverException if the ConnectPolicy given in connection parameters
+ * is unknown or if the ConnectPolicy could not be created
* @throw ConnectionException if the requested controller could not be
* reached
* @throw AuthenticationException if a login error occured, or if an
@@ -373,20 +374,21 @@
protected:
/**
- * Starts a connection by sending all connection/authentication informations.
+ * Starts a connection by retrieving a new controller to connect to from the
+ * pool and sends all connection/authentication informations to it.
* Warning: this function only sends the connection infos, but there is no
* guaranty that we are connected afterwards. [EMAIL PROTECTED]
#finalizeConnect()} will
* do the job of checking and finishing connection establishment.
* @return true if the connection initialization succeeds
- * @throw DriverException if the connect policy is NULL
+ * @throw NoMoreControllerException if there is no alive controller left
* @throw ConnectionException if the requested controller could not be
* reached
* @throw AuthenticationException if a login error occured, or if an
* IO exception occured during authentication (premature close of
* connection)
*/
- void initConnection()
- throw (DriverException, ConnectionException,
+ void initConnectionToNextController()
+ throw (NoMoreControllerException,
ConnectionException,
AuthenticationException, UnexpectedException);
/**
* Reads the controller acknowledgements and misc parameters that finish
Index: carob/include/ControllerPool.hpp
diff -u carob/include/ControllerPool.hpp:1.9
carob/include/ControllerPool.hpp:1.10
--- carob/include/ControllerPool.hpp:1.9 Fri Dec 8 16:07:10 2006
+++ carob/include/ControllerPool.hpp Mon Dec 11 19:14:45 2006
@@ -24,7 +24,6 @@
#include "ControllerInfo.hpp"
#include "CarobException.hpp"
#include "CriticalSection.hpp"
-
#include <vector>
#include <map>
@@ -98,6 +97,16 @@
JavaSocket* socket);
/**
+ * Unregisters the given socket from the callback so it can no more be killed
+ * or deleted. To be used when socket creation or connection failed
+ *
+ * @param controller the controller to which the socket is connected
+ * @param socketFd the socket file descriptor to unregister
+ */
+ void unRegisterSocket(const ControllerInfo&
controller,
+ JavaSocket* socket);
+
+ /**
* Tell the watcher that a failure has been detected on the given
controller.<br>
* This function should be called when a connection error occurs on the given
* controller
@@ -125,6 +134,12 @@
void controllerUp(const ControllerInfo& controller);
/**
+ * Gets a reference to the lock object used in this class
+ * @see void Connection::initConnection()
+ */
+ CriticalSection& getLock() { return pool_CS; }
+
+ /**
* Display useful info in a string
*/
operator std::wstring();
Index: carob/include/ControllerStateChangedCallback.hpp
diff -u carob/include/ControllerStateChangedCallback.hpp:1.3
carob/include/ControllerStateChangedCallback.hpp:1.4
--- carob/include/ControllerStateChangedCallback.hpp:1.3 Mon Dec 4
15:13:48 2006
+++ carob/include/ControllerStateChangedCallback.hpp Mon Dec 11 19:14:45 2006
@@ -83,7 +83,12 @@
void onControllerUp(const ControllerInfo& ctrl);
/** Adds the given socket to the list of monitored sockets for given
controller */
void registerSocket(const ControllerInfo& ctrl, JavaSocket* socketFd);
-
+ /**
+ * Removes the given socket from the list of monitored sockets for a given
+ * controller. This function should be called when socket creation or
+ * connection failed
+ */
+ void unRegisterSocket(const ControllerInfo& ctrl, JavaSocket* socketFd);
private:
/** The list of controllers with their set of sockets */
std::map<ControllerInfo, std::vector<JavaSocket*> > controllers_and_sockets;
Index: carob/src/Connection.cpp
diff -u carob/src/Connection.cpp:1.98 carob/src/Connection.cpp:1.99
--- carob/src/Connection.cpp:1.98 Fri Dec 8 18:02:08 2006
+++ carob/src/Connection.cpp Mon Dec 11 19:14:45 2006
@@ -92,10 +92,8 @@
{
try
{
- connected_controller = controller_pool.getController();
-
// Do the authentication stuff
- initConnection();
+ initConnectionToNextController();
// receive ack and other params
finalizeConnect();
isClosed = false;
@@ -114,8 +112,6 @@
{
//Do some clean up
delete driverSocketPtr; driverSocketPtr = NULL;
- //suspect failing controller and try next one
- controller_pool.forceControllerDown(connected_controller);
}
catch (NoMoreControllerException& nmce)
{
@@ -155,23 +151,29 @@
socket<<static_cast<int32_t>(command);
}
-void Connection::initConnection()
- throw (DriverException, ConnectionException, AuthenticationException,
- UnexpectedException)
+void Connection::initConnectionToNextController()
+ throw (NoMoreControllerException, ConnectionException,
+ AuthenticationException, UnexpectedException)
{
- wstring fctName(L"Connection::initConnection");
+ wstring fctName(L"Connection::initConnectionToNextController");
bool protocolVersionSend = false,
dbNameSend = false,
userNameSend = false,
userPassSend = false;
- if (isInfoEnabled())
- logInfo(fctName, L"Authenticating with controller "
- + static_cast<wstring>(connected_controller));
try
{
- //Here is the connection protocol...
- // 1. connect to the controller
- driverSocketPtr = connected_controller.connect(controller_pool);
+ // This must lock the pool synchro to avoid controller list operations
+ // between getController() and connect() calls
+ {
+ LockScope(&controller_pool.getLock());
+ connected_controller = controller_pool.getController();
+ if (isInfoEnabled())
+ logInfo(fctName, L"Authenticating with controller "
+ + static_cast<wstring>(connected_controller));
+ //Here is the connection protocol...
+ // 1. connect to the controller
+ driverSocketPtr = connected_controller.connect(controller_pool);
+ }
// 2. sent the Protocol version information
*driverSocketPtr<<ProtocolVersion;
protocolVersionSend = true;
@@ -191,6 +193,8 @@
+ L" (" + connExcpt.description() + L").";
if (isErrorEnabled())
logError(fctName, msg);
+ //suspect failing controller
+ controller_pool.forceControllerDown(connected_controller);
throw ConnectionException(msg);
}
catch (SocketIOException sockIOExcpt)
@@ -1260,8 +1264,7 @@
{
if (isDebugEnabled())
logDebug(fctName, L"Getting a new controller from the list...");
- connected_controller = controller_pool.getController();
- initConnection();
+ initConnectionToNextController();
finalizeConnect();
if (isInfoEnabled())
logInfo(fctName, L"Connection succeded");
Index: carob/src/ControllerInfo.cpp
diff -u carob/src/ControllerInfo.cpp:1.5 carob/src/ControllerInfo.cpp:1.6
--- carob/src/ControllerInfo.cpp:1.5 Mon Dec 4 15:13:48 2006
+++ carob/src/ControllerInfo.cpp Mon Dec 11 19:14:45 2006
@@ -210,10 +210,19 @@
if (isWarnEnabled())
logWarn(fctName, L"IP v6 host detected. This feature is untested");
}
- socketPtr->create(family);
+ try
+ {
+ socketPtr->create(family);
+ }
+ catch (ConnectionException ce)
+ {
+ delete socketPtr;
+ freeaddrinfo(addr);
+ throw;
+ }
// register the socket to our policy so it can be killed during connection
pool.registerSocket(*this, socketPtr);
-
+
if (isDebugEnabled())
logDebug(fctName, L"Connecting...");
// if we got multiple addresses, we will try to connect to all of these (in
@@ -236,6 +245,8 @@
}
catch (ConnectionException ce)
{
+ pool.unRegisterSocket(*this, socketPtr);
+ delete socketPtr;
freeaddrinfo(addr);
throw ce;
}
@@ -244,6 +255,8 @@
addrIter = addrIter->ai_next;
}
// could not connect to any of the addresses
+ pool.unRegisterSocket(*this, socketPtr);
+ delete socketPtr;
freeaddrinfo(addr);
throw ConnectionException(L"Unable to connect. Last error code was "
+ toUserString(errno));
Index: carob/src/ControllerPool.cpp
diff -u carob/src/ControllerPool.cpp:1.14 carob/src/ControllerPool.cpp:1.15
--- carob/src/ControllerPool.cpp:1.14 Fri Dec 8 16:07:10 2006
+++ carob/src/ControllerPool.cpp Mon Dec 11 19:14:45 2006
@@ -92,6 +92,13 @@
callback_ptr->registerSocket(controller, socket);
}
+void AbstractControllerPool::unRegisterSocket(const ControllerInfo& controller,
+ JavaSocket* socket)
+{
+ LockScope ls(&pool_CS);
+ callback_ptr->unRegisterSocket(controller, socket);
+}
+
void AbstractControllerPool::forceControllerDown(const ControllerInfo&
controller)
{
LockScope ls(&pool_CS);
Index: carob/src/ControllerStateChangedCallback.cpp
diff -u carob/src/ControllerStateChangedCallback.cpp:1.4
carob/src/ControllerStateChangedCallback.cpp:1.5
--- carob/src/ControllerStateChangedCallback.cpp:1.4 Mon Dec 4 15:13:48 2006
+++ carob/src/ControllerStateChangedCallback.cpp Mon Dec 11 19:14:45 2006
@@ -62,6 +62,27 @@
controllers_and_sockets[ctrl] = sockets;
}
+void SocketKillerCallback::unRegisterSocket(const ControllerInfo& ctrl,
+ JavaSocket* s)
+{
+ LockScope ls(&controllers_and_sockets_CS);
+ map<ControllerInfo, vector<JavaSocket*> >::iterator ctrlIter =
+ controllers_and_sockets.find(ctrl);
+ if (ctrlIter != controllers_and_sockets.end())
+ {
+ vector<JavaSocket*> sockets = ctrlIter->second;
+ vector<JavaSocket*>::iterator socketIter = sockets.begin();
+ while (socketIter != sockets.end())
+ {
+ if (*socketIter == s)
+ socketIter = sockets.erase(socketIter);
+ else
+ socketIter++;
+ }
+ controllers_and_sockets[ctrl] = sockets;
+ }
+}
+
void SocketKillerCallback::onControllerDown(const ControllerInfo& ctrl)
{
wstring fctName(L"SocketKillerCallback::OnControllerDown");
_______________________________________________
Carob-commits mailing list
[email protected]
https://forge.continuent.org/mailman/listinfo/carob-commits