KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > com > sun > jts > CosTransactions > LogCursor


1 /*
2  * The contents of this file are subject to the terms
3  * of the Common Development and Distribution License
4  * (the License). You may not use this file except in
5  * compliance with the License.
6  *
7  * You can obtain a copy of the license at
8  * https://glassfish.dev.java.net/public/CDDLv1.0.html or
9  * glassfish/bootstrap/legal/CDDLv1.0.txt.
10  * See the License for the specific language governing
11  * permissions and limitations under the License.
12  *
13  * When distributing Covered Code, include this CDDL
14  * Header Notice in each file and include the License file
15  * at glassfish/bootstrap/legal/CDDLv1.0.txt.
16  * If applicable, add the following below the CDDL Header,
17  * with the fields enclosed by brackets [] replaced by
18  * you own identifying information:
19  * "Portions Copyrighted [year] [name of copyright owner]"
20  *
21  * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
22  */

23
24 /*
25  * Copyright 2004-2005 Sun Microsystems, Inc. All rights reserved.
26  * Use is subject to license terms.
27  */

28 //----------------------------------------------------------------------------
29
//
30
// Module: LogCursor.java
31
//
32
// Description: Log file browsing operations.
33
//
34
// Product: com.sun.jts.CosTransactions
35
//
36
// Author: Simon Holdsworth
37
//
38
// Date: March, 1997
39
//
40
// Copyright (c): 1995-1997 IBM Corp.
41
//
42
// The source code for this program is not published or otherwise divested
43
// of its trade secrets, irrespective of what has been deposited with the
44
// U.S. Copyright Office.
45
//
46
// This software contains confidential and proprietary information of
47
// IBM Corp.
48
//----------------------------------------------------------------------------
49

50 package com.sun.jts.CosTransactions;
51
52 // Import required classes.
53

54 import java.util.*;
55
56 /**Contains information for an open cursor.
57  *
58  * @version 0.01
59  *
60  * @author Simon Holdsworth, IBM Corporation
61  *
62  * @see
63 */

64 //----------------------------------------------------------------------------
65
// CHANGE HISTORY
66
//
67
// Version By Change Description
68
// 0.01 SAJH Initial implementation.
69
//-----------------------------------------------------------------------------
70

71 class LogCursor {
72     /**Constants used to identify browse direction.
73      */

74     final static int ASCENDING = 0;
75     final static int DESCENDING = 1;
76
77     /**Internal instance members.
78      */

79     LogCursor blockValid;
80     LogControl logControl;
81     LogHandle logHandle;
82     LogLSN startLSN;
83     LogLSN endLSN;
84     LogLSN currentLSN;
85     int direction;
86     boolean symbolicsChecked;
87
88     /**Creates a cursor for a browse in the given range.
89      *
90      * @param control The LogControl object for the log instance.
91      * @param handle the handle for the log file.
92      * @param startLSN The LSN for the start of the browse.
93      * @param endLSN The LSN for the end of the browse.
94      *
95      * @return
96      *
97      * @see
98      */

99     LogCursor( LogControl control,
100                LogHandle handle,
101                LogLSN startLSN,
102                LogLSN endLSN ) {
103
104         logHandle = handle;
105         logControl = control;
106
107         // Initialise the Log_CursorDescriptor block
108
// - set start of range field to startLsn
109
// - set end of range field to endLsn
110
// - set current position to startLsn
111
// - IF startLsn < endLsn
112
// set direction field to ASCENDING
113
// ELSE
114
// set direction field to DESCENDING
115
// - set the file descriptor to the logHandle parameter
116
// - set the BlockValid field to the address of the
117
// Log_FileDescriptor block
118

119         this.startLSN = new LogLSN(startLSN);
120         currentLSN = new LogLSN(startLSN);
121         this.endLSN = new LogLSN(endLSN);
122         if( startLSN.lessThan(endLSN) )
123             direction = ASCENDING;
124         else
125             direction = DESCENDING;
126
127         blockValid = this;
128         symbolicsChecked = false;
129
130     }
131
132
133     /**Destroys a cursor.
134      *
135      * @param
136      *
137      * @return
138      *
139      * @see
140      */

141     public void finalize() {
142         blockValid = null;
143
144     }
145
146     /**Reads a record from the cursor.
147      *
148      * @param type An array which will contain the type for record read.
149      * @param LSNread The LSN of the record read.
150      *
151      * @return The bytes read.
152      *
153      * @exception LogException The operation failed.
154      *
155      * @see
156      */

157     synchronized byte[] readCursor( int[/*1*/] type,
158                                     LogLSN LSNread )
159         throws LogException {
160
161         // Check BlockValid field in Log_CursorDescriptor block pointed to
162
// by cursorId parameter, and ensure it is valid
163
// IF not valid Log_CursorDescriptor
164
// Return LOG_INVALID_CURSOR
165

166         if( blockValid != this )
167             throw new LogException(null,LogException.LOG_INVALID_CURSOR,1);
168
169         // Check BlockValid field in Log_FileDescriptor block pointed to
170
// by field in Log_CursorDescriptor block and ensure it is valid
171

172         if( logHandle == null || logHandle.blockValid != logHandle )
173             throw new LogException(null,LogException.LOG_INVALID_CURSOR,2);
174
175         // IF not LogInitialised Return LOG_NOT_INITIALISED
176

177         if( !logControl.logInitialised )
178             throw new LogException(null,LogException.LOG_NOT_INITIALISED,3);
179
180         // IF the head LSN in the Log_FileDescriptor block = LOG_NULL_LSN
181
// Unlock the Log_FileDescriptor latch
182
// Return LOG_END_OF_CURSOR
183

184
185         if( logHandle.logControlDescriptor.headLSN.isNULL() )
186             throw new LogException(null,LogException.LOG_END_OF_CURSOR,5);
187
188         // Check if the current position in Log_CursorDescriptor block
189
// contains symbolic constants
190
// IF equal to LOG_HEAD_LSN
191
// Replace it with head LSN value from Log_FileDescriptor block
192
// ELSE
193
// IF equal to LOG_TAIL_LSN
194
// Replace it with tail LSN value from Log_FileDescriptor block
195

196         if( !symbolicsChecked ) {
197             if( currentLSN.equals(LogLSN.HEAD_LSN) )
198                 currentLSN.copy(logHandle.logControlDescriptor.headLSN);
199             else if( currentLSN.equals(LogLSN.TAIL_LSN) )
200                 currentLSN.copy(logHandle.logControlDescriptor.tailLSN);
201
202             symbolicsChecked = true;
203         }
204
205         // Check that the current position lies within the log record range
206
// IF current position > head LSN (in Log_FileDescriptor block)
207
// Indicate 'end of cursor'
208
// ELSE
209
// IF current position < tail LSN (indicating log truncate)
210
// Indicate 'end of cursor'
211
// IF 'end of cursor' has been set
212
// Unlock the Log_FileDescriptor latch
213
// Return LOG_END_OF_CURSOR
214

215         if( currentLSN.greaterThan(logHandle.logControlDescriptor.headLSN) ||
216             currentLSN.lessThan(logHandle.logControlDescriptor.tailLSN) )
217             throw new LogException(null,LogException.LOG_END_OF_CURSOR,6);
218
219         // Now retrieve the record identified by the CurrentLogLSN value.
220
// This is done in a loop, since we may have to do this more than once
221
// if the 'current position' LSN points to a link record.
222

223         boolean recordRetrieved = false;
224         LogExtent logEDP = null;
225         LogRecordHeader logRH = null;
226         LogRecordEnding logRE = null;
227
228         while( !recordRetrieved ) {
229
230             // Determine the extent file containing the 'current position'
231
// log record
232
// Position the file pointer at the 'current position' using LSEEK
233
// IF not successful allow the error to pass to the caller.
234
// Unlock the Log_FileDescriptor latch
235
// Return error from Log_PositionFilePointer function
236

237             logEDP = logHandle.positionFilePointer(currentLSN,0,LogExtent.ACCESSTYPE_READ);
238
239             // Issue READ to get the log record header
240
// IF not successful
241
// set last access as unknown as we cannot be sure of the
242
// new cursor position.
243
// Unlock the Log_FileDescriptor latch
244
// return LOG_READ_FAILURE
245

246             byte[] headerBytes = new byte[LogRecordHeader.SIZEOF];
247             int bytesRead = 0;
248             try {
249                 bytesRead = logEDP.fileHandle.fileRead(headerBytes);
250             } catch( LogException le ) {
251                 logEDP.lastAccess = LogExtent.ACCESSTYPE_UNKNOWN;
252                 throw new LogException(null,LogException.LOG_READ_FAILURE,8);
253             }
254
255             logRH = new LogRecordHeader(headerBytes,0);
256             logEDP.cursorPosition += bytesRead;
257
258             // IF the lsn value in the record header is not same as the
259
// 'current cursor position' lsn
260
// Unlock the Log_FileDescriptor latch
261
// Return LOG_CORRUPTED
262

263             if( !logRH.currentLSN.equals(currentLSN) )
264                 throw new LogException(null,LogException.LOG_CORRUPTED,9);
265
266             // Check the record header in case its a link record thats been read in
267
// IF it is a link record
268
// IF cursor is ASCENDING
269
// Set 'current position' to next LSN in link record
270
// ELSE
271
// Set 'current position' to previous LSN in link record
272
// Iterate LOOP
273

274             if( logRH.recordType == LogHandle.LINK )
275                 if( direction == ASCENDING )
276                     currentLSN.copy(logRH.nextLSN);
277                 else
278                     currentLSN.copy(logRH.previousLSN);
279             else
280                 recordRetrieved = true;
281         }
282
283         // Set up a 2-element iovec array so that the record data
284
// and record ending are separated during the READV
285

286         byte[][] readVect = new byte[2][];
287         readVect[0] = new byte[logRH.recordLength];
288         readVect[1] = new byte[LogRecordEnding.SIZEOF];
289
290         // Issue READV to get the log record
291
// IF not successful
292
// Unlock the Log_FileDescriptor latch
293
// Return LOG_READ_FAILURE
294

295         int bytesRead = 0;
296         try {
297             bytesRead = logEDP.fileHandle.readVector(readVect);
298         } catch( LogException le ) {
299             logEDP.lastAccess = LogExtent.ACCESSTYPE_UNKNOWN;
300             throw new LogException(null,le.errorCode,11);
301         }
302         logEDP.cursorPosition += bytesRead;
303
304         logRE = new LogRecordEnding(readVect[1],0);
305
306         // IF the lsn contained in the record ending is not the same as the
307
// 'current cursor position' lsn
308
// Unlock the Log_FileDescriptor latch
309
// Return LOG_CORRUPTED
310

311         if( !logRE.currentLSN.equals(currentLSN) )
312             throw new LogException(null,LogException.LOG_CORRUPTED,12);
313
314         // Update the Log_CursorDescriptor 'current position'
315
// IF cursor is ASCENDING
316
// Set 'current position' to next LSN in log record
317
// ELSE
318
// Set 'current position' to previous LSN in log record
319

320         if( direction == ASCENDING )
321             currentLSN.copy(logRH.nextLSN);
322         else
323             currentLSN.copy(logRH.previousLSN);
324
325         // Copy the record type and lsn values from the
326
// Log_RecordHeader to callers recordTypeP and lsnP
327
// parameters respectively
328

329         type[0] = logRH.recordType;
330         LSNread.copy(logRH.currentLSN);
331
332         // Return LOG_SUCCESS
333

334         return readVect[0];
335     }
336 }
337
Popular Tags