src/java.rmi/share/classes/sun/rmi/log/ReliableLog.java
author rehn
Fri, 29 Nov 2019 12:09:25 +0100
changeset 59325 3636bab5e81e
parent 47216 71c04702a3d5
permissions -rw-r--r--
8234086: VM operation can be simplified Reviewed-by: kbarrett, dholmes, dcubed
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
     1
/*
14342
8435a30053c1 7197491: update copyright year to match last edit in jdk8 jdk repository
alanb
parents: 12040
diff changeset
     2
 * Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved.
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
     3
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
90ce3da70b43 Initial load
duke
parents:
diff changeset
     4
 *
90ce3da70b43 Initial load
duke
parents:
diff changeset
     5
 * This code is free software; you can redistribute it and/or modify it
90ce3da70b43 Initial load
duke
parents:
diff changeset
     6
 * under the terms of the GNU General Public License version 2 only, as
5506
202f599c92aa 6943119: Rebrand source copyright notices
ohair
parents: 715
diff changeset
     7
 * published by the Free Software Foundation.  Oracle designates this
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
     8
 * particular file as subject to the "Classpath" exception as provided
5506
202f599c92aa 6943119: Rebrand source copyright notices
ohair
parents: 715
diff changeset
     9
 * by Oracle in the LICENSE file that accompanied this code.
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
    10
 *
90ce3da70b43 Initial load
duke
parents:
diff changeset
    11
 * This code is distributed in the hope that it will be useful, but WITHOUT
90ce3da70b43 Initial load
duke
parents:
diff changeset
    12
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
90ce3da70b43 Initial load
duke
parents:
diff changeset
    13
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
90ce3da70b43 Initial load
duke
parents:
diff changeset
    14
 * version 2 for more details (a copy is included in the LICENSE file that
90ce3da70b43 Initial load
duke
parents:
diff changeset
    15
 * accompanied this code).
90ce3da70b43 Initial load
duke
parents:
diff changeset
    16
 *
90ce3da70b43 Initial load
duke
parents:
diff changeset
    17
 * You should have received a copy of the GNU General Public License version
90ce3da70b43 Initial load
duke
parents:
diff changeset
    18
 * 2 along with this work; if not, write to the Free Software Foundation,
90ce3da70b43 Initial load
duke
parents:
diff changeset
    19
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
90ce3da70b43 Initial load
duke
parents:
diff changeset
    20
 *
5506
202f599c92aa 6943119: Rebrand source copyright notices
ohair
parents: 715
diff changeset
    21
 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
202f599c92aa 6943119: Rebrand source copyright notices
ohair
parents: 715
diff changeset
    22
 * or visit www.oracle.com if you need additional information or have any
202f599c92aa 6943119: Rebrand source copyright notices
ohair
parents: 715
diff changeset
    23
 * questions.
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
    24
 */
90ce3da70b43 Initial load
duke
parents:
diff changeset
    25
90ce3da70b43 Initial load
duke
parents:
diff changeset
    26
package sun.rmi.log;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    27
90ce3da70b43 Initial load
duke
parents:
diff changeset
    28
import java.io.*;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    29
import java.lang.reflect.Constructor;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    30
import java.rmi.server.RMIClassLoader;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    31
import java.security.AccessController;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    32
import java.security.PrivilegedAction;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    33
90ce3da70b43 Initial load
duke
parents:
diff changeset
    34
/**
90ce3da70b43 Initial load
duke
parents:
diff changeset
    35
 * This class is a simple implementation of a reliable Log.  The
90ce3da70b43 Initial load
duke
parents:
diff changeset
    36
 * client of a ReliableLog must provide a set of callbacks (via a
90ce3da70b43 Initial load
duke
parents:
diff changeset
    37
 * LogHandler) that enables a ReliableLog to read and write
90ce3da70b43 Initial load
duke
parents:
diff changeset
    38
 * checkpoints and log records.  This implementation ensures that the
90ce3da70b43 Initial load
duke
parents:
diff changeset
    39
 * current value of the data stored (via a ReliableLog) is recoverable
90ce3da70b43 Initial load
duke
parents:
diff changeset
    40
 * after a system crash. <p>
90ce3da70b43 Initial load
duke
parents:
diff changeset
    41
 *
90ce3da70b43 Initial load
duke
parents:
diff changeset
    42
 * The secondary storage strategy is to record values in files using a
90ce3da70b43 Initial load
duke
parents:
diff changeset
    43
 * representation of the caller's choosing.  Two sorts of files are
90ce3da70b43 Initial load
duke
parents:
diff changeset
    44
 * kept: snapshots and logs.  At any instant, one snapshot is current.
90ce3da70b43 Initial load
duke
parents:
diff changeset
    45
 * The log consists of a sequence of updates that have occurred since
90ce3da70b43 Initial load
duke
parents:
diff changeset
    46
 * the current snapshot was taken.  The current stable state is the
90ce3da70b43 Initial load
duke
parents:
diff changeset
    47
 * value of the snapshot, as modified by the sequence of updates in
90ce3da70b43 Initial load
duke
parents:
diff changeset
    48
 * the log.  From time to time, the client of a ReliableLog instructs
90ce3da70b43 Initial load
duke
parents:
diff changeset
    49
 * the package to make a new snapshot and clear the log.  A ReliableLog
90ce3da70b43 Initial load
duke
parents:
diff changeset
    50
 * arranges disk writes such that updates are stable (as long as the
90ce3da70b43 Initial load
duke
parents:
diff changeset
    51
 * changes are force-written to disk) and atomic : no update is lost,
90ce3da70b43 Initial load
duke
parents:
diff changeset
    52
 * and each update either is recorded completely in the log or not at
90ce3da70b43 Initial load
duke
parents:
diff changeset
    53
 * all.  Making a new snapshot is also atomic. <p>
90ce3da70b43 Initial load
duke
parents:
diff changeset
    54
 *
90ce3da70b43 Initial load
duke
parents:
diff changeset
    55
 * Normal use for maintaining the recoverable store is as follows: The
90ce3da70b43 Initial load
duke
parents:
diff changeset
    56
 * client maintains the relevant data structure in virtual memory.  As
90ce3da70b43 Initial load
duke
parents:
diff changeset
    57
 * updates happen to the structure, the client informs the ReliableLog
90ce3da70b43 Initial load
duke
parents:
diff changeset
    58
 * (all it "log") by calling log.update.  Periodically, the client
90ce3da70b43 Initial load
duke
parents:
diff changeset
    59
 * calls log.snapshot to provide the current value of the data
90ce3da70b43 Initial load
duke
parents:
diff changeset
    60
 * structure.  On restart, the client calls log.recover to obtain the
90ce3da70b43 Initial load
duke
parents:
diff changeset
    61
 * latest snapshot and the following sequences of updates; the client
90ce3da70b43 Initial load
duke
parents:
diff changeset
    62
 * applies the updates to the snapshot to obtain the state that
90ce3da70b43 Initial load
duke
parents:
diff changeset
    63
 * existed before the crash. <p>
90ce3da70b43 Initial load
duke
parents:
diff changeset
    64
 *
90ce3da70b43 Initial load
duke
parents:
diff changeset
    65
 * The current logfile format is: <ol>
90ce3da70b43 Initial load
duke
parents:
diff changeset
    66
 * <li> a format version number (two 4-octet integers, major and
90ce3da70b43 Initial load
duke
parents:
diff changeset
    67
 * minor), followed by
90ce3da70b43 Initial load
duke
parents:
diff changeset
    68
 * <li> a sequence of log records.  Each log record contains, in
90ce3da70b43 Initial load
duke
parents:
diff changeset
    69
 * order, <ol>
90ce3da70b43 Initial load
duke
parents:
diff changeset
    70
 * <li> a 4-octet integer representing the length of the following log
90ce3da70b43 Initial load
duke
parents:
diff changeset
    71
 * data,
90ce3da70b43 Initial load
duke
parents:
diff changeset
    72
 * <li> the log data (variable length). </ol> </ol> <p>
90ce3da70b43 Initial load
duke
parents:
diff changeset
    73
 *
90ce3da70b43 Initial load
duke
parents:
diff changeset
    74
 * @see LogHandler
90ce3da70b43 Initial load
duke
parents:
diff changeset
    75
 *
90ce3da70b43 Initial load
duke
parents:
diff changeset
    76
 * @author Ann Wollrath
90ce3da70b43 Initial load
duke
parents:
diff changeset
    77
 *
90ce3da70b43 Initial load
duke
parents:
diff changeset
    78
 */
90ce3da70b43 Initial load
duke
parents:
diff changeset
    79
public class ReliableLog {
90ce3da70b43 Initial load
duke
parents:
diff changeset
    80
90ce3da70b43 Initial load
duke
parents:
diff changeset
    81
    public final static int PreferredMajorVersion = 0;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    82
    public final static int PreferredMinorVersion = 2;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    83
90ce3da70b43 Initial load
duke
parents:
diff changeset
    84
    // sun.rmi.log.debug=false
90ce3da70b43 Initial load
duke
parents:
diff changeset
    85
    private boolean Debug = false;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    86
90ce3da70b43 Initial load
duke
parents:
diff changeset
    87
    private static String snapshotPrefix = "Snapshot.";
90ce3da70b43 Initial load
duke
parents:
diff changeset
    88
    private static String logfilePrefix = "Logfile.";
90ce3da70b43 Initial load
duke
parents:
diff changeset
    89
    private static String versionFile = "Version_Number";
90ce3da70b43 Initial load
duke
parents:
diff changeset
    90
    private static String newVersionFile = "New_Version_Number";
90ce3da70b43 Initial load
duke
parents:
diff changeset
    91
    private static int    intBytes = 4;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    92
    private static long   diskPageSize = 512;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    93
90ce3da70b43 Initial load
duke
parents:
diff changeset
    94
    private File dir;                   // base directory
90ce3da70b43 Initial load
duke
parents:
diff changeset
    95
    private int version = 0;            // current snapshot and log version
90ce3da70b43 Initial load
duke
parents:
diff changeset
    96
    private String logName = null;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    97
    private LogFile log = null;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    98
    private long snapshotBytes = 0;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    99
    private long logBytes = 0;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   100
    private int logEntries = 0;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   101
    private long lastSnapshot = 0;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   102
    private long lastLog = 0;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   103
    //private long padBoundary = intBytes;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   104
    private LogHandler handler;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   105
    private final byte[] intBuf = new byte[4];
90ce3da70b43 Initial load
duke
parents:
diff changeset
   106
90ce3da70b43 Initial load
duke
parents:
diff changeset
   107
    // format version numbers read from/written to this.log
90ce3da70b43 Initial load
duke
parents:
diff changeset
   108
    private int majorFormatVersion = 0;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   109
    private int minorFormatVersion = 0;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   110
90ce3da70b43 Initial load
duke
parents:
diff changeset
   111
90ce3da70b43 Initial load
duke
parents:
diff changeset
   112
    /**
90ce3da70b43 Initial load
duke
parents:
diff changeset
   113
     * Constructor for the log file.  If the system property
90ce3da70b43 Initial load
duke
parents:
diff changeset
   114
     * sun.rmi.log.class is non-null and the class specified by this
90ce3da70b43 Initial load
duke
parents:
diff changeset
   115
     * property a) can be loaded, b) is a subclass of LogFile, and c) has a
90ce3da70b43 Initial load
duke
parents:
diff changeset
   116
     * public two-arg constructor (String, String), ReliableLog uses the
90ce3da70b43 Initial load
duke
parents:
diff changeset
   117
     * constructor to construct the LogFile.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   118
     **/
90ce3da70b43 Initial load
duke
parents:
diff changeset
   119
    private static final Constructor<? extends LogFile>
90ce3da70b43 Initial load
duke
parents:
diff changeset
   120
        logClassConstructor = getLogClassConstructor();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   121
90ce3da70b43 Initial load
duke
parents:
diff changeset
   122
    /**
90ce3da70b43 Initial load
duke
parents:
diff changeset
   123
     * Creates a ReliableLog to handle checkpoints and logging in a
90ce3da70b43 Initial load
duke
parents:
diff changeset
   124
     * stable storage directory.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   125
     *
90ce3da70b43 Initial load
duke
parents:
diff changeset
   126
     * @param dirPath path to the stable storage directory
30655
d83f50188ca9 8080422: some docs cleanup for core libs
avstepan
parents: 25859
diff changeset
   127
     * @param handler the closure object containing callbacks for logging and
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   128
     * recovery
90ce3da70b43 Initial load
duke
parents:
diff changeset
   129
     * @param pad ignored
90ce3da70b43 Initial load
duke
parents:
diff changeset
   130
     * @exception IOException If a directory creation error has
90ce3da70b43 Initial load
duke
parents:
diff changeset
   131
     * occurred or if initialSnapshot callback raises an exception or
90ce3da70b43 Initial load
duke
parents:
diff changeset
   132
     * if an exception occurs during invocation of the handler's
90ce3da70b43 Initial load
duke
parents:
diff changeset
   133
     * snapshot method or if other IOException occurs.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   134
     */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   135
    public ReliableLog(String dirPath,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   136
                     LogHandler handler,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   137
                     boolean pad)
90ce3da70b43 Initial load
duke
parents:
diff changeset
   138
        throws IOException
90ce3da70b43 Initial load
duke
parents:
diff changeset
   139
    {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   140
        super();
51
6fe31bc95bbc 6600143: Remove another 450 unnecessary casts
martin
parents: 2
diff changeset
   141
        this.Debug = AccessController.doPrivileged(
23333
b0af2c7c8c91 8035808: Eliminate dependency to GetPropertyAction and other sun.security.action convenient classes
mchung
parents: 14342
diff changeset
   142
            (PrivilegedAction<Boolean>) () -> Boolean.getBoolean("sun.rmi.log.debug"));
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   143
        dir = new File(dirPath);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   144
        if (!(dir.exists() && dir.isDirectory())) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   145
            // create directory
90ce3da70b43 Initial load
duke
parents:
diff changeset
   146
            if (!dir.mkdir()) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   147
                throw new IOException("could not create directory for log: " +
90ce3da70b43 Initial load
duke
parents:
diff changeset
   148
                                      dirPath);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   149
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   150
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   151
        //padBoundary = (pad ? diskPageSize : intBytes);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   152
        this.handler = handler;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   153
        lastSnapshot = 0;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   154
        lastLog = 0;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   155
        getVersion();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   156
        if (version == 0) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   157
            try {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   158
                snapshot(handler.initialSnapshot());
90ce3da70b43 Initial load
duke
parents:
diff changeset
   159
            } catch (IOException e) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   160
                throw e;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   161
            } catch (Exception e) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   162
                throw new IOException("initial snapshot failed with " +
90ce3da70b43 Initial load
duke
parents:
diff changeset
   163
                                      "exception: " + e);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   164
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   165
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   166
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   167
90ce3da70b43 Initial load
duke
parents:
diff changeset
   168
    /**
90ce3da70b43 Initial load
duke
parents:
diff changeset
   169
     * Creates a ReliableLog to handle checkpoints and logging in a
90ce3da70b43 Initial load
duke
parents:
diff changeset
   170
     * stable storage directory.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   171
     *
90ce3da70b43 Initial load
duke
parents:
diff changeset
   172
     * @param dirPath path to the stable storage directory
30655
d83f50188ca9 8080422: some docs cleanup for core libs
avstepan
parents: 25859
diff changeset
   173
     * @param handler the closure object containing callbacks for logging and
d83f50188ca9 8080422: some docs cleanup for core libs
avstepan
parents: 25859
diff changeset
   174
     *        recovery
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   175
     * @exception IOException If a directory creation error has
90ce3da70b43 Initial load
duke
parents:
diff changeset
   176
     * occurred or if initialSnapshot callback raises an exception
90ce3da70b43 Initial load
duke
parents:
diff changeset
   177
     */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   178
    public ReliableLog(String dirPath,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   179
                     LogHandler handler)
90ce3da70b43 Initial load
duke
parents:
diff changeset
   180
        throws IOException
90ce3da70b43 Initial load
duke
parents:
diff changeset
   181
    {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   182
        this(dirPath, handler, false);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   183
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   184
90ce3da70b43 Initial load
duke
parents:
diff changeset
   185
    /* public methods */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   186
90ce3da70b43 Initial load
duke
parents:
diff changeset
   187
    /**
90ce3da70b43 Initial load
duke
parents:
diff changeset
   188
     * Returns an object which is the value recorded in the current
90ce3da70b43 Initial load
duke
parents:
diff changeset
   189
     * snapshot.  This snapshot is recovered by calling the client
90ce3da70b43 Initial load
duke
parents:
diff changeset
   190
     * supplied callback "recover" and then subsequently invoking
90ce3da70b43 Initial load
duke
parents:
diff changeset
   191
     * the "readUpdate" callback to apply any logged updates to the state.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   192
     *
90ce3da70b43 Initial load
duke
parents:
diff changeset
   193
     * @exception IOException If recovery fails due to serious log
90ce3da70b43 Initial load
duke
parents:
diff changeset
   194
     * corruption, read update failure, or if an exception occurs
90ce3da70b43 Initial load
duke
parents:
diff changeset
   195
     * during the recover callback
90ce3da70b43 Initial load
duke
parents:
diff changeset
   196
     */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   197
    public synchronized Object recover()
90ce3da70b43 Initial load
duke
parents:
diff changeset
   198
        throws IOException
90ce3da70b43 Initial load
duke
parents:
diff changeset
   199
    {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   200
        if (Debug)
90ce3da70b43 Initial load
duke
parents:
diff changeset
   201
            System.err.println("log.debug: recover()");
90ce3da70b43 Initial load
duke
parents:
diff changeset
   202
90ce3da70b43 Initial load
duke
parents:
diff changeset
   203
        if (version == 0)
90ce3da70b43 Initial load
duke
parents:
diff changeset
   204
            return null;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   205
90ce3da70b43 Initial load
duke
parents:
diff changeset
   206
        Object snapshot;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   207
        String fname = versionName(snapshotPrefix);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   208
        File snapshotFile = new File(fname);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   209
        InputStream in =
90ce3da70b43 Initial load
duke
parents:
diff changeset
   210
                new BufferedInputStream(new FileInputStream(snapshotFile));
90ce3da70b43 Initial load
duke
parents:
diff changeset
   211
90ce3da70b43 Initial load
duke
parents:
diff changeset
   212
        if (Debug)
90ce3da70b43 Initial load
duke
parents:
diff changeset
   213
            System.err.println("log.debug: recovering from " + fname);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   214
90ce3da70b43 Initial load
duke
parents:
diff changeset
   215
        try {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   216
            try {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   217
                snapshot = handler.recover(in);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   218
90ce3da70b43 Initial load
duke
parents:
diff changeset
   219
            } catch (IOException e) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   220
                throw e;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   221
            } catch (Exception e) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   222
                if (Debug)
90ce3da70b43 Initial load
duke
parents:
diff changeset
   223
                    System.err.println("log.debug: recovery failed: " + e);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   224
                throw new IOException("log recover failed with " +
90ce3da70b43 Initial load
duke
parents:
diff changeset
   225
                                      "exception: " + e);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   226
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   227
            snapshotBytes = snapshotFile.length();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   228
        } finally {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   229
            in.close();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   230
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   231
90ce3da70b43 Initial load
duke
parents:
diff changeset
   232
        return recoverUpdates(snapshot);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   233
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   234
90ce3da70b43 Initial load
duke
parents:
diff changeset
   235
    /**
90ce3da70b43 Initial load
duke
parents:
diff changeset
   236
     * Records this update in the log file (does not force update to disk).
90ce3da70b43 Initial load
duke
parents:
diff changeset
   237
     * The update is recorded by calling the client's "writeUpdate" callback.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   238
     * This method must not be called until this log's recover method has
90ce3da70b43 Initial load
duke
parents:
diff changeset
   239
     * been invoked (and completed).
90ce3da70b43 Initial load
duke
parents:
diff changeset
   240
     *
90ce3da70b43 Initial load
duke
parents:
diff changeset
   241
     * @param value the object representing the update
90ce3da70b43 Initial load
duke
parents:
diff changeset
   242
     * @exception IOException If an exception occurred during a
90ce3da70b43 Initial load
duke
parents:
diff changeset
   243
     * writeUpdate callback or if other I/O error has occurred.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   244
     */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   245
    public synchronized void update(Object value) throws IOException {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   246
        update(value, true);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   247
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   248
90ce3da70b43 Initial load
duke
parents:
diff changeset
   249
    /**
90ce3da70b43 Initial load
duke
parents:
diff changeset
   250
     * Records this update in the log file.  The update is recorded by
90ce3da70b43 Initial load
duke
parents:
diff changeset
   251
     * calling the client's writeUpdate callback.  This method must not be
90ce3da70b43 Initial load
duke
parents:
diff changeset
   252
     * called until this log's recover method has been invoked
90ce3da70b43 Initial load
duke
parents:
diff changeset
   253
     * (and completed).
90ce3da70b43 Initial load
duke
parents:
diff changeset
   254
     *
90ce3da70b43 Initial load
duke
parents:
diff changeset
   255
     * @param value the object representing the update
90ce3da70b43 Initial load
duke
parents:
diff changeset
   256
     * @param forceToDisk ignored; changes are always forced to disk
90ce3da70b43 Initial load
duke
parents:
diff changeset
   257
     * @exception IOException If force-write to log failed or an
90ce3da70b43 Initial load
duke
parents:
diff changeset
   258
     * exception occurred during the writeUpdate callback or if other
90ce3da70b43 Initial load
duke
parents:
diff changeset
   259
     * I/O error occurs while updating the log.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   260
     */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   261
    public synchronized void update(Object value, boolean forceToDisk)
90ce3da70b43 Initial load
duke
parents:
diff changeset
   262
        throws IOException
90ce3da70b43 Initial load
duke
parents:
diff changeset
   263
    {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   264
        // avoid accessing a null log field.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   265
        if (log == null) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   266
            throw new IOException("log is inaccessible, " +
90ce3da70b43 Initial load
duke
parents:
diff changeset
   267
                "it may have been corrupted or closed");
90ce3da70b43 Initial load
duke
parents:
diff changeset
   268
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   269
90ce3da70b43 Initial load
duke
parents:
diff changeset
   270
        /*
90ce3da70b43 Initial load
duke
parents:
diff changeset
   271
         * If the entry length field spans a sector boundary, write
90ce3da70b43 Initial load
duke
parents:
diff changeset
   272
         * the high order bit of the entry length, otherwise write zero for
90ce3da70b43 Initial load
duke
parents:
diff changeset
   273
         * the entry length.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   274
         */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   275
        long entryStart = log.getFilePointer();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   276
        boolean spansBoundary = log.checkSpansBoundary(entryStart);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   277
        writeInt(log, spansBoundary? 1<<31 : 0);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   278
90ce3da70b43 Initial load
duke
parents:
diff changeset
   279
        /*
90ce3da70b43 Initial load
duke
parents:
diff changeset
   280
         * Write update, and sync.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   281
         */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   282
        try {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   283
            handler.writeUpdate(new LogOutputStream(log), value);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   284
        } catch (IOException e) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   285
            throw e;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   286
        } catch (Exception e) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   287
            throw (IOException)
90ce3da70b43 Initial load
duke
parents:
diff changeset
   288
                new IOException("write update failed").initCause(e);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   289
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   290
        log.sync();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   291
90ce3da70b43 Initial load
duke
parents:
diff changeset
   292
        long entryEnd = log.getFilePointer();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   293
        int updateLen = (int) ((entryEnd - entryStart) - intBytes);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   294
        log.seek(entryStart);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   295
90ce3da70b43 Initial load
duke
parents:
diff changeset
   296
        if (spansBoundary) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   297
            /*
90ce3da70b43 Initial load
duke
parents:
diff changeset
   298
             * If length field spans a sector boundary, then
90ce3da70b43 Initial load
duke
parents:
diff changeset
   299
             * the next two steps are required (see 4652922):
90ce3da70b43 Initial load
duke
parents:
diff changeset
   300
             *
90ce3da70b43 Initial load
duke
parents:
diff changeset
   301
             * 1) Write actual length with high order bit set; sync.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   302
             * 2) Then clear high order bit of length; sync.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   303
             */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   304
            writeInt(log, updateLen | 1<<31);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   305
            log.sync();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   306
90ce3da70b43 Initial load
duke
parents:
diff changeset
   307
            log.seek(entryStart);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   308
            log.writeByte(updateLen >> 24);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   309
            log.sync();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   310
90ce3da70b43 Initial load
duke
parents:
diff changeset
   311
        } else {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   312
            /*
90ce3da70b43 Initial load
duke
parents:
diff changeset
   313
             * Write actual length; sync.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   314
             */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   315
            writeInt(log, updateLen);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   316
            log.sync();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   317
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   318
90ce3da70b43 Initial load
duke
parents:
diff changeset
   319
        log.seek(entryEnd);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   320
        logBytes = entryEnd;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   321
        lastLog = System.currentTimeMillis();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   322
        logEntries++;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   323
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   324
90ce3da70b43 Initial load
duke
parents:
diff changeset
   325
    /**
90ce3da70b43 Initial load
duke
parents:
diff changeset
   326
     * Returns the constructor for the log file if the system property
90ce3da70b43 Initial load
duke
parents:
diff changeset
   327
     * sun.rmi.log.class is non-null and the class specified by the
90ce3da70b43 Initial load
duke
parents:
diff changeset
   328
     * property a) can be loaded, b) is a subclass of LogFile, and c) has a
90ce3da70b43 Initial load
duke
parents:
diff changeset
   329
     * public two-arg constructor (String, String); otherwise returns null.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   330
     **/
90ce3da70b43 Initial load
duke
parents:
diff changeset
   331
    private static Constructor<? extends LogFile>
90ce3da70b43 Initial load
duke
parents:
diff changeset
   332
        getLogClassConstructor() {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   333
51
6fe31bc95bbc 6600143: Remove another 450 unnecessary casts
martin
parents: 2
diff changeset
   334
        String logClassName = AccessController.doPrivileged(
23333
b0af2c7c8c91 8035808: Eliminate dependency to GetPropertyAction and other sun.security.action convenient classes
mchung
parents: 14342
diff changeset
   335
            (PrivilegedAction<String>) () -> System.getProperty("sun.rmi.log.class"));
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   336
        if (logClassName != null) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   337
            try {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   338
                ClassLoader loader =
90ce3da70b43 Initial load
duke
parents:
diff changeset
   339
                    AccessController.doPrivileged(
90ce3da70b43 Initial load
duke
parents:
diff changeset
   340
                        new PrivilegedAction<ClassLoader>() {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   341
                            public ClassLoader run() {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   342
                               return ClassLoader.getSystemClassLoader();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   343
                            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   344
                        });
12040
558b0e0d5910 7146763: Warnings cleanup in the sun.rmi and related packages
khazra
parents: 9502
diff changeset
   345
                Class<? extends LogFile> cl =
558b0e0d5910 7146763: Warnings cleanup in the sun.rmi and related packages
khazra
parents: 9502
diff changeset
   346
                    loader.loadClass(logClassName).asSubclass(LogFile.class);
558b0e0d5910 7146763: Warnings cleanup in the sun.rmi and related packages
khazra
parents: 9502
diff changeset
   347
                return cl.getConstructor(String.class, String.class);
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   348
            } catch (Exception e) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   349
                System.err.println("Exception occurred:");
90ce3da70b43 Initial load
duke
parents:
diff changeset
   350
                e.printStackTrace();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   351
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   352
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   353
        return null;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   354
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   355
90ce3da70b43 Initial load
duke
parents:
diff changeset
   356
    /**
90ce3da70b43 Initial load
duke
parents:
diff changeset
   357
     * Records this value as the current snapshot by invoking the client
90ce3da70b43 Initial load
duke
parents:
diff changeset
   358
     * supplied "snapshot" callback and then empties the log.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   359
     *
90ce3da70b43 Initial load
duke
parents:
diff changeset
   360
     * @param value the object representing the new snapshot
90ce3da70b43 Initial load
duke
parents:
diff changeset
   361
     * @exception IOException If an exception occurred during the
90ce3da70b43 Initial load
duke
parents:
diff changeset
   362
     * snapshot callback or if other I/O error has occurred during the
90ce3da70b43 Initial load
duke
parents:
diff changeset
   363
     * snapshot process
90ce3da70b43 Initial load
duke
parents:
diff changeset
   364
     */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   365
    public synchronized void snapshot(Object value)
90ce3da70b43 Initial load
duke
parents:
diff changeset
   366
        throws IOException
90ce3da70b43 Initial load
duke
parents:
diff changeset
   367
    {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   368
        int oldVersion = version;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   369
        incrVersion();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   370
90ce3da70b43 Initial load
duke
parents:
diff changeset
   371
        String fname = versionName(snapshotPrefix);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   372
        File snapshotFile = new File(fname);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   373
        FileOutputStream out = new FileOutputStream(snapshotFile);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   374
        try {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   375
            try {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   376
                handler.snapshot(out, value);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   377
            } catch (IOException e) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   378
                throw e;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   379
            } catch (Exception e) {
9502
de183d393b77 6896297: (rmi) fix ConcurrentModificationException causing TCK failure
smarks
parents: 5506
diff changeset
   380
                throw new IOException("snapshot failed", e);
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   381
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   382
            lastSnapshot = System.currentTimeMillis();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   383
        } finally {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   384
            out.close();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   385
            snapshotBytes = snapshotFile.length();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   386
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   387
90ce3da70b43 Initial load
duke
parents:
diff changeset
   388
        openLogFile(true);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   389
        writeVersionFile(true);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   390
        commitToNewVersion();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   391
        deleteSnapshot(oldVersion);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   392
        deleteLogFile(oldVersion);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   393
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   394
90ce3da70b43 Initial load
duke
parents:
diff changeset
   395
    /**
90ce3da70b43 Initial load
duke
parents:
diff changeset
   396
     * Close the stable storage directory in an orderly manner.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   397
     *
90ce3da70b43 Initial load
duke
parents:
diff changeset
   398
     * @exception IOException If an I/O error occurs when the log is
90ce3da70b43 Initial load
duke
parents:
diff changeset
   399
     * closed
90ce3da70b43 Initial load
duke
parents:
diff changeset
   400
     */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   401
    public synchronized void close() throws IOException {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   402
        if (log == null) return;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   403
        try {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   404
            log.close();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   405
        } finally {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   406
            log = null;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   407
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   408
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   409
90ce3da70b43 Initial load
duke
parents:
diff changeset
   410
    /**
90ce3da70b43 Initial load
duke
parents:
diff changeset
   411
     * Returns the size of the snapshot file in bytes;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   412
     */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   413
    public long snapshotSize() {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   414
        return snapshotBytes;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   415
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   416
90ce3da70b43 Initial load
duke
parents:
diff changeset
   417
    /**
90ce3da70b43 Initial load
duke
parents:
diff changeset
   418
     * Returns the size of the log file in bytes;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   419
     */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   420
    public long logSize() {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   421
        return logBytes;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   422
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   423
90ce3da70b43 Initial load
duke
parents:
diff changeset
   424
    /* private methods */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   425
90ce3da70b43 Initial load
duke
parents:
diff changeset
   426
    /**
90ce3da70b43 Initial load
duke
parents:
diff changeset
   427
     * Write an int value in single write operation.  This method
90ce3da70b43 Initial load
duke
parents:
diff changeset
   428
     * assumes that the caller is synchronized on the log file.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   429
     *
90ce3da70b43 Initial load
duke
parents:
diff changeset
   430
     * @param out output stream
90ce3da70b43 Initial load
duke
parents:
diff changeset
   431
     * @param val int value
90ce3da70b43 Initial load
duke
parents:
diff changeset
   432
     * @throws IOException if any other I/O error occurs
90ce3da70b43 Initial load
duke
parents:
diff changeset
   433
     */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   434
    private void writeInt(DataOutput out, int val)
90ce3da70b43 Initial load
duke
parents:
diff changeset
   435
        throws IOException
90ce3da70b43 Initial load
duke
parents:
diff changeset
   436
    {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   437
        intBuf[0] = (byte) (val >> 24);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   438
        intBuf[1] = (byte) (val >> 16);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   439
        intBuf[2] = (byte) (val >> 8);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   440
        intBuf[3] = (byte) val;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   441
        out.write(intBuf);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   442
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   443
90ce3da70b43 Initial load
duke
parents:
diff changeset
   444
    /**
90ce3da70b43 Initial load
duke
parents:
diff changeset
   445
     * Generates a filename prepended with the stable storage directory path.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   446
     *
90ce3da70b43 Initial load
duke
parents:
diff changeset
   447
     * @param name the leaf name of the file
90ce3da70b43 Initial load
duke
parents:
diff changeset
   448
     */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   449
    private String fName(String name) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   450
        return dir.getPath() + File.separator + name;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   451
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   452
90ce3da70b43 Initial load
duke
parents:
diff changeset
   453
    /**
90ce3da70b43 Initial load
duke
parents:
diff changeset
   454
     * Generates a version 0 filename prepended with the stable storage
90ce3da70b43 Initial load
duke
parents:
diff changeset
   455
     * directory path
90ce3da70b43 Initial load
duke
parents:
diff changeset
   456
     *
90ce3da70b43 Initial load
duke
parents:
diff changeset
   457
     * @param name version file name
90ce3da70b43 Initial load
duke
parents:
diff changeset
   458
     */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   459
    private String versionName(String name) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   460
        return versionName(name, 0);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   461
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   462
90ce3da70b43 Initial load
duke
parents:
diff changeset
   463
    /**
90ce3da70b43 Initial load
duke
parents:
diff changeset
   464
     * Generates a version filename prepended with the stable storage
90ce3da70b43 Initial load
duke
parents:
diff changeset
   465
     * directory path with the version number as a suffix.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   466
     *
90ce3da70b43 Initial load
duke
parents:
diff changeset
   467
     * @param name version file name
90ce3da70b43 Initial load
duke
parents:
diff changeset
   468
     * @thisversion a version number
90ce3da70b43 Initial load
duke
parents:
diff changeset
   469
     */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   470
    private String versionName(String prefix, int ver) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   471
        ver = (ver == 0) ? version : ver;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   472
        return fName(prefix) + String.valueOf(ver);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   473
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   474
90ce3da70b43 Initial load
duke
parents:
diff changeset
   475
    /**
90ce3da70b43 Initial load
duke
parents:
diff changeset
   476
     * Increments the directory version number.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   477
     */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   478
    private void incrVersion() {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   479
        do { version++; } while (version==0);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   480
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   481
90ce3da70b43 Initial load
duke
parents:
diff changeset
   482
    /**
90ce3da70b43 Initial load
duke
parents:
diff changeset
   483
     * Delete a file.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   484
     *
90ce3da70b43 Initial load
duke
parents:
diff changeset
   485
     * @param name the name of the file
90ce3da70b43 Initial load
duke
parents:
diff changeset
   486
     * @exception IOException If new version file couldn't be removed
90ce3da70b43 Initial load
duke
parents:
diff changeset
   487
     */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   488
    private void deleteFile(String name) throws IOException {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   489
90ce3da70b43 Initial load
duke
parents:
diff changeset
   490
        File f = new File(name);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   491
        if (!f.delete())
90ce3da70b43 Initial load
duke
parents:
diff changeset
   492
            throw new IOException("couldn't remove file: " + name);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   493
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   494
90ce3da70b43 Initial load
duke
parents:
diff changeset
   495
    /**
90ce3da70b43 Initial load
duke
parents:
diff changeset
   496
     * Removes the new version number file.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   497
     *
90ce3da70b43 Initial load
duke
parents:
diff changeset
   498
     * @exception IOException If an I/O error has occurred.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   499
     */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   500
    private void deleteNewVersionFile() throws IOException {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   501
        deleteFile(fName(newVersionFile));
90ce3da70b43 Initial load
duke
parents:
diff changeset
   502
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   503
90ce3da70b43 Initial load
duke
parents:
diff changeset
   504
    /**
90ce3da70b43 Initial load
duke
parents:
diff changeset
   505
     * Removes the snapshot file.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   506
     *
90ce3da70b43 Initial load
duke
parents:
diff changeset
   507
     * @param ver the version to remove
90ce3da70b43 Initial load
duke
parents:
diff changeset
   508
     * @exception IOException If an I/O error has occurred.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   509
     */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   510
    private void deleteSnapshot(int ver) throws IOException {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   511
        if (ver == 0) return;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   512
        deleteFile(versionName(snapshotPrefix, ver));
90ce3da70b43 Initial load
duke
parents:
diff changeset
   513
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   514
90ce3da70b43 Initial load
duke
parents:
diff changeset
   515
    /**
90ce3da70b43 Initial load
duke
parents:
diff changeset
   516
     * Removes the log file.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   517
     *
90ce3da70b43 Initial load
duke
parents:
diff changeset
   518
     * @param ver the version to remove
90ce3da70b43 Initial load
duke
parents:
diff changeset
   519
     * @exception IOException If an I/O error has occurred.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   520
     */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   521
    private void deleteLogFile(int ver) throws IOException {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   522
        if (ver == 0) return;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   523
        deleteFile(versionName(logfilePrefix, ver));
90ce3da70b43 Initial load
duke
parents:
diff changeset
   524
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   525
90ce3da70b43 Initial load
duke
parents:
diff changeset
   526
    /**
90ce3da70b43 Initial load
duke
parents:
diff changeset
   527
     * Opens the log file in read/write mode.  If file does not exist, it is
90ce3da70b43 Initial load
duke
parents:
diff changeset
   528
     * created.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   529
     *
90ce3da70b43 Initial load
duke
parents:
diff changeset
   530
     * @param truncate if true and file exists, file is truncated to zero
90ce3da70b43 Initial load
duke
parents:
diff changeset
   531
     * length
90ce3da70b43 Initial load
duke
parents:
diff changeset
   532
     * @exception IOException If an I/O error has occurred.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   533
     */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   534
    private void openLogFile(boolean truncate) throws IOException {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   535
        try {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   536
            close();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   537
        } catch (IOException e) { /* assume this is okay */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   538
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   539
90ce3da70b43 Initial load
duke
parents:
diff changeset
   540
        logName = versionName(logfilePrefix);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   541
90ce3da70b43 Initial load
duke
parents:
diff changeset
   542
        try {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   543
            log = (logClassConstructor == null ?
90ce3da70b43 Initial load
duke
parents:
diff changeset
   544
                   new LogFile(logName, "rw") :
90ce3da70b43 Initial load
duke
parents:
diff changeset
   545
                   logClassConstructor.newInstance(logName, "rw"));
90ce3da70b43 Initial load
duke
parents:
diff changeset
   546
        } catch (Exception e) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   547
            throw (IOException) new IOException(
90ce3da70b43 Initial load
duke
parents:
diff changeset
   548
                "unable to construct LogFile instance").initCause(e);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   549
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   550
90ce3da70b43 Initial load
duke
parents:
diff changeset
   551
        if (truncate) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   552
            initializeLogFile();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   553
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   554
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   555
90ce3da70b43 Initial load
duke
parents:
diff changeset
   556
    /**
90ce3da70b43 Initial load
duke
parents:
diff changeset
   557
     * Creates a new log file, truncated and initialized with the format
90ce3da70b43 Initial load
duke
parents:
diff changeset
   558
     * version number preferred by this implementation.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   559
     * <p>Environment: inited, synchronized
90ce3da70b43 Initial load
duke
parents:
diff changeset
   560
     * <p>Precondition: valid: log, log contains nothing useful
90ce3da70b43 Initial load
duke
parents:
diff changeset
   561
     * <p>Postcondition: if successful, log is initialised with the format
90ce3da70b43 Initial load
duke
parents:
diff changeset
   562
     * version number (Preferred{Major,Minor}Version), and logBytes is
90ce3da70b43 Initial load
duke
parents:
diff changeset
   563
     * set to the resulting size of the updatelog, and logEntries is set to
90ce3da70b43 Initial load
duke
parents:
diff changeset
   564
     * zero.  Otherwise, log is in an indeterminate state, and logBytes
90ce3da70b43 Initial load
duke
parents:
diff changeset
   565
     * is unchanged, and logEntries is unchanged.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   566
     *
90ce3da70b43 Initial load
duke
parents:
diff changeset
   567
     * @exception IOException If an I/O error has occurred.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   568
     */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   569
    private void initializeLogFile()
90ce3da70b43 Initial load
duke
parents:
diff changeset
   570
        throws IOException
90ce3da70b43 Initial load
duke
parents:
diff changeset
   571
    {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   572
        log.setLength(0);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   573
        majorFormatVersion = PreferredMajorVersion;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   574
        writeInt(log, PreferredMajorVersion);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   575
        minorFormatVersion = PreferredMinorVersion;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   576
        writeInt(log, PreferredMinorVersion);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   577
        logBytes = intBytes * 2;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   578
        logEntries = 0;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   579
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   580
90ce3da70b43 Initial load
duke
parents:
diff changeset
   581
90ce3da70b43 Initial load
duke
parents:
diff changeset
   582
    /**
90ce3da70b43 Initial load
duke
parents:
diff changeset
   583
     * Writes out version number to file.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   584
     *
90ce3da70b43 Initial load
duke
parents:
diff changeset
   585
     * @param newVersion if true, writes to a new version file
90ce3da70b43 Initial load
duke
parents:
diff changeset
   586
     * @exception IOException If an I/O error has occurred.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   587
     */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   588
    private void writeVersionFile(boolean newVersion) throws IOException {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   589
        String name;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   590
        if (newVersion) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   591
            name = newVersionFile;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   592
        } else {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   593
            name = versionFile;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   594
        }
12040
558b0e0d5910 7146763: Warnings cleanup in the sun.rmi and related packages
khazra
parents: 9502
diff changeset
   595
        try (FileOutputStream fos = new FileOutputStream(fName(name));
558b0e0d5910 7146763: Warnings cleanup in the sun.rmi and related packages
khazra
parents: 9502
diff changeset
   596
             DataOutputStream out = new DataOutputStream(fos)) {
558b0e0d5910 7146763: Warnings cleanup in the sun.rmi and related packages
khazra
parents: 9502
diff changeset
   597
            writeInt(out, version);
558b0e0d5910 7146763: Warnings cleanup in the sun.rmi and related packages
khazra
parents: 9502
diff changeset
   598
        }
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   599
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   600
90ce3da70b43 Initial load
duke
parents:
diff changeset
   601
    /**
90ce3da70b43 Initial load
duke
parents:
diff changeset
   602
     * Creates the initial version file
90ce3da70b43 Initial load
duke
parents:
diff changeset
   603
     *
90ce3da70b43 Initial load
duke
parents:
diff changeset
   604
     * @exception IOException If an I/O error has occurred.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   605
     */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   606
    private void createFirstVersion() throws IOException {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   607
        version = 0;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   608
        writeVersionFile(false);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   609
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   610
90ce3da70b43 Initial load
duke
parents:
diff changeset
   611
    /**
90ce3da70b43 Initial load
duke
parents:
diff changeset
   612
     * Commits (atomically) the new version.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   613
     *
90ce3da70b43 Initial load
duke
parents:
diff changeset
   614
     * @exception IOException If an I/O error has occurred.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   615
     */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   616
    private void commitToNewVersion() throws IOException {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   617
        writeVersionFile(false);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   618
        deleteNewVersionFile();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   619
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   620
90ce3da70b43 Initial load
duke
parents:
diff changeset
   621
    /**
90ce3da70b43 Initial load
duke
parents:
diff changeset
   622
     * Reads version number from a file.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   623
     *
90ce3da70b43 Initial load
duke
parents:
diff changeset
   624
     * @param name the name of the version file
90ce3da70b43 Initial load
duke
parents:
diff changeset
   625
     * @return the version
90ce3da70b43 Initial load
duke
parents:
diff changeset
   626
     * @exception IOException If an I/O error has occurred.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   627
     */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   628
    private int readVersion(String name) throws IOException {
12040
558b0e0d5910 7146763: Warnings cleanup in the sun.rmi and related packages
khazra
parents: 9502
diff changeset
   629
        try (DataInputStream in = new DataInputStream
558b0e0d5910 7146763: Warnings cleanup in the sun.rmi and related packages
khazra
parents: 9502
diff changeset
   630
                (new FileInputStream(name))) {
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   631
            return in.readInt();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   632
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   633
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   634
90ce3da70b43 Initial load
duke
parents:
diff changeset
   635
    /**
90ce3da70b43 Initial load
duke
parents:
diff changeset
   636
     * Sets the version.  If version file does not exist, the initial
90ce3da70b43 Initial load
duke
parents:
diff changeset
   637
     * version file is created.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   638
     *
90ce3da70b43 Initial load
duke
parents:
diff changeset
   639
     * @exception IOException If an I/O error has occurred.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   640
     */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   641
    private void getVersion() throws IOException {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   642
        try {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   643
            version = readVersion(fName(newVersionFile));
90ce3da70b43 Initial load
duke
parents:
diff changeset
   644
            commitToNewVersion();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   645
        } catch (IOException e) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   646
            try {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   647
                deleteNewVersionFile();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   648
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   649
            catch (IOException ex) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   650
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   651
90ce3da70b43 Initial load
duke
parents:
diff changeset
   652
            try {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   653
                version = readVersion(fName(versionFile));
90ce3da70b43 Initial load
duke
parents:
diff changeset
   654
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   655
            catch (IOException ex) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   656
                createFirstVersion();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   657
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   658
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   659
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   660
90ce3da70b43 Initial load
duke
parents:
diff changeset
   661
    /**
90ce3da70b43 Initial load
duke
parents:
diff changeset
   662
     * Applies outstanding updates to the snapshot.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   663
     *
90ce3da70b43 Initial load
duke
parents:
diff changeset
   664
     * @param state the most recent snapshot
90ce3da70b43 Initial load
duke
parents:
diff changeset
   665
     * @exception IOException If serious log corruption is detected or
90ce3da70b43 Initial load
duke
parents:
diff changeset
   666
     * if an exception occurred during a readUpdate callback or if
90ce3da70b43 Initial load
duke
parents:
diff changeset
   667
     * other I/O error has occurred.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   668
     * @return the resulting state of the object after all updates
90ce3da70b43 Initial load
duke
parents:
diff changeset
   669
     */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   670
    private Object recoverUpdates(Object state)
90ce3da70b43 Initial load
duke
parents:
diff changeset
   671
        throws IOException
90ce3da70b43 Initial load
duke
parents:
diff changeset
   672
    {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   673
        logBytes = 0;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   674
        logEntries = 0;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   675
90ce3da70b43 Initial load
duke
parents:
diff changeset
   676
        if (version == 0) return state;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   677
90ce3da70b43 Initial load
duke
parents:
diff changeset
   678
        String fname = versionName(logfilePrefix);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   679
        InputStream in =
90ce3da70b43 Initial load
duke
parents:
diff changeset
   680
                new BufferedInputStream(new FileInputStream(fname));
90ce3da70b43 Initial load
duke
parents:
diff changeset
   681
        DataInputStream dataIn = new DataInputStream(in);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   682
90ce3da70b43 Initial load
duke
parents:
diff changeset
   683
        if (Debug)
90ce3da70b43 Initial load
duke
parents:
diff changeset
   684
            System.err.println("log.debug: reading updates from " + fname);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   685
90ce3da70b43 Initial load
duke
parents:
diff changeset
   686
        try {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   687
            majorFormatVersion = dataIn.readInt(); logBytes += intBytes;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   688
            minorFormatVersion = dataIn.readInt(); logBytes += intBytes;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   689
        } catch (EOFException e) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   690
            /* This is a log which was corrupted and/or cleared (by
90ce3da70b43 Initial load
duke
parents:
diff changeset
   691
             * fsck or equivalent).  This is not an error.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   692
             */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   693
            openLogFile(true);  // create and truncate
90ce3da70b43 Initial load
duke
parents:
diff changeset
   694
            in = null;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   695
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   696
        /* A new major version number is a catastrophe (it means
90ce3da70b43 Initial load
duke
parents:
diff changeset
   697
         * that the file format is incompatible with older
90ce3da70b43 Initial load
duke
parents:
diff changeset
   698
         * clients, and we'll only be breaking things by trying to
90ce3da70b43 Initial load
duke
parents:
diff changeset
   699
         * use the log).  A new minor version is no big deal for
90ce3da70b43 Initial load
duke
parents:
diff changeset
   700
         * upward compatibility.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   701
         */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   702
        if (majorFormatVersion != PreferredMajorVersion) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   703
            if (Debug) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   704
                System.err.println("log.debug: major version mismatch: " +
90ce3da70b43 Initial load
duke
parents:
diff changeset
   705
                        majorFormatVersion + "." + minorFormatVersion);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   706
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   707
            throw new IOException("Log file " + logName + " has a " +
90ce3da70b43 Initial load
duke
parents:
diff changeset
   708
                                  "version " + majorFormatVersion +
90ce3da70b43 Initial load
duke
parents:
diff changeset
   709
                                  "." + minorFormatVersion +
90ce3da70b43 Initial load
duke
parents:
diff changeset
   710
                                  " format, and this implementation " +
90ce3da70b43 Initial load
duke
parents:
diff changeset
   711
                                  " understands only version " +
90ce3da70b43 Initial load
duke
parents:
diff changeset
   712
                                  PreferredMajorVersion + "." +
90ce3da70b43 Initial load
duke
parents:
diff changeset
   713
                                  PreferredMinorVersion);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   714
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   715
90ce3da70b43 Initial load
duke
parents:
diff changeset
   716
        try {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   717
            while (in != null) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   718
                int updateLen = 0;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   719
90ce3da70b43 Initial load
duke
parents:
diff changeset
   720
                try {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   721
                    updateLen = dataIn.readInt();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   722
                } catch (EOFException e) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   723
                    if (Debug)
90ce3da70b43 Initial load
duke
parents:
diff changeset
   724
                        System.err.println("log.debug: log was sync'd cleanly");
90ce3da70b43 Initial load
duke
parents:
diff changeset
   725
                    break;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   726
                }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   727
                if (updateLen <= 0) {/* crashed while writing last log entry */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   728
                    if (Debug) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   729
                        System.err.println(
90ce3da70b43 Initial load
duke
parents:
diff changeset
   730
                            "log.debug: last update incomplete, " +
90ce3da70b43 Initial load
duke
parents:
diff changeset
   731
                            "updateLen = 0x" +
90ce3da70b43 Initial load
duke
parents:
diff changeset
   732
                            Integer.toHexString(updateLen));
90ce3da70b43 Initial load
duke
parents:
diff changeset
   733
                    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   734
                    break;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   735
                }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   736
90ce3da70b43 Initial load
duke
parents:
diff changeset
   737
                // this is a fragile use of available() which relies on the
90ce3da70b43 Initial load
duke
parents:
diff changeset
   738
                // twin facts that BufferedInputStream correctly consults
90ce3da70b43 Initial load
duke
parents:
diff changeset
   739
                // the underlying stream, and that FileInputStream returns
90ce3da70b43 Initial load
duke
parents:
diff changeset
   740
                // the number of bytes remaining in the file (via FIONREAD).
90ce3da70b43 Initial load
duke
parents:
diff changeset
   741
                if (in.available() < updateLen) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   742
                    /* corrupted record at end of log (can happen since we
90ce3da70b43 Initial load
duke
parents:
diff changeset
   743
                     * do only one fsync)
90ce3da70b43 Initial load
duke
parents:
diff changeset
   744
                     */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   745
                    if (Debug)
90ce3da70b43 Initial load
duke
parents:
diff changeset
   746
                        System.err.println("log.debug: log was truncated");
90ce3da70b43 Initial load
duke
parents:
diff changeset
   747
                    break;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   748
                }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   749
90ce3da70b43 Initial load
duke
parents:
diff changeset
   750
                if (Debug)
90ce3da70b43 Initial load
duke
parents:
diff changeset
   751
                    System.err.println("log.debug: rdUpdate size " + updateLen);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   752
                try {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   753
                    state = handler.readUpdate(new LogInputStream(in, updateLen),
90ce3da70b43 Initial load
duke
parents:
diff changeset
   754
                                          state);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   755
                } catch (IOException e) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   756
                    throw e;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   757
                } catch (Exception e) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   758
                    e.printStackTrace();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   759
                    throw new IOException("read update failed with " +
90ce3da70b43 Initial load
duke
parents:
diff changeset
   760
                                          "exception: " + e);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   761
                }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   762
                logBytes += (intBytes + updateLen);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   763
                logEntries++;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   764
            } /* while */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   765
        } finally {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   766
            if (in != null)
90ce3da70b43 Initial load
duke
parents:
diff changeset
   767
                in.close();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   768
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   769
90ce3da70b43 Initial load
duke
parents:
diff changeset
   770
        if (Debug)
90ce3da70b43 Initial load
duke
parents:
diff changeset
   771
            System.err.println("log.debug: recovered updates: " + logEntries);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   772
90ce3da70b43 Initial load
duke
parents:
diff changeset
   773
        /* reopen log file at end */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   774
        openLogFile(false);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   775
90ce3da70b43 Initial load
duke
parents:
diff changeset
   776
        // avoid accessing a null log field
90ce3da70b43 Initial load
duke
parents:
diff changeset
   777
        if (log == null) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   778
            throw new IOException("rmid's log is inaccessible, " +
90ce3da70b43 Initial load
duke
parents:
diff changeset
   779
                "it may have been corrupted or closed");
90ce3da70b43 Initial load
duke
parents:
diff changeset
   780
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   781
90ce3da70b43 Initial load
duke
parents:
diff changeset
   782
        log.seek(logBytes);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   783
        log.setLength(logBytes);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   784
90ce3da70b43 Initial load
duke
parents:
diff changeset
   785
        return state;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   786
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   787
90ce3da70b43 Initial load
duke
parents:
diff changeset
   788
    /**
90ce3da70b43 Initial load
duke
parents:
diff changeset
   789
     * ReliableLog's log file implementation.  This implementation
90ce3da70b43 Initial load
duke
parents:
diff changeset
   790
     * is subclassable for testing purposes.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   791
     */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   792
    public static class LogFile extends RandomAccessFile {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   793
90ce3da70b43 Initial load
duke
parents:
diff changeset
   794
        private final FileDescriptor fd;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   795
90ce3da70b43 Initial load
duke
parents:
diff changeset
   796
        /**
90ce3da70b43 Initial load
duke
parents:
diff changeset
   797
         * Constructs a LogFile and initializes the file descriptor.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   798
         **/
90ce3da70b43 Initial load
duke
parents:
diff changeset
   799
        public LogFile(String name, String mode)
90ce3da70b43 Initial load
duke
parents:
diff changeset
   800
            throws FileNotFoundException, IOException
90ce3da70b43 Initial load
duke
parents:
diff changeset
   801
        {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   802
            super(name, mode);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   803
            this.fd = getFD();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   804
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   805
90ce3da70b43 Initial load
duke
parents:
diff changeset
   806
        /**
90ce3da70b43 Initial load
duke
parents:
diff changeset
   807
         * Invokes sync on the file descriptor for this log file.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   808
         */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   809
        protected void sync() throws IOException {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   810
            fd.sync();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   811
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   812
90ce3da70b43 Initial load
duke
parents:
diff changeset
   813
        /**
90ce3da70b43 Initial load
duke
parents:
diff changeset
   814
         * Returns true if writing 4 bytes starting at the specified file
90ce3da70b43 Initial load
duke
parents:
diff changeset
   815
         * position, would span a 512 byte sector boundary; otherwise returns
90ce3da70b43 Initial load
duke
parents:
diff changeset
   816
         * false.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   817
         **/
90ce3da70b43 Initial load
duke
parents:
diff changeset
   818
        protected boolean checkSpansBoundary(long fp) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   819
            return  fp % 512 > 508;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   820
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   821
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   822
}