blob: aa5d9116c182f75ed0b809abd2b62100785843c6 [file] [log] [blame]
Thomas Vachuska4f1a60c2014-10-28 13:39:07 -07001/*
2 * Copyright 2014 Open Networking Laboratory
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
Ayaka Koshibef9b02fc2014-10-15 17:07:05 -070016package org.onlab.onos.store.mastership.impl;
17
Yuta HIGUCHIb5b71b32014-10-30 02:41:25 -070018import static org.onlab.onos.net.MastershipRole.MASTER;
19import static org.onlab.onos.net.MastershipRole.NONE;
20import static org.onlab.onos.net.MastershipRole.STANDBY;
21
Ayaka Koshibef9b02fc2014-10-15 17:07:05 -070022import java.util.Collections;
Yuta HIGUCHI868def02014-10-23 12:09:43 -070023import java.util.EnumMap;
Ayaka Koshibef9b02fc2014-10-15 17:07:05 -070024import java.util.LinkedList;
25import java.util.List;
26import java.util.Map;
27
28import org.onlab.onos.cluster.NodeId;
Ayaka Koshibeabedb092014-10-20 17:01:31 -070029import org.onlab.onos.cluster.RoleInfo;
Ayaka Koshibef9b02fc2014-10-15 17:07:05 -070030import org.onlab.onos.net.MastershipRole;
31
Ayaka Koshibefc981cf2014-10-21 12:44:17 -070032import com.google.common.base.MoreObjects;
33import com.google.common.base.MoreObjects.ToStringHelper;
34
Ayaka Koshibef9b02fc2014-10-15 17:07:05 -070035/**
36 * A structure that holds node mastership roles associated with a
Thomas Vachuskae0f804a2014-10-27 23:40:48 -070037 * {@link org.onlab.onos.net.DeviceId}. This structure needs to be locked through IMap.
Ayaka Koshibef9b02fc2014-10-15 17:07:05 -070038 */
Yuta HIGUCHI868def02014-10-23 12:09:43 -070039final class RoleValue {
Ayaka Koshibef9b02fc2014-10-15 17:07:05 -070040
Yuta HIGUCHI868def02014-10-23 12:09:43 -070041 protected final Map<MastershipRole, List<NodeId>> value = new EnumMap<>(MastershipRole.class);
Ayaka Koshibef9b02fc2014-10-15 17:07:05 -070042
43 public RoleValue() {
44 value.put(MastershipRole.MASTER, new LinkedList<NodeId>());
45 value.put(MastershipRole.STANDBY, new LinkedList<NodeId>());
46 value.put(MastershipRole.NONE, new LinkedList<NodeId>());
47 }
48
Yuta HIGUCHI868def02014-10-23 12:09:43 -070049 // exposing internals for serialization purpose only
50 Map<MastershipRole, List<NodeId>> value() {
Ayaka Koshibef9b02fc2014-10-15 17:07:05 -070051 return Collections.unmodifiableMap(value);
52 }
53
54 public List<NodeId> nodesOfRole(MastershipRole type) {
55 return value.get(type);
56 }
57
Ayaka Koshibe98bd12f2014-11-01 20:13:37 -070058 /**
59 * Returns the first node to match the MastershipRole, or if there
60 * are none, null.
61 *
62 * @param type the role
63 * @return a node ID or null
64 */
Ayaka Koshibef9b02fc2014-10-15 17:07:05 -070065 public NodeId get(MastershipRole type) {
66 return value.get(type).isEmpty() ? null : value.get(type).get(0);
67 }
68
69 public boolean contains(MastershipRole type, NodeId nodeId) {
70 return value.get(type).contains(nodeId);
71 }
72
Yuta HIGUCHIb5b71b32014-10-30 02:41:25 -070073 public MastershipRole getRole(NodeId nodeId) {
74 if (contains(MASTER, nodeId)) {
75 return MASTER;
76 }
77 if (contains(STANDBY, nodeId)) {
78 return STANDBY;
79 }
80 return NONE;
81 }
82
Ayaka Koshibef9b02fc2014-10-15 17:07:05 -070083 /**
84 * Associates a node to a certain role.
85 *
86 * @param type the role
87 * @param nodeId the node ID of the node to associate
Yuta HIGUCHIb5b71b32014-10-30 02:41:25 -070088 * @return true if modified
Ayaka Koshibef9b02fc2014-10-15 17:07:05 -070089 */
Yuta HIGUCHIb5b71b32014-10-30 02:41:25 -070090 public boolean add(MastershipRole type, NodeId nodeId) {
Ayaka Koshibef9b02fc2014-10-15 17:07:05 -070091 List<NodeId> nodes = value.get(type);
92
93 if (!nodes.contains(nodeId)) {
Yuta HIGUCHIb5b71b32014-10-30 02:41:25 -070094 return nodes.add(nodeId);
Ayaka Koshibef9b02fc2014-10-15 17:07:05 -070095 }
Yuta HIGUCHIb5b71b32014-10-30 02:41:25 -070096 return false;
Ayaka Koshibef9b02fc2014-10-15 17:07:05 -070097 }
98
99 /**
100 * Removes a node from a certain role.
101 *
102 * @param type the role
103 * @param nodeId the ID of the node to remove
Yuta HIGUCHIb5b71b32014-10-30 02:41:25 -0700104 * @return true if modified
Ayaka Koshibef9b02fc2014-10-15 17:07:05 -0700105 */
106 public boolean remove(MastershipRole type, NodeId nodeId) {
107 List<NodeId> nodes = value.get(type);
108 if (!nodes.isEmpty()) {
109 return nodes.remove(nodeId);
110 } else {
111 return false;
112 }
113 }
114
115 /**
116 * Reassigns a node from one role to another. If the node was not of the
117 * old role, it will still be assigned the new role.
118 *
119 * @param nodeId the Node ID of node changing roles
120 * @param from the old role
121 * @param to the new role
Yuta HIGUCHIb5b71b32014-10-30 02:41:25 -0700122 * @return true if modified
Ayaka Koshibef9b02fc2014-10-15 17:07:05 -0700123 */
Yuta HIGUCHIb5b71b32014-10-30 02:41:25 -0700124 public boolean reassign(NodeId nodeId, MastershipRole from, MastershipRole to) {
125 boolean modified = remove(from, nodeId);
126 modified |= add(to, nodeId);
127 return modified;
Ayaka Koshibef9b02fc2014-10-15 17:07:05 -0700128 }
129
130 /**
131 * Replaces a node in one role with another node. Even if there is no node to
132 * replace, the new node is associated to the role.
133 *
134 * @param from the old NodeId to replace
135 * @param to the new NodeId
136 * @param type the role associated with the old NodeId
Yuta HIGUCHIb5b71b32014-10-30 02:41:25 -0700137 * @return true if modified
Ayaka Koshibef9b02fc2014-10-15 17:07:05 -0700138 */
Yuta HIGUCHIb5b71b32014-10-30 02:41:25 -0700139 public boolean replace(NodeId from, NodeId to, MastershipRole type) {
140 boolean modified = remove(type, from);
141 modified |= add(type, to);
142 return modified;
Ayaka Koshibef9b02fc2014-10-15 17:07:05 -0700143 }
144
Ayaka Koshibe67af1f42014-10-20 15:26:37 -0700145 /**
146 * Summarizes this RoleValue as a RoleInfo. Note that master and/or backups
147 * may be empty, so the values should be checked for safety.
148 *
149 * @return the RoleInfo.
150 */
151 public RoleInfo roleInfo() {
152 return new RoleInfo(
153 get(MastershipRole.MASTER), nodesOfRole(MastershipRole.STANDBY));
154 }
155
Ayaka Koshibee8e45352014-10-16 00:37:19 -0700156 @Override
157 public String toString() {
Ayaka Koshibefc981cf2014-10-21 12:44:17 -0700158 ToStringHelper helper = MoreObjects.toStringHelper(this.getClass());
Ayaka Koshibee8e45352014-10-16 00:37:19 -0700159 for (Map.Entry<MastershipRole, List<NodeId>> el : value.entrySet()) {
Ayaka Koshibefc981cf2014-10-21 12:44:17 -0700160 helper.add(el.getKey().toString(), el.getValue());
Ayaka Koshibee8e45352014-10-16 00:37:19 -0700161 }
Ayaka Koshibefc981cf2014-10-21 12:44:17 -0700162 return helper.toString();
Ayaka Koshibee8e45352014-10-16 00:37:19 -0700163 }
Ayaka Koshibef9b02fc2014-10-15 17:07:05 -0700164}