Package org.chaidb.db.log

Source Code of org.chaidb.db.log.MemLogManagerImpl

/*
* Copyright (C) 2006  http://www.chaidb.org
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
* GNU General Public License for more details.
*
*/

package org.chaidb.db.log;

import org.chaidb.db.KernelContext;
import org.chaidb.db.exception.ChaiDBException;
import org.chaidb.db.exception.ErrorCode;
import org.chaidb.db.index.InMemIndex;
import org.chaidb.db.index.Key;

import java.util.Hashtable;

public class MemLogManagerImpl extends MemLogManager {

    static final short NORMAL = 0;     //the transaction is proceeding
    static final short PRE_COMMIT = 1; //the transaction have precommit
    static final short ROLLBACK = 2;   //the transaction is rollbacking

    /* The count of transaction */
    private int maxCount = DEFAULT_MAX_TXN_COUNT;
    /* Save transactions log */
    private Hashtable txnsLog = null;

    /**
     * default constructor
     */
    public MemLogManagerImpl() {
        txnsLog = new Hashtable();
    }

    /**
     * Set the max transaction number
     */
    public void setMaxTxnCount(int maxTxnCount) {
        maxCount = maxTxnCount;
    }

    /**
     * clear the in-memory log
     */
    private void cleanMemoryLog(int txnId) {
        Integer id = new Integer(txnId);
        txnsLog.remove(id);
    }

    /**
     * Add in-memory index change log
     *
     * @param txnId  The id of transaction.
     * @param mode   The mode of operation.(STORE_INSERT, STORE_REPLACE, DELETE)
     * @param index  The operated index.
     * @param key    The key of the index entry to be operated.
     * @param newObj The new value after operation.
     * @param oldObj The old value before operation.
     */
    public void addMemoryLog(int txnId, InMemIndex index, short mode, KernelContext kContext, Key key, Object newObj, Object oldObj) throws ChaiDBException {
        MemLogRecord record = new MemLogRecord(index, key, mode, kContext, oldObj, newObj);
        Integer id = new Integer(txnId);
        Link lk = (Link) txnsLog.get(id);
        if (lk == null) {
            if (txnsLog.size() < maxCount) {
                lk = new Link();
                txnsLog.put(id, lk);
            } else throw new ChaiDBException(ErrorCode.TXN_TOO_MANY_IN_MEMORY);
        }
        // record the in-memory log only when the status is normal
        if (lk.status == NORMAL) lk.insertHead(record);
    }

    /**
     * Flush any change in memory to B-Tree.
     *
     * @param txnId The id of transaction.
     */
    public void preCommit(int txnId) throws ChaiDBException {
        Integer id = new Integer(txnId);
        Link lk = (Link) txnsLog.get(id);
        // if no in-memory transaction log or the change have flush to B-Tree,return
        if (lk == null || lk.status == PRE_COMMIT) return;
        // apply every in-memroy change to B-Tree in order(from the tail to head)
        MemLogRecord record = lk.tail;
        while (record != null) {
            record.getIDBIndex().memFlush(record.getMode(), record.getKernelContext(), record.getKey(), record.getNewValue());
            record = record.pre;
        }
        lk.status = PRE_COMMIT;
    }

    /**
     * Clear the log in memory.
     * Precommit must be called before calling it.
     *
     * @param txnId The id of transaction.
     */
    public void commit(int txnId) throws ChaiDBException {
        Integer id = new Integer(txnId);
        Link lk = (Link) txnsLog.get(id);
        if (lk == null) return;
        if (lk.status != PRE_COMMIT) throw new ChaiDBException(ErrorCode.TRANSACTION_LACK_PRECOMMIT);
        cleanMemoryLog(txnId);
    }

    /**
     * Rollback any change of in memory indexes.
     *
     * @param txnId The id of transaction.
     */
    public void rollback(int txnId) throws ChaiDBException {
        Integer id = new Integer(txnId);
        Link lk = (Link) txnsLog.get(id);
        // if no in-memory transaction log return
        if (lk == null) return;
        // set the status to rollback
        lk.status = ROLLBACK;
        // undo each in-memroy change in reverse order(from head to tail)
        MemLogRecord record = lk.head;
        while (record != null) {
            record.getIDBIndex().memUndo(record.getMode(), record.getKernelContext(), record.getKey(), record.getOldValue());
            record = record.next;
        }
        cleanMemoryLog(txnId);
    }

    /**
     * the inner class for in-memory log link head
     */
    class Link {
        short status = NORMAL;      //the intial status is NORMAL
        MemLogRecord head = null;   //the head of in-memory log list
        MemLogRecord tail = null;   //the tail of in-memory log list

        /**
         * insert the in-memory log into the head of list
         *
         * @param record The record of in-memory log
         */
        void insertHead(MemLogRecord record) {
            if (head == null) {
                head = record;
                tail = record;
            } else {
                record.next = head;
                head.pre = record;
                head = record;
            }
        }
    }

}
TOP

Related Classes of org.chaidb.db.log.MemLogManagerImpl

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.