Author: jflesch
Date: 2006-07-22 03:08:37 +0000 (Sat, 22 Jul 2006)
New Revision: 9708
Added:
trunk/apps/Thaw/src/thaw/plugins/Restarter.java
Modified:
trunk/apps/Thaw/src/thaw/core/ConfigWindow.java
trunk/apps/Thaw/src/thaw/core/Logger.java
trunk/apps/Thaw/src/thaw/core/NodeConfigPanel.java
trunk/apps/Thaw/src/thaw/fcp/FCPClientGet.java
trunk/apps/Thaw/src/thaw/fcp/FCPClientPut.java
trunk/apps/Thaw/src/thaw/fcp/FCPConnection.java
trunk/apps/Thaw/src/thaw/fcp/FCPQueueManager.java
trunk/apps/Thaw/src/thaw/fcp/FCPTransferQuery.java
trunk/apps/Thaw/src/thaw/i18n/thaw.properties
trunk/apps/Thaw/src/thaw/i18n/thaw_fr.properties
trunk/apps/Thaw/src/thaw/plugins/FetchPlugin.java
trunk/apps/Thaw/src/thaw/plugins/StatusBar.java
Log:
Add a plugin (thaw.plugins.Restarter) to restart automagically failed downloads
Modified: trunk/apps/Thaw/src/thaw/core/ConfigWindow.java
===================================================================
--- trunk/apps/Thaw/src/thaw/core/ConfigWindow.java 2006-07-21 23:43:31 UTC
(rev 9707)
+++ trunk/apps/Thaw/src/thaw/core/ConfigWindow.java 2006-07-22 03:08:37 UTC
(rev 9708)
@@ -136,6 +136,14 @@
setVisible(false);
}
+
+ if(e.getSource() == okButton) {
+ /* should reinit the whole connection correctly */
+ core.getPluginManager().stopPlugins();
+ core.initNodeConnection();
+ core.getPluginManager().loadPlugins();
+ core.getPluginManager().runPlugins();
+ }
}
Modified: trunk/apps/Thaw/src/thaw/core/Logger.java
===================================================================
--- trunk/apps/Thaw/src/thaw/core/Logger.java 2006-07-21 23:43:31 UTC (rev
9707)
+++ trunk/apps/Thaw/src/thaw/core/Logger.java 2006-07-22 03:08:37 UTC (rev
9708)
@@ -94,10 +94,10 @@
* As it. Similar to verbose()
*/
public static void asIt(Object o, String msg) {
- //if(LOG_LEVEL >= 5) {
+ if(LOG_LEVEL >= 5) {
System.out.println(msg);
notifyLogListeners(msg);
- //}
+ }
}
Modified: trunk/apps/Thaw/src/thaw/core/NodeConfigPanel.java
===================================================================
--- trunk/apps/Thaw/src/thaw/core/NodeConfigPanel.java 2006-07-21 23:43:31 UTC
(rev 9707)
+++ trunk/apps/Thaw/src/thaw/core/NodeConfigPanel.java 2006-07-22 03:08:37 UTC
(rev 9708)
@@ -79,12 +79,6 @@
for(int i=0;i < paramNames.length;i++) {
core.getConfig().setValue(configNames[i],
paramFields[i].getText());
}
-
- /* should reinit the whole connection correctly */
- core.getPluginManager().stopPlugins();
- core.initNodeConnection();
- core.getPluginManager().loadPlugins();
- core.getPluginManager().runPlugins();
}
Modified: trunk/apps/Thaw/src/thaw/fcp/FCPClientGet.java
===================================================================
--- trunk/apps/Thaw/src/thaw/fcp/FCPClientGet.java 2006-07-21 23:43:31 UTC
(rev 9707)
+++ trunk/apps/Thaw/src/thaw/fcp/FCPClientGet.java 2006-07-22 03:08:37 UTC
(rev 9708)
@@ -39,6 +39,7 @@
private boolean running = false;
private boolean successful = false;
+ private boolean fatal = true;
private boolean isLockOwner = false;
@@ -242,23 +243,18 @@
Logger.debug(this, "Unknow URI ? was probably a
stop order so no problem ...");
return;
}
- /*
- if(message.getValue("Fatal").equals("False")) {
- Logger.debug(this, "Non-fatal protocol error");
- status = "Protocol warning
("+message.getValue("CodeDescription")+")";
- return;
- }
- */
Logger.error(this, "=== PROTOCOL ERROR ===
\n"+message.toString());
status = "Protocol Error
("+message.getValue("CodeDescription")+")";
progress = 100;
running = false;
- successful = false;
+ successful = false;
+ fatal = true;
if(message.getValue("Fatal") != null &&
message.getValue("Fatal").equals("false")) {
+ fatal = false;
status = status + " (non-fatal)";
}
@@ -294,8 +290,11 @@
running = false;
successful = false;
+ fatal = true;
+
if(message.getValue("Fatal") != null &&
message.getValue("Fatal").equals("false")) {
+ fatal = false;
status = status + " (non-fatal)";
}
@@ -649,6 +648,7 @@
progress = 100;
successful = false;
+ fatal = true;
status = "Stopped";
setChanged();
notifyObservers();
@@ -723,6 +723,10 @@
return successful;
}
+ public boolean isFatallyFailed() {
+ return ((!successful) && fatal);
+ }
+
public boolean isRunning() {
return running;
}
Modified: trunk/apps/Thaw/src/thaw/fcp/FCPClientPut.java
===================================================================
--- trunk/apps/Thaw/src/thaw/fcp/FCPClientPut.java 2006-07-21 23:43:31 UTC
(rev 9707)
+++ trunk/apps/Thaw/src/thaw/fcp/FCPClientPut.java 2006-07-22 03:08:37 UTC
(rev 9708)
@@ -37,6 +37,7 @@
private boolean running = false;
private boolean finished = false;
private boolean successful = false;
+ private boolean fatal = true;
private boolean sending = false;
private FCPGenerateSSK sskGenerator = null;
@@ -93,6 +94,7 @@
this.running = false;
this.finished = false;
this.successful = false;
+ this.fatal = true;
}
@@ -190,6 +192,7 @@
running = true;
finished = false;
successful = false;
+ fatal = true;
}
@@ -202,6 +205,7 @@
status = "EMPTY OR UNREACHABLE FILE";
successful = false;
+ fatal = true;
finished = true;
running = false;
@@ -353,6 +357,7 @@
if(ret == true) {
successful = false;
+ fatal = true;
finished = false;
progress = 0;
running = true;
@@ -453,6 +458,7 @@
status = "Stopped";
finished = false;
successful = false;
+ fatal= true;
running = false;
setChanged();
@@ -539,12 +545,15 @@
successful = false;
running = false;
finished = true;
+ fatal = true;
status = "Failed
("+msg.getValue("CodeDescription")+")";
if(msg.getValue("Fatal") != null &&
- msg.getValue("Fatal").equals("false"))
+ msg.getValue("Fatal").equals("false")) {
status = status + " (non-fatal)";
+ fatal = false;
+ }
setChanged();
notifyObservers();
@@ -555,6 +564,7 @@
successful = false;
running = false;
+ fatal = true;
finished = true;
if(lockOwner) {
@@ -563,9 +573,12 @@
}
status = "Protocol error
("+msg.getValue("CodeDescription")+")";
+
if(msg.getValue("Fatal") != null &&
- msg.getValue("Fatal").equals("false"))
+ msg.getValue("Fatal").equals("false")) {
status = status + " (non-fatal)";
+ fatal = false;
+ }
setChanged();
notifyObservers();
@@ -662,6 +675,7 @@
running = false;
successful = false;
finished = false;
+ fatal = true;
removeRequest();
return false;
@@ -788,6 +802,10 @@
return successful;
}
+ public boolean isFatallyFailed() {
+ return ((!successful) && fatal);
+ }
+
/**
* not tested : TODO : to test it
*/
Modified: trunk/apps/Thaw/src/thaw/fcp/FCPConnection.java
===================================================================
--- trunk/apps/Thaw/src/thaw/fcp/FCPConnection.java 2006-07-21 23:43:31 UTC
(rev 9707)
+++ trunk/apps/Thaw/src/thaw/fcp/FCPConnection.java 2006-07-22 03:08:37 UTC
(rev 9708)
@@ -27,6 +27,8 @@
private final static boolean DEBUG_MODE = true;
private final static int MAX_RECV = 1024;
+ private byte[] recvBytes = new byte[MAX_RECV]; /* global to avoid each
time free() / malloc() */
+
private FCPBufferedStream bufferedOut = null;
private int maxUploadSpeed = 0;
@@ -366,8 +368,6 @@
if(in != null && reader != null && socket != null &&
socket.isConnected()) {
try {
- byte[] recvBytes = new byte[MAX_RECV];
-
for(int i = 0; i < recvBytes.length ; i++)
recvBytes[i] = 0;
@@ -385,6 +385,8 @@
else
Logger.notice(this,
"Disconnected");
+ disconnect(); /* will warn
everybody */
+
return null;
}
Modified: trunk/apps/Thaw/src/thaw/fcp/FCPQueueManager.java
===================================================================
--- trunk/apps/Thaw/src/thaw/fcp/FCPQueueManager.java 2006-07-21 23:43:31 UTC
(rev 9707)
+++ trunk/apps/Thaw/src/thaw/fcp/FCPQueueManager.java 2006-07-22 03:08:37 UTC
(rev 9708)
@@ -84,12 +84,27 @@
/**
* Take care: Can change while you're using it.
+ * The running queue contains running request, but also finished/failed
ones.
*/
public Vector getRunningQueue() {
return runningQueries;
}
/**
+ * @return < 0 if no limit
+ */
+ public int getMaxDownloads() {
+ return maxDownloads;
+ }
+
+ /**
+ * @return < 0 if no limite
+ */
+ public int getMaxInsertions() {
+ return maxInsertions;
+ }
+
+ /**
* @return false if already added.
*/
public boolean addQueryToThePendingQueue(FCPTransferQuery query) {
Modified: trunk/apps/Thaw/src/thaw/fcp/FCPTransferQuery.java
===================================================================
--- trunk/apps/Thaw/src/thaw/fcp/FCPTransferQuery.java 2006-07-21 23:43:31 UTC
(rev 9707)
+++ trunk/apps/Thaw/src/thaw/fcp/FCPTransferQuery.java 2006-07-22 03:08:37 UTC
(rev 9708)
@@ -101,6 +101,7 @@
* Query is considered as a failure is isFinished() && !isSuccesful()
*/
public boolean isSuccessful();
+ public boolean isFatallyFailed();
/**
* Use to save the query in an XML file / a database / whatever.
Modified: trunk/apps/Thaw/src/thaw/i18n/thaw.properties
===================================================================
--- trunk/apps/Thaw/src/thaw/i18n/thaw.properties 2006-07-21 23:43:31 UTC
(rev 9707)
+++ trunk/apps/Thaw/src/thaw/i18n/thaw.properties 2006-07-22 03:08:37 UTC
(rev 9708)
@@ -126,7 +126,13 @@
thaw.plugin.statistics.running=Running:
thaw.plugin.statistics.pending=Pending:
+thaw.plugin.restarter.restarter=Restart failed downloads
+# If someone find a better name for the following one ...
+thaw.plugin.restarter.configTabName=Failed downloads
+thaw.plugin.restarter.interval=Interval between each restart (in seconds)
+thaw.plugin.restarter.restartFatals=Restart also fataly failed downloads
+
## Warnings
thaw.warning.title=Warning
thaw.warning.isWriting=Warning ! Thaw is writing data. It would be better to
quit when thaw will finish. Are you sure you want to quit ?
Modified: trunk/apps/Thaw/src/thaw/i18n/thaw_fr.properties
===================================================================
--- trunk/apps/Thaw/src/thaw/i18n/thaw_fr.properties 2006-07-21 23:43:31 UTC
(rev 9707)
+++ trunk/apps/Thaw/src/thaw/i18n/thaw_fr.properties 2006-07-22 03:08:37 UTC
(rev 9708)
@@ -126,6 +126,12 @@
thaw.plugin.statistics.pending=En attente:
+thaw.plugin.restarter.restarter=Red?marre les t?l?chargements ?chou?s
+thaw.plugin.restarter.configTabName=T?l?chargements ?chou?s
+thaw.plugin.restarter.interval=Intervale entre chaque red?marrage (in seconds)
+thaw.plugin.restarter.restartFatals=R?d?marrer aussi les t?l?chargements
consid?r?s comme fatalement ?chou?s
+
+
## Warnings
thaw.warning.title=Avertissement
thaw.warning.isWriting=Attention ! Thaw est entrain d'?crire des informations.
Il serait pr?f?rable de quitter une fois ces envois finis. Etes-vous s?r de
vouloir quitter ?
Modified: trunk/apps/Thaw/src/thaw/plugins/FetchPlugin.java
===================================================================
--- trunk/apps/Thaw/src/thaw/plugins/FetchPlugin.java 2006-07-21 23:43:31 UTC
(rev 9707)
+++ trunk/apps/Thaw/src/thaw/plugins/FetchPlugin.java 2006-07-22 03:08:37 UTC
(rev 9708)
@@ -50,6 +50,9 @@
String destination) {
for(int i = 0 ; i < keys.length ; i++) {
+ if(keys[i].length() < 10)
+ continue;
+
String[] subKey = keys[i].split("\\?"); /* Because of
VolodyA :p */
String key =
subKey[0].replaceFirst("http://127.0.0.1:8888/", "");
Added: trunk/apps/Thaw/src/thaw/plugins/Restarter.java
===================================================================
--- trunk/apps/Thaw/src/thaw/plugins/Restarter.java 2006-07-21 23:43:31 UTC
(rev 9707)
+++ trunk/apps/Thaw/src/thaw/plugins/Restarter.java 2006-07-22 03:08:37 UTC
(rev 9708)
@@ -0,0 +1,226 @@
+package thaw.plugins;
+
+import javax.swing.JPanel;
+import javax.swing.JTextField;
+import javax.swing.JLabel;
+import javax.swing.JCheckBox;
+import java.awt.GridLayout;
+
+import java.util.Vector;
+import java.util.Iterator;
+import java.util.Observer;
+import java.util.Observable;
+import java.util.Random;
+
+import thaw.i18n.I18n;
+import thaw.core.*;
+import thaw.fcp.*;
+
+/**
+ * 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.
+ */
+public class Restarter implements Observer, Runnable, 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(Core core) {
+ this.core = core;
+
+ /* 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(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"),
configPanel);
+ core.getConfigWindow().addObserver(this);
+
+ running = true;
+ restarter = new Thread(this);
+ restarter.start();
+
+ return true;
+ }
+
+
+ public boolean stop() {
+ core.getConfigWindow().removeTab(configPanel);
+ core.getConfigWindow().deleteObserver(this);
+ running = false;
+
+ return true;
+ }
+
+
+ public void run() {
+ while(running) {
+ try {
+
+ for(timeElapsed = 0 ; timeElapsed < interval &&
running; timeElapsed++) {
+ Thread.sleep(1000);
+ }
+
+ } catch(java.lang.InterruptedException e) {
+ // We really really really don't care.
+ }
+
+ Logger.notice(this, "Restarting [some] failed
downloads");
+
+ try {
+ if(!running)
+ break;
+
+ int maxDownloads =
core.getQueueManager().getMaxDownloads();
+ int alreadyRunning = 0;
+ int failed = 0;
+ Vector runningQueue =
core.getQueueManager().getRunningQueue();
+
+
+ if(maxDownloads >= 0) {
+ /* We count how many are really running
+ and we write down those which are
failed */
+ for(Iterator it =
runningQueue.iterator();
+ it.hasNext();) {
+ 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) {
+ int toRestart = (new
Random()).nextInt(failed);
+
+ Iterator it =
runningQueue.iterator();
+ int i = 0;
+
+ while(it.hasNext()) {
+ 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(Iterator it =
runningQueue.iterator();
+ it.hasNext();) {
+ FCPTransferQuery query =
(FCPTransferQuery)it.next();
+
+ if(query.getQueryType() == 1 &&
query.isFinished()
+ && !query.isSuccessful()
+ && (restartFatals ||
!query.isFatallyFailed()))
+ restartQuery(query);
+ }
+ }
+
+
+
+ } catch(java.util.ConcurrentModificationException e) {
+ Logger.notice(this, "Collision ! Sorry I will
restart failed downloads later ...");
+ } catch(Exception e) {
+ Logger.error(this, "Exception : "+e);
+ }
+
+ }
+ }
+
+
+ public void restartQuery(FCPTransferQuery query) {
+ query.stop(core.getQueueManager());
+
+ if(query.getMaxAttempt() >= 0)
+ query.setAttempt(0);
+
+ query.start(core.getQueueManager());
+ }
+
+ public void update(Observable o, 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");
+ }
+
+}
Modified: trunk/apps/Thaw/src/thaw/plugins/StatusBar.java
===================================================================
--- trunk/apps/Thaw/src/thaw/plugins/StatusBar.java 2006-07-21 23:43:31 UTC
(rev 9707)
+++ trunk/apps/Thaw/src/thaw/plugins/StatusBar.java 2006-07-22 03:08:37 UTC
(rev 9708)
@@ -12,7 +12,7 @@
public final static String SEPARATOR = " ";
private Core core;
- private boolean running;
+ private boolean running = true;
private Thread refresher;