recovery.java
来自「jsr170接口的java实现。是个apache的开源项目。」· Java 代码 · 共 175 行
JAVA
175 行
/* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */package org.apache.jackrabbit.core.query.lucene;import org.slf4j.Logger;import org.slf4j.LoggerFactory;import java.util.Set;import java.util.HashSet;import java.util.Iterator;import java.util.List;import java.io.IOException;/** * Implements the recovery process. */class Recovery { /** * The logger instance for this class. */ private static final Logger log = LoggerFactory.getLogger(Recovery.class); /** * The MultiIndex where to run the recovery on. */ private final MultiIndex index; /** * The redo redoLog. */ private final RedoLog redoLog; /** * The ids of the uncommitted transactions. Set of Integer objects. */ private final Set losers = new HashSet(); /** * Creates a new Recovery instance. * * @param index the MultiIndex to recover. * @param redoLog the redo redoLog. */ private Recovery(MultiIndex index, RedoLog redoLog) { this.index = index; this.redoLog = redoLog; } /** * Runs a recovery on <code>index</code> if <code>redoLog</code> contains * log entries. * <p/> * If recovery succeeds the <code>index</code> is flushed and the redo log * is cleared. That is, the <code>index</code> is stable.<br/> * If recovery fails an IOException is thrown, and the redo log will not * be modified. The recovery process can then be executed again, after * fixing the cause of the IOException (e.g. disk full). * * @param index the index to recover. * @param redoLog the redo log. * @throws IOException if the recovery fails. */ static void run(MultiIndex index, RedoLog redoLog) throws IOException { if (!redoLog.hasEntries()) { log.debug("RedoLog is empty, no recovery needed."); return; } log.info("Found uncommitted redo log. Applying changes now..."); Recovery r = new Recovery(index, redoLog); r.run(); log.info("Redo changes applied."); } /** * Runs the recovery process. * * @throws IOException if the recovery fails. */ private void run() throws IOException { List actions = redoLog.getActions(); // find loser transactions for (Iterator it = actions.iterator(); it.hasNext();) { MultiIndex.Action a = (MultiIndex.Action) it.next(); if (a.getType() == MultiIndex.Action.TYPE_START) { losers.add(new Long(a.getTransactionId())); } else if (a.getType() == MultiIndex.Action.TYPE_COMMIT) { losers.remove(new Long(a.getTransactionId())); } } // find last volatile commit without changes from a loser int lastSafeVolatileCommit = -1; Set transactionIds = new HashSet(); for (int i = 0; i < actions.size(); i++) { MultiIndex.Action a = (MultiIndex.Action) actions.get(i); if (a.getType() == MultiIndex.Action.TYPE_COMMIT) { transactionIds.clear(); } else if (a.getType() == MultiIndex.Action.TYPE_VOLATILE_COMMIT) { transactionIds.retainAll(losers); // check if transactionIds contains losers if (transactionIds.size() > 0) { // found dirty volatile commit break; } else { lastSafeVolatileCommit = i; } } else { transactionIds.add(new Long(a.getTransactionId())); } } // delete dirty indexes for (int i = lastSafeVolatileCommit + 1; i < actions.size(); i++) { MultiIndex.Action a = (MultiIndex.Action) actions.get(i); if (a.getType() == MultiIndex.Action.TYPE_CREATE_INDEX) { a.undo(index); } } // replay actions up to last safe volatile commit // ignore add node actions, they are included in volatile commits for (int i = 0; i < actions.size() && i <= lastSafeVolatileCommit; i++) { MultiIndex.Action a = (MultiIndex.Action) actions.get(i); switch (a.getType()) { case MultiIndex.Action.TYPE_ADD_INDEX: case MultiIndex.Action.TYPE_CREATE_INDEX: case MultiIndex.Action.TYPE_DELETE_INDEX: case MultiIndex.Action.TYPE_DELETE_NODE: // ignore actions by the index merger. // the previously created index of a merge has been // deleted because it was considered dirty. // we are conservative here and let the index merger do // its work again. if (a.getTransactionId() == MultiIndex.Action.INTERNAL_TRANS_REPL_INDEXES) { continue; } a.execute(index); } } // now replay the rest until we encounter a loser transaction for (int i = lastSafeVolatileCommit + 1; i < actions.size(); i++) { MultiIndex.Action a = (MultiIndex.Action) actions.get(i); if (losers.contains(new Long(a.getTransactionId()))) { break; } else { // ignore actions by the index merger. if (a.getTransactionId() == MultiIndex.Action.INTERNAL_TRANS_REPL_INDEXES) { continue; } a.execute(index); } } // now we are consistent again -> flush index.flush(); }}
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?