Skip to content

Commit

Permalink
OAK-7389: Mongo/FileBlobStore does not update timestamp for already e…
Browse files Browse the repository at this point in the history
…xisting blobs

Refresh the timestamp for FileBlobStore and upsert the blob for Mongo to update the timestamp in case already there

git-svn-id: https://svn.apache.org/repos/asf/jackrabbit/oak/trunk@1828502 13f79535-47bb-0310-9956-ffa450edef68
  • Loading branch information
amit-jain committed Apr 6, 2018
1 parent 655ecf7 commit b4e3118
Show file tree
Hide file tree
Showing 4 changed files with 60 additions and 20 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,7 @@ public String writeBlob(String tempFilePath) throws IOException {
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();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ public class MemoryBlobStore extends AbstractBlobStore {

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
Expand All @@ -46,7 +47,9 @@ protected byte[] readBlockFromBackend(BlockId id) {

@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
Expand Down Expand Up @@ -90,8 +93,11 @@ public long countDeleteChunks(List<String> chunkIds, long maxLastModifiedTime) t
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++;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -445,6 +445,28 @@ public void deleteCount() throws Exception {
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(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());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,8 @@
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;
Expand All @@ -32,7 +34,6 @@

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;
Expand Down Expand Up @@ -92,24 +93,30 @@ public MongoBlobStore(MongoDatabase db, long cacheSize) {
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);
}
}

Expand Down Expand Up @@ -158,9 +165,13 @@ protected void mark(BlockId blockId) throws Exception {
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);
}

Expand Down

0 comments on commit b4e3118

Please sign in to comment.