KickJava   Java API By Example, From Geeks To Geeks.

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


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

8
9 package com.sleepycat.je.log;
10
11 import java.nio.ByteBuffer JavaDoc;
12
13 import com.sleepycat.je.DatabaseException;
14 import com.sleepycat.je.dbi.EnvironmentImpl;
15 import com.sleepycat.je.latch.Latch;
16 import com.sleepycat.je.latch.LatchSupport;
17 import com.sleepycat.je.utilint.DbLsn;
18
19 /**
20  * DbLogBuffers hold outgoing, newly written log entries.
21  */

22 class LogBuffer implements LogSource {
23
24     private static final String JavaDoc DEBUG_NAME = LogBuffer.class.getName();
25
26     /* Storage */
27     private ByteBuffer JavaDoc buffer;
28
29     /* Information about what log entries are held here. */
30     private long firstLsn;
31     private long lastLsn;
32
33     /* The read latch serializes access to and modification of the LSN info. */
34     private Latch readLatch;
35
36     /*
37      * Buffer may be rewritten because an IOException previously occurred.
38      */

39     private boolean rewriteAllowed;
40
41     LogBuffer(int capacity, EnvironmentImpl env)
42     throws DatabaseException {
43
44         if (env.useDirectNIO()) {
45             buffer = ByteBuffer.allocateDirect(capacity);
46         } else {
47             buffer = ByteBuffer.allocate(capacity);
48         }
49         readLatch = LatchSupport.makeLatch(DEBUG_NAME, env);
50         reinit();
51     }
52
53     /*
54      * Used by LogManager for the case when we have a temporary buffer in hand
55      * and no LogBuffers in the LogBufferPool are large enough to hold the
56      * current entry being written. We just wrap the temporary ByteBuffer
57      * in a LogBuffer and pass it to FileManager. [#12674].
58      */

59     LogBuffer(ByteBuffer JavaDoc buffer, long firstLsn)
60     throws DatabaseException {
61
62     this.buffer = buffer;
63         this.firstLsn = firstLsn;
64         this.lastLsn = firstLsn;
65     rewriteAllowed = false;
66     }
67
68     void reinit()
69     throws DatabaseException {
70
71         readLatch.acquire();
72         buffer.clear();
73         firstLsn = DbLsn.NULL_LSN;
74         lastLsn = DbLsn.NULL_LSN;
75     rewriteAllowed = false;
76         readLatch.release();
77     }
78
79     /*
80      * Write support
81      */

82         
83     /**
84      * Return first LSN held in this buffer. Assumes the log write latch is
85      * held.
86      */

87     long getFirstLsn() {
88         return firstLsn;
89     }
90
91     /**
92      * This LSN has been written to the log.
93      */

94     void registerLsn(long lsn)
95     throws DatabaseException {
96
97         readLatch.acquire();
98     try {
99         if (lastLsn != DbLsn.NULL_LSN) {
100         assert (DbLsn.compareTo(lsn, lastLsn) > 0);
101         }
102         lastLsn = lsn;
103         if (firstLsn == DbLsn.NULL_LSN) {
104         firstLsn = lsn;
105         }
106     } finally {
107         readLatch.release();
108     }
109     }
110
111     /**
112      * Check capacity of buffer. Assumes that the log write latch is held.
113      * @return true if this buffer can hold this many more bytes.
114      */

115     boolean hasRoom(int numBytes) {
116         return (numBytes <= (buffer.capacity() - buffer.position()));
117     }
118
119     /**
120      * @return the actual data buffer.
121      */

122     ByteBuffer JavaDoc getDataBuffer() {
123         return buffer;
124     }
125
126     /**
127      * @return capacity in bytes
128      */

129     int getCapacity() {
130         return buffer.capacity();
131     }
132
133     /*
134      * Read support
135      */

136
137     /**
138      * Support for reading a log entry out of a still-in-memory log
139      * @return true if this buffer holds the entry at this LSN. The
140      * buffer will be latched for read. Returns false if
141      * LSN is not here, and releases the read latch.
142      */

143     boolean containsLsn(long lsn)
144     throws DatabaseException {
145
146         /* Latch before we look at the LSNs. */
147         readLatch.acquire();
148         boolean found = false;
149         if ((firstLsn != DbLsn.NULL_LSN) &&
150             ((DbLsn.compareTo(firstLsn, lsn) <= 0) &&
151          (DbLsn.compareTo(lastLsn, lsn) >= 0))) {
152             found = true;
153         }
154         
155         if (found) {
156             return true;
157         } else {
158             readLatch.release();
159             return false;
160         }
161     }
162   
163     /**
164      * When modifying the buffer, acquire the readLatch. Call release() to
165      * release the latch. Note that containsLsn() acquires the latch for
166      * reading.
167      */

168     public void latchForWrite()
169         throws DatabaseException {
170
171         readLatch.acquire();
172     }
173
174     /*
175      * LogSource support
176      */

177
178     /**
179      * @see LogSource#release
180      */

181     public void release()
182     throws DatabaseException {
183
184         readLatch.releaseIfOwner();
185     }
186
187     boolean getRewriteAllowed() {
188     return rewriteAllowed;
189     }
190
191     void setRewriteAllowed() {
192     rewriteAllowed = true;
193     }
194
195     /**
196      * @see LogSource#getBytes
197      */

198     public ByteBuffer JavaDoc getBytes(long fileOffset) {
199
200         /*
201          * Make a copy of this buffer (doesn't copy data, only buffer state)
202          * and position it to read the requested data.
203      *
204      * Note that we catch Exception here because it is possible that
205      * another thread is modifying the state of buffer simultaneously.
206      * Specifically, this can happen if another thread is writing this log
207      * buffer out and it does (e.g.) a flip operation on it. The actual
208      * mark/pos of the buffer may be caught in an unpredictable state. We
209      * could add another latch to protect this buffer, but that's heavier
210      * weight than we need. So the easiest thing to do is to just retry
211      * the duplicate operation. See [#9822].
212          */

213         ByteBuffer JavaDoc copy = null;
214     while (true) {
215         try {
216         copy = buffer.duplicate();
217         copy.position((int)
218                   (fileOffset - DbLsn.getFileOffset(firstLsn)));
219         break;
220         } catch (IllegalArgumentException JavaDoc IAE) {
221         continue;
222         }
223     }
224         return copy;
225     }
226
227     /**
228      * @see LogSource#getBytes
229      */

230     public ByteBuffer JavaDoc getBytes(long fileOffset, int numBytes) {
231         ByteBuffer JavaDoc copy = getBytes(fileOffset);
232         /* Log Buffer should always hold a whole entry. */
233         assert (copy.remaining() >= numBytes) :
234             "copy.remaining=" + copy.remaining() +
235             " numBytes=" + numBytes;
236         return copy;
237     }
238 }
239
Popular Tags