blob: 7328c8d01647a934fdfdc7ce4989aeeef9cd3712 [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 HIGUCHI86f142f2016-07-09 17:44:09 -070024import com.esotericsoftware.kryo.io.Output;
Yuta HIGUCHI91768e32014-11-22 05:06:35 -080025import com.esotericsoftware.kryo.pool.KryoCallback;
Yuta HIGUCHI633cf882014-10-20 09:10:28 -070026import com.esotericsoftware.kryo.pool.KryoFactory;
Yuta HIGUCHI91768e32014-11-22 05:06:35 -080027import com.esotericsoftware.kryo.pool.KryoPool;
28import com.google.common.base.MoreObjects;
Yuta HIGUCHI24a086b2014-09-21 23:28:41 -070029import com.google.common.collect.ImmutableList;
Jonathan Hartbe093f72016-03-25 11:14:29 -070030import org.apache.commons.lang3.tuple.Pair;
31import org.objenesis.strategy.StdInstantiatorStrategy;
32import org.slf4j.Logger;
33
34import java.io.InputStream;
35import java.io.OutputStream;
36import java.nio.ByteBuffer;
37import java.util.ArrayList;
38import java.util.List;
HIGUCHI Yutab2d0fd82016-05-17 20:34:58 -070039import java.util.Objects;
Jonathan Hartbe093f72016-03-25 11:14:29 -070040
HIGUCHI Yutab2d0fd82016-05-17 20:34:58 -070041import static com.google.common.base.Preconditions.checkNotNull;
Jonathan Hartbe093f72016-03-25 11:14:29 -070042import static org.slf4j.LoggerFactory.getLogger;
Yuta HIGUCHI24a086b2014-09-21 23:28:41 -070043
Yuta HIGUCHI24a086b2014-09-21 23:28:41 -070044/**
45 * Pool of Kryo instances, with classes pre-registered.
46 */
47//@ThreadSafe
Yuta HIGUCHI91768e32014-11-22 05:06:35 -080048public final class KryoNamespace implements KryoFactory, KryoPool {
Yuta HIGUCHI24a086b2014-09-21 23:28:41 -070049
50 /**
51 * Default buffer size used for serialization.
52 *
53 * @see #serialize(Object)
54 */
Yuta HIGUCHI38782052014-11-09 23:51:58 -080055 public static final int DEFAULT_BUFFER_SIZE = 4096;
Yuta HIGUCHId2a38822014-11-06 19:05:04 -080056 public static final int MAX_BUFFER_SIZE = 100 * 1000 * 1000;
Yuta HIGUCHI24a086b2014-09-21 23:28:41 -070057
Yuta HIGUCHI91768e32014-11-22 05:06:35 -080058 /**
59 * ID to use if this KryoNamespace does not define registration id.
60 */
61 public static final int FLOATING_ID = -1;
62
63 /**
64 * Smallest ID free to use for user defined registrations.
65 */
HIGUCHI Yuta0a1f29e2016-05-05 15:34:41 -070066 public static final int INITIAL_ID = 16;
Yuta HIGUCHI91768e32014-11-22 05:06:35 -080067
HIGUCHI Yutab2d0fd82016-05-17 20:34:58 -070068 private static final String NO_NAME = "(no name)";
69
HIGUCHI Yutab49b0072016-02-22 22:50:45 -080070 private static final Logger log = getLogger(KryoNamespace.class);
71
Yuta HIGUCHI91768e32014-11-22 05:06:35 -080072
HIGUCHI Yutab2d0fd82016-05-17 20:34:58 -070073
Yuta HIGUCHI91768e32014-11-22 05:06:35 -080074 private final KryoPool pool = new KryoPool.Builder(this)
75 .softReferences()
76 .build();
77
78 private final ImmutableList<RegistrationBlock> registeredBlocks;
79
Yuta HIGUCHI24a086b2014-09-21 23:28:41 -070080 private final boolean registrationRequired;
HIGUCHI Yutab2d0fd82016-05-17 20:34:58 -070081 private final String friendlyName;
Yuta HIGUCHI24a086b2014-09-21 23:28:41 -070082
83 /**
Yuta HIGUCHI8d143d22014-10-19 23:15:09 -070084 * KryoNamespace builder.
Yuta HIGUCHI24a086b2014-09-21 23:28:41 -070085 */
86 //@NotThreadSafe
87 public static final class Builder {
88
Yuta HIGUCHI91768e32014-11-22 05:06:35 -080089 private int blockHeadId = INITIAL_ID;
90 private List<Pair<Class<?>, Serializer<?>>> types = new ArrayList<>();
91 private List<RegistrationBlock> blocks = new ArrayList<>();
Yuta HIGUCHI2befc662014-10-30 15:57:49 -070092 private boolean registrationRequired = true;
Yuta HIGUCHI24a086b2014-09-21 23:28:41 -070093
94 /**
Yuta HIGUCHI8d143d22014-10-19 23:15:09 -070095 * Builds a {@link KryoNamespace} instance.
Yuta HIGUCHI24a086b2014-09-21 23:28:41 -070096 *
Yuta HIGUCHI8d143d22014-10-19 23:15:09 -070097 * @return KryoNamespace
Yuta HIGUCHI24a086b2014-09-21 23:28:41 -070098 */
Yuta HIGUCHI8d143d22014-10-19 23:15:09 -070099 public KryoNamespace build() {
HIGUCHI Yutab2d0fd82016-05-17 20:34:58 -0700100 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) {
Yuta HIGUCHI91768e32014-11-22 05:06:35 -0800110 if (!types.isEmpty()) {
111 blocks.add(new RegistrationBlock(this.blockHeadId, types));
112 }
HIGUCHI Yutab2d0fd82016-05-17 20:34:58 -0700113 return new KryoNamespace(blocks, registrationRequired, friendlyName).populate(1);
Yuta HIGUCHI91768e32014-11-22 05:06:35 -0800114 }
115
116 /**
117 * Sets the next Kryo registration Id for following register entries.
118 *
119 * @param id Kryo registration Id
120 * @return this
121 *
122 * @see Kryo#register(Class, Serializer, int)
123 */
124 public Builder nextId(final int id) {
125 if (!types.isEmpty()) {
HIGUCHI Yutab49b0072016-02-22 22:50:45 -0800126 if (id != FLOATING_ID && id < blockHeadId + types.size()) {
127
HIGUCHI Yuta163efb52016-05-18 19:24:19 -0700128 if (log.isWarnEnabled()) {
129 log.warn("requested nextId {} could potentially overlap " +
130 "with existing registrations {}+{} ",
131 id, blockHeadId, types.size(), new RuntimeException());
132 }
HIGUCHI Yutab49b0072016-02-22 22:50:45 -0800133 }
Yuta HIGUCHI91768e32014-11-22 05:06:35 -0800134 blocks.add(new RegistrationBlock(this.blockHeadId, types));
135 types = new ArrayList<>();
136 }
137 this.blockHeadId = id;
138 return this;
Yuta HIGUCHI24a086b2014-09-21 23:28:41 -0700139 }
140
141 /**
142 * Registers classes to be serialized using Kryo default serializer.
143 *
144 * @param expectedTypes list of classes
145 * @return this
146 */
147 public Builder register(final Class<?>... expectedTypes) {
148 for (Class<?> clazz : expectedTypes) {
Yuta HIGUCHI91768e32014-11-22 05:06:35 -0800149 types.add(Pair.of(clazz, null));
Yuta HIGUCHI24a086b2014-09-21 23:28:41 -0700150 }
151 return this;
152 }
153
154 /**
155 * Registers a class and it's serializer.
156 *
Yuta HIGUCHI91768e32014-11-22 05:06:35 -0800157 * @param classes list of classes to register
Yuta HIGUCHI24a086b2014-09-21 23:28:41 -0700158 * @param serializer serializer to use for the class
159 * @return this
160 */
Yuta HIGUCHI91768e32014-11-22 05:06:35 -0800161 public Builder register(Serializer<?> serializer, final Class<?>... classes) {
162 for (Class<?> clazz : classes) {
163 types.add(Pair.of(clazz, serializer));
164 }
165 return this;
166 }
167
168 private Builder register(RegistrationBlock block) {
169 if (block.begin() != FLOATING_ID) {
170 // flush pending types
171 nextId(block.begin());
172 blocks.add(block);
173 nextId(block.begin() + block.types().size());
174 } else {
175 // flush pending types
176 final int addedBlockBegin = blockHeadId + types.size();
177 nextId(addedBlockBegin);
178 blocks.add(new RegistrationBlock(addedBlockBegin, block.types()));
179 nextId(addedBlockBegin + block.types().size());
180 }
Yuta HIGUCHI24a086b2014-09-21 23:28:41 -0700181 return this;
182 }
183
184 /**
Yuta HIGUCHI8d143d22014-10-19 23:15:09 -0700185 * Registers all the class registered to given KryoNamespace.
Yuta HIGUCHI24a086b2014-09-21 23:28:41 -0700186 *
Yuta HIGUCHI91768e32014-11-22 05:06:35 -0800187 * @param ns KryoNamespace
Yuta HIGUCHI24a086b2014-09-21 23:28:41 -0700188 * @return this
189 */
Yuta HIGUCHI91768e32014-11-22 05:06:35 -0800190 public Builder register(final KryoNamespace ns) {
HIGUCHI Yutab2d0fd82016-05-17 20:34:58 -0700191
192 if (blocks.containsAll(ns.registeredBlocks)) {
193 // Everything was already registered.
194 log.debug("Ignoring {}, already registered.", ns);
195 return this;
196 }
Yuta HIGUCHI91768e32014-11-22 05:06:35 -0800197 for (RegistrationBlock block : ns.registeredBlocks) {
198 this.register(block);
199 }
Yuta HIGUCHI24a086b2014-09-21 23:28:41 -0700200 return this;
201 }
Yuta HIGUCHI2befc662014-10-30 15:57:49 -0700202
Yuta HIGUCHI91768e32014-11-22 05:06:35 -0800203 /**
204 * Sets the registrationRequired flag.
205 *
206 * @param registrationRequired Kryo's registrationRequired flag
207 * @return this
208 *
209 * @see Kryo#setRegistrationRequired(boolean)
210 */
Yuta HIGUCHI2befc662014-10-30 15:57:49 -0700211 public Builder setRegistrationRequired(boolean registrationRequired) {
212 this.registrationRequired = registrationRequired;
213 return this;
214 }
Yuta HIGUCHI24a086b2014-09-21 23:28:41 -0700215 }
216
217 /**
Yuta HIGUCHI8d143d22014-10-19 23:15:09 -0700218 * Creates a new {@link KryoNamespace} builder.
Yuta HIGUCHI24a086b2014-09-21 23:28:41 -0700219 *
220 * @return builder
221 */
222 public static Builder newBuilder() {
223 return new Builder();
224 }
225
226 /**
227 * Creates a Kryo instance pool.
228 *
Jonathan Hart4f60f982014-10-27 08:11:17 -0700229 * @param registeredTypes types to register
Yuta HIGUCHI2befc662014-10-30 15:57:49 -0700230 * @param registrationRequired
HIGUCHI Yutab2d0fd82016-05-17 20:34:58 -0700231 * @param friendlyName friendly name for the namespace
Yuta HIGUCHI24a086b2014-09-21 23:28:41 -0700232 */
HIGUCHI Yutab2d0fd82016-05-17 20:34:58 -0700233 private KryoNamespace(final List<RegistrationBlock> registeredTypes,
234 boolean registrationRequired,
235 String friendlyName) {
Yuta HIGUCHI91768e32014-11-22 05:06:35 -0800236 this.registeredBlocks = ImmutableList.copyOf(registeredTypes);
Yuta HIGUCHI2befc662014-10-30 15:57:49 -0700237 this.registrationRequired = registrationRequired;
HIGUCHI Yutab2d0fd82016-05-17 20:34:58 -0700238 this.friendlyName = checkNotNull(friendlyName);
Yuta HIGUCHI24a086b2014-09-21 23:28:41 -0700239 }
240
241 /**
242 * Populates the Kryo pool.
243 *
244 * @param instances to add to the pool
245 * @return this
246 */
Yuta HIGUCHI8d143d22014-10-19 23:15:09 -0700247 public KryoNamespace populate(int instances) {
Yuta HIGUCHI91768e32014-11-22 05:06:35 -0800248
Yuta HIGUCHI24a086b2014-09-21 23:28:41 -0700249 for (int i = 0; i < instances; ++i) {
Yuta HIGUCHI91768e32014-11-22 05:06:35 -0800250 release(create());
Yuta HIGUCHI24a086b2014-09-21 23:28:41 -0700251 }
Yuta HIGUCHI24a086b2014-09-21 23:28:41 -0700252 return this;
253 }
254
255 /**
Yuta HIGUCHI24a086b2014-09-21 23:28:41 -0700256 * Serializes given object to byte array using Kryo instance in pool.
257 * <p>
Yuta HIGUCHI38782052014-11-09 23:51:58 -0800258 * Note: Serialized bytes must be smaller than {@link #MAX_BUFFER_SIZE}.
Yuta HIGUCHI24a086b2014-09-21 23:28:41 -0700259 *
260 * @param obj Object to serialize
261 * @return serialized bytes
262 */
263 public byte[] serialize(final Object obj) {
264 return serialize(obj, DEFAULT_BUFFER_SIZE);
265 }
266
267 /**
268 * Serializes given object to byte array using Kryo instance in pool.
269 *
270 * @param obj Object to serialize
271 * @param bufferSize maximum size of serialized bytes
272 * @return serialized bytes
273 */
274 public byte[] serialize(final Object obj, final int bufferSize) {
Yuta HIGUCHI86f142f2016-07-09 17:44:09 -0700275 Output out = new Output(bufferSize, MAX_BUFFER_SIZE);
276 return pool.run(kryo -> {
277 kryo.writeClassAndObject(out, obj);
278 out.flush();
279 return out.toBytes();
280 });
Yuta HIGUCHI24a086b2014-09-21 23:28:41 -0700281 }
282
283 /**
Yuta HIGUCHIf4b107e2014-09-29 17:27:26 -0700284 * Serializes given object to byte buffer using Kryo instance in pool.
285 *
286 * @param obj Object to serialize
287 * @param buffer to write to
288 */
289 public void serialize(final Object obj, final ByteBuffer buffer) {
290 ByteBufferOutput out = new ByteBufferOutput(buffer);
Yuta HIGUCHI91768e32014-11-22 05:06:35 -0800291 Kryo kryo = borrow();
Yuta HIGUCHIf4b107e2014-09-29 17:27:26 -0700292 try {
293 kryo.writeClassAndObject(out, obj);
Yuta HIGUCHIcac919c2014-10-20 22:17:20 -0700294 out.flush();
Yuta HIGUCHIf4b107e2014-09-29 17:27:26 -0700295 } finally {
Yuta HIGUCHI91768e32014-11-22 05:06:35 -0800296 release(kryo);
297 }
298 }
299
300 /**
301 * Serializes given object to OutputStream using Kryo instance in pool.
302 *
303 * @param obj Object to serialize
304 * @param stream to write to
305 */
306 public void serialize(final Object obj, final OutputStream stream) {
307 serialize(obj, stream, DEFAULT_BUFFER_SIZE);
308 }
309
310 /**
311 * Serializes given object to OutputStream using Kryo instance in pool.
312 *
313 * @param obj Object to serialize
314 * @param stream to write to
315 * @param bufferSize size of the buffer in front of the stream
316 */
317 public void serialize(final Object obj, final OutputStream stream, final int bufferSize) {
318 ByteBufferOutput out = new ByteBufferOutput(stream, bufferSize);
319 Kryo kryo = borrow();
320 try {
321 kryo.writeClassAndObject(out, obj);
322 out.flush();
323 } finally {
324 release(kryo);
Yuta HIGUCHIf4b107e2014-09-29 17:27:26 -0700325 }
326 }
327
328 /**
Yuta HIGUCHI24a086b2014-09-21 23:28:41 -0700329 * Deserializes given byte array to Object using Kryo instance in pool.
330 *
331 * @param bytes serialized bytes
332 * @param <T> deserialized Object type
333 * @return deserialized Object
334 */
335 public <T> T deserialize(final byte[] bytes) {
336 Input in = new Input(bytes);
Yuta HIGUCHI91768e32014-11-22 05:06:35 -0800337 Kryo kryo = borrow();
Yuta HIGUCHI24a086b2014-09-21 23:28:41 -0700338 try {
339 @SuppressWarnings("unchecked")
340 T obj = (T) kryo.readClassAndObject(in);
341 return obj;
342 } finally {
Yuta HIGUCHI91768e32014-11-22 05:06:35 -0800343 release(kryo);
Yuta HIGUCHI24a086b2014-09-21 23:28:41 -0700344 }
345 }
346
Yuta HIGUCHIf4b107e2014-09-29 17:27:26 -0700347 /**
348 * Deserializes given byte buffer to Object using Kryo instance in pool.
349 *
350 * @param buffer input with serialized bytes
351 * @param <T> deserialized Object type
352 * @return deserialized Object
353 */
354 public <T> T deserialize(final ByteBuffer buffer) {
355 ByteBufferInput in = new ByteBufferInput(buffer);
Yuta HIGUCHI91768e32014-11-22 05:06:35 -0800356 Kryo kryo = borrow();
Yuta HIGUCHIf4b107e2014-09-29 17:27:26 -0700357 try {
358 @SuppressWarnings("unchecked")
359 T obj = (T) kryo.readClassAndObject(in);
360 return obj;
361 } finally {
Yuta HIGUCHI91768e32014-11-22 05:06:35 -0800362 release(kryo);
Yuta HIGUCHIf4b107e2014-09-29 17:27:26 -0700363 }
364 }
Yuta HIGUCHI24a086b2014-09-21 23:28:41 -0700365
366 /**
Yuta HIGUCHI91768e32014-11-22 05:06:35 -0800367 * Deserializes given InputStream to an Object using Kryo instance in pool.
368 *
369 * @param stream input stream
370 * @param <T> deserialized Object type
371 * @return deserialized Object
372 */
373 public <T> T deserialize(final InputStream stream) {
374 return deserialize(stream, DEFAULT_BUFFER_SIZE);
375 }
376
377 /**
378 * Deserializes given InputStream to an Object using Kryo instance in pool.
379 *
380 * @param stream input stream
381 * @param <T> deserialized Object type
382 * @return deserialized Object
383 * @param bufferSize size of the buffer in front of the stream
384 */
385 public <T> T deserialize(final InputStream stream, final int bufferSize) {
386 ByteBufferInput in = new ByteBufferInput(stream, bufferSize);
387 Kryo kryo = borrow();
388 try {
389 @SuppressWarnings("unchecked")
390 T obj = (T) kryo.readClassAndObject(in);
391 return obj;
392 } finally {
393 release(kryo);
394 }
395 }
396
HIGUCHI Yutab2d0fd82016-05-17 20:34:58 -0700397 private String friendlyName() {
398 return friendlyName;
399 }
400
Yuta HIGUCHI91768e32014-11-22 05:06:35 -0800401 /**
Jonathan Hart679d24d2016-05-13 13:29:53 -0700402 * Gets the number of classes registered in this Kryo namespace.
403 *
404 * @return size of namespace
405 */
406 public int size() {
407 return (int) registeredBlocks.stream()
408 .flatMap(block -> block.types().stream())
409 .count();
410 }
411
412 /**
Yuta HIGUCHI91768e32014-11-22 05:06:35 -0800413 * Creates a Kryo instance.
Yuta HIGUCHI24a086b2014-09-21 23:28:41 -0700414 *
415 * @return Kryo instance
416 */
Yuta HIGUCHI633cf882014-10-20 09:10:28 -0700417 @Override
418 public Kryo create() {
HIGUCHI Yuta0a1f29e2016-05-05 15:34:41 -0700419 log.trace("Creating Kryo instance for {}", this);
Yuta HIGUCHI24a086b2014-09-21 23:28:41 -0700420 Kryo kryo = new Kryo();
421 kryo.setRegistrationRequired(registrationRequired);
Jonathan Hartbe093f72016-03-25 11:14:29 -0700422
423 // TODO rethink whether we want to use StdInstantiatorStrategy
424 kryo.setInstantiatorStrategy(
425 new Kryo.DefaultInstantiatorStrategy(new StdInstantiatorStrategy()));
426
Yuta HIGUCHI91768e32014-11-22 05:06:35 -0800427 for (RegistrationBlock block : registeredBlocks) {
428 int id = block.begin();
429 if (id == FLOATING_ID) {
430 id = kryo.getNextRegistrationId();
431 }
432 for (Pair<Class<?>, Serializer<?>> entry : block.types()) {
HIGUCHI Yuta0a1f29e2016-05-05 15:34:41 -0700433 register(kryo, entry.getLeft(), entry.getRight(), id++);
Yuta HIGUCHI24a086b2014-09-21 23:28:41 -0700434 }
435 }
436 return kryo;
437 }
Yuta HIGUCHI533ec322014-09-30 13:29:52 -0700438
HIGUCHI Yuta0a1f29e2016-05-05 15:34:41 -0700439 /**
440 * Register {@code type} and {@code serializer} to {@code kryo} instance.
441 *
442 * @param kryo Kryo instance
443 * @param type type to register
444 * @param serializer Specific serializer to register or null to use default.
445 * @param id type registration id to use
446 */
HIGUCHI Yutab2d0fd82016-05-17 20:34:58 -0700447 private void register(Kryo kryo, Class<?> type, Serializer<?> serializer, int id) {
HIGUCHI Yuta0a1f29e2016-05-05 15:34:41 -0700448 Registration existing = kryo.getRegistration(id);
449 if (existing != null) {
450 if (existing.getType() != type) {
HIGUCHI Yutab2d0fd82016-05-17 20:34:58 -0700451 log.error("{}: Failed to register {} as {}, {} was already registered.",
452 friendlyName(), type, id, existing.getType());
HIGUCHI Yuta0a1f29e2016-05-05 15:34:41 -0700453
454 throw new IllegalStateException(String.format(
455 "Failed to register %s as %s, %s was already registered.",
456 type, id, existing.getType()));
457 }
458 // falling through to register call for now.
459 // Consider skipping, if there's reasonable
460 // way to compare serializer equivalence.
461 }
462 Registration r;
463 if (serializer == null) {
464 r = kryo.register(type, id);
465 } else {
466 r = kryo.register(type, serializer, id);
467 }
468 if (r.getId() != id) {
HIGUCHI Yutab2d0fd82016-05-17 20:34:58 -0700469 log.warn("{}: {} already registed as {}. Skipping {}.",
470 friendlyName(), r.getType(), r.getId(), id);
HIGUCHI Yuta0a1f29e2016-05-05 15:34:41 -0700471 }
472 log.trace("{} registered as {}", r.getType(), r.getId());
473 }
474
Yuta HIGUCHI91768e32014-11-22 05:06:35 -0800475 @Override
476 public Kryo borrow() {
477 return pool.borrow();
478 }
Yuta HIGUCHI533ec322014-09-30 13:29:52 -0700479
Yuta HIGUCHI91768e32014-11-22 05:06:35 -0800480 @Override
481 public void release(Kryo kryo) {
482 pool.release(kryo);
483 }
Yuta HIGUCHI533ec322014-09-30 13:29:52 -0700484
Yuta HIGUCHI91768e32014-11-22 05:06:35 -0800485 @Override
486 public <T> T run(KryoCallback<T> callback) {
487 return pool.run(callback);
488 }
489
490 @Override
491 public String toString() {
HIGUCHI Yutab2d0fd82016-05-17 20:34:58 -0700492 if (friendlyName != NO_NAME) {
493 return MoreObjects.toStringHelper(getClass())
494 .omitNullValues()
495 .add("friendlyName", friendlyName)
496 // omit lengthy detail, when there's a name
497 .toString();
498 }
Yuta HIGUCHI91768e32014-11-22 05:06:35 -0800499 return MoreObjects.toStringHelper(getClass())
500 .add("registeredBlocks", registeredBlocks)
501 .toString();
502 }
503
504 static final class RegistrationBlock {
505 private final int begin;
506 private final ImmutableList<Pair<Class<?>, Serializer<?>>> types;
507
508 public RegistrationBlock(int begin, List<Pair<Class<?>, Serializer<?>>> types) {
509 this.begin = begin;
510 this.types = ImmutableList.copyOf(types);
Yuta HIGUCHI533ec322014-09-30 13:29:52 -0700511 }
512
Yuta HIGUCHI91768e32014-11-22 05:06:35 -0800513 public int begin() {
514 return begin;
Yuta HIGUCHI533ec322014-09-30 13:29:52 -0700515 }
516
Yuta HIGUCHI91768e32014-11-22 05:06:35 -0800517 public ImmutableList<Pair<Class<?>, Serializer<?>>> types() {
518 return types;
519 }
520
521 @Override
522 public String toString() {
523 return MoreObjects.toStringHelper(getClass())
524 .add("begin", begin)
525 .add("types", types)
526 .toString();
Yuta HIGUCHI533ec322014-09-30 13:29:52 -0700527 }
HIGUCHI Yutab2d0fd82016-05-17 20:34:58 -0700528
529 @Override
530 public int hashCode() {
531 return types.hashCode();
532 }
533
534 // Only the registered types are used for equality.
535 @Override
536 public boolean equals(Object obj) {
537 if (this == obj) {
538 return true;
539 }
540
541 if (obj instanceof RegistrationBlock) {
542 RegistrationBlock that = (RegistrationBlock) obj;
543 return Objects.equals(this.types, that.types);
544 }
545 return false;
546 }
Yuta HIGUCHI533ec322014-09-30 13:29:52 -0700547 }
Yuta HIGUCHI24a086b2014-09-21 23:28:41 -0700548}