blob: d3fcf3eb77d2c983972a0f3ffff9df135e8a4abd [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;
Yuta HIGUCHIc8e19d42014-09-24 17:20:52 -07007
tomb41d1ac2014-09-24 01:51:24 -07008import org.apache.felix.scr.annotations.Activate;
9import org.apache.felix.scr.annotations.Component;
10import org.apache.felix.scr.annotations.Deactivate;
11import org.apache.felix.scr.annotations.Reference;
12import org.apache.felix.scr.annotations.ReferenceCardinality;
13import org.apache.felix.scr.annotations.Service;
14import org.onlab.onos.cluster.ClusterService;
15import org.onlab.onos.cluster.MastershipEvent;
16import org.onlab.onos.cluster.MastershipStore;
tom0755a362014-09-24 11:54:43 -070017import org.onlab.onos.cluster.MastershipStoreDelegate;
tomb41d1ac2014-09-24 01:51:24 -070018import org.onlab.onos.cluster.NodeId;
19import org.onlab.onos.net.DeviceId;
20import org.onlab.onos.net.MastershipRole;
21import org.onlab.onos.store.impl.AbsentInvalidatingLoadingCache;
22import org.onlab.onos.store.impl.AbstractDistributedStore;
23import org.onlab.onos.store.impl.OptionalCacheLoader;
24
25import java.util.Map;
26import java.util.Objects;
27import java.util.Set;
28
29import static com.google.common.cache.CacheBuilder.newBuilder;
30
31/**
32 * Distributed implementation of the cluster nodes store.
33 */
34@Component(immediate = true)
35@Service
tom0755a362014-09-24 11:54:43 -070036public class DistributedMastershipStore
37 extends AbstractDistributedStore<MastershipEvent, MastershipStoreDelegate>
tomb41d1ac2014-09-24 01:51:24 -070038 implements MastershipStore {
39
40 private IMap<byte[], byte[]> rawMasters;
41 private LoadingCache<DeviceId, Optional<NodeId>> masters;
42
43 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
44 protected ClusterService clusterService;
45
Ayaka Koshibe406d0102014-09-24 16:08:12 -070046 @Override
tomb41d1ac2014-09-24 01:51:24 -070047 @Activate
48 public void activate() {
49 super.activate();
50
51 rawMasters = theInstance.getMap("masters");
52 OptionalCacheLoader<DeviceId, NodeId> nodeLoader
53 = new OptionalCacheLoader<>(storeService, rawMasters);
54 masters = new AbsentInvalidatingLoadingCache<>(newBuilder().build(nodeLoader));
55 rawMasters.addEntryListener(new RemoteEventHandler<>(masters), true);
56
Yuta HIGUCHIc8e19d42014-09-24 17:20:52 -070057 loadMasters();
58
tomb41d1ac2014-09-24 01:51:24 -070059 log.info("Started");
60 }
61
Yuta HIGUCHIc8e19d42014-09-24 17:20:52 -070062 private void loadMasters() {
63 for (byte[] keyBytes : rawMasters.keySet()) {
64 final DeviceId id = deserialize(keyBytes);
65 masters.refresh(id);
66 }
67 }
68
tomb41d1ac2014-09-24 01:51:24 -070069 @Deactivate
70 public void deactivate() {
71 log.info("Stopped");
72 }
73
74 @Override
Ayaka Koshibe406d0102014-09-24 16:08:12 -070075 public MastershipEvent setMaster(NodeId nodeId, DeviceId deviceId) {
tomb41d1ac2014-09-24 01:51:24 -070076 synchronized (this) {
77 NodeId currentMaster = getMaster(deviceId);
Ayaka Koshibe406d0102014-09-24 16:08:12 -070078 if (Objects.equals(currentMaster, nodeId)) {
tomb41d1ac2014-09-24 01:51:24 -070079 return null;
80 }
81
82 // FIXME: for now implementing semantics of setMaster
83 rawMasters.put(serialize(deviceId), serialize(nodeId));
84 masters.put(deviceId, Optional.of(nodeId));
85 return new MastershipEvent(MastershipEvent.Type.MASTER_CHANGED, deviceId, nodeId);
86 }
87 }
88
89 @Override
90 public NodeId getMaster(DeviceId deviceId) {
91 return masters.getUnchecked(deviceId).orNull();
92 }
93
94 @Override
95 public Set<DeviceId> getDevices(NodeId nodeId) {
96 ImmutableSet.Builder<DeviceId> builder = ImmutableSet.builder();
97 for (Map.Entry<DeviceId, Optional<NodeId>> entry : masters.asMap().entrySet()) {
98 if (nodeId.equals(entry.getValue().get())) {
99 builder.add(entry.getKey());
100 }
101 }
102 return builder.build();
103 }
104
105 @Override
106 public MastershipRole requestRole(DeviceId deviceId) {
107 // FIXME: for now we are 'selecting' as master whoever asks
Ayaka Koshibe406d0102014-09-24 16:08:12 -0700108 setMaster(clusterService.getLocalNode().id(), deviceId);
tomb41d1ac2014-09-24 01:51:24 -0700109 return MastershipRole.MASTER;
110 }
111
112 @Override
113 public MastershipRole getRole(NodeId nodeId, DeviceId deviceId) {
114 NodeId master = masters.getUnchecked(deviceId).orNull();
115 return nodeId.equals(master) ? MastershipRole.MASTER : MastershipRole.STANDBY;
116 }
117
118}