package org.cdlib.xtf.util;
/**
* Copyright (c) 2004, Regents of the University of California
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* - Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* - Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* - Neither the name of the University of California nor the names of its
* contributors may be used to endorse or promote products derived from this
* software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
import java.io.IOException;
import java.io.RandomAccessFile;
/**
* Represents a single sub-file within a {@link StructuredFile}. A sub-file
* provides standard DataInput/DataOutput facilities, and takes care of
* writing to the correct subset of the main StructuredFile.
*
* @author Martin Haye
*/
class SubFileWriter extends SubStoreWriter
{
/** Actual disk file to write to */
private RandomAccessFile file;
/** The structured file that owns this Subfile */
private StructuredFile parent;
/** Absolute file position for the subfile's start */
private long segOffset;
/** Current write position within the subfile */
private long writtenPos = 0;
/** Size of the buffer to maintain */
private static final int BUF_SIZE = 32768;
/** Buffered data (cuts down access to the physical file) */
private byte[] buf = new byte[BUF_SIZE];
/** Amount of data buffered */
private int bufTop = 0;
/**
* Construct a subfile writer.
*
* @param file Disk file to attach to
* @param parent Structured file to attach to
* @param segOffset Beginning offset of the segment
*/
SubFileWriter(RandomAccessFile file, StructuredFile parent, long segOffset)
throws IOException
{
this.file = file;
this.parent = parent;
this.segOffset = segOffset;
}
public void close()
throws IOException
{
synchronized (parent)
{
// Force a flush.
checkLength(BUF_SIZE);
// And notify the main StructuredFile.
parent.closeWriter(this);
file = null;
}
}
public long length()
throws IOException
{
return writtenPos + bufTop;
}
/**
* Ensure that the buffer has room for the specified number of bytes.
* If not, it is flushed.
*
* @param nBytes Amount of space desired
*/
private void checkLength(int nBytes)
throws IOException
{
if (parent.curSubFile != this) {
file.seek(writtenPos + segOffset);
parent.curSubFile = this;
}
if (bufTop + nBytes > BUF_SIZE) {
file.write(buf, 0, bufTop);
writtenPos += bufTop;
bufTop = 0;
}
}
public void write(byte[] b)
throws IOException
{
write(b, 0, b.length);
}
public void write(byte[] b, int off, int len)
throws IOException
{
synchronized (parent)
{
checkLength(len);
if (len > BUF_SIZE) {
file.write(b, off, len);
writtenPos += len;
}
else {
System.arraycopy(b, off, buf, bufTop, len);
bufTop += len;
}
}
}
public void writeByte(int v)
throws IOException
{
synchronized (parent) {
checkLength(1);
buf[bufTop++] = (byte)(v & 0xff);
}
}
public void writeInt(int v)
throws IOException
{
synchronized (parent) {
checkLength(4);
buf[bufTop++] = (byte)((v >>> 24) & 0xFF);
buf[bufTop++] = (byte)((v >>> 16) & 0xFF);
buf[bufTop++] = (byte)((v >>> 8) & 0xFF);
buf[bufTop++] = (byte)((v >>> 0) & 0xFF);
}
}
} // class Subfile