package thaw.plugins; import java.awt.GridLayout; import java.util.Iterator; import java.util.Observable; import java.util.Observer; import java.util.Random; import java.util.Vector; import javax.swing.JCheckBox; import javax.swing.JLabel; import javax.swing.JPanel; import javax.swing.JTextField; import thaw.core.Core; import thaw.core.I18n; import thaw.core.Logger; import thaw.core.Plugin; import thaw.core.ThawThread; import thaw.core.ThawRunnable; import thaw.fcp.FCPTransferQuery; /** * This plugin, after a given time, restart all/some the failed downloads (if maxDownloads >= 0, downloads to restart are choosen randomly). * A not too bad example to show how to make plugins. * @deprecated When this plugin was created, MaxRetries was stupidly set to 0 instead of -1 => now this plugin is useless. */ public class Restarter implements Observer, ThawRunnable, Plugin { private int interval = 180; /* in s */ private boolean restartFatals = false; private int timeElapsed = 0; private Core core; private boolean running = true; private Thread restarter = null; private JPanel configPanel; private JLabel restartIntervalLabel; private JTextField restartIntervalField; private JCheckBox restartFatalsBox; public boolean run(final Core core) { this.core = core; core.getConfig().addListener("restartInterval", this); core.getConfig().addListener("restartFatals", this); /* Reloading value from the configuration */ try { if((core.getConfig().getValue("restartInterval") != null) && (core.getConfig().getValue("restartFatals") != null)) { interval = Integer.parseInt(core.getConfig().getValue("restartInterval")); restartFatals = Boolean.valueOf(core.getConfig().getValue("restartFatals")).booleanValue(); } } catch(final Exception e) { /* probably conversion errors */ /* Yes I know, it's dirty */ Logger.notice(this, "Unable to read / understand value from the config. Using default values"); } /* Adding restart config tab to the config window */ configPanel = new JPanel(); configPanel.setLayout(new GridLayout(15, 1)); restartIntervalLabel = new JLabel(I18n.getMessage("thaw.plugin.restarter.interval")); restartIntervalField = new JTextField(Integer.toString(interval)); restartFatalsBox = new JCheckBox(I18n.getMessage("thaw.plugin.restarter.restartFatals"), restartFatals); configPanel.add(restartIntervalLabel); configPanel.add(restartIntervalField); configPanel.add(restartFatalsBox); core.getConfigWindow().addTab(I18n.getMessage("thaw.plugin.restarter.configTabName"), thaw.gui.IconBox.minRefreshAction, configPanel); core.getConfigWindow().addObserver(this); running = true; restarter = new ThawThread(this, "Restarter", this); restarter.start(); return true; } public void stop() { core.getConfigWindow().removeTab(configPanel); core.getConfigWindow().deleteObserver(this); running = false; } public void run() { while(running) { try { for(timeElapsed = 0 ; (timeElapsed < interval) && running; timeElapsed++) { Thread.sleep(1000); } } catch(final java.lang.InterruptedException e) { // We really really really don't care. } Logger.info(this, "Restarting some failed downloads (if there are some)"); if(!running) break; final int maxDownloads = core.getQueueManager().getMaxDownloads(); int alreadyRunning = 0; int failed = 0; final Vector runningQueue = core.getQueueManager().getRunningQueue(); try { synchronized(runningQueue) { if(maxDownloads >= 0) { /* We count how many are really running and we write down those which are failed */ for(final Iterator it = runningQueue.iterator(); it.hasNext();) { final FCPTransferQuery query = (FCPTransferQuery)it.next(); if(query.getQueryType() != 1) continue; if(query.isRunning() && !query.isFinished()) { alreadyRunning++; } if(query.isFinished() && !query.isSuccessful() && (restartFatals || !query.isFatallyFailed()) ) { failed++; } } /* We choose randomly the ones to restart */ while((alreadyRunning < maxDownloads) && (failed > 0)) { final int toRestart = (new Random()).nextInt(failed); final Iterator it = runningQueue.iterator(); int i = 0; while(it.hasNext()) { final FCPTransferQuery query = (FCPTransferQuery)it.next(); if(query.getQueryType() != 1) continue; if(query.isFinished() && !query.isSuccessful() && (restartFatals || !query.isFatallyFailed())) { if(i == toRestart) { restartQuery(query); break; } i++; } } alreadyRunning++; failed--; } } else { /* => if maxDownloads < 0 */ /* We restart them all */ for(final Iterator it = runningQueue.iterator(); it.hasNext();) { final FCPTransferQuery query = (FCPTransferQuery)it.next(); if((query.getQueryType() == 1) && query.isFinished() && !query.isSuccessful() && (restartFatals || !query.isFatallyFailed())) restartQuery(query); } } } } catch(final Exception e) { Logger.error(this, "Exception : "+e); } } } public void restartQuery(final FCPTransferQuery query) { query.stop(core.getQueueManager()); if(query.getMaxAttempt() >= 0) query.setAttempt(0); query.start(core.getQueueManager()); } public void update(final Observable o, final Object arg) { if(o == core.getConfigWindow()) { if(arg == core.getConfigWindow().getOkButton()){ core.getConfig().setValue("restartInterval", restartIntervalField.getText()); core.getConfig().setValue("restartFatals", Boolean.toString(restartFatalsBox.isSelected())); /* Plugin will be stop() and start(), so no need to reload config */ return; } if(arg == core.getConfigWindow().getCancelButton()) { restartIntervalField.setText(Integer.toString(interval)); restartFatalsBox.setSelected(restartFatals); return; } } } public String getNameForUser() { return I18n.getMessage("thaw.plugin.restarter.restarter"); } public javax.swing.ImageIcon getIcon() { return thaw.gui.IconBox.refreshAction; } }