All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.bigdata.journal.DirectBufferStrategy Maven / Gradle / Ivy

/**

Copyright (C) SYSTAP, LLC DBA Blazegraph 2006-2016.  All rights reserved.

Contact:
     SYSTAP, LLC DBA Blazegraph
     2501 Calvert ST NW #106
     Washington, DC 20008
     [email protected]

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; version 2 of the License.

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.

You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
*/
package com.bigdata.journal;

import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.channels.ClosedByInterruptException;
import java.nio.channels.ClosedChannelException;
import java.util.concurrent.ExecutorService;

import com.bigdata.io.FileChannelUtility;

/**
 * Direct buffer strategy uses a direct {@link ByteBuffer} as a write through
 * cache and writes through to disk for persistence.
 * 
 * @author Bryan Thompson
 * @version $Id$
 * 
 * @see BufferMode#Direct
 * 
 * @todo modify to support aio (asynchronous io). aio can be supported with a
 *       2nd thread that writes behind from the cache to the file. force() will
 *       need to be modified to wait until the aio thread has caught up to the
 *       nextOffset (i.e., has written all data that is dirty on the buffer).
 */
public class DirectBufferStrategy extends DiskBackedBufferStrategy {

    DirectBufferStrategy(long maximumExtent, FileMetadata fileMetadata) {

        super(maximumExtent, BufferMode.Direct, fileMetadata);

    }

    public boolean isFullyBuffered() {
        
        return true;
        
    }
    
    /**
     * Extends the basic behavior to write through to the backing file.
     * 

* Note: {@link ClosedChannelException} can be thrown out of this method. * This exception is an indication that the backing channel was closed while * a writer was still running. *

* Note: {@link ClosedByInterruptException} can be thrown out of this method * (wrapped as a {@link RuntimeException}). This exception is an indication * that a writer was interrupted. This will occur if you are using * {@link ExecutorService#shutdownNow()} on a service that is running one or * more writers. In such cases this should not be considered an error but * the expected result of interrupting the writer. *

* However, note that {@link ClosedByInterruptException} means that the * channel was actually closed when the writer was * interrupted. This means that you basically can not interrupt running * writers without having to re-open the channel. */ public long write(final ByteBuffer data) { /* * write the record on the buffer - this also detects and handles * overflow, error checks the address range, etc. */ final long addr = super.write(data); // The offset into the buffer for this record. final long offset = getOffset(addr); // The length of the record. final int nbytes = getByteCount(addr); // obtain a view in case there are concurrent writes on the buffer. final ByteBuffer buffer = getBufferView(false/* readOnly */); // Set limit to just those bytes that were written on the buffer. buffer.limit( (int) offset + nbytes ); // Set position on the buffer. buffer.position( (int) offset ); try { /* * Write on the backing file. * * Note: We use the direct buffer as the source since it is a native * memory buffer so that transfer to the disk cache should be * optimized by Java and the OS. */ FileChannelUtility.writeAll(opener, buffer, headerSize + offset); } catch( IOException ex ) { throw new RuntimeException( ex ); } return addr; } synchronized public void truncate(final long newExtent) { super.truncate(newExtent); try { // extend the file. getRandomAccessFile().setLength(newExtent); /* * since we just changed the file length we force the data to disk * and update the file metadata. this is a relatively expensive * operation but we want to make sure that we do not loose track of * a change in the length of the file. * * @todo an alternative would be to set a marker on the buffer such * that the next force() also forced the metadata to disk. */ force(true); if (log.isDebugEnabled()) log.info("Disk file: newLength=" + cf.format(newExtent)); } catch(IOException ex) { throw new RuntimeException(ex); } } /** * Not needed for directBuffers */ public void setNextOffset(long lastOffset) { } }





© 2015 - 2025 Weber Informatics LLC | Privacy Policy