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 ch...@apache.org on 2016/08/05 10:46:02 UTC
svn commit: r1755284 - in /jackrabbit/oak/trunk:
oak-core/src/main/java/org/apache/jackrabbit/oak/core/
oak-core/src/main/java/org/apache/jackrabbit/oak/spi/commit/
oak-it/src/test/java/org/apache/jackrabbit/oak/spi/commit/
Author: chetanm
Date: Fri Aug 5 10:46:02 2016
New Revision: 1755284
URL: http://svn.apache.org/viewvc?rev=1755284&view=rev
Log:
OAK-4640 - Provide a way for commit hook to record meta data for a given commit
Added:
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/core/ResetCommitAttributeHook.java (with props)
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/core/SimpleCommitContext.java (with props)
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/spi/commit/CommitContext.java (with props)
jackrabbit/oak/trunk/oak-it/src/test/java/org/apache/jackrabbit/oak/spi/commit/
jackrabbit/oak/trunk/oak-it/src/test/java/org/apache/jackrabbit/oak/spi/commit/CommitContextTest.java (with props)
Modified:
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/core/MutableRoot.java
Modified: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/core/MutableRoot.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/core/MutableRoot.java?rev=1755284&r1=1755283&r2=1755284&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/core/MutableRoot.java (original)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/core/MutableRoot.java Fri Aug 5 10:46:02 2016
@@ -34,6 +34,7 @@ import java.util.Map;
import javax.annotation.Nonnull;
import javax.security.auth.Subject;
+import com.google.common.collect.ImmutableMap;
import org.apache.jackrabbit.oak.api.Blob;
import org.apache.jackrabbit.oak.api.CommitFailedException;
import org.apache.jackrabbit.oak.api.ContentSession;
@@ -44,6 +45,7 @@ import org.apache.jackrabbit.oak.plugins
import org.apache.jackrabbit.oak.query.ExecutionContext;
import org.apache.jackrabbit.oak.query.QueryEngineImpl;
import org.apache.jackrabbit.oak.query.QueryEngineSettings;
+import org.apache.jackrabbit.oak.spi.commit.CommitContext;
import org.apache.jackrabbit.oak.spi.commit.CommitHook;
import org.apache.jackrabbit.oak.spi.commit.CommitInfo;
import org.apache.jackrabbit.oak.spi.commit.CompositeEditorProvider;
@@ -243,7 +245,7 @@ class MutableRoot implements Root {
checkLive();
ContentSession session = getContentSession();
CommitInfo commitInfo = new CommitInfo(
- session.toString(), session.getAuthInfo().getUserID(), info);
+ session.toString(), session.getAuthInfo().getUserID(), newInfoWithCommitContext(info));
store.merge(builder, getCommitHook(), commitInfo);
secureBuilder.baseChanged();
modCount = 0;
@@ -267,7 +269,7 @@ class MutableRoot implements Root {
*/
private CommitHook getCommitHook() {
List<CommitHook> hooks = newArrayList();
-
+ hooks.add(ResetCommitAttributeHook.INSTANCE);
hooks.add(hook);
List<CommitHook> postValidationHooks = new ArrayList<CommitHook>();
@@ -365,6 +367,13 @@ class MutableRoot implements Root {
return securityProvider.getConfiguration(AuthorizationConfiguration.class);
}
+ private static Map<String, Object> newInfoWithCommitContext(Map<String, Object> info){
+ return ImmutableMap.<String, Object>builder()
+ .putAll(info)
+ .put(CommitContext.NAME, new SimpleCommitContext())
+ .build();
+ }
+
//---------------------------------------------------------< MoveRecord >---
/**
Added: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/core/ResetCommitAttributeHook.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/core/ResetCommitAttributeHook.java?rev=1755284&view=auto
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/core/ResetCommitAttributeHook.java (added)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/core/ResetCommitAttributeHook.java Fri Aug 5 10:46:02 2016
@@ -0,0 +1,49 @@
+/*
+ * 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.core;
+
+import javax.annotation.Nonnull;
+
+import org.apache.jackrabbit.oak.api.CommitFailedException;
+import org.apache.jackrabbit.oak.spi.commit.CommitContext;
+import org.apache.jackrabbit.oak.spi.commit.CommitHook;
+import org.apache.jackrabbit.oak.spi.commit.CommitInfo;
+import org.apache.jackrabbit.oak.spi.state.NodeState;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+
+public enum ResetCommitAttributeHook implements CommitHook {
+ INSTANCE;
+
+ @Nonnull
+ @Override
+ public NodeState processCommit(NodeState before, NodeState after, CommitInfo info)
+ throws CommitFailedException {
+ //Reset the attributes upon each commit attempt
+ resetAttributes(info);
+ return after;
+ }
+
+ private static void resetAttributes(CommitInfo info) {
+ SimpleCommitContext attrs = (SimpleCommitContext) info.getInfo().get(CommitContext.NAME);
+ //As per implementation this should not be null
+ checkNotNull(attrs, "No commit attribute instance found in info map").clear();
+ }
+}
Propchange: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/core/ResetCommitAttributeHook.java
------------------------------------------------------------------------------
svn:eol-style = native
Added: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/core/SimpleCommitContext.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/core/SimpleCommitContext.java?rev=1755284&view=auto
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/core/SimpleCommitContext.java (added)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/core/SimpleCommitContext.java Fri Aug 5 10:46:02 2016
@@ -0,0 +1,50 @@
+/*
+ * 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.core;
+
+import java.util.Map;
+
+import com.google.common.collect.Maps;
+import org.apache.jackrabbit.oak.spi.commit.CommitContext;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+
+public class SimpleCommitContext implements CommitContext {
+ private final Map<String, Object> attrs = Maps.newHashMap();
+
+ @Override
+ public void set(String name, Object value) {
+ attrs.put(checkNotNull(name), value);
+ }
+
+ @Override
+ public Object get(String name) {
+ return attrs.get(checkNotNull(name));
+ }
+
+ @Override
+ public void remove(String name) {
+ attrs.remove(checkNotNull(name));
+ }
+
+ void clear(){
+ attrs.clear();
+ }
+}
Propchange: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/core/SimpleCommitContext.java
------------------------------------------------------------------------------
svn:eol-style = native
Added: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/spi/commit/CommitContext.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/spi/commit/CommitContext.java?rev=1755284&view=auto
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/spi/commit/CommitContext.java (added)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/spi/commit/CommitContext.java Fri Aug 5 10:46:02 2016
@@ -0,0 +1,71 @@
+/*
+ * 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.spi.commit;
+
+import javax.annotation.CheckForNull;
+
+/**
+ * A CommitContext instance can be obtained from {@link CommitInfo#getInfo()}
+ * if it has been set before the merge call. This can then be used by CommitHook
+ * to record some metadata regarding the commit.
+ *
+ * <p>CommitContext state would be reset in case commit is retried from within
+ * NodeStore say when a merge exception occurs.
+ */
+public interface CommitContext {
+ /**
+ * Name of the entry of the mutable commit attributes map in the {@code info}
+ * map in {@link CommitInfo#getInfo()}
+ */
+ String NAME = "oak.commitAttributes";
+
+ /**
+ * Stores an attribute related to this commit.
+ * Attributes are reset if the commit is retried.
+ *
+ * <p>If the object passed in is null, the effect is the same as
+ * calling {@link #remove}.
+ *
+ * @param name a <code>String</code> specifying the name of the attribute
+ * @param value the <code>Object</code> to be stored
+ */
+ void set(String name, Object value);
+
+ /**
+ * Returns the value of the named attribute as an <code>Object</code>,
+ * or <code>null</code> if no attribute of the given name exists.
+ *
+ * @param name <code>String</code> specifying the name of
+ * the attribute
+ *
+ * @return an <code>Object</code> containing the value
+ * of the attribute, or <code>null</code> if the attribute does not exist
+ */
+ @CheckForNull
+ Object get(String name);
+
+ /**
+ * Removes an attribute from this commit.
+ *
+ * @param name a <code>String</code> specifying
+ * the name of the attribute to remove
+ */
+ void remove(String name);
+}
Propchange: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/spi/commit/CommitContext.java
------------------------------------------------------------------------------
svn:eol-style = native
Added: jackrabbit/oak/trunk/oak-it/src/test/java/org/apache/jackrabbit/oak/spi/commit/CommitContextTest.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-it/src/test/java/org/apache/jackrabbit/oak/spi/commit/CommitContextTest.java?rev=1755284&view=auto
==============================================================================
--- jackrabbit/oak/trunk/oak-it/src/test/java/org/apache/jackrabbit/oak/spi/commit/CommitContextTest.java (added)
+++ jackrabbit/oak/trunk/oak-it/src/test/java/org/apache/jackrabbit/oak/spi/commit/CommitContextTest.java Fri Aug 5 10:46:02 2016
@@ -0,0 +1,198 @@
+/*
+ * 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.spi.commit;
+
+import java.io.Closeable;
+import java.io.IOException;
+import java.util.concurrent.atomic.AtomicInteger;
+
+import javax.annotation.Nonnull;
+import javax.annotation.Nullable;
+import javax.jcr.NoSuchWorkspaceException;
+import javax.security.auth.login.LoginException;
+
+import com.google.common.collect.ImmutableMap;
+import org.apache.jackrabbit.oak.Oak;
+import org.apache.jackrabbit.oak.OakBaseTest;
+import org.apache.jackrabbit.oak.api.CommitFailedException;
+import org.apache.jackrabbit.oak.api.ContentRepository;
+import org.apache.jackrabbit.oak.api.ContentSession;
+import org.apache.jackrabbit.oak.api.Root;
+import org.apache.jackrabbit.oak.api.Tree;
+import org.apache.jackrabbit.oak.fixture.NodeStoreFixture;
+import org.apache.jackrabbit.oak.spi.security.OpenSecurityProvider;
+import org.apache.jackrabbit.oak.spi.state.NodeState;
+import org.junit.After;
+import org.junit.Assume;
+import org.junit.Test;
+
+import static org.apache.jackrabbit.oak.api.CommitFailedException.MERGE;
+import static org.hamcrest.core.StringContains.containsString;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
+
+public class CommitContextTest extends OakBaseTest {
+ private CommitInfoCapturingObserver observer = new CommitInfoCapturingObserver();
+ private ContentSession session;
+ private ContentRepository repository;
+
+ public CommitContextTest(NodeStoreFixture fixture) {
+ super(fixture);
+ }
+
+ @After
+ public void closeRepository() throws IOException {
+ if (session != null) {
+ session.close();
+ }
+
+ if (repository instanceof Closeable) {
+ ((Closeable) repository).close();
+ }
+ }
+
+ @Test
+ public void basicSetup() throws Exception {
+ repository = new Oak(store)
+ .with(new OpenSecurityProvider())
+ .with(observer)
+ .createContentRepository();
+
+ session = newSession();
+ Root root = session.getLatestRoot();
+ Tree tree = root.getTree("/");
+ tree.setProperty("a", 1);
+ root.commit(ImmutableMap.<String, Object>of("foo", "bar"));
+
+ assertNotNull(observer.info);
+ assertTrue(observer.info.getInfo().containsKey("foo"));
+
+ assertTrue(observer.info.getInfo().containsKey(CommitContext.NAME));
+
+ try {
+ observer.info.getInfo().put("x", "y");
+ fail("Info map should be immutable");
+ } catch (Exception ignore) {
+
+ }
+ }
+
+ @Test
+ public void attributeAddedByCommitHook() throws Exception{
+ repository = new Oak(store)
+ .with(new OpenSecurityProvider())
+ .with(observer)
+ .with(new CommitHook() {
+ @Nonnull
+ @Override
+ public NodeState processCommit(NodeState before, NodeState after, CommitInfo info)
+ throws CommitFailedException {
+ CommitContext attrs = (CommitContext) info.getInfo().get(CommitContext.NAME);
+ assertNotNull(attrs);
+ attrs.set("foo", "bar");
+ return after;
+ }
+ })
+ .createContentRepository();
+
+ session = newSession();
+ Root root = session.getLatestRoot();
+ Tree tree = root.getTree("/");
+ tree.setProperty("a", 1);
+ root.commit();
+
+ assertNotNull(observer.info);
+
+ CommitContext attrs = (CommitContext) observer.info.getInfo().get(CommitContext.NAME);
+ assertNotNull(attrs.get("foo"));
+ }
+
+ @Test
+ public void attributesBeingReset() throws Exception{
+ //This test can only work with DocumentNodeStore as only that
+ //reattempt a failed merge. SegmentNodeStore would not do another
+ //attempt
+ assumeDocumentStore();
+ final AtomicInteger invokeCount = new AtomicInteger();
+ repository = new Oak(store)
+ .with(new OpenSecurityProvider())
+ .with(observer)
+ .with(new CommitHook() {
+ @Nonnull
+ @Override
+ public NodeState processCommit(NodeState before, NodeState after, CommitInfo info)
+ throws CommitFailedException {
+ CommitContext attrs = (CommitContext) info.getInfo().get(CommitContext.NAME);
+ int count = invokeCount.getAndIncrement();
+ if (count == 0) {
+ attrs.set("a", "1");
+ attrs.set("b", "2");
+ } else {
+ attrs.set("a", "3");
+ }
+ return after;
+ }
+ })
+ .with(new CommitHook() {
+ @Nonnull
+ @Override
+ public NodeState processCommit(NodeState before, NodeState after,
+ CommitInfo info) throws CommitFailedException {
+ if (invokeCount.get() == 1){
+ throw new CommitFailedException(MERGE, 0, "attribute reset test");
+ }
+ return after;
+ }
+ })
+ .createContentRepository();
+
+ session = newSession();
+ Root root = session.getLatestRoot();
+ Tree tree = root.getTree("/");
+ tree.setProperty("a", 1);
+ root.commit();
+
+ assertNotNull(observer.info);
+
+ CommitContext attrs = (CommitContext) observer.info.getInfo().get(CommitContext.NAME);
+ assertEquals("3", attrs.get("a"));
+ assertNull(attrs.get("b"));
+ }
+
+ private void assumeDocumentStore() {
+ Assume.assumeThat(fixture.toString(), containsString("DocumentNodeStore"));
+ }
+
+ private ContentSession newSession() throws LoginException, NoSuchWorkspaceException {
+ return repository.login(null, null);
+ }
+
+ private static class CommitInfoCapturingObserver implements Observer {
+ CommitInfo info;
+
+ @Override
+ public void contentChanged(@Nonnull NodeState root, @Nullable CommitInfo info) {
+ this.info = info;
+ }
+ }
+}
Propchange: jackrabbit/oak/trunk/oak-it/src/test/java/org/apache/jackrabbit/oak/spi/commit/CommitContextTest.java
------------------------------------------------------------------------------
svn:eol-style = native