package com.golshadi.majid.core.chunkWorker; import com.golshadi.majid.Utils.helper.FileUtils; import com.golshadi.majid.database.elements.Chunk; import com.golshadi.majid.database.elements.Task; import java.io.File; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; import java.net.HttpURLConnection; import java.net.MalformedURLException; import java.net.SocketTimeoutException; import java.net.URL; /** * Created by Majid Golshadi on 4/14/2014. */ public class AsyncWorker extends Thread{ private final int BUFFER_SIZE = 1024; private final Task task; private final Chunk chunk; private final Moderator observer; private byte[] buffer; private ConnectionWatchDog watchDog; public boolean stop = false; public AsyncWorker(Task task, Chunk chunk, Moderator moderator){ buffer = new byte[BUFFER_SIZE]; this.task = task; this.chunk = chunk; this.observer = moderator; } @Override public void run() { try { URL url = new URL(task.url); HttpURLConnection connection = (HttpURLConnection) url.openConnection(); // Avoid timeout exception which usually occurs in low network connection.setConnectTimeout(0); connection.setReadTimeout(0); if (chunk.end != 0) // support unresumable links connection.setRequestProperty("Range", "bytes=" + chunk.begin + "-" + chunk.end); connection.connect(); File cf = new File(FileUtils.address(task.save_address, String.valueOf(chunk.id))); // Check response code first to avoid error stream int status = connection.getResponseCode(); InputStream remoteFileIn; if(status == 416) remoteFileIn = connection.getErrorStream(); else remoteFileIn = connection.getInputStream(); FileOutputStream chunkFile = new FileOutputStream(cf, true); int len = 0; // set watchDoger to stop thread after 1sec if no connection lost watchDog = new ConnectionWatchDog(5000, this); watchDog.start(); while (!this.isInterrupted() && (len = remoteFileIn.read(buffer)) > 0) { watchDog.reset(); chunkFile.write(buffer, 0, len); process(len); } chunkFile.flush(); chunkFile.close(); watchDog.interrupt(); connection.disconnect(); if (!this.isInterrupted()) { observer.rebuild(chunk); } }catch (SocketTimeoutException e) { e.printStackTrace(); observer.connectionLost(task.id); puaseRelatedTask(); } catch (MalformedURLException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } return; } private void process(int read) { observer.process(chunk.task_id, read); } private void puaseRelatedTask() { observer.pause(task.id); } private boolean flag = true; public void connectionTimeOut(){ if (flag) { watchDog.interrupt(); flag = false; observer.connectionLost(task.id); puaseRelatedTask(); } } }