/* 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;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import org.voltcore.utils.Pair;
import com.google_voltpatches.common.net.HostAndPort;
public interface ProducerDRGateway {
public interface DRProducerResponseHandler {
public void notifyOfResponse(boolean success, boolean shouldRetry, String failureCause);
}
static class MeshMemberInfo {
public MeshMemberInfo(byte clusterId, long creationTime, int partitionCount,
int protocolVersion, List<HostAndPort> nodes) {
m_clusterId = clusterId;
m_creationTime = creationTime;
m_partitionCount = partitionCount;
m_protocolVersion = protocolVersion;
m_nodes = nodes;
}
public MeshMemberInfo(byte clusterId, long creationTime, List<HostAndPort> nodes) {
this(clusterId, creationTime, 0, 0, nodes);
}
public MeshMemberInfo(MeshMemberInfo staleNodeInfo, List<HostAndPort> nodes) {
m_clusterId = staleNodeInfo.m_clusterId;
m_creationTime = staleNodeInfo.m_creationTime;
m_protocolVersion = staleNodeInfo.m_protocolVersion;
m_partitionCount = staleNodeInfo.m_partitionCount;
m_nodes = nodes;
}
public static MeshMemberInfo createFromHostStrings(byte clusterId, long creationTime, int partitionCount,
int protocolVersion, List<String> nodes) {
List<HostAndPort> hostAndPorts = new ArrayList<>(nodes.size());
for (String hostPortString : nodes) {
hostAndPorts.add(HostAndPort.fromString(hostPortString));
}
return new MeshMemberInfo(clusterId, creationTime, partitionCount, protocolVersion, hostAndPorts);
}
public int getClusterId() { return (int)m_clusterId; }
public final byte m_clusterId;
/**
* This is the persistent cluster create time. NOT THE CLUSTER RECOVERY TIME.
*/
public final long m_creationTime;
/**
* ProtocolVersion may or may not be valid depending on who generates this object
*/
public final int m_protocolVersion;
/**
* Number of partitions in this cluster (excluding MP Site)
*/
public final int m_partitionCount;
/**
* This is either the configured (by conversation file) HostAndPort pairs or the
* HostAndPort pairs found in the MeshQuery response
*/
public final List<HostAndPort> m_nodes;
}
/**
* Start the main thread and the state machine, wait until all nodes converge on the initial state.
* @throws IOException
*/
public void startAndWaitForGlobalAgreement() throws IOException;
/**
* Truncate the DR log using the snapshot restore truncation point cached
* earlier. This is called on recover before the command log replay starts
* to drop all binary logs generated after the snapshot. Command log replay
* will recreate those binary logs.
*/
public void truncateDRLog();
/**
* Getter for collecting the set of conversations in the producer conversation file at
* initialization time. If we have been initialized with clusters 5 and 8, and we connect
* to cluster 5 but id does not know about cluster 8 we need to set a StartCursor immediately
* before we even subscribe, if any conversation was the dataSource for this cluster, it
* will be assigned in Pair.first. If Pair.first is -1, it means that this cluster was the
* original leader and the data on this cluster was not derived from a sync snapshot
*/
public Pair<Byte, List<MeshMemberInfo>> getInitialConversations();
/**
* Start listening on the ports
*/
public abstract void startListening(boolean drProducerEnabled, int listenPort, String portInterface) throws IOException;
/**
* @return true if bindPorts has been called.
*/
public abstract boolean isStarted();
/**
* Queues up a task to move all the InvocationBuffers to the PersistentBinaryDeque
* @param nofsync do not force the sync to disk (when True)
* @return the FutureTask indicating completion
*/
public abstract void forceAllBuffersToDisk(boolean nofsync);
public abstract boolean isActive();
public abstract void setActive(boolean active);
public abstract void start();
public abstract void shutdown() throws InterruptedException;
public abstract void updateCatalog(final CatalogContext catalog, final int listenPort);
public abstract byte getDRClusterId();
public void cacheSnapshotRestoreTruncationPoint(Map<Integer, Long> sequenceNumbers);
/**
* Clear all queued DR buffers for a master, useful when the replica goes away
*/
public void deactivateDR();
public void deactivateDR(byte clusterId);
public void activateDRProducer();
/**
* Blocks until snaphot is generated for the specified cluster id.
* If the snapshot has already been generated, this will return immediately
*
* @param forClusterId the cluster for which producer should generate snapshot.
* This is used and has a meaningful value only in MULTICLUSTER_PROTOCOL_VERSION
* or higher.
*/
public void blockOnSyncSnapshotGeneration(byte forClusterId);
/**
* Sets the DR protocol version with EE. This will also generate a <code>DR_STREAM_START</code>
* event for all partitions, if <code>genStreamStart</code> flag is true.
*
* @param drVersion the DR protocol version that must be set with EE.
* @param genStreamStart <code>DR_STREAM_START</code> event will be generated for all partitions
* if this is true.
*
* @return Returns true if the operation was successful. False otherwise.
*/
public boolean setDRProtocolVersion(int drVersion, boolean genStreamStart);
/**
* Use this to set up cursors in DR binary logs for clusters. This will initiate the process.
* When the process is complete, the passed in handler will be notified of the status.
*
* @param requestedCursors the clusters for which cursors must be started
* @param leaderClusterId ID of the cluster that needs to be marked as the snapshot source
* @param handler callback to notify the status of the operation
*/
public void startCursor(final List<MeshMemberInfo> requestedCursors,
final byte leaderClusterId, final DRProducerResponseHandler handler);
/**
* Get the DR producer node stats. This method may block because the task
* runs on the producer thread and it waits for the asynchronous task to
* finish.
* @return The producer node stats keyed by cluster IDs or null if on error
*/
public Map<Byte, DRProducerNodeStats> getNodeDRStats();
public void resumeAllReadersAsync();
public void pauseAllReadersAsync();
}