⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 transactionmanager.java

📁 Java Crawler with domain knowledge path
💻 JAVA
字号:
/** * JDBM LICENSE v1.00 * * Redistribution and use of this software and associated documentation * ("Software"), with or without modification, are permitted provided * that the following conditions are met: * * 1. Redistributions of source code must retain copyright *    statements and notices.  Redistributions must also contain a *    copy of this document. * * 2. Redistributions in binary form must reproduce the *    above copyright notice, this list of conditions and the *    following disclaimer in the documentation and/or other *    materials provided with the distribution. * * 3. The name "JDBM" must not be used to endorse or promote *    products derived from this Software without prior written *    permission of Cees de Groot.  For written permission, *    please contact cg@cdegroot.com. * * 4. Products derived from this Software may not be called "JDBM" *    nor may "JDBM" appear in their names without prior written *    permission of Cees de Groot. * * 5. Due credit should be given to the JDBM Project *    (http://jdbm.sourceforge.net/). * * THIS SOFTWARE IS PROVIDED BY THE JDBM PROJECT AND CONTRIBUTORS * ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT * NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL * CEES DE GROOT OR ANY CONTRIBUTORS BE LIABLE FOR ANY DIRECT, * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED * OF THE POSSIBILITY OF SUCH DAMAGE. * * Copyright 2000 (C) Cees de Groot. All Rights Reserved. * Contributions are Copyright (C) 2000 by their associated contributors. * * $Id: TransactionManager.java,v 1.7 2005/06/25 23:12:32 doomdark Exp $ */package jdbm.recman;import java.io.*;import java.util.*;/** *  This class manages the transaction log that belongs to every *  {@link RecordFile}. The transaction log is either clean, or *  in progress. In the latter case, the transaction manager *  takes care of a roll forward. *<p> *  Implementation note: this is a proof-of-concept implementation *  which hasn't been optimized for speed. For instance, all sorts *  of streams are created for every transaction. */// TODO: Handle the case where we are recovering lg9 and lg0, were we// should start with lg9 instead of lg0!public final class TransactionManager {    private RecordFile owner;    // streams for transaction log.    private FileOutputStream fos;    private ObjectOutputStream oos;    /**      * By default, we keep 10 transactions in the log file before     * synchronizing it with the main database file.     */    static final int DEFAULT_TXNS_IN_LOG = 10;    /**      * Maximum number of transactions before the log file is     * synchronized with the main database file.     */    private int _maxTxns = DEFAULT_TXNS_IN_LOG;    /**     * In-core copy of transactions. We could read everything back from     * the log file, but the RecordFile needs to keep the dirty blocks in     * core anyway, so we might as well point to them and spare us a lot     * of hassle.     */    private ArrayList[] txns = new ArrayList[DEFAULT_TXNS_IN_LOG];    private int curTxn = -1;    /** Extension of a log file. */    static final String extension = ".lg";    /**     *  Instantiates a transaction manager instance. If recovery     *  needs to be performed, it is done.     *     *  @param owner the RecordFile instance that owns this transaction mgr.     */    TransactionManager(RecordFile owner) throws IOException {        this.owner = owner;        recover();        open();    }        /**     * Synchronize log file data with the main database file.     * <p>     * After this call, the main database file is guaranteed to be      * consistent and guaranteed to be the only file needed for      * backup purposes.     */    public void synchronizeLog()        throws IOException    {        synchronizeLogFromMemory();    }        /**     * Set the maximum number of transactions to record in     * the log (and keep in memory) before the log is     * synchronized with the main database file.     * <p>     * This method must be called while there are no     * pending transactions in the log.     */    public void setMaximumTransactionsInLog( int maxTxns )        throws IOException    {        if ( maxTxns <= 0 ) {            throw new IllegalArgumentException(                 "Argument 'maxTxns' must be greater than 0." );        }        if ( curTxn != -1 ) {            throw new IllegalStateException(                 "Cannot change setting while transactions are pending in the log" );        }        _maxTxns = maxTxns;        txns = new ArrayList[ maxTxns ];    }        /** Builds logfile name  */    private String makeLogName() {        return owner.getFileName() + extension;    }    /** Synchs in-core transactions to data file and opens a fresh log */    private void synchronizeLogFromMemory() throws IOException {        close();        TreeSet blockList = new TreeSet( new BlockIoComparator() );        int numBlocks = 0;        int writtenBlocks = 0;        for (int i = 0; i < _maxTxns; i++) {            if (txns[i] == null)                continue;            // Add each block to the blockList, replacing the old copy of this            // block if necessary, thus avoiding writing the same block twice            for (Iterator k = txns[i].iterator(); k.hasNext(); ) {                BlockIo block = (BlockIo)k.next();                if ( blockList.contains( block ) ) {                    block.decrementTransactionCount();                }                else {                    writtenBlocks++;                    boolean result = blockList.add( block );                }                numBlocks++;            }            txns[i] = null;        }        // Write the blocks from the blockList to disk        synchronizeBlocks(blockList.iterator(), true);        owner.sync();        open();    }    /** Opens the log file */    private void open() throws IOException {        fos = new FileOutputStream(makeLogName());        oos = new ObjectOutputStream(fos);        oos.writeShort(Magic.LOGFILE_HEADER);        oos.flush();        curTxn = -1;    }    /** Startup recovery on all files */    private void recover() throws IOException {        String logName = makeLogName();        File logFile = new File(logName);        if (!logFile.exists())            return;        if (logFile.length() == 0) {            logFile.delete();            return;        }        FileInputStream fis = new FileInputStream(logFile);        ObjectInputStream ois = new ObjectInputStream(fis);        try {            if (ois.readShort() != Magic.LOGFILE_HEADER)                throw new Error("Bad magic on log file");        } catch (IOException e) {            // corrupted/empty logfile            logFile.delete();            return;        }        while (true) {            ArrayList blocks = null;            try {                blocks = (ArrayList) ois.readObject();            } catch (ClassNotFoundException e) {                throw new Error("Unexcepted exception: " + e);            } catch (IOException e) {                // corrupted logfile, ignore rest of transactions                break;            }            synchronizeBlocks(blocks.iterator(), false);            // ObjectInputStream must match exactly each            // ObjectOutputStream created during writes            try {                ois = new ObjectInputStream(fis);            } catch (IOException e) {                // corrupted logfile, ignore rest of transactions                break;            }        }        owner.sync();        logFile.delete();    }    /** Synchronizes the indicated blocks with the owner. */    private void synchronizeBlocks(Iterator blockIterator, boolean fromCore)    throws IOException {        // write block vector elements to the data file.        while ( blockIterator.hasNext() ) {            BlockIo cur = (BlockIo)blockIterator.next();            owner.synch(cur);            if (fromCore) {                cur.decrementTransactionCount();                if (!cur.isInTransaction()) {                    owner.releaseFromTransaction(cur, true);                }            }        }    }    /** Set clean flag on the blocks. */    private void setClean(ArrayList blocks)    throws IOException {        for (Iterator k = blocks.iterator(); k.hasNext(); ) {            BlockIo cur = (BlockIo) k.next();            cur.setClean();        }    }    /** Discards the indicated blocks and notify the owner. */    private void discardBlocks(ArrayList blocks)    throws IOException {        for (Iterator k = blocks.iterator(); k.hasNext(); ) {            BlockIo cur = (BlockIo) k.next();            cur.decrementTransactionCount();            if (!cur.isInTransaction()) {                owner.releaseFromTransaction(cur, false);            }        }    }    /**     *  Starts a transaction. This can block if all slots have been filled     *  with full transactions, waiting for the synchronization thread to     *  clean out slots.     */    void start() throws IOException {        curTxn++;        if (curTxn == _maxTxns) {            synchronizeLogFromMemory();            curTxn = 0;        }        txns[curTxn] = new ArrayList();    }    /**     *  Indicates the block is part of the transaction.     */    void add(BlockIo block) throws IOException {        block.incrementTransactionCount();        txns[curTxn].add(block);    }    /**     *  Commits the transaction to the log file.     */    void commit() throws IOException {        oos.writeObject(txns[curTxn]);        sync();        // set clean flag to indicate blocks have been written to log        setClean(txns[curTxn]);        // open a new ObjectOutputStream in order to store        // newer states of BlockIo        oos = new ObjectOutputStream(fos);    }    /** Flushes and syncs */    private void sync() throws IOException {        oos.flush();        fos.flush();        fos.getFD().sync();    }    /**     *  Shutdowns the transaction manager. Resynchronizes outstanding     *  logs.     */    void shutdown() throws IOException {        synchronizeLogFromMemory();        close();    }    /**     *  Closes open files.     */    private void close() throws IOException {        sync();        oos.close();        fos.close();        oos = null;        fos = null;    }    /**     * Force closing the file without synchronizing pending transaction data.     * Used for testing purposes only.     */    void forceClose() throws IOException {        oos.close();        fos.close();        oos = null;        fos = null;    }    /**     * Use the disk-based transaction log to synchronize the data file.     * Outstanding memory logs are discarded because they are believed     * to be inconsistent.     */    void synchronizeLogFromDisk() throws IOException {        close();        for ( int i=0; i < _maxTxns; i++ ) {            if (txns[i] == null)                continue;            discardBlocks(txns[i]);            txns[i] = null;        }        recover();        open();    }    /** INNER CLASS.     *  Comparator class for use by the tree set used to store the blocks     *  to write for this transaction.  The BlockIo objects are ordered by     *  their blockIds.     */    public static class BlockIoComparator        implements Comparator    {        public int compare( Object o1, Object o2 ) {            BlockIo block1 = (BlockIo)o1;            BlockIo block2 = (BlockIo)o2;            int result = 0;            if ( block1.getBlockId() == block2.getBlockId() ) {                result = 0;            }            else if ( block1.getBlockId() < block2.getBlockId() ) {                result = -1;            }            else {                result = 1;            }            return result;        }        public boolean equals(Object obj) {            return super.equals(obj);        }    } // class BlockIOComparator}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -