| /* |
| * Copyright 2014 Open Networking Laboratory |
| * |
| * 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 org.onosproject.store.mastership.impl; |
| |
| import static org.onosproject.net.MastershipRole.MASTER; |
| import static org.onosproject.net.MastershipRole.NONE; |
| import static org.onosproject.net.MastershipRole.STANDBY; |
| |
| import java.util.Collections; |
| import java.util.EnumMap; |
| import java.util.LinkedList; |
| import java.util.List; |
| import java.util.Map; |
| |
| import org.onosproject.cluster.NodeId; |
| import org.onosproject.cluster.RoleInfo; |
| import org.onosproject.net.MastershipRole; |
| |
| import com.google.common.base.MoreObjects; |
| import com.google.common.base.MoreObjects.ToStringHelper; |
| import com.google.common.collect.Lists; |
| |
| /** |
| * A structure that holds node mastership roles associated with a |
| * {@link org.onosproject.net.DeviceId}. This structure needs to be locked through IMap. |
| */ |
| final class RoleValue { |
| |
| protected final Map<MastershipRole, List<NodeId>> value = new EnumMap<>(MastershipRole.class); |
| |
| /** |
| * Constructs empty RoleValue. |
| */ |
| public RoleValue() { |
| value.put(MastershipRole.MASTER, new LinkedList<NodeId>()); |
| value.put(MastershipRole.STANDBY, new LinkedList<NodeId>()); |
| value.put(MastershipRole.NONE, new LinkedList<NodeId>()); |
| } |
| |
| /** |
| * Constructs copy of specified RoleValue. |
| * |
| * @param original original to create copy from |
| */ |
| public RoleValue(final RoleValue original) { |
| value.put(MASTER, Lists.newLinkedList(original.value.get(MASTER))); |
| value.put(STANDBY, Lists.newLinkedList(original.value.get(STANDBY))); |
| value.put(NONE, Lists.newLinkedList(original.value.get(NONE))); |
| } |
| |
| // exposing internals for serialization purpose only |
| Map<MastershipRole, List<NodeId>> value() { |
| return Collections.unmodifiableMap(value); |
| } |
| |
| public List<NodeId> nodesOfRole(MastershipRole type) { |
| return value.get(type); |
| } |
| |
| /** |
| * Returns the first node to match the MastershipRole, or if there |
| * are none, null. |
| * |
| * @param type the role |
| * @return a node ID or null |
| */ |
| public NodeId get(MastershipRole type) { |
| return value.get(type).isEmpty() ? null : value.get(type).get(0); |
| } |
| |
| public boolean contains(MastershipRole type, NodeId nodeId) { |
| return value.get(type).contains(nodeId); |
| } |
| |
| public MastershipRole getRole(NodeId nodeId) { |
| if (contains(MASTER, nodeId)) { |
| return MASTER; |
| } |
| if (contains(STANDBY, nodeId)) { |
| return STANDBY; |
| } |
| return NONE; |
| } |
| |
| /** |
| * Associates a node to a certain role. |
| * |
| * @param type the role |
| * @param nodeId the node ID of the node to associate |
| * @return true if modified |
| */ |
| public boolean add(MastershipRole type, NodeId nodeId) { |
| List<NodeId> nodes = value.get(type); |
| |
| if (!nodes.contains(nodeId)) { |
| return nodes.add(nodeId); |
| } |
| return false; |
| } |
| |
| /** |
| * Removes a node from a certain role. |
| * |
| * @param type the role |
| * @param nodeId the ID of the node to remove |
| * @return true if modified |
| */ |
| public boolean remove(MastershipRole type, NodeId nodeId) { |
| List<NodeId> nodes = value.get(type); |
| if (!nodes.isEmpty()) { |
| return nodes.remove(nodeId); |
| } else { |
| return false; |
| } |
| } |
| |
| /** |
| * Reassigns a node from one role to another. If the node was not of the |
| * old role, it will still be assigned the new role. |
| * |
| * @param nodeId the Node ID of node changing roles |
| * @param from the old role |
| * @param to the new role |
| * @return true if modified |
| */ |
| public boolean reassign(NodeId nodeId, MastershipRole from, MastershipRole to) { |
| boolean modified = remove(from, nodeId); |
| modified |= add(to, nodeId); |
| return modified; |
| } |
| |
| /** |
| * Replaces a node in one role with another node. Even if there is no node to |
| * replace, the new node is associated to the role. |
| * |
| * @param from the old NodeId to replace |
| * @param to the new NodeId |
| * @param type the role associated with the old NodeId |
| * @return true if modified |
| */ |
| public boolean replace(NodeId from, NodeId to, MastershipRole type) { |
| boolean modified = remove(type, from); |
| modified |= add(type, to); |
| return modified; |
| } |
| |
| /** |
| * Summarizes this RoleValue as a RoleInfo. Note that master and/or backups |
| * may be empty, so the values should be checked for safety. |
| * |
| * @return the RoleInfo. |
| */ |
| public RoleInfo roleInfo() { |
| return new RoleInfo( |
| get(MastershipRole.MASTER), nodesOfRole(MastershipRole.STANDBY)); |
| } |
| |
| @Override |
| public String toString() { |
| ToStringHelper helper = MoreObjects.toStringHelper(this.getClass()); |
| for (Map.Entry<MastershipRole, List<NodeId>> el : value.entrySet()) { |
| helper.add(el.getKey().toString(), el.getValue()); |
| } |
| return helper.toString(); |
| } |
| } |