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
2902 additions
and
159 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 | +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 | } | ... | ... |
... | @@ -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 | +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 | +} |
... | @@ -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"; |
... | @@ -42,6 +43,8 @@ public class MastershipManager | ... | @@ -42,6 +43,8 @@ public class MastershipManager |
42 | protected final AbstractListenerRegistry<MastershipEvent, MastershipListener> | 43 | protected final AbstractListenerRegistry<MastershipEvent, MastershipListener> |
43 | listenerRegistry = new AbstractListenerRegistry<>(); | 44 | listenerRegistry = new AbstractListenerRegistry<>(); |
44 | 45 | ||
46 | + private final MastershipStoreDelegate delegate = new InternalDelegate(); | ||
47 | + | ||
45 | @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) | 48 | @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) |
46 | protected MastershipStore store; | 49 | protected MastershipStore store; |
47 | 50 | ||
... | @@ -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 | 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,14 +38,9 @@ import org.onlab.onos.net.device.DeviceStoreDelegate; | ... | @@ -31,14 +38,9 @@ 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 & NB APIs. | 45 | * Provides implementation of the device SB & NB APIs. |
44 | */ | 46 | */ |
... | @@ -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,7 +173,8 @@ public class DeviceManager | ... | @@ -168,7 +173,8 @@ 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 | ||
... | @@ -182,14 +188,16 @@ public class DeviceManager | ... | @@ -182,14 +188,16 @@ public class DeviceManager |
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); |
... | @@ -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 | +} |
... | @@ -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()); | ... | ... |
core/store/dist/pom.xml
0 → 100644
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> |
core/store/dist/src/main/java/org/onlab/onos/store/cluster/impl/ClusterDefinitionStore.java
0 → 100644
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 | +} |
core/store/dist/src/main/java/org/onlab/onos/store/cluster/impl/DistributedClusterStore.java
0 → 100644
This diff is collapsed. Click to expand it.
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 | +} |
core/store/dist/src/main/java/org/onlab/onos/store/device/impl/OnosDistributedDeviceStore.java
0 → 100644
This diff is collapsed. Click to expand it.
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 | +} |
core/store/dist/src/main/java/org/onlab/onos/store/flow/impl/DistributedFlowRuleStore.java
0 → 100644
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 | ... | ... |
core/store/dist/src/main/java/org/onlab/onos/store/link/impl/OnosDistributedLinkStore.java
0 → 100644
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 | } | ... | ... |
This diff is collapsed. Click to expand it.
core/store/dist/src/main/java/org/onlab/onos/store/topology/impl/DefaultTopologyGraph.java
0 → 100644
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 | +} |
core/store/dist/src/main/java/org/onlab/onos/store/topology/impl/DistributedTopologyStore.java
0 → 100644
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 | +} |
core/store/hz/cluster/pom.xml
0 → 100644
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; |
... | @@ -53,7 +54,7 @@ public class DistributedMastershipStore | ... | @@ -53,7 +54,7 @@ public class DistributedMastershipStore |
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 | } | ... | ... |
core/store/hz/common/pom.xml
0 → 100644
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 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()) | ... | ... |
core/store/hz/net/pom.xml
0 → 100644
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 | +} |
core/store/hz/net/src/main/java/org/onlab/onos/store/flow/impl/DistributedFlowRuleStore.java
0 → 100644
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 | } | ... | ... |
This diff is collapsed. Click to expand it.
core/store/hz/net/src/main/java/org/onlab/onos/store/topology/impl/DefaultTopologyGraph.java
0 → 100644
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 | +} |
core/store/hz/net/src/main/java/org/onlab/onos/store/topology/impl/DistributedTopologyStore.java
0 → 100644
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 | ... | ... |
core/store/hz/pom.xml
0 → 100644
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> | ... | ... |
core/store/serializers/pom.xml
0 → 100644
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"); | ... | ... |
core/store/trivial/src/test/java/org/onlab/onos/net/trivial/impl/SimpleDeviceStoreTest.java
0 → 100644
This diff is collapsed. Click to expand it.
core/store/trivial/src/test/java/org/onlab/onos/net/trivial/impl/SimpleLinkStoreTest.java
0 → 100644
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.
tools/test/bin/onos-start-network
0 → 100755
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.
-
Please register or login to post a comment