2362N/A * Copyright (c) 1997, 2008, Oracle and/or its affiliates. All rights reserved. 0N/A * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 0N/A * This code is free software; you can redistribute it and/or modify it 0N/A * under the terms of the GNU General Public License version 2 only, as 2362N/A * published by the Free Software Foundation. Oracle designates this 0N/A * particular file as subject to the "Classpath" exception as provided 2362N/A * by Oracle in the LICENSE file that accompanied this code. 0N/A * This code is distributed in the hope that it will be useful, but WITHOUT 0N/A * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 0N/A * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 0N/A * version 2 for more details (a copy is included in the LICENSE file that 0N/A * accompanied this code). 0N/A * You should have received a copy of the GNU General Public License version 0N/A * 2 along with this work; if not, write to the Free Software Foundation, 0N/A * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 2362N/A * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 2362N/A * or visit www.oracle.com if you need additional information or have any 0N/A * This class is a simple implementation of a reliable Log. The 0N/A * client of a ReliableLog must provide a set of callbacks (via a 0N/A * LogHandler) that enables a ReliableLog to read and write 0N/A * checkpoints and log records. This implementation ensures that the 0N/A * current value of the data stored (via a ReliableLog) is recoverable 0N/A * after a system crash. <p> 0N/A * The secondary storage strategy is to record values in files using a 0N/A * representation of the caller's choosing. Two sorts of files are 0N/A * kept: snapshots and logs. At any instant, one snapshot is current. 0N/A * The log consists of a sequence of updates that have occurred since 0N/A * the current snapshot was taken. The current stable state is the 0N/A * value of the snapshot, as modified by the sequence of updates in 0N/A * the log. From time to time, the client of a ReliableLog instructs 0N/A * the package to make a new snapshot and clear the log. A ReliableLog 0N/A * arranges disk writes such that updates are stable (as long as the 0N/A * changes are force-written to disk) and atomic : no update is lost, 0N/A * and each update either is recorded completely in the log or not at 0N/A * all. Making a new snapshot is also atomic. <p> 0N/A * Normal use for maintaining the recoverable store is as follows: The 0N/A * client maintains the relevant data structure in virtual memory. As 0N/A * updates happen to the structure, the client informs the ReliableLog 0N/A * (all it "log") by calling log.update. Periodically, the client 0N/A * calls log.snapshot to provide the current value of the data 0N/A * structure. On restart, the client calls log.recover to obtain the 0N/A * latest snapshot and the following sequences of updates; the client 0N/A * applies the updates to the snapshot to obtain the state that 0N/A * existed before the crash. <p> 0N/A * The current logfile format is: <ol> 0N/A * <li> a format version number (two 4-octet integers, major and 0N/A * minor), followed by 0N/A * <li> a sequence of log records. Each log record contains, in 0N/A * <li> a 4-octet integer representing the length of the following log 0N/A * <li> the log data (variable length). </ol> </ol> <p> 0N/A * @author Ann Wollrath 0N/A // sun.rmi.log.debug=false 0N/A private int version =
0;
// current snapshot and log version 0N/A //private long padBoundary = intBytes; 0N/A * Constructor for the log file. If the system property 0N/A * sun.rmi.log.class is non-null and the class specified by this 0N/A * property a) can be loaded, b) is a subclass of LogFile, and c) has a 0N/A * public two-arg constructor (String, String), ReliableLog uses the 0N/A * constructor to construct the LogFile. 0N/A * Creates a ReliableLog to handle checkpoints and logging in a 0N/A * stable storage directory. 0N/A * @param dirPath path to the stable storage directory 0N/A * @param logCl the closure object containing callbacks for logging and 0N/A * @param pad ignored 0N/A * @exception IOException If a directory creation error has 0N/A * occurred or if initialSnapshot callback raises an exception or 0N/A * if an exception occurs during invocation of the handler's 0N/A * snapshot method or if other IOException occurs. 0N/A //padBoundary = (pad ? diskPageSize : intBytes); 0N/A * Creates a ReliableLog to handle checkpoints and logging in a 0N/A * stable storage directory. 0N/A * @param dirPath path to the stable storage directory 0N/A * @param logCl the closure object containing callbacks for logging and 0N/A * @exception IOException If a directory creation error has 0N/A * occurred or if initialSnapshot callback raises an exception 0N/A /* public methods */ 0N/A * Returns an object which is the value recorded in the current 0N/A * snapshot. This snapshot is recovered by calling the client 0N/A * supplied callback "recover" and then subsequently invoking 0N/A * the "readUpdate" callback to apply any logged updates to the state. 0N/A * @exception IOException If recovery fails due to serious log 0N/A * corruption, read update failure, or if an exception occurs 0N/A * during the recover callback 0N/A * Records this update in the log file (does not force update to disk). 0N/A * The update is recorded by calling the client's "writeUpdate" callback. 0N/A * This method must not be called until this log's recover method has 0N/A * been invoked (and completed). 0N/A * @param value the object representing the update 0N/A * @exception IOException If an exception occurred during a 0N/A * writeUpdate callback or if other I/O error has occurred. 0N/A * Records this update in the log file. The update is recorded by 0N/A * calling the client's writeUpdate callback. This method must not be 0N/A * called until this log's recover method has been invoked 0N/A * @param value the object representing the update 0N/A * @param forceToDisk ignored; changes are always forced to disk 0N/A * @exception IOException If force-write to log failed or an 0N/A * exception occurred during the writeUpdate callback or if other 0N/A * I/O error occurs while updating the log. 0N/A // avoid accessing a null log field. 0N/A "it may have been corrupted or closed");
0N/A * If the entry length field spans a sector boundary, write 0N/A * the high order bit of the entry length, otherwise write zero for 0N/A * Write update, and sync. 0N/A * If length field spans a sector boundary, then 0N/A * the next two steps are required (see 4652922): 0N/A * 1) Write actual length with high order bit set; sync. 0N/A * 2) Then clear high order bit of length; sync. 0N/A * Write actual length; sync. 0N/A * Returns the constructor for the log file if the system property 0N/A * sun.rmi.log.class is non-null and the class specified by the 0N/A * property a) can be loaded, b) is a subclass of LogFile, and c) has a 0N/A * public two-arg constructor (String, String); otherwise returns null. 0N/A * Records this value as the current snapshot by invoking the client 0N/A * supplied "snapshot" callback and then empties the log. 0N/A * @param value the object representing the new snapshot 0N/A * @exception IOException If an exception occurred during the 0N/A * snapshot callback or if other I/O error has occurred during the 0N/A * Close the stable storage directory in an orderly manner. 0N/A * @exception IOException If an I/O error occurs when the log is 0N/A * Returns the size of the snapshot file in bytes; 0N/A * Returns the size of the log file in bytes; 0N/A /* private methods */ 0N/A * Write an int value in single write operation. This method 0N/A * assumes that the caller is synchronized on the log file. 0N/A * @param out output stream 0N/A * @param val int value 0N/A * @throws IOException if any other I/O error occurs 0N/A * Generates a filename prepended with the stable storage directory path. 0N/A * @param name the leaf name of the file 0N/A * Generates a version 0 filename prepended with the stable storage 0N/A * @param name version file name 0N/A * Generates a version filename prepended with the stable storage 0N/A * directory path with the version number as a suffix. 0N/A * @param name version file name 0N/A * @thisversion a version number 0N/A * Increments the directory version number. 0N/A * @param name the name of the file 0N/A * @exception IOException If new version file couldn't be removed 0N/A * Removes the new version number file. 0N/A * @exception IOException If an I/O error has occurred. 0N/A * Removes the snapshot file. 0N/A * @param ver the version to remove 0N/A * @exception IOException If an I/O error has occurred. 0N/A * Removes the log file. 0N/A * @param ver the version to remove 0N/A * @exception IOException If an I/O error has occurred. 0N/A * Opens the log file in read/write mode. If file does not exist, it is 0N/A * @param truncate if true and file exists, file is truncated to zero 0N/A * @exception IOException If an I/O error has occurred. 0N/A * Creates a new log file, truncated and initialized with the format 0N/A * version number preferred by this implementation. 0N/A * <p>Environment: inited, synchronized 0N/A * <p>Precondition: valid: log, log contains nothing useful 0N/A * <p>Postcondition: if successful, log is initialised with the format 0N/A * version number (Preferred{Major,Minor}Version), and logBytes is 0N/A * set to the resulting size of the updatelog, and logEntries is set to 0N/A * zero. Otherwise, log is in an indeterminate state, and logBytes 0N/A * is unchanged, and logEntries is unchanged. 0N/A * @exception IOException If an I/O error has occurred. 0N/A * Writes out version number to file. 0N/A * @param newVersion if true, writes to a new version file 0N/A * @exception IOException If an I/O error has occurred. 0N/A * Creates the initial version file 0N/A * @exception IOException If an I/O error has occurred. 0N/A * Commits (atomically) the new version. 0N/A * @exception IOException If an I/O error has occurred. 0N/A * Reads version number from a file. 0N/A * @param name the name of the version file 0N/A * @return the version 0N/A * @exception IOException If an I/O error has occurred. 0N/A * Sets the version. If version file does not exist, the initial 0N/A * version file is created. 0N/A * @exception IOException If an I/O error has occurred. 0N/A * Applies outstanding updates to the snapshot. 0N/A * @param state the most recent snapshot 0N/A * @exception IOException If serious log corruption is detected or 0N/A * if an exception occurred during a readUpdate callback or if 0N/A * other I/O error has occurred. 0N/A * @return the resulting state of the object after all updates 0N/A /* This is a log which was corrupted and/or cleared (by 0N/A * fsck or equivalent). This is not an error. 0N/A /* A new major version number is a catastrophe (it means 0N/A * that the file format is incompatible with older 0N/A * clients, and we'll only be breaking things by trying to 0N/A * use the log). A new minor version is no big deal for 0N/A * upward compatibility. 0N/A " format, and this implementation " +
0N/A " understands only version " +
0N/A if (
updateLen <=
0) {
/* crashed while writing last log entry */ 0N/A "log.debug: last update incomplete, " +
0N/A // this is a fragile use of available() which relies on the 0N/A // twin facts that BufferedInputStream correctly consults 0N/A // the underlying stream, and that FileInputStream returns 0N/A // the number of bytes remaining in the file (via FIONREAD). 0N/A /* corrupted record at end of log (can happen since we 0N/A * do only one fsync) 0N/A /* reopen log file at end */ 0N/A // avoid accessing a null log field 0N/A "it may have been corrupted or closed");
0N/A * ReliableLog's log file implementation. This implementation 0N/A * is subclassable for testing purposes. 0N/A * Constructs a LogFile and initializes the file descriptor. 0N/A * Invokes sync on the file descriptor for this log file. 0N/A * Returns true if writing 4 bytes starting at the specified file 0N/A * position, would span a 512 byte sector boundary; otherwise returns