Package org.chaidb.db.log.logrecord

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

/*
* 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.Db;
import org.chaidb.db.exception.ChaiDBException;
import org.chaidb.db.helper.ByteTool;
import org.chaidb.db.helper.Config;
import org.chaidb.db.helper.FileUtil;
import org.chaidb.db.index.btree.bufmgr.PageBufferManager;
import org.chaidb.db.log.LogManager;
import org.chaidb.db.log.LogRecord;
import org.chaidb.db.log.Lsn;

import java.io.File;


/**
* file operations log.
* Fields:
* fileName: String  file name
* operationFlag: byte operation flag:delete or new
* fileOrDirFlag: byte file or directory
*/
public class FileOperationLogRecord extends LogRecord {
    private static final Logger logger = Logger.getLogger(FileOperationLogRecord.class);

    private static PageBufferManager bpm = PageBufferManager.getInstance();
    static final byte FILENAME_LENGTH_SIZE = 2; //4 bytes
    static final byte FLAG_SIZE = 1; //1 bytes
    public static final byte FILE_UPDATE_OPE_BYTE = 2;
    public static final byte FILE_NEW_OPERATION = 1;
    public static final byte FILE_DELETE_OPERATION = 0;
    public static final byte FILE_FLAG = 1;
    public static final byte DIRECTORY_FLAG = 0;

    /**
     * file name
     */
    private String fileName = "";

    /**
     * file name String length
     */
    private short rNameLen;
    private String rName = "";

    /**
     * operation flag
     * flag :1 new
     * :0 delete
     */
    private byte operationFlag;

    /**
     * file or directory flag
     * fileOrDirFlag: 0 dir
     * : 1 file
     */
    private byte fileOrDirFlag;

    /**
     * Default Constructor
     */
    public FileOperationLogRecord() {
        super();
    }

    /**
     * Constructor
     *
     * @param fileName
     * @param operationFlag
     * @param fileOrDirFlag
     * @param txnId
     */
    public FileOperationLogRecord(String fileName, byte operationFlag, byte fileOrDirFlag, int txnId) {
        super();
        this.fileName = fileName;
        this.rName = bpm.getRelatviePath(fileName);
        this.rNameLen = (short) rName.length();
        this.operationFlag = operationFlag;
        this.fileOrDirFlag = fileOrDirFlag;
        super.setTxnId(txnId);
        super.setType(LOG_FILE_OPERATION);
    }

    /**
     * get operation flag
     */
    public byte getOperationFlag() {
        return operationFlag;
    }

    public String getFileName() {
        return fileName;
    }

    public byte getFileOrDirFlag() {
        return fileOrDirFlag;
    }

    /**
     * just for compatible
     */
    public String getBTreeFileName() {
        return null;
    }

    /**
     * user interface to add a log record and put it to buffer pool
     */
    public Lsn log() throws ChaiDBException {
        if (!Config.TXN_SUPPORT) {
            return null;
        }

        super.log();

        LogManager logMgr = Db.getLogManager();
        Lsn newLsn = null;

        //        if (operationFlag == FILE_DELETE_OPERATION) {
        //            newLsn = logMgr.put(this, LogManager.LOG_FLUSH);//flush log to log file while do delete collection/index operation
        //        } else {
        //            newLsn = logMgr.put(this, LogManager.LOG_DATA);//not flush log to log file,just put it to log buffer
        //        }

        /* modified by marriane 2003-11-6,flush log either deleting or creating operation for fixing inconsistent issue */
        newLsn = logMgr.put(this, LogManager.LOG_FLUSH);

        return newLsn;
    }

    /**
     * converts a byte array into a log record instance
     *
     * @param bArr
     * @param start pointer
     * @return boolean true|false
     */
    public boolean read(byte[] bArr, int start) throws ChaiDBException {
        /* construct a new LogRecord instance */
        super.read(bArr, start);

        /* get the values of FileOperationLogRecord Object */
        int step = start + super.getRecordLength();

        rNameLen = ByteTool.bytesToShort(bArr, step, msbFirst);

        step += FILENAME_LENGTH_SIZE;

        byte[] fileNameArr = new byte[rNameLen];
        System.arraycopy(bArr, step, fileNameArr, 0, rNameLen);
        rName = ByteTool.toString(fileNameArr);
        fileName = bpm.getFullPath(rName);

        step += rNameLen;
        operationFlag = bArr[step];

        step += FLAG_SIZE;
        fileOrDirFlag = bArr[step];

        return true;
    }

    /**
     * redo or undo the operation for recovery
     * REDO:
     * NEW_REDO:
     * if file is directory,mkdirs()
     * else, createNewFile()
     * DELETE_REDO:
     * if file is directory,delete all files in the path and the path self.
     * else, delete the file self.
     * UNDO:
     * NEW_UNDO:
     * if file is directory,delete all files in the path and the path self.
     * else, delete the file self.
     * DELETE_UNDO:
     * do REDO operation,because deleting operation couldn't be UNDO.
     *
     * @param recoverFlag REDO or UNDO.
     * @return boolean true|false
     */
    public boolean recover(short recoverFlag) throws ChaiDBException {
        try {
            File file = new File(fileName);
            boolean existFlag = file.exists();

            /* do REDO */
            if ((recoverFlag == LogRecord.REDO) && (operationFlag == FILE_NEW_OPERATION) && (!existFlag)) {
                /* renew the file or recreate the directory */
                if (fileOrDirFlag == DIRECTORY_FLAG) {
                    file.mkdirs();
                } else {
                    file.createNewFile();
                }
            } else
            if (((recoverFlag == LogRecord.REDO) && (operationFlag == FILE_DELETE_OPERATION) && existFlag) || ((recoverFlag == LogRecord.UNDO) && (((operationFlag == FILE_NEW_OPERATION) && existFlag) || (operationFlag == FILE_DELETE_OPERATION) || (operationFlag == FILE_UPDATE_OPE_BYTE)))) {
                /* modified by marriane for close btree while delete
                directory or file */
                try {
                    if (file.isFile()) {
                        bpm.dCloseBTree(file.getAbsolutePath());
                    } else {
                        bpm.dCloseAllTreesofCollection(file);
                    }
                } finally {
                    FileUtil.removeFileOrDirectory(file); //modified by marriane 2003-11-6 for fixing bug #4644.
                }
            }

            return true;
        } catch (Exception e) {
            {
                logger.debug(e);
            }

            return false;
        }
    }

    /**
     * print data and help in debugging log files
     */
    public void print() throws ChaiDBException {
        super.print();

        if (fileOrDirFlag == FILE_FLAG) {
            {
                logger.debug("file opration");
            }
        } else if (fileOrDirFlag == DIRECTORY_FLAG) {
            {
                logger.debug("directory operatin");
            }
        }

        {
            logger.debug("name:" + fileName);
        }

        if (operationFlag == FILE_NEW_OPERATION) {
            {
                logger.debug("[operation]: NEW FILE");
            }
        } else if (operationFlag == FILE_DELETE_OPERATION) {
            {
                logger.debug("[operation]: DELETE FILE");
            }
        }
    }

    /**
     * converts a log record instance into a byte array.
     * The byte array has the following format:
     * ----------------------------------------------------------------------
     * | hdr | type | txn | prevLsn | rNameLen | fileName | operationFlag |
     * ----------------------------------------------------------------------
     * | fileOrDirFlag
     * ----------------------------------------------------------------------
     * rNameLen : 2  bytes.
     * fileName:     rNameLen bytes.
     * operationFlag: 1 bytes.
     * fileOrDirFlag: 1 bytes.
     *
     * @param byteArray
     * @param start     pointer
     */
    public void toBytes(byte[] byteArray, int start) throws ChaiDBException {
        super.toBytes(byteArray, start);

        int step = start + super.getRecordLength();
        ByteTool.shortToBytes(byteArray, step, rNameLen);

        step += FILENAME_LENGTH_SIZE;
        System.arraycopy(rName.getBytes(), 0, byteArray, step, rNameLen);

        step += rNameLen;
        byteArray[step] = operationFlag;
        step += FLAG_SIZE;
        byteArray[step] = fileOrDirFlag;
    }

    /**
     * get current log record type total length
     *
     * @return int total lenth
     */
    public int getRecordLength() {
        return super.getRecordLength() + FILENAME_LENGTH_SIZE + rNameLen + (FLAG_SIZE * 2);
    }
}
TOP

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

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.