Package org.xtreemfs.babudb.log

Source Code of org.xtreemfs.babudb.log.DiskLogFile

/*
* Copyright (c) 2008 - 2011, Jan Stender, Bjoern Kolbeck, Mikael Hoegqvist,
*                     Felix Hupfeld, Felix Langner, Zuse Institute Berlin
*
* Licensed under the BSD License, see LICENSE file for details.
*
*/

package org.xtreemfs.babudb.log;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.channels.FileChannel;
import java.util.zip.CRC32;
import java.util.zip.Checksum;

import org.xtreemfs.babudb.lsmdb.LSN;
import org.xtreemfs.foundation.buffer.BufferPool;
import org.xtreemfs.foundation.buffer.ReusableBuffer;
import org.xtreemfs.foundation.logging.Logging;

/**
* Interface for reading on-disk operation logs.
*
* @author bjko
*/
public class DiskLogFile {
   
    protected File            file;
   
    protected FileChannel     channel;
   
    protected FileInputStream fis;
   
    protected Checksum        csumAlgo;
   
    protected ByteBuffer      myInt;
   
    protected LogEntry        next;
   
    public DiskLogFile(String baseDir, LSN logLSN) throws IOException, LogEntryException {
        this(baseDir + DiskLogger.createLogFileName(logLSN.getViewId(), logLSN.getSequenceNo()));
    }
   
    public DiskLogFile(String filename) throws IOException, LogEntryException {
       
        file = new File(filename);
        fis = new FileInputStream(file);
        channel = fis.getChannel();
        myInt = ByteBuffer.allocate(Integer.SIZE / 8);
        csumAlgo = new CRC32();
       
        next = getNext();
    }
   
    public void close() throws IOException {
        LogEntry tmp = next;
        next = null;
        if (tmp != null) tmp.free();
        channel.close();
        fis.close();
    }
   
    public boolean hasNext() {
        return next != null;
    }
   
    public LogEntry next() throws LogEntryException {
        LogEntry tmp = next;
        next = getNext();
        return tmp;
    }
   
    protected LogEntry getNext() throws LogEntryException {
       
        long offset = -1;
        ReusableBuffer item = null;
        try {
           
            if (channel.position() == channel.size())
                return null;
           
            int numRead = channel.read(myInt);
            if (numRead < Integer.SIZE / 8)
                return null;
           
            myInt.flip();
            int entrySize = myInt.getInt();
            myInt.flip();
            offset = channel.position() - Integer.SIZE / 8;
            channel.position(offset);
           
            if (entrySize < 0)
                throw new LogEntryException("log entry with negative size detected: " + entrySize);
           
            item = BufferPool.allocate(entrySize);
            channel.read(item.getBuffer());
            item.flip();
            LogEntry e = LogEntry.deserialize(item, csumAlgo);
            csumAlgo.reset();
            return e;
           
        } catch (LogEntryException ex) {
           
            // in case of an invalid log entry ...
            Logging.logMessage(Logging.LEVEL_ERROR, this, "***** INVALID LOG ENTRY *****");
            Logging.logMessage(Logging.LEVEL_ERROR, this,
                "the log contains an invalid log entry at offset %d, file will be truncated at offset %d",
                offset, offset);
            Logging.logMessage(Logging.LEVEL_ERROR, this, ex.getMessage());
           
            // trucate the log at the end of the previous entry
            try {
               
                // close the channel
                channel.close();
               
                // truncate the file
                FileOutputStream fout = new FileOutputStream(file, true);
                fout.getChannel().truncate(offset);
                fout.close();
               
                // re-open the channel and set the position behind the last
                // entry
                fis = new FileInputStream(file);
                channel = fis.getChannel();
                channel.position(offset);
               
            } catch (IOException exc) {
                throw new LogEntryException("Cannot truncate log file: " + ex);
            }
           
            return null;
           
        } catch (IOException ex) {
           
            Logging.logMessage(Logging.LEVEL_DEBUG, this, ex.getMessage());
            throw new LogEntryException("Cannot read log entry: " + ex);
           
        } finally {
            if (item != null)
                BufferPool.free(item);
        }
       
    }
   
}
TOP

Related Classes of org.xtreemfs.babudb.log.DiskLogFile

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.