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;




Reply via email to