package org.jgroups.blocks; import org.jgroups.logging.Log; import org.jgroups.logging.LogFactory; import org.jgroups.annotations.Experimental; import java.io.*; /** * @author Bela Ban */ @Experimental public class GridInputStream extends InputStream { final ReplCache<String,byte[]> cache; final int chunk_size; final String name; protected final GridFile file; // file representing this input stream int index=0; // index into the file for writing int local_index=0; byte[] current_buffer=null; boolean end_reached=false; final static Log log=LogFactory.getLog(GridInputStream.class); GridInputStream(GridFile file, ReplCache<String, byte[]> cache, int chunk_size) throws FileNotFoundException { this.file=file; this.name=file.getPath(); this.cache=cache; this.chunk_size=chunk_size; } public int read() throws IOException { int bytes_remaining_to_read=getBytesRemainingInChunk(); if(bytes_remaining_to_read == 0) { if(end_reached) return -1; current_buffer=fetchNextChunk(); local_index=0; if(current_buffer == null) return -1; else if(current_buffer.length < chunk_size) end_reached=true; bytes_remaining_to_read=getBytesRemainingInChunk(); } int retval=current_buffer[local_index++]; index++; return retval; } public int read(byte[] b) throws IOException { return read(b, 0, b.length); } public int read(byte[] b, int off, int len) throws IOException { int bytes_read=0; while(len > 0) { int bytes_remaining_to_read=getBytesRemainingInChunk(); if(bytes_remaining_to_read == 0) { if(end_reached) return bytes_read > 0? bytes_read : -1; current_buffer=fetchNextChunk(); local_index=0; if(current_buffer == null) return bytes_read > 0? bytes_read : -1; else if(current_buffer.length < chunk_size) end_reached=true; bytes_remaining_to_read=getBytesRemainingInChunk(); } int bytes_to_read=Math.min(len, bytes_remaining_to_read); // bytes_to_read=Math.min(bytes_to_read, current_buffer.length - local_index); System.arraycopy(current_buffer, local_index, b, off, bytes_to_read); local_index+=bytes_to_read; off+=bytes_to_read; len-=bytes_to_read; bytes_read+=bytes_to_read; index+=bytes_to_read; } return bytes_read; } public long skip(long n) throws IOException { throw new UnsupportedOperationException(); } public int available() throws IOException { throw new UnsupportedOperationException(); } public void close() throws IOException { local_index=index=0; end_reached=false; } private int getBytesRemainingInChunk() { // return chunk_size - local_index; return current_buffer == null? 0 : current_buffer.length - local_index; } private byte[] fetchNextChunk() { int chunk_number=getChunkNumber(); String key=name + ".#" + chunk_number; byte[] val= cache.get(key); if(log.isTraceEnabled()) log.trace("fetching index=" + index + ", key=" + key +": " + (val != null? val.length + " bytes" : "null")); return val; } private int getChunkNumber() { return index / chunk_size; } }