package com.bigdata.rwstore.sector;
import java.io.*;
import java.nio.ByteBuffer;
import org.apache.log4j.Logger;
/************************************************************************
* PSInputStream
*
* Unlike the original PSInputStream this does not incrementally read
* from the store but rather immediate maps the ByteBuffers to the
* in-memory storage.
**/
public class PSInputStream extends InputStream {
/**
* Logger.
*/
final private static Logger log = Logger.getLogger(PSInputStream.class);
final ByteBuffer[] m_buffers;
int m_index = 0;
int m_cursor = 0;
public PSInputStream(IMemoryManager mm, long addr) {
int sze = mm.allocationSize(addr);
if (sze > SectorAllocator.BLOB_SIZE) {
int buffers = 1 + (sze-1)/SectorAllocator.BLOB_SIZE;
m_buffers = new ByteBuffer[buffers];
// blob header
ByteBuffer[] hdr = mm.get((addr & 0xFFFFFFFF00000000L) + ((buffers+1)*4));
/*
* The header can itself be a blob array of buffers
*/
int rem = sze;
int hdrsze = hdr[0].getInt();
if (hdrsze != buffers)
throw new IllegalStateException("Check blob header assumptions: hdrsize("
+ hdrsze + ") != buffers(" + buffers + ")");
/*
* Calculate the data remaining in all header buffers
*/
{
int totalRemaining = 0;
for (ByteBuffer hbuf : hdr) {
totalRemaining += hbuf.remaining();
}
if (totalRemaining != (buffers*4))
throw new IllegalStateException("Check blob header assumptions, remaining: "
+ totalRemaining + " for " + buffers + " buffers");
}
int index = 0;
int hdrIndex = 0;
while (rem > SectorAllocator.BLOB_SIZE) {
long ba = hdr[hdrIndex].getInt();
ba <<= 32;
ByteBuffer[] block = mm.get(ba + SectorAllocator.BLOB_SIZE);
m_buffers[index++] = block[0];
rem -= SectorAllocator.BLOB_SIZE;
if (hdr[hdrIndex].remaining() == 0) {
hdrIndex++; // next header buffer
}
}
if (rem > 0) {
long ba = hdr[hdrIndex].getInt();
ba <<= 32;
ByteBuffer[] block = mm.get(ba + rem);
m_buffers[index] = block[0];
}
} else if (sze == 0) {
m_buffers = new ByteBuffer[0];
} else {
m_buffers = mm.get(addr);
}
}
@Override
public int read() throws IOException {
if (m_index >= m_buffers.length)
return -1;
final ByteBuffer buf = m_buffers[m_index];
final int rem = buf.remaining();
assert rem > 0;
if (rem == 1)
m_index++;
return 0xFF & buf.get();
}
public synchronized int read(byte b[], int off, int len) throws IOException {
if (m_index >= m_buffers.length)
return -1;
ByteBuffer buf = m_buffers[m_index];
int rem = buf.remaining();
int retlen = 0;
while (len > rem) {
buf.get(b, off, rem);
retlen += rem;
off += rem;
len -= rem;
if (++m_index == m_buffers.length)
return retlen;
buf = m_buffers[m_index];
rem = buf.remaining();
}
if (len > 0) {
buf.get(b, off, len);
rem -= len;
retlen += len;
if (rem == 0)
m_index++;
}
return retlen;
}
}