Package org.chaidb.db.log.logrecord

Source Code of org.chaidb.db.log.logrecord.BTreeInsertLeafNodeLogRecord

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

import org.apache.log4j.Logger;
import org.chaidb.db.exception.ChaiDBException;
import org.chaidb.db.exception.ErrorCode;
import org.chaidb.db.helper.ByteTool;
import org.chaidb.db.index.btree.BTreeSpec;

public class BTreeInsertLeafNodeLogRecord extends BTreeLogRecord {
    private static final Logger logger = Logger.getLogger(BTreeInsertLeafNodeLogRecord.class);
    /* old upbound and lowbound on BTreePage */
    private short oldLowBound; //2bytes
    private short oldUpBound;  //2bytes

    /* new upbound and lowbound on BTreePage */
    private short newLowBound; //2bytes
    private short newUpBound;  //2bytes

    /* head offset location on BTreePage */
    private short headOffset; //2bytes

    /* insert node offset value on BTreePage */
    private short nodeOffset; //2bytes

    /* head move index byte array length on BTreePage */
    private short headMoveIndexArrLen; //2bytes

    /* head move index byte array on BTreePage */
    private byte[] headMoveIndexArr; //headMoveIndexArrLen

    private short compressedHeadMoveIndexArrLen;

    private byte[] compressedHeadMoveIndexArr;

    /* BTreeNode value length on BTreePage */
    private short nodeValueLen; //2bytes

    /* BTreeNode value on BTreePage */
    private byte[] nodeValue; //nodeValueLen bytes

    /* DataPage PageNumber */
    private int dataPageNum;

    /* old upbound on DataPage */
    private short dataPageOldUpBound; //2bytes

    /* old lowbound on DataPage */
    private short dataPageNewUpBound; //2bytes


    /* DataNode value length on DataPage */
    private short dataNodeValueLen; //2bytes

    /* DataNode value on DataPage */
    private byte[] dataNodeValue; //dataNodeValueLen bytes

    /* Node size */
    private short nodeSize; //2bytes

    private static final int OLD_LOWBOUND_SIZE = 2; //2 bytes
    private static final int OLD_UPBOUND_SIZE = 2; //2 bytes
    private static final int NEW_LOWBOUND_SIZE = 2; //2 bytes
    private static final int NEW_UPBOUND_SIZE = 2; //2 bytes
    private static final int HEAD_OFFSET_SIZE = 2; //2 bytes
    private static final int NODE_OFFSET_SIZE = 2; //2 bytes
    private static final int HEAD_MOVE_INDEX_LENGTH_SIZE = 2; //2 bytes
    private static final int NODE_VALUE_LENGTH_SIZE = 2; //2 bytes
    private static final int NODE_SIZE = 2; //2 bytes

    /**
     * default Constructor
     */
    public BTreeInsertLeafNodeLogRecord() {
        super();
        super.setType(LOG_BTREE_INSERT_LEAF_NODE);
    }

    public BTreeInsertLeafNodeLogRecord(int treeId, int newPageNum, int newTxnId, short oldLowBound, short oldUpBound, short newLowBound, short newUpBound, short headOffset, short nodeOffset, byte[] headMoveOffsetArr, byte[] nodeValue, int dataPageNum, short dataPageOldUpBound, short dataPageNewUpBound, byte[] dataNodeValue, short nodeSize, short btreeType) {
        super(treeId, newPageNum, newTxnId, btreeType);
        super.setType(LOG_BTREE_INSERT_LEAF_NODE);
        this.oldLowBound = oldLowBound;
        this.oldUpBound = oldUpBound;
        this.newLowBound = newLowBound;
        this.newUpBound = newUpBound;
        this.headOffset = headOffset;
        this.nodeOffset = nodeOffset;
        this.nodeSize = nodeSize;

        this.headMoveIndexArr = headMoveOffsetArr;
        if ((headMoveOffsetArr != null) && (headMoveOffsetArr.length > 0)) {
            this.headMoveIndexArrLen = (short) headMoveIndexArr.length;
            compressedHeadMoveIndexArr = offset2Location(headMoveIndexArr);
            compressedHeadMoveIndexArrLen = (short) compressedHeadMoveIndexArr.length;
        } else {
            this.headMoveIndexArrLen = 0;
        }

        if (nodeValue != null) {
            this.nodeValueLen = (short) nodeValue.length;
        } else {
            this.nodeValueLen = 0;
        }
        this.nodeValue = nodeValue;

        this.dataPageNum = dataPageNum;
        this.dataPageOldUpBound = dataPageOldUpBound;
        this.dataPageNewUpBound = dataPageNewUpBound;
        if (dataNodeValue != null) {
            this.dataNodeValueLen = (short) dataNodeValue.length;
        } else {
            this.dataNodeValueLen = 0;
        }
        this.dataNodeValue = dataNodeValue;


    }

    public short getOldLowBound() {
        return oldLowBound;
    }

    public short getOldUpBound() {
        return oldUpBound;
    }

    public short getNewLowBound() {
        return newLowBound;
    }

    public short getNewUpBound() {
        return newUpBound;
    }

    public short getHeadOffset() {
        return headOffset;
    }

    public short getNodeOffset() {
        return nodeOffset;
    }

    public byte[] getHeadMoveIndexArr() {
        if (headMoveIndexArr != null) {
            return ByteTool.copyByteArray(headMoveIndexArr, 0, headMoveIndexArr.length);
        }
        return null;
    }

    public int getDataPageNum() {
        return dataPageNum;
    }

    public short getDataPageOldUpBound() {
        return dataPageOldUpBound;
    }

    public short getDataPageNewUpBound() {
        return dataPageNewUpBound;
    }

    public byte[] getDataNodeValue() {
        if (dataNodeValue != null) {
            return ByteTool.copyByteArray(dataNodeValue, 0, dataNodeValue.length);
        }
        return null;
    }

    public byte[] getNodeValue() {
        if (nodeValue != null) {
            return ByteTool.copyByteArray(nodeValue, 0, nodeValue.length);
        }
        return null;
    }

    public short getNodeSize() {
        return nodeSize;
    }

    public short getDataNodeValueLen() {
        return dataNodeValueLen;
    }

    public short getNodeValueLen() {
        return nodeValueLen;
    }

    /**
     * return move index length
     *
     * @return short headMoveIndexArrLen
     */
    public short getHeadMoveIndexArrLen() {
        return headMoveIndexArrLen;
    }

    /**
     * offset move array in BTreePage are transfered into location array
     *
     * @param moveOffsetArr
     * @return byte[] moveLocArr
     */
    private byte[] offset2Location(byte[] moveOffsetArr) {
        int len = moveOffsetArr.length;
        short pageSize = (short) BTreeSpec.PAGE_SIZE;
        byte[] moveLocArr = new byte[len / 2];
        for (int i = 0; i < len; i += 2) {
            short offset = ByteTool.bytesToShort(moveOffsetArr, i, msbFirst);
            byte location = (byte) ((pageSize - offset) / nodeSize);
            moveLocArr[i / 2] = location;
        }
        return moveLocArr;
    }

    /**
     * location move array in BTreePage are transfered into offset array
     *
     * @param moveLocArr
     * @return byte[] moveOffsetArr
     */
    private byte[] location2Offset(byte[] moveLocArr) {
        int len = moveLocArr.length;
        short pageSize = (short) BTreeSpec.PAGE_SIZE;
        byte[] moveOffsetArr = new byte[0];
        for (int i = 0; i < len; i++) {
            short location = ByteTool.unsignedByteToShort(moveLocArr[i]);
            short offset = (short) (pageSize - location * nodeSize);
            moveOffsetArr = ByteTool.append(moveOffsetArr, ByteTool.shortToBytes(offset));
        }
        return moveOffsetArr;
    }


    /**
     * converts a byte array into a log record instance
     */
    public boolean read(byte[] bArr, int start) throws ChaiDBException {

        /* construct a new LogRecord instance */
        super.read(bArr, start);

        /* get the values of BTreeMoveLogRecord Object */
        int step = start + super.getRecordLength();
        oldLowBound = ByteTool.bytesToShort(bArr, step, msbFirst);
        step = step + OLD_LOWBOUND_SIZE;
        oldUpBound = ByteTool.bytesToShort(bArr, step, msbFirst);
        step = step + OLD_UPBOUND_SIZE;
        newLowBound = ByteTool.bytesToShort(bArr, step, msbFirst);
        step = step + NEW_LOWBOUND_SIZE;
        newUpBound = ByteTool.bytesToShort(bArr, step, msbFirst);
        step = step + NEW_UPBOUND_SIZE;
        headOffset = ByteTool.bytesToShort(bArr, step, msbFirst);
        step = step + HEAD_OFFSET_SIZE;
        nodeOffset = ByteTool.bytesToShort(bArr, step, msbFirst);
        step = step + NODE_OFFSET_SIZE;

        nodeSize = ByteTool.bytesToShort(bArr, step, msbFirst);
        step = step + NODE_SIZE;

        compressedHeadMoveIndexArrLen = ByteTool.bytesToShort(bArr, step, msbFirst);
        step = step + HEAD_MOVE_INDEX_LENGTH_SIZE;
        if (compressedHeadMoveIndexArrLen > 0) {
            compressedHeadMoveIndexArr = ByteTool.copyByteArray(bArr, step, compressedHeadMoveIndexArrLen);
            headMoveIndexArr = location2Offset(compressedHeadMoveIndexArr);
            headMoveIndexArrLen = (short) headMoveIndexArr.length;
            step = step + compressedHeadMoveIndexArrLen;
        }

        nodeValueLen = ByteTool.bytesToShort(bArr, step, msbFirst);
        step = step + NODE_VALUE_LENGTH_SIZE;
        if (nodeValueLen > 0) {
            nodeValue = ByteTool.copyByteArray(bArr, step, nodeValueLen);
        }

        step = step + nodeValueLen;
        dataPageNum = ByteTool.bytesToInt(bArr, step, msbFirst);

        step = step + BTreeLogRecord.PAGENUM_SIZE;
        dataPageOldUpBound = ByteTool.bytesToShort(bArr, step, msbFirst);

        step = step + OLD_UPBOUND_SIZE;
        dataPageNewUpBound = ByteTool.bytesToShort(bArr, step, msbFirst);

        step = step + NEW_UPBOUND_SIZE;
        dataNodeValueLen = ByteTool.bytesToShort(bArr, step, msbFirst);
        step = step + NODE_VALUE_LENGTH_SIZE;

        if (dataNodeValueLen > 0) {
            dataNodeValue = ByteTool.copyByteArray(bArr, step, dataNodeValueLen);
        }

        return true;
    }


    /**
     * do redo function
     *
     * @param page
     * @return boolean true|false
     */
    protected boolean doRedo(byte[] page) throws ChaiDBException {
        /* redo insert node operation */
        try {
            /* update lowBound and upBound value */
            System.arraycopy(ByteTool.shortToBytes(newLowBound), 0, page, BTreeSpec.OFF_LOWERBOUND, NEW_LOWBOUND_SIZE);

            System.arraycopy(ByteTool.shortToBytes(newUpBound), 0, page, BTreeSpec.OFF_UPPERBOUND, NEW_UPBOUND_SIZE);

            /* add head offset */
            System.arraycopy(ByteTool.shortToBytes(nodeOffset), 0, page, headOffset, NODE_OFFSET_SIZE);

            /* move head index if have any to move */
            if (headMoveIndexArrLen > 0) {
                System.arraycopy(headMoveIndexArr, 0, page, headOffset + HEAD_OFFSET_SIZE, headMoveIndexArrLen);
            }

            /* add node value */
            if (nodeValueLen > 0) {
                System.arraycopy(nodeValue, 0, page, nodeOffset, nodeValueLen);
            }

            byte[] dataPage = getPage(dataPageNum, true);
            System.arraycopy(ByteTool.shortToBytes(dataPageNewUpBound), 0, dataPage, BTreeSpec.OFF_UPPERBOUND, NEW_UPBOUND_SIZE);

            if (dataNodeValueLen > 0) {
                System.arraycopy(dataNodeValue, 0, dataPage, dataPageNewUpBound, dataNodeValueLen);
            }
            releasePage(dataPageNum, true);

        } catch (Exception e) {
            logger.debug(e);
            throw new ChaiDBException(ErrorCode.LOG_REDO_FAILED, e.toString());
        }
        return true;
    }

    /**
     * do undo function
     *
     * @param page
     * @return boolean true|false
     */
    protected boolean doUndo(byte[] page) throws ChaiDBException {
        /* undo insert node operation */
        try {
            /* reset lowBouand and upBound value as old value */
            System.arraycopy(ByteTool.shortToBytes(oldLowBound), 0, page, BTreeSpec.OFF_LOWERBOUND, OLD_LOWBOUND_SIZE);

            System.arraycopy(ByteTool.shortToBytes(oldUpBound), 0, page, BTreeSpec.OFF_UPPERBOUND, OLD_UPBOUND_SIZE);

            /* delete head offset and move later index to its location */
            if (headMoveIndexArrLen > 0) {
                System.arraycopy(headMoveIndexArr, 0, page, headOffset, headMoveIndexArrLen);
            }

            /* delete node value in nodeOffset location ,in fact nothing need to do
               after upbound is reset old value
             */

            byte[] dataPage = getPage(dataPageNum, true);
            System.arraycopy(ByteTool.shortToBytes(dataPageOldUpBound), 0, dataPage, BTreeSpec.OFF_UPPERBOUND, OLD_UPBOUND_SIZE);

            releasePage(dataPageNum, true);
            /* delete dataNode value in dataNodeOffset location ,in fact
               nothing need to do after upbound is reset old value
             */


        } catch (Exception e) {
            logger.debug(e);
            throw new ChaiDBException(ErrorCode.LOG_UNDO_FAILED, e.toString());
        }
        return true;
    }


    /**
     * print data and help in debugging log files
     */
    public void print() throws ChaiDBException {
        //logger.log(ServerLog.LOG_DEBUG,"begin: printing the information of BTreeInsertLeafNodeLogRecord object......");
        super.print();

        logger.debug("old LowBound UpBound: 0x" + Integer.toHexString(oldLowBound) + "_" + Integer.toHexString(oldUpBound));

        logger.debug("new LowBound UpBound: 0x" + Integer.toHexString(newLowBound) + "_" + Integer.toHexString(newUpBound));


        logger.debug("headOffset_nodeOffset: 0x" + Integer.toHexString(headOffset) + "_" + Integer.toHexString(nodeOffset));

        logger.debug("move len:" + headMoveIndexArrLen);
        if (headMoveIndexArrLen > 0) {

            logger.debug("move index array:" + ByteTool.toHexString(1, headMoveIndexArr, 0, headMoveIndexArr.length));
        }
        logger.debug("node len:" + nodeValueLen);
        if (nodeValueLen > 0) {

            logger.debug("node value :" + ByteTool.toHexString(1, nodeValue, 0, nodeValue.length));
        }


        logger.debug("dataPage pageNumber: 0x" + Integer.toHexString(dataPageNum));


        logger.debug("dataPage Old|New UpBound: 0x" + Integer.toHexString(dataPageOldUpBound) + "_" + Integer.toHexString(dataPageNewUpBound));

        logger.debug("DataNode len:" + dataNodeValueLen);
        if (dataNodeValueLen > 0) {

            logger.debug("DataNode value :" + ByteTool.toHexString(1, dataNodeValue, 0, dataNodeValue.length));
        }

        //logger.log(ServerLog.LOG_DEBUG,"end: printing the information of BTreeInsertLeafNodeLogRecord object.");

    }

    /**
     * converts a log record instance into a byte array.
     * The byte array has the following format:
     * --------------------------------------------------------------------
     * | oldLowBound | oldUpBound | newLowBound | newUpBound              |
     * --------------------------------------------------------------------
     * | headOffset | nodeOffset | btreePageFlag | headMoveIndexArrLen    |
     * --------------------------------------------------------------------
     * | headMoveIndexArr | nodeValueLen | nodeValue | dataPageNum        |
     * --------------------------------------------------------------------
     * | dataPageOldUpBound |dataPageNewUpBound | dataNodeValueLen        |
     * --------------------------------------------------------------------
     * | nodeSize  |  dataNodeValue |                                     |
     * --------------------------------------------------------------------
     * oldLowBund: 2bytes
     * oldUpBound: 2bytes
     * newLowBound: 2bytes
     * newUpBound: 2bytes
     * headOffset: 2bytes
     * nodeOffset: 2bytes
     * btreePageFlag: 1byte
     * headMoveIndexArrLen: 2bytes
     * headMoveIndexArr: headMoveIndexArrLen bytes
     * nodeValueLen: 2bytes
     * nodeValue: nodeValueLen bytes
     * dataPageNum: 4bytes
     * dataPageOldUpBund: 2bytes
     * dataPageNewUpBound: 2bytes
     * dataNodeValueLen: 2bytes
     * nodeSize: 2bytes
     * dataNodeValue: dataNodeValueLen bytes
     */
    public void toBytes(byte[] byteArray, int start) throws ChaiDBException {
        super.toBytes(byteArray, start);
        int step = start + super.getRecordLength();

        ByteTool.shortToBytes(byteArray, step, oldLowBound);
        step += OLD_LOWBOUND_SIZE;

        ByteTool.shortToBytes(byteArray, step, oldUpBound);
        step += OLD_UPBOUND_SIZE;

        ByteTool.shortToBytes(byteArray, step, newLowBound);
        step += NEW_LOWBOUND_SIZE;

        ByteTool.shortToBytes(byteArray, step, newUpBound);
        step += NEW_UPBOUND_SIZE;

        ByteTool.shortToBytes(byteArray, step, headOffset);
        step += HEAD_OFFSET_SIZE;

        ByteTool.shortToBytes(byteArray, step, nodeOffset);
        step += NODE_OFFSET_SIZE;

        ByteTool.shortToBytes(byteArray, step, nodeSize);
        step += NODE_SIZE;

        ByteTool.shortToBytes(byteArray, step, compressedHeadMoveIndexArrLen);
        step += HEAD_MOVE_INDEX_LENGTH_SIZE;
        if (compressedHeadMoveIndexArrLen > 0) {
            System.arraycopy(compressedHeadMoveIndexArr, 0, byteArray, step, compressedHeadMoveIndexArrLen);
            step += compressedHeadMoveIndexArrLen;
        }

        ByteTool.shortToBytes(byteArray, step, nodeValueLen);
        step += NODE_VALUE_LENGTH_SIZE;
        if (nodeValueLen > 0) {
            System.arraycopy(nodeValue, 0, byteArray, step, nodeValueLen);
        }

        step += nodeValueLen;
        ByteTool.intToBytes(byteArray, step, dataPageNum, msbFirst);
        step += BTreeLogRecord.PAGENUM_SIZE;

        ByteTool.shortToBytes(byteArray, step, dataPageOldUpBound);
        step += OLD_UPBOUND_SIZE;

        ByteTool.shortToBytes(byteArray, step, dataPageNewUpBound);
        step += NEW_UPBOUND_SIZE;

        ByteTool.shortToBytes(byteArray, step, dataNodeValueLen);
        step += NODE_VALUE_LENGTH_SIZE;
        if (dataNodeValueLen > 0) {
            System.arraycopy(dataNodeValue, 0, byteArray, step, dataNodeValueLen);
        }
    }

    /**
     * get current log record type total length
     *
     * @return int total lenth
     */
    public int getRecordLength() {
        return super.getRecordLength() + OLD_LOWBOUND_SIZE + OLD_UPBOUND_SIZE * 2 + NEW_LOWBOUND_SIZE + NEW_UPBOUND_SIZE * 2 + HEAD_OFFSET_SIZE + NODE_OFFSET_SIZE + HEAD_MOVE_INDEX_LENGTH_SIZE + compressedHeadMoveIndexArrLen + NODE_VALUE_LENGTH_SIZE * 2 + NODE_SIZE + nodeValueLen + dataNodeValueLen + BTreeLogRecord.PAGENUM_SIZE;
    }

}
TOP

Related Classes of org.chaidb.db.log.logrecord.BTreeInsertLeafNodeLogRecord

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.