View Javadoc
1   /*
2    * This file is part of Waarp Project (named also Waarp or GG).
3    *
4    *  Copyright (c) 2019, Waarp SAS, and individual contributors by the @author
5    *  tags. See the COPYRIGHT.txt in the distribution for a full listing of
6    * individual contributors.
7    *
8    *  All Waarp Project is free software: you can redistribute it and/or
9    * modify it under the terms of the GNU General Public License as published by
10   * the Free Software Foundation, either version 3 of the License, or (at your
11   * option) any later version.
12   *
13   * Waarp is distributed in the hope that it will be useful, but WITHOUT ANY
14   * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
15   * A PARTICULAR PURPOSE. See the GNU General Public License for more details.
16   *
17   *  You should have received a copy of the GNU General Public License along with
18   * Waarp . If not, see <http://www.gnu.org/licenses/>.
19   */
20  
21  package org.waarp.openr66.protocol.localhandler.packet.compression;
22  
23  import org.waarp.common.logging.WaarpLogger;
24  import org.waarp.common.logging.WaarpLoggerFactory;
25  import org.waarp.compress.WaarpZstdCodec;
26  import org.waarp.openr66.context.R66Session;
27  import org.waarp.openr66.protocol.exception.OpenR66ProtocolPacketException;
28  import org.waarp.openr66.protocol.localhandler.packet.DataPacket;
29  
30  import java.util.Arrays;
31  
32  /**
33   * ZSTD efficient compression mode (JNI, Unsafe or Safe mode)
34   */
35  public class ZstdCompressionCodecDataPacket {
36    private static final WaarpLogger logger =
37        WaarpLoggerFactory.getLogger(ZstdCompressionCodecDataPacket.class);
38    private final WaarpZstdCodec waarpZstdCodec = new WaarpZstdCodec();
39  
40    /**
41     * @param dataPacket the DataPacket to compress in place
42     */
43    public final void compress(final DataPacket dataPacket,
44                               final R66Session session)
45        throws OpenR66ProtocolPacketException {
46      final byte[] data = dataPacket.getData();
47      final int originalSize = dataPacket.getLengthPacket();
48      if (originalSize == 0) {
49        return;
50      }
51      byte[] toCompress =
52          session.getSessionReusableCompressionBuffer(originalSize);
53      try {
54        // Try using default half max buffer
55        final int length = waarpZstdCodec.getCompressorCodec()
56                                         .compress(data, originalSize, toCompress,
57                                                   toCompress.length);
58        if (length < toCompress.length) {
59          final byte[] bytes = Arrays.copyOfRange(toCompress, 0, length);
60          toCompress = bytes;
61        }
62        logger.debug("DataPacket Compression is {} on {} for BlockSize {}",
63                     toCompress.length, originalSize, data.length);
64        dataPacket.updateFromCompressionCodec(toCompress, length);
65      } catch (final Exception e) {
66        // Might be because toCompress is not enough wide
67        logger.error("DataPacket Compression to {} on {} for BlockSize {}",
68                     toCompress.length, dataPacket.getLengthPacket(),
69                     dataPacket.getData().length, e);
70        throw new OpenR66ProtocolPacketException(e);
71      }
72    }
73  
74    /**
75     * @param dataPacket the DataPacket to uncompress in place
76     */
77    public final void uncompress(final DataPacket dataPacket,
78                                 final R66Session session)
79        throws OpenR66ProtocolPacketException {
80      final byte[] data = dataPacket.getData();
81      final int originalSize = dataPacket.getLengthPacket();
82      if (originalSize == 0) {
83        return;
84      }
85      try {
86        byte[] toDeCompress = session.getReusableBuffer(
87            waarpZstdCodec.getCompressorCodec()
88                          .getDecompressedSize(data, originalSize));
89        final int length = waarpZstdCodec.getCompressorCodec()
90                                         .decompress(data, originalSize,
91                                                     toDeCompress,
92                                                     toDeCompress.length);
93        if (length != toDeCompress.length) {
94          toDeCompress = Arrays.copyOf(toDeCompress, length);
95        }
96        logger.debug("DataPacket Decompression is {} on {} for BlockSize {}",
97                     originalSize, length, data.length);
98        dataPacket.updateFromCompressionCodec(toDeCompress, length);
99      } catch (final Exception e) {
100       logger.error("DataPacket Decompression was {} on {} for BlockSize {}",
101                    originalSize, data.length, session.getBlockSize(), e);
102       throw new OpenR66ProtocolPacketException(e);
103     }
104   }
105 }