Madan Jampani
Committed by Gerrit Code Review

New flowrule store that utilizes a simple mechanism to periodically backsup its flowentries.

For efficiency reasons backups are only run for those devices whose flow entries are updated (since last backup) or if the device master/backup has changed.
This backup mechanism will be a short term solution until we get to a more close to real-time backup approach.
This change also disables the flowrule store based on hazelcast.

Change-Id: Iaae08852edee20b999ff97c60ca8bc6576e645f6
...@@ -17,8 +17,8 @@ package org.onosproject.store.flow; ...@@ -17,8 +17,8 @@ package org.onosproject.store.flow;
17 17
18 import static com.google.common.base.Preconditions.checkNotNull; 18 import static com.google.common.base.Preconditions.checkNotNull;
19 19
20 -import java.util.Collection;
21 import java.util.Collections; 20 import java.util.Collections;
21 +import java.util.List;
22 22
23 import org.onosproject.cluster.NodeId; 23 import org.onosproject.cluster.NodeId;
24 24
...@@ -30,15 +30,15 @@ import com.google.common.base.Optional; ...@@ -30,15 +30,15 @@ import com.google.common.base.Optional;
30 public final class ReplicaInfo { 30 public final class ReplicaInfo {
31 31
32 private final Optional<NodeId> master; 32 private final Optional<NodeId> master;
33 - private final Collection<NodeId> backups; 33 + private final List<NodeId> backups;
34 34
35 /** 35 /**
36 * Creates a ReplicaInfo instance. 36 * Creates a ReplicaInfo instance.
37 * 37 *
38 * @param master NodeId of the node where the master copy should be 38 * @param master NodeId of the node where the master copy should be
39 - * @param backups collection of NodeId, where backup copies should be placed 39 + * @param backups list of NodeId, where backup copies should be placed
40 */ 40 */
41 - public ReplicaInfo(NodeId master, Collection<NodeId> backups) { 41 + public ReplicaInfo(NodeId master, List<NodeId> backups) {
42 this.master = Optional.fromNullable(master); 42 this.master = Optional.fromNullable(master);
43 this.backups = checkNotNull(backups); 43 this.backups = checkNotNull(backups);
44 } 44 }
...@@ -57,7 +57,7 @@ public final class ReplicaInfo { ...@@ -57,7 +57,7 @@ public final class ReplicaInfo {
57 * 57 *
58 * @return collection of NodeId, where backup copies should be placed 58 * @return collection of NodeId, where backup copies should be placed
59 */ 59 */
60 - public Collection<NodeId> backups() { 60 + public List<NodeId> backups() {
61 return backups; 61 return backups;
62 } 62 }
63 63
......
...@@ -108,7 +108,7 @@ import static org.slf4j.LoggerFactory.getLogger; ...@@ -108,7 +108,7 @@ import static org.slf4j.LoggerFactory.getLogger;
108 /** 108 /**
109 * Manages inventory of flow rules using a distributed state management protocol. 109 * Manages inventory of flow rules using a distributed state management protocol.
110 */ 110 */
111 -@Component(immediate = true) 111 +@Component(immediate = false, enabled = false)
112 @Service 112 @Service
113 public class DistributedFlowRuleStore 113 public class DistributedFlowRuleStore
114 extends AbstractHazelcastStore<FlowRuleBatchEvent, FlowRuleStoreDelegate> 114 extends AbstractHazelcastStore<FlowRuleBatchEvent, FlowRuleStoreDelegate>
......
...@@ -37,4 +37,7 @@ public final class FlowStoreMessageSubjects { ...@@ -37,4 +37,7 @@ public final class FlowStoreMessageSubjects {
37 37
38 public static final MessageSubject REMOTE_APPLY_COMPLETED 38 public static final MessageSubject REMOTE_APPLY_COMPLETED
39 = new MessageSubject("peer-apply-completed"); 39 = new MessageSubject("peer-apply-completed");
40 +
41 + public static final MessageSubject FLOW_TABLE_BACKUP
42 + = new MessageSubject("peer-flow-table-backup");
40 } 43 }
......
...@@ -21,6 +21,8 @@ import static org.onosproject.store.flow.ReplicaInfoEvent.Type.MASTER_CHANGED; ...@@ -21,6 +21,8 @@ import static org.onosproject.store.flow.ReplicaInfoEvent.Type.MASTER_CHANGED;
21 import static org.onosproject.store.flow.ReplicaInfoEvent.Type.BACKUPS_CHANGED; 21 import static org.onosproject.store.flow.ReplicaInfoEvent.Type.BACKUPS_CHANGED;
22 22
23 import java.util.Collections; 23 import java.util.Collections;
24 +import java.util.List;
25 +
24 import org.apache.felix.scr.annotations.Activate; 26 import org.apache.felix.scr.annotations.Activate;
25 import org.apache.felix.scr.annotations.Component; 27 import org.apache.felix.scr.annotations.Component;
26 import org.apache.felix.scr.annotations.Deactivate; 28 import org.apache.felix.scr.annotations.Deactivate;
...@@ -28,6 +30,7 @@ import org.apache.felix.scr.annotations.Reference; ...@@ -28,6 +30,7 @@ import org.apache.felix.scr.annotations.Reference;
28 import org.apache.felix.scr.annotations.ReferenceCardinality; 30 import org.apache.felix.scr.annotations.ReferenceCardinality;
29 import org.apache.felix.scr.annotations.Service; 31 import org.apache.felix.scr.annotations.Service;
30 import org.onosproject.cluster.NodeId; 32 import org.onosproject.cluster.NodeId;
33 +import org.onosproject.cluster.RoleInfo;
31 import org.onosproject.event.AbstractListenerRegistry; 34 import org.onosproject.event.AbstractListenerRegistry;
32 import org.onosproject.event.EventDeliveryService; 35 import org.onosproject.event.EventDeliveryService;
33 import org.onosproject.mastership.MastershipEvent; 36 import org.onosproject.mastership.MastershipEvent;
...@@ -76,9 +79,7 @@ public class ReplicaInfoManager implements ReplicaInfoService { ...@@ -76,9 +79,7 @@ public class ReplicaInfoManager implements ReplicaInfoService {
76 79
77 @Override 80 @Override
78 public ReplicaInfo getReplicaInfoFor(DeviceId deviceId) { 81 public ReplicaInfo getReplicaInfoFor(DeviceId deviceId) {
79 - // TODO: populate backup List when we reach the point we need them. 82 + return buildFromRoleInfo(mastershipService.getNodesFor(deviceId));
80 - return new ReplicaInfo(mastershipService.getMasterFor(deviceId),
81 - Collections.<NodeId>emptyList());
82 } 83 }
83 84
84 @Override 85 @Override
...@@ -91,13 +92,17 @@ public class ReplicaInfoManager implements ReplicaInfoService { ...@@ -91,13 +92,17 @@ public class ReplicaInfoManager implements ReplicaInfoService {
91 listenerRegistry.removeListener(checkNotNull(listener)); 92 listenerRegistry.removeListener(checkNotNull(listener));
92 } 93 }
93 94
95 + private static ReplicaInfo buildFromRoleInfo(RoleInfo roles) {
96 + List<NodeId> backups = roles.backups() == null ?
97 + Collections.emptyList() : roles.backups();
98 + return new ReplicaInfo(roles.master(), backups);
99 + }
100 +
94 final class InternalMastershipListener implements MastershipListener { 101 final class InternalMastershipListener implements MastershipListener {
95 102
96 @Override 103 @Override
97 public void event(MastershipEvent event) { 104 public void event(MastershipEvent event) {
98 - final ReplicaInfo replicaInfo 105 + final ReplicaInfo replicaInfo = buildFromRoleInfo(event.roleInfo());
99 - = new ReplicaInfo(event.roleInfo().master(),
100 - event.roleInfo().backups());
101 106
102 switch (event.type()) { 107 switch (event.type()) {
103 case MASTER_CHANGED: 108 case MASTER_CHANGED:
......
...@@ -38,7 +38,7 @@ import java.io.InputStream; ...@@ -38,7 +38,7 @@ import java.io.InputStream;
38 /** 38 /**
39 * Auxiliary bootstrap of distributed store. 39 * Auxiliary bootstrap of distributed store.
40 */ 40 */
41 -@Component(immediate = true) 41 +@Component(immediate = false, enabled = false)
42 @Service 42 @Service
43 public class StoreManager implements StoreService { 43 public class StoreManager implements StoreService {
44 44
......
...@@ -218,6 +218,8 @@ public class ConsistentDeviceMastershipStore ...@@ -218,6 +218,8 @@ public class ConsistentDeviceMastershipStore
218 NodeId master = null; 218 NodeId master = null;
219 final List<NodeId> standbys = Lists.newLinkedList(); 219 final List<NodeId> standbys = Lists.newLinkedList();
220 220
221 + List<NodeId> candidates = leadershipService.getCandidates(createDeviceMastershipTopic(deviceId));
222 +
221 for (Map.Entry<NodeId, MastershipRole> entry : roles.entrySet()) { 223 for (Map.Entry<NodeId, MastershipRole> entry : roles.entrySet()) {
222 if (entry.getValue() == MastershipRole.MASTER) { 224 if (entry.getValue() == MastershipRole.MASTER) {
223 master = entry.getKey(); 225 master = entry.getKey();
...@@ -226,7 +228,9 @@ public class ConsistentDeviceMastershipStore ...@@ -226,7 +228,9 @@ public class ConsistentDeviceMastershipStore
226 } 228 }
227 } 229 }
228 230
229 - return new RoleInfo(master, standbys); 231 + List<NodeId> sortedStandbyList = candidates.stream().filter(standbys::contains).collect(Collectors.toList());
232 +
233 + return new RoleInfo(master, sortedStandbyList);
230 } 234 }
231 235
232 @Override 236 @Override
......
...@@ -153,6 +153,11 @@ public class ReplicaInfoManagerTest { ...@@ -153,6 +153,11 @@ public class ReplicaInfoManagerTest {
153 } 153 }
154 154
155 @Override 155 @Override
156 + public RoleInfo getNodesFor(DeviceId deviceId) {
157 + return new RoleInfo(masters.get(deviceId), Collections.emptyList());
158 + }
159 +
160 + @Override
156 public void addListener(MastershipListener listener) { 161 public void addListener(MastershipListener listener) {
157 mastershipListenerRegistry.addListener(listener); 162 mastershipListenerRegistry.addListener(listener);
158 } 163 }
......
...@@ -18,6 +18,7 @@ package org.onosproject.store.serializers; ...@@ -18,6 +18,7 @@ package org.onosproject.store.serializers;
18 import com.google.common.collect.ImmutableList; 18 import com.google.common.collect.ImmutableList;
19 import com.google.common.collect.ImmutableMap; 19 import com.google.common.collect.ImmutableMap;
20 import com.google.common.collect.ImmutableSet; 20 import com.google.common.collect.ImmutableSet;
21 +
21 import org.onlab.packet.ChassisId; 22 import org.onlab.packet.ChassisId;
22 import org.onlab.packet.Ip4Address; 23 import org.onlab.packet.Ip4Address;
23 import org.onlab.packet.Ip4Prefix; 24 import org.onlab.packet.Ip4Prefix;
...@@ -170,6 +171,8 @@ import java.util.HashMap; ...@@ -170,6 +171,8 @@ import java.util.HashMap;
170 import java.util.HashSet; 171 import java.util.HashSet;
171 import java.util.LinkedList; 172 import java.util.LinkedList;
172 import java.util.Optional; 173 import java.util.Optional;
174 +import java.util.concurrent.ConcurrentHashMap;
175 +import java.util.concurrent.CopyOnWriteArraySet;
173 176
174 public final class KryoNamespaces { 177 public final class KryoNamespaces {
175 178
...@@ -191,6 +194,8 @@ public final class KryoNamespaces { ...@@ -191,6 +194,8 @@ public final class KryoNamespaces {
191 ImmutableMap.of("a", 1).getClass(), 194 ImmutableMap.of("a", 1).getClass(),
192 ImmutableMap.of("R", 2, "D", 2).getClass()) 195 ImmutableMap.of("R", 2, "D", 2).getClass())
193 .register(HashMap.class) 196 .register(HashMap.class)
197 + .register(ConcurrentHashMap.class)
198 + .register(CopyOnWriteArraySet.class)
194 .register(ArrayList.class, 199 .register(ArrayList.class,
195 LinkedList.class, 200 LinkedList.class,
196 HashSet.class 201 HashSet.class
......