Author: toad
Date: 2005-11-05 22:32:47 +0000 (Sat, 05 Nov 2005)
New Revision: 7489

Added:
   
trunk/freenet/src/freenet/support/PaddedEphemerallyEncryptedBucketFactory.java
   trunk/freenet/src/freenet/support/io/TempBucketFactory.java
   trunk/freenet/src/freenet/support/io/TempBucketHook.java
   trunk/freenet/src/freenet/support/io/TempFileBucket.java
Modified:
   trunk/freenet/src/freenet/node/Node.java
   trunk/freenet/src/freenet/node/TextModeClientInterface.java
   trunk/freenet/src/freenet/support/PaddedEphemerallyEncryptedBucket.java
Log:
Working towards making TMCI use HighLevelSimpleClientInterface.

Modified: trunk/freenet/src/freenet/node/Node.java
===================================================================
--- trunk/freenet/src/freenet/node/Node.java    2005-11-05 21:28:16 UTC (rev 
7488)
+++ trunk/freenet/src/freenet/node/Node.java    2005-11-05 22:32:47 UTC (rev 
7489)
@@ -24,6 +24,9 @@
 import java.util.HashSet;
 import java.util.Hashtable;

+import freenet.client.ArchiveManager;
+import freenet.client.HighLevelSimpleClient;
+import freenet.client.HighLevelSimpleClientImpl;
 import freenet.crypt.DiffieHellman;
 import freenet.crypt.RandomSource;
 import freenet.crypt.Yarrow;
@@ -44,11 +47,14 @@
 import freenet.keys.NodeCHK;
 import freenet.store.BaseFreenetStore;
 import freenet.store.FreenetStore;
+import freenet.support.BucketFactory;
 import freenet.support.FileLoggerHook;
 import freenet.support.HexUtil;
 import freenet.support.LRUQueue;
 import freenet.support.Logger;
+import freenet.support.PaddedEphemerallyEncryptedBucketFactory;
 import freenet.support.SimpleFieldSet;
+import freenet.support.io.TempBucketFactory;

 /**
  * @author amphibian
@@ -120,6 +126,10 @@
     public final long bootID;
     public final long startupTime;

+    // Client stuff
+    final ArchiveManager archiveManager;
+    final BucketFactory tempBucketFactory;
+    
     /**
      * Read all storable settings (identity etc) from the node file.
      * @param filename The name of the file to read from.
@@ -298,6 +308,7 @@
         bootID = random.nextLong();
         localStreamContexts = new Hashtable();
         peers.writePeers();
+        tempBucketFactory = new PaddedEphemerallyEncryptedBucketFactory(new 
TempBucketFactory("temp", true));
     }

     void start(SwapRequestInterval interval) {
@@ -705,4 +716,8 @@
         myName = key;
         writeNodeFile();
     }
+
+       public HighLevelSimpleClient makeClient() {
+               return new HighLevelSimpleClientImpl(this, archiveManager, 
null, random);
+       }
 }

Modified: trunk/freenet/src/freenet/node/TextModeClientInterface.java
===================================================================
--- trunk/freenet/src/freenet/node/TextModeClientInterface.java 2005-11-05 
21:28:16 UTC (rev 7488)
+++ trunk/freenet/src/freenet/node/TextModeClientInterface.java 2005-11-05 
22:32:47 UTC (rev 7489)
@@ -13,6 +13,7 @@
 import java.net.MalformedURLException;
 import java.util.Hashtable;

+import freenet.client.HighLevelSimpleClient;
 import freenet.crypt.RandomSource;
 import freenet.io.comm.PeerParseException;
 import freenet.keys.CHKBlock;
@@ -35,10 +36,12 @@

     final RandomSource r;
     final Node n;
+    final HighLevelSimpleClient client;
     final Hashtable streams;

     TextModeClientInterface(Node n) {
         this.n = n;
+        client = n.makeClient();
         this.r = n.random;
         streams = new Hashtable();
         new Thread(this).start();

Modified: 
trunk/freenet/src/freenet/support/PaddedEphemerallyEncryptedBucket.java
===================================================================
--- trunk/freenet/src/freenet/support/PaddedEphemerallyEncryptedBucket.java     
2005-11-05 21:28:16 UTC (rev 7488)
+++ trunk/freenet/src/freenet/support/PaddedEphemerallyEncryptedBucket.java     
2005-11-05 22:32:47 UTC (rev 7489)
@@ -207,4 +207,11 @@
                readOnly = true;
        }

+       /**
+        * @return The underlying Bucket.
+        */
+       public Bucket getUnderlying() {
+               return bucket;
+       }
+
 }

Added: 
trunk/freenet/src/freenet/support/PaddedEphemerallyEncryptedBucketFactory.java
===================================================================
--- 
trunk/freenet/src/freenet/support/PaddedEphemerallyEncryptedBucketFactory.java  
    2005-11-05 21:28:16 UTC (rev 7488)
+++ 
trunk/freenet/src/freenet/support/PaddedEphemerallyEncryptedBucketFactory.java  
    2005-11-05 22:32:47 UTC (rev 7489)
@@ -0,0 +1,36 @@
+package freenet.support;
+
+import java.io.IOException;
+
+import freenet.crypt.RandomSource;
+import freenet.crypt.UnsupportedCipherException;
+
+/**
+ * Factory wrapper for PaddedEphemerallyEncryptedBucket's, which are themselves
+ * wrappers.
+ */
+public class PaddedEphemerallyEncryptedBucketFactory implements BucketFactory {
+
+       final BucketFactory baseFactory;
+       final RandomSource random;
+       final int minSize;
+       
+       public PaddedEphemerallyEncryptedBucketFactory(BucketFactory factory, 
RandomSource r, int minSize) {
+               baseFactory = factory;
+               this.minSize = minSize;
+               this.random = r;
+       }
+
+       public Bucket makeBucket(long size) throws IOException {
+               try {
+                       return new 
PaddedEphemerallyEncryptedBucket(baseFactory.makeBucket(size), minSize, random);
+               } catch (UnsupportedCipherException e) {
+                       throw new Error(e);
+               }
+       }
+
+       public void freeBucket(Bucket b) throws IOException {
+               
baseFactory.freeBucket(((PaddedEphemerallyEncryptedBucket)b).getUnderlying());
+       }
+
+}

Added: trunk/freenet/src/freenet/support/io/TempBucketFactory.java
===================================================================
--- trunk/freenet/src/freenet/support/io/TempBucketFactory.java 2005-11-05 
21:28:16 UTC (rev 7488)
+++ trunk/freenet/src/freenet/support/io/TempBucketFactory.java 2005-11-05 
22:32:47 UTC (rev 7489)
@@ -0,0 +1,200 @@
+package freenet.support.io;
+
+import java.io.File;
+import java.io.IOException;
+
+import freenet.crypt.RandomSource;
+import freenet.support.Bucket;
+import freenet.support.BucketFactory;
+import freenet.support.Logger;
+
+/*
+ * This code is part of fproxy, an HTTP proxy server for Freenet. It is
+ * distributed under the GNU Public Licence (GPL) version 2. See
+ * http://www.gnu.org/ for further details of the GPL.
+ */
+
+/**
+ * Temporary Bucket Factory
+ * 
+ * @author giannij
+ */
+public class TempBucketFactory implements BucketFactory {
+       private File tmpDir = null;
+
+       private static class NOPHook implements TempBucketHook {
+               public void enlargeFile(long curLength, long finalLength) {
+               }
+               public void shrinkFile(long curLength, long finalLength) {
+               }
+               public void deleteFile(long curLength) {
+               }
+               public void createFile(long curLength) {
+               }
+       }
+
+       private final static TempBucketHook DONT_HOOK = new NOPHook();
+       private static TempBucketHook hook = DONT_HOOK;
+       private static boolean logDebug=true;
+       
+       private final RandomSource random;
+       private final String prefix;
+
+       public static long defaultIncrement = 4096;
+
+       // Storage accounting disabled by default.
+       public TempBucketFactory(String temp, boolean wipeFiles, RandomSource 
random, String prefix) throws IOException {
+               logDebug = Logger.shouldLog(Logger.DEBUG,this);
+               tmpDir = new File(temp);
+               if (tmpDir == null)
+                       tmpDir = new File(System.getProperty("java.io.tmpdir"));
+               this.random = random;
+               this.prefix = prefix;
+               if(!tmpDir.exists()) {
+                       tmpDir.mkdir();
+               }
+               if(!(tmpDir.isDirectory() && tmpDir.canRead() && 
tmpDir.canWrite()))
+                       throw new IOException("Not a directory or cannot 
read/write: "+tmpDir);
+               
+               if(wipeFiles) {
+                       File[] filenames = tmpDir.listFiles();
+                       if(filenames != null) {
+                               for(int i=0;i<filenames.length;i++) {
+                                       File f = filenames[i];
+                                       String name = f.getName();
+                                       if((File.separatorChar == '\\' && 
name.toLowerCase().startsWith(prefix.toLowerCase()) ||
+                                                       
name.startsWith(prefix))) {
+                                               f.delete();
+                                       }
+                               }
+                       }
+               }
+               //     Core.logger.log(this, "Creating TempBucketFactory, 
tmpDir = "+
+               //                  (tmpDir == null ? "(null)" : tmpDir),
+               //                  new Exception("debug"), Logger.DEBUG);
+       }
+
+       public TempBucketFactory(RandomSource random) throws IOException {
+               this(System.getProperty("java.io.tmpdir"), true, random, 
"freenet-temp-");
+               if (logDebug)
+                       Logger.debug(
+                               this,
+                               "Creating TempBucketFactory, tmpDir = " + 
tmpDir,
+                               new Exception("debug"));
+       }
+
+       public Bucket makeBucket(long size) throws IOException {
+               return makeBucket(size, 1.25F, defaultIncrement);
+       }
+
+       public Bucket makeBucket(long size, float factor) throws IOException {
+               return makeBucket(size, factor, defaultIncrement);
+       }
+
+       /**
+        * Create a temp bucket
+        * 
+        * @param size
+        *            Default size
+        * @param factor
+        *            Factor to increase size by when need more space
+        * @return A temporary Bucket
+        * @exception IOException
+        *                If it is not possible to create a temp bucket due to 
an
+        *                I/O error
+        */
+       public TempFileBucket makeBucket(long size, float factor, long 
increment)
+               throws IOException {
+               logDebug = Logger.shouldLog(Logger.DEBUG,this);
+               File f = null;
+               do {
+                       if (tmpDir != null) {
+                               f =
+                                       new File(
+                                               tmpDir,
+                                               "tbf_"
+                                                       + Long.toHexString(
+                                                               
Math.abs(random.nextInt())));
+                               if (logDebug)
+                                       Logger.debug(
+                                               this,
+                                               "Temp file in " + tmpDir);
+                       } else {
+                               f =
+                                       new File(
+                                               "tbf_"
+                                                       + Long.toHexString(
+                                                               
Math.abs(random.nextInt())));
+                               if (logDebug)
+                                       Logger.debug(this, "Temp file in pwd");
+                       }
+               } while (f.exists());
+
+               //System.err.println("TEMP BUCKET CREATED: " + 
f.getAbsolutePath());
+               //(new Exception("creating TempBucket")).printStackTrace();
+
+               if (logDebug)
+                       Logger.debug(
+                               this,
+                               "Temp bucket created: "
+                                       + f.getAbsolutePath()
+                                       + " with hook "
+                                       + hook
+                                       + " initial length "
+                                       + size,
+                               new Exception("creating TempBucket"));
+
+               return new TempFileBucket(f, hook, size, increment, factor);
+       }
+
+       /**
+        * Free bucket
+        * 
+        * @param b
+        *            Description of the Parameter
+        */
+       public void freeBucket(Bucket b) {
+               if (b instanceof TempFileBucket) {
+                       if (logDebug)
+                               Logger.debug(
+                                       this,
+                                       "Temp bucket released: "
+                                               + ((TempFileBucket) 
b).getFile().getAbsolutePath(),
+                                       new Exception("debug"));
+                       if (!((TempFileBucket) b).release()) {
+                               System.err.println("Could not release temp 
bucket" + b);
+                               Logger.error(
+                                       this,
+                                       "Could not release temp bucket " + b,
+                                        new Exception("Failed to release 
tempbucket"));
+                       }
+               }
+       }
+
+       /**
+        * Sets the storage accounting hook.
+        * 
+        * @param t
+        *            The hook object to use to keep track of the amount of 
storage
+        *            used. It is legal for t to be null. In this case storage
+        *            accounting is disabled.
+        */
+       public static void setHook(TempBucketHook t) {
+               if (logDebug)
+                       Logger.debug(
+                               TempBucketFactory.class,
+                               "Set TempBucketHook to " + t);
+               hook = t;
+               if (hook == null) {
+                       // Allow hooks to be disabled w/o sprinkling
+                       // if (hook != null) {/*blah blah */} calls
+                       // throughout the code.
+                       hook = DONT_HOOK;
+                       if (logDebug) {
+                               Logger.debug(
+                                       TempBucketHook.class,
+                                       "TempBucketHook file usage management 
was disabled.");
+                       }
+               }
+       }
+}

Added: trunk/freenet/src/freenet/support/io/TempBucketHook.java
===================================================================
--- trunk/freenet/src/freenet/support/io/TempBucketHook.java    2005-11-05 
21:28:16 UTC (rev 7488)
+++ trunk/freenet/src/freenet/support/io/TempBucketHook.java    2005-11-05 
22:32:47 UTC (rev 7489)
@@ -0,0 +1,31 @@
+package freenet.support.io;
+
+import java.io.IOException;
+
+public interface TempBucketHook {
+    
+    /** Allocate space for a write making the file larger
+     * Call this before writing a file, make sure you call shrinkFile if the 
write fails
+     * @param curLength the length of the file before the write
+     * @param finalLength the length of the file after the write
+     * @throws IOException if insufficient space
+     */
+    void enlargeFile(long curLength, long finalLength) throws IOException;
+    
+    /** Deallocate space after a write enlarging the file fails
+     * Call this if enlargeFile was called but the write failed.
+     * Also call it if you want to truncate a file
+     * @param curLength original length before write
+     * @param finalLength length the file would have been if the write had 
succeeded
+     */
+    void shrinkFile(long curLength, long finalLength);
+    
+    /** Deallocate space for a temp file, AFTER successful delete completed
+     */
+    void deleteFile(long curLength);
+    
+    /** Allocate space for a temp file, before actually creating it
+     */
+    void createFile(long curLength) throws IOException;
+
+}

Added: trunk/freenet/src/freenet/support/io/TempFileBucket.java
===================================================================
--- trunk/freenet/src/freenet/support/io/TempFileBucket.java    2005-11-05 
21:28:16 UTC (rev 7488)
+++ trunk/freenet/src/freenet/support/io/TempFileBucket.java    2005-11-05 
22:32:47 UTC (rev 7489)
@@ -0,0 +1,430 @@
+package freenet.support.io;
+
+import java.io.File;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.util.Vector;
+
+import freenet.support.Logger;
+
+/*
+ *  This code is part of fproxy, an HTTP proxy server for Freenet.
+ *  It is distributed under the GNU Public Licence (GPL) version 2.  See
+ *  http://www.gnu.org/ for further details of the GPL.
+ */
+/**
+ * Temporary file handling. TempFileBuckets start empty.
+ *
+ * @author     giannij
+ */
+public class TempFileBucket extends FileBucket {
+       TempBucketHook hook = null;
+       // How much we have asked the Hook to allocate for us
+       long fakeLength = 0;
+       long minAlloc;
+       float factor;
+       private static boolean logDebug = true;
+       /**
+        * Constructor for the TempFileBucket object
+        *
+        * @param  f  File
+        */
+       protected TempFileBucket(
+               File f,
+               TempBucketHook hook,
+               long startLength,
+               long minAlloc,
+               float factor)
+               throws IOException {
+               super(f, false, true, true);
+               logDebug = Logger.shouldLog(Logger.DEBUG, this);
+               if (minAlloc > 0)
+                       this.minAlloc = minAlloc;
+               else
+                       this.minAlloc = 1024;
+               this.factor = factor;
+               if (factor < 1.0)
+                       throw new IllegalArgumentException("factor must be >= 
1.0");
+
+               // Make sure finalize wacks temp file 
+               // if it is not explictly freed.
+               newFile = true;
+
+               //System.err.println("FproxyServlet.TempFileBucket -- created: 
" +
+               //         f.getAbsolutePath());
+               this.hook = hook;
+               long x = startLength <= 0 ? minAlloc : startLength;
+               hook.createFile(x);
+               this.fakeLength = x;
+               if (logDebug)
+                       Logger.debug(
+                               this,
+                               "Initializing TempFileBucket(" + f + "," + hook 
+ ")");
+       }
+
+       /**
+        *  Gets the realInputStream attribute of the TempFileBucket object
+        *
+        * @return                  The realInputStream value
+        * @exception  IOException  Description of the Exception
+        */
+       InputStream getRealInputStream() throws IOException {
+               if (released)
+                       throw new IllegalStateException(
+                               "Trying to getInputStream on " + "released 
TempFileBucket!");
+               if (logDebug)
+                       Logger.debug(
+                               this,
+                               "getRealInputStream() for " + file,
+                               new Exception("debug"));
+               if (!file.exists())
+                       return new NullInputStream();
+               else
+                       return new HookedFileBucketInputStream(file);
+       }
+
+       /**
+        *  Gets the realOutputStream attribute of the TempFileBucket object
+        *
+        * @return                  The realOutputStream value
+        * @exception  IOException  Description of the Exception
+        */
+       OutputStream getRealOutputStream() throws IOException {
+               if (logDebug)
+                       Logger.debug(
+                               this,
+                               "getRealOutputStream() for " + file,
+                               new Exception("debug"));
+               return super.getOutputStream();
+       }
+
+       // Wrap non-const members so we can tell
+       // when code touches the Bucket after it
+       // has been released.
+       /**
+        *  Gets the inputStream attribute of the TempFileBucket object
+        *
+        * @return                  The inputStream value
+        * @exception  IOException  Description of the Exception
+        */
+       public synchronized InputStream getInputStream() throws IOException {
+               logDebug = Logger.shouldLog(Logger.DEBUG, this);
+               if (logDebug)
+                       Logger.debug(this, "getInputStream for " + file);
+               InputStream newIn = new SpyInputStream(this, 
file.getAbsolutePath());
+               return newIn;
+       }
+
+       /**
+        *  Gets the outputStream attribute of the TempFileBucket object
+        *
+        * @return                  The outputStream value
+        * @exception  IOException  Description of the Exception
+        */
+       public synchronized OutputStream getOutputStream() throws IOException {
+               logDebug = Logger.shouldLog(Logger.DEBUG, this);
+               if (logDebug)
+                       Logger.debug(this, "getOutputStream for " + file);
+               return new SpyOutputStream(this, file.getAbsolutePath());
+       }
+
+       /**
+        *  Release
+        *
+        * @return    Success
+        */
+       public synchronized boolean release() {
+               //System.err.println("FproxyServlet.TempFileBucket -- release: 
" +                      // file.getAbsolutePath());
+
+               //System.err.println("CALL STACK: ");
+               //(new Exception()).printStackTrace();
+
+               // Force all open streams closed.
+               // Windows won't let us delete the file unless we
+               // do this.
+               logDebug = Logger.shouldLog(Logger.DEBUG, this);
+               if (logDebug)
+                       Logger.debug(this, "Releasing TempFileBucket " + file);
+               for (int i = 0; i < streams.size(); i++) {
+                       try {
+                               if (streams.elementAt(i) instanceof 
InputStream) {
+                                       InputStream is = (InputStream) 
streams.elementAt(i);
+                                       is.close();
+
+                                       if (logDebug) {
+                                               Logger.debug(
+                                                       this,
+                                                       "closed open 
InputStream !: "
+                                                               + 
file.getAbsolutePath(),
+                                                       new Exception("debug"));
+                                               if (is instanceof 
FileBucketInputStream) {
+                                                       Logger.debug(
+                                                               this,
+                                                               "Open 
InputStream created: ",
+                                                               
((FileBucketInputStream) is).e);
+                                               }
+                                       }
+                               } else if (streams.elementAt(i) instanceof 
OutputStream) {
+                                       OutputStream os = (OutputStream) 
(streams.elementAt(i));
+                                       os.close();
+                                       if (logDebug) {
+                                               Logger.debug(
+                                                       this,
+                                                       "closed open 
OutputStream !: "
+                                                               + 
file.getAbsolutePath(),
+                                                       new Exception("debug"));
+                                               if (os instanceof 
FileBucketOutputStream) {
+                                                       Logger.debug(
+                                                               this,
+                                                               "Open 
OutputStream created: ",
+                                                               
((FileBucketOutputStream) os).e);
+                                               }
+
+                                       }
+                               }
+                       } catch (IOException ioe) {
+                       }
+               }
+               if (logDebug)
+                       Logger.debug(this, "Closed streams for " + file);
+               if (released) {
+                       Logger.minor(
+                               this,
+                               "Already released file: " + file.getName());
+                       if (file.exists())
+                               throw new IllegalStateException(
+                                       "already released file "
+                                               + file.getName()
+                                               + " BUT IT STILL EXISTS!");
+                       return true;
+               }
+               if (logDebug)
+                       Logger.debug(
+                               this,
+                               "Checked for released for " + file);
+               released = true;
+               if (file.exists()) {
+                       if (logDebug)
+                               Logger.debug(
+                                       this,
+                                       "Deleting bucket " + file.getName());
+                       if (!file.delete()) {
+                               Logger.error(
+                                       this,
+                                       "Delete failed on bucket " + 
file.getName(),
+                                       new Exception());
+                               // Nonrecoverable; even though the user can't 
fix it it's still very serious
+                               return false;
+                       } else {
+                               if (hook != null)
+                                       hook.deleteFile(fakeLength);
+                       }
+               } else {
+                       if (hook != null)
+                               hook.deleteFile(fakeLength);
+               }
+               if (logDebug)
+                       Logger.debug(
+                               this,
+                               "release() returning true for " + file);
+               return true;
+       }
+
+       /**
+        *  Gets the released attribute of the TempFileBucket object
+        *
+        * @return    The released value
+        */
+       public final synchronized boolean isReleased() {
+               return released;
+       }
+
+       /**
+        *  Finalize
+        *
+        * @exception  Throwable  Description of the Exception
+        */
+       public void finalize() throws Throwable {
+               if (logDebug)
+                       Logger.debug(this, "Finalizing TempFileBucket for " + 
file);
+               super.finalize();
+       }
+
+       protected Vector streams = new Vector();
+       private boolean released;
+
+       protected FileBucketOutputStream newFileBucketOutputStream(
+               String s,
+               boolean append,
+               long restartCount)
+               throws IOException {
+               if (logDebug)
+                       Logger.debug(this,
+                               "Creating new HookedFileBucketOutputStream for 
" + file);
+               if (hook != null)
+                       return new HookedFileBucketOutputStream(s, append, 
restartCount);
+               else
+                       return super.newFileBucketOutputStream(s, append, 
restartCount);
+       }
+
+       protected void deleteFile() {
+               if (logDebug)
+                       Logger.debug(this, "Deleting " + file);
+               file.delete();
+               if (hook != null)
+                       hook.deleteFile(fakeLength);
+       }
+
+       protected synchronized void resetLength() {
+               if (logDebug)
+                       Logger.debug(this, "Resetting length for " + file);
+               if (length != 0) {
+                       if (hook != null) {
+                               hook.shrinkFile(0, fakeLength);
+                               fakeLength = 0;
+                       }
+                       super.resetLength();
+               }
+       }
+
+       protected final void getLengthSynchronized(long len) throws IOException 
{
+               //       Core.logger.log(this, "getLengthSynchronized("+len+
+               //                    "); fakeLength = "+fakeLength, 
Logger.DEBUG);
+               long l = fakeLength;
+               long ol = l;
+               while (len > l) {
+                       l = (long) (l * factor);
+                       if (minAlloc > 0)
+                               l = l + minAlloc - (l % minAlloc);
+                       if (l <= fakeLength)
+                               throw new IllegalStateException("Bucket 
extension error!");
+                       //        Core.logger.log(this, "l now "+l, 
Logger.DEBUG);
+                       if (ol == l)
+                               throw new IllegalStateException("infinite 
loop");
+                       ol = l;
+               }
+               if (fakeLength != l) {
+                       if (Logger.shouldLog(Logger.DEBUG, this))
+                               Logger.debug(
+                                       this,
+                                       "getLengthSynchronized("
+                                               + len
+                                               + "): increasing "
+                                               + fakeLength
+                                               + " to: "
+                                               + l
+                                               + " (real length: "
+                                               + length
+                                               + ")");
+                       hook.enlargeFile(fakeLength, l);
+               }
+               fakeLength = l;
+       }
+
+       public String toString(){
+               return "TempFileBucket (File: 
'"+getFile().getAbsolutePath()+"', streams: "+streams.size()+", hook: 
"+hook+")";
+       }
+
+       class HookedFileBucketInputStream extends FileBucketInputStream {
+               HookedFileBucketInputStream(File f) throws IOException {
+                       super(f);
+                       streams.addElement(this);
+               }
+
+               public void close() throws IOException {
+                       super.close();
+                       while (streams.remove(this));
+               }
+       }
+
+       class HookedFileBucketOutputStream extends FileBucketOutputStream {
+
+               protected HookedFileBucketOutputStream(
+                       String s,
+                       boolean append,
+                       long restartCount)
+                       throws IOException {
+                       super(s, append, restartCount);
+                       streams.addElement(this);
+                       if (Logger.shouldLog(Logger.DEBUG, this))
+                               Logger.debug(
+                                       this,
+                                       "Created HookedFileBucketOutputStream("
+                                               + s
+                                               + ","
+                                               + append
+                                               + ","
+                                               + restartCount
+                                               + ")");
+               }
+
+               public void close() throws IOException {
+                       super.close();
+                       while (streams.remove(this));
+               }
+
+               public void write(byte[] b) throws IOException {
+                       //        Core.logger.log(this, 
"HookedFileBucketOutputStream.write(byte[] len "+
+                       //                        b.length+") for "+file, 
Logger.DEBUG);
+                       synchronized (TempFileBucket.this) {
+                               //            Core.logger.log(this, 
"Synchronized on TempFileBucket", 
+                               //                            Logger.DEBUG);
+                               super.confirmWriteSynchronized();
+                               //            Core.logger.log(this, 
"confirmWriteSynchronized()", Logger.DEBUG);
+                               long finalLength = length + b.length;
+                               //            Core.logger.log(this, 
"length="+length+", finalLength="+finalLength,
+                               //                            Logger.DEBUG);
+                               long realStartLen = fakeLength;
+                               getLengthSynchronized(finalLength);
+                               //            Core.logger.log(this, "Called 
hook.enlargeFile()", Logger.DEBUG);
+                               try {
+                                       super.write(b);
+                                       //                Core.logger.log(this, 
"Written", Logger.DEBUG);
+                               } catch (IOException e) {
+                                       //                Core.logger.log(this, 
"Write failed", Logger.DEBUG);
+                                       hook.shrinkFile(realStartLen, 
fakeLength);
+                                       fakeLength = realStartLen;
+                                       //                Core.logger.log(this, 
"Shrank file", Logger.DEBUG);
+                                       throw e;
+                               }
+                       }
+               }
+
+               public void write(byte[] b, int off, int len) throws 
IOException {
+                       //        Core.logger.log(this, 
"HookedFileBucketOutputStream.write(byte[], "+off+
+                       //                        ","+len+") for "+file, 
Logger.DEBUG);
+                       synchronized (TempFileBucket.this) {
+                               long finalLength = length + len;
+                               long realStartLen = fakeLength;
+                               getLengthSynchronized(finalLength);
+                               try {
+                                       super.write(b, off, len);
+                               } catch (IOException e) {
+                                       hook.shrinkFile(realStartLen, 
fakeLength);
+                                       fakeLength = realStartLen;
+                                       throw e;
+                               }
+                       }
+               }
+
+               public void write(int b) throws IOException {
+                       //        Core.logger.log(this, 
"HookedFileBucketOutputStream.write(int) for "+file,
+                       //                        Logger.DEBUG);
+                       synchronized (TempFileBucket.this) {
+                               long finalLength = length + 1;
+                               long realStartLen = fakeLength;
+                               getLengthSynchronized(finalLength);
+                               try {
+                                       super.write(b);
+                               } catch (IOException e) {
+                                       hook.shrinkFile(realStartLen, 
fakeLength);
+                                       fakeLength = realStartLen;
+                                       throw e;
+                               }
+                       }
+               }
+
+       }
+
+}


Reply via email to