Package org.chaidb.db

Source Code of org.chaidb.db.DBState

/*
* 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;

import org.apache.log4j.Logger;
import org.chaidb.db.exception.ChaiDBException;
import org.chaidb.db.helper.ByteTool;
import org.chaidb.db.log.DefaultLogFile;
import org.chaidb.db.log.Lsn;
import org.chaidb.db.transaction.Transaction;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.RandomAccessFile;

public class DBState {

    private static final Logger logger = Logger.getLogger(DBState.class);

    public static final String DB_STATE = "chaidb.state";
    private static String LOG_FILE_PATH = DefaultLogFile.getInstance().getLogFilePath();
    public static String DB_STATE_FILE = null;

    static {
        if (LOG_FILE_PATH.endsWith(File.separator)) DB_STATE_FILE = LOG_FILE_PATH + DB_STATE;
        else DB_STATE_FILE = LOG_FILE_PATH + File.separator + DB_STATE;
    }

    static private DBState singleton = new DBState();

    /**
     * the state file reference
     */
    private RandomAccessFile file = null;

    /**
     * The index info for different operation
     */
    private static final int LOG_INDEX = 0;

    private static final int ARCHIVE_INDEX = 2;

    private static final int TXN_INDEX = 4;

    private static final int NEED_RECOVERY_INDEX = 8;

    private static final int LAST_CHECKPOINT_INDEX = 12;

    /**
     * if the file not exists then create it.
     * if the file exists then read properties.
     */
    private DBState() {
    }


    public static DBState getInstance() {
        return singleton;
    }


    /**
     * open the state file based on file name
     */
    private void open(String fileName, String mode) throws ChaiDBException {
        open(new File(fileName), mode);
    }

    private void open(File file, String mode) throws ChaiDBException {
        try {
            this.file = new RandomAccessFile(file, mode);
        } catch (FileNotFoundException fnfe) {
            try {
                String dir = file.getAbsolutePath();
                dir = dir.substring(0, dir.lastIndexOf(File.separator));
                new File(dir).mkdirs();
                this.file = new RandomAccessFile(file, "rws");
            } catch (Exception e) {
                String details = "Open for file " + file.getName() + " failed. " + e.toString() + ".";
                throw new ChaiDBException(0, details);
            }
        } catch (IOException ioe) {
            String details = "Open for file " + file.getName() + " failed. " + ioe.toString() + ".";
            throw new ChaiDBException(0, details);
        }
    }

    /**
     * close the state file
     */
    private void close() throws ChaiDBException {
        try {
            file.close();
        } catch (IOException ioe) {
            String details = "Close for the state file failed. " + ioe.toString() + ".";
            throw new ChaiDBException(0, details);
        }
    }


    /**
     * Reads a state from the database file
     *
     * @param stateIndex The position to read the state.
     * @param state      The state data
     *                   state data will be touched.
     */
    private synchronized void readState(int stateIndex, byte[] state) throws ChaiDBException {

        try {
            open(DB_STATE_FILE, "r");
            file.seek((long) stateIndex);
            file.read(state);
        } catch (IOException e) {
            String details = "The read state operation failed. " + e.toString() + ".";
            throw new ChaiDBException(0, details);
        } finally {
            close();
        }
    }

    /**
     * Write a state back to the state file
     *
     * @param state      The state data
     * @param stateIndex The position to put the state data.
     */
    private synchronized void writeState(byte[] state, int stateIndex) throws ChaiDBException {

        try {
            open(DB_STATE_FILE, "rws");
            file.seek((long) stateIndex);
            file.write(state);
        } catch (IOException ioe) {
            String details = "The write state operation failed. " + ioe.toString() + ".";
            throw new ChaiDBException(0, details);
        } finally {
            close();
        }
    }


    public void setLatestCheckPoint(Lsn lastCheckPoint) throws ChaiDBException {
        byte[] lsn = lastCheckPoint.toBytes();
        writeState(lsn, LAST_CHECKPOINT_INDEX);
    }

// --Recycle Bin START (10/28/03 2:30 PM):
//    public Lsn getLatestCheckPointLsn() throws ChaiDBException {
//        byte[] blsn = new byte[Lsn.getLsnLength()];
//        readState(LAST_CHECKPOINT_INDEX, blsn);
//        Lsn lsn = new Lsn();
//        lsn.read(blsn, 0);
//        return lsn;
//    }
// --Recycle Bin STOP (10/28/03 2:30 PM)

    public byte[] getLatestCheckPoint() throws ChaiDBException {
        byte[] blsn = new byte[Lsn.getLsnLength()];
        readState(LAST_CHECKPOINT_INDEX, blsn);
        return blsn;
    }


    public boolean setNeedRecovery(boolean needRecovery) {
        try {
            int nNeedRecovery;
            nNeedRecovery = needRecovery ? 1 : 0;
            byte[] stateValue = ByteTool.intToBytes(nNeedRecovery, true);
            writeState(stateValue, NEED_RECOVERY_INDEX);
        } catch (Exception e) {
            logger.error(e);
            return false;
        }
        return true;
    }

    public boolean getNeedRecovery() {
        try {
            byte[] stateValue = new byte[4];
            readState(NEED_RECOVERY_INDEX, stateValue);
            int nNeedRecovery = ByteTool.bytesToInt(stateValue, 0, true);
            return (nNeedRecovery == 1);
        } catch (Exception e) {
            logger.error(e);
            return true;
        }
    }

    public void setLatestLogFileId(short fileId) throws ChaiDBException {
        byte[] stateValue = ByteTool.shortToBytes(fileId);
        writeState(stateValue, LOG_INDEX);
    }

    public short getLatestLogFileId() throws ChaiDBException {
        byte[] stateValue = new byte[Lsn.LSN_FILEID_SIZE];
        readState(LOG_INDEX, stateValue);
        return ByteTool.bytesToShort(stateValue, 0, true);
    }

    public void setArchiveFlag(boolean bArchive) throws ChaiDBException {
        short nArchive = bArchive ? (short) 1 : (short) 0;
        byte[] stateValue = ByteTool.shortToBytes(nArchive);
        writeState(stateValue, ARCHIVE_INDEX);
    }

    public boolean getArchiveFlag() throws ChaiDBException {
        byte[] stateValue = new byte[2];
        readState(ARCHIVE_INDEX, stateValue);
        short archive = ByteTool.bytesToShort(stateValue, 0, true);
        return (archive == 1);
    }

    public void setLatestTxnId(int TxnId) throws ChaiDBException {
        byte[] stateValue = ByteTool.intToBytes(TxnId);
        writeState(stateValue, TXN_INDEX);
    }

    public int getLatestTxnId() throws ChaiDBException {
        byte[] stateValue = new byte[Transaction.TXN_ID_SIZE];
        readState(TXN_INDEX, stateValue);
        return ByteTool.bytesToInt(stateValue, 0, true);
    }
}
TOP

Related Classes of org.chaidb.db.DBState

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.