Index: oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/property/OrderedIndex.java IDEA additional info: Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP <+>UTF-8 =================================================================== --- oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/property/OrderedIndex.java (date 1412352606000) +++ oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/property/OrderedIndex.java (revision ) @@ -124,25 +124,29 @@ * the default direction for sorting the index */ OrderDirection DEFAULT_DIRECTION = OrderDirection.ASC; - + + /** - * defines the default distribution of items across the skip list. It's with a factor of 10% + * Defines the distribution of items across the skip list. With a factor of 25% * having therefore - * + * *
*
lane 0:
100.0% (the base linked list)
- *
lane 1:
10.0%
- *
lane 2:
1.0%
- *
lane 3:
0.1%
+ *
lane 1:
25.0%
+ *
lane 2:
6.25%
+ *
lane 3:
1.56%
+ *
------
*
*/ double DEFAULT_PROBABILITY = 0.1; + double PROBABILITY = Double.valueOf( + System.getProperty("oak.ordered.skip.prob", String.valueOf(DEFAULT_PROBABILITY)).trim()); - + /** - * the number of lanes used in the SkipList + * the number of lanes used in the SkipList. The default is 32 */ - int LANES = 4; + int LANES = Integer.getInteger("oak.ordered.skip.lanes", 32); - + /** * Convenience Predicate that will force the implementor to expose what we're searching for * Index: oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/property/strategy/OrderedContentMirrorStoreStrategy.java IDEA additional info: Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP <+>UTF-8 =================================================================== --- oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/property/strategy/OrderedContentMirrorStoreStrategy.java (date 1412352606000) +++ oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/property/strategy/OrderedContentMirrorStoreStrategy.java (revision ) @@ -23,6 +23,7 @@ import java.io.UnsupportedEncodingException; import java.net.URLEncoder; +import java.util.Arrays; import java.util.Collections; import java.util.Deque; import java.util.Iterator; @@ -33,6 +34,7 @@ import javax.annotation.Nonnull; import javax.annotation.Nullable; +import com.google.common.collect.ImmutableList; import org.apache.jackrabbit.oak.api.PropertyState; import org.apache.jackrabbit.oak.api.Type; import org.apache.jackrabbit.oak.plugins.index.property.OrderedIndex; @@ -51,7 +53,6 @@ import com.google.common.base.Charsets; import com.google.common.base.Strings; -import com.google.common.collect.ImmutableList; import com.google.common.collect.Iterables; import com.google.common.collect.Lists; @@ -73,7 +74,7 @@ /** * convenience property for initialising an empty multi-value :next */ - public static final Iterable EMPTY_NEXT = ImmutableList.of("", "", "", ""); + public static final Iterable EMPTY_NEXT = ImmutableList.of(""); /** * convenience property that represent an empty :next as array @@ -117,10 +118,10 @@ private static void printWalkedLanes(final String msg, final String[] walked) { String m = (msg == null) ? "" : msg; if (walked == null) { - LOG.debug(m + " walked: null"); + LOG.trace(m + " walked: null"); } else { for (int i = 0; i < walked.length; i++) { - LOG.debug("{}walked[{}]: {}", new Object[] { m, i, walked[i] }); + LOG.trace("{}walked[{}]: {}", new Object[] {m, i, walked[i]}); } } } @@ -144,8 +145,8 @@ // we use the seek for seeking the right spot. The walkedLanes will have all our // predecessors String entry = seek(index, condition, walked); - if (LOG.isDebugEnabled()) { - LOG.debug("fetchKeyNode() - entry: {} ", entry); + if (LOG.isTraceEnabled()) { + LOG.trace("fetchKeyNode() - entry: {} ", entry); printWalkedLanes("fetchKeyNode() - ", walked); } @@ -162,10 +163,12 @@ LOG.debug("fetchKeyNode() - extracted lane: {}", lane); String next; NodeBuilder predecessor; + List vals; for (int l = lane; l >= 0; l--) { + vals = Lists.newArrayList(); // let's update the predecessors starting from the coin-flip lane predecessor = index.getChildNode(walked[l]); - next = getPropertyNext(predecessor, l); + next = getPropertyNext(predecessor, vals, l); setPropertyNext(predecessor, key, l); setPropertyNext(node, next, l); if (LOG.isDebugEnabled()) { @@ -834,7 +837,9 @@ int lane; boolean stillLaning; - String nextkey; + String nextkey; + NodeBuilder currentKeyNode = index.getChildNode(currentKey); + List vals = Lists.newArrayList(); if ((direction.isAscending() && condition instanceof PredicateLessThan) || (direction.isDescending() && condition instanceof PredicateGreaterThan)) { @@ -846,7 +851,7 @@ lane = 0; do { stillLaning = lane < OrderedIndex.LANES; - nextkey = getPropertyNext(index.getChildNode(currentKey), lane); + nextkey = getPropertyNext(currentKeyNode, vals, lane); if ((Strings.isNullOrEmpty(nextkey) || !walkingPredicate.apply(nextkey)) && lane < OrderedIndex.LANES) { // if we're currently pointing to NIL or the next element does not fit the search // but we still have lanes left @@ -856,6 +861,10 @@ found = nextkey; } else { currentKey = nextkey; + vals = Lists.newArrayList(); + if (!Strings.isNullOrEmpty(currentKey)) { + currentKeyNode = index.getChildNode(currentKey); + } if (keepWalked && !Strings.isNullOrEmpty(currentKey)) { walkedLanes[lane] = currentKey; } @@ -869,7 +878,7 @@ do { stillLaning = lane > 0; - nextkey = getPropertyNext(index.getChildNode(currentKey), lane); + nextkey = getPropertyNext(currentKeyNode, vals, lane); if ((Strings.isNullOrEmpty(nextkey) || !walkingPredicate.apply(nextkey)) && lane > 0) { // if we're currently pointing to NIL or the next element does not fit the search // but we still have lanes left, let's lower the lane; @@ -879,6 +888,10 @@ found = nextkey; } else { currentKey = nextkey; + vals = Lists.newArrayList(); + if (!Strings.isNullOrEmpty(currentKey)) { + currentKeyNode = index.getChildNode(currentKey); + } if (keepWalked && !Strings.isNullOrEmpty(currentKey)) { for (int l = lane; l >= 0; l--) { walkedLanes[l] = currentKey; @@ -1071,12 +1084,7 @@ */ static void setPropertyNext(@Nonnull final NodeBuilder node, final String... next) { if (node != null && next != null) { - String n1 = (next.length > 0) ? next[0] : ""; - String n2 = (next.length > 1) ? next[1] : ""; - String n3 = (next.length > 2) ? next[2] : ""; - String n4 = (next.length > 3) ? next[3] : ""; - - node.setProperty(NEXT, ImmutableList.of(n1, n2, n3, n4), Type.STRINGS); + node.setProperty(NEXT, Arrays.asList(next), Type.STRINGS); } } @@ -1096,12 +1104,12 @@ String[] values; if (next.isArray()) { values = Iterables.toArray(next.getValue(Type.STRINGS), String.class); - if (values.length < OrderedIndex.LANES) { + if (values.length < lane + 1) { // it could be we increased the number of lanes and running on some existing // content LOG.debug("topping-up the number of lanes."); List vv = Lists.newArrayList(values); - for (int i = vv.size(); i <= OrderedIndex.LANES; i++) { + for (int i = vv.size(); i <= lane; i++) { vv.add(""); } values = vv.toArray(new String[vv.size()]); @@ -1159,6 +1167,38 @@ } /** + * short-cut for using NodeBuilder. See {@code getNext(NodeState)} + */ + String getPropertyNext(@Nonnull final NodeBuilder node, List vals, final int lane) { + checkNotNull(node); + + String next = ""; + + if (vals.isEmpty()) { + PropertyState ps = node.getProperty(NEXT); + if (ps != null) { + if (ps.isArray()) { + Iterable values = ps.getValue(Type.STRINGS); + Iterables.addAll(vals, values); + if (vals.size() > lane) { + next = vals.get(Math.min(vals.size() - 1, lane)); + } + } else { + next = ps.getValue(Type.STRING); + if (next != null) { + vals.set(0, next); + } + } + } + } else { + if (vals.size() > lane) { + next = vals.get(Math.min(vals.size() - 1, lane)); + } + } + return next; + } + + /** * retrieve the lane to be updated based on probabilistic approach. * * Having 4 lanes if we have the 3 to be updated it means we'll have to update lanes @@ -1168,7 +1208,7 @@ * * It uses {@code getLane(Random)} by passing a {@code new Random(System.currentTimeMillis())} * - * @see OrderedIndex.DEFAULT_PROBABILITY + * @see OrderedIndex.PROBABILITY * * @return the lane to start updating from. */ @@ -1186,10 +1226,10 @@ final int maxLanes = OrderedIndex.LANES - 1; int lane = 0; - while (rnd.nextDouble() < OrderedIndex.DEFAULT_PROBABILITY && lane < maxLanes) { + while (rnd.nextDouble() < OrderedIndex.PROBABILITY && lane < maxLanes) { lane++; } return lane; } -} \ No newline at end of file +}