Author: davide Date: Thu Aug 21 14:03:32 2014 New Revision: 1619396 URL: http://svn.apache.org/r1619396 Log: OAK-2035 OrderedIndex fails to keep a correct skipList on TarMK
Merged r1618624 in 1.0 Added: jackrabbit/oak/branches/1.0/oak-jcr/src/test/java/org/apache/jackrabbit/oak/jcr/OrderedIndexIT.java - copied unchanged from r1618624, jackrabbit/oak/trunk/oak-jcr/src/test/java/org/apache/jackrabbit/oak/jcr/OrderedIndexIT.java jackrabbit/oak/branches/1.0/oak-jcr/src/test/java/org/apache/jackrabbit/oak/jcr/util/ - copied from r1618624, jackrabbit/oak/trunk/oak-jcr/src/test/java/org/apache/jackrabbit/oak/jcr/util/ Modified: jackrabbit/oak/branches/1.0/ (props changed) jackrabbit/oak/branches/1.0/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/property/strategy/OrderedContentMirrorStoreStrategy.java jackrabbit/oak/branches/1.0/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/index/property/strategy/OrderedContentMirrorStorageStrategyTest.java Propchange: jackrabbit/oak/branches/1.0/ ------------------------------------------------------------------------------ Merged /jackrabbit/oak/trunk:r1618624 Modified: jackrabbit/oak/branches/1.0/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/property/strategy/OrderedContentMirrorStoreStrategy.java URL: http://svn.apache.org/viewvc/jackrabbit/oak/branches/1.0/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/property/strategy/OrderedContentMirrorStoreStrategy.java?rev=1619396&r1=1619395&r2=1619396&view=diff ============================================================================== --- jackrabbit/oak/branches/1.0/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/property/strategy/OrderedContentMirrorStoreStrategy.java (original) +++ jackrabbit/oak/branches/1.0/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/property/strategy/OrderedContentMirrorStoreStrategy.java Thu Aug 21 14:03:32 2014 @@ -114,8 +114,20 @@ public class OrderedContentMirrorStoreSt this.direction = direction; } + private static void printWalkedLanes(final String msg, final String[] walked) { + String m = (msg == null) ? "" : msg; + if (walked == null) { + LOG.debug(m + " walked: null"); + } else { + for (int i = 0; i < walked.length; i++) { + LOG.debug("{}walked[{}]: {}", new Object[] { m, i, walked[i] }); + } + } + } + @Override NodeBuilder fetchKeyNode(@Nonnull NodeBuilder index, @Nonnull String key) { + LOG.debug("fetchKeyNode() - new item '{}' -----------------------------------------", key); // this is where the actual adding and maintenance of index's keys happen NodeBuilder node = null; NodeBuilder start = index.child(START); @@ -132,8 +144,14 @@ public class OrderedContentMirrorStoreSt // 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); + printWalkedLanes("fetchKeyNode() - ", walked); + } + if (entry != null && entry.equals(key)) { // it's an existing node. We should not need to update anything around pointers + LOG.debug("fetchKeyNode() - node already there."); node = index.getChildNode(key); } else { // the entry does not exits yet @@ -141,6 +159,7 @@ public class OrderedContentMirrorStoreSt // it's a brand new node. let's start setting an empty next setPropertyNext(node, EMPTY_NEXT_ARRAY); int lane = getLane(); + LOG.debug("fetchKeyNode() - extracted lane: {}", lane); String next; NodeBuilder predecessor; for (int l = lane; l >= 0; l--) { @@ -149,6 +168,12 @@ public class OrderedContentMirrorStoreSt next = getPropertyNext(predecessor, l); setPropertyNext(predecessor, key, l); setPropertyNext(node, next, l); + if (LOG.isDebugEnabled()) { + LOG.debug("fetchKeyNode() - on lane: {}", l); + LOG.debug("fetchKeyNode() - next from previous: {}", next); + LOG.debug("fetchKeyNode() - new status of predecessor name: {} - {} ", walked[l], predecessor.getProperty(NEXT)); + LOG.debug("fetchKeyNode() - new node name: {} - {}", key, node.getProperty(NEXT)); + } } } return node; @@ -268,21 +293,33 @@ public class OrderedContentMirrorStoreSt public Iterable<String> query(final Filter filter, final String indexName, final NodeState indexMeta, final String indexStorageNodeName, final PropertyRestriction pr) { + if (LOG.isDebugEnabled()) { + LOG.debug("query() - filter: {}", filter); + LOG.debug("query() - indexName: {}", indexName); + LOG.debug("query() - indexMeta: {}", indexMeta); + LOG.debug("query() - indexStorageNodeName: {}", indexStorageNodeName); + LOG.debug("query() - pr: {}", pr); + } final NodeState indexState = indexMeta.getChildNode(indexStorageNodeName); final NodeBuilder index = new ReadOnlyBuilder(indexState); - - if (pr.first != null && !pr.first.equals(pr.last)) { + final String firstEncoded = (pr.first == null) ? null + : encode(pr.first.getValue(Type.STRING)); + final String lastEncoded = (pr.last == null) ? null + : encode(pr.last.getValue(Type.STRING)); + + if (firstEncoded != null && !firstEncoded.equals(lastEncoded)) { // '>' & '>=' and between use case + LOG.debug("'>' & '>=' and between use case"); ChildNodeEntry firstValueableItem; String firstValuableItemKey; Iterable<String> it = Collections.emptyList(); Iterable<ChildNodeEntry> childrenIterable; - if (pr.last == null) { + if (lastEncoded == null) { LOG.debug("> & >= case."); firstValuableItemKey = seek(index, - new PredicateGreaterThan(pr.first.getValue(Type.STRING), pr.firstIncluding)); + new PredicateGreaterThan(firstEncoded, pr.firstIncluding)); if (firstValuableItemKey != null) { firstValueableItem = new OrderedChildNodeEntry(firstValuableItemKey, indexState.getChildNode(firstValuableItemKey)); @@ -291,15 +328,15 @@ public class OrderedContentMirrorStoreSt it = new QueryResultsWrapper(filter, indexName, childrenIterable); } else { it = new QueryResultsWrapper(filter, indexName, new BetweenIterable( - indexState, firstValueableItem, pr.first.getValue(Type.STRING), + indexState, firstValueableItem, firstEncoded, pr.firstIncluding, direction)); } } } else { String first, last; boolean includeFirst, includeLast; - first = pr.first.getValue(Type.STRING); - last = pr.last.getValue(Type.STRING); + first = firstEncoded; + last = lastEncoded; includeFirst = pr.firstIncluding; includeLast = pr.lastIncluding; @@ -330,9 +367,10 @@ public class OrderedContentMirrorStoreSt } return it; - } else if (pr.last != null && !pr.last.equals(pr.first)) { + } else if (lastEncoded != null && !lastEncoded.equals(firstEncoded)) { // '<' & '<=' use case - final String searchfor = pr.last.getValue(Type.STRING); + LOG.debug("'<' & '<=' use case"); + final String searchfor = lastEncoded; final boolean include = pr.lastIncluding; Predicate<String> predicate = new PredicateLessThan(searchfor, include); @@ -359,8 +397,8 @@ public class OrderedContentMirrorStoreSt return it; } else { // property is not null. AKA "open query" - Iterable<String> values = null; - return query(filter, indexName, indexMeta, values); + LOG.debug("property is not null. AKA 'open query'. FullIterable"); + return new QueryResultsWrapper(filter, indexName, new FullIterable(indexState, false)); } } @@ -602,8 +640,10 @@ public class OrderedContentMirrorStoreSt @Override public boolean hasNext() { - return (includeStart && start.equals(current)) - || (!includeStart && !Strings.isNullOrEmpty(getPropertyNext(current))); + boolean hasNext = (includeStart && start.equals(current)) + || (!includeStart && !Strings.isNullOrEmpty(getPropertyNext(current))); + + return hasNext; } @Override @@ -622,6 +662,7 @@ public class OrderedContentMirrorStoreSt throw new NoSuchElementException(); } } + return entry; } @@ -751,7 +792,10 @@ public class OrderedContentMirrorStoreSt @Nullable final String[] walkedLanes) { boolean keepWalked = false; String searchfor = condition.getSearchFor(); - LOG.debug("seek() - Searching for: {}", condition.getSearchFor()); + if (LOG.isDebugEnabled()) { + LOG.debug("seek() - Searching for: {}", condition.getSearchFor()); + LOG.debug("seek() - condition: {}", condition); + } Predicate<String> walkingPredicate = direction.isAscending() ? new PredicateLessThan(searchfor, true) : new PredicateGreaterThan(searchfor, true); @@ -781,6 +825,8 @@ public class OrderedContentMirrorStoreSt // we're asking for a <, <= query from ascending index or >, >= from descending // we have to walk the lanes from bottom to up rather than up to bottom. + LOG.debug("seek() - cross case"); + lane = 0; do { stillLaning = lane < OrderedIndex.LANES; @@ -801,6 +847,8 @@ public class OrderedContentMirrorStoreSt } } while (((!Strings.isNullOrEmpty(nextkey) && walkingPredicate.apply(nextkey)) || stillLaning) && (found == null)); } else { + LOG.debug("seek() - plain case"); + lane = OrderedIndex.LANES - 1; do { @@ -854,7 +902,6 @@ public class OrderedContentMirrorStoreSt * {@code searchfor} */ static class PredicateGreaterThan implements Predicate<String> { - private String searchforEncoded; private String searchforDecoded; private boolean include; @@ -863,7 +910,6 @@ public class OrderedContentMirrorStoreSt } public PredicateGreaterThan(@Nonnull String searchfor, boolean include) { - this.searchforEncoded = encode(searchfor); this.searchforDecoded = searchfor; this.include = include; } @@ -873,8 +919,8 @@ public class OrderedContentMirrorStoreSt boolean b = false; if (!Strings.isNullOrEmpty(arg0)) { String name = arg0; - b = searchforEncoded.compareTo(name) < 0 || (include && searchforEncoded - .equals(name)); + b = searchforDecoded.compareTo(name) < 0 || + (include && searchforDecoded.equals(name)); } return b; @@ -890,7 +936,6 @@ public class OrderedContentMirrorStoreSt * evaluates when the current element is less than (<) and less than equal {@code searchfor} */ static class PredicateLessThan implements Predicate<String> { - private String searchforEncoded; private String searchforOriginal; private boolean include; @@ -899,7 +944,6 @@ public class OrderedContentMirrorStoreSt } public PredicateLessThan(@Nonnull String searchfor, boolean include) { - this.searchforEncoded = encode(searchfor); this.searchforOriginal = searchfor; this.include = include; } @@ -909,10 +953,10 @@ public class OrderedContentMirrorStoreSt boolean b = false; if (!Strings.isNullOrEmpty(arg0)) { String name = arg0; - b = searchforEncoded.compareTo(name) > 0 - || (include && searchforEncoded.equals(name)); + b = searchforOriginal.compareTo(name) > 0 + || (include && searchforOriginal.equals(name)); } - + return b; } Modified: jackrabbit/oak/branches/1.0/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/index/property/strategy/OrderedContentMirrorStorageStrategyTest.java URL: http://svn.apache.org/viewvc/jackrabbit/oak/branches/1.0/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/index/property/strategy/OrderedContentMirrorStorageStrategyTest.java?rev=1619396&r1=1619395&r2=1619396&view=diff ============================================================================== --- jackrabbit/oak/branches/1.0/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/index/property/strategy/OrderedContentMirrorStorageStrategyTest.java (original) +++ jackrabbit/oak/branches/1.0/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/index/property/strategy/OrderedContentMirrorStorageStrategyTest.java Thu Aug 21 14:03:32 2014 @@ -3253,7 +3253,6 @@ public class OrderedContentMirrorStorage // testing the exception in case of wrong parameters String searchFor = "wedontcareaswetesttheexception"; - NodeState node = index.getChildNode(searchFor); String entry = searchFor; String[] wl = new String[0]; String item = null; @@ -3390,6 +3389,12 @@ public class OrderedContentMirrorStorage predicate = new PredicateLessThan(searchfor, true); entry = null; assertFalse(predicate.apply(entry)); + + // equality matching + searchfor = "2012-11-25T21:00:45.967-07:00"; + entry = "2012-11-25T21%3A00%3A45.967-07%3A00"; + predicate = new PredicateLessThan(searchfor, true); + assertTrue("this should have matched the equality flag", predicate.apply(entry)); } /**