/** Copyright (C) SYSTAP, LLC DBA Blazegraph 2006-2016. All rights reserved. Contact: SYSTAP, LLC DBA Blazegraph 2501 Calvert ST NW #106 Washington, DC 20008 licenses@blazegraph.com 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.nio.MappedByteBuffer; import java.nio.channels.FileLock; /** * <p> * Memory-mapped journal strategy (this mode is NOT recommended). * </p> * <p> * Note: the use of {@link FileLock} with a memory-mapped file is NOT * recommended by the JDK as this combination is not permitted on some * platforms. * </p> * <p> * Note: Extension and truncation of a mapped file are not possible with the JDK * since there is no way to guarentee that the mapped file will be unmapped in a * timely manner. Journals that handle {@link IJournal#overflow()} should * trigger overflow just a bit earlier for a {@link MappedByteBuffer} in an * attempt to avoid running out of space in the journal. If a transaction can * not be committed due to overflow, it could be re-committed <em>after</em> * handling the overflow event (e.g., throw a "CommitRetryException"). * </p> * <p> * The mapped mode has nearly the performance of the transient mode in some * tests. However the use of mapped files might not prove worth the candle due * to the difficulties with resource deallocation for this strategy and the good * performance of some alternative strategies. There are also some other issues * that have shown up in some of the tests suites -- look carefully if you are * going to pursue this! * </p> * * @author <a href="mailto:thompsonbry@users.sourceforge.net">Bryan Thompson</a> * @version $Id$ * * @see http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=4724038 * @see BufferMode#Mapped */ public class MappedBufferStrategy extends DiskBackedBufferStrategy { /** * A strongly typed reference to the buffer exposing memory-map specific * operations. * <p> * Note: The buffer is mapped onto the user extent from the first byte after * the root blocks through the last byte of the file. This means that we do * not need to translate the offset of an address when writing onto the * buffer. */ final MappedByteBuffer mappedBuffer; public boolean isFullyBuffered() { return false; } MappedBufferStrategy(long maximumExtent, FileMetadata fileMetadata) { super(maximumExtent, BufferMode.Mapped, fileMetadata); this.mappedBuffer = (MappedByteBuffer) fileMetadata.buffer; } /** * Force the data to disk. * * @see MappedByteBuffer#force() */ public void force(boolean metadata) { mappedBuffer.force(); // Note: This super class invocation is probably not required. super.force(metadata ); } /** * The file channel is closed, but according to * http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=4724038 there is no * way to guarentee when the mapped file will be released. */ public void close() { super.close(); } /** * Overrides the default behavior so that an exception is NOT thrown if the * file can not be deleted. Since Java can not provide for synchronous unmap * of memory-mapped files, we can not delete the backing file immediately. * Instead, we mark the file for "deleteOnExit" and let the VM attempt to * clean it up when it exits. */ public void deleteResources() { if( isOpen() ) { throw new IllegalStateException(); } if( ! file.delete() ) { log.warn("Could not delete memory-mapped file: " + file.getAbsoluteFile() + " - marked for deletion on exit"); try { file.deleteOnExit(); } catch(NullPointerException ex) { /* * Ignore NPE caused by a known Sun bug. * * See http://bugs.sun.com/view_bug.do?bug_id=6526376 */ } } } /** * Note: Extension and truncation of a mapped file are not possible with the * JDK since there is no way to guarentee that the mapped file will be * unmapped in a timely manner. * * @exception UnsupportedOperationException * Always thrown. */ public void truncate(long newExtent) { throw new UnsupportedOperationException( "Mapped file may not be extended or truncated."); } }