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/12/03 16:53:51 UTC

svn commit: r886831 - in /db/derby/code/trunk/java: engine/org/apache/derby/impl/store/raw/data/ engine/org/apache/derby/loc/ shared/org/apache/derby/shared/common/reference/ testing/org/apache/derbyTesting/functionTests/tests/lang/ testing/org/apache/...

Author: dag
Date: Thu Dec  3 15:53:02 2009
New Revision: 886831

URL: http://svn.apache.org/viewvc?rev=886831&view=rev
Log:
DERBY-151 Thread termination -> XSDG after operation is 'complete'

This patch catches the exception seen by RAFContainer4
readFull/Write/full when the embedding application thread sees an
interrupt, and asks the user to inspect the app to find the cause.
Before this patch, the symptoms were puzzling to the user, suggesting
that the disk might be full.

The database level error seen is XSDG9:
"Derby thread received an interrupt during a disk I/O operation, please check your application for the source of the interrupt. "

A new store test, Derby151Test, checks this behavior.


Added:
    db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/store/Derby151Test.java   (with props)
Modified:
    db/derby/code/trunk/java/engine/org/apache/derby/impl/store/raw/data/FileContainer.java
    db/derby/code/trunk/java/engine/org/apache/derby/impl/store/raw/data/RAFContainer4.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/ErrorCodeTest.java
    db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/store/_Suite.java

Modified: db/derby/code/trunk/java/engine/org/apache/derby/impl/store/raw/data/FileContainer.java
URL: http://svn.apache.org/viewvc/db/derby/code/trunk/java/engine/org/apache/derby/impl/store/raw/data/FileContainer.java?rev=886831&r1=886830&r2=886831&view=diff
==============================================================================
--- db/derby/code/trunk/java/engine/org/apache/derby/impl/store/raw/data/FileContainer.java (original)
+++ db/derby/code/trunk/java/engine/org/apache/derby/impl/store/raw/data/FileContainer.java Thu Dec  3 15:53:02 2009
@@ -903,9 +903,10 @@
      * @param bytes the bytes to write
      * @param offset the offset to start writing at
      * @throws IOException if an I/O error occurs while writing
+	 * @exception StandardException  Derby Standard error policy
      */
     void writeAtOffset(StorageRandomAccessFile file, byte[] bytes, long offset)
-            throws IOException
+            throws IOException, StandardException
     {
         file.seek(offset);
         file.write(bytes);
@@ -919,8 +920,10 @@
 		positioned at the beginning of the first allocation page.
 
 		@exception IOException error in read the embryonic page from file
+		@exception StandardException  Derby Standard error policy
 	*/
-	protected byte[] getEmbryonicPage(DataInput fileData) throws IOException
+	protected byte[] getEmbryonicPage(DataInput fileData) throws
+		IOException, StandardException
 	{
 		byte[] epage = new byte[AllocPage.MAX_BORROWED_SPACE];
 
@@ -941,9 +944,10 @@
      * {@code FileContainer.FIRST_ALLOC_PAGE_OFFSET})
      * @return a byte array containing the embryonic page
      * @throws IOException if an I/O error occurs while reading
+	 * @throws StandardException  Derby Standard error policy
      */
     byte[] getEmbryonicPage(StorageRandomAccessFile file, long offset)
-            throws IOException
+            throws IOException, StandardException
     {
         file.seek(offset);
         return getEmbryonicPage(file);

Modified: db/derby/code/trunk/java/engine/org/apache/derby/impl/store/raw/data/RAFContainer4.java
URL: http://svn.apache.org/viewvc/db/derby/code/trunk/java/engine/org/apache/derby/impl/store/raw/data/RAFContainer4.java?rev=886831&r1=886830&r2=886831&view=diff
==============================================================================
--- db/derby/code/trunk/java/engine/org/apache/derby/impl/store/raw/data/RAFContainer4.java (original)
+++ db/derby/code/trunk/java/engine/org/apache/derby/impl/store/raw/data/RAFContainer4.java Thu Dec  3 15:53:02 2009
@@ -23,6 +23,7 @@
 
 
 import org.apache.derby.iapi.error.StandardException;
+import org.apache.derby.iapi.reference.SQLState;
 import org.apache.derby.iapi.services.sanity.SanityManager;
 
 import org.apache.derby.iapi.store.raw.ContainerKey;
@@ -33,6 +34,7 @@
 import java.nio.ByteBuffer;
 import java.nio.channels.FileChannel;
 import java.nio.channels.ClosedChannelException;
+import java.nio.channels.ClosedByInterruptException;
 import org.apache.derby.io.StorageRandomAccessFile;
 
 /**
@@ -422,7 +424,7 @@
      * @throws IOException if an I/O error occurs while writing
      */
     void writeAtOffset(StorageRandomAccessFile file, byte[] bytes, long offset)
-            throws IOException
+            throws IOException, StandardException
     {
         FileChannel ioChannel = getChannel(file);
         if (ioChannel != null) {
@@ -442,9 +444,10 @@
      * {@code FileContainer.FIRST_ALLOC_PAGE_OFFSET})
      * @return a byte array containing the embryonic page
      * @throws IOException if an I/O error occurs while reading
+     * @throws StandardException if thread is interrupted.
      */
     byte[] getEmbryonicPage(StorageRandomAccessFile file, long offset)
-            throws IOException
+            throws IOException, StandardException
     {
         FileChannel ioChannel = getChannel(file);
         if (ioChannel != null) {
@@ -459,21 +462,32 @@
 
     /**
      * Attempts to fill buf completely from start until it's full.
-     * <p>
+     * <p/>
      * FileChannel has no readFull() method, so we roll our own.
+     * <p/>
+     * @param dstBuffer buffer to read into
+     * @param srcChannel channel to read from
+     * @param position file position from where to read
+     *
+     * @throws IOException if an I/O error occurs while reading
+     * @throws StandardException If thread is interrupted.
      */
     private final void readFull(ByteBuffer dstBuffer,
                                 FileChannel srcChannel,
                                 long position)
-        throws IOException
+            throws IOException, StandardException
     {
         while(dstBuffer.remaining() > 0) {
-            if( srcChannel.read(dstBuffer, position + dstBuffer.position())
-                    == -1)
-            {
-                throw new EOFException(
-                        "Reached end of file while attempting to read a "
-                        + "whole page.");
+            try {
+                if (srcChannel.read(dstBuffer,
+                                    position + dstBuffer.position()) == -1) {
+                        throw new EOFException(
+                            "Reached end of file while attempting to read a "
+                            + "whole page.");
+                }
+            } catch (ClosedByInterruptException e) {
+                throw StandardException.newException(
+                    SQLState.FILE_IO_INTERRUPTED, e);
             }
         }
     }
@@ -481,16 +495,28 @@
     /**
      * Attempts to write buf completely from start until end, at the given
      * position in the destination fileChannel.
-     * <p>
+     * <p/>
      * FileChannel has no writeFull() method, so we roll our own.
+     * <p/>
+     * @param srcBuffer buffer to write
+     * @param dstChannel channel to write to
+     * @param position file position to start writing at
+     *
+     * @throws IOException if an I/O error occurs while writing
+     * @throws StandardException If thread is interrupted.
      */
     private final void writeFull(ByteBuffer srcBuffer,
                                  FileChannel dstChannel,
                                  long position)
-        throws IOException
+            throws IOException, StandardException
     {
         while(srcBuffer.remaining() > 0) {
-            dstChannel.write(srcBuffer, position + srcBuffer.position());
+            try {
+                dstChannel.write(srcBuffer, position + srcBuffer.position());
+            } catch (ClosedByInterruptException e) {
+                throw StandardException.newException(
+                    SQLState.FILE_IO_INTERRUPTED, e);
+            }
         }
     }
 }

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=886831&r1=886830&r2=886831&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 Dec  3 15:53:02 2009
@@ -5635,6 +5635,11 @@
                 <arg>value</arg>
             </msg>
 
+            <msg>
+                <name>XSDG9.D</name>
+                <text>Derby thread received an interrupt during a disk I/O operation, please check your application for the source of the interrupt.</text>
+            </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=886831&r1=886830&r2=886831&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 Dec  3 15:53:02 2009
@@ -531,6 +531,7 @@
 	String DATA_DIRECTORY_NOT_FOUND_IN_BACKUP                   = "XSDG6.D";
 	String UNABLE_TO_REMOVE_DATA_DIRECTORY                      = "XSDG7.D";
 	String UNABLE_TO_COPY_DATA_DIRECTORY                        = "XSDG8.D";
+	String FILE_IO_INTERRUPTED                                  = "XSDG9.D";
 
 
 

Modified: db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/lang/ErrorCodeTest.java
URL: http://svn.apache.org/viewvc/db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/lang/ErrorCodeTest.java?rev=886831&r1=886830&r2=886831&view=diff
==============================================================================
--- db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/lang/ErrorCodeTest.java (original)
+++ db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/lang/ErrorCodeTest.java Thu Dec  3 15:53:02 2009
@@ -214,6 +214,7 @@
         		{"XSDG6","Data segment directory not found in {0} backup during restore. Please make sure that backup copy is the right one and it is not corrupted.","45000"},
         		{"XSDG7","Directory {0} could not be removed during restore. Please make sure that permissions are correct.","45000"},
         		{"XSDG8","Unable to copy directory '{0}' to '{1}' during restore. Please make sure that there is enough space and permissions are correct. ","45000"},
+        		{"XSDG9","Derby thread received an interrupt during a disk I/O operation, please check your application for the source of the interrupt.","45000"},
         		{"XSLA0","Cannot flush the log file to disk {0}.","45000"},
         		{"XSLA1","Log Record has been sent to the stream, but it cannot be applied to the store (Object {0}).  This may cause recovery problems also.","45000"},
         		{"XSLA2","System will shutdown, got I/O Exception while accessing log file.","45000"},

Added: db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/store/Derby151Test.java
URL: http://svn.apache.org/viewvc/db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/store/Derby151Test.java?rev=886831&view=auto
==============================================================================
--- db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/store/Derby151Test.java (added)
+++ db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/store/Derby151Test.java Thu Dec  3 15:53:02 2009
@@ -0,0 +1,131 @@
+/*
+  Class org.apache.derbyTesting.functionTests.tests.store.Derby151Test
+
+  Licensed to the Apache Software Foundation (ASF) under one or more
+  contributor license agreements.  See the NOTICE file distributed with
+  this work for additional information regarding copyright ownership.
+  The ASF licenses this file to you under the Apache License, Version 2.0
+  (the "License"); you may not use this file except in compliance with
+  the License.  You may obtain a copy of the License at
+
+  http://www.apache.org/licenses/LICENSE-2.0
+
+  Unless required by applicable law or agreed to in writing, software
+  distributed under the License is distributed on an "AS IS" BASIS,
+  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  See the License for the specific language governing permissions and
+  limitations under the License.
+
+*/
+package org.apache.derbyTesting.functionTests.tests.store;
+
+import org.apache.derbyTesting.junit.BaseJDBCTestCase;
+import org.apache.derbyTesting.junit.CleanDatabaseTestSetup;
+import org.apache.derbyTesting.junit.DatabasePropertyTestSetup;
+import org.apache.derbyTesting.junit.TestConfiguration;
+
+import org.apache.derby.shared.common.sanity.SanityManager;
+
+import junit.framework.Assert;
+import junit.framework.Test;
+import junit.framework.TestSuite;
+
+import java.sql.CallableStatement;
+import java.sql.Connection;
+import java.sql.PreparedStatement;
+import java.sql.ResultSet;
+import java.sql.Statement;
+import java.sql.SQLException;
+
+/**
+ *   Test to reproduce and verify fix for DERBY-151.
+ */
+
+public class Derby151Test extends BaseJDBCTestCase
+{
+
+    public Derby151Test(String name)
+    {
+        super(name);
+    }
+
+
+    protected static Test baseSuite(String name)
+    {
+        TestSuite suite = new TestSuite(name);
+        suite.addTestSuite(Derby151Test.class);
+        return new CleanDatabaseTestSetup(
+            new TestSuite(Derby151Test.class, name));
+    }
+
+
+    protected void setUp()
+            throws java.lang.Exception {
+        super.setUp();
+
+        Statement stmt = createStatement();
+        stmt.executeUpdate("CREATE TABLE d151(x int primary key)");
+        stmt.close();
+    }
+    /**
+     * Clean up the connection maintained by this test.
+     */
+    protected void tearDown()
+            throws java.lang.Exception {
+
+        Statement stmt = createStatement();
+        stmt.executeUpdate("DROP TABLE d151");
+        stmt.close();
+
+        super.tearDown();
+    }
+
+
+    public void testD151 () throws SQLException {
+        PreparedStatement insert =
+            prepareStatement("insert into d151 values (?)");
+        try {
+            for (int i = 0; i < 10000; i++) {
+                insert.setInt(1, i);
+                insert.executeUpdate();
+                Thread.currentThread().interrupt();
+            }
+
+            // We were not able to prokove any error, but that should not fail
+            // the test; the results here may depend on VMs possibly.  So just,
+            // report this fact in verbose mode:
+
+            println("Not able to test fix for DERBY-151: No interrupt seen");
+
+        } catch (SQLException e) {
+            assertSQLState("XSDG9", e);
+        }
+        insert.close(); // already closed by error
+    }
+
+    public static Test suite()
+    {
+        TestSuite suite = new TestSuite("Derby151Test");
+        suite.addTest(
+            baseSuite("Derby151Test:embedded"));
+
+        // Note: We are not adding a client/Server version since the explicit
+        // interrupt may (will) upset the communication socket to the client.
+        // I see 08006 SQL state on OpenSolaris/JDK1.6.
+        //
+        //    :
+        // org.apache.derby.client.am.DisconnectException:
+        //                    A communications error has been detected: null.
+        //    :
+        // java.io.InterruptedIOException
+        //    at java.net.SocketOutputStream.socketWrite0(Native Method)
+        //    at java.net.SocketOutputStream.socketWrite(
+        //                                         SocketOutputStream.java:92)
+        //    at java.net.SocketOutputStream.write(SocketOutputStream.java:136)
+        //
+        // which happened before any error in RAFContainer4.
+
+
+        return suite;
+    }
+}

Propchange: db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/store/Derby151Test.java
------------------------------------------------------------------------------
    svn:eol-style = native

Modified: db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/store/_Suite.java
URL: http://svn.apache.org/viewvc/db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/store/_Suite.java?rev=886831&r1=886830&r2=886831&view=diff
==============================================================================
--- db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/store/_Suite.java (original)
+++ db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/store/_Suite.java Thu Dec  3 15:53:02 2009
@@ -56,6 +56,7 @@
         suite.addTest(ClassLoaderBootTest.suite());
         suite.addTest(StreamingColumnTest.suite());
         suite.addTest(Derby3625Test.suite());
+        suite.addTest(Derby151Test.suite());
         suite.addTest(PositionedStoreStreamTest.suite());
         suite.addTest(OSReadOnlyTest.suite());
         suite.addTest(BackupRestoreTest.suite());