1 /*******************************************************************************
\r
2 * Copyright (c) 2007, 2010 Association for Decentralized Information Management
\r
3 * in Industry THTH ry.
\r
4 * All rights reserved. This program and the accompanying materials
\r
5 * are made available under the terms of the Eclipse Public License v1.0
\r
6 * which accompanies this distribution, and is available at
\r
7 * http://www.eclipse.org/legal/epl-v10.html
\r
10 * VTT Technical Research Centre of Finland - initial API and implementation
\r
11 *******************************************************************************/
\r
12 package org.simantics.db.procore.cluster;
\r
14 import java.nio.ByteBuffer;
\r
15 import java.nio.ByteOrder;
\r
17 import org.simantics.compressions.Compressions;
\r
18 import org.simantics.db.exception.InternalException;
\r
21 static private final int InLength = 1<<20;
\r
23 public static class DecompressStruct {
\r
24 public long[] longs;
\r
26 public byte[] bytes;
\r
28 static class SourceData {
\r
29 SourceData(byte[] data) {
\r
34 return data.length - offset;
\r
37 int inLength = 4; // sizeof(int)
\r
38 assert(left() >= inLength); // must have data for input
\r
39 ByteBuffer buffer = ByteBuffer.wrap(data, offset, inLength);
\r
40 buffer.order(ByteOrder.LITTLE_ENDIAN); // argh!
\r
41 int t = buffer.getInt();
\r
45 void readBytes(byte[] bytes, int aOffset, int inLength) {
\r
46 assert(left() >= inLength); // must have data for input
\r
47 System.arraycopy(data, offset, bytes, aOffset, inLength);
\r
53 public static DecompressStruct decompress(byte[] data) throws InternalException {
\r
54 assert(data.length > 12); // 3*(table size)
\r
55 SourceData sourceData = new SourceData(data);
\r
56 DecompressStruct struct = new DecompressStruct();
\r
57 int longSize = sourceData.readInt();
\r
58 int intSize = sourceData.readInt();
\r
59 int byteSize = sourceData.readInt();
\r
60 struct.longs = new long[longSize];
\r
62 decompress(sourceData, struct.longs);
\r
63 struct.ints = new int[intSize];
\r
64 decompress(sourceData, struct.ints);
\r
65 struct.bytes = new byte[byteSize];
\r
66 decompress(sourceData, struct.bytes);
\r
67 } catch (CompressionException e) {
\r
68 throw new InternalException("Failed to decompress.", e);
\r
72 private static void decompress(SourceData sourceData, long[] longs) throws CompressionException {
\r
73 int length = longs.length * 8;
\r
74 ByteBuffer bytes = ByteBuffer.allocate(length);
\r
75 int size = decompressRaw(sourceData, bytes.array());
\r
76 assert(size == length);
\r
77 bytes.order(ByteOrder.LITTLE_ENDIAN); // argh
\r
78 for (int i=0; i<longs.length; ++i)
\r
79 longs[i] = bytes.getLong();
\r
81 private static void decompress(SourceData sourceData, int[] ints) throws CompressionException {
\r
82 int length = ints.length * 4;
\r
83 ByteBuffer bytes = ByteBuffer.allocate(length);
\r
84 int size = decompressRaw(sourceData, bytes.array());
\r
85 assert(size == length);
\r
86 bytes.order(ByteOrder.LITTLE_ENDIAN); // argh
\r
87 for (int i=0; i<ints.length; ++i)
\r
88 ints[i] = bytes.getInt();
\r
90 private static void decompress(SourceData sourceData, byte[] bytes) throws CompressionException {
\r
91 int size = decompressRaw(sourceData, bytes);
\r
92 assert(size == bytes.length);
\r
94 private static int decompressRaw(SourceData sourceData, byte[] bytes) throws CompressionException {
\r
95 int aDstSize = bytes.length;
\r
99 for (int dstSize = 0;;) {
\r
100 int dataLength = sourceData.readInt();
\r
101 assert(dataLength <= InLength); // data is written in blocks
\r
102 if (0 == dataLength) // EOF
\r
104 dstSize += dataLength;
\r
105 int inLength = sourceData.readInt();
\r
107 assert(aDstSize >= dstSize); // must have space for data
\r
108 assert(sourceData.left() >= inLength); // must have data for input
\r
109 assert(inLength > 0); // no data no block
\r
110 assert(inLength <= InLength); // input size is block size or less
\r
111 assert(inLength <= dataLength); // input size is never bigger than data size
\r
113 if (inLength < dataLength) {// block was actually compressed
\r
114 decompress(sourceData.data, sourceData.offset, inLength, bytes, dstOffset, dataLength);
\r
115 sourceData.offset += inLength;
\r
116 dstOffset += dataLength;
\r
118 sourceData.readBytes(bytes, dstOffset, inLength);
\r
119 dstOffset += inLength;
\r
123 private static void decompress(byte[] in, int inOffset, int inLength, byte[] out, int outOffset, int outLength) throws CompressionException {
\r
124 ByteBuffer inBuffer = ByteBuffer.allocateDirect(inLength);
\r
125 inBuffer.put(in, inOffset, inLength);
\r
127 ByteBuffer outBuffer = ByteBuffer.allocateDirect(outLength);
\r
128 int inflateSize = Compressions.get(Compressions.LZ4).decompressBuffer(inBuffer, 0, inLength, outBuffer, 0, outLength);
\r
129 // int inflateSize = org.simantics.fastlz.FastLZ.decompressBuffer(inBuffer, 0, inLength, outBuffer, 0, outLength);
\r
130 if (inflateSize != outLength)
\r
131 throw new RuntimeException("Decompression error.");
\r
132 //outBuffer.flip();
\r
133 outBuffer.get(out, outOffset, outLength);
\r