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