KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > h2 > store > DataPage


1 /*
2  * Copyright 2004-2006 H2 Group. Licensed under the H2 License, Version 1.0 (http://h2database.com/html/license.html).
3  * Initial Developer: H2 Group
4  */

5 package org.h2.store;
6
7 import java.math.BigDecimal JavaDoc;
8 import java.sql.Date JavaDoc;
9 import java.sql.SQLException JavaDoc;
10 import java.sql.Time JavaDoc;
11 import java.sql.Timestamp JavaDoc;
12
13 import org.h2.engine.Constants;
14 import org.h2.message.Message;
15 import org.h2.util.MathUtils;
16 import org.h2.value.Value;
17 import org.h2.value.ValueArray;
18 import org.h2.value.ValueBoolean;
19 import org.h2.value.ValueByte;
20 import org.h2.value.ValueBytes;
21 import org.h2.value.ValueDate;
22 import org.h2.value.ValueDecimal;
23 import org.h2.value.ValueDouble;
24 import org.h2.value.ValueFloat;
25 import org.h2.value.ValueInt;
26 import org.h2.value.ValueJavaObject;
27 import org.h2.value.ValueLob;
28 import org.h2.value.ValueLong;
29 import org.h2.value.ValueNull;
30 import org.h2.value.ValueShort;
31 import org.h2.value.ValueString;
32 import org.h2.value.ValueStringIgnoreCase;
33 import org.h2.value.ValueTime;
34 import org.h2.value.ValueTimestamp;
35 import org.h2.value.ValueUuid;
36
37 /**
38  * @author Thomas
39  */

40 public abstract class DataPage {
41     
42     static final boolean CHECKSUM = true;
43     protected DataHandler handler;
44     protected byte[] data;
45     protected int pos;
46     
47     public static DataPage create(DataHandler handler, int capacity) {
48         if(handler.getTextStorage()) {
49             return new DataPageText(handler, new byte[capacity]);
50         } else {
51             return new DataPageBinary(handler, new byte[capacity]);
52         }
53     }
54
55     public static DataPage create(DataHandler handler, byte[] buff) {
56         if(handler.getTextStorage()) {
57             return new DataPageText(handler, buff);
58         } else {
59             return new DataPageBinary(handler, buff);
60         }
61     }
62
63     protected DataPage(DataHandler handler, int capacity) {
64         this(handler, new byte[capacity]);
65     }
66     
67     protected DataPage(DataHandler handler, byte[] data) {
68         this.handler = handler;
69         this.data = data;
70     }
71
72     public void checkCapacity(int plus) {
73         if (pos + plus >= data.length) {
74             byte[] d = new byte[(data.length+plus) * 2];
75             // must copy everything, because pos could be 0 and data may be still required
76
System.arraycopy(data, 0, d, 0, data.length);
77             data = d;
78         }
79     }
80     
81     public abstract void updateChecksum();
82     public abstract void check(int len) throws SQLException JavaDoc;
83     public abstract int getFillerLength();
84     public abstract void setInt(int pos, int x);
85
86     public int length() {
87         return pos;
88     }
89
90     public byte[] getBytes() {
91         return data;
92     }
93
94     public void reset() {
95         pos = 0;
96     }
97
98     public void writeDataPageNoSize(DataPage page) {
99         checkCapacity(page.pos);
100         // don't write filler
101
int len = page.pos - getFillerLength();
102         System.arraycopy(page.data, 0, data, pos, len);
103         pos += len;
104     }
105
106     public DataPage readDataPageNoSize() {
107         int len = data.length - pos;
108         DataPage page = DataPage.create(handler, len);
109         System.arraycopy(data, pos, page.data, 0, len);
110         page.pos = len;
111         return page;
112     }
113     
114     public void write(byte[] buff, int off, int len) {
115         checkCapacity(len);
116         System.arraycopy(buff, 0, data, pos, len);
117         pos += len;
118     }
119     
120     public void read(byte[] buff, int off, int len) {
121         System.arraycopy(data, pos, buff, off, len);
122         pos += len;
123     }
124
125     public void writeByte(byte x) {
126         data[pos++] = x;
127     }
128
129     public int readByte() {
130         return data[pos++];
131     }
132
133     public abstract void writeInt(int x);
134     public abstract int readInt();
135     public abstract int getIntLen();
136     public abstract int getLongLen(long x);
137     public abstract int getStringLen(String JavaDoc s);
138     public abstract String JavaDoc readString();
139     public abstract void writeString(String JavaDoc s);
140
141     public long readLong() {
142         return ((long)(readInt()) << 32) + (readInt() & 0xffffffffL);
143     }
144
145     public void writeLong(long x) {
146         writeInt((int)(x >>> 32));
147         writeInt((int)x);
148     }
149
150     public void writeValue(Value v) throws SQLException JavaDoc {
151         if(Constants.CHECK) {
152             checkCapacity(8);
153         }
154         // TODO text output: could be in the Value... classes
155
if (v == ValueNull.INSTANCE) {
156             data[pos++] = '-';
157             return;
158         }
159         int start = pos;
160         data[pos++] = (byte)(v.getType() + 'a');
161         switch (v.getType()) {
162         case Value.BOOLEAN:
163         case Value.BYTE:
164         case Value.SHORT:
165         case Value.INT:
166             writeInt(v.getInt());
167             break;
168         case Value.LONG:
169             writeLong(v.getLong());
170             break;
171         case Value.DECIMAL:
172             String JavaDoc s = v.getString();
173             writeString(s);
174             break;
175         case Value.TIME:
176             writeLong(v.getTimeNoCopy().getTime());
177             break;
178         case Value.DATE:
179             writeLong(v.getDateNoCopy().getTime());
180             break;
181         case Value.TIMESTAMP: {
182             Timestamp JavaDoc ts = v.getTimestampNoCopy();
183             writeLong(ts.getTime());
184             writeInt(ts.getNanos());
185             break;
186         }
187         case Value.JAVA_OBJECT:
188         case Value.BYTES: {
189             byte[] b = v.getBytesNoCopy();
190             writeInt(b.length);
191             write(b, 0, b.length);
192             break;
193         }
194         case Value.UUID: {
195             ValueUuid uuid = (ValueUuid)v;
196             writeLong(uuid.getHigh());
197             writeLong(uuid.getLow());
198             break;
199         }
200         case Value.STRING:
201         case Value.STRING_IGNORECASE:
202             writeString(v.getString());
203             break;
204         case Value.DOUBLE:
205             writeLong(Double.doubleToLongBits(v.getDouble()));
206             break;
207         case Value.FLOAT:
208             writeInt(Float.floatToIntBits(v.getFloat()));
209             break;
210         case Value.BLOB:
211         case Value.CLOB: {
212             ValueLob lob = (ValueLob)v;
213             lob.convertToFileIfRequired(handler);
214             byte[] small = lob.getSmall();
215             if(small == null) {
216                 // TODO lob: currently use -2 for historical reasons (-1 didn't store precision)
217
writeInt(-2);
218                 writeInt(lob.getTableId());
219                 writeInt(lob.getObjectId());
220                 writeLong(lob.getPrecision());
221                 writeByte((byte)(lob.useCompression() ? 1 : 0)); // compression flag
222
} else {
223                 writeInt(small.length);
224                 write(small, 0, small.length);
225             }
226             break;
227         }
228         case Value.ARRAY: {
229             Value[] list = ((ValueArray)v).getList();
230             writeInt(list.length);
231             for(int i=0; i<list.length; i++) {
232                 writeValue(list[i]);
233             }
234             break;
235         }
236         default:
237             throw Message.getInternalError("type=" + v.getType());
238         }
239         if(Constants.CHECK2) {
240             if(pos - start != getValueLen(v)) {
241                 throw Message.getInternalError("value size error: got " + (pos-start) + " expected " + getValueLen(v));
242             }
243         }
244     }
245     
246     public int getValueLen(Value v) throws SQLException JavaDoc {
247         if (v == ValueNull.INSTANCE) {
248             return 1;
249         }
250         switch (v.getType()) {
251         case Value.BOOLEAN:
252         case Value.BYTE:
253         case Value.SHORT:
254         case Value.INT:
255             return 1 + getIntLen();
256         case Value.LONG:
257             return 1 + getLongLen(v.getLong());
258         case Value.DOUBLE:
259             return 1 + getLongLen(Double.doubleToLongBits(v.getDouble()));
260         case Value.FLOAT:
261             return 1 + getIntLen();
262         case Value.STRING:
263         case Value.STRING_IGNORECASE:
264         case Value.DECIMAL:
265             return 1 + getStringLen(v.getString());
266         case Value.JAVA_OBJECT:
267         case Value.BYTES: {
268             int len = v.getBytesNoCopy().length;
269             return 1 + getIntLen() + len;
270         }
271         case Value.UUID: {
272             ValueUuid uuid = (ValueUuid) v;
273             return 1 + getLongLen(uuid.getHigh()) + getLongLen(uuid.getLow());
274         }
275         case Value.TIME:
276             return 1 + getLongLen(v.getTimeNoCopy().getTime());
277         case Value.DATE:
278             return 1 + getLongLen(v.getDateNoCopy().getTime());
279         case Value.TIMESTAMP: {
280             Timestamp JavaDoc ts = v.getTimestampNoCopy();
281             return 1 + getLongLen(ts.getTime()) + getIntLen();
282         }
283         case Value.BLOB:
284         case Value.CLOB:{
285             int len = 1;
286             ValueLob lob = (ValueLob)v;
287             lob.convertToFileIfRequired(handler);
288             byte[] small = lob.getSmall();
289             if(small != null) {
290                 len += getIntLen() + small.length;
291             } else {
292                 len += getIntLen() + getIntLen() + getIntLen() + getLongLen(lob.getPrecision()) + 1;
293             }
294             return len;
295         }
296         case Value.ARRAY: {
297             Value[] list = ((ValueArray)v).getList();
298             int len = 1 + getIntLen();
299             for(int i=0; i<list.length; i++) {
300                 len += getValueLen(list[i]);
301             }
302             return len;
303         }
304         default:
305             throw Message.getInternalError("type=" + v.getType());
306         }
307     }
308
309     public Value readValue() throws SQLException JavaDoc {
310         int type = data[pos++];
311         if(type == '-') {
312             return ValueNull.INSTANCE;
313         }
314         type = (type - 'a');
315         switch (type) {
316         case Value.BOOLEAN:
317             return ValueBoolean.get(readInt() == 1);
318         case Value.BYTE:
319             return ValueByte.get((byte)readInt());
320         case Value.SHORT:
321             return ValueShort.get((short)readInt());
322         case Value.INT:
323             return ValueInt.get(readInt());
324         case Value.LONG:
325             return ValueLong.get(readLong());
326         case Value.DECIMAL:
327             return ValueDecimal.get(new BigDecimal JavaDoc(readString()));
328         case Value.DATE:
329             return ValueDate.getNoCopy(new Date JavaDoc(readLong()));
330         case Value.TIME:
331             // need to normalize the year, month and day
332
return ValueTime.get(new Time JavaDoc(readLong()));
333         case Value.TIMESTAMP: {
334             Timestamp JavaDoc ts = new Timestamp JavaDoc(readLong());
335             ts.setNanos(readInt());
336             return ValueTimestamp.getNoCopy(ts);
337         }
338         case Value.JAVA_OBJECT: {
339             int len = readInt();
340             byte[] b = new byte[len];
341             read(b, 0, len);
342             return ValueJavaObject.getNoCopy(b);
343         }
344         case Value.BYTES: {
345             int len = readInt();
346             byte[] b = new byte[len];
347             read(b, 0, len);
348             return ValueBytes.getNoCopy(b);
349         }
350         case Value.UUID:
351             return ValueUuid.get(readLong(), readLong());
352         case Value.STRING:
353             return ValueString.get(readString());
354         case Value.STRING_IGNORECASE:
355             return ValueStringIgnoreCase.get(readString());
356         case Value.DOUBLE:
357             return ValueDouble.get(Double.longBitsToDouble(readLong()));
358         case Value.FLOAT:
359             return ValueFloat.get(Float.intBitsToFloat(readInt()));
360         case Value.BLOB:
361         case Value.CLOB: {
362             int smallLen = readInt();
363             if(smallLen >= 0) {
364                 byte[] small = new byte[smallLen];
365                 read(small, 0, smallLen);
366                 return ValueLob.createSmallLob(type, small);
367             } else {
368                 int tableId = readInt();
369                 int objectId = readInt();
370                 long precision = 0;
371                 boolean compression = false;
372                 // TODO lob: -2 is for historical reasons (-1 didn't store precision)
373
if(smallLen == -2) {
374                     precision = readLong();
375                     compression = readByte() == 1;
376                 }
377                 return ValueLob.open(type, handler, tableId, objectId, precision, compression);
378             }
379         }
380         case Value.ARRAY: {
381             int len = readInt();
382             Value[] list = new Value[len];
383             for(int i=0; i<len; i++) {
384                 list[i] = readValue();
385             }
386             return ValueArray.get(list);
387         }
388         default:
389             throw Message.getInternalError("type=" + type);
390         }
391     }
392     
393     public abstract void fill(int len);
394
395     public void fillAligned() {
396         // TODO datapage: fillAligned should not use a fixed constant '2'
397
// 0..6 > 8, 7..14 > 16, 15..22 > 24, ...
398
fill(MathUtils.roundUp(pos+2, Constants.FILE_BLOCK_SIZE));
399     }
400
401     public void setPos(int pos) {
402         this.pos = pos;
403     }
404
405 }
406
Popular Tags