This is an automated email from the ASF dual-hosted git repository.

andy pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/jena.git


The following commit(s) were added to refs/heads/main by this push:
     new dabb3a4ca1 GH-2315: Clearup failed compaction on MS Windows
dabb3a4ca1 is described below

commit dabb3a4ca1732412d628c89450462e83280b6244
Author: Andy Seaborne <a...@apache.org>
AuthorDate: Sun Mar 10 20:08:53 2024 +0000

    GH-2315: Clearup failed compaction on MS Windows
---
 .../java/org/apache/jena/tdb2/sys/DatabaseOps.java | 42 ++++++++++++++++++----
 .../apache/jena/tdb2/sys/DatabaseOpsWindows.java   | 34 ++++++++++++++++--
 2 files changed, 68 insertions(+), 8 deletions(-)

diff --git a/jena-tdb2/src/main/java/org/apache/jena/tdb2/sys/DatabaseOps.java 
b/jena-tdb2/src/main/java/org/apache/jena/tdb2/sys/DatabaseOps.java
index 2ea936aa89..429a6899f3 100644
--- a/jena-tdb2/src/main/java/org/apache/jena/tdb2/sys/DatabaseOps.java
+++ b/jena-tdb2/src/main/java/org/apache/jena/tdb2/sys/DatabaseOps.java
@@ -30,7 +30,10 @@ import java.util.zip.GZIPOutputStream;
 import org.apache.jena.atlas.RuntimeIOException;
 import org.apache.jena.atlas.io.IO;
 import org.apache.jena.atlas.io.IOX;
-import org.apache.jena.atlas.lib.*;
+import org.apache.jena.atlas.lib.DateTimeUtils;
+import org.apache.jena.atlas.lib.InternalErrorException;
+import org.apache.jena.atlas.lib.Pair;
+import org.apache.jena.atlas.lib.StrUtils;
 import org.apache.jena.atlas.logging.FmtLog;
 import org.apache.jena.atlas.logging.Log;
 import org.apache.jena.base.Sys;
@@ -85,11 +88,15 @@ public class DatabaseOps {
 
     // Additional suffix used during compact
     private static final String dbTmpSuffix      = "-tmp";
-    private static final String dbTmpPattern     = "[\\d]+-tmp";
+    private static final String dbTmpPattern     = "[\\d]+"+dbTmpSuffix;
 
-    private static final String BACKUPS_DIR  = "Backups";
+    private static final String BACKUPS_DIR      = "Backups";
     // Basename of the backup file. "backup_{DateTime}.nq.gz
-    private static final String BACKUPS_FN   = "backup";
+    private static final String BACKUPS_FN       = "backup";
+
+    // A file name for a list of files to remove in cleanDatabaseDirectory()
+    // while initializing the area for TDB2 usage in this JVM.
+    /*package*/ static final String incompleteWIP    = "jena-tdb-temp-files";
 
     private enum ScanAccept { EXACT, SKIP }
 
@@ -164,12 +171,35 @@ public class DatabaseOps {
     /**
      * Clear out any partial compactions.
      */
-    private static void cleanDatabaseDirectory(Path directory) {
-        List<Path> tmpDirs = scanForDirByPattern(directory, dbNameBase, SEP, 
dbTmpPattern, ScanAccept.SKIP);
+    private static void cleanDatabaseDirectory(Path containerDirectory) {
+        // Remove "-tmp" directories.
+        List<Path> tmpDirs = scanForDirByPattern(containerDirectory, 
dbNameBase, SEP, dbTmpPattern, ScanAccept.SKIP);
         for ( Path dir : tmpDirs ) {
             FmtLog.info(LOG, "Remove incomplete compaction temporary 
directory: "+dir);
             IO.deleteAll(dir);
         }
+        // Remove anything listed in "jena-tdb-temp-files" (used by Windows 
compaction)
+        try {
+            Path workfileList = containerDirectory.resolve(incompleteWIP);
+            if ( Files.exists(workfileList) ) {
+                List<String> filenames = Files.readAllLines(workfileList);
+                for ( String fn : filenames) {
+                    FmtLog.info(LOG, "Remove incomplete work-in-progress: 
"+fn);
+                    Path path = Path.of(fn);
+                    if ( Files.exists(path) ) {
+                        try {
+                            IO.deleteAll(path);
+                        } catch (Throwable ex) {
+                            FmtLog.error(LOG, "Exception while deleting "+fn+ 
" : manual clean-up required");
+                        }
+                    }
+                }
+                // Remove the list of clean-ups.
+                Files.delete(workfileList);
+            }
+        } catch (IOException e) {
+            throw IOX.exception(e);
+        }
     }
 
     private static ReorderTransformation maybeTransform(ReorderTransformation 
reorderTransform, Location location) {
diff --git 
a/jena-tdb2/src/main/java/org/apache/jena/tdb2/sys/DatabaseOpsWindows.java 
b/jena-tdb2/src/main/java/org/apache/jena/tdb2/sys/DatabaseOpsWindows.java
index dbd7695b17..def9c504a0 100644
--- a/jena-tdb2/src/main/java/org/apache/jena/tdb2/sys/DatabaseOpsWindows.java
+++ b/jena-tdb2/src/main/java/org/apache/jena/tdb2/sys/DatabaseOpsWindows.java
@@ -31,6 +31,8 @@ import java.util.regex.Matcher;
 import java.util.regex.Pattern;
 import java.util.stream.Stream;
 
+import org.apache.jena.atlas.RuntimeIOException;
+import org.apache.jena.atlas.io.IO;
 import org.apache.jena.atlas.io.IOX;
 import org.apache.jena.atlas.lib.InternalErrorException;
 import org.apache.jena.atlas.lib.Lib;
@@ -82,13 +84,41 @@ class DatabaseOpsWindows {
             // Check version
             int v = extractIndexX(db1.getFileName().toString(), dbPrefix, SEP);
             String next = FilenameUtils.filename(dbPrefix, SEP, v+1);
-
             Path db2 = db1.getParent().resolve(next);
+
+            // Write note about location to be used into the container
+            Path inProgress = base.resolve(DatabaseOps.incompleteWIP);
+            try {
+                Files.writeString(inProgress, 
db2.toAbsolutePath().toString()+"\n");
+            } catch(IOException ex) {
+                // Try clean-up
+                try { Files.delete(inProgress); } catch(IOException ex2) { }
+                throw IOX.exception(ex);
+            }
+
             IOX.createDirectory(db2);
             Location loc2 = IO_DB.asLocation(db2);
             LOG.debug(String.format("Compact %s -> %s\n", db1.getFileName(), 
db2.getFileName()));
 
-            compaction(container, loc1, loc2);
+            try {
+                compaction(container, loc1, loc2);
+                // Container now using the new location.
+            } catch (RuntimeIOException ex) {
+                // Clear up - disk problems.
+                try { IO.deleteAll(db2); } catch (Throwable th) { /* Continue 
with original error. */ }
+                throw ex;
+            } catch (Throwable th) {
+                // Jena and Java errors
+                try { IO.deleteAll(db2); } catch (Throwable th2) { /* Continue 
with original error. */ }
+                throw th;
+            }
+
+            try {
+                // Remove note about location.
+                Files.delete(inProgress);
+            } catch(IOException ex) {
+                throw IOX.exception(ex);
+            }
 
             if ( shouldDeleteOld ) {
                 // Compact put each of the databases into exclusive mode to do 
the switchover.

Reply via email to