blob: 8baaec89247616da7995bf29661cded8105ef8fe [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you 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.
*/
package org.apache.iotdb.consensus;
import org.apache.iotdb.common.rpc.thrift.TSStatus;
import org.apache.iotdb.commons.consensus.ConsensusGroupId;
import org.apache.iotdb.consensus.common.DataSet;
import org.apache.iotdb.consensus.common.Peer;
import org.apache.iotdb.consensus.common.request.IConsensusRequest;
import org.apache.iotdb.consensus.config.ConsensusConfig;
import org.apache.iotdb.consensus.exception.ConsensusException;
import org.apache.iotdb.consensus.exception.ConsensusGroupAlreadyExistException;
import org.apache.iotdb.consensus.exception.ConsensusGroupNotExistException;
import org.apache.iotdb.consensus.exception.IllegalPeerEndpointException;
import org.apache.iotdb.consensus.exception.IllegalPeerNumException;
import org.apache.iotdb.consensus.exception.PeerAlreadyInConsensusGroupException;
import org.apache.iotdb.consensus.exception.PeerNotInConsensusGroupException;
import javax.annotation.concurrent.ThreadSafe;
import java.io.IOException;
import java.util.List;
/** Consensus module base interface. */
@ThreadSafe
public interface IConsensus {
/**
* Start the consensus module.
*
* @throws IOException when start consensus errors
*/
void start() throws IOException;
/**
* Stop the consensus module.
*
* @throws IOException when stop consensus errors
*/
void stop() throws IOException;
/**
* Write data to the corresponding consensus group.
*
* @param groupId the consensus group this request belongs
* @param request write request
* @return write result
* @throws ConsensusGroupNotExistException when the specified consensus group doesn't exist
* @throws ConsensusException when write doesn't success with other reasons
*/
TSStatus write(ConsensusGroupId groupId, IConsensusRequest request) throws ConsensusException;
/**
* Read data from the corresponding consensus group.
*
* @param groupId the consensus group this request belongs
* @param request read request
* @return read result
* @throws ConsensusGroupNotExistException when the specified consensus group doesn't exist
* @throws ConsensusException when read doesn't success with other reasons
*/
DataSet read(ConsensusGroupId groupId, IConsensusRequest request) throws ConsensusException;
// multi consensus group API
/**
* Require the <em>local node</em> to create a Peer and become a member of the given consensus
* group. This node will prepare and initialize local statemachine {@link IStateMachine} and other
* data structures. After this method returns, we can call {@link #addRemotePeer(ConsensusGroupId,
* Peer)} to notify original group that this new Peer is prepared to be added into the latest
* configuration. createLocalPeer should be called on a node that does not contain any peer of the
* consensus group, to avoid one node having more than one replica.
*
* @param groupId the consensus group this peer belongs
* @param peers other known peers in this group
* @throws ConsensusGroupAlreadyExistException when the specified consensus group already exists
* @throws IllegalPeerNumException when the peer num is illegal. The exception is that it is legal
* to pass an empty list for RaftConsensus
* @throws IllegalPeerEndpointException when peers don't contain local node. The exception is that
* it is legal to pass an empty list for RaftConsensus
* @throws ConsensusException when createLocalPeer doesn't success with other reasons
*/
void createLocalPeer(ConsensusGroupId groupId, List<Peer> peers) throws ConsensusException;
/**
* When the <em>local node</em> is no longer a member of the given consensus group, call this
* method to do cleanup works. This method will close local statemachine {@link IStateMachine},
* delete local data and do other cleanup works. deleteLocalPeer should be called after
* successfully removing this peer from current consensus group configuration (by calling {@link
* #removeRemotePeer(ConsensusGroupId, Peer)}).
*
* @param groupId the consensus group this peer used to belong
* @throws ConsensusGroupNotExistException when the specified consensus group doesn't exist
* @throws ConsensusException when deleteLocalPeer doesn't success with other reasons
*/
void deleteLocalPeer(ConsensusGroupId groupId) throws ConsensusException;
// single consensus group API
/**
* Tell the group that a new Peer is prepared to be added into this group. Call {@link
* #createLocalPeer(ConsensusGroupId, List)} on the new Peer before calling this method. When this
* method returns, the group data should be already transmitted to the new Peer. That is, the new
* peer is available to answer client requests by the time this method successfully returns.
* addRemotePeer should be called on a living peer of the consensus group. For example: We'd like
* to add a peer D to (A, B, C) group. We need to execute addPeer in A, B or C.
*
* @param groupId the consensus group this peer belongs
* @param peer the newly added peer
* @throws PeerAlreadyInConsensusGroupException when the peer has been added into this consensus
* group
* @throws ConsensusException when addRemotePeer doesn't success with other reasons
*/
void addRemotePeer(ConsensusGroupId groupId, Peer peer) throws ConsensusException;
/**
* Tell the group to remove an active Peer. The removed peer can no longer answer group requests
* when this method successfully returns. Call {@link #deleteLocalPeer(ConsensusGroupId)} on the
* removed Peer to do cleanup jobs after this method successfully returns. removeRemotePeer should
* be called on a living peer of its consensus group. For example: a group has A, B, C. We'd like
* to remove C, in case C is dead, the removePeer should be sent to A or B.
*
* @param groupId the consensus group this peer belongs
* @param peer the peer to be removed
* @throws PeerNotInConsensusGroupException when the peer hasn't yet joined this consensus group
* @throws ConsensusException when removeRemotePeer doesn't success with other reasons
*/
void removeRemotePeer(ConsensusGroupId groupId, Peer peer) throws ConsensusException;
/**
* Reset the peer list of the corresponding consensus group. Currently only used in the automatic
* cleanup of region migration as a rollback for {@link #addRemotePeer(ConsensusGroupId, Peer)},
* so it will only be less but not more.
*
* @param groupId the consensus group
* @param peers the new peer list
* @throws ConsensusException when resetPeerList doesn't success with other reasons
* @throws ConsensusGroupNotExistException when the specified consensus group doesn't exist
*/
void resetPeerList(ConsensusGroupId groupId, List<Peer> peers) throws ConsensusException;
// management API
/**
* Transfer the leadership to other peer to meet some load balancing needs.
*
* @param groupId the consensus group which should execute this command
* @param newLeader the target leader peer
* @throws ConsensusGroupNotExistException when the specified consensus group doesn't exist
* @throws ConsensusException when transferLeader doesn't success with other reasons
*/
void transferLeader(ConsensusGroupId groupId, Peer newLeader) throws ConsensusException;
/**
* Trigger the snapshot of the corresponding consensus group.
*
* @param groupId the consensus group which should execute this command
* @param force if {@link true}, force to take a snapshot
* @throws ConsensusException when triggerSnapshot doesn't success with other reasons
*/
void triggerSnapshot(ConsensusGroupId groupId, boolean force) throws ConsensusException;
/**
* Determine if the current peer is the leader in the corresponding consensus group.
*
* @param groupId the consensus group
* @return {@code true} or {@code false}
*/
boolean isLeader(ConsensusGroupId groupId);
/**
* Returns the logic clock of the current consensus group
*
* @param groupId the consensus group
* @return long
*/
long getLogicalClock(ConsensusGroupId groupId);
/**
* Determine if the current peer is the leader and already able to provide services in the
* corresponding consensus group.
*
* @param groupId the consensus group
* @return {@code true} or {@code false}
*/
boolean isLeaderReady(ConsensusGroupId groupId);
/**
* Return the leader peer of the corresponding consensus group.
*
* @param groupId the consensus group
* @return return null if group doesn't exist or leader is undetermined, or return leader Peer
*/
Peer getLeader(ConsensusGroupId groupId);
/**
* Return all consensus group ids.
*
* @return consensusGroupId list
*/
List<ConsensusGroupId> getAllConsensusGroupIds();
/**
* Return all consensus group ids from disk.
*
* <p>We need to parse all the RegionGroupIds from the disk directory before starting the
* consensus layer, and {@link #getAllConsensusGroupIds()} returns an empty list, so we need to
* add a new interface.
*
* @return consensusGroupId list
*/
List<ConsensusGroupId> getAllConsensusGroupIdsWithoutStarting();
/**
* Return the region directory of the corresponding consensus group.
*
* @param groupId the consensus group
* @return region directory
*/
String getRegionDirFromConsensusGroupId(ConsensusGroupId groupId);
/**
* Reload the consensus config.
*
* @param consensusConfig the new consensus config
*/
void reloadConsensusConfig(ConsensusConfig consensusConfig);
}