package com.taobao.tddl.executor; import java.util.concurrent.Callable; import java.util.concurrent.ExecutorService; import java.util.concurrent.Future; import com.taobao.tddl.common.exception.TddlException; import com.taobao.tddl.common.exception.TddlRuntimeException; import com.taobao.tddl.common.model.lifecycle.AbstractLifecycle; import com.taobao.tddl.executor.common.ExecutionContext; import com.taobao.tddl.executor.common.ExecutorContext; import com.taobao.tddl.executor.cursor.ISchematicCursor; import com.taobao.tddl.executor.cursor.ResultCursor; import com.taobao.tddl.executor.spi.ITopologyExecutor; import com.taobao.tddl.optimizer.OptimizerContext; import com.taobao.tddl.optimizer.core.plan.IDataNodeExecutor; public class TopologyExecutor extends AbstractLifecycle implements ITopologyExecutor { public String dataNode = "localhost"; @Override public Future<ISchematicCursor> execByExecPlanNodeFuture(final IDataNodeExecutor qc, final ExecutionContext executionContext) throws TddlException { final ExecutorContext executorContext = ExecutorContext.getContext(); final OptimizerContext optimizerContext = OptimizerContext.getContext(); ExecutorService concurrentExecutors = executionContext.getExecutorService(); if (concurrentExecutors == null) { throw new TddlRuntimeException("concurrentExecutors is null, cannot query parallelly"); } Future<ISchematicCursor> task = concurrentExecutors.submit(new Callable<ISchematicCursor>() { @Override public ISchematicCursor call() throws Exception { ExecutorContext.setContext(executorContext); OptimizerContext.setContext(optimizerContext); return execByExecPlanNode(qc, executionContext); } }); return task; } @Override public ISchematicCursor execByExecPlanNode(IDataNodeExecutor qc, ExecutionContext executionContext) throws TddlException { return getGroupExecutor(qc, executionContext).execByExecPlanNode(qc, executionContext); } private IExecutor getGroupExecutor(IDataNodeExecutor qc, ExecutionContext executionContext) { if (executionContext == null) executionContext = new ExecutionContext(); String group = qc.getDataNode(); if (group == null) { throw new RuntimeException("group in plan is null, plan is:\n" + qc); } return getGroupExecutor(group, executionContext); } private IExecutor getGroupExecutor(String group, ExecutionContext executionContext) { IExecutor executor = null; executor = ExecutorContext.getContext().getTopologyHandler().get(group); if (executor == null) { throw new RuntimeException("cannot find executor for group:" + group + "\ngroups:\n" + ExecutorContext.getContext().getTopologyHandler()); } if (!executionContext.isAutoCommit()) { // sql不在同一个节点上,是跨机事务,报错。 if (executionContext.getTransactionGroup() != null && !executionContext.getTransactionGroup().equals(group)) { throw new TddlRuntimeException("transaction across group is not supported, aim group is:" + group + ", current transaction group is:" + executionContext.getTransactionGroup()); } } return executor; } @Override public ResultCursor commit(ExecutionContext executionContext) throws TddlException { ResultCursor rc = new ResultCursor(null, executionContext); if (executionContext.getTransactionGroup() == null) { return rc; } return getGroupExecutor(executionContext.getTransactionGroup(), executionContext).commit(executionContext); } @Override public ResultCursor rollback(ExecutionContext executionContext) throws TddlException { ResultCursor rc = new ResultCursor(null, executionContext); if (executionContext.getTransactionGroup() == null) { return rc; } return getGroupExecutor(executionContext.getTransactionGroup(), executionContext).rollback(executionContext); } @Override public Future<ResultCursor> commitFuture(final ExecutionContext executionContext) throws TddlException { final ExecutorContext executorContext = ExecutorContext.getContext(); final OptimizerContext optimizerContext = OptimizerContext.getContext(); ExecutorService concurrentExecutors = executionContext.getExecutorService(); if (concurrentExecutors == null) { throw new TddlRuntimeException("concurrentExecutors is null, cannot query parallelly"); } Future<ResultCursor> task = concurrentExecutors.submit(new Callable<ResultCursor>() { @Override public ResultCursor call() throws Exception { ExecutorContext.setContext(executorContext); OptimizerContext.setContext(optimizerContext); return commit(executionContext); } }); return task; } @Override public Future<ResultCursor> rollbackFuture(final ExecutionContext executionContext) throws TddlException { final ExecutorContext executorContext = ExecutorContext.getContext(); final OptimizerContext optimizerContext = OptimizerContext.getContext(); ExecutorService concurrentExecutors = executionContext.getExecutorService(); if (concurrentExecutors == null) { throw new TddlRuntimeException("concurrentExecutors is null, cannot query parallelly"); } Future<ResultCursor> task = concurrentExecutors.submit(new Callable<ResultCursor>() { @Override public ResultCursor call() throws Exception { ExecutorContext.setContext(executorContext); OptimizerContext.setContext(optimizerContext); return rollback(executionContext); } }); return task; } @Override public String getDataNode() { return dataNode; } public void setDataNode(String dataNode) { this.dataNode = dataNode; } }