Search in sources :

Example 1 with AbortTxn

use of com.zimbra.cs.redolog.op.AbortTxn in project zm-mailbox by Zimbra.

the class RedoPlayer method runCrashRecovery.

/**
     *
     * @param redoLogMgr
     * @param postStartupRecoveryOps operations to recover/redo after startup
     *                               completes and clients are allowed to
     *                               connect
     * @return number of operations redone (regardless of their success)
     * @throws Exception
     */
public int runCrashRecovery(RedoLogManager redoLogMgr, List<RedoableOp> postStartupRecoveryOps) throws Exception {
    File redoLog = redoLogMgr.getLogFile();
    if (!redoLog.exists())
        return 0;
    long lookBackTstamp = Long.MAX_VALUE;
    long lookBackDuration = RedoConfig.redoLogCrashRecoveryLookbackSec() * 1000;
    if (lookBackDuration > 0) {
        // Guess the last op's timestamp.  Use the log file's last modified time.  Sanity check it by
        // going no earlier than the create time written in the log.  We can't rely on the last
        // op time field in the header because that is only accurate when the file was closed normally
        // but in crash recovery we're not dealing with a normally closed log.
        long logLastModTime = redoLog.lastModified();
        long logCreateTime = (new FileLogReader(redoLog)).getHeader().getCreateTime();
        long lastOpTstamp = Math.max(logLastModTime, logCreateTime);
        lookBackTstamp = lastOpTstamp - lookBackDuration;
    }
    // scanLog can truncate the current redo.log if it finds junk data at the end
    // from the previous crash.  Close log writer before scanning and reopen after
    // so we don't accidentally undo the truncation on the next write to the log.
    LogWriter logWriter = redoLogMgr.getLogWriter();
    logWriter.close();
    scanLog(redoLog, false, null, Long.MIN_VALUE, Long.MAX_VALUE, lookBackTstamp);
    logWriter.open();
    int numOps;
    synchronized (mOpsMapGuard) {
        numOps = mOpsMap.size();
    }
    if (numOps == 0) {
        ZimbraLog.redolog.info("No uncommitted transactions to redo");
        return 0;
    }
    synchronized (mOpsMapGuard) {
        Set entrySet = mOpsMap.entrySet();
        ZimbraLog.redolog.info("Redoing " + numOps + " uncommitted transactions");
        for (Iterator it = entrySet.iterator(); it.hasNext(); ) {
            Map.Entry entry = (Entry) it.next();
            RedoableOp op = (RedoableOp) entry.getValue();
            if (op == null)
                continue;
            if (op.deferCrashRecovery()) {
                ZimbraLog.redolog.info("Deferring crash recovery to after startup: " + op);
                postStartupRecoveryOps.add(op);
                continue;
            }
            if (ZimbraLog.redolog.isInfoEnabled())
                ZimbraLog.redolog.info("REDOING: " + op);
            boolean success = false;
            try {
                op.redo();
                success = true;
            } catch (Exception e) {
                ZimbraLog.redolog.error("Redo failed for [" + op + "]." + "  Backend state of affected item is indeterminate." + "  Marking operation as aborted and moving on.", e);
            } finally {
                if (success) {
                    CommitTxn commit = new CommitTxn(op);
                    redoLogMgr.logOnly(commit, true);
                } else {
                    AbortTxn abort = new AbortTxn(op);
                    redoLogMgr.logOnly(abort, true);
                }
            }
        }
        mOpsMap.clear();
    }
    return numOps;
}
Also used : Entry(java.util.Map.Entry) Set(java.util.Set) HashSet(java.util.HashSet) CommitTxn(com.zimbra.cs.redolog.op.CommitTxn) FileLogReader(com.zimbra.cs.redolog.logger.FileLogReader) Checkpoint(com.zimbra.cs.redolog.op.Checkpoint) IOException(java.io.IOException) ServiceException(com.zimbra.common.service.ServiceException) AbortTxn(com.zimbra.cs.redolog.op.AbortTxn) Entry(java.util.Map.Entry) LogWriter(com.zimbra.cs.redolog.logger.LogWriter) RedoableOp(com.zimbra.cs.redolog.op.RedoableOp) Iterator(java.util.Iterator) File(java.io.File) ConcurrentHashMap(java.util.concurrent.ConcurrentHashMap) HashMap(java.util.HashMap) ConcurrentMap(java.util.concurrent.ConcurrentMap) LinkedHashMap(java.util.LinkedHashMap) Map(java.util.Map)

Example 2 with AbortTxn

use of com.zimbra.cs.redolog.op.AbortTxn in project zm-mailbox by Zimbra.

the class RedoLogManager method abort.

public void abort(RedoableOp op) {
    if (mEnabled) {
        AbortTxn abort = new AbortTxn(op);
        // Abort records are written with fsync, to prevent triggering
        // redo during crash recovery.
        log(abort, true);
        abort.setSerializedByteArray(null);
    }
}
Also used : AbortTxn(com.zimbra.cs.redolog.op.AbortTxn)

Aggregations

AbortTxn (com.zimbra.cs.redolog.op.AbortTxn)2 ServiceException (com.zimbra.common.service.ServiceException)1 FileLogReader (com.zimbra.cs.redolog.logger.FileLogReader)1 LogWriter (com.zimbra.cs.redolog.logger.LogWriter)1 Checkpoint (com.zimbra.cs.redolog.op.Checkpoint)1 CommitTxn (com.zimbra.cs.redolog.op.CommitTxn)1 RedoableOp (com.zimbra.cs.redolog.op.RedoableOp)1 File (java.io.File)1 IOException (java.io.IOException)1 HashMap (java.util.HashMap)1 HashSet (java.util.HashSet)1 Iterator (java.util.Iterator)1 LinkedHashMap (java.util.LinkedHashMap)1 Map (java.util.Map)1 Entry (java.util.Map.Entry)1 Set (java.util.Set)1 ConcurrentHashMap (java.util.concurrent.ConcurrentHashMap)1 ConcurrentMap (java.util.concurrent.ConcurrentMap)1