Package org.chaidb.db.index.btree.hbt

Source Code of org.chaidb.db.index.btree.hbt.HyperBTree

/*
* 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.index.btree.hbt;

import org.apache.log4j.Logger;
import org.chaidb.db.KernelContext;
import org.chaidb.db.api.DuplicatedKeyIterator;
import org.chaidb.db.api.keys.NodeId;
import org.chaidb.db.exception.ChaiDBException;
import org.chaidb.db.exception.ErrorCode;
import org.chaidb.db.index.IDBIndex;
import org.chaidb.db.index.IDuplicatedKeyBTree;
import org.chaidb.db.index.Key;
import org.chaidb.db.index.btree.AbstractBTree;
import org.chaidb.db.index.btree.BTreeNode;
import org.chaidb.db.index.btree.BTreePage;
import org.chaidb.db.index.btree.bufmgr.PageNumber;
import org.chaidb.db.lock.LockManager;

import java.util.ArrayList;
import java.util.Enumeration;
import java.util.Iterator;

/**
* HyperBTree, support duplicated key and persistent features.
* It will be used with INT index, STRING index, DATE index, etc.
* User: arefool
* Date: Mar 13, 2003
* Time: 5:30:26 PM
*/
public class HyperBTree extends AbstractBTree implements IDuplicatedKeyBTree {

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

    /**
     * returns the index type of this index
     *
     * @return A short integer representing the index type
     */
    public short getType() {
        return IDBIndex.HYPER_BTREE;
    }


    protected AbstractBTree GenerateClonedBTree() throws ChaiDBException {
        return new HyperBTree();
    }

    protected void copyData(AbstractBTree newBTree, KernelContext kContext) throws ChaiDBException {
        try {
            this.acquire(kContext, LockManager.LOCK_READ);
            newBTree.acquire(kContext, LockManager.LOCK_WRITE);

            Enumeration keys = keys(kContext);
            Iterator it = null;
            Object tmpId = null;
            while (keys.hasMoreElements()) {
                Key key = (Key) keys.nextElement();
                it = lookup(key, kContext);
                while (it.hasNext()) {
                    tmpId = it.next();
                    (newBTree).store(key, tmpId, IDBIndex.STORE_REPLACE, kContext);
                }

            }
        } finally {
            newBTree.release(kContext);
            this.release(kContext);
        }
    }

    /**
     * Delete a value from HyperBTree.
     * If the key has no-value after the value is deleted, this operation will delete the key-value Pairs.
     *
     * @param key
     * @param value
     * @param kContext
     * @return
     * @throws ChaiDBException
     */
    public boolean delete(Key key, Object value, KernelContext kContext) throws ChaiDBException {
        kContext.checkLock(getBTreeName());
        if (value == null || !(value instanceof NodeId)) {
            throw new ChaiDBException(ErrorCode.BTREE_DEBUG, "the value is invalid , maybe null or not node id type.");
        }
        this.getBTreeSpec().setModified(true);
        NodeId nodeid = (NodeId) value;
        NodeId tmpId = null;
        DuplicatedKeyIterator dki = lookup(key, kContext);
        try {
            while (dki.hasNext()) {
                tmpId = (NodeId) dki.next();
                if (tmpId.equals(nodeid)) {
                    dki.remove();
                    return true;
                }
            } //end while
        } finally {
            dki.close();
        }
        return false;
    }

    public int delete(int docId, KernelContext kContext) throws ChaiDBException {

        kContext.checkLock(getBTreeName());
        this.getBTreeSpec().setModified(true);
        try {
            this.acquire(kContext, LockManager.LOCK_WRITE);
            int ret = 0;
            Enumeration enuKeys = keys(kContext);
            while (enuKeys.hasMoreElements()) {
                Key key = (Key) enuKeys.nextElement();
                ret += delete(key, docId, kContext);
            }
            return ret;
        } finally {
            this.release(kContext);
        }
    }

    /**
     * Delete a key from HyperBTree.
     *
     * @param key
     * @param docId
     * @param kContext
     * @return the counts of have deleted successfully
     * @throws ChaiDBException
     */
    public int delete(Key key, int docId, KernelContext kContext) throws ChaiDBException {

        kContext.checkLock(getBTreeName());
        this.getBTreeSpec().setModified(true);
        int ret = 0;
        DuplicatedKeyIterator dki = lookup(key, kContext);
        try {
            while (dki.hasNext()) {
                NodeId nodeid = (NodeId) dki.next();
                if (nodeid.getDocId() == docId) {
                    dki.remove();
                    ret++;
                }
            } //end while
        } finally {
            dki.close();
        }
        return ret;
    }


    /**
     * Return an Iterator to get all corresponding value of a key.
     *
     * @param key
     * @param kContext
     * @return
     * @throws ChaiDBException
     */
    public DuplicatedKeyIterator lookup(Key key, KernelContext kContext) throws ChaiDBException {
        kContext.checkLock(getBTreeName());
        HyperBTreeIterator it = null;
        it = HyperBTreeIterator.createIterator(this, kContext);
        try {
            PageNumber root = getTopRoot();

            BTreePage rootPage = new BTreePage(id, root, btreeSpec, buffer);
            if (rootPage.getPage() == null) {
                return it;
            }
            BTreeNode n = rootPage.search(key, kContext);
            if (n != null) {
                NodePosition firstNode = new NodePosition(n.getPageNumber().getPageNumber(), n.getDataNodeOffset());
                it.initIterator(firstNode);
            }
            // unfix root and leaf page.
            buffer.releasePage(id, rootPage.pageNumber, false);
        } finally {
            doFinalJob();
        }

        return it;
    }

    /**
     * returns the values which key is in the range of bottomKey and topKey
     * it's used in UDI btree for range-base search in XPath and XQuery
     *
     * @param minKey        smallest key value
     * @param maxKey        largest key value
     * @param includeMinKey true means nodes with the minKey are included
     *                      in the value list. Otherwise, they are excluded.
     * @param includeMaxKey true means nodes with the maxKey are included
     *                      in the value list. Otherwise, they are excluded.
     * @return Vector nodeId list which key is in the range of minKey and
     *         maxKey,if not found, return null
     * @throws ChaiDBException Exception while looking up the key
     */
    public ArrayList rangeLookup(Key minKey, Key maxKey, boolean includeMinKey, boolean includeMaxKey, KernelContext kContext) throws ChaiDBException {
        kContext.checkLock(getBTreeName());
        ArrayList keys = rangeLookupKeys(minKey, maxKey, includeMinKey, includeMaxKey, kContext);
        try {
            ArrayList newList = new ArrayList(keys.size());
            DuplicatedKeyIterator it = null;
            Key key;
            for (int i = 0; i < keys.size(); i++) {
                key = (Key) keys.get(i);
                it = lookup(key, kContext);
                newList.add(it);
            }
            return newList;

        } catch (Exception ee) {
            logger.error(ee);
            String details = "Converter failed in Hyper BTree to decode : " + ee.toString() + ".";
            throw new ChaiDBException(ErrorCode.CONVERTER_DECODING_ERROR, details);
        }
    }

    public ArrayList rangeLookupKeys(Key minKey, Key maxKey, boolean includeMinKey, boolean includeMaxKey, KernelContext kContext) throws ChaiDBException {

        kContext.checkLock(getBTreeName());
        ArrayList values = new ArrayList();

        try {
            PageNumber root = getTopRoot();
            rangeLookupKeys(minKey, maxKey, includeMinKey, includeMaxKey, root, values, kContext);
        } finally {
            doFinalJob();
        }
        return values;
    }


    /**
     * returns the values which key is in the range of bottomKey and topKey
     * it's used in UDI btree for range-base search in XPath and XQuery
     *
     * @param minKey minKey smallest key value
     * @param maxKey maxKey largest key value
     * @return Vector nodeId list which key is in the range of minKey and
     *         maxKey,if not found, return null
     * @throws ChaiDBException Exception while looking up the key
     */
    public ArrayList rangeLookup(Key minKey, Key maxKey, KernelContext kContext) throws ChaiDBException {
        kContext.checkLock(getBTreeName());
        return rangeLookup(minKey, maxKey, true, true, kContext);
    }

    //here convert is not performed
    protected void rangeLookupKeys(Key minKey, Key maxKey, boolean includeMinKey, boolean includeMaxKey, PageNumber root, ArrayList values, KernelContext kContext) throws ChaiDBException {

        if (!checkKeyPair(minKey, maxKey)) return;

        BTreePage page;

        if (minKey == null) {
            page = findLeftMostLeaf(root);
        } else {
            page = new BTreePage(id, root, btreeSpec, getBuffer());
            if (page.getPage() != null) {
                page = page.getLeaf(minKey, kContext, BTreePage.SEARCH);
                getBuffer().releasePage(id, root, false);
            }
        }
        if (page.getPage() != null) {
            page.searchKeys(minKey, maxKey, includeMinKey, includeMaxKey, kContext, values);
            // unfix root and leaf page.
            getBuffer().releasePage(id, page.pageNumber, false);
        }

    }

    /**
     * returns enumeration of keys.
     *
     * @return Enumeration of keys
     */
    public Enumeration keys(KernelContext kContext) {
        try {
            kContext.checkLock(getBTreeName());
            return new HyperBTreeEnumerator(this, btreeSpec, buffer, kContext);
        } catch (ChaiDBException e) {
            logger.error(e);
            return null;
        }
    }

}
TOP

Related Classes of org.chaidb.db.index.btree.hbt.HyperBTree

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.