package com.asgow.ciel.io;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import com.asgow.ciel.executor.Ciel;
import com.asgow.ciel.references.Reference;
import com.asgow.ciel.rpc.WorkerRpc.WaitAsyncInputResponse;
public class CielInputStream extends InputStream {
private InputStream real_is;
private boolean done;
private boolean succeeded;
private boolean blocking;
private boolean must_close;
private int size;
private long bytes_read;
private Reference ref;
private int chunk_size;
public CielInputStream(Reference ref, int chunk_size, String filename, boolean done, boolean blocking, int initial_size) {
try {
this.real_is = new FileInputStream(filename);
} catch (FileNotFoundException e) {
throw new RuntimeException(e);
}
this.ref = ref;
this.done = done;
if(done)
this.succeeded = true;
this.chunk_size = chunk_size;
this.must_close = !done;
this.blocking = blocking;
this.size = initial_size;
this.bytes_read = 0;
}
private void waitForMore() throws IOException {
long target_size = this.bytes_read + this.chunk_size;
WaitAsyncInputResponse response = Ciel.RPC.waitAsyncInput(this.ref.getId(), false, target_size);
this.size = response.size;
this.done = response.done;
this.succeeded = response.success;
if(!this.succeeded) {
throw new IOException("Failure reported waiting for ref " + this.ref.getId());
}
}
@Override
public int read() throws IOException {
for(int i = 0; i < 10; i++) {
int ret = this.real_is.read();
if(ret == -1) {
if(this.done || this.blocking) {
return ret;
}
else {
waitForMore();
}
}
else {
bytes_read++;
return ret;
}
}
throw new IOException("Too many retries reading " + this.ref.toString());
}
@Override
public int available() throws IOException {
return this.real_is.available();
}
@Override
public void close() throws IOException {
this.real_is.close();
if(this.must_close) {
Ciel.RPC.closeAsyncInput(this.ref.getId(), this.chunk_size);
}
}
@Override
public boolean markSupported() {
return false;
}
@Override
public int read(byte[] b, int off, int len) throws IOException {
for(int i = 0; i < 10; i++) {
int ret = this.real_is.read(b, off, len);
if(ret == -1) {
if(this.done || this.blocking) {
return ret;
}
else {
waitForMore();
}
}
else {
bytes_read += ret;
return ret;
}
}
throw new IOException("Too many retries trying to read " + this.ref.getId());
}
@Override
public int read(byte[] b) throws IOException {
return read(b, 0, b.length);
}
@Override
public long skip(long n) throws IOException {
for(int i = 0; i < 10; i++) {
long ret = this.real_is.skip(n);
if(ret == 0) {
if(this.done || this.blocking) {
return 0;
}
else {
waitForMore();
}
}
else {
bytes_read += ret;
return ret;
}
}
throw new IOException("Too many retries skipping " + n + " bytes of ref " + this.ref.getId());
}
}