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 mi...@apache.org on 2014/03/02 19:05:49 UTC

svn commit: r1573334 - in /db/derby/code/branches/10.10: ./ java/client/org/apache/derby/client/am/ java/client/org/apache/derby/client/net/ java/engine/org/apache/derby/loc/ java/shared/org/apache/derby/shared/common/reference/ java/testing/org/apache...

Author: mikem
Date: Sun Mar  2 18:05:49 2014
New Revision: 1573334

URL: http://svn.apache.org/r1573334
Log:
DERBY-5317: Detect attempts to reuse a connection that in the middle of sending a request to the server. Use this to provide a better error message and avoid the NPE.
DERBY-6386 - Errors in jdbc4.LobStreamTest if derbyclient.jar is first in the classpath

backported change #1530704 to fix DERBY-5317 from trunk to 10.10, needed some
   hand merging to fix difference in argument ordering between 10.10 and trunk.
backported change #1534425 to fix DERBY-6386 which was caused by DERBY5317 fix.


Modified:
    db/derby/code/branches/10.10/   (props changed)
    db/derby/code/branches/10.10/java/client/org/apache/derby/client/am/Agent.java
    db/derby/code/branches/10.10/java/client/org/apache/derby/client/am/BlobLocatorInputStream.java
    db/derby/code/branches/10.10/java/client/org/apache/derby/client/am/ClobLocatorInputStream.java
    db/derby/code/branches/10.10/java/client/org/apache/derby/client/am/ClobLocatorReader.java
    db/derby/code/branches/10.10/java/client/org/apache/derby/client/net/NetAgent.java
    db/derby/code/branches/10.10/java/client/org/apache/derby/client/net/Request.java
    db/derby/code/branches/10.10/java/engine/org/apache/derby/loc/messages.xml
    db/derby/code/branches/10.10/java/shared/org/apache/derby/shared/common/reference/SQLState.java
    db/derby/code/branches/10.10/java/testing/org/apache/derbyTesting/functionTests/tests/lang/ErrorCodeTest.java
    db/derby/code/branches/10.10/java/testing/org/apache/derbyTesting/functionTests/tests/largedata/LobLimitsTest.java

Propchange: db/derby/code/branches/10.10/
------------------------------------------------------------------------------
  Merged /db/derby/code/trunk:r1530704

Modified: db/derby/code/branches/10.10/java/client/org/apache/derby/client/am/Agent.java
URL: http://svn.apache.org/viewvc/db/derby/code/branches/10.10/java/client/org/apache/derby/client/am/Agent.java?rev=1573334&r1=1573333&r2=1573334&view=diff
==============================================================================
--- db/derby/code/branches/10.10/java/client/org/apache/derby/client/am/Agent.java (original)
+++ db/derby/code/branches/10.10/java/client/org/apache/derby/client/am/Agent.java Sun Mar  2 18:05:49 2014
@@ -263,9 +263,8 @@ public abstract class Agent {
         }
         connection_.completeChainBreakingDisconnect();
     }
-
-    public void beginWriteChainOutsideUOW() throws SqlException {
-    }
+    
+    abstract public void beginWriteChainOutsideUOW() throws SqlException;
 
     public void beginWriteChain(Statement statement) throws SqlException {
         connection_.writeTransactionStart(statement);
@@ -275,10 +274,10 @@ public abstract class Agent {
         beginWriteChain(statement);
     }
 
-    protected void endWriteChain() {
-    }
+    abstract protected void endWriteChain();
 
     protected final void endBatchedWriteChain() {
+        endWriteChain();
     }
 
     protected void beginReadChain(Statement statement) throws SqlException {

Modified: db/derby/code/branches/10.10/java/client/org/apache/derby/client/am/BlobLocatorInputStream.java
URL: http://svn.apache.org/viewvc/db/derby/code/branches/10.10/java/client/org/apache/derby/client/am/BlobLocatorInputStream.java?rev=1573334&r1=1573333&r2=1573334&view=diff
==============================================================================
--- db/derby/code/branches/10.10/java/client/org/apache/derby/client/am/BlobLocatorInputStream.java (original)
+++ db/derby/code/branches/10.10/java/client/org/apache/derby/client/am/BlobLocatorInputStream.java Sun Mar  2 18:05:49 2014
@@ -178,9 +178,10 @@ public class BlobLocatorInputStream exte
             currentPos += result.length;
             return result;       
         } catch (SqlException ex) {
-            IOException ioEx = new IOException();
-            ioEx.initCause(ex);
-            throw ioEx;
+            // Passing cause as ctor argument ensures that the IOException 
+            // inherits the cause's message, (unlike invoking initCause() on a 
+            // default-constructed IOException).
+            throw new IOException(ex);
         }
     }
 

Modified: db/derby/code/branches/10.10/java/client/org/apache/derby/client/am/ClobLocatorInputStream.java
URL: http://svn.apache.org/viewvc/db/derby/code/branches/10.10/java/client/org/apache/derby/client/am/ClobLocatorInputStream.java?rev=1573334&r1=1573333&r2=1573334&view=diff
==============================================================================
--- db/derby/code/branches/10.10/java/client/org/apache/derby/client/am/ClobLocatorInputStream.java (original)
+++ db/derby/code/branches/10.10/java/client/org/apache/derby/client/am/ClobLocatorInputStream.java Sun Mar  2 18:05:49 2014
@@ -150,9 +150,10 @@ public class ClobLocatorInputStream exte
             currentPos += result.length;
             return result;
         } catch (SqlException ex) {
-            IOException ioEx = new IOException();
-            ioEx.initCause(ex);
-            throw ioEx;
+            // Passing cause as ctor argument ensures that the IOException 
+            // inherits the cause's message, (unlike invoking initCause() on a 
+            // default-constructed IOException).
+            throw new IOException(ex);
         }
     }
 

Modified: db/derby/code/branches/10.10/java/client/org/apache/derby/client/am/ClobLocatorReader.java
URL: http://svn.apache.org/viewvc/db/derby/code/branches/10.10/java/client/org/apache/derby/client/am/ClobLocatorReader.java?rev=1573334&r1=1573333&r2=1573334&view=diff
==============================================================================
--- db/derby/code/branches/10.10/java/client/org/apache/derby/client/am/ClobLocatorReader.java (original)
+++ db/derby/code/branches/10.10/java/client/org/apache/derby/client/am/ClobLocatorReader.java Sun Mar  2 18:05:49 2014
@@ -226,9 +226,10 @@ public class ClobLocatorReader extends j
             currentPos += result.length;
             return result;
         } catch (SqlException ex) {
-            IOException ioEx = new IOException();
-            ioEx.initCause(ex);
-            throw ioEx;
+            // Passing cause as ctor argument ensures that the IOException 
+            // inherits the cause's message, (unlike invoking initCause() on a 
+            // default-constructed IOException).
+            throw new IOException(ex);
         }
     }
 }

Modified: db/derby/code/branches/10.10/java/client/org/apache/derby/client/net/NetAgent.java
URL: http://svn.apache.org/viewvc/db/derby/code/branches/10.10/java/client/org/apache/derby/client/net/NetAgent.java?rev=1573334&r1=1573333&r2=1573334&view=diff
==============================================================================
--- db/derby/code/branches/10.10/java/client/org/apache/derby/client/net/NetAgent.java (original)
+++ db/derby/code/branches/10.10/java/client/org/apache/derby/client/net/NetAgent.java Sun Mar  2 18:05:49 2014
@@ -102,6 +102,13 @@ public class NetAgent extends Agent {
     public SqlException exceptionOpeningSocket_ = null;
     public SqlException exceptionConvertingRdbnam = null;
     
+    /**
+     * Flag which indicates that a writeChain has been started and data sent to
+     * the server.
+     * If true, starting a new write chain will throw a DisconnectException. 
+     * It is cleared when the write chain is ended.
+     */
+    private boolean writeChainIsDirty_ = false;
     //---------------------constructors/finalizer---------------------------------
     public NetAgent(NetConnection netConnection,
                     org.apache.derby.client.am.LogWriter logWriter) throws SqlException {
@@ -461,23 +468,41 @@ public class NetAgent extends Agent {
             throw de;
         }
     }
-
+    /**
+     * Marks the agent's write chain as dirty. A write chain is dirty when data
+     * from it has been sent to the server. A dirty write chain cannot be reset 
+     * and reused for another request until the remaining data has been sent to
+     * the server and the write chain properly ended. 
+     * 
+     * Resetting a dirty chain will cause the new request to be appended to the 
+     * unfinished request already at the server, which will likely lead to 
+     * cryptic syntax errors.
+     */
+    void markWriteChainAsDirty() {    
+        writeChainIsDirty_ = true;
+    }
+    
+    private void verifyWriteChainIsClean() throws DisconnectException {
+        if (writeChainIsDirty_) { 
+            throw new DisconnectException(this, 
+                new ClientMessageId(SQLState.NET_WRITE_CHAIN_IS_DIRTY));
+        }
+    }
     public void beginWriteChainOutsideUOW() throws SqlException {
+        verifyWriteChainIsClean();
         request_.initialize();
         writeDeferredResetConnection();
-        super.beginWriteChainOutsideUOW();
     }
 
     public void beginWriteChain(org.apache.derby.client.am.Statement statement) throws SqlException {
+        verifyWriteChainIsClean();
         request_.initialize();
         writeDeferredResetConnection();
         super.beginWriteChain(statement);
     }
 
-    protected void endWriteChain() {
-        super.endWriteChain();
-    }
-
+    protected void endWriteChain() {}
+    
     private void readDeferredResetConnection() throws SqlException {
         if (!netConnection_.resetConnectionAtFirstSql_) {
             return;
@@ -494,19 +519,19 @@ public class NetAgent extends Agent {
     }
 
     protected void beginReadChain(org.apache.derby.client.am.Statement statement) throws SqlException {
+        // Clear here as endWriteChain may not always be called
+        writeChainIsDirty_ = false;
         readDeferredResetConnection();
         super.beginReadChain(statement);
     }
 
     protected void beginReadChainOutsideUOW() throws SqlException {
+        // Clear here as endWriteChain may not always be called
+        writeChainIsDirty_ = false;
         readDeferredResetConnection();
         super.beginReadChainOutsideUOW();
     }
 
-    public void endReadChain() throws SqlException {
-        super.endReadChain();
-    }
-
     /**
      * Switches the current CCSID manager to UTF-8
      */

Modified: db/derby/code/branches/10.10/java/client/org/apache/derby/client/net/Request.java
URL: http://svn.apache.org/viewvc/db/derby/code/branches/10.10/java/client/org/apache/derby/client/net/Request.java?rev=1573334&r1=1573333&r2=1573334&view=diff
==============================================================================
--- db/derby/code/branches/10.10/java/client/org/apache/derby/client/net/Request.java (original)
+++ db/derby/code/branches/10.10/java/client/org/apache/derby/client/net/Request.java Sun Mar  2 18:05:49 2014
@@ -36,6 +36,7 @@ import java.io.ObjectOutputStream;
 import java.io.UnsupportedEncodingException;
 import java.nio.ByteBuffer;
 import java.nio.CharBuffer;
+import org.apache.derby.shared.common.error.ExceptionUtil;
 
 
 public class Request {
@@ -318,7 +319,27 @@ public class Request {
                 try {
                     bytesRead =
                         in.read(buffer.array(), buffer.position(), bytesToRead);
-                } catch (Exception e) {
+                } catch (IOException ioe) {
+                    if (netAgent_.getOutputStream() == null) {
+                        // The exception has taken down the connection, so we 
+                        // check if it was caused by attempting to 
+                        // read the stream from our own connection...
+                        for (Throwable t = ioe; t != null; t = t.getCause()) {
+                            if (t instanceof SqlException
+                                    && ((SqlException) t).getSQLState().equals(ExceptionUtil.getSQLStateFromIdentifier(SQLState.NET_WRITE_CHAIN_IS_DIRTY))) {
+                                throw new SqlException(netAgent_.logWriter_,
+                                        new ClientMessageId(SQLState.NET_LOCATOR_STREAM_PARAMS_NOT_SUPPORTED),
+                                        ioe, parameterIndex);
+                            }
+                        }
+                        // Something else has killed the connection, fast forward to despair...
+                        throw new SqlException(netAgent_.logWriter_,
+                                new ClientMessageId(SQLState.NET_DISCONNECT_EXCEPTION_ON_READ),
+                                ioe, parameterIndex, ioe.getMessage());
+                    }
+                    // The OutPutStream is still intact so try to finish request
+                    // with what we managed to read
+
                     status = DRDAConstants.STREAM_READ_ERROR;
                     padScalarStreamForError(leftToRead, bytesToRead,
                             writeEXTDTAStatusByte, status);
@@ -327,7 +348,7 @@ public class Request {
                         new SqlException(
                             netAgent_.logWriter_,
                             new ClientMessageId(SQLState.NET_EXCEPTION_ON_READ),
-                            parameterIndex, e.getMessage(), e));
+                            parameterIndex, ioe.getMessage(), ioe));
 
                     return;
                 }
@@ -1207,6 +1228,7 @@ public class Request {
 
     protected void sendBytes(java.io.OutputStream socketOutputStream) throws java.io.IOException {
         try {
+            netAgent_.markWriteChainAsDirty();
             socketOutputStream.write(buffer.array(), 0, buffer.position());
             socketOutputStream.flush();
         } finally {

Modified: db/derby/code/branches/10.10/java/engine/org/apache/derby/loc/messages.xml
URL: http://svn.apache.org/viewvc/db/derby/code/branches/10.10/java/engine/org/apache/derby/loc/messages.xml?rev=1573334&r1=1573333&r2=1573334&view=diff
==============================================================================
--- db/derby/code/branches/10.10/java/engine/org/apache/derby/loc/messages.xml (original)
+++ db/derby/code/branches/10.10/java/engine/org/apache/derby/loc/messages.xml Sun Mar  2 18:05:49 2014
@@ -5216,6 +5216,23 @@ ln=lower-case two-letter ISO-639 languag
                 <arg>targetClassName</arg>
             </msg>
 
+            <msg>
+                <name>XN022.C</name>
+                <text>A write chain that has transmitted data to the server cannot be reset until the request is finished and the chain terminated.</text>
+            </msg>
+            
+            <msg>
+                <name>XN023.C</name>
+                <text>The stream specified by parameter #{0} is locator-based and requires a nested request on the same connection to be materialized. This is not supported.</text>
+                <arg>number</arg>
+            </msg>
+            
+            <msg>
+                <name>XN024.C</name>
+                <text>Encountered an exception which terminated the connection, while reading from the stream specified by parameter #{0}. The Exception had this message: '{1}'.</text>
+                <arg>number</arg>
+                <arg>messageText</arg>
+            </msg>
         </family>
 
 

Modified: db/derby/code/branches/10.10/java/shared/org/apache/derby/shared/common/reference/SQLState.java
URL: http://svn.apache.org/viewvc/db/derby/code/branches/10.10/java/shared/org/apache/derby/shared/common/reference/SQLState.java?rev=1573334&r1=1573333&r2=1573334&view=diff
==============================================================================
--- db/derby/code/branches/10.10/java/shared/org/apache/derby/shared/common/reference/SQLState.java (original)
+++ db/derby/code/branches/10.10/java/shared/org/apache/derby/shared/common/reference/SQLState.java Sun Mar  2 18:05:49 2014
@@ -1620,6 +1620,9 @@ public interface SQLState {
     String NET_XARETVAL_ERROR                                       = "XN019.S";
     String NET_MARSHALLING_UDT_ERROR                     = "XN020.S";
     String NET_UDT_COERCION_ERROR                               = "XN021.S";
+    String NET_WRITE_CHAIN_IS_DIRTY                                 = "XN022.C";
+    String NET_LOCATOR_STREAM_PARAMS_NOT_SUPPORTED                  = "XN023.C";
+    String NET_DISCONNECT_EXCEPTION_ON_READ                         = "XN024.C";
     
     // XML - Derby-specific XML errors not covered by
     // SQL standard.

Modified: db/derby/code/branches/10.10/java/testing/org/apache/derbyTesting/functionTests/tests/lang/ErrorCodeTest.java
URL: http://svn.apache.org/viewvc/db/derby/code/branches/10.10/java/testing/org/apache/derbyTesting/functionTests/tests/lang/ErrorCodeTest.java?rev=1573334&r1=1573333&r2=1573334&view=diff
==============================================================================
--- db/derby/code/branches/10.10/java/testing/org/apache/derbyTesting/functionTests/tests/lang/ErrorCodeTest.java (original)
+++ db/derby/code/branches/10.10/java/testing/org/apache/derbyTesting/functionTests/tests/lang/ErrorCodeTest.java Sun Mar  2 18:05:49 2014
@@ -201,6 +201,9 @@ public final class ErrorCodeTest extends
         		{"XJ05B","JDBC attribute '{0}' has an invalid value '{1}', valid values are '{2}'.","40000"},
         		{"XJ081","Conflicting create/restore/recovery attributes specified.","40000"},
         		{"XJ213","The traceLevel connection property does not have a valid format for a number.","40000"},
+        		{"XN022","A write chain that has transmitted data to the server cannot be reset until the request is finished and the chain terminated.","40000"},
+        		{"XN023","The stream specified by parameter #{0} is locator-based and requires a nested request on the same connection to be materialized. This is not supported.","40000"},
+        		{"XN024","Encountered an exception which terminated the connection, while reading from the stream specified by parameter #{0}. The Exception had this message: '{1}'.","40000"},
         		{"XRE20","Failover performed successfully for database '{0}', the database has been shutdown.","45000"},
         		{"XSDB0","Unexpected exception on in-memory page {0}","45000"},
         		{"XSDB1","Unknown page format at page {0}","45000"},

Modified: db/derby/code/branches/10.10/java/testing/org/apache/derbyTesting/functionTests/tests/largedata/LobLimitsTest.java
URL: http://svn.apache.org/viewvc/db/derby/code/branches/10.10/java/testing/org/apache/derbyTesting/functionTests/tests/largedata/LobLimitsTest.java?rev=1573334&r1=1573333&r2=1573334&view=diff
==============================================================================
--- db/derby/code/branches/10.10/java/testing/org/apache/derbyTesting/functionTests/tests/largedata/LobLimitsTest.java (original)
+++ db/derby/code/branches/10.10/java/testing/org/apache/derbyTesting/functionTests/tests/largedata/LobLimitsTest.java Sun Mar  2 18:05:49 2014
@@ -1082,18 +1082,22 @@ public class LobLimitsTest extends BaseJ
         long dlen = rs.getLong(2);
         assertEquals("FAIL - MISMATCH LENGTHS GOT " + l + " expected "
                 + dlen + " for row in CLOBTBL with ID=" + id, dlen, l);
-        // DERBY-5317 cannot use setCharacterStream with value from
-        // Clob.getCharacterStream because server will try to stream
-        // lob to and from server at the same time. setClob can be
-        // used as a work around.
-        if (!usingDerbyNetClient()) {
-            PreparedStatement psUpd =
-                    prepareStatement("update CLOBTBL set content=?, " +
-                            "dlen =? where id = ?");
-            psUpd.setCharacterStream(1, value.getCharacterStream(), (int) l);
-            psUpd.setLong(2, l);
-            psUpd.setInt(3, updateId);
-
+                
+        PreparedStatement psUpd =
+                prepareStatement("update CLOBTBL set content=?, "
+                + "dlen =? where id = ?");
+        psUpd.setCharacterStream(1, value.getCharacterStream(), (int) l);
+        psUpd.setLong(2, l);
+        psUpd.setInt(3, updateId);
+        if (usingDerbyNetClient()) {
+            // DERBY-5317 cannot use setCharacterStream with value from
+            // Clob.getCharacterStream because server will try to stream
+            // lob to and from server at the same time. setClob can be
+            // used as a work around.
+            // Verify that new error is thrown 
+            assertPreparedStatementError("XN023", psUpd);
+            return;
+        } else {
             assertUpdateCount(psUpd, 1);
         }
         commit();