/** * Copyright 2016 vip.com. * <p> * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * </p> */ package com.vip.saturn.job.internal.election; import java.util.concurrent.atomic.AtomicBoolean; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import com.vip.saturn.job.basic.AbstractSaturnService; import com.vip.saturn.job.basic.JobScheduler; import com.vip.saturn.job.basic.SaturnConstant; import com.vip.saturn.job.internal.storage.LeaderExecutionCallback; import com.vip.saturn.job.utils.BlockUtils; /** * 选举主节点的服务. * * */ public class LeaderElectionService extends AbstractSaturnService{ static Logger log = LoggerFactory.getLogger(LeaderElectionService.class); private AtomicBoolean isShutdown = new AtomicBoolean(false); public LeaderElectionService(final JobScheduler jobScheduler) { super(jobScheduler); } @Override public void shutdown() { synchronized (isShutdown) { if(isShutdown.compareAndSet(false, true)) { try { // Release my leader position if (executorName.equals(getJobNodeStorage().getJobNodeDataDirectly(ElectionNode.LEADER_HOST))) { getJobNodeStorage().removeJobNodeIfExisted(ElectionNode.LEADER_HOST); log.info("[{}] msg={} that was {}'s leader, released itself", jobName, executorName, jobName); } } catch (Throwable t) { log.error(t.getMessage(), t); } } } } /** * 选举主节点. */ public void leaderElection() { getJobNodeStorage().executeInLeader(ElectionNode.LATCH, new LeaderElectionExecutionCallback()); } /** * 判断当前节点是否是主节点,如果没有主节点,则选举,直到有主节点 * * @return 当前节点是否是主节点 */ public Boolean isLeader() { while (!isShutdown.get() && !hasLeader()) { log.info("[{}] msg=No leader, try to election", jobName); leaderElection(); } return executorName.equals(getJobNodeStorage().getJobNodeDataDirectly(ElectionNode.LEADER_HOST)); } /** * 判断是否已经有主节点 * * @return 是否已经有主节点 */ public boolean hasLeader() { return getJobNodeStorage().isJobNodeExisted(ElectionNode.LEADER_HOST); } class LeaderElectionExecutionCallback implements LeaderExecutionCallback { @Override public void execute() { synchronized (isShutdown) { if(isShutdown.get()) { return; } if (!getJobNodeStorage().isJobNodeExisted(ElectionNode.LEADER_HOST)) { getJobNodeStorage().fillEphemeralJobNode(ElectionNode.LEADER_HOST, executorName); log.info("[{}] msg=executor {} become job {}'s leader", jobName, executorName, jobName); } } } } }