Package org.chaidb.db.api

Source Code of org.chaidb.db.api.Database

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

import org.apache.log4j.Logger;
import org.apache.log4j.PropertyConfigurator;
import org.chaidb.db.Db;
import org.chaidb.db.DbEnvironment;
import org.chaidb.db.KernelContext;
import org.chaidb.db.DBState;
import org.chaidb.db.exception.ChaiDBException;
import org.chaidb.db.exception.ErrorCode;
import org.chaidb.db.helper.Config;
import org.chaidb.db.index.BTreeFactory;
import org.chaidb.db.index.IDBIndex;
import org.chaidb.db.transaction.recover.TransactionRecover;

import java.io.File;
import java.util.Date;
import java.util.HashMap;
import java.util.ArrayList;

/**
* Database is the instance of Database. It consist of one or more BTrees.
*/
public class Database {
    private static Db db = null;
    private KernelContext kc;
    private HashMap openedBTree = new HashMap(10);
    private HashMap btree2Path = new HashMap(10);
    private Logger log = Logger.getLogger(Database.class);

    public boolean isOpened() {
        return opened;
    }

    private boolean opened =false;

    /**
     * Create a database instance and open the database.
     *
     * @throws ChaiDBException
     */
    public Database(String dbHome) throws ChaiDBException {
        System.setProperty("chaidb.home", dbHome);
        PropertyConfigurator.configure(Database.class.getResource("/org/chaidb/log4j.properties"));
        if (db == null) {
            boolean needRecovery = DBState.getInstance().getNeedRecovery();
            recoverWhenServerStart(needRecovery);
            db = new Db();
        }
        kc = new KernelContext();
        opened = true;
    }

    /**
     * Close the database. All opened BTree will be closed ahead.
     *
     * @throws ChaiDBException
     */
    public void close() throws ChaiDBException {
        ArrayList list = new ArrayList(btree2Path.keySet());
        for (int i = 0; i < list.size(); i++) {
            BTree tree = (BTree) list.get(i);
            tree.close();
        }

        DBState.getInstance().setNeedRecovery(false);
        opened = false;
    }

    /**
     * Open a BTree instance, if the BTree doesn't exist, it will be created.
     *
     * @param filename  file name of the BTree
     * @param btreeType Regular BTree or Hyper BTree
     * @return the instance of the BTree
     * @throws ChaiDBException if there is any error while opening the BTree
     */
    public BTree openBTree(String filename, BTreeType btreeType) throws ChaiDBException {
        if (openedBTree.containsKey(filename)) {
            return (BTree)openedBTree.get(filename);
        }
        String path = DbEnvironment.getDataHome().concat(filename);
        IDBIndex index = BTreeFactory.createBTree(btreeType.typeId);
        index.open(path, kc);
        BTree bTree = new BTree(this, index, btreeType, kc);
        openedBTree.put(filename, bTree);
        btree2Path.put(bTree, filename);
        return bTree;
    }

    /**
     * Close the BTree instance, this method should only be called by BTree.close()
     *
     * @param btree
     * @throws ChaiDBException
     */
    void removeBTreeFromMap(BTree btree) throws ChaiDBException {
        if (!btree2Path.containsKey(btree)) {
            throw new ChaiDBException(ErrorCode.BTREE_NOT_FOUND);
        }
        String filename = (String) btree2Path.remove(btree);
        openedBTree.remove(filename);      
    }

    /**
     * Drop a BTree on disk. The file will be deleted.
     *
     * @param filename file name of the BTree
     * @return true if the BTree was dropped successfully.
     * @throws ChaiDBException
     */
    public boolean dropBTree(String filename) throws ChaiDBException {
        if (openedBTree.containsKey(filename)) {
            throw new ChaiDBException(ErrorCode.BTREE_ALREADY_OPENED);
        }
        String path = DbEnvironment.getDataHome().concat(File.separator).concat(filename);
        return new File(path).delete();
    }

    private void recoverWhenServerStart(boolean needRecovery) throws ChaiDBException {
        TransactionRecover txnRecover;
        if (needRecovery) {
            System.out.println("[" + new Date().toString() + "] Database is recovering from an inconsistent status...");
            // It is NOT a real sys error, just to make message about
            // "begin recovery" visible even at the default log level.
            // This is a request from Sequoia.
            log.info("Begin normal recovery...");
            long begin = System.currentTimeMillis();
            txnRecover = Db.getTxnManager().setRecover(TransactionRecover.NORMAL_RECOVER);
            try {
                txnRecover.doRecover();
                long end = System.currentTimeMillis();
                System.out.println("[" + new Date().toString() + "] Recovery finished in " + ((end - begin) / 1000) + " seconds.");
                log.info("Success of normal recovery!!!");
            } catch (ChaiDBException e) {
                System.out.println("[" + new Date().toString() + "] Failure to do recovery!!! Please refer to log file for more information.");
                log.info("Failure to do recovery!!!");
                log.debug(e);
            }
            if (!Config.TXN_SUPPORT) {
                needRecovery = false;
                /*
                     * Here all items are written to disk. This seems not to be efficent,but
                     * this behavior is called in a relative low possibility, influencing the
                     * whole system performance little.
                     */
                DBState.getInstance().setNeedRecovery(needRecovery);
            }

        } else {   //In order to present system crush. when this.needRecovery == 0 ;
            if (!DbEnvironment.READ_ONLY) {
                if (Config.TXN_SUPPORT) {
                    try {
                        Db.getTxnManager().doCheckpoint();
                    } catch (ChaiDBException e) {
                        throw e;
                    }
                    needRecovery = true;
                    /*
                    * Here all items are written to disk. This seems not to be efficent,but
                    * this behavior is called in a relative low possibility, influencing the
                    * whole system performance little.
                    */
                    DBState.getInstance().setNeedRecovery(needRecovery);
                }
            }
        }
    }

    /**
     * Begin a transaction, use Transaction.commit or Transaction.rollback then.
     *
     * @return instance of new transaction
     * @throws ChaiDBException
     */
    public Transaction beginTransaction() throws ChaiDBException {
        Transaction transaction = new Transaction();
        kc.setTxn(transaction.getTxn());
        return transaction;
    }
}
TOP

Related Classes of org.chaidb.db.api.Database

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.