/**
* Alipay.com Inc.
* Copyright (c) 2004-2012 All Rights Reserved.
*/
package com.alipay.zdal.client.jdbc;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.List;
import java.util.Map;
import javax.sql.DataSource;
import org.apache.log4j.Logger;
import com.alipay.zdal.client.dispatcher.SqlDispatcher;
import com.alipay.zdal.common.OperationDBType;
/**
*
* @author ����
* @version $Id: RetryableTStatement.java, v 0.1 2014-1-6 ����01:49:21 Exp $
*/
public class RetryableTStatement extends ZdalStatement {
private static final Logger logger = Logger
.getLogger(RetryableTStatement.class);
public boolean redirectToWriteDatabase = false;
public RetryableTStatement(SqlDispatcher writeDispatcher, SqlDispatcher readDispatcher) {
super(writeDispatcher, readDispatcher);
}
// @Override
// /*
// * TEST required :����1�����ԣ��������ԣ������ߵ�43�к�ݹ�������׳��쳣�����
// *
// * �����ᱣ֤dbIndex->Connection+datasource+dbselector map�е�Datasource�ض���ֵ
// */
// protected void createConnection(DBSelector dbselector, String dbIndex,
// RetringContext retringContext) throws SQLException {
//
// try {
// // �������Ӳ��ŵ�TConnection ��map dbSelectorID->connection+datasource+dbSelector��
// super.createConnection(dbselector, dbIndex, retringContext);
//
// } catch (RetrySQLException e) {
//
// retringContext.addSQLException(e.getSqlException());
//
// validRetryable(retringContext, e.getSqlException());
//
// dbselector = removeCurrentDataSourceFromDbSelector( dbselector, e.getCurrentDataSource(),
// retringContext);
//
// // ���������ӳ������������������,������Ƴ���ѭ��Ƕ��ʱ����Ϊ�ܹ�ȡ��ConnectionAndDataSource��������������������������
// getConnectionProxy().removeConnectionAndDatasourceByID(dbIndex);
// // ���removeʧ�ܻ�Ϊд�������Ѿ�ֱ���׳��� ������ﶼ�dzɹ���
// createConnection(dbselector, dbIndex, retringContext);
// }
// }
// protected boolean reachMaxRetryableTimes(RetringContext retringContext) {
// return retringContext.getAlreadyRetringTimes() > retringTimes;
// }
@Override
protected Statement createStatementInternal(Connection connection, String dbIndex,
Map<DataSource, SQLException> failedDataSources)
throws SQLException {
try {
return super.createStatementInternal(connection, dbIndex, failedDataSources);
} catch (SQLException e) {
//retringContext.addSQLException(e);
//validRetryable(retringContext, e);
//added by fanzeng, ��Ҫ��һ����֤�˴��Ƿ���Ҫ����
validRetryable(dbIndex, e, OperationDBType.readFromDb);
if (failedDataSources != null) {
ConnectionAndDatasource connectionAndDatasource = getConnectionProxy()
.getConnectionAndDatasourceByDBSelectorID(dbIndex);
failedDataSources.put(connectionAndDatasource.parentDataSource, e);
} else {
//����������ʱ����Ҫ���ԣ�failedDataSourcesΪnullֵ��ֱ�ӽ��쳣�׳�
//added by fanzeng.
throw e;
}
connection = tryToConnectToOtherAvailableDataSource(dbIndex, failedDataSources);
return createStatementInternal(connection, dbIndex, failedDataSources);
}
}
@Override
protected void queryAndAddResultToCollection(String dbSelectorId,
List<ResultSet> actualResultSets,
SqlAndTable targetSql, Statement stmt,
Map<DataSource, SQLException> failedDataSources)
throws SQLException {
try {
super.queryAndAddResultToCollection(dbSelectorId, actualResultSets, targetSql, stmt,
failedDataSources);
} catch (SQLException e) {
//retringContext.addSQLException(e);
//validRetryable(retringContext,e);
validRetryable(dbSelectorId, e, OperationDBType.readFromDb);
if (failedDataSources != null) {
ConnectionAndDatasource connectionAndDatasource = getConnectionProxy()
.getConnectionAndDatasourceByDBSelectorID(dbSelectorId);
failedDataSources.put(connectionAndDatasource.parentDataSource, e);
} else {
//����������ʱ����Ҫ���ԣ�failedDataSourcesΪnullֵ��ֱ�ӽ��쳣�׳�
//added by fanzeng.
throw e;
}
Connection connection = tryToConnectToOtherAvailableDataSource(dbSelectorId,
failedDataSources);
stmt = createStatementInternal(connection, dbSelectorId, failedDataSources);
queryAndAddResultToCollection(dbSelectorId, actualResultSets, targetSql, stmt,
failedDataSources);
}
}
/**
* 1.�ȴ�parent TConnection�����л�ȡconnectionsMap.<br>
* 2.����DBSelectorId�ҵ���Ӧ��connection��Ϣ��<br>
* 3.�Ƴ�connectionsMap���������Datasource.<br>
* 4.�Ƴ�dbSelector�з��������datasource .(����dbSelectorһ�Σ�Ȼ���Ƴ�).<br>
* 5.����dbSelectorId���µ�dbSelector.���°���Ȩ��ѡ��һ��datasource.<br>
* 6.��ȡ���ӣ�����connectionsMap.<br>
* 7.��������<br>
*
* @param dbIndex
* @param retringContext
* @param e
* @return
* @throws SQLException
*/
protected Connection tryToConnectToOtherAvailableDataSource(
String dbIndex,
Map<DataSource, SQLException> failedDataSources)
throws SQLException {
Connection connection;
//��TConnection��connectionsMap��ȡ����connection
ConnectionAndDatasource connectionAndDatasource = getConnectionProxy()
.getConnectionAndDatasourceByDBSelectorID(dbIndex);
DBSelector dbSelector = connectionAndDatasource.dbSelector;
//DataSource ds = connectionAndDatasource.parentDataSource;
//��dbSelector���Ƴ���ǰ�������datasource
//dbSelector = removeCurrentDataSourceFromDbSelector(dbSelector, ds,
// retringContext);
//�Ӹ������Ƴ�
getConnectionProxy().removeConnectionAndDatasourceByID(dbIndex);
// ���½�������, exclueDataSource = connectionAndDatasource.parentDataSource
createConnection(dbSelector, dbIndex, failedDataSources);
connection = getConnectionProxy().getConnectionAndDatasourceByDBSelectorID(dbIndex).connection;
return connection;
}
/**
* dbselector��֧������ֱ�����쳣
* @param dbSelectorId
* @param currentException
* @throws SQLException
*/
protected void validRetryable(String dbSelectorId, SQLException currentException,
OperationDBType type) throws SQLException {
ConnectionAndDatasource connectionAndDatasource = getConnectionProxy()
.getConnectionAndDatasourceByDBSelectorID(dbSelectorId);
if (!connectionAndDatasource.dbSelector.isSupportRetry(type)) {
logger.warn("������������ԣ�dbSelectorId=" + dbSelectorId + ",type=" + type, currentException);
throw currentException;
}
}
/**
* �Ӻ�ѡselector���Ƴ���ǰdatasource.
*
* Ϊ�˱�֤����dbSelector����selector����ԭ�е�����״̬��ÿ���Ƴ�ʱ�����ȸ���һ�� ������dbSelector�������д���
*
* ����Ѿ�û�б�ѡ���Ϊһ��д�� ��ֱ���׳��쳣
*
* @param exceptions
* @return
* @throws SQLException
*/
/*public DBSelector removeCurrentDataSourceFromDbSelector(
DBSelector dbSelector,
DataSource currentDataSource, RetringContext retringContext)
throws SQLException {
dbSelector = dbSelector.copyAndRemove(currentDataSource);
if (dbSelector == null) {
// ��ʾû�ж���Ŀ�ɹ�ѡ��
ExceptionUtils.throwSQLException(retringContext.getSqlExceptions(),
"getConnection", Collections.emptyList());
} else {
retringContext.addRetringTimes();
}
return dbSelector;
}*/
// /**
// * ��֤�Ƿ���Ҫ����
// *
// * @param retringContext
// * @param currentException
// * @throws SQLException
// */
// protected void validRetryable(RetringContext retringContext,
// SQLException currentException) throws SQLException {
// if(retringContext == null){
// ExceptionUtils.throwSQLException(currentException,
// "getConnection", Collections.emptyList());
// }
// if (!retringContext.isExceptionFatal(currentException)) {
// ExceptionUtils.throwSQLException(retringContext.getSqlExceptions(),
// "getConnection", Collections.emptyList());
// }
// if (!retringContext.isNeedRetry()) {
// // �����д����,��ô����Ҫ���ԣ�ֱ���׳�
// ExceptionUtils.throwSQLException(retringContext.getSqlExceptions(),
// "getConnection", Collections.emptyList());
// }
// // ������Դ����������ƣ�ֱ���״��ȥ
// if (reachMaxRetryableTimes(retringContext)) {
// ExceptionUtils.throwSQLException(retringContext.getSqlExceptions(),
// "getConnection", Collections.emptyList());
// }
// }
}