improve oracle exception sorter error code

This commit is contained in:
wenshao
2013-05-02 20:36:15 +08:00
parent c38ac3088f
commit 650a5b451a
2 changed files with 135 additions and 25 deletions
@@ -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<Integer> fatalErrorCodes = new HashSet<Integer>();
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<Integer> getFatalErrorCodes() {
return fatalErrorCodes;
}
public void setFatalErrorCodes(Set<Integer> 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);
}
}
@@ -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)));
}
}