You are viewing a plain text version of this content. The canonical link for it is here.
Posted to oak-commits@jackrabbit.apache.org by mr...@apache.org on 2014/12/02 11:14:23 UTC
svn commit: r1642837 - in /jackrabbit/oak/trunk:
oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/document/
oak-core/src/test/java/org/apache/jackrabbit/oak/kernel/
oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/document/
oak-run/src/...
Author: mreutegg
Date: Tue Dec 2 10:14:22 2014
New Revision: 1642837
URL: http://svn.apache.org/r1642837
Log:
OAK-2291: Associate user defined values with checkpoint
Implementation for DocumentNodeStore
Modified:
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/document/Checkpoints.java
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/document/DocumentCheckpointMBean.java
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/document/DocumentNodeStore.java
jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/kernel/CheckpointTest.java
jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/document/CheckpointsTest.java
jackrabbit/oak/trunk/oak-run/src/main/java/org/apache/jackrabbit/oak/checkpoint/Checkpoints.java
jackrabbit/oak/trunk/oak-run/src/main/java/org/apache/jackrabbit/oak/plugins/document/CheckpointsHelper.java
jackrabbit/oak/trunk/oak-run/src/main/js/oak-mongo.js
Modified: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/document/Checkpoints.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/document/Checkpoints.java?rev=1642837&r1=1642836&r2=1642837&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/document/Checkpoints.java (original)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/document/Checkpoints.java Tue Dec 2 10:14:22 2014
@@ -19,15 +19,23 @@
package org.apache.jackrabbit.oak.plugins.document;
+import java.math.BigInteger;
+import java.util.Collections;
import java.util.Map;
import java.util.SortedMap;
import java.util.concurrent.atomic.AtomicInteger;
import javax.annotation.CheckForNull;
+import org.apache.jackrabbit.oak.commons.json.JsopBuilder;
+import org.apache.jackrabbit.oak.commons.json.JsopReader;
+import org.apache.jackrabbit.oak.commons.json.JsopTokenizer;
+import org.apache.jackrabbit.oak.commons.json.JsopWriter;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
+import com.google.common.collect.Maps;
+
/**
* Checkpoints provide details around which revision are to be kept. These
@@ -37,7 +45,8 @@ class Checkpoints {
private static final String ID = "checkpoint";
/**
- * Property name to store all checkpoint data. The data is stored as Revision => expiryTime
+ * Property name to store all checkpoint data. The data is either stored as
+ * Revision => expiryTime or Revision => JSON with expiryTime and info.
*/
private static final String PROP_CHECKPOINT = "data";
@@ -63,13 +72,15 @@ class Checkpoints {
createIfNotExist();
}
- public Revision create(long lifetimeInMillis) {
+ public Revision create(long lifetimeInMillis, Map<String, String> info) {
Revision r = nodeStore.getHeadRevision();
createCounter.getAndIncrement();
performCleanupIfRequired();
UpdateOp op = new UpdateOp(ID, false);
- long endTime = nodeStore.getClock().getTime() + lifetimeInMillis;
- op.setMapEntry(PROP_CHECKPOINT, r, Long.toString(endTime));
+ long endTime = BigInteger.valueOf(nodeStore.getClock().getTime())
+ .add(BigInteger.valueOf(lifetimeInMillis))
+ .min(BigInteger.valueOf(Long.MAX_VALUE)).longValue();
+ op.setMapEntry(PROP_CHECKPOINT, r, new Info(endTime, info).toString());
store.createOrUpdate(Collection.SETTINGS, op);
return r;
}
@@ -92,7 +103,7 @@ class Checkpoints {
@CheckForNull
public Revision getOldestRevisionToKeep() {
//Get uncached doc
- SortedMap<Revision, String> checkpoints = getCheckpoints();
+ SortedMap<Revision, Info> checkpoints = getCheckpoints();
if(checkpoints == null){
log.debug("No checkpoint registered so far");
@@ -104,8 +115,8 @@ class Checkpoints {
Revision lastAliveRevision = null;
long oldestExpiryTime = 0;
- for (Map.Entry<Revision, String> e : checkpoints.entrySet()) {
- final long expiryTime = Long.parseLong(e.getValue());
+ for (Map.Entry<Revision, Info> e : checkpoints.entrySet()) {
+ final long expiryTime = e.getValue().getExpiryTime();
if (currentTime > expiryTime) {
op.removeMapEntry(PROP_CHECKPOINT, e.getKey());
} else if (expiryTime > oldestExpiryTime) {
@@ -124,13 +135,22 @@ class Checkpoints {
@SuppressWarnings("unchecked")
@CheckForNull
- SortedMap<Revision, String> getCheckpoints() {
+ SortedMap<Revision, Info> getCheckpoints() {
Document cdoc = store.find(Collection.SETTINGS, ID, 0);
- return (SortedMap<Revision, String>) cdoc.get(PROP_CHECKPOINT);
+ SortedMap<Revision, String> data =
+ (SortedMap<Revision, String>) cdoc.get(PROP_CHECKPOINT);
+ if (data == null) {
+ return null;
+ }
+ SortedMap<Revision, Info> checkpoints = Maps.newTreeMap(data.comparator());
+ for (Map.Entry<Revision, String> entry : data.entrySet()) {
+ checkpoints.put(entry.getKey(), Info.fromString(entry.getValue()));
+ }
+ return checkpoints;
}
int size(){
- SortedMap<Revision, String> checkpoints = getCheckpoints();
+ SortedMap<Revision, Info> checkpoints = getCheckpoints();
return checkpoints == null ? 0 : checkpoints.size();
}
@@ -154,5 +174,66 @@ class Checkpoints {
}
}
+ static final class Info {
+
+ private static final String EXPIRES = "expires";
+ private final long expiryTime;
+
+ private final Map<String, String> info;
+
+ private Info(long expiryTime, Map<String, String> info) {
+ this.expiryTime = expiryTime;
+ this.info = Collections.unmodifiableMap(info);
+ }
+
+ static Info fromString(String info) {
+ long expiryTime;
+ Map<String, String> map;
+ if (info.startsWith("{")) {
+ map = Maps.newHashMap();
+ JsopReader reader = new JsopTokenizer(info);
+ reader.read('{');
+ String key = reader.readString();
+ if (!EXPIRES.equals(key)) {
+ throw new IllegalArgumentException("First entry in the " +
+ "checkpoint info must be the expires date: " + info);
+ }
+ reader.read(':');
+ expiryTime = Long.parseLong(reader.readString());
+ while (reader.matches(',')) {
+ key = reader.readString();
+ reader.read(':');
+ map.put(key, reader.readString());
+ }
+ reader.read('}');
+ reader.read(JsopReader.END);
+ } else {
+ // old format
+ map = Collections.emptyMap();
+ expiryTime = Long.parseLong(info);
+ }
+ return new Info(expiryTime, map);
+ }
+
+ Map<String, String> get() {
+ return info;
+ }
+
+ long getExpiryTime() {
+ return expiryTime;
+ }
+
+ @Override
+ public String toString() {
+ JsopWriter writer = new JsopBuilder();
+ writer.object();
+ writer.key(EXPIRES).value(Long.toString(expiryTime));
+ for (Map.Entry<String, String> entry : info.entrySet()) {
+ writer.key(entry.getKey()).value(entry.getValue());
+ }
+ writer.endObject();
+ return writer.toString();
+ }
+ }
}
Modified: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/document/DocumentCheckpointMBean.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/document/DocumentCheckpointMBean.java?rev=1642837&r1=1642836&r2=1642837&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/document/DocumentCheckpointMBean.java (original)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/document/DocumentCheckpointMBean.java Tue Dec 2 10:14:22 2014
@@ -29,6 +29,8 @@ import javax.management.openmbean.Tabula
import org.apache.jackrabbit.oak.util.AbstractCheckpointMBean;
+import static org.apache.jackrabbit.oak.plugins.document.Checkpoints.Info;
+
/**
* {@code CheckpointMBean} implementation for the {@code DocumentNodeStore}.
*/
@@ -41,17 +43,18 @@ public class DocumentCheckpointMBean ext
@Override
protected void collectCheckpoints(TabularDataSupport tab) throws OpenDataException {
- Map<Revision, String> checkpoints = store.getCheckpoints().getCheckpoints();
+ Map<Revision, Info> checkpoints = store.getCheckpoints().getCheckpoints();
if (checkpoints == null) {
checkpoints = Collections.emptyMap();
}
- for (Entry<Revision, String> checkpoint : checkpoints.entrySet()) {
+ for (Entry<Revision, Info> checkpoint : checkpoints.entrySet()) {
String id = checkpoint.getKey().toString();
+ Info info = checkpoint.getValue();
Date created = new Date(checkpoint.getKey().getTimestamp());
- Date expires = new Date(Long.parseLong(checkpoint.getValue()));
+ Date expires = new Date(info.getExpiryTime());
tab.put(id, toCompositeData(
- id, created.toString(), expires.toString(), store.checkpointInfo(id)));
+ id, created.toString(), expires.toString(), info.get()));
}
}
Modified: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/document/DocumentNodeStore.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/document/DocumentNodeStore.java?rev=1642837&r1=1642836&r2=1642837&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/document/DocumentNodeStore.java (original)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/document/DocumentNodeStore.java Tue Dec 2 10:14:22 2014
@@ -1365,19 +1365,27 @@ public final class DocumentNodeStore
@Nonnull
@Override
public String checkpoint(long lifetime, @Nonnull Map<String, String> properties) {
- throw new UnsupportedOperationException(); // FIXME implement. See OAK-2291
+ return checkpoints.create(lifetime, properties).toString();
}
@Nonnull
@Override
public String checkpoint(long lifetime) {
- return checkpoints.create(lifetime).toString();
+ Map<String, String> empty = Collections.emptyMap();
+ return checkpoint(lifetime, empty);
}
@Nonnull
@Override
public Map<String, String> checkpointInfo(@Nonnull String checkpoint) {
- throw new UnsupportedOperationException(); // FIXME implement. See OAK-2291
+ Revision r = Revision.fromString(checkpoint);
+ Checkpoints.Info info = checkpoints.getCheckpoints().get(r);
+ if (info == null) {
+ // checkpoint does not exist
+ return Collections.emptyMap();
+ } else {
+ return info.get();
+ }
}
@CheckForNull
Modified: jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/kernel/CheckpointTest.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/kernel/CheckpointTest.java?rev=1642837&r1=1642836&r2=1642837&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/kernel/CheckpointTest.java (original)
+++ jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/kernel/CheckpointTest.java Tue Dec 2 10:14:22 2014
@@ -23,7 +23,6 @@ import static org.junit.Assert.assertEqu
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
-import static org.junit.Assume.assumeTrue;
import static org.junit.runners.Parameterized.Parameters;
import java.util.Arrays;
@@ -102,8 +101,6 @@ public class CheckpointTest {
@Test
public void checkpointInfo() throws CommitFailedException {
- // FIXME implement. See OAK-2291
- assumeTrue(fixture != NodeStoreFixture.MONGO_NS);
ImmutableMap<String, String> props = ImmutableMap.of(
"one", "1", "two", "2", "three", "2");
String cp = store.checkpoint(Long.MAX_VALUE, props);
Modified: jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/document/CheckpointsTest.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/document/CheckpointsTest.java?rev=1642837&r1=1642836&r2=1642837&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/document/CheckpointsTest.java (original)
+++ jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/document/CheckpointsTest.java Tue Dec 2 10:14:22 2014
@@ -18,6 +18,8 @@
*/
package org.apache.jackrabbit.oak.plugins.document;
+import java.util.Collections;
+import java.util.Map;
import java.util.concurrent.TimeUnit;
import org.apache.jackrabbit.oak.spi.commit.CommitInfo;
@@ -28,9 +30,13 @@ import org.junit.Before;
import org.junit.Ignore;
import org.junit.Test;
+import com.google.common.collect.ImmutableMap;
+
import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNotSame;
import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertTrue;
public class CheckpointsTest {
@@ -147,4 +153,52 @@ public class CheckpointsTest {
assertEquals(1, store.getCheckpoints().size());
assertEquals(r1, store.getCheckpoints().getOldestRevisionToKeep());
}
+
+ @Test
+ public void readOldFormat() throws Exception {
+ clock.waitUntil(System.currentTimeMillis());
+ DocumentStore docStore = store.getDocumentStore();
+ Map<String, String> empty = Collections.emptyMap();
+ Revision r = Revision.fromString(
+ store.checkpoint(Integer.MAX_VALUE, empty));
+
+ Document doc = docStore.find(Collection.SETTINGS, "checkpoint");
+ assertNotNull(doc);
+ @SuppressWarnings("unchecked")
+ Map<Revision, String> data = (Map<Revision, String>) doc.get("data");
+ assertNotNull(data);
+ assertEquals(1, data.size());
+ assertTrue(data.containsKey(r));
+
+ // manually update checkpoint data with old format
+ UpdateOp update = new UpdateOp("checkpoint", false);
+ long expires = clock.getTime() + 1000 + Integer.MAX_VALUE;
+ update.setMapEntry("data", r, String.valueOf(expires));
+ assertNotNull(docStore.findAndUpdate(Collection.SETTINGS, update));
+
+ Checkpoints.Info info = store.getCheckpoints().getCheckpoints().get(r);
+ assertNotNull(info);
+ assertEquals(expires, info.getExpiryTime());
+ }
+
+ @Test
+ public void expiryOverflow() throws Exception {
+ clock.waitUntil(System.currentTimeMillis());
+ Map<String, String> empty = Collections.emptyMap();
+ Revision r = Revision.fromString(
+ store.checkpoint(Long.MAX_VALUE, empty));
+ Checkpoints.Info info = store.getCheckpoints().getCheckpoints().get(r);
+ assertNotNull(info);
+ assertEquals(Long.MAX_VALUE, info.getExpiryTime());
+ }
+
+ @Test
+ public void userInfoNamedExpires() throws Exception {
+ Map<String, String> props = ImmutableMap.of("expires", "today");
+ Revision r = Revision.fromString(
+ store.checkpoint(Integer.MAX_VALUE, props));
+ Map<String, String> info = store.checkpointInfo(r.toString());
+ assertNotNull(info);
+ assertEquals(props, info);
+ }
}
Modified: jackrabbit/oak/trunk/oak-run/src/main/java/org/apache/jackrabbit/oak/checkpoint/Checkpoints.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-run/src/main/java/org/apache/jackrabbit/oak/checkpoint/Checkpoints.java?rev=1642837&r1=1642836&r2=1642837&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-run/src/main/java/org/apache/jackrabbit/oak/checkpoint/Checkpoints.java (original)
+++ jackrabbit/oak/trunk/oak-run/src/main/java/org/apache/jackrabbit/oak/checkpoint/Checkpoints.java Tue Dec 2 10:14:22 2014
@@ -175,10 +175,10 @@ public abstract class Checkpoints {
@Override
public List<CP> list() {
List<CP> list = Lists.newArrayList();
- for (Map.Entry<Revision, String> entry : getCheckpoints(store).entrySet()) {
+ for (Map.Entry<Revision, Long> entry : getCheckpoints(store).entrySet()) {
list.add(new CP(entry.getKey().toString(),
entry.getKey().getTimestamp(),
- Long.parseLong(entry.getValue())));
+ entry.getValue()));
}
return list;
}
Modified: jackrabbit/oak/trunk/oak-run/src/main/java/org/apache/jackrabbit/oak/plugins/document/CheckpointsHelper.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-run/src/main/java/org/apache/jackrabbit/oak/plugins/document/CheckpointsHelper.java?rev=1642837&r1=1642836&r2=1642837&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-run/src/main/java/org/apache/jackrabbit/oak/plugins/document/CheckpointsHelper.java (original)
+++ jackrabbit/oak/trunk/oak-run/src/main/java/org/apache/jackrabbit/oak/plugins/document/CheckpointsHelper.java Tue Dec 2 10:14:22 2014
@@ -18,16 +18,26 @@
*/
package org.apache.jackrabbit.oak.plugins.document;
+import java.util.Map;
import java.util.SortedMap;
+import com.google.common.collect.Maps;
+
+import static org.apache.jackrabbit.oak.plugins.document.Checkpoints.Info;
+
/**
* Helper class to access package private functionality.
*/
public abstract class CheckpointsHelper {
- public static SortedMap<Revision, String> getCheckpoints(
+ public static SortedMap<Revision, Long> getCheckpoints(
DocumentNodeStore store) {
- return store.getCheckpoints().getCheckpoints();
+ SortedMap<Revision, Info> checkpoints = store.getCheckpoints().getCheckpoints();
+ SortedMap<Revision, Long> map = Maps.newTreeMap(checkpoints.comparator());
+ for (Map.Entry<Revision, Info> entry : checkpoints.entrySet()) {
+ map.put(entry.getKey(), entry.getValue().getExpiryTime());
+ }
+ return map;
}
public static long removeAll(DocumentNodeStore store) {
Modified: jackrabbit/oak/trunk/oak-run/src/main/js/oak-mongo.js
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-run/src/main/js/oak-mongo.js?rev=1642837&r1=1642836&r2=1642837&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-run/src/main/js/oak-mongo.js (original)
+++ jackrabbit/oak/trunk/oak-run/src/main/js/oak-mongo.js Tue Dec 2 10:14:22 2014
@@ -222,7 +222,12 @@ var oak = (function(global){
var r;
for (r in data) {
var rev = new Revision(r);
- var exp = data[r];
+ var exp;
+ if (exp.charAt(0) == '{') {
+ exp = JSON.parse(data[r])["expires"];
+ } else {
+ exp = data[r];
+ }
result[r] = {created:rev.asDate(), expires:new Date(parseInt(exp, 10))};
}
return result;