Index: oak-blob/src/main/java/org/apache/jackrabbit/oak/spi/blob/FileBlobStore.java IDEA additional info: Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP <+>UTF-8 =================================================================== --- oak-blob/src/main/java/org/apache/jackrabbit/oak/spi/blob/FileBlobStore.java (revision e7f6d26b5abe0cc27ad47730410e0a7d6061a74e) +++ oak-blob/src/main/java/org/apache/jackrabbit/oak/spi/blob/FileBlobStore.java (date 1522920806000) @@ -109,6 +109,7 @@ protected synchronized void storeBlock(byte[] digest, int level, byte[] data) throws IOException { File f = getFile(digest, false); if (f.exists()) { + FileUtils.touch(f); return; } File parent = f.getParentFile(); Index: oak-blob/src/main/java/org/apache/jackrabbit/oak/spi/blob/MemoryBlobStore.java IDEA additional info: Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP <+>UTF-8 =================================================================== --- oak-blob/src/main/java/org/apache/jackrabbit/oak/spi/blob/MemoryBlobStore.java (revision e7f6d26b5abe0cc27ad47730410e0a7d6061a74e) +++ oak-blob/src/main/java/org/apache/jackrabbit/oak/spi/blob/MemoryBlobStore.java (date 1522923222000) @@ -33,6 +33,7 @@ private HashMap map = new HashMap(); private HashMap old = new HashMap(); + private HashMap timestamps = new HashMap(); private boolean mark; @Override @@ -46,7 +47,9 @@ @Override protected synchronized void storeBlock(byte[] digest, int level, byte[] data) { - map.put(new BlockId(digest, 0), data); + BlockId id = new BlockId(digest, 0); + map.put(id, data); + timestamps.put(id, System.currentTimeMillis()); } @Override @@ -90,8 +93,11 @@ for (String chunkId : chunkIds) { BlockId id = new BlockId(StringUtils.convertHexToBytes(chunkId), 0); if (map.containsKey(id)) { - map.remove(id); - count++; + if (maxLastModifiedTime == 0 || (maxLastModifiedTime > 0 && maxLastModifiedTime > timestamps.get(id))) { + map.remove(id); + timestamps.remove(id); + count++; + } } else if (old.containsKey(id)) { old.remove(id); count++; Index: oak-blob/src/test/java/org/apache/jackrabbit/oak/spi/blob/AbstractBlobStoreTest.java IDEA additional info: Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP <+>UTF-8 =================================================================== --- oak-blob/src/test/java/org/apache/jackrabbit/oak/spi/blob/AbstractBlobStoreTest.java (revision e7f6d26b5abe0cc27ad47730410e0a7d6061a74e) +++ oak-blob/src/test/java/org/apache/jackrabbit/oak/spi/blob/AbstractBlobStoreTest.java (date 1522923413000) @@ -445,6 +445,28 @@ assertEquals(ids.size(), count); } + @Test + public void deleteUpdatedBlob() throws Exception { + String id = store.writeBlob(randomStream(0, getArtifactSize())); + Thread.sleep(100); + + long beforeUpdateTime = System.currentTimeMillis(); + + Thread.sleep(200); + + // Should update the timestamp + String id2 = store.writeBlob(randomStream(0, getArtifactSize())); + assertEquals(id, id2); + + Set chunks = Sets.newHashSet(); + Iterator iter = store.resolveChunks(id.toString()); + while (iter.hasNext()) { + chunks.add(iter.next()); + } + long count = store.countDeleteChunks(Lists.newArrayList(chunks), beforeUpdateTime); + assertEquals("Deleted updated blobs", 0, count); + } + @Test public void uploadCallback() throws Exception { assumeTrue(supportsStatsCollection()); Index: oak-store-document/src/main/java/org/apache/jackrabbit/oak/plugins/document/mongo/MongoBlobStore.java IDEA additional info: Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP <+>UTF-8 =================================================================== --- oak-store-document/src/main/java/org/apache/jackrabbit/oak/plugins/document/mongo/MongoBlobStore.java (revision e7f6d26b5abe0cc27ad47730410e0a7d6061a74e) +++ oak-store-document/src/main/java/org/apache/jackrabbit/oak/plugins/document/mongo/MongoBlobStore.java (date 1522923584000) @@ -103,10 +103,12 @@ try { getBlobCollection().insertOne(mongoBlob); } catch (DuplicateKeyException e) { - // the same block was already stored before: ignore + // the same block was already stored before: update timestamp + updateTimestamp(id, System.currentTimeMillis()); } catch (MongoException e) { if (e.getCode() == DUPLICATE_KEY_ERROR_CODE) { - // the same block was already stored before: ignore + // the same block was already stored before: update timestamp + updateTimestamp(id, System.currentTimeMillis()); } else { throw new IOException(e.getMessage(), e); } @@ -158,9 +160,13 @@ return; } String id = StringUtils.convertBytesToHex(blockId.getDigest()); + updateTimestamp(id, minLastModified); + } + + private void updateTimestamp(String id, long minLastModified) { Bson query = getBlobQuery(id, minLastModified); Bson update = new BasicDBObject("$set", - new BasicDBObject(MongoBlob.KEY_LAST_MOD, System.currentTimeMillis())); + new BasicDBObject(MongoBlob.KEY_LAST_MOD, System.currentTimeMillis())); getBlobCollection().updateOne(query, update); }