/*
* The contents of this file are subject to the Mozilla Public License
* Version 1.1 (the "License"); you may not use this file except in
* compliance with the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS"
* basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
* the License for the specific language governing rights and limitations
* under the License.
*
* The Original Code is the Kowari Metadata Store.
*
* The Initial Developer of the Original Code is Plugged In Software Pty
* Ltd (http://www.pisoftware.com, mailto:info@pisoftware.com). Portions
* created by Plugged In Software Pty Ltd are Copyright (C) 2001,2002
* Plugged In Software Pty Ltd. All Rights Reserved.
*
* Contributor(s): N/A.
*
* [NOTE: The text of this Exhibit A may differ slightly from the text
* of the notices in the Source Code files of the Original Code. You
* should use the text of this Exhibit A rather than the text found in the
* Original Code Source Code for Your Modifications.]
*
*/
package org.mulgara.util;
// Java 2 standard packages
import java.io.*;
import java.nio.*;
// Third party packages
import org.apache.log4j.*;
/**
* An IntFile that is accessed using explicit I/O.
*
* @created 2003-01-09
*
* @author David Makepeace
*
* @version $Revision: 1.9 $
*
* @modified $Date: 2005/01/05 04:59:29 $
*
* @maintenanceAuthor $Author: newmana $
*
* @company <A href="mailto:info@PIsoftware.com">Plugged In Software</A>
*
* @copyright © 2001-2003 <A href="http://www.PIsoftware.com/">Plugged In
* Software Pty Ltd</A>
*
* @licence <a href="{@docRoot}/../../LICENCE">Mozilla Public License v1.1</a>
*/
public final class ExplicitIntFile extends IntFile {
@SuppressWarnings("unused")
private static final Logger logger = Logger.getLogger(ExplicitIntFile.class.getName());
private ByteBuffer byteBuffer;
private IntBuffer intBuffer;
private LongBuffer longBuffer;
private long fileSize; // The current size of the file in longs.
/**
* Constructs an ExplicitIntFile for the specified file.
*
* @param file The file to open.
* @throws IOException if an I/O error occurs.
*/
ExplicitIntFile(File file) throws IOException {
super(file);
fileSize = size;
byteBuffer = ByteBuffer.allocateDirect(SIZEOF_LONG);
intBuffer = byteBuffer.asIntBuffer();
longBuffer = byteBuffer.asLongBuffer();
}
/**
* Sets the size of the file in longs. The file will be truncated if
* <code>newSize</code> is less than the current size.
*
* @param newSize the new size of the file in longs.
* @throws IOException if an I/O error occurs.
*/
public void setSize(long newSize) throws IOException {
super.setSize(newSize);
if (newSize <= fileSize) {
fileSize = newSize;
truncate(fileSize * SIZEOF_LONG);
}
}
/**
* Reads the long at the specified offset into the file.
*
* @param key The offset into the file in longs.
* @return the long at the specified offset.
*/
public synchronized long getLong(long key) {
assert key >= 0;
if (key >= fileSize) {
return 0;
}
byteBuffer.clear();
try {
// TODO Handle ClosedChannelException and reopen FileChannel.
if (fc.read(byteBuffer, key * SIZEOF_LONG) != SIZEOF_LONG) {
throw new RuntimeException("Short read of IntFile: " + file);
}
} catch (IOException ex) {
throw new RuntimeException("IOException: " + file, ex);
}
return longBuffer.get(0);
}
/**
* Reads the int at the specified offset into the file.
*
* @param key The offset into the file in ints.
* @return the int at the specified offset.
*/
public synchronized int getInt(long key) {
assert key >= 0;
if ((key / (SIZEOF_LONG / SIZEOF_INT)) >= fileSize) {
return 0;
}
byteBuffer.limit(SIZEOF_INT);
byteBuffer.rewind();
try {
// TODO Handle ClosedChannelException and reopen FileChannel.
if (fc.read(byteBuffer, key * SIZEOF_INT) != SIZEOF_INT) {
throw new RuntimeException("Short read of IntFile: " + file);
}
} catch (IOException ex) {
throw new RuntimeException("IOException: " + file, ex);
}
return intBuffer.get(0);
}
/**
* Reads the byte at the specified offset into the file.
*
* @param key The offset into the file in bytes.
* @return the byte at the specified offset.
*/
public synchronized byte getByte(long key) {
assert key >= 0;
if ((key / SIZEOF_LONG) >= fileSize) {
return 0;
}
byteBuffer.limit(1);
byteBuffer.rewind();
try {
// TODO Handle ClosedChannelException and reopen FileChannel.
if (fc.read(byteBuffer, key) != 1) {
throw new RuntimeException("Short read of IntFile: " + file);
}
} catch (IOException ex) {
throw new RuntimeException("IOException: " + file, ex);
}
return byteBuffer.get(0);
}
/**
* Writes a long to the file at the specified offset.
*
* @param key The offset into the file in longs.
* @param l The long to write.
* @throws IOException if an I/O error occurs.
*/
public synchronized void putLong(long key, long l) throws IOException {
assert key >= 0;
// Auto-expand.
if (key >= fileSize) {
if (l == 0) {
return;
}
fileSize = key + 1;
if (fileSize > size) {
size = fileSize;
}
}
byteBuffer.clear();
longBuffer.put(0, l);
// TODO Handle ClosedChannelException and reopen FileChannel.
if (fc.write(byteBuffer, key * SIZEOF_LONG) != SIZEOF_LONG) {
throw new RuntimeException("Short write of IntFile: " + file);
}
}
/**
* Writes an int to the file at the specified offset.
*
* @param key The offset into the file in ints.
* @param i The int to write.
* @throws IOException if an I/O error occurs.
*/
public synchronized void putInt(long key, int i) throws IOException {
assert key >= 0;
// Auto-expand.
long lKey = key / (SIZEOF_LONG / SIZEOF_INT);
if (lKey >= fileSize) {
if (i == 0) {
return;
}
putLong(lKey, 0);
}
byteBuffer.limit(SIZEOF_INT);
byteBuffer.rewind();
intBuffer.put(0, i);
// TODO Handle ClosedChannelException and reopen FileChannel.
if (fc.write(byteBuffer, key * SIZEOF_INT) != SIZEOF_INT) {
throw new RuntimeException("Short write of IntFile: " + file);
}
}
/**
* Writes a byte to the file at the specified offset.
*
* @param key The offset into the file in bytes.
* @param b The byte to write.
* @throws IOException if an I/O error occurs.
*/
public synchronized void putByte(long key, byte b) throws IOException {
assert key >= 0;
// Auto-expand.
long lKey = key / SIZEOF_LONG;
if (lKey >= fileSize) {
if (b == 0) {
return;
}
putLong(lKey, 0);
}
byteBuffer.limit(1);
byteBuffer.rewind();
byteBuffer.put(0, b);
// TODO Handle ClosedChannelException and reopen FileChannel.
if (fc.write(byteBuffer, key) != 1) {
throw new RuntimeException("Short write of IntFile: " + file);
}
}
/**
* Truncates the file to zero length.
*
* @throws IOException if an I/O error occurs.
*/
public void clear() throws IOException {
fileSize = 0;
super.clear();
}
/**
* Closes the file.
*
* @throws IOException if an I/O error occurs.
*/
public synchronized void close() throws IOException {
byteBuffer = null;
intBuffer = null;
longBuffer = null;
super.close();
}
}