alshabib

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

Showing 64 changed files with 1213 additions and 105 deletions
...@@ -56,7 +56,8 @@ public interface MastershipService { ...@@ -56,7 +56,8 @@ public interface MastershipService {
56 Set<DeviceId> getDevicesOf(NodeId nodeId); 56 Set<DeviceId> getDevicesOf(NodeId nodeId);
57 57
58 /** 58 /**
59 - * Returns the mastership term service for getting term information. 59 + * Returns the mastership term service for getting read-only
60 + * term information.
60 * 61 *
61 * @return the MastershipTermService for this mastership manager 62 * @return the MastershipTermService for this mastership manager
62 */ 63 */
......
...@@ -64,4 +64,14 @@ public interface MastershipStore extends Store<MastershipEvent, MastershipStoreD ...@@ -64,4 +64,14 @@ public interface MastershipStore extends Store<MastershipEvent, MastershipStoreD
64 * @return the current master's ID and the term value for device, or null 64 * @return the current master's ID and the term value for device, or null
65 */ 65 */
66 MastershipTerm getTermFor(DeviceId deviceId); 66 MastershipTerm getTermFor(DeviceId deviceId);
67 +
68 + /**
69 + * Revokes a controller instance's mastership over a device and hands
70 + * over mastership to another controller instance.
71 + *
72 + * @param nodeId the controller instance identifier
73 + * @param deviceId device to revoke mastership for
74 + * @return a mastership event
75 + */
76 + MastershipEvent unsetMaster(NodeId nodeId, DeviceId deviceId);
67 } 77 }
......
...@@ -48,6 +48,7 @@ public interface DeviceStore extends Store<DeviceEvent, DeviceStoreDelegate> { ...@@ -48,6 +48,7 @@ public interface DeviceStore extends Store<DeviceEvent, DeviceStoreDelegate> {
48 DeviceEvent createOrUpdateDevice(ProviderId providerId, DeviceId deviceId, 48 DeviceEvent createOrUpdateDevice(ProviderId providerId, DeviceId deviceId,
49 DeviceDescription deviceDescription); 49 DeviceDescription deviceDescription);
50 50
51 + // TODO: We may need to enforce that ancillary cannot interfere this state
51 /** 52 /**
52 * Removes the specified infrastructure device. 53 * Removes the specified infrastructure device.
53 * 54 *
...@@ -60,22 +61,24 @@ public interface DeviceStore extends Store<DeviceEvent, DeviceStoreDelegate> { ...@@ -60,22 +61,24 @@ public interface DeviceStore extends Store<DeviceEvent, DeviceStoreDelegate> {
60 * Updates the ports of the specified infrastructure device using the given 61 * Updates the ports of the specified infrastructure device using the given
61 * list of port descriptions. The list is assumed to be comprehensive. 62 * list of port descriptions. The list is assumed to be comprehensive.
62 * 63 *
64 + * @param providerId provider identifier
63 * @param deviceId device identifier 65 * @param deviceId device identifier
64 * @param portDescriptions list of port descriptions 66 * @param portDescriptions list of port descriptions
65 * @return ready to send events describing what occurred; empty list if no change 67 * @return ready to send events describing what occurred; empty list if no change
66 */ 68 */
67 - List<DeviceEvent> updatePorts(DeviceId deviceId, 69 + List<DeviceEvent> updatePorts(ProviderId providerId, DeviceId deviceId,
68 List<PortDescription> portDescriptions); 70 List<PortDescription> portDescriptions);
69 71
70 /** 72 /**
71 * Updates the port status of the specified infrastructure device using the 73 * Updates the port status of the specified infrastructure device using the
72 * given port description. 74 * given port description.
73 * 75 *
76 + * @param providerId provider identifier
74 * @param deviceId device identifier 77 * @param deviceId device identifier
75 * @param portDescription port description 78 * @param portDescription port description
76 * @return ready to send event describing what occurred; null if no change 79 * @return ready to send event describing what occurred; null if no change
77 */ 80 */
78 - DeviceEvent updatePortStatus(DeviceId deviceId, 81 + DeviceEvent updatePortStatus(ProviderId providerId, DeviceId deviceId,
79 PortDescription portDescription); 82 PortDescription portDescription);
80 83
81 /** 84 /**
......
...@@ -35,10 +35,22 @@ public abstract class AbstractProviderRegistry<P extends Provider, S extends Pro ...@@ -35,10 +35,22 @@ public abstract class AbstractProviderRegistry<P extends Provider, S extends Pro
35 public synchronized S register(P provider) { 35 public synchronized S register(P provider) {
36 checkNotNull(provider, "Provider cannot be null"); 36 checkNotNull(provider, "Provider cannot be null");
37 checkState(!services.containsKey(provider.id()), "Provider %s already registered", provider.id()); 37 checkState(!services.containsKey(provider.id()), "Provider %s already registered", provider.id());
38 +
39 + // If the provider is a primary one, check for a conflict.
40 + ProviderId pid = provider.id();
41 + checkState(pid.isAncillary() || !providersByScheme.containsKey(pid.scheme()),
42 + "A primary provider with id %s is already registered",
43 + providersByScheme.get(pid.scheme()));
44 +
38 S service = createProviderService(provider); 45 S service = createProviderService(provider);
39 services.put(provider.id(), service); 46 services.put(provider.id(), service);
40 providers.put(provider.id(), provider); 47 providers.put(provider.id(), provider);
41 - // FIXME populate scheme look-up 48 +
49 + // Register the provider by URI scheme only if it is not ancillary.
50 + if (!pid.isAncillary()) {
51 + providersByScheme.put(pid.scheme(), provider);
52 + }
53 +
42 return service; 54 return service;
43 } 55 }
44 56
......
...@@ -11,6 +11,7 @@ public class ProviderId { ...@@ -11,6 +11,7 @@ public class ProviderId {
11 11
12 private final String scheme; 12 private final String scheme;
13 private final String id; 13 private final String id;
14 + private final boolean ancillary;
14 15
15 /** 16 /**
16 * Creates a new provider identifier from the specified string. 17 * Creates a new provider identifier from the specified string.
...@@ -21,8 +22,22 @@ public class ProviderId { ...@@ -21,8 +22,22 @@ public class ProviderId {
21 * @param id string identifier 22 * @param id string identifier
22 */ 23 */
23 public ProviderId(String scheme, String id) { 24 public ProviderId(String scheme, String id) {
25 + this(scheme, id, false);
26 + }
27 +
28 + /**
29 + * Creates a new provider identifier from the specified string.
30 + * The providers are expected to follow the reverse DNS convention, e.g.
31 + * {@code org.onlab.onos.provider.of.device}
32 + *
33 + * @param scheme device URI scheme to which this provider is bound, e.g. "of", "snmp"
34 + * @param id string identifier
35 + * @param ancillary ancillary provider indicator
36 + */
37 + public ProviderId(String scheme, String id, boolean ancillary) {
24 this.scheme = scheme; 38 this.scheme = scheme;
25 this.id = id; 39 this.id = id;
40 + this.ancillary = ancillary;
26 } 41 }
27 42
28 /** 43 /**
...@@ -35,6 +50,15 @@ public class ProviderId { ...@@ -35,6 +50,15 @@ public class ProviderId {
35 } 50 }
36 51
37 /** 52 /**
53 + * Indicates whether the provider id belongs to an ancillary provider.
54 + *
55 + * @return true for ancillary; false for primary provider
56 + */
57 + public boolean isAncillary() {
58 + return ancillary;
59 + }
60 +
61 + /**
38 * Returns the device URI scheme specific id portion. 62 * Returns the device URI scheme specific id portion.
39 * 63 *
40 * @return id 64 * @return id
...@@ -56,14 +80,16 @@ public class ProviderId { ...@@ -56,14 +80,16 @@ public class ProviderId {
56 if (obj instanceof ProviderId) { 80 if (obj instanceof ProviderId) {
57 final ProviderId other = (ProviderId) obj; 81 final ProviderId other = (ProviderId) obj;
58 return Objects.equals(this.scheme, other.scheme) && 82 return Objects.equals(this.scheme, other.scheme) &&
59 - Objects.equals(this.id, other.id); 83 + Objects.equals(this.id, other.id) &&
84 + this.ancillary == other.ancillary;
60 } 85 }
61 return false; 86 return false;
62 } 87 }
63 88
64 @Override 89 @Override
65 public String toString() { 90 public String toString() {
66 - return toStringHelper(this).add("scheme", scheme).add("id", id).toString(); 91 + return toStringHelper(this).add("scheme", scheme).add("id", id)
92 + .add("ancillary", ancillary).toString();
67 } 93 }
68 94
69 } 95 }
......
1 +package org.onlab.onos.cluster;
2 +
3 +import static org.junit.Assert.assertEquals;
4 +
5 +import org.junit.Test;
6 +
7 +import com.google.common.testing.EqualsTester;
8 +
9 +public class MastershipTermTest {
10 +
11 + private static final NodeId N1 = new NodeId("foo");
12 + private static final NodeId N2 = new NodeId("bar");
13 +
14 + private static final MastershipTerm TERM1 = MastershipTerm.of(N1, 0);
15 + private static final MastershipTerm TERM2 = MastershipTerm.of(N2, 1);
16 + private static final MastershipTerm TERM3 = MastershipTerm.of(N2, 1);
17 + private static final MastershipTerm TERM4 = MastershipTerm.of(N1, 1);
18 +
19 + @Test
20 + public void basics() {
21 + assertEquals("incorrect term number", 0, TERM1.termNumber());
22 + assertEquals("incorrect master", new NodeId("foo"), TERM1.master());
23 + }
24 +
25 + @Test
26 + public void testEquality() {
27 + new EqualsTester().addEqualityGroup(MastershipTerm.of(N1, 0), TERM1)
28 + .addEqualityGroup(TERM2, TERM3)
29 + .addEqualityGroup(TERM4);
30 + }
31 +
32 +}
...@@ -35,7 +35,7 @@ public class AbstractProviderRegistryTest { ...@@ -35,7 +35,7 @@ public class AbstractProviderRegistryTest {
35 assertThat("provider not found", registry.getProviders().contains(fooId)); 35 assertThat("provider not found", registry.getProviders().contains(fooId));
36 assertEquals("incorrect provider", psFoo.provider(), pFoo); 36 assertEquals("incorrect provider", psFoo.provider(), pFoo);
37 37
38 - ProviderId barId = new ProviderId("of", "bar"); 38 + ProviderId barId = new ProviderId("snmp", "bar");
39 TestProvider pBar = new TestProvider(barId); 39 TestProvider pBar = new TestProvider(barId);
40 TestProviderService psBar = registry.register(pBar); 40 TestProviderService psBar = registry.register(pBar);
41 assertEquals("incorrect provider count", 2, registry.getProviders().size()); 41 assertEquals("incorrect provider count", 2, registry.getProviders().size());
...@@ -49,6 +49,16 @@ public class AbstractProviderRegistryTest { ...@@ -49,6 +49,16 @@ public class AbstractProviderRegistryTest {
49 assertThat("provider not found", registry.getProviders().contains(barId)); 49 assertThat("provider not found", registry.getProviders().contains(barId));
50 } 50 }
51 51
52 + @Test
53 + public void ancillaryProviders() {
54 + TestProviderRegistry registry = new TestProviderRegistry();
55 + TestProvider pFoo = new TestProvider(new ProviderId("of", "foo"));
56 + TestProvider pBar = new TestProvider(new ProviderId("of", "bar", true));
57 + registry.register(pFoo);
58 + registry.register(pBar);
59 + assertEquals("incorrect provider count", 2, registry.getProviders().size());
60 + }
61 +
52 @Test(expected = IllegalStateException.class) 62 @Test(expected = IllegalStateException.class)
53 public void duplicateRegistration() { 63 public void duplicateRegistration() {
54 TestProviderRegistry registry = new TestProviderRegistry(); 64 TestProviderRegistry registry = new TestProviderRegistry();
...@@ -57,6 +67,15 @@ public class AbstractProviderRegistryTest { ...@@ -57,6 +67,15 @@ public class AbstractProviderRegistryTest {
57 registry.register(pFoo); 67 registry.register(pFoo);
58 } 68 }
59 69
70 + @Test(expected = IllegalStateException.class)
71 + public void duplicateSchemeRegistration() {
72 + TestProviderRegistry registry = new TestProviderRegistry();
73 + TestProvider pFoo = new TestProvider(new ProviderId("of", "foo"));
74 + TestProvider pBar = new TestProvider(new ProviderId("of", "bar"));
75 + registry.register(pFoo);
76 + registry.register(pBar);
77 + }
78 +
60 @Test 79 @Test
61 public void voidUnregistration() { 80 public void voidUnregistration() {
62 TestProviderRegistry registry = new TestProviderRegistry(); 81 TestProviderRegistry registry = new TestProviderRegistry();
......
...@@ -11,6 +11,8 @@ import org.apache.felix.scr.annotations.Deactivate; ...@@ -11,6 +11,8 @@ import org.apache.felix.scr.annotations.Deactivate;
11 import org.apache.felix.scr.annotations.Reference; 11 import org.apache.felix.scr.annotations.Reference;
12 import org.apache.felix.scr.annotations.ReferenceCardinality; 12 import org.apache.felix.scr.annotations.ReferenceCardinality;
13 import org.apache.felix.scr.annotations.Service; 13 import org.apache.felix.scr.annotations.Service;
14 +import org.onlab.onos.cluster.ClusterEvent;
15 +import org.onlab.onos.cluster.ClusterEventListener;
14 import org.onlab.onos.cluster.ClusterService; 16 import org.onlab.onos.cluster.ClusterService;
15 import org.onlab.onos.cluster.MastershipAdminService; 17 import org.onlab.onos.cluster.MastershipAdminService;
16 import org.onlab.onos.cluster.MastershipEvent; 18 import org.onlab.onos.cluster.MastershipEvent;
...@@ -52,9 +54,12 @@ implements MastershipService, MastershipAdminService { ...@@ -52,9 +54,12 @@ implements MastershipService, MastershipAdminService {
52 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) 54 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
53 protected ClusterService clusterService; 55 protected ClusterService clusterService;
54 56
57 + private ClusterEventListener clusterListener = new InternalClusterEventListener();
58 +
55 @Activate 59 @Activate
56 public void activate() { 60 public void activate() {
57 eventDispatcher.addSink(MastershipEvent.class, listenerRegistry); 61 eventDispatcher.addSink(MastershipEvent.class, listenerRegistry);
62 + clusterService.addListener(clusterListener);
58 store.setDelegate(delegate); 63 store.setDelegate(delegate);
59 log.info("Started"); 64 log.info("Started");
60 } 65 }
...@@ -62,6 +67,7 @@ implements MastershipService, MastershipAdminService { ...@@ -62,6 +67,7 @@ implements MastershipService, MastershipAdminService {
62 @Deactivate 67 @Deactivate
63 public void deactivate() { 68 public void deactivate() {
64 eventDispatcher.removeSink(MastershipEvent.class); 69 eventDispatcher.removeSink(MastershipEvent.class);
70 + clusterService.removeListener(clusterListener);
65 store.unsetDelegate(delegate); 71 store.unsetDelegate(delegate);
66 log.info("Stopped"); 72 log.info("Stopped");
67 } 73 }
...@@ -71,14 +77,18 @@ implements MastershipService, MastershipAdminService { ...@@ -71,14 +77,18 @@ implements MastershipService, MastershipAdminService {
71 checkNotNull(nodeId, NODE_ID_NULL); 77 checkNotNull(nodeId, NODE_ID_NULL);
72 checkNotNull(deviceId, DEVICE_ID_NULL); 78 checkNotNull(deviceId, DEVICE_ID_NULL);
73 checkNotNull(role, ROLE_NULL); 79 checkNotNull(role, ROLE_NULL);
74 - //TODO figure out appropriate action for non-MASTER roles, if we even set those 80 +
81 + MastershipEvent event = null;
75 if (role.equals(MastershipRole.MASTER)) { 82 if (role.equals(MastershipRole.MASTER)) {
76 - MastershipEvent event = store.setMaster(nodeId, deviceId); 83 + event = store.setMaster(nodeId, deviceId);
84 + } else {
85 + event = store.unsetMaster(nodeId, deviceId);
86 + }
87 +
77 if (event != null) { 88 if (event != null) {
78 post(event); 89 post(event);
79 } 90 }
80 } 91 }
81 - }
82 92
83 @Override 93 @Override
84 public MastershipRole getLocalRole(DeviceId deviceId) { 94 public MastershipRole getLocalRole(DeviceId deviceId) {
...@@ -88,8 +98,16 @@ implements MastershipService, MastershipAdminService { ...@@ -88,8 +98,16 @@ implements MastershipService, MastershipAdminService {
88 98
89 @Override 99 @Override
90 public void relinquishMastership(DeviceId deviceId) { 100 public void relinquishMastership(DeviceId deviceId) {
91 - checkNotNull(deviceId, DEVICE_ID_NULL); 101 + MastershipRole role = getLocalRole(deviceId);
92 - // FIXME: add method to store to give up mastership and trigger new master selection process 102 + if (!role.equals(MastershipRole.MASTER)) {
103 + return;
104 + }
105 +
106 + MastershipEvent event = store.unsetMaster(
107 + clusterService.getLocalNode().id(), deviceId);
108 + if (event != null) {
109 + post(event);
110 + }
93 } 111 }
94 112
95 @Override 113 @Override
...@@ -146,6 +164,26 @@ implements MastershipService, MastershipAdminService { ...@@ -146,6 +164,26 @@ implements MastershipService, MastershipAdminService {
146 164
147 } 165 }
148 166
167 + //callback for reacting to cluster events
168 + private class InternalClusterEventListener implements ClusterEventListener {
169 +
170 + @Override
171 + public void event(ClusterEvent event) {
172 + switch (event.type()) {
173 + //FIXME: worry about addition when the time comes
174 + case INSTANCE_ADDED:
175 + case INSTANCE_ACTIVATED:
176 + break;
177 + case INSTANCE_REMOVED:
178 + case INSTANCE_DEACTIVATED:
179 + break;
180 + default:
181 + log.warn("unknown cluster event {}", event);
182 + }
183 + }
184 +
185 + }
186 +
149 public class InternalDelegate implements MastershipStoreDelegate { 187 public class InternalDelegate implements MastershipStoreDelegate {
150 188
151 @Override 189 @Override
......
...@@ -16,6 +16,7 @@ import org.onlab.onos.cluster.ClusterService; ...@@ -16,6 +16,7 @@ import org.onlab.onos.cluster.ClusterService;
16 import org.onlab.onos.cluster.MastershipEvent; 16 import org.onlab.onos.cluster.MastershipEvent;
17 import org.onlab.onos.cluster.MastershipListener; 17 import org.onlab.onos.cluster.MastershipListener;
18 import org.onlab.onos.cluster.MastershipService; 18 import org.onlab.onos.cluster.MastershipService;
19 +import org.onlab.onos.cluster.MastershipTermService;
19 import org.onlab.onos.cluster.MastershipTerm; 20 import org.onlab.onos.cluster.MastershipTerm;
20 import org.onlab.onos.event.AbstractListenerRegistry; 21 import org.onlab.onos.event.AbstractListenerRegistry;
21 import org.onlab.onos.event.EventDeliveryService; 22 import org.onlab.onos.event.EventDeliveryService;
...@@ -76,6 +77,8 @@ public class DeviceManager ...@@ -76,6 +77,8 @@ public class DeviceManager
76 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) 77 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
77 protected MastershipService mastershipService; 78 protected MastershipService mastershipService;
78 79
80 + protected MastershipTermService termService;
81 +
79 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) 82 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
80 protected ClockService clockService; 83 protected ClockService clockService;
81 84
...@@ -84,6 +87,7 @@ public class DeviceManager ...@@ -84,6 +87,7 @@ public class DeviceManager
84 store.setDelegate(delegate); 87 store.setDelegate(delegate);
85 eventDispatcher.addSink(DeviceEvent.class, listenerRegistry); 88 eventDispatcher.addSink(DeviceEvent.class, listenerRegistry);
86 mastershipService.addListener(mastershipListener); 89 mastershipService.addListener(mastershipListener);
90 + termService = mastershipService.requestTermService();
87 log.info("Started"); 91 log.info("Started");
88 } 92 }
89 93
...@@ -198,7 +202,7 @@ public class DeviceManager ...@@ -198,7 +202,7 @@ public class DeviceManager
198 log.info("Device {} connected", deviceId); 202 log.info("Device {} connected", deviceId);
199 mastershipService.requestRoleFor(deviceId); 203 mastershipService.requestRoleFor(deviceId);
200 provider().roleChanged(event.subject(), 204 provider().roleChanged(event.subject(),
201 - mastershipService.getLocalRole(deviceId)); 205 + mastershipService.requestRoleFor(deviceId));
202 post(event); 206 post(event);
203 } 207 }
204 } 208 }
...@@ -208,8 +212,11 @@ public class DeviceManager ...@@ -208,8 +212,11 @@ public class DeviceManager
208 checkNotNull(deviceId, DEVICE_ID_NULL); 212 checkNotNull(deviceId, DEVICE_ID_NULL);
209 checkValidity(); 213 checkValidity();
210 DeviceEvent event = store.markOffline(deviceId); 214 DeviceEvent event = store.markOffline(deviceId);
215 +
216 + //we're no longer capable of mastership.
211 if (event != null) { 217 if (event != null) {
212 log.info("Device {} disconnected", deviceId); 218 log.info("Device {} disconnected", deviceId);
219 + mastershipService.relinquishMastership(deviceId);
213 post(event); 220 post(event);
214 } 221 }
215 } 222 }
...@@ -221,8 +228,9 @@ public class DeviceManager ...@@ -221,8 +228,9 @@ public class DeviceManager
221 checkNotNull(portDescriptions, 228 checkNotNull(portDescriptions,
222 "Port descriptions list cannot be null"); 229 "Port descriptions list cannot be null");
223 checkValidity(); 230 checkValidity();
224 - List<DeviceEvent> events = store.updatePorts(deviceId, 231 + this.provider().id();
225 - portDescriptions); 232 + List<DeviceEvent> events = store.updatePorts(this.provider().id(),
233 + deviceId, portDescriptions);
226 for (DeviceEvent event : events) { 234 for (DeviceEvent event : events) {
227 post(event); 235 post(event);
228 } 236 }
...@@ -234,8 +242,8 @@ public class DeviceManager ...@@ -234,8 +242,8 @@ public class DeviceManager
234 checkNotNull(deviceId, DEVICE_ID_NULL); 242 checkNotNull(deviceId, DEVICE_ID_NULL);
235 checkNotNull(portDescription, PORT_DESCRIPTION_NULL); 243 checkNotNull(portDescription, PORT_DESCRIPTION_NULL);
236 checkValidity(); 244 checkValidity();
237 - DeviceEvent event = store.updatePortStatus(deviceId, 245 + DeviceEvent event = store.updatePortStatus(this.provider().id(),
238 - portDescription); 246 + deviceId, portDescription);
239 if (event != null) { 247 if (event != null) {
240 log.info("Device {} port {} status changed", deviceId, event 248 log.info("Device {} port {} status changed", deviceId, event
241 .port().number()); 249 .port().number());
......
...@@ -65,8 +65,8 @@ public class DefaultTopologyProvider extends AbstractProvider ...@@ -65,8 +65,8 @@ public class DefaultTopologyProvider extends AbstractProvider
65 private volatile boolean isStarted = false; 65 private volatile boolean isStarted = false;
66 66
67 private TopologyProviderService providerService; 67 private TopologyProviderService providerService;
68 - private DeviceListener deviceListener = new InnerDeviceListener(); 68 + private DeviceListener deviceListener = new InternalDeviceListener();
69 - private LinkListener linkListener = new InnerLinkListener(); 69 + private LinkListener linkListener = new InternalLinkListener();
70 70
71 private EventAccumulator accumulator; 71 private EventAccumulator accumulator;
72 private ExecutorService executor; 72 private ExecutorService executor;
...@@ -132,7 +132,7 @@ public class DefaultTopologyProvider extends AbstractProvider ...@@ -132,7 +132,7 @@ public class DefaultTopologyProvider extends AbstractProvider
132 } 132 }
133 133
134 // Callback for device events 134 // Callback for device events
135 - private class InnerDeviceListener implements DeviceListener { 135 + private class InternalDeviceListener implements DeviceListener {
136 @Override 136 @Override
137 public void event(DeviceEvent event) { 137 public void event(DeviceEvent event) {
138 DeviceEvent.Type type = event.type(); 138 DeviceEvent.Type type = event.type();
...@@ -144,7 +144,7 @@ public class DefaultTopologyProvider extends AbstractProvider ...@@ -144,7 +144,7 @@ public class DefaultTopologyProvider extends AbstractProvider
144 } 144 }
145 145
146 // Callback for link events 146 // Callback for link events
147 - private class InnerLinkListener implements LinkListener { 147 + private class InternalLinkListener implements LinkListener {
148 @Override 148 @Override
149 public void event(LinkEvent event) { 149 public void event(LinkEvent event) {
150 accumulator.add(event); 150 accumulator.add(event);
......
...@@ -15,10 +15,11 @@ import org.onlab.onos.cluster.MastershipTermService; ...@@ -15,10 +15,11 @@ import org.onlab.onos.cluster.MastershipTermService;
15 import org.onlab.onos.cluster.NodeId; 15 import org.onlab.onos.cluster.NodeId;
16 import org.onlab.onos.event.impl.TestEventDispatcher; 16 import org.onlab.onos.event.impl.TestEventDispatcher;
17 import org.onlab.onos.net.DeviceId; 17 import org.onlab.onos.net.DeviceId;
18 -import org.onlab.onos.net.trivial.impl.SimpleMastershipStore; 18 +import org.onlab.onos.store.trivial.impl.SimpleMastershipStore;
19 import org.onlab.packet.IpPrefix; 19 import org.onlab.packet.IpPrefix;
20 20
21 import static org.junit.Assert.assertEquals; 21 import static org.junit.Assert.assertEquals;
22 +import static org.junit.Assert.assertNull;
22 import static org.onlab.onos.net.MastershipRole.*; 23 import static org.onlab.onos.net.MastershipRole.*;
23 24
24 /** 25 /**
...@@ -65,7 +66,24 @@ public class MastershipManagerTest { ...@@ -65,7 +66,24 @@ public class MastershipManagerTest {
65 66
66 @Test 67 @Test
67 public void relinquishMastership() { 68 public void relinquishMastership() {
68 - //TODO 69 + //no backups - should turn to standby and no master for device
70 + mgr.setRole(NID_LOCAL, DEV_MASTER, MASTER);
71 + assertEquals("wrong role:", MASTER, mgr.getLocalRole(DEV_MASTER));
72 + mgr.relinquishMastership(DEV_MASTER);
73 + assertNull("wrong master:", mgr.getMasterFor(DEV_OTHER));
74 + assertEquals("wrong role:", STANDBY, mgr.getLocalRole(DEV_MASTER));
75 +
76 + //not master, nothing should happen
77 + mgr.setRole(NID_LOCAL, DEV_OTHER, STANDBY);
78 + mgr.relinquishMastership(DEV_OTHER);
79 + assertNull("wrong role:", mgr.getMasterFor(DEV_OTHER));
80 +
81 + //provide NID_OTHER as backup and relinquish
82 + mgr.setRole(NID_LOCAL, DEV_MASTER, MASTER);
83 + assertEquals("wrong master:", NID_LOCAL, mgr.getMasterFor(DEV_MASTER));
84 + mgr.setRole(NID_OTHER, DEV_MASTER, STANDBY);
85 + mgr.relinquishMastership(DEV_MASTER);
86 + assertEquals("wrong master:", NID_OTHER, mgr.getMasterFor(DEV_MASTER));
69 } 87 }
70 88
71 @Test 89 @Test
...@@ -95,7 +113,6 @@ public class MastershipManagerTest { ...@@ -95,7 +113,6 @@ public class MastershipManagerTest {
95 mgr.setRole(NID_LOCAL, DEV_MASTER, MASTER); 113 mgr.setRole(NID_LOCAL, DEV_MASTER, MASTER);
96 mgr.setRole(NID_LOCAL, DEV_OTHER, STANDBY); 114 mgr.setRole(NID_LOCAL, DEV_OTHER, STANDBY);
97 assertEquals("should be one device:", 1, mgr.getDevicesOf(NID_LOCAL).size()); 115 assertEquals("should be one device:", 1, mgr.getDevicesOf(NID_LOCAL).size());
98 -
99 //hand both devices to NID_LOCAL 116 //hand both devices to NID_LOCAL
100 mgr.setRole(NID_LOCAL, DEV_OTHER, MASTER); 117 mgr.setRole(NID_LOCAL, DEV_OTHER, MASTER);
101 assertEquals("should be two devices:", 2, mgr.getDevicesOf(NID_LOCAL).size()); 118 assertEquals("should be two devices:", 2, mgr.getDevicesOf(NID_LOCAL).size());
......
...@@ -27,7 +27,7 @@ import org.onlab.onos.net.device.DeviceService; ...@@ -27,7 +27,7 @@ import org.onlab.onos.net.device.DeviceService;
27 import org.onlab.onos.net.device.PortDescription; 27 import org.onlab.onos.net.device.PortDescription;
28 import org.onlab.onos.net.provider.AbstractProvider; 28 import org.onlab.onos.net.provider.AbstractProvider;
29 import org.onlab.onos.net.provider.ProviderId; 29 import org.onlab.onos.net.provider.ProviderId;
30 -import org.onlab.onos.net.trivial.impl.SimpleDeviceStore; 30 +import org.onlab.onos.store.trivial.impl.SimpleDeviceStore;
31 31
32 import java.util.ArrayList; 32 import java.util.ArrayList;
33 import java.util.Iterator; 33 import java.util.Iterator;
......
...@@ -40,7 +40,7 @@ import org.onlab.onos.net.flow.criteria.Criterion; ...@@ -40,7 +40,7 @@ import org.onlab.onos.net.flow.criteria.Criterion;
40 import org.onlab.onos.net.flow.instructions.Instruction; 40 import org.onlab.onos.net.flow.instructions.Instruction;
41 import org.onlab.onos.net.provider.AbstractProvider; 41 import org.onlab.onos.net.provider.AbstractProvider;
42 import org.onlab.onos.net.provider.ProviderId; 42 import org.onlab.onos.net.provider.ProviderId;
43 -import org.onlab.onos.net.trivial.impl.SimpleFlowRuleStore; 43 +import org.onlab.onos.store.trivial.impl.SimpleFlowRuleStore;
44 44
45 import com.google.common.collect.Lists; 45 import com.google.common.collect.Lists;
46 import com.google.common.collect.Sets; 46 import com.google.common.collect.Sets;
......
...@@ -34,7 +34,7 @@ import org.onlab.onos.net.host.HostProviderService; ...@@ -34,7 +34,7 @@ import org.onlab.onos.net.host.HostProviderService;
34 import org.onlab.onos.net.host.PortAddresses; 34 import org.onlab.onos.net.host.PortAddresses;
35 import org.onlab.onos.net.provider.AbstractProvider; 35 import org.onlab.onos.net.provider.AbstractProvider;
36 import org.onlab.onos.net.provider.ProviderId; 36 import org.onlab.onos.net.provider.ProviderId;
37 -import org.onlab.onos.net.trivial.impl.SimpleHostStore; 37 +import org.onlab.onos.store.trivial.impl.SimpleHostStore;
38 import org.onlab.packet.IpPrefix; 38 import org.onlab.packet.IpPrefix;
39 import org.onlab.packet.MacAddress; 39 import org.onlab.packet.MacAddress;
40 import org.onlab.packet.VlanId; 40 import org.onlab.packet.VlanId;
......
...@@ -23,7 +23,7 @@ import org.onlab.onos.net.provider.AbstractProvider; ...@@ -23,7 +23,7 @@ import org.onlab.onos.net.provider.AbstractProvider;
23 import org.onlab.onos.net.provider.ProviderId; 23 import org.onlab.onos.net.provider.ProviderId;
24 import org.onlab.onos.event.impl.TestEventDispatcher; 24 import org.onlab.onos.event.impl.TestEventDispatcher;
25 import org.onlab.onos.net.device.impl.DeviceManager; 25 import org.onlab.onos.net.device.impl.DeviceManager;
26 -import org.onlab.onos.net.trivial.impl.SimpleLinkStore; 26 +import org.onlab.onos.store.trivial.impl.SimpleLinkStore;
27 27
28 import java.util.ArrayList; 28 import java.util.ArrayList;
29 import java.util.Iterator; 29 import java.util.Iterator;
......
...@@ -24,7 +24,7 @@ import org.onlab.onos.net.topology.TopologyProvider; ...@@ -24,7 +24,7 @@ import org.onlab.onos.net.topology.TopologyProvider;
24 import org.onlab.onos.net.topology.TopologyProviderRegistry; 24 import org.onlab.onos.net.topology.TopologyProviderRegistry;
25 import org.onlab.onos.net.topology.TopologyProviderService; 25 import org.onlab.onos.net.topology.TopologyProviderService;
26 import org.onlab.onos.net.topology.TopologyService; 26 import org.onlab.onos.net.topology.TopologyService;
27 -import org.onlab.onos.net.trivial.impl.SimpleTopologyStore; 27 +import org.onlab.onos.store.trivial.impl.SimpleTopologyStore;
28 28
29 import java.util.ArrayList; 29 import java.util.ArrayList;
30 import java.util.List; 30 import java.util.List;
......
1 +package org.onlab.onos.store.cluster.messaging;
2 +
3 +import static org.onlab.onos.store.cluster.messaging.MessageSubject.AE_ADVERTISEMENT;
4 +import java.util.Map;
5 +
6 +import org.onlab.onos.cluster.NodeId;
7 +import org.onlab.onos.store.Timestamp;
8 +
9 +import com.google.common.collect.ImmutableMap;
10 +
11 +/**
12 + * Anti-Entropy advertisement message.
13 + * <p>
14 + * Message to advertise the information this node holds.
15 + *
16 + * @param <ID> ID type
17 + */
18 +public class AntiEntropyAdvertisement<ID> extends ClusterMessage {
19 +
20 + private final NodeId sender;
21 + private final ImmutableMap<ID, Timestamp> advertisement;
22 +
23 + /**
24 + * Creates anti-entropy advertisement message.
25 + *
26 + * @param sender sender of this message
27 + * @param advertisement timestamp information of the data sender holds
28 + */
29 + public AntiEntropyAdvertisement(NodeId sender, Map<ID, Timestamp> advertisement) {
30 + super(AE_ADVERTISEMENT);
31 + this.sender = sender;
32 + this.advertisement = ImmutableMap.copyOf(advertisement);
33 + }
34 +
35 + public NodeId sender() {
36 + return sender;
37 + }
38 +
39 + public ImmutableMap<ID, Timestamp> advertisement() {
40 + return advertisement;
41 + }
42 +
43 + // Default constructor for serializer
44 + protected AntiEntropyAdvertisement() {
45 + super(AE_ADVERTISEMENT);
46 + this.sender = null;
47 + this.advertisement = null;
48 + }
49 +}
1 +package org.onlab.onos.store.cluster.messaging;
2 +
3 +import static org.onlab.onos.store.cluster.messaging.MessageSubject.AE_REPLY;
4 +
5 +import java.util.Map;
6 +import java.util.Set;
7 +
8 +import org.onlab.onos.cluster.NodeId;
9 +import org.onlab.onos.store.device.impl.VersionedValue;
10 +
11 +import com.google.common.collect.ImmutableMap;
12 +import com.google.common.collect.ImmutableSet;
13 +
14 +/**
15 + * Anti-Entropy reply message.
16 + * <p>
17 + * Message to send in reply to advertisement or another reply.
18 + * Suggest to the sender about the more up-to-date data this node has,
19 + * and request for more recent data that the receiver has.
20 + */
21 +public class AntiEntropyReply<ID, V extends VersionedValue<?>> extends ClusterMessage {
22 +
23 + private final NodeId sender;
24 + private final ImmutableMap<ID, V> suggestion;
25 + private final ImmutableSet<ID> request;
26 +
27 + /**
28 + * Creates a reply to anti-entropy message.
29 + *
30 + * @param sender sender of this message
31 + * @param suggestion collection of more recent values, sender had
32 + * @param request Collection of identifiers
33 + */
34 + public AntiEntropyReply(NodeId sender,
35 + Map<ID, V> suggestion,
36 + Set<ID> request) {
37 + super(AE_REPLY);
38 + this.sender = sender;
39 + this.suggestion = ImmutableMap.copyOf(suggestion);
40 + this.request = ImmutableSet.copyOf(request);
41 + }
42 +
43 + public NodeId sender() {
44 + return sender;
45 + }
46 +
47 + /**
48 + * Returns collection of values, which the recipient of this reply is likely
49 + * to be missing or has outdated version.
50 + *
51 + * @return
52 + */
53 + public ImmutableMap<ID, V> suggestion() {
54 + return suggestion;
55 + }
56 +
57 + /**
58 + * Returns collection of identifier to request.
59 + *
60 + * @return collection of identifier to request
61 + */
62 + public ImmutableSet<ID> request() {
63 + return request;
64 + }
65 +
66 + /**
67 + * Checks if reply contains any suggestion or request.
68 + *
69 + * @return true if nothing is suggested and requested
70 + */
71 + public boolean isEmpty() {
72 + return suggestion.isEmpty() && request.isEmpty();
73 + }
74 +
75 + // Default constructor for serializer
76 + protected AntiEntropyReply() {
77 + super(AE_REPLY);
78 + this.sender = null;
79 + this.suggestion = null;
80 + this.request = null;
81 + }
82 +}
...@@ -15,6 +15,12 @@ public enum MessageSubject { ...@@ -15,6 +15,12 @@ public enum MessageSubject {
15 LEAVING_MEMBER, 15 LEAVING_MEMBER,
16 16
17 /** Signifies a heart-beat message. */ 17 /** Signifies a heart-beat message. */
18 - ECHO 18 + ECHO,
19 +
20 + /** Anti-Entropy advertisement message. */
21 + AE_ADVERTISEMENT,
22 +
23 + /** Anti-Entropy reply message. */
24 + AE_REPLY,
19 25
20 } 26 }
......
1 +package org.onlab.onos.store.device.impl;
2 +
3 +import java.util.Collection;
4 +import java.util.HashMap;
5 +import java.util.Map;
6 +
7 +import org.onlab.onos.cluster.NodeId;
8 +import org.onlab.onos.net.Device;
9 +import org.onlab.onos.net.DeviceId;
10 +import org.onlab.onos.store.Timestamp;
11 +import org.onlab.onos.store.cluster.messaging.AntiEntropyAdvertisement;
12 +
13 +// TODO DeviceID needs to be changed to something like (ProviderID, DeviceID)
14 +// TODO: Handle Port as part of these messages, or separate messages for Ports?
15 +
16 +public class DeviceAntiEntropyAdvertisement
17 + extends AntiEntropyAdvertisement<DeviceId> {
18 +
19 +
20 + public DeviceAntiEntropyAdvertisement(NodeId sender,
21 + Map<DeviceId, Timestamp> advertisement) {
22 + super(sender, advertisement);
23 + }
24 +
25 + // May need to add ProviderID, etc.
26 + public static DeviceAntiEntropyAdvertisement create(
27 + NodeId self,
28 + Collection<VersionedValue<Device>> localValues) {
29 +
30 + Map<DeviceId, Timestamp> ads = new HashMap<>(localValues.size());
31 + for (VersionedValue<Device> e : localValues) {
32 + ads.put(e.entity().id(), e.timestamp());
33 + }
34 + return new DeviceAntiEntropyAdvertisement(self, ads);
35 + }
36 +
37 + // For serializer
38 + protected DeviceAntiEntropyAdvertisement() {}
39 +}
1 +package org.onlab.onos.store.device.impl;
2 +
3 +import java.util.Collection;
4 +import java.util.HashMap;
5 +import java.util.HashSet;
6 +import java.util.Map;
7 +import java.util.Set;
8 +
9 +import org.onlab.onos.cluster.NodeId;
10 +import org.onlab.onos.net.Device;
11 +import org.onlab.onos.net.DeviceId;
12 +import org.onlab.onos.store.Timestamp;
13 +import org.onlab.onos.store.cluster.messaging.AntiEntropyReply;
14 +
15 +import com.google.common.collect.ImmutableMap;
16 +import com.google.common.collect.ImmutableSet;
17 +
18 +public class DeviceAntiEntropyReply
19 + extends AntiEntropyReply<DeviceId, VersionedValue<Device>> {
20 +
21 +
22 + public DeviceAntiEntropyReply(NodeId sender,
23 + Map<DeviceId, VersionedValue<Device>> suggestion,
24 + Set<DeviceId> request) {
25 + super(sender, suggestion, request);
26 + }
27 +
28 + /**
29 + * Creates a reply to Anti-Entropy advertisement.
30 + *
31 + * @param advertisement to respond to
32 + * @param self node identifier representing local node
33 + * @param localValues local values held on this node
34 + * @return reply message
35 + */
36 + public static DeviceAntiEntropyReply reply(
37 + DeviceAntiEntropyAdvertisement advertisement,
38 + NodeId self,
39 + Collection<VersionedValue<Device>> localValues
40 + ) {
41 +
42 + ImmutableMap<DeviceId, Timestamp> ads = advertisement.advertisement();
43 +
44 + ImmutableMap.Builder<DeviceId, VersionedValue<Device>>
45 + sug = ImmutableMap.builder();
46 +
47 + Set<DeviceId> req = new HashSet<>(ads.keySet());
48 +
49 + for (VersionedValue<Device> e : localValues) {
50 + final DeviceId id = e.entity().id();
51 + final Timestamp local = e.timestamp();
52 + final Timestamp theirs = ads.get(id);
53 + if (theirs == null) {
54 + // they don't have it, suggest
55 + sug.put(id, e);
56 + // don't need theirs
57 + req.remove(id);
58 + } else if (local.compareTo(theirs) < 0) {
59 + // they got older one, suggest
60 + sug.put(id, e);
61 + // don't need theirs
62 + req.remove(id);
63 + } else if (local.equals(theirs)) {
64 + // same, don't need theirs
65 + req.remove(id);
66 + }
67 + }
68 +
69 + return new DeviceAntiEntropyReply(self, sug.build(), req);
70 + }
71 +
72 + /**
73 + * Creates a reply to request for values held locally.
74 + *
75 + * @param requests message containing the request
76 + * @param self node identifier representing local node
77 + * @param localValues local valeds held on this node
78 + * @return reply message
79 + */
80 + public static DeviceAntiEntropyReply reply(
81 + DeviceAntiEntropyReply requests,
82 + NodeId self,
83 + Map<DeviceId, VersionedValue<Device>> localValues
84 + ) {
85 +
86 + Set<DeviceId> reqs = requests.request();
87 +
88 + Map<DeviceId, VersionedValue<Device>> requested = new HashMap<>(reqs.size());
89 + for (DeviceId id : reqs) {
90 + final VersionedValue<Device> value = localValues.get(id);
91 + if (value != null) {
92 + requested.put(id, value);
93 + }
94 + }
95 +
96 + Set<DeviceId> empty = ImmutableSet.of();
97 + return new DeviceAntiEntropyReply(self, requested, empty);
98 + }
99 +
100 + // For serializer
101 + protected DeviceAntiEntropyReply() {}
102 +}
...@@ -40,6 +40,7 @@ import java.util.Map; ...@@ -40,6 +40,7 @@ import java.util.Map;
40 import java.util.Objects; 40 import java.util.Objects;
41 import java.util.Set; 41 import java.util.Set;
42 import java.util.concurrent.ConcurrentHashMap; 42 import java.util.concurrent.ConcurrentHashMap;
43 +import java.util.concurrent.ConcurrentMap;
43 44
44 import static com.google.common.base.Preconditions.checkArgument; 45 import static com.google.common.base.Preconditions.checkArgument;
45 import static org.onlab.onos.net.device.DeviceEvent.Type.*; 46 import static org.onlab.onos.net.device.DeviceEvent.Type.*;
...@@ -59,8 +60,8 @@ public class OnosDistributedDeviceStore ...@@ -59,8 +60,8 @@ public class OnosDistributedDeviceStore
59 60
60 public static final String DEVICE_NOT_FOUND = "Device with ID %s not found"; 61 public static final String DEVICE_NOT_FOUND = "Device with ID %s not found";
61 62
62 - private ConcurrentHashMap<DeviceId, VersionedValue<Device>> devices; 63 + private ConcurrentMap<DeviceId, VersionedValue<Device>> devices;
63 - private ConcurrentHashMap<DeviceId, Map<PortNumber, VersionedValue<Port>>> devicePorts; 64 + private ConcurrentMap<DeviceId, Map<PortNumber, VersionedValue<Port>>> devicePorts;
64 65
65 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) 66 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
66 protected ClockService clockService; 67 protected ClockService clockService;
...@@ -191,7 +192,7 @@ public class OnosDistributedDeviceStore ...@@ -191,7 +192,7 @@ public class OnosDistributedDeviceStore
191 } 192 }
192 193
193 @Override 194 @Override
194 - public List<DeviceEvent> updatePorts(DeviceId deviceId, 195 + public List<DeviceEvent> updatePorts(ProviderId providerId, DeviceId deviceId,
195 List<PortDescription> portDescriptions) { 196 List<PortDescription> portDescriptions) {
196 List<DeviceEvent> events = new ArrayList<>(); 197 List<DeviceEvent> events = new ArrayList<>();
197 synchronized (this) { 198 synchronized (this) {
...@@ -295,7 +296,7 @@ public class OnosDistributedDeviceStore ...@@ -295,7 +296,7 @@ public class OnosDistributedDeviceStore
295 } 296 }
296 297
297 @Override 298 @Override
298 - public DeviceEvent updatePortStatus(DeviceId deviceId, 299 + public DeviceEvent updatePortStatus(ProviderId providerId, DeviceId deviceId,
299 PortDescription portDescription) { 300 PortDescription portDescription) {
300 VersionedValue<Device> device = devices.get(deviceId); 301 VersionedValue<Device> device = devices.get(deviceId);
301 checkArgument(device != null, DEVICE_NOT_FOUND, deviceId); 302 checkArgument(device != null, DEVICE_NOT_FOUND, deviceId);
......
1 package org.onlab.onos.store.device.impl; 1 package org.onlab.onos.store.device.impl;
2 2
3 +import java.util.Objects;
4 +
3 import org.onlab.onos.store.Timestamp; 5 import org.onlab.onos.store.Timestamp;
4 6
5 /** 7 /**
...@@ -42,4 +44,35 @@ public class VersionedValue<T> { ...@@ -42,4 +44,35 @@ public class VersionedValue<T> {
42 public Timestamp timestamp() { 44 public Timestamp timestamp() {
43 return timestamp; 45 return timestamp;
44 } 46 }
47 +
48 +
49 + @Override
50 + public int hashCode() {
51 + return Objects.hash(entity, timestamp, isUp);
52 + }
53 +
54 + @Override
55 + public boolean equals(Object obj) {
56 + if (this == obj) {
57 + return true;
58 + }
59 + if (obj == null) {
60 + return false;
61 + }
62 + if (getClass() != obj.getClass()) {
63 + return false;
64 + }
65 + @SuppressWarnings("unchecked")
66 + VersionedValue<T> that = (VersionedValue<T>) obj;
67 + return Objects.equals(this.entity, that.entity) &&
68 + Objects.equals(this.timestamp, that.timestamp) &&
69 + Objects.equals(this.isUp, that.isUp);
70 + }
71 +
72 + // Default constructor for serializer
73 + protected VersionedValue() {
74 + this.entity = null;
75 + this.isUp = false;
76 + this.timestamp = null;
77 + }
45 } 78 }
......
...@@ -123,6 +123,12 @@ implements MastershipStore { ...@@ -123,6 +123,12 @@ implements MastershipStore {
123 return null; 123 return null;
124 } 124 }
125 125
126 + @Override
127 + public MastershipEvent unsetMaster(NodeId nodeId, DeviceId deviceId) {
128 + // TODO Auto-generated method stub
129 + return null;
130 + }
131 +
126 private class RemoteMasterShipEventHandler extends RemoteCacheEventHandler<DeviceId, NodeId> { 132 private class RemoteMasterShipEventHandler extends RemoteCacheEventHandler<DeviceId, NodeId> {
127 public RemoteMasterShipEventHandler(LoadingCache<DeviceId, Optional<NodeId>> cache) { 133 public RemoteMasterShipEventHandler(LoadingCache<DeviceId, Optional<NodeId>> cache) {
128 super(cache); 134 super(cache);
......
...@@ -221,7 +221,7 @@ public class DistributedDeviceStore ...@@ -221,7 +221,7 @@ public class DistributedDeviceStore
221 } 221 }
222 222
223 @Override 223 @Override
224 - public List<DeviceEvent> updatePorts(DeviceId deviceId, 224 + public List<DeviceEvent> updatePorts(ProviderId providerId, DeviceId deviceId,
225 List<PortDescription> portDescriptions) { 225 List<PortDescription> portDescriptions) {
226 List<DeviceEvent> events = new ArrayList<>(); 226 List<DeviceEvent> events = new ArrayList<>();
227 synchronized (this) { 227 synchronized (this) {
...@@ -319,7 +319,7 @@ public class DistributedDeviceStore ...@@ -319,7 +319,7 @@ public class DistributedDeviceStore
319 } 319 }
320 320
321 @Override 321 @Override
322 - public DeviceEvent updatePortStatus(DeviceId deviceId, 322 + public DeviceEvent updatePortStatus(ProviderId providerId, DeviceId deviceId,
323 PortDescription portDescription) { 323 PortDescription portDescription) {
324 synchronized (this) { 324 synchronized (this) {
325 Device device = devices.getUnchecked(deviceId).orNull(); 325 Device device = devices.getUnchecked(deviceId).orNull();
......
...@@ -28,7 +28,7 @@ import com.google.common.collect.ImmutableSet; ...@@ -28,7 +28,7 @@ import com.google.common.collect.ImmutableSet;
28 import com.google.common.collect.Multimap; 28 import com.google.common.collect.Multimap;
29 29
30 /** 30 /**
31 - * Manages inventory of flow rules using trivial in-memory implementation. 31 + * TEMPORARY: Manages inventory of flow rules using distributed store implementation.
32 */ 32 */
33 //FIXME: I LIE I AM NOT DISTRIBUTED 33 //FIXME: I LIE I AM NOT DISTRIBUTED
34 @Component(immediate = true) 34 @Component(immediate = true)
......
1 +/**
2 + * Implementation of flow store using Hazelcast distributed structures.
3 + */
4 +package org.onlab.onos.store.flow.impl;
...@@ -39,8 +39,8 @@ import com.google.common.collect.Multimap; ...@@ -39,8 +39,8 @@ import com.google.common.collect.Multimap;
39 import com.google.common.collect.Sets; 39 import com.google.common.collect.Sets;
40 40
41 /** 41 /**
42 - * Manages inventory of end-station hosts using trivial in-memory 42 + * TEMPORARY: Manages inventory of end-station hosts using distributed
43 - * implementation. 43 + * structures implementation.
44 */ 44 */
45 //FIXME: I LIE I AM NOT DISTRIBUTED 45 //FIXME: I LIE I AM NOT DISTRIBUTED
46 @Component(immediate = true) 46 @Component(immediate = true)
......
1 +/**
2 + * Implementation of host store using Hazelcast distributed structures.
3 + */
4 +package org.onlab.onos.store.host.impl;
...@@ -28,7 +28,7 @@ import org.onlab.onos.store.AbstractStore; ...@@ -28,7 +28,7 @@ import org.onlab.onos.store.AbstractStore;
28 import org.slf4j.Logger; 28 import org.slf4j.Logger;
29 29
30 /** 30 /**
31 - * Manages inventory of topology snapshots using trivial in-memory 31 + * TEMPORARY: Manages inventory of topology snapshots using distributed
32 * structures implementation. 32 * structures implementation.
33 */ 33 */
34 //FIXME: I LIE I AM NOT DISTRIBUTED 34 //FIXME: I LIE I AM NOT DISTRIBUTED
......
1 +/**
2 + * Implementation of topology store using Hazelcast distributed structures.
3 + */
4 +package org.onlab.onos.store.topology.impl;
...@@ -201,7 +201,7 @@ public class DistributedDeviceStoreTest { ...@@ -201,7 +201,7 @@ public class DistributedDeviceStoreTest {
201 new DefaultPortDescription(P2, true) 201 new DefaultPortDescription(P2, true)
202 ); 202 );
203 203
204 - List<DeviceEvent> events = deviceStore.updatePorts(DID1, pds); 204 + List<DeviceEvent> events = deviceStore.updatePorts(PID, DID1, pds);
205 205
206 Set<PortNumber> expectedPorts = Sets.newHashSet(P1, P2); 206 Set<PortNumber> expectedPorts = Sets.newHashSet(P1, P2);
207 for (DeviceEvent event : events) { 207 for (DeviceEvent event : events) {
...@@ -220,7 +220,7 @@ public class DistributedDeviceStoreTest { ...@@ -220,7 +220,7 @@ public class DistributedDeviceStoreTest {
220 new DefaultPortDescription(P3, true) 220 new DefaultPortDescription(P3, true)
221 ); 221 );
222 222
223 - events = deviceStore.updatePorts(DID1, pds2); 223 + events = deviceStore.updatePorts(PID, DID1, pds2);
224 assertFalse("event should be triggered", events.isEmpty()); 224 assertFalse("event should be triggered", events.isEmpty());
225 for (DeviceEvent event : events) { 225 for (DeviceEvent event : events) {
226 PortNumber num = event.port().number(); 226 PortNumber num = event.port().number();
...@@ -243,7 +243,7 @@ public class DistributedDeviceStoreTest { ...@@ -243,7 +243,7 @@ public class DistributedDeviceStoreTest {
243 new DefaultPortDescription(P1, false), 243 new DefaultPortDescription(P1, false),
244 new DefaultPortDescription(P2, true) 244 new DefaultPortDescription(P2, true)
245 ); 245 );
246 - events = deviceStore.updatePorts(DID1, pds3); 246 + events = deviceStore.updatePorts(PID, DID1, pds3);
247 assertFalse("event should be triggered", events.isEmpty()); 247 assertFalse("event should be triggered", events.isEmpty());
248 for (DeviceEvent event : events) { 248 for (DeviceEvent event : events) {
249 PortNumber num = event.port().number(); 249 PortNumber num = event.port().number();
...@@ -268,9 +268,9 @@ public class DistributedDeviceStoreTest { ...@@ -268,9 +268,9 @@ public class DistributedDeviceStoreTest {
268 List<PortDescription> pds = Arrays.<PortDescription>asList( 268 List<PortDescription> pds = Arrays.<PortDescription>asList(
269 new DefaultPortDescription(P1, true) 269 new DefaultPortDescription(P1, true)
270 ); 270 );
271 - deviceStore.updatePorts(DID1, pds); 271 + deviceStore.updatePorts(PID, DID1, pds);
272 272
273 - DeviceEvent event = deviceStore.updatePortStatus(DID1, 273 + DeviceEvent event = deviceStore.updatePortStatus(PID, DID1,
274 new DefaultPortDescription(P1, false)); 274 new DefaultPortDescription(P1, false));
275 assertEquals(PORT_UPDATED, event.type()); 275 assertEquals(PORT_UPDATED, event.type());
276 assertDevice(DID1, SW1, event.subject()); 276 assertDevice(DID1, SW1, event.subject());
...@@ -286,7 +286,7 @@ public class DistributedDeviceStoreTest { ...@@ -286,7 +286,7 @@ public class DistributedDeviceStoreTest {
286 new DefaultPortDescription(P1, true), 286 new DefaultPortDescription(P1, true),
287 new DefaultPortDescription(P2, true) 287 new DefaultPortDescription(P2, true)
288 ); 288 );
289 - deviceStore.updatePorts(DID1, pds); 289 + deviceStore.updatePorts(PID, DID1, pds);
290 290
291 Set<PortNumber> expectedPorts = Sets.newHashSet(P1, P2); 291 Set<PortNumber> expectedPorts = Sets.newHashSet(P1, P2);
292 List<Port> ports = deviceStore.getPorts(DID1); 292 List<Port> ports = deviceStore.getPorts(DID1);
...@@ -309,7 +309,7 @@ public class DistributedDeviceStoreTest { ...@@ -309,7 +309,7 @@ public class DistributedDeviceStoreTest {
309 new DefaultPortDescription(P1, true), 309 new DefaultPortDescription(P1, true),
310 new DefaultPortDescription(P2, false) 310 new DefaultPortDescription(P2, false)
311 ); 311 );
312 - deviceStore.updatePorts(DID1, pds); 312 + deviceStore.updatePorts(PID, DID1, pds);
313 313
314 Port port1 = deviceStore.getPort(DID1, P1); 314 Port port1 = deviceStore.getPort(DID1, P1);
315 assertEquals(P1, port1.number()); 315 assertEquals(P1, port1.number());
......
1 +package org.onlab.onos.store.serializers;
2 +
3 +import java.util.Collections;
4 +import java.util.HashMap;
5 +import java.util.Map;
6 +
7 +import org.onlab.util.KryoPool.FamilySerializer;
8 +
9 +import com.esotericsoftware.kryo.Kryo;
10 +import com.esotericsoftware.kryo.io.Input;
11 +import com.esotericsoftware.kryo.io.Output;
12 +import com.esotericsoftware.kryo.serializers.MapSerializer;
13 +import com.google.common.collect.ImmutableMap;
14 +
15 +/**
16 +* Kryo Serializer for {@link ImmutableMap}.
17 +*/
18 +public class ImmutableMapSerializer extends FamilySerializer<ImmutableMap<?, ?>> {
19 +
20 + private final MapSerializer mapSerializer = new MapSerializer();
21 +
22 + public ImmutableMapSerializer() {
23 + // non-null, immutable
24 + super(false, true);
25 + }
26 +
27 + @Override
28 + public void write(Kryo kryo, Output output, ImmutableMap<?, ?> object) {
29 + // wrapping with unmodifiableMap proxy
30 + // to avoid Kryo from writing only the reference marker of this instance,
31 + // which will be embedded right before this method call.
32 + kryo.writeObject(output, Collections.unmodifiableMap(object), mapSerializer);
33 + }
34 +
35 + @Override
36 + public ImmutableMap<?, ?> read(Kryo kryo, Input input,
37 + Class<ImmutableMap<?, ?>> type) {
38 + Map<?, ?> map = kryo.readObject(input, HashMap.class, mapSerializer);
39 + return ImmutableMap.copyOf(map);
40 + }
41 +
42 + @Override
43 + public void registerFamilies(Kryo kryo) {
44 + kryo.register(ImmutableMap.of().getClass(), this);
45 + kryo.register(ImmutableMap.of(1, 2).getClass(), this);
46 + kryo.register(ImmutableMap.of(1, 2, 3, 4).getClass(), this);
47 + // TODO register required ImmutableMap variants
48 + }
49 +}
1 +package org.onlab.onos.store.serializers;
2 +
3 +import java.util.ArrayList;
4 +import java.util.List;
5 +
6 +import org.onlab.util.KryoPool.FamilySerializer;
7 +
8 +import com.esotericsoftware.kryo.Kryo;
9 +import com.esotericsoftware.kryo.io.Input;
10 +import com.esotericsoftware.kryo.io.Output;
11 +import com.esotericsoftware.kryo.serializers.CollectionSerializer;
12 +import com.google.common.collect.ImmutableSet;
13 +
14 +/**
15 +* Kryo Serializer for {@link ImmutableSet}.
16 +*/
17 +public class ImmutableSetSerializer extends FamilySerializer<ImmutableSet<?>> {
18 +
19 + private final CollectionSerializer serializer = new CollectionSerializer();
20 +
21 + public ImmutableSetSerializer() {
22 + // non-null, immutable
23 + super(false, true);
24 + }
25 +
26 + @Override
27 + public void write(Kryo kryo, Output output, ImmutableSet<?> object) {
28 + kryo.writeObject(output, object.asList(), serializer);
29 + }
30 +
31 + @Override
32 + public ImmutableSet<?> read(Kryo kryo, Input input,
33 + Class<ImmutableSet<?>> type) {
34 + List<?> elms = kryo.readObject(input, ArrayList.class, serializer);
35 + return ImmutableSet.copyOf(elms);
36 + }
37 +
38 + @Override
39 + public void registerFamilies(Kryo kryo) {
40 + kryo.register(ImmutableSet.of().getClass(), this);
41 + kryo.register(ImmutableSet.of(1).getClass(), this);
42 + kryo.register(ImmutableSet.of(1, 2).getClass(), this);
43 + // TODO register required ImmutableSet variants
44 + }
45 +}
1 package org.onlab.onos.store.serializers; 1 package org.onlab.onos.store.serializers;
2 2
3 import java.net.URI; 3 import java.net.URI;
4 +import java.nio.ByteBuffer;
4 import java.util.ArrayList; 5 import java.util.ArrayList;
5 import java.util.HashMap; 6 import java.util.HashMap;
6 7
...@@ -100,4 +101,14 @@ public class KryoSerializationManager implements KryoSerializationService { ...@@ -100,4 +101,14 @@ public class KryoSerializationManager implements KryoSerializationService {
100 return serializerPool.deserialize(bytes); 101 return serializerPool.deserialize(bytes);
101 } 102 }
102 103
104 + @Override
105 + public void serialize(Object obj, ByteBuffer buffer) {
106 + serializerPool.serialize(obj, buffer);
107 + }
108 +
109 + @Override
110 + public <T> T deserialize(ByteBuffer buffer) {
111 + return serializerPool.deserialize(buffer);
112 + }
113 +
103 } 114 }
......
1 package org.onlab.onos.store.serializers; 1 package org.onlab.onos.store.serializers;
2 2
3 +import java.nio.ByteBuffer;
4 +
3 // TODO: To be replaced with SerializationService from IOLoop activity 5 // TODO: To be replaced with SerializationService from IOLoop activity
4 /** 6 /**
5 * Service to serialize Objects into byte array. 7 * Service to serialize Objects into byte array.
...@@ -16,6 +18,15 @@ public interface KryoSerializationService { ...@@ -16,6 +18,15 @@ public interface KryoSerializationService {
16 public byte[] serialize(final Object obj); 18 public byte[] serialize(final Object obj);
17 19
18 /** 20 /**
21 + * Serializes the specified object into bytes using one of the
22 + * pre-registered serializers.
23 + *
24 + * @param obj object to be serialized
25 + * @param buffer to write serialized bytes
26 + */
27 + public void serialize(final Object obj, ByteBuffer buffer);
28 +
29 + /**
19 * Deserializes the specified bytes into an object using one of the 30 * Deserializes the specified bytes into an object using one of the
20 * pre-registered serializers. 31 * pre-registered serializers.
21 * 32 *
...@@ -24,4 +35,12 @@ public interface KryoSerializationService { ...@@ -24,4 +35,12 @@ public interface KryoSerializationService {
24 */ 35 */
25 public <T> T deserialize(final byte[] bytes); 36 public <T> T deserialize(final byte[] bytes);
26 37
38 + /**
39 + * Deserializes the specified bytes into an object using one of the
40 + * pre-registered serializers.
41 + *
42 + * @param buffer bytes to be deserialized
43 + * @return deserialized object
44 + */
45 + public <T> T deserialize(final ByteBuffer buffer);
27 } 46 }
......
1 +package org.onlab.onos.store.serializers;
2 +
3 +import org.onlab.onos.net.MastershipRole;
4 +
5 +import com.esotericsoftware.kryo.Kryo;
6 +import com.esotericsoftware.kryo.Serializer;
7 +import com.esotericsoftware.kryo.io.Input;
8 +import com.esotericsoftware.kryo.io.Output;
9 +
10 +/**
11 + * Kryo Serializer for {@link org.onlab.onos.net.MastershipRole}.
12 + */
13 +public class MastershipRoleSerializer extends Serializer<MastershipRole> {
14 +
15 + @Override
16 + public MastershipRole read(Kryo kryo, Input input, Class<MastershipRole> type) {
17 + final String role = kryo.readObject(input, String.class);
18 + return MastershipRole.valueOf(role);
19 + }
20 +
21 + @Override
22 + public void write(Kryo kryo, Output output, MastershipRole object) {
23 + kryo.writeObject(output, object.toString());
24 + }
25 +
26 +}
1 +package org.onlab.onos.store.serializers;
2 +
3 +import org.onlab.onos.cluster.MastershipTerm;
4 +import org.onlab.onos.cluster.NodeId;
5 +
6 +import com.esotericsoftware.kryo.Kryo;
7 +import com.esotericsoftware.kryo.Serializer;
8 +import com.esotericsoftware.kryo.io.Input;
9 +import com.esotericsoftware.kryo.io.Output;
10 +
11 +/**
12 + * Kryo Serializer for {@link org.onlab.onos.cluster.MastershipTerm}.
13 + */
14 +public class MastershipTermSerializer extends Serializer<MastershipTerm> {
15 +
16 + @Override
17 + public MastershipTerm read(Kryo kryo, Input input, Class<MastershipTerm> type) {
18 + final NodeId node = new NodeId(kryo.readObject(input, String.class));
19 + final int term = input.readInt();
20 + return MastershipTerm.of(node, term);
21 + }
22 +
23 + @Override
24 + public void write(Kryo kryo, Output output, MastershipTerm object) {
25 + output.writeString(object.master().toString());
26 + output.writeInt(object.termNumber());
27 + }
28 +
29 +}
1 +package org.onlab.onos.store.serializers;
2 +
3 +import static org.onlab.onos.net.DeviceId.deviceId;
4 +import static org.onlab.onos.net.PortNumber.portNumber;
5 +
6 +import java.net.URI;
7 +import java.nio.ByteBuffer;
8 +import java.util.ArrayList;
9 +import java.util.HashMap;
10 +
11 +import org.junit.After;
12 +import org.junit.Before;
13 +import org.junit.BeforeClass;
14 +import org.junit.Test;
15 +import org.onlab.onos.cluster.MastershipTerm;
16 +import org.onlab.onos.cluster.NodeId;
17 +import org.onlab.onos.net.ConnectPoint;
18 +import org.onlab.onos.net.DefaultDevice;
19 +import org.onlab.onos.net.DefaultLink;
20 +import org.onlab.onos.net.DefaultPort;
21 +import org.onlab.onos.net.Device;
22 +import org.onlab.onos.net.DeviceId;
23 +import org.onlab.onos.net.Link;
24 +import org.onlab.onos.net.LinkKey;
25 +import org.onlab.onos.net.MastershipRole;
26 +import org.onlab.onos.net.PortNumber;
27 +import org.onlab.onos.net.provider.ProviderId;
28 +import org.onlab.packet.IpPrefix;
29 +import org.onlab.util.KryoPool;
30 +
31 +import com.google.common.collect.ImmutableMap;
32 +import com.google.common.collect.ImmutableSet;
33 +import com.google.common.testing.EqualsTester;
34 +
35 +import de.javakaffee.kryoserializers.URISerializer;
36 +
37 +public class KryoSerializerTests {
38 + private static final ProviderId PID = new ProviderId("of", "foo");
39 + private static final DeviceId DID1 = deviceId("of:foo");
40 + private static final DeviceId DID2 = deviceId("of:bar");
41 + private static final PortNumber P1 = portNumber(1);
42 + private static final PortNumber P2 = portNumber(2);
43 + private static final ConnectPoint CP1 = new ConnectPoint(DID1, P1);
44 + private static final ConnectPoint CP2 = new ConnectPoint(DID2, P2);
45 + private static final String MFR = "whitebox";
46 + private static final String HW = "1.1.x";
47 + private static final String SW1 = "3.8.1";
48 + private static final String SW2 = "3.9.5";
49 + private static final String SN = "43311-12345";
50 + private static final Device DEV1 = new DefaultDevice(PID, DID1, Device.Type.SWITCH, MFR, HW, SW1, SN);
51 +
52 + private static KryoPool kryos;
53 +
54 + @BeforeClass
55 + public static void setUpBeforeClass() throws Exception {
56 + kryos = KryoPool.newBuilder()
57 + .register(
58 + ArrayList.class,
59 + HashMap.class
60 + )
61 + .register(
62 + Device.Type.class,
63 + Link.Type.class
64 +
65 +// ControllerNode.State.class,
66 +// DefaultControllerNode.class,
67 +// MastershipRole.class,
68 +// Port.class,
69 +// Element.class,
70 + )
71 + .register(ConnectPoint.class, new ConnectPointSerializer())
72 + .register(DefaultLink.class, new DefaultLinkSerializer())
73 + .register(DefaultPort.class, new DefaultPortSerializer())
74 + .register(DeviceId.class, new DeviceIdSerializer())
75 + .register(ImmutableMap.class, new ImmutableMapSerializer())
76 + .register(ImmutableSet.class, new ImmutableSetSerializer())
77 + .register(IpPrefix.class, new IpPrefixSerializer())
78 + .register(LinkKey.class, new LinkKeySerializer())
79 + .register(NodeId.class, new NodeIdSerializer())
80 + .register(PortNumber.class, new PortNumberSerializer())
81 + .register(ProviderId.class, new ProviderIdSerializer())
82 +
83 + .register(DefaultDevice.class)
84 +
85 + .register(URI.class, new URISerializer())
86 +
87 + .register(MastershipRole.class, new MastershipRoleSerializer())
88 + .register(MastershipTerm.class, new MastershipTermSerializer())
89 + .build();
90 + }
91 +
92 + @Before
93 + public void setUp() throws Exception {
94 + }
95 +
96 + @After
97 + public void tearDown() throws Exception {
98 + // removing Kryo instance to use fresh Kryo on each tests
99 + kryos.getKryo();
100 + }
101 +
102 + private static <T> void testSerialized(T original) {
103 + ByteBuffer buffer = ByteBuffer.allocate(1 * 1024 * 1024);
104 + kryos.serialize(original, buffer);
105 + buffer.flip();
106 + T copy = kryos.deserialize(buffer);
107 +
108 + new EqualsTester()
109 + .addEqualityGroup(original, copy)
110 + .testEquals();
111 + }
112 +
113 +
114 + @Test
115 + public final void test() {
116 + testSerialized(new ConnectPoint(DID1, P1));
117 + testSerialized(new DefaultLink(PID, CP1, CP2, Link.Type.DIRECT));
118 + testSerialized(new DefaultPort(DEV1, P1, true));
119 + testSerialized(DID1);
120 + testSerialized(ImmutableMap.of(DID1, DEV1, DID2, DEV1));
121 + testSerialized(ImmutableMap.of(DID1, DEV1));
122 + testSerialized(ImmutableMap.of());
123 + testSerialized(ImmutableSet.of(DID1, DID2));
124 + testSerialized(ImmutableSet.of(DID1));
125 + testSerialized(ImmutableSet.of());
126 + testSerialized(IpPrefix.valueOf("192.168.0.1/24"));
127 + testSerialized(new LinkKey(CP1, CP2));
128 + testSerialized(new NodeId("SomeNodeIdentifier"));
129 + testSerialized(P1);
130 + testSerialized(PID);
131 + }
132 +
133 +}
1 -package org.onlab.onos.net.trivial.impl; 1 +package org.onlab.onos.store.trivial.impl;
2 2
3 import com.google.common.collect.ImmutableMap; 3 import com.google.common.collect.ImmutableMap;
4 import com.google.common.collect.ImmutableSet; 4 import com.google.common.collect.ImmutableSet;
......
1 -package org.onlab.onos.net.trivial.impl; 1 +package org.onlab.onos.store.trivial.impl;
2 2
3 import org.onlab.graph.AdjacencyListsGraph; 3 import org.onlab.graph.AdjacencyListsGraph;
4 import org.onlab.onos.net.topology.TopologyEdge; 4 import org.onlab.onos.net.topology.TopologyEdge;
......
1 -package org.onlab.onos.net.trivial.impl; 1 +package org.onlab.onos.store.trivial.impl;
2 2
3 import org.apache.felix.scr.annotations.Component; 3 import org.apache.felix.scr.annotations.Component;
4 import org.apache.felix.scr.annotations.Service; 4 import org.apache.felix.scr.annotations.Service;
......
1 -package org.onlab.onos.net.trivial.impl; 1 +package org.onlab.onos.store.trivial.impl;
2 2
3 import org.onlab.onos.net.DeviceId; 3 import org.onlab.onos.net.DeviceId;
4 4
......
1 -package org.onlab.onos.net.trivial.impl; 1 +package org.onlab.onos.store.trivial.impl;
2 2
3 import com.google.common.collect.ImmutableSet; 3 import com.google.common.collect.ImmutableSet;
4 import org.apache.felix.scr.annotations.Activate; 4 import org.apache.felix.scr.annotations.Activate;
......
1 -package org.onlab.onos.net.trivial.impl; 1 +package org.onlab.onos.store.trivial.impl;
2 2
3 import com.google.common.collect.FluentIterable; 3 import com.google.common.collect.FluentIterable;
4 import com.google.common.collect.ImmutableList; 4 import com.google.common.collect.ImmutableList;
...@@ -143,7 +143,7 @@ public class SimpleDeviceStore ...@@ -143,7 +143,7 @@ public class SimpleDeviceStore
143 } 143 }
144 144
145 @Override 145 @Override
146 - public List<DeviceEvent> updatePorts(DeviceId deviceId, 146 + public List<DeviceEvent> updatePorts(ProviderId providerId, DeviceId deviceId,
147 List<PortDescription> portDescriptions) { 147 List<PortDescription> portDescriptions) {
148 List<DeviceEvent> events = new ArrayList<>(); 148 List<DeviceEvent> events = new ArrayList<>();
149 synchronized (this) { 149 synchronized (this) {
...@@ -221,7 +221,7 @@ public class SimpleDeviceStore ...@@ -221,7 +221,7 @@ public class SimpleDeviceStore
221 } 221 }
222 222
223 @Override 223 @Override
224 - public DeviceEvent updatePortStatus(DeviceId deviceId, 224 + public DeviceEvent updatePortStatus(ProviderId providerId, DeviceId deviceId,
225 PortDescription portDescription) { 225 PortDescription portDescription) {
226 synchronized (this) { 226 synchronized (this) {
227 Device device = devices.get(deviceId); 227 Device device = devices.get(deviceId);
......
1 -package org.onlab.onos.net.trivial.impl; 1 +package org.onlab.onos.store.trivial.impl;
2 2
3 import static org.onlab.onos.net.flow.FlowRuleEvent.Type.RULE_ADDED; 3 import static org.onlab.onos.net.flow.FlowRuleEvent.Type.RULE_ADDED;
4 import static org.onlab.onos.net.flow.FlowRuleEvent.Type.RULE_REMOVED; 4 import static org.onlab.onos.net.flow.FlowRuleEvent.Type.RULE_REMOVED;
......
1 -package org.onlab.onos.net.trivial.impl; 1 +package org.onlab.onos.store.trivial.impl;
2 2
3 import static org.onlab.onos.net.host.HostEvent.Type.HOST_ADDED; 3 import static org.onlab.onos.net.host.HostEvent.Type.HOST_ADDED;
4 import static org.onlab.onos.net.host.HostEvent.Type.HOST_MOVED; 4 import static org.onlab.onos.net.host.HostEvent.Type.HOST_MOVED;
......
1 -package org.onlab.onos.net.trivial.impl; 1 +package org.onlab.onos.store.trivial.impl;
2 2
3 import com.google.common.collect.HashMultimap; 3 import com.google.common.collect.HashMultimap;
4 import com.google.common.collect.ImmutableSet; 4 import com.google.common.collect.ImmutableSet;
......
1 -package org.onlab.onos.net.trivial.impl; 1 +package org.onlab.onos.store.trivial.impl;
2 2
3 import static org.slf4j.LoggerFactory.getLogger; 3 import static org.slf4j.LoggerFactory.getLogger;
4 4
...@@ -7,8 +7,6 @@ import java.util.HashMap; ...@@ -7,8 +7,6 @@ import java.util.HashMap;
7 import java.util.HashSet; 7 import java.util.HashSet;
8 import java.util.Map; 8 import java.util.Map;
9 import java.util.Set; 9 import java.util.Set;
10 -import java.util.concurrent.ConcurrentHashMap;
11 -import java.util.concurrent.ConcurrentMap;
12 import java.util.concurrent.atomic.AtomicInteger; 10 import java.util.concurrent.atomic.AtomicInteger;
13 11
14 import org.apache.felix.scr.annotations.Activate; 12 import org.apache.felix.scr.annotations.Activate;
...@@ -48,8 +46,10 @@ public class SimpleMastershipStore ...@@ -48,8 +46,10 @@ public class SimpleMastershipStore
48 new DefaultControllerNode(new NodeId("local"), LOCALHOST); 46 new DefaultControllerNode(new NodeId("local"), LOCALHOST);
49 47
50 //devices mapped to their masters, to emulate multiple nodes 48 //devices mapped to their masters, to emulate multiple nodes
51 - protected final ConcurrentMap<DeviceId, NodeId> masterMap = 49 + protected final Map<DeviceId, NodeId> masterMap = new HashMap<>();
52 - new ConcurrentHashMap<>(); 50 + //emulate backups with pile of nodes
51 + protected final Set<NodeId> backups = new HashSet<>();
52 + //terms
53 protected final Map<DeviceId, AtomicInteger> termMap = new HashMap<>(); 53 protected final Map<DeviceId, AtomicInteger> termMap = new HashMap<>();
54 54
55 @Activate 55 @Activate
...@@ -64,26 +64,30 @@ public class SimpleMastershipStore ...@@ -64,26 +64,30 @@ public class SimpleMastershipStore
64 64
65 @Override 65 @Override
66 public MastershipEvent setMaster(NodeId nodeId, DeviceId deviceId) { 66 public MastershipEvent setMaster(NodeId nodeId, DeviceId deviceId) {
67 + MastershipRole role = getRole(nodeId, deviceId);
67 68
68 - NodeId node = masterMap.get(deviceId);
69 - if (node == null) {
70 synchronized (this) { 69 synchronized (this) {
70 + switch (role) {
71 + case MASTER:
72 + return null;
73 + case STANDBY:
74 + masterMap.put(deviceId, nodeId);
75 + termMap.get(deviceId).incrementAndGet();
76 + backups.add(nodeId);
77 + break;
78 + case NONE:
71 masterMap.put(deviceId, nodeId); 79 masterMap.put(deviceId, nodeId);
72 termMap.put(deviceId, new AtomicInteger()); 80 termMap.put(deviceId, new AtomicInteger());
81 + backups.add(nodeId);
82 + break;
83 + default:
84 + log.warn("unknown Mastership Role {}", role);
85 + return null;
73 } 86 }
74 - return new MastershipEvent(MASTER_CHANGED, deviceId, nodeId);
75 } 87 }
76 88
77 - if (node.equals(nodeId)) {
78 - return null;
79 - } else {
80 - synchronized (this) {
81 - masterMap.put(deviceId, nodeId);
82 - termMap.get(deviceId).incrementAndGet();
83 return new MastershipEvent(MASTER_CHANGED, deviceId, nodeId); 89 return new MastershipEvent(MASTER_CHANGED, deviceId, nodeId);
84 } 90 }
85 - }
86 - }
87 91
88 @Override 92 @Override
89 public NodeId getMaster(DeviceId deviceId) { 93 public NodeId getMaster(DeviceId deviceId) {
...@@ -103,34 +107,111 @@ public class SimpleMastershipStore ...@@ -103,34 +107,111 @@ public class SimpleMastershipStore
103 107
104 @Override 108 @Override
105 public MastershipRole requestRole(DeviceId deviceId) { 109 public MastershipRole requestRole(DeviceId deviceId) {
106 - return getRole(instance.id(), deviceId); 110 + //query+possible reelection
111 + NodeId node = instance.id();
112 + MastershipRole role = getRole(node, deviceId);
113 +
114 + switch (role) {
115 + case MASTER:
116 + break;
117 + case STANDBY:
118 + synchronized (this) {
119 + //try to "re-elect", since we're really not distributed
120 + NodeId rel = reelect(node);
121 + if (rel == null) {
122 + masterMap.put(deviceId, node);
123 + termMap.put(deviceId, new AtomicInteger());
124 + role = MastershipRole.MASTER;
125 + }
126 + backups.add(node);
127 + }
128 + break;
129 + case NONE:
130 + //first to get to it, say we are master
131 + synchronized (this) {
132 + masterMap.put(deviceId, node);
133 + termMap.put(deviceId, new AtomicInteger());
134 + backups.add(node);
135 + role = MastershipRole.MASTER;
136 + }
137 + break;
138 + default:
139 + log.warn("unknown Mastership Role {}", role);
140 + }
141 + return role;
107 } 142 }
108 143
109 @Override 144 @Override
110 public MastershipRole getRole(NodeId nodeId, DeviceId deviceId) { 145 public MastershipRole getRole(NodeId nodeId, DeviceId deviceId) {
111 - NodeId node = masterMap.get(deviceId); 146 + //just query
147 + NodeId current = masterMap.get(deviceId);
112 MastershipRole role; 148 MastershipRole role;
113 - if (node != null) { 149 +
114 - if (node.equals(nodeId)) { 150 + if (current == null) {
115 - role = MastershipRole.MASTER; 151 + if (backups.contains(nodeId)) {
116 - } else {
117 role = MastershipRole.STANDBY; 152 role = MastershipRole.STANDBY;
153 + } else {
154 + role = MastershipRole.NONE;
118 } 155 }
119 } else { 156 } else {
120 - //masterMap doesn't contain it. 157 + if (current.equals(nodeId)) {
121 role = MastershipRole.MASTER; 158 role = MastershipRole.MASTER;
122 - masterMap.put(deviceId, nodeId); 159 + } else {
160 + role = MastershipRole.STANDBY;
161 + }
123 } 162 }
124 return role; 163 return role;
125 } 164 }
126 165
127 @Override 166 @Override
128 public MastershipTerm getTermFor(DeviceId deviceId) { 167 public MastershipTerm getTermFor(DeviceId deviceId) {
129 - if (masterMap.get(deviceId) == null) { 168 + if ((masterMap.get(deviceId) == null) ||
169 + (termMap.get(deviceId) == null)) {
130 return null; 170 return null;
131 } 171 }
132 return MastershipTerm.of( 172 return MastershipTerm.of(
133 masterMap.get(deviceId), termMap.get(deviceId).get()); 173 masterMap.get(deviceId), termMap.get(deviceId).get());
134 } 174 }
135 175
176 + @Override
177 + public MastershipEvent unsetMaster(NodeId nodeId, DeviceId deviceId) {
178 + MastershipRole role = getRole(nodeId, deviceId);
179 + synchronized (this) {
180 + switch (role) {
181 + case MASTER:
182 + NodeId backup = reelect(nodeId);
183 + if (backup == null) {
184 + masterMap.remove(deviceId);
185 + } else {
186 + masterMap.put(deviceId, backup);
187 + termMap.get(deviceId).incrementAndGet();
188 + return new MastershipEvent(MASTER_CHANGED, deviceId, backup);
189 + }
190 + case STANDBY:
191 + case NONE:
192 + if (!termMap.containsKey(deviceId)) {
193 + termMap.put(deviceId, new AtomicInteger());
194 + }
195 + backups.add(nodeId);
196 + break;
197 + default:
198 + log.warn("unknown Mastership Role {}", role);
199 + }
200 + }
201 + return null;
202 + }
203 +
204 + //dumbly selects next-available node that's not the current one
205 + //emulate leader election
206 + private NodeId reelect(NodeId nodeId) {
207 + NodeId backup = null;
208 + for (NodeId n : backups) {
209 + if (!n.equals(nodeId)) {
210 + backup = n;
211 + break;
212 + }
213 + }
214 + return backup;
215 + }
216 +
136 } 217 }
......
1 -package org.onlab.onos.net.trivial.impl; 1 +package org.onlab.onos.store.trivial.impl;
2 2
3 import org.apache.felix.scr.annotations.Activate; 3 import org.apache.felix.scr.annotations.Activate;
4 import org.apache.felix.scr.annotations.Component; 4 import org.apache.felix.scr.annotations.Component;
......
...@@ -2,4 +2,4 @@ ...@@ -2,4 +2,4 @@
2 * Implementations of in-memory stores suitable for unit testing and 2 * Implementations of in-memory stores suitable for unit testing and
3 * experimentation; not for production use. 3 * experimentation; not for production use.
4 */ 4 */
5 -package org.onlab.onos.net.trivial.impl; 5 +package org.onlab.onos.store.trivial.impl;
......
1 -package org.onlab.onos.net.trivial.impl; 1 +package org.onlab.onos.store.trivial.impl;
2 2
3 import org.junit.Before; 3 import org.junit.Before;
4 import org.junit.Test; 4 import org.junit.Test;
......
1 /** 1 /**
2 * 2 *
3 */ 3 */
4 -package org.onlab.onos.net.trivial.impl; 4 +package org.onlab.onos.store.trivial.impl;
5 5
6 import static org.junit.Assert.*; 6 import static org.junit.Assert.*;
7 import static org.onlab.onos.net.Device.Type.SWITCH; 7 import static org.onlab.onos.net.Device.Type.SWITCH;
...@@ -182,7 +182,7 @@ public class SimpleDeviceStoreTest { ...@@ -182,7 +182,7 @@ public class SimpleDeviceStoreTest {
182 new DefaultPortDescription(P2, true) 182 new DefaultPortDescription(P2, true)
183 ); 183 );
184 184
185 - List<DeviceEvent> events = deviceStore.updatePorts(DID1, pds); 185 + List<DeviceEvent> events = deviceStore.updatePorts(PID, DID1, pds);
186 186
187 Set<PortNumber> expectedPorts = Sets.newHashSet(P1, P2); 187 Set<PortNumber> expectedPorts = Sets.newHashSet(P1, P2);
188 for (DeviceEvent event : events) { 188 for (DeviceEvent event : events) {
...@@ -201,7 +201,7 @@ public class SimpleDeviceStoreTest { ...@@ -201,7 +201,7 @@ public class SimpleDeviceStoreTest {
201 new DefaultPortDescription(P3, true) 201 new DefaultPortDescription(P3, true)
202 ); 202 );
203 203
204 - events = deviceStore.updatePorts(DID1, pds2); 204 + events = deviceStore.updatePorts(PID, DID1, pds2);
205 assertFalse("event should be triggered", events.isEmpty()); 205 assertFalse("event should be triggered", events.isEmpty());
206 for (DeviceEvent event : events) { 206 for (DeviceEvent event : events) {
207 PortNumber num = event.port().number(); 207 PortNumber num = event.port().number();
...@@ -224,7 +224,7 @@ public class SimpleDeviceStoreTest { ...@@ -224,7 +224,7 @@ public class SimpleDeviceStoreTest {
224 new DefaultPortDescription(P1, false), 224 new DefaultPortDescription(P1, false),
225 new DefaultPortDescription(P2, true) 225 new DefaultPortDescription(P2, true)
226 ); 226 );
227 - events = deviceStore.updatePorts(DID1, pds3); 227 + events = deviceStore.updatePorts(PID, DID1, pds3);
228 assertFalse("event should be triggered", events.isEmpty()); 228 assertFalse("event should be triggered", events.isEmpty());
229 for (DeviceEvent event : events) { 229 for (DeviceEvent event : events) {
230 PortNumber num = event.port().number(); 230 PortNumber num = event.port().number();
...@@ -249,9 +249,9 @@ public class SimpleDeviceStoreTest { ...@@ -249,9 +249,9 @@ public class SimpleDeviceStoreTest {
249 List<PortDescription> pds = Arrays.<PortDescription>asList( 249 List<PortDescription> pds = Arrays.<PortDescription>asList(
250 new DefaultPortDescription(P1, true) 250 new DefaultPortDescription(P1, true)
251 ); 251 );
252 - deviceStore.updatePorts(DID1, pds); 252 + deviceStore.updatePorts(PID, DID1, pds);
253 253
254 - DeviceEvent event = deviceStore.updatePortStatus(DID1, 254 + DeviceEvent event = deviceStore.updatePortStatus(PID, DID1,
255 new DefaultPortDescription(P1, false)); 255 new DefaultPortDescription(P1, false));
256 assertEquals(PORT_UPDATED, event.type()); 256 assertEquals(PORT_UPDATED, event.type());
257 assertDevice(DID1, SW1, event.subject()); 257 assertDevice(DID1, SW1, event.subject());
...@@ -267,7 +267,7 @@ public class SimpleDeviceStoreTest { ...@@ -267,7 +267,7 @@ public class SimpleDeviceStoreTest {
267 new DefaultPortDescription(P1, true), 267 new DefaultPortDescription(P1, true),
268 new DefaultPortDescription(P2, true) 268 new DefaultPortDescription(P2, true)
269 ); 269 );
270 - deviceStore.updatePorts(DID1, pds); 270 + deviceStore.updatePorts(PID, DID1, pds);
271 271
272 Set<PortNumber> expectedPorts = Sets.newHashSet(P1, P2); 272 Set<PortNumber> expectedPorts = Sets.newHashSet(P1, P2);
273 List<Port> ports = deviceStore.getPorts(DID1); 273 List<Port> ports = deviceStore.getPorts(DID1);
...@@ -290,7 +290,7 @@ public class SimpleDeviceStoreTest { ...@@ -290,7 +290,7 @@ public class SimpleDeviceStoreTest {
290 new DefaultPortDescription(P1, true), 290 new DefaultPortDescription(P1, true),
291 new DefaultPortDescription(P2, false) 291 new DefaultPortDescription(P2, false)
292 ); 292 );
293 - deviceStore.updatePorts(DID1, pds); 293 + deviceStore.updatePorts(PID, DID1, pds);
294 294
295 Port port1 = deviceStore.getPort(DID1, P1); 295 Port port1 = deviceStore.getPort(DID1, P1);
296 assertEquals(P1, port1.number()); 296 assertEquals(P1, port1.number());
......
1 -package org.onlab.onos.net.trivial.impl; 1 +package org.onlab.onos.store.trivial.impl;
2 2
3 import static org.junit.Assert.*; 3 import static org.junit.Assert.*;
4 import static org.onlab.onos.net.DeviceId.deviceId; 4 import static org.onlab.onos.net.DeviceId.deviceId;
......
1 +package org.onlab.onos.store.trivial.impl;
2 +
3 +import java.util.Set;
4 +import java.util.concurrent.atomic.AtomicInteger;
5 +
6 +import org.junit.After;
7 +import org.junit.Before;
8 +import org.junit.Test;
9 +import org.onlab.onos.cluster.MastershipTerm;
10 +import org.onlab.onos.cluster.NodeId;
11 +import org.onlab.onos.net.DeviceId;
12 +
13 +import com.google.common.collect.Sets;
14 +
15 +import static org.junit.Assert.assertEquals;
16 +import static org.junit.Assert.assertNull;
17 +import static org.junit.Assert.assertTrue;
18 +import static org.onlab.onos.net.MastershipRole.*;
19 +import static org.onlab.onos.cluster.MastershipEvent.Type.*;
20 +
21 +/**
22 + * Test for the simple MastershipStore implementation.
23 + */
24 +public class SimpleMastershipStoreTest {
25 +
26 + private static final DeviceId DID1 = DeviceId.deviceId("of:01");
27 + private static final DeviceId DID2 = DeviceId.deviceId("of:02");
28 + private static final DeviceId DID3 = DeviceId.deviceId("of:03");
29 + private static final DeviceId DID4 = DeviceId.deviceId("of:04");
30 +
31 + private static final NodeId N1 = new NodeId("local");
32 + private static final NodeId N2 = new NodeId("other");
33 +
34 + private SimpleMastershipStore sms;
35 +
36 + @Before
37 + public void setUp() throws Exception {
38 + sms = new SimpleMastershipStore();
39 + sms.activate();
40 + }
41 +
42 + @After
43 + public void tearDown() throws Exception {
44 + sms.deactivate();
45 + }
46 +
47 + @Test
48 + public void getRole() {
49 + //special case, no backup or master
50 + put(DID1, N1, false, false);
51 + assertEquals("wrong role", NONE, sms.getRole(N1, DID1));
52 +
53 + //backup exists but we aren't mapped
54 + put(DID2, N1, false, true);
55 + assertEquals("wrong role", STANDBY, sms.getRole(N1, DID2));
56 +
57 + //N2 is master
58 + put(DID3, N2, true, true);
59 + assertEquals("wrong role", MASTER, sms.getRole(N2, DID3));
60 +
61 + //N2 is master but N1 is only in backups set
62 + put(DID4, N2, true, false);
63 + assertEquals("wrong role", STANDBY, sms.getRole(N1, DID4));
64 + }
65 +
66 + @Test
67 + public void getMaster() {
68 + put(DID3, N2, true, true);
69 + assertEquals("wrong role", MASTER, sms.getRole(N2, DID3));
70 + assertEquals("wrong device", N2, sms.getMaster(DID3));
71 + }
72 +
73 + @Test
74 + public void setMaster() {
75 + put(DID1, N1, false, false);
76 + assertEquals("wrong event", MASTER_CHANGED, sms.setMaster(N1, DID1).type());
77 + assertEquals("wrong role", MASTER, sms.getRole(N1, DID1));
78 + //set node that's already master - should be ignored
79 + assertNull("wrong event", sms.setMaster(N1, DID1));
80 +
81 + //set STANDBY to MASTER
82 + put(DID2, N1, false, true);
83 + assertEquals("wrong role", STANDBY, sms.getRole(N1, DID2));
84 + assertEquals("wrong event", MASTER_CHANGED, sms.setMaster(N1, DID2).type());
85 + assertEquals("wrong role", MASTER, sms.getRole(N1, DID2));
86 + }
87 +
88 + @Test
89 + public void getDevices() {
90 + Set<DeviceId> d = Sets.newHashSet(DID1, DID2);
91 +
92 + put(DID1, N2, true, true);
93 + put(DID2, N2, true, true);
94 + put(DID3, N1, true, true);
95 + assertTrue("wrong devices", d.equals(sms.getDevices(N2)));
96 + }
97 +
98 + @Test
99 + public void getTermFor() {
100 + put(DID1, N1, true, true);
101 + assertEquals("wrong term", MastershipTerm.of(N1, 0), sms.getTermFor(DID1));
102 +
103 + //switch to N2 and back - 2 term switches
104 + sms.setMaster(N2, DID1);
105 + sms.setMaster(N1, DID1);
106 + assertEquals("wrong term", MastershipTerm.of(N1, 2), sms.getTermFor(DID1));
107 + }
108 +
109 + @Test
110 + public void requestRole() {
111 + //NONE - become MASTER
112 + put(DID1, N1, false, false);
113 + assertEquals("wrong role", MASTER, sms.requestRole(DID1));
114 +
115 + //STANDBY without backup - become MASTER
116 + put(DID2, N1, false, true);
117 + assertEquals("wrong role", MASTER, sms.requestRole(DID2));
118 +
119 + //STANDBY with backup - stay STANDBY
120 + put(DID3, N2, false, true);
121 + assertEquals("wrong role", STANDBY, sms.requestRole(DID3));
122 +
123 + //local (N1) is MASTER - stay MASTER
124 + put(DID4, N1, true, true);
125 + assertEquals("wrong role", MASTER, sms.requestRole(DID4));
126 + }
127 +
128 + @Test
129 + public void unsetMaster() {
130 + //NONE - record backup but take no other action
131 + put(DID1, N1, false, false);
132 + sms.unsetMaster(N1, DID1);
133 + assertTrue("not backed up", sms.backups.contains(N1));
134 + sms.termMap.clear();
135 + sms.unsetMaster(N1, DID1);
136 + assertTrue("term not set", sms.termMap.containsKey(DID1));
137 +
138 + //no backup, MASTER
139 + put(DID1, N1, true, true);
140 + assertNull("wrong event", sms.unsetMaster(N1, DID1));
141 + assertNull("wrong node", sms.masterMap.get(DID1));
142 +
143 + //backup, switch
144 + sms.masterMap.clear();
145 + put(DID1, N1, true, true);
146 + put(DID2, N2, true, true);
147 + assertEquals("wrong event", MASTER_CHANGED, sms.unsetMaster(N1, DID1).type());
148 + }
149 +
150 + //helper to populate master/backup structures
151 + private void put(DeviceId dev, NodeId node, boolean store, boolean backup) {
152 + if (store) {
153 + sms.masterMap.put(dev, node);
154 + }
155 + if (backup) {
156 + sms.backups.add(node);
157 + }
158 + sms.termMap.put(dev, new AtomicInteger());
159 + }
160 +}
...@@ -419,7 +419,7 @@ ...@@ -419,7 +419,7 @@
419 <group> 419 <group>
420 <title>Core Subsystems</title> 420 <title>Core Subsystems</title>
421 <packages> 421 <packages>
422 - org.onlab.onos.cluster.impl:org.onlab.onos.net.device.impl:org.onlab.onos.net.link.impl:org.onlab.onos.net.host.impl:org.onlab.onos.net.topology.impl:org.onlab.onos.net.packet.impl:org.onlab.onos.net.flow.impl:org.onlab.onos.net.trivial.*:org.onlab.onos.net.*.impl:org.onlab.onos.event.impl:org.onlab.onos.store.* 422 + org.onlab.onos.cluster.impl:org.onlab.onos.net.device.impl:org.onlab.onos.net.link.impl:org.onlab.onos.net.host.impl:org.onlab.onos.net.topology.impl:org.onlab.onos.net.packet.impl:org.onlab.onos.net.flow.impl:org.onlab.onos.store.trivial.*:org.onlab.onos.net.*.impl:org.onlab.onos.event.impl:org.onlab.onos.store.*
423 </packages> 423 </packages>
424 </group> 424 </group>
425 <group> 425 <group>
......
...@@ -6,22 +6,21 @@ ...@@ -6,22 +6,21 @@
6 export ONOS_ROOT=${ONOS_ROOT:-~/onos-next} 6 export ONOS_ROOT=${ONOS_ROOT:-~/onos-next}
7 7
8 # Setup some environmental context for developers 8 # Setup some environmental context for developers
9 -export JAVA_HOME=$(/usr/libexec/java_home) 9 +export JAVA_HOME=$(/usr/libexec/java_home -v 1.7)
10 export MAVEN=${MAVEN:-~/Applications/apache-maven-3.2.2} 10 export MAVEN=${MAVEN:-~/Applications/apache-maven-3.2.2}
11 export KARAF=${KARAF:-~/Applications/apache-karaf-3.0.1} 11 export KARAF=${KARAF:-~/Applications/apache-karaf-3.0.1}
12 export KARAF_LOG=$KARAF/data/log/karaf.log 12 export KARAF_LOG=$KARAF/data/log/karaf.log
13 13
14 # Setup a path 14 # Setup a path
15 -export PS=":" 15 +export PATH="$PATH:$ONOS_ROOT/tools/dev/bin:$ONOS_ROOT/tools/test/bin"
16 -export PATH="$PATH:$ONOS_ROOT/tools/dev:$ONOS_ROOT/tools/build" 16 +export PATH="$PATH:$ONOS_ROOT/tools/build"
17 -export PATH="$PATH:$ONOS_ROOT/tools/test/bin"
18 export PATH="$PATH:$MAVEN/bin:$KARAF/bin" 17 export PATH="$PATH:$MAVEN/bin:$KARAF/bin"
19 export PATH="$PATH:." 18 export PATH="$PATH:."
20 19
21 # Convenience utility to warp to various ONOS source projects 20 # Convenience utility to warp to various ONOS source projects
22 # e.g. 'o api', 'o dev', 'o' 21 # e.g. 'o api', 'o dev', 'o'
23 function o { 22 function o {
24 - cd $(find $ONOS_ROOT/ -type d | egrep -v '\.git|target|src' | \ 23 + cd $(find $ONOS_ROOT/ -type d | egrep -v '\.git|target' | \
25 egrep "${1:-$ONOS_ROOT}" | head -n 1) 24 egrep "${1:-$ONOS_ROOT}" | head -n 1)
26 } 25 }
27 26
...@@ -30,11 +29,12 @@ alias mci='mvn clean install' ...@@ -30,11 +29,12 @@ alias mci='mvn clean install'
30 29
31 # Short-hand for ONOS build, package and test. 30 # Short-hand for ONOS build, package and test.
32 alias ob='onos-build' 31 alias ob='onos-build'
32 +alias obs='onos-build-selective'
33 alias op='onos-package' 33 alias op='onos-package'
34 alias ot='onos-test' 34 alias ot='onos-test'
35 35
36 # Short-hand for tailing the ONOS (karaf) log 36 # Short-hand for tailing the ONOS (karaf) log
37 -alias tl='$ONOS_ROOT/tools/dev/watchLog' 37 +alias tl='$ONOS_ROOT/tools/dev/bin/onos-local-log'
38 alias tlo='tl | grep --colour=always org.onlab' 38 alias tlo='tl | grep --colour=always org.onlab'
39 39
40 # Pretty-print JSON output 40 # Pretty-print JSON output
......
1 +#!/bin/bash
2 +#------------------------------------------------------------------------------
3 +# Selectively builds only those projects that contained modified Java files.
4 +#------------------------------------------------------------------------------
5 +
6 +projects=$(find $ONOS_ROOT -name '*.java' \
7 + -not -path '*/openflowj/*' -and -not -path '.git/*' \
8 + -exec $ONOS_ROOT/tools/dev/bin/onos-build-selective-hook {} \; | \
9 + sort -u | sed "s:$ONOS_ROOT::g" | tr '\n' ',' | \
10 + sed 's:/,:,:g;s:,/:,:g;s:^/::g;s:,$::g')
11 +
12 +[ -n "$projects" ] && cd $ONOS_ROOT && mvn --projects $projects ${@:-clean install}
...\ No newline at end of file ...\ No newline at end of file
1 +#------------------------------------------------------------------------------
2 +# Echoes project-level directory if a Java file within is newer than its
3 +# class file counterpart
4 +#------------------------------------------------------------------------------
5 +
6 +javaFile=${1#*\/src\/*\/java/}
7 +basename=${1/*\//}
8 +
9 +[ $basename = "package-info.java" ] && exit 0
10 +
11 +src=${1/$javaFile/}
12 +project=${src/src*/}
13 +classFile=${javaFile/.java/.class}
14 +
15 +[ ${project}target/classes/$classFile -nt ${src}$javaFile -o \
16 + ${project}target/test-classes/$classFile -nt ${src}$javaFile ] \
17 + || echo ${src/src*/}
18 +
1 -unset OC1 OC2 OC3 OC4 OC5 OC6 OC7 OC8 OC9 OCN ONOS_NIC 1 +unset OC1 OC2 OC3 OC4 OC5 OC6 OC7 OC8 OC9 OCN ONOS_NIC ONOS_FEATURES
......
...@@ -239,12 +239,41 @@ public final class KryoPool { ...@@ -239,12 +239,41 @@ public final class KryoPool {
239 Kryo kryo = new Kryo(); 239 Kryo kryo = new Kryo();
240 kryo.setRegistrationRequired(registrationRequired); 240 kryo.setRegistrationRequired(registrationRequired);
241 for (Pair<Class<?>, Serializer<?>> registry : registeredTypes) { 241 for (Pair<Class<?>, Serializer<?>> registry : registeredTypes) {
242 - if (registry.getRight() == null) { 242 + final Serializer<?> serializer = registry.getRight();
243 + if (serializer == null) {
243 kryo.register(registry.getLeft()); 244 kryo.register(registry.getLeft());
244 } else { 245 } else {
245 - kryo.register(registry.getLeft(), registry.getRight()); 246 + kryo.register(registry.getLeft(), serializer);
247 + if (serializer instanceof FamilySerializer) {
248 + FamilySerializer<?> fser = (FamilySerializer<?>) serializer;
249 + fser.registerFamilies(kryo);
250 + }
246 } 251 }
247 } 252 }
248 return kryo; 253 return kryo;
249 } 254 }
255 +
256 + /**
257 + * Serializer implementation, which required registration of family of Classes.
258 + * @param <T> base type of this serializer.
259 + */
260 + public abstract static class FamilySerializer<T> extends Serializer<T> {
261 +
262 +
263 + public FamilySerializer(boolean acceptsNull) {
264 + super(acceptsNull);
265 + }
266 +
267 + public FamilySerializer(boolean acceptsNull, boolean immutable) {
268 + super(acceptsNull, immutable);
269 + }
270 +
271 + /**
272 + * Registers other classes this Serializer supports.
273 + *
274 + * @param kryo instance to register classes to
275 + */
276 + public void registerFamilies(Kryo kryo) {
277 + }
278 + }
250 } 279 }
......