Java tutorial
/* * Copyright 2013 LinkedIn, Inc * * 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. */ package voldemort.utils; import java.util.ArrayList; import java.util.Collections; import java.util.List; import java.util.Set; import org.apache.log4j.Logger; import voldemort.cluster.Cluster; import voldemort.cluster.Node; import com.google.common.collect.Lists; import com.google.common.collect.Sets; import com.google.common.collect.Lists; import com.google.common.collect.Sets; /** * UpdateClusterUtils provides helper methods for manipulating nodes and * clusters. The methods are used by rebalancing tools and in tests. */ public class UpdateClusterUtils { private static Logger logger = Logger.getLogger(UpdateClusterUtils.class); /** * Creates a replica of the node with the new partitions list * * @param node The node whose replica we are creating * @param partitionsList The new partitions list * @return Replica of node with new partitions list */ public static Node updateNode(Node node, List<Integer> partitionsList) { return new Node(node.getId(), node.getHost(), node.getHttpPort(), node.getSocketPort(), node.getAdminPort(), node.getZoneId(), partitionsList); } /** * Add a partition to the node provided * * @param node The node to which we'll add the partition * @param donatedPartition The partition to add * @return The new node with the new partition */ public static Node addPartitionToNode(final Node node, Integer donatedPartition) { return UpdateClusterUtils.addPartitionsToNode(node, Sets.newHashSet(donatedPartition)); } /** * Remove a partition from the node provided * * @param node The node from which we're removing the partition * @param donatedPartition The partitions to remove * @return The new node without the partition */ public static Node removePartitionFromNode(final Node node, Integer donatedPartition) { return UpdateClusterUtils.removePartitionsFromNode(node, Sets.newHashSet(donatedPartition)); } /** * Add the set of partitions to the node provided * * @param node The node to which we'll add the partitions * @param donatedPartitions The list of partitions to add * @return The new node with the new partitions */ public static Node addPartitionsToNode(final Node node, final Set<Integer> donatedPartitions) { List<Integer> deepCopy = new ArrayList<Integer>(node.getPartitionIds()); deepCopy.addAll(donatedPartitions); Collections.sort(deepCopy); return updateNode(node, deepCopy); } /** * Remove the set of partitions from the node provided * * @param node The node from which we're removing the partitions * @param donatedPartitions The list of partitions to remove * @return The new node without the partitions */ public static Node removePartitionsFromNode(final Node node, final Set<Integer> donatedPartitions) { List<Integer> deepCopy = new ArrayList<Integer>(node.getPartitionIds()); deepCopy.removeAll(donatedPartitions); return updateNode(node, deepCopy); } /** * Concatenates the list of current nodes in the given cluster with the new * nodes provided and returns an updated cluster metadata. <br> * If the nodes being updated already exist in the current metadata, we take * the updated ones * * @param currentCluster The current cluster metadata * @param updatedNodeList The list of new nodes to be added * @return New cluster metadata containing both the sets of nodes */ public static Cluster updateCluster(Cluster currentCluster, List<Node> updatedNodeList) { List<Node> newNodeList = new ArrayList<Node>(updatedNodeList); for (Node currentNode : currentCluster.getNodes()) { if (!updatedNodeList.contains(currentNode)) newNodeList.add(currentNode); } Collections.sort(newNodeList); return new Cluster(currentCluster.getName(), newNodeList, Lists.newArrayList(currentCluster.getZones())); } /** * Updates the existing cluster such that we remove partitions mentioned * from the stealer node and add them to the donor node * * @param currentCluster Existing cluster metadata. Both stealer and donor * node should already exist in this metadata * @param stealerNodeId Id of node for which we are stealing the partitions * @param donatedPartitions List of partitions we are moving * @return Updated cluster metadata */ public static Cluster createUpdatedCluster(Cluster currentCluster, int stealerNodeId, List<Integer> donatedPartitions) { Cluster updatedCluster = Cluster.cloneCluster(currentCluster); // Go over every donated partition one by one for (int donatedPartition : donatedPartitions) { // Gets the donor Node that owns this donated partition Node donorNode = updatedCluster.getNodeForPartitionId(donatedPartition); Node stealerNode = updatedCluster.getNodeById(stealerNodeId); if (donorNode == stealerNode) { // Moving to the same location = No-op continue; } // Update the list of partitions for this node donorNode = removePartitionFromNode(donorNode, donatedPartition); stealerNode = addPartitionToNode(stealerNode, donatedPartition); // Sort the nodes updatedCluster = updateCluster(updatedCluster, Lists.newArrayList(donorNode, stealerNode)); } return updatedCluster; } }