Author: toad
Date: 2008-06-19 18:49:58 +0000 (Thu, 19 Jun 2008)
New Revision: 20500

Modified:
   branches/db4o/freenet/src/freenet/node/NodeClientCore.java
   branches/db4o/freenet/src/freenet/support/io/FileUtil.java
   branches/db4o/freenet/src/freenet/support/io/FilenameGenerator.java
   branches/db4o/freenet/src/freenet/support/io/PersistentTempBucketFactory.java
Log:
Persist the persistent temp bucket factory.
Support moving it from one dir and prefix to another dir and prefix.

Modified: branches/db4o/freenet/src/freenet/node/NodeClientCore.java
===================================================================
--- branches/db4o/freenet/src/freenet/node/NodeClientCore.java  2008-06-19 
18:13:56 UTC (rev 20499)
+++ branches/db4o/freenet/src/freenet/node/NodeClientCore.java  2008-06-19 
18:49:58 UTC (rev 20500)
@@ -215,7 +215,10 @@
                                        }
                });
                try {
-                       persistentTempBucketFactory = new 
PersistentTempBucketFactory(new 
File(nodeConfig.getString("persistentTempDir")), "freenet-temp-", random, 
node.fastWeakRandom);
+                       File dir = new 
File(nodeConfig.getString("persistentTempDir"));
+                       String prefix = "freenet-temp-";
+                       persistentTempBucketFactory = 
PersistentTempBucketFactory.load(dir, prefix, random, node.fastWeakRandom, 
container, node.nodeDBHandle);
+                       persistentTempBucketFactory.init(dir, prefix, random, 
node.fastWeakRandom);
                        persistentEncryptedTempBucketFactory = new 
PersistentEncryptedTempBucketFactory(persistentTempBucketFactory);
                } catch (IOException e2) {
                        String msg = "Could not find or create persistent 
temporary directory";

Modified: branches/db4o/freenet/src/freenet/support/io/FileUtil.java
===================================================================
--- branches/db4o/freenet/src/freenet/support/io/FileUtil.java  2008-06-19 
18:13:56 UTC (rev 20499)
+++ branches/db4o/freenet/src/freenet/support/io/FileUtil.java  2008-06-19 
18:49:58 UTC (rev 20500)
@@ -182,6 +182,52 @@
             return true;
         }

+        /**
+         * Like renameTo(), but can move across filesystems, by copying the 
data.
+         * @param f
+         * @param file
+         */
+       public static boolean moveTo(File orig, File dest, boolean overwrite) {
+            if(orig.equals(dest))
+                throw new IllegalArgumentException("Huh? the two file 
descriptors are the same!");
+            if(!orig.exists()) {
+               throw new IllegalArgumentException("Original doesn't exist!");
+            }
+               if(dest.exists() && overwrite)
+                       dest.delete();
+               else {
+                       System.err.println("Not overwriting "+dest+" - already 
exists moving "+orig);
+                       return false;
+               }
+               if(!orig.renameTo(dest)) {
+                       // Copy the data
+                       InputStream is = null;
+                       OutputStream os = null;
+                       try {
+                               is = new FileInputStream(orig);
+                               os = new FileOutputStream(dest);
+                               copy(is, os, orig.length());
+                               is.close();
+                               is = null;
+                               os.close();
+                               os = null;
+                               orig.delete();
+                               return true;
+                       } catch (IOException e) {
+                               dest.delete();
+                               Logger.error(FileUtil.class, "Move failed from 
"+orig+" to "+dest+" : "+e, e);
+                               System.err.println("Move failed from "+orig+" 
to "+dest+" : "+e);
+                               e.printStackTrace();
+                               return false;
+                       } finally {
+                               Closer.close(is);
+                               Closer.close(os);
+                       }
+               } else return true;
+       }
+
+
+        
        public static String sanitize(String s) {
                StringBuffer sb = new StringBuffer(s.length());
                for(int i=0;i<s.length();i++) {

Modified: branches/db4o/freenet/src/freenet/support/io/FilenameGenerator.java
===================================================================
--- branches/db4o/freenet/src/freenet/support/io/FilenameGenerator.java 
2008-06-19 18:13:56 UTC (rev 20499)
+++ branches/db4o/freenet/src/freenet/support/io/FilenameGenerator.java 
2008-06-19 18:49:58 UTC (rev 20500)
@@ -12,9 +12,9 @@

 public class FilenameGenerator {

-    private final Random random;
-    private final String prefix;
-    private final File tmpDir;
+    private transient Random random;
+    private String prefix;
+    private File tmpDir;

     /**
      * @param random
@@ -104,4 +104,91 @@
                }
        }

+       public File getDir() {
+               return tmpDir;
+       }
+
+       /**
+        * Set up the dir and prefix. Note that while we can change the dir and 
prefix, we *cannot do so online*,
+        * at least not on Windows.
+        * @param dir
+        * @param prefix
+        */
+       public void init(File dir, String prefix, Random random) throws 
IOException {
+               this.random = random;
+               if(tmpDir.equals(dir) && this.prefix.equals(prefix)) {
+                       Logger.normal(this, "Initialised FilenameGenerator 
successfully - no change in dir and prefix: dir="+dir+" prefix="+prefix);
+               } else if(!tmpDir.equals(dir) && this.prefix.equals(prefix)) {
+                       if((!dir.exists()) && tmpDir.renameTo(dir)) {
+                               tmpDir = dir;
+                               // This will interest the user, since they 
changed it.
+                               String msg = "Successfully renamed persistent 
temporary directory from "+tmpDir+" to "+dir;
+                               Logger.error(this, msg);
+                               System.err.println(msg);
+                       } else {
+                               if(!dir.exists()) {
+                                       if(!dir.mkdir()) {
+                                               // FIXME localise these errors 
somehow??
+                                               System.err.println("Unable to 
create new temporary directory: "+dir);
+                                               throw new IOException("Unable 
to create new temporary directory: "+dir);
+                                       }
+                               }
+                               if(!(dir.canRead() && dir.canWrite())) {
+                                       // FIXME localise these errors somehow??
+                                       System.err.println("Unable to read and 
write new temporary directory: "+dir);
+                                       throw new IOException("Unable to read 
and write new temporary directory: "+dir);
+                               }
+                               int moved = 0;
+                               int failed = 0;
+                               // Move each file
+                               File[] list = tmpDir.listFiles();
+                               for(int i=0;i<list.length;i++) {
+                                       File f = list[i];
+                                       String name = f.getName();
+                                       if(!name.startsWith(prefix)) continue;
+                                       if(FileUtil.moveTo(f, new File(dir, 
name), true))
+                                               moved++;
+                                       else
+                                               failed++;
+                               }
+                               if(failed > 0) {
+                                       // FIXME maybe a useralert
+                                       System.err.println("WARNING: Not all 
files successfully moved changing temp dir: "+failed+" failed.");
+                                       System.err.println("WARNING: Some 
persistent downloads etc may fail.");
+                               }
+                       }
+               } else {
+                       if(!dir.exists()) {
+                               if(!dir.mkdir()) {
+                                       // FIXME localise these errors somehow??
+                                       System.err.println("Unable to create 
new temporary directory: "+dir);
+                                       throw new IOException("Unable to create 
new temporary directory: "+dir);
+                               }
+                       }
+                       if(!(dir.canRead() && dir.canWrite())) {
+                               // FIXME localise these errors somehow??
+                               System.err.println("Unable to read and write 
new temporary directory: "+dir);
+                               throw new IOException("Unable to read and write 
new temporary directory: "+dir);
+                       }
+                       int moved = 0;
+                       int failed = 0;
+                       // Move each file
+                       File[] list = tmpDir.listFiles();
+                       for(int i=0;i<list.length;i++) {
+                               File f = list[i];
+                               String name = f.getName();
+                               if(!name.startsWith(this.prefix)) continue;
+                               String newName = prefix + 
name.substring(this.prefix.length());
+                               if(FileUtil.moveTo(f, new File(dir, newName), 
true)) {
+                                       moved++;
+                               }
+                       }
+                       if(failed > 0) {
+                               // FIXME maybe a useralert
+                               System.err.println("WARNING: Not all files 
successfully moved changing temp dir: "+failed+" failed.");
+                               System.err.println("WARNING: Some persistent 
downloads etc may fail.");
+                       }
+               }
+       }
+
 }

Modified: 
branches/db4o/freenet/src/freenet/support/io/PersistentTempBucketFactory.java
===================================================================
--- 
branches/db4o/freenet/src/freenet/support/io/PersistentTempBucketFactory.java   
    2008-06-19 18:13:56 UTC (rev 20499)
+++ 
branches/db4o/freenet/src/freenet/support/io/PersistentTempBucketFactory.java   
    2008-06-19 18:49:58 UTC (rev 20500)
@@ -3,17 +3,20 @@
  * http://www.gnu.org/ for further details of the GPL. */
 package freenet.support.io;

-import freenet.crypt.RandomSource;
 import java.io.File;
 import java.io.IOException;
 import java.util.HashSet;
-import java.util.Iterator;
 import java.util.LinkedList;
+import java.util.Random;

+import com.db4o.ObjectContainer;
+import com.db4o.ObjectSet;
+import com.db4o.query.Predicate;
+
+import freenet.crypt.RandomSource;
 import freenet.support.Logger;
 import freenet.support.api.Bucket;
 import freenet.support.api.BucketFactory;
-import java.util.Random;

 /**
  * Handles persistent temp files. These are used for e.g. persistent downloads.
@@ -26,9 +29,6 @@
  */
 public class PersistentTempBucketFactory implements BucketFactory, 
PersistentFileTracker {

-       /** Directory containing persistent temporary files */
-       private final File dir;
-       
        /** Original contents of directory */
        private HashSet originalFiles;

@@ -36,16 +36,18 @@
        private final FilenameGenerator fg;

        /** Random number generator */
-       private final RandomSource strongPRNG;
-       private final Random weakPRNG;
+       private transient RandomSource strongPRNG;
+       private transient Random weakPRNG;

        /** Buckets to free */
        private LinkedList bucketsToFree;
+       
+       private final long nodeDBHandle;

-       public PersistentTempBucketFactory(File dir, String prefix, 
RandomSource strongPRNG, Random weakPRNG) throws IOException {
+       public PersistentTempBucketFactory(File dir, String prefix, 
RandomSource strongPRNG, Random weakPRNG, long nodeDBHandle) throws IOException 
{
                boolean logMINOR = Logger.shouldLog(Logger.MINOR, this);
-               this.dir = dir;
                this.strongPRNG = strongPRNG;
+               this.nodeDBHandle = nodeDBHandle;
                this.weakPRNG = weakPRNG;
                this.fg = new FilenameGenerator(weakPRNG, false, dir, prefix);
                if(!dir.exists()) {
@@ -78,6 +80,12 @@
                bucketsToFree = new LinkedList();
        }

+       public void init(File dir, String prefix, RandomSource strongPRNG, 
Random weakPRNG) throws IOException {
+               this.strongPRNG = strongPRNG;
+               this.weakPRNG = weakPRNG;
+               fg.init(dir, prefix, weakPRNG);
+       }
+       
        public void register(File file) {
                synchronized(this) {
                        if(originalFiles == null)
@@ -139,7 +147,7 @@
        }

        public File getDir() {
-               return dir;
+               return fg.getDir();
        }

        public FilenameGenerator getGenerator() {
@@ -154,4 +162,19 @@
                return fg.getID(file);
        }

+       public static PersistentTempBucketFactory load(File dir, String prefix, 
RandomSource random, Random fastWeakRandom, ObjectContainer container, final 
long nodeDBHandle) throws IOException {
+               ObjectSet results = container.query(new Predicate() {
+                       public boolean match(PersistentTempBucketFactory 
factory) {
+                               if(factory.nodeDBHandle == nodeDBHandle) return 
true;
+                               return false;
+                       }
+               });
+               if(results.hasNext()) {
+                       PersistentTempBucketFactory factory = 
(PersistentTempBucketFactory) results.next();
+                       factory.init(dir, prefix, random, fastWeakRandom);
+                       return factory;
+               } else
+                       return new PersistentTempBucketFactory(dir, prefix, 
random, fastWeakRandom, nodeDBHandle);
+       }
+
 }


Reply via email to