blob: a074b944b5f9aa5c25eddd32313f10523f1ef2ee [file] [log] [blame]
/*
* 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.onlab.onos.store.mastership.impl;
import static org.onlab.onos.net.MastershipRole.MASTER;
import static org.onlab.onos.net.MastershipRole.NONE;
import static org.onlab.onos.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.onlab.onos.cluster.NodeId;
import org.onlab.onos.cluster.RoleInfo;
import org.onlab.onos.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.onlab.onos.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();
}
}