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.