Return-Path: Delivered-To: apmail-db-derby-commits-archive@www.apache.org Received: (qmail 1616 invoked from network); 18 Jan 2008 08:22:33 -0000 Received: from hermes.apache.org (HELO mail.apache.org) (140.211.11.2) by minotaur.apache.org with SMTP; 18 Jan 2008 08:22:33 -0000 Received: (qmail 67871 invoked by uid 500); 18 Jan 2008 08:22:23 -0000 Delivered-To: apmail-db-derby-commits-archive@db.apache.org Received: (qmail 67843 invoked by uid 500); 18 Jan 2008 08:22:23 -0000 Mailing-List: contact derby-commits-help@db.apache.org; run by ezmlm Precedence: bulk list-help: list-unsubscribe: List-Post: Reply-To: "Derby Development" List-Id: Delivered-To: mailing list derby-commits@db.apache.org Received: (qmail 67821 invoked by uid 99); 18 Jan 2008 08:22:23 -0000 Received: from nike.apache.org (HELO nike.apache.org) (192.87.106.230) by apache.org (qpsmtpd/0.29) with ESMTP; Fri, 18 Jan 2008 00:22:23 -0800 X-ASF-Spam-Status: No, hits=-100.0 required=10.0 tests=ALL_TRUSTED X-Spam-Check-By: apache.org Received: from [140.211.11.3] (HELO eris.apache.org) (140.211.11.3) by apache.org (qpsmtpd/0.29) with ESMTP; Fri, 18 Jan 2008 08:22:17 +0000 Received: by eris.apache.org (Postfix, from userid 65534) id 930DE1A9832; Fri, 18 Jan 2008 00:22:08 -0800 (PST) Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit Subject: svn commit: r613097 - in /db/derby/code/trunk/java: engine/org/apache/derby/iapi/reference/ engine/org/apache/derby/impl/jdbc/ engine/org/apache/derby/loc/ shared/org/apache/derby/shared/common/reference/ Date: Fri, 18 Jan 2008 08:22:07 -0000 To: derby-commits@db.apache.org From: oysteing@apache.org X-Mailer: svnmailer-1.0.8 Message-Id: <20080118082208.930DE1A9832@eris.apache.org> X-Virus-Checked: Checked by ClamAV on apache.org Author: oysteing Date: Fri Jan 18 00:22:06 2008 New Revision: 613097 URL: http://svn.apache.org/viewvc?rev=613097&view=rev Log: DERBY-3205: Implement connection url attribute for starting slave. (Contributed by Jorgen Loland) Modified: db/derby/code/trunk/java/engine/org/apache/derby/iapi/reference/Attribute.java db/derby/code/trunk/java/engine/org/apache/derby/impl/jdbc/EmbedConnection.java db/derby/code/trunk/java/engine/org/apache/derby/loc/messages.xml db/derby/code/trunk/java/shared/org/apache/derby/shared/common/reference/Attribute.java db/derby/code/trunk/java/shared/org/apache/derby/shared/common/reference/SQLState.java Modified: db/derby/code/trunk/java/engine/org/apache/derby/iapi/reference/Attribute.java URL: http://svn.apache.org/viewvc/db/derby/code/trunk/java/engine/org/apache/derby/iapi/reference/Attribute.java?rev=613097&r1=613096&r2=613097&view=diff ============================================================================== --- db/derby/code/trunk/java/engine/org/apache/derby/iapi/reference/Attribute.java (original) +++ db/derby/code/trunk/java/engine/org/apache/derby/iapi/reference/Attribute.java Fri Jan 18 00:22:06 2008 @@ -113,6 +113,16 @@ String REPLICATION_STOP_MASTER = "stopMaster"; /** + * Attribute name to start replication slave mode for a database. + */ + String REPLICATION_START_SLAVE = "startSlave"; + + /** + * Attribute name to stop replication slave mode for a database. + */ + String REPLICATION_STOP_SLAVE = "stopSlave"; + + /** * If startMaster is true, this attribute is used to specify the * host name the master should connect to. This is a required * attribute. Modified: db/derby/code/trunk/java/engine/org/apache/derby/impl/jdbc/EmbedConnection.java URL: http://svn.apache.org/viewvc/db/derby/code/trunk/java/engine/org/apache/derby/impl/jdbc/EmbedConnection.java?rev=613097&r1=613096&r2=613097&view=diff ============================================================================== --- db/derby/code/trunk/java/engine/org/apache/derby/impl/jdbc/EmbedConnection.java (original) +++ db/derby/code/trunk/java/engine/org/apache/derby/impl/jdbc/EmbedConnection.java Fri Jan 18 00:22:06 2008 @@ -48,6 +48,9 @@ import org.apache.derby.iapi.sql.dictionary.DataDictionary; import org.apache.derby.iapi.store.access.XATransactionController; +import org.apache.derby.iapi.services.replication.master.MasterFactory; +import org.apache.derby.iapi.services.replication.slave.SlaveFactory; + /* can't import due to name overlap: import java.sql.Connection; import java.sql.ResultSet; @@ -229,11 +232,38 @@ isEncryptionBoot(info)); boolean isTwoPhaseUpgradeBoot = (!createBoot && isHardUpgradeBoot(info)); + boolean isStartSlaveBoot = isStartReplicationSlaveBoot(info); // Save original properties if we modified them for // two phase encryption or upgrade boot. Properties savedInfo = null; + if (isStartSlaveBoot) { + if (database != null) { + throw StandardException.newException( + SQLState.CANNOT_START_SLAVE_ALREADY_BOOTED, + getTR().getDBName()); + } else if (createBoot || + shutdown || + isTwoPhaseEncryptionBoot || + isTwoPhaseUpgradeBoot) { + throw StandardException.newException( + SQLState.REPLICATION_CONFLICTING_ATTRIBUTES, + Attribute.REPLICATION_START_SLAVE); + } + + // We need to boot the slave database two times. The + // first boot will check authentication and + // authorization. The second boot will put the + // database in replication slave mode. SLAVE_PRE_MODE + // ensures that log records are not written to disk + // during the first boot. This is necessary because + // the second boot needs a log that is exactly equal + // to the log at the master. + info.setProperty(SlaveFactory.REPLICATION_MODE, + SlaveFactory.SLAVE_PRE_MODE); + } + if (database != null) { // database already booted by someone else @@ -312,23 +342,56 @@ handleStopReplicationMaster(tr, info); } - if (isTwoPhaseEncryptionBoot || isTwoPhaseUpgradeBoot) { - - // DERBY-2264: shutdown and boot again with encryption or - // upgrade attributes active. This is restricted to the - // database owner if authentication and sqlAuthorization is on. + if (isTwoPhaseEncryptionBoot || + isTwoPhaseUpgradeBoot || + isStartSlaveBoot) { + + // shutdown and boot again with encryption, upgrade or + // start replication slave attributes active. This is + // restricted to the database owner if authentication + // and sqlAuthorization is on. if (!usingNoneAuth && getLanguageConnection().usesSqlAuthorization()) { - // a failure here leaves database booted, but no - // (re)encryption has taken place and the connection is - // rejected. - checkIsDBOwner(isTwoPhaseEncryptionBoot? OP_ENCRYPT : - OP_HARD_UPGRADE); + int operation; + if (isTwoPhaseEncryptionBoot) { + operation = OP_ENCRYPT; + } else if (isTwoPhaseUpgradeBoot) { + operation = OP_HARD_UPGRADE; + } else { + operation = OP_REPLICATION; + } + try { + // a failure here leaves database booted, but no + // (re)encryption has taken place and the connection is + // rejected. + checkIsDBOwner(operation); + } catch (SQLException sqle) { + if (isStartSlaveBoot) { + // If authorization fails for the start + // slave command, we want to shutdown the + // database which is currently in the + // SLAVE_PRE_MODE. + handleException(tr.shutdownDatabaseException()); + } + throw sqle; + } + } + + if (isStartSlaveBoot) { + // Let the next boot of the database be + // replication slave mode + info.setProperty(SlaveFactory.REPLICATION_MODE, + SlaveFactory.SLAVE_MODE); + info.setProperty(SlaveFactory.SLAVE_DB, + getTR().getDBName()); + } else { + // reboot using saved properties which + // include the (re)encyption or upgrade attribute(s) + info = savedInfo; } - // shutdown and reboot using saved properties which - // include the (re)encyption or upgrade attribute(s) - info = savedInfo; + // Authentication and authorization done - shutdown + // the database handleException(tr.shutdownDatabaseException()); restoreContextStack(); tr = new TransactionResourceImpl(driver, url, info); @@ -336,6 +399,8 @@ setupContextStack(); context = pushConnectionContext(tr.getContextManager()); + // Reboot the database in the correct + // encrypt/upgrade/slave replication mode if (!bootDatabase(info, false)) { if (SanityManager.DEBUG) { @@ -347,9 +412,20 @@ setInactive(); return; } - // don't need to check user credentials again, did - // that on first plain boot, so just start - tr.startTransaction(); + + if (isStartSlaveBoot) { + // We don't return a connection to the client who + // called startSlave. Rather, we throw an + // exception stating that replication slave mode + // has been successfully started for the database + throw StandardException.newException( + SQLState.REPLICATION_SLAVE_STARTED_OK, + getTR().getDBName()); + } else { + // don't need to check user credentials again, did + // that on first plain boot, so just start + tr.startTransaction(); + } } // now we have the database connection, we can shut down @@ -482,6 +558,12 @@ p.getProperty(Attribute.UPGRADE_ATTR)).booleanValue(); } + private boolean isStartReplicationSlaveBoot(Properties p) { + return ((Boolean.valueOf( + p.getProperty(Attribute.REPLICATION_START_SLAVE)). + booleanValue())); + } + private boolean isStartReplicationMasterBoot(Properties p) { return ((Boolean.valueOf( p.getProperty(Attribute.REPLICATION_START_MASTER)). @@ -533,9 +615,7 @@ tr.getDatabase().startReplicationMaster(slavehost, slaveport, - org.apache.derby.iapi. - services.replication. - master.MasterFactory. + MasterFactory. ASYNCHRONOUS_MODE); } Modified: db/derby/code/trunk/java/engine/org/apache/derby/loc/messages.xml URL: http://svn.apache.org/viewvc/db/derby/code/trunk/java/engine/org/apache/derby/loc/messages.xml?rev=613097&r1=613096&r2=613097&view=diff ============================================================================== --- db/derby/code/trunk/java/engine/org/apache/derby/loc/messages.xml (original) +++ db/derby/code/trunk/java/engine/org/apache/derby/loc/messages.xml Fri Jan 18 00:22:06 2008 @@ -4763,6 +4763,23 @@ Could not stop replication because the database is not in replication master mode. + + XRE08 + Replication slave mode started successfully for database '{0}'. Connection refused because the database is in replication slave mode. + dbname + + + + XRE09 + Cannot start replication slave mode for database '{0}'. The database has already been booted. + dbname + + + + XRE10 + Conflicting attributes specified. See reference manual for attributes allowed in combination with replication attribute '{0}'. + attribute + Modified: db/derby/code/trunk/java/shared/org/apache/derby/shared/common/reference/Attribute.java URL: http://svn.apache.org/viewvc/db/derby/code/trunk/java/shared/org/apache/derby/shared/common/reference/Attribute.java?rev=613097&r1=613096&r2=613097&view=diff ============================================================================== --- db/derby/code/trunk/java/shared/org/apache/derby/shared/common/reference/Attribute.java (original) +++ db/derby/code/trunk/java/shared/org/apache/derby/shared/common/reference/Attribute.java Fri Jan 18 00:22:06 2008 @@ -103,6 +103,16 @@ String REPLICATION_STOP_MASTER = "stopMaster"; /** + * Attribute name to start replication slave mode for a database. + */ + String REPLICATION_START_SLAVE = "startSlave"; + + /** + * Attribute name to stop replication slave mode for a database. + */ + String REPLICATION_STOP_SLAVE = "stopSlave"; + + /** * If startMaster is true, this attribute is used to specify the * host name the master should connect to. This is a required * attribute. Modified: db/derby/code/trunk/java/shared/org/apache/derby/shared/common/reference/SQLState.java URL: http://svn.apache.org/viewvc/db/derby/code/trunk/java/shared/org/apache/derby/shared/common/reference/SQLState.java?rev=613097&r1=613096&r2=613097&view=diff ============================================================================== --- db/derby/code/trunk/java/shared/org/apache/derby/shared/common/reference/SQLState.java (original) +++ db/derby/code/trunk/java/shared/org/apache/derby/shared/common/reference/SQLState.java Fri Jan 18 00:22:06 2008 @@ -1765,5 +1765,8 @@ String REPLICATION_LOG_OUT_OF_SYNCH = "XRE05"; String REPLICATION_MASTER_TIMED_OUT = "XRE06"; String REPLICATION_UNABLE_TO_STOP_MASTER = "XRE07"; + String REPLICATION_SLAVE_STARTED_OK = "XRE08"; + String CANNOT_START_SLAVE_ALREADY_BOOTED = "XRE09"; + String REPLICATION_CONFLICTING_ATTRIBUTES = "XRE10"; }