]> gerrit.simantics Code Review - simantics/platform.git/blob - bundles/org.simantics.db.server/src/org/simantics/db/server/internal/ClusterDecompressor.java
Fixed multiple issues causing dangling references to discarded queries
[simantics/platform.git] / bundles / org.simantics.db.server / src / org / simantics / db / server / internal / ClusterDecompressor.java
1 package org.simantics.db.server.internal;
2
3 import java.nio.ByteBuffer;
4 import java.util.Arrays;
5
6 import org.simantics.fastlz.FastLZ;
7 import org.simantics.fastlz.FastLZJava;
8
9
10 /**
11  * @author Tuukka Lehtonen
12  */
13 public class ClusterDecompressor {
14
15     private byte[] inflateBuffer;
16
17     public Object[] inflateCluster(int inflateSize, ByteBuffer deflatedCluster)
18             throws CompressionException {
19         int deflatedSize = deflatedCluster.limit();
20         Object[] arrays = new Object[3];
21         int inflated = decompressCluster(deflatedCluster, deflatedSize, inflateSize, arrays);
22         if (inflated != inflateSize)
23             throw new CompressionException("decompression error, inflated "
24                     + inflated + " bytes when " + inflateSize + " expected.");
25         return arrays;
26     }
27
28     /**
29      * Wrapper for the old native direct byte buffer version of cluster
30      * decompression.
31      *
32      * @param deflated
33      * @param deflatedSize
34      * @param inflatedSize
35      * @param arrays
36      *            expects an array of 3 elements. The decompression result will
37      *            be stored in here. [0] = cluster long array (long[]), [1] =
38      *            cluster int array (int[]), [2] = cluster byte array (byte[]).
39      * @return the amount of bytes inflated from the deflated cluster. Matches
40      *         inflatedSize when successful.
41      *
42      * @see FastLZ#decompressCluster(ByteBuffer, int, int, Object[])
43      */
44     public int decompressCluster(ByteBuffer deflated, int deflatedSize, int inflatedSize, Object[] arrays) {
45         if (deflated.isDirect()) {
46             if (FastLZ.isNativeInitialized()) {
47                 FastLZ.decompressCluster(deflated, deflatedSize, inflatedSize, arrays);
48                 return inflatedSize;
49             }
50             // REALLY SLOW FALLBACK: java code for direct byte buffers
51         }
52         byte[] array = null;
53         if (deflated.hasArray()) {
54             array = deflated.array();
55         } else {
56             // SLOW FALLBACK: read-only heap byte buffer
57             array = new byte[deflatedSize];
58             int pos = deflated.position();
59             deflated.position(0);
60             deflated.get(array, 0, deflatedSize);
61             deflated.position(pos);
62         }
63         return decompressCluster(array, deflatedSize, inflatedSize, arrays);
64     }
65
66     /**
67      * @param deflated
68      * @param deflatedSize
69      * @param inflatedSize
70      * @param arrays
71      * @return
72      */
73     public synchronized int decompressCluster(byte[] deflated, int deflatedSize, int inflatedSize, Object[] arrays) {
74         if (inflateBuffer == null) {
75             inflateBuffer = new byte[inflatedSize];
76         } else if (inflateBuffer.length < inflatedSize) {
77             inflateBuffer = new byte[inflatedSize];
78         }
79         return decompressCluster(deflated, deflatedSize, inflateBuffer, inflatedSize, arrays);
80     }
81
82     /**
83      * @param deflated
84      * @param deflatedSize
85      * @param inflated
86      * @param inflatedSize
87      * @param arrays
88      * @return amount of bytes inflated from the original deflated buffer.
89      *         Should match inflatedSize if everything went ok, otherwise will
90      *         not.
91      */
92     public static int decompressCluster(byte[] deflated, int deflatedSize, byte[] inflated, int inflatedSize, Object[] arrays) {
93         if (inflated.length < inflatedSize)
94             throw new IllegalArgumentException("inflate buffer size (" + inflated.length + ") is smaller than inflated size (" + inflatedSize + ")");
95
96         int decompressedBytes = FastLZJava.decompress(deflated, 0, deflatedSize, inflated, 0, inflatedSize);
97         if (decompressedBytes != inflatedSize)
98             return decompressedBytes;
99
100         int offset = 0;
101
102         int longCount = readInt(inflated, offset);
103         long[] longs = new long[longCount];
104         copyLongs(inflated, offset + 4, longs);
105         offset += 4 + 8*longCount;
106
107         int intCount = readInt(inflated, offset);
108         int[] ints = new int[intCount];
109         copyInts(inflated, offset + 4, ints);
110         offset += 4 + 4*intCount;
111
112         int byteCount = readInt(inflated, offset);
113         byte[] bytes = Arrays.copyOfRange(inflated, offset + 4, offset + 4 + byteCount);
114
115         arrays[0] = longs;
116         arrays[1] = ints;
117         arrays[2] = bytes;
118
119         return decompressedBytes;
120     }
121
122     private static void copyInts(byte[] bytes, int i, int[] ints) {
123         int offset = i;
124         int count = ints.length;
125         for (int a = 0; a < count; ++a, offset += 4) {
126             int value = (((int) bytes[offset] & 0xff)) |
127                     (((int) bytes[offset+1] & 0xff) << 8) |
128                     (((int) bytes[offset+2] & 0xff) << 16) |
129                     (((int) bytes[offset+3] & 0xff) << 24);
130             ints[a] = value;
131         }
132     }
133
134     private static void copyLongs(byte[] bytes, int i, long[] longs) {
135         int offset = i;
136         int count = longs.length;
137         for (int a = 0; a < count; ++a, offset += 8) {
138             long value = (((long) bytes[offset] & 0xff)) |
139                     (((long) bytes[offset+1] & 0xff) << 8) |
140                     (((long) bytes[offset+2] & 0xff) << 16) |
141                     (((long) bytes[offset+3] & 0xff) << 24) |
142                     (((long) bytes[offset+4] & 0xff) << 32) |
143                     (((long) bytes[offset+5] & 0xff) << 40) |
144                     (((long) bytes[offset+6] & 0xff) << 48) |
145                     (((long) bytes[offset+7] & 0xff) << 56);
146             longs[a] = value;
147         }
148     }
149
150     private static int readInt(byte[] array, int offset) {
151         return (((int) array[offset] & 0xff)) |
152                 (((int) array[offset+1] & 0xff) << 8) |
153                 (((int) array[offset+2] & 0xff) << 16) |
154                 (((int) array[offset+3] & 0xff) << 24);
155     }
156
157 }