package com.github.ltsopensource.core.cluster;
import com.github.ltsopensource.core.AppContext;
import com.github.ltsopensource.core.commons.utils.CollectionUtils;
import com.github.ltsopensource.core.constant.EcTopic;
import com.github.ltsopensource.core.listener.MasterChangeListener;
import com.github.ltsopensource.core.logger.Logger;
import com.github.ltsopensource.core.logger.LoggerFactory;
import com.github.ltsopensource.ec.EventInfo;
import java.util.List;
import java.util.concurrent.CopyOnWriteArrayList;
import java.util.concurrent.locks.ReentrantLock;
/**
* @author Robert HG (254963746@qq.com) on 8/23/14.
* Master 选举
* 选举思想:
* 选出每种节点中的master, 通过每个节点的创建时间来决定 (创建时间最小的便是master, 即最早创建的是master)
* 当master 挂掉之后, 要重新选举
*/
public class MasterElector {
private static final Logger LOGGER = LoggerFactory.getLogger(MasterElector.class);
private AppContext appContext;
private List<MasterChangeListener> listeners;
private Node master;
private ReentrantLock lock = new ReentrantLock();
public MasterElector(AppContext appContext) {
this.appContext = appContext;
}
public void addMasterChangeListener(List<MasterChangeListener> masterChangeListeners) {
if (listeners == null) {
listeners = new CopyOnWriteArrayList<MasterChangeListener>();
}
if (CollectionUtils.isNotEmpty(masterChangeListeners)) {
listeners.addAll(masterChangeListeners);
}
}
public void addNodes(List<Node> nodes) {
lock.lock();
try {
Node newMaster = null;
for (Node node : nodes) {
if (newMaster == null) {
newMaster = node;
} else {
if (newMaster.getCreateTime() > node.getCreateTime()) {
newMaster = node;
}
}
}
addNode(newMaster);
} finally {
lock.unlock();
}
}
/**
* 当前节点是否是master
*/
public boolean isCurrentMaster() {
return master != null && master.getIdentity().equals(appContext.getConfig().getIdentity());
}
public void addNode(Node newNode) {
lock.lock();
try {
if (master == null) {
master = newNode;
notifyListener();
} else {
if (master.getCreateTime() > newNode.getCreateTime()) {
master = newNode;
notifyListener();
}
}
} finally {
lock.unlock();
}
}
public void removeNode(List<Node> removedNodes) {
lock.lock();
try {
if (master != null) {
boolean masterRemoved = false;
for (Node removedNode : removedNodes) {
if (master.getIdentity().equals(removedNode.getIdentity())) {
masterRemoved = true;
}
}
if (masterRemoved) {
// 如果挂掉的是master, 需要重新选举
List<Node> nodes = appContext.getSubscribedNodeManager().
getNodeList(appContext.getConfig().getNodeType(), appContext.getConfig().getNodeGroup());
if (CollectionUtils.isNotEmpty(nodes)) {
Node newMaster = null;
for (Node node : nodes) {
if (newMaster == null) {
newMaster = node;
} else {
if (newMaster.getCreateTime() > node.getCreateTime()) {
newMaster = node;
}
}
}
master = newMaster;
notifyListener();
}
}
}
} finally {
lock.unlock();
}
}
private void notifyListener() {
boolean isMaster = false;
if (appContext.getConfig().getIdentity().equals(master.getIdentity())) {
LOGGER.info("Current node become the master node:{}", master);
isMaster = true;
} else {
LOGGER.info("Master node is :{}", master);
isMaster = false;
}
if (listeners != null) {
for (MasterChangeListener masterChangeListener : listeners) {
try {
masterChangeListener.change(master, isMaster);
} catch (Throwable t) {
LOGGER.error("MasterChangeListener notify error!", t);
}
}
}
EventInfo eventInfo = new EventInfo(EcTopic.MASTER_CHANGED);
eventInfo.setParam("master", master);
appContext.getEventCenter().publishSync(eventInfo);
}
}