Ayaka Koshibe

Merge branch 'master' of ssh://gerrit.onlab.us:29418/onos-next

Conflicts:
	core/net/src/main/java/org/onlab/onos/cluster/impl/MastershipManager.java
	core/net/src/main/java/org/onlab/onos/net/device/impl/DeviceManager.java
	core/store/hz/cluster/src/main/java/org/onlab/onos/store/cluster/impl/DistributedMastershipStore.java

Change-Id: I6a8b756fc20968e18ea3fd145e155d6282cea945
Showing 117 changed files with 2914 additions and 171 deletions
...@@ -28,10 +28,6 @@ ...@@ -28,10 +28,6 @@
28 <version>${project.version}</version> 28 <version>${project.version}</version>
29 </dependency> 29 </dependency>
30 <dependency> 30 <dependency>
31 - <groupId>org.livetribe.slp</groupId>
32 - <artifactId>livetribe-slp</artifactId>
33 - </dependency>
34 - <dependency>
35 <groupId>org.apache.karaf.shell</groupId> 31 <groupId>org.apache.karaf.shell</groupId>
36 <artifactId>org.apache.karaf.shell.console</artifactId> 32 <artifactId>org.apache.karaf.shell.console</artifactId>
37 </dependency> 33 </dependency>
......
...@@ -233,7 +233,7 @@ public class IOLoopTestClient { ...@@ -233,7 +233,7 @@ public class IOLoopTestClient {
233 } 233 }
234 234
235 @Override 235 @Override
236 - protected void connect(SelectionKey key) { 236 + protected void connect(SelectionKey key) throws IOException {
237 super.connect(key); 237 super.connect(key);
238 TestMessageStream b = (TestMessageStream) key.attachment(); 238 TestMessageStream b = (TestMessageStream) key.attachment();
239 Worker w = ((CustomIOLoop) b.loop()).worker; 239 Worker w = ((CustomIOLoop) b.loop()).worker;
......
1 /** 1 /**
2 * Sample application for use in various experiments. 2 * Sample application for use in various experiments.
3 */ 3 */
4 -package org.onlab.onos.foo;
...\ No newline at end of file ...\ No newline at end of file
4 +package org.onlab.onos.foo;
......
1 +livetribe.slp.da.expired.services.purge.period=60
2 +livetribe.slp.sa.client.connect.address=127.0.0.1
3 +livetribe.slp.sa.client.factory=org.livetribe.slp.sa.StandardServiceAgentClient$Factory
4 +livetribe.slp.sa.factory=org.livetribe.slp.sa.StandardServiceAgent$Factory
5 +livetribe.slp.sa.service.renewal.enabled=true
6 +livetribe.slp.sa.unicast.prefer.tcp=false
7 +livetribe.slp.tcp.connector.factory=org.livetribe.slp.spi.net.SocketTCPConnector$Factory
8 +livetribe.slp.tcp.connector.server.factory=org.livetribe.slp.spi.net.SocketTCPConnectorServer$Factory
9 +livetribe.slp.tcp.message.max.length=4096
10 +livetribe.slp.tcp.read.timeout=300000
11 +livetribe.slp.ua.client.factory=org.livetribe.slp.ua.StandardUserAgentClient$Factory
12 +livetribe.slp.ua.factory=org.livetribe.slp.ua.StandardUserAgent$Factory
13 +livetribe.slp.ua.unicast.prefer.tcp=false
14 +livetribe.slp.udp.connector.factory=org.livetribe.slp.spi.net.SocketUDPConnector$Factory
15 +livetribe.slp.udp.connector.server.factory=org.livetribe.slp.spi.net.SocketUDPConnectorServer$Factory
16 +net.slp.DAAddresses=
17 +net.slp.DAAttributes=
18 +net.slp.DAHeartBeat=10800
19 +net.slp.MTU=1400
20 +net.slp.SAAttributes=
21 +net.slp.broadcastAddress=255.255.255.255
22 +net.slp.datagramTimeouts=150,250,400
23 +net.slp.interfaces=0.0.0.0
24 +net.slp.isBroadcastOnly=false
25 +net.slp.locale=en
26 +net.slp.multicastAddress=239.255.255.253
27 +net.slp.multicastMaximumWait=15000
28 +net.slp.multicastTTL=255
29 +net.slp.multicastTimeouts=150,250,400,600,1000
30 +net.slp.notificationPort=1847
31 +net.slp.port=427
32 +net.slp.useScopes=default
33 +
34 +org.onlab.cluster.name = TV-ONOS
1 +package org.onlab.onos.cli;
2 +
3 +import org.apache.karaf.shell.commands.Argument;
4 +import org.apache.karaf.shell.commands.Command;
5 +import org.onlab.onos.cluster.ClusterAdminService;
6 +import org.onlab.onos.cluster.NodeId;
7 +import org.onlab.packet.IpPrefix;
8 +
9 +/**
10 + * Adds a new controller cluster node.
11 + */
12 +@Command(scope = "onos", name = "add-node",
13 + description = "Adds a new controller cluster node")
14 +public class NodeAddCommand extends AbstractShellCommand {
15 +
16 + @Argument(index = 0, name = "nodeId", description = "Node ID",
17 + required = true, multiValued = false)
18 + String nodeId = null;
19 +
20 + @Argument(index = 1, name = "ip", description = "Node IP address",
21 + required = true, multiValued = false)
22 + String ip = null;
23 +
24 + @Argument(index = 2, name = "tcpPort", description = "Node TCP listen port",
25 + required = false, multiValued = false)
26 + int tcpPort = 9876;
27 +
28 + @Override
29 + protected void execute() {
30 + ClusterAdminService service = get(ClusterAdminService.class);
31 + service.addNode(new NodeId(nodeId), IpPrefix.valueOf(ip), tcpPort);
32 + }
33 +
34 +}
1 +package org.onlab.onos.cli;
2 +
3 +import org.apache.karaf.shell.commands.Argument;
4 +import org.apache.karaf.shell.commands.Command;
5 +import org.onlab.onos.cluster.ClusterAdminService;
6 +import org.onlab.onos.cluster.NodeId;
7 +
8 +/**
9 + * Removes a controller cluster node.
10 + */
11 +@Command(scope = "onos", name = "remove-node",
12 + description = "Removes a new controller cluster node")
13 +public class NodeRemoveCommand extends AbstractShellCommand {
14 +
15 + @Argument(index = 0, name = "nodeId", description = "Node ID",
16 + required = true, multiValued = false)
17 + String nodeId = null;
18 +
19 + @Override
20 + protected void execute() {
21 + ClusterAdminService service = get(ClusterAdminService.class);
22 + service.removeNode(new NodeId(nodeId));
23 + }
24 +
25 +}
...@@ -17,7 +17,7 @@ import static com.google.common.collect.Lists.newArrayList; ...@@ -17,7 +17,7 @@ import static com.google.common.collect.Lists.newArrayList;
17 public class NodesListCommand extends AbstractShellCommand { 17 public class NodesListCommand extends AbstractShellCommand {
18 18
19 private static final String FMT = 19 private static final String FMT =
20 - "id=%s, ip=%s, state=%s %s"; 20 + "id=%s, address=%s:%s, state=%s %s";
21 21
22 @Override 22 @Override
23 protected void execute() { 23 protected void execute() {
...@@ -26,7 +26,7 @@ public class NodesListCommand extends AbstractShellCommand { ...@@ -26,7 +26,7 @@ public class NodesListCommand extends AbstractShellCommand {
26 Collections.sort(nodes, Comparators.NODE_COMPARATOR); 26 Collections.sort(nodes, Comparators.NODE_COMPARATOR);
27 ControllerNode self = service.getLocalNode(); 27 ControllerNode self = service.getLocalNode();
28 for (ControllerNode node : nodes) { 28 for (ControllerNode node : nodes) {
29 - print(FMT, node.id(), node.ip(), 29 + print(FMT, node.id(), node.ip(), node.tcpPort(),
30 service.getState(node.id()), 30 service.getState(node.id()),
31 node.equals(self) ? "*" : ""); 31 node.equals(self) ? "*" : "");
32 } 32 }
......
...@@ -103,4 +103,4 @@ public class FlowsListCommand extends AbstractShellCommand { ...@@ -103,4 +103,4 @@ public class FlowsListCommand extends AbstractShellCommand {
103 103
104 } 104 }
105 105
106 -}
...\ No newline at end of file ...\ No newline at end of file
106 +}
......
...@@ -5,6 +5,12 @@ ...@@ -5,6 +5,12 @@
5 <action class="org.onlab.onos.cli.NodesListCommand"/> 5 <action class="org.onlab.onos.cli.NodesListCommand"/>
6 </command> 6 </command>
7 <command> 7 <command>
8 + <action class="org.onlab.onos.cli.NodeAddCommand"/>
9 + </command>
10 + <command>
11 + <action class="org.onlab.onos.cli.NodeRemoveCommand"/>
12 + </command>
13 + <command>
8 <action class="org.onlab.onos.cli.MastersListCommand"/> 14 <action class="org.onlab.onos.cli.MastersListCommand"/>
9 <completers> 15 <completers>
10 <ref component-id="clusterIdCompleter"/> 16 <ref component-id="clusterIdCompleter"/>
......
1 package org.onlab.onos.cluster; 1 package org.onlab.onos.cluster;
2 2
3 +import org.onlab.packet.IpPrefix;
4 +
3 /** 5 /**
4 * Service for administering the cluster node membership. 6 * Service for administering the cluster node membership.
5 */ 7 */
6 public interface ClusterAdminService { 8 public interface ClusterAdminService {
7 9
8 /** 10 /**
11 + * Adds a new controller node to the cluster.
12 + *
13 + * @param nodeId controller node identifier
14 + * @param ip node IP listen address
15 + * @param tcpPort tcp listen port
16 + * @return newly added node
17 + */
18 + ControllerNode addNode(NodeId nodeId, IpPrefix ip, int tcpPort);
19 +
20 + /**
9 * Removes the specified node from the cluster node list. 21 * Removes the specified node from the cluster node list.
10 * 22 *
11 * @param nodeId controller node identifier 23 * @param nodeId controller node identifier
......
1 package org.onlab.onos.cluster; 1 package org.onlab.onos.cluster;
2 2
3 import org.onlab.onos.store.Store; 3 import org.onlab.onos.store.Store;
4 +import org.onlab.packet.IpPrefix;
4 5
5 import java.util.Set; 6 import java.util.Set;
6 7
...@@ -40,6 +41,16 @@ public interface ClusterStore extends Store<ClusterEvent, ClusterStoreDelegate> ...@@ -40,6 +41,16 @@ public interface ClusterStore extends Store<ClusterEvent, ClusterStoreDelegate>
40 ControllerNode.State getState(NodeId nodeId); 41 ControllerNode.State getState(NodeId nodeId);
41 42
42 /** 43 /**
44 + * Adds a new controller node to the cluster.
45 + *
46 + * @param nodeId controller node identifier
47 + * @param ip node IP listen address
48 + * @param tcpPort tcp listen port
49 + * @return newly added node
50 + */
51 + ControllerNode addNode(NodeId nodeId, IpPrefix ip, int tcpPort);
52 +
53 + /**
43 * Removes the specified node from the inventory of cluster nodes. 54 * Removes the specified node from the inventory of cluster nodes.
44 * 55 *
45 * @param nodeId controller instance identifier 56 * @param nodeId controller instance identifier
......
...@@ -35,4 +35,12 @@ public interface ControllerNode { ...@@ -35,4 +35,12 @@ public interface ControllerNode {
35 */ 35 */
36 IpPrefix ip(); 36 IpPrefix ip();
37 37
38 +
39 + /**
40 + * Returns the TCP port on which the node listens for connections.
41 + *
42 + * @return TCP port
43 + */
44 + int tcpPort();
45 +
38 } 46 }
......
...@@ -11,13 +11,17 @@ import static com.google.common.base.MoreObjects.toStringHelper; ...@@ -11,13 +11,17 @@ import static com.google.common.base.MoreObjects.toStringHelper;
11 */ 11 */
12 public class DefaultControllerNode implements ControllerNode { 12 public class DefaultControllerNode implements ControllerNode {
13 13
14 + private static final int DEFAULT_PORT = 9876;
15 +
14 private final NodeId id; 16 private final NodeId id;
15 private final IpPrefix ip; 17 private final IpPrefix ip;
18 + private final int tcpPort;
16 19
17 // For serialization 20 // For serialization
18 private DefaultControllerNode() { 21 private DefaultControllerNode() {
19 this.id = null; 22 this.id = null;
20 this.ip = null; 23 this.ip = null;
24 + this.tcpPort = 0;
21 } 25 }
22 26
23 /** 27 /**
...@@ -27,8 +31,19 @@ public class DefaultControllerNode implements ControllerNode { ...@@ -27,8 +31,19 @@ public class DefaultControllerNode implements ControllerNode {
27 * @param ip instance IP address 31 * @param ip instance IP address
28 */ 32 */
29 public DefaultControllerNode(NodeId id, IpPrefix ip) { 33 public DefaultControllerNode(NodeId id, IpPrefix ip) {
34 + this(id, ip, DEFAULT_PORT);
35 + }
36 +
37 + /**
38 + * Creates a new instance with the specified id and IP address and TCP port.
39 + *
40 + * @param id instance identifier
41 + * @param ip instance IP address
42 + */
43 + public DefaultControllerNode(NodeId id, IpPrefix ip, int tcpPort) {
30 this.id = id; 44 this.id = id;
31 this.ip = ip; 45 this.ip = ip;
46 + this.tcpPort = tcpPort;
32 } 47 }
33 48
34 @Override 49 @Override
...@@ -42,6 +57,11 @@ public class DefaultControllerNode implements ControllerNode { ...@@ -42,6 +57,11 @@ public class DefaultControllerNode implements ControllerNode {
42 } 57 }
43 58
44 @Override 59 @Override
60 + public int tcpPort() {
61 + return tcpPort;
62 + }
63 +
64 + @Override
45 public int hashCode() { 65 public int hashCode() {
46 return Objects.hash(id); 66 return Objects.hash(id);
47 } 67 }
...@@ -60,7 +80,8 @@ public class DefaultControllerNode implements ControllerNode { ...@@ -60,7 +80,8 @@ public class DefaultControllerNode implements ControllerNode {
60 80
61 @Override 81 @Override
62 public String toString() { 82 public String toString() {
63 - return toStringHelper(this).add("id", id).add("ip", ip).toString(); 83 + return toStringHelper(this).add("id", id)
84 + .add("ip", ip).add("tcpPort", tcpPort).toString();
64 } 85 }
65 86
66 } 87 }
......
1 +package org.onlab.onos.net.proxyarp;
2 +
3 +import org.onlab.packet.Ethernet;
4 +import org.onlab.packet.IpPrefix;
5 +
6 +/**
7 + * Service for processing arp requests on behalf of applications.
8 + */
9 +public interface ProxyArpService {
10 +
11 + /**
12 + * Returns whether this particular ip address is known to the system.
13 + *
14 + * @param addr
15 + * a ip address
16 + * @return true if know, false otherwise
17 + */
18 + boolean known(IpPrefix addr);
19 +
20 + /**
21 + * Sends a reply for a given request. If the host is not known then the arp
22 + * will be flooded at all edge ports.
23 + *
24 + * @param request
25 + * an arp request
26 + */
27 + void reply(Ethernet request);
28 +
29 +}
1 +/**
2 + * Base abstractions related to the proxy arp service.
3 + */
4 +package org.onlab.onos.net.proxyarp;
1 +package org.onlab.onos.store;
2 +
3 +import org.onlab.onos.cluster.MastershipTerm;
4 +import org.onlab.onos.net.DeviceId;
5 +
6 +// TODO: Consider renaming to DeviceClockService?
7 +/**
8 + * Interface for a logical clock service that vends per device timestamps.
9 + */
10 +public interface ClockService {
11 +
12 + /**
13 + * Returns a new timestamp for the specified deviceId.
14 + * @param deviceId device identifier.
15 + * @return timestamp.
16 + */
17 + public Timestamp getTimestamp(DeviceId deviceId);
18 +
19 + // TODO: Should this be here or separate as Admin service, etc.?
20 + /**
21 + * Updates the mastership term for the specified deviceId.
22 + * @param deviceId device identifier.
23 + * @param term mastership term.
24 + */
25 + public void setMastershipTerm(DeviceId deviceId, MastershipTerm term);
26 +}
1 /** 1 /**
2 * Abstractions for creating and interacting with distributed stores. 2 * Abstractions for creating and interacting with distributed stores.
3 */ 3 */
4 -package org.onlab.onos.store;
...\ No newline at end of file ...\ No newline at end of file
4 +package org.onlab.onos.store;
......
...@@ -40,13 +40,14 @@ ...@@ -40,13 +40,14 @@
40 Currently required for DistributedDeviceManagerTest. --> 40 Currently required for DistributedDeviceManagerTest. -->
41 <dependency> 41 <dependency>
42 <groupId>org.onlab.onos</groupId> 42 <groupId>org.onlab.onos</groupId>
43 - <artifactId>onos-core-store</artifactId> 43 + <artifactId>onos-core-hz-net</artifactId>
44 <version>${project.version}</version> 44 <version>${project.version}</version>
45 <scope>test</scope> 45 <scope>test</scope>
46 </dependency> 46 </dependency>
47 <dependency> 47 <dependency>
48 <groupId>org.onlab.onos</groupId> 48 <groupId>org.onlab.onos</groupId>
49 - <artifactId>onos-core-store</artifactId> 49 + <!-- FIXME: should be somewhere else -->
50 + <artifactId>onos-core-hz-common</artifactId>
50 <version>${project.version}</version> 51 <version>${project.version}</version>
51 <classifier>tests</classifier> 52 <classifier>tests</classifier>
52 <scope>test</scope> 53 <scope>test</scope>
......
...@@ -16,10 +16,12 @@ import org.onlab.onos.cluster.ControllerNode; ...@@ -16,10 +16,12 @@ import org.onlab.onos.cluster.ControllerNode;
16 import org.onlab.onos.cluster.NodeId; 16 import org.onlab.onos.cluster.NodeId;
17 import org.onlab.onos.event.AbstractListenerRegistry; 17 import org.onlab.onos.event.AbstractListenerRegistry;
18 import org.onlab.onos.event.EventDeliveryService; 18 import org.onlab.onos.event.EventDeliveryService;
19 +import org.onlab.packet.IpPrefix;
19 import org.slf4j.Logger; 20 import org.slf4j.Logger;
20 21
21 import java.util.Set; 22 import java.util.Set;
22 23
24 +import static com.google.common.base.Preconditions.checkArgument;
23 import static com.google.common.base.Preconditions.checkNotNull; 25 import static com.google.common.base.Preconditions.checkNotNull;
24 import static org.slf4j.LoggerFactory.getLogger; 26 import static org.slf4j.LoggerFactory.getLogger;
25 27
...@@ -81,6 +83,14 @@ public class ClusterManager implements ClusterService, ClusterAdminService { ...@@ -81,6 +83,14 @@ public class ClusterManager implements ClusterService, ClusterAdminService {
81 } 83 }
82 84
83 @Override 85 @Override
86 + public ControllerNode addNode(NodeId nodeId, IpPrefix ip, int tcpPort) {
87 + checkNotNull(nodeId, INSTANCE_ID_NULL);
88 + checkNotNull(ip, "IP address cannot be null");
89 + checkArgument(tcpPort > 5000, "TCP port must be > 5000");
90 + return store.addNode(nodeId, ip, tcpPort);
91 + }
92 +
93 + @Override
84 public void removeNode(NodeId nodeId) { 94 public void removeNode(NodeId nodeId) {
85 checkNotNull(nodeId, INSTANCE_ID_NULL); 95 checkNotNull(nodeId, INSTANCE_ID_NULL);
86 store.removeNode(nodeId); 96 store.removeNode(nodeId);
......
1 package org.onlab.onos.cluster.impl; 1 package org.onlab.onos.cluster.impl;
2 2
3 +import static com.google.common.base.Preconditions.checkNotNull;
4 +import static org.slf4j.LoggerFactory.getLogger;
5 +
6 +import java.util.Set;
7 +
3 import org.apache.felix.scr.annotations.Activate; 8 import org.apache.felix.scr.annotations.Activate;
4 import org.apache.felix.scr.annotations.Component; 9 import org.apache.felix.scr.annotations.Component;
5 import org.apache.felix.scr.annotations.Deactivate; 10 import org.apache.felix.scr.annotations.Deactivate;
...@@ -14,6 +19,7 @@ import org.onlab.onos.cluster.MastershipEvent; ...@@ -14,6 +19,7 @@ import org.onlab.onos.cluster.MastershipEvent;
14 import org.onlab.onos.cluster.MastershipListener; 19 import org.onlab.onos.cluster.MastershipListener;
15 import org.onlab.onos.cluster.MastershipService; 20 import org.onlab.onos.cluster.MastershipService;
16 import org.onlab.onos.cluster.MastershipStore; 21 import org.onlab.onos.cluster.MastershipStore;
22 +import org.onlab.onos.cluster.MastershipStoreDelegate;
17 import org.onlab.onos.cluster.MastershipTerm; 23 import org.onlab.onos.cluster.MastershipTerm;
18 import org.onlab.onos.cluster.MastershipTermService; 24 import org.onlab.onos.cluster.MastershipTermService;
19 import org.onlab.onos.cluster.NodeId; 25 import org.onlab.onos.cluster.NodeId;
...@@ -23,15 +29,10 @@ import org.onlab.onos.net.DeviceId; ...@@ -23,15 +29,10 @@ import org.onlab.onos.net.DeviceId;
23 import org.onlab.onos.net.MastershipRole; 29 import org.onlab.onos.net.MastershipRole;
24 import org.slf4j.Logger; 30 import org.slf4j.Logger;
25 31
26 -import java.util.Set;
27 -
28 -import static com.google.common.base.Preconditions.checkNotNull;
29 -import static org.slf4j.LoggerFactory.getLogger;
30 -
31 @Component(immediate = true) 32 @Component(immediate = true)
32 @Service 33 @Service
33 public class MastershipManager 34 public class MastershipManager
34 - implements MastershipService, MastershipAdminService { 35 +implements MastershipService, MastershipAdminService {
35 36
36 private static final String NODE_ID_NULL = "Node ID cannot be null"; 37 private static final String NODE_ID_NULL = "Node ID cannot be null";
37 private static final String DEVICE_ID_NULL = "Device ID cannot be null"; 38 private static final String DEVICE_ID_NULL = "Device ID cannot be null";
...@@ -40,7 +41,9 @@ public class MastershipManager ...@@ -40,7 +41,9 @@ public class MastershipManager
40 private final Logger log = getLogger(getClass()); 41 private final Logger log = getLogger(getClass());
41 42
42 protected final AbstractListenerRegistry<MastershipEvent, MastershipListener> 43 protected final AbstractListenerRegistry<MastershipEvent, MastershipListener>
43 - listenerRegistry = new AbstractListenerRegistry<>(); 44 + listenerRegistry = new AbstractListenerRegistry<>();
45 +
46 + private final MastershipStoreDelegate delegate = new InternalDelegate();
44 47
45 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) 48 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
46 protected MastershipStore store; 49 protected MastershipStore store;
...@@ -57,6 +60,7 @@ public class MastershipManager ...@@ -57,6 +60,7 @@ public class MastershipManager
57 public void activate() { 60 public void activate() {
58 eventDispatcher.addSink(MastershipEvent.class, listenerRegistry); 61 eventDispatcher.addSink(MastershipEvent.class, listenerRegistry);
59 clusterService.addListener(clusterListener); 62 clusterService.addListener(clusterListener);
63 + store.setDelegate(delegate);
60 log.info("Started"); 64 log.info("Started");
61 } 65 }
62 66
...@@ -64,6 +68,7 @@ public class MastershipManager ...@@ -64,6 +68,7 @@ public class MastershipManager
64 public void deactivate() { 68 public void deactivate() {
65 eventDispatcher.removeSink(MastershipEvent.class); 69 eventDispatcher.removeSink(MastershipEvent.class);
66 clusterService.removeListener(clusterListener); 70 clusterService.removeListener(clusterListener);
71 + store.unsetDelegate(delegate);
67 log.info("Stopped"); 72 log.info("Stopped");
68 } 73 }
69 74
...@@ -188,4 +193,15 @@ public class MastershipManager ...@@ -188,4 +193,15 @@ public class MastershipManager
188 } 193 }
189 194
190 } 195 }
196 +
197 + public class InternalDelegate implements MastershipStoreDelegate {
198 +
199 + @Override
200 + public void notify(MastershipEvent event) {
201 + log.info("dispatching mastership event {}", event);
202 + eventDispatcher.post(event);
203 + }
204 +
205 + }
206 +
191 } 207 }
......
1 /** 1 /**
2 * Subsystem for tracking controller cluster nodes. 2 * Subsystem for tracking controller cluster nodes.
3 */ 3 */
4 -package org.onlab.onos.cluster.impl;
...\ No newline at end of file ...\ No newline at end of file
4 +package org.onlab.onos.cluster.impl;
......
1 package org.onlab.onos.net.device.impl; 1 package org.onlab.onos.net.device.impl;
2 2
3 +import static com.google.common.base.Preconditions.checkNotNull;
4 +import static org.onlab.onos.net.device.DeviceEvent.Type.DEVICE_MASTERSHIP_CHANGED;
5 +import static org.slf4j.LoggerFactory.getLogger;
6 +
7 +import java.util.List;
8 +
3 import org.apache.felix.scr.annotations.Activate; 9 import org.apache.felix.scr.annotations.Activate;
4 import org.apache.felix.scr.annotations.Component; 10 import org.apache.felix.scr.annotations.Component;
5 import org.apache.felix.scr.annotations.Deactivate; 11 import org.apache.felix.scr.annotations.Deactivate;
...@@ -11,6 +17,7 @@ import org.onlab.onos.cluster.MastershipEvent; ...@@ -11,6 +17,7 @@ import org.onlab.onos.cluster.MastershipEvent;
11 import org.onlab.onos.cluster.MastershipListener; 17 import org.onlab.onos.cluster.MastershipListener;
12 import org.onlab.onos.cluster.MastershipService; 18 import org.onlab.onos.cluster.MastershipService;
13 import org.onlab.onos.cluster.MastershipTermService; 19 import org.onlab.onos.cluster.MastershipTermService;
20 +import org.onlab.onos.cluster.MastershipTerm;
14 import org.onlab.onos.event.AbstractListenerRegistry; 21 import org.onlab.onos.event.AbstractListenerRegistry;
15 import org.onlab.onos.event.EventDeliveryService; 22 import org.onlab.onos.event.EventDeliveryService;
16 import org.onlab.onos.net.Device; 23 import org.onlab.onos.net.Device;
...@@ -31,22 +38,17 @@ import org.onlab.onos.net.device.DeviceStoreDelegate; ...@@ -31,22 +38,17 @@ import org.onlab.onos.net.device.DeviceStoreDelegate;
31 import org.onlab.onos.net.device.PortDescription; 38 import org.onlab.onos.net.device.PortDescription;
32 import org.onlab.onos.net.provider.AbstractProviderRegistry; 39 import org.onlab.onos.net.provider.AbstractProviderRegistry;
33 import org.onlab.onos.net.provider.AbstractProviderService; 40 import org.onlab.onos.net.provider.AbstractProviderService;
41 +import org.onlab.onos.store.ClockService;
34 import org.slf4j.Logger; 42 import org.slf4j.Logger;
35 43
36 -import java.util.List;
37 -
38 -import static com.google.common.base.Preconditions.checkNotNull;
39 -import static org.onlab.onos.net.device.DeviceEvent.Type.DEVICE_MASTERSHIP_CHANGED;
40 -import static org.slf4j.LoggerFactory.getLogger;
41 -
42 /** 44 /**
43 * Provides implementation of the device SB &amp; NB APIs. 45 * Provides implementation of the device SB &amp; NB APIs.
44 */ 46 */
45 @Component(immediate = true) 47 @Component(immediate = true)
46 @Service 48 @Service
47 public class DeviceManager 49 public class DeviceManager
48 - extends AbstractProviderRegistry<DeviceProvider, DeviceProviderService> 50 + extends AbstractProviderRegistry<DeviceProvider, DeviceProviderService>
49 - implements DeviceService, DeviceAdminService, DeviceProviderRegistry { 51 + implements DeviceService, DeviceAdminService, DeviceProviderRegistry {
50 52
51 private static final String DEVICE_ID_NULL = "Device ID cannot be null"; 53 private static final String DEVICE_ID_NULL = "Device ID cannot be null";
52 private static final String PORT_NUMBER_NULL = "Port number cannot be null"; 54 private static final String PORT_NUMBER_NULL = "Port number cannot be null";
...@@ -56,10 +58,10 @@ public class DeviceManager ...@@ -56,10 +58,10 @@ public class DeviceManager
56 58
57 private final Logger log = getLogger(getClass()); 59 private final Logger log = getLogger(getClass());
58 60
59 - protected final AbstractListenerRegistry<DeviceEvent, DeviceListener> 61 + protected final AbstractListenerRegistry<DeviceEvent, DeviceListener> listenerRegistry =
60 - listenerRegistry = new AbstractListenerRegistry<>(); 62 + new AbstractListenerRegistry<>();
61 63
62 - private DeviceStoreDelegate delegate = new InternalStoreDelegate(); 64 + private final DeviceStoreDelegate delegate = new InternalStoreDelegate();
63 65
64 private final MastershipListener mastershipListener = new InternalMastershipListener(); 66 private final MastershipListener mastershipListener = new InternalMastershipListener();
65 67
...@@ -77,6 +79,9 @@ public class DeviceManager ...@@ -77,6 +79,9 @@ public class DeviceManager
77 79
78 protected MastershipTermService termService; 80 protected MastershipTermService termService;
79 81
82 + @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
83 + protected ClockService clockService;
84 +
80 @Activate 85 @Activate
81 public void activate() { 86 public void activate() {
82 store.setDelegate(delegate); 87 store.setDelegate(delegate);
...@@ -168,33 +173,36 @@ public class DeviceManager ...@@ -168,33 +173,36 @@ public class DeviceManager
168 } 173 }
169 174
170 @Override 175 @Override
171 - protected DeviceProviderService createProviderService(DeviceProvider provider) { 176 + protected DeviceProviderService createProviderService(
177 + DeviceProvider provider) {
172 return new InternalDeviceProviderService(provider); 178 return new InternalDeviceProviderService(provider);
173 } 179 }
174 180
175 // Personalized device provider service issued to the supplied provider. 181 // Personalized device provider service issued to the supplied provider.
176 private class InternalDeviceProviderService 182 private class InternalDeviceProviderService
177 - extends AbstractProviderService<DeviceProvider> 183 + extends AbstractProviderService<DeviceProvider>
178 - implements DeviceProviderService { 184 + implements DeviceProviderService {
179 185
180 InternalDeviceProviderService(DeviceProvider provider) { 186 InternalDeviceProviderService(DeviceProvider provider) {
181 super(provider); 187 super(provider);
182 } 188 }
183 189
184 @Override 190 @Override
185 - public void deviceConnected(DeviceId deviceId, DeviceDescription deviceDescription) { 191 + public void deviceConnected(DeviceId deviceId,
192 + DeviceDescription deviceDescription) {
186 checkNotNull(deviceId, DEVICE_ID_NULL); 193 checkNotNull(deviceId, DEVICE_ID_NULL);
187 checkNotNull(deviceDescription, DEVICE_DESCRIPTION_NULL); 194 checkNotNull(deviceDescription, DEVICE_DESCRIPTION_NULL);
188 checkValidity(); 195 checkValidity();
189 DeviceEvent event = store.createOrUpdateDevice(provider().id(), 196 DeviceEvent event = store.createOrUpdateDevice(provider().id(),
190 - deviceId, deviceDescription); 197 + deviceId, deviceDescription);
191 198
192 - // If there was a change of any kind, trigger role selection process. 199 + // If there was a change of any kind, trigger role selection
200 + // process.
193 if (event != null) { 201 if (event != null) {
194 log.info("Device {} connected", deviceId); 202 log.info("Device {} connected", deviceId);
195 mastershipService.requestRoleFor(deviceId); 203 mastershipService.requestRoleFor(deviceId);
196 provider().roleChanged(event.subject(), 204 provider().roleChanged(event.subject(),
197 - mastershipService.getLocalRole(deviceId)); 205 + mastershipService.getLocalRole(deviceId));
198 post(event); 206 post(event);
199 } 207 }
200 } 208 }
...@@ -214,25 +222,30 @@ public class DeviceManager ...@@ -214,25 +222,30 @@ public class DeviceManager
214 } 222 }
215 223
216 @Override 224 @Override
217 - public void updatePorts(DeviceId deviceId, List<PortDescription> portDescriptions) { 225 + public void updatePorts(DeviceId deviceId,
226 + List<PortDescription> portDescriptions) {
218 checkNotNull(deviceId, DEVICE_ID_NULL); 227 checkNotNull(deviceId, DEVICE_ID_NULL);
219 - checkNotNull(portDescriptions, "Port descriptions list cannot be null"); 228 + checkNotNull(portDescriptions,
229 + "Port descriptions list cannot be null");
220 checkValidity(); 230 checkValidity();
221 - List<DeviceEvent> events = store.updatePorts(deviceId, portDescriptions); 231 + List<DeviceEvent> events = store.updatePorts(deviceId,
232 + portDescriptions);
222 for (DeviceEvent event : events) { 233 for (DeviceEvent event : events) {
223 post(event); 234 post(event);
224 } 235 }
225 } 236 }
226 237
227 @Override 238 @Override
228 - public void portStatusChanged(DeviceId deviceId, PortDescription portDescription) { 239 + public void portStatusChanged(DeviceId deviceId,
240 + PortDescription portDescription) {
229 checkNotNull(deviceId, DEVICE_ID_NULL); 241 checkNotNull(deviceId, DEVICE_ID_NULL);
230 checkNotNull(portDescription, PORT_DESCRIPTION_NULL); 242 checkNotNull(portDescription, PORT_DESCRIPTION_NULL);
231 checkValidity(); 243 checkValidity();
232 - DeviceEvent event = store.updatePortStatus(deviceId, portDescription); 244 + DeviceEvent event = store.updatePortStatus(deviceId,
245 + portDescription);
233 if (event != null) { 246 if (event != null) {
234 - log.info("Device {} port {} status changed", deviceId, 247 + log.info("Device {} port {} status changed", deviceId, event
235 - event.port().number()); 248 + .port().number());
236 post(event); 249 post(event);
237 } 250 }
238 } 251 }
...@@ -240,8 +253,8 @@ public class DeviceManager ...@@ -240,8 +253,8 @@ public class DeviceManager
240 @Override 253 @Override
241 public void unableToAssertRole(DeviceId deviceId, MastershipRole role) { 254 public void unableToAssertRole(DeviceId deviceId, MastershipRole role) {
242 // FIXME: implement response to this notification 255 // FIXME: implement response to this notification
243 - log.warn("Failed to assert role [{}] onto Device {}", 256 + log.warn("Failed to assert role [{}] onto Device {}", role,
244 - role, deviceId); 257 + deviceId);
245 } 258 }
246 } 259 }
247 260
...@@ -253,18 +266,24 @@ public class DeviceManager ...@@ -253,18 +266,24 @@ public class DeviceManager
253 } 266 }
254 267
255 // Intercepts mastership events 268 // Intercepts mastership events
256 - private class InternalMastershipListener implements MastershipListener { 269 + private class InternalMastershipListener
270 + implements MastershipListener {
257 @Override 271 @Override
258 public void event(MastershipEvent event) { 272 public void event(MastershipEvent event) {
259 - // FIXME: for now we're taking action only on becoming master
260 if (event.master().equals(clusterService.getLocalNode().id())) { 273 if (event.master().equals(clusterService.getLocalNode().id())) {
274 + MastershipTerm term = mastershipService.requestTermService()
275 + .getMastershipTerm(event.subject());
276 + clockService.setMastershipTerm(event.subject(), term);
261 applyRole(event.subject(), MastershipRole.MASTER); 277 applyRole(event.subject(), MastershipRole.MASTER);
278 + } else {
279 + applyRole(event.subject(), MastershipRole.STANDBY);
262 } 280 }
263 } 281 }
264 } 282 }
265 283
266 // Store delegate to re-post events emitted from the store. 284 // Store delegate to re-post events emitted from the store.
267 - private class InternalStoreDelegate implements DeviceStoreDelegate { 285 + private class InternalStoreDelegate
286 + implements DeviceStoreDelegate {
268 @Override 287 @Override
269 public void notify(DeviceEvent event) { 288 public void notify(DeviceEvent event) {
270 post(event); 289 post(event);
......
1 +package org.onlab.onos.proxyarp.impl;
2 +
3 +import static com.google.common.base.Preconditions.checkArgument;
4 +import static com.google.common.base.Preconditions.checkNotNull;
5 +
6 +import java.nio.ByteBuffer;
7 +import java.util.Set;
8 +
9 +import org.apache.felix.scr.annotations.Reference;
10 +import org.apache.felix.scr.annotations.ReferenceCardinality;
11 +import org.onlab.onos.net.Host;
12 +import org.onlab.onos.net.flow.DefaultTrafficTreatment;
13 +import org.onlab.onos.net.flow.TrafficTreatment;
14 +import org.onlab.onos.net.host.HostService;
15 +import org.onlab.onos.net.packet.DefaultOutboundPacket;
16 +import org.onlab.onos.net.packet.PacketService;
17 +import org.onlab.onos.net.proxyarp.ProxyArpService;
18 +import org.onlab.onos.net.topology.TopologyService;
19 +import org.onlab.packet.ARP;
20 +import org.onlab.packet.Ethernet;
21 +import org.onlab.packet.IpPrefix;
22 +import org.onlab.packet.VlanId;
23 +
24 +public class ProxyArpManager implements ProxyArpService {
25 +
26 + private static final String MAC_ADDR_NULL = "Mac address cannot be null.";
27 + private static final String REQUEST_NULL = "Arp request cannot be null.";
28 + private static final String REQUEST_NOT_ARP = "Ethernet frame does not contain ARP request.";
29 + private static final String NOT_ARP_REQUEST = "ARP is not a request.";
30 +
31 + @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
32 + protected HostService hostService;
33 +
34 + @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
35 + protected PacketService packetService;
36 +
37 + @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
38 + protected TopologyService topologyService;
39 +
40 + @Override
41 + public boolean known(IpPrefix addr) {
42 + checkNotNull(MAC_ADDR_NULL, addr);
43 + Set<Host> hosts = hostService.getHostsByIp(addr);
44 + return !hosts.isEmpty();
45 + }
46 +
47 + @Override
48 + public void reply(Ethernet request) {
49 + checkNotNull(REQUEST_NULL, request);
50 + checkArgument(request.getEtherType() == Ethernet.TYPE_ARP,
51 + REQUEST_NOT_ARP);
52 + ARP arp = (ARP) request.getPayload();
53 + checkArgument(arp.getOpCode() == ARP.OP_REQUEST, NOT_ARP_REQUEST);
54 +
55 + VlanId vlan = VlanId.vlanId(request.getVlanID());
56 + Set<Host> hosts = hostService.getHostsByIp(IpPrefix.valueOf(arp
57 + .getTargetProtocolAddress()));
58 +
59 + Host h = null;
60 + for (Host host : hosts) {
61 + if (host.vlan().equals(vlan)) {
62 + h = host;
63 + break;
64 + }
65 + }
66 +
67 + if (h == null) {
68 + flood(request);
69 + return;
70 + }
71 +
72 + Ethernet arpReply = buildArpReply(h, request);
73 + // TODO: check send status with host service.
74 + TrafficTreatment.Builder builder = new DefaultTrafficTreatment.Builder();
75 + builder.setOutput(h.location().port());
76 + packetService.emit(new DefaultOutboundPacket(h.location().deviceId(),
77 + builder.build(), ByteBuffer.wrap(arpReply.serialize())));
78 + }
79 +
80 + private void flood(Ethernet request) {
81 + // TODO: flood on all edge ports.
82 + }
83 +
84 + private Ethernet buildArpReply(Host h, Ethernet request) {
85 + Ethernet eth = new Ethernet();
86 + eth.setDestinationMACAddress(request.getSourceMACAddress());
87 + eth.setSourceMACAddress(h.mac().getAddress());
88 + eth.setEtherType(Ethernet.TYPE_ARP);
89 + ARP arp = new ARP();
90 + arp.setOpCode(ARP.OP_REPLY);
91 + arp.setSenderHardwareAddress(h.mac().getAddress());
92 + arp.setTargetHardwareAddress(request.getSourceMACAddress());
93 +
94 + arp.setTargetProtocolAddress(((ARP) request.getPayload())
95 + .getSenderProtocolAddress());
96 + arp.setSenderProtocolAddress(h.ipAddresses().iterator().next().toInt());
97 + eth.setPayload(arp);
98 + return eth;
99 + }
100 +}
1 +/**
2 + * Core subsystem for responding to arp requests.
3 + */
4 +package org.onlab.onos.proxyarp.impl;
...@@ -32,9 +32,9 @@ import org.onlab.onos.net.device.DeviceService; ...@@ -32,9 +32,9 @@ import org.onlab.onos.net.device.DeviceService;
32 import org.onlab.onos.net.device.PortDescription; 32 import org.onlab.onos.net.device.PortDescription;
33 import org.onlab.onos.net.provider.AbstractProvider; 33 import org.onlab.onos.net.provider.AbstractProvider;
34 import org.onlab.onos.net.provider.ProviderId; 34 import org.onlab.onos.net.provider.ProviderId;
35 +import org.onlab.onos.store.common.StoreManager;
36 +import org.onlab.onos.store.common.TestStoreManager;
35 import org.onlab.onos.store.device.impl.DistributedDeviceStore; 37 import org.onlab.onos.store.device.impl.DistributedDeviceStore;
36 -import org.onlab.onos.store.impl.StoreManager;
37 -import org.onlab.onos.store.impl.TestStoreManager;
38 import org.onlab.packet.IpPrefix; 38 import org.onlab.packet.IpPrefix;
39 39
40 import java.util.ArrayList; 40 import java.util.ArrayList;
...@@ -163,7 +163,7 @@ public class DistributedDeviceManagerTest { ...@@ -163,7 +163,7 @@ public class DistributedDeviceManagerTest {
163 public void deviceDisconnected() { 163 public void deviceDisconnected() {
164 connectDevice(DID1, SW1); 164 connectDevice(DID1, SW1);
165 connectDevice(DID2, SW1); 165 connectDevice(DID2, SW1);
166 - validateEvents(DEVICE_ADDED, DEVICE_ADDED, DEVICE_ADDED, DEVICE_ADDED); 166 + validateEvents(DEVICE_ADDED, DEVICE_ADDED);
167 assertTrue("device should be available", service.isAvailable(DID1)); 167 assertTrue("device should be available", service.isAvailable(DID1));
168 168
169 // Disconnect 169 // Disconnect
...@@ -182,10 +182,10 @@ public class DistributedDeviceManagerTest { ...@@ -182,10 +182,10 @@ public class DistributedDeviceManagerTest {
182 @Test 182 @Test
183 public void deviceUpdated() { 183 public void deviceUpdated() {
184 connectDevice(DID1, SW1); 184 connectDevice(DID1, SW1);
185 - validateEvents(DEVICE_ADDED, DEVICE_ADDED); 185 + validateEvents(DEVICE_ADDED);
186 186
187 connectDevice(DID1, SW2); 187 connectDevice(DID1, SW2);
188 - validateEvents(DEVICE_UPDATED, DEVICE_UPDATED); 188 + validateEvents(DEVICE_UPDATED);
189 } 189 }
190 190
191 @Test 191 @Test
...@@ -202,7 +202,7 @@ public class DistributedDeviceManagerTest { ...@@ -202,7 +202,7 @@ public class DistributedDeviceManagerTest {
202 pds.add(new DefaultPortDescription(P2, true)); 202 pds.add(new DefaultPortDescription(P2, true));
203 pds.add(new DefaultPortDescription(P3, true)); 203 pds.add(new DefaultPortDescription(P3, true));
204 providerService.updatePorts(DID1, pds); 204 providerService.updatePorts(DID1, pds);
205 - validateEvents(DEVICE_ADDED, DEVICE_ADDED, PORT_ADDED, PORT_ADDED, PORT_ADDED); 205 + validateEvents(DEVICE_ADDED, PORT_ADDED, PORT_ADDED, PORT_ADDED);
206 pds.clear(); 206 pds.clear();
207 207
208 pds.add(new DefaultPortDescription(P1, false)); 208 pds.add(new DefaultPortDescription(P1, false));
...@@ -218,7 +218,7 @@ public class DistributedDeviceManagerTest { ...@@ -218,7 +218,7 @@ public class DistributedDeviceManagerTest {
218 pds.add(new DefaultPortDescription(P1, true)); 218 pds.add(new DefaultPortDescription(P1, true));
219 pds.add(new DefaultPortDescription(P2, true)); 219 pds.add(new DefaultPortDescription(P2, true));
220 providerService.updatePorts(DID1, pds); 220 providerService.updatePorts(DID1, pds);
221 - validateEvents(DEVICE_ADDED, DEVICE_ADDED, PORT_ADDED, PORT_ADDED); 221 + validateEvents(DEVICE_ADDED, PORT_ADDED, PORT_ADDED);
222 222
223 providerService.portStatusChanged(DID1, new DefaultPortDescription(P1, false)); 223 providerService.portStatusChanged(DID1, new DefaultPortDescription(P1, false));
224 validateEvents(PORT_UPDATED); 224 validateEvents(PORT_UPDATED);
...@@ -233,7 +233,7 @@ public class DistributedDeviceManagerTest { ...@@ -233,7 +233,7 @@ public class DistributedDeviceManagerTest {
233 pds.add(new DefaultPortDescription(P1, true)); 233 pds.add(new DefaultPortDescription(P1, true));
234 pds.add(new DefaultPortDescription(P2, true)); 234 pds.add(new DefaultPortDescription(P2, true));
235 providerService.updatePorts(DID1, pds); 235 providerService.updatePorts(DID1, pds);
236 - validateEvents(DEVICE_ADDED, DEVICE_ADDED, PORT_ADDED, PORT_ADDED); 236 + validateEvents(DEVICE_ADDED, PORT_ADDED, PORT_ADDED);
237 assertEquals("wrong port count", 2, service.getPorts(DID1).size()); 237 assertEquals("wrong port count", 2, service.getPorts(DID1).size());
238 238
239 Port port = service.getPort(DID1, P1); 239 Port port = service.getPort(DID1, P1);
...@@ -247,7 +247,7 @@ public class DistributedDeviceManagerTest { ...@@ -247,7 +247,7 @@ public class DistributedDeviceManagerTest {
247 connectDevice(DID2, SW2); 247 connectDevice(DID2, SW2);
248 assertEquals("incorrect device count", 2, service.getDeviceCount()); 248 assertEquals("incorrect device count", 2, service.getDeviceCount());
249 admin.removeDevice(DID1); 249 admin.removeDevice(DID1);
250 - validateEvents(DEVICE_ADDED, DEVICE_ADDED, DEVICE_ADDED, DEVICE_ADDED, DEVICE_REMOVED, DEVICE_REMOVED); 250 + validateEvents(DEVICE_ADDED, DEVICE_ADDED, DEVICE_REMOVED);
251 assertNull("device should not be found", service.getDevice(DID1)); 251 assertNull("device should not be found", service.getDevice(DID1));
252 assertNotNull("device should be found", service.getDevice(DID2)); 252 assertNotNull("device should be found", service.getDevice(DID2));
253 assertEquals("incorrect device count", 1, service.getDeviceCount()); 253 assertEquals("incorrect device count", 1, service.getDeviceCount());
......
...@@ -20,7 +20,6 @@ ...@@ -20,7 +20,6 @@
20 <module>api</module> 20 <module>api</module>
21 <module>net</module> 21 <module>net</module>
22 <module>store</module> 22 <module>store</module>
23 - <module>trivial</module>
24 </modules> 23 </modules>
25 24
26 <dependencies> 25 <dependencies>
......
1 +<?xml version="1.0" encoding="UTF-8"?>
2 +<project xmlns="http://maven.apache.org/POM/4.0.0"
3 + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
4 + xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
5 + <modelVersion>4.0.0</modelVersion>
6 +
7 + <parent>
8 + <groupId>org.onlab.onos</groupId>
9 + <artifactId>onos-core-store</artifactId>
10 + <version>1.0.0-SNAPSHOT</version>
11 + <relativePath>../pom.xml</relativePath>
12 + </parent>
13 +
14 + <artifactId>onos-core-dist</artifactId>
15 + <packaging>bundle</packaging>
16 +
17 + <description>ONOS Gossip based distributed store subsystems</description>
18 +
19 + <dependencies>
20 + <dependency>
21 + <groupId>org.onlab.onos</groupId>
22 + <artifactId>onos-api</artifactId>
23 + </dependency>
24 + <dependency>
25 + <groupId>org.onlab.onos</groupId>
26 + <artifactId>onos-core-serializers</artifactId>
27 + <version>${project.version}</version>
28 + </dependency>
29 +
30 +
31 + <dependency>
32 + <groupId>org.onlab.onos</groupId>
33 + <artifactId>onlab-nio</artifactId>
34 + <version>${project.version}</version>
35 + </dependency>
36 +
37 + <dependency>
38 + <groupId>com.fasterxml.jackson.core</groupId>
39 + <artifactId>jackson-databind</artifactId>
40 + </dependency>
41 + <dependency>
42 + <groupId>com.fasterxml.jackson.core</groupId>
43 + <artifactId>jackson-annotations</artifactId>
44 + </dependency>
45 +
46 + <dependency>
47 + <groupId>org.apache.felix</groupId>
48 + <artifactId>org.apache.felix.scr.annotations</artifactId>
49 + </dependency>
50 + <dependency>
51 + <groupId>de.javakaffee</groupId>
52 + <artifactId>kryo-serializers</artifactId>
53 + </dependency>
54 + </dependencies>
55 +
56 + <build>
57 + <plugins>
58 + <plugin>
59 + <groupId>org.apache.felix</groupId>
60 + <artifactId>maven-scr-plugin</artifactId>
61 + </plugin>
62 + </plugins>
63 + </build>
64 +
65 +</project>
1 +package org.onlab.onos.store.cluster.impl;
2 +
3 +import com.fasterxml.jackson.core.JsonEncoding;
4 +import com.fasterxml.jackson.core.JsonFactory;
5 +import com.fasterxml.jackson.databind.JsonNode;
6 +import com.fasterxml.jackson.databind.ObjectMapper;
7 +import com.fasterxml.jackson.databind.node.ArrayNode;
8 +import com.fasterxml.jackson.databind.node.ObjectNode;
9 +import org.onlab.onos.cluster.DefaultControllerNode;
10 +import org.onlab.onos.cluster.NodeId;
11 +import org.onlab.packet.IpPrefix;
12 +
13 +import java.io.File;
14 +import java.io.IOException;
15 +import java.util.HashSet;
16 +import java.util.Iterator;
17 +import java.util.Set;
18 +
19 +/**
20 + * Allows for reading and writing cluster definition as a JSON file.
21 + */
22 +public class ClusterDefinitionStore {
23 +
24 + private final File file;
25 +
26 + /**
27 + * Creates a reader/writer of the cluster definition file.
28 + *
29 + * @param filePath location of the definition file
30 + */
31 + public ClusterDefinitionStore(String filePath) {
32 + file = new File(filePath);
33 + }
34 +
35 + /**
36 + * Returns set of the controller nodes, including self.
37 + *
38 + * @return set of controller nodes
39 + */
40 + public Set<DefaultControllerNode> read() throws IOException {
41 + Set<DefaultControllerNode> nodes = new HashSet<>();
42 + ObjectMapper mapper = new ObjectMapper();
43 + ObjectNode clusterNodeDef = (ObjectNode) mapper.readTree(file);
44 + Iterator<JsonNode> it = ((ArrayNode) clusterNodeDef.get("nodes")).elements();
45 + while (it.hasNext()) {
46 + ObjectNode nodeDef = (ObjectNode) it.next();
47 + nodes.add(new DefaultControllerNode(new NodeId(nodeDef.get("id").asText()),
48 + IpPrefix.valueOf(nodeDef.get("ip").asText()),
49 + nodeDef.get("tcpPort").asInt(9876)));
50 + }
51 + return nodes;
52 + }
53 +
54 + /**
55 + * Writes the given set of the controller nodes.
56 + *
57 + * @param nodes set of controller nodes
58 + */
59 + public void write(Set<DefaultControllerNode> nodes) throws IOException {
60 + ObjectMapper mapper = new ObjectMapper();
61 + ObjectNode clusterNodeDef = mapper.createObjectNode();
62 + ArrayNode nodeDefs = mapper.createArrayNode();
63 + clusterNodeDef.set("nodes", nodeDefs);
64 + for (DefaultControllerNode node : nodes) {
65 + ObjectNode nodeDef = mapper.createObjectNode();
66 + nodeDef.put("id", node.id().toString())
67 + .put("ip", node.ip().toString())
68 + .put("tcpPort", node.tcpPort());
69 + nodeDefs.add(nodeDef);
70 + }
71 + mapper.writeTree(new JsonFactory().createGenerator(file, JsonEncoding.UTF8),
72 + clusterNodeDef);
73 + }
74 +
75 +}
1 +package org.onlab.onos.store.cluster.impl;
2 +
3 +import org.onlab.nio.AbstractMessage;
4 +
5 +import java.util.Objects;
6 +
7 +import static com.google.common.base.MoreObjects.toStringHelper;
8 +
9 +/**
10 + * Base message for cluster-wide communications using TLVs.
11 + */
12 +public class TLVMessage extends AbstractMessage {
13 +
14 + private final int type;
15 + private final byte[] data;
16 +
17 + /**
18 + * Creates an immutable TLV message.
19 + *
20 + * @param type message type
21 + * @param data message data bytes
22 + */
23 + public TLVMessage(int type, byte[] data) {
24 + this.length = data.length + TLVMessageStream.METADATA_LENGTH;
25 + this.type = type;
26 + this.data = data;
27 + }
28 +
29 + /**
30 + * Returns the message type indicator.
31 + *
32 + * @return message type
33 + */
34 + public int type() {
35 + return type;
36 + }
37 +
38 + /**
39 + * Returns the data bytes.
40 + *
41 + * @return message data
42 + */
43 + public byte[] data() {
44 + return data;
45 + }
46 +
47 + @Override
48 + public int hashCode() {
49 + return Objects.hash(type, data);
50 + }
51 +
52 + @Override
53 + public boolean equals(Object obj) {
54 + if (this == obj) {
55 + return true;
56 + }
57 + if (obj == null || getClass() != obj.getClass()) {
58 + return false;
59 + }
60 + final TLVMessage other = (TLVMessage) obj;
61 + return Objects.equals(this.type, other.type) &&
62 + Objects.equals(this.data, other.data);
63 + }
64 +
65 + @Override
66 + public String toString() {
67 + return toStringHelper(this).add("type", type).add("length", length).toString();
68 + }
69 +
70 +}
1 +package org.onlab.onos.store.cluster.impl;
2 +
3 +import org.onlab.nio.IOLoop;
4 +import org.onlab.nio.MessageStream;
5 +import org.onlab.onos.cluster.DefaultControllerNode;
6 +
7 +import java.nio.ByteBuffer;
8 +import java.nio.channels.ByteChannel;
9 +
10 +import static com.google.common.base.Preconditions.checkState;
11 +
12 +/**
13 + * Stream for transferring TLV messages between cluster members.
14 + */
15 +public class TLVMessageStream extends MessageStream<TLVMessage> {
16 +
17 + public static final int METADATA_LENGTH = 16; // 8 + 4 + 4
18 +
19 + private static final int LENGTH_OFFSET = 12;
20 + private static final long MARKER = 0xfeedcafecafefeedL;
21 +
22 + private DefaultControllerNode node;
23 +
24 + /**
25 + * Creates a message stream associated with the specified IO loop and
26 + * backed by the given byte channel.
27 + *
28 + * @param loop IO loop
29 + * @param byteChannel backing byte channel
30 + * @param bufferSize size of the backing byte buffers
31 + * @param maxIdleMillis maximum number of millis the stream can be idle
32 + */
33 + protected TLVMessageStream(IOLoop<TLVMessage, ?> loop, ByteChannel byteChannel,
34 + int bufferSize, int maxIdleMillis) {
35 + super(loop, byteChannel, bufferSize, maxIdleMillis);
36 + }
37 +
38 + /**
39 + * Returns the node with which this stream is associated.
40 + *
41 + * @return controller node
42 + */
43 + DefaultControllerNode node() {
44 + return node;
45 + }
46 +
47 + /**
48 + * Sets the node with which this stream is affiliated.
49 + *
50 + * @param node controller node
51 + */
52 + void setNode(DefaultControllerNode node) {
53 + checkState(this.node == null, "Stream is already bound to a node");
54 + this.node = node;
55 + }
56 +
57 + @Override
58 + protected TLVMessage read(ByteBuffer buffer) {
59 + // Do we have enough bytes to read the header? If not, bail.
60 + if (buffer.remaining() < METADATA_LENGTH) {
61 + return null;
62 + }
63 +
64 + // Peek at the length and if we have enough to read the entire message
65 + // go ahead, otherwise bail.
66 + int length = buffer.getInt(buffer.position() + LENGTH_OFFSET);
67 + if (buffer.remaining() < length) {
68 + return null;
69 + }
70 +
71 + // At this point, we have enough data to read a complete message.
72 + long marker = buffer.getLong();
73 + checkState(marker == MARKER, "Incorrect message marker");
74 +
75 + int type = buffer.getInt();
76 + length = buffer.getInt();
77 +
78 + // TODO: add deserialization hook here
79 + byte[] data = new byte[length - METADATA_LENGTH];
80 + buffer.get(data);
81 +
82 + return new TLVMessage(type, data);
83 + }
84 +
85 + @Override
86 + protected void write(TLVMessage message, ByteBuffer buffer) {
87 + buffer.putLong(MARKER);
88 + buffer.putInt(message.type());
89 + buffer.putInt(message.length());
90 +
91 + // TODO: add serialization hook here
92 + buffer.put(message.data());
93 + }
94 +
95 +}
1 +package org.onlab.onos.store.device.impl;
2 +
3 +import static org.slf4j.LoggerFactory.getLogger;
4 +
5 +import java.util.concurrent.ConcurrentHashMap;
6 +import java.util.concurrent.ConcurrentMap;
7 +import java.util.concurrent.atomic.AtomicInteger;
8 +
9 +import org.apache.felix.scr.annotations.Activate;
10 +import org.apache.felix.scr.annotations.Component;
11 +import org.apache.felix.scr.annotations.Deactivate;
12 +import org.apache.felix.scr.annotations.Service;
13 +import org.onlab.onos.cluster.MastershipTerm;
14 +import org.onlab.onos.net.DeviceId;
15 +import org.onlab.onos.store.ClockService;
16 +import org.onlab.onos.store.Timestamp;
17 +import org.onlab.onos.store.impl.OnosTimestamp;
18 +import org.slf4j.Logger;
19 +
20 +@Component(immediate = true)
21 +@Service
22 +public class OnosClockService implements ClockService {
23 +
24 + private final Logger log = getLogger(getClass());
25 +
26 + // TODO: Implement per device ticker that is reset to 0 at the beginning of a new term.
27 + private final AtomicInteger ticker = new AtomicInteger(0);
28 + private ConcurrentMap<DeviceId, MastershipTerm> deviceMastershipTerms = new ConcurrentHashMap<>();
29 +
30 + @Activate
31 + public void activate() {
32 + log.info("Started");
33 + }
34 +
35 + @Deactivate
36 + public void deactivate() {
37 + log.info("Stopped");
38 + }
39 +
40 + @Override
41 + public Timestamp getTimestamp(DeviceId deviceId) {
42 + MastershipTerm term = deviceMastershipTerms.get(deviceId);
43 + if (term == null) {
44 + throw new IllegalStateException("Requesting timestamp for a deviceId without mastership");
45 + }
46 + return new OnosTimestamp(term.termNumber(), ticker.incrementAndGet());
47 + }
48 +
49 + @Override
50 + public void setMastershipTerm(DeviceId deviceId, MastershipTerm term) {
51 + deviceMastershipTerms.put(deviceId, term);
52 + }
53 +}
1 +package org.onlab.onos.store.device.impl;
2 +
3 +import org.onlab.onos.store.Timestamp;
4 +
5 +/**
6 + * Wrapper class for a entity that is versioned
7 + * and can either be up or down.
8 + *
9 + * @param <T> type of the value.
10 + */
11 +public class VersionedValue<T> {
12 + private final T entity;
13 + private final Timestamp timestamp;
14 + private final boolean isUp;
15 +
16 + public VersionedValue(T entity, boolean isUp, Timestamp timestamp) {
17 + this.entity = entity;
18 + this.isUp = isUp;
19 + this.timestamp = timestamp;
20 + }
21 +
22 + /**
23 + * Returns the value.
24 + * @return value.
25 + */
26 + public T entity() {
27 + return entity;
28 + }
29 +
30 + /**
31 + * Tells whether the entity is up or down.
32 + * @return true if up, false otherwise.
33 + */
34 + public boolean isUp() {
35 + return isUp;
36 + }
37 +
38 + /**
39 + * Returns the timestamp (version) associated with this entity.
40 + * @return timestamp.
41 + */
42 + public Timestamp timestamp() {
43 + return timestamp;
44 + }
45 +}
1 +/**
2 + * Implementation of device store using distributed structures.
3 + */
4 +package org.onlab.onos.store.device.impl;
1 +package org.onlab.onos.store.flow.impl;
2 +
3 +import static org.onlab.onos.net.flow.FlowRuleEvent.Type.RULE_ADDED;
4 +import static org.onlab.onos.net.flow.FlowRuleEvent.Type.RULE_REMOVED;
5 +import static org.slf4j.LoggerFactory.getLogger;
6 +
7 +import java.util.Collection;
8 +import java.util.Collections;
9 +
10 +import org.apache.felix.scr.annotations.Activate;
11 +import org.apache.felix.scr.annotations.Component;
12 +import org.apache.felix.scr.annotations.Deactivate;
13 +import org.apache.felix.scr.annotations.Service;
14 +import org.onlab.onos.ApplicationId;
15 +import org.onlab.onos.net.DeviceId;
16 +import org.onlab.onos.net.flow.DefaultFlowRule;
17 +import org.onlab.onos.net.flow.FlowRule;
18 +import org.onlab.onos.net.flow.FlowRule.FlowRuleState;
19 +import org.onlab.onos.net.flow.FlowRuleEvent;
20 +import org.onlab.onos.net.flow.FlowRuleEvent.Type;
21 +import org.onlab.onos.net.flow.FlowRuleStore;
22 +import org.onlab.onos.net.flow.FlowRuleStoreDelegate;
23 +import org.onlab.onos.store.AbstractStore;
24 +import org.slf4j.Logger;
25 +
26 +import com.google.common.collect.ArrayListMultimap;
27 +import com.google.common.collect.ImmutableSet;
28 +import com.google.common.collect.Multimap;
29 +
30 +/**
31 + * Manages inventory of flow rules using trivial in-memory implementation.
32 + */
33 +//FIXME: I LIE I AM NOT DISTRIBUTED
34 +@Component(immediate = true)
35 +@Service
36 +public class DistributedFlowRuleStore
37 +extends AbstractStore<FlowRuleEvent, FlowRuleStoreDelegate>
38 +implements FlowRuleStore {
39 +
40 + private final Logger log = getLogger(getClass());
41 +
42 + // store entries as a pile of rules, no info about device tables
43 + private final Multimap<DeviceId, FlowRule> flowEntries =
44 + ArrayListMultimap.<DeviceId, FlowRule>create();
45 +
46 + private final Multimap<ApplicationId, FlowRule> flowEntriesById =
47 + ArrayListMultimap.<ApplicationId, FlowRule>create();
48 +
49 + @Activate
50 + public void activate() {
51 + log.info("Started");
52 + }
53 +
54 + @Deactivate
55 + public void deactivate() {
56 + log.info("Stopped");
57 + }
58 +
59 +
60 + @Override
61 + public synchronized FlowRule getFlowRule(FlowRule rule) {
62 + for (FlowRule f : flowEntries.get(rule.deviceId())) {
63 + if (f.equals(rule)) {
64 + return f;
65 + }
66 + }
67 + return null;
68 + }
69 +
70 + @Override
71 + public synchronized Iterable<FlowRule> getFlowEntries(DeviceId deviceId) {
72 + Collection<FlowRule> rules = flowEntries.get(deviceId);
73 + if (rules == null) {
74 + return Collections.emptyList();
75 + }
76 + return ImmutableSet.copyOf(rules);
77 + }
78 +
79 + @Override
80 + public synchronized Iterable<FlowRule> getFlowEntriesByAppId(ApplicationId appId) {
81 + Collection<FlowRule> rules = flowEntriesById.get(appId);
82 + if (rules == null) {
83 + return Collections.emptyList();
84 + }
85 + return ImmutableSet.copyOf(rules);
86 + }
87 +
88 + @Override
89 + public synchronized void storeFlowRule(FlowRule rule) {
90 + FlowRule f = new DefaultFlowRule(rule, FlowRuleState.PENDING_ADD);
91 + DeviceId did = f.deviceId();
92 + if (!flowEntries.containsEntry(did, f)) {
93 + flowEntries.put(did, f);
94 + flowEntriesById.put(rule.appId(), f);
95 + }
96 + }
97 +
98 + @Override
99 + public synchronized void deleteFlowRule(FlowRule rule) {
100 + FlowRule f = new DefaultFlowRule(rule, FlowRuleState.PENDING_REMOVE);
101 + DeviceId did = f.deviceId();
102 +
103 + /*
104 + * find the rule and mark it for deletion.
105 + * Ultimately a flow removed will come remove it.
106 + */
107 +
108 + if (flowEntries.containsEntry(did, f)) {
109 + //synchronized (flowEntries) {
110 + flowEntries.remove(did, f);
111 + flowEntries.put(did, f);
112 + flowEntriesById.remove(rule.appId(), rule);
113 + //}
114 + }
115 + }
116 +
117 + @Override
118 + public synchronized FlowRuleEvent addOrUpdateFlowRule(FlowRule rule) {
119 + DeviceId did = rule.deviceId();
120 +
121 + // check if this new rule is an update to an existing entry
122 + if (flowEntries.containsEntry(did, rule)) {
123 + //synchronized (flowEntries) {
124 + // Multimaps support duplicates so we have to remove our rule
125 + // and replace it with the current version.
126 + flowEntries.remove(did, rule);
127 + flowEntries.put(did, rule);
128 + //}
129 + return new FlowRuleEvent(Type.RULE_UPDATED, rule);
130 + }
131 +
132 + flowEntries.put(did, rule);
133 + return new FlowRuleEvent(RULE_ADDED, rule);
134 + }
135 +
136 + @Override
137 + public synchronized FlowRuleEvent removeFlowRule(FlowRule rule) {
138 + //synchronized (this) {
139 + if (flowEntries.remove(rule.deviceId(), rule)) {
140 + return new FlowRuleEvent(RULE_REMOVED, rule);
141 + } else {
142 + return null;
143 + }
144 + //}
145 + }
146 +
147 +
148 +
149 +
150 +
151 +
152 +
153 +}
1 +package org.onlab.onos.store.host.impl;
2 +
3 +import static org.onlab.onos.net.host.HostEvent.Type.HOST_ADDED;
4 +import static org.onlab.onos.net.host.HostEvent.Type.HOST_MOVED;
5 +import static org.onlab.onos.net.host.HostEvent.Type.HOST_REMOVED;
6 +import static org.onlab.onos.net.host.HostEvent.Type.HOST_UPDATED;
7 +import static org.slf4j.LoggerFactory.getLogger;
8 +
9 +import java.util.Collections;
10 +import java.util.HashSet;
11 +import java.util.Map;
12 +import java.util.Set;
13 +import java.util.concurrent.ConcurrentHashMap;
14 +
15 +import org.apache.felix.scr.annotations.Activate;
16 +import org.apache.felix.scr.annotations.Component;
17 +import org.apache.felix.scr.annotations.Deactivate;
18 +import org.apache.felix.scr.annotations.Service;
19 +import org.onlab.onos.net.ConnectPoint;
20 +import org.onlab.onos.net.DefaultHost;
21 +import org.onlab.onos.net.DeviceId;
22 +import org.onlab.onos.net.Host;
23 +import org.onlab.onos.net.HostId;
24 +import org.onlab.onos.net.host.HostDescription;
25 +import org.onlab.onos.net.host.HostEvent;
26 +import org.onlab.onos.net.host.HostStore;
27 +import org.onlab.onos.net.host.HostStoreDelegate;
28 +import org.onlab.onos.net.host.PortAddresses;
29 +import org.onlab.onos.net.provider.ProviderId;
30 +import org.onlab.onos.store.AbstractStore;
31 +import org.onlab.packet.IpPrefix;
32 +import org.onlab.packet.MacAddress;
33 +import org.onlab.packet.VlanId;
34 +import org.slf4j.Logger;
35 +
36 +import com.google.common.collect.HashMultimap;
37 +import com.google.common.collect.ImmutableSet;
38 +import com.google.common.collect.Multimap;
39 +import com.google.common.collect.Sets;
40 +
41 +/**
42 + * Manages inventory of end-station hosts using trivial in-memory
43 + * implementation.
44 + */
45 +//FIXME: I LIE I AM NOT DISTRIBUTED
46 +@Component(immediate = true)
47 +@Service
48 +public class DistributedHostStore
49 +extends AbstractStore<HostEvent, HostStoreDelegate>
50 +implements HostStore {
51 +
52 + private final Logger log = getLogger(getClass());
53 +
54 + // Host inventory
55 + private final Map<HostId, Host> hosts = new ConcurrentHashMap<>();
56 +
57 + // Hosts tracked by their location
58 + private final Multimap<ConnectPoint, Host> locations = HashMultimap.create();
59 +
60 + private final Map<ConnectPoint, PortAddresses> portAddresses =
61 + new ConcurrentHashMap<>();
62 +
63 + @Activate
64 + public void activate() {
65 + log.info("Started");
66 + }
67 +
68 + @Deactivate
69 + public void deactivate() {
70 + log.info("Stopped");
71 + }
72 +
73 + @Override
74 + public HostEvent createOrUpdateHost(ProviderId providerId, HostId hostId,
75 + HostDescription hostDescription) {
76 + Host host = hosts.get(hostId);
77 + if (host == null) {
78 + return createHost(providerId, hostId, hostDescription);
79 + }
80 + return updateHost(providerId, host, hostDescription);
81 + }
82 +
83 + // creates a new host and sends HOST_ADDED
84 + private HostEvent createHost(ProviderId providerId, HostId hostId,
85 + HostDescription descr) {
86 + DefaultHost newhost = new DefaultHost(providerId, hostId,
87 + descr.hwAddress(),
88 + descr.vlan(),
89 + descr.location(),
90 + descr.ipAddresses());
91 + synchronized (this) {
92 + hosts.put(hostId, newhost);
93 + locations.put(descr.location(), newhost);
94 + }
95 + return new HostEvent(HOST_ADDED, newhost);
96 + }
97 +
98 + // checks for type of update to host, sends appropriate event
99 + private HostEvent updateHost(ProviderId providerId, Host host,
100 + HostDescription descr) {
101 + DefaultHost updated;
102 + HostEvent event;
103 + if (!host.location().equals(descr.location())) {
104 + updated = new DefaultHost(providerId, host.id(),
105 + host.mac(),
106 + host.vlan(),
107 + descr.location(),
108 + host.ipAddresses());
109 + event = new HostEvent(HOST_MOVED, updated);
110 +
111 + } else if (!(host.ipAddresses().equals(descr.ipAddresses()))) {
112 + updated = new DefaultHost(providerId, host.id(),
113 + host.mac(),
114 + host.vlan(),
115 + descr.location(),
116 + descr.ipAddresses());
117 + event = new HostEvent(HOST_UPDATED, updated);
118 + } else {
119 + return null;
120 + }
121 + synchronized (this) {
122 + hosts.put(host.id(), updated);
123 + locations.remove(host.location(), host);
124 + locations.put(updated.location(), updated);
125 + }
126 + return event;
127 + }
128 +
129 + @Override
130 + public HostEvent removeHost(HostId hostId) {
131 + synchronized (this) {
132 + Host host = hosts.remove(hostId);
133 + if (host != null) {
134 + locations.remove((host.location()), host);
135 + return new HostEvent(HOST_REMOVED, host);
136 + }
137 + return null;
138 + }
139 + }
140 +
141 + @Override
142 + public int getHostCount() {
143 + return hosts.size();
144 + }
145 +
146 + @Override
147 + public Iterable<Host> getHosts() {
148 + return Collections.unmodifiableSet(new HashSet<>(hosts.values()));
149 + }
150 +
151 + @Override
152 + public Host getHost(HostId hostId) {
153 + return hosts.get(hostId);
154 + }
155 +
156 + @Override
157 + public Set<Host> getHosts(VlanId vlanId) {
158 + Set<Host> vlanset = new HashSet<>();
159 + for (Host h : hosts.values()) {
160 + if (h.vlan().equals(vlanId)) {
161 + vlanset.add(h);
162 + }
163 + }
164 + return vlanset;
165 + }
166 +
167 + @Override
168 + public Set<Host> getHosts(MacAddress mac) {
169 + Set<Host> macset = new HashSet<>();
170 + for (Host h : hosts.values()) {
171 + if (h.mac().equals(mac)) {
172 + macset.add(h);
173 + }
174 + }
175 + return macset;
176 + }
177 +
178 + @Override
179 + public Set<Host> getHosts(IpPrefix ip) {
180 + Set<Host> ipset = new HashSet<>();
181 + for (Host h : hosts.values()) {
182 + if (h.ipAddresses().contains(ip)) {
183 + ipset.add(h);
184 + }
185 + }
186 + return ipset;
187 + }
188 +
189 + @Override
190 + public Set<Host> getConnectedHosts(ConnectPoint connectPoint) {
191 + return ImmutableSet.copyOf(locations.get(connectPoint));
192 + }
193 +
194 + @Override
195 + public Set<Host> getConnectedHosts(DeviceId deviceId) {
196 + Set<Host> hostset = new HashSet<>();
197 + for (ConnectPoint p : locations.keySet()) {
198 + if (p.deviceId().equals(deviceId)) {
199 + hostset.addAll(locations.get(p));
200 + }
201 + }
202 + return hostset;
203 + }
204 +
205 + @Override
206 + public void updateAddressBindings(PortAddresses addresses) {
207 + synchronized (portAddresses) {
208 + PortAddresses existing = portAddresses.get(addresses.connectPoint());
209 + if (existing == null) {
210 + portAddresses.put(addresses.connectPoint(), addresses);
211 + } else {
212 + Set<IpPrefix> union = Sets.union(existing.ips(), addresses.ips())
213 + .immutableCopy();
214 +
215 + MacAddress newMac = (addresses.mac() == null) ? existing.mac()
216 + : addresses.mac();
217 +
218 + PortAddresses newAddresses =
219 + new PortAddresses(addresses.connectPoint(), union, newMac);
220 +
221 + portAddresses.put(newAddresses.connectPoint(), newAddresses);
222 + }
223 + }
224 + }
225 +
226 + @Override
227 + public void removeAddressBindings(PortAddresses addresses) {
228 + synchronized (portAddresses) {
229 + PortAddresses existing = portAddresses.get(addresses.connectPoint());
230 + if (existing != null) {
231 + Set<IpPrefix> difference =
232 + Sets.difference(existing.ips(), addresses.ips()).immutableCopy();
233 +
234 + // If they removed the existing mac, set the new mac to null.
235 + // Otherwise, keep the existing mac.
236 + MacAddress newMac = existing.mac();
237 + if (addresses.mac() != null && addresses.mac().equals(existing.mac())) {
238 + newMac = null;
239 + }
240 +
241 + PortAddresses newAddresses =
242 + new PortAddresses(addresses.connectPoint(), difference, newMac);
243 +
244 + portAddresses.put(newAddresses.connectPoint(), newAddresses);
245 + }
246 + }
247 + }
248 +
249 + @Override
250 + public void clearAddressBindings(ConnectPoint connectPoint) {
251 + synchronized (portAddresses) {
252 + portAddresses.remove(connectPoint);
253 + }
254 + }
255 +
256 + @Override
257 + public Set<PortAddresses> getAddressBindings() {
258 + synchronized (portAddresses) {
259 + return new HashSet<>(portAddresses.values());
260 + }
261 + }
262 +
263 + @Override
264 + public PortAddresses getAddressBindingsForPort(ConnectPoint connectPoint) {
265 + PortAddresses addresses;
266 +
267 + synchronized (portAddresses) {
268 + addresses = portAddresses.get(connectPoint);
269 + }
270 +
271 + if (addresses == null) {
272 + addresses = new PortAddresses(connectPoint, null, null);
273 + }
274 +
275 + return addresses;
276 + }
277 +
278 +}
1 package org.onlab.onos.store.impl; 1 package org.onlab.onos.store.impl;
2 2
3 -import static com.google.common.base.Preconditions.checkNotNull;
4 import static com.google.common.base.Preconditions.checkArgument; 3 import static com.google.common.base.Preconditions.checkArgument;
5 4
6 import java.util.Objects; 5 import java.util.Objects;
7 6
8 -import org.onlab.onos.net.ElementId;
9 import org.onlab.onos.store.Timestamp; 7 import org.onlab.onos.store.Timestamp;
10 8
11 import com.google.common.base.MoreObjects; 9 import com.google.common.base.MoreObjects;
...@@ -14,22 +12,20 @@ import com.google.common.collect.ComparisonChain; ...@@ -14,22 +12,20 @@ import com.google.common.collect.ComparisonChain;
14 // If it is store specific, implement serializable interfaces? 12 // If it is store specific, implement serializable interfaces?
15 /** 13 /**
16 * Default implementation of Timestamp. 14 * Default implementation of Timestamp.
15 + * TODO: Better documentation.
17 */ 16 */
18 public final class OnosTimestamp implements Timestamp { 17 public final class OnosTimestamp implements Timestamp {
19 18
20 - private final ElementId id;
21 private final int termNumber; 19 private final int termNumber;
22 private final int sequenceNumber; 20 private final int sequenceNumber;
23 21
24 /** 22 /**
25 * Default version tuple. 23 * Default version tuple.
26 * 24 *
27 - * @param id identifier of the element
28 * @param termNumber the mastership termNumber 25 * @param termNumber the mastership termNumber
29 * @param sequenceNumber the sequenceNumber number within the termNumber 26 * @param sequenceNumber the sequenceNumber number within the termNumber
30 */ 27 */
31 - public OnosTimestamp(ElementId id, int termNumber, int sequenceNumber) { 28 + public OnosTimestamp(int termNumber, int sequenceNumber) {
32 - this.id = checkNotNull(id);
33 this.termNumber = termNumber; 29 this.termNumber = termNumber;
34 this.sequenceNumber = sequenceNumber; 30 this.sequenceNumber = sequenceNumber;
35 } 31 }
...@@ -38,9 +34,6 @@ public final class OnosTimestamp implements Timestamp { ...@@ -38,9 +34,6 @@ public final class OnosTimestamp implements Timestamp {
38 public int compareTo(Timestamp o) { 34 public int compareTo(Timestamp o) {
39 checkArgument(o instanceof OnosTimestamp, "Must be OnosTimestamp", o); 35 checkArgument(o instanceof OnosTimestamp, "Must be OnosTimestamp", o);
40 OnosTimestamp that = (OnosTimestamp) o; 36 OnosTimestamp that = (OnosTimestamp) o;
41 - checkArgument(this.id.equals(that.id),
42 - "Cannot compare version for different element this:%s, that:%s",
43 - this, that);
44 37
45 return ComparisonChain.start() 38 return ComparisonChain.start()
46 .compare(this.termNumber, that.termNumber) 39 .compare(this.termNumber, that.termNumber)
...@@ -50,7 +43,7 @@ public final class OnosTimestamp implements Timestamp { ...@@ -50,7 +43,7 @@ public final class OnosTimestamp implements Timestamp {
50 43
51 @Override 44 @Override
52 public int hashCode() { 45 public int hashCode() {
53 - return Objects.hash(id, termNumber, sequenceNumber); 46 + return Objects.hash(termNumber, sequenceNumber);
54 } 47 }
55 48
56 @Override 49 @Override
...@@ -62,30 +55,19 @@ public final class OnosTimestamp implements Timestamp { ...@@ -62,30 +55,19 @@ public final class OnosTimestamp implements Timestamp {
62 return false; 55 return false;
63 } 56 }
64 OnosTimestamp that = (OnosTimestamp) obj; 57 OnosTimestamp that = (OnosTimestamp) obj;
65 - return Objects.equals(this.id, that.id) && 58 + return Objects.equals(this.termNumber, that.termNumber) &&
66 - Objects.equals(this.termNumber, that.termNumber) &&
67 Objects.equals(this.sequenceNumber, that.sequenceNumber); 59 Objects.equals(this.sequenceNumber, that.sequenceNumber);
68 } 60 }
69 61
70 @Override 62 @Override
71 public String toString() { 63 public String toString() {
72 return MoreObjects.toStringHelper(getClass()) 64 return MoreObjects.toStringHelper(getClass())
73 - .add("id", id)
74 .add("termNumber", termNumber) 65 .add("termNumber", termNumber)
75 .add("sequenceNumber", sequenceNumber) 66 .add("sequenceNumber", sequenceNumber)
76 .toString(); 67 .toString();
77 } 68 }
78 69
79 /** 70 /**
80 - * Returns the element.
81 - *
82 - * @return element identifier
83 - */
84 - public ElementId id() {
85 - return id;
86 - }
87 -
88 - /**
89 * Returns the termNumber. 71 * Returns the termNumber.
90 * 72 *
91 * @return termNumber 73 * @return termNumber
......
1 +package org.onlab.onos.store.link.impl;
2 +
3 +import static org.onlab.onos.net.Link.Type.DIRECT;
4 +import static org.onlab.onos.net.Link.Type.INDIRECT;
5 +import static org.onlab.onos.net.link.LinkEvent.Type.LINK_ADDED;
6 +import static org.onlab.onos.net.link.LinkEvent.Type.LINK_REMOVED;
7 +import static org.onlab.onos.net.link.LinkEvent.Type.LINK_UPDATED;
8 +import static org.slf4j.LoggerFactory.getLogger;
9 +
10 +import java.util.HashSet;
11 +import java.util.Set;
12 +import java.util.concurrent.ConcurrentHashMap;
13 +import java.util.concurrent.ConcurrentMap;
14 +
15 +import org.apache.felix.scr.annotations.Activate;
16 +import org.apache.felix.scr.annotations.Component;
17 +import org.apache.felix.scr.annotations.Deactivate;
18 +import org.apache.felix.scr.annotations.Reference;
19 +import org.apache.felix.scr.annotations.ReferenceCardinality;
20 +import org.apache.felix.scr.annotations.Service;
21 +import org.onlab.onos.net.ConnectPoint;
22 +import org.onlab.onos.net.DefaultLink;
23 +import org.onlab.onos.net.DeviceId;
24 +import org.onlab.onos.net.Link;
25 +import org.onlab.onos.net.LinkKey;
26 +import org.onlab.onos.net.link.LinkDescription;
27 +import org.onlab.onos.net.link.LinkEvent;
28 +import org.onlab.onos.net.link.LinkStore;
29 +import org.onlab.onos.net.link.LinkStoreDelegate;
30 +import org.onlab.onos.net.provider.ProviderId;
31 +import org.onlab.onos.store.AbstractStore;
32 +import org.onlab.onos.store.ClockService;
33 +import org.onlab.onos.store.Timestamp;
34 +import org.onlab.onos.store.device.impl.VersionedValue;
35 +import org.slf4j.Logger;
36 +
37 +import com.google.common.collect.HashMultimap;
38 +import com.google.common.collect.ImmutableSet;
39 +import com.google.common.collect.Multimap;
40 +import com.google.common.collect.ImmutableSet.Builder;
41 +
42 +import static com.google.common.base.Preconditions.checkArgument;
43 +import static com.google.common.base.Preconditions.checkState;
44 +
45 +/**
46 + * Manages inventory of infrastructure links using a protocol that takes into consideration
47 + * the order in which events occur.
48 + */
49 +// FIXME: This does not yet implement the full protocol.
50 +// The full protocol requires the sender of LLDP message to include the
51 +// version information of src device/port and the receiver to
52 +// take that into account when figuring out if a more recent src
53 +// device/port down event renders the link discovery obsolete.
54 +@Component(immediate = true)
55 +@Service
56 +public class OnosDistributedLinkStore
57 + extends AbstractStore<LinkEvent, LinkStoreDelegate>
58 + implements LinkStore {
59 +
60 + private final Logger log = getLogger(getClass());
61 +
62 + // Link inventory
63 + private ConcurrentMap<LinkKey, VersionedValue<Link>> links;
64 +
65 + public static final String LINK_NOT_FOUND = "Link between %s and %s not found";
66 +
67 + // TODO synchronize?
68 + // Egress and ingress link sets
69 + private final Multimap<DeviceId, VersionedValue<Link>> srcLinks = HashMultimap.create();
70 + private final Multimap<DeviceId, VersionedValue<Link>> dstLinks = HashMultimap.create();
71 +
72 + @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
73 + protected ClockService clockService;
74 +
75 + @Activate
76 + public void activate() {
77 +
78 + links = new ConcurrentHashMap<>();
79 +
80 + log.info("Started");
81 + }
82 +
83 + @Deactivate
84 + public void deactivate() {
85 + log.info("Stopped");
86 + }
87 +
88 + @Override
89 + public int getLinkCount() {
90 + return links.size();
91 + }
92 +
93 + @Override
94 + public Iterable<Link> getLinks() {
95 + Builder<Link> builder = ImmutableSet.builder();
96 + synchronized (this) {
97 + for (VersionedValue<Link> link : links.values()) {
98 + builder.add(link.entity());
99 + }
100 + return builder.build();
101 + }
102 + }
103 +
104 + @Override
105 + public Set<Link> getDeviceEgressLinks(DeviceId deviceId) {
106 + Set<VersionedValue<Link>> egressLinks = ImmutableSet.copyOf(srcLinks.get(deviceId));
107 + Set<Link> rawEgressLinks = new HashSet<>();
108 + for (VersionedValue<Link> link : egressLinks) {
109 + rawEgressLinks.add(link.entity());
110 + }
111 + return rawEgressLinks;
112 + }
113 +
114 + @Override
115 + public Set<Link> getDeviceIngressLinks(DeviceId deviceId) {
116 + Set<VersionedValue<Link>> ingressLinks = ImmutableSet.copyOf(dstLinks.get(deviceId));
117 + Set<Link> rawIngressLinks = new HashSet<>();
118 + for (VersionedValue<Link> link : ingressLinks) {
119 + rawIngressLinks.add(link.entity());
120 + }
121 + return rawIngressLinks;
122 + }
123 +
124 + @Override
125 + public Link getLink(ConnectPoint src, ConnectPoint dst) {
126 + VersionedValue<Link> link = links.get(new LinkKey(src, dst));
127 + checkArgument(link != null, "LINK_NOT_FOUND", src, dst);
128 + return link.entity();
129 + }
130 +
131 + @Override
132 + public Set<Link> getEgressLinks(ConnectPoint src) {
133 + Set<Link> egressLinks = new HashSet<>();
134 + for (VersionedValue<Link> link : srcLinks.get(src.deviceId())) {
135 + if (link.entity().src().equals(src)) {
136 + egressLinks.add(link.entity());
137 + }
138 + }
139 + return egressLinks;
140 + }
141 +
142 + @Override
143 + public Set<Link> getIngressLinks(ConnectPoint dst) {
144 + Set<Link> ingressLinks = new HashSet<>();
145 + for (VersionedValue<Link> link : dstLinks.get(dst.deviceId())) {
146 + if (link.entity().dst().equals(dst)) {
147 + ingressLinks.add(link.entity());
148 + }
149 + }
150 + return ingressLinks;
151 + }
152 +
153 + @Override
154 + public LinkEvent createOrUpdateLink(ProviderId providerId,
155 + LinkDescription linkDescription) {
156 +
157 + final DeviceId destinationDeviceId = linkDescription.dst().deviceId();
158 + final Timestamp newTimestamp = clockService.getTimestamp(destinationDeviceId);
159 +
160 + LinkKey key = new LinkKey(linkDescription.src(), linkDescription.dst());
161 + VersionedValue<Link> link = links.get(key);
162 + if (link == null) {
163 + return createLink(providerId, key, linkDescription, newTimestamp);
164 + }
165 +
166 + checkState(newTimestamp.compareTo(link.timestamp()) > 0,
167 + "Existing Link has a timestamp in the future!");
168 +
169 + return updateLink(providerId, link, key, linkDescription, newTimestamp);
170 + }
171 +
172 + // Creates and stores the link and returns the appropriate event.
173 + private LinkEvent createLink(ProviderId providerId, LinkKey key,
174 + LinkDescription linkDescription, Timestamp timestamp) {
175 + VersionedValue<Link> link = new VersionedValue<Link>(new DefaultLink(providerId, key.src(), key.dst(),
176 + linkDescription.type()), true, timestamp);
177 + synchronized (this) {
178 + links.put(key, link);
179 + addNewLink(link, timestamp);
180 + }
181 + // FIXME: notify peers.
182 + return new LinkEvent(LINK_ADDED, link.entity());
183 + }
184 +
185 + // update Egress and ingress link sets
186 + private void addNewLink(VersionedValue<Link> link, Timestamp timestamp) {
187 + Link rawLink = link.entity();
188 + synchronized (this) {
189 + srcLinks.put(rawLink.src().deviceId(), link);
190 + dstLinks.put(rawLink.dst().deviceId(), link);
191 + }
192 + }
193 +
194 + // Updates, if necessary the specified link and returns the appropriate event.
195 + private LinkEvent updateLink(ProviderId providerId, VersionedValue<Link> existingLink,
196 + LinkKey key, LinkDescription linkDescription, Timestamp timestamp) {
197 + // FIXME confirm Link update condition is OK
198 + if (existingLink.entity().type() == INDIRECT && linkDescription.type() == DIRECT) {
199 + synchronized (this) {
200 +
201 + VersionedValue<Link> updatedLink = new VersionedValue<Link>(
202 + new DefaultLink(providerId, existingLink.entity().src(), existingLink.entity().dst(),
203 + linkDescription.type()), true, timestamp);
204 + links.replace(key, existingLink, updatedLink);
205 +
206 + replaceLink(existingLink, updatedLink);
207 + // FIXME: notify peers.
208 + return new LinkEvent(LINK_UPDATED, updatedLink.entity());
209 + }
210 + }
211 + return null;
212 + }
213 +
214 + // update Egress and ingress link sets
215 + private void replaceLink(VersionedValue<Link> current, VersionedValue<Link> updated) {
216 + synchronized (this) {
217 + srcLinks.remove(current.entity().src().deviceId(), current);
218 + dstLinks.remove(current.entity().dst().deviceId(), current);
219 +
220 + srcLinks.put(current.entity().src().deviceId(), updated);
221 + dstLinks.put(current.entity().dst().deviceId(), updated);
222 + }
223 + }
224 +
225 + @Override
226 + public LinkEvent removeLink(ConnectPoint src, ConnectPoint dst) {
227 + synchronized (this) {
228 + LinkKey key = new LinkKey(src, dst);
229 + VersionedValue<Link> link = links.remove(key);
230 + if (link != null) {
231 + removeLink(link);
232 + // notify peers
233 + return new LinkEvent(LINK_REMOVED, link.entity());
234 + }
235 + return null;
236 + }
237 + }
238 +
239 + // update Egress and ingress link sets
240 + private void removeLink(VersionedValue<Link> link) {
241 + synchronized (this) {
242 + srcLinks.remove(link.entity().src().deviceId(), link);
243 + dstLinks.remove(link.entity().dst().deviceId(), link);
244 + }
245 + }
246 +}
1 package org.onlab.onos.store.serializers; 1 package org.onlab.onos.store.serializers;
2 2
3 -import org.onlab.onos.net.ElementId;
4 import org.onlab.onos.store.impl.OnosTimestamp; 3 import org.onlab.onos.store.impl.OnosTimestamp;
5 4
6 import com.esotericsoftware.kryo.Kryo; 5 import com.esotericsoftware.kryo.Kryo;
...@@ -20,18 +19,17 @@ public class OnosTimestampSerializer extends Serializer<OnosTimestamp> { ...@@ -20,18 +19,17 @@ public class OnosTimestampSerializer extends Serializer<OnosTimestamp> {
20 // non-null, immutable 19 // non-null, immutable
21 super(false, true); 20 super(false, true);
22 } 21 }
22 +
23 @Override 23 @Override
24 public void write(Kryo kryo, Output output, OnosTimestamp object) { 24 public void write(Kryo kryo, Output output, OnosTimestamp object) {
25 - kryo.writeClassAndObject(output, object.id());
26 output.writeInt(object.termNumber()); 25 output.writeInt(object.termNumber());
27 output.writeInt(object.sequenceNumber()); 26 output.writeInt(object.sequenceNumber());
28 } 27 }
29 28
30 @Override 29 @Override
31 public OnosTimestamp read(Kryo kryo, Input input, Class<OnosTimestamp> type) { 30 public OnosTimestamp read(Kryo kryo, Input input, Class<OnosTimestamp> type) {
32 - ElementId id = (ElementId) kryo.readClassAndObject(input);
33 final int term = input.readInt(); 31 final int term = input.readInt();
34 final int sequence = input.readInt(); 32 final int sequence = input.readInt();
35 - return new OnosTimestamp(id, term, sequence); 33 + return new OnosTimestamp(term, sequence);
36 } 34 }
37 } 35 }
......
1 +package org.onlab.onos.store.topology.impl;
2 +
3 +import org.onlab.graph.AdjacencyListsGraph;
4 +import org.onlab.onos.net.topology.TopologyEdge;
5 +import org.onlab.onos.net.topology.TopologyGraph;
6 +import org.onlab.onos.net.topology.TopologyVertex;
7 +
8 +import java.util.Set;
9 +
10 +/**
11 + * Default implementation of an immutable topology graph based on a generic
12 + * implementation of adjacency lists graph.
13 + */
14 +public class DefaultTopologyGraph
15 + extends AdjacencyListsGraph<TopologyVertex, TopologyEdge>
16 + implements TopologyGraph {
17 +
18 + /**
19 + * Creates a topology graph comprising of the specified vertexes and edges.
20 + *
21 + * @param vertexes set of graph vertexes
22 + * @param edges set of graph edges
23 + */
24 + public DefaultTopologyGraph(Set<TopologyVertex> vertexes, Set<TopologyEdge> edges) {
25 + super(vertexes, edges);
26 + }
27 +
28 +}
1 +package org.onlab.onos.store.topology.impl;
2 +
3 +import static org.slf4j.LoggerFactory.getLogger;
4 +
5 +import java.util.List;
6 +import java.util.Set;
7 +
8 +import org.apache.felix.scr.annotations.Activate;
9 +import org.apache.felix.scr.annotations.Component;
10 +import org.apache.felix.scr.annotations.Deactivate;
11 +import org.apache.felix.scr.annotations.Service;
12 +import org.onlab.onos.event.Event;
13 +import org.onlab.onos.net.ConnectPoint;
14 +import org.onlab.onos.net.DeviceId;
15 +import org.onlab.onos.net.Link;
16 +import org.onlab.onos.net.Path;
17 +import org.onlab.onos.net.provider.ProviderId;
18 +import org.onlab.onos.net.topology.ClusterId;
19 +import org.onlab.onos.net.topology.GraphDescription;
20 +import org.onlab.onos.net.topology.LinkWeight;
21 +import org.onlab.onos.net.topology.Topology;
22 +import org.onlab.onos.net.topology.TopologyCluster;
23 +import org.onlab.onos.net.topology.TopologyEvent;
24 +import org.onlab.onos.net.topology.TopologyGraph;
25 +import org.onlab.onos.net.topology.TopologyStore;
26 +import org.onlab.onos.net.topology.TopologyStoreDelegate;
27 +import org.onlab.onos.store.AbstractStore;
28 +import org.slf4j.Logger;
29 +
30 +/**
31 + * Manages inventory of topology snapshots using trivial in-memory
32 + * structures implementation.
33 + */
34 +//FIXME: I LIE I AM NOT DISTRIBUTED
35 +@Component(immediate = true)
36 +@Service
37 +public class DistributedTopologyStore
38 +extends AbstractStore<TopologyEvent, TopologyStoreDelegate>
39 +implements TopologyStore {
40 +
41 + private final Logger log = getLogger(getClass());
42 +
43 + private volatile DefaultTopology current;
44 +
45 + @Activate
46 + public void activate() {
47 + log.info("Started");
48 + }
49 +
50 + @Deactivate
51 + public void deactivate() {
52 + log.info("Stopped");
53 + }
54 + @Override
55 + public Topology currentTopology() {
56 + return current;
57 + }
58 +
59 + @Override
60 + public boolean isLatest(Topology topology) {
61 + // Topology is current only if it is the same as our current topology
62 + return topology == current;
63 + }
64 +
65 + @Override
66 + public TopologyGraph getGraph(Topology topology) {
67 + return defaultTopology(topology).getGraph();
68 + }
69 +
70 + @Override
71 + public Set<TopologyCluster> getClusters(Topology topology) {
72 + return defaultTopology(topology).getClusters();
73 + }
74 +
75 + @Override
76 + public TopologyCluster getCluster(Topology topology, ClusterId clusterId) {
77 + return defaultTopology(topology).getCluster(clusterId);
78 + }
79 +
80 + @Override
81 + public Set<DeviceId> getClusterDevices(Topology topology, TopologyCluster cluster) {
82 + return defaultTopology(topology).getClusterDevices(cluster);
83 + }
84 +
85 + @Override
86 + public Set<Link> getClusterLinks(Topology topology, TopologyCluster cluster) {
87 + return defaultTopology(topology).getClusterLinks(cluster);
88 + }
89 +
90 + @Override
91 + public Set<Path> getPaths(Topology topology, DeviceId src, DeviceId dst) {
92 + return defaultTopology(topology).getPaths(src, dst);
93 + }
94 +
95 + @Override
96 + public Set<Path> getPaths(Topology topology, DeviceId src, DeviceId dst,
97 + LinkWeight weight) {
98 + return defaultTopology(topology).getPaths(src, dst, weight);
99 + }
100 +
101 + @Override
102 + public boolean isInfrastructure(Topology topology, ConnectPoint connectPoint) {
103 + return defaultTopology(topology).isInfrastructure(connectPoint);
104 + }
105 +
106 + @Override
107 + public boolean isBroadcastPoint(Topology topology, ConnectPoint connectPoint) {
108 + return defaultTopology(topology).isBroadcastPoint(connectPoint);
109 + }
110 +
111 + @Override
112 + public TopologyEvent updateTopology(ProviderId providerId,
113 + GraphDescription graphDescription,
114 + List<Event> reasons) {
115 + // First off, make sure that what we're given is indeed newer than
116 + // what we already have.
117 + if (current != null && graphDescription.timestamp() < current.time()) {
118 + return null;
119 + }
120 +
121 + // Have the default topology construct self from the description data.
122 + DefaultTopology newTopology =
123 + new DefaultTopology(providerId, graphDescription);
124 +
125 + // Promote the new topology to current and return a ready-to-send event.
126 + synchronized (this) {
127 + current = newTopology;
128 + return new TopologyEvent(TopologyEvent.Type.TOPOLOGY_CHANGED, current);
129 + }
130 + }
131 +
132 + // Validates the specified topology and returns it as a default
133 + private DefaultTopology defaultTopology(Topology topology) {
134 + if (topology instanceof DefaultTopology) {
135 + return (DefaultTopology) topology;
136 + }
137 + throw new IllegalArgumentException("Topology class " + topology.getClass() +
138 + " not supported");
139 + }
140 +
141 +}
1 +package org.onlab.onos.store.topology.impl;
2 +
3 +import org.onlab.onos.net.DeviceId;
4 +
5 +import java.util.Objects;
6 +
7 +/**
8 + * Key for filing pre-computed paths between source and destination devices.
9 + */
10 +class PathKey {
11 + private final DeviceId src;
12 + private final DeviceId dst;
13 +
14 + /**
15 + * Creates a path key from the given source/dest pair.
16 + * @param src source device
17 + * @param dst destination device
18 + */
19 + PathKey(DeviceId src, DeviceId dst) {
20 + this.src = src;
21 + this.dst = dst;
22 + }
23 +
24 + @Override
25 + public int hashCode() {
26 + return Objects.hash(src, dst);
27 + }
28 +
29 + @Override
30 + public boolean equals(Object obj) {
31 + if (this == obj) {
32 + return true;
33 + }
34 + if (obj instanceof PathKey) {
35 + final PathKey other = (PathKey) obj;
36 + return Objects.equals(this.src, other.src) && Objects.equals(this.dst, other.dst);
37 + }
38 + return false;
39 + }
40 +}
1 +<?xml version="1.0" encoding="UTF-8"?>
2 +<project xmlns="http://maven.apache.org/POM/4.0.0"
3 + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
4 + xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
5 + <modelVersion>4.0.0</modelVersion>
6 +
7 + <parent>
8 + <groupId>org.onlab.onos</groupId>
9 + <artifactId>onos-core-hz</artifactId>
10 + <version>1.0.0-SNAPSHOT</version>
11 + <relativePath>../pom.xml</relativePath>
12 + </parent>
13 +
14 + <artifactId>onos-core-hz-cluster</artifactId>
15 + <packaging>bundle</packaging>
16 +
17 + <description>ONOS Hazelcast based distributed store subsystems</description>
18 +
19 + <dependencies>
20 + <dependency>
21 + <groupId>org.onlab.onos</groupId>
22 + <artifactId>onos-api</artifactId>
23 + </dependency>
24 + <dependency>
25 + <groupId>org.onlab.onos</groupId>
26 + <artifactId>onos-core-serializers</artifactId>
27 + <version>${project.version}</version>
28 + </dependency>
29 + <dependency>
30 + <groupId>org.onlab.onos</groupId>
31 + <artifactId>onos-core-hz-common</artifactId>
32 + <version>${project.version}</version>
33 + </dependency>
34 + <dependency>
35 + <groupId>org.onlab.onos</groupId>
36 + <artifactId>onos-core-hz-common</artifactId>
37 + <classifier>tests</classifier>
38 + <scope>test</scope>
39 + <version>${project.version}</version>
40 + </dependency>
41 + <dependency>
42 + <groupId>org.apache.felix</groupId>
43 + <artifactId>org.apache.felix.scr.annotations</artifactId>
44 + </dependency>
45 + <dependency>
46 + <groupId>com.hazelcast</groupId>
47 + <artifactId>hazelcast</artifactId>
48 + </dependency>
49 + <dependency>
50 + <groupId>de.javakaffee</groupId>
51 + <artifactId>kryo-serializers</artifactId>
52 + </dependency>
53 + </dependencies>
54 +
55 + <build>
56 + <plugins>
57 + <plugin>
58 + <groupId>org.apache.felix</groupId>
59 + <artifactId>maven-scr-plugin</artifactId>
60 + </plugin>
61 + </plugins>
62 + </build>
63 +
64 +</project>
...@@ -8,6 +8,7 @@ import com.hazelcast.core.Member; ...@@ -8,6 +8,7 @@ import com.hazelcast.core.Member;
8 import com.hazelcast.core.MemberAttributeEvent; 8 import com.hazelcast.core.MemberAttributeEvent;
9 import com.hazelcast.core.MembershipEvent; 9 import com.hazelcast.core.MembershipEvent;
10 import com.hazelcast.core.MembershipListener; 10 import com.hazelcast.core.MembershipListener;
11 +
11 import org.apache.felix.scr.annotations.Activate; 12 import org.apache.felix.scr.annotations.Activate;
12 import org.apache.felix.scr.annotations.Component; 13 import org.apache.felix.scr.annotations.Component;
13 import org.apache.felix.scr.annotations.Deactivate; 14 import org.apache.felix.scr.annotations.Deactivate;
...@@ -18,9 +19,9 @@ import org.onlab.onos.cluster.ClusterStoreDelegate; ...@@ -18,9 +19,9 @@ import org.onlab.onos.cluster.ClusterStoreDelegate;
18 import org.onlab.onos.cluster.ControllerNode; 19 import org.onlab.onos.cluster.ControllerNode;
19 import org.onlab.onos.cluster.DefaultControllerNode; 20 import org.onlab.onos.cluster.DefaultControllerNode;
20 import org.onlab.onos.cluster.NodeId; 21 import org.onlab.onos.cluster.NodeId;
21 -import org.onlab.onos.store.impl.AbsentInvalidatingLoadingCache; 22 +import org.onlab.onos.store.common.AbsentInvalidatingLoadingCache;
22 -import org.onlab.onos.store.impl.AbstractDistributedStore; 23 +import org.onlab.onos.store.common.AbstractHazelcastStore;
23 -import org.onlab.onos.store.impl.OptionalCacheLoader; 24 +import org.onlab.onos.store.common.OptionalCacheLoader;
24 import org.onlab.packet.IpPrefix; 25 import org.onlab.packet.IpPrefix;
25 26
26 import java.util.Map; 27 import java.util.Map;
...@@ -38,7 +39,7 @@ import static org.onlab.onos.cluster.ControllerNode.State; ...@@ -38,7 +39,7 @@ import static org.onlab.onos.cluster.ControllerNode.State;
38 @Component(immediate = true) 39 @Component(immediate = true)
39 @Service 40 @Service
40 public class DistributedClusterStore 41 public class DistributedClusterStore
41 - extends AbstractDistributedStore<ClusterEvent, ClusterStoreDelegate> 42 + extends AbstractHazelcastStore<ClusterEvent, ClusterStoreDelegate>
42 implements ClusterStore { 43 implements ClusterStore {
43 44
44 private IMap<byte[], byte[]> rawNodes; 45 private IMap<byte[], byte[]> rawNodes;
...@@ -57,7 +58,7 @@ public class DistributedClusterStore ...@@ -57,7 +58,7 @@ public class DistributedClusterStore
57 OptionalCacheLoader<NodeId, DefaultControllerNode> nodeLoader 58 OptionalCacheLoader<NodeId, DefaultControllerNode> nodeLoader
58 = new OptionalCacheLoader<>(storeService, rawNodes); 59 = new OptionalCacheLoader<>(storeService, rawNodes);
59 nodes = new AbsentInvalidatingLoadingCache<>(newBuilder().build(nodeLoader)); 60 nodes = new AbsentInvalidatingLoadingCache<>(newBuilder().build(nodeLoader));
60 - rawNodes.addEntryListener(new RemoteEventHandler<>(nodes), true); 61 + rawNodes.addEntryListener(new RemoteCacheEventHandler<>(nodes), true);
61 62
62 loadClusterNodes(); 63 loadClusterNodes();
63 64
...@@ -67,7 +68,7 @@ public class DistributedClusterStore ...@@ -67,7 +68,7 @@ public class DistributedClusterStore
67 // Loads the initial set of cluster nodes 68 // Loads the initial set of cluster nodes
68 private void loadClusterNodes() { 69 private void loadClusterNodes() {
69 for (Member member : theInstance.getCluster().getMembers()) { 70 for (Member member : theInstance.getCluster().getMembers()) {
70 - addMember(member); 71 + addNode(node(member));
71 } 72 }
72 } 73 }
73 74
...@@ -103,6 +104,11 @@ public class DistributedClusterStore ...@@ -103,6 +104,11 @@ public class DistributedClusterStore
103 } 104 }
104 105
105 @Override 106 @Override
107 + public ControllerNode addNode(NodeId nodeId, IpPrefix ip, int tcpPort) {
108 + return addNode(new DefaultControllerNode(nodeId, ip, tcpPort));
109 + }
110 +
111 + @Override
106 public void removeNode(NodeId nodeId) { 112 public void removeNode(NodeId nodeId) {
107 synchronized (this) { 113 synchronized (this) {
108 rawNodes.remove(serialize(nodeId)); 114 rawNodes.remove(serialize(nodeId));
...@@ -111,8 +117,7 @@ public class DistributedClusterStore ...@@ -111,8 +117,7 @@ public class DistributedClusterStore
111 } 117 }
112 118
113 // Adds a new node based on the specified member 119 // Adds a new node based on the specified member
114 - private synchronized ControllerNode addMember(Member member) { 120 + private synchronized ControllerNode addNode(DefaultControllerNode node) {
115 - DefaultControllerNode node = node(member);
116 rawNodes.put(serialize(node.id()), serialize(node)); 121 rawNodes.put(serialize(node.id()), serialize(node));
117 nodes.put(node.id(), Optional.of(node)); 122 nodes.put(node.id(), Optional.of(node));
118 states.put(node.id(), State.ACTIVE); 123 states.put(node.id(), State.ACTIVE);
...@@ -135,7 +140,7 @@ public class DistributedClusterStore ...@@ -135,7 +140,7 @@ public class DistributedClusterStore
135 @Override 140 @Override
136 public void memberAdded(MembershipEvent membershipEvent) { 141 public void memberAdded(MembershipEvent membershipEvent) {
137 log.info("Member {} added", membershipEvent.getMember()); 142 log.info("Member {} added", membershipEvent.getMember());
138 - ControllerNode node = addMember(membershipEvent.getMember()); 143 + ControllerNode node = addNode(node(membershipEvent.getMember()));
139 notifyDelegate(new ClusterEvent(INSTANCE_ACTIVATED, node)); 144 notifyDelegate(new ClusterEvent(INSTANCE_ACTIVATED, node));
140 } 145 }
141 146
......
1 package org.onlab.onos.store.cluster.impl; 1 package org.onlab.onos.store.cluster.impl;
2 2
3 -import com.google.common.base.Optional; 3 +import static com.google.common.cache.CacheBuilder.newBuilder;
4 -import com.google.common.cache.LoadingCache; 4 +import static org.onlab.onos.cluster.MastershipEvent.Type.MASTER_CHANGED;
5 -import com.google.common.collect.ImmutableSet; 5 +
6 -import com.hazelcast.core.IMap; 6 +import java.util.Map;
7 +import java.util.Objects;
8 +import java.util.Set;
7 9
8 import org.apache.felix.scr.annotations.Activate; 10 import org.apache.felix.scr.annotations.Activate;
9 import org.apache.felix.scr.annotations.Component; 11 import org.apache.felix.scr.annotations.Component;
...@@ -19,15 +21,14 @@ import org.onlab.onos.cluster.MastershipTerm; ...@@ -19,15 +21,14 @@ import org.onlab.onos.cluster.MastershipTerm;
19 import org.onlab.onos.cluster.NodeId; 21 import org.onlab.onos.cluster.NodeId;
20 import org.onlab.onos.net.DeviceId; 22 import org.onlab.onos.net.DeviceId;
21 import org.onlab.onos.net.MastershipRole; 23 import org.onlab.onos.net.MastershipRole;
22 -import org.onlab.onos.store.impl.AbsentInvalidatingLoadingCache; 24 +import org.onlab.onos.store.common.AbsentInvalidatingLoadingCache;
23 -import org.onlab.onos.store.impl.AbstractDistributedStore; 25 +import org.onlab.onos.store.common.AbstractHazelcastStore;
24 -import org.onlab.onos.store.impl.OptionalCacheLoader; 26 +import org.onlab.onos.store.common.OptionalCacheLoader;
25 27
26 -import java.util.Map; 28 +import com.google.common.base.Optional;
27 -import java.util.Objects; 29 +import com.google.common.cache.LoadingCache;
28 -import java.util.Set; 30 +import com.google.common.collect.ImmutableSet;
29 - 31 +import com.hazelcast.core.IMap;
30 -import static com.google.common.cache.CacheBuilder.newBuilder;
31 32
32 /** 33 /**
33 * Distributed implementation of the cluster nodes store. 34 * Distributed implementation of the cluster nodes store.
...@@ -35,8 +36,8 @@ import static com.google.common.cache.CacheBuilder.newBuilder; ...@@ -35,8 +36,8 @@ import static com.google.common.cache.CacheBuilder.newBuilder;
35 @Component(immediate = true) 36 @Component(immediate = true)
36 @Service 37 @Service
37 public class DistributedMastershipStore 38 public class DistributedMastershipStore
38 - extends AbstractDistributedStore<MastershipEvent, MastershipStoreDelegate> 39 +extends AbstractHazelcastStore<MastershipEvent, MastershipStoreDelegate>
39 - implements MastershipStore { 40 +implements MastershipStore {
40 41
41 private IMap<byte[], byte[]> rawMasters; 42 private IMap<byte[], byte[]> rawMasters;
42 private LoadingCache<DeviceId, Optional<NodeId>> masters; 43 private LoadingCache<DeviceId, Optional<NodeId>> masters;
...@@ -51,9 +52,9 @@ public class DistributedMastershipStore ...@@ -51,9 +52,9 @@ public class DistributedMastershipStore
51 52
52 rawMasters = theInstance.getMap("masters"); 53 rawMasters = theInstance.getMap("masters");
53 OptionalCacheLoader<DeviceId, NodeId> nodeLoader 54 OptionalCacheLoader<DeviceId, NodeId> nodeLoader
54 - = new OptionalCacheLoader<>(storeService, rawMasters); 55 + = new OptionalCacheLoader<>(storeService, rawMasters);
55 masters = new AbsentInvalidatingLoadingCache<>(newBuilder().build(nodeLoader)); 56 masters = new AbsentInvalidatingLoadingCache<>(newBuilder().build(nodeLoader));
56 - rawMasters.addEntryListener(new RemoteEventHandler<>(masters), true); 57 + rawMasters.addEntryListener(new RemoteMasterShipEventHandler(masters), true);
57 58
58 loadMasters(); 59 loadMasters();
59 60
...@@ -128,4 +129,25 @@ public class DistributedMastershipStore ...@@ -128,4 +129,25 @@ public class DistributedMastershipStore
128 return null; 129 return null;
129 } 130 }
130 131
132 + private class RemoteMasterShipEventHandler extends RemoteCacheEventHandler<DeviceId, NodeId> {
133 + 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 +
131 } 153 }
......
1 +<?xml version="1.0" encoding="UTF-8"?>
2 +<project xmlns="http://maven.apache.org/POM/4.0.0"
3 + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
4 + xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
5 + <modelVersion>4.0.0</modelVersion>
6 +
7 + <parent>
8 + <groupId>org.onlab.onos</groupId>
9 + <artifactId>onos-core-hz</artifactId>
10 + <version>1.0.0-SNAPSHOT</version>
11 + <relativePath>../pom.xml</relativePath>
12 + </parent>
13 +
14 + <artifactId>onos-core-hz-common</artifactId>
15 + <packaging>bundle</packaging>
16 +
17 + <description>ONOS Hazelcast based distributed store subsystems</description>
18 +
19 + <dependencies>
20 + <dependency>
21 + <groupId>org.onlab.onos</groupId>
22 + <artifactId>onos-api</artifactId>
23 + </dependency>
24 + <dependency>
25 + <groupId>org.onlab.onos</groupId>
26 + <artifactId>onos-core-serializers</artifactId>
27 + <version>${project.version}</version>
28 + </dependency>
29 + <dependency>
30 + <groupId>org.apache.felix</groupId>
31 + <artifactId>org.apache.felix.scr.annotations</artifactId>
32 + </dependency>
33 + <dependency>
34 + <groupId>com.hazelcast</groupId>
35 + <artifactId>hazelcast</artifactId>
36 + </dependency>
37 + <dependency>
38 + <groupId>de.javakaffee</groupId>
39 + <artifactId>kryo-serializers</artifactId>
40 + </dependency>
41 + </dependencies>
42 +
43 + <build>
44 + <plugins>
45 + <plugin>
46 + <groupId>org.apache.felix</groupId>
47 + <artifactId>maven-scr-plugin</artifactId>
48 + </plugin>
49 + </plugins>
50 + </build>
51 +
52 +</project>
1 -package org.onlab.onos.store.impl; 1 +package org.onlab.onos.store.common;
2 2
3 import java.util.concurrent.Callable; 3 import java.util.concurrent.Callable;
4 import java.util.concurrent.ExecutionException; 4 import java.util.concurrent.ExecutionException;
......
1 -package org.onlab.onos.store.impl; 1 +package org.onlab.onos.store.common;
2 2
3 import com.google.common.base.Optional; 3 import com.google.common.base.Optional;
4 import com.google.common.cache.LoadingCache; 4 import com.google.common.cache.LoadingCache;
...@@ -6,6 +6,8 @@ import com.hazelcast.core.EntryAdapter; ...@@ -6,6 +6,8 @@ import com.hazelcast.core.EntryAdapter;
6 import com.hazelcast.core.EntryEvent; 6 import com.hazelcast.core.EntryEvent;
7 import com.hazelcast.core.HazelcastInstance; 7 import com.hazelcast.core.HazelcastInstance;
8 import com.hazelcast.core.MapEvent; 8 import com.hazelcast.core.MapEvent;
9 +import com.hazelcast.core.Member;
10 +
9 import org.apache.felix.scr.annotations.Activate; 11 import org.apache.felix.scr.annotations.Activate;
10 import org.apache.felix.scr.annotations.Component; 12 import org.apache.felix.scr.annotations.Component;
11 import org.apache.felix.scr.annotations.Reference; 13 import org.apache.felix.scr.annotations.Reference;
...@@ -13,7 +15,6 @@ import org.apache.felix.scr.annotations.ReferenceCardinality; ...@@ -13,7 +15,6 @@ import org.apache.felix.scr.annotations.ReferenceCardinality;
13 import org.onlab.onos.event.Event; 15 import org.onlab.onos.event.Event;
14 import org.onlab.onos.store.AbstractStore; 16 import org.onlab.onos.store.AbstractStore;
15 import org.onlab.onos.store.StoreDelegate; 17 import org.onlab.onos.store.StoreDelegate;
16 -import org.onlab.onos.store.common.StoreService;
17 import org.slf4j.Logger; 18 import org.slf4j.Logger;
18 19
19 import static com.google.common.base.Preconditions.checkNotNull; 20 import static com.google.common.base.Preconditions.checkNotNull;
...@@ -23,7 +24,7 @@ import static org.slf4j.LoggerFactory.getLogger; ...@@ -23,7 +24,7 @@ import static org.slf4j.LoggerFactory.getLogger;
23 * Abstraction of a distributed store based on Hazelcast. 24 * Abstraction of a distributed store based on Hazelcast.
24 */ 25 */
25 @Component(componentAbstract = true) 26 @Component(componentAbstract = true)
26 -public abstract class AbstractDistributedStore<E extends Event, D extends StoreDelegate<E>> 27 +public abstract class AbstractHazelcastStore<E extends Event, D extends StoreDelegate<E>>
27 extends AbstractStore<E, D> { 28 extends AbstractStore<E, D> {
28 29
29 protected final Logger log = getLogger(getClass()); 30 protected final Logger log = getLogger(getClass());
...@@ -66,8 +67,9 @@ public abstract class AbstractDistributedStore<E extends Event, D extends StoreD ...@@ -66,8 +67,9 @@ public abstract class AbstractDistributedStore<E extends Event, D extends StoreD
66 * @param <K> IMap key type after deserialization 67 * @param <K> IMap key type after deserialization
67 * @param <V> IMap value type after deserialization 68 * @param <V> IMap value type after deserialization
68 */ 69 */
69 - public class RemoteEventHandler<K, V> extends EntryAdapter<byte[], byte[]> { 70 + public class RemoteCacheEventHandler<K, V> extends EntryAdapter<byte[], byte[]> {
70 71
72 + private final Member localMember;
71 private LoadingCache<K, Optional<V>> cache; 73 private LoadingCache<K, Optional<V>> cache;
72 74
73 /** 75 /**
...@@ -75,17 +77,26 @@ public abstract class AbstractDistributedStore<E extends Event, D extends StoreD ...@@ -75,17 +77,26 @@ public abstract class AbstractDistributedStore<E extends Event, D extends StoreD
75 * 77 *
76 * @param cache cache to update 78 * @param cache cache to update
77 */ 79 */
78 - public RemoteEventHandler(LoadingCache<K, Optional<V>> cache) { 80 + public RemoteCacheEventHandler(LoadingCache<K, Optional<V>> cache) {
81 + this.localMember = theInstance.getCluster().getLocalMember();
79 this.cache = checkNotNull(cache); 82 this.cache = checkNotNull(cache);
80 } 83 }
81 84
82 @Override 85 @Override
83 public void mapCleared(MapEvent event) { 86 public void mapCleared(MapEvent event) {
87 + if (localMember.equals(event.getMember())) {
88 + // ignore locally triggered event
89 + return;
90 + }
84 cache.invalidateAll(); 91 cache.invalidateAll();
85 } 92 }
86 93
87 @Override 94 @Override
88 public void entryAdded(EntryEvent<byte[], byte[]> event) { 95 public void entryAdded(EntryEvent<byte[], byte[]> event) {
96 + if (localMember.equals(event.getMember())) {
97 + // ignore locally triggered event
98 + return;
99 + }
89 K key = deserialize(event.getKey()); 100 K key = deserialize(event.getKey());
90 V newVal = deserialize(event.getValue()); 101 V newVal = deserialize(event.getValue());
91 Optional<V> newValue = Optional.of(newVal); 102 Optional<V> newValue = Optional.of(newVal);
...@@ -95,6 +106,10 @@ public abstract class AbstractDistributedStore<E extends Event, D extends StoreD ...@@ -95,6 +106,10 @@ public abstract class AbstractDistributedStore<E extends Event, D extends StoreD
95 106
96 @Override 107 @Override
97 public void entryUpdated(EntryEvent<byte[], byte[]> event) { 108 public void entryUpdated(EntryEvent<byte[], byte[]> event) {
109 + if (localMember.equals(event.getMember())) {
110 + // ignore locally triggered event
111 + return;
112 + }
98 K key = deserialize(event.getKey()); 113 K key = deserialize(event.getKey());
99 V oldVal = deserialize(event.getOldValue()); 114 V oldVal = deserialize(event.getOldValue());
100 Optional<V> oldValue = Optional.fromNullable(oldVal); 115 Optional<V> oldValue = Optional.fromNullable(oldVal);
...@@ -106,6 +121,10 @@ public abstract class AbstractDistributedStore<E extends Event, D extends StoreD ...@@ -106,6 +121,10 @@ public abstract class AbstractDistributedStore<E extends Event, D extends StoreD
106 121
107 @Override 122 @Override
108 public void entryRemoved(EntryEvent<byte[], byte[]> event) { 123 public void entryRemoved(EntryEvent<byte[], byte[]> event) {
124 + if (localMember.equals(event.getMember())) {
125 + // ignore locally triggered event
126 + return;
127 + }
109 K key = deserialize(event.getKey()); 128 K key = deserialize(event.getKey());
110 V val = deserialize(event.getOldValue()); 129 V val = deserialize(event.getOldValue());
111 cache.invalidate(key); 130 cache.invalidate(key);
...@@ -141,4 +160,80 @@ public abstract class AbstractDistributedStore<E extends Event, D extends StoreD ...@@ -141,4 +160,80 @@ public abstract class AbstractDistributedStore<E extends Event, D extends StoreD
141 } 160 }
142 } 161 }
143 162
163 + /**
164 + * Distributed object remote event entry listener.
165 + *
166 + * @param <K> Entry key type after deserialization
167 + * @param <V> Entry value type after deserialization
168 + */
169 + public class RemoteEventHandler<K, V> extends EntryAdapter<byte[], byte[]> {
170 +
171 + private final Member localMember;
172 +
173 + public RemoteEventHandler() {
174 + this.localMember = theInstance.getCluster().getLocalMember();
175 + }
176 + @Override
177 + public void entryAdded(EntryEvent<byte[], byte[]> event) {
178 + if (localMember.equals(event.getMember())) {
179 + // ignore locally triggered event
180 + return;
181 + }
182 + K key = deserialize(event.getKey());
183 + V newVal = deserialize(event.getValue());
184 + onAdd(key, newVal);
185 + }
186 +
187 + @Override
188 + public void entryRemoved(EntryEvent<byte[], byte[]> event) {
189 + if (localMember.equals(event.getMember())) {
190 + // ignore locally triggered event
191 + return;
192 + }
193 + K key = deserialize(event.getKey());
194 + V val = deserialize(event.getValue());
195 + onRemove(key, val);
196 + }
197 +
198 + @Override
199 + public void entryUpdated(EntryEvent<byte[], byte[]> event) {
200 + if (localMember.equals(event.getMember())) {
201 + // ignore locally triggered event
202 + return;
203 + }
204 + K key = deserialize(event.getKey());
205 + V oldVal = deserialize(event.getOldValue());
206 + V newVal = deserialize(event.getValue());
207 + onUpdate(key, oldVal, newVal);
208 + }
209 +
210 + /**
211 + * Remote entry addition hook.
212 + *
213 + * @param key new key
214 + * @param newVal new value
215 + */
216 + protected void onAdd(K key, V newVal) {
217 + }
218 +
219 + /**
220 + * Remote entry update hook.
221 + *
222 + * @param key new key
223 + * @param oldValue old value
224 + * @param newVal new value
225 + */
226 + protected void onUpdate(K key, V oldValue, V newVal) {
227 + }
228 +
229 + /**
230 + * Remote entry remove hook.
231 + *
232 + * @param key new key
233 + * @param val old value
234 + */
235 + protected void onRemove(K key, V val) {
236 + }
237 + }
238 +
144 } 239 }
......
1 -package org.onlab.onos.store.impl; 1 +package org.onlab.onos.store.common;
2 2
3 import static com.google.common.base.Preconditions.checkNotNull; 3 import static com.google.common.base.Preconditions.checkNotNull;
4 4
5 -import org.onlab.onos.store.common.StoreService;
6 -
7 import com.google.common.base.Optional; 5 import com.google.common.base.Optional;
8 import com.google.common.cache.CacheLoader; 6 import com.google.common.cache.CacheLoader;
9 import com.hazelcast.core.IMap; 7 import com.hazelcast.core.IMap;
......
1 -package org.onlab.onos.store.impl; 1 +package org.onlab.onos.store.common;
2 2
3 import com.hazelcast.config.Config; 3 import com.hazelcast.config.Config;
4 import com.hazelcast.config.FileSystemXmlConfig; 4 import com.hazelcast.config.FileSystemXmlConfig;
...@@ -27,7 +27,6 @@ import org.onlab.onos.net.MastershipRole; ...@@ -27,7 +27,6 @@ import org.onlab.onos.net.MastershipRole;
27 import org.onlab.onos.net.Port; 27 import org.onlab.onos.net.Port;
28 import org.onlab.onos.net.PortNumber; 28 import org.onlab.onos.net.PortNumber;
29 import org.onlab.onos.net.provider.ProviderId; 29 import org.onlab.onos.net.provider.ProviderId;
30 -import org.onlab.onos.store.common.StoreService;
31 import org.onlab.onos.store.serializers.ConnectPointSerializer; 30 import org.onlab.onos.store.serializers.ConnectPointSerializer;
32 import org.onlab.onos.store.serializers.DefaultLinkSerializer; 31 import org.onlab.onos.store.serializers.DefaultLinkSerializer;
33 import org.onlab.onos.store.serializers.DefaultPortSerializer; 32 import org.onlab.onos.store.serializers.DefaultPortSerializer;
...@@ -35,7 +34,6 @@ import org.onlab.onos.store.serializers.DeviceIdSerializer; ...@@ -35,7 +34,6 @@ import org.onlab.onos.store.serializers.DeviceIdSerializer;
35 import org.onlab.onos.store.serializers.IpPrefixSerializer; 34 import org.onlab.onos.store.serializers.IpPrefixSerializer;
36 import org.onlab.onos.store.serializers.LinkKeySerializer; 35 import org.onlab.onos.store.serializers.LinkKeySerializer;
37 import org.onlab.onos.store.serializers.NodeIdSerializer; 36 import org.onlab.onos.store.serializers.NodeIdSerializer;
38 -import org.onlab.onos.store.serializers.OnosTimestampSerializer;
39 import org.onlab.onos.store.serializers.PortNumberSerializer; 37 import org.onlab.onos.store.serializers.PortNumberSerializer;
40 import org.onlab.onos.store.serializers.ProviderIdSerializer; 38 import org.onlab.onos.store.serializers.ProviderIdSerializer;
41 import org.onlab.packet.IpPrefix; 39 import org.onlab.packet.IpPrefix;
...@@ -102,7 +100,6 @@ public class StoreManager implements StoreService { ...@@ -102,7 +100,6 @@ public class StoreManager implements StoreService {
102 .register(DeviceId.class, new DeviceIdSerializer()) 100 .register(DeviceId.class, new DeviceIdSerializer())
103 .register(PortNumber.class, new PortNumberSerializer()) 101 .register(PortNumber.class, new PortNumberSerializer())
104 .register(DefaultPort.class, new DefaultPortSerializer()) 102 .register(DefaultPort.class, new DefaultPortSerializer())
105 - .register(OnosTimestamp.class, new OnosTimestampSerializer())
106 .register(LinkKey.class, new LinkKeySerializer()) 103 .register(LinkKey.class, new LinkKeySerializer())
107 .register(ConnectPoint.class, new ConnectPointSerializer()) 104 .register(ConnectPoint.class, new ConnectPointSerializer())
108 .register(DefaultLink.class, new DefaultLinkSerializer()) 105 .register(DefaultLink.class, new DefaultLinkSerializer())
......
1 -package org.onlab.onos.store.impl; 1 +package org.onlab.onos.store.common;
2 2
3 import java.io.FileNotFoundException; 3 import java.io.FileNotFoundException;
4 import java.util.UUID; 4 import java.util.UUID;
......
1 +<?xml version="1.0" encoding="UTF-8"?>
2 +<project xmlns="http://maven.apache.org/POM/4.0.0"
3 + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
4 + xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
5 + <modelVersion>4.0.0</modelVersion>
6 +
7 + <parent>
8 + <groupId>org.onlab.onos</groupId>
9 + <artifactId>onos-core-hz</artifactId>
10 + <version>1.0.0-SNAPSHOT</version>
11 + <relativePath>../pom.xml</relativePath>
12 + </parent>
13 +
14 + <artifactId>onos-core-hz-net</artifactId>
15 + <packaging>bundle</packaging>
16 +
17 + <description>ONOS Hazelcast based distributed store subsystems</description>
18 +
19 + <dependencies>
20 + <dependency>
21 + <groupId>org.onlab.onos</groupId>
22 + <artifactId>onos-api</artifactId>
23 + </dependency>
24 + <dependency>
25 + <groupId>org.onlab.onos</groupId>
26 + <artifactId>onos-core-serializers</artifactId>
27 + <version>${project.version}</version>
28 + </dependency>
29 + <dependency>
30 + <groupId>org.onlab.onos</groupId>
31 + <artifactId>onos-core-hz-common</artifactId>
32 + <version>${project.version}</version>
33 + </dependency>
34 + <dependency>
35 + <groupId>org.onlab.onos</groupId>
36 + <artifactId>onos-core-hz-common</artifactId>
37 + <classifier>tests</classifier>
38 + <scope>test</scope>
39 + <version>${project.version}</version>
40 + </dependency>
41 + <dependency>
42 + <groupId>org.apache.felix</groupId>
43 + <artifactId>org.apache.felix.scr.annotations</artifactId>
44 + </dependency>
45 + <dependency>
46 + <groupId>com.hazelcast</groupId>
47 + <artifactId>hazelcast</artifactId>
48 + </dependency>
49 + <dependency>
50 + <groupId>de.javakaffee</groupId>
51 + <artifactId>kryo-serializers</artifactId>
52 + </dependency>
53 + </dependencies>
54 +
55 + <build>
56 + <plugins>
57 + <plugin>
58 + <groupId>org.apache.felix</groupId>
59 + <artifactId>maven-scr-plugin</artifactId>
60 + </plugin>
61 + </plugins>
62 + </build>
63 +
64 +</project>
1 package org.onlab.onos.store.device.impl; 1 package org.onlab.onos.store.device.impl;
2 2
3 import static com.google.common.base.Predicates.notNull; 3 import static com.google.common.base.Predicates.notNull;
4 +
4 import com.google.common.base.Optional; 5 import com.google.common.base.Optional;
5 import com.google.common.cache.LoadingCache; 6 import com.google.common.cache.LoadingCache;
6 import com.google.common.collect.FluentIterable; 7 import com.google.common.collect.FluentIterable;
...@@ -26,9 +27,9 @@ import org.onlab.onos.net.device.DeviceStore; ...@@ -26,9 +27,9 @@ import org.onlab.onos.net.device.DeviceStore;
26 import org.onlab.onos.net.device.DeviceStoreDelegate; 27 import org.onlab.onos.net.device.DeviceStoreDelegate;
27 import org.onlab.onos.net.device.PortDescription; 28 import org.onlab.onos.net.device.PortDescription;
28 import org.onlab.onos.net.provider.ProviderId; 29 import org.onlab.onos.net.provider.ProviderId;
29 -import org.onlab.onos.store.impl.AbsentInvalidatingLoadingCache; 30 +import org.onlab.onos.store.common.AbsentInvalidatingLoadingCache;
30 -import org.onlab.onos.store.impl.AbstractDistributedStore; 31 +import org.onlab.onos.store.common.AbstractHazelcastStore;
31 -import org.onlab.onos.store.impl.OptionalCacheLoader; 32 +import org.onlab.onos.store.common.OptionalCacheLoader;
32 import org.slf4j.Logger; 33 import org.slf4j.Logger;
33 34
34 import java.util.ArrayList; 35 import java.util.ArrayList;
...@@ -52,7 +53,7 @@ import static org.slf4j.LoggerFactory.getLogger; ...@@ -52,7 +53,7 @@ import static org.slf4j.LoggerFactory.getLogger;
52 @Component(immediate = true) 53 @Component(immediate = true)
53 @Service 54 @Service
54 public class DistributedDeviceStore 55 public class DistributedDeviceStore
55 - extends AbstractDistributedStore<DeviceEvent, DeviceStoreDelegate> 56 + extends AbstractHazelcastStore<DeviceEvent, DeviceStoreDelegate>
56 implements DeviceStore { 57 implements DeviceStore {
57 58
58 private final Logger log = getLogger(getClass()); 59 private final Logger log = getLogger(getClass());
...@@ -71,6 +72,10 @@ public class DistributedDeviceStore ...@@ -71,6 +72,10 @@ public class DistributedDeviceStore
71 private IMap<byte[], byte[]> rawDevicePorts; 72 private IMap<byte[], byte[]> rawDevicePorts;
72 private LoadingCache<DeviceId, Optional<Map<PortNumber, Port>>> devicePorts; 73 private LoadingCache<DeviceId, Optional<Map<PortNumber, Port>>> devicePorts;
73 74
75 + private String devicesListener;
76 +
77 + private String portsListener;
78 +
74 @Override 79 @Override
75 @Activate 80 @Activate
76 public void activate() { 81 public void activate() {
...@@ -85,7 +90,7 @@ public class DistributedDeviceStore ...@@ -85,7 +90,7 @@ public class DistributedDeviceStore
85 = new OptionalCacheLoader<>(storeService, rawDevices); 90 = new OptionalCacheLoader<>(storeService, rawDevices);
86 devices = new AbsentInvalidatingLoadingCache<>(newBuilder().build(deviceLoader)); 91 devices = new AbsentInvalidatingLoadingCache<>(newBuilder().build(deviceLoader));
87 // refresh/populate cache based on notification from other instance 92 // refresh/populate cache based on notification from other instance
88 - rawDevices.addEntryListener(new RemoteDeviceEventHandler(devices), includeValue); 93 + devicesListener = rawDevices.addEntryListener(new RemoteDeviceEventHandler(devices), includeValue);
89 94
90 // TODO cache availableDevices 95 // TODO cache availableDevices
91 availableDevices = theInstance.getSet("availableDevices"); 96 availableDevices = theInstance.getSet("availableDevices");
...@@ -95,7 +100,7 @@ public class DistributedDeviceStore ...@@ -95,7 +100,7 @@ public class DistributedDeviceStore
95 = new OptionalCacheLoader<>(storeService, rawDevicePorts); 100 = new OptionalCacheLoader<>(storeService, rawDevicePorts);
96 devicePorts = new AbsentInvalidatingLoadingCache<>(newBuilder().build(devicePortLoader)); 101 devicePorts = new AbsentInvalidatingLoadingCache<>(newBuilder().build(devicePortLoader));
97 // refresh/populate cache based on notification from other instance 102 // refresh/populate cache based on notification from other instance
98 - rawDevicePorts.addEntryListener(new RemotePortEventHandler(devicePorts), includeValue); 103 + portsListener = rawDevicePorts.addEntryListener(new RemotePortEventHandler(devicePorts), includeValue);
99 104
100 loadDeviceCache(); 105 loadDeviceCache();
101 loadDevicePortsCache(); 106 loadDevicePortsCache();
...@@ -105,6 +110,8 @@ public class DistributedDeviceStore ...@@ -105,6 +110,8 @@ public class DistributedDeviceStore
105 110
106 @Deactivate 111 @Deactivate
107 public void deactivate() { 112 public void deactivate() {
113 + rawDevicePorts.removeEntryListener(portsListener);
114 + rawDevices.removeEntryListener(devicesListener);
108 log.info("Stopped"); 115 log.info("Stopped");
109 } 116 }
110 117
...@@ -353,7 +360,7 @@ public class DistributedDeviceStore ...@@ -353,7 +360,7 @@ public class DistributedDeviceStore
353 } 360 }
354 } 361 }
355 362
356 - private class RemoteDeviceEventHandler extends RemoteEventHandler<DeviceId, DefaultDevice> { 363 + private class RemoteDeviceEventHandler extends RemoteCacheEventHandler<DeviceId, DefaultDevice> {
357 public RemoteDeviceEventHandler(LoadingCache<DeviceId, Optional<DefaultDevice>> cache) { 364 public RemoteDeviceEventHandler(LoadingCache<DeviceId, Optional<DefaultDevice>> cache) {
358 super(cache); 365 super(cache);
359 } 366 }
...@@ -374,7 +381,7 @@ public class DistributedDeviceStore ...@@ -374,7 +381,7 @@ public class DistributedDeviceStore
374 } 381 }
375 } 382 }
376 383
377 - private class RemotePortEventHandler extends RemoteEventHandler<DeviceId, Map<PortNumber, Port>> { 384 + private class RemotePortEventHandler extends RemoteCacheEventHandler<DeviceId, Map<PortNumber, Port>> {
378 public RemotePortEventHandler(LoadingCache<DeviceId, Optional<Map<PortNumber, Port>>> cache) { 385 public RemotePortEventHandler(LoadingCache<DeviceId, Optional<Map<PortNumber, Port>>> cache) {
379 super(cache); 386 super(cache);
380 } 387 }
......
1 +package org.onlab.onos.store.device.impl;
2 +
3 +import org.apache.felix.scr.annotations.Component;
4 +import org.apache.felix.scr.annotations.Service;
5 +import org.onlab.onos.cluster.MastershipTerm;
6 +import org.onlab.onos.net.DeviceId;
7 +import org.onlab.onos.store.ClockService;
8 +import org.onlab.onos.store.Timestamp;
9 +
10 +// FIXME: Code clone in onos-core-trivial, onos-core-hz-net
11 +/**
12 + * Dummy implementation of {@link ClockService}.
13 + */
14 +@Component(immediate = true)
15 +@Service
16 +public class NoOpClockService implements ClockService {
17 +
18 + @Override
19 + public Timestamp getTimestamp(DeviceId deviceId) {
20 + return new Timestamp() {
21 +
22 + @Override
23 + public int compareTo(Timestamp o) {
24 + throw new IllegalStateException("Never expected to be used.");
25 + }
26 + };
27 + }
28 +
29 + @Override
30 + public void setMastershipTerm(DeviceId deviceId, MastershipTerm term) {
31 + }
32 +}
1 +package org.onlab.onos.store.flow.impl;
2 +
3 +import static org.onlab.onos.net.flow.FlowRuleEvent.Type.RULE_ADDED;
4 +import static org.onlab.onos.net.flow.FlowRuleEvent.Type.RULE_REMOVED;
5 +import static org.slf4j.LoggerFactory.getLogger;
6 +
7 +import java.util.Collection;
8 +import java.util.Collections;
9 +
10 +import org.apache.felix.scr.annotations.Activate;
11 +import org.apache.felix.scr.annotations.Component;
12 +import org.apache.felix.scr.annotations.Deactivate;
13 +import org.apache.felix.scr.annotations.Service;
14 +import org.onlab.onos.ApplicationId;
15 +import org.onlab.onos.net.DeviceId;
16 +import org.onlab.onos.net.flow.DefaultFlowRule;
17 +import org.onlab.onos.net.flow.FlowRule;
18 +import org.onlab.onos.net.flow.FlowRule.FlowRuleState;
19 +import org.onlab.onos.net.flow.FlowRuleEvent;
20 +import org.onlab.onos.net.flow.FlowRuleEvent.Type;
21 +import org.onlab.onos.net.flow.FlowRuleStore;
22 +import org.onlab.onos.net.flow.FlowRuleStoreDelegate;
23 +import org.onlab.onos.store.AbstractStore;
24 +import org.slf4j.Logger;
25 +
26 +import com.google.common.collect.ArrayListMultimap;
27 +import com.google.common.collect.ImmutableSet;
28 +import com.google.common.collect.Multimap;
29 +
30 +/**
31 + * Manages inventory of flow rules using trivial in-memory implementation.
32 + */
33 +//FIXME: I LIE I AM NOT DISTRIBUTED
34 +@Component(immediate = true)
35 +@Service
36 +public class DistributedFlowRuleStore
37 +extends AbstractStore<FlowRuleEvent, FlowRuleStoreDelegate>
38 +implements FlowRuleStore {
39 +
40 + private final Logger log = getLogger(getClass());
41 +
42 + // store entries as a pile of rules, no info about device tables
43 + private final Multimap<DeviceId, FlowRule> flowEntries =
44 + ArrayListMultimap.<DeviceId, FlowRule>create();
45 +
46 + private final Multimap<ApplicationId, FlowRule> flowEntriesById =
47 + ArrayListMultimap.<ApplicationId, FlowRule>create();
48 +
49 + @Activate
50 + public void activate() {
51 + log.info("Started");
52 + }
53 +
54 + @Deactivate
55 + public void deactivate() {
56 + log.info("Stopped");
57 + }
58 +
59 +
60 + @Override
61 + public synchronized FlowRule getFlowRule(FlowRule rule) {
62 + for (FlowRule f : flowEntries.get(rule.deviceId())) {
63 + if (f.equals(rule)) {
64 + return f;
65 + }
66 + }
67 + return null;
68 + }
69 +
70 + @Override
71 + public synchronized Iterable<FlowRule> getFlowEntries(DeviceId deviceId) {
72 + Collection<FlowRule> rules = flowEntries.get(deviceId);
73 + if (rules == null) {
74 + return Collections.emptyList();
75 + }
76 + return ImmutableSet.copyOf(rules);
77 + }
78 +
79 + @Override
80 + public synchronized Iterable<FlowRule> getFlowEntriesByAppId(ApplicationId appId) {
81 + Collection<FlowRule> rules = flowEntriesById.get(appId);
82 + if (rules == null) {
83 + return Collections.emptyList();
84 + }
85 + return ImmutableSet.copyOf(rules);
86 + }
87 +
88 + @Override
89 + public synchronized void storeFlowRule(FlowRule rule) {
90 + FlowRule f = new DefaultFlowRule(rule, FlowRuleState.PENDING_ADD);
91 + DeviceId did = f.deviceId();
92 + if (!flowEntries.containsEntry(did, f)) {
93 + flowEntries.put(did, f);
94 + flowEntriesById.put(rule.appId(), f);
95 + }
96 + }
97 +
98 + @Override
99 + public synchronized void deleteFlowRule(FlowRule rule) {
100 + FlowRule f = new DefaultFlowRule(rule, FlowRuleState.PENDING_REMOVE);
101 + DeviceId did = f.deviceId();
102 +
103 + /*
104 + * find the rule and mark it for deletion.
105 + * Ultimately a flow removed will come remove it.
106 + */
107 +
108 + if (flowEntries.containsEntry(did, f)) {
109 + //synchronized (flowEntries) {
110 + flowEntries.remove(did, f);
111 + flowEntries.put(did, f);
112 + flowEntriesById.remove(rule.appId(), rule);
113 + //}
114 + }
115 + }
116 +
117 + @Override
118 + public synchronized FlowRuleEvent addOrUpdateFlowRule(FlowRule rule) {
119 + DeviceId did = rule.deviceId();
120 +
121 + // check if this new rule is an update to an existing entry
122 + if (flowEntries.containsEntry(did, rule)) {
123 + //synchronized (flowEntries) {
124 + // Multimaps support duplicates so we have to remove our rule
125 + // and replace it with the current version.
126 + flowEntries.remove(did, rule);
127 + flowEntries.put(did, rule);
128 + //}
129 + return new FlowRuleEvent(Type.RULE_UPDATED, rule);
130 + }
131 +
132 + flowEntries.put(did, rule);
133 + return new FlowRuleEvent(RULE_ADDED, rule);
134 + }
135 +
136 + @Override
137 + public synchronized FlowRuleEvent removeFlowRule(FlowRule rule) {
138 + //synchronized (this) {
139 + if (flowEntries.remove(rule.deviceId(), rule)) {
140 + return new FlowRuleEvent(RULE_REMOVED, rule);
141 + } else {
142 + return null;
143 + }
144 + //}
145 + }
146 +
147 +
148 +
149 +
150 +
151 +
152 +
153 +}
1 +package org.onlab.onos.store.host.impl;
2 +
3 +import static org.onlab.onos.net.host.HostEvent.Type.HOST_ADDED;
4 +import static org.onlab.onos.net.host.HostEvent.Type.HOST_MOVED;
5 +import static org.onlab.onos.net.host.HostEvent.Type.HOST_REMOVED;
6 +import static org.onlab.onos.net.host.HostEvent.Type.HOST_UPDATED;
7 +import static org.slf4j.LoggerFactory.getLogger;
8 +
9 +import java.util.Collections;
10 +import java.util.HashSet;
11 +import java.util.Map;
12 +import java.util.Set;
13 +import java.util.concurrent.ConcurrentHashMap;
14 +
15 +import org.apache.felix.scr.annotations.Activate;
16 +import org.apache.felix.scr.annotations.Component;
17 +import org.apache.felix.scr.annotations.Deactivate;
18 +import org.apache.felix.scr.annotations.Service;
19 +import org.onlab.onos.net.ConnectPoint;
20 +import org.onlab.onos.net.DefaultHost;
21 +import org.onlab.onos.net.DeviceId;
22 +import org.onlab.onos.net.Host;
23 +import org.onlab.onos.net.HostId;
24 +import org.onlab.onos.net.host.HostDescription;
25 +import org.onlab.onos.net.host.HostEvent;
26 +import org.onlab.onos.net.host.HostStore;
27 +import org.onlab.onos.net.host.HostStoreDelegate;
28 +import org.onlab.onos.net.host.PortAddresses;
29 +import org.onlab.onos.net.provider.ProviderId;
30 +import org.onlab.onos.store.AbstractStore;
31 +import org.onlab.packet.IpPrefix;
32 +import org.onlab.packet.MacAddress;
33 +import org.onlab.packet.VlanId;
34 +import org.slf4j.Logger;
35 +
36 +import com.google.common.collect.HashMultimap;
37 +import com.google.common.collect.ImmutableSet;
38 +import com.google.common.collect.Multimap;
39 +import com.google.common.collect.Sets;
40 +
41 +/**
42 + * Manages inventory of end-station hosts using trivial in-memory
43 + * implementation.
44 + */
45 +//FIXME: I LIE I AM NOT DISTRIBUTED
46 +@Component(immediate = true)
47 +@Service
48 +public class DistributedHostStore
49 +extends AbstractStore<HostEvent, HostStoreDelegate>
50 +implements HostStore {
51 +
52 + private final Logger log = getLogger(getClass());
53 +
54 + // Host inventory
55 + private final Map<HostId, Host> hosts = new ConcurrentHashMap<>();
56 +
57 + // Hosts tracked by their location
58 + private final Multimap<ConnectPoint, Host> locations = HashMultimap.create();
59 +
60 + private final Map<ConnectPoint, PortAddresses> portAddresses =
61 + new ConcurrentHashMap<>();
62 +
63 + @Activate
64 + public void activate() {
65 + log.info("Started");
66 + }
67 +
68 + @Deactivate
69 + public void deactivate() {
70 + log.info("Stopped");
71 + }
72 +
73 + @Override
74 + public HostEvent createOrUpdateHost(ProviderId providerId, HostId hostId,
75 + HostDescription hostDescription) {
76 + Host host = hosts.get(hostId);
77 + if (host == null) {
78 + return createHost(providerId, hostId, hostDescription);
79 + }
80 + return updateHost(providerId, host, hostDescription);
81 + }
82 +
83 + // creates a new host and sends HOST_ADDED
84 + private HostEvent createHost(ProviderId providerId, HostId hostId,
85 + HostDescription descr) {
86 + DefaultHost newhost = new DefaultHost(providerId, hostId,
87 + descr.hwAddress(),
88 + descr.vlan(),
89 + descr.location(),
90 + descr.ipAddresses());
91 + synchronized (this) {
92 + hosts.put(hostId, newhost);
93 + locations.put(descr.location(), newhost);
94 + }
95 + return new HostEvent(HOST_ADDED, newhost);
96 + }
97 +
98 + // checks for type of update to host, sends appropriate event
99 + private HostEvent updateHost(ProviderId providerId, Host host,
100 + HostDescription descr) {
101 + DefaultHost updated;
102 + HostEvent event;
103 + if (!host.location().equals(descr.location())) {
104 + updated = new DefaultHost(providerId, host.id(),
105 + host.mac(),
106 + host.vlan(),
107 + descr.location(),
108 + host.ipAddresses());
109 + event = new HostEvent(HOST_MOVED, updated);
110 +
111 + } else if (!(host.ipAddresses().equals(descr.ipAddresses()))) {
112 + updated = new DefaultHost(providerId, host.id(),
113 + host.mac(),
114 + host.vlan(),
115 + descr.location(),
116 + descr.ipAddresses());
117 + event = new HostEvent(HOST_UPDATED, updated);
118 + } else {
119 + return null;
120 + }
121 + synchronized (this) {
122 + hosts.put(host.id(), updated);
123 + locations.remove(host.location(), host);
124 + locations.put(updated.location(), updated);
125 + }
126 + return event;
127 + }
128 +
129 + @Override
130 + public HostEvent removeHost(HostId hostId) {
131 + synchronized (this) {
132 + Host host = hosts.remove(hostId);
133 + if (host != null) {
134 + locations.remove((host.location()), host);
135 + return new HostEvent(HOST_REMOVED, host);
136 + }
137 + return null;
138 + }
139 + }
140 +
141 + @Override
142 + public int getHostCount() {
143 + return hosts.size();
144 + }
145 +
146 + @Override
147 + public Iterable<Host> getHosts() {
148 + return Collections.unmodifiableSet(new HashSet<>(hosts.values()));
149 + }
150 +
151 + @Override
152 + public Host getHost(HostId hostId) {
153 + return hosts.get(hostId);
154 + }
155 +
156 + @Override
157 + public Set<Host> getHosts(VlanId vlanId) {
158 + Set<Host> vlanset = new HashSet<>();
159 + for (Host h : hosts.values()) {
160 + if (h.vlan().equals(vlanId)) {
161 + vlanset.add(h);
162 + }
163 + }
164 + return vlanset;
165 + }
166 +
167 + @Override
168 + public Set<Host> getHosts(MacAddress mac) {
169 + Set<Host> macset = new HashSet<>();
170 + for (Host h : hosts.values()) {
171 + if (h.mac().equals(mac)) {
172 + macset.add(h);
173 + }
174 + }
175 + return macset;
176 + }
177 +
178 + @Override
179 + public Set<Host> getHosts(IpPrefix ip) {
180 + Set<Host> ipset = new HashSet<>();
181 + for (Host h : hosts.values()) {
182 + if (h.ipAddresses().contains(ip)) {
183 + ipset.add(h);
184 + }
185 + }
186 + return ipset;
187 + }
188 +
189 + @Override
190 + public Set<Host> getConnectedHosts(ConnectPoint connectPoint) {
191 + return ImmutableSet.copyOf(locations.get(connectPoint));
192 + }
193 +
194 + @Override
195 + public Set<Host> getConnectedHosts(DeviceId deviceId) {
196 + Set<Host> hostset = new HashSet<>();
197 + for (ConnectPoint p : locations.keySet()) {
198 + if (p.deviceId().equals(deviceId)) {
199 + hostset.addAll(locations.get(p));
200 + }
201 + }
202 + return hostset;
203 + }
204 +
205 + @Override
206 + public void updateAddressBindings(PortAddresses addresses) {
207 + synchronized (portAddresses) {
208 + PortAddresses existing = portAddresses.get(addresses.connectPoint());
209 + if (existing == null) {
210 + portAddresses.put(addresses.connectPoint(), addresses);
211 + } else {
212 + Set<IpPrefix> union = Sets.union(existing.ips(), addresses.ips())
213 + .immutableCopy();
214 +
215 + MacAddress newMac = (addresses.mac() == null) ? existing.mac()
216 + : addresses.mac();
217 +
218 + PortAddresses newAddresses =
219 + new PortAddresses(addresses.connectPoint(), union, newMac);
220 +
221 + portAddresses.put(newAddresses.connectPoint(), newAddresses);
222 + }
223 + }
224 + }
225 +
226 + @Override
227 + public void removeAddressBindings(PortAddresses addresses) {
228 + synchronized (portAddresses) {
229 + PortAddresses existing = portAddresses.get(addresses.connectPoint());
230 + if (existing != null) {
231 + Set<IpPrefix> difference =
232 + Sets.difference(existing.ips(), addresses.ips()).immutableCopy();
233 +
234 + // If they removed the existing mac, set the new mac to null.
235 + // Otherwise, keep the existing mac.
236 + MacAddress newMac = existing.mac();
237 + if (addresses.mac() != null && addresses.mac().equals(existing.mac())) {
238 + newMac = null;
239 + }
240 +
241 + PortAddresses newAddresses =
242 + new PortAddresses(addresses.connectPoint(), difference, newMac);
243 +
244 + portAddresses.put(newAddresses.connectPoint(), newAddresses);
245 + }
246 + }
247 + }
248 +
249 + @Override
250 + public void clearAddressBindings(ConnectPoint connectPoint) {
251 + synchronized (portAddresses) {
252 + portAddresses.remove(connectPoint);
253 + }
254 + }
255 +
256 + @Override
257 + public Set<PortAddresses> getAddressBindings() {
258 + synchronized (portAddresses) {
259 + return new HashSet<>(portAddresses.values());
260 + }
261 + }
262 +
263 + @Override
264 + public PortAddresses getAddressBindingsForPort(ConnectPoint connectPoint) {
265 + PortAddresses addresses;
266 +
267 + synchronized (portAddresses) {
268 + addresses = portAddresses.get(connectPoint);
269 + }
270 +
271 + if (addresses == null) {
272 + addresses = new PortAddresses(connectPoint, null, null);
273 + }
274 +
275 + return addresses;
276 + }
277 +
278 +}
...@@ -10,6 +10,7 @@ import static org.slf4j.LoggerFactory.getLogger; ...@@ -10,6 +10,7 @@ import static org.slf4j.LoggerFactory.getLogger;
10 10
11 import java.util.HashSet; 11 import java.util.HashSet;
12 import java.util.Set; 12 import java.util.Set;
13 +
13 import org.apache.felix.scr.annotations.Activate; 14 import org.apache.felix.scr.annotations.Activate;
14 import org.apache.felix.scr.annotations.Component; 15 import org.apache.felix.scr.annotations.Component;
15 import org.apache.felix.scr.annotations.Deactivate; 16 import org.apache.felix.scr.annotations.Deactivate;
...@@ -24,9 +25,9 @@ import org.onlab.onos.net.link.LinkEvent; ...@@ -24,9 +25,9 @@ import org.onlab.onos.net.link.LinkEvent;
24 import org.onlab.onos.net.link.LinkStore; 25 import org.onlab.onos.net.link.LinkStore;
25 import org.onlab.onos.net.link.LinkStoreDelegate; 26 import org.onlab.onos.net.link.LinkStoreDelegate;
26 import org.onlab.onos.net.provider.ProviderId; 27 import org.onlab.onos.net.provider.ProviderId;
27 -import org.onlab.onos.store.impl.AbsentInvalidatingLoadingCache; 28 +import org.onlab.onos.store.common.AbsentInvalidatingLoadingCache;
28 -import org.onlab.onos.store.impl.AbstractDistributedStore; 29 +import org.onlab.onos.store.common.AbstractHazelcastStore;
29 -import org.onlab.onos.store.impl.OptionalCacheLoader; 30 +import org.onlab.onos.store.common.OptionalCacheLoader;
30 import org.slf4j.Logger; 31 import org.slf4j.Logger;
31 32
32 import com.google.common.base.Optional; 33 import com.google.common.base.Optional;
...@@ -43,7 +44,7 @@ import com.hazelcast.core.IMap; ...@@ -43,7 +44,7 @@ import com.hazelcast.core.IMap;
43 @Component(immediate = true) 44 @Component(immediate = true)
44 @Service 45 @Service
45 public class DistributedLinkStore 46 public class DistributedLinkStore
46 - extends AbstractDistributedStore<LinkEvent, LinkStoreDelegate> 47 + extends AbstractHazelcastStore<LinkEvent, LinkStoreDelegate>
47 implements LinkStore { 48 implements LinkStore {
48 49
49 private final Logger log = getLogger(getClass()); 50 private final Logger log = getLogger(getClass());
...@@ -57,6 +58,8 @@ public class DistributedLinkStore ...@@ -57,6 +58,8 @@ public class DistributedLinkStore
57 private final Multimap<DeviceId, Link> srcLinks = HashMultimap.create(); 58 private final Multimap<DeviceId, Link> srcLinks = HashMultimap.create();
58 private final Multimap<DeviceId, Link> dstLinks = HashMultimap.create(); 59 private final Multimap<DeviceId, Link> dstLinks = HashMultimap.create();
59 60
61 + private String linksListener;
62 +
60 @Override 63 @Override
61 @Activate 64 @Activate
62 public void activate() { 65 public void activate() {
...@@ -70,7 +73,7 @@ public class DistributedLinkStore ...@@ -70,7 +73,7 @@ public class DistributedLinkStore
70 = new OptionalCacheLoader<>(storeService, rawLinks); 73 = new OptionalCacheLoader<>(storeService, rawLinks);
71 links = new AbsentInvalidatingLoadingCache<>(newBuilder().build(linkLoader)); 74 links = new AbsentInvalidatingLoadingCache<>(newBuilder().build(linkLoader));
72 // refresh/populate cache based on notification from other instance 75 // refresh/populate cache based on notification from other instance
73 - rawLinks.addEntryListener(new RemoteLinkEventHandler(links), includeValue); 76 + linksListener = rawLinks.addEntryListener(new RemoteLinkEventHandler(links), includeValue);
74 77
75 loadLinkCache(); 78 loadLinkCache();
76 79
...@@ -79,7 +82,7 @@ public class DistributedLinkStore ...@@ -79,7 +82,7 @@ public class DistributedLinkStore
79 82
80 @Deactivate 83 @Deactivate
81 public void deactivate() { 84 public void deactivate() {
82 - super.activate(); 85 + rawLinks.removeEntryListener(linksListener);
83 log.info("Stopped"); 86 log.info("Stopped");
84 } 87 }
85 88
...@@ -232,7 +235,7 @@ public class DistributedLinkStore ...@@ -232,7 +235,7 @@ public class DistributedLinkStore
232 } 235 }
233 } 236 }
234 237
235 - private class RemoteLinkEventHandler extends RemoteEventHandler<LinkKey, DefaultLink> { 238 + private class RemoteLinkEventHandler extends RemoteCacheEventHandler<LinkKey, DefaultLink> {
236 public RemoteLinkEventHandler(LoadingCache<LinkKey, Optional<DefaultLink>> cache) { 239 public RemoteLinkEventHandler(LoadingCache<LinkKey, Optional<DefaultLink>> cache) {
237 super(cache); 240 super(cache);
238 } 241 }
......
1 +package org.onlab.onos.store.topology.impl;
2 +
3 +import org.onlab.graph.AdjacencyListsGraph;
4 +import org.onlab.onos.net.topology.TopologyEdge;
5 +import org.onlab.onos.net.topology.TopologyGraph;
6 +import org.onlab.onos.net.topology.TopologyVertex;
7 +
8 +import java.util.Set;
9 +
10 +/**
11 + * Default implementation of an immutable topology graph based on a generic
12 + * implementation of adjacency lists graph.
13 + */
14 +public class DefaultTopologyGraph
15 + extends AdjacencyListsGraph<TopologyVertex, TopologyEdge>
16 + implements TopologyGraph {
17 +
18 + /**
19 + * Creates a topology graph comprising of the specified vertexes and edges.
20 + *
21 + * @param vertexes set of graph vertexes
22 + * @param edges set of graph edges
23 + */
24 + public DefaultTopologyGraph(Set<TopologyVertex> vertexes, Set<TopologyEdge> edges) {
25 + super(vertexes, edges);
26 + }
27 +
28 +}
1 +package org.onlab.onos.store.topology.impl;
2 +
3 +import static org.slf4j.LoggerFactory.getLogger;
4 +
5 +import java.util.List;
6 +import java.util.Set;
7 +
8 +import org.apache.felix.scr.annotations.Activate;
9 +import org.apache.felix.scr.annotations.Component;
10 +import org.apache.felix.scr.annotations.Deactivate;
11 +import org.apache.felix.scr.annotations.Service;
12 +import org.onlab.onos.event.Event;
13 +import org.onlab.onos.net.ConnectPoint;
14 +import org.onlab.onos.net.DeviceId;
15 +import org.onlab.onos.net.Link;
16 +import org.onlab.onos.net.Path;
17 +import org.onlab.onos.net.provider.ProviderId;
18 +import org.onlab.onos.net.topology.ClusterId;
19 +import org.onlab.onos.net.topology.GraphDescription;
20 +import org.onlab.onos.net.topology.LinkWeight;
21 +import org.onlab.onos.net.topology.Topology;
22 +import org.onlab.onos.net.topology.TopologyCluster;
23 +import org.onlab.onos.net.topology.TopologyEvent;
24 +import org.onlab.onos.net.topology.TopologyGraph;
25 +import org.onlab.onos.net.topology.TopologyStore;
26 +import org.onlab.onos.net.topology.TopologyStoreDelegate;
27 +import org.onlab.onos.store.AbstractStore;
28 +import org.slf4j.Logger;
29 +
30 +/**
31 + * Manages inventory of topology snapshots using trivial in-memory
32 + * structures implementation.
33 + */
34 +//FIXME: I LIE I AM NOT DISTRIBUTED
35 +@Component(immediate = true)
36 +@Service
37 +public class DistributedTopologyStore
38 +extends AbstractStore<TopologyEvent, TopologyStoreDelegate>
39 +implements TopologyStore {
40 +
41 + private final Logger log = getLogger(getClass());
42 +
43 + private volatile DefaultTopology current;
44 +
45 + @Activate
46 + public void activate() {
47 + log.info("Started");
48 + }
49 +
50 + @Deactivate
51 + public void deactivate() {
52 + log.info("Stopped");
53 + }
54 + @Override
55 + public Topology currentTopology() {
56 + return current;
57 + }
58 +
59 + @Override
60 + public boolean isLatest(Topology topology) {
61 + // Topology is current only if it is the same as our current topology
62 + return topology == current;
63 + }
64 +
65 + @Override
66 + public TopologyGraph getGraph(Topology topology) {
67 + return defaultTopology(topology).getGraph();
68 + }
69 +
70 + @Override
71 + public Set<TopologyCluster> getClusters(Topology topology) {
72 + return defaultTopology(topology).getClusters();
73 + }
74 +
75 + @Override
76 + public TopologyCluster getCluster(Topology topology, ClusterId clusterId) {
77 + return defaultTopology(topology).getCluster(clusterId);
78 + }
79 +
80 + @Override
81 + public Set<DeviceId> getClusterDevices(Topology topology, TopologyCluster cluster) {
82 + return defaultTopology(topology).getClusterDevices(cluster);
83 + }
84 +
85 + @Override
86 + public Set<Link> getClusterLinks(Topology topology, TopologyCluster cluster) {
87 + return defaultTopology(topology).getClusterLinks(cluster);
88 + }
89 +
90 + @Override
91 + public Set<Path> getPaths(Topology topology, DeviceId src, DeviceId dst) {
92 + return defaultTopology(topology).getPaths(src, dst);
93 + }
94 +
95 + @Override
96 + public Set<Path> getPaths(Topology topology, DeviceId src, DeviceId dst,
97 + LinkWeight weight) {
98 + return defaultTopology(topology).getPaths(src, dst, weight);
99 + }
100 +
101 + @Override
102 + public boolean isInfrastructure(Topology topology, ConnectPoint connectPoint) {
103 + return defaultTopology(topology).isInfrastructure(connectPoint);
104 + }
105 +
106 + @Override
107 + public boolean isBroadcastPoint(Topology topology, ConnectPoint connectPoint) {
108 + return defaultTopology(topology).isBroadcastPoint(connectPoint);
109 + }
110 +
111 + @Override
112 + public TopologyEvent updateTopology(ProviderId providerId,
113 + GraphDescription graphDescription,
114 + List<Event> reasons) {
115 + // First off, make sure that what we're given is indeed newer than
116 + // what we already have.
117 + if (current != null && graphDescription.timestamp() < current.time()) {
118 + return null;
119 + }
120 +
121 + // Have the default topology construct self from the description data.
122 + DefaultTopology newTopology =
123 + new DefaultTopology(providerId, graphDescription);
124 +
125 + // Promote the new topology to current and return a ready-to-send event.
126 + synchronized (this) {
127 + current = newTopology;
128 + return new TopologyEvent(TopologyEvent.Type.TOPOLOGY_CHANGED, current);
129 + }
130 + }
131 +
132 + // Validates the specified topology and returns it as a default
133 + private DefaultTopology defaultTopology(Topology topology) {
134 + if (topology instanceof DefaultTopology) {
135 + return (DefaultTopology) topology;
136 + }
137 + throw new IllegalArgumentException("Topology class " + topology.getClass() +
138 + " not supported");
139 + }
140 +
141 +}
1 +package org.onlab.onos.store.topology.impl;
2 +
3 +import org.onlab.onos.net.DeviceId;
4 +
5 +import java.util.Objects;
6 +
7 +/**
8 + * Key for filing pre-computed paths between source and destination devices.
9 + */
10 +class PathKey {
11 + private final DeviceId src;
12 + private final DeviceId dst;
13 +
14 + /**
15 + * Creates a path key from the given source/dest pair.
16 + * @param src source device
17 + * @param dst destination device
18 + */
19 + PathKey(DeviceId src, DeviceId dst) {
20 + this.src = src;
21 + this.dst = dst;
22 + }
23 +
24 + @Override
25 + public int hashCode() {
26 + return Objects.hash(src, dst);
27 + }
28 +
29 + @Override
30 + public boolean equals(Object obj) {
31 + if (this == obj) {
32 + return true;
33 + }
34 + if (obj instanceof PathKey) {
35 + final PathKey other = (PathKey) obj;
36 + return Objects.equals(this.src, other.src) && Objects.equals(this.dst, other.dst);
37 + }
38 + return false;
39 + }
40 +}
...@@ -20,6 +20,7 @@ import org.junit.After; ...@@ -20,6 +20,7 @@ import org.junit.After;
20 import org.junit.AfterClass; 20 import org.junit.AfterClass;
21 import org.junit.Before; 21 import org.junit.Before;
22 import org.junit.BeforeClass; 22 import org.junit.BeforeClass;
23 +import org.junit.Ignore;
23 import org.junit.Test; 24 import org.junit.Test;
24 import org.onlab.onos.net.Device; 25 import org.onlab.onos.net.Device;
25 import org.onlab.onos.net.DeviceId; 26 import org.onlab.onos.net.DeviceId;
...@@ -32,15 +33,18 @@ import org.onlab.onos.net.device.DeviceEvent; ...@@ -32,15 +33,18 @@ import org.onlab.onos.net.device.DeviceEvent;
32 import org.onlab.onos.net.device.DeviceStoreDelegate; 33 import org.onlab.onos.net.device.DeviceStoreDelegate;
33 import org.onlab.onos.net.device.PortDescription; 34 import org.onlab.onos.net.device.PortDescription;
34 import org.onlab.onos.net.provider.ProviderId; 35 import org.onlab.onos.net.provider.ProviderId;
36 +import org.onlab.onos.store.common.StoreManager;
35 import org.onlab.onos.store.common.StoreService; 37 import org.onlab.onos.store.common.StoreService;
36 -import org.onlab.onos.store.impl.StoreManager; 38 +import org.onlab.onos.store.common.TestStoreManager;
37 -import org.onlab.onos.store.impl.TestStoreManager;
38 39
39 import com.google.common.collect.Iterables; 40 import com.google.common.collect.Iterables;
40 import com.google.common.collect.Sets; 41 import com.google.common.collect.Sets;
41 import com.hazelcast.config.Config; 42 import com.hazelcast.config.Config;
42 import com.hazelcast.core.Hazelcast; 43 import com.hazelcast.core.Hazelcast;
43 44
45 +/**
46 + * Test of the Hazelcast based distributed DeviceStore implementation.
47 + */
44 public class DistributedDeviceStoreTest { 48 public class DistributedDeviceStoreTest {
45 49
46 private static final ProviderId PID = new ProviderId("of", "foo"); 50 private static final ProviderId PID = new ProviderId("of", "foo");
...@@ -326,6 +330,7 @@ public class DistributedDeviceStoreTest { ...@@ -326,6 +330,7 @@ public class DistributedDeviceStoreTest {
326 } 330 }
327 331
328 // TODO add test for Port events when we have them 332 // TODO add test for Port events when we have them
333 + @Ignore("Ignore until Delegate spec. is clear.")
329 @Test 334 @Test
330 public final void testEvents() throws InterruptedException { 335 public final void testEvents() throws InterruptedException {
331 final CountDownLatch addLatch = new CountDownLatch(1); 336 final CountDownLatch addLatch = new CountDownLatch(1);
......
...@@ -15,6 +15,7 @@ import org.junit.After; ...@@ -15,6 +15,7 @@ import org.junit.After;
15 import org.junit.AfterClass; 15 import org.junit.AfterClass;
16 import org.junit.Before; 16 import org.junit.Before;
17 import org.junit.BeforeClass; 17 import org.junit.BeforeClass;
18 +import org.junit.Ignore;
18 import org.junit.Test; 19 import org.junit.Test;
19 import org.onlab.onos.net.ConnectPoint; 20 import org.onlab.onos.net.ConnectPoint;
20 import org.onlab.onos.net.DeviceId; 21 import org.onlab.onos.net.DeviceId;
...@@ -26,24 +27,22 @@ import org.onlab.onos.net.link.DefaultLinkDescription; ...@@ -26,24 +27,22 @@ import org.onlab.onos.net.link.DefaultLinkDescription;
26 import org.onlab.onos.net.link.LinkEvent; 27 import org.onlab.onos.net.link.LinkEvent;
27 import org.onlab.onos.net.link.LinkStoreDelegate; 28 import org.onlab.onos.net.link.LinkStoreDelegate;
28 import org.onlab.onos.net.provider.ProviderId; 29 import org.onlab.onos.net.provider.ProviderId;
30 +import org.onlab.onos.store.common.StoreManager;
29 import org.onlab.onos.store.common.StoreService; 31 import org.onlab.onos.store.common.StoreService;
30 -import org.onlab.onos.store.impl.StoreManager; 32 +import org.onlab.onos.store.common.TestStoreManager;
31 -import org.onlab.onos.store.impl.TestStoreManager;
32 33
33 import com.google.common.collect.Iterables; 34 import com.google.common.collect.Iterables;
34 import com.hazelcast.config.Config; 35 import com.hazelcast.config.Config;
35 import com.hazelcast.core.Hazelcast; 36 import com.hazelcast.core.Hazelcast;
36 37
38 +/**
39 + * Test of the Hazelcast based distributed LinkStore implementation.
40 + */
37 public class DistributedLinkStoreTest { 41 public class DistributedLinkStoreTest {
38 42
39 private static final ProviderId PID = new ProviderId("of", "foo"); 43 private static final ProviderId PID = new ProviderId("of", "foo");
40 private static final DeviceId DID1 = deviceId("of:foo"); 44 private static final DeviceId DID1 = deviceId("of:foo");
41 private static final DeviceId DID2 = deviceId("of:bar"); 45 private static final DeviceId DID2 = deviceId("of:bar");
42 -// private static final String MFR = "whitebox";
43 -// private static final String HW = "1.1.x";
44 -// private static final String SW1 = "3.8.1";
45 -// private static final String SW2 = "3.9.5";
46 -// private static final String SN = "43311-12345";
47 46
48 private static final PortNumber P1 = PortNumber.portNumber(1); 47 private static final PortNumber P1 = PortNumber.portNumber(1);
49 private static final PortNumber P2 = PortNumber.portNumber(2); 48 private static final PortNumber P2 = PortNumber.portNumber(2);
...@@ -302,6 +301,7 @@ public class DistributedLinkStoreTest { ...@@ -302,6 +301,7 @@ public class DistributedLinkStoreTest {
302 assertLink(linkId2, DIRECT, linkStore.getLink(d2P2, d1P1)); 301 assertLink(linkId2, DIRECT, linkStore.getLink(d2P2, d1P1));
303 } 302 }
304 303
304 + @Ignore("Ignore until Delegate spec. is clear.")
305 @Test 305 @Test
306 public final void testEvents() throws InterruptedException { 306 public final void testEvents() throws InterruptedException {
307 307
......
1 +<?xml version="1.0" encoding="UTF-8"?>
2 +<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
3 + <modelVersion>4.0.0</modelVersion>
4 +
5 + <parent>
6 + <groupId>org.onlab.onos</groupId>
7 + <artifactId>onos-core-store</artifactId>
8 + <version>1.0.0-SNAPSHOT</version>
9 + <relativePath>../pom.xml</relativePath>
10 + </parent>
11 +
12 + <artifactId>onos-core-hz</artifactId>
13 + <packaging>pom</packaging>
14 +
15 + <description>ONOS Core Hazelcast Store subsystem</description>
16 +
17 + <modules>
18 + <module>common</module>
19 + <module>cluster</module>
20 + <module>net</module>
21 + </modules>
22 +
23 + <dependencies>
24 + <dependency>
25 + <groupId>com.google.guava</groupId>
26 + <artifactId>guava</artifactId>
27 + </dependency>
28 + <dependency>
29 + <groupId>org.onlab.onos</groupId>
30 + <artifactId>onlab-misc</artifactId>
31 + </dependency>
32 + <dependency>
33 + <groupId>org.onlab.onos</groupId>
34 + <artifactId>onlab-junit</artifactId>
35 + </dependency>
36 + <dependency>
37 + <groupId>com.hazelcast</groupId>
38 + <artifactId>hazelcast</artifactId>
39 + </dependency>
40 + </dependencies>
41 +
42 + <build>
43 + <plugins>
44 + <plugin>
45 + <groupId>org.apache.felix</groupId>
46 + <artifactId>maven-bundle-plugin</artifactId>
47 + </plugin>
48 + </plugins>
49 + </build>
50 +
51 +</project>
1 <?xml version="1.0" encoding="UTF-8"?> 1 <?xml version="1.0" encoding="UTF-8"?>
2 -<project xmlns="http://maven.apache.org/POM/4.0.0" 2 +<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
3 - xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
4 - xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
5 <modelVersion>4.0.0</modelVersion> 3 <modelVersion>4.0.0</modelVersion>
6 4
7 <parent> 5 <parent>
...@@ -12,34 +10,41 @@ ...@@ -12,34 +10,41 @@
12 </parent> 10 </parent>
13 11
14 <artifactId>onos-core-store</artifactId> 12 <artifactId>onos-core-store</artifactId>
15 - <packaging>bundle</packaging> 13 + <packaging>pom</packaging>
16 14
17 - <description>ONOS distributed store subsystems</description> 15 + <description>ONOS Core Store subsystem</description>
16 +
17 + <modules>
18 + <module>trivial</module>
19 + <module>dist</module>
20 + <module>hz</module>
21 + <module>serializers</module>
22 + </modules>
18 23
19 <dependencies> 24 <dependencies>
20 <dependency> 25 <dependency>
26 + <groupId>com.google.guava</groupId>
27 + <artifactId>guava</artifactId>
28 + </dependency>
29 + <dependency>
21 <groupId>org.onlab.onos</groupId> 30 <groupId>org.onlab.onos</groupId>
22 - <artifactId>onos-api</artifactId> 31 + <artifactId>onlab-misc</artifactId>
23 </dependency> 32 </dependency>
24 <dependency> 33 <dependency>
25 - <groupId>org.apache.felix</groupId> 34 + <groupId>org.onlab.onos</groupId>
26 - <artifactId>org.apache.felix.scr.annotations</artifactId> 35 + <artifactId>onlab-junit</artifactId>
27 </dependency> 36 </dependency>
28 <dependency> 37 <dependency>
29 <groupId>com.hazelcast</groupId> 38 <groupId>com.hazelcast</groupId>
30 <artifactId>hazelcast</artifactId> 39 <artifactId>hazelcast</artifactId>
31 </dependency> 40 </dependency>
32 - <dependency>
33 - <groupId>de.javakaffee</groupId>
34 - <artifactId>kryo-serializers</artifactId>
35 - </dependency>
36 </dependencies> 41 </dependencies>
37 42
38 <build> 43 <build>
39 <plugins> 44 <plugins>
40 <plugin> 45 <plugin>
41 <groupId>org.apache.felix</groupId> 46 <groupId>org.apache.felix</groupId>
42 - <artifactId>maven-scr-plugin</artifactId> 47 + <artifactId>maven-bundle-plugin</artifactId>
43 </plugin> 48 </plugin>
44 </plugins> 49 </plugins>
45 </build> 50 </build>
......
1 +<?xml version="1.0" encoding="UTF-8"?>
2 +<project xmlns="http://maven.apache.org/POM/4.0.0"
3 + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
4 + xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
5 + <modelVersion>4.0.0</modelVersion>
6 +
7 + <parent>
8 + <groupId>org.onlab.onos</groupId>
9 + <artifactId>onos-core-store</artifactId>
10 + <version>1.0.0-SNAPSHOT</version>
11 + <relativePath>../pom.xml</relativePath>
12 + </parent>
13 +
14 + <artifactId>onos-core-serializers</artifactId>
15 + <packaging>bundle</packaging>
16 +
17 + <description>Serializers for ONOS classes</description>
18 +
19 + <dependencies>
20 + <dependency>
21 + <groupId>org.onlab.onos</groupId>
22 + <artifactId>onos-api</artifactId>
23 + </dependency>
24 + <dependency>
25 + <groupId>org.apache.felix</groupId>
26 + <artifactId>org.apache.felix.scr.annotations</artifactId>
27 + </dependency>
28 + <dependency>
29 + <groupId>de.javakaffee</groupId>
30 + <artifactId>kryo-serializers</artifactId>
31 + </dependency>
32 + </dependencies>
33 +
34 + <build>
35 + <plugins>
36 + <plugin>
37 + <groupId>org.apache.felix</groupId>
38 + <artifactId>maven-scr-plugin</artifactId>
39 + </plugin>
40 + </plugins>
41 + </build>
42 +
43 +</project>
...@@ -6,7 +6,7 @@ ...@@ -6,7 +6,7 @@
6 6
7 <parent> 7 <parent>
8 <groupId>org.onlab.onos</groupId> 8 <groupId>org.onlab.onos</groupId>
9 - <artifactId>onos-core</artifactId> 9 + <artifactId>onos-core-store</artifactId>
10 <version>1.0.0-SNAPSHOT</version> 10 <version>1.0.0-SNAPSHOT</version>
11 <relativePath>../pom.xml</relativePath> 11 <relativePath>../pom.xml</relativePath>
12 </parent> 12 </parent>
......
1 +package org.onlab.onos.net.trivial.impl;
2 +
3 +import org.apache.felix.scr.annotations.Component;
4 +import org.apache.felix.scr.annotations.Service;
5 +import org.onlab.onos.cluster.MastershipTerm;
6 +import org.onlab.onos.net.DeviceId;
7 +import org.onlab.onos.store.ClockService;
8 +import org.onlab.onos.store.Timestamp;
9 +
10 +//FIXME: Code clone in onos-core-trivial, onos-core-hz-net
11 +/**
12 + * Dummy implementation of {@link ClockService}.
13 + */
14 +@Component(immediate = true)
15 +@Service
16 +public class NoOpClockService implements ClockService {
17 +
18 + @Override
19 + public Timestamp getTimestamp(DeviceId deviceId) {
20 + return new Timestamp() {
21 +
22 + @Override
23 + public int compareTo(Timestamp o) {
24 + throw new IllegalStateException("Never expected to be used.");
25 + }
26 + };
27 + }
28 +
29 + @Override
30 + public void setMastershipTerm(DeviceId deviceId, MastershipTerm term) {
31 + }
32 +}
...@@ -20,7 +20,7 @@ import java.util.Set; ...@@ -20,7 +20,7 @@ import java.util.Set;
20 import static org.slf4j.LoggerFactory.getLogger; 20 import static org.slf4j.LoggerFactory.getLogger;
21 21
22 /** 22 /**
23 - * Manages inventory of infrastructure DEVICES using trivial in-memory 23 + * Manages inventory of infrastructure devices using trivial in-memory
24 * structures implementation. 24 * structures implementation.
25 */ 25 */
26 @Component(immediate = true) 26 @Component(immediate = true)
...@@ -68,6 +68,11 @@ public class SimpleClusterStore ...@@ -68,6 +68,11 @@ public class SimpleClusterStore
68 } 68 }
69 69
70 @Override 70 @Override
71 + public ControllerNode addNode(NodeId nodeId, IpPrefix ip, int tcpPort) {
72 + return null;
73 + }
74 +
75 + @Override
71 public void removeNode(NodeId nodeId) { 76 public void removeNode(NodeId nodeId) {
72 } 77 }
73 78
......
...@@ -101,9 +101,6 @@ public class SimpleDeviceStore ...@@ -101,9 +101,6 @@ public class SimpleDeviceStore
101 synchronized (this) { 101 synchronized (this) {
102 devices.put(deviceId, device); 102 devices.put(deviceId, device);
103 availableDevices.add(deviceId); 103 availableDevices.add(deviceId);
104 -
105 - // For now claim the device as a master automatically.
106 - // roles.put(deviceId, MastershipRole.MASTER);
107 } 104 }
108 return new DeviceEvent(DeviceEvent.Type.DEVICE_ADDED, device, null); 105 return new DeviceEvent(DeviceEvent.Type.DEVICE_ADDED, device, null);
109 } 106 }
...@@ -189,7 +186,7 @@ public class SimpleDeviceStore ...@@ -189,7 +186,7 @@ public class SimpleDeviceStore
189 new DefaultPort(device, portDescription.portNumber(), 186 new DefaultPort(device, portDescription.portNumber(),
190 portDescription.isEnabled()); 187 portDescription.isEnabled());
191 ports.put(port.number(), updatedPort); 188 ports.put(port.number(), updatedPort);
192 - return new DeviceEvent(PORT_UPDATED, device, port); 189 + return new DeviceEvent(PORT_UPDATED, device, updatedPort);
193 } 190 }
194 return null; 191 return null;
195 } 192 }
......
...@@ -51,8 +51,6 @@ public class SimpleLinkStore ...@@ -51,8 +51,6 @@ public class SimpleLinkStore
51 private final Multimap<DeviceId, Link> srcLinks = HashMultimap.create(); 51 private final Multimap<DeviceId, Link> srcLinks = HashMultimap.create();
52 private final Multimap<DeviceId, Link> dstLinks = HashMultimap.create(); 52 private final Multimap<DeviceId, Link> dstLinks = HashMultimap.create();
53 53
54 - private static final Set<Link> EMPTY = ImmutableSet.of();
55 -
56 @Activate 54 @Activate
57 public void activate() { 55 public void activate() {
58 log.info("Started"); 56 log.info("Started");
......
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.