You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@jackrabbit.apache.org by am...@apache.org on 2015/03/23 13:17:23 UTC

svn commit: r1668612 - in /jackrabbit/trunk: jackrabbit-core/src/test/java/org/apache/jackrabbit/core/data/DataStoreTest.java jackrabbit-data/src/main/java/org/apache/jackrabbit/core/data/FileDataStore.java

Author: amitj
Date: Mon Mar 23 12:17:22 2015
New Revision: 1668612

URL: http://svn.apache.org/r1668612
Log:
JCR-3862: [FileDataStore]: deleteRecord leaves the parent directories empty

Modified:
    jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/data/DataStoreTest.java
    jackrabbit/trunk/jackrabbit-data/src/main/java/org/apache/jackrabbit/core/data/FileDataStore.java

Modified: jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/data/DataStoreTest.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/data/DataStoreTest.java?rev=1668612&r1=1668611&r2=1668612&view=diff
==============================================================================
--- jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/data/DataStoreTest.java (original)
+++ jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/data/DataStoreTest.java Mon Mar 23 12:17:22 2015
@@ -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;
 
@@ -102,6 +103,44 @@ public class DataStoreTest extends JUnit
         }
     }
 
+    public void testDeleteRecordWithParentCollision() throws Exception {
+        FileDataStore fds = new FileDataStore();
+        fds.init(testDir + "/fileDeleteCollision");
+
+        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));
+        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 {
         byte[] data = new byte[12345];
         new Random(12345).nextBytes(data);

Modified: jackrabbit/trunk/jackrabbit-data/src/main/java/org/apache/jackrabbit/core/data/FileDataStore.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-data/src/main/java/org/apache/jackrabbit/core/data/FileDataStore.java?rev=1668612&r1=1668611&r2=1668612&view=diff
==============================================================================
--- jackrabbit/trunk/jackrabbit-data/src/main/java/org/apache/jackrabbit/core/data/FileDataStore.java (original)
+++ jackrabbit/trunk/jackrabbit-data/src/main/java/org/apache/jackrabbit/core/data/FileDataStore.java Mon Mar 23 12:17:22 2015
@@ -280,12 +280,38 @@ public class FileDataStore extends Abstr
         File file = getFile(identifier);
         synchronized (this) {
             if (file.exists()) {
-                if (!file.delete()) {
+                if (file.delete()) {
+                    deleteEmptyParentDirs(file);
+                } else {
                     log.warn("Failed to delete file " + file.getAbsolutePath());
                 }
             }
         }
-	}
+    }
+
+    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)) {
+                String[] entries = parent.list();
+                if (entries == null) {
+                    log.warn("Failed to list directory {}", parent.getAbsolutePath());
+                    break;
+                }
+                if (entries.length > 0) {
+                    break;
+                }
+                boolean deleted = parent.delete();
+                log.debug("Deleted parent [{}] of file [{}]: {}",
+                        new Object[]{parent, file.getAbsolutePath(), deleted});
+                parent = parent.getParentFile();
+            }
+        } catch (IOException e) {
+            log.warn("Error in parents deletion for " + file.getAbsoluteFile(), e);
+        }
+    }
 
     public int deleteAllOlderThan(long min) {
         int count = 0;