Author: amitj Date: Tue Mar 13 05:27:11 2018 New Revision: 1826604 URL: http://svn.apache.org/viewvc?rev=1826604&view=rev Log: OAK-7209: Race condition can resurrect blobs during blob GC Merge r1826532 from trunk
Modified: jackrabbit/oak/branches/1.8/ (props changed) jackrabbit/oak/branches/1.8/oak-blob-plugins/src/main/java/org/apache/jackrabbit/oak/plugins/blob/datastore/BlobIdTracker.java jackrabbit/oak/branches/1.8/oak-blob-plugins/src/test/java/org/apache/jackrabbit/oak/plugins/blob/datastore/BlobIdTrackerTest.java Propchange: jackrabbit/oak/branches/1.8/ ------------------------------------------------------------------------------ --- svn:mergeinfo (original) +++ svn:mergeinfo Tue Mar 13 05:27:11 2018 @@ -1,3 +1,3 @@ /jackrabbit/oak/branches/1.0:1665962 -/jackrabbit/oak/trunk:1820660-1820661,1820729,1820734,1820859,1820861,1820878,1820888,1820947,1821130,1821140-1821141,1821240,1821249,1821258,1821325,1821358,1821361-1821362,1821370,1821375,1821393,1821477,1821487,1821516,1821665,1821668,1821681,1822121,1822201,1822207,1822723,1822808,1822850,1822934,1823135,1823163,1823169,1824196,1824198,1824962,1825362,1825381,1825442,1825448,1825466,1825470,1825475,1825523,1825525,1825619-1825621,1825651,1825654,1825992,1826079,1826090,1826096,1826237,1826338 +/jackrabbit/oak/trunk:1820660-1820661,1820729,1820734,1820859,1820861,1820878,1820888,1820947,1821130,1821140-1821141,1821240,1821249,1821258,1821325,1821358,1821361-1821362,1821370,1821375,1821393,1821477,1821487,1821516,1821665,1821668,1821681,1822121,1822201,1822207,1822723,1822808,1822850,1822934,1823135,1823163,1823169,1824196,1824198,1824962,1825362,1825381,1825442,1825448,1825466,1825470,1825475,1825523,1825525,1825619-1825621,1825651,1825654,1825992,1826079,1826090,1826096,1826237,1826338,1826532 /jackrabbit/trunk:1345480 Modified: jackrabbit/oak/branches/1.8/oak-blob-plugins/src/main/java/org/apache/jackrabbit/oak/plugins/blob/datastore/BlobIdTracker.java URL: http://svn.apache.org/viewvc/jackrabbit/oak/branches/1.8/oak-blob-plugins/src/main/java/org/apache/jackrabbit/oak/plugins/blob/datastore/BlobIdTracker.java?rev=1826604&r1=1826603&r2=1826604&view=diff ============================================================================== --- jackrabbit/oak/branches/1.8/oak-blob-plugins/src/main/java/org/apache/jackrabbit/oak/plugins/blob/datastore/BlobIdTracker.java (original) +++ jackrabbit/oak/branches/1.8/oak-blob-plugins/src/main/java/org/apache/jackrabbit/oak/plugins/blob/datastore/BlobIdTracker.java Tue Mar 13 05:27:11 2018 @@ -144,8 +144,8 @@ public class BlobIdTracker implements Cl } @Override public void remove(File recs, Options options) throws IOException { + globalMerge(); if (options == Options.ACTIVE_DELETION) { - globalMerge(); deleteTracker.track(recs); } store.removeRecords(recs); @@ -153,11 +153,13 @@ public class BlobIdTracker implements Cl } @Override public void remove(File recs) throws IOException { + globalMerge(); store.removeRecords(recs); snapshot(true); } @Override public void remove(Iterator<String> recs) throws IOException { + globalMerge(); store.removeRecords(recs); snapshot(true); } Modified: jackrabbit/oak/branches/1.8/oak-blob-plugins/src/test/java/org/apache/jackrabbit/oak/plugins/blob/datastore/BlobIdTrackerTest.java URL: http://svn.apache.org/viewvc/jackrabbit/oak/branches/1.8/oak-blob-plugins/src/test/java/org/apache/jackrabbit/oak/plugins/blob/datastore/BlobIdTrackerTest.java?rev=1826604&r1=1826603&r2=1826604&view=diff ============================================================================== --- jackrabbit/oak/branches/1.8/oak-blob-plugins/src/test/java/org/apache/jackrabbit/oak/plugins/blob/datastore/BlobIdTrackerTest.java (original) +++ jackrabbit/oak/branches/1.8/oak-blob-plugins/src/test/java/org/apache/jackrabbit/oak/plugins/blob/datastore/BlobIdTrackerTest.java Tue Mar 13 05:27:11 2018 @@ -124,7 +124,7 @@ public class BlobIdTrackerTest { @Test public void addSnapshotRemove() throws Exception { LOG.info("In addSnapshotRemove"); - snapshotRemove(tracker.new SnapshotJob()); + snapshotRemove(tracker.new SnapshotJob(), false); } @Test @@ -132,7 +132,7 @@ public class BlobIdTrackerTest { LOG.info("In snapshotIgnoreAfterRemove"); BlobIdTracker.SnapshotJob job = tracker.new SnapshotJob(); - snapshotRemove(job); + snapshotRemove(job, false); // Since already retrieved the datastore should be empty unless the snapshot has actually run ScheduledFuture<?> scheduledFuture = @@ -149,7 +149,8 @@ public class BlobIdTrackerTest { Clock clock = Clock.ACCURATE; BlobIdTracker.SnapshotJob job = tracker.new SnapshotJob(100, clock); - Set<String> present = snapshotRemove(job); + // Mimics a call to get after add and before remove similar to the calls in GC + Set<String> present = snapshotRemove(job, false); clock.waitUntil(System.currentTimeMillis() + 100); @@ -162,12 +163,36 @@ public class BlobIdTrackerTest { read(dataStore.getAllMetadataRecords(BLOBREFERENCES.getType()))); } - private Set<String> snapshotRemove(BlobIdTracker.SnapshotJob job) throws Exception { + @Test + public void snapshotBeforeRemove() throws Exception { + LOG.info("In snapshotBeforeRemove"); + + Clock clock = Clock.ACCURATE; + BlobIdTracker.SnapshotJob job = tracker.new SnapshotJob(100, clock); + + //Mimic an intervening snapshot between add and remove by skipping the retrieve call. + Set<String> present = snapshotRemove(job, true); + + clock.waitUntil(System.currentTimeMillis() + 100); + + // Since already retrieved the datastore should not be empty unless the snapshot is ignored + ScheduledFuture<?> scheduledFuture = + scheduler.schedule(job, 0, TimeUnit.MILLISECONDS); + scheduledFuture.get(); + + assertEquals("Elements not equal after snapshot after remove", present, + read(dataStore.getAllMetadataRecords(BLOBREFERENCES.getType()))); + } + + private Set<String> snapshotRemove(BlobIdTracker.SnapshotJob job, boolean skipGetBeforeRemove) throws Exception { Set<String> initAdd = add(tracker, range(0, 4)); ScheduledFuture<?> scheduledFuture = scheduler.schedule(job, 0, TimeUnit.MILLISECONDS); scheduledFuture.get(); - assertEquals("Extra elements after add", initAdd, retrieve(tracker)); + + if (!skipGetBeforeRemove) { + assertEquals("Extra elements after add", initAdd, retrieve(tracker)); + } remove(tracker, folder.newFile(), initAdd, range(1, 2)); assertEquals("Extra elements after removes synced with datastore",