package multimonster.converter.plugin.jmx;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import org.apache.log4j.Logger;
import multimonster.common.pipe.Pipe;
import multimonster.common.pipe.PipeClosedException;
/**
* @author Holger Velke
*/
public class FileToPipe implements Runnable {
private static Logger log = Logger.getLogger(FileToPipe.class);
private static int RETRY_MAX = 20;
private static long RETRY_DELAY = 250; //ms
private int MAX_BUF_SIZE = Pipe.getPipeSegmentSize(); //8 kB
private String inputFileName = null;
private Pipe output = null;
private Process transcode = null;
private boolean transcodeKilled = false;
private boolean inputFileGrowing = true;
private int count = 0;
private static final long WAIT_TIME = 40;
/**
* @param from_tc_fileName
* @param output
*/
public FileToPipe(String inputFileName, Pipe output, Process transcode) {
if (inputFileName == null)
throw new IllegalArgumentException("inputFileName is 'null'");
this.inputFileName = inputFileName;
if (output == null)
throw new IllegalArgumentException("output Pipe is 'null'");
this.output = output;
if (transcode == null)
throw new IllegalArgumentException("reference to transcode is 'null'");
this.transcode = transcode;
}
/* (non-Javadoc)
* @see java.lang.Runnable#run()
*/
public void run() {
FileInputStream input = null;
input = getTranscodeOutput();
if (input == null) {
output.close();
log.error("unable to find transcodes output file: "+inputFileName);
return;
}
try {
try {
byte[] buf = new byte[MAX_BUF_SIZE];
int readSize = 0;
while (true) {
readSize = getNextReadSize(input);
if (readSize != 0) {
int read = 0;
read = input.read(buf,0,readSize);
if (-1 == read)
break;
output.write(buf, read);
count += buf.length;
} else if (output.isClosed()){
killTranscode();
break;
}
}
input.close();
output.close();
} catch (PipeClosedException e) {
// output-pipe closed, no need to do more conversion-work
input.close();
killTranscode();
}
} catch (IOException e) {
log.error(e);
}
log.debug("finished " + count + " bytes");
}
/**
* @param inputFileGrowing The inputFileGrowing to set.
*/
public void setInputFileGrowing(boolean inputFileGrowing) {
this.inputFileGrowing = inputFileGrowing;
}
/**
* @return Returns the transcodeKilled.
*/
public boolean isTranscodeKilled() {
return transcodeKilled;
}
private FileInputStream getTranscodeOutput(){
FileInputStream input = null;
for (int i = 0; i < RETRY_MAX; i++) {
try {
input = new FileInputStream(inputFileName);
} catch (FileNotFoundException e) {
input = null;
}
if (input != null)
break;
synchronized (this) {
try {
wait(RETRY_DELAY);
} catch (InterruptedException e) {
}
}
}
return input;
}
private int getNextReadSize(FileInputStream input) throws IOException{
int avail = 0;
if (inputFileGrowing) {
avail = input.available();
if (avail == 0) {
synchronized (this) {
try {
wait(WAIT_TIME);
} catch (InterruptedException e) {
}
}
} else if (avail < MAX_BUF_SIZE) {
//buf = new byte[avail];
return avail;
} else {
//buf = new byte[MAX_BUF_SIZE];
return MAX_BUF_SIZE;
}
} else {
//buf = new byte[MAX_BUF_SIZE];
return MAX_BUF_SIZE;
}
return 0;
}
private void killTranscode(){
if (transcode != null){
transcodeKilled = true;
transcode.destroy();
}
log.info("Output-Pipe closed, killing transcode-process");
}
}