/*
* 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;
import java.util.Vector;
/**
* files deletion log.
* Fields:
* fileName: String file name
* operationFlag: byte operation flag:delete or new
* fileOrDirFlag: byte file or directory
*/
public class FilesDeleteLogRecord extends LogRecord {
private static final Logger logger = Logger.getLogger(FilesDeleteLogRecord.class);
private static PageBufferManager bpm = PageBufferManager.getInstance();
/**
* delete files number
*/
private short deleteFilesNumber;
/**
* file name list
*/
private Vector deleteFiles = new Vector();
static final byte DELETE_FILES_NUMBER_SIZE = 2; //2bytes
static final byte FILENAME_LENGTH_SIZE = 2; //4 bytes
/**
* Default Constructor
*/
public FilesDeleteLogRecord() {
super();
}
/**
* Constructor
*
* @param deleteFiles
* @param txnId
*/
public FilesDeleteLogRecord(Vector deleteFiles, int txnId) {
super();
super.setTxnId(txnId);
super.setType(LOG_DELETE_FILES);
if (deleteFiles.size() > 0) {
this.deleteFilesNumber = (short) deleteFiles.size();
this.deleteFiles = deleteFiles;
}
}
public Vector getDeleteFilesList() {
return deleteFiles;
}
/**
* 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 = 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();
deleteFilesNumber = ByteTool.bytesToShort(bArr, step, msbFirst);
step += DELETE_FILES_NUMBER_SIZE;
short fileNameLen = 0;
deleteFiles = new Vector();
for (int i = 0; i < deleteFilesNumber; i++) {
fileNameLen = ByteTool.bytesToShort(bArr, step, msbFirst);
step += FILENAME_LENGTH_SIZE;
byte[] fileNameArr = new byte[fileNameLen];
System.arraycopy(bArr, step, fileNameArr, 0, fileNameLen);
deleteFiles.add(bpm.getFullPath(ByteTool.toString(fileNameArr)));
step += fileNameLen;
}
return true;
}
/**
* redo or undo the operation for recovery
* 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 {
if (deleteFilesNumber <= 0) return true;
try {
for (int i = 0; i < deleteFilesNumber; i++) {
String fileName = (String) deleteFiles.get(i);
File file = new File(fileName);
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 (deleteFilesNumber > 0) {
{
logger.debug("DELETE FILE List:");
}
for (int i = 0; i < deleteFilesNumber; i++) {
{
logger.debug(deleteFiles.get(i));
}
}
}
}
/**
* converts a log record instance into a byte array.
* The byte array has the following format:
* ----------------------------------------------------------------------
* | hdr | type | txn | prevLsn | deleteFilesNumber|fileNameLen | fileName
* ----------------------------------------------------------------------
* |fileNameLen|fileName....
* --------------------------
* deleteFilesNumber: 2bytes
* fileNameLen : 2 bytes.
* fileName: fileNameLen 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, deleteFilesNumber);
step += DELETE_FILES_NUMBER_SIZE;
short fileNameLen;
String fileName = "";
String rname = "";
for (int i = 0; i < deleteFilesNumber; i++) {
fileName = (String) deleteFiles.get(i);
rname = bpm.getRelatviePath(fileName);
fileNameLen = (short) rname.length();
ByteTool.shortToBytes(byteArray, step, fileNameLen);
step += FILENAME_LENGTH_SIZE;
System.arraycopy(rname.getBytes(), 0, byteArray, step, fileNameLen);
step += fileNameLen;
}
}
/**
* get current log record type total length
*
* @return int total lenth
*/
public int getRecordLength() {
int recordLen = super.getRecordLength() + DELETE_FILES_NUMBER_SIZE;
short fileNameLen;
String fileName = "";
String rname = "";
for (int i = 0; i < deleteFilesNumber; i++) {
fileName = (String) deleteFiles.get(i);
rname = bpm.getRelatviePath(fileName);
fileNameLen = (short) rname.length();
recordLen += FILENAME_LENGTH_SIZE;
recordLen += fileNameLen;
}
return recordLen;
}
}