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;
+ }
+ }
+ }
+
+ }
+
+}