KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > com > sleepycat > je > log > LogUtils


1 /*-
2  * See the file LICENSE for redistribution information.
3  *
4  * Copyright (c) 2002,2006 Oracle. All rights reserved.
5  *
6  * $Id: LogUtils.java,v 1.49 2006/10/30 21:14:20 bostic Exp $
7  */

8
9 package com.sleepycat.je.log;
10
11 import java.nio.ByteBuffer JavaDoc;
12 import java.sql.Timestamp JavaDoc;
13
14 import javax.transaction.xa.Xid JavaDoc;
15
16 /**
17  * This class holds convenience methods for marshalling internal JE data to and
18  * from the log.
19  */

20 public class LogUtils {
21     /* Storage sizes for int, long in log. */
22     public static final int SHORT_BYTES = 2;
23     public static final int INT_BYTES = 4;
24     public static final int LONG_BYTES = 8;
25     public static final int UNSIGNED_INT_BYTES = 4;
26
27     private static final boolean DEBUG = false;
28
29     /*
30      * We can return the same byte[] for 0 length arrays.
31      */

32     public static final byte[] ZERO_LENGTH_BYTE_ARRAY = new byte[0];
33
34     /**
35      * Marshall a long into the next 4 bytes in this buffer. Necessary when the
36      * long is used to hold an unsigned int.
37      */

38     public static void writeUnsignedInt(ByteBuffer JavaDoc buf, long value) {
39         buf.put((byte) (value >>> 0));
40         buf.put((byte) (value >>> 8));
41         buf.put((byte) (value >>> 16));
42         buf.put((byte) (value >>> 24));
43     }
44
45     /**
46      * Unmarshall the next four bytes which hold an unsigned int into a long.
47      */

48     public static long getUnsignedInt(ByteBuffer JavaDoc buf) {
49     long ret = (buf.get() & 0xFFL) << 0;
50     ret += (buf.get() & 0xFFL) << 8;
51     ret += (buf.get() & 0xFFL) << 16;
52     ret += (buf.get() & 0xFFL) << 24;
53     return ret;
54     }
55
56     /*
57      * Marshall objects.
58      */

59
60     /**
61      * Write a short into the log.
62      */

63     public static void writeShort(ByteBuffer JavaDoc logBuf, short i) {
64         byte b = (byte) ((i >> 0) & 0xff);
65         logBuf.put(b);
66         b = (byte) ((i >> 8) & 0xff);
67         logBuf.put(b);
68     }
69
70     /**
71      * Read a short from the log.
72      */

73     public static short readShort(ByteBuffer JavaDoc logBuf) {
74         return (short) (((logBuf.get() & 0xFF) << 0) +
75                         ((logBuf.get() & 0xFF) << 8));
76     }
77
78     /**
79      * Write an int into the log.
80      */

81     public static void writeInt(ByteBuffer JavaDoc logBuf, int i) {
82         byte b = (byte) ((i >> 0) & 0xff);
83         logBuf.put(b);
84         b = (byte) ((i >> 8) & 0xff);
85         logBuf.put(b);
86         b = (byte) ((i >> 16) & 0xff);
87         logBuf.put(b);
88         b = (byte) ((i >> 24) & 0xff);
89         logBuf.put(b);
90     }
91
92     /**
93      * Read a int from the log.
94      */

95     public static int readInt(ByteBuffer JavaDoc logBuf) {
96     int ret = (logBuf.get() & 0xFF) << 0;
97     ret += (logBuf.get() & 0xFF) << 8;
98     ret += (logBuf.get() & 0xFF) << 16;
99     ret += (logBuf.get() & 0xFF) << 24;
100     return ret;
101     }
102
103     /**
104      * @return log storage size for a byteArray.
105      */

106     public static int getIntLogSize() {
107         return INT_BYTES;
108     }
109
110     /**
111      * Write an int into the log in MSB order. Used for ordered keys.
112      */

113     public static void writeIntMSB(ByteBuffer JavaDoc logBuf, int i) {
114         byte b = (byte) ((i >> 24) & 0xff);
115         logBuf.put(b);
116         b = (byte) ((i >> 16) & 0xff);
117         logBuf.put(b);
118         b = (byte) ((i >> 8) & 0xff);
119         logBuf.put(b);
120         b = (byte) ((i >> 0) & 0xff);
121         logBuf.put(b);
122     }
123
124     /**
125      * Read a int from the log in MSB order. Used for ordered keys.
126      */

127     public static int readIntMSB(ByteBuffer JavaDoc logBuf) {
128     int ret = (logBuf.get() & 0xFF) << 24;
129     ret += (logBuf.get() & 0xFF) << 16;
130     ret += (logBuf.get() & 0xFF) << 8;
131     ret += (logBuf.get() & 0xFF) << 0;
132     return ret;
133     }
134
135     /**
136      * Write a long into the log.
137      */

138     public static void writeLong(ByteBuffer JavaDoc logBuf, long l) {
139         byte b =(byte) (l >>> 0);
140         logBuf.put(b);
141         b =(byte) (l >>> 8);
142         logBuf.put(b);
143         b =(byte) (l >>> 16);
144         logBuf.put(b);
145         b =(byte) (l >>> 24);
146         logBuf.put(b);
147         b =(byte) (l >>> 32);
148         logBuf.put(b);
149         b =(byte) (l >>> 40);
150         logBuf.put(b);
151         b =(byte) (l >>> 48);
152         logBuf.put(b);
153         b =(byte) (l >>> 56);
154         logBuf.put(b);
155     }
156
157     /**
158      * Read a long from the log.
159      */

160     public static long readLong(ByteBuffer JavaDoc logBuf) {
161     long ret = (logBuf.get() & 0xFFL) << 0;
162     ret += (logBuf.get() & 0xFFL) << 8;
163     ret += (logBuf.get() & 0xFFL) << 16;
164     ret += (logBuf.get() & 0xFFL) << 24;
165     ret += (logBuf.get() & 0xFFL) << 32;
166     ret += (logBuf.get() & 0xFFL) << 40;
167     ret += (logBuf.get() & 0xFFL) << 48;
168     ret += (logBuf.get() & 0xFFL) << 56;
169     return ret;
170     }
171
172     /**
173      * @return log storage size for a byteArray.
174      */

175     public static int getLongLogSize() {
176         return LONG_BYTES;
177     }
178
179     /**
180      * Write a byte array into the log. The size is stored first as an integer.
181      */

182     public static void writeByteArray(ByteBuffer JavaDoc logBuf,
183                                       byte[] b) {
184
185         /* Write the length. */
186         writeInt(logBuf, b.length);
187
188         /* Add the data itself. */
189         logBuf.put(b); // data
190
}
191
192     /**
193      * Read a byte array from the log. The size is stored first as an integer.
194      */

195     public static byte[] readByteArray(ByteBuffer JavaDoc logBuf) {
196         int size = readInt(logBuf); // how long is it?
197
if (DEBUG) {
198             System.out.println("pos = " + logBuf.position() +
199                                " byteArray is " + size + " on read");
200         }
201     if (size == 0) {
202         return ZERO_LENGTH_BYTE_ARRAY;
203     }
204         byte[] b = new byte[size];
205         logBuf.get(b); // read it out
206
return b;
207     }
208
209     /**
210      * @return log storage size for a byteArray
211      */

212     public static int getByteArrayLogSize(byte[] b) {
213         return INT_BYTES + b.length;
214     }
215
216     /**
217      * Write a string into the log. The size is stored first as an integer.
218      */

219     public static void writeString(ByteBuffer JavaDoc logBuf,
220                                    String JavaDoc stringVal) {
221         writeByteArray(logBuf, stringVal.getBytes());
222     }
223
224     /**
225      * Read a string from the log. The size is stored first as an integer.
226      */

227     public static String JavaDoc readString(ByteBuffer JavaDoc logBuf) {
228         return new String JavaDoc(readByteArray(logBuf));
229     }
230
231     /**
232      * @return log storage size for a string
233      */

234     public static int getStringLogSize(String JavaDoc s) {
235         return INT_BYTES + s.length();
236     }
237
238     /**
239      * Write a timestamp into the log.
240      */

241     public static void writeTimestamp(ByteBuffer JavaDoc logBuf,
242                                       Timestamp JavaDoc time) {
243         writeLong(logBuf, time.getTime());
244     }
245
246     /**
247      * Read a timestamp from the log.
248      */

249     public static Timestamp JavaDoc readTimestamp(ByteBuffer JavaDoc logBuf) {
250         long millis = readLong(logBuf);
251         return new Timestamp JavaDoc(millis);
252     }
253
254     /**
255      * @return log storage size for a timestamp
256      */

257     public static int getTimestampLogSize() {
258         return LONG_BYTES;
259     }
260
261     /**
262      * Write a boolean into the log.
263      */

264     public static void writeBoolean(ByteBuffer JavaDoc logBuf,
265                                     boolean bool) {
266         byte val = bool ? (byte) 1 : (byte) 0;
267         logBuf.put(val);
268     }
269
270     /**
271      * Read a boolean from the log.
272      */

273     public static boolean readBoolean(ByteBuffer JavaDoc logBuf) {
274         byte val = logBuf.get();
275         return (val == (byte) 1) ? true : false;
276     }
277
278     /**
279      * @return log storage size for a boolean.
280      */

281     public static int getBooleanLogSize() {
282         return 1;
283     }
284
285     /*
286      * Dumping support.
287      */

288     public static boolean dumpBoolean(ByteBuffer JavaDoc itemBuffer, StringBuffer JavaDoc sb,
289                                       String JavaDoc tag) {
290         sb.append("<");
291         sb.append(tag);
292         sb.append(" exists = \"");
293         boolean exists = readBoolean(itemBuffer);
294         sb.append(exists);
295         if (exists) {
296             sb.append("\">");
297         } else {
298             /* Close off the tag, we're done. */
299             sb.append("\"/>");
300         }
301         return exists;
302     }
303
304     /**
305      * The byte[]'s in Xid's are known to be 255 or less in length. So instead
306      * of using read/writeByteArray(), we can save 6 bytes per record by making
307      * the byte[] length be 1 byte instead of 4.
308      */

309     public static int getXidSize(Xid JavaDoc xid) {
310     byte[] gid = xid.getGlobalTransactionId();
311     byte[] bqual = xid.getBranchQualifier();
312     return
313         INT_BYTES + // FormatId
314
1 + // gxid length byte
315
1 + // bqual length byte
316
(gid == null ? 0 : gid.length) + // gid bytes
317
(bqual == null ? 0 : bqual.length); // bqual bytes
318
}
319
320     /*
321      * Xid.gid[] and bqual[] can't be longer than 64 bytes so we can get away
322      * with writing the length in one byte, rather than 4.
323      */

324     public static void writeXid(ByteBuffer JavaDoc logBuf, Xid JavaDoc xid) {
325     byte[] gid = xid.getGlobalTransactionId();
326     byte[] bqual = xid.getBranchQualifier();
327
328     writeInt(logBuf, xid.getFormatId());
329
330     if (gid == null) {
331         logBuf.put((byte) -1);
332     } else {
333         logBuf.put((byte) (gid.length));
334         logBuf.put(gid);
335     }
336
337     if (bqual == null) {
338         logBuf.put((byte) -1);
339     } else {
340         logBuf.put((byte) (bqual.length));
341         logBuf.put(bqual);
342     }
343     }
344
345     /*
346      * Xid.gid[] and bqual[] can't be longer than 64 bytes so we can get away
347      * with writing the length in one byte, rather than 4.
348      */

349     public static Xid JavaDoc readXid(ByteBuffer JavaDoc logBuf) {
350     int formatId = readInt(logBuf);
351
352     int gidLen = logBuf.get();
353     byte[] gid = null;
354     if (gidLen >= 0) {
355         gid = new byte[gidLen];
356         logBuf.get(gid);
357     }
358
359     int bqualLen = logBuf.get();
360     byte[] bqual = null;
361     if (bqualLen >= 0) {
362         bqual = new byte[bqualLen];
363         logBuf.get(bqual);
364     }
365
366     return new XidImpl(formatId, gid, bqual);
367     }
368
369     public static class XidImpl implements Xid JavaDoc {
370     private int formatId;
371     private byte[] gid;
372     private byte[] bqual;
373
374     /* public for unit tests. */
375     public XidImpl(int formatId, byte[] gid, byte[] bqual) {
376         this.formatId = formatId;
377         this.gid = gid;
378         this.bqual = bqual;
379     }
380
381     public int getFormatId() {
382         return formatId;
383     }
384
385     public byte[] getGlobalTransactionId() {
386         return gid;
387     }
388
389     public byte[] getBranchQualifier() {
390         return bqual;
391     }
392
393     public boolean equals(Object JavaDoc o) {
394         if (!(o instanceof XidImpl)) {
395         return false;
396         }
397
398         XidImpl xid = (XidImpl) o;
399         if (xid.getFormatId() != formatId) {
400         return false;
401         }
402         if (compareByteArrays(xid.getGlobalTransactionId(), gid) &&
403         compareByteArrays(xid.getBranchQualifier(), bqual)) {
404         return true;
405         }
406
407         return false;
408     }
409
410     public int hashCode() {
411         int code = formatId;
412         if (gid != null) {
413         for (int i = 0; i < gid.length; i++) {
414             code += gid[i];
415         }
416         }
417         if (bqual != null) {
418         for (int i = 0; i < bqual.length; i++) {
419             code += bqual[i];
420         }
421         }
422         return code;
423     }
424
425     private boolean compareByteArrays(byte[] b1, byte[] b2) {
426         if (b1 == null ||
427         b2 == null) {
428         return b1 == b2;
429         }
430
431         if (b1.length != b2.length) {
432         return false;
433         }
434
435         for (int i = 0; i < b1.length; i++) {
436         if (b1[i] != b2[i]) {
437             return false;
438         }
439         }
440
441         return true;
442     }
443
444     public String JavaDoc toString() {
445         StringBuffer JavaDoc sb = new StringBuffer JavaDoc();
446         sb.append("<Xid formatId=\"").append(formatId);
447         sb.append("\" gTxnId=\"");
448         if (gid == null) {
449         sb.append("null");
450         } else {
451         sb.append(new String JavaDoc(gid));
452         }
453         sb.append("\" bqual=\"");
454         if (bqual == null) {
455         sb.append("null");
456         } else {
457         sb.append(new String JavaDoc(bqual));
458         }
459         sb.append("\"/>");
460         return sb.toString();
461     }
462     }
463 }
464
Popular Tags