blob: 18e6e96eab364e5391e88c5abc0ce5aeb04acae9 [file] [log] [blame]
tomb41d1ac2014-09-24 01:51:24 -07001package org.onlab.onos.store.cluster.impl;
2
alshabib339a3d92014-09-26 17:54:32 -07003import static com.google.common.cache.CacheBuilder.newBuilder;
4import static org.onlab.onos.cluster.MastershipEvent.Type.MASTER_CHANGED;
5
6import java.util.Map;
7import java.util.Objects;
8import java.util.Set;
Yuta HIGUCHIc8e19d42014-09-24 17:20:52 -07009
tomb41d1ac2014-09-24 01:51:24 -070010import org.apache.felix.scr.annotations.Activate;
11import org.apache.felix.scr.annotations.Component;
12import org.apache.felix.scr.annotations.Deactivate;
13import org.apache.felix.scr.annotations.Reference;
14import org.apache.felix.scr.annotations.ReferenceCardinality;
15import org.apache.felix.scr.annotations.Service;
16import org.onlab.onos.cluster.ClusterService;
17import org.onlab.onos.cluster.MastershipEvent;
18import org.onlab.onos.cluster.MastershipStore;
tom0755a362014-09-24 11:54:43 -070019import org.onlab.onos.cluster.MastershipStoreDelegate;
Ayaka Koshibeb70d34b2014-09-25 15:43:01 -070020import org.onlab.onos.cluster.MastershipTerm;
tomb41d1ac2014-09-24 01:51:24 -070021import org.onlab.onos.cluster.NodeId;
22import org.onlab.onos.net.DeviceId;
23import org.onlab.onos.net.MastershipRole;
Yuta HIGUCHIb5df76d2014-09-27 20:54:00 -070024import org.onlab.onos.store.common.AbsentInvalidatingLoadingCache;
25import org.onlab.onos.store.common.AbstractHazelcastStore;
26import org.onlab.onos.store.common.OptionalCacheLoader;
tomb41d1ac2014-09-24 01:51:24 -070027
alshabib339a3d92014-09-26 17:54:32 -070028import com.google.common.base.Optional;
29import com.google.common.cache.LoadingCache;
30import com.google.common.collect.ImmutableSet;
31import com.hazelcast.core.IMap;
tomb41d1ac2014-09-24 01:51:24 -070032
33/**
34 * Distributed implementation of the cluster nodes store.
35 */
36@Component(immediate = true)
37@Service
tom0755a362014-09-24 11:54:43 -070038public class DistributedMastershipStore
Yuta HIGUCHI2e963892014-09-27 13:00:39 -070039extends AbstractHazelcastStore<MastershipEvent, MastershipStoreDelegate>
alshabib339a3d92014-09-26 17:54:32 -070040implements MastershipStore {
tomb41d1ac2014-09-24 01:51:24 -070041
42 private IMap<byte[], byte[]> rawMasters;
43 private LoadingCache<DeviceId, Optional<NodeId>> masters;
44
45 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
46 protected ClusterService clusterService;
47
Ayaka Koshibe406d0102014-09-24 16:08:12 -070048 @Override
tomb41d1ac2014-09-24 01:51:24 -070049 @Activate
50 public void activate() {
51 super.activate();
52
53 rawMasters = theInstance.getMap("masters");
54 OptionalCacheLoader<DeviceId, NodeId> nodeLoader
Yuta HIGUCHIad4c2182014-09-29 11:16:23 -070055 = new OptionalCacheLoader<>(kryoSerializationService, rawMasters);
tomb41d1ac2014-09-24 01:51:24 -070056 masters = new AbsentInvalidatingLoadingCache<>(newBuilder().build(nodeLoader));
alshabib339a3d92014-09-26 17:54:32 -070057 rawMasters.addEntryListener(new RemoteMasterShipEventHandler(masters), true);
tomb41d1ac2014-09-24 01:51:24 -070058
Yuta HIGUCHIc8e19d42014-09-24 17:20:52 -070059 loadMasters();
60
tomb41d1ac2014-09-24 01:51:24 -070061 log.info("Started");
62 }
63
Yuta HIGUCHIc8e19d42014-09-24 17:20:52 -070064 private void loadMasters() {
65 for (byte[] keyBytes : rawMasters.keySet()) {
66 final DeviceId id = deserialize(keyBytes);
67 masters.refresh(id);
68 }
69 }
70
tomb41d1ac2014-09-24 01:51:24 -070071 @Deactivate
72 public void deactivate() {
73 log.info("Stopped");
74 }
75
76 @Override
Ayaka Koshibe406d0102014-09-24 16:08:12 -070077 public MastershipEvent setMaster(NodeId nodeId, DeviceId deviceId) {
tomb41d1ac2014-09-24 01:51:24 -070078 synchronized (this) {
79 NodeId currentMaster = getMaster(deviceId);
Ayaka Koshibe406d0102014-09-24 16:08:12 -070080 if (Objects.equals(currentMaster, nodeId)) {
tomb41d1ac2014-09-24 01:51:24 -070081 return null;
82 }
83
84 // FIXME: for now implementing semantics of setMaster
85 rawMasters.put(serialize(deviceId), serialize(nodeId));
86 masters.put(deviceId, Optional.of(nodeId));
87 return new MastershipEvent(MastershipEvent.Type.MASTER_CHANGED, deviceId, nodeId);
88 }
89 }
90
91 @Override
92 public NodeId getMaster(DeviceId deviceId) {
93 return masters.getUnchecked(deviceId).orNull();
94 }
95
96 @Override
97 public Set<DeviceId> getDevices(NodeId nodeId) {
98 ImmutableSet.Builder<DeviceId> builder = ImmutableSet.builder();
99 for (Map.Entry<DeviceId, Optional<NodeId>> entry : masters.asMap().entrySet()) {
100 if (nodeId.equals(entry.getValue().get())) {
101 builder.add(entry.getKey());
102 }
103 }
104 return builder.build();
105 }
106
107 @Override
108 public MastershipRole requestRole(DeviceId deviceId) {
109 // FIXME: for now we are 'selecting' as master whoever asks
Ayaka Koshibe406d0102014-09-24 16:08:12 -0700110 setMaster(clusterService.getLocalNode().id(), deviceId);
tomb41d1ac2014-09-24 01:51:24 -0700111 return MastershipRole.MASTER;
112 }
113
114 @Override
115 public MastershipRole getRole(NodeId nodeId, DeviceId deviceId) {
116 NodeId master = masters.getUnchecked(deviceId).orNull();
117 return nodeId.equals(master) ? MastershipRole.MASTER : MastershipRole.STANDBY;
118 }
119
Ayaka Koshibeb70d34b2014-09-25 15:43:01 -0700120 @Override
121 public MastershipTerm getTermFor(DeviceId deviceId) {
122 // TODO Auto-generated method stub
123 return null;
124 }
125
Ayaka Koshibed9f693e2014-09-29 18:04:54 -0700126 @Override
127 public MastershipEvent unsetMaster(NodeId nodeId, DeviceId deviceId) {
128 // TODO Auto-generated method stub
129 return null;
130 }
131
Yuta HIGUCHIfec9e192014-09-28 14:58:02 -0700132 private class RemoteMasterShipEventHandler extends RemoteCacheEventHandler<DeviceId, NodeId> {
alshabib339a3d92014-09-26 17:54:32 -0700133 public RemoteMasterShipEventHandler(LoadingCache<DeviceId, Optional<NodeId>> cache) {
134 super(cache);
135 }
136
137 @Override
138 protected void onAdd(DeviceId deviceId, NodeId nodeId) {
139 notifyDelegate(new MastershipEvent(MASTER_CHANGED, deviceId, nodeId));
140 }
141
142 @Override
143 protected void onRemove(DeviceId deviceId, NodeId nodeId) {
144 notifyDelegate(new MastershipEvent(MASTER_CHANGED, deviceId, nodeId));
145 }
146
147 @Override
148 protected void onUpdate(DeviceId deviceId, NodeId oldNodeId, NodeId nodeId) {
149 notifyDelegate(new MastershipEvent(MASTER_CHANGED, deviceId, nodeId));
150 }
151 }
152
tomb41d1ac2014-09-24 01:51:24 -0700153}