blob: 61dbe6196c2e7179b80e28506be79056faf9c2c8 [file] [log] [blame]
Ayaka Koshibea7f044e2014-09-23 16:56:20 -07001package org.onlab.onos.net.trivial.impl;
2
3import static org.slf4j.LoggerFactory.getLogger;
4
5import java.util.Collections;
Ayaka Koshibeb70d34b2014-09-25 15:43:01 -07006import java.util.HashMap;
Ayaka Koshibe406d0102014-09-24 16:08:12 -07007import java.util.HashSet;
8import java.util.Map;
Ayaka Koshibea7f044e2014-09-23 16:56:20 -07009import java.util.Set;
10import java.util.concurrent.ConcurrentHashMap;
11import java.util.concurrent.ConcurrentMap;
Ayaka Koshibeb70d34b2014-09-25 15:43:01 -070012import java.util.concurrent.atomic.AtomicInteger;
Ayaka Koshibea7f044e2014-09-23 16:56:20 -070013
14import org.apache.felix.scr.annotations.Activate;
15import org.apache.felix.scr.annotations.Component;
16import org.apache.felix.scr.annotations.Deactivate;
17import org.apache.felix.scr.annotations.Service;
18import org.onlab.onos.cluster.ControllerNode;
19import org.onlab.onos.cluster.DefaultControllerNode;
20import org.onlab.onos.cluster.MastershipEvent;
21import org.onlab.onos.cluster.MastershipStore;
tomf80c9722014-09-24 14:49:18 -070022import org.onlab.onos.cluster.MastershipStoreDelegate;
Ayaka Koshibeb70d34b2014-09-25 15:43:01 -070023import org.onlab.onos.cluster.MastershipTerm;
Ayaka Koshibea7f044e2014-09-23 16:56:20 -070024import org.onlab.onos.cluster.NodeId;
25import org.onlab.onos.net.DeviceId;
26import org.onlab.onos.net.MastershipRole;
tomf80c9722014-09-24 14:49:18 -070027import org.onlab.onos.store.AbstractStore;
Ayaka Koshibea7f044e2014-09-23 16:56:20 -070028import org.onlab.packet.IpPrefix;
29import org.slf4j.Logger;
30
31import static org.onlab.onos.cluster.MastershipEvent.Type.*;
32
33/**
34 * Manages inventory of controller mastership over devices using
Ayaka Koshibe406d0102014-09-24 16:08:12 -070035 * trivial, non-distributed in-memory structures implementation.
Ayaka Koshibea7f044e2014-09-23 16:56:20 -070036 */
37@Component(immediate = true)
38@Service
tomf80c9722014-09-24 14:49:18 -070039public class SimpleMastershipStore
40 extends AbstractStore<MastershipEvent, MastershipStoreDelegate>
41 implements MastershipStore {
Ayaka Koshibea7f044e2014-09-23 16:56:20 -070042
Ayaka Koshibea7f044e2014-09-23 16:56:20 -070043 private final Logger log = getLogger(getClass());
44
Ayaka Koshibe406d0102014-09-24 16:08:12 -070045 public static final IpPrefix LOCALHOST = IpPrefix.valueOf("127.0.0.1");
Ayaka Koshibea7f044e2014-09-23 16:56:20 -070046
Ayaka Koshibe406d0102014-09-24 16:08:12 -070047 private ControllerNode instance =
48 new DefaultControllerNode(new NodeId("local"), LOCALHOST);
49
50 //devices mapped to their masters, to emulate multiple nodes
51 protected final ConcurrentMap<DeviceId, NodeId> masterMap =
tomb41d1ac2014-09-24 01:51:24 -070052 new ConcurrentHashMap<>();
Ayaka Koshibeb70d34b2014-09-25 15:43:01 -070053 protected final Map<DeviceId, AtomicInteger> termMap = new HashMap<>();
Ayaka Koshibea7f044e2014-09-23 16:56:20 -070054
55 @Activate
56 public void activate() {
Ayaka Koshibea7f044e2014-09-23 16:56:20 -070057 log.info("Started");
58 }
59
60 @Deactivate
61 public void deactivate() {
62 log.info("Stopped");
63 }
64
65 @Override
Ayaka Koshibe406d0102014-09-24 16:08:12 -070066 public MastershipEvent setMaster(NodeId nodeId, DeviceId deviceId) {
67
68 NodeId node = masterMap.get(deviceId);
69 if (node == null) {
Ayaka Koshibeb70d34b2014-09-25 15:43:01 -070070 synchronized (this) {
71 masterMap.put(deviceId, nodeId);
72 termMap.put(deviceId, new AtomicInteger());
73 }
Ayaka Koshibe406d0102014-09-24 16:08:12 -070074 return new MastershipEvent(MASTER_CHANGED, deviceId, nodeId);
Ayaka Koshibea7f044e2014-09-23 16:56:20 -070075 }
Ayaka Koshibe406d0102014-09-24 16:08:12 -070076
77 if (node.equals(nodeId)) {
78 return null;
79 } else {
Ayaka Koshibeb70d34b2014-09-25 15:43:01 -070080 synchronized (this) {
81 masterMap.put(deviceId, nodeId);
82 termMap.get(deviceId).incrementAndGet();
83 return new MastershipEvent(MASTER_CHANGED, deviceId, nodeId);
84 }
Ayaka Koshibe406d0102014-09-24 16:08:12 -070085 }
Ayaka Koshibea7f044e2014-09-23 16:56:20 -070086 }
87
88 @Override
Ayaka Koshibea7f044e2014-09-23 16:56:20 -070089 public NodeId getMaster(DeviceId deviceId) {
Ayaka Koshibe406d0102014-09-24 16:08:12 -070090 return masterMap.get(deviceId);
Ayaka Koshibea7f044e2014-09-23 16:56:20 -070091 }
92
93 @Override
94 public Set<DeviceId> getDevices(NodeId nodeId) {
Ayaka Koshibe406d0102014-09-24 16:08:12 -070095 Set<DeviceId> ids = new HashSet<>();
96 for (Map.Entry<DeviceId, NodeId> d : masterMap.entrySet()) {
97 if (d.getValue().equals(nodeId)) {
98 ids.add(d.getKey());
99 }
100 }
101 return Collections.unmodifiableSet(ids);
Ayaka Koshibea7f044e2014-09-23 16:56:20 -0700102 }
103
104 @Override
tomb41d1ac2014-09-24 01:51:24 -0700105 public MastershipRole requestRole(DeviceId deviceId) {
106 return getRole(instance.id(), deviceId);
107 }
108
109 @Override
Ayaka Koshibea7f044e2014-09-23 16:56:20 -0700110 public MastershipRole getRole(NodeId nodeId, DeviceId deviceId) {
Ayaka Koshibe406d0102014-09-24 16:08:12 -0700111 NodeId node = masterMap.get(deviceId);
112 MastershipRole role;
113 if (node != null) {
114 if (node.equals(nodeId)) {
115 role = MastershipRole.MASTER;
116 } else {
117 role = MastershipRole.STANDBY;
118 }
119 } else {
120 //masterMap doesn't contain it.
Ayaka Koshibea7f044e2014-09-23 16:56:20 -0700121 role = MastershipRole.MASTER;
Ayaka Koshibe406d0102014-09-24 16:08:12 -0700122 masterMap.put(deviceId, nodeId);
Ayaka Koshibea7f044e2014-09-23 16:56:20 -0700123 }
124 return role;
125 }
126
Ayaka Koshibeb70d34b2014-09-25 15:43:01 -0700127 @Override
128 public MastershipTerm getTermFor(DeviceId deviceId) {
129 if (masterMap.get(deviceId) == null) {
130 return null;
131 }
132 return MastershipTerm.of(
133 masterMap.get(deviceId), termMap.get(deviceId).get());
134 }
135
Ayaka Koshibea7f044e2014-09-23 16:56:20 -0700136}