You are viewing a plain text version of this content. The canonical link for it is here.
Posted to oak-commits@jackrabbit.apache.org by da...@apache.org on 2014/06/12 13:21:54 UTC
svn commit: r1602124 [1/3] - in /jackrabbit/oak/branches/1.0: ./
oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/property/
oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/property/strategy/
oak-core/src/test/java/org/apach...
Author: davide
Date: Thu Jun 12 11:21:53 2014
New Revision: 1602124
URL: http://svn.apache.org/r1602124
Log:
OAK-1570 - Improve perfomances of the OrderedIndex while insert
merged into 1.0 branch
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/OrderedIndex.java
jackrabbit/oak/branches/1.0/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/property/strategy/ContentMirrorStoreStrategy.java
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/BasicOrderedPropertyIndexQueryTest.java
jackrabbit/oak/branches/1.0/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/index/property/OrderedPropertyIndexDescendingQueryTest.java
jackrabbit/oak/branches/1.0/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/index/property/OrderedPropertyIndexQueryTest.java
jackrabbit/oak/branches/1.0/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/index/property/strategy/OrderedContentMirrorStorageStrategyTest.java
jackrabbit/oak/branches/1.0/oak-jcr/src/test/java/org/apache/jackrabbit/oak/jcr/OrderedIndexConcurrentClusterIT.java
Propchange: jackrabbit/oak/branches/1.0/
------------------------------------------------------------------------------
Merged /jackrabbit/oak/trunk:r1600088
Modified: jackrabbit/oak/branches/1.0/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/property/OrderedIndex.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/branches/1.0/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/property/OrderedIndex.java?rev=1602124&r1=1602123&r2=1602124&view=diff
==============================================================================
--- jackrabbit/oak/branches/1.0/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/property/OrderedIndex.java (original)
+++ jackrabbit/oak/branches/1.0/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/property/OrderedIndex.java Thu Jun 12 11:21:53 2014
@@ -91,6 +91,14 @@ public interface OrderedIndex {
public static boolean isDescending(NodeState indexMeta) {
return DESC.equals(fromIndexMeta(indexMeta));
}
+
+ public boolean isAscending() {
+ return ASC.equals(this);
+ }
+
+ public boolean isDescending() {
+ return DESC.equals(this);
+ }
/**
* convenience method that tells if the provided index definition is ascending
@@ -116,4 +124,34 @@ public interface OrderedIndex {
* 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%
+ * having therefore
+ *
+ * <dl>
+ * <dt>lane 0:</dt> <dd>100.0% (the base linked list)</dd>
+ * <dt>lane 1:</dt> <dd>10.0%</dd>
+ * <dt>lane 2:</dt> <dd>1.0%</dd>
+ * <dt>lane 3:</dt> <dd>0.1%</dd>
+ * </dl>
+ */
+ double DEFAULT_PROBABILITY = 0.1;
+
+ /**
+ * the number of lanes used in the SkipList
+ */
+ int LANES = 4;
+
+ /**
+ * Convenience Predicate that will force the implementor to expose what we're searching for
+ *
+ * @param <T>
+ */
+ interface Predicate<T> extends com.google.common.base.Predicate<T> {
+ /**
+ * @return the string we're searching for during this predicate
+ */
+ String getSearchFor();
+ }
}
Modified: jackrabbit/oak/branches/1.0/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/property/strategy/ContentMirrorStoreStrategy.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/ContentMirrorStoreStrategy.java?rev=1602124&r1=1602123&r2=1602124&view=diff
==============================================================================
--- jackrabbit/oak/branches/1.0/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/property/strategy/ContentMirrorStoreStrategy.java (original)
+++ jackrabbit/oak/branches/1.0/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/property/strategy/ContentMirrorStoreStrategy.java Thu Jun 12 11:21:53 2014
@@ -100,7 +100,7 @@ public class ContentMirrorStoreStrategy
}
// Prune all index nodes that are no longer needed
- prune(index, builders);
+ prune(index, builders, key);
}
}
@@ -431,8 +431,9 @@ public class ContentMirrorStoreStrategy
* the current index
* @param builders
* list of nodes to prune
+ * @param key the key of the index we're processing
*/
- void prune(final NodeBuilder index, final Deque<NodeBuilder> builders) {
+ void prune(final NodeBuilder index, final Deque<NodeBuilder> builders, final String key) {
for (NodeBuilder node : builders) {
if (node.getBoolean("match") || node.getChildNodeCount(1) > 0) {
return;
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=1602124&r1=1602123&r2=1602124&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 Jun 12 11:21:53 2014
@@ -24,6 +24,7 @@ import java.util.Collections;
import java.util.Deque;
import java.util.Iterator;
import java.util.NoSuchElementException;
+import java.util.Random;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
@@ -32,6 +33,7 @@ import org.apache.jackrabbit.oak.api.Pro
import org.apache.jackrabbit.oak.api.Type;
import org.apache.jackrabbit.oak.plugins.index.property.OrderedIndex;
import org.apache.jackrabbit.oak.plugins.index.property.OrderedIndex.OrderDirection;
+import org.apache.jackrabbit.oak.plugins.index.property.OrderedIndex.Predicate;
import org.apache.jackrabbit.oak.plugins.memory.EmptyNodeState;
import org.apache.jackrabbit.oak.spi.query.Filter;
import org.apache.jackrabbit.oak.spi.query.Filter.PropertyRestriction;
@@ -42,8 +44,9 @@ import org.apache.jackrabbit.oak.spi.sta
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
-import com.google.common.base.Predicate;
import com.google.common.base.Strings;
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.Iterables;
/**
* Same as for {@link ContentMirrorStoreStrategy} but the order of the keys is kept by using the
@@ -60,6 +63,15 @@ import com.google.common.base.Strings;
* </code>
*/
public class OrderedContentMirrorStoreStrategy extends ContentMirrorStoreStrategy {
+ /**
+ * convenience property for initialising an empty multi-value :next
+ */
+ public static final Iterable<String> EMPTY_NEXT = ImmutableList.of("", "", "", "");
+
+ /**
+ * convenience property that represent an empty :next as array
+ */
+ public static final String[] EMPTY_NEXT_ARRAY = Iterables.toArray(EMPTY_NEXT, String.class);
/**
* the property linking to the next node
@@ -75,11 +87,12 @@ public class OrderedContentMirrorStoreSt
* a NodeState used for easy creating of an empty :start
*/
public static final NodeState EMPTY_START_NODE = EmptyNodeState.EMPTY_NODE.builder()
- .setProperty(NEXT, "")
- .getNodeState();
+ .setProperty(NEXT, EMPTY_NEXT, Type.STRINGS).getNodeState();
private static final Logger LOG = LoggerFactory.getLogger(OrderedContentMirrorStoreStrategy.class);
-
+
+ private static final Random RND = new Random(System.currentTimeMillis());
+
/**
* the direction of the index.
*/
@@ -96,80 +109,73 @@ public class OrderedContentMirrorStoreSt
@Override
NodeBuilder fetchKeyNode(@Nonnull NodeBuilder index, @Nonnull String key) {
- NodeBuilder localkey = null;
+ // this is where the actual adding and maintenance of index's keys happen
+ NodeBuilder node = null;
NodeBuilder start = index.child(START);
-
- // identifying the right place for insert
- String n = start.getString(NEXT);
- if (Strings.isNullOrEmpty(n)) {
- // new/empty index
- localkey = index.child(key);
- localkey.setProperty(NEXT, "");
- start.setProperty(NEXT, key);
- } else {
- // specific use-case where the item has to be added as first of the list
- String nextKey = n;
- Iterable<? extends ChildNodeEntry> children = getChildNodeEntries(index.getNodeState(),
- true);
- for (ChildNodeEntry child : children) {
- nextKey = child.getNodeState().getString(NEXT);
- if (Strings.isNullOrEmpty(nextKey)) {
- // we're at the last element, therefore our 'key' has to be appended
- index.getChildNode(child.getName()).setProperty(NEXT, key);
- localkey = index.child(key);
- localkey.setProperty(NEXT, "");
- } else {
- if (isInsertHere(key, nextKey)) {
- index.getChildNode(child.getName()).setProperty(NEXT, key);
- localkey = index.child(key);
- localkey.setProperty(NEXT, nextKey);
- break;
- }
- }
- }
+ Predicate<ChildNodeEntry> condition = direction.isAscending()
+ ? new PredicateGreaterThan(key, true)
+ : new PredicateLessThan(key, true);
+ ChildNodeEntry[] walked = new ChildNodeEntry[OrderedIndex.LANES];
+
+ if (Strings.isNullOrEmpty(getPropertyNext(start))) {
+ // it means we're in an empty/new index. Setting properly the :start's :next
+ setPropertyNext(start, EMPTY_NEXT_ARRAY);
}
-
- return localkey;
- }
-
- /**
- * tells whether or not the is right to insert here a new item.
- *
- * @param newItemKey the new item key to be added
- * @param existingItemKey the 'here' of the existing index
- * @return true for green light on insert false otherwise.
- */
- private boolean isInsertHere(@Nonnull String newItemKey, @Nonnull String existingItemKey) {
- if (OrderDirection.ASC.equals(direction)) {
- return newItemKey.compareTo(existingItemKey) < 0;
+
+ // we use the seek for seeking the right spot. The walkedLanes will have all our
+ // predecessors
+ ChildNodeEntry entry = seek(index.getNodeState(), condition, walked);
+ if (entry != null && entry.getName().equals(key)) {
+ // it's an existing node. We should not need to update anything around pointers
+ node = index.getChildNode(key);
} else {
- return newItemKey.compareTo(existingItemKey) > 0;
+ // the entry does not exits yet
+ node = index.child(key);
+ // it's a brand new node. let's start setting an empty next
+ setPropertyNext(node, EMPTY_NEXT_ARRAY);
+ int lane = getLane();
+ String next;
+ NodeBuilder predecessor;
+ for (int l = lane; l >= 0; l--) {
+ // let's update the predecessors starting from the coin-flip lane
+ predecessor = index.getChildNode(walked[l].getName());
+ next = getPropertyNext(predecessor, l);
+ setPropertyNext(predecessor, key, l);
+ setPropertyNext(node, next, l);
+ }
}
+ return node;
}
@Override
- void prune(final NodeBuilder index, final Deque<NodeBuilder> builders) {
+ void prune(final NodeBuilder index, final Deque<NodeBuilder> builders, final String key) {
for (NodeBuilder node : builders) {
if (node.hasProperty("match") || node.getChildNodeCount(1) > 0) {
return;
} else if (node.exists()) {
if (node.hasProperty(NEXT)) {
- // it's an index key and we have to relink the list
- // (1) find the previous element
- ChildNodeEntry previous = findPrevious(
- index.getNodeState(), node.getNodeState());
- if (previous == null) {
- LOG.debug("previous not found. Already deleted in the meanwhile. Skipping re-link");
- } else {
- LOG.debug("previous: {}", previous);
- // (2) find the next element
- String next = node.getString(NEXT);
- if (next == null) {
- next = "";
+ ChildNodeEntry[] walkedLanes = new ChildNodeEntry[OrderedIndex.LANES];
+ ChildNodeEntry entry;
+ String lane0Next, prevNext, currNext;
+
+ // for as long as we have the an entry and we didn't update the lane0 we have
+ // to keep searching and update
+ do {
+ entry = seek(index.getNodeState(),
+ new PredicateEquals(key),
+ walkedLanes
+ );
+ lane0Next = getPropertyNext(walkedLanes[0]);
+ for (int lane = walkedLanes.length - 1; lane >= 0; lane--) {
+ prevNext = getPropertyNext(walkedLanes[lane], lane);
+ if (key.equals(prevNext)) {
+ // if it's actually pointing to us let's deal with it
+ currNext = getPropertyNext(node, lane);
+ setPropertyNext(index.getChildNode(walkedLanes[lane].getName()),
+ currNext, lane);
+ }
}
- // (3) re-link the previous to the next
- index.getChildNode(previous.getName()).setProperty(NEXT, next);
- }
+ } while (entry != null && !key.equals(lane0Next));
}
node.remove();
}
@@ -177,43 +183,6 @@ public class OrderedContentMirrorStoreSt
}
/**
- * find the previous item (ChildNodeEntry) in the index given the provided NodeState for
- * comparison
- *
- * in an index sorted in ascending manner where we have @{code [1, 2, 3, 4, 5]} if we ask for
- * a previous given 4 it will be 3. previous(4)=3.
- *
- * in an index sorted in descending manner where we have @{code [5, 4, 3, 2, 1]} if we as for
- * a previous given 4 it will be 5. previous(4)=5.
- *
- * @param index the index we want to look into ({@code :index})
- * @param node the node we want to compare
- * @return the previous item or null if not found.
- */
- @Nullable
- ChildNodeEntry findPrevious(@Nonnull final NodeState index, @Nonnull final NodeState node) {
- ChildNodeEntry previous = null;
- ChildNodeEntry current = null;
- boolean found = false;
- Iterator<? extends ChildNodeEntry> it = getChildNodeEntries(index, true).iterator();
-
- while (!found && it.hasNext()) {
- current = it.next();
- if (previous == null) {
- // first iteration
- previous = current;
- } else {
- found = node.equals(current.getNodeState());
- if (!found) {
- previous = current;
- }
- }
- }
-
- return found ? previous : null;
- }
-
- /**
* retrieve an Iterable for going through the index in the right order without the :start node
*
* @param index the root of the index (:index)
@@ -239,7 +208,8 @@ public class OrderedContentMirrorStoreSt
Iterable<? extends ChildNodeEntry> cne = null;
final NodeState start = index.getChildNode(START);
- if ((!start.exists() || Strings.isNullOrEmpty(start.getString(NEXT))) && !includeStart) {
+ String startNext = getPropertyNext(start);
+ if ((!start.exists() || Strings.isNullOrEmpty(startNext)) && !includeStart) {
// if the property is not there or is empty it means we're empty
cne = Collections.emptyList();
} else {
@@ -290,8 +260,14 @@ public class OrderedContentMirrorStoreSt
firstValueableItem = seek(index,
new PredicateGreaterThan(pr.first.getValue(Type.STRING), pr.firstIncluding));
if (firstValueableItem != null) {
- childrenIterable = new SeekedIterable(index, firstValueableItem);
- it = new QueryResultsWrapper(filter, indexName, childrenIterable);
+ if (direction.isAscending()) {
+ childrenIterable = new SeekedIterable(index, firstValueableItem);
+ it = new QueryResultsWrapper(filter, indexName, childrenIterable);
+ } else {
+ it = new QueryResultsWrapper(filter, indexName, new BetweenIterable(index,
+ firstValueableItem, pr.first.getValue(Type.STRING), pr.firstIncluding,
+ direction));
+ }
}
} else {
String first, last;
@@ -341,8 +317,13 @@ public class OrderedContentMirrorStoreSt
Iterable<String> it = Collections.emptyList();
if (firstValueableItem != null) {
- it = new QueryResultsWrapper(filter, indexName, new SeekedIterable(index,
- firstValueableItem));
+ if (direction.isAscending()) {
+ it = new QueryResultsWrapper(filter, indexName, new BetweenIterable(index,
+ firstValueableItem, searchfor, include, direction));
+ } else {
+ it = new QueryResultsWrapper(filter, indexName, new SeekedIterable(index,
+ firstValueableItem));
+ }
}
return it;
} else {
@@ -356,7 +337,7 @@ public class OrderedContentMirrorStoreSt
return value.replaceAll("%3A", ":");
}
- private static final class OrderedChildNodeEntry extends AbstractChildNodeEntry {
+ static class OrderedChildNodeEntry extends AbstractChildNodeEntry {
private final String name;
private final NodeState state;
@@ -447,6 +428,11 @@ public class OrderedContentMirrorStoreSt
return b;
}
+
+ @Override
+ public String getSearchFor() {
+ throw new UnsupportedOperationException();
+ }
};
CountingNodeVisitor v;
@@ -497,6 +483,11 @@ public class OrderedContentMirrorStoreSt
return b;
}
+
+ @Override
+ public String getSearchFor() {
+ throw new UnsupportedOperationException();
+ }
};
CountingNodeVisitor v;
@@ -558,9 +549,9 @@ public class OrderedContentMirrorStoreSt
private static class FullIterator implements Iterator<ChildNodeEntry> {
private boolean includeStart;
private NodeState start;
- private NodeState current;
+ NodeState current;
private NodeState index;
- private String currentName;
+ String currentName;
public FullIterator(NodeState index, NodeState start, boolean includeStart,
NodeState current) {
@@ -573,7 +564,7 @@ public class OrderedContentMirrorStoreSt
@Override
public boolean hasNext() {
return (includeStart && start.equals(current))
- || (!includeStart && !Strings.isNullOrEmpty(current.getString(NEXT)));
+ || (!includeStart && !Strings.isNullOrEmpty(getPropertyNext(current)));
}
@Override
@@ -585,7 +576,7 @@ public class OrderedContentMirrorStoreSt
includeStart = false;
} else {
if (hasNext()) {
- currentName = current.getString(NEXT);
+ currentName = getPropertyNext(current);
current = index.getChildNode(currentName);
entry = new OrderedChildNodeEntry(currentName, current);
} else {
@@ -670,6 +661,8 @@ public class OrderedContentMirrorStoreSt
if (firstReturned) {
return super.next();
} else {
+ currentName = first.getName();
+ current = first.getNodeState();
firstReturned = true;
return first;
}
@@ -692,28 +685,116 @@ public class OrderedContentMirrorStoreSt
return new SeekedIterator(index, start, first);
}
}
+
+ /**
+ * see {@link #seek(NodeState, Predicate<ChildNodeEntry>, ChildNodeEntry[])} passing null as
+ * last argument
+ */
+ ChildNodeEntry seek(@Nonnull NodeState index,
+ @Nonnull Predicate<ChildNodeEntry> condition) {
+ return seek(index, condition, null);
+ }
/**
- * seek for an element in the index given the provided Predicate
+ * seek for an element in the index given the provided Predicate. If {@code walkedLanes} won't
+ * be null it will have on the way out the last elements of each lane walked through during the
+ * seek.
*
* @param index the index content node {@code :index}
* @param condition the predicate to evaluate
+ * @param walkedLanes if not null will contain the last element of the walked lanes with each
+ * lane represented by the corresponding position in the array. <b>You have</b> to
+ * pass in an array already sized as {@link OrderedIndex#LANES} or an
+ * {@link IllegalArgumentException} will be raised
* @return the entry or null if not found
*/
- static ChildNodeEntry seek(@Nonnull NodeState index,
- @Nonnull Predicate<ChildNodeEntry> condition) {
+ ChildNodeEntry seek(@Nonnull final NodeState index,
+ @Nonnull final Predicate<ChildNodeEntry> condition,
+ @Nullable final ChildNodeEntry[] walkedLanes) {
+ boolean keepWalked = false;
+ String searchfor = condition.getSearchFor();
+ LOG.debug("seek() - Searching for: {}", condition.getSearchFor());
+ Predicate<ChildNodeEntry> walkingPredicate = direction.isAscending()
+ ? new PredicateLessThan(searchfor, true)
+ : new PredicateGreaterThan(searchfor, true);
+ // we always begin with :start
+ ChildNodeEntry current = new OrderedChildNodeEntry(START, index.getChildNode(START));
+ ChildNodeEntry found = null;
- // TODO the FullIterable will have to be replaced with something else once we'll have the
- // Skip part of the list implemented.
- Iterable<ChildNodeEntry> children = new FullIterable(index, false);
- ChildNodeEntry entry = null;
- for (ChildNodeEntry child : children) {
- if (condition.apply(child)) {
- entry = child;
- break;
+ if (walkedLanes != null) {
+ if (walkedLanes.length != OrderedIndex.LANES) {
+ throw new IllegalArgumentException(String.format(
+ "Wrong size for keeping track of the Walked Lanes. Expected %d but was %d",
+ OrderedIndex.LANES, walkedLanes.length));
+ }
+ // ensuring the right data
+ for (int i = 0; i < walkedLanes.length; i++) {
+ walkedLanes[i] = current;
}
+ keepWalked = true;
+ }
+
+ int lane;
+ boolean stillLaning;
+ String nextkey;
+ ChildNodeEntry next;
+
+ if ((direction.isAscending() && condition instanceof PredicateLessThan)
+ || (direction.isDescending() && condition instanceof PredicateGreaterThan)) {
+ // 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.
+
+ lane = 0;
+ do {
+ stillLaning = lane < OrderedIndex.LANES;
+ nextkey = getPropertyNext(current, lane);
+ next = (Strings.isNullOrEmpty(nextkey))
+ ? null
+ : new OrderedChildNodeEntry(nextkey, index.getChildNode(nextkey));
+ if ((next == null || !walkingPredicate.apply(next)) && 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
+ lane++;
+ } else {
+ if (condition.apply(next)) {
+ found = next;
+ } else {
+ current = next;
+ if (keepWalked && current != null) {
+ walkedLanes[lane] = current;
+ }
+ }
+ }
+ } while (((next != null && walkingPredicate.apply(next)) || stillLaning) && (found == null));
+ } else {
+ lane = OrderedIndex.LANES - 1;
+
+ do {
+ stillLaning = lane > 0;
+ nextkey = getPropertyNext(current, lane);
+ next = (Strings.isNullOrEmpty(nextkey))
+ ? null
+ : new OrderedChildNodeEntry(nextkey, index.getChildNode(nextkey));
+ if ((next == null || !walkingPredicate.apply(next)) && 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;
+ lane--;
+ } else {
+ if (condition.apply(next)) {
+ found = next;
+ } else {
+ current = next;
+ if (keepWalked && current != null) {
+ for (int l = lane; l >= 0; l--) {
+ walkedLanes[l] = current;
+ }
+ }
+ }
+ }
+ } while (((next != null && walkingPredicate.apply(next)) || stillLaning) && (found == null));
}
- return entry;
+
+ return found;
}
/**
@@ -730,6 +811,11 @@ public class OrderedContentMirrorStoreSt
public boolean apply(ChildNodeEntry arg0) {
return arg0 != null && searchfor.equals(arg0.getName());
}
+
+ @Override
+ public String getSearchFor() {
+ return searchfor;
+ }
}
/**
@@ -760,6 +846,11 @@ public class OrderedContentMirrorStoreSt
return b;
}
+
+ @Override
+ public String getSearchFor() {
+ return searchfor;
+ }
}
/**
@@ -788,6 +879,11 @@ public class OrderedContentMirrorStoreSt
return b;
}
+
+ @Override
+ public String getSearchFor() {
+ return searchfor;
+ }
}
/**
@@ -838,23 +934,156 @@ public class OrderedContentMirrorStoreSt
@Override
public boolean apply(String input) {
- return d.equals(OrderDirection.ASC)
- ? v.compareTo(input) > 0 || (i && v.equals(input))
- : v.compareTo(input) < 0 || (i && v.equals(input));
+ // splitting in multiple lines for easier debugging
+ boolean compareTo, equals, apply;
+ if (d.equals(OrderDirection.ASC)) {
+ compareTo = v.compareTo(input) > 0;
+ } else {
+ compareTo = v.compareTo(input) < 0;
+ }
+
+ equals = v.equals(input);
+ apply = compareTo || (i && equals);
+ return apply;
+ }
+
+ @Override
+ public String getSearchFor() {
+ throw new UnsupportedOperationException();
}
};
}
@Override
public boolean hasNext() {
- boolean next = super.hasNext();
+ boolean hasNext = super.hasNext();
String name = getCurrentName();
+
+ if (name != null && hasNext) {
+ String next = getPropertyNext(current);
+ hasNext = hasNext && condition.apply(next);
+ }
+ return hasNext;
+ }
+ }
- if (name != null && next) {
- name = convert(name);
- next = next && condition.apply(name);
+ /**
+ * set the value of the the :next at position 0
+ *
+ * @param node the node to modify
+ * @param next the 'next' value
+ */
+ 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);
+ }
+ }
+
+ /**
+ * set the value of the :next at the given position. If the property :next won't be there by the
+ * time this method is invoked it won't perform any action
+ *
+ * @param node
+ * @param value
+ * @param lane
+ */
+ static void setPropertyNext(@Nonnull final NodeBuilder node,
+ final String value, final int lane) {
+ if (node != null && value != null && lane >= 0 && lane < OrderedIndex.LANES) {
+ PropertyState next = node.getProperty(NEXT);
+ if (next != null) {
+ String[] values = Iterables.toArray(next.getValue(Type.STRINGS), String.class);
+ values[lane] = value;
+ setPropertyNext(node, values);
}
- return next;
}
}
-}
+
+ /**
+ * see {@link #getPropertyNext(NodeState, int)} by providing '0' as lane
+ */
+ static String getPropertyNext(@Nonnull final NodeState nodeState) {
+ return getPropertyNext(nodeState, 0);
+ }
+
+ /**
+ * return the 'next' value at the provided position
+ *
+ * @param nodeState the node state to inspect
+ * @return the next value
+ */
+ static String getPropertyNext(@Nonnull final NodeState state, final int lane) {
+ String next = "";
+ PropertyState ps = state.getProperty(NEXT);
+ if (ps != null) {
+ next = (lane < OrderedIndex.LANES) ? ps.getValue(Type.STRING, lane)
+ : "";
+ }
+ return next;
+ }
+
+ /**
+ * short-cut for using NodeBuilder. See {@code getNext(NodeState)}
+ */
+ static String getPropertyNext(@Nonnull final NodeBuilder node) {
+ return getPropertyNext(node.getNodeState());
+ }
+
+ /**
+ * short-cut for using NodeBuilder. See {@code getNext(NodeState)}
+ */
+ static String getPropertyNext(@Nonnull final NodeBuilder node, final int lane) {
+ return getPropertyNext(node.getNodeState(), lane);
+ }
+
+ /**
+ * short-cut for using ChildNodeEntry. See {@code getNext(NodeState)}
+ */
+ static String getPropertyNext(@Nonnull final ChildNodeEntry child) {
+ return getPropertyNext(child.getNodeState());
+ }
+
+ static String getPropertyNext(@Nonnull final ChildNodeEntry child, int lane) {
+ return getPropertyNext(child.getNodeState(), lane);
+ }
+
+ /**
+ * 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
+ * 0,1,2 and 3. If we'll have 2 only 0,1,2 and so on.
+ *
+ * Lane 0 will always be updated as it's the base linked list.
+ *
+ * It uses {@code getLane(Random)} by passing a {@code new Random(System.currentTimeMillis())}
+ *
+ * @see OrderedIndex.DEFAULT_PROBABILITY
+ *
+ * @return the lane to start updating from.
+ */
+ public int getLane() {
+ return getLane(RND);
+ }
+
+ /**
+ * used for mocking purposes or advanced uses. Use the {@code getLane()} where possible
+ *
+ * @param rnd the Random generator to be used for probability
+ * @return the lane to be updated.
+ */
+ int getLane(@Nonnull final Random rnd) {
+ final int maxLanes = OrderedIndex.LANES - 1;
+ int lane = 0;
+
+ while (rnd.nextDouble() < OrderedIndex.DEFAULT_PROBABILITY && lane < maxLanes) {
+ lane++;
+ }
+
+ return lane;
+ }
+}
\ No newline at end of file
Modified: jackrabbit/oak/branches/1.0/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/index/property/BasicOrderedPropertyIndexQueryTest.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/branches/1.0/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/index/property/BasicOrderedPropertyIndexQueryTest.java?rev=1602124&r1=1602123&r2=1602124&view=diff
==============================================================================
--- jackrabbit/oak/branches/1.0/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/index/property/BasicOrderedPropertyIndexQueryTest.java (original)
+++ jackrabbit/oak/branches/1.0/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/index/property/BasicOrderedPropertyIndexQueryTest.java Thu Jun 12 11:21:53 2014
@@ -63,8 +63,7 @@ public abstract class BasicOrderedProper
/**
* formatter for date conversions
*/
- protected static final SimpleDateFormat ISO_8601_2000 = new SimpleDateFormat(
- "yyyy-MM-dd'T'HH:mm:ss.SSS'Z'");
+ protected static final String ISO_8601_2000 = "yyyy-MM-dd'T'HH:mm:ss.SSS'Z'";
/**
* generate a list of values to be used as ordered set. Will return something like
@@ -198,8 +197,9 @@ public abstract class BasicOrderedProper
List<String> values = new ArrayList<String>(amount);
Calendar lstart = (Calendar) start.clone();
int hours = (OrderDirection.DESC.equals(direction)) ? -12 : 12;
+ SimpleDateFormat sdf = new SimpleDateFormat(ISO_8601_2000);
for (int i = 0; i < amount; i++) {
- values.add(ISO_8601_2000.format(lstart.getTime()));
+ values.add(sdf.format(lstart.getTime()));
lstart.add(Calendar.HOUR_OF_DAY, hours);
}
Modified: jackrabbit/oak/branches/1.0/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/index/property/OrderedPropertyIndexDescendingQueryTest.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/branches/1.0/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/index/property/OrderedPropertyIndexDescendingQueryTest.java?rev=1602124&r1=1602123&r2=1602124&view=diff
==============================================================================
--- jackrabbit/oak/branches/1.0/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/index/property/OrderedPropertyIndexDescendingQueryTest.java (original)
+++ jackrabbit/oak/branches/1.0/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/index/property/OrderedPropertyIndexDescendingQueryTest.java Thu Jun 12 11:21:53 2014
@@ -22,6 +22,7 @@ import static junit.framework.Assert.ass
import static org.apache.jackrabbit.JcrConstants.NT_UNSTRUCTURED;
import java.text.ParseException;
+import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Collections;
import java.util.Iterator;
@@ -162,7 +163,7 @@ public class OrderedPropertyIndexDescend
Calendar searchForCalendar = (Calendar) start.clone();
searchForCalendar.add(Calendar.HOUR_OF_DAY, 36);
- String searchFor = ISO_8601_2000.format(searchForCalendar.getTime());
+ String searchFor = new SimpleDateFormat(ISO_8601_2000).format(searchForCalendar.getTime());
// re-sorting descending for matching the actual index direction
Collections.sort(nodes, Collections.reverseOrder());
@@ -206,7 +207,7 @@ public class OrderedPropertyIndexDescend
Calendar searchForCalendar = (Calendar) start.clone();
searchForCalendar.add(Calendar.HOUR_OF_DAY, 36);
- String searchFor = ISO_8601_2000.format(searchForCalendar.getTime());
+ String searchFor = new SimpleDateFormat(ISO_8601_2000).format(searchForCalendar.getTime());
// re-sorting descending for matching the actual index direction
Collections.sort(nodes, Collections.reverseOrder());
@@ -251,7 +252,7 @@ public class OrderedPropertyIndexDescend
Calendar searchForCalendar = (Calendar) start.clone();
searchForCalendar.add(Calendar.HOUR_OF_DAY, -36);
- String searchFor = ISO_8601_2000.format(searchForCalendar.getTime());
+ String searchFor = new SimpleDateFormat(ISO_8601_2000).format(searchForCalendar.getTime());
Map<String, PropertyValue> filter = ImmutableMap.of(ORDERED_PROPERTY,
PropertyValues.newDate(searchFor));
Iterator<? extends ResultRow> results = executeQuery(
@@ -291,7 +292,7 @@ public class OrderedPropertyIndexDescend
Calendar searchForCalendar = (Calendar) start.clone();
searchForCalendar.add(Calendar.HOUR_OF_DAY, -36);
- String searchFor = ISO_8601_2000.format(searchForCalendar.getTime());
+ String searchFor = new SimpleDateFormat(ISO_8601_2000).format(searchForCalendar.getTime());
Map<String, PropertyValue> filter = ImmutableMap.of(ORDERED_PROPERTY,
PropertyValues.newDate(searchFor));
Iterator<? extends ResultRow> results = executeQuery(
@@ -334,7 +335,7 @@ public class OrderedPropertyIndexDescend
Calendar searchForCalendar = (Calendar) start.clone();
searchForCalendar.add(Calendar.HOUR_OF_DAY, 36);
- String searchFor = ISO_8601_2000.format(searchForCalendar.getTime());
+ String searchFor = new SimpleDateFormat(ISO_8601_2000).format(searchForCalendar.getTime());
// re-sorting descending for matching the actual index direction
Collections.sort(nodes, Collections.reverseOrder());
@@ -372,12 +373,13 @@ public class OrderedPropertyIndexDescend
Calendar searchForCalendarStart = (Calendar) start.clone();
searchForCalendarStart.add(Calendar.HOUR_OF_DAY, 36);
- String searchForStart = ISO_8601_2000.format(searchForCalendarStart.getTime());
+ SimpleDateFormat sdf = new SimpleDateFormat(ISO_8601_2000);
+ String searchForStart = sdf.format(searchForCalendarStart.getTime());
Calendar endCalendar = Calendar.getInstance();
- endCalendar.setTime(ISO_8601_2000.parse(nodes.get(nodes.size() - 1).getValue()));
+ endCalendar.setTime(sdf.parse(nodes.get(nodes.size() - 1).getValue()));
endCalendar.add(Calendar.HOUR_OF_DAY, -36);
- String searchForEnd = ISO_8601_2000.format(endCalendar.getTime());
+ String searchForEnd = sdf.format(endCalendar.getTime());
Map<String, PropertyValue> filter = ImmutableMap.of("start",
PropertyValues.newDate(searchForStart), "end", PropertyValues.newDate(searchForEnd));
@@ -432,12 +434,13 @@ public class OrderedPropertyIndexDescend
Calendar searchForCalendarStart = (Calendar) start.clone();
searchForCalendarStart.add(Calendar.HOUR_OF_DAY, 36);
- String searchForStart = ISO_8601_2000.format(searchForCalendarStart.getTime());
+ SimpleDateFormat sdf = new SimpleDateFormat(ISO_8601_2000);
+ String searchForStart = sdf.format(searchForCalendarStart.getTime());
Calendar endCalendar = Calendar.getInstance();
- endCalendar.setTime(ISO_8601_2000.parse(nodes.get(nodes.size() - 1).getValue()));
+ endCalendar.setTime(sdf.parse(nodes.get(nodes.size() - 1).getValue()));
endCalendar.add(Calendar.HOUR_OF_DAY, -36);
- String searchForEnd = ISO_8601_2000.format(endCalendar.getTime());
+ String searchForEnd = sdf.format(endCalendar.getTime());
Map<String, PropertyValue> filter = ImmutableMap.of("start",
PropertyValues.newDate(searchForStart), "end", PropertyValues.newDate(searchForEnd));
@@ -479,12 +482,13 @@ public class OrderedPropertyIndexDescend
Calendar searchForCalendarStart = (Calendar) start.clone();
searchForCalendarStart.add(Calendar.HOUR_OF_DAY, 36);
- String searchForStart = ISO_8601_2000.format(searchForCalendarStart.getTime());
+ SimpleDateFormat sdf = new SimpleDateFormat(ISO_8601_2000);
+ String searchForStart = sdf.format(searchForCalendarStart.getTime());
Calendar endCalendar = Calendar.getInstance();
- endCalendar.setTime(ISO_8601_2000.parse(nodes.get(nodes.size() - 1).getValue()));
+ endCalendar.setTime(sdf.parse(nodes.get(nodes.size() - 1).getValue()));
endCalendar.add(Calendar.HOUR_OF_DAY, -36);
- String searchForEnd = ISO_8601_2000.format(endCalendar.getTime());
+ String searchForEnd = sdf.format(endCalendar.getTime());
Map<String, PropertyValue> filter = ImmutableMap.of("start",
PropertyValues.newDate(searchForStart), "end", PropertyValues.newDate(searchForEnd));
@@ -526,12 +530,13 @@ public class OrderedPropertyIndexDescend
Calendar searchForCalendarStart = (Calendar) start.clone();
searchForCalendarStart.add(Calendar.HOUR_OF_DAY, 36);
- String searchForStart = ISO_8601_2000.format(searchForCalendarStart.getTime());
+ SimpleDateFormat sdf = new SimpleDateFormat(ISO_8601_2000);
+ String searchForStart = sdf.format(searchForCalendarStart.getTime());
Calendar endCalendar = Calendar.getInstance();
- endCalendar.setTime(ISO_8601_2000.parse(nodes.get(nodes.size() - 1).getValue()));
+ endCalendar.setTime(sdf.parse(nodes.get(nodes.size() - 1).getValue()));
endCalendar.add(Calendar.HOUR_OF_DAY, -36);
- String searchForEnd = ISO_8601_2000.format(endCalendar.getTime());
+ String searchForEnd = sdf.format(endCalendar.getTime());
Map<String, PropertyValue> filter = ImmutableMap.of("start",
PropertyValues.newDate(searchForStart), "end", PropertyValues.newDate(searchForEnd));
Modified: jackrabbit/oak/branches/1.0/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/index/property/OrderedPropertyIndexQueryTest.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/branches/1.0/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/index/property/OrderedPropertyIndexQueryTest.java?rev=1602124&r1=1602123&r2=1602124&view=diff
==============================================================================
--- jackrabbit/oak/branches/1.0/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/index/property/OrderedPropertyIndexQueryTest.java (original)
+++ jackrabbit/oak/branches/1.0/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/index/property/OrderedPropertyIndexQueryTest.java Thu Jun 12 11:21:53 2014
@@ -25,6 +25,7 @@ import static org.apache.jackrabbit.oak.
import static org.junit.Assert.assertNotNull;
import java.text.ParseException;
+import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Collections;
import java.util.Iterator;
@@ -33,6 +34,7 @@ import java.util.Map;
import javax.jcr.RepositoryException;
+
import org.apache.jackrabbit.JcrConstants;
import org.apache.jackrabbit.oak.api.CommitFailedException;
import org.apache.jackrabbit.oak.api.PropertyValue;
@@ -170,7 +172,7 @@ public class OrderedPropertyIndexQueryTe
Calendar searchForCalendar = (Calendar) start.clone();
searchForCalendar.add(Calendar.HOUR_OF_DAY, 36);
- String searchFor = ISO_8601_2000.format(searchForCalendar.getTime());
+ String searchFor = new SimpleDateFormat(ISO_8601_2000).format(searchForCalendar.getTime());
Map<String, PropertyValue> filter = ImmutableMap.of(ORDERED_PROPERTY,
PropertyValues.newDate(searchFor));
Iterator<? extends ResultRow> results = executeQuery(
@@ -209,7 +211,7 @@ public class OrderedPropertyIndexQueryTe
Calendar searchForCalendar = (Calendar) start.clone();
searchForCalendar.add(Calendar.HOUR_OF_DAY, 36);
- String searchFor = ISO_8601_2000.format(searchForCalendar.getTime());
+ String searchFor = new SimpleDateFormat(ISO_8601_2000).format(searchForCalendar.getTime());
Map<String, PropertyValue> filter = ImmutableMap.of(ORDERED_PROPERTY,
PropertyValues.newDate(searchFor));
Iterator<? extends ResultRow> results = executeQuery(
@@ -227,8 +229,6 @@ public class OrderedPropertyIndexQueryTe
/**
* test the range query in case of '<' condition
*
- * in this case as we're ascending we're expecting an empty resultset with the proper
- * provider. not the lowcost one.
* @throws Exception
*/
@Test
@@ -251,7 +251,7 @@ public class OrderedPropertyIndexQueryTe
Calendar searchForCalendar = (Calendar) start.clone();
searchForCalendar.add(Calendar.HOUR_OF_DAY, -36);
- String searchFor = ISO_8601_2000.format(searchForCalendar.getTime());
+ String searchFor = new SimpleDateFormat(ISO_8601_2000).format(searchForCalendar.getTime());
// re-sorting ascending as the index is ASC and the results will be returned as ASC
Collections.sort(nodes);
@@ -307,7 +307,7 @@ public class OrderedPropertyIndexQueryTe
Calendar searchForCalendar = (Calendar) start.clone();
searchForCalendar.add(Calendar.HOUR_OF_DAY, -36);
- String searchFor = ISO_8601_2000.format(searchForCalendar.getTime());
+ String searchFor = new SimpleDateFormat(ISO_8601_2000).format(searchForCalendar.getTime());
// re-sorting ascending as the index is ASC and the results will be returned as ASC
Collections.sort(nodes);
@@ -614,7 +614,7 @@ public class OrderedPropertyIndexQueryTe
Calendar searchForCalendar = (Calendar) start.clone();
searchForCalendar.add(Calendar.HOUR_OF_DAY, 36);
- String searchFor = ISO_8601_2000.format(searchForCalendar.getTime());
+ String searchFor = new SimpleDateFormat(ISO_8601_2000).format(searchForCalendar.getTime());
Iterator<? extends ResultRow> results = executeQuery(String.format(query, searchFor), SQL2,
null).getRows().iterator();
Iterator<ValuePathTuple> filtered = Iterables.filter(nodes,
@@ -648,12 +648,13 @@ public class OrderedPropertyIndexQueryTe
Calendar searchForCalendarStart = (Calendar) start.clone();
searchForCalendarStart.add(Calendar.HOUR_OF_DAY, 36);
- String searchForStart = ISO_8601_2000.format(searchForCalendarStart.getTime());
+ SimpleDateFormat sdf = new SimpleDateFormat(ISO_8601_2000);
+ String searchForStart = sdf.format(searchForCalendarStart.getTime());
Calendar endCalendar = Calendar.getInstance();
- endCalendar.setTime(ISO_8601_2000.parse(nodes.get(nodes.size() - 1).getValue()));
+ endCalendar.setTime(sdf.parse(nodes.get(nodes.size() - 1).getValue()));
endCalendar.add(Calendar.HOUR_OF_DAY, -36);
- String searchForEnd = ISO_8601_2000.format(endCalendar.getTime());
+ String searchForEnd = sdf.format(endCalendar.getTime());
Map<String, PropertyValue> filter = ImmutableMap.of("start",
PropertyValues.newDate(searchForStart), "end", PropertyValues.newDate(searchForEnd));
@@ -693,12 +694,13 @@ public class OrderedPropertyIndexQueryTe
Calendar searchForCalendarStart = (Calendar) start.clone();
searchForCalendarStart.add(Calendar.HOUR_OF_DAY, 36);
- String searchForStart = ISO_8601_2000.format(searchForCalendarStart.getTime());
+ SimpleDateFormat sdf = new SimpleDateFormat(ISO_8601_2000);
+ String searchForStart = sdf.format(searchForCalendarStart.getTime());
Calendar endCalendar = Calendar.getInstance();
- endCalendar.setTime(ISO_8601_2000.parse(nodes.get(nodes.size() - 1).getValue()));
+ endCalendar.setTime(sdf.parse(nodes.get(nodes.size() - 1).getValue()));
endCalendar.add(Calendar.HOUR_OF_DAY, -36);
- String searchForEnd = ISO_8601_2000.format(endCalendar.getTime());
+ String searchForEnd = sdf.format(endCalendar.getTime());
Map<String, PropertyValue> filter = ImmutableMap.of("start",
PropertyValues.newDate(searchForStart), "end", PropertyValues.newDate(searchForEnd));
@@ -738,12 +740,13 @@ public class OrderedPropertyIndexQueryTe
Calendar searchForCalendarStart = (Calendar) start.clone();
searchForCalendarStart.add(Calendar.HOUR_OF_DAY, 36);
- String searchForStart = ISO_8601_2000.format(searchForCalendarStart.getTime());
+ SimpleDateFormat sdf = new SimpleDateFormat(ISO_8601_2000);
+ String searchForStart = sdf.format(searchForCalendarStart.getTime());
Calendar endCalendar = Calendar.getInstance();
- endCalendar.setTime(ISO_8601_2000.parse(nodes.get(nodes.size() - 1).getValue()));
+ endCalendar.setTime(sdf.parse(nodes.get(nodes.size() - 1).getValue()));
endCalendar.add(Calendar.HOUR_OF_DAY, -36);
- String searchForEnd = ISO_8601_2000.format(endCalendar.getTime());
+ String searchForEnd = sdf.format(endCalendar.getTime());
Map<String, PropertyValue> filter = ImmutableMap.of("start",
PropertyValues.newDate(searchForStart), "end", PropertyValues.newDate(searchForEnd));
@@ -753,10 +756,6 @@ public class OrderedPropertyIndexQueryTe
Iterator<ValuePathTuple> filtered = Iterables.filter(nodes,
new ValuePathTuple.BetweenPredicate(searchForStart, searchForEnd, false, true))
.iterator();
-
- filtered = Iterables.filter(nodes,
- new ValuePathTuple.BetweenPredicate(searchForStart, searchForEnd, false, true))
- .iterator();
assertRightOrder(Lists.newArrayList(filtered), results);
assertFalse("We should have looped throuhg all the results", results.hasNext());
@@ -784,15 +783,16 @@ public class OrderedPropertyIndexQueryTe
List<ValuePathTuple> nodes = addChildNodes(
generateOrderedDates(10, direction, start), test, direction, Type.DATE);
root.commit();
-
+
Calendar searchForCalendarStart = (Calendar) start.clone();
searchForCalendarStart.add(Calendar.HOUR_OF_DAY, 36);
- String searchForStart = ISO_8601_2000.format(searchForCalendarStart.getTime());
+ SimpleDateFormat sdf = new SimpleDateFormat(ISO_8601_2000);
+ String searchForStart = sdf.format(searchForCalendarStart.getTime());
Calendar endCalendar = Calendar.getInstance();
- endCalendar.setTime(ISO_8601_2000.parse(nodes.get(nodes.size() - 1).getValue()));
+ endCalendar.setTime(sdf.parse(nodes.get(nodes.size() - 1).getValue()));
endCalendar.add(Calendar.HOUR_OF_DAY, -36);
- String searchForEnd = ISO_8601_2000.format(endCalendar.getTime());
+ String searchForEnd = sdf.format(endCalendar.getTime());
Map<String, PropertyValue> filter = ImmutableMap.of("start",
PropertyValues.newDate(searchForStart), "end", PropertyValues.newDate(searchForEnd));
@@ -800,10 +800,6 @@ public class OrderedPropertyIndexQueryTe
.iterator();
Iterator<ValuePathTuple> filtered = Iterables.filter(nodes,
- new ValuePathTuple.BetweenPredicate(searchForStart, searchForEnd, false, true))
- .iterator();
-
- filtered = Iterables.filter(nodes,
new ValuePathTuple.BetweenPredicate(searchForStart, searchForEnd, true, true))
.iterator();
@@ -813,4 +809,4 @@ public class OrderedPropertyIndexQueryTe
setTravesalEnabled(true);
}
-}
+}
\ No newline at end of file