package de.fuberlin.wiwiss.marbles.loading;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import org.apache.commons.httpclient.HttpClient;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import de.fuberlin.wiwiss.ng4j.semwebclient.DereferencingTask;
/**
* The DereferencingTaskQueue is a thread which observes the
* DereferencerThreads. It starts all DereferencerThreads tries to
* assign new tasks to free DereferencerThreads and interrupts them
* if the timeout is reached.
*
* Adapted to the Apache HTTP Client by Christian Becker
*/
public class DereferencingTaskQueue extends Thread {
private static int MAX_PENDING_TASKS = 5;
private int maxthreads;
private List<DereferencerThread> threads = new ArrayList<DereferencerThread>();
private boolean stopped = false;
private LinkedList<DereferencingTask> tasks = new LinkedList<DereferencingTask>();
private Log log = LogFactory.getLog(DereferencingTaskQueue.class);
private int maxfilesize;
private HttpClient httpClient;
private SpongerProvider spongerProvider;
public DereferencingTaskQueue(HttpClient httpClient, SpongerProvider spongerProvider, int maxThreads, int maxfilesize) {
this.maxthreads = maxThreads;
this.maxfilesize = maxfilesize;
this.httpClient = httpClient;
this.spongerProvider = spongerProvider;
setName("Queue");
start();
}
public synchronized boolean addTask(DereferencingTask task) {
if (tasks.size() > MAX_PENDING_TASKS)
return false;
/* prefer step 0 tasks as these halt processing */
if (task.getStep() == 0)
this.tasks.addFirst(task);
else
this.tasks.addLast(task);
this.log.debug("Enqueue: <" + task.getURI() + ">@" + task.getStep() +
" (n = " + this.tasks.size() + ")");
this.notify();
return true;
}
public void run() {
initThreadPool(this.maxthreads);
while (!this.stopped) {
checkForTasksAndWait();
}
}
public synchronized void close() {
Iterator<DereferencerThread> it = this.threads.iterator();
while (it.hasNext()) {
DereferencerThread thread = (DereferencerThread) it.next();
thread.stopThread();
thread.interrupt();
thread = null;
}
this.stopped = true;
notify();
}
private void checkForTasksAndWait() {
try {
this.tryAssignTask();
// TODO Wake up when a worker thread is finished
synchronized (this) {
wait(100);
}
} catch (InterruptedException ex) {
// Don't know when this happens
throw new RuntimeException(ex);
}
}
private synchronized void tryAssignTask() {
if (this.tasks.isEmpty())
return;
DereferencingTask task = (DereferencingTask) this.tasks.getFirst();
Iterator<DereferencerThread> it = this.threads.iterator();
while (it.hasNext()) {
DereferencerThread thread = it.next();
if (thread.startDereferencingIfAvailable(task)) {
this.tasks.removeFirst();
this.log.debug("Dequeue: <" + task.getURI() + ">@" + task.getStep() +
" (n = " + this.tasks.size() + ")");
break;
}
}
}
private void initThreadPool(int numThreads) {
for (int i = 0; i < numThreads; i++) {
DereferencerThread thread = new DereferencerThread(httpClient, spongerProvider);
thread.setName("DerefThread"+i);
thread.setMaxfilesize(this.maxfilesize);
thread.start();
this.threads.add(thread);
}
}
}