blob: 10c116bad221e0dd5be4f55376f29910b85d1114 [file] [log] [blame]
tomb41d1ac2014-09-24 01:51:24 -07001package org.onlab.onos.store.cluster.impl;
2
3import com.google.common.base.Optional;
4import com.google.common.cache.LoadingCache;
5import com.google.common.collect.ImmutableSet;
6import com.hazelcast.core.IMap;
7import org.apache.felix.scr.annotations.Activate;
8import org.apache.felix.scr.annotations.Component;
9import org.apache.felix.scr.annotations.Deactivate;
10import org.apache.felix.scr.annotations.Reference;
11import org.apache.felix.scr.annotations.ReferenceCardinality;
12import org.apache.felix.scr.annotations.Service;
13import org.onlab.onos.cluster.ClusterService;
14import org.onlab.onos.cluster.MastershipEvent;
15import org.onlab.onos.cluster.MastershipStore;
tom0755a362014-09-24 11:54:43 -070016import org.onlab.onos.cluster.MastershipStoreDelegate;
tomb41d1ac2014-09-24 01:51:24 -070017import org.onlab.onos.cluster.NodeId;
18import org.onlab.onos.net.DeviceId;
19import org.onlab.onos.net.MastershipRole;
20import org.onlab.onos.store.impl.AbsentInvalidatingLoadingCache;
21import org.onlab.onos.store.impl.AbstractDistributedStore;
22import org.onlab.onos.store.impl.OptionalCacheLoader;
23
24import java.util.Map;
25import java.util.Objects;
26import java.util.Set;
27
28import static com.google.common.cache.CacheBuilder.newBuilder;
29
30/**
31 * Distributed implementation of the cluster nodes store.
32 */
33@Component(immediate = true)
34@Service
tom0755a362014-09-24 11:54:43 -070035public class DistributedMastershipStore
36 extends AbstractDistributedStore<MastershipEvent, MastershipStoreDelegate>
tomb41d1ac2014-09-24 01:51:24 -070037 implements MastershipStore {
38
39 private IMap<byte[], byte[]> rawMasters;
40 private LoadingCache<DeviceId, Optional<NodeId>> masters;
41
42 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
43 protected ClusterService clusterService;
44
Ayaka Koshibe406d0102014-09-24 16:08:12 -070045 @Override
tomb41d1ac2014-09-24 01:51:24 -070046 @Activate
47 public void activate() {
48 super.activate();
49
50 rawMasters = theInstance.getMap("masters");
51 OptionalCacheLoader<DeviceId, NodeId> nodeLoader
52 = new OptionalCacheLoader<>(storeService, rawMasters);
53 masters = new AbsentInvalidatingLoadingCache<>(newBuilder().build(nodeLoader));
54 rawMasters.addEntryListener(new RemoteEventHandler<>(masters), true);
55
56 log.info("Started");
57 }
58
59 @Deactivate
60 public void deactivate() {
61 log.info("Stopped");
62 }
63
64 @Override
Ayaka Koshibe406d0102014-09-24 16:08:12 -070065 public MastershipEvent setMaster(NodeId nodeId, DeviceId deviceId) {
tomb41d1ac2014-09-24 01:51:24 -070066 synchronized (this) {
67 NodeId currentMaster = getMaster(deviceId);
Ayaka Koshibe406d0102014-09-24 16:08:12 -070068 if (Objects.equals(currentMaster, nodeId)) {
tomb41d1ac2014-09-24 01:51:24 -070069 return null;
70 }
71
72 // FIXME: for now implementing semantics of setMaster
73 rawMasters.put(serialize(deviceId), serialize(nodeId));
74 masters.put(deviceId, Optional.of(nodeId));
75 return new MastershipEvent(MastershipEvent.Type.MASTER_CHANGED, deviceId, nodeId);
76 }
77 }
78
79 @Override
80 public NodeId getMaster(DeviceId deviceId) {
81 return masters.getUnchecked(deviceId).orNull();
82 }
83
84 @Override
85 public Set<DeviceId> getDevices(NodeId nodeId) {
86 ImmutableSet.Builder<DeviceId> builder = ImmutableSet.builder();
87 for (Map.Entry<DeviceId, Optional<NodeId>> entry : masters.asMap().entrySet()) {
88 if (nodeId.equals(entry.getValue().get())) {
89 builder.add(entry.getKey());
90 }
91 }
92 return builder.build();
93 }
94
95 @Override
96 public MastershipRole requestRole(DeviceId deviceId) {
97 // FIXME: for now we are 'selecting' as master whoever asks
Ayaka Koshibe406d0102014-09-24 16:08:12 -070098 setMaster(clusterService.getLocalNode().id(), deviceId);
tomb41d1ac2014-09-24 01:51:24 -070099 return MastershipRole.MASTER;
100 }
101
102 @Override
103 public MastershipRole getRole(NodeId nodeId, DeviceId deviceId) {
104 NodeId master = masters.getUnchecked(deviceId).orNull();
105 return nodeId.equals(master) ? MastershipRole.MASTER : MastershipRole.STANDBY;
106 }
107
108}