/** * diqube: Distributed Query Base. * * Copyright (C) 2015 Bastian Gloeckle * * This file is part of diqube. * * diqube 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 this program. If not, see <http://www.gnu.org/licenses/>. */ package org.diqube.cluster; import java.util.Collection; import java.util.Set; import org.diqube.connection.NodeAddress; import org.diqube.consensus.ConsensusMethod; import org.diqube.consensus.ConsensusStateMachine; import org.diqube.consensus.ConsensusUtil; import io.atomix.copycat.Command; import io.atomix.copycat.Query; import io.atomix.copycat.server.Commit; /** * A cluster-safe state machine to distribute data of what nodes are in the cluster and what nodes know what tables. * * @author Bastian Gloeckle */ @ConsensusStateMachine public interface ClusterLayoutStateMachine { /** * Sets the tables available on a node. A node without any tables denotes an available empty node. */ @ConsensusMethod(dataClass = SetTablesOfNode.class) public void setTablesOfNode(Commit<SetTablesOfNode> commit); /** * Remove a node from the cluster layout - when a node left the cluster. */ @ConsensusMethod(dataClass = RemoveNode.class) public void removeNode(Commit<RemoveNode> commit); /** * Query that returns those node addresses which serve a specific table. */ @ConsensusMethod(dataClass = FindNodesServingTable.class, additionalSerializationClasses = NodeAddress.class) public Set<NodeAddress> findNodesServingTable(Commit<FindNodesServingTable> commit); /** * Query that returns a list of all known reachable nodes. */ @ConsensusMethod(dataClass = GetAllNodes.class, additionalSerializationClasses = NodeAddress.class) public Set<NodeAddress> getAllNodes(Commit<GetAllNodes> commit); /** * Query that returns whether a specific node is known to be reachable in the Cluster layout. */ @ConsensusMethod(dataClass = IsNodeKnown.class) public Boolean isNodeKnown(Commit<IsNodeKnown> commit); /** * Query that returns the names of all tables available in the cluster. */ @ConsensusMethod(dataClass = GetAllTablesServed.class) public Set<String> getAllTablesServed(Commit<GetAllTablesServed> commit); public static class GetAllTablesServed implements Query<Set<String>> { private static final long serialVersionUID = 1L; public static Commit<GetAllTablesServed> local() { GetAllTablesServed res = new GetAllTablesServed(); return ConsensusUtil.localCommit(res); } } public static class IsNodeKnown implements Query<Boolean> { private static final long serialVersionUID = 1L; private NodeAddress node; public NodeAddress getNode() { return node; } @Override public ConsistencyLevel consistency() { return ConsistencyLevel.BOUNDED_LINEARIZABLE; } public static Commit<IsNodeKnown> local(NodeAddress node) { IsNodeKnown res = new IsNodeKnown(); res.node = node; return ConsensusUtil.localCommit(res); } } public static class GetAllNodes implements Query<Set<NodeAddress>> { private static final long serialVersionUID = 1L; @Override public ConsistencyLevel consistency() { return ConsistencyLevel.BOUNDED_LINEARIZABLE; } public static Commit<GetAllNodes> local() { GetAllNodes res = new GetAllNodes(); return ConsensusUtil.localCommit(res); } } public static class FindNodesServingTable implements Query<Set<NodeAddress>> { private static final long serialVersionUID = 1L; private String tableName; public String getTableName() { return tableName; } @Override public ConsistencyLevel consistency() { return ConsistencyLevel.BOUNDED_LINEARIZABLE; } public static Commit<FindNodesServingTable> local(String tableName) { FindNodesServingTable res = new FindNodesServingTable(); res.tableName = tableName; return ConsensusUtil.localCommit(res); } } public static class RemoveNode implements Command<Void> { private static final long serialVersionUID = 1L; private NodeAddress node; @Override public CompactionMode compaction() { return CompactionMode.SEQUENTIAL; } public NodeAddress getNode() { return node; } public static Commit<RemoveNode> local(NodeAddress node) { RemoveNode res = new RemoveNode(); res.node = node; return ConsensusUtil.localCommit(res); } } public static class SetTablesOfNode implements Command<Void> { private static final long serialVersionUID = 1L; private NodeAddress node; private Collection<String> tables; @Override public CompactionMode compaction() { return CompactionMode.FULL; } public NodeAddress getNode() { return node; } public Collection<String> getTables() { return tables; } public static Commit<SetTablesOfNode> local(NodeAddress node, Collection<String> tables) { SetTablesOfNode res = new SetTablesOfNode(); res.node = node; res.tables = tables; return ConsensusUtil.localCommit(res); } } }