MultiplexingNodeStore sometimes fails to release checkpoint
Use NodeStore#checkpoints() to test whether a checkpoint exists.
package org.apache.jackrabbit.oak.plugins.multiplex;
import com.google.common.base.Predicate;
+import com.google.common.base.Predicates;
+import com.google.common.collect.Iterables;
import com.google.common.collect.Lists;
import com.google.common.collect.Sets;
import org.apache.jackrabbit.oak.api.Blob;
@@ -257,6 +259,9 @@ public class MultiplexingNodeStore implements NodeStore, Observable {
@Override
public Map<String, String> checkpointInfo(String checkpoint) {
+ if (!checkpointExists(ctx.getGlobalStore().getNodeStore(), checkpoint)) {
+ return Collections.emptyMap();
+ }
return copyOf(filterKeys(ctx.getGlobalStore().getNodeStore().checkpointInfo(checkpoint), new Predicate<String>() {
@Override
public boolean apply(String input) {
@@ -267,6 +272,9 @@ public class MultiplexingNodeStore implements NodeStore, Observable {
@Override
public NodeState retrieve(String checkpoint) {
+ if (!checkpointExists(ctx.getGlobalStore().getNodeStore(), checkpoint)) {
+ return null;
+ }
Map<String, String> props = ctx.getGlobalStore().getNodeStore().checkpointInfo(checkpoint);
if (props == null) {
return null;
@@ -275,7 +283,7 @@ public class MultiplexingNodeStore implements NodeStore, Observable {
nodeStates.put(ctx.getGlobalStore(), ctx.getGlobalStore().getNodeStore().retrieve(checkpoint));
for (MountedNodeStore nodeStore : ctx.getNonDefaultStores()) {
NodeState nodeState = null;
- if (!nodeStore.getNodeStore().checkpointInfo(checkpoint).isEmpty()) {
+ if (checkpointExists(nodeStore.getNodeStore(), checkpoint)) {
nodeState = nodeStore.getNodeStore().retrieve(checkpoint);
}
if (nodeState == null) {
@@ -294,14 +302,18 @@ public class MultiplexingNodeStore implements NodeStore, Observable {
@Override
public boolean release(String checkpoint) {
- Map<String, String> props = ctx.getGlobalStore().getNodeStore().checkpointInfo(checkpoint);
- if (props == null) {
- return false;
+ Map<String, String> props;
+ boolean result;
+ if (checkpointExists(ctx.getGlobalStore().getNodeStore(), checkpoint)) {
+ props = ctx.getGlobalStore().getNodeStore().checkpointInfo(checkpoint);
+ result = ctx.getGlobalStore().getNodeStore().release(checkpoint);
+ } else {
+ props = Collections.emptyMap();
+ result = true;
}
- boolean result = ctx.getGlobalStore().getNodeStore().release(checkpoint);
for (MountedNodeStore nodeStore : ctx.getNonDefaultStores()) {
boolean released = false;
- if (!nodeStore.getNodeStore().checkpointInfo(checkpoint).isEmpty()) {
+ if (checkpointExists(nodeStore.getNodeStore(), checkpoint)) {
released = nodeStore.getNodeStore().release(checkpoint);
}
if (!released) {
@@ -315,6 +327,10 @@ public class MultiplexingNodeStore implements NodeStore, Observable {
return result;
}
+ private static boolean checkpointExists(NodeStore nodeStore, String checkpoint) {
+ return Iterables.any(nodeStore.checkpoints(), Predicates.equalTo(checkpoint));
+ }
+
@Override
public Closeable addObserver(final Observer observer) {
observer.contentChanged(getRoot(), CommitInfo.EMPTY_EXTERNAL);
