/* This file is part of VoltDB.
* Copyright (C) 2008-2017 VoltDB Inc.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with VoltDB. If not, see <http://www.gnu.org/licenses/>.
*/
package org.voltdb.iv2;
import java.util.List;
import java.util.concurrent.ExecutionException;
import org.apache.zookeeper_voltpatches.ZooKeeper;
import org.voltcore.logging.VoltLogger;
import org.voltcore.utils.CoreUtils;
import org.voltcore.utils.Pair;
import org.voltcore.zk.BabySitter;
import org.voltcore.zk.BabySitter.Callback;
import org.voltcore.zk.LeaderElector;
import org.voltdb.VoltDB;
import org.voltdb.VoltZK;
import com.google_voltpatches.common.base.Supplier;
public class SpTerm implements Term
{
VoltLogger tmLog = new VoltLogger("TM");
private final String m_whoami;
private final InitiatorMailbox m_mailbox;
private final int m_partitionId;
private final ZooKeeper m_zk;
// Initialized in start() -- when the term begins.
protected BabySitter m_babySitter;
// runs on the babysitter thread when a replica changes.
// simply forward the notice to the initiator mailbox; it controls
// the Term processing.
Callback m_replicasChangeHandler = new Callback()
{
@Override
public void run(List<String> children)
{
// remove the leader; convert to hsids; deal with the replica change.
List<Long> replicas = VoltZK.childrenToReplicaHSIds(children);
tmLog.debug(m_whoami
+ "replica change handler updating replica list to: "
+ CoreUtils.hsIdCollectionToString(replicas));
m_mailbox.updateReplicas(replicas, null);
}
};
/**
* Setup a new Term but don't take any action to take responsibility.
*/
public SpTerm(ZooKeeper zk, int partitionId, long initiatorHSId, InitiatorMailbox mailbox,
String whoami)
{
m_zk = zk;
m_partitionId = partitionId;
m_mailbox = mailbox;
m_whoami = whoami;
}
/**
* Start a new Term. This starts watching followers via ZK. Block on an
* appropriate repair algorithm to watch final promotion to leader.
*/
@Override
public void start()
{
try {
Pair<BabySitter, List<String>> pair = BabySitter.blockingFactory(m_zk,
LeaderElector.electionDirForPartition(VoltZK.leaders_initiators, m_partitionId),
m_replicasChangeHandler);
m_babySitter = pair.getFirst();
}
catch (ExecutionException ee) {
VoltDB.crashLocalVoltDB("Unable to create babysitter starting term.", true, ee);
} catch (InterruptedException e) {
VoltDB.crashLocalVoltDB("Unable to create babysitter starting term.", true, e);
}
}
@Override
public void shutdown()
{
if (m_babySitter != null) {
m_babySitter.shutdown();
}
}
@Override
public Supplier<List<Long>> getInterestingHSIds()
{
return new Supplier<List<Long>>() {
@Override
public List<Long> get() {
List<String> survivorsNames = m_babySitter.lastSeenChildren();
List<Long> survivors = VoltZK.childrenToReplicaHSIds(survivorsNames);
return survivors;
}
};
}
}