package com.ctrip.platform.dal.dao.task;
import static com.ctrip.platform.dal.dao.helper.DalShardingHelper.detectDistributedTransaction;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.concurrent.Callable;
import com.ctrip.platform.dal.dao.DalHints;
import com.ctrip.platform.dal.dao.ResultMerger;
import com.ctrip.platform.dal.dao.client.DalWatcher;
import com.ctrip.platform.dal.exceptions.DalException;
import com.ctrip.platform.dal.exceptions.ErrorCode;
public class DalSingleTaskRequest<T> implements DalRequest<int[]>{
private String logicDbName;
private DalHints hints;
private boolean isList;
private T rawPojo;
private List<T> rawPojos;
private List<Map<String, ?>> daoPojos;
private SingleTask<T> task;
private DalSingleTaskRequest(String logicDbName, DalHints hints, SingleTask<T> task) {
this.logicDbName = logicDbName;
this.task = task;
this.hints = hints;
}
public DalSingleTaskRequest(String logicDbName, DalHints hints, T rawPojo, SingleTask<T> task) {
this(logicDbName, hints, task);
this.rawPojo = rawPojo;
isList = false;
}
public DalSingleTaskRequest(String logicDbName, DalHints hints, List<T> rawPojos, SingleTask<T> task) {
this(logicDbName, hints, task);
this.rawPojos = rawPojos;
isList = true;
}
@Override
public void validate() throws SQLException {
if(isList && null == rawPojos)
throw new DalException(ErrorCode.ValidatePojoList);
if(isList == false && null == rawPojo)
throw new DalException(ErrorCode.ValidatePojo);
if(task == null)
throw new DalException(ErrorCode.ValidateTask);
if(isList == false){
rawPojos = new ArrayList<>(1);
rawPojos.add(rawPojo);
}
daoPojos = task.getPojosFields(rawPojos);
detectDistributedTransaction(logicDbName, hints, daoPojos);
}
@Override
public boolean isCrossShard() {
// The single task request is always executed as if the pojos are not corss shard even they really are.
return false;
}
@Override
public Callable<int[]> createTask() {
return new SingleTaskCallable<>(hints, daoPojos, rawPojos, task);
}
@Override
public Map<String, Callable<int[]>> createTasks() throws SQLException {
throw new DalException(ErrorCode.NotSupported);
}
@Override
public ResultMerger<int[]> getMerger() {
// Not support for now. Maybe support for new hints in the future
return null;
}
private static class SingleTaskCallable<T> implements Callable<int[]> {
private DalHints hints;
private List<Map<String, ?>> daoPojos;
private List<T> rawPojos;
private SingleTask<T> task;
public SingleTaskCallable(DalHints hints, List<Map<String, ?>> daoPojos, List<T> rawPojos, SingleTask<T> task){
this.hints = hints;
this.daoPojos = daoPojos;
this.rawPojos = rawPojos;
this.task = task;
}
@Override
public int[] call() throws Exception {
int[] counts = new int[daoPojos.size()];
DalHints localHints = hints.clone();// To avoid shard id being polluted by each pojos
for (int i = 0; i < daoPojos.size(); i++) {
DalWatcher.begin();// TODO check if we needed
try {
counts[i] = task.execute(localHints, daoPojos.get(i), rawPojos.get(i));
} catch (SQLException e) {
hints.handleError("Error when execute single pojo operation", e);
}
}
return counts;
}
}
}