KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > com > quadcap > sql > file > LogBuffer


1 package com.quadcap.sql.file;
2
3 /* Copyright 1997 - 2003 Quadcap Software. All rights reserved.
4  *
5  * This software is distributed under the Quadcap Free Software License.
6  * This software may be used or modified for any purpose, personal or
7  * commercial. Open Source redistributions are permitted. Commercial
8  * redistribution of larger works derived from, or works which bundle
9  * this software requires a "Commercial Redistribution License"; see
10  * http://www.quadcap.com/purchase.
11  *
12  * Redistributions qualify as "Open Source" under one of the following terms:
13  *
14  * Redistributions are made at no charge beyond the reasonable cost of
15  * materials and delivery.
16  *
17  * Redistributions are accompanied by a copy of the Source Code or by an
18  * irrevocable offer to provide a copy of the Source Code for up to three
19  * years at the cost of materials and delivery. Such redistributions
20  * must allow further use, modification, and redistribution of the Source
21  * Code under substantially the same terms as this license.
22  *
23  * Redistributions of source code must retain the copyright notices as they
24  * appear in each source code file, these license terms, and the
25  * disclaimer/limitation of liability set forth as paragraph 6 below.
26  *
27  * Redistributions in binary form must reproduce this Copyright Notice,
28  * these license terms, and the disclaimer/limitation of liability set
29  * forth as paragraph 6 below, in the documentation and/or other materials
30  * provided with the distribution.
31  *
32  * The Software is provided on an "AS IS" basis. No warranty is
33  * provided that the Software is free of defects, or fit for a
34  * particular purpose.
35  *
36  * Limitation of Liability. Quadcap Software shall not be liable
37  * for any damages suffered by the Licensee or any third party resulting
38  * from use of the Software.
39  */

40
41 import java.io.InputStream JavaDoc;
42 import java.io.IOException JavaDoc;
43 import java.io.OutputStream JavaDoc;
44
45 import java.util.Properties JavaDoc;
46
47 import com.quadcap.util.Debug;
48 import com.quadcap.util.Util;
49
50 /**
51  * A bounded buffer based on an underlying RandomAccess
52  *
53  * @author Stan Bailes
54  */

55 public class LogBuffer {
56     RandomAccess ra;
57
58     /**
59      * "Begin" pointer.
60      */

61     int bX;
62
63     /**
64      * "End" pointer
65      */

66     int eX;
67
68     /**
69      * "Checkpoint" pointer
70      */

71     int cX;
72
73     /**
74      * Size Limit, in octets.
75      */

76     int maxSize = 128 * 1024 * 1024;
77
78     /**
79      * Total header bytes
80      */

81     static final int headerSize = 16;
82
83     /**
84      * Default constructor (for factory)
85      */

86     public LogBuffer() {}
87
88     /**
89      * Initialize from existing randomaccess
90      */

91     public void init(RandomAccess ra, Properties JavaDoc props) throws IOException JavaDoc {
92         this.ra = ra;
93         this.bX = ra.readInt(0);
94         this.eX = ra.readInt(4);
95         this.cX = ra.readInt(8);
96         maxSize = Integer.parseInt(props.getProperty("maxLogSize", "" + maxSize));
97     }
98
99     /**
100      * Create a new one
101      *
102      * @param ra the underlying random access interface to the store
103      * @param m the maximum size of this buffer.
104      */

105     public void init(RandomAccess ra, int m) throws IOException JavaDoc {
106         this.ra = ra;
107         this.bX = 0;
108         this.eX = 0;
109         this.cX = 0;
110         this.maxSize = m;
111         sync();
112     }
113
114     /**
115      * Return an InputStream which will supply a subset of the buffer starting
116      * at 'pos' and ending at the current buffer end
117      */

118     public InputStream JavaDoc getInputStream(int pos) {
119         return new LogInputStream(this, pos, this.eX);
120     }
121
122     /**
123      * Return an OutputStream which can be used to write to the end of
124      * the buffer
125      */

126     public OutputStream JavaDoc getOutputStream() {
127         return new LogOutputStream(this);
128     }
129
130     /**
131      * Return the current end position (the position of the next byte to
132      * be written)
133      */

134     public int getEnd() { return eX; }
135
136     /**
137      * Return the current begin position (the position of the first byte
138      * written
139      */

140     public int getBegin() { return bX; }
141
142     /**
143      * Return the value marking the end of the last checkpoint
144      */

145     public int getCheckpoint() { return cX; }
146
147     /**
148      * Set the checkpoint value
149      */

150     public void checkpoint() { this.cX = this.eX; }
151
152     /**
153      * Move the begin pointer past some bytes.
154      */

155     public void setBegin(int b) {
156         //#ifdef DEBUG
157
if (Trace.bit(13)) {
158             Debug.println(toString() + ".setBegin(" + b + ")");
159         }
160         //#endif
161
bX = b;
162     }
163
164     /**
165      * Reset the buffer to its empty state
166      */

167     public void reset() {
168         //#ifdef DEBUG
169
if (Trace.bit(13)) {
170             Debug.println(toString() + ".reset() -----------------------");
171         }
172         //#endif
173
bX = 0;
174         eX = 0;
175         cX = 0;
176     }
177
178     /**
179      * Truncate the underlying region to the current actual size of the
180      * buffer
181      */

182     public void truncate() throws IOException JavaDoc {
183         ra.resize(size() + headerSize);
184     }
185
186     /**
187      * Return the size of the active area
188      */

189     public int size() {
190         return eX - bX;
191     }
192     
193     /**
194      * Read a range of bytes from the buffer
195      */

196     public int read(int pos, byte[] buf, int off, int cnt)
197         throws IOException JavaDoc
198     {
199         int ret = 0;
200         if (cnt > 0) {
201             ra.read(pos + headerSize, buf, off, cnt);
202             ret = cnt;
203         }
204         //#ifdef DEBUG
205
if (Trace.bit(13)) {
206             Debug.println(toString() + ".read(" + pos + ", " + cnt + ") = " +
207                           ret + ", " +
208                           Util.hexBytes(buf, off, ret));
209         }
210         //#endif
211
return ret;
212     }
213
214     /**
215      * Read a single byte
216      */

217     public int readByte(int pos) throws IOException JavaDoc {
218         int ret = ra.readByte(pos + headerSize);
219         //#ifdef DEBUG
220
if (Trace.bit(13)) {
221             Debug.println(toString() + ".read(" + pos + ") = " + ret);
222         }
223         //#endif
224
return ret;
225     }
226
227     /**
228      * Write a range of bytes to the end of the buffer, updating 'eX' to
229      * point to the new end of the buffer.
230      */

231     public void write(byte[] buf, int off, int cnt)
232         throws IOException JavaDoc
233     {
234         //#ifdef DEBUG
235
if (Trace.bit(13)) {
236             Debug.println(toString() + ".write(" +
237                           Util.hexBytes(buf, off, cnt) + ")");
238         }
239         //#endif
240
if (eX + cnt > maxSize) {
241             //#ifdef DEBUG
242
Debug.println("eX: " + eX + ", write(" + off + ": " +
243                           Util.strBytes(buf, off, cnt));
244             //#endif
245
throw new IOException JavaDoc("LogBuffer full: " + eX + " + " + cnt + " bytes");
246         }
247         if (cnt > 0) {
248             ra.write(eX + headerSize, buf, off, cnt);
249             eX += cnt;
250         }
251     }
252
253     /**
254      * Write a single byte to the buffer. Do not modify eX.
255      */

256     public void writeByte(int pos, int b) throws IOException JavaDoc {
257         //#ifdef DEBUG
258
if (Trace.bit(13)) {
259             Debug.println(toString() + ".writeByte(" +
260                           pos + ", " + b + ")");
261         }
262         //#endif
263
ra.writeByte(pos + headerSize, b);
264     }
265
266     /**
267      * Flush any changes to disk.
268      */

269     public void sync() throws IOException JavaDoc {
270         //#ifdef DEBUG
271
if (Trace.bit(13) || Trace.bit(24)) {
272             Debug.println(toString() + ".sync()");
273         }
274         //#endif
275
ra.writeInt(0, bX);
276         ra.writeInt(4, eX);
277         ra.writeInt(8, cX);
278         ra.writeInt(12, maxSize);
279         ra.flush();
280     }
281
282     /**
283      * Close the file
284      */

285     public void close() throws IOException JavaDoc {
286         //#ifdef DEBUG
287
if (Trace.bit(13)) {
288             Debug.println(toString() + ".close()");
289         }
290         //#endif
291
sync();
292         ra.close();
293     }
294
295     /**
296      * Perform buffer-wrapping address incrementing math
297      */

298     public int addPos(int pos, int amt) {
299         int ret = pos + amt;
300         return ret;
301     }
302
303     /**
304      * Inner input stream
305      */

306     class LogInputStream extends InputStream JavaDoc {
307         LogBuffer b;
308         int pos;
309         int lim;
310
311         LogInputStream(LogBuffer b, int pos, int lim) {
312             //#ifdef DEBUG
313
if (Trace.bit(13)) {
314                 Debug.println("CIS(" + pos + "-" + lim + ")");
315             }
316             //#endif
317
this.b = b;
318             this.pos = pos;
319             this.lim = lim;
320         }
321
322         public int read(byte[] buf, int off, int cnt)
323             throws IOException JavaDoc
324         {
325             //#ifdef DEBUG
326
int xpos = pos;
327             //#endif
328
int xpos2 = pos + cnt;
329             if (xpos2 > lim) {
330                 cnt -= (xpos2 - lim);
331             }
332             int ret = -1;
333             if (cnt > 0) {
334                 ret = b.read(pos, buf, off, cnt);
335                 if (ret > 0) {
336                     pos = b.addPos(pos, ret);
337                 } else {
338                     ret = -1;
339                 }
340             }
341             //#ifdef DEBUG
342
if (Trace.bit(14)) {
343                 Debug.println("CIS[" + xpos + "-" + lim +
344                               "].read() = " + ret + ": " +
345                               Util.hexBytes(buf, off, ret));
346             }
347             //#endif
348
return ret;
349         }
350         
351         public int read() throws IOException JavaDoc {
352             //#ifdef DEBUG
353
int xpos = pos;
354             //#endif
355
int ret = b.readByte(pos);
356             if (ret >= 0) {
357                 pos = b.addPos(pos, 1);
358             }
359             //#ifdef DEBUG
360
if (Trace.bit(14)) {
361                 Debug.println("CIS[" + xpos + "].read() = " + ret);
362             }
363             //#endif
364
return ret;
365         }
366     }
367
368     /**
369      * Inner output stream
370      */

371     class LogOutputStream extends OutputStream JavaDoc {
372         LogBuffer b;
373
374         LogOutputStream(LogBuffer b) {
375             this.b = b;
376         }
377         
378         public void write(byte[] buf, int off, int cnt) throws IOException JavaDoc {
379             //#ifdef DEBUG
380
if (Trace.bit(14)) {
381                 Debug.println("COS[" + b.eX + "].write(" +
382                               Util.hexBytes(buf, off, cnt) + ")");
383             }
384             //#endif
385
b.write(buf, off, cnt);
386         }
387
388         public void write(int x) throws IOException JavaDoc {
389             //#ifdef DEBUG
390
if (Trace.bit(14)) {
391                 Debug.println("COS[" + b.eX + "].write(" + x + ")");
392             }
393             //#endif
394
if (false) {
395                 b.writeByte(b.eX, x);
396                 b.eX = addPos(b.eX, 1);
397             } else {
398                 byte[] fu = new byte[1];
399                 fu[0] = (byte)x;
400                 write(fu, 0, 1);
401             }
402         }
403     }
404     
405     //#ifdef DEBUG
406

407     public String JavaDoc toString() {
408         return "LogBuffer(" + maxSize + "," + bX + "," + eX + "," + cX + ")";
409     }
410
411     public static void main(String JavaDoc[] args) {
412         try {
413             test1();
414         } catch (Throwable JavaDoc t) {
415             Debug.print(t);
416         }
417     }
418
419     static void test1() throws Exception JavaDoc {
420         int size = 100000;
421         ByteArrayRandomAccess bra = new ByteArrayRandomAccess(size + 12);
422         BufferedRandomAccess bbra = new BufferedRandomAccess(bra);
423         LogBuffer cb = new LogBuffer();
424         cb.init(bbra, size);
425  
426 // for (int i = 0; i < size; i++) {
427
// cb.writeByte(i, (byte)(i & 0xff));
428
// }
429
// for (int i = 0; i < size; i++) {
430
// int ret = cb.readByte(i);
431
// if (ret != (i & 0xff)) {
432
// throw new Exception("LogBuffer.test1 " + i +
433
// " (" + (i&0xff) + ")" +
434
// ", got " + ret);
435
// }
436
// }
437

438         int xs = 12;
439         int[] poss = new int[xs];
440         int[] sizz = new int[xs];
441         int beg = cb.getBegin();
442         byte[] buf = new byte[4096];
443         byte[] rbuf = new byte[4096];
444         OutputStream JavaDoc os = cb.getOutputStream();
445         int wsize = 1;
446         for (int i = 0; i < xs; i++) {
447             poss[i] = cb.getEnd();
448             sizz[i] = wsize+1;
449             wsize += wsize;
450             makeBuf(buf, i, sizz[i]);
451             os.write(buf, 0, sizz[i]);
452             for (int j = 0; j < i; j++) {
453                 makeBuf(buf, j, sizz[j]);
454                 InputStream JavaDoc is = cb.getInputStream(poss[j]);
455                 is.read(rbuf, 0, sizz[i]);
456                 if (Util.compareBytes(buf, 0, sizz[j], rbuf, 0, sizz[j]) != 0){
457                     throw new Exception JavaDoc("R " + i + ": " +
458                                         Util.hexBytes(buf, 0, sizz[i]) +
459                                         " vs " + j + ": " +
460                                         Util.hexBytes(rbuf, 0, sizz[i]));
461                 }
462             }
463         }
464         
465     }
466
467     static void makeBuf(byte[] buf, int x, int siz) {
468         x *= 13;
469         for (int i = 0; i < siz; i++) {
470             buf[i] = (byte)(x++);
471         }
472     }
473
474     //#endif
475

476 }
477
Popular Tags