JCRVLT-697: count moves of stashed child nodes towards autosave limit (#288)
* JCRVLT-697: count stash ops towards autosave limit
* JCRVLT-697: add test coverage
* JCRVLT-697: avoid major version change by adding default impl
* JCRVLT-697: add 'since' annotation to new API
* JCRVLT-697: explain change in the test
diff --git a/vault-core/src/main/java/org/apache/jackrabbit/vault/fs/api/ImportInfo.java b/vault-core/src/main/java/org/apache/jackrabbit/vault/fs/api/ImportInfo.java
index 116d206..bcc9e85 100644
--- a/vault-core/src/main/java/org/apache/jackrabbit/vault/fs/api/ImportInfo.java
+++ b/vault-core/src/main/java/org/apache/jackrabbit/vault/fs/api/ImportInfo.java
@@ -52,6 +52,15 @@
void onCreated(String path);
/**
+ * Marks that the child node at {@code path} was moved due to stashing.
+ * @param path the path
+ * @since 3.6.10
+ */
+ default void onStashed(String path) {
+ // by default do nothing
+ };
+
+ /**
* Marks that the node at {@code path} was deleted.
* @param path the path
*/
@@ -125,7 +134,7 @@
* @return a new, merged info.
*/
ImportInfo merge(ImportInfo info);
-
+
/**
* returns the number of non-NOP entries.
* @return the number of modified entries.
diff --git a/vault-core/src/main/java/org/apache/jackrabbit/vault/fs/api/package-info.java b/vault-core/src/main/java/org/apache/jackrabbit/vault/fs/api/package-info.java
index 625d01f..f05a7ad 100644
--- a/vault-core/src/main/java/org/apache/jackrabbit/vault/fs/api/package-info.java
+++ b/vault-core/src/main/java/org/apache/jackrabbit/vault/fs/api/package-info.java
@@ -15,7 +15,7 @@
* limitations under the License.
*/
-@Version("2.11.0")
+@Version("2.12.0")
package org.apache.jackrabbit.vault.fs.api;
import org.osgi.annotation.versioning.Version;
diff --git a/vault-core/src/main/java/org/apache/jackrabbit/vault/fs/impl/io/DocViewImporter.java b/vault-core/src/main/java/org/apache/jackrabbit/vault/fs/impl/io/DocViewImporter.java
index 7ac3f3a..97a01b7 100644
--- a/vault-core/src/main/java/org/apache/jackrabbit/vault/fs/impl/io/DocViewImporter.java
+++ b/vault-core/src/main/java/org/apache/jackrabbit/vault/fs/impl/io/DocViewImporter.java
@@ -971,7 +971,7 @@
// try to set uuid via sysview import if it differs from existing one
if (identifier.isPresent() && !node.getIdentifier().equals(identifier.get()) && !"rep:root".equals(ni.getPrimaryType().orElse(""))) {
NodeStash stash = new NodeStash(session, node.getPath());
- stash.stash();
+ stash.stash(importInfo);
Node parent = node.getParent();
removeReferences(node);
node.remove();
diff --git a/vault-core/src/main/java/org/apache/jackrabbit/vault/fs/impl/io/ImportInfoImpl.java b/vault-core/src/main/java/org/apache/jackrabbit/vault/fs/impl/io/ImportInfoImpl.java
index e09f797..2106cb2 100644
--- a/vault-core/src/main/java/org/apache/jackrabbit/vault/fs/impl/io/ImportInfoImpl.java
+++ b/vault-core/src/main/java/org/apache/jackrabbit/vault/fs/impl/io/ImportInfoImpl.java
@@ -158,6 +158,12 @@
numErrors++;
}
+ @Override
+ public void onStashed(String path) {
+ // path currently unused
+ numModified += 1;
+ }
+
/**
* remembers that a package path was remapped during import. e.g. when the importer follows and existing
* authorizable for MERGE and UPDATE modes.
@@ -211,7 +217,7 @@
public Collection<String> getToVersion() {
return toVersion;
}
-
+
public void registerToVersion(String path) {
toVersion.add(path);
}
diff --git a/vault-core/src/main/java/org/apache/jackrabbit/vault/fs/impl/io/JcrSysViewTransformer.java b/vault-core/src/main/java/org/apache/jackrabbit/vault/fs/impl/io/JcrSysViewTransformer.java
index 22b75c8..e7e18a9 100644
--- a/vault-core/src/main/java/org/apache/jackrabbit/vault/fs/impl/io/JcrSysViewTransformer.java
+++ b/vault-core/src/main/java/org/apache/jackrabbit/vault/fs/impl/io/JcrSysViewTransformer.java
@@ -110,7 +110,7 @@
if (existingPath != null) {
// check if there is an existing node with the name
recovery = new NodeStash(session, existingPath).excludeName("rep:cache");
- recovery.stash();
+ recovery.stash(null);
}
excludeNode(NAME_REP_CACHE);
this.importMode = importMode;
diff --git a/vault-core/src/main/java/org/apache/jackrabbit/vault/fs/impl/io/NodeStash.java b/vault-core/src/main/java/org/apache/jackrabbit/vault/fs/impl/io/NodeStash.java
index d6a4afc..8629a53 100644
--- a/vault-core/src/main/java/org/apache/jackrabbit/vault/fs/impl/io/NodeStash.java
+++ b/vault-core/src/main/java/org/apache/jackrabbit/vault/fs/impl/io/NodeStash.java
@@ -114,7 +114,7 @@
* Moves the child nodes and optionally properties of the path to a temporary location.
* @return the stashed node's primary type (if it needs to be kept)
*/
- public @Nullable String stash() {
+ public @Nullable String stash(@Nullable ImportInfo importInfo) {
try {
Node parent = session.getNode(path);
Node tmp = getOrCreateTemporaryNode();
@@ -131,8 +131,12 @@
continue;
}
try {
- session.move(child.getPath(), tmp.getPath() + "/" + name);
+ String path = child.getPath();
+ session.move(path, tmp.getPath() + "/" + name);
childNodeCount += 1;
+ if (importInfo != null) {
+ importInfo.onStashed(path);
+ }
} catch (RepositoryException e) {
log.error("Error while moving child node to temporary location. Child will be removed.", e);
}
@@ -183,6 +187,7 @@
Node parent = session.getNode(path);
NodeIterator iter = tmpNode.getNodes();
boolean hasErrors = false;
+
while (iter.hasNext()) {
Node child = iter.nextNode();
String newPath = parent.getPath() + "/" + child.getName();
@@ -190,7 +195,11 @@
if (session.nodeExists(newPath)) {
log.debug("Skipping restore from temporary location {} as node already exists at {}", child.getPath(), newPath);
} else {
- session.move(child.getPath(), newPath);
+ String path = child.getPath();
+ session.move(path, newPath);
+ if (importInfo != null) {
+ importInfo.onStashed(path);
+ }
}
} catch (RepositoryException e) {
log.warn(
diff --git a/vault-core/src/test/java/org/apache/jackrabbit/vault/packaging/integration/NodeStashingIT.java b/vault-core/src/test/java/org/apache/jackrabbit/vault/packaging/integration/NodeStashingIT.java
index 4ab759b..1b7d029 100644
--- a/vault-core/src/test/java/org/apache/jackrabbit/vault/packaging/integration/NodeStashingIT.java
+++ b/vault-core/src/test/java/org/apache/jackrabbit/vault/packaging/integration/NodeStashingIT.java
@@ -22,11 +22,15 @@
import static org.junit.Assume.assumeTrue;
import java.io.IOException;
+import java.util.LinkedList;
+import java.util.List;
import javax.jcr.Node;
import javax.jcr.RepositoryException;
import org.apache.jackrabbit.vault.fs.api.ImportMode;
+import org.apache.jackrabbit.vault.fs.api.ProgressTrackerListener;
+import org.apache.jackrabbit.vault.fs.api.ProgressTrackerListener.Mode;
import org.apache.jackrabbit.vault.fs.io.ImportOptions;
import org.apache.jackrabbit.vault.packaging.PackageException;
import org.junit.Test;
@@ -65,6 +69,9 @@
// update same path but without mixin allowing child nodes and different
// UUID so that node stashing kicks in
+ Collector col = new Collector();
+ options.setListener(col);
+
extractVaultPackage("/test-packages/stashing/update.zip", options);
// child node should be retained
@@ -79,5 +86,22 @@
// make sure mixin type was restored
assertTrue(node2.isNodeType("{" + TESTNS + "}hasMandatoryChildNode"));
+
+ // before JCRVLT-697, this would have been only one node
+ String expected = "saving approx 3 nodes...";
+ assertTrue("Expected message '" + expected + "' not seen in: " + col.actions, col.actions.contains(expected));
+ }
+
+ private static class Collector implements ProgressTrackerListener {
+ private final List<String> actions = new LinkedList<>();
+
+ public void onMessage(Mode mode, String action, String path) {
+ if (Mode.PATHS == mode) {
+ actions.add(action);
+ }
+ }
+
+ public void onError(Mode mode, String path, Exception e) {
+ }
}
}
\ No newline at end of file