Package com.nokia.dempsy.serialization.kryo

Source Code of com.nokia.dempsy.serialization.kryo.KryoSerializer$KryoHolder

/*
* Copyright 2012 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
*      http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package com.nokia.dempsy.serialization.kryo;

import java.util.Arrays;
import java.util.List;
import java.util.concurrent.ConcurrentLinkedQueue;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.esotericsoftware.kryo.Kryo;
import com.esotericsoftware.kryo.KryoException;
import com.esotericsoftware.kryo.io.Input;
import com.esotericsoftware.kryo.io.Output;
import com.nokia.dempsy.internal.util.SafeString;
import com.nokia.dempsy.serialization.SerializationException;
import com.nokia.dempsy.serialization.Serializer;

/**
* This is the implementation of the Kryo based serialization for Dempsy.
* It can be configured with registered classes using Spring by passing
* a list of {@link Registration} instances to the constructor.
*/
public class KryoSerializer<T> implements Serializer<T>
{
   private static Logger logger = LoggerFactory.getLogger(KryoSerializer.class);
   private static class KryoHolder
   {
      public Kryo kryo = new Kryo();
      public Output output = new Output(1024, 1024*1024*1024);
      public Input input = new Input();
   }
   // need an object pool of Kryo instances since Kryo is not thread safe
   private ConcurrentLinkedQueue<KryoHolder> kryopool = new ConcurrentLinkedQueue<KryoHolder>();
   private List<Registration> registrations = null;
   private KryoOptimizer optimizer = null;
   private boolean requireRegistration = false;
  
   /**
    * Create an unconfigured default {@link KryoSerializer} with no registered classes.
    */
   public KryoSerializer() {}
  
   /**
    * Create an {@link KryoSerializer} with the provided registrations. This can be
    * used from a Spring configuration.
    */
   public KryoSerializer(Registration... regs)
   {
      registrations = Arrays.asList(regs);
   }
  
   /**
    * Create an {@link KryoSerializer} with the provided registrations and Application specific
    * Optimizer. This can be used from a Spring configuration.
    */
   public KryoSerializer(KryoOptimizer optimizer, Registration... regs)
   {
      registrations = Arrays.asList(regs);
      this.optimizer = optimizer;
   }
  
   /**
    * Set the optimizer. This is provided for a dependency injection framework to use. If it's called
    * @param optimizer
    */
   public synchronized void setKryoOptimizer(KryoOptimizer optimizer)
   {
      this.optimizer= optimizer;
      kryopool.clear(); // need to create new Kryo's.
   }
  
   /**
    * You can require Kryo to serialize only registered classes by passing '<code>true</code>' to
    * setKryoRegistrationRequired. The default is '<code>false</code>'.
    */
   public synchronized void setKryoRegistrationRequired(boolean requireRegistration)
   {
      if (this.requireRegistration != requireRegistration)
      {
         this.requireRegistration = requireRegistration;
         kryopool.clear();
      }
   }

   @Override
   public byte[] serialize(T object) throws SerializationException
   {
      KryoHolder k = null;
      try
      {
         k = getKryoHolder();
         k.output.clear();
         k.kryo.writeClassAndObject(k.output, object);
         return k.output.toBytes();
      }
      catch (KryoException ke)
      {
         throw new SerializationException("Failed to serialize.",ke);
      }
      catch (IllegalArgumentException e) // this happens when requiring registration but serializing an unregistered class
      {
         throw new SerializationException("Failed to serialize " + SafeString.objectDescription(object) +
               " (did you require registration and attempt to serialize an unregistered class?)", e);
      }
      finally
      {
         if (k != null)
            kryopool.offer(k);
      }
   }
  
   @SuppressWarnings("unchecked")
   @Override
   public T deserialize(byte[] data) throws SerializationException
   {
      KryoHolder k = null;
      try
      {
         k = getKryoHolder();
         k.input.setBuffer(data);
         return (T)(k.kryo.readClassAndObject(k.input))
      }
      catch (KryoException ke)
      {
         throw new SerializationException("Failed to deserialize.",ke);
      }
      catch (IllegalArgumentException e) // this happens when requiring registration but deserializing an unregistered class
      {
         throw new SerializationException("Failed to deserialize. Did you require registration and attempt to deserialize an unregistered class?", e);
      }
      finally
      {
         if (k != null)
            kryopool.offer(k);
      }
   }
  
   private KryoHolder getKryoHolder()
   {
      KryoHolder ret = kryopool.poll();
      if (ret == null)
      {
         ret = new KryoHolder();
         if (requireRegistration)
            ret.kryo.setRegistrationRequired(requireRegistration);
        
         if (optimizer != null)
         {
            try { optimizer.preRegister(ret.kryo); }
            catch (Throwable th) { logger.error("Optimizer for KryoSerializer \"" + SafeString.valueOfClass(optimizer) +
                  "\" threw and unepexcted exception.... continuing.",th); }
         }

         if (registrations != null)
         {
            for (Registration reg : registrations)
            {
               try
               {
                  if (reg.id == -1)
                     ret.kryo.register(Class.forName(reg.classname));
                  else
                     ret.kryo.register(Class.forName(reg.classname), reg.id);
               }
               catch (ClassNotFoundException cnfe)
               {
                  logger.error("Cannot register the class " + SafeString.valueOf(reg.classname) + " with Kryo because the class couldn't be found.");
               }
            }
         }
        
         if (optimizer != null)
         {
            try { optimizer.postRegister(ret.kryo); }
            catch (Throwable th) { logger.error("Optimizer for KryoSerializer \"" + SafeString.valueOfClass(optimizer) +
                  "\" threw and unepexcted exception.... continuing.",th); }
         }
      }
      return ret;
   }

}
TOP

Related Classes of com.nokia.dempsy.serialization.kryo.KryoSerializer$KryoHolder

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.