[prev in list] [next in list] [prev in thread] [next in thread] 

List:       jedit-cvs
Subject:    [ jEdit-commits ] SF.net SVN: jedit: [9041]
From:       vanza () users ! sourceforge ! net
Date:       2007-02-28 7:19:29
Message-ID: E1HMJ61-0004Es-P9 () sc8-pr-svn4 ! sourceforge ! net
[Download RAW message or body]

Revision: 9041
          http://svn.sourceforge.net/jedit/?rev=9041&view=rev
Author:   vanza
Date:     2007-02-27 23:19:29 -0800 (Tue, 27 Feb 2007)

Log Message:
-----------
Windows (at least) doesn't have an atomic rename. On top of that, it doesn't allow \
renaming if the target already exists. So, if the first attempt fails, be really \
paranoid when trying to rename the file (and also lose the atomicity in the \
process)...

Modified Paths:
--------------
    plugins/CommonControls/trunk/common/io/AtomicOutputStream.java

Modified: plugins/CommonControls/trunk/common/io/AtomicOutputStream.java
===================================================================
--- plugins/CommonControls/trunk/common/io/AtomicOutputStream.java	2007-02-28 \
                07:17:46 UTC (rev 9040)
+++ plugins/CommonControls/trunk/common/io/AtomicOutputStream.java	2007-02-28 \
07:19:29 UTC (rev 9041) @@ -27,7 +27,11 @@
 /**
  *	<p>An "atomic" output stream. It is "atomic" in the sense that the
  *	target file won't be overwritten until "close()" is called, at which
- *	point a rename is done (rename is atomic).</p>
+ *	point a rename is done. A point of note that for this stream to
+ *	actually be atomic, "rename" needs to be atomic, such as in POSIX
+ *	systems. Windows, for example, doesn't have this property, so this
+ *	stream tries to do the next best thing (delete the original, then
+ *	rename).</p>
  *
  *	<p>This stream works a little bit differently than other streams, in the
  *	sense that it has a second close method called {@link #rollback()}. This
@@ -69,7 +73,10 @@
 	public AtomicOutputStream(File path)
 		throws IOException
 	{
-		this.temp	= File.createTempFile(path.getName(), "tmp", path.getParentFile());
+		if (path.exists() && !path.canWrite()) {
+			throw new IOException("Can't write to " + path.getAbsolutePath());
+		}
+		this.temp	= File.createTempFile(path.getName(), ".tmp", path.getParentFile());
 		this.out 	= new FileOutputStream(temp);
 		this.target	= path;
 	}
@@ -90,7 +97,27 @@
 		try {
 			out.close();
 			if (!temp.renameTo(target)) {
-				throw new IOException("Can't rename temp file to " + target.getName());
+				/*
+				 * Windows doesn't allow renaming to a file that already exists.
+				 * So take a "slow, non-atomic" path in this case. This is
+				 * pretty ugly and absolutely not atomic, but I'm trying to be
+				 * really paranoid.
+				 */
+				if (target.exists()) {
+					File backup = File.createTempFile(target.getName(),
+													  ".backup",
+													  target.getParentFile());
+					backup.delete();
+					if (!target.renameTo(backup) || !temp.renameTo(target)) {
+						if (backup.exists() && !target.exists()) {
+							backup.renameTo(target);
+						}
+						throw new IOException("Can't rename temp file to " + target.getName());
+					}
+					backup.delete();
+				} else {
+					throw new IOException("Can't rename temp file to " + target.getName());
+				}
 			}
 		} finally {
 			out = null;


This was sent by the SourceForge.net collaborative development platform, the world's \
largest Open Source development site.

-------------------------------------------------------------------------
Take Surveys. Earn Cash. Influence the Future of IT
Join SourceForge.net's Techsay panel and you'll get the chance to share your
opinions on IT & business topics through brief surveys-and earn cash
http://www.techsay.com/default.php?page=join.php&p=sourceforge&CID=DEVDEV
_______________________________________________
jEdit-CVS mailing list
jEdit-CVS@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/jedit-cvs


[prev in list] [next in list] [prev in thread] [next in thread] 

Configure | About | News | Add a list | Sponsored by KoreLogic