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 <[email protected]>
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.