Author: cyberdo
Date: 2006-03-11 00:26:13 +0000 (Sat, 11 Mar 2006)
New Revision: 8223

Added:
   trunk/freenet/src/freenet/clients/http/SymlinkerToadlet.java
   trunk/freenet/src/freenet/pluginmanager/FredPluginThreadless.java
Modified:
   trunk/freenet/src/freenet/node/Node.java
   trunk/freenet/src/freenet/node/Version.java
   trunk/freenet/src/freenet/pluginmanager/PluginHandler.java
   trunk/freenet/src/freenet/pluginmanager/PluginInfoWrapper.java
   trunk/freenet/src/freenet/pluginmanager/PluginManager.java
Log:
524: Plugins may now "implement" FredPluginThreadless, which makes the thread
never being started. This saves resources.
Introducing SymlinkerToadlet, to make aliases. No front end yet. Hard-coded 
links:
/sl/search/ => /plugins/plugins.Librarian/
/sl/gallery/ => /plugins/plugins.TestGallery/


Added: trunk/freenet/src/freenet/clients/http/SymlinkerToadlet.java
===================================================================
--- trunk/freenet/src/freenet/clients/http/SymlinkerToadlet.java        
2006-03-11 00:11:20 UTC (rev 8222)
+++ trunk/freenet/src/freenet/clients/http/SymlinkerToadlet.java        
2006-03-11 00:26:13 UTC (rev 8223)
@@ -0,0 +1,164 @@
+package freenet.clients.http;
+
+import java.io.IOException;
+import java.io.PrintWriter;
+import java.io.StringWriter;
+import java.net.URI;
+import java.net.URISyntaxException;
+import java.util.Date;
+import java.util.HashMap;
+import java.util.Iterator;
+
+import freenet.client.HighLevelSimpleClient;
+import freenet.clients.http.Toadlet;
+import freenet.clients.http.ToadletContext;
+import freenet.clients.http.ToadletContextClosedException;
+import freenet.node.Node;
+import freenet.pluginmanager.HTTPRequest;
+import freenet.pluginmanager.PluginHTTPException;
+import freenet.pluginmanager.PluginInfoWrapper;
+import freenet.pluginmanager.PluginManager;
+import freenet.support.Logger;
+import freenet.support.MultiValueTable;
+import freenet.client.HighLevelSimpleClient;
+import freenet.config.InvalidConfigValueException;
+import freenet.config.StringArrCallback;
+import freenet.config.StringArrOption;
+import freenet.config.SubConfig;
+
+public class SymlinkerToadlet extends Toadlet {
+       
+       private final HashMap linkMap = new HashMap();
+       private final Node node;
+       SubConfig tslconfig;
+       
+       public SymlinkerToadlet(HighLevelSimpleClient client, String CSSName, 
Node node) {
+               super(client, CSSName);
+               this.node = node;
+               tslconfig = new SubConfig("toadletsymlinker", node.config);
+               tslconfig.register("symlinks", null, 9, true, "Symlinks in 
ToadletServer", 
+                               "A list of \"alias#target\"'s that forms a 
bunch of symlinks", 
+                       new StringArrCallback() {
+                       public String get() {
+                               return getConfigLoadString();
+                       }
+                       public void set(String val) throws 
InvalidConfigValueException {
+                               //if(storeDir.equals(new File(val))) return;
+                               // FIXME
+                               throw new InvalidConfigValueException("Cannot 
set the plugins that's loaded.");
+                       }
+               });
+               
+               String fns[] = tslconfig.getStringArr("symlinks");
+               if (fns != null)
+                       for (int i = 0 ; i < fns.length ; i++) {
+                               String tuple[] = 
StringArrOption.decode(fns[i]).split("#");
+                               if (tuple.length == 2)
+                                       System.err.println("Adding link: " + 
tuple[0] + " => " + tuple[1]);
+                       }
+
+               if (fns != null)
+                       for (int i = 0 ; i < fns.length ; i++) {
+                               //System.err.println("Load: " + 
StringArrOption.decode(fns[i]));
+                               String tuple[] = 
StringArrOption.decode(fns[i]).split("#");
+                               if (tuple.length == 2)
+                                       addLink(tuple[0], tuple[1]);
+                       }
+               tslconfig.finishedInitialization();
+               
+               fns = tslconfig.getStringArr("symlinks");
+               if (fns != null)
+                       for (int i = 0 ; i < fns.length ; i++) {
+                               String tuple[] = 
StringArrOption.decode(fns[i]).split("#");
+                               if (tuple.length == 2)
+                                       Logger.normal(this, "Added link: " + 
tuple[0] + " => " + tuple[1]);
+                       }
+               addLink("/sl/search/", "/plugins/plugins.Librarian/");
+               addLink("/sl/gallery/", "/plugins/plugins.TestGallery/");
+       }
+       
+       public boolean addLink(String alias, String target) {
+               synchronized (linkMap) {
+                       if (linkMap.put(alias, target) == alias) {
+                               Logger.normal(this, "Adding link: " + alias + " 
=> " + target);
+                               node.config.store();
+                               return true;
+                       } else {
+                               Logger.error(this, "Adding link: " + alias + " 
=> " + target);
+                               return false;
+                       }
+               }
+       }
+       
+       public boolean removeLink(String alias) {
+               synchronized (linkMap) {
+                       Object o;
+                       if ((o = linkMap.remove(alias))!= null) {
+                               Logger.normal(this, "Removing link: " + alias + 
" => " + o);
+                               node.config.store();
+                               return true;
+                       } else {
+                               Logger.error(this, "Adding link: " + alias + " 
=> " + o);
+                               return false;
+                       }
+               }
+       }
+       
+       private String getConfigLoadString() {
+               String retarr[] = new String[linkMap.size()];
+               synchronized (linkMap) {
+                       Iterator it = linkMap.keySet().iterator();
+                       int i = 0;
+                       while(it.hasNext()) {
+                               String key = (String)it.next();
+                               retarr[i++] = key + "#" + linkMap.get(key); 
+                       }
+               }
+               return StringArrOption.arrayToString(retarr);
+       }
+       
+       public String supportedMethods() {
+               return "GET";
+       }
+       
+       public void handleGet(URI uri, ToadletContext ctx)
+       throws ToadletContextClosedException, IOException, RedirectException {
+               String path = uri.getPath();
+               String foundkey = null;
+               String foundtarget = null;
+               synchronized (linkMap) {
+                       Iterator it = linkMap.keySet().iterator();
+                       while (it.hasNext()) {
+                               String key = (String)it.next();
+                               if (path.startsWith(key)) {
+                                       foundkey = key;
+                                       foundtarget = (String)linkMap.get(key);
+                               }
+                       }
+               }
+               
+               // TODO redirect to errorpage
+               if ((foundtarget == null) || (foundkey == null)) {
+                       writeReply(ctx, 404, "text/html", "Path not found", 
"Page not found");
+                       return;
+               }
+               
+               path = foundtarget + path.substring(foundkey.length());
+               URI outuri = null;
+               try {
+                       outuri = new URI(null, null,
+                                path, uri.getQuery(), uri.getFragment());
+               } catch (URISyntaxException e) {
+                       // TODO Handle error somehow
+                       writeReply(ctx, 200, "text/html", "OK", e.getMessage());
+                       return;
+               }
+               
+               uri.getRawQuery();
+            
+               RedirectException re = new RedirectException();
+               re.newuri = outuri;
+               throw re;
+       }
+       
+}

Modified: trunk/freenet/src/freenet/node/Node.java
===================================================================
--- trunk/freenet/src/freenet/node/Node.java    2006-03-11 00:11:20 UTC (rev 
8222)
+++ trunk/freenet/src/freenet/node/Node.java    2006-03-11 00:26:13 UTC (rev 
8223)
@@ -31,6 +31,7 @@
 import freenet.client.async.ClientRequestScheduler;
 import freenet.clients.http.FproxyToadlet;
 import freenet.clients.http.SimpleToadletServer;
+import freenet.clients.http.SymlinkerToadlet;
 import freenet.config.Config;
 import freenet.config.FilePersistentConfig;
 import freenet.config.IntCallback;
@@ -253,6 +254,7 @@
     TextModeClientInterface tmci;
     FCPServer fcpServer;
     FproxyToadlet fproxyServlet;
+    private SymlinkerToadlet symlinkerToadlet;
     SimpleToadletServer toadletContainer;

     // Persistent temporary buckets
@@ -908,6 +910,9 @@
                        e.printStackTrace();
                        throw new 
NodeInitException(EXIT_COULD_NOT_START_FPROXY, "Could not start fproxy: "+e);
                }
+               
+               symlinkerToadlet = new 
SymlinkerToadlet(makeClient(RequestStarter.INTERACTIVE_PRIORITY_CLASS),"", 
this);
+               toadletContainer.register(symlinkerToadlet, "/sl/", true);
                /*
         SimpleToadletServer server = new SimpleToadletServer(port+2000);
         FproxyToadlet fproxy = new 
FproxyToadlet(n.makeClient(RequestStarter.INTERACTIVE_PRIORITY_CLASS));
@@ -2076,4 +2081,8 @@
        public void setFCPServer(FCPServer fcp) {
                this.fcpServer = fcp;
        }
+
+       public SymlinkerToadlet getSymlinkerToadlet() {
+               return symlinkerToadlet;
+       }
 }

Modified: trunk/freenet/src/freenet/node/Version.java
===================================================================
--- trunk/freenet/src/freenet/node/Version.java 2006-03-11 00:11:20 UTC (rev 
8222)
+++ trunk/freenet/src/freenet/node/Version.java 2006-03-11 00:26:13 UTC (rev 
8223)
@@ -20,7 +20,7 @@
        public static final String protocolVersion = "1.0";

        /** The build number of the current revision */
-       private static final int buildNumber = 523;
+       private static final int buildNumber = 524;

        /** Oldest build of Fred we will talk to */
        private static final int lastGoodBuild = 507;

Added: trunk/freenet/src/freenet/pluginmanager/FredPluginThreadless.java
===================================================================
--- trunk/freenet/src/freenet/pluginmanager/FredPluginThreadless.java   
2006-03-11 00:11:20 UTC (rev 8222)
+++ trunk/freenet/src/freenet/pluginmanager/FredPluginThreadless.java   
2006-03-11 00:26:13 UTC (rev 8223)
@@ -0,0 +1,10 @@
+package freenet.pluginmanager;
+
+public interface FredPluginThreadless {
+       
+       // Let them return null if unhandled
+
+       public String handleHTTPGet(HTTPRequest request) throws 
PluginHTTPException;
+       public String handleHTTPPut(HTTPRequest request) throws 
PluginHTTPException;
+       public String handleHTTPPost(HTTPRequest request) throws 
PluginHTTPException;
+}

Modified: trunk/freenet/src/freenet/pluginmanager/PluginHandler.java
===================================================================
--- trunk/freenet/src/freenet/pluginmanager/PluginHandler.java  2006-03-11 
00:11:20 UTC (rev 8222)
+++ trunk/freenet/src/freenet/pluginmanager/PluginHandler.java  2006-03-11 
00:26:13 UTC (rev 8223)
@@ -19,8 +19,13 @@
        public static PluginInfoWrapper startPlugin(PluginManager pm, String 
filename, FredPlugin plug, PluginRespirator pr) {
                PluginStarter ps = new PluginStarter(pr);
                PluginInfoWrapper pi = new PluginInfoWrapper(plug, ps, 
filename);
+               
+               // This is an ugly trick... sorry ;o)
+               // The thread still exists as an identifier, but is never 
started if the
+               // plugin doesn't require it
                ps.setPlugin(pm, plug);
-               ps.start();
+               if (!pi.isThreadlessPlugin())
+                       ps.start();
                return pi;
        }


Modified: trunk/freenet/src/freenet/pluginmanager/PluginInfoWrapper.java
===================================================================
--- trunk/freenet/src/freenet/pluginmanager/PluginInfoWrapper.java      
2006-03-11 00:11:20 UTC (rev 8222)
+++ trunk/freenet/src/freenet/pluginmanager/PluginInfoWrapper.java      
2006-03-11 00:26:13 UTC (rev 8223)
@@ -1,6 +1,8 @@
 package freenet.pluginmanager;

 import java.util.Date;
+import java.util.HashMap;
+import java.util.HashSet;

 public class PluginInfoWrapper {
        // Parameters to make the object OTP
@@ -12,7 +14,9 @@
        private String threadName;
        private FredPlugin plug;
        private boolean isPproxyPlugin;
+       private boolean isThreadlessPlugin;
        private String filename;
+       private HashSet toadletLinks=new HashSet(); 
        //public String 

        public PluginInfoWrapper(FredPlugin plug, Thread ps, String filename) {
@@ -26,6 +30,7 @@
                ps.setName(threadName);
                fedPluginThread = true;
                isPproxyPlugin = (plug instanceof FredPluginHTTP);
+               isThreadlessPlugin = (plug instanceof FredPluginThreadless);
        }

        public String toString() {
@@ -43,7 +48,29 @@
        public String getPluginClassName(){
                return plug.getClass().getName().toString();
        }
-
+       
+       public String[] getPluginToadletSymlinks(){
+               synchronized (toadletLinks) {
+                       return (String[])toadletLinks.toArray();
+               }
+       }
+       
+       public boolean addPluginToadletSymlink(String linkfrom){
+               synchronized (toadletLinks) {
+                       if (toadletLinks.size() < 1)
+                               toadletLinks = new HashSet();
+                       return toadletLinks.add(linkfrom);
+               }
+       }
+       
+       public boolean removePluginToadletSymlink(String linkfrom){
+               synchronized (toadletLinks) {
+                       if (toadletLinks.size() < 1)
+                               return false;
+                       return toadletLinks.remove(linkfrom);
+               }
+       }
+       
        public void stopPlugin() {
                plug.terminate();
                thread.interrupt();
@@ -60,5 +87,13 @@
        public String getFilename() {
                return filename;
        }
+
+       public boolean isThreadlessPlugin() {
+               return isThreadlessPlugin;
+       }
+
+       public Thread getThread() {
+               return thread;
+       }

 }

Modified: trunk/freenet/src/freenet/pluginmanager/PluginManager.java
===================================================================
--- trunk/freenet/src/freenet/pluginmanager/PluginManager.java  2006-03-11 
00:11:20 UTC (rev 8222)
+++ trunk/freenet/src/freenet/pluginmanager/PluginManager.java  2006-03-11 
00:26:13 UTC (rev 8223)
@@ -158,6 +158,7 @@
                                                        Logger.normal(this, 
"Removed HTTP handler for /plugins/"+
                                                                        
pi.getPluginClassName()+"/");
                                                } catch (Throwable ex) {
+                                                       Logger.error(this, 
"removing Plugin", ex);
                                                }
                                        }
                                }
@@ -168,6 +169,47 @@
                }
                saveConfig();
        }
+       
+       public void addToadletSymlinks(PluginInfoWrapper pi) {
+               synchronized (toadletList) {
+                       try {
+                               String targets[] = 
pi.getPluginToadletSymlinks();
+                               if (targets == null)
+                                       return;
+                               
+                               for (int i = 0 ; i < targets.length ; i++) {
+                                       toadletList.remove(targets[i]);
+                                       Logger.normal(this, "Removed HTTP 
symlink: " + targets[i] +
+                                                       " => 
/plugins/"+pi.getPluginClassName()+"/");
+                               }
+                       } catch (Throwable ex) {
+                               Logger.error(this, "removing Toadlet-link", ex);
+                       }
+               }
+               saveConfig();
+       }
+       
+       public void removeToadletSymlinks(PluginInfoWrapper pi) {
+               synchronized (toadletList) {
+                       String rm = null;
+                       try {
+                               String targets[] = 
pi.getPluginToadletSymlinks();
+                               if (targets == null)
+                                       return;
+                               
+                               for (int i = 0 ; i < targets.length ; i++) {
+                                       rm = targets[i];
+                                       toadletList.remove(targets[i]);
+                                       
pi.removePluginToadletSymlink(targets[i]);
+                                       Logger.normal(this, "Removed HTTP 
symlink: " + targets[i] +
+                                                       " => 
/plugins/"+pi.getPluginClassName()+"/");
+                               }
+                       } catch (Throwable ex) {
+                               Logger.error(this, "removing Toadlet-link: " + 
rm, ex);
+                       }
+               }
+               saveConfig();
+       }

        public String dumpPlugins() {
                StringBuffer out= new StringBuffer();
@@ -213,16 +255,21 @@
        }

        public void killPlugin(String name) {
+               PluginInfoWrapper pi = null;
+               boolean found = false;
                synchronized (pluginInfo) {
                        Iterator it = pluginInfo.keySet().iterator();
-                       while (it.hasNext()) {
-                               PluginInfoWrapper pi = (PluginInfoWrapper) 
pluginInfo.get(it.next());
+                       while (it.hasNext() && !found) {
+                               pi = (PluginInfoWrapper) 
pluginInfo.get(it.next());
                                if (pi.getThreadName().equals(name))
-                               {
-                                       pi.stopPlugin();
-                               }
+                                       found = true;
                        }
                }
+               if (found)
+                       if (pi.isThreadlessPlugin())
+                               removePlugin(pi.getThread());
+                       else
+                               pi.stopPlugin();
        }




Reply via email to