blob: 70fdfc81d2fcd7630e0eb22cee8e3bd578aab270 [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
Yuta HIGUCHI91768e32014-11-22 05:06:35 -080082
Yuta HIGUCHI24a086b2014-09-21 23:28:41 -070083 /**
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 Yutab2d0fd82016-05-17 20:34:58 -0700128 log.warn("requested nextId {} could potentially overlap " +
HIGUCHI Yutab49b0072016-02-22 22:50:45 -0800129 "with existing registrations {}+{} ",
130 id, blockHeadId, types.size());
131 }
Yuta HIGUCHI91768e32014-11-22 05:06:35 -0800132 blocks.add(new RegistrationBlock(this.blockHeadId, types));
133 types = new ArrayList<>();
134 }
135 this.blockHeadId = id;
136 return this;
Yuta HIGUCHI24a086b2014-09-21 23:28:41 -0700137 }
138
139 /**
140 * Registers classes to be serialized using Kryo default serializer.
141 *
142 * @param expectedTypes list of classes
143 * @return this
144 */
145 public Builder register(final Class<?>... expectedTypes) {
146 for (Class<?> clazz : expectedTypes) {
Yuta HIGUCHI91768e32014-11-22 05:06:35 -0800147 types.add(Pair.of(clazz, null));
Yuta HIGUCHI24a086b2014-09-21 23:28:41 -0700148 }
149 return this;
150 }
151
152 /**
153 * Registers a class and it's serializer.
154 *
Yuta HIGUCHI91768e32014-11-22 05:06:35 -0800155 * @param classes list of classes to register
Yuta HIGUCHI24a086b2014-09-21 23:28:41 -0700156 * @param serializer serializer to use for the class
157 * @return this
158 */
Yuta HIGUCHI91768e32014-11-22 05:06:35 -0800159 public Builder register(Serializer<?> serializer, final Class<?>... classes) {
160 for (Class<?> clazz : classes) {
161 types.add(Pair.of(clazz, serializer));
162 }
163 return this;
164 }
165
166 private Builder register(RegistrationBlock block) {
167 if (block.begin() != FLOATING_ID) {
168 // flush pending types
169 nextId(block.begin());
170 blocks.add(block);
171 nextId(block.begin() + block.types().size());
172 } else {
173 // flush pending types
174 final int addedBlockBegin = blockHeadId + types.size();
175 nextId(addedBlockBegin);
176 blocks.add(new RegistrationBlock(addedBlockBegin, block.types()));
177 nextId(addedBlockBegin + block.types().size());
178 }
Yuta HIGUCHI24a086b2014-09-21 23:28:41 -0700179 return this;
180 }
181
182 /**
Yuta HIGUCHI8d143d22014-10-19 23:15:09 -0700183 * Registers all the class registered to given KryoNamespace.
Yuta HIGUCHI24a086b2014-09-21 23:28:41 -0700184 *
Yuta HIGUCHI91768e32014-11-22 05:06:35 -0800185 * @param ns KryoNamespace
Yuta HIGUCHI24a086b2014-09-21 23:28:41 -0700186 * @return this
187 */
Yuta HIGUCHI91768e32014-11-22 05:06:35 -0800188 public Builder register(final KryoNamespace ns) {
HIGUCHI Yutab2d0fd82016-05-17 20:34:58 -0700189
190 if (blocks.containsAll(ns.registeredBlocks)) {
191 // Everything was already registered.
192 log.debug("Ignoring {}, already registered.", ns);
193 return this;
194 }
Yuta HIGUCHI91768e32014-11-22 05:06:35 -0800195 for (RegistrationBlock block : ns.registeredBlocks) {
196 this.register(block);
197 }
Yuta HIGUCHI24a086b2014-09-21 23:28:41 -0700198 return this;
199 }
Yuta HIGUCHI2befc662014-10-30 15:57:49 -0700200
Yuta HIGUCHI91768e32014-11-22 05:06:35 -0800201 /**
202 * Sets the registrationRequired flag.
203 *
204 * @param registrationRequired Kryo's registrationRequired flag
205 * @return this
206 *
207 * @see Kryo#setRegistrationRequired(boolean)
208 */
Yuta HIGUCHI2befc662014-10-30 15:57:49 -0700209 public Builder setRegistrationRequired(boolean registrationRequired) {
210 this.registrationRequired = registrationRequired;
211 return this;
212 }
Yuta HIGUCHI24a086b2014-09-21 23:28:41 -0700213 }
214
215 /**
Yuta HIGUCHI8d143d22014-10-19 23:15:09 -0700216 * Creates a new {@link KryoNamespace} builder.
Yuta HIGUCHI24a086b2014-09-21 23:28:41 -0700217 *
218 * @return builder
219 */
220 public static Builder newBuilder() {
221 return new Builder();
222 }
223
224 /**
225 * Creates a Kryo instance pool.
226 *
Jonathan Hart4f60f982014-10-27 08:11:17 -0700227 * @param registeredTypes types to register
Yuta HIGUCHI2befc662014-10-30 15:57:49 -0700228 * @param registrationRequired
HIGUCHI Yutab2d0fd82016-05-17 20:34:58 -0700229 * @param friendlyName friendly name for the namespace
Yuta HIGUCHI24a086b2014-09-21 23:28:41 -0700230 */
HIGUCHI Yutab2d0fd82016-05-17 20:34:58 -0700231 private KryoNamespace(final List<RegistrationBlock> registeredTypes,
232 boolean registrationRequired,
233 String friendlyName) {
Yuta HIGUCHI91768e32014-11-22 05:06:35 -0800234 this.registeredBlocks = ImmutableList.copyOf(registeredTypes);
Yuta HIGUCHI2befc662014-10-30 15:57:49 -0700235 this.registrationRequired = registrationRequired;
HIGUCHI Yutab2d0fd82016-05-17 20:34:58 -0700236 this.friendlyName = checkNotNull(friendlyName);
Yuta HIGUCHI24a086b2014-09-21 23:28:41 -0700237 }
238
239 /**
240 * Populates the Kryo pool.
241 *
242 * @param instances to add to the pool
243 * @return this
244 */
Yuta HIGUCHI8d143d22014-10-19 23:15:09 -0700245 public KryoNamespace populate(int instances) {
Yuta HIGUCHI91768e32014-11-22 05:06:35 -0800246
Yuta HIGUCHI24a086b2014-09-21 23:28:41 -0700247 for (int i = 0; i < instances; ++i) {
Yuta HIGUCHI91768e32014-11-22 05:06:35 -0800248 release(create());
Yuta HIGUCHI24a086b2014-09-21 23:28:41 -0700249 }
Yuta HIGUCHI24a086b2014-09-21 23:28:41 -0700250 return this;
251 }
252
253 /**
Yuta HIGUCHI24a086b2014-09-21 23:28:41 -0700254 * Serializes given object to byte array using Kryo instance in pool.
255 * <p>
Yuta HIGUCHI38782052014-11-09 23:51:58 -0800256 * Note: Serialized bytes must be smaller than {@link #MAX_BUFFER_SIZE}.
Yuta HIGUCHI24a086b2014-09-21 23:28:41 -0700257 *
258 * @param obj Object to serialize
259 * @return serialized bytes
260 */
261 public byte[] serialize(final Object obj) {
262 return serialize(obj, DEFAULT_BUFFER_SIZE);
263 }
264
265 /**
266 * Serializes given object to byte array using Kryo instance in pool.
267 *
268 * @param obj Object to serialize
269 * @param bufferSize maximum size of serialized bytes
270 * @return serialized bytes
271 */
272 public byte[] serialize(final Object obj, final int bufferSize) {
Yuta HIGUCHId2a38822014-11-06 19:05:04 -0800273 ByteBufferOutput out = new ByteBufferOutput(bufferSize, MAX_BUFFER_SIZE);
Yuta HIGUCHI24a086b2014-09-21 23:28:41 -0700274 try {
Madan Jampani22fa5cb2015-04-13 15:53:44 -0700275 Kryo kryo = borrow();
276 try {
277 kryo.writeClassAndObject(out, obj);
278 out.flush();
279 return out.toBytes();
280 } finally {
281 release(kryo);
282 }
Yuta HIGUCHI24a086b2014-09-21 23:28:41 -0700283 } finally {
Madan Jampani22fa5cb2015-04-13 15:53:44 -0700284 out.release();
Yuta HIGUCHI24a086b2014-09-21 23:28:41 -0700285 }
286 }
287
288 /**
Yuta HIGUCHIf4b107e2014-09-29 17:27:26 -0700289 * Serializes given object to byte buffer using Kryo instance in pool.
290 *
291 * @param obj Object to serialize
292 * @param buffer to write to
293 */
294 public void serialize(final Object obj, final ByteBuffer buffer) {
295 ByteBufferOutput out = new ByteBufferOutput(buffer);
Yuta HIGUCHI91768e32014-11-22 05:06:35 -0800296 Kryo kryo = borrow();
Yuta HIGUCHIf4b107e2014-09-29 17:27:26 -0700297 try {
298 kryo.writeClassAndObject(out, obj);
Yuta HIGUCHIcac919c2014-10-20 22:17:20 -0700299 out.flush();
Yuta HIGUCHIf4b107e2014-09-29 17:27:26 -0700300 } finally {
Yuta HIGUCHI91768e32014-11-22 05:06:35 -0800301 release(kryo);
302 }
303 }
304
305 /**
306 * Serializes given object to OutputStream using Kryo instance in pool.
307 *
308 * @param obj Object to serialize
309 * @param stream to write to
310 */
311 public void serialize(final Object obj, final OutputStream stream) {
312 serialize(obj, stream, DEFAULT_BUFFER_SIZE);
313 }
314
315 /**
316 * Serializes given object to OutputStream using Kryo instance in pool.
317 *
318 * @param obj Object to serialize
319 * @param stream to write to
320 * @param bufferSize size of the buffer in front of the stream
321 */
322 public void serialize(final Object obj, final OutputStream stream, final int bufferSize) {
323 ByteBufferOutput out = new ByteBufferOutput(stream, bufferSize);
324 Kryo kryo = borrow();
325 try {
326 kryo.writeClassAndObject(out, obj);
327 out.flush();
328 } finally {
329 release(kryo);
Yuta HIGUCHIf4b107e2014-09-29 17:27:26 -0700330 }
331 }
332
333 /**
Yuta HIGUCHI24a086b2014-09-21 23:28:41 -0700334 * Deserializes given byte array to Object using Kryo instance in pool.
335 *
336 * @param bytes serialized bytes
337 * @param <T> deserialized Object type
338 * @return deserialized Object
339 */
340 public <T> T deserialize(final byte[] bytes) {
341 Input in = new Input(bytes);
Yuta HIGUCHI91768e32014-11-22 05:06:35 -0800342 Kryo kryo = borrow();
Yuta HIGUCHI24a086b2014-09-21 23:28:41 -0700343 try {
344 @SuppressWarnings("unchecked")
345 T obj = (T) kryo.readClassAndObject(in);
346 return obj;
347 } finally {
Yuta HIGUCHI91768e32014-11-22 05:06:35 -0800348 release(kryo);
Yuta HIGUCHI24a086b2014-09-21 23:28:41 -0700349 }
350 }
351
Yuta HIGUCHIf4b107e2014-09-29 17:27:26 -0700352 /**
353 * Deserializes given byte buffer to Object using Kryo instance in pool.
354 *
355 * @param buffer input with serialized bytes
356 * @param <T> deserialized Object type
357 * @return deserialized Object
358 */
359 public <T> T deserialize(final ByteBuffer buffer) {
360 ByteBufferInput in = new ByteBufferInput(buffer);
Yuta HIGUCHI91768e32014-11-22 05:06:35 -0800361 Kryo kryo = borrow();
Yuta HIGUCHIf4b107e2014-09-29 17:27:26 -0700362 try {
363 @SuppressWarnings("unchecked")
364 T obj = (T) kryo.readClassAndObject(in);
365 return obj;
366 } finally {
Yuta HIGUCHI91768e32014-11-22 05:06:35 -0800367 release(kryo);
Yuta HIGUCHIf4b107e2014-09-29 17:27:26 -0700368 }
369 }
Yuta HIGUCHI24a086b2014-09-21 23:28:41 -0700370
371 /**
Yuta HIGUCHI91768e32014-11-22 05:06:35 -0800372 * Deserializes given InputStream to an Object using Kryo instance in pool.
373 *
374 * @param stream input stream
375 * @param <T> deserialized Object type
376 * @return deserialized Object
377 */
378 public <T> T deserialize(final InputStream stream) {
379 return deserialize(stream, DEFAULT_BUFFER_SIZE);
380 }
381
382 /**
383 * Deserializes given InputStream to an Object using Kryo instance in pool.
384 *
385 * @param stream input stream
386 * @param <T> deserialized Object type
387 * @return deserialized Object
388 * @param bufferSize size of the buffer in front of the stream
389 */
390 public <T> T deserialize(final InputStream stream, final int bufferSize) {
391 ByteBufferInput in = new ByteBufferInput(stream, bufferSize);
392 Kryo kryo = borrow();
393 try {
394 @SuppressWarnings("unchecked")
395 T obj = (T) kryo.readClassAndObject(in);
396 return obj;
397 } finally {
398 release(kryo);
399 }
400 }
401
HIGUCHI Yutab2d0fd82016-05-17 20:34:58 -0700402 private String friendlyName() {
403 return friendlyName;
404 }
405
Yuta HIGUCHI91768e32014-11-22 05:06:35 -0800406 /**
407 * Creates a Kryo instance.
Yuta HIGUCHI24a086b2014-09-21 23:28:41 -0700408 *
409 * @return Kryo instance
410 */
Yuta HIGUCHI633cf882014-10-20 09:10:28 -0700411 @Override
412 public Kryo create() {
HIGUCHI Yuta0a1f29e2016-05-05 15:34:41 -0700413 log.trace("Creating Kryo instance for {}", this);
Yuta HIGUCHI24a086b2014-09-21 23:28:41 -0700414 Kryo kryo = new Kryo();
415 kryo.setRegistrationRequired(registrationRequired);
Jonathan Hartbe093f72016-03-25 11:14:29 -0700416
417 // TODO rethink whether we want to use StdInstantiatorStrategy
418 kryo.setInstantiatorStrategy(
419 new Kryo.DefaultInstantiatorStrategy(new StdInstantiatorStrategy()));
420
Yuta HIGUCHI91768e32014-11-22 05:06:35 -0800421 for (RegistrationBlock block : registeredBlocks) {
422 int id = block.begin();
423 if (id == FLOATING_ID) {
424 id = kryo.getNextRegistrationId();
425 }
426 for (Pair<Class<?>, Serializer<?>> entry : block.types()) {
HIGUCHI Yuta0a1f29e2016-05-05 15:34:41 -0700427 register(kryo, entry.getLeft(), entry.getRight(), id++);
Yuta HIGUCHI24a086b2014-09-21 23:28:41 -0700428 }
429 }
430 return kryo;
431 }
Yuta HIGUCHI533ec322014-09-30 13:29:52 -0700432
HIGUCHI Yuta0a1f29e2016-05-05 15:34:41 -0700433 /**
434 * Register {@code type} and {@code serializer} to {@code kryo} instance.
435 *
436 * @param kryo Kryo instance
437 * @param type type to register
438 * @param serializer Specific serializer to register or null to use default.
439 * @param id type registration id to use
440 */
HIGUCHI Yutab2d0fd82016-05-17 20:34:58 -0700441 private void register(Kryo kryo, Class<?> type, Serializer<?> serializer, int id) {
HIGUCHI Yuta0a1f29e2016-05-05 15:34:41 -0700442 Registration existing = kryo.getRegistration(id);
443 if (existing != null) {
444 if (existing.getType() != type) {
HIGUCHI Yutab2d0fd82016-05-17 20:34:58 -0700445 log.error("{}: Failed to register {} as {}, {} was already registered.",
446 friendlyName(), type, id, existing.getType());
HIGUCHI Yuta0a1f29e2016-05-05 15:34:41 -0700447
448 throw new IllegalStateException(String.format(
449 "Failed to register %s as %s, %s was already registered.",
450 type, id, existing.getType()));
451 }
452 // falling through to register call for now.
453 // Consider skipping, if there's reasonable
454 // way to compare serializer equivalence.
455 }
456 Registration r;
457 if (serializer == null) {
458 r = kryo.register(type, id);
459 } else {
460 r = kryo.register(type, serializer, id);
461 }
462 if (r.getId() != id) {
HIGUCHI Yutab2d0fd82016-05-17 20:34:58 -0700463 log.warn("{}: {} already registed as {}. Skipping {}.",
464 friendlyName(), r.getType(), r.getId(), id);
HIGUCHI Yuta0a1f29e2016-05-05 15:34:41 -0700465 }
466 log.trace("{} registered as {}", r.getType(), r.getId());
467 }
468
Yuta HIGUCHI91768e32014-11-22 05:06:35 -0800469 @Override
470 public Kryo borrow() {
471 return pool.borrow();
472 }
Yuta HIGUCHI533ec322014-09-30 13:29:52 -0700473
Yuta HIGUCHI91768e32014-11-22 05:06:35 -0800474 @Override
475 public void release(Kryo kryo) {
476 pool.release(kryo);
477 }
Yuta HIGUCHI533ec322014-09-30 13:29:52 -0700478
Yuta HIGUCHI91768e32014-11-22 05:06:35 -0800479 @Override
480 public <T> T run(KryoCallback<T> callback) {
481 return pool.run(callback);
482 }
483
484 @Override
485 public String toString() {
HIGUCHI Yutab2d0fd82016-05-17 20:34:58 -0700486 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 }
Yuta HIGUCHI91768e32014-11-22 05:06:35 -0800493 return MoreObjects.toStringHelper(getClass())
494 .add("registeredBlocks", registeredBlocks)
495 .toString();
496 }
497
498 static final class RegistrationBlock {
499 private final int begin;
500 private final ImmutableList<Pair<Class<?>, Serializer<?>>> types;
501
502 public RegistrationBlock(int begin, List<Pair<Class<?>, Serializer<?>>> types) {
503 this.begin = begin;
504 this.types = ImmutableList.copyOf(types);
Yuta HIGUCHI533ec322014-09-30 13:29:52 -0700505 }
506
Yuta HIGUCHI91768e32014-11-22 05:06:35 -0800507 public int begin() {
508 return begin;
Yuta HIGUCHI533ec322014-09-30 13:29:52 -0700509 }
510
Yuta HIGUCHI91768e32014-11-22 05:06:35 -0800511 public ImmutableList<Pair<Class<?>, Serializer<?>>> types() {
512 return types;
513 }
514
515 @Override
516 public String toString() {
517 return MoreObjects.toStringHelper(getClass())
518 .add("begin", begin)
519 .add("types", types)
520 .toString();
Yuta HIGUCHI533ec322014-09-30 13:29:52 -0700521 }
HIGUCHI Yutab2d0fd82016-05-17 20:34:58 -0700522
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 }
Yuta HIGUCHI533ec322014-09-30 13:29:52 -0700541 }
Yuta HIGUCHI24a086b2014-09-21 23:28:41 -0700542}