source: osm/applications/editors/josm/plugins/imagerycache/src/org/mapdb/BTreeKeySerializer.java@ 29484

Last change on this file since 29484 was 29484, checked in by akks, 11 years ago

JOSM/ImageryCache: updated MapDB (no more deadlocks, Java 1.6 compatible), less crashes, multiple-JOSM support

File size: 6.1 KB
Line 
1package org.mapdb;
2
3import java.io.DataInput;
4import java.io.DataOutput;
5import java.io.IOException;
6
7/**
8 * Custom serializer for BTreeMap keys.
9 * Is used to take advantage of Delta Compression.
10 *
11 * @param <K>
12 */
13public abstract class BTreeKeySerializer<K>{
14 public abstract void serialize(DataOutput out, int start, int end, Object[] keys) throws IOException;
15
16 public abstract Object[] deserialize(DataInput in, int start, int end, int size) throws IOException;
17
18 static final class BasicKeySerializer extends BTreeKeySerializer<Object> {
19
20 protected final Serializer defaultSerializer;
21
22 BasicKeySerializer(Serializer defaultSerializer) {
23 this.defaultSerializer = defaultSerializer;
24 }
25
26 @Override
27 public void serialize(DataOutput out, int start, int end, Object[] keys) throws IOException {
28 for(int i = start;i<end;i++){
29 defaultSerializer.serialize(out,keys[i]);
30 }
31 }
32
33 @Override
34 public Object[] deserialize(DataInput in, int start, int end, int size) throws IOException{
35 Object[] ret = new Object[size];
36 for(int i=start; i<end; i++){
37 ret[i] = defaultSerializer.deserialize(in,-1);
38 }
39 return ret;
40 }
41 }
42
43
44 public static final BTreeKeySerializer<Long> ZERO_OR_POSITIVE_LONG = new BTreeKeySerializer<Long>() {
45 @Override
46 public void serialize(DataOutput out, int start, int end, Object[] keys) throws IOException {
47 if(start>=end) return;
48// System.out.println(start+" - "+end+" - "+Arrays.toString(keys));
49 long prev = (Long)keys[start];
50 Utils.packLong(out,prev);
51 for(int i=start+1;i<end;i++){
52 long curr = (Long)keys[i];
53 Utils.packLong(out, curr-prev);
54 prev = curr;
55 }
56 }
57
58 @Override
59 public Object[] deserialize(DataInput in, int start, int end, int size) throws IOException {
60 Object[] ret = new Long[size];
61 long prev = 0 ;
62 for(int i = start; i<end; i++){
63 ret[i] = prev = prev + Utils.unpackLong(in);
64 }
65 return ret;
66 }
67 };
68
69 public static final BTreeKeySerializer<Integer> ZERO_OR_POSITIVE_INT = new BTreeKeySerializer<Integer>() {
70 @Override
71 public void serialize(DataOutput out, int start, int end, Object[] keys) throws IOException {
72 if(start>=end) return;
73// System.out.println(start+" - "+end+" - "+Arrays.toString(keys));
74 int prev = (Integer)keys[start];
75 Utils.packLong(out,prev);
76 for(int i=start+1;i<end;i++){
77 int curr = (Integer)keys[i];
78 Utils.packInt(out, curr-prev);
79 prev = curr;
80 }
81 }
82
83 @Override
84 public Object[] deserialize(DataInput in, int start, int end, int size) throws IOException {
85 Object[] ret = new Integer[size];
86 int prev = 0 ;
87 for(int i = start; i<end; i++){
88 ret[i] = prev = prev + Utils.unpackInt(in);
89 }
90 return ret;
91 }
92 };
93
94
95 public static final BTreeKeySerializer<String> STRING = new BTreeKeySerializer<String>() {
96
97 @Override
98 public void serialize(DataOutput out, int start, int end, Object[] keys) throws IOException {
99 byte[] previous = null;
100 for (int i = start; i < end; i++) {
101 byte[] b = ((String) keys[i]).getBytes(Utils.UTF8);
102 leadingValuePackWrite(out, b, previous, 0);
103 previous = b;
104 }
105 }
106
107 @Override
108 public Object[] deserialize(DataInput in, int start, int end, int size) throws IOException {
109 Object[] ret = new Object[size];
110 byte[] previous = null;
111 for (int i = start; i < end; i++) {
112 byte[] b = leadingValuePackRead(in, previous, 0);
113 if (b == null) continue;
114 ret[i] = new String(b,Utils.UTF8);
115 previous = b;
116 }
117 return ret;
118 }
119 };
120
121 /**
122 * Read previously written data
123 *
124 * @author Kevin Day
125 */
126 public static byte[] leadingValuePackRead(DataInput in, byte[] previous, int ignoreLeadingCount) throws IOException {
127 int len = Utils.unpackInt(in) - 1; // 0 indicates null
128 if (len == -1)
129 return null;
130
131 int actualCommon = Utils.unpackInt(in);
132
133 byte[] buf = new byte[len];
134
135 if (previous == null) {
136 actualCommon = 0;
137 }
138
139
140 if (actualCommon > 0) {
141 in.readFully(buf, 0, ignoreLeadingCount);
142 System.arraycopy(previous, ignoreLeadingCount, buf, ignoreLeadingCount, actualCommon - ignoreLeadingCount);
143 }
144 in.readFully(buf, actualCommon, len - actualCommon);
145 return buf;
146 }
147
148 /**
149 * This method is used for delta compression for keys.
150 * Writes the contents of buf to the DataOutput out, with special encoding if
151 * there are common leading bytes in the previous group stored by this compressor.
152 *
153 * @author Kevin Day
154 */
155 public static void leadingValuePackWrite(DataOutput out, byte[] buf, byte[] previous, int ignoreLeadingCount) throws IOException {
156 if (buf == null) {
157 Utils.packInt(out, 0);
158 return;
159 }
160
161 int actualCommon = ignoreLeadingCount;
162
163 if (previous != null) {
164 int maxCommon = buf.length > previous.length ? previous.length : buf.length;
165
166 if (maxCommon > Short.MAX_VALUE) maxCommon = Short.MAX_VALUE;
167
168 for (; actualCommon < maxCommon; actualCommon++) {
169 if (buf[actualCommon] != previous[actualCommon])
170 break;
171 }
172 }
173
174
175 // there are enough common bytes to justify compression
176 Utils.packInt(out, buf.length + 1);// store as +1, 0 indicates null
177 Utils.packInt(out, actualCommon);
178 out.write(buf, 0, ignoreLeadingCount);
179 out.write(buf, actualCommon, buf.length - actualCommon);
180
181 }
182}
Note: See TracBrowser for help on using the repository browser.