9d3b1686e0226926593de957bcdbd9b70e2b90d9
[onosfw.git] /
1 /*
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  */
16 package org.onosproject.store.mastership.impl;
17
18 import static org.onosproject.net.MastershipRole.MASTER;
19 import static org.onosproject.net.MastershipRole.NONE;
20 import static org.onosproject.net.MastershipRole.STANDBY;
21
22 import java.util.Collections;
23 import java.util.EnumMap;
24 import java.util.LinkedList;
25 import java.util.List;
26 import java.util.Map;
27
28 import org.onosproject.cluster.NodeId;
29 import org.onosproject.cluster.RoleInfo;
30 import org.onosproject.net.MastershipRole;
31
32 import com.google.common.base.MoreObjects;
33 import com.google.common.base.MoreObjects.ToStringHelper;
34 import com.google.common.collect.Lists;
35
36 /**
37  * A structure that holds node mastership roles associated with a
38  * {@link org.onosproject.net.DeviceId}. This structure needs to be locked through IMap.
39  */
40 final class RoleValue {
41
42     protected final Map<MastershipRole, List<NodeId>> value = new EnumMap<>(MastershipRole.class);
43
44     /**
45      * Constructs empty RoleValue.
46      */
47     public RoleValue() {
48         value.put(MastershipRole.MASTER, new LinkedList<NodeId>());
49         value.put(MastershipRole.STANDBY, new LinkedList<NodeId>());
50         value.put(MastershipRole.NONE, new LinkedList<NodeId>());
51     }
52
53     /**
54      * Constructs copy of specified RoleValue.
55      *
56      * @param original original to create copy from
57      */
58     public RoleValue(final RoleValue original) {
59         value.put(MASTER, Lists.newLinkedList(original.value.get(MASTER)));
60         value.put(STANDBY, Lists.newLinkedList(original.value.get(STANDBY)));
61         value.put(NONE, Lists.newLinkedList(original.value.get(NONE)));
62     }
63
64     // exposing internals for serialization purpose only
65     Map<MastershipRole, List<NodeId>> value() {
66         return Collections.unmodifiableMap(value);
67     }
68
69     public List<NodeId> nodesOfRole(MastershipRole type) {
70         return value.get(type);
71     }
72
73     /**
74      * Returns the first node to match the MastershipRole, or if there
75      * are none, null.
76      *
77      * @param type the role
78      * @return a node ID or null
79      */
80     public NodeId get(MastershipRole type) {
81         return value.get(type).isEmpty() ? null : value.get(type).get(0);
82     }
83
84     public boolean contains(MastershipRole type, NodeId nodeId) {
85         return value.get(type).contains(nodeId);
86     }
87
88     public MastershipRole getRole(NodeId nodeId) {
89         if (contains(MASTER, nodeId)) {
90             return MASTER;
91         }
92         if (contains(STANDBY, nodeId)) {
93             return STANDBY;
94         }
95         return NONE;
96     }
97
98     /**
99      * Associates a node to a certain role.
100      *
101      * @param type the role
102      * @param nodeId the node ID of the node to associate
103      * @return true if modified
104      */
105     public boolean add(MastershipRole type, NodeId nodeId) {
106         List<NodeId> nodes = value.get(type);
107
108         if (!nodes.contains(nodeId)) {
109             return nodes.add(nodeId);
110         }
111         return false;
112     }
113
114     /**
115      * Removes a node from a certain role.
116      *
117      * @param type the role
118      * @param nodeId the ID of the node to remove
119      * @return true if modified
120      */
121     public boolean remove(MastershipRole type, NodeId nodeId) {
122         List<NodeId> nodes = value.get(type);
123         if (!nodes.isEmpty()) {
124             return nodes.remove(nodeId);
125         } else {
126             return false;
127         }
128     }
129
130     /**
131      * Reassigns a node from one role to another. If the node was not of the
132      * old role, it will still be assigned the new role.
133      *
134      * @param nodeId the Node ID of node changing roles
135      * @param from the old role
136      * @param to the new role
137      * @return true if modified
138      */
139     public boolean reassign(NodeId nodeId, MastershipRole from, MastershipRole to) {
140         boolean modified = remove(from, nodeId);
141         modified |= add(to, nodeId);
142         return modified;
143     }
144
145     /**
146      * Replaces a node in one role with another node. Even if there is no node to
147      * replace, the new node is associated to the role.
148      *
149      * @param from the old NodeId to replace
150      * @param to the new NodeId
151      * @param type the role associated with the old NodeId
152      * @return true if modified
153      */
154     public boolean replace(NodeId from, NodeId to, MastershipRole type) {
155         boolean modified = remove(type, from);
156         modified |= add(type, to);
157         return modified;
158     }
159
160     /**
161      * Summarizes this RoleValue as a RoleInfo. Note that master and/or backups
162      * may be empty, so the values should be checked for safety.
163      *
164      * @return the RoleInfo.
165      */
166     public RoleInfo roleInfo() {
167         return new RoleInfo(
168                 get(MastershipRole.MASTER), nodesOfRole(MastershipRole.STANDBY));
169     }
170
171     @Override
172     public String toString() {
173         ToStringHelper helper = MoreObjects.toStringHelper(this.getClass());
174         for (Map.Entry<MastershipRole, List<NodeId>> el : value.entrySet()) {
175             helper.add(el.getKey().toString(), el.getValue());
176         }
177         return helper.toString();
178     }
179 }