package com.alibaba.doris.admin.service.expansion.processor;
import java.util.List;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import com.alibaba.doris.admin.core.AdminServiceLocator;
import com.alibaba.doris.admin.dataobject.PhysicalNodeDO;
import com.alibaba.doris.admin.service.common.AdminServiceException;
import com.alibaba.doris.admin.service.common.migrate.MigrateThread;
import com.alibaba.doris.admin.service.common.migrate.manager.MigrateManager;
import com.alibaba.doris.admin.service.common.migrate.status.MigrateStatus;
import com.alibaba.doris.admin.service.common.node.NodesManager;
import com.alibaba.doris.admin.service.expansion.migrate.ExpansionMigrateThread;
import com.alibaba.doris.common.NodeRouteStatus;
import com.alibaba.doris.common.StoreNodeSequenceEnum;
/**
* 扩容迁移Processor
*
* @author frank
*/
public class ExpansionMigrateProcessor {
private static final Log log = LogFactory
.getLog(ExpansionMigrateProcessor.class);
private static ExpansionMigrateProcessor instance = new ExpansionMigrateProcessor();
private boolean isMainAdmin = AdminServiceLocator.getAdminService()
.isMasterAdmin();
private ExpansionMigrateProcessor() {
}
public static ExpansionMigrateProcessor getInstance() {
return instance;
}
/**
* 启动扩容迁移任务,任务启动立即返回,该方法可重复调用,每次调用都会重发迁移命令,reset迁移状态<br>
* 如果已经在扩容迁移中,输入的新增节点被忽略
*
* @param newNodes 序列中新增的节点
* @param sequence 要扩容的序列,仅正常序列和临时序列
* @throws AdminServiceException 扩容任务不能启动
*/
public synchronized void migerate(List<String> newNodePhysicalIdList, StoreNodeSequenceEnum sequence)
throws AdminServiceException {
if (!isMainAdmin) {
if (log.isErrorEnabled()) {
log.error("This is backup admin server, doesn't support expansion migrating task.");
}
throw new AdminServiceException("This is backup admin server, doesn't support expansion migrating task.");
}
if (newNodePhysicalIdList == null || newNodePhysicalIdList.isEmpty() || sequence == null) {
if(log.isErrorEnabled()){
log.error("illegal input param! newNodePhysicalIdList:"+newNodePhysicalIdList+"sequence:"+sequence);
}
throw new AdminServiceException("illegal input param! newNodePhysicalIdList:"+newNodePhysicalIdList+"sequence:"+sequence);
}
if (log.isInfoEnabled()) {
log.info("execute migerate in " + sequence + " for " + newNodePhysicalIdList);
}
NodesManager.getInstance().reLoadNodes();
List<PhysicalNodeDO> nodeList = NodesManager.getInstance().getNodeListBySequence(sequence);
// 检查序列中现有节点,是否可进行扩容迁移
for (PhysicalNodeDO node : nodeList) {
// 如果节点路由状态不OK,不得扩容
if (node.getStatus() != NodeRouteStatus.OK.getValue()) {
throw new AdminServiceException("Node("+node.getPhysicalId() + ") is NG, couldn't expansion.");
}
// 如果有正在迁移的Node,不得扩容
MigrateStatus ms = MigrateManager.getInstance().getMigerateStatus(node.getPhysicalId());
if (ms != null) {
throw new AdminServiceException(node.getPhysicalId()
+ " node is resolving failover or expanding,forbidden to expansion");
}
}
// 当前序列已在迁移中,不可迁移
if (MigrateManager.getInstance().getMigerateThread(String.valueOf(sequence.getValue())) != null) {
throw new AdminServiceException(sequence + " is expanding!");
}
//这个逻辑不会被执行,先保留
if (isMigrating(sequence)) {// 序列正在迁移中,kill & restart,
MigrateThread migThread = getMigThread(sequence);
migThread.over();
if (log.isWarnEnabled()) {
log.warn(sequence + " is migerating,kill and restart.");
}
}
// 启动迁移线程
ExpansionMigrateThread migThread = new ExpansionMigrateThread(newNodePhysicalIdList, sequence);
// migThread.start();
if (log.isInfoEnabled()) {
log.info("start migerate thread " + migThread);
}
}
/**
* 启动扩容迁移(重新启动未完成迁移)
*
* @param sequence
* @throws AdminServiceException
*/
public synchronized void migerate(StoreNodeSequenceEnum sequence) throws AdminServiceException {
if (!isMainAdmin) {
if (log.isErrorEnabled()) {
log.error("This is backup admin server, doesn't support expansion migrating task.");
}
throw new AdminServiceException("This is backup admin server, doesn't support expansion migrating task.");
}
MigrateThread mt = MigrateManager.getInstance().getMigerateThread(String.valueOf(sequence.getValue()));
if (mt == null) {
throw new AdminServiceException(sequence + " is NOT expanding!");
}
if (!mt.redo()) {
throw new AdminServiceException(sequence
+ " expanding migrate command maybe could execute in some store node");
}
}
/**
* 检查序列是否正在扩容迁移,执行迁移前最好调用该方法
*
* @param sequence
* @return
*/
public boolean isMigrating(StoreNodeSequenceEnum sequence) {
return MigrateManager.getInstance().isMigrating(String.valueOf(sequence.getValue()));
}
/**
* 检查节点是否在扩容迁移中,包括源节点和目标节点
*
* @param physicalId
* @return
*/
public boolean isMigrating(String physicalId) {
return MigrateManager.getInstance().isMigrating(physicalId);
}
/**
* 获得正在迁移中的序列的新节点
*
* @param sequence
* @return
*/
public List<String> getMigeratingNewNode(StoreNodeSequenceEnum sequence) {
if (!isMigrating(sequence)) {
return null;
}
return getMigThread(sequence).getMigeratingNodePhysicalIdList();
}
private MigrateThread getMigThread(StoreNodeSequenceEnum sequence) {
return MigrateManager.getInstance().getMigerateThread(String.valueOf(sequence.getValue()));
}
}