You are viewing a plain text version of this content. The canonical link for it is here.
Posted to derby-commits@db.apache.org by da...@apache.org on 2009/04/30 00:07:37 UTC
svn commit: r769962 - in /db/derby/code/trunk/java:
engine/org/apache/derby/impl/db/SlaveDatabase.java
testing/org/apache/derbyTesting/functionTests/tests/replicationTests/ReplicationRun_Local_3_p3.java
Author: dag
Date: Wed Apr 29 22:07:37 2009
New Revision: 769962
URL: http://svn.apache.org/viewvc?rev=769962&view=rev
Log:
DERBY-4186 After master stop, test fails when it succeeds in connecting (rebooting) shut-down ex-slave
Patch derby-4186-2, which solves this issue by
a) fixing a bug in SlaveDataBase, which loses and exception iff a
command to stop replication arrives from the master to the slave
before the initial connection (successful slave started) command
returns. This is a corner case race condition, and not very likely to
occur in practice, since it makes little sense to stop replication
immediately after starting it.
b) fixing a bug in the test, which switched on its head what is really
expected behavior, and also adds a waiting loop to allow intermediate
state on slave after the master is stopped. Also fixed some erroneous
comment and removed some cruft.
Modified:
db/derby/code/trunk/java/engine/org/apache/derby/impl/db/SlaveDatabase.java
db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/replicationTests/ReplicationRun_Local_3_p3.java
Modified: db/derby/code/trunk/java/engine/org/apache/derby/impl/db/SlaveDatabase.java
URL: http://svn.apache.org/viewvc/db/derby/code/trunk/java/engine/org/apache/derby/impl/db/SlaveDatabase.java?rev=769962&r1=769961&r2=769962&view=diff
==============================================================================
--- db/derby/code/trunk/java/engine/org/apache/derby/impl/db/SlaveDatabase.java (original)
+++ db/derby/code/trunk/java/engine/org/apache/derby/impl/db/SlaveDatabase.java Wed Apr 29 22:07:37 2009
@@ -25,6 +25,7 @@
import org.apache.derby.iapi.reference.Attribute;
import org.apache.derby.iapi.reference.SQLState;
import org.apache.derby.iapi.error.StandardException;
+import org.apache.derby.iapi.error.ExceptionSeverity;
import org.apache.derby.iapi.jdbc.AuthenticationService;
import org.apache.derby.iapi.services.context.ContextManager;
import org.apache.derby.iapi.services.context.ContextService;
@@ -134,6 +135,7 @@
// Check that the database was booted successfully, or throw
// the exception that caused the boot to fail.
verifySuccessfulBoot();
+
inBoot = false;
// This module has now been booted (hence active=true) even
@@ -349,6 +351,21 @@
}
}
}
+
+ if (bootException != null &&
+ SQLState.SHUTDOWN_DATABASE.startsWith(
+ bootException.getSQLState()) &&
+ bootException.getSeverity() == ExceptionSeverity.DATABASE_SEVERITY) {
+
+ // DERBY-4186: This is a corner case. Master made us shut down
+ // before the initial connect which establishes the slave has
+ // finalized it setting up of the slave and returned control to the
+ // application. bootException is set while we (application thread)
+ // are waiting in the sleep in the loop above (by the
+ // SlaveDatabaseBootThread thread in its call to handleShutdown),
+ // and this was previously ignored.
+ throw bootException;
+ }
}
/**
Modified: db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/replicationTests/ReplicationRun_Local_3_p3.java
URL: http://svn.apache.org/viewvc/db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/replicationTests/ReplicationRun_Local_3_p3.java?rev=769962&r1=769961&r2=769962&view=diff
==============================================================================
--- db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/replicationTests/ReplicationRun_Local_3_p3.java (original)
+++ db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/replicationTests/ReplicationRun_Local_3_p3.java Wed Apr 29 22:07:37 2009
@@ -20,8 +20,10 @@
*/
package org.apache.derbyTesting.functionTests.tests.replicationTests;
+import java.sql.SQLException;
import junit.framework.Test;
import junit.framework.TestSuite;
+import org.apache.derby.jdbc.ClientDataSource;
import org.apache.derbyTesting.junit.SecurityManagerSetup;
@@ -34,6 +36,10 @@
public class ReplicationRun_Local_3_p3 extends ReplicationRun_Local_3
{
+
+ final static String CANNOT_CONNECT_TO_DB_IN_SLAVE_MODE = "08004";
+ final static String REPLICATION_NOT_IN_MASTER_MODE = "XRE07";
+ final static int MAX_TRIES = 20;
/**
* Creates a new instance of ReplicationRun_Local
@@ -150,11 +156,11 @@
// 3 separate test
// stopMaster
- // failover on slave
+ // shutdown on slave
assertException(
_stopMaster(masterServerHost, masterServerPort,
masterDatabasePath + FS + masterDbSubPath + FS + replicatedDb),
- null); // Implies failover. // OK to continue.
+ null); // Implies slave should shut down. // OK to continue.
/* showCurrentState("Post stopMaster +1s", 1000L,
masterDatabasePath + FS + masterDbSubPath + FS + replicatedDb,
masterServerHost, masterServerPort); */
@@ -167,49 +173,78 @@
showCurrentState("Post stopMaster +5s", 5000L,
slaveDatabasePath + FS + slaveDbSubPath + FS + replicatedDb,
slaveServerHost, slaveServerPort); */
- waitForSQLState("08004", 1000L, 20, // 08004.C.7 - CANNOT_CONNECT_TO_DB_IN_SLAVE_MODE
- slaveDatabasePath + FS + slaveDbSubPath + FS + replicatedDb,
- slaveServerHost, slaveServerPort);
- /* Got it above... showCurrentState("Post stopMaster +30s", 30000L,
- slaveDatabasePath + FS + slaveDbSubPath + FS + replicatedDb,
- slaveServerHost, slaveServerPort); // 08004 */
- /* Got it above... showCurrentState("Post stopMaster +60s", 30000L,
- masterDatabasePath + FS + masterDbSubPath + FS + replicatedDb,
- masterServerHost, masterServerPort); // CONNECTED */
+
+ // Connect to the ex-slave db, to verify that we can boot it and
+ // connect to it.
+ //
+ // DERBY-4186: We use a loop below, to allow for intermediate state on
+ // the slave db after master stopped and before slave reaches the
+ // expected final state.
+ //
+ // If we get here quick enough we see this error state:
+ // CANNOT_CONNECT_TO_DB_IN_SLAVE_MODE
+ //
+ // The final end state is successful connect (i.e. a reboot) after
+ // stopped slave and db shutdown.
+
+ SQLException gotEx = null;
+ int tries = MAX_TRIES;
+
+ while (tries-- > 0) {
+ gotEx = null;
+ try
+ {
+ String connectionURL =
+ slaveDatabasePath + FS + slaveDbSubPath + FS + replicatedDb;
+ ClientDataSource ds = new ClientDataSource();
+ ds.setDatabaseName(connectionURL);
+ ds.setServerName(slaveServerHost);
+ ds.setPortNumber(slaveServerPort);
+ ds.getConnection().close();
+ util.DEBUG("Successfully connected after shutdown: " +
+ connectionURL);
+ break;
+ }
+ catch (SQLException se)
+ {
+ if (se.getSQLState().
+ equals(CANNOT_CONNECT_TO_DB_IN_SLAVE_MODE)) {
+ // Try again, shutdown did not complete yet..
+ gotEx = se;
+ util.DEBUG(
+ "got SLAVE_OPERATION_DENIED_WHILE_CONNECTED, sleep");
+ Thread.sleep(1000L);
+ continue;
+
+ } else {
+ // Something else, so report.
+ gotEx = se;
+ break;
+ }
+ }
+ }
+
+ if (gotEx != null) {
+ String reason;
+ if (gotEx.getSQLState().
+ equals(CANNOT_CONNECT_TO_DB_IN_SLAVE_MODE)) {
+ reason = "Tried " + MAX_TRIES + " times...";
+ } else {
+ reason = "Unexpected SQL state: " + gotEx.getSQLState();
+ }
+
+ util.DEBUG(reason);
+ throw gotEx;
+ }
+
+ // A failover on ex-master db should fail now
assertException(
_failOver(masterServerHost, masterServerPort,
masterDatabasePath+FS+masterDbSubPath+FS+replicatedDb),
- "XRE07");
- /* _p2: assertException(
- _failOver(slaveServerHost, slaveServerPort,
- slaveDatabasePath+FS+slaveDbSubPath+FS+replicatedDb),
- "XRE07"); // Hangs!? even after killMaster server. */
-
- // 5 separate test
- // slave: "normal" connect to slave db
-
- // 6 separate test
- // slave: 'internal-stopslave=true'
-
- /* failOver(jvmVersion,
- masterDatabasePath, masterDbSubPath, replicatedDb,
- masterServerHost, // Where the master db is run.
- masterServerPort,
- testClientHost); // XRE07 Could not perform operation because the database is not in replication master mode.
- */
-
- waitForSQLState("08004", 1000L, 20, // 08004.C.7 - CANNOT_CONNECT_TO_DB_IN_SLAVE_MODE
- slaveDatabasePath + FS + slaveDbSubPath + FS + replicatedDb,
- slaveServerHost, slaveServerPort); // _failOver above fails...
- /*
- connectPing(slaveDatabasePath+FS+slaveDbSubPath+FS+replicatedDb,
- slaveServerHost,slaveServerPort,
- testClientHost); //
- */
-
- // Not relevant as we can not connect. verifySlave();
-
- // We should verify the master as well, at least to see that we still can connect.
+ REPLICATION_NOT_IN_MASTER_MODE);
+
+ // We should verify the master as well, at least to see that we still
+ // can connect.
verifyMaster();
stopServer(jvmVersion, derbyVersion,