KryoNamespace improvements
- Ignore duplicate Namespace registration
- Add friendly name for helping logging
- ONOS-4528
Change-Id: Id78f2a0f6e9715a7880875039825e294a68592a9
diff --git a/core/store/serializers/src/main/java/org/onosproject/store/serializers/KryoNamespaces.java b/core/store/serializers/src/main/java/org/onosproject/store/serializers/KryoNamespaces.java
index c1d25b7..4073804 100644
--- a/core/store/serializers/src/main/java/org/onosproject/store/serializers/KryoNamespaces.java
+++ b/core/store/serializers/src/main/java/org/onosproject/store/serializers/KryoNamespaces.java
@@ -277,7 +277,7 @@
.register(char[].class)
.register(String[].class)
.register(boolean[].class)
- .build();
+ .build("BASIC");
/**
* KryoNamespace which can serialize ON.lab misc classes.
@@ -297,7 +297,7 @@
.register(Bandwidth.class)
.register(Bandwidth.bps(1L).getClass())
.register(Bandwidth.bps(1.0).getClass())
- .build();
+ .build("MISC");
/**
* Kryo registration Id for user custom registration.
@@ -542,7 +542,7 @@
.register(VlanCodec.class)
.register(MplsCodec.class)
.register(NoOpCodec.class)
- .build();
+ .build("API");
// not to be instantiated
diff --git a/utils/misc/src/main/java/org/onlab/util/KryoNamespace.java b/utils/misc/src/main/java/org/onlab/util/KryoNamespace.java
index a8b1e16..70fdfc8 100644
--- a/utils/misc/src/main/java/org/onlab/util/KryoNamespace.java
+++ b/utils/misc/src/main/java/org/onlab/util/KryoNamespace.java
@@ -35,7 +35,9 @@
import java.nio.ByteBuffer;
import java.util.ArrayList;
import java.util.List;
+import java.util.Objects;
+import static com.google.common.base.Preconditions.checkNotNull;
import static org.slf4j.LoggerFactory.getLogger;
/**
@@ -62,9 +64,12 @@
*/
public static final int INITIAL_ID = 16;
+ private static final String NO_NAME = "(no name)";
+
private static final Logger log = getLogger(KryoNamespace.class);
+
private final KryoPool pool = new KryoPool.Builder(this)
.softReferences()
.build();
@@ -72,6 +77,7 @@
private final ImmutableList<RegistrationBlock> registeredBlocks;
private final boolean registrationRequired;
+ private final String friendlyName;
/**
@@ -91,10 +97,20 @@
* @return KryoNamespace
*/
public KryoNamespace build() {
+ return build(NO_NAME);
+ }
+
+ /**
+ * Builds a {@link KryoNamespace} instance.
+ *
+ * @param friendlyName friendly name for the namespace
+ * @return KryoNamespace
+ */
+ public KryoNamespace build(String friendlyName) {
if (!types.isEmpty()) {
blocks.add(new RegistrationBlock(this.blockHeadId, types));
}
- return new KryoNamespace(blocks, registrationRequired).populate(1);
+ return new KryoNamespace(blocks, registrationRequired, friendlyName).populate(1);
}
/**
@@ -109,7 +125,7 @@
if (!types.isEmpty()) {
if (id != FLOATING_ID && id < blockHeadId + types.size()) {
- log.warn("requested nextId {} could potentially overlap" +
+ log.warn("requested nextId {} could potentially overlap " +
"with existing registrations {}+{} ",
id, blockHeadId, types.size());
}
@@ -170,6 +186,12 @@
* @return this
*/
public Builder register(final KryoNamespace ns) {
+
+ if (blocks.containsAll(ns.registeredBlocks)) {
+ // Everything was already registered.
+ log.debug("Ignoring {}, already registered.", ns);
+ return this;
+ }
for (RegistrationBlock block : ns.registeredBlocks) {
this.register(block);
}
@@ -204,10 +226,14 @@
*
* @param registeredTypes types to register
* @param registrationRequired
+ * @param friendlyName friendly name for the namespace
*/
- private KryoNamespace(final List<RegistrationBlock> registeredTypes, boolean registrationRequired) {
+ private KryoNamespace(final List<RegistrationBlock> registeredTypes,
+ boolean registrationRequired,
+ String friendlyName) {
this.registeredBlocks = ImmutableList.copyOf(registeredTypes);
this.registrationRequired = registrationRequired;
+ this.friendlyName = checkNotNull(friendlyName);
}
/**
@@ -373,6 +399,10 @@
}
}
+ private String friendlyName() {
+ return friendlyName;
+ }
+
/**
* Creates a Kryo instance.
*
@@ -408,12 +438,12 @@
* @param serializer Specific serializer to register or null to use default.
* @param id type registration id to use
*/
- private static void register(Kryo kryo, Class<?> type, Serializer<?> serializer, int id) {
+ private void register(Kryo kryo, Class<?> type, Serializer<?> serializer, int id) {
Registration existing = kryo.getRegistration(id);
if (existing != null) {
if (existing.getType() != type) {
- log.error("Failed to register {} as {}, {} was already registered.",
- type, id, existing.getType());
+ log.error("{}: Failed to register {} as {}, {} was already registered.",
+ friendlyName(), type, id, existing.getType());
throw new IllegalStateException(String.format(
"Failed to register %s as %s, %s was already registered.",
@@ -430,8 +460,8 @@
r = kryo.register(type, serializer, id);
}
if (r.getId() != id) {
- log.debug("{} already registed as {}. Skipping {}.",
- r.getType(), r.getId(), id);
+ log.warn("{}: {} already registed as {}. Skipping {}.",
+ friendlyName(), r.getType(), r.getId(), id);
}
log.trace("{} registered as {}", r.getType(), r.getId());
}
@@ -453,6 +483,13 @@
@Override
public String toString() {
+ if (friendlyName != NO_NAME) {
+ return MoreObjects.toStringHelper(getClass())
+ .omitNullValues()
+ .add("friendlyName", friendlyName)
+ // omit lengthy detail, when there's a name
+ .toString();
+ }
return MoreObjects.toStringHelper(getClass())
.add("registeredBlocks", registeredBlocks)
.toString();
@@ -482,5 +519,24 @@
.add("types", types)
.toString();
}
+
+ @Override
+ public int hashCode() {
+ return types.hashCode();
+ }
+
+ // Only the registered types are used for equality.
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj) {
+ return true;
+ }
+
+ if (obj instanceof RegistrationBlock) {
+ RegistrationBlock that = (RegistrationBlock) obj;
+ return Objects.equals(this.types, that.types);
+ }
+ return false;
+ }
}
}