← Back to team overview

slub.team team mailing list archive

[Merge] lp:~slub.team/goobi-production/bug-988813 into lp:goobi-production

 

Ralf Claussnitzer has proposed merging lp:~slub.team/goobi-production/bug-988813 into lp:goobi-production.

Requested reviews:
  Henning Gerhardt (henning-gerhardt)
Related bugs:
  Bug #988813 in Goobi.Production: "Renaming of files sometimes fails"
  https://bugs.launchpad.net/goobi-production/+bug/988813

For more details, see:
https://code.launchpad.net/~slub.team/goobi-production/bug-988813/+merge/105207

Reconciled with master branch. Uses FilesystemHelper class for file renaming.
-- 
https://code.launchpad.net/~slub.team/goobi-production/bug-988813/+merge/105207
Your team Saxon State Library Team is subscribed to branch lp:goobi-production.
=== modified file 'src/de/sub/goobi/beans/Prozess.java'
--- src/de/sub/goobi/beans/Prozess.java	2012-05-08 11:14:41 +0000
+++ src/de/sub/goobi/beans/Prozess.java	2012-05-09 13:36:18 +0000
@@ -58,6 +58,7 @@
 import de.sub.goobi.persistence.BenutzerDAO;
 import de.sub.goobi.persistence.ProzessDAO;
 import de.sub.goobi.config.ConfigMain;
+import de.sub.goobi.helper.FilesystemHelper;
 import de.sub.goobi.helper.Helper;
 import de.sub.goobi.helper.enums.MetadataFormat;
 import de.sub.goobi.helper.enums.StepStatus;
@@ -727,17 +728,6 @@
 		return result;
 	}
 
-	private void renameMetadataFile(String oldFileName, String newFileName) {
-		File oldFile;
-		File newFile;
-
-		if (oldFileName != null && newFileName != null) {
-			oldFile = new File(oldFileName);
-			newFile = new File(newFileName);
-			oldFile.renameTo(newFile);
-		}
-	}
-
 	private String getTemporaryMetadataFileName(String fileName) {
 		File temporaryFile = new File(fileName);
 		String directoryPath = temporaryFile.getParentFile().getPath();
@@ -746,7 +736,8 @@
 		return directoryPath + File.separator + temporaryFileName;
 	}
 
-	private void removePrefixFromRelatedMetsAnchorFileFor(String temporaryMetadataFilename) {
+	private void removePrefixFromRelatedMetsAnchorFileFor(String temporaryMetadataFilename)
+		throws IOException {
 		File temporaryFile = new File(temporaryMetadataFilename);
 		File temporaryAnchorFile;
 
@@ -761,7 +752,7 @@
 			temporaryAnchorFileName = directoryPath + File.separator + temporaryAnchorFileName;
 			anchorFileName = directoryPath + File.separator + anchorFileName;
 
-			renameMetadataFile(temporaryAnchorFileName, anchorFileName);
+			FilesystemHelper.renameFile(temporaryAnchorFileName, anchorFileName);
 		}
 	}
 
@@ -793,7 +784,7 @@
 		writeResult = ff.write(temporaryMetadataFileName);
 		if (writeResult) {
 			createBackupFile();
-			renameMetadataFile(temporaryMetadataFileName, metadataFileName);
+			FilesystemHelper.renameFile(temporaryMetadataFileName, metadataFileName);
 			removePrefixFromRelatedMetsAnchorFileFor(temporaryMetadataFileName);
 		}
 	}

=== added file 'src/de/sub/goobi/helper/FilesystemHelper.java'
--- src/de/sub/goobi/helper/FilesystemHelper.java	1970-01-01 00:00:00 +0000
+++ src/de/sub/goobi/helper/FilesystemHelper.java	2012-05-09 13:36:18 +0000
@@ -0,0 +1,95 @@
+/*
+ * This file is part of the Goobi Application - a Workflow tool for the support of
+ * mass digitization.
+ *
+ * Visit the websites for more information.
+ *     - http://gdz.sub.uni-goettingen.de
+ *     - http://www.goobi.org
+ *     - http://launchpad.net/goobi-production
+ *
+ * This program is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License as published by the Free Software
+ * Foundation; either version 2 of the License, or (at your option) any later
+ * version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT ANY
+ * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+ * PARTICULAR PURPOSE. See the GNU General Public License for more details. You
+ * should have received a copy of the GNU General Public License along with this
+ * program; if not, write to the Free Software Foundation, Inc., 59 Temple Place,
+ * Suite 330, Boston, MA 02111-1307 USA
+ */
+
+package de.sub.goobi.helper;
+
+import java.io.File;
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.util.Arrays;
+
+import org.apache.commons.io.FileUtils;
+import org.apache.commons.lang.SystemUtils;
+import org.apache.log4j.Logger;
+
+import de.sub.goobi.config.ConfigMain;
+
+/**
+ * Helper class for file system operations.
+ * 
+ * @author Matthias Ronge <matthias.ronge@xxxxxxxxxxxx>
+ */
+public class FilesystemHelper {
+	private static final Logger logger = Logger
+			.getLogger(FilesystemHelper.class);
+
+	/**
+	 * This function implements file renaming. Renaming of files is full of
+	 * mischief under Windows which unaccountably holds locks on files.
+	 * Sometimes running the JVM’s garbage collector puts things right.
+	 * 
+	 * @param oldFileName
+	 *            File to move or rename
+	 * @param newFileName
+	 *            New file name / destination
+	 * @throws IOException
+	 *             is thrown if the rename fails permanently
+	 */
+	public static void renameFile(String oldFileName, String newFileName)
+			throws IOException {
+		final int SLEEP_INTERVAL_MILLIS = 20;
+		final int MAX_WAIT_MILLIS = 150000; // 2½ minutes
+		File oldFile;
+		File newFile;
+		boolean success;
+		int millisWaited = 0;
+
+		if (oldFileName != null && newFileName != null) {
+			oldFile = new File(oldFileName);
+			newFile = new File(newFileName);
+			do {
+				if (SystemUtils.IS_OS_WINDOWS
+						&& millisWaited == SLEEP_INTERVAL_MILLIS) {
+					logger.warn("renameMetadataFile(): This is Windows. Running the garbage collector may yield good results. Forcing immediate garbage collection now!");
+					System.gc();
+				}
+				success = oldFile.renameTo(newFile);
+				if (!success) {
+					if (millisWaited == 0)
+						logger.info("renameMetadataFile(): Rename failed. File may be locked. Retrying.");
+					try {
+						Thread.sleep(SLEEP_INTERVAL_MILLIS);
+					} catch (InterruptedException e) {
+					}
+					millisWaited += SLEEP_INTERVAL_MILLIS;
+				}
+			} while (!success && millisWaited < MAX_WAIT_MILLIS);
+			if (!success) {
+				logger.error("renameMetadataFile(): Rename failed. This is a permanent error. Giving up.");
+				throw new IOException("Renaming of " + oldFileName + " into "
+						+ newFileName + " failed.");
+			} else if (millisWaited > 0)
+				logger.info("renameMetadataFile(): Rename finally succeeded after"
+						+ Integer.toString(millisWaited) + " milliseconds.");
+		}
+	}
+}


Follow ups