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 rh...@apache.org on 2011/09/08 20:50:40 UTC
svn commit: r1166859 - in /db/derby/code/trunk/java:
engine/org/apache/derby/impl/sql/catalog/ engine/org/apache/derby/loc/
shared/org/apache/derby/shared/common/reference/
testing/org/apache/derbyTesting/functionTests/tests/lang/
Author: rhillegas
Date: Thu Sep 8 18:50:40 2011
New Revision: 1166859
URL: http://svn.apache.org/viewvc?rev=1166859&view=rev
Log:
DERBY-5398: Use a transient transaction to flush unused sequence values back to disk during orderly engine shutdown.
Modified:
db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/catalog/SequenceUpdater.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/SQLState.java
db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/lang/SequenceGeneratorTest.java
Modified: db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/catalog/SequenceUpdater.java
URL: http://svn.apache.org/viewvc/db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/catalog/SequenceUpdater.java?rev=1166859&r1=1166858&r2=1166859&view=diff
==============================================================================
--- db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/catalog/SequenceUpdater.java (original)
+++ db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/catalog/SequenceUpdater.java Thu Sep 8 18:50:40 2011
@@ -29,10 +29,13 @@ import org.apache.derby.iapi.services.ca
import org.apache.derby.iapi.services.cache.CacheManager;
import org.apache.derby.iapi.services.context.ContextManager;
import org.apache.derby.iapi.services.context.ContextService;
+import org.apache.derby.iapi.services.i18n.MessageService;
+import org.apache.derby.iapi.services.monitor.Monitor;
import org.apache.derby.iapi.services.property.PropertyUtil;
import org.apache.derby.iapi.services.sanity.SanityManager;
import org.apache.derby.iapi.sql.conn.LanguageConnectionContext;
import org.apache.derby.iapi.sql.dictionary.SequenceDescriptor;
+import org.apache.derby.iapi.store.access.AccessFactory;
import org.apache.derby.iapi.store.access.TransactionController;
import org.apache.derby.iapi.types.NumberDataValue;
import org.apache.derby.iapi.types.RowLocation;
@@ -195,10 +198,24 @@ public abstract class SequenceUpdater im
//
// Flush current value to disk. This prevents us from leaking values when DDL
// is performed. The metadata caches are invalidated and cleared when DDL is performed.
+ // We flush the current value to disk on database shutdown also.
//
if ( _sequenceGenerator != null )
{
- updateCurrentValueOnDisk( null, peekAtCurrentValue() );
+ boolean gapClosed = updateCurrentValueOnDisk( null, peekAtCurrentValue() );
+
+ // log an error message if we failed to flush the preallocated values.
+ if ( !gapClosed )
+ {
+ String errorMessage = MessageService.getTextMessage
+ (
+ SQLState.LANG_CANT_FLUSH_PREALLOCATOR,
+ _sequenceGenerator.getSchemaName(),
+ _sequenceGenerator.getName()
+ );
+
+ Monitor.getStream().println( errorMessage );
+ }
}
_uuidString = null;
@@ -400,7 +417,33 @@ public abstract class SequenceUpdater im
*/
public boolean updateCurrentValueOnDisk( Long oldValue, Long newValue ) throws StandardException
{
- TransactionController executionTransaction = getLCC().getTransactionExecute();
+ LanguageConnectionContext lcc = getLCC();
+
+ //
+ // Not having an LCC should mean that we are in the middle of engine
+ // shutdown. We get here only to flush the current value to disk so that
+ // we don't leak unused sequence numbers. See DERBY-5398.
+ //
+ if ( lcc == null )
+ {
+ if (SanityManager.DEBUG)
+ {
+ SanityManager.ASSERT( oldValue == null, "We should be flushing unused sequence values here." );
+ }
+
+ ContextService csf = ContextService.getFactory();
+ ContextManager cm = csf.getCurrentContextManager();
+ AccessFactory af = _dd.af;
+ TransactionController dummyTransaction = af.getTransaction( cm );
+
+ boolean retval = updateCurrentValueOnDisk( dummyTransaction, oldValue, newValue, false );
+ dummyTransaction.commit();
+ dummyTransaction.destroy();
+
+ return retval;
+ }
+
+ TransactionController executionTransaction = lcc.getTransactionExecute();
TransactionController nestedTransaction = null;
try {
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=1166859&r1=1166858&r2=1166859&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 Thu Sep 8 18:50:40 2011
@@ -3452,6 +3452,13 @@ Guide.
<arg>className</arg>
</msg>
+ <msg>
+ <name>X0Y86.S</name>
+ <text>Derby could not obtain the locks needed to release the unused, preallocated values for the sequence '{0}'.'{1}'. As a result, unexpected gaps may appear in this sequence.</text>
+ <arg>schemaName</arg>
+ <arg>sequenceName</arg>
+ </msg>
+
</family>
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=1166859&r1=1166858&r2=1166859&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 Thu Sep 8 18:50:40 2011
@@ -1371,6 +1371,7 @@ public interface SQLState {
String LANG_IGNORE_MISSING_INDEX_ROW_DURING_DELETE = "X0Y83.S";
String LANG_TOO_MUCH_CONTENTION_ON_SEQUENCE = "X0Y84.S";
String LANG_UNKNOWN_SEQUENCE_PREALLOCATOR = "X0Y85.S";
+ String LANG_CANT_FLUSH_PREALLOCATOR = "X0Y86.S";
// TEMPORARY EXECUTION RESTRICTIONS
Modified: db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/lang/SequenceGeneratorTest.java
URL: http://svn.apache.org/viewvc/db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/lang/SequenceGeneratorTest.java?rev=1166859&r1=1166858&r2=1166859&view=diff
==============================================================================
--- db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/lang/SequenceGeneratorTest.java (original)
+++ db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/lang/SequenceGeneratorTest.java Thu Sep 8 18:50:40 2011
@@ -654,6 +654,33 @@ public class SequenceGeneratorTest exte
);
}
+ /**
+ * <p>
+ * Test that sequence values are not leaked during an orderly system shutdown.
+ * See DERBY-5398.
+ * </p>
+ */
+ public void test_10_5398() throws Exception
+ {
+ Connection conn = openUserConnection( TEST_DBO );
+
+ goodStatement( conn, "create sequence seq_10\n" );
+
+ int seq_10_value = Integer.MIN_VALUE;
+ long seq_10_upperBound;
+
+ seq_10_upperBound = seq_10_value + ALLOCATION_COUNT;
+ vetBumping( conn, TEST_DBO, "SEQ_10", seq_10_value++, seq_10_upperBound );
+
+ // bring down the engine, then reboot the database
+ getTestConfiguration().shutdownEngine();
+ conn = openUserConnection( TEST_DBO );
+
+ // verify that we did not leak any values
+ seq_10_upperBound = seq_10_value + ALLOCATION_COUNT;
+ vetBumping( conn, TEST_DBO, "SEQ_10", seq_10_value++, seq_10_upperBound );
+ }
+
///////////////////////////////////////////////////////////////////////////////////
//
// MINIONS