Index: ../jackrabbit/jackrabbit-data/src/main/java/org/apache/jackrabbit/core/data/FileDataStore.java IDEA additional info: Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP <+>UTF-8 =================================================================== --- ../jackrabbit/jackrabbit-data/src/main/java/org/apache/jackrabbit/core/data/FileDataStore.java (date 1426779994000) +++ ../jackrabbit/jackrabbit-data/src/main/java/org/apache/jackrabbit/core/data/FileDataStore.java (revision ) @@ -283,9 +283,26 @@ if (!file.delete()) { log.warn("Failed to delete file " + file.getAbsolutePath()); } + deleteEmptyParentDirs(file); } + } + } + + private void deleteEmptyParentDirs(File file) { + File parent = file.getParentFile(); + try { + // Only iterate & delete if parent directory of the blob file is child + // of the base directory and if it is empty + while (FileUtils.directoryContains(directory, parent) && + (parent.list().length == 0)) { + boolean deleted = parent.delete(); + log.info("Deleted [{}] of file [{}]: {}", new Object[]{parent, file.getAbsolutePath(), deleted}); + parent = parent.getParentFile(); + } + } catch (IOException e) { + log.info("Error in parents deletion for " + file.getAbsoluteFile(), e); } - } + } public int deleteAllOlderThan(long min) { int count = 0; Index: ../jackrabbit/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/data/DataStoreTest.java IDEA additional info: Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP <+>UTF-8 =================================================================== --- ../jackrabbit/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/data/DataStoreTest.java (date 1426779994000) +++ ../jackrabbit/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/data/DataStoreTest.java (revision ) @@ -17,6 +17,7 @@ package org.apache.jackrabbit.core.data; import org.apache.commons.io.FileUtils; +import org.apache.commons.io.IOUtils; import org.apache.jackrabbit.core.data.db.DbDataStore; import org.apache.jackrabbit.test.JUnitTest; @@ -100,6 +101,46 @@ t.printStackTrace(); throw new Error(t); } + } + + public void testDeleteRecordWithParentCollision() throws Exception { + FileDataStore fds = new FileDataStore(); + fds.init(testDir + "/fileDelete"); + + String c1 = "06b2f82fd81b2c20"; + String c2 = "02c60cb75083ceef"; + DataRecord d1 = fds.addRecord(IOUtils.toInputStream(c1)); + DataRecord d2 = fds.addRecord(IOUtils.toInputStream(c2)); + fds.deleteRecord(d1.getIdentifier()); + DataRecord testRecord = fds.getRecordIfStored(d2.getIdentifier()); + + assertNotNull(testRecord); + assertEquals(d2.getIdentifier(), testRecord.getIdentifier()); + // Check the presence of the parent directory (relies on internal details of the FileDataStore) + File parentDirD1 = new File( + fds.getPath() + System.getProperty("file.separator") + d1.getIdentifier().toString().substring(0, 2)); + assertTrue(parentDirD1.exists()); + } + + public void testDeleteRecordWithoutParentCollision() throws Exception { + FileDataStore fds = new FileDataStore(); + fds.init(testDir + "/fileDelete"); + + String c1 = "idhfigjhehgkdfgk"; + String c2 = "02c60cb75083ceef"; + DataRecord d1 = fds.addRecord(IOUtils.toInputStream(c1)); + DataRecord d2 = fds.addRecord(IOUtils.toInputStream(c2)); + System.out.println(d1); + System.out.println(d2); + fds.deleteRecord(d1.getIdentifier()); + DataRecord testRecord = fds.getRecordIfStored(d2.getIdentifier()); + + assertNotNull(testRecord); + assertEquals(d2.getIdentifier(), testRecord.getIdentifier()); + // Check the absence of the parent directory (relies on internal details of the FileDataStore) + File parentDirD1 = new File( + fds.getPath() + System.getProperty("file.separator") + d1.getIdentifier().toString().substring(0, 2)); + assertFalse(parentDirD1.exists()); } public void testReference() throws Exception {