HIGUCHI Yuta
Committed by Gerrit Code Review

KryoNamespace improvements

- Ignore duplicate Namespace registration
- Add friendly name for helping logging

- ONOS-4528

Change-Id: Id78f2a0f6e9715a7880875039825e294a68592a9
...@@ -277,7 +277,7 @@ public final class KryoNamespaces { ...@@ -277,7 +277,7 @@ public final class KryoNamespaces {
277 .register(char[].class) 277 .register(char[].class)
278 .register(String[].class) 278 .register(String[].class)
279 .register(boolean[].class) 279 .register(boolean[].class)
280 - .build(); 280 + .build("BASIC");
281 281
282 /** 282 /**
283 * KryoNamespace which can serialize ON.lab misc classes. 283 * KryoNamespace which can serialize ON.lab misc classes.
...@@ -297,7 +297,7 @@ public final class KryoNamespaces { ...@@ -297,7 +297,7 @@ public final class KryoNamespaces {
297 .register(Bandwidth.class) 297 .register(Bandwidth.class)
298 .register(Bandwidth.bps(1L).getClass()) 298 .register(Bandwidth.bps(1L).getClass())
299 .register(Bandwidth.bps(1.0).getClass()) 299 .register(Bandwidth.bps(1.0).getClass())
300 - .build(); 300 + .build("MISC");
301 301
302 /** 302 /**
303 * Kryo registration Id for user custom registration. 303 * Kryo registration Id for user custom registration.
...@@ -542,7 +542,7 @@ public final class KryoNamespaces { ...@@ -542,7 +542,7 @@ public final class KryoNamespaces {
542 .register(VlanCodec.class) 542 .register(VlanCodec.class)
543 .register(MplsCodec.class) 543 .register(MplsCodec.class)
544 .register(NoOpCodec.class) 544 .register(NoOpCodec.class)
545 - .build(); 545 + .build("API");
546 546
547 547
548 // not to be instantiated 548 // not to be instantiated
......
...@@ -35,7 +35,9 @@ import java.io.OutputStream; ...@@ -35,7 +35,9 @@ import java.io.OutputStream;
35 import java.nio.ByteBuffer; 35 import java.nio.ByteBuffer;
36 import java.util.ArrayList; 36 import java.util.ArrayList;
37 import java.util.List; 37 import java.util.List;
38 +import java.util.Objects;
38 39
40 +import static com.google.common.base.Preconditions.checkNotNull;
39 import static org.slf4j.LoggerFactory.getLogger; 41 import static org.slf4j.LoggerFactory.getLogger;
40 42
41 /** 43 /**
...@@ -62,9 +64,12 @@ public final class KryoNamespace implements KryoFactory, KryoPool { ...@@ -62,9 +64,12 @@ public final class KryoNamespace implements KryoFactory, KryoPool {
62 */ 64 */
63 public static final int INITIAL_ID = 16; 65 public static final int INITIAL_ID = 16;
64 66
67 + private static final String NO_NAME = "(no name)";
68 +
65 private static final Logger log = getLogger(KryoNamespace.class); 69 private static final Logger log = getLogger(KryoNamespace.class);
66 70
67 71
72 +
68 private final KryoPool pool = new KryoPool.Builder(this) 73 private final KryoPool pool = new KryoPool.Builder(this)
69 .softReferences() 74 .softReferences()
70 .build(); 75 .build();
...@@ -72,6 +77,7 @@ public final class KryoNamespace implements KryoFactory, KryoPool { ...@@ -72,6 +77,7 @@ public final class KryoNamespace implements KryoFactory, KryoPool {
72 private final ImmutableList<RegistrationBlock> registeredBlocks; 77 private final ImmutableList<RegistrationBlock> registeredBlocks;
73 78
74 private final boolean registrationRequired; 79 private final boolean registrationRequired;
80 + private final String friendlyName;
75 81
76 82
77 /** 83 /**
...@@ -91,10 +97,20 @@ public final class KryoNamespace implements KryoFactory, KryoPool { ...@@ -91,10 +97,20 @@ public final class KryoNamespace implements KryoFactory, KryoPool {
91 * @return KryoNamespace 97 * @return KryoNamespace
92 */ 98 */
93 public KryoNamespace build() { 99 public KryoNamespace build() {
100 + return build(NO_NAME);
101 + }
102 +
103 + /**
104 + * Builds a {@link KryoNamespace} instance.
105 + *
106 + * @param friendlyName friendly name for the namespace
107 + * @return KryoNamespace
108 + */
109 + public KryoNamespace build(String friendlyName) {
94 if (!types.isEmpty()) { 110 if (!types.isEmpty()) {
95 blocks.add(new RegistrationBlock(this.blockHeadId, types)); 111 blocks.add(new RegistrationBlock(this.blockHeadId, types));
96 } 112 }
97 - return new KryoNamespace(blocks, registrationRequired).populate(1); 113 + return new KryoNamespace(blocks, registrationRequired, friendlyName).populate(1);
98 } 114 }
99 115
100 /** 116 /**
...@@ -109,7 +125,7 @@ public final class KryoNamespace implements KryoFactory, KryoPool { ...@@ -109,7 +125,7 @@ public final class KryoNamespace implements KryoFactory, KryoPool {
109 if (!types.isEmpty()) { 125 if (!types.isEmpty()) {
110 if (id != FLOATING_ID && id < blockHeadId + types.size()) { 126 if (id != FLOATING_ID && id < blockHeadId + types.size()) {
111 127
112 - log.warn("requested nextId {} could potentially overlap" + 128 + log.warn("requested nextId {} could potentially overlap " +
113 "with existing registrations {}+{} ", 129 "with existing registrations {}+{} ",
114 id, blockHeadId, types.size()); 130 id, blockHeadId, types.size());
115 } 131 }
...@@ -170,6 +186,12 @@ public final class KryoNamespace implements KryoFactory, KryoPool { ...@@ -170,6 +186,12 @@ public final class KryoNamespace implements KryoFactory, KryoPool {
170 * @return this 186 * @return this
171 */ 187 */
172 public Builder register(final KryoNamespace ns) { 188 public Builder register(final KryoNamespace ns) {
189 +
190 + if (blocks.containsAll(ns.registeredBlocks)) {
191 + // Everything was already registered.
192 + log.debug("Ignoring {}, already registered.", ns);
193 + return this;
194 + }
173 for (RegistrationBlock block : ns.registeredBlocks) { 195 for (RegistrationBlock block : ns.registeredBlocks) {
174 this.register(block); 196 this.register(block);
175 } 197 }
...@@ -204,10 +226,14 @@ public final class KryoNamespace implements KryoFactory, KryoPool { ...@@ -204,10 +226,14 @@ public final class KryoNamespace implements KryoFactory, KryoPool {
204 * 226 *
205 * @param registeredTypes types to register 227 * @param registeredTypes types to register
206 * @param registrationRequired 228 * @param registrationRequired
229 + * @param friendlyName friendly name for the namespace
207 */ 230 */
208 - private KryoNamespace(final List<RegistrationBlock> registeredTypes, boolean registrationRequired) { 231 + private KryoNamespace(final List<RegistrationBlock> registeredTypes,
232 + boolean registrationRequired,
233 + String friendlyName) {
209 this.registeredBlocks = ImmutableList.copyOf(registeredTypes); 234 this.registeredBlocks = ImmutableList.copyOf(registeredTypes);
210 this.registrationRequired = registrationRequired; 235 this.registrationRequired = registrationRequired;
236 + this.friendlyName = checkNotNull(friendlyName);
211 } 237 }
212 238
213 /** 239 /**
...@@ -373,6 +399,10 @@ public final class KryoNamespace implements KryoFactory, KryoPool { ...@@ -373,6 +399,10 @@ public final class KryoNamespace implements KryoFactory, KryoPool {
373 } 399 }
374 } 400 }
375 401
402 + private String friendlyName() {
403 + return friendlyName;
404 + }
405 +
376 /** 406 /**
377 * Creates a Kryo instance. 407 * Creates a Kryo instance.
378 * 408 *
...@@ -408,12 +438,12 @@ public final class KryoNamespace implements KryoFactory, KryoPool { ...@@ -408,12 +438,12 @@ public final class KryoNamespace implements KryoFactory, KryoPool {
408 * @param serializer Specific serializer to register or null to use default. 438 * @param serializer Specific serializer to register or null to use default.
409 * @param id type registration id to use 439 * @param id type registration id to use
410 */ 440 */
411 - private static void register(Kryo kryo, Class<?> type, Serializer<?> serializer, int id) { 441 + private void register(Kryo kryo, Class<?> type, Serializer<?> serializer, int id) {
412 Registration existing = kryo.getRegistration(id); 442 Registration existing = kryo.getRegistration(id);
413 if (existing != null) { 443 if (existing != null) {
414 if (existing.getType() != type) { 444 if (existing.getType() != type) {
415 - log.error("Failed to register {} as {}, {} was already registered.", 445 + log.error("{}: Failed to register {} as {}, {} was already registered.",
416 - type, id, existing.getType()); 446 + friendlyName(), type, id, existing.getType());
417 447
418 throw new IllegalStateException(String.format( 448 throw new IllegalStateException(String.format(
419 "Failed to register %s as %s, %s was already registered.", 449 "Failed to register %s as %s, %s was already registered.",
...@@ -430,8 +460,8 @@ public final class KryoNamespace implements KryoFactory, KryoPool { ...@@ -430,8 +460,8 @@ public final class KryoNamespace implements KryoFactory, KryoPool {
430 r = kryo.register(type, serializer, id); 460 r = kryo.register(type, serializer, id);
431 } 461 }
432 if (r.getId() != id) { 462 if (r.getId() != id) {
433 - log.debug("{} already registed as {}. Skipping {}.", 463 + log.warn("{}: {} already registed as {}. Skipping {}.",
434 - r.getType(), r.getId(), id); 464 + friendlyName(), r.getType(), r.getId(), id);
435 } 465 }
436 log.trace("{} registered as {}", r.getType(), r.getId()); 466 log.trace("{} registered as {}", r.getType(), r.getId());
437 } 467 }
...@@ -453,6 +483,13 @@ public final class KryoNamespace implements KryoFactory, KryoPool { ...@@ -453,6 +483,13 @@ public final class KryoNamespace implements KryoFactory, KryoPool {
453 483
454 @Override 484 @Override
455 public String toString() { 485 public String toString() {
486 + if (friendlyName != NO_NAME) {
487 + return MoreObjects.toStringHelper(getClass())
488 + .omitNullValues()
489 + .add("friendlyName", friendlyName)
490 + // omit lengthy detail, when there's a name
491 + .toString();
492 + }
456 return MoreObjects.toStringHelper(getClass()) 493 return MoreObjects.toStringHelper(getClass())
457 .add("registeredBlocks", registeredBlocks) 494 .add("registeredBlocks", registeredBlocks)
458 .toString(); 495 .toString();
...@@ -482,5 +519,24 @@ public final class KryoNamespace implements KryoFactory, KryoPool { ...@@ -482,5 +519,24 @@ public final class KryoNamespace implements KryoFactory, KryoPool {
482 .add("types", types) 519 .add("types", types)
483 .toString(); 520 .toString();
484 } 521 }
522 +
523 + @Override
524 + public int hashCode() {
525 + return types.hashCode();
526 + }
527 +
528 + // Only the registered types are used for equality.
529 + @Override
530 + public boolean equals(Object obj) {
531 + if (this == obj) {
532 + return true;
533 + }
534 +
535 + if (obj instanceof RegistrationBlock) {
536 + RegistrationBlock that = (RegistrationBlock) obj;
537 + return Objects.equals(this.types, that.types);
538 + }
539 + return false;
540 + }
485 } 541 }
486 } 542 }
......