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 a9faab2fc38..d8b20629832 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 @@ -101,6 +101,8 @@ public class DatabaseOps { // while initializing the area for TDB2 usage in this JVM. /*package*/ static final String incompleteWIP = "jena-tdb-temp-files"; + // EXACT: error on any other "Data*" name except for compaction temporary directories. + // SKIP: ignore other names. private enum ScanAccept { EXACT, SKIP } /** @@ -531,11 +533,17 @@ private static List scanForDirByPattern(Path directory, String namebase, S Pattern pattern = Pattern.compile(Pattern.quote(namebase)+ Pattern.quote(nameSep)+ trailerPattern); + // Left behind by an incomplete compaction; removed when the database is next connected. + Pattern tmpPattern = Pattern.compile(Pattern.quote(namebase)+ + Pattern.quote(nameSep)+ + dbTmpPattern); List paths = new ArrayList<>(); try (DirectoryStream stream = Files.newDirectoryStream(directory, namebase + "*")) { for ( Path entry : stream ) { String filename = entry.getFileName().toString(); if ( !pattern.matcher(filename).matches() ) { + if ( tmpPattern.matcher(filename).matches() ) + continue; switch ( skipOthers ) { case EXACT: throw new DBOpEnvException("Invalid filename for matching: "+entry.getFileName()); case SKIP: continue; diff --git a/jena-tdb2/src/test/java/org/apache/jena/tdb2/sys/TestDatabaseCompact.java b/jena-tdb2/src/test/java/org/apache/jena/tdb2/sys/TestDatabaseCompact.java index 488651ae451..acaac093229 100644 --- a/jena-tdb2/src/test/java/org/apache/jena/tdb2/sys/TestDatabaseCompact.java +++ b/jena-tdb2/src/test/java/org/apache/jena/tdb2/sys/TestDatabaseCompact.java @@ -337,4 +337,27 @@ private void compact_prefixes_3_test() { assertFalse(Files.exists(pathFile2)); assertFalse(Files.exists(pathTmp2)); } + + @Test public void compact_recovery_2() throws IOException { + DatasetGraph dsg = DatabaseMgr.connectDatasetGraph(dir); + Txn.executeWrite(dsg, ()->dsg.add(quad1)); + + DatasetGraphSwitchable dsgs = (DatasetGraphSwitchable)dsg; + Path containerPath = dsgs.getContainerPath(); + Path storagePath = DatabaseOps.findStorageLocation(containerPath); + assertNotNull(storagePath); + + // Mock an incomplete compaction. + Path pathTmp = containerPath.resolve("Data-0002-tmp"); + Files.createDirectory(pathTmp); + TDBInternal.expel(dsg); + + // Before reconnecting (which cleans up) - e.g. Fuseki checking the database. + assertEquals(storagePath, DatabaseOps.findStorageLocation(containerPath)); + assertEquals(storagePath, DatabaseOps.findStorageLocation(dir)); + + DatasetGraph dsg2 = DatabaseMgr.connectDatasetGraph(dir); + Txn.executeRead(dsg2, ()->assertTrue(dsg2.contains(quad1))); + assertFalse(Files.exists(pathTmp)); + } }