Author: amitj Date: Fri Apr 6 08:50:07 2018 New Revision: 1828502 URL: http://svn.apache.org/viewvc?rev=1828502&view=rev Log: OAK-7389: Mongo/FileBlobStore does not update timestamp for already existing blobs
Refresh the timestamp for FileBlobStore and upsert the blob for Mongo to update the timestamp in case already there Modified: jackrabbit/oak/trunk/oak-blob/src/main/java/org/apache/jackrabbit/oak/spi/blob/FileBlobStore.java jackrabbit/oak/trunk/oak-blob/src/main/java/org/apache/jackrabbit/oak/spi/blob/MemoryBlobStore.java jackrabbit/oak/trunk/oak-blob/src/test/java/org/apache/jackrabbit/oak/spi/blob/AbstractBlobStoreTest.java jackrabbit/oak/trunk/oak-store-document/src/main/java/org/apache/jackrabbit/oak/plugins/document/mongo/MongoBlobStore.java Modified: jackrabbit/oak/trunk/oak-blob/src/main/java/org/apache/jackrabbit/oak/spi/blob/FileBlobStore.java URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-blob/src/main/java/org/apache/jackrabbit/oak/spi/blob/FileBlobStore.java?rev=1828502&r1=1828501&r2=1828502&view=diff ============================================================================== --- jackrabbit/oak/trunk/oak-blob/src/main/java/org/apache/jackrabbit/oak/spi/blob/FileBlobStore.java (original) +++ jackrabbit/oak/trunk/oak-blob/src/main/java/org/apache/jackrabbit/oak/spi/blob/FileBlobStore.java Fri Apr 6 08:50:07 2018 @@ -109,6 +109,7 @@ public class FileBlobStore extends Abstr 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(); Modified: jackrabbit/oak/trunk/oak-blob/src/main/java/org/apache/jackrabbit/oak/spi/blob/MemoryBlobStore.java URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-blob/src/main/java/org/apache/jackrabbit/oak/spi/blob/MemoryBlobStore.java?rev=1828502&r1=1828501&r2=1828502&view=diff ============================================================================== --- jackrabbit/oak/trunk/oak-blob/src/main/java/org/apache/jackrabbit/oak/spi/blob/MemoryBlobStore.java (original) +++ jackrabbit/oak/trunk/oak-blob/src/main/java/org/apache/jackrabbit/oak/spi/blob/MemoryBlobStore.java Fri Apr 6 08:50:07 2018 @@ -33,6 +33,7 @@ public class MemoryBlobStore extends Abs private HashMap<BlockId, byte[]> map = new HashMap<BlockId, byte[]>(); private HashMap<BlockId, byte[]> old = new HashMap<BlockId, byte[]>(); + private HashMap<BlockId, Long> timestamps = new HashMap<BlockId, Long>(); private boolean mark; @Override @@ -46,7 +47,9 @@ public class MemoryBlobStore extends Abs @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 @@ public class MemoryBlobStore extends Abs 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++; Modified: jackrabbit/oak/trunk/oak-blob/src/test/java/org/apache/jackrabbit/oak/spi/blob/AbstractBlobStoreTest.java URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-blob/src/test/java/org/apache/jackrabbit/oak/spi/blob/AbstractBlobStoreTest.java?rev=1828502&r1=1828501&r2=1828502&view=diff ============================================================================== --- jackrabbit/oak/trunk/oak-blob/src/test/java/org/apache/jackrabbit/oak/spi/blob/AbstractBlobStoreTest.java (original) +++ jackrabbit/oak/trunk/oak-blob/src/test/java/org/apache/jackrabbit/oak/spi/blob/AbstractBlobStoreTest.java Fri Apr 6 08:50:07 2018 @@ -446,6 +446,28 @@ public abstract class AbstractBlobStoreT } @Test + public void deleteUpdatedBlob() throws Exception { + String id = store.writeBlob(randomStream(0, getArtifactSize())); + Thread.sleep(100); + + long beforeUpdateTime = System.currentTimeMillis(); + + Thread.sleep(1000); + + // Should update the timestamp + String id2 = store.writeBlob(randomStream(0, getArtifactSize())); + assertEquals(id, id2); + + Set<String> chunks = Sets.newHashSet(); + Iterator<String> 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()); TestCollector collector = new TestCollector(); Modified: jackrabbit/oak/trunk/oak-store-document/src/main/java/org/apache/jackrabbit/oak/plugins/document/mongo/MongoBlobStore.java URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-store-document/src/main/java/org/apache/jackrabbit/oak/plugins/document/mongo/MongoBlobStore.java?rev=1828502&r1=1828501&r2=1828502&view=diff ============================================================================== --- jackrabbit/oak/trunk/oak-store-document/src/main/java/org/apache/jackrabbit/oak/plugins/document/mongo/MongoBlobStore.java (original) +++ jackrabbit/oak/trunk/oak-store-document/src/main/java/org/apache/jackrabbit/oak/plugins/document/mongo/MongoBlobStore.java Fri Apr 6 08:50:07 2018 @@ -22,6 +22,8 @@ import java.util.Iterator; import java.util.List; import java.util.concurrent.TimeUnit; +import com.mongodb.client.model.UpdateOptions; +import com.mongodb.client.result.UpdateResult; import org.apache.jackrabbit.oak.commons.StringUtils; import org.apache.jackrabbit.oak.plugins.blob.CachingBlobStore; import org.bson.Document; @@ -32,7 +34,6 @@ import org.slf4j.LoggerFactory; import com.google.common.collect.AbstractIterator; import com.mongodb.BasicDBObject; -import com.mongodb.DuplicateKeyException; import com.mongodb.MongoClient; import com.mongodb.MongoException; import com.mongodb.client.MongoCollection; @@ -92,24 +93,30 @@ public class MongoBlobStore extends Cach protected void storeBlock(byte[] digest, int level, byte[] data) throws IOException { String id = StringUtils.convertBytesToHex(digest); cache.put(id, data); - // Check if it already exists? - MongoBlob mongoBlob = new MongoBlob(); - mongoBlob.setId(id); - mongoBlob.setData(data); - mongoBlob.setLevel(level); - mongoBlob.setLastMod(System.currentTimeMillis()); - // TODO check the return value - // TODO verify insert is fast if the entry already exists + + // Create the mongo blob object + BasicDBObject mongoBlob = new BasicDBObject(MongoBlob.KEY_ID, id); + mongoBlob.append(MongoBlob.KEY_DATA, data); + mongoBlob.append(MongoBlob.KEY_LEVEL, level); + + // If update only the lastMod needs to be modified + BasicDBObject updateBlob =new BasicDBObject(MongoBlob.KEY_LAST_MOD, System.currentTimeMillis()); + + BasicDBObject upsert = new BasicDBObject(); + upsert.append("$setOnInsert", mongoBlob) + .append("$set", updateBlob); + try { - getBlobCollection().insertOne(mongoBlob); - } catch (DuplicateKeyException e) { - // the same block was already stored before: ignore - } catch (MongoException e) { - if (e.getCode() == DUPLICATE_KEY_ERROR_CODE) { - // the same block was already stored before: ignore + Bson query = getBlobQuery(id, -1); + UpdateOptions options = new UpdateOptions().upsert(true); + UpdateResult result = getBlobCollection().updateOne(query, upsert, options); + if (result != null && result.getUpsertedId() == null) { + LOG.trace("Block with id [{}] updated", id); } else { - throw new IOException(e.getMessage(), e); + LOG.trace("Block with id [{}] created", id); } + } catch (MongoException e) { + throw new IOException(e.getMessage(), e); } } @@ -158,9 +165,13 @@ public class MongoBlobStore extends Cach 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); }