Fix for Kryo related issue crossing OSGi bundle boundaries.
Change-Id: I121dfe360de14a5b4760e5d2fd8cb2db93e0be63
diff --git a/core/api/src/main/java/org/onlab/onos/net/DeviceId.java b/core/api/src/main/java/org/onlab/onos/net/DeviceId.java
index 8d96d8b..ef8c5ab 100644
--- a/core/api/src/main/java/org/onlab/onos/net/DeviceId.java
+++ b/core/api/src/main/java/org/onlab/onos/net/DeviceId.java
@@ -7,9 +7,6 @@
*/
public final class DeviceId extends ElementId {
- // Default constructor for serialization
- protected DeviceId() {}
-
// Public construction is prohibited
private DeviceId(URI uri) {
super(uri);
diff --git a/core/api/src/main/java/org/onlab/onos/net/provider/ProviderId.java b/core/api/src/main/java/org/onlab/onos/net/provider/ProviderId.java
index 8d3d571..725748a 100644
--- a/core/api/src/main/java/org/onlab/onos/net/provider/ProviderId.java
+++ b/core/api/src/main/java/org/onlab/onos/net/provider/ProviderId.java
@@ -12,12 +12,6 @@
private final String scheme;
private final String id;
- // Default constructor for serialization
- protected ProviderId() {
- scheme = null;
- id = null;
- }
-
/**
* Creates a new provider identifier from the specified string.
* The providers are expected to follow the reverse DNS convention, e.g.
@@ -40,6 +34,15 @@
return scheme;
}
+ /**
+ * Returns the device URI scheme specific id portion.
+ *
+ * @return id
+ */
+ public String id() {
+ return id;
+ }
+
@Override
public int hashCode() {
return Objects.hash(scheme, id);
diff --git a/core/net/src/test/java/org/onlab/onos/net/device/impl/DistributedDeviceManagerTest.java b/core/net/src/test/java/org/onlab/onos/net/device/impl/DistributedDeviceManagerTest.java
index a928572..222216c 100644
--- a/core/net/src/test/java/org/onlab/onos/net/device/impl/DistributedDeviceManagerTest.java
+++ b/core/net/src/test/java/org/onlab/onos/net/device/impl/DistributedDeviceManagerTest.java
@@ -112,7 +112,7 @@
mgr.deactivate();
dstore.deactivate();
- dstore.theInstance.shutdown();
+ ((TestDistributedDeviceStore) dstore).shutdownHz();
}
private void connectDevice(DeviceId deviceId, String swVersion) {
@@ -290,5 +290,12 @@
}
};
}
+
+ /**
+ * Shutdowns the hazelcast instance.
+ */
+ public void shutdownHz() {
+ theInstance.shutdown();
+ }
}
}
diff --git a/core/store/src/main/java/org/onlab/onos/store/device/impl/DefaultPortSerializer.java b/core/store/src/main/java/org/onlab/onos/store/device/impl/DefaultPortSerializer.java
index 4a60eb8..bd0aa06 100644
--- a/core/store/src/main/java/org/onlab/onos/store/device/impl/DefaultPortSerializer.java
+++ b/core/store/src/main/java/org/onlab/onos/store/device/impl/DefaultPortSerializer.java
@@ -16,6 +16,9 @@
import com.google.common.collect.ImmutableSet;
// TODO move to util, etc.
+/**
+ * Kryo Serializer for {@link DefaultPort}.
+ */
public final class DefaultPortSerializer extends
Serializer<DefaultPort> {
@@ -23,6 +26,9 @@
= new CollectionSerializer(IpPrefix.class,
new IpPrefixSerializer(), false);
+ /**
+ * Default constructor.
+ */
public DefaultPortSerializer() {
// non-null, immutable
super(false, true);
diff --git a/core/store/src/main/java/org/onlab/onos/store/device/impl/DistributedDeviceStore.java b/core/store/src/main/java/org/onlab/onos/store/device/impl/DistributedDeviceStore.java
index b8c1cdf..fe03cda 100644
--- a/core/store/src/main/java/org/onlab/onos/store/device/impl/DistributedDeviceStore.java
+++ b/core/store/src/main/java/org/onlab/onos/store/device/impl/DistributedDeviceStore.java
@@ -44,6 +44,10 @@
import org.onlab.util.KryoPool;
import org.slf4j.Logger;
+import com.esotericsoftware.kryo.Kryo;
+import com.esotericsoftware.kryo.Serializer;
+import com.esotericsoftware.kryo.io.Input;
+import com.esotericsoftware.kryo.io.Output;
import com.google.common.base.Optional;
import com.google.common.cache.CacheBuilder;
import com.google.common.cache.CacheLoader;
@@ -68,103 +72,26 @@
@Service
public class DistributedDeviceStore implements DeviceStore {
- /**
- * An IMap EntryListener, which reflects each remote event to cache.
- *
- * @param <K> IMap key type after deserialization
- * @param <V> IMap value type after deserialization
- */
- public static final class RemoteEventHandler<K, V> extends
- EntryAdapter<byte[], byte[]> {
-
- private LoadingCache<K, Optional<V>> cache;
-
- /**
- * Constructor.
- *
- * @param cache cache to update
- */
- public RemoteEventHandler(
- LoadingCache<K, Optional<V>> cache) {
- this.cache = checkNotNull(cache);
- }
-
- @Override
- public void mapCleared(MapEvent event) {
- cache.invalidateAll();
- }
-
- @Override
- public void entryUpdated(EntryEvent<byte[], byte[]> event) {
- cache.put(POOL.<K>deserialize(event.getKey()),
- Optional.of(POOL.<V>deserialize(
- event.getValue())));
- }
-
- @Override
- public void entryRemoved(EntryEvent<byte[], byte[]> event) {
- cache.invalidate(POOL.<DeviceId>deserialize(event.getKey()));
- }
-
- @Override
- public void entryAdded(EntryEvent<byte[], byte[]> event) {
- entryUpdated(event);
- }
- }
-
- /**
- * CacheLoader to wrap Map value with Optional,
- * to handle negative hit on underlying IMap.
- *
- * @param <K> IMap key type after deserialization
- * @param <V> IMap value type after deserialization
- */
- public static final class OptionalCacheLoader<K, V> extends
- CacheLoader<K, Optional<V>> {
-
- private IMap<byte[], byte[]> rawMap;
-
- /**
- * Constructor.
- *
- * @param rawMap underlying IMap
- */
- public OptionalCacheLoader(IMap<byte[], byte[]> rawMap) {
- this.rawMap = checkNotNull(rawMap);
- }
-
- @Override
- public Optional<V> load(K key) throws Exception {
- byte[] keyBytes = serialize(key);
- byte[] valBytes = rawMap.get(keyBytes);
- if (valBytes == null) {
- return Optional.absent();
- }
- V dev = deserialize(valBytes);
- return Optional.of(dev);
- }
- }
-
private final Logger log = getLogger(getClass());
public static final String DEVICE_NOT_FOUND = "Device with ID %s not found";
// FIXME Slice out types used in common to separate pool/namespace.
private static final KryoPool POOL = KryoPool.newBuilder()
- .register(URI.class, new URISerializer())
.register(
ArrayList.class,
+ HashMap.class,
- ProviderId.class,
Device.Type.class,
- DeviceId.class,
DefaultDevice.class,
MastershipRole.class,
- HashMap.class,
Port.class,
Element.class
)
+ .register(URI.class, new URISerializer())
+ .register(ProviderId.class, new ProviderIdSerializer())
+ .register(DeviceId.class, new DeviceIdSerializer())
.register(PortNumber.class, new PortNumberSerializer())
.register(DefaultPort.class, new DefaultPortSerializer())
.build()
@@ -190,7 +117,7 @@
@Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
protected StoreService storeService;
- /*protected*/public HazelcastInstance theInstance;
+ protected HazelcastInstance theInstance;
@Activate
@@ -517,4 +444,94 @@
return POOL.deserialize(bytes);
}
+ public static final class DeviceIdSerializer extends Serializer<DeviceId> {
+
+ @Override
+ public void write(Kryo kryo, Output output, DeviceId object) {
+ kryo.writeObject(output, object.uri());
+ }
+
+ @Override
+ public DeviceId read(Kryo kryo, Input input, Class<DeviceId> type) {
+ final URI uri = kryo.readObject(input, URI.class);
+ return DeviceId.deviceId(uri);
+ }
+ }
+
+ /**
+ * An IMap EntryListener, which reflects each remote event to cache.
+ *
+ * @param <K> IMap key type after deserialization
+ * @param <V> IMap value type after deserialization
+ */
+ public static final class RemoteEventHandler<K, V> extends
+ EntryAdapter<byte[], byte[]> {
+
+ private LoadingCache<K, Optional<V>> cache;
+
+ /**
+ * Constructor.
+ *
+ * @param cache cache to update
+ */
+ public RemoteEventHandler(
+ LoadingCache<K, Optional<V>> cache) {
+ this.cache = checkNotNull(cache);
+ }
+
+ @Override
+ public void mapCleared(MapEvent event) {
+ cache.invalidateAll();
+ }
+
+ @Override
+ public void entryUpdated(EntryEvent<byte[], byte[]> event) {
+ cache.put(POOL.<K>deserialize(event.getKey()),
+ Optional.of(POOL.<V>deserialize(
+ event.getValue())));
+ }
+
+ @Override
+ public void entryRemoved(EntryEvent<byte[], byte[]> event) {
+ cache.invalidate(POOL.<DeviceId>deserialize(event.getKey()));
+ }
+
+ @Override
+ public void entryAdded(EntryEvent<byte[], byte[]> event) {
+ entryUpdated(event);
+ }
+ }
+
+ /**
+ * CacheLoader to wrap Map value with Optional,
+ * to handle negative hit on underlying IMap.
+ *
+ * @param <K> IMap key type after deserialization
+ * @param <V> IMap value type after deserialization
+ */
+ public static final class OptionalCacheLoader<K, V> extends
+ CacheLoader<K, Optional<V>> {
+
+ private IMap<byte[], byte[]> rawMap;
+
+ /**
+ * Constructor.
+ *
+ * @param rawMap underlying IMap
+ */
+ public OptionalCacheLoader(IMap<byte[], byte[]> rawMap) {
+ this.rawMap = checkNotNull(rawMap);
+ }
+
+ @Override
+ public Optional<V> load(K key) throws Exception {
+ byte[] keyBytes = serialize(key);
+ byte[] valBytes = rawMap.get(keyBytes);
+ if (valBytes == null) {
+ return Optional.absent();
+ }
+ V dev = deserialize(valBytes);
+ return Optional.of(dev);
+ }
+ }
}
diff --git a/core/store/src/main/java/org/onlab/onos/store/device/impl/IpPrefixSerializer.java b/core/store/src/main/java/org/onlab/onos/store/device/impl/IpPrefixSerializer.java
index 3d3efe0..d6296a3 100644
--- a/core/store/src/main/java/org/onlab/onos/store/device/impl/IpPrefixSerializer.java
+++ b/core/store/src/main/java/org/onlab/onos/store/device/impl/IpPrefixSerializer.java
@@ -8,8 +8,14 @@
import com.esotericsoftware.kryo.io.Output;
// TODO move to util, etc.
+/**
+ * Kryo Serializer for {@link IpPrefix}.
+ */
public final class IpPrefixSerializer extends Serializer<IpPrefix> {
+ /**
+ * Default constructor.
+ */
public IpPrefixSerializer() {
// non-null, immutable
super(false, true);
diff --git a/core/store/src/main/java/org/onlab/onos/store/device/impl/PortNumberSerializer.java b/core/store/src/main/java/org/onlab/onos/store/device/impl/PortNumberSerializer.java
index 4483187..ae11867 100644
--- a/core/store/src/main/java/org/onlab/onos/store/device/impl/PortNumberSerializer.java
+++ b/core/store/src/main/java/org/onlab/onos/store/device/impl/PortNumberSerializer.java
@@ -8,9 +8,15 @@
import com.esotericsoftware.kryo.io.Output;
// TODO move to util, etc.
+/**
+ * Serializer for {@link PortNumber}.
+ */
public final class PortNumberSerializer extends
Serializer<PortNumber> {
+ /**
+ * Default constructor.
+ */
public PortNumberSerializer() {
// non-null, immutable
super(false, true);
diff --git a/core/store/src/main/java/org/onlab/onos/store/device/impl/ProviderIdSerializer.java b/core/store/src/main/java/org/onlab/onos/store/device/impl/ProviderIdSerializer.java
new file mode 100644
index 0000000..82b7a70
--- /dev/null
+++ b/core/store/src/main/java/org/onlab/onos/store/device/impl/ProviderIdSerializer.java
@@ -0,0 +1,37 @@
+package org.onlab.onos.store.device.impl;
+
+import org.onlab.onos.net.provider.ProviderId;
+
+import com.esotericsoftware.kryo.Kryo;
+import com.esotericsoftware.kryo.Serializer;
+import com.esotericsoftware.kryo.io.Input;
+import com.esotericsoftware.kryo.io.Output;
+
+//TODO move to util, etc.
+/**
+ * Serializer for {@link ProviderId}.
+ */
+public class ProviderIdSerializer extends Serializer<ProviderId> {
+
+ /**
+ * Default constructor.
+ */
+ public ProviderIdSerializer() {
+ // non-null, immutable
+ super(false, true);
+ }
+
+ @Override
+ public void write(Kryo kryo, Output output, ProviderId object) {
+ output.writeString(object.scheme());
+ output.writeString(object.id());
+ }
+
+ @Override
+ public ProviderId read(Kryo kryo, Input input, Class<ProviderId> type) {
+ String scheme = input.readString();
+ String id = input.readString();
+ return new ProviderId(scheme, id);
+ }
+
+}