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 md...@apache.org on 2014/12/01 15:34:19 UTC
svn commit: r1642692 - in /jackrabbit/oak/trunk/oak-core/src:
main/java/org/apache/jackrabbit/oak/kernel/
main/java/org/apache/jackrabbit/oak/plugins/document/
main/java/org/apache/jackrabbit/oak/plugins/memory/
main/java/org/apache/jackrabbit/oak/plug...
Author: mduerig
Date: Mon Dec 1 14:34:19 2014
New Revision: 1642692
URL: http://svn.apache.org/r1642692
Log:
OAK-2291: Associate user defined values with checkpoint
Initial implementation
Added:
jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/kernel/CheckpointTest.java
Modified:
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/kernel/KernelNodeStore.java
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/document/DocumentNodeStore.java
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/memory/MemoryNodeStore.java
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/segment/SegmentNodeStore.java
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/spi/state/NodeStore.java
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/spi/state/ProxyNodeStore.java
jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/NodeStoreFixture.java
Modified: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/kernel/KernelNodeStore.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/kernel/KernelNodeStore.java?rev=1642692&r1=1642691&r2=1642692&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/kernel/KernelNodeStore.java (original)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/kernel/KernelNodeStore.java Mon Dec 1 14:34:19 2014
@@ -22,6 +22,8 @@ import static com.google.common.base.Pre
import java.io.Closeable;
import java.io.IOException;
import java.io.InputStream;
+import java.util.Collections;
+import java.util.Map;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
@@ -211,12 +213,26 @@ public class KernelNodeStore implements
}
}
+
+ @Nonnull
+ @Override
+ public String checkpoint(long lifetime, @Nonnull Map<String, String> properties) {
+ throw new UnsupportedOperationException("MicroKernel based NodeStore implementations do " +
+ "not support checkpoint metadata");
+ }
+
@Override @Nonnull
public String checkpoint(long lifetime) {
checkArgument(lifetime > 0);
return kernel.checkpoint(lifetime);
}
+ @Nonnull
+ @Override
+ public Map<String, String> checkpointInfo(@Nonnull String checkpoint) {
+ return Collections.emptyMap();
+ }
+
@Override @CheckForNull
public NodeState retrieve(@Nonnull String checkpoint) {
try {
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=1642692&r1=1642691&r2=1642692&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 Mon Dec 1 14:34:19 2014
@@ -1364,10 +1364,22 @@ public final class DocumentNodeStore
@Nonnull
@Override
+ public String checkpoint(long lifetime, @Nonnull Map<String, String> properties) {
+ throw new UnsupportedOperationException(); // FIXME implement. See OAK-2291
+ }
+
+ @Nonnull
+ @Override
public String checkpoint(long lifetime) {
return checkpoints.create(lifetime).toString();
}
+ @Nonnull
+ @Override
+ public Map<String, String> checkpointInfo(@Nonnull String checkpoint) {
+ throw new UnsupportedOperationException(); // FIXME implement. See OAK-2291
+ }
+
@CheckForNull
@Override
public NodeState retrieve(@Nonnull String checkpoint) {
Modified: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/memory/MemoryNodeStore.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/memory/MemoryNodeStore.java?rev=1642692&r1=1642691&r2=1642692&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/memory/MemoryNodeStore.java (original)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/memory/MemoryNodeStore.java Mon Dec 1 14:34:19 2014
@@ -26,6 +26,7 @@ import static org.apache.jackrabbit.oak.
import java.io.Closeable;
import java.io.IOException;
import java.io.InputStream;
+import java.util.Collections;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.atomic.AtomicReference;
@@ -34,6 +35,7 @@ import javax.annotation.CheckForNull;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
+import com.google.common.collect.Maps;
import com.google.common.io.ByteStreams;
import org.apache.jackrabbit.oak.api.Blob;
@@ -56,7 +58,7 @@ public class MemoryNodeStore implements
private final AtomicReference<NodeState> root;
- private final Map<String, NodeState> checkpoints = newHashMap();
+ private final Map<String, Checkpoint> checkpoints = newHashMap();
private final Map<Closeable, Observer> observers = newHashMap();
@@ -187,17 +189,40 @@ public class MemoryNodeStore implements
return null;
}
- @Override @Nonnull
- public synchronized String checkpoint(long lifetime) {
+ @Nonnull
+ @Override
+ public String checkpoint(long lifetime, @Nonnull Map<String, String> properties) {
checkArgument(lifetime > 0);
+ checkNotNull(properties);
String checkpoint = "checkpoint" + checkpoints.size();
- checkpoints.put(checkpoint, getRoot());
+ checkpoints.put(checkpoint, new Checkpoint(getRoot(), properties));
return checkpoint;
}
+ @Override @Nonnull
+ public synchronized String checkpoint(long lifetime) {
+ return checkpoint(lifetime, Collections.<String, String>emptyMap());
+ }
+
+ @Nonnull
+ @Override
+ public Map<String, String> checkpointInfo(@Nonnull String checkpoint) {
+ Checkpoint cp = checkpoints.get(checkNotNull(checkpoint));
+ if (cp == null) {
+ return Collections.emptyMap();
+ } else {
+ return cp.getProperties();
+ }
+ }
+
@Override @CheckForNull
public synchronized NodeState retrieve(@Nonnull String checkpoint) {
- return checkpoints.get(checkNotNull(checkpoint));
+ Checkpoint cp = checkpoints.get(checkNotNull(checkpoint));
+ if (cp == null) {
+ return null;
+ } else {
+ return cp.getRoot();
+ }
}
@Override
@@ -281,4 +306,21 @@ public class MemoryNodeStore implements
}
}
+ private static class Checkpoint {
+ private final NodeState root;
+ private final Map<String, String> properties;
+
+ private Checkpoint(NodeState root, Map<String, String> properties) {
+ this.root = root;
+ this.properties = Maps.newHashMap(properties);
+ }
+
+ public NodeState getRoot() {
+ return root;
+ }
+
+ public Map<String, String> getProperties() {
+ return properties;
+ }
+ }
}
Modified: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/segment/SegmentNodeStore.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/segment/SegmentNodeStore.java?rev=1642692&r1=1642691&r2=1642692&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/segment/SegmentNodeStore.java (original)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/segment/SegmentNodeStore.java Mon Dec 1 14:34:19 2014
@@ -22,11 +22,15 @@ import static java.lang.System.currentTi
import static java.util.concurrent.TimeUnit.MILLISECONDS;
import static java.util.concurrent.TimeUnit.NANOSECONDS;
import static java.util.concurrent.TimeUnit.SECONDS;
+import static org.apache.jackrabbit.oak.api.Type.STRING;
import static org.apache.jackrabbit.oak.plugins.segment.Record.fastEquals;
import java.io.Closeable;
import java.io.IOException;
import java.io.InputStream;
+import java.util.Collections;
+import java.util.Map;
+import java.util.Map.Entry;
import java.util.Random;
import java.util.UUID;
import java.util.concurrent.Semaphore;
@@ -35,6 +39,7 @@ import java.util.concurrent.atomic.Atomi
import javax.annotation.CheckForNull;
import javax.annotation.Nonnull;
+import com.google.common.collect.Maps;
import org.apache.jackrabbit.oak.api.Blob;
import org.apache.jackrabbit.oak.api.CommitFailedException;
import org.apache.jackrabbit.oak.api.PropertyState;
@@ -210,9 +215,11 @@ public class SegmentNodeStore implements
"without specifying BlobStore");
}
- @Override @Nonnull
- public synchronized String checkpoint(long lifetime) {
+ @Nonnull
+ @Override
+ public String checkpoint(long lifetime, @Nonnull Map<String, String> properties) {
checkArgument(lifetime > 0);
+ checkNotNull(properties);
String name = UUID.randomUUID().toString();
long now = System.currentTimeMillis();
@@ -239,6 +246,12 @@ public class SegmentNodeStore implements
NodeBuilder cp = checkpoints.child(name);
cp.setProperty("timestamp", now + lifetime);
cp.setProperty("created", now);
+
+ NodeBuilder props = cp.setChildNode("properties");
+ for (Entry<String, String> p : properties.entrySet()) {
+ props.setProperty(p.getKey(), p.getValue());
+ }
+
cp.setChildNode(ROOT, state.getChildNode(ROOT));
SegmentNodeState newState = builder.getNodeState();
@@ -261,6 +274,28 @@ public class SegmentNodeStore implements
return name;
}
+ @Override @Nonnull
+ public synchronized String checkpoint(long lifetime) {
+ return checkpoint(lifetime, Collections.<String, String>emptyMap());
+ }
+
+ @Nonnull
+ @Override
+ public Map<String, String> checkpointInfo(@Nonnull String checkpoint) {
+ Map<String, String> properties = Maps.newHashMap();
+ checkNotNull(checkpoint);
+ NodeState cp = head.get()
+ .getChildNode("checkpoints")
+ .getChildNode(checkpoint)
+ .getChildNode("properties");
+
+ for (PropertyState prop : cp.getProperties()) {
+ properties.put(prop.getName(), prop.getValue(STRING));
+ }
+
+ return properties;
+ }
+
@Override @CheckForNull
public NodeState retrieve(@Nonnull String checkpoint) {
checkNotNull(checkpoint);
Modified: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/spi/state/NodeStore.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/spi/state/NodeStore.java?rev=1642692&r1=1642691&r2=1642692&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/spi/state/NodeStore.java (original)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/spi/state/NodeStore.java Mon Dec 1 14:34:19 2014
@@ -18,6 +18,7 @@ package org.apache.jackrabbit.oak.spi.st
import java.io.IOException;
import java.io.InputStream;
+import java.util.Map;
import javax.annotation.CheckForNull;
import javax.annotation.Nonnull;
@@ -116,6 +117,27 @@ public interface NodeStore {
* remains valid for at least as long as requested and allows that state
* of the repository to be retrieved using the returned opaque string
* reference.
+ * <p>
+ * The {@code properties} passed to this methods are associated with the
+ * checkpoint and can be retrieved through the {@link #checkpointInfo(String)}
+ * method. Its semantics is entirely application specific.
+ *
+ * @param lifetime time (in milliseconds, > 0) that the checkpoint
+ * should remain available
+ * @param properties properties to associate with the checkpoint
+ * @return string reference of this checkpoint
+ */
+ @Nonnull
+ String checkpoint(long lifetime, @Nonnull Map<String, String> properties);
+
+ /**
+ * Creates a new checkpoint of the latest root of the tree. The checkpoint
+ * remains valid for at least as long as requested and allows that state
+ * of the repository to be retrieved using the returned opaque string
+ * reference.
+ * <p>
+ * This method is a shortcut for {@link #checkpoint(long, Map)} passing
+ * an empty map for its 2nd argument.
*
* @param lifetime time (in milliseconds, > 0) that the checkpoint
* should remain available
@@ -125,6 +147,17 @@ public interface NodeStore {
String checkpoint(long lifetime);
/**
+ * Retrieve the properties associated with a checkpoint.
+ *
+ * @param checkpoint string reference of a checkpoint
+ * @return the properties associated with the checkpoint referenced by
+ * {@code checkpoint} or an empty map when there is no such
+ * checkpoint.
+ */
+ @Nonnull
+ Map<String, String> checkpointInfo(@Nonnull String checkpoint);
+
+ /**
* Retrieves the root node from a previously created repository checkpoint.
*
* @param checkpoint string reference of a checkpoint
Modified: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/spi/state/ProxyNodeStore.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/spi/state/ProxyNodeStore.java?rev=1642692&r1=1642691&r2=1642692&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/spi/state/ProxyNodeStore.java (original)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/spi/state/ProxyNodeStore.java Mon Dec 1 14:34:19 2014
@@ -18,6 +18,7 @@ package org.apache.jackrabbit.oak.spi.st
import java.io.IOException;
import java.io.InputStream;
+import java.util.Map;
import javax.annotation.Nonnull;
@@ -62,11 +63,23 @@ public abstract class ProxyNodeStore imp
return getNodeStore().getBlob(reference);
}
+ @Nonnull
+ @Override
+ public String checkpoint(long lifetime, @Nonnull Map<String, String> properties) {
+ return getNodeStore().checkpoint(lifetime, properties);
+ }
+
@Override
public String checkpoint(long lifetime) {
return getNodeStore().checkpoint(lifetime);
}
+ @Nonnull
+ @Override
+ public Map<String, String> checkpointInfo(@Nonnull String checkpoint) {
+ return getNodeStore().checkpointInfo(checkpoint);
+ }
+
@Override
public NodeState retrieve(String checkpoint) {
return getNodeStore().retrieve(checkpoint);
Modified: jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/NodeStoreFixture.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/NodeStoreFixture.java?rev=1642692&r1=1642691&r2=1642692&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/NodeStoreFixture.java (original)
+++ jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/NodeStoreFixture.java Mon Dec 1 14:34:19 2014
@@ -24,6 +24,7 @@ import java.io.IOException;
import org.apache.jackrabbit.oak.kernel.KernelNodeStore;
import org.apache.jackrabbit.oak.plugins.document.DocumentMK;
import org.apache.jackrabbit.oak.plugins.document.DocumentNodeStore;
+import org.apache.jackrabbit.oak.plugins.memory.MemoryNodeStore;
import org.apache.jackrabbit.oak.plugins.segment.SegmentNodeStore;
import org.apache.jackrabbit.oak.plugins.segment.memory.MemoryStore;
import org.apache.jackrabbit.oak.spi.state.NodeStore;
@@ -91,6 +92,16 @@ public abstract class NodeStoreFixture {
}
};
+ public static final NodeStoreFixture MEMORY_NS = new NodeStoreFixture() {
+ @Override
+ public NodeStore createNodeStore() {
+ return new MemoryNodeStore();
+ }
+
+ @Override
+ public void dispose(NodeStore nodeStore) { }
+ };
+
public abstract NodeStore createNodeStore();
public abstract void dispose(NodeStore nodeStore);
Added: 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=1642692&view=auto
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/kernel/CheckpointTest.java (added)
+++ jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/kernel/CheckpointTest.java Mon Dec 1 14:34:19 2014
@@ -0,0 +1,116 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.jackrabbit.oak.kernel;
+
+import static org.junit.Assert.assertEquals;
+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;
+import java.util.Collection;
+
+import com.google.common.collect.ImmutableMap;
+import org.apache.jackrabbit.oak.NodeStoreFixture;
+import org.apache.jackrabbit.oak.api.CommitFailedException;
+import org.apache.jackrabbit.oak.spi.commit.CommitInfo;
+import org.apache.jackrabbit.oak.spi.commit.EmptyHook;
+import org.apache.jackrabbit.oak.spi.state.NodeBuilder;
+import org.apache.jackrabbit.oak.spi.state.NodeState;
+import org.apache.jackrabbit.oak.spi.state.NodeStore;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
+
+@RunWith(value = Parameterized.class)
+public class CheckpointTest {
+
+ @Parameters
+ public static Collection<Object[]> fixtures() {
+ Object[][] fixtures = new Object[][] {
+ {NodeStoreFixture.MONGO_MK},
+ {NodeStoreFixture.MONGO_NS},
+ {NodeStoreFixture.SEGMENT_MK},
+ {NodeStoreFixture.MEMORY_NS},
+ };
+ return Arrays.asList(fixtures);
+ }
+
+ private final NodeStoreFixture fixture;
+
+ private NodeStore store;
+
+ private NodeState root;
+
+ public CheckpointTest(NodeStoreFixture fixture) {
+ this.fixture = fixture;
+ }
+
+ @Before
+ public void setUp() throws Exception {
+ store = fixture.createNodeStore();
+ NodeBuilder builder = store.getRoot().builder();
+ NodeBuilder test = builder.child("test");
+ test.setProperty("a", 1);
+ test.setProperty("b", 2);
+ test.setProperty("c", 3);
+ test.child("x");
+ test.child("y");
+ test.child("z");
+ root = store.merge(builder, EmptyHook.INSTANCE, CommitInfo.EMPTY);
+ }
+
+ @After
+ public void tearDown() throws Exception {
+ fixture.dispose(store);
+ }
+
+ @Test
+ public void checkpoint() throws CommitFailedException {
+ String cp = store.checkpoint(Long.MAX_VALUE);
+
+ NodeBuilder builder = store.getRoot().builder();
+ builder.setChildNode("new");
+ store.merge(builder, EmptyHook.INSTANCE, CommitInfo.EMPTY);
+
+ assertFalse(root.equals(store.getRoot()));
+ assertEquals(root, store.retrieve(cp));
+
+ assertTrue(store.release(cp));
+ if (fixture != NodeStoreFixture.MONGO_MK && fixture != NodeStoreFixture.MONGO_NS) {
+ assertNull(store.retrieve(cp));
+ }
+ }
+
+ @Test
+ public void checkpointInfo() throws CommitFailedException {
+ // FIXME implement. See OAK-2291
+ assumeTrue(fixture != NodeStoreFixture.MONGO_MK && fixture != NodeStoreFixture.MONGO_NS);
+ ImmutableMap<String, String> props = ImmutableMap.of(
+ "one", "1", "two", "2", "three", "2");
+ String cp = store.checkpoint(Long.MAX_VALUE, props);
+ assertEquals(props, store.checkpointInfo(cp));
+ }
+
+}