diff --git a/src/main/java/com/alibaba/druid/pool/vendor/OracleExceptionSorter.java b/src/main/java/com/alibaba/druid/pool/vendor/OracleExceptionSorter.java index da5fd7e820..43b9afede9 100644 --- a/src/main/java/com/alibaba/druid/pool/vendor/OracleExceptionSorter.java +++ b/src/main/java/com/alibaba/druid/pool/vendor/OracleExceptionSorter.java @@ -17,42 +17,112 @@ package com.alibaba.druid.pool.vendor; import java.io.Serializable; import java.sql.SQLException; +import java.util.HashSet; +import java.util.Set; import com.alibaba.druid.pool.ExceptionSorter; +import com.alibaba.druid.support.logging.Log; +import com.alibaba.druid.support.logging.LogFactory; /** * Implementation of ExceptionSorter for Oracle. */ public class OracleExceptionSorter implements ExceptionSorter, Serializable { + private final static Log LOG = LogFactory.getLog(OracleExceptionSorter.class); + private static final long serialVersionUID = -9146226891418913174L; + private Set fatalErrorCodes = new HashSet(); + public OracleExceptionSorter(){ + String property = System.getProperty("druid.oracle.fatalErrorCodes"); + if (property != null) { + String[] items = property.split("\\,"); + for (String item : items) { + if (item != null && item.length() > 0) { + try { + int code = Integer.parseInt(item); + fatalErrorCodes.add(code); + } catch (NumberFormatException e) { + LOG.error("parse druid.oracle.fatalErrorCodes error", e); + } + } + } + } + } + + public Set getFatalErrorCodes() { + return fatalErrorCodes; + } + + public void setFatalErrorCodes(Set fatalErrorCodes) { + this.fatalErrorCodes = fatalErrorCodes; } public boolean isExceptionFatal(final SQLException e) { final int error_code = Math.abs(e.getErrorCode()); // I can't remember if the errors are negative or positive. - if ((error_code == 28) // session has been killed - || (error_code == 600) // Internal oracle error - || (error_code == 1012) // not logged on - || (error_code == 1014) // Oracle shutdown in progress - || (error_code == 1033) // Oracle initialization or shutdown in progress - || (error_code == 1034) // Oracle not available - || (error_code == 1035) // ORACLE only available to users with RESTRICTED SESSION privilege - || (error_code == 1089) // immediate shutdown in progress - no operations are permitted - || (error_code == 1090) // shutdown in progress - connection is not permitted - || (error_code == 1092) // ORACLE instance terminated. Disconnection forced - || (error_code == 1094) // ALTER DATABASE CLOSE in progress. Connections not permitted - || (error_code == 2396) // exceeded maximum idle time, please connect again - || (error_code == 3106) // fatal two-task communication protocol error - || (error_code == 3111) // break received on communication channel - || (error_code == 3113) // end-of-file on communication channel - || (error_code == 3114) // not connected to ORACLE - || (error_code >= 12100 && error_code <= 12299) // TNS issues - || (error_code == 17410) // No more data to read from socket - ) { - return true; + switch (error_code) { + case 28: // your session has been killed + case 600: // Internal oracle error + case 1012: // not logged on + case 1014: // Oracle shutdown in progress + case 1033: // Oracle initialization or shutdown in progress + case 1034: // Oracle not available + case 1035: // ORACLE only available to users with RESTRICTED SESSION privilege + case 1089: // immediate shutdown in progress - no operations are permitted + case 1090: // shutdown in progress - connection is not permitted + case 1092: // ORACLE instance terminated. Disconnection forced + case 1094: // ALTER DATABASE CLOSE in progress. Connections not permitted + case 2396: // exceeded maximum idle time, please connect again + case 3106: // fatal two-task communication protocol error + case 3111: // break received on communication channel + case 3113: // end-of-file on communication channel + case 3114: // not connected to ORACLE + + case 3134: // Connections to this server version are no longer supported. + case 3135: // connection lost contact + case 3136: // inbound connection timed out + case 3138: // Connection terminated due to security policy violation + case 3142: // Connection was lost for the specified session and serial number. This is either due to session + // being killed or network problems. + case 3143: // Connection was lost for the specified process ID and thread ID. This is either due to session + // being killed or network problems. + case 3144: // Connection was lost for the specified process ID. This is either due to session being killed + // or network problems. + case 3145: // I/O streaming direction error + case 3149: // Invalid Oracle error code, Cause: An invalid Oracle error code was received by the server. + + case 6801: // TLI Driver: listen for SPX server reconnect failed + case 6802: // TLI Driver: could not open the /etc/netware/yellowpages file + case 6805: // TLI Driver: could not send datagram SAP packet for SPX + case 9918: // Unable to get user privileges from SQL*Net + case 9920: // Unable to get sensitivity label from connection + case 9921: // Unable to get information label from connection + + // TTC(Two-Task Common) ERROR CODE + case 17001: // Internal Error + case 17002: // Io exception + case 17008: // Closed Connection + case 17024: // No data read + case 17089: // internal error + case 17409: // invalid buffer length + case 17410: // No more data to read from socket + case 17416: // FATAl + + case 25407: // connection terminated + case 25408: // can not safely replay call + case 25409: // failover happened during the network operation,cannot continue + case 25425: // connection lost during rollback + case 29276: // transfer timeout + case 30676: // socket read or write failed + return true; + default: + if (error_code >= 12100 && error_code <= 12299) { // TNS issues + return true; + } + break; } final String error_text = (e.getMessage()).toUpperCase(); @@ -60,12 +130,18 @@ public class OracleExceptionSorter implements ExceptionSorter, Serializable { // Exclude oracle user defined error codes (20000 through 20999) from consideration when looking for // certain strings. - if ((error_code < 20000 || error_code >= 21000) - && ((error_text.indexOf("SOCKET") > -1) // for control socket error - || (error_text.indexOf("CONNECTION HAS ALREADY BEEN CLOSED") > -1) || (error_text.indexOf("BROKEN PIPE") > -1))) { - return true; + if ((error_code < 20000 || error_code >= 21000)) { + if ((error_text.indexOf("SOCKET") > -1) // for control socket error + || (error_text.indexOf("套接字") > -1) // for control socket error + || (error_text.indexOf("CONNECTION HAS ALREADY BEEN CLOSED") > -1) // + || (error_text.indexOf("BROKEN PIPE") > -1) // + || (error_text.indexOf("管道已结束") > -1) // + ) { + return true; + } + } - return false; + return fatalErrorCodes.contains(error_code); } } diff --git a/src/test/java/com/alibaba/druid/bvt/pool/exception/OracleExceptionSorter_userDefined.java b/src/test/java/com/alibaba/druid/bvt/pool/exception/OracleExceptionSorter_userDefined.java new file mode 100644 index 0000000000..3ec9212e32 --- /dev/null +++ b/src/test/java/com/alibaba/druid/bvt/pool/exception/OracleExceptionSorter_userDefined.java @@ -0,0 +1,34 @@ +package com.alibaba.druid.bvt.pool.exception; + +import java.sql.SQLException; + +import junit.framework.TestCase; + +import org.junit.Assert; + +import com.alibaba.druid.pool.vendor.OracleExceptionSorter; + +public class OracleExceptionSorter_userDefined extends TestCase { + + protected void setUp() throws Exception { + System.setProperty("druid.oracle.fatalErrorCodes", "1,2,3,a,"); + } + + protected void tearDown() throws Exception { + System.clearProperty("druid.oracle.fatalErrorCodes"); + } + + public void test_userDefinedErrorCodes() throws Exception { + OracleExceptionSorter sorter = new OracleExceptionSorter(); + Assert.assertEquals(3, sorter.getFatalErrorCodes().size()); + Assert.assertTrue(sorter.getFatalErrorCodes().contains(1)); + Assert.assertTrue(sorter.getFatalErrorCodes().contains(2)); + Assert.assertTrue(sorter.getFatalErrorCodes().contains(3)); + + Assert.assertTrue(sorter.isExceptionFatal(new SQLException("xx", "xx", 1))); + Assert.assertTrue(sorter.isExceptionFatal(new SQLException("xx", "xx", 2))); + Assert.assertTrue(sorter.isExceptionFatal(new SQLException("xx", "xx", 3))); + Assert.assertFalse(sorter.isExceptionFatal(new SQLException("xx", "xx", 4))); + Assert.assertTrue(sorter.isExceptionFatal(new SQLException("xx", "xx", 28))); + } +}