/*******************************************************************************
* Copyright (c) 2005-2008, G. Weirich and Elexis
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* G. Weirich - initial implementation
*
*******************************************************************************/
package ch.elexis.core.ui.actions;
import java.util.Hashtable;
import java.util.Vector;
import org.eclipse.core.runtime.Platform;
import org.eclipse.core.runtime.jobs.IJobManager;
import org.eclipse.core.runtime.jobs.ILock;
import org.eclipse.core.runtime.jobs.Job;
import ch.elexis.core.ui.actions.BackgroundJob.BackgroundJobListener;
import ch.rgw.tools.ExHandler;
/**
* Ein Sammelbecken für Background-Jobs. Der JobPool steuert den Ablauf der Jobs: Er achtet darauf,
* dass derselbe Job nicht mehrmals gleichzeitig gestartet wird, und dass nicht zuviele Jobs
* parallel laufen. Dafür können Jobs in eine Warteschlange eingereiht werden, wo sie nacheinander
* abgearbeitet werden. Die Priorität der Jobs wird aus org.eclipse.core.runtime.jobs.Job entnommen.
* Die Werte bedeuten:
* <ul>
* <li>Job.INTERACTIVE: Höchste Priorität, nur für kurzlaufende Jobs, die ummittelbare Auswirkung
* auf die Benutzeroberfläche haben.</li>
* <li>Job.SHORT: Hohe Priorität, für Jobs die höchstens ein bis zwei Sekunden laufen, und auf die
* der Anwender wartet</li>
* <li>Job.LONG: Mittlere Priorität für Jobs, die mehrere Sekunden lang laufen, und die deshalb die
* Benutzeroberfläche nicht beeinträchtigen sollen</li>
* <li>Job.DECORATE; Niedrigste Priorität für allgemeine Hintergrundjobs, die nur laufen, wenn sonst
* nichts zu tun ist</li>
* </ul>
*
* @see BackgroundJob
* @author gerry
*
* @deprecated Neuer Code sollte das Eclipse Job API verwenden
* @see BackgroundJob
*/
@Deprecated
public class JobPool implements BackgroundJobListener {
private Hashtable<String, BackgroundJob> pool = new Hashtable<String, BackgroundJob>();
private Vector<String> running = new Vector<String>();
private Vector<String> waiting = new Vector<String>();
private Vector<String> queued = new Vector<String>();
private ILock changeLock;
private static JobPool thePool;
private JobPool(){
IJobManager jobman = Platform.getJobManager();
changeLock = jobman.newLock();
}
public void dispose(){
for (BackgroundJob job : pool.values()) {
try {
if (job.cancel() == false) {
job.getThread().interrupt();
}
} catch (Throwable t) {
ExHandler.handle(t);
}
}
}
/**
* Den JobPool erzeugen bzw. holen. Es soll nur einen geben, deswegen als Singleton
* implementiert
*/
public static JobPool getJobPool(){
if (thePool == null) {
thePool = new JobPool();
}
return thePool;
}
/**
* Einen neuen Job hinzufügen. Ein Job bleibt im Pool bis zum Programmende. Er hat entweder den
* Status running, waiting oder queued. Jobs, die waiting oder queued sind, brauchen keine
* Systemressourcen. addJob lässt den Job zunächst im status waiting
*
* @param job
* der Job
* @return true wenn erfolgreich, false wenn dieser Job oder ein Job gleichen Namens schon im
* Pool ist oder bei einem sonstigen Fehler.
*/
public boolean addJob(BackgroundJob job){
try {
changeLock.acquire();
if (pool.get(job.getJobname()) != null) {
return false;
}
job.addListener(this);
pool.put(job.getJobname(), job);
waiting.add(job.getJobname());
return true;
} catch (Exception ex) {
ExHandler.handle(ex);
return false;
} finally {
changeLock.release();
}
}
/**
* Einen Job anhand seines Namens finden
*
* @param name
* Name des Jobs
* @return den Job oder null, wenn nicht vorhanden.
*/
public BackgroundJob getJob(String name){
BackgroundJob ret = pool.get(name);
return ret;
}
/**
* Einen Job starten
*
* @param name
* Name des Jobs
* @param priority
* gewpnschte Priorität (Job.INTERACTIVE bis JOB.DECORATIONS)
* @return true wenn der Job gestartet wurde, d.h. er läuft dann noch bei Rückkehr dieser
* Funktion. false, wenn der Job schon lief, oder wenn er nicht gefunden wurde.
*/
public boolean activate(String name, int priority){
try {
changeLock.acquire();
if (waiting.remove(name) == true) {
BackgroundJob job = pool.get(name);
if (job == null) {
return false;
}
running.add(name);
job.setPriority(priority);
job.schedule();
return true;
}
return false;
} catch (Exception ex) {
ExHandler.handle(ex);
return false;
} finally {
changeLock.release();
}
}
/**
* Einen Job in die Warteschlange setzen. Er wird gestartet, sobald ein eventuell schon
* laufender Job beendet ist.
*
* @param name
* Name des Jobs
*/
public void queue(String name){
try {
changeLock.acquire();
if (running.isEmpty()) {
activate(name, Job.BUILD);
} else {
queued.add(name);
}
} catch (Exception ex) {
ExHandler.handle(ex);
} finally {
changeLock.release();
}
}
/**
* Diese Funktion ist für internen Gebrauch. Organisation der Warteschlange
*/
public void jobFinished(BackgroundJob j){
try {
changeLock.acquire();
running.remove(j.getJobname());
waiting.add(j.getJobname());
if (!queued.isEmpty()) {
String nextJob = queued.remove(0);
activate(nextJob, Job.BUILD);
}
} catch (Exception e) {
ExHandler.handle(e);
} finally {
changeLock.release();
}
}
}