RAStreamBufferMgr.java from BIRT at Krugle
Show RAStreamBufferMgr.java syntax highlighted
/*******************************************************************************
* Copyright (c) 2004 Actuate Corporation.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Actuate Corporation - initial API and implementation
*******************************************************************************/
package org.eclipse.birt.core.archive;
import java.io.IOException;
import java.io.RandomAccessFile;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.eclipse.birt.core.util.IOUtil;
public class RAStreamBufferMgr {
private RandomAccessFile randomFile;
// The total number of buffer has been allocated.
private int totalBuffer;
// An arraylist to keep the buffer in order.
// When MAX_NUMBER_OF_STREAM_BUFFER has been reached, we reuse the
// buffer from the beginning of the list. There is less chance they
// are going to be visited again.
private List bufferList = new ArrayList( IOUtil.MAX_NUMBER_OF_STREAM_BUFFER );
// A hash table to map between offset and buffer
private Map bufferMap = new HashMap();
// The buffer will be used for next operation
private RAStreamBuffer currentBuffer;
public RAStreamBufferMgr( RandomAccessFile randomFile ) throws IOException
{
this.randomFile = randomFile;
this.totalBuffer = 0;
this.currentBuffer = getBuffer( 0 );
}
/*
* The file pointer in the underlying file if no buffer is used.
*/
public long getFilePointer( )
{
return currentBuffer.getOffset() + currentBuffer.getBufCur();
}
/*
* Write the data in array b[], if current buffer is not enough to hold
* all the data, a new buffer will be allocated or an old buffer will
* be reused.
*/
public void write (byte b[], int off, int len ) throws IOException
{
while ( len > 0 )
{
int ret = currentBuffer.write( b, off, len );
len -= ret;
off += ret;
if ( len > 0)
{
currentBuffer = getBuffer( currentBuffer.getOffset()
+ IOUtil.RA_STREAM_BUFFER_LENGTH);
currentBuffer.setBufCur( 0 );
}
}
}
public void seek( long localPos ) throws IOException
{
long offset = ( localPos / IOUtil.RA_STREAM_BUFFER_LENGTH )
* IOUtil.RA_STREAM_BUFFER_LENGTH;
if ( currentBuffer.getOffset() != offset )
currentBuffer = getBuffer( offset );
currentBuffer.setBufCur( (int)(localPos - offset) );
}
/*
* Flush all the buffers
*/
public void flushBuffer() throws IOException
{
for ( int i = 0; i < totalBuffer; i++ )
{
RAStreamBuffer buffer = (RAStreamBuffer)bufferList.get(i);
buffer.flushBuffer();
}
}
/**
* Get next available buffer for the data from position offset.
* @param offset
* @return
* @throws IOException
*/
private RAStreamBuffer getBuffer( long offset ) throws IOException
{
// If we already have a buffer allocated for that offset, just
// return it.
Long offsetKey = new Long(offset);
RAStreamBuffer buffer = (RAStreamBuffer)bufferMap.get( offsetKey );
if ( buffer != null )
return buffer;
// If not, and MAX_NUMBER_OF_STREAM_BUFFER has not been reached,
// allocate a new buffer for it.
if ( totalBuffer < IOUtil.MAX_NUMBER_OF_STREAM_BUFFER )
{
buffer = new RAStreamBuffer( this.randomFile );
buffer.resetBuffer( offset );
totalBuffer ++;
bufferList.add( buffer );
bufferMap.put(offsetKey, buffer);
return buffer;
}
// If no buffer has been found, and MAX_NUMBER_OF_STREAM_BUFFER has
// been reached, reuse the buffer from the beginning of the list and
// put the buffer to the end of the list.
buffer = (RAStreamBuffer)bufferList.get( 0 );
buffer.flushBuffer();
bufferMap.remove( new Long(buffer.getOffset()) );
buffer.resetBuffer( offset );
bufferMap.put( offsetKey, buffer);
bufferList.remove( 0 );
bufferList.add( buffer );
return buffer;
}
}
See more files for this project here