Modified: jackrabbit/oak/trunk/oak-store-document/src/main/java/org/apache/jackrabbit/oak/plugins/document/NodeDocumentSweeper.java URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-store-document/src/main/java/org/apache/jackrabbit/oak/plugins/document/NodeDocumentSweeper.java?rev=1857240&r1=1857239&r2=1857240&view=diff ============================================================================== --- jackrabbit/oak/trunk/oak-store-document/src/main/java/org/apache/jackrabbit/oak/plugins/document/NodeDocumentSweeper.java (original) +++ jackrabbit/oak/trunk/oak-store-document/src/main/java/org/apache/jackrabbit/oak/plugins/document/NodeDocumentSweeper.java Wed Apr 10 11:13:19 2019 @@ -137,10 +137,10 @@ final class NodeDocumentSweeper { return null; } - Iterable<Map.Entry<String, UpdateOp>> ops = sweepOperations(documents); - for (List<Map.Entry<String, UpdateOp>> batch : partition(ops, INVALIDATE_BATCH_SIZE)) { - Map<String, UpdateOp> updates = newHashMap(); - for (Map.Entry<String, UpdateOp> entry : batch) { + Iterable<Map.Entry<Path, UpdateOp>> ops = sweepOperations(documents); + for (List<Map.Entry<Path, UpdateOp>> batch : partition(ops, INVALIDATE_BATCH_SIZE)) { + Map<Path, UpdateOp> updates = newHashMap(); + for (Map.Entry<Path, UpdateOp> entry : batch) { updates.put(entry.getKey(), entry.getValue()); } listener.sweepUpdate(updates); @@ -149,17 +149,17 @@ final class NodeDocumentSweeper { return head; } - private Iterable<Map.Entry<String, UpdateOp>> sweepOperations( + private Iterable<Map.Entry<Path, UpdateOp>> sweepOperations( final Iterable<NodeDocument> docs) { return filter(transform(docs, - new Function<NodeDocument, Map.Entry<String, UpdateOp>>() { + new Function<NodeDocument, Map.Entry<Path, UpdateOp>>() { @Override - public Map.Entry<String, UpdateOp> apply(NodeDocument doc) { + public Map.Entry<Path, UpdateOp> apply(NodeDocument doc) { return immutableEntry(doc.getPath(), sweepOne(doc)); } - }), new Predicate<Map.Entry<String, UpdateOp>>() { + }), new Predicate<Map.Entry<Path, UpdateOp>>() { @Override - public boolean apply(Map.Entry<String, UpdateOp> input) { + public boolean apply(Map.Entry<Path, UpdateOp> input) { return input.getValue() != null; } });
Added: jackrabbit/oak/trunk/oak-store-document/src/main/java/org/apache/jackrabbit/oak/plugins/document/Path.java URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-store-document/src/main/java/org/apache/jackrabbit/oak/plugins/document/Path.java?rev=1857240&view=auto ============================================================================== --- jackrabbit/oak/trunk/oak-store-document/src/main/java/org/apache/jackrabbit/oak/plugins/document/Path.java (added) +++ jackrabbit/oak/trunk/oak-store-document/src/main/java/org/apache/jackrabbit/oak/plugins/document/Path.java Wed Apr 10 11:13:19 2019 @@ -0,0 +1,368 @@ +/* + * 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.plugins.document; + +import java.util.Arrays; +import java.util.Objects; + +import org.apache.jackrabbit.oak.cache.CacheValue; +import org.apache.jackrabbit.oak.commons.PathUtils; +import org.apache.jackrabbit.oak.commons.StringUtils; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import static com.google.common.base.Preconditions.checkArgument; +import static com.google.common.base.Preconditions.checkNotNull; +import static com.google.common.collect.Iterables.elementsEqual; + +/** + * The {@code Path} class is closely modeled after the semantics of + * {@code PathUtils} in oak-commons. Corresponding methods in this class can + * be used as a replacement for the methods in {@code PathUtils} on {@code Path} + * objects. + */ +public final class Path implements CacheValue, Comparable<Path> { + + public static final Path ROOT = new Path(null, "", "".hashCode()); + + @Nullable + private final Path parent; + + @NotNull + private final String name; + + private int hash; + + private Path(@Nullable Path parent, + @NotNull String name, + int hash) { + this.parent = parent; + this.name = name; + this.hash = hash; + } + + /** + * Creates a new {@code Path} from the given parent {@code Path}. The name + * of the new {@code Path} cannot be the empty {@code String}. + * + * @param parent the parent {@code Path}. + * @param name the name of the new {@code Path}. + * @throws IllegalArgumentException if the {@code name} is empty. + */ + public Path(@NotNull Path parent, @NotNull String name) { + this(checkNotNull(parent), checkNotNull(name), -1); + checkArgument(!name.isEmpty(), "name cannot be the empty String"); + } + + /** + * Creates a relative path with a single name element. The name cannot be + * the empty {@code String}. + * + * @param name the name of the first path element. + * @throws IllegalArgumentException if the {@code name} is empty. + */ + public Path(@NotNull String name) { + this(null, checkNotNull(name), -1); + checkArgument(!name.isEmpty(), "name cannot be the empty String"); + } + + /** + * Returns the name of this path. The {@link #ROOT} is the only path with + * an empty name. That is a String with length zero. + * + * @return the name of this path. + */ + @NotNull + public String getName() { + return name; + } + + /** + * Returns the names of the path elements with increasing {@link #getDepth()} + * starting at depth 1. + * + * @return the names of the path elements. + */ + @NotNull + public Iterable<String> elements() { + return elements(false); + } + + /** + * Returns {@code true} if this is the {@link #ROOT} path; {@code false} + * otherwise. + * + * @return whether this is the {@link #ROOT} path. + */ + public boolean isRoot() { + return name.isEmpty(); + } + + /** + * The parent of this path or {@code null} if this path does not have a + * parent. The {@link #ROOT} path and the first path element of a relative + * path do not have a parent. + * + * @return the parent of this path or {@code null} if this path does not + * have a parent. + */ + @Nullable + public Path getParent() { + return parent; + } + + /** + * @return the number of characters of the {@code String} representation of + * this path. + */ + public int length() { + if (isRoot()) { + return 1; + } + int length = 0; + Path p = this; + while (p != null) { + length += p.name.length(); + if (p.parent != null) { + length++; + } + p = p.parent; + } + return length; + } + + /** + * The depth of this path. The {@link #ROOT} has a depth of 0. The path + * {@code /foo/bar} as well as {@code bar/baz} have depth 2. + * + * @return the depth of the path. + */ + public int getDepth() { + return getNumberOfPathElements(false); + } + + /** + * Get the nth ancestor of a path. The 1st ancestor is the parent path, + * 2nd ancestor the grandparent path, and so on... + * <p> + * If {@code nth <= 0}, then this path is returned. + * + * @param nth indicates the ancestor level for which the path should be + * calculated. + * @return the ancestor path + */ + @NotNull + public Path getAncestor(int nth) { + Path p = this; + while (nth-- > 0 && p.parent != null) { + p = p.parent; + } + return p; + } + + /** + * Return {@code true} if {@code this} path is an ancestor of the + * {@code other} path, otherwise {@code false}. + * + * @param other the other path. + * @return whether this path is an ancestor of the other path. + */ + public boolean isAncestorOf(@NotNull Path other) { + checkNotNull(other); + int depthDiff = other.getDepth() - getDepth(); + return depthDiff > 0 + && elementsEqual(elements(true), other.getAncestor(depthDiff).elements(true)); + } + + /** + * @return {@code true} if this is an absolute path; {@code false} otherwise. + */ + public boolean isAbsolute() { + Path p = this; + while (p.parent != null) { + p = p.parent; + } + return p.isRoot(); + } + + /** + * Creates a {@code Path} from a {@code String}. + * + * @param path the {@code String} to parse. + * @return the {@code Path} from the {@code String}. + * @throws IllegalArgumentException if the {@code path} is the empty + * {@code String}. + */ + @NotNull + public static Path fromString(@NotNull String path) throws IllegalArgumentException { + checkNotNull(path); + Path p = null; + if (PathUtils.isAbsolute(path)) { + p = ROOT; + } + for (String name : PathUtils.elements(path)) { + name = StringCache.get(name); + if (p == null) { + p = new Path(name); + } else { + p = new Path(p, StringCache.get(name)); + } + } + if (p == null) { + throw new IllegalArgumentException("path must not be empty"); + } + return p; + } + + /** + * Appends the {@code String} representation of this {@code Path} to the + * passed {@code StringBuilder}. See also {@link #toString()}. + * + * @param sb the {@code StringBuilder} this {@code Path} is appended to. + * @return the passed {@code StringBuilder}. + */ + @NotNull + public StringBuilder toStringBuilder(@NotNull StringBuilder sb) { + if (isRoot()) { + sb.append('/'); + } else { + buildPath(sb); + } + return sb; + } + + @Override + public int getMemory() { + int memory = 0; + Path p = this; + while (p.parent != null) { + memory += 24; // shallow size + memory += StringUtils.estimateMemoryUsage(name); + p = p.parent; + } + return memory; + } + + @Override + public int compareTo(@NotNull Path other) { + if (this == other) { + return 0; + } + Path t = this; + int off = t.getNumberOfPathElements(true) - + checkNotNull(other).getNumberOfPathElements(true); + int corrected = off; + while (corrected > 0) { + t = t.parent; + corrected--; + } + while (corrected < 0) { + other = other.parent; + corrected++; + } + int cp = comparePath(t, other); + if (cp != 0) { + return cp; + } + return Integer.signum(off); + } + + @Override + public String toString() { + if (isRoot()) { + return "/"; + } else { + return buildPath(new StringBuilder(length())).toString(); + } + } + + @Override + public int hashCode() { + int h = hash; + if (h == -1 && parent != null) { + h = 17; + h = 37 * h + parent.hashCode(); + h = 37 * h + name.hashCode(); + hash = h; + } + return h; + } + + @Override + public boolean equals(Object obj) { + if (this == obj) { + return true; + } else if (obj instanceof Path) { + Path other = (Path) obj; + return this.name.equals(other.name) + && Objects.equals(this.parent, other.parent); + } + return false; + } + + //-------------------------< internal >------------------------------------- + + private Iterable<String> elements(boolean withRoot) { + int size = getNumberOfPathElements(withRoot); + String[] elements = new String[size]; + Path p = this; + for (int i = size - 1; p != null; i--) { + if (withRoot || !p.isRoot()) { + elements[i] = p.name; + } + p = p.parent; + } + return Arrays.asList(elements); + } + + private StringBuilder buildPath(StringBuilder sb) { + if (parent != null) { + parent.buildPath(sb).append("/"); + } + sb.append(name); + return sb; + } + + /** + * Returns the number of path elements. Depending on {@code withRoot} the + * root of an absolute path is also taken into account. + * + * @param withRoot whether the root of an absolute path is also counted. + * @return the number of path elements. + */ + private int getNumberOfPathElements(boolean withRoot) { + int depth = 0; + for (Path p = this; p != null; p = p.parent) { + if (withRoot || !p.isRoot()) { + depth++; + } + } + return depth; + } + + private static int comparePath(Path a, Path b) { + if (a.parent != b.parent) { + int cp = comparePath(a.parent, b.parent); + if (cp != 0) { + return cp; + } + } + return a.name.compareTo(b.name); + } +} Propchange: jackrabbit/oak/trunk/oak-store-document/src/main/java/org/apache/jackrabbit/oak/plugins/document/Path.java ------------------------------------------------------------------------------ svn:eol-style = native Modified: jackrabbit/oak/trunk/oak-store-document/src/main/java/org/apache/jackrabbit/oak/plugins/document/PathComparator.java URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-store-document/src/main/java/org/apache/jackrabbit/oak/plugins/document/PathComparator.java?rev=1857240&r1=1857239&r2=1857240&view=diff ============================================================================== --- jackrabbit/oak/trunk/oak-store-document/src/main/java/org/apache/jackrabbit/oak/plugins/document/PathComparator.java (original) +++ jackrabbit/oak/trunk/oak-store-document/src/main/java/org/apache/jackrabbit/oak/plugins/document/PathComparator.java Wed Apr 10 11:13:19 2019 @@ -24,25 +24,25 @@ import java.util.Comparator; import org.apache.jackrabbit.oak.plugins.document.util.Utils; /** - * Implements a comparator, which sorts path string according to 1) their - * depth (highest first) and 2) the path string itself. + * Implements a comparator, which sorts paths according to 1) their depth + * (highest first) and 2) the paths natural ordering. */ -public class PathComparator implements Comparator<String>, Serializable { +public class PathComparator implements Comparator<Path>, Serializable { private static final long serialVersionUID = -1523171906146067782L; - public static final Comparator<String> INSTANCE = new PathComparator(); + public static final Comparator<Path> INSTANCE = new PathComparator(); private PathComparator() { } @Override - public int compare(String o1, String o2) { - int d1 = Utils.pathDepth(o1); - int d2 = Utils.pathDepth(o2); + public int compare(Path p1, Path p2) { + int d1 = p1.getDepth(); + int d2 = p2.getDepth(); if (d1 != d2) { return Integer.signum(d2 - d1); } - return o1.compareTo(o2); + return p1.compareTo(p2); } } Modified: jackrabbit/oak/trunk/oak-store-document/src/main/java/org/apache/jackrabbit/oak/plugins/document/PathRev.java URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-store-document/src/main/java/org/apache/jackrabbit/oak/plugins/document/PathRev.java?rev=1857240&r1=1857239&r2=1857240&view=diff ============================================================================== --- jackrabbit/oak/trunk/oak-store-document/src/main/java/org/apache/jackrabbit/oak/plugins/document/PathRev.java (original) +++ jackrabbit/oak/trunk/oak-store-document/src/main/java/org/apache/jackrabbit/oak/plugins/document/PathRev.java Wed Apr 10 11:13:19 2019 @@ -19,7 +19,6 @@ package org.apache.jackrabbit.oak.plugins.document; import org.apache.jackrabbit.oak.cache.CacheValue; -import org.apache.jackrabbit.oak.commons.StringUtils; import org.jetbrains.annotations.NotNull; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -27,31 +26,37 @@ import org.slf4j.LoggerFactory; import static com.google.common.base.Preconditions.checkNotNull; /** - * A cache key implementation, which is a combination of a path string and a - * revision. + * A cache key implementation, which is a combination of a path and a revision + * vector. */ -public final class PathRev implements CacheValue { +public final class PathRev implements CacheValue, Comparable<PathRev> { private static final Logger LOG = LoggerFactory.getLogger(PathRev.class); - private final String path; + private final Path path; private final RevisionVector revision; - public PathRev(@NotNull String path, @NotNull RevisionVector revision) { + private int hash; + + public PathRev(@NotNull Path path, @NotNull RevisionVector revision) { this.path = checkNotNull(path); this.revision = checkNotNull(revision); } - public String getPath() { + public Path getPath() { return path; } + public RevisionVector getRevision() { + return revision; + } + @Override public int getMemory() { - long size = 24 // shallow size - + (long)StringUtils.estimateMemoryUsage(path) // path - + revision.getMemory(); // revision + long size = 24L // shallow size + + path.getMemory() // path + + revision.getMemory(); // revision if (size > Integer.MAX_VALUE) { LOG.debug("Estimated memory footprint larger than Integer.MAX_VALUE: {}.", size); size = Integer.MAX_VALUE; @@ -59,12 +64,31 @@ public final class PathRev implements Ca return (int) size; } - //----------------------------< Object >------------------------------------ + //---------------------------< Comparable >--------------------------------- + + public int compareTo(@NotNull PathRev other) { + if (this == other) { + return 0; + } + int compare = this.path.compareTo(other.path); + if (compare != 0) { + return compare; + } + return this.revision.compareTo(other.revision); + } + //----------------------------< Object >------------------------------------ @Override public int hashCode() { - return path.hashCode() ^ revision.hashCode(); + int h = this.hash; + if (h == 0) { + h = 17; + h = 37 * h + path.hashCode(); + h = 37 * h + revision.hashCode(); + this.hash = h; + } + return h; } @Override @@ -88,25 +112,4 @@ public final class PathRev implements Ca return sb.toString(); } - public String asString() { - return toString(); - } - - public static PathRev fromString(String s) { - int index = s.lastIndexOf('@'); - return new PathRev(s.substring(0, index), - RevisionVector.fromString(s.substring(index + 1))); - } - - public int compareTo(PathRev b) { - if (this == b) { - return 0; - } - int compare = path.compareTo(b.path); - if (compare == 0) { - compare = revision.compareTo(b.revision); - } - return compare; - } - } Modified: jackrabbit/oak/trunk/oak-store-document/src/main/java/org/apache/jackrabbit/oak/plugins/document/PropertyHistory.java URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-store-document/src/main/java/org/apache/jackrabbit/oak/plugins/document/PropertyHistory.java?rev=1857240&r1=1857239&r2=1857240&view=diff ============================================================================== --- jackrabbit/oak/trunk/oak-store-document/src/main/java/org/apache/jackrabbit/oak/plugins/document/PropertyHistory.java (original) +++ jackrabbit/oak/trunk/oak-store-document/src/main/java/org/apache/jackrabbit/oak/plugins/document/PropertyHistory.java Wed Apr 10 11:13:19 2019 @@ -47,7 +47,7 @@ class PropertyHistory implements Iterabl private final NodeDocument doc; private final String property; // path of the main document - private final String mainPath; + private final Path mainPath; public PropertyHistory(@NotNull NodeDocument doc, @NotNull String property) { Modified: jackrabbit/oak/trunk/oak-store-document/src/main/java/org/apache/jackrabbit/oak/plugins/document/ResetDiff.java URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-store-document/src/main/java/org/apache/jackrabbit/oak/plugins/document/ResetDiff.java?rev=1857240&r1=1857239&r2=1857240&view=diff ============================================================================== --- jackrabbit/oak/trunk/oak-store-document/src/main/java/org/apache/jackrabbit/oak/plugins/document/ResetDiff.java (original) +++ jackrabbit/oak/trunk/oak-store-document/src/main/java/org/apache/jackrabbit/oak/plugins/document/ResetDiff.java Wed Apr 10 11:13:19 2019 @@ -19,7 +19,6 @@ package org.apache.jackrabbit.oak.plugin import java.util.Map; import org.apache.jackrabbit.oak.api.PropertyState; -import org.apache.jackrabbit.oak.commons.PathUtils; import org.apache.jackrabbit.oak.plugins.document.util.Utils; import org.apache.jackrabbit.oak.spi.state.NodeState; import org.apache.jackrabbit.oak.spi.state.NodeStateDiff; @@ -38,19 +37,19 @@ class ResetDiff implements NodeStateDiff private final ResetDiff parent; private final Revision revision; - private final String path; - private final Map<String, UpdateOp> operations; + private final Path path; + private final Map<Path, UpdateOp> operations; private UpdateOp update; ResetDiff(@NotNull Revision revision, - @NotNull Map<String, UpdateOp> operations) { - this(null, revision, "/", operations); + @NotNull Map<Path, UpdateOp> operations) { + this(null, revision, Path.ROOT, operations); } private ResetDiff(@Nullable ResetDiff parent, @NotNull Revision revision, - @NotNull String path, - @NotNull Map<String, UpdateOp> operations) { + @NotNull Path path, + @NotNull Map<Path, UpdateOp> operations) { this.parent = parent; this.revision = checkNotNull(revision); this.path = checkNotNull(path); @@ -78,7 +77,7 @@ class ResetDiff implements NodeStateDiff @Override public boolean childNodeAdded(String name, NodeState after) { NodeDocument.removeCommitRoot(getUpdateOp(), revision); - String p = PathUtils.concat(path, name); + Path p = new Path(path, name); ResetDiff diff = new ResetDiff(this, revision, p, operations); UpdateOp op = diff.getUpdateOp(); NodeDocument.removeDeleted(op, revision); @@ -94,20 +93,20 @@ class ResetDiff implements NodeStateDiff public boolean childNodeChanged(String name, NodeState before, NodeState after) { - String p = PathUtils.concat(path, name); + Path p = new Path(path, name); return after.compareAgainstBaseState(before, new ResetDiff(this, revision, p, operations)); } @Override public boolean childNodeDeleted(String name, NodeState before) { - String p = PathUtils.concat(path, name); + Path p = new Path(path, name); ResetDiff diff = new ResetDiff(this, revision, p, operations); NodeDocument.removeDeleted(diff.getUpdateOp(), revision); return MISSING_NODE.compareAgainstBaseState(before, diff); } - Map<String, UpdateOp> getOperations() { + Map<Path, UpdateOp> getOperations() { return operations; } Modified: jackrabbit/oak/trunk/oak-store-document/src/main/java/org/apache/jackrabbit/oak/plugins/document/SplitDocumentCleanUp.java URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-store-document/src/main/java/org/apache/jackrabbit/oak/plugins/document/SplitDocumentCleanUp.java?rev=1857240&r1=1857239&r2=1857240&view=diff ============================================================================== --- jackrabbit/oak/trunk/oak-store-document/src/main/java/org/apache/jackrabbit/oak/plugins/document/SplitDocumentCleanUp.java (original) +++ jackrabbit/oak/trunk/oak-store-document/src/main/java/org/apache/jackrabbit/oak/plugins/document/SplitDocumentCleanUp.java Wed Apr 10 11:13:19 2019 @@ -114,11 +114,9 @@ public class SplitDocumentCleanUp implem return; } - String splitDocPath = splitDoc.getPath(); - int slashIdx = splitDocPath.lastIndexOf('/'); - int height = Integer.parseInt(splitDocPath.substring(slashIdx + 1)); - Revision rev = Revision.fromString( - splitDocPath.substring(splitDocPath.lastIndexOf('/', slashIdx - 1) + 1, slashIdx)); + Path splitDocPath = splitDoc.getPath(); + int height = Integer.parseInt(splitDocPath.getName()); + Revision rev = Revision.fromString(splitDocPath.getParent().getName()); doc = doc.findPrevReferencingDoc(rev, height); if (doc == null) { LOG.warn("Split document {} for path {} not referenced anymore. Main document is {}", Modified: jackrabbit/oak/trunk/oak-store-document/src/main/java/org/apache/jackrabbit/oak/plugins/document/SplitOperations.java URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-store-document/src/main/java/org/apache/jackrabbit/oak/plugins/document/SplitOperations.java?rev=1857240&r1=1857239&r2=1857240&view=diff ============================================================================== --- jackrabbit/oak/trunk/oak-store-document/src/main/java/org/apache/jackrabbit/oak/plugins/document/SplitOperations.java (original) +++ jackrabbit/oak/trunk/oak-store-document/src/main/java/org/apache/jackrabbit/oak/plugins/document/SplitOperations.java Wed Apr 10 11:13:19 2019 @@ -77,7 +77,7 @@ class SplitOperations { private static final DocumentStore STORE = new MemoryDocumentStore(); private final NodeDocument doc; - private final String path; + private final Path path; private final String id; private final Revision headRevision; private final RevisionContext context; @@ -314,11 +314,11 @@ class SplitOperations { if (h == null || l == null) { throw new IllegalStateException(); } - String prevPath = Utils.getPreviousPathFor(path, h, entry.getKey() + 1); + Path prevPath = Utils.getPreviousPathFor(path, h, entry.getKey() + 1); String prevId = Utils.getIdFromPath(prevPath); UpdateOp intermediate = new UpdateOp(prevId, true); - if (Utils.isLongPath(prevPath)) { - intermediate.set(NodeDocument.PATH, prevPath); + if (Utils.isIdFromLongPath(prevId)) { + intermediate.set(NodeDocument.PATH, prevPath.toString()); } setPrevious(main, new Range(h, l, entry.getKey() + 1)); for (Range r : entry.getValue()) { @@ -351,10 +351,11 @@ class SplitOperations { // move to another document main = new UpdateOp(id, false); setPrevious(main, new Range(high, low, 0)); - String oldPath = Utils.getPreviousPathFor(path, high, 0); - UpdateOp old = new UpdateOp(Utils.getIdFromPath(oldPath), true); - if (Utils.isLongPath(oldPath)) { - old.set(NodeDocument.PATH, oldPath); + Path oldPath = Utils.getPreviousPathFor(path, high, 0); + String oldId = Utils.getIdFromPath(oldPath); + UpdateOp old = new UpdateOp(oldId, true); + if (Utils.isIdFromLongPath(oldId)) { + old.set(NodeDocument.PATH, oldPath.toString()); } for (String property : committedChanges.keySet()) { NavigableMap<Revision, String> splitMap = committedChanges.get(property); Modified: jackrabbit/oak/trunk/oak-store-document/src/main/java/org/apache/jackrabbit/oak/plugins/document/StringCache.java URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-store-document/src/main/java/org/apache/jackrabbit/oak/plugins/document/StringCache.java?rev=1857240&r1=1857239&r2=1857240&view=diff ============================================================================== --- jackrabbit/oak/trunk/oak-store-document/src/main/java/org/apache/jackrabbit/oak/plugins/document/StringCache.java (original) +++ jackrabbit/oak/trunk/oak-store-document/src/main/java/org/apache/jackrabbit/oak/plugins/document/StringCache.java Wed Apr 10 11:13:19 2019 @@ -16,13 +16,13 @@ */ package org.apache.jackrabbit.oak.plugins.document; +import java.util.HashMap; import java.util.Map; import org.apache.jackrabbit.JcrConstants; import org.apache.jackrabbit.oak.spi.nodetype.NodeTypeConstants; import org.apache.jackrabbit.oak.spi.version.VersionConstants; -import com.google.common.collect.ImmutableMap; import org.apache.jackrabbit.oak.spi.state.ConflictType; /** @@ -139,11 +139,11 @@ public final class StringCache { } private static Map<String, String> createStringMap(String... strings) { - ImmutableMap.Builder<String, String> builder = ImmutableMap.builder(); + Map<String, String> map = new HashMap<>(); for (String string : strings) { - builder.put(string, string); + map.put(string, string); } - return builder.build(); + return map; } // must be a power of 2 Modified: jackrabbit/oak/trunk/oak-store-document/src/main/java/org/apache/jackrabbit/oak/plugins/document/TieredDiffCache.java URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-store-document/src/main/java/org/apache/jackrabbit/oak/plugins/document/TieredDiffCache.java?rev=1857240&r1=1857239&r2=1857240&view=diff ============================================================================== --- jackrabbit/oak/trunk/oak-store-document/src/main/java/org/apache/jackrabbit/oak/plugins/document/TieredDiffCache.java (original) +++ jackrabbit/oak/trunk/oak-store-document/src/main/java/org/apache/jackrabbit/oak/plugins/document/TieredDiffCache.java Wed Apr 10 11:13:19 2019 @@ -53,7 +53,7 @@ class TieredDiffCache extends DiffCache @Override public String getChanges(@NotNull RevisionVector from, @NotNull RevisionVector to, - @NotNull String path, + @NotNull Path path, @Nullable Loader loader) { // do not check local cache when changes are external if (isLocalChange(from, to, clusterId)) { Modified: jackrabbit/oak/trunk/oak-store-document/src/main/java/org/apache/jackrabbit/oak/plugins/document/UnmergedBranches.java URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-store-document/src/main/java/org/apache/jackrabbit/oak/plugins/document/UnmergedBranches.java?rev=1857240&r1=1857239&r2=1857240&view=diff ============================================================================== --- jackrabbit/oak/trunk/oak-store-document/src/main/java/org/apache/jackrabbit/oak/plugins/document/UnmergedBranches.java (original) +++ jackrabbit/oak/trunk/oak-store-document/src/main/java/org/apache/jackrabbit/oak/plugins/document/UnmergedBranches.java Wed Apr 10 11:13:19 2019 @@ -71,7 +71,7 @@ class UnmergedBranches { if (!initialized.compareAndSet(false, true)) { throw new IllegalStateException("already initialized"); } - NodeDocument doc = store.find(Collection.NODES, Utils.getIdFromPath("/")); + NodeDocument doc = store.find(Collection.NODES, Utils.getIdFromPath(Path.ROOT)); if (doc == null) { return; } Modified: jackrabbit/oak/trunk/oak-store-document/src/main/java/org/apache/jackrabbit/oak/plugins/document/UnsavedModifications.java URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-store-document/src/main/java/org/apache/jackrabbit/oak/plugins/document/UnsavedModifications.java?rev=1857240&r1=1857239&r2=1857240&view=diff ============================================================================== --- jackrabbit/oak/trunk/oak-store-document/src/main/java/org/apache/jackrabbit/oak/plugins/document/UnsavedModifications.java (original) +++ jackrabbit/oak/trunk/oak-store-document/src/main/java/org/apache/jackrabbit/oak/plugins/document/UnsavedModifications.java Wed Apr 10 11:13:19 2019 @@ -24,7 +24,6 @@ import java.util.concurrent.ConcurrentMa import java.util.concurrent.TimeUnit; import java.util.concurrent.locks.Lock; -import org.apache.jackrabbit.oak.commons.PathUtils; import org.apache.jackrabbit.oak.plugins.document.util.MapFactory; import org.apache.jackrabbit.oak.plugins.document.util.Utils; import org.jetbrains.annotations.NotNull; @@ -41,7 +40,6 @@ import com.google.common.collect.Lists; import com.google.common.collect.Maps; import static com.google.common.base.Preconditions.checkNotNull; -import static org.apache.jackrabbit.oak.commons.PathUtils.ROOT_PATH; import static org.apache.jackrabbit.oak.plugins.document.Collection.CLUSTER_NODES; import static org.apache.jackrabbit.oak.plugins.document.Collection.NODES; import static org.apache.jackrabbit.oak.plugins.document.Commit.createUpdateOp; @@ -59,7 +57,7 @@ class UnsavedModifications { */ static final int BACKGROUND_MULTI_UPDATE_LIMIT = 100; - private final ConcurrentMap<String, Revision> map = MapFactory.getInstance().create(); + private final ConcurrentMap<Path, Revision> map = MapFactory.getInstance().create(); /** * Puts a revision for the given path. The revision for the given path is @@ -72,7 +70,7 @@ class UnsavedModifications { * was none or the current revision is newer. */ @Nullable - public Revision put(@NotNull String path, @NotNull Revision revision) { + public Revision put(@NotNull Path path, @NotNull Revision revision) { checkNotNull(path); checkNotNull(revision); for (;;) { @@ -95,12 +93,12 @@ class UnsavedModifications { } @Nullable - public Revision get(String path) { + public Revision get(Path path) { return map.get(path); } @NotNull - public Collection<String> getPaths() { + public Collection<Path> getPaths() { return map.keySet(); } @@ -112,19 +110,19 @@ class UnsavedModifications { * @return matching paths with pending modifications. */ @NotNull - public Iterable<String> getPaths(@NotNull final Revision start) { + public Iterable<Path> getPaths(@NotNull final Revision start) { if (map.isEmpty()) { return Collections.emptyList(); } else { return Iterables.transform(Iterables.filter(map.entrySet(), - new Predicate<Map.Entry<String, Revision>>() { + new Predicate<Map.Entry<Path, Revision>>() { @Override - public boolean apply(Map.Entry<String, Revision> input) { + public boolean apply(Map.Entry<Path, Revision> input) { return start.compareRevisionTime(input.getValue()) < 1; } - }), new Function<Map.Entry<String, Revision>, String>() { + }), new Function<Map.Entry<Path, Revision>, Path>() { @Override - public String apply(Map.Entry<String, Revision> input) { + public Path apply(Map.Entry<Path, Revision> input) { return input.getKey(); } }); @@ -163,7 +161,7 @@ class UnsavedModifications { stats.lock = sw.elapsed(TimeUnit.MILLISECONDS); sw.reset().start(); Revision sweepRev; - Map<String, Revision> pending; + Map<Path, Revision> pending; try { snapshot.acquiring(getMostRecentRevision()); pending = Maps.newTreeMap(PathComparator.INSTANCE); @@ -174,23 +172,23 @@ class UnsavedModifications { } stats.num = pending.size(); List<UpdateOp> updates = Lists.newArrayList(); - Map<String, Revision> pathToRevision = Maps.newHashMap(); - for (Iterable<Map.Entry<String, Revision>> batch : Iterables.partition( + Map<Path, Revision> pathToRevision = Maps.newHashMap(); + for (Iterable<Map.Entry<Path, Revision>> batch : Iterables.partition( pending.entrySet(), BACKGROUND_MULTI_UPDATE_LIMIT)) { - for (Map.Entry<String, Revision> entry : batch) { - String p = entry.getKey(); + for (Map.Entry<Path, Revision> entry : batch) { + Path p = entry.getKey(); Revision r = entry.getValue(); - if (PathUtils.denotesRoot(entry.getKey())) { + if (p.isRoot()) { // update root individually at the end continue; } updates.add(newUpdateOp(p, r)); - pathToRevision.put(p, r); + pathToRevision.put(entry.getKey(), r); } if (!updates.isEmpty()) { store.createOrUpdate(NODES, updates); stats.calls++; - for (Map.Entry<String, Revision> entry : pathToRevision.entrySet()) { + for (Map.Entry<Path, Revision> entry : pathToRevision.entrySet()) { map.remove(entry.getKey(), entry.getValue()); LOG.debug("Updated _lastRev to {} on {}", entry.getValue(), entry.getKey()); } @@ -200,9 +198,9 @@ class UnsavedModifications { } } // finally update remaining root document - Revision rootRev = pending.get(ROOT_PATH); + Revision rootRev = pending.get(Path.ROOT); if (rootRev != null) { - UpdateOp rootUpdate = newUpdateOp(ROOT_PATH, rootRev); + UpdateOp rootUpdate = newUpdateOp(Path.ROOT, rootRev); // also update to most recent sweep revision if (sweepRev != null) { NodeDocument.setSweepRevision(rootUpdate, sweepRev); @@ -210,8 +208,8 @@ class UnsavedModifications { } store.findAndUpdate(NODES, rootUpdate); stats.calls++; - map.remove(ROOT_PATH, rootRev); - LOG.debug("Updated _lastRev to {} on {}", rootRev, ROOT_PATH); + map.remove(Path.ROOT, rootRev); + LOG.debug("Updated _lastRev to {} on {}", rootRev, Path.ROOT); int cid = rootRev.getClusterId(); UpdateOp update = new UpdateOp(String.valueOf(cid), false); @@ -228,7 +226,7 @@ class UnsavedModifications { return map.toString(); } - private static UpdateOp newUpdateOp(String path, Revision r) { + private static UpdateOp newUpdateOp(Path path, Revision r) { UpdateOp updateOp = createUpdateOp(path, r, false); NodeDocument.setLastRev(updateOp, r); return updateOp; @@ -236,7 +234,7 @@ class UnsavedModifications { private Revision getMostRecentRevision() { // use revision of root document - Revision rev = map.get(ROOT_PATH); + Revision rev = map.get(Path.ROOT); // otherwise find most recent if (rev == null) { for (Revision r : map.values()) { Modified: jackrabbit/oak/trunk/oak-store-document/src/main/java/org/apache/jackrabbit/oak/plugins/document/VersionGarbageCollector.java URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-store-document/src/main/java/org/apache/jackrabbit/oak/plugins/document/VersionGarbageCollector.java?rev=1857240&r1=1857239&r2=1857240&view=diff ============================================================================== --- jackrabbit/oak/trunk/oak-store-document/src/main/java/org/apache/jackrabbit/oak/plugins/document/VersionGarbageCollector.java (original) +++ jackrabbit/oak/trunk/oak-store-document/src/main/java/org/apache/jackrabbit/oak/plugins/document/VersionGarbageCollector.java Wed Apr 10 11:13:19 2019 @@ -764,7 +764,7 @@ public class VersionGarbageCollector { // all previous document ids can be constructed from the // previous ranges map. this works for first level previous // documents only. - final String path = doc.getPath(); + final Path path = doc.getPath(); return Iterators.transform(prevRanges.entrySet().iterator(), new Function<Map.Entry<Revision, Range>, String>() { @Override Modified: jackrabbit/oak/trunk/oak-store-document/src/main/java/org/apache/jackrabbit/oak/plugins/document/bundlor/BundledDocumentDiffer.java URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-store-document/src/main/java/org/apache/jackrabbit/oak/plugins/document/bundlor/BundledDocumentDiffer.java?rev=1857240&r1=1857239&r2=1857240&view=diff ============================================================================== --- jackrabbit/oak/trunk/oak-store-document/src/main/java/org/apache/jackrabbit/oak/plugins/document/bundlor/BundledDocumentDiffer.java (original) +++ jackrabbit/oak/trunk/oak-store-document/src/main/java/org/apache/jackrabbit/oak/plugins/document/bundlor/BundledDocumentDiffer.java Wed Apr 10 11:13:19 2019 @@ -26,6 +26,7 @@ import org.apache.jackrabbit.oak.commons import org.apache.jackrabbit.oak.plugins.document.AbstractDocumentNodeState; import org.apache.jackrabbit.oak.plugins.document.DocumentNodeState; import org.apache.jackrabbit.oak.plugins.document.DocumentNodeStore; +import org.apache.jackrabbit.oak.plugins.document.Path; import org.apache.jackrabbit.oak.spi.state.NodeStateUtils; import static com.google.common.base.Preconditions.checkNotNull; @@ -103,7 +104,7 @@ public class BundledDocumentDiffer { //and from there traverse down to the actual child node checkState(BundlorUtils.isBundledChild(state)); String bundlingPath = state.getString(DocumentBundlor.META_PROP_BUNDLING_PATH); - String bundlingRootPath = PathUtils.getAncestorPath(state.getPath(), PathUtils.getDepth(bundlingPath)); + Path bundlingRootPath = state.getPath().getAncestor(PathUtils.getDepth(bundlingPath)); DocumentNodeState bundlingRoot = nodeStore.getNode(bundlingRootPath, state.getLastRevision()); result = (DocumentNodeState) NodeStateUtils.getNode(bundlingRoot, bundlingPath); } else { Modified: jackrabbit/oak/trunk/oak-store-document/src/main/java/org/apache/jackrabbit/oak/plugins/document/bundlor/BundlingHandler.java URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-store-document/src/main/java/org/apache/jackrabbit/oak/plugins/document/bundlor/BundlingHandler.java?rev=1857240&r1=1857239&r2=1857240&view=diff ============================================================================== --- jackrabbit/oak/trunk/oak-store-document/src/main/java/org/apache/jackrabbit/oak/plugins/document/bundlor/BundlingHandler.java (original) +++ jackrabbit/oak/trunk/oak-store-document/src/main/java/org/apache/jackrabbit/oak/plugins/document/bundlor/BundlingHandler.java Wed Apr 10 11:13:19 2019 @@ -24,25 +24,25 @@ import java.util.Set; import com.google.common.collect.Sets; import org.apache.jackrabbit.oak.api.PropertyState; import org.apache.jackrabbit.oak.commons.PathUtils; +import org.apache.jackrabbit.oak.plugins.document.Path; import org.apache.jackrabbit.oak.spi.state.NodeState; import static com.google.common.base.Preconditions.checkNotNull; -import static org.apache.jackrabbit.oak.commons.PathUtils.ROOT_PATH; import static org.apache.jackrabbit.oak.plugins.memory.EmptyNodeState.EMPTY_NODE; import static org.apache.jackrabbit.oak.plugins.memory.PropertyStates.createProperty; public class BundlingHandler { private final BundledTypesRegistry registry; - private final String path; + private final Path path; private final BundlingContext ctx; private final NodeState nodeState; public BundlingHandler(BundledTypesRegistry registry) { - this(checkNotNull(registry), BundlingContext.NULL, ROOT_PATH, EMPTY_NODE); + this(checkNotNull(registry), BundlingContext.NULL, Path.ROOT, EMPTY_NODE); } - private BundlingHandler(BundledTypesRegistry registry, BundlingContext ctx, String path, NodeState nodeState) { + private BundlingHandler(BundledTypesRegistry registry, BundlingContext ctx, Path path, NodeState nodeState) { this.registry = registry; this.path = path; this.ctx = ctx; @@ -67,7 +67,7 @@ public class BundlingHandler { /** * Returns absolute path of the current node */ - public String getNodeFullPath() { + public Path getNodeFullPath() { return path; } @@ -86,12 +86,12 @@ public class BundlingHandler { return ctx.removedProps; } - public String getRootBundlePath() { + public Path getRootBundlePath() { return ctx.isBundling() ? ctx.bundlingPath : path; } public BundlingHandler childAdded(String name, NodeState state){ - String childPath = childPath(name); + Path childPath = childPath(name); BundlingContext childContext; Matcher childMatcher = ctx.matcher.next(name); if (childMatcher.isMatch()) { @@ -111,7 +111,7 @@ public class BundlingHandler { } public BundlingHandler childDeleted(String name, NodeState state){ - String childPath = childPath(name); + Path childPath = childPath(name); BundlingContext childContext; Matcher childMatcher = ctx.matcher.next(name); if (childMatcher.isMatch()) { @@ -127,7 +127,7 @@ public class BundlingHandler { } public BundlingHandler childChanged(String name, NodeState before, NodeState after){ - String childPath = childPath(name); + Path childPath = childPath(name); BundlingContext childContext; Matcher childMatcher = ctx.matcher.next(name); if (childMatcher.isMatch()) { @@ -151,22 +151,22 @@ public class BundlingHandler { @Override public String toString() { - String result = path; + String result = path.toString(); if (isBundledNode()){ result = path + "( Bundling root - " + getRootBundlePath() + ")"; } return result; } - private String childPath(String name){ - return PathUtils.concat(path, name); + private Path childPath(String name){ + return new Path(path, name); } private BundlingContext createChildContext(Matcher childMatcher) { return ctx.child(childMatcher); } - private static BundlingContext getBundlorContext(String path, NodeState state) { + private static BundlingContext getBundlorContext(Path path, NodeState state) { BundlingContext result = BundlingContext.NULL; PropertyState bundlorConfig = state.getProperty(DocumentBundlor.META_PROP_PATTERN); if (bundlorConfig != null){ @@ -199,13 +199,13 @@ public class BundlingHandler { } private static class BundlingContext { - static final BundlingContext NULL = new BundlingContext("", Matcher.NON_MATCHING); - final String bundlingPath; + static final BundlingContext NULL = new BundlingContext(Path.ROOT, Matcher.NON_MATCHING); + final Path bundlingPath; final Matcher matcher; final Set<PropertyState> metaProps = Sets.newHashSet(); final Set<String> removedProps = Sets.newHashSet(); - public BundlingContext(String bundlingPath, Matcher matcher) { + public BundlingContext(Path bundlingPath, Matcher matcher) { this.bundlingPath = bundlingPath; this.matcher = matcher; } Modified: jackrabbit/oak/trunk/oak-store-document/src/main/java/org/apache/jackrabbit/oak/plugins/document/locks/StripedNodeDocumentLocks.java URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-store-document/src/main/java/org/apache/jackrabbit/oak/plugins/document/locks/StripedNodeDocumentLocks.java?rev=1857240&r1=1857239&r2=1857240&view=diff ============================================================================== --- jackrabbit/oak/trunk/oak-store-document/src/main/java/org/apache/jackrabbit/oak/plugins/document/locks/StripedNodeDocumentLocks.java (original) +++ jackrabbit/oak/trunk/oak-store-document/src/main/java/org/apache/jackrabbit/oak/plugins/document/locks/StripedNodeDocumentLocks.java Wed Apr 10 11:13:19 2019 @@ -18,13 +18,14 @@ package org.apache.jackrabbit.oak.plugin import java.util.concurrent.locks.Lock; +import org.apache.jackrabbit.oak.plugins.document.Path; import org.apache.jackrabbit.oak.plugins.document.util.Utils; import com.google.common.util.concurrent.Striped; public class StripedNodeDocumentLocks implements NodeDocumentLocks { - private static final String ROOT = Utils.getIdFromPath("/"); + private static final String ROOT = Utils.getIdFromPath(Path.ROOT); /** * Locks to ensure cache consistency on reads, writes and invalidation. Modified: jackrabbit/oak/trunk/oak-store-document/src/main/java/org/apache/jackrabbit/oak/plugins/document/mongo/MongoVersionGCSupport.java URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-store-document/src/main/java/org/apache/jackrabbit/oak/plugins/document/mongo/MongoVersionGCSupport.java?rev=1857240&r1=1857239&r2=1857240&view=diff ============================================================================== --- jackrabbit/oak/trunk/oak-store-document/src/main/java/org/apache/jackrabbit/oak/plugins/document/mongo/MongoVersionGCSupport.java (original) +++ jackrabbit/oak/trunk/oak-store-document/src/main/java/org/apache/jackrabbit/oak/plugins/document/mongo/MongoVersionGCSupport.java Wed Apr 10 11:13:19 2019 @@ -38,6 +38,7 @@ import com.mongodb.client.model.Filters; import org.apache.jackrabbit.oak.plugins.document.Document; import org.apache.jackrabbit.oak.plugins.document.NodeDocument; +import org.apache.jackrabbit.oak.plugins.document.Path; import org.apache.jackrabbit.oak.plugins.document.Revision; import org.apache.jackrabbit.oak.plugins.document.RevisionVector; import org.apache.jackrabbit.oak.plugins.document.SplitDocumentCleanUp; @@ -189,7 +190,7 @@ public class MongoVersionGCSupport exten // only remove those older than sweep rev List<Bson> queries = Lists.newArrayList(); for (Revision r : sweepRevs) { - String idSuffix = Utils.getPreviousIdFor("/", r, 0); + String idSuffix = Utils.getPreviousIdFor(Path.ROOT, r, 0); idSuffix = idSuffix.substring(idSuffix.lastIndexOf('-')); // id/path constraint for previous documents Modified: jackrabbit/oak/trunk/oak-store-document/src/main/java/org/apache/jackrabbit/oak/plugins/document/persistentCache/CacheType.java URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-store-document/src/main/java/org/apache/jackrabbit/oak/plugins/document/persistentCache/CacheType.java?rev=1857240&r1=1857239&r2=1857240&view=diff ============================================================================== --- jackrabbit/oak/trunk/oak-store-document/src/main/java/org/apache/jackrabbit/oak/plugins/document/persistentCache/CacheType.java (original) +++ jackrabbit/oak/trunk/oak-store-document/src/main/java/org/apache/jackrabbit/oak/plugins/document/persistentCache/CacheType.java Wed Apr 10 11:13:19 2019 @@ -16,44 +16,60 @@ */ package org.apache.jackrabbit.oak.plugins.document.persistentCache; +import java.nio.ByteBuffer; + import org.apache.jackrabbit.oak.plugins.document.LocalDiffCache; import org.apache.jackrabbit.oak.plugins.document.DocumentNodeState; import org.apache.jackrabbit.oak.plugins.document.DocumentNodeStore; import org.apache.jackrabbit.oak.plugins.document.DocumentStore; +import org.apache.jackrabbit.oak.plugins.document.MemoryDiffCache; +import org.apache.jackrabbit.oak.plugins.document.NamePathRev; import org.apache.jackrabbit.oak.plugins.document.NodeDocument; +import org.apache.jackrabbit.oak.plugins.document.Path; import org.apache.jackrabbit.oak.plugins.document.PathRev; +import org.apache.jackrabbit.oak.plugins.document.RevisionVector; import org.apache.jackrabbit.oak.plugins.document.util.RevisionsKey; import org.apache.jackrabbit.oak.plugins.document.util.StringValue; +import org.h2.mvstore.WriteBuffer; +import org.h2.mvstore.type.StringDataType; public enum CacheType { NODE { + @Override - public <K> String keyToString(K key) { - return ((PathRev) key).asString(); + public <K> void writeKey(WriteBuffer buffer, K key) { + PathRev pr = (PathRev) key; + DataTypeUtil.pathRevToBuffer(pr, buffer); } + @SuppressWarnings("unchecked") @Override - public <K> K keyFromString(String key) { - return (K) PathRev.fromString(key); + public <K> K readKey(ByteBuffer buffer) { + return (K) DataTypeUtil.pathRevFromBuffer(buffer); } + @Override public <K> int compareKeys(K a, K b) { return ((PathRev) a).compareTo((PathRev) b); } + @Override - public <V> String valueToString(V value) { - return ((DocumentNodeState) value).asString(); + public <V> void writeValue(WriteBuffer buffer, V value) { + DataTypeUtil.stateToBuffer((DocumentNodeState) value, buffer); } + @SuppressWarnings("unchecked") @Override - public <V> V valueFromString( - DocumentNodeStore store, DocumentStore docStore, String value) { - return (V) DocumentNodeState.fromString(store, value); + public <V> V readValue(DocumentNodeStore store, + DocumentStore docStore, + ByteBuffer buffer) { + return (V) DataTypeUtil.stateFromBuffer(store, buffer); } + @Override public <K> boolean shouldCache(DocumentNodeStore store, K key) { - String path = ((PathRev) key).getPath(); + Path path = ((PathRev) key).getPath(); if (!store.getNodeCachePredicate().apply(path)){ return false; } @@ -62,33 +78,40 @@ public enum CacheType { }, CHILDREN { + @Override - public <K> String keyToString(K key) { - return ((PathRev) key).asString(); + public <K> void writeKey(WriteBuffer buffer, K key) { + DataTypeUtil.namePathRevToBuffer((NamePathRev) key, buffer); } + @SuppressWarnings("unchecked") @Override - public <K> K keyFromString(String key) { - return (K) PathRev.fromString(key); + public <K> K readKey(ByteBuffer buffer) { + return (K) DataTypeUtil.namePathRevFromBuffer(buffer); } + @Override public <K> int compareKeys(K a, K b) { - return ((PathRev) a).compareTo((PathRev) b); + return ((NamePathRev) a).compareTo((NamePathRev) b); } + @Override - public <V> String valueToString(V value) { - return ((DocumentNodeState.Children) value).asString(); + public <V> void writeValue(WriteBuffer buffer, V value) { + String s = ((DocumentNodeState.Children) value).asString(); + StringDataType.INSTANCE.write(buffer, s); } + @SuppressWarnings("unchecked") @Override - public <V> V valueFromString( - DocumentNodeStore store, DocumentStore docStore, String value) { - return (V) DocumentNodeState.Children.fromString(value); + public <V> V readValue(DocumentNodeStore store, + DocumentStore docStore, + ByteBuffer buffer) { + return (V) DocumentNodeState.Children.fromString(readString(buffer)); } @Override public <K> boolean shouldCache(DocumentNodeStore store, K key) { - String path = ((PathRev) key).getPath(); + Path path = ((NamePathRev) key).getPath(); if (!store.getNodeCachePredicate().apply(path)){ return false; } @@ -97,29 +120,44 @@ public enum CacheType { }, DIFF { + @Override - public <K> String keyToString(K key) { - return ((PathRev) key).asString(); + public <K> void writeKey(WriteBuffer buffer, K key) { + MemoryDiffCache.Key k = ((MemoryDiffCache.Key) key); + DataTypeUtil.pathToBuffer(k.getPath(), buffer); + DataTypeUtil.revisionVectorToBuffer(k.getFromRevision(), buffer); + DataTypeUtil.revisionVectorToBuffer(k.getToRevision(), buffer); } + @SuppressWarnings("unchecked") @Override - public <K> K keyFromString(String key) { - return (K) PathRev.fromString(key); + public <K> K readKey(ByteBuffer buffer) { + Path p = DataTypeUtil.pathFromBuffer(buffer); + RevisionVector from = DataTypeUtil.revisionVectorFromBuffer(buffer); + RevisionVector to = DataTypeUtil.revisionVectorFromBuffer(buffer); + return (K) new MemoryDiffCache.Key(p, from, to); } + + @Override public <K> int compareKeys(K a, K b) { - return ((PathRev) a).compareTo((PathRev) b); - } + return ((MemoryDiffCache.Key) a).compareTo((MemoryDiffCache.Key) b); + } + @Override - public <V> String valueToString(V value) { - return ((StringValue) value).asString(); + public <V> void writeValue(WriteBuffer buffer, V value) { + String s = ((StringValue) value).asString(); + StringDataType.INSTANCE.write(buffer, s); } + @SuppressWarnings("unchecked") @Override - public <V> V valueFromString( - DocumentNodeStore store, DocumentStore docStore, String value) { - return (V) StringValue.fromString(value); + public <V> V readValue(DocumentNodeStore store, + DocumentStore docStore, + ByteBuffer buffer) { + return (V) StringValue.fromString(readString(buffer)); } + @Override public <K> boolean shouldCache(DocumentNodeStore store, K key) { return true; @@ -127,27 +165,34 @@ public enum CacheType { }, DOCUMENT { + @Override - public <K> String keyToString(K key) { + public <K> void writeKey(WriteBuffer buffer, K key) { throw new UnsupportedOperationException(); } + @Override - public <K> K keyFromString(String key) { + public <K> K readKey(ByteBuffer buffer) { throw new UnsupportedOperationException(); } + @Override public <K> int compareKeys(K a, K b) { throw new UnsupportedOperationException(); - } + } + @Override - public <V> String valueToString(V value) { + public <V> void writeValue(WriteBuffer buffer, V value) { throw new UnsupportedOperationException(); } + @Override - public <V> V valueFromString( - DocumentNodeStore store, DocumentStore docStore, String value) { + public <V> V readValue(DocumentNodeStore store, + DocumentStore docStore, + ByteBuffer buffer) { throw new UnsupportedOperationException(); } + @Override public <K> boolean shouldCache(DocumentNodeStore store, K key) { return false; @@ -155,29 +200,38 @@ public enum CacheType { }, PREV_DOCUMENT { + @Override - public <K> String keyToString(K key) { - return ((StringValue) key).asString(); + public <K> void writeKey(WriteBuffer buffer, K key) { + String s = ((StringValue) key).asString(); + StringDataType.INSTANCE.write(buffer, s); } + @SuppressWarnings("unchecked") @Override - public <K> K keyFromString(String key) { - return (K) StringValue.fromString(key); + public <K> K readKey(ByteBuffer buffer) { + return (K) StringValue.fromString(readString(buffer)); } + @Override public <K> int compareKeys(K a, K b) { return ((StringValue) a).asString().compareTo(((StringValue) b).asString()); } + @Override - public <V> String valueToString(V value) { - return ((NodeDocument) value).asString(); + public <V> void writeValue(WriteBuffer buffer, V value) { + String s = ((NodeDocument) value).asString(); + StringDataType.INSTANCE.write(buffer, s); } + @SuppressWarnings("unchecked") @Override - public <V> V valueFromString( - DocumentNodeStore store, DocumentStore docStore, String value) { - return (V) NodeDocument.fromString(docStore, value); + public <V> V readValue(DocumentNodeStore store, + DocumentStore docStore, + ByteBuffer buffer) { + return (V) NodeDocument.fromString(docStore, readString(buffer)); } + @Override public <K> boolean shouldCache(DocumentNodeStore store, K key) { return true; @@ -185,29 +239,41 @@ public enum CacheType { }, LOCAL_DIFF { + @Override - public <K> String keyToString(K key) { - return ((RevisionsKey) key).asString(); + public <K> void writeKey(WriteBuffer buffer, K key) { + RevisionsKey revisionsKey = ((RevisionsKey) key); + DataTypeUtil.revisionVectorToBuffer(revisionsKey.getRev1(), buffer); + DataTypeUtil.revisionVectorToBuffer(revisionsKey.getRev2(), buffer); } + @SuppressWarnings("unchecked") @Override - public <K> K keyFromString(String key) { - return (K) RevisionsKey.fromString(key); + public <K> K readKey(ByteBuffer buffer) { + RevisionVector rv1 = DataTypeUtil.revisionVectorFromBuffer(buffer); + RevisionVector rv2 = DataTypeUtil.revisionVectorFromBuffer(buffer); + return (K) new RevisionsKey(rv1, rv2); } + @Override public <K> int compareKeys(K a, K b) { return ((RevisionsKey) a).compareTo((RevisionsKey) b); } + @Override - public <V> String valueToString(V value) { - return ((LocalDiffCache.Diff) value).asString(); + public <V> void writeValue(WriteBuffer buffer, V value) { + String s = ((LocalDiffCache.Diff) value).asString(); + StringDataType.INSTANCE.write(buffer, s); } + @SuppressWarnings("unchecked") @Override - public <V> V valueFromString( - DocumentNodeStore store, DocumentStore docStore, String value) { - return (V) LocalDiffCache.Diff.fromString(value); + public <V> V readValue(DocumentNodeStore store, + DocumentStore docStore, + ByteBuffer buffer) { + return (V) LocalDiffCache.Diff.fromString(readString(buffer)); } + @Override public <K> boolean shouldCache(DocumentNodeStore store, K key) { return true; @@ -216,13 +282,22 @@ public enum CacheType { public static final CacheType[] VALUES = CacheType.values(); - public abstract <K> String keyToString(K key); - public abstract <K> K keyFromString(String key); + public String getMapName() { + // add a version suffix to the name and increment the version + // whenever the serialization for a key or value changes + return name() + "-v1"; + } + + public abstract <K> void writeKey(WriteBuffer buffer, K key); + public abstract <K> K readKey(ByteBuffer buffer); public abstract <K> int compareKeys(K a, K b); - public abstract <V> String valueToString(V value); - public abstract <V> V valueFromString( - DocumentNodeStore store, DocumentStore docStore, String value); + public abstract <V> void writeValue(WriteBuffer buffer, V value); + public abstract <V> V readValue( + DocumentNodeStore store, DocumentStore docStore, ByteBuffer buffer); public abstract <K> boolean shouldCache(DocumentNodeStore store, K key); + private static String readString(ByteBuffer buffer) { + return StringDataType.INSTANCE.read(buffer); + } } Added: jackrabbit/oak/trunk/oak-store-document/src/main/java/org/apache/jackrabbit/oak/plugins/document/persistentCache/DataTypeUtil.java URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-store-document/src/main/java/org/apache/jackrabbit/oak/plugins/document/persistentCache/DataTypeUtil.java?rev=1857240&view=auto ============================================================================== --- jackrabbit/oak/trunk/oak-store-document/src/main/java/org/apache/jackrabbit/oak/plugins/document/persistentCache/DataTypeUtil.java (added) +++ jackrabbit/oak/trunk/oak-store-document/src/main/java/org/apache/jackrabbit/oak/plugins/document/persistentCache/DataTypeUtil.java Wed Apr 10 11:13:19 2019 @@ -0,0 +1,169 @@ +/* + * 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.plugins.document.persistentCache; + +import java.nio.ByteBuffer; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import org.apache.jackrabbit.oak.api.PropertyState; +import org.apache.jackrabbit.oak.plugins.document.DocumentNodeState; +import org.apache.jackrabbit.oak.plugins.document.DocumentNodeStore; +import org.apache.jackrabbit.oak.plugins.document.NamePathRev; +import org.apache.jackrabbit.oak.plugins.document.Path; +import org.apache.jackrabbit.oak.plugins.document.PathRev; +import org.apache.jackrabbit.oak.plugins.document.Revision; +import org.apache.jackrabbit.oak.plugins.document.RevisionVector; +import org.h2.mvstore.DataUtils; +import org.h2.mvstore.WriteBuffer; +import org.h2.mvstore.type.StringDataType; + +/** + * Utility class to write various types to a buffer and read it back again. + */ +class DataTypeUtil { + + static void booleanToBuffer(boolean b, WriteBuffer buffer) { + buffer.put((byte) (b ? 1 : 0)); + } + + static boolean booleanFromBuffer(ByteBuffer buffer) { + return buffer.get() != 0; + } + + static void revisionVectorToBuffer(RevisionVector rv, WriteBuffer buffer) { + buffer.putVarInt(rv.getDimensions()); + for (Revision r : rv) { + buffer.putLong(r.getTimestamp()); + buffer.putVarInt(r.getCounter()); + buffer.putVarInt(r.getClusterId()); + booleanToBuffer(r.isBranch(), buffer); + } + } + + static RevisionVector revisionVectorFromBuffer(ByteBuffer buffer) { + int dim = DataUtils.readVarInt(buffer); + List<Revision> revisions = new ArrayList<>(); + for (int i = 0; i < dim; i++) { + revisions.add(new Revision( + buffer.getLong(), + DataUtils.readVarInt(buffer), + DataUtils.readVarInt(buffer), + booleanFromBuffer(buffer)) + ); + } + return new RevisionVector(revisions); + } + + static void pathToBuffer(Path p, WriteBuffer buffer) { + int len = p.getDepth() + (p.isAbsolute() ? 1 : 0); + buffer.putVarInt(len); + // write path elements backwards + while (p != null) { + StringDataType.INSTANCE.write(buffer, p.getName()); + p = p.getParent(); + } + } + + static Path pathFromBuffer(ByteBuffer buffer) { + int numElements = DataUtils.readVarInt(buffer); + List<String> elements = new ArrayList<>(numElements); + for (int i = 0; i < numElements; i++) { + elements.add(StringDataType.INSTANCE.read(buffer)); + } + // elements are written backwards + String firstElement = elements.get(elements.size() - 1); + Path p; + if (firstElement.isEmpty()) { + p = Path.ROOT; + } else { + p = new Path(firstElement); + } + // construct path with remaining elements + for (int i = elements.size() - 2; i >= 0; i--) { + p = new Path(p, elements.get(i)); + } + return p; + } + + static void pathRevToBuffer(PathRev pr, WriteBuffer buffer) { + pathToBuffer(pr.getPath(), buffer); + revisionVectorToBuffer(pr.getRevision(), buffer); + } + + static PathRev pathRevFromBuffer(ByteBuffer buffer) { + return new PathRev( + pathFromBuffer(buffer), + revisionVectorFromBuffer(buffer) + ); + } + + static void namePathRevToBuffer(NamePathRev pnr, WriteBuffer buffer) { + StringDataType.INSTANCE.write(buffer, pnr.getName()); + pathToBuffer(pnr.getPath(), buffer); + revisionVectorToBuffer(pnr.getRevision(), buffer); + } + + static NamePathRev namePathRevFromBuffer(ByteBuffer buffer) { + return new NamePathRev( + StringDataType.INSTANCE.read(buffer), + pathFromBuffer(buffer), + revisionVectorFromBuffer(buffer) + ); + } + + static void stateToBuffer(DocumentNodeState state, WriteBuffer buffer) { + pathToBuffer(state.getPath(), buffer); + revisionVectorToBuffer(state.getRootRevision(), buffer); + RevisionVector lastRevision = state.getLastRevision(); + if (lastRevision == null) { + lastRevision = RevisionVector.fromString(""); + } + revisionVectorToBuffer(lastRevision, buffer); + buffer.putVarInt(state.getMemory()); + booleanToBuffer(state.hasNoChildren(), buffer); + Map<String, String> props = state.getAllBundledProperties(); + buffer.putVarInt(props.size()); + for (Map.Entry<String, String> e : props.entrySet()) { + StringDataType.INSTANCE.write(buffer, e.getKey()); + StringDataType.INSTANCE.write(buffer, e.getValue()); + } + } + + static DocumentNodeState stateFromBuffer(DocumentNodeStore store, + ByteBuffer buffer) { + Path p = pathFromBuffer(buffer); + RevisionVector rootRevision = revisionVectorFromBuffer(buffer); + RevisionVector lastRevision = revisionVectorFromBuffer(buffer); + if (lastRevision.getDimensions() == 0) { + lastRevision = null; + } + int mem = DataUtils.readVarInt(buffer); + boolean noChildren = booleanFromBuffer(buffer); + int numProps = DataUtils.readVarInt(buffer); + Map<String, PropertyState> props = new HashMap<>(numProps); + for (int i = 0; i < numProps; i++) { + String name = StringDataType.INSTANCE.read(buffer); + String value = StringDataType.INSTANCE.read(buffer); + props.put(name, store.createPropertyState(name, value)); + } + return new DocumentNodeState(store, p, rootRevision, props, + !noChildren, mem, lastRevision, false); + } +} Propchange: jackrabbit/oak/trunk/oak-store-document/src/main/java/org/apache/jackrabbit/oak/plugins/document/persistentCache/DataTypeUtil.java ------------------------------------------------------------------------------ svn:eol-style = native Modified: jackrabbit/oak/trunk/oak-store-document/src/main/java/org/apache/jackrabbit/oak/plugins/document/persistentCache/KeyDataType.java URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-store-document/src/main/java/org/apache/jackrabbit/oak/plugins/document/persistentCache/KeyDataType.java?rev=1857240&r1=1857239&r2=1857240&view=diff ============================================================================== --- jackrabbit/oak/trunk/oak-store-document/src/main/java/org/apache/jackrabbit/oak/plugins/document/persistentCache/KeyDataType.java (original) +++ jackrabbit/oak/trunk/oak-store-document/src/main/java/org/apache/jackrabbit/oak/plugins/document/persistentCache/KeyDataType.java Wed Apr 10 11:13:19 2019 @@ -21,7 +21,6 @@ import java.nio.ByteBuffer; import org.apache.jackrabbit.oak.cache.CacheValue; import org.h2.mvstore.WriteBuffer; import org.h2.mvstore.type.DataType; -import org.h2.mvstore.type.StringDataType; public class KeyDataType implements DataType { @@ -43,14 +42,12 @@ public class KeyDataType implements Data @Override public void write(WriteBuffer buff, Object obj) { - String s = type.keyToString(obj); - StringDataType.INSTANCE.write(buff, s); + type.writeKey(buff, obj); } @Override public Object read(ByteBuffer buff) { - String s = StringDataType.INSTANCE.read(buff); - return type.keyFromString(s); + return type.readKey(buff); } @Override Modified: jackrabbit/oak/trunk/oak-store-document/src/main/java/org/apache/jackrabbit/oak/plugins/document/persistentCache/NodeCache.java URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-store-document/src/main/java/org/apache/jackrabbit/oak/plugins/document/persistentCache/NodeCache.java?rev=1857240&r1=1857239&r2=1857240&view=diff ============================================================================== --- jackrabbit/oak/trunk/oak-store-document/src/main/java/org/apache/jackrabbit/oak/plugins/document/persistentCache/NodeCache.java (original) +++ jackrabbit/oak/trunk/oak-store-document/src/main/java/org/apache/jackrabbit/oak/plugins/document/persistentCache/NodeCache.java Wed Apr 10 11:13:19 2019 @@ -112,8 +112,7 @@ class NodeCache<K extends CacheValue, V public void addGeneration(int generation, boolean readOnly) { MVMap.Builder<K, V> b = new MVMap.Builder<K, V>(). keyType(keyType).valueType(valueType); - String mapName = type.name(); - CacheMap<K, V> m = cache.openMap(generation, mapName, b); + CacheMap<K, V> m = cache.openMap(generation, type.getMapName(), b); map.addReadMap(generation, m); if (!readOnly) { map.setWriteMap(m); Modified: jackrabbit/oak/trunk/oak-store-document/src/main/java/org/apache/jackrabbit/oak/plugins/document/persistentCache/ValueDataType.java URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-store-document/src/main/java/org/apache/jackrabbit/oak/plugins/document/persistentCache/ValueDataType.java?rev=1857240&r1=1857239&r2=1857240&view=diff ============================================================================== --- jackrabbit/oak/trunk/oak-store-document/src/main/java/org/apache/jackrabbit/oak/plugins/document/persistentCache/ValueDataType.java (original) +++ jackrabbit/oak/trunk/oak-store-document/src/main/java/org/apache/jackrabbit/oak/plugins/document/persistentCache/ValueDataType.java Wed Apr 10 11:13:19 2019 @@ -23,7 +23,9 @@ import org.apache.jackrabbit.oak.plugins import org.apache.jackrabbit.oak.plugins.document.DocumentStore; import org.h2.mvstore.WriteBuffer; import org.h2.mvstore.type.DataType; -import org.h2.mvstore.type.StringDataType; +import org.jetbrains.annotations.NotNull; + +import static com.google.common.base.Preconditions.checkNotNull; public class ValueDataType implements DataType { @@ -31,9 +33,9 @@ public class ValueDataType implements Da private final DocumentStore docStore; private final CacheType type; - public ValueDataType( - DocumentNodeStore docNodeStore, - DocumentStore docStore, CacheType type) { + ValueDataType(DocumentNodeStore docNodeStore, + DocumentStore docStore, + CacheType type) { this.docNodeStore = docNodeStore; this.docStore = docStore; this.type = type; @@ -51,14 +53,12 @@ public class ValueDataType implements Da @Override public void write(WriteBuffer buff, Object obj) { - String s = type.valueToString(obj); - StringDataType.INSTANCE.write(buff, s); + type.writeValue(buff, obj); } @Override public Object read(ByteBuffer buff) { - String s = StringDataType.INSTANCE.read(buff); - return type.valueFromString(docNodeStore, docStore, s); + return type.readValue(docNodeStore, docStore, buff); } @Override Modified: jackrabbit/oak/trunk/oak-store-document/src/main/java/org/apache/jackrabbit/oak/plugins/document/secondary/DelegatingDocumentNodeState.java URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-store-document/src/main/java/org/apache/jackrabbit/oak/plugins/document/secondary/DelegatingDocumentNodeState.java?rev=1857240&r1=1857239&r2=1857240&view=diff ============================================================================== --- jackrabbit/oak/trunk/oak-store-document/src/main/java/org/apache/jackrabbit/oak/plugins/document/secondary/DelegatingDocumentNodeState.java (original) +++ jackrabbit/oak/trunk/oak-store-document/src/main/java/org/apache/jackrabbit/oak/plugins/document/secondary/DelegatingDocumentNodeState.java Wed Apr 10 11:13:19 2019 @@ -25,6 +25,7 @@ import com.google.common.collect.Iterabl import org.apache.jackrabbit.oak.api.PropertyState; import org.apache.jackrabbit.oak.plugins.document.AbstractDocumentNodeState; import org.apache.jackrabbit.oak.plugins.document.NodeStateDiffer; +import org.apache.jackrabbit.oak.plugins.document.Path; import org.apache.jackrabbit.oak.plugins.document.RevisionVector; import org.apache.jackrabbit.oak.plugins.memory.MemoryChildNodeEntry; import org.apache.jackrabbit.oak.plugins.memory.MemoryNodeBuilder; @@ -36,9 +37,6 @@ import org.jetbrains.annotations.Nullabl import static com.google.common.base.Preconditions.checkNotNull; import static com.google.common.base.Preconditions.checkState; -import static org.apache.jackrabbit.oak.commons.PathUtils.ROOT_PATH; -import static org.apache.jackrabbit.oak.commons.PathUtils.concat; -import static org.apache.jackrabbit.oak.commons.PathUtils.denotesRoot; /** * NodeState wrapper which wraps another NodeState (mostly SegmentNodeState) @@ -61,7 +59,7 @@ public class DelegatingDocumentNodeState private final NodeState delegate; private final RevisionVector rootRevision; private final boolean fromExternalChange; - private final String path; + private final Path path; private RevisionVector lastRevision; @@ -75,7 +73,7 @@ public class DelegatingDocumentNodeState public static NodeState wrapIfPossible(NodeState delegate, NodeStateDiffer differ) { if (hasMetaProps(delegate)) { String revVector = getRequiredProp(delegate, PROP_REVISION); - return new DelegatingDocumentNodeState(delegate, ROOT_PATH, RevisionVector.fromString(revVector), false, differ); + return new DelegatingDocumentNodeState(delegate, Path.ROOT, RevisionVector.fromString(revVector), false, differ); } return delegate; } @@ -86,10 +84,10 @@ public class DelegatingDocumentNodeState public static AbstractDocumentNodeState wrap(NodeState delegate, NodeStateDiffer differ) { String revVector = getRequiredProp(delegate, PROP_REVISION); - return new DelegatingDocumentNodeState(delegate, ROOT_PATH, RevisionVector.fromString(revVector), false, differ); + return new DelegatingDocumentNodeState(delegate, Path.ROOT, RevisionVector.fromString(revVector), false, differ); } - private DelegatingDocumentNodeState(NodeState delegate, String path, RevisionVector rootRevision, + private DelegatingDocumentNodeState(NodeState delegate, Path path, RevisionVector rootRevision, boolean fromExternalChange, NodeStateDiffer differ) { this.differ = differ; this.delegate = delegate; @@ -111,7 +109,7 @@ public class DelegatingDocumentNodeState //~----------------------------------< AbstractDocumentNodeState > @Override - public String getPath() { + public Path getPath() { return path; } @@ -192,7 +190,7 @@ public class DelegatingDocumentNodeState @NotNull @Override public NodeBuilder builder() { - checkState(!denotesRoot(getPath()), "Builder cannot be opened for root " + + checkState(!getPath().isRoot(), "Builder cannot be opened for root " + "path for state of type [%s]", delegate.getClass()); return new MemoryNodeBuilder(this); } @@ -261,7 +259,7 @@ public class DelegatingDocumentNodeState private NodeState decorate(String nodeName, NodeState childNode) { if (childNode.exists()) { - return new DelegatingDocumentNodeState(childNode, concat(path, nodeName), rootRevision, + return new DelegatingDocumentNodeState(childNode, new Path(path, nodeName), rootRevision, fromExternalChange, differ); } return childNode; Modified: jackrabbit/oak/trunk/oak-store-document/src/main/java/org/apache/jackrabbit/oak/plugins/document/secondary/PathFilteringDiff.java URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-store-document/src/main/java/org/apache/jackrabbit/oak/plugins/document/secondary/PathFilteringDiff.java?rev=1857240&r1=1857239&r2=1857240&view=diff ============================================================================== --- jackrabbit/oak/trunk/oak-store-document/src/main/java/org/apache/jackrabbit/oak/plugins/document/secondary/PathFilteringDiff.java (original) +++ jackrabbit/oak/trunk/oak-store-document/src/main/java/org/apache/jackrabbit/oak/plugins/document/secondary/PathFilteringDiff.java Wed Apr 10 11:13:19 2019 @@ -22,7 +22,6 @@ package org.apache.jackrabbit.oak.plugin import java.util.List; import org.apache.jackrabbit.oak.api.PropertyState; -import org.apache.jackrabbit.oak.commons.PathUtils; import org.apache.jackrabbit.oak.plugins.document.AbstractDocumentNodeState; import org.apache.jackrabbit.oak.plugins.document.RevisionVector; import org.apache.jackrabbit.oak.spi.filter.PathFilter; @@ -56,7 +55,7 @@ class PathFilteringDiff extends ApplyDif @Override public boolean childNodeAdded(String name, NodeState after) { AbstractDocumentNodeState afterDoc = asDocumentState(after, name); - String nextPath = afterDoc.getPath(); + String nextPath = afterDoc.getPath().toString(); PathFilter.Result result = ctx.pathFilter.filter(nextPath); if (result == PathFilter.Result.EXCLUDE){ return true; @@ -75,7 +74,7 @@ class PathFilteringDiff extends ApplyDif @Override public boolean childNodeChanged(String name, NodeState before, NodeState after) { AbstractDocumentNodeState afterDoc = asDocumentState(after, name); - String nextPath = afterDoc.getPath(); + String nextPath = afterDoc.getPath().toString(); if (ctx.pathFilter.filter(nextPath) != PathFilter.Result.EXCLUDE) { ctx.traversingNode(nextPath); NodeBuilder childBuilder = builder.getChildNode(name); @@ -88,7 +87,7 @@ class PathFilteringDiff extends ApplyDif @Override public boolean childNodeDeleted(String name, NodeState before) { - String path = asDocumentState(before, name).getPath(); + String path = asDocumentState(before, name).getPath().toString(); if (ctx.pathFilter.filter(path) != PathFilter.Result.EXCLUDE) { return super.childNodeDeleted(name, before); } @@ -104,7 +103,7 @@ class PathFilteringDiff extends ApplyDif static void copyMetaProperties(AbstractDocumentNodeState state, NodeBuilder builder, List<String> metaPropNames) { //Only set root revision on root node - if (PathUtils.denotesRoot(state.getPath())) { + if (state.getPath().isRoot()) { builder.setProperty(asPropertyState(PROP_REVISION, state.getRootRevision())); }
