]> gerrit.simantics Code Review - simantics/platform.git/blobdiff - bundles/org.simantics.db.server/src/org/simantics/db/server/internal/ClusterDecompressor.java
Migrated source code from Simantics SVN
[simantics/platform.git] / bundles / org.simantics.db.server / src / org / simantics / db / server / internal / ClusterDecompressor.java
diff --git a/bundles/org.simantics.db.server/src/org/simantics/db/server/internal/ClusterDecompressor.java b/bundles/org.simantics.db.server/src/org/simantics/db/server/internal/ClusterDecompressor.java
new file mode 100644 (file)
index 0000000..1beaf2c
--- /dev/null
@@ -0,0 +1,157 @@
+package org.simantics.db.server.internal;\r
+\r
+import java.nio.ByteBuffer;\r
+import java.util.Arrays;\r
+\r
+import org.simantics.fastlz.FastLZ;\r
+import org.simantics.fastlz.FastLZJava;\r
+\r
+\r
+/**\r
+ * @author Tuukka Lehtonen\r
+ */\r
+public class ClusterDecompressor {\r
+\r
+    private byte[] inflateBuffer;\r
+\r
+    public Object[] inflateCluster(int inflateSize, ByteBuffer deflatedCluster)\r
+            throws CompressionException {\r
+        int deflatedSize = deflatedCluster.limit();\r
+        Object[] arrays = new Object[3];\r
+        int inflated = decompressCluster(deflatedCluster, deflatedSize, inflateSize, arrays);\r
+        if (inflated != inflateSize)\r
+            throw new CompressionException("decompression error, inflated "\r
+                    + inflated + " bytes when " + inflateSize + " expected.");\r
+        return arrays;\r
+    }\r
+\r
+    /**\r
+     * Wrapper for the old native direct byte buffer version of cluster\r
+     * decompression.\r
+     *\r
+     * @param deflated\r
+     * @param deflatedSize\r
+     * @param inflatedSize\r
+     * @param arrays\r
+     *            expects an array of 3 elements. The decompression result will\r
+     *            be stored in here. [0] = cluster long array (long[]), [1] =\r
+     *            cluster int array (int[]), [2] = cluster byte array (byte[]).\r
+     * @return the amount of bytes inflated from the deflated cluster. Matches\r
+     *         inflatedSize when successful.\r
+     *\r
+     * @see FastLZ#decompressCluster(ByteBuffer, int, int, Object[])\r
+     */\r
+    public int decompressCluster(ByteBuffer deflated, int deflatedSize, int inflatedSize, Object[] arrays) {\r
+        if (deflated.isDirect()) {\r
+            if (FastLZ.isNativeInitialized()) {\r
+                FastLZ.decompressCluster(deflated, deflatedSize, inflatedSize, arrays);\r
+                return inflatedSize;\r
+            }\r
+            // REALLY SLOW FALLBACK: java code for direct byte buffers\r
+        }\r
+        byte[] array = null;\r
+        if (deflated.hasArray()) {\r
+            array = deflated.array();\r
+        } else {\r
+            // SLOW FALLBACK: read-only heap byte buffer\r
+            array = new byte[deflatedSize];\r
+            int pos = deflated.position();\r
+            deflated.position(0);\r
+            deflated.get(array, 0, deflatedSize);\r
+            deflated.position(pos);\r
+        }\r
+        return decompressCluster(array, deflatedSize, inflatedSize, arrays);\r
+    }\r
+\r
+    /**\r
+     * @param deflated\r
+     * @param deflatedSize\r
+     * @param inflatedSize\r
+     * @param arrays\r
+     * @return\r
+     */\r
+    public synchronized int decompressCluster(byte[] deflated, int deflatedSize, int inflatedSize, Object[] arrays) {\r
+        if (inflateBuffer == null) {\r
+            inflateBuffer = new byte[inflatedSize];\r
+        } else if (inflateBuffer.length < inflatedSize) {\r
+            inflateBuffer = new byte[inflatedSize];\r
+        }\r
+        return decompressCluster(deflated, deflatedSize, inflateBuffer, inflatedSize, arrays);\r
+    }\r
+\r
+    /**\r
+     * @param deflated\r
+     * @param deflatedSize\r
+     * @param inflated\r
+     * @param inflatedSize\r
+     * @param arrays\r
+     * @return amount of bytes inflated from the original deflated buffer.\r
+     *         Should match inflatedSize if everything went ok, otherwise will\r
+     *         not.\r
+     */\r
+    public static int decompressCluster(byte[] deflated, int deflatedSize, byte[] inflated, int inflatedSize, Object[] arrays) {\r
+        if (inflated.length < inflatedSize)\r
+            throw new IllegalArgumentException("inflate buffer size (" + inflated.length + ") is smaller than inflated size (" + inflatedSize + ")");\r
+\r
+        int decompressedBytes = FastLZJava.decompress(deflated, 0, deflatedSize, inflated, 0, inflatedSize);\r
+        if (decompressedBytes != inflatedSize)\r
+            return decompressedBytes;\r
+\r
+        int offset = 0;\r
+\r
+        int longCount = readInt(inflated, offset);\r
+        long[] longs = new long[longCount];\r
+        copyLongs(inflated, offset + 4, longs);\r
+        offset += 4 + 8*longCount;\r
+\r
+        int intCount = readInt(inflated, offset);\r
+        int[] ints = new int[intCount];\r
+        copyInts(inflated, offset + 4, ints);\r
+        offset += 4 + 4*intCount;\r
+\r
+        int byteCount = readInt(inflated, offset);\r
+        byte[] bytes = Arrays.copyOfRange(inflated, offset + 4, offset + 4 + byteCount);\r
+\r
+        arrays[0] = longs;\r
+        arrays[1] = ints;\r
+        arrays[2] = bytes;\r
+\r
+        return decompressedBytes;\r
+    }\r
+\r
+    private static void copyInts(byte[] bytes, int i, int[] ints) {\r
+        int offset = i;\r
+        int count = ints.length;\r
+        for (int a = 0; a < count; ++a, offset += 4) {\r
+            int value = (((int) bytes[offset] & 0xff)) |\r
+                    (((int) bytes[offset+1] & 0xff) << 8) |\r
+                    (((int) bytes[offset+2] & 0xff) << 16) |\r
+                    (((int) bytes[offset+3] & 0xff) << 24);\r
+            ints[a] = value;\r
+        }\r
+    }\r
+\r
+    private static void copyLongs(byte[] bytes, int i, long[] longs) {\r
+        int offset = i;\r
+        int count = longs.length;\r
+        for (int a = 0; a < count; ++a, offset += 8) {\r
+            long value = (((long) bytes[offset] & 0xff)) |\r
+                    (((long) bytes[offset+1] & 0xff) << 8) |\r
+                    (((long) bytes[offset+2] & 0xff) << 16) |\r
+                    (((long) bytes[offset+3] & 0xff) << 24) |\r
+                    (((long) bytes[offset+4] & 0xff) << 32) |\r
+                    (((long) bytes[offset+5] & 0xff) << 40) |\r
+                    (((long) bytes[offset+6] & 0xff) << 48) |\r
+                    (((long) bytes[offset+7] & 0xff) << 56);\r
+            longs[a] = value;\r
+        }\r
+    }\r
+\r
+    private static int readInt(byte[] array, int offset) {\r
+        return (((int) array[offset] & 0xff)) |\r
+                (((int) array[offset+1] & 0xff) << 8) |\r
+                (((int) array[offset+2] & 0xff) << 16) |\r
+                (((int) array[offset+3] & 0xff) << 24);\r
+    }\r
+\r
+}\r