KickJava   Java API By Example, From Geeks To Geeks.

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


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 2006 Sun Microsystems, Inc. All rights reserved.
26  * Use is subject to license terms.
27  */

28 //----------------------------------------------------------------------------
29
//
30
// Module: LogFileHandle.java
31
//
32
// Description: Physical log file 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.io.*;
55 import java.util.*;
56
57 /**This class encapsulates file I/O operations and the file handle.
58  *
59  * @version 0.01
60  *
61  * @author Simon Holdsworth, IBM Corporation
62  *
63  * @see
64 */

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

72 class LogFileHandle {
73     /**The log file should be accessed in read only mode.
74      */

75     final static int OPEN_RDONLY = 0x00000001;
76
77     /**The log file should be accessed in read/write mode.
78      */

79     final static int OPEN_RDWR = 0x00000002;
80
81     /**The log file should be opened as a new file if necessary.
82      */

83     final static int OPEN_CREAT = 0x00000004;
84
85     /**The log file should be synchronized with the file system.
86      */

87     final static int OPEN_SYNC = 0x00000008;
88
89     /**Seek relative location to the current position.
90      */

91     final static int SEEK_RELATIVE = 0;
92
93     /**Seek absolute location in the file.
94      */

95     final static int SEEK_ABSOLUTE = 1;
96
97     /**Open options string for file read only.
98      */

99     final static String JavaDoc MODE_READONLY = "r"/*#Frozen*/; // rb
100

101     /**Open options string for file read/write, old file.
102      */

103     static String JavaDoc MODE_READWRITEOLD = "rw"/*#Frozen*/; // wb-
104

105     /**open options string for file read/write, new file.
106      */

107     static String JavaDoc MODE_READWRITENEW = "rw"/*#Frozen*/; // wb+
108

109     static String JavaDoc dsyncProp = null;
110
111     final static String JavaDoc DSYNC_PROPERTY = "com.sun.appserv.transaction.nofdsync";
112
113     /**The maximum length of a file name.
114      */

115     //!final static int LOG_FNAME_MAX = FILENAME_MAX;
116
final static int LOG_FNAME_MAX = 252;
117
118     /**The size of a block in the file system.
119      */

120     final static int FILESYSTEM_BLOCKSIZE = 4096;
121
122     /**Instance information.
123      */

124     private RandomAccessFile fhandle = null;
125     private FileDescriptor fd = null;
126     private byte[] bufferData = null;
127     boolean buffered = false;
128     int bufferUpdateStart = -1;
129     int bufferUpdateEnd = -1;
130     int buffPos = 0;
131
132     static {
133         dsyncProp = System.getProperty(DSYNC_PROPERTY);
134         if (dsyncProp != null) {
135             MODE_READWRITEOLD = "rwd";
136             MODE_READWRITENEW = "rwd";
137         }
138     }
139
140     /**Default LogFileHandle constructor.
141      *
142      * @param
143      *
144      * @return
145      *
146      * @see
147      */

148     LogFileHandle() {
149         fhandle = null;
150         fd = null; //@MA
151

152     }
153
154     /**Creates a new file handle for the given file.
155      *
156      * @param file The File to be opened.
157      * @param int Open options
158      *
159      * @return
160      *
161      * @exception LogException Opening the file failed.
162      *
163      * @see
164      */

165     LogFileHandle( File file,
166                    int openOptions )
167         throws LogException {
168
169         // Perform buffering depending on the flag.
170

171         if (dsyncProp == null) {
172             if( (openOptions & OPEN_SYNC) == 0 )
173                 buffered = true;
174         }
175
176         // Change the OpenOptions to the format expected by CLOSE
177

178         if( (openOptions & OPEN_RDONLY) != 0 )
179             fileOpen(file,MODE_READONLY);
180         else
181             try {
182                 fileOpen(file,MODE_READWRITEOLD);
183             } catch( LogException e ) {
184                 if( (openOptions & OPEN_CREAT) != 0 )
185                     fileOpen(file,MODE_READWRITENEW);
186             }
187     }
188
189     /**Destroys the FileHandle, closing the file, if open.
190      *
191      * @param
192      *
193      * @return
194      *
195      * @exception LogException The close of the file failed.
196      *
197      * @see
198      */

199     public void finalize()
200         throws LogException {
201
202         // Ensure that the file is closed.
203
// If the file is buffered, this ensures that the buffer is written out
204
// if necessary.
205

206         if( fhandle != null )
207             fileClose();
208
209         // Discard the buffer.
210

211         bufferData = null;
212
213     }
214
215     /**Reads from the file.
216      *
217      * @param buffer Buffer for file read.
218      *
219      * @return Number of bytes read.
220      *
221      * @exception LogException The read failed.
222      *
223      * @see
224      */

225     int fileRead( byte[] buffer )
226         throws LogException{
227
228         int bytesRead = 0;
229
230         if( buffer.length > 0 )
231             try {
232
233                 // If buffered, then copy the file buffer into the required array.
234

235                 if( buffered ) {
236
237                     // If the current position is beyond the end of the buffer then the read fails.
238

239                     if( buffPos >= bufferData.length )
240                         bytesRead = -1;
241
242                     // Otherwise if the buffer is not big enough for all the bytes, return those that
243
// it does contain, else return all the bytes asked for.
244

245                     else {
246                         if( buffPos + buffer.length >= bufferData.length )
247                             bytesRead = bufferData.length - buffPos;
248                         else
249                             bytesRead = buffer.length;
250
251                         System.arraycopy(bufferData,buffPos,buffer,0,bytesRead);
252                         buffPos += bytesRead;
253                     }
254                 }
255
256                 // Otherwise read the data from the file.
257

258                 else {
259                     bytesRead = fhandle.read(buffer);
260                     if( bytesRead == -1 ) bytesRead = 0;
261                 }
262             } catch( Throwable JavaDoc exc ) {
263                 throw new LogException(null,LogException.LOG_READ_FAILURE,1);
264             }
265
266         return bytesRead;
267     }
268
269     /**Writes to the file.
270      *
271      * @param buffer The bytes to write.
272      *
273      * @return The number of bytes written.
274      *
275      * @exception LogException The write failed.
276      *
277      * @see
278      */

279     int fileWrite( byte[] buffer )
280         throws LogException {
281
282         if( buffer.length > 0 )
283             try {
284
285                 // If buffered, then copy the array into the file buffer.
286

287                 if( buffered ) {
288
289                     // If the array copy requires more bytes than exist in the buffer, then the
290
// buffer must be extended to the required size.
291

292                     if( buffPos + buffer.length >= bufferData.length ) {
293                         byte[] newBufferData = new byte[buffPos+buffer.length];
294                         if( bufferData.length > 0 )
295                             System.arraycopy(bufferData,0,newBufferData,0,bufferData.length);
296                         bufferData = newBufferData;
297                     }
298
299                     // Copy the data.
300

301                     System.arraycopy(buffer,0,bufferData,buffPos,buffer.length);
302
303                     // Remember how much of the buffer has been updated, and increase the current
304
// buffer position.
305

306                     if( bufferUpdateStart == -1 ||
307                         buffPos < bufferUpdateStart )
308                         bufferUpdateStart = buffPos;
309
310                     buffPos += buffer.length;
311
312                     if( buffPos > bufferUpdateEnd )
313                         bufferUpdateEnd = buffPos;
314                 }
315
316                 // Otherwise write the data to the file.
317
// For non-buffered writes, we always sync to the file system.
318

319                 else {
320                     fhandle.write(buffer);
321                     if (dsyncProp == null)
322                         fd.sync();
323                 }
324             } catch( Throwable JavaDoc e ) {
325                 int errCode = LogException.LOG_WRITE_FAILURE;
326                 //$ if( errno == ENOSPC )
327
//$ retCode = LogControl.LOG_NO_SPACE;
328
throw new LogException(null,errCode,1);
329             }
330
331         return buffer.length;
332     }
333
334     /**Opens the given file.
335      *
336      * @param file The name of the file.
337      * @param fileMode The mode to open in.
338      *
339      * @return
340      *
341      * @exception LogException The open failed.
342      *
343      * @see
344      */

345     void fileOpen( File file,
346                    String JavaDoc fileMode )
347         throws LogException {
348         fhandle = null;
349         try {
350             fhandle = new RandomAccessFile(file,fileMode);
351             fd = fhandle.getFD();
352
353             // If buffering, and the opened file has contents, then allocate the buffer
354
// and read the file contents in. Otherwise make the buffer an empty array.
355

356             if( buffered )
357                 if( fhandle.length() > 0 ) {
358                     bufferData = new byte[(int)fhandle.length()];
359                     fhandle.readFully(bufferData);
360                 }
361                 else
362                     bufferData = new byte[0];
363         } catch( Throwable JavaDoc e ) {
364             throw new LogException(null,LogException.LOG_OPEN_FAILURE,1);
365         }
366
367     }
368
369     /**Closes the file.
370      *
371      * @param
372      *
373      * @return
374      *
375      * @exception LogException The close failed
376      *
377      * @see
378      */

379     void fileClose()
380         throws LogException {
381
382         try {
383
384             // If buffered, then ensure that the buffer is stored and synced with the
385
// file system.
386

387             if( bufferUpdateStart != -1 )
388                 fileSync();
389
390             // Close the file.
391

392             fhandle.close();
393         } catch( Throwable JavaDoc e ) {
394             throw new LogException(null,LogException.LOG_CLOSE_FAILURE,1);
395         }
396
397         // Reset the file handle and descriptor values.
398

399         fhandle = null;
400         fd = null; //@MA
401

402     }
403
404     /**Seeks the given position in the file.
405      *
406      * @param position Position to seek.
407      * @param seekMode Mode of seek.
408      *
409      * @return
410      *
411      * @exception LogException The seek failed.
412      *
413      * @see
414      */

415
416     void fileSeek( long position,
417                    int seekMode )
418         throws LogException {
419
420         // Adjust the position being sought if it is relative to the current position.
421

422         long absPos = position;
423         try {
424
425             // If buffered, then simply set the buffer position.
426
// If the position is beyond the end of the buffer, then the buffer will be
427
// extended when the next write occurs.
428

429             if( buffered ) {
430                 if( seekMode == SEEK_RELATIVE )
431                     absPos = buffPos + position;
432                 buffPos = (int)absPos;
433             }
434
435             // Otherwise seek the position in the file.
436

437             else {
438                 if( seekMode == SEEK_RELATIVE )
439                     absPos = fhandle.getFilePointer() + position;
440                 fhandle.seek(absPos);
441             }
442         } catch( Throwable JavaDoc e ) {
443             throw new LogException(null,LogException.LOG_READ_FAILURE,1);
444         }
445     }
446
447     /**Synchronises (flushes) the file to the file system.
448      *
449      * @param
450      *
451      * @return
452      *
453      * @exception LogException The sync failed
454      *
455      * @see
456      */

457     void fileSync() throws LogException {
458
459         // Synchronization is only done for buffered files which have been updated.
460
// Non-buffered files have every write synchronized with the file system.
461

462         if( bufferUpdateStart != -1 )
463             try {
464                 fhandle.seek(bufferUpdateStart);
465                 fhandle.write(bufferData,bufferUpdateStart,bufferUpdateEnd-bufferUpdateStart);
466                 if (dsyncProp == null)
467                     fd.sync();
468
469                 bufferUpdateStart = -1;
470                 bufferUpdateEnd = -1;
471             } catch (Throwable JavaDoc e) {
472                 throw new LogException(null,LogException.LOG_READ_FAILURE,1);
473             }
474
475     }
476
477     /**Reads a vector of records from the file.
478      *
479      * @param vector The vector to contain the records to be read.
480      *
481      * @return The total number of bytes read.
482      *
483      * @exception LogException The read failed.
484      *
485      * @see
486      */

487     int readVector( byte[][] vector )
488         throws LogException {
489         int bytesRead = 0;
490         for( int i = 0; i < vector.length; i++ )
491             bytesRead += fileRead(vector[i]);
492
493         return bytesRead;
494     }
495
496     /**Allocates more storage for the file.
497      *
498      * @param bytesToClear Number of bytes to allocate for the file.
499      *
500      * @return
501      *
502      * @exception LogException The allocation failed.
503      *
504      * @see
505      */

506
507     void allocFileStorage( int bytesToClear )
508         throws LogException {
509         int numberOfBlocks; // Number of blocks to write
510
int bytesRemaining; // Remaining bytes
511
byte[] singleChar1 = new byte[1];
512         byte[] singleChar2 = new byte[1];
513         long bytesWritten;
514
515
516         if( bytesToClear == 0 ) {
517             return;
518         }
519         /* Don't bother with the compilcated version. Just write out a byte at the
520            appropriate place.
521
522            // Calculate the number of blocks and remaining bytes
523
524            numberOfBlocks = bytesToClear / FILESYSTEM_BLOCKSIZE;
525            bytesRemaining = bytesToClear % FILESYSTEM_BLOCKSIZE;
526
527            // Initialise the single characters to be written to force allocation.
528
529            singleChar1[0] = (byte)0x01;
530            singleChar2[0] = (byte)0xff;
531
532            // For each block, write a single char and seek to the next block
533            // multiple from the current position
534
535            for( int i = 1; i <= numberOfBlocks; i++ )
536            {
537
538            // Write the single char at start of the file block
539
540            fileWrite(singleChar1);
541
542            // Now seek to the end of block
543
544            fileSeek(FILESYSTEM_BLOCKSIZE-2,SEEK_RELATIVE);
545
546            // Write the single char at end of the file block
547
548            fileWrite(singleChar2);
549            }
550
551            // If there are still bytes remaining, get them allocated too.
552
553            if( bytesRemaining > 0 )
554            {
555
556            // Now write out a byte at the beginning and end of the remaining
557            // area to be allocated
558
559            fileWrite(singleChar1);
560            if( --bytesRemaining > 0 )
561            {
562
563            // Seek to end of area and write the last char
564
565            fileSeek(bytesRemaining-1,SEEK_RELATIVE);
566
567            // Now write a byte at the end of the remaining area to be allocated.
568
569            fileWrite(singleChar2);
570            }
571            }
572
573            This is the quick version which only does one write.
574         */

575
576         fileSeek(bytesToClear-1,SEEK_RELATIVE);
577         fileWrite(singleChar2);
578
579         // Move the file pointer back to its original location on the file
580
// by seeking -BytesToClear
581

582         fileSeek(-bytesToClear,SEEK_RELATIVE);
583
584         // If the file is buffered, make sue the space is really allocated.
585

586         if( buffered )
587             fileSync();
588
589     }
590 }
591
Popular Tags