I read data from a source location via BufferedInputStream
and I pass the data to a destination using BufferedOutputStream
. The problem I'm having is that sometimes my thread never exits the while loop because of starving on the bandwidth. Any ideas? Here's the code:
BufferedInputStream bis = new BufferedInputStream(sourceConnection.getInputStream());
BufferedOutputStream request = new BufferedOutputStream(destConnection.getOutputStream());
request.write(content.getBytes("UTF-8"));
boolean eof = false;
byte[] input = new byte[4096];
while ((length = bis.read(input)) != -1) {
request.write(input, 0, length);
request.flush();
}
request.close();
bis.close();
So to fix the issue I did a few things. I set the entire transfer process in a separate thread using an executor with a timeout
ScheduledExecutorService executor = Executors.newScheduledThreadPool(1);
final Future<Boolean> handler = executor.submit(new Callable<Boolean>() {
@Override
public Boolean call() throws Exception {
return processTransfer();
}
});
success = handler.get(10, TimeUnit.MINUTES);
That way if the transfer takes longer than 10 minutes, it exits with an exeption. The second thing was change the original code to detect starvation:
long lastDataRecvTime = System.currentTimeMillis();
byte[] input;
while (true) {
if(System.currentTimeMillis() - lastDataRecvTime >= 5 * 60 * 1000) {
throw new RuntimeException("Nothing received for 5 minutes. Transfer starved. Exiting");
}
int availableBuf = request.getAvailableBufferSize();
if(availableBuf == 0) {
request.flush();
continue;
}
input = new byte[Math.min(4096, availableBuf)];
int length = bis.read(input);
if (length == -1)
break;
if(length == 0) {
try { Thread.sleep(1); } catch (Exception ignored){}
continue;
}
lastDataRecvTime = System.currentTimeMillis();
request.write(input, 0, length);
}
request.flush();
request.close();
bis.close();
Thanks for the help