|
|
Choosing A Webhost: |
CVS update of carob (4 files): msg#00088db.carob.cvs
Date: Friday, February 24, 2006 @ 12:56:41 Author: gilles Path: /cvsroot/carob/carob Modified: include/Connection.hpp (1.61 -> 1.62) src/Connection.cpp (1.69 -> 1.70) src/ControllerConnectPolicy.cpp (1.10 -> 1.11) test/10-Connection/TestConnect.cpp (1.4 -> 1.5) Connection: - Changed Connection constructor behavior: now connects to other controllers in the connection policy list in case of failure + fixed exceptions thrown - Extracted closeSocket() new function from close (for reconnection to be able to close only the socket) - Added reconnectOrDie() function that tries reconnection on all non suspect controllers - Changed reconnect() to take these two functions into account - Added ConnectionException to the functions that do reconnection - Removed setConnectionParametersOnRequest() call from reconnection loop (the connection doesn't change => do it once for all) - Fixed FO_TRY_NTIMES macro to be more readable - Added logging ControllerConnectPolicy: - Added forgotten call to updateSuspectList() ! - Added logging for ping socket creation TestConnect: - Connection change took into account (authentication exception instead of connection exception) ------------------------------------+ include/Connection.hpp | 54 +++++-- src/Connection.cpp | 250 ++++++++++++++++++++++------------- src/ControllerConnectPolicy.cpp | 5 test/10-Connection/TestConnect.cpp | 4 4 files changed, 208 insertions(+), 105 deletions(-) Index: carob/include/Connection.hpp diff -u carob/include/Connection.hpp:1.61 carob/include/Connection.hpp:1.62 --- carob/include/Connection.hpp:1.61 Fri Feb 17 17:15:45 2006 +++ carob/include/Connection.hpp Fri Feb 24 12:56:41 2006 @@ -171,7 +171,7 @@ void setAutoCommit(bool autoCommit) throw (SocketIOException, BackendException, ControllerException, ProtocolException, - UnexpectedException); + ConnectionException, UnexpectedException); /** * Makes all changes made since the previous commit/rollback permanent and * releases any database locks currently held by the <code>Connection</code>. @@ -183,7 +183,8 @@ * @see Connection#setAutoCommit(boolean) */ void commit() throw (SocketIOException, DriverException, - ProtocolException, UnexpectedException); + ProtocolException, ConnectionException, + UnexpectedException); /** * Drops all changes made since the previous commit/rollback and releases any * database locks currently held by this connection. If the connection was in @@ -193,7 +194,8 @@ * @see Connection#commit() */ void rollback() throw (SocketIOException, DriverException, - ProtocolException, UnexpectedException); + ProtocolException, ConnectionException, + UnexpectedException); /** * SQL statements without parameters are normally executed using * <code>Statement</code> objects. If the same SQL statement is executed @@ -232,7 +234,8 @@ DriverResultSet* statementExecuteQuery(RequestWithResultSetParameters& request) throw (SocketIOException, BackendException, ControllerException, ProtocolException, - NotImplementedException, UnexpectedException); + NotImplementedException, ConnectionException, + UnexpectedException); /** * Performs a write request and return the number of rows affected. * @@ -243,7 +246,7 @@ int statementExecuteUpdate(Request& r) throw (SocketIOException, BackendException, ControllerException, ProtocolException, - UnexpectedException); + ConnectionException, UnexpectedException); /** * Calls a request that returns a list of results. * This list is returned as a copy (ie. not a pointer) because it contains @@ -258,7 +261,8 @@ RequestWithResultSetParameters& request) throw (SocketIOException, BackendException, ControllerException, - ProtocolException, UnexpectedException); + ProtocolException, ConnectionException, + UnexpectedException); /** * Performs a write request and returns the auto-generated keys * @@ -273,7 +277,8 @@ Request &request) throw (SocketIOException, BackendException,ControllerException, - ProtocolException, UnexpectedException); + ProtocolException, ConnectionException, + UnexpectedException); /** * Closes the remote ResultSet given its cursor name. * @@ -326,7 +331,8 @@ DriverResultSet* preparedStatementGetMetaData(const std::wstring &sqlTemplate) throw (SocketIOException, BackendException, ProtocolException, ControllerException, - NotImplementedException, UnexpectedException); + NotImplementedException, ConnectionException, + UnexpectedException); protected: /** @@ -360,14 +366,20 @@ AuthenticationException, UnexpectedException); /** - * Closes a connection by sending appropriate commands to the controller. + * Deletes all statements created by this connection and closes the socket + * to the connected controller. * If an error occurs while closing, just logs the error and returns false, * but does not throw any exception. - * Called mainly by the connection destructor. * @return true if the connection has been closed without errors */ bool close(); - + /** + * Closes the socket by sending appropriate commands to the controller. + * If an error occurs while closing, just logs the error and returns false, + * but does not throw any exception. + * @return true if the connection has been closed without errors + */ + bool closeSocket(); /** * Serializes a write request on the output stream by sending only the needed * parameters to reconstruct it on the controller @@ -437,7 +449,8 @@ */ void beginTransactionIfNeeded() throw (SocketIOException, BackendException, ControllerException, - ProtocolException, UnexpectedException); + ProtocolException, ConnectionException, + UnexpectedException); /** * Set the autocommit mode and read-only status on this request. @@ -592,10 +605,23 @@ * controller chosen using the policy specified in the connection parameters * of this connection. * + * @throw ConnectionException if the next controller (get from connection + * policy) is also down * @throw NoMoreControllerException if no valid controller left - * @throw DriverException if an other error occured + * @throw DriverException if controllers are misconfigurated + */ + void tryToReconnect() throw (NoMoreControllerException, + DriverException, UnexpectedException); + /** + * Calls reconnect until : + * - success + * - NoMoreControllerException + * - Other unrecoverable error + * + * @throw ConnectionException if no valid controller is left + * @throw DriverException if controllers are misconfigurated */ - void reconnect() throw (NoMoreControllerException, + void reconnectOrDie() throw (ConnectionException, DriverException, UnexpectedException); /** * Forbids Connection creation that would lead to unexpected state. Index: carob/src/Connection.cpp diff -u carob/src/Connection.cpp:1.69 carob/src/Connection.cpp:1.70 --- carob/src/Connection.cpp:1.69 Tue Feb 21 17:51:43 2006 +++ carob/src/Connection.cpp Fri Feb 24 12:56:41 2006 @@ -42,25 +42,22 @@ // When a SocketIOException occurs between these to macros, sleep and try to // reconnect(). Sleeping time depends on the retry #. Only N retries are // performed -#define FO_TRY_NTIMES(N) for (int foCnt=0; foCnt<N; foCnt++) { try { -#define FO_CATCH_NTIMES break; /* if no exception, get out of the for */\ -} catch (SocketIOException sioe) { ::sleep(static_cast<int>(foCnt*0.5)); reconnect(); } } - -/* This gives: -for (int foCnt=0; foCnt<N; foCnt++) -{ - try - { - ***CODE*** - break; // if no exception, get out of the for - } - catch (SocketIOException sioe) - { - ::sleep(foCnt*0.5); // 0s the 1st and 2nd time, 1s the 3rd and 4th... - reconnect(); - } +#define FO_TRY_NTIMES(N)\ +for (int foCnt=0; foCnt<N; foCnt++)\ +{\ + try\ + {\ + /* Code to monitor will go here */ +#define FO_CATCH_NTIMES\ + break; /* if no exception, get out of the for */\ + }\ + catch (SocketIOException sioe)\ + {\ + ::sleep(static_cast<int>(foCnt*0.5)); /* sleep incrementally */\ + reconnectOrDie();\ + }\ } -*/ + Connection::Connection(const ConnectionParameters& prms) throw (DriverException, ConnectionException, AuthenticationException, UnexpectedException) : @@ -85,25 +82,52 @@ throw DriverException(L"Unsupported connection policy #" + toWString(parameters.getConnectPolicy())); } persistent_connection = parameters.getPersistentConnection(); - try + while (isClosed) { - if (connect_policy_ptr == NULL) - throw DriverException(L"Connection policy error. Aborting."); - connected_controller = connect_policy_ptr->getController(); - - //Do the authentication stuff, then receive ack and other params - if (initConnection() && finalizeConnect()) + try { - isClosed = false; + if (connect_policy_ptr == NULL) + throw DriverException(L"Connection policy error. Aborting."); + connected_controller = connect_policy_ptr->getController(); + + //Do the authentication stuff, then receive ack and other params + if (initConnection() && finalizeConnect()) + { + isClosed = false; + } + } + // SocketIO and connection exceptions indicate dead controller => try to + // connect to the next one in the controller list + catch (SocketIOException sioe) + { + //Do some clean up + delete driverSocketPtr; driverSocketPtr = NULL; + //suspect failing controller and try next one + connect_policy_ptr->suspectControllerOfFailure(connected_controller); + } + catch (ConnectionException ce) + { + //Do some clean up + delete driverSocketPtr; driverSocketPtr = NULL; + //suspect failing controller and try next one + connect_policy_ptr->suspectControllerOfFailure(connected_controller); + } + catch (NoMoreControllerException nmce) + { + // Clean all: we are in constructor, destructor won't be called ! + delete driverSocketPtr; driverSocketPtr = NULL; + delete connect_policy_ptr; connect_policy_ptr = NULL; + // + throw (ConnectionException(nmce.description())); + } + // Other exceptions must be reported to the user + catch (...) + { + // Clean all: we are in constructor, destructor won't be called ! + delete driverSocketPtr; driverSocketPtr = NULL; + delete connect_policy_ptr; connect_policy_ptr = NULL; + throw; } - } - catch (...) - { - //Do some clean up: we are in constructor so if we throw an exception, the - //destructor will never be called... - delete driverSocketPtr; driverSocketPtr = NULL; - delete connect_policy_ptr; connect_policy_ptr = NULL; - throw; } } @@ -304,12 +328,15 @@ bool Connection::close() { - wstring fctName(L"Connection::closeConnection"); + wstring fctName(L"Connection::close"); //Wait until other methods/Commands are done LockScope ls(&connectionCS); isClosed = true; + + if (isDebugEnabled()) + logDebug(fctName, L"Deleting statements created by this connection"); //delete all statement created by this connection for (std::list<Statement*>::iterator iter = created_statements.begin(); iter != created_statements.end(); iter++) @@ -318,13 +345,21 @@ } created_statements.clear(); + return closeSocket(); +} + +bool Connection::closeSocket() +{ + wstring fctName(L"Connection::closeSocket"); + bool closeOK = false; + if (driverSocketPtr == NULL) { return false; } - bool closeOK = false; + if (isDebugEnabled()) - logDebug(fctName, L"Closing connection"); + logDebug(fctName, L"Closing socket to controller"); try { // Try to cleanly close the connection (also on controller side) @@ -334,7 +369,7 @@ catch (...) { if (isWarnEnabled()) - logWarn(fctName, L"Could not warn controller we are closing connection"); + logWarn(fctName, L"Could not inform controller we are closing connection"); } try { @@ -356,7 +391,7 @@ void Connection::setAutoCommit(bool autoCommitPrm) throw (SocketIOException, BackendException, ControllerException, - ProtocolException, UnexpectedException) + ProtocolException, ConnectionException, UnexpectedException) { wstring fctName(L"Connection::setAutoCommit"); @@ -408,7 +443,8 @@ } void Connection::beginTransactionIfNeeded() throw (SocketIOException, -BackendException, ControllerException, ProtocolException, UnexpectedException) + BackendException, ControllerException, ProtocolException, + ConnectionException, UnexpectedException) { if (mustBeginTransaction) { @@ -431,7 +467,7 @@ } void Connection::commit() throw (SocketIOException, DriverException, - ProtocolException, UnexpectedException) + ProtocolException, ConnectionException, UnexpectedException) { wstring fctName(L"Connection::commit"); @@ -464,7 +500,7 @@ } catch (SocketIOException e) { // Connection failed, try to reconnect and re-exec the commit - reconnect(); + reconnectOrDie(); int64_t acknowledgedTransactionId = retrieveCommitResult(); if (acknowledgedTransactionId != transactionId) { @@ -481,7 +517,7 @@ } void Connection::rollback() throw (SocketIOException, DriverException, - ProtocolException, UnexpectedException) + ProtocolException, ConnectionException, UnexpectedException) { wstring fctName(L"Connection::rollback"); @@ -515,7 +551,7 @@ } catch (SocketIOException e) { // Connection failed, try to reconnect and re-exec the rollback - reconnect(); + reconnectOrDie(); int64_t acknowledgedTransactionId = retrieveRollbackResult(); if (acknowledgedTransactionId != transactionId) { @@ -559,7 +595,8 @@ DriverResultSet* Connection::preparedStatementGetMetaData(const wstring &sqlTemplate) throw (SocketIOException, BackendException, ControllerException, - ProtocolException, NotImplementedException, UnexpectedException) + ProtocolException, NotImplementedException, ConnectionException, + UnexpectedException) { checkIfConnected(); wstring fctName(L"Connection::PreparedStatementGetMetaData"); @@ -588,7 +625,8 @@ DriverResultSet* Connection::statementExecuteQuery (RequestWithResultSetParameters& request) throw (SocketIOException, BackendException, ControllerException, - ProtocolException, NotImplementedException, UnexpectedException) + ProtocolException, NotImplementedException, ConnectionException, + UnexpectedException) { wstring fctName(L"Connection::statementExecuteQuery"); @@ -597,11 +635,11 @@ checkIfConnected(); beginTransactionIfNeeded(); + setConnectionParametersOnRequest(request); DriverResultSet* retVal = NULL; FO_TRY_NTIMES(RECONNECT_RETRIES) - setConnectionParametersOnRequest(request); if (isDebugEnabled()) logDebug(fctName, L"Sending read request " + static_cast<wstring>(request)); sendCommand(*driverSocketPtr, StatementExecuteQuery); @@ -614,7 +652,7 @@ int Connection::statementExecuteUpdate(Request& request) throw (SocketIOException, BackendException, ControllerException, - ProtocolException, UnexpectedException) + ProtocolException, ConnectionException, UnexpectedException) { wstring fctName(L"Connection::statementExecuteUpdate"); @@ -622,17 +660,18 @@ checkIfConnected(); beginTransactionIfNeeded(); + setConnectionParametersOnRequest(request); int controllerResponse = -1; FO_TRY_NTIMES(RECONNECT_RETRIES) - setConnectionParametersOnRequest(request); if (isDebugEnabled()) logDebug(fctName, L"Sending write request " + static_cast<wstring>(request)); sendCommand(*driverSocketPtr, StatementExecuteUpdate); writeRequestOnStream(request); request.setId(receiveLongOrException()); FO_CATCH_NTIMES + // At this point, the request id has been received, let's retrieve the // update count try @@ -652,26 +691,27 @@ std::list<ResultSetOrUpdateCount> Connection::statementExecute( RequestWithResultSetParameters& request) throw (SocketIOException, BackendException, ControllerException, ProtocolException, - UnexpectedException) + ConnectionException, UnexpectedException) { wstring fctName(L"Connection::statementExecute"); LockScope ls(&connectionCS); checkIfConnected(); beginTransactionIfNeeded(); + setConnectionParametersOnRequest(request); std::list<ResultSetOrUpdateCount> results; FO_TRY_NTIMES(RECONNECT_RETRIES) if (isDebugEnabled()) logDebug(fctName, L"Sending request " + static_cast<wstring>(request)); - setConnectionParametersOnRequest(request); if (!autoCommit) writeExecutedInTransaction = true; sendCommand(*driverSocketPtr, StatementExecute); request.sendToStream(*driverSocketPtr); request.setId(receiveLongOrException()); FO_CATCH_NTIMES + try { results = fetchMultipleResultsFromStream(); @@ -701,7 +741,8 @@ std::list<ResultSetOrUpdateCount> Connection::statementExecuteUpdateWithKeys( Request &request) throw (SocketIOException, BackendException, - ControllerException, ProtocolException, UnexpectedException) + ControllerException, ProtocolException, ConnectionException, + UnexpectedException) { wstring fctName(L"Connection::statementExecuteUpdateWithKeys"); @@ -709,13 +750,13 @@ checkIfConnected(); beginTransactionIfNeeded(); + setConnectionParametersOnRequest(request); std::list<ResultSetOrUpdateCount> result; for (int failuresCnt=0; failuresCnt<RECONNECT_RETRIES; failuresCnt++) { // this for is in the case we were disconnected and the controller did not // get the update request FO_TRY_NTIMES(RECONNECT_RETRIES) - setConnectionParametersOnRequest(request); if (isDebugEnabled()) logDebug(fctName, L"Executing write request with keys: " + static_cast<wstring>(request)); @@ -1040,15 +1081,49 @@ return results; } -void Connection::reconnect() throw (NoMoreControllerException, DriverException, - UnexpectedException) +void Connection::reconnectOrDie() throw (ConnectionException, + DriverException, UnexpectedException) { - wstring fctName(L"Connection::reconnect"); + wstring fctName(L"Connection::reconnectOrDie"); + bool reconnected = false; + while (!reconnected) + { + try + { + tryToReconnect(); + reconnected = true; + } + catch (ConnectionException ce) + { + if (isDebugEnabled()) + logDebug(fctName, L"Controller " + + static_cast<wstring>(connected_controller) + + L" seams to be down - giving it a last chance..."); + } + catch (NoMoreControllerException nmce) + { + throw (ConnectionException(nmce.description())); + } + // other exceptions are forwarded to caller... + } +} + +void Connection::tryToReconnect() throw (NoMoreControllerException, +DriverException, UnexpectedException) +{ + wstring fctName(L"Connection::tryToReconnect"); //Wait until other methods/Commands are done LockScope ls(&connectionCS); + if (isWarnEnabled()) + logWarn(fctName, L"Connection to controller lost - trying to reconnect"); + // close everything - close(); + if (isDebugEnabled()) + logDebug(fctName, L"Closing socket of lost connection"); + + isClosed = true; + closeSocket(); // try to reconnect to the same controller if it has never been suspected of // failure before @@ -1056,10 +1131,10 @@ { try { + if (isDebugEnabled()) + logDebug(fctName, L"Trying to reconnect to the same controller..."); if (initConnection() && finalizeConnect()) { - if (isInfoEnabled()) - logInfo(fctName, L"Reconnection to the same controller succeded"); isClosed = false; } } @@ -1068,45 +1143,40 @@ delete driverSocketPtr; driverSocketPtr = NULL; } } - if (isClosed) + if (isClosed) //connection failed { + if (isDebugEnabled()) + logDebug(fctName, L"Controller " + static_cast<wstring>(connected_controller) + + L" is still not responding, suspecting it of failure"); connect_policy_ptr->suspectControllerOfFailure(connected_controller); - } - try - { - connected_controller = connect_policy_ptr->getController(); - if (initConnection() && finalizeConnect()) + try { - if (isInfoEnabled()) - logInfo(fctName, L"Connection succeded"); - isClosed = false; + if (isDebugEnabled()) + logDebug(fctName, L"Getting a new controller from the list..."); + connected_controller = connect_policy_ptr->getController(); + if (initConnection() && finalizeConnect()) + { + if (isInfoEnabled()) + logInfo(fctName, L"Connection succeded"); + isClosed = false; + } + } + catch (AuthenticationException ae) + { + // Should not happen, this probably mean an inconsistency in controller + // configuration but safely ignore (see below) + wstring msg = L"Warning! Authentication exception received on connection retry, controller configuration might be inconsistent"; + if (isWarnEnabled()) + logWarn(fctName, msg); + throw DriverException(msg+ae.description()); } } - catch (AuthenticationException ae) - { - // Should not happen, this probably mean an inconsistency in controller - // configuration but safely ignore (see below) - wstring msg = L"Warning! Authentication exception received on connection retry, controller configuration might be inconsistent"; - if (isWarnEnabled()) - logWarn(fctName, msg); - throw DriverException(msg+ae.description()); - } - catch (ConnectionException ce) - { - // Should not happen, this probably mean an inconsistency in controller - // configuration but safely ignore (see below) - wstring msg = L"Warning! Connection exception received on connection retry, controller configuration might be inconsistent"; - if (isWarnEnabled()) - logWarn(fctName, msg); - throw DriverException(msg+ce.description()); - } - // Connection succeeded, restore the previous connection state on the // controller try { if (isInfoEnabled()) - logInfo(fctName, L"Restoring connection state on controller " + logInfo(fctName, L"Restoring connection state on the new controller " + static_cast<wstring>(connected_controller)); sendCommand(*driverSocketPtr, RestoreConnectionState); *driverSocketPtr<<writeExecutedInTransaction; @@ -1116,10 +1186,12 @@ *driverSocketPtr<<persistent_connection; if (persistent_connection) *driverSocketPtr<<persistent_connection_id; + if (isInfoEnabled()) + logInfo(fctName, L"Transparent reconnection succeeded"); } catch (SocketIOException sioe) { - throw (DriverException(L"Failed to reconnect to controller" + throw (ConnectionException(L"Error in reconnection attempt: " + sioe.description())); } } Index: carob/src/ControllerConnectPolicy.cpp diff -u carob/src/ControllerConnectPolicy.cpp:1.10 carob/src/ControllerConnectPolicy.cpp:1.11 --- carob/src/ControllerConnectPolicy.cpp:1.10 Tue Feb 21 17:08:06 2006 +++ carob/src/ControllerConnectPolicy.cpp Fri Feb 24 12:56:41 2006 @@ -152,6 +152,9 @@ bool AbstractControllerConnectPolicy::isSuspectedOfFailure( const ControllerInfo& controllerInfo) { + // This is a good place to do the ping on suspected controllers, we are + // called by most of the functions in this class + updateSuspectList(); // Just compare controller info with each item in the whole list for (SuspectList::const_iterator iter = suspected_controllers.begin(); iter != suspected_controllers.end(); iter++) @@ -181,6 +184,8 @@ controller_failure_number++; SuspectController newSuspect; newSuspect.controllerInfo = controllerInfo; + if (isDebugEnabled()) + logDebug(fctName, L"Creating ping socket to suspect controller..."); // creates and prepares a new socket for pinging the controller newSuspect.pingSocketPtr = new JavaSocket(); newSuspect.pingSocketPtr->create(false); //create non blocking Index: carob/test/10-Connection/TestConnect.cpp diff -u carob/test/10-Connection/TestConnect.cpp:1.4 carob/test/10-Connection/TestConnect.cpp:1.5 --- carob/test/10-Connection/TestConnect.cpp:1.4 Tue Feb 14 18:35:48 2006 +++ carob/test/10-Connection/TestConnect.cpp Fri Feb 24 12:56:41 2006 @@ -115,11 +115,11 @@ // We should receive an exception instead of coming here CPPUNIT_ASSERT(false); } - catch (ConnectionException ce) + catch (AuthenticationException ae) { if (isErrorEnabled()) logError(fctName, L"Connection failed (this is ok). Exception: " - + ce.description()); + + ae.description()); CPPUNIT_ASSERT(true); } }
|
|
| <Prev in Thread] | Current Thread | [Next in Thread> |
|---|---|---|
| Previous by Date: | CVS update of carob/src (JavaSocket.cpp), gilles-Tt5JLJuBijYiZlD9aYmxOGD2FQJk+8+b |
|---|---|
| Next by Date: | CVS update of carob/test/10-Connection (2 files), gilles-Tt5JLJuBijYiZlD9aYmxOGD2FQJk+8+b |
| Previous by Thread: | CVS update of carob (4 files), gilles-Tt5JLJuBijYiZlD9aYmxOGD2FQJk+8+b |
| Next by Thread: | CVS update of carob (2 files), gilles-Tt5JLJuBijYiZlD9aYmxOGD2FQJk+8+b |
| Indexes: | [Date] [Thread] [Top] [All Lists] |
Free MagazinesCisco NewsReceive a free quarterly e-newsletter with exclusive articles on how Cisco IT uses its own products and solutions to enable the business. subscribe Systems Management News, the newspaper for IT systems administration and data center managers! Each issue of Systems Management News is chock-full of news and analysis to help you understand what's happening in your field. subscribe The Enterprise Newsweekly eWeek is the essential technology information source for builders of e-business. subscribe Oracle Magazine Oracle Magazine contains technology strategy articles, sample code, tips, Oracle and partner news, how to articles for developers and DBAs, and more. Oracle (NASDAQ: ORCL) is the world's largest enterprise software company. subscribe Total Telecom Total Telecom is "The Economist of the communications industry". subscribe |
Home
| advertise | OSDir is
an inevitable website.
|