Package ch.usi.dslab.bezerra.netwrapper.codecs

Source Code of ch.usi.dslab.bezerra.netwrapper.codecs.CodecLZ4

/*

Netwrapper - A library for easy networking in Java
Copyright (C) 2014, University of Lugano
This file is part of Netwrapper.
Netwrapper is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
*/

package ch.usi.dslab.bezerra.netwrapper.codecs;

import java.nio.ByteBuffer;

import net.jpountz.lz4.LZ4Compressor;
import net.jpountz.lz4.LZ4Factory;
import net.jpountz.lz4.LZ4FastDecompressor;

public class CodecLZ4 implements Codec {

   private CodecUncompressedKryo codecUncompressed = new CodecUncompressedKryo();

   private static ThreadLocal<LZ4Factory> lz4Factory = new ThreadLocal<LZ4Factory>() {
      @Override protected LZ4Factory initialValue() {
         LZ4Factory lz4Factory = LZ4Factory.fastestInstance();
         return lz4Factory;
      }
   };

   @Override
   public byte[] getBytes(Object obj) {
      final LZ4Factory factory = lz4Factory.get();
      byte[] data = codecUncompressed.getBytes(obj);
      final int decompressedLength = data.length;
      LZ4Compressor compressor = factory.fastCompressor();
      int maxCompressedLength = compressor.maxCompressedLength(decompressedLength);
      byte[] compressed = new byte[4 + maxCompressedLength];
      compressor.compress(data, 0, decompressedLength, compressed, 4, maxCompressedLength);
      return compressed;
   }

   @Override
   public Object createObjectFromBytes(byte[] bytes) {
      // decompress
     
      // received format = | decompressed len (4B) | compressed bytes (bytes.length - 4) |
     
      final LZ4Factory factory = lz4Factory.get();
      int compressedLength = bytes.length - 4;
      ByteBuffer compbb = ByteBuffer.wrap(bytes);
      int decompressedLength = compbb.getInt();

     
      LZ4FastDecompressor decompressor = factory.fastDecompressor();
      byte[] decompressedBytes = new byte[decompressedLength];
      int compressedLength2 = decompressor.decompress(bytes, 4, decompressedBytes, 0, decompressedLength);
     
      assert(compressedLength == compressedLength2);
     
      return codecUncompressed.createObjectFromBytes(decompressedBytes);
   }

   @Override
   public ByteBuffer getByteBufferWithLengthHeader(Object obj) {
      final LZ4Factory factory = lz4Factory.get();

      byte[] data = codecUncompressed.getBytes(obj);
      final int decompressedLength = data.length;

      // compress data
      LZ4Compressor compressor = factory.fastCompressor();
      int maxCompressedLength = compressor.maxCompressedLength(decompressedLength);
      byte[] compressed = new byte[8 + maxCompressedLength];
      int compressedLength = compressor.compress(data, 0, decompressedLength, compressed, 8, maxCompressedLength);

      // tcpreceiver decoder expects | x = message length (4B) | message    (x bytes)                           |
      // we are providing            | x = y + 4          (4B) | dec length (4 bytes) | comp. message (y bytes) |
      //
      //
      //
      // which also means:
      //
      //                                                [-------------------- LENGTH IN HEADER -----------------------]
      //                                                                        [-----------COMPRESSED LENGTH---------]
      // received format = | compressed length + 4 (4B) | decompressed len (4B) | compressed bytes (bytes.length - 4) |
     
      ByteBuffer bb = ByteBuffer.wrap(compressed);
      bb.putInt(4 + compressedLength); // length of the whole message, excluding length header
      bb.putInt(decompressedLength);
      bb.position(0);
      bb.limit(8 + compressedLength);

      return bb;
   }

   @Override
   public Object createObjectFromByteBufferWithLengthHeader(ByteBuffer buffer) {
      // decompress
      //                                                [-------------------- LENGTH IN HEADER -----------------------]
      //                                                                        [-----------COMPRESSED LENGTH---------]
      // received format = | compressed length + 4 (4B) | decompressed len (4B) | compressed bytes (bytes.length - 4) |
     
      final LZ4Factory factory = lz4Factory.get();
     
      int compressedLength      = buffer.getInt() - 4;
      int decompressedLength    = buffer.getInt();
      int compressedBytesOffset = buffer.arrayOffset() + buffer.position();
      byte[] compressedBytes    = buffer.array();
     
      LZ4FastDecompressor decompressor = factory.fastDecompressor();
      byte[] decompressedBytes = new byte[decompressedLength];
      int compressedLength2 = decompressor.decompress(compressedBytes, compressedBytesOffset, decompressedBytes, 0, decompressedLength);
     
      assert(compressedLength == compressedLength2);
     
      return codecUncompressed.createObjectFromBytes(decompressedBytes);
   }

   @Override
   public Object deepDuplicate(Object o) {
      return codecUncompressed.deepDuplicate(o);
   }
}
TOP

Related Classes of ch.usi.dslab.bezerra.netwrapper.codecs.CodecLZ4

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.