blob: 5fb1afc5c72502b13580beef720d4c7bac691243 [file] [log] [blame]
Thomas Vachuska24c849c2014-10-27 09:53:05 -07001/*
Brian O'Connor5ab426f2016-04-09 01:19:45 -07002 * Copyright 2014-present Open Networking Laboratory
Thomas Vachuska24c849c2014-10-27 09:53:05 -07003 *
Thomas Vachuska4f1a60c2014-10-28 13:39:07 -07004 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
Thomas Vachuska24c849c2014-10-27 09:53:05 -07007 *
Thomas Vachuska4f1a60c2014-10-28 13:39:07 -07008 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
Thomas Vachuska24c849c2014-10-27 09:53:05 -070015 */
Yuta HIGUCHI24a086b2014-09-21 23:28:41 -070016package org.onlab.util;
17
Yuta HIGUCHI24a086b2014-09-21 23:28:41 -070018import com.esotericsoftware.kryo.Kryo;
HIGUCHI Yuta0a1f29e2016-05-05 15:34:41 -070019import com.esotericsoftware.kryo.Registration;
Yuta HIGUCHI24a086b2014-09-21 23:28:41 -070020import com.esotericsoftware.kryo.Serializer;
Yuta HIGUCHIf4b107e2014-09-29 17:27:26 -070021import com.esotericsoftware.kryo.io.ByteBufferInput;
22import com.esotericsoftware.kryo.io.ByteBufferOutput;
Yuta HIGUCHI24a086b2014-09-21 23:28:41 -070023import com.esotericsoftware.kryo.io.Input;
Yuta HIGUCHI91768e32014-11-22 05:06:35 -080024import com.esotericsoftware.kryo.pool.KryoCallback;
Yuta HIGUCHI633cf882014-10-20 09:10:28 -070025import com.esotericsoftware.kryo.pool.KryoFactory;
Yuta HIGUCHI91768e32014-11-22 05:06:35 -080026import com.esotericsoftware.kryo.pool.KryoPool;
27import com.google.common.base.MoreObjects;
Yuta HIGUCHI24a086b2014-09-21 23:28:41 -070028import com.google.common.collect.ImmutableList;
Jonathan Hartbe093f72016-03-25 11:14:29 -070029import org.apache.commons.lang3.tuple.Pair;
30import org.objenesis.strategy.StdInstantiatorStrategy;
31import org.slf4j.Logger;
32
33import java.io.InputStream;
34import java.io.OutputStream;
35import java.nio.ByteBuffer;
36import java.util.ArrayList;
37import java.util.List;
HIGUCHI Yutab2d0fd82016-05-17 20:34:58 -070038import java.util.Objects;
Jonathan Hartbe093f72016-03-25 11:14:29 -070039
HIGUCHI Yutab2d0fd82016-05-17 20:34:58 -070040import static com.google.common.base.Preconditions.checkNotNull;
Jonathan Hartbe093f72016-03-25 11:14:29 -070041import static org.slf4j.LoggerFactory.getLogger;
Yuta HIGUCHI24a086b2014-09-21 23:28:41 -070042
Yuta HIGUCHI24a086b2014-09-21 23:28:41 -070043/**
44 * Pool of Kryo instances, with classes pre-registered.
45 */
46//@ThreadSafe
Yuta HIGUCHI91768e32014-11-22 05:06:35 -080047public final class KryoNamespace implements KryoFactory, KryoPool {
Yuta HIGUCHI24a086b2014-09-21 23:28:41 -070048
49 /**
50 * Default buffer size used for serialization.
51 *
52 * @see #serialize(Object)
53 */
Yuta HIGUCHI38782052014-11-09 23:51:58 -080054 public static final int DEFAULT_BUFFER_SIZE = 4096;
Yuta HIGUCHId2a38822014-11-06 19:05:04 -080055 public static final int MAX_BUFFER_SIZE = 100 * 1000 * 1000;
Yuta HIGUCHI24a086b2014-09-21 23:28:41 -070056
Yuta HIGUCHI91768e32014-11-22 05:06:35 -080057 /**
58 * ID to use if this KryoNamespace does not define registration id.
59 */
60 public static final int FLOATING_ID = -1;
61
62 /**
63 * Smallest ID free to use for user defined registrations.
64 */
HIGUCHI Yuta0a1f29e2016-05-05 15:34:41 -070065 public static final int INITIAL_ID = 16;
Yuta HIGUCHI91768e32014-11-22 05:06:35 -080066
HIGUCHI Yutab2d0fd82016-05-17 20:34:58 -070067 private static final String NO_NAME = "(no name)";
68
HIGUCHI Yutab49b0072016-02-22 22:50:45 -080069 private static final Logger log = getLogger(KryoNamespace.class);
70
Yuta HIGUCHI91768e32014-11-22 05:06:35 -080071
HIGUCHI Yutab2d0fd82016-05-17 20:34:58 -070072
Yuta HIGUCHI91768e32014-11-22 05:06:35 -080073 private final KryoPool pool = new KryoPool.Builder(this)
74 .softReferences()
75 .build();
76
77 private final ImmutableList<RegistrationBlock> registeredBlocks;
78
Yuta HIGUCHI24a086b2014-09-21 23:28:41 -070079 private final boolean registrationRequired;
HIGUCHI Yutab2d0fd82016-05-17 20:34:58 -070080 private final String friendlyName;
Yuta HIGUCHI24a086b2014-09-21 23:28:41 -070081
82 /**
Yuta HIGUCHI8d143d22014-10-19 23:15:09 -070083 * KryoNamespace builder.
Yuta HIGUCHI24a086b2014-09-21 23:28:41 -070084 */
85 //@NotThreadSafe
86 public static final class Builder {
87
Yuta HIGUCHI91768e32014-11-22 05:06:35 -080088 private int blockHeadId = INITIAL_ID;
89 private List<Pair<Class<?>, Serializer<?>>> types = new ArrayList<>();
90 private List<RegistrationBlock> blocks = new ArrayList<>();
Yuta HIGUCHI2befc662014-10-30 15:57:49 -070091 private boolean registrationRequired = true;
Yuta HIGUCHI24a086b2014-09-21 23:28:41 -070092
93 /**
Yuta HIGUCHI8d143d22014-10-19 23:15:09 -070094 * Builds a {@link KryoNamespace} instance.
Yuta HIGUCHI24a086b2014-09-21 23:28:41 -070095 *
Yuta HIGUCHI8d143d22014-10-19 23:15:09 -070096 * @return KryoNamespace
Yuta HIGUCHI24a086b2014-09-21 23:28:41 -070097 */
Yuta HIGUCHI8d143d22014-10-19 23:15:09 -070098 public KryoNamespace build() {
HIGUCHI Yutab2d0fd82016-05-17 20:34:58 -070099 return build(NO_NAME);
100 }
101
102 /**
103 * Builds a {@link KryoNamespace} instance.
104 *
105 * @param friendlyName friendly name for the namespace
106 * @return KryoNamespace
107 */
108 public KryoNamespace build(String friendlyName) {
Yuta HIGUCHI91768e32014-11-22 05:06:35 -0800109 if (!types.isEmpty()) {
110 blocks.add(new RegistrationBlock(this.blockHeadId, types));
111 }
HIGUCHI Yutab2d0fd82016-05-17 20:34:58 -0700112 return new KryoNamespace(blocks, registrationRequired, friendlyName).populate(1);
Yuta HIGUCHI91768e32014-11-22 05:06:35 -0800113 }
114
115 /**
116 * Sets the next Kryo registration Id for following register entries.
117 *
118 * @param id Kryo registration Id
119 * @return this
120 *
121 * @see Kryo#register(Class, Serializer, int)
122 */
123 public Builder nextId(final int id) {
124 if (!types.isEmpty()) {
HIGUCHI Yutab49b0072016-02-22 22:50:45 -0800125 if (id != FLOATING_ID && id < blockHeadId + types.size()) {
126
HIGUCHI Yuta163efb52016-05-18 19:24:19 -0700127 if (log.isWarnEnabled()) {
128 log.warn("requested nextId {} could potentially overlap " +
129 "with existing registrations {}+{} ",
130 id, blockHeadId, types.size(), new RuntimeException());
131 }
HIGUCHI Yutab49b0072016-02-22 22:50:45 -0800132 }
Yuta HIGUCHI91768e32014-11-22 05:06:35 -0800133 blocks.add(new RegistrationBlock(this.blockHeadId, types));
134 types = new ArrayList<>();
135 }
136 this.blockHeadId = id;
137 return this;
Yuta HIGUCHI24a086b2014-09-21 23:28:41 -0700138 }
139
140 /**
141 * Registers classes to be serialized using Kryo default serializer.
142 *
143 * @param expectedTypes list of classes
144 * @return this
145 */
146 public Builder register(final Class<?>... expectedTypes) {
147 for (Class<?> clazz : expectedTypes) {
Yuta HIGUCHI91768e32014-11-22 05:06:35 -0800148 types.add(Pair.of(clazz, null));
Yuta HIGUCHI24a086b2014-09-21 23:28:41 -0700149 }
150 return this;
151 }
152
153 /**
154 * Registers a class and it's serializer.
155 *
Yuta HIGUCHI91768e32014-11-22 05:06:35 -0800156 * @param classes list of classes to register
Yuta HIGUCHI24a086b2014-09-21 23:28:41 -0700157 * @param serializer serializer to use for the class
158 * @return this
159 */
Yuta HIGUCHI91768e32014-11-22 05:06:35 -0800160 public Builder register(Serializer<?> serializer, final Class<?>... classes) {
161 for (Class<?> clazz : classes) {
162 types.add(Pair.of(clazz, serializer));
163 }
164 return this;
165 }
166
167 private Builder register(RegistrationBlock block) {
168 if (block.begin() != FLOATING_ID) {
169 // flush pending types
170 nextId(block.begin());
171 blocks.add(block);
172 nextId(block.begin() + block.types().size());
173 } else {
174 // flush pending types
175 final int addedBlockBegin = blockHeadId + types.size();
176 nextId(addedBlockBegin);
177 blocks.add(new RegistrationBlock(addedBlockBegin, block.types()));
178 nextId(addedBlockBegin + block.types().size());
179 }
Yuta HIGUCHI24a086b2014-09-21 23:28:41 -0700180 return this;
181 }
182
183 /**
Yuta HIGUCHI8d143d22014-10-19 23:15:09 -0700184 * Registers all the class registered to given KryoNamespace.
Yuta HIGUCHI24a086b2014-09-21 23:28:41 -0700185 *
Yuta HIGUCHI91768e32014-11-22 05:06:35 -0800186 * @param ns KryoNamespace
Yuta HIGUCHI24a086b2014-09-21 23:28:41 -0700187 * @return this
188 */
Yuta HIGUCHI91768e32014-11-22 05:06:35 -0800189 public Builder register(final KryoNamespace ns) {
HIGUCHI Yutab2d0fd82016-05-17 20:34:58 -0700190
191 if (blocks.containsAll(ns.registeredBlocks)) {
192 // Everything was already registered.
193 log.debug("Ignoring {}, already registered.", ns);
194 return this;
195 }
Yuta HIGUCHI91768e32014-11-22 05:06:35 -0800196 for (RegistrationBlock block : ns.registeredBlocks) {
197 this.register(block);
198 }
Yuta HIGUCHI24a086b2014-09-21 23:28:41 -0700199 return this;
200 }
Yuta HIGUCHI2befc662014-10-30 15:57:49 -0700201
Yuta HIGUCHI91768e32014-11-22 05:06:35 -0800202 /**
203 * Sets the registrationRequired flag.
204 *
205 * @param registrationRequired Kryo's registrationRequired flag
206 * @return this
207 *
208 * @see Kryo#setRegistrationRequired(boolean)
209 */
Yuta HIGUCHI2befc662014-10-30 15:57:49 -0700210 public Builder setRegistrationRequired(boolean registrationRequired) {
211 this.registrationRequired = registrationRequired;
212 return this;
213 }
Yuta HIGUCHI24a086b2014-09-21 23:28:41 -0700214 }
215
216 /**
Yuta HIGUCHI8d143d22014-10-19 23:15:09 -0700217 * Creates a new {@link KryoNamespace} builder.
Yuta HIGUCHI24a086b2014-09-21 23:28:41 -0700218 *
219 * @return builder
220 */
221 public static Builder newBuilder() {
222 return new Builder();
223 }
224
225 /**
226 * Creates a Kryo instance pool.
227 *
Jonathan Hart4f60f982014-10-27 08:11:17 -0700228 * @param registeredTypes types to register
Yuta HIGUCHI2befc662014-10-30 15:57:49 -0700229 * @param registrationRequired
HIGUCHI Yutab2d0fd82016-05-17 20:34:58 -0700230 * @param friendlyName friendly name for the namespace
Yuta HIGUCHI24a086b2014-09-21 23:28:41 -0700231 */
HIGUCHI Yutab2d0fd82016-05-17 20:34:58 -0700232 private KryoNamespace(final List<RegistrationBlock> registeredTypes,
233 boolean registrationRequired,
234 String friendlyName) {
Yuta HIGUCHI91768e32014-11-22 05:06:35 -0800235 this.registeredBlocks = ImmutableList.copyOf(registeredTypes);
Yuta HIGUCHI2befc662014-10-30 15:57:49 -0700236 this.registrationRequired = registrationRequired;
HIGUCHI Yutab2d0fd82016-05-17 20:34:58 -0700237 this.friendlyName = checkNotNull(friendlyName);
Yuta HIGUCHI24a086b2014-09-21 23:28:41 -0700238 }
239
240 /**
241 * Populates the Kryo pool.
242 *
243 * @param instances to add to the pool
244 * @return this
245 */
Yuta HIGUCHI8d143d22014-10-19 23:15:09 -0700246 public KryoNamespace populate(int instances) {
Yuta HIGUCHI91768e32014-11-22 05:06:35 -0800247
Yuta HIGUCHI24a086b2014-09-21 23:28:41 -0700248 for (int i = 0; i < instances; ++i) {
Yuta HIGUCHI91768e32014-11-22 05:06:35 -0800249 release(create());
Yuta HIGUCHI24a086b2014-09-21 23:28:41 -0700250 }
Yuta HIGUCHI24a086b2014-09-21 23:28:41 -0700251 return this;
252 }
253
254 /**
Yuta HIGUCHI24a086b2014-09-21 23:28:41 -0700255 * Serializes given object to byte array using Kryo instance in pool.
256 * <p>
Yuta HIGUCHI38782052014-11-09 23:51:58 -0800257 * Note: Serialized bytes must be smaller than {@link #MAX_BUFFER_SIZE}.
Yuta HIGUCHI24a086b2014-09-21 23:28:41 -0700258 *
259 * @param obj Object to serialize
260 * @return serialized bytes
261 */
262 public byte[] serialize(final Object obj) {
263 return serialize(obj, DEFAULT_BUFFER_SIZE);
264 }
265
266 /**
267 * Serializes given object to byte array using Kryo instance in pool.
268 *
269 * @param obj Object to serialize
270 * @param bufferSize maximum size of serialized bytes
271 * @return serialized bytes
272 */
273 public byte[] serialize(final Object obj, final int bufferSize) {
Yuta HIGUCHId2a38822014-11-06 19:05:04 -0800274 ByteBufferOutput out = new ByteBufferOutput(bufferSize, MAX_BUFFER_SIZE);
Yuta HIGUCHI24a086b2014-09-21 23:28:41 -0700275 try {
Madan Jampani22fa5cb2015-04-13 15:53:44 -0700276 Kryo kryo = borrow();
277 try {
278 kryo.writeClassAndObject(out, obj);
279 out.flush();
280 return out.toBytes();
281 } finally {
282 release(kryo);
283 }
Yuta HIGUCHI24a086b2014-09-21 23:28:41 -0700284 } finally {
Madan Jampani22fa5cb2015-04-13 15:53:44 -0700285 out.release();
Yuta HIGUCHI24a086b2014-09-21 23:28:41 -0700286 }
287 }
288
289 /**
Yuta HIGUCHIf4b107e2014-09-29 17:27:26 -0700290 * Serializes given object to byte buffer using Kryo instance in pool.
291 *
292 * @param obj Object to serialize
293 * @param buffer to write to
294 */
295 public void serialize(final Object obj, final ByteBuffer buffer) {
296 ByteBufferOutput out = new ByteBufferOutput(buffer);
Yuta HIGUCHI91768e32014-11-22 05:06:35 -0800297 Kryo kryo = borrow();
Yuta HIGUCHIf4b107e2014-09-29 17:27:26 -0700298 try {
299 kryo.writeClassAndObject(out, obj);
Yuta HIGUCHIcac919c2014-10-20 22:17:20 -0700300 out.flush();
Yuta HIGUCHIf4b107e2014-09-29 17:27:26 -0700301 } finally {
Yuta HIGUCHI91768e32014-11-22 05:06:35 -0800302 release(kryo);
303 }
304 }
305
306 /**
307 * Serializes given object to OutputStream using Kryo instance in pool.
308 *
309 * @param obj Object to serialize
310 * @param stream to write to
311 */
312 public void serialize(final Object obj, final OutputStream stream) {
313 serialize(obj, stream, DEFAULT_BUFFER_SIZE);
314 }
315
316 /**
317 * Serializes given object to OutputStream using Kryo instance in pool.
318 *
319 * @param obj Object to serialize
320 * @param stream to write to
321 * @param bufferSize size of the buffer in front of the stream
322 */
323 public void serialize(final Object obj, final OutputStream stream, final int bufferSize) {
324 ByteBufferOutput out = new ByteBufferOutput(stream, bufferSize);
325 Kryo kryo = borrow();
326 try {
327 kryo.writeClassAndObject(out, obj);
328 out.flush();
329 } finally {
330 release(kryo);
Yuta HIGUCHIf4b107e2014-09-29 17:27:26 -0700331 }
332 }
333
334 /**
Yuta HIGUCHI24a086b2014-09-21 23:28:41 -0700335 * Deserializes given byte array to Object using Kryo instance in pool.
336 *
337 * @param bytes serialized bytes
338 * @param <T> deserialized Object type
339 * @return deserialized Object
340 */
341 public <T> T deserialize(final byte[] bytes) {
342 Input in = new Input(bytes);
Yuta HIGUCHI91768e32014-11-22 05:06:35 -0800343 Kryo kryo = borrow();
Yuta HIGUCHI24a086b2014-09-21 23:28:41 -0700344 try {
345 @SuppressWarnings("unchecked")
346 T obj = (T) kryo.readClassAndObject(in);
347 return obj;
348 } finally {
Yuta HIGUCHI91768e32014-11-22 05:06:35 -0800349 release(kryo);
Yuta HIGUCHI24a086b2014-09-21 23:28:41 -0700350 }
351 }
352
Yuta HIGUCHIf4b107e2014-09-29 17:27:26 -0700353 /**
354 * Deserializes given byte buffer to Object using Kryo instance in pool.
355 *
356 * @param buffer input with serialized bytes
357 * @param <T> deserialized Object type
358 * @return deserialized Object
359 */
360 public <T> T deserialize(final ByteBuffer buffer) {
361 ByteBufferInput in = new ByteBufferInput(buffer);
Yuta HIGUCHI91768e32014-11-22 05:06:35 -0800362 Kryo kryo = borrow();
Yuta HIGUCHIf4b107e2014-09-29 17:27:26 -0700363 try {
364 @SuppressWarnings("unchecked")
365 T obj = (T) kryo.readClassAndObject(in);
366 return obj;
367 } finally {
Yuta HIGUCHI91768e32014-11-22 05:06:35 -0800368 release(kryo);
Yuta HIGUCHIf4b107e2014-09-29 17:27:26 -0700369 }
370 }
Yuta HIGUCHI24a086b2014-09-21 23:28:41 -0700371
372 /**
Yuta HIGUCHI91768e32014-11-22 05:06:35 -0800373 * Deserializes given InputStream to an Object using Kryo instance in pool.
374 *
375 * @param stream input stream
376 * @param <T> deserialized Object type
377 * @return deserialized Object
378 */
379 public <T> T deserialize(final InputStream stream) {
380 return deserialize(stream, DEFAULT_BUFFER_SIZE);
381 }
382
383 /**
384 * Deserializes given InputStream to an Object using Kryo instance in pool.
385 *
386 * @param stream input stream
387 * @param <T> deserialized Object type
388 * @return deserialized Object
389 * @param bufferSize size of the buffer in front of the stream
390 */
391 public <T> T deserialize(final InputStream stream, final int bufferSize) {
392 ByteBufferInput in = new ByteBufferInput(stream, bufferSize);
393 Kryo kryo = borrow();
394 try {
395 @SuppressWarnings("unchecked")
396 T obj = (T) kryo.readClassAndObject(in);
397 return obj;
398 } finally {
399 release(kryo);
400 }
401 }
402
HIGUCHI Yutab2d0fd82016-05-17 20:34:58 -0700403 private String friendlyName() {
404 return friendlyName;
405 }
406
Yuta HIGUCHI91768e32014-11-22 05:06:35 -0800407 /**
Jonathan Hart679d24d2016-05-13 13:29:53 -0700408 * Gets the number of classes registered in this Kryo namespace.
409 *
410 * @return size of namespace
411 */
412 public int size() {
413 return (int) registeredBlocks.stream()
414 .flatMap(block -> block.types().stream())
415 .count();
416 }
417
418 /**
Yuta HIGUCHI91768e32014-11-22 05:06:35 -0800419 * Creates a Kryo instance.
Yuta HIGUCHI24a086b2014-09-21 23:28:41 -0700420 *
421 * @return Kryo instance
422 */
Yuta HIGUCHI633cf882014-10-20 09:10:28 -0700423 @Override
424 public Kryo create() {
HIGUCHI Yuta0a1f29e2016-05-05 15:34:41 -0700425 log.trace("Creating Kryo instance for {}", this);
Yuta HIGUCHI24a086b2014-09-21 23:28:41 -0700426 Kryo kryo = new Kryo();
427 kryo.setRegistrationRequired(registrationRequired);
Jonathan Hartbe093f72016-03-25 11:14:29 -0700428
429 // TODO rethink whether we want to use StdInstantiatorStrategy
430 kryo.setInstantiatorStrategy(
431 new Kryo.DefaultInstantiatorStrategy(new StdInstantiatorStrategy()));
432
Yuta HIGUCHI91768e32014-11-22 05:06:35 -0800433 for (RegistrationBlock block : registeredBlocks) {
434 int id = block.begin();
435 if (id == FLOATING_ID) {
436 id = kryo.getNextRegistrationId();
437 }
438 for (Pair<Class<?>, Serializer<?>> entry : block.types()) {
HIGUCHI Yuta0a1f29e2016-05-05 15:34:41 -0700439 register(kryo, entry.getLeft(), entry.getRight(), id++);
Yuta HIGUCHI24a086b2014-09-21 23:28:41 -0700440 }
441 }
442 return kryo;
443 }
Yuta HIGUCHI533ec322014-09-30 13:29:52 -0700444
HIGUCHI Yuta0a1f29e2016-05-05 15:34:41 -0700445 /**
446 * Register {@code type} and {@code serializer} to {@code kryo} instance.
447 *
448 * @param kryo Kryo instance
449 * @param type type to register
450 * @param serializer Specific serializer to register or null to use default.
451 * @param id type registration id to use
452 */
HIGUCHI Yutab2d0fd82016-05-17 20:34:58 -0700453 private void register(Kryo kryo, Class<?> type, Serializer<?> serializer, int id) {
HIGUCHI Yuta0a1f29e2016-05-05 15:34:41 -0700454 Registration existing = kryo.getRegistration(id);
455 if (existing != null) {
456 if (existing.getType() != type) {
HIGUCHI Yutab2d0fd82016-05-17 20:34:58 -0700457 log.error("{}: Failed to register {} as {}, {} was already registered.",
458 friendlyName(), type, id, existing.getType());
HIGUCHI Yuta0a1f29e2016-05-05 15:34:41 -0700459
460 throw new IllegalStateException(String.format(
461 "Failed to register %s as %s, %s was already registered.",
462 type, id, existing.getType()));
463 }
464 // falling through to register call for now.
465 // Consider skipping, if there's reasonable
466 // way to compare serializer equivalence.
467 }
468 Registration r;
469 if (serializer == null) {
470 r = kryo.register(type, id);
471 } else {
472 r = kryo.register(type, serializer, id);
473 }
474 if (r.getId() != id) {
HIGUCHI Yutab2d0fd82016-05-17 20:34:58 -0700475 log.warn("{}: {} already registed as {}. Skipping {}.",
476 friendlyName(), r.getType(), r.getId(), id);
HIGUCHI Yuta0a1f29e2016-05-05 15:34:41 -0700477 }
478 log.trace("{} registered as {}", r.getType(), r.getId());
479 }
480
Yuta HIGUCHI91768e32014-11-22 05:06:35 -0800481 @Override
482 public Kryo borrow() {
483 return pool.borrow();
484 }
Yuta HIGUCHI533ec322014-09-30 13:29:52 -0700485
Yuta HIGUCHI91768e32014-11-22 05:06:35 -0800486 @Override
487 public void release(Kryo kryo) {
488 pool.release(kryo);
489 }
Yuta HIGUCHI533ec322014-09-30 13:29:52 -0700490
Yuta HIGUCHI91768e32014-11-22 05:06:35 -0800491 @Override
492 public <T> T run(KryoCallback<T> callback) {
493 return pool.run(callback);
494 }
495
496 @Override
497 public String toString() {
HIGUCHI Yutab2d0fd82016-05-17 20:34:58 -0700498 if (friendlyName != NO_NAME) {
499 return MoreObjects.toStringHelper(getClass())
500 .omitNullValues()
501 .add("friendlyName", friendlyName)
502 // omit lengthy detail, when there's a name
503 .toString();
504 }
Yuta HIGUCHI91768e32014-11-22 05:06:35 -0800505 return MoreObjects.toStringHelper(getClass())
506 .add("registeredBlocks", registeredBlocks)
507 .toString();
508 }
509
510 static final class RegistrationBlock {
511 private final int begin;
512 private final ImmutableList<Pair<Class<?>, Serializer<?>>> types;
513
514 public RegistrationBlock(int begin, List<Pair<Class<?>, Serializer<?>>> types) {
515 this.begin = begin;
516 this.types = ImmutableList.copyOf(types);
Yuta HIGUCHI533ec322014-09-30 13:29:52 -0700517 }
518
Yuta HIGUCHI91768e32014-11-22 05:06:35 -0800519 public int begin() {
520 return begin;
Yuta HIGUCHI533ec322014-09-30 13:29:52 -0700521 }
522
Yuta HIGUCHI91768e32014-11-22 05:06:35 -0800523 public ImmutableList<Pair<Class<?>, Serializer<?>>> types() {
524 return types;
525 }
526
527 @Override
528 public String toString() {
529 return MoreObjects.toStringHelper(getClass())
530 .add("begin", begin)
531 .add("types", types)
532 .toString();
Yuta HIGUCHI533ec322014-09-30 13:29:52 -0700533 }
HIGUCHI Yutab2d0fd82016-05-17 20:34:58 -0700534
535 @Override
536 public int hashCode() {
537 return types.hashCode();
538 }
539
540 // Only the registered types are used for equality.
541 @Override
542 public boolean equals(Object obj) {
543 if (this == obj) {
544 return true;
545 }
546
547 if (obj instanceof RegistrationBlock) {
548 RegistrationBlock that = (RegistrationBlock) obj;
549 return Objects.equals(this.types, that.types);
550 }
551 return false;
552 }
Yuta HIGUCHI533ec322014-09-30 13:29:52 -0700553 }
Yuta HIGUCHI24a086b2014-09-21 23:28:41 -0700554}