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 ch...@apache.org on 2016/08/04 09:48:31 UTC

svn commit: r1755168 - in /jackrabbit/oak/trunk/oak-lucene/src: main/java/org/apache/jackrabbit/oak/plugins/index/lucene/ main/java/org/apache/jackrabbit/oak/plugins/index/lucene/reader/ test/java/org/apache/jackrabbit/oak/plugins/index/lucene/ test/ja...

Author: chetanm
Date: Thu Aug  4 09:48:31 2016
New Revision: 1755168

URL: http://svn.apache.org/viewvc?rev=1755168&view=rev
Log:
OAK-4566 - Multiplexing store support in Lucene Indexes

Support for multiple readers on query side via MultiReader feature of Lucene.

Added:
    jackrabbit/oak/trunk/oak-lucene/src/test/java/org/apache/jackrabbit/oak/plugins/index/lucene/MultiplexingLucenePropertyIndexTest.java   (with props)
Modified:
    jackrabbit/oak/trunk/oak-lucene/src/main/java/org/apache/jackrabbit/oak/plugins/index/lucene/IndexNode.java
    jackrabbit/oak/trunk/oak-lucene/src/main/java/org/apache/jackrabbit/oak/plugins/index/lucene/reader/DefaultIndexReader.java
    jackrabbit/oak/trunk/oak-lucene/src/main/java/org/apache/jackrabbit/oak/plugins/index/lucene/reader/DefaultIndexReaderFactory.java
    jackrabbit/oak/trunk/oak-lucene/src/main/java/org/apache/jackrabbit/oak/plugins/index/lucene/reader/LuceneIndexReader.java
    jackrabbit/oak/trunk/oak-lucene/src/test/java/org/apache/jackrabbit/oak/plugins/index/lucene/LucenePropertyIndexTest.java
    jackrabbit/oak/trunk/oak-lucene/src/test/java/org/apache/jackrabbit/oak/plugins/index/lucene/reader/DefaultIndexReaderFactoryTest.java

Modified: jackrabbit/oak/trunk/oak-lucene/src/main/java/org/apache/jackrabbit/oak/plugins/index/lucene/IndexNode.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-lucene/src/main/java/org/apache/jackrabbit/oak/plugins/index/lucene/IndexNode.java?rev=1755168&r1=1755167&r2=1755168&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-lucene/src/main/java/org/apache/jackrabbit/oak/plugins/index/lucene/IndexNode.java (original)
+++ jackrabbit/oak/trunk/oak-lucene/src/main/java/org/apache/jackrabbit/oak/plugins/index/lucene/IndexNode.java Thu Aug  4 09:48:31 2016
@@ -30,6 +30,8 @@ import org.apache.jackrabbit.oak.commons
 import org.apache.jackrabbit.oak.plugins.index.lucene.reader.LuceneIndexReader;
 import org.apache.jackrabbit.oak.plugins.index.lucene.reader.LuceneIndexReaderFactory;
 import org.apache.jackrabbit.oak.spi.state.NodeState;
+import org.apache.lucene.index.IndexReader;
+import org.apache.lucene.index.MultiReader;
 import org.apache.lucene.search.IndexSearcher;
 import org.apache.lucene.search.suggest.analyzing.AnalyzingInfixSuggester;
 import org.apache.lucene.store.Directory;
@@ -54,6 +56,8 @@ class IndexNode {
 
     private final ReadWriteLock lock = new ReentrantReadWriteLock();
 
+    private final IndexSearcher indexSearcher;
+
     private boolean closed = false;
 
     IndexNode(String name, IndexDefinition definition, List<LuceneIndexReader> readers)
@@ -62,6 +66,7 @@ class IndexNode {
         this.name = name;
         this.definition = definition;
         this.readers = readers;
+        this.indexSearcher = new IndexSearcher(createReader(readers));
     }
 
     String getName() {
@@ -73,7 +78,7 @@ class IndexNode {
     }
 
     IndexSearcher getSearcher() {
-        return getDefaultReader().getSearcher();
+        return indexSearcher;
     }
 
     Directory getSuggestDirectory() {
@@ -113,9 +118,20 @@ class IndexNode {
     }
 
     private LuceneIndexReader getDefaultReader(){
+        //TODO This is still required to support Suggester, Spellcheck etc
         Preconditions.checkArgument(readers.size() == 1, "Multiple readers provided. Default reader cannot be " +
                 "determined %s", readers);
         return readers.get(0);
     }
 
+    private IndexReader createReader(List<LuceneIndexReader> readers) {
+        if (readers.size() == 1){
+            return readers.get(0).getReader();
+        }
+        IndexReader[] readerArr = new IndexReader[readers.size()];
+        for (int i = 0; i < readerArr.length; i++) {
+            readerArr[i] = readers.get(i).getReader();
+        }
+        return new MultiReader(readerArr, true);
+    }
 }

Modified: jackrabbit/oak/trunk/oak-lucene/src/main/java/org/apache/jackrabbit/oak/plugins/index/lucene/reader/DefaultIndexReader.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-lucene/src/main/java/org/apache/jackrabbit/oak/plugins/index/lucene/reader/DefaultIndexReader.java?rev=1755168&r1=1755167&r2=1755168&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-lucene/src/main/java/org/apache/jackrabbit/oak/plugins/index/lucene/reader/DefaultIndexReader.java (original)
+++ jackrabbit/oak/trunk/oak-lucene/src/main/java/org/apache/jackrabbit/oak/plugins/index/lucene/reader/DefaultIndexReader.java Thu Aug  4 09:48:31 2016
@@ -28,7 +28,6 @@ import org.apache.jackrabbit.oak.plugins
 import org.apache.lucene.analysis.Analyzer;
 import org.apache.lucene.index.DirectoryReader;
 import org.apache.lucene.index.IndexReader;
-import org.apache.lucene.search.IndexSearcher;
 import org.apache.lucene.search.suggest.analyzing.AnalyzingInfixSuggester;
 import org.apache.lucene.store.Directory;
 
@@ -36,13 +35,11 @@ public class DefaultIndexReader implemen
     private final Directory directory;
     private final Directory suggestDirectory;
     private final IndexReader reader;
-    private final IndexSearcher searcher;
     private final AnalyzingInfixSuggester lookup;
 
     public DefaultIndexReader(Directory directory, @Nullable Directory suggestDirectory, Analyzer analyzer) throws IOException {
         this.directory = directory;
         this.reader = DirectoryReader.open(directory);
-        this.searcher = new IndexSearcher(reader);
         this.suggestDirectory = suggestDirectory;
         if (suggestDirectory != null) {
             this.lookup = SuggestHelper.getLookup(suggestDirectory, analyzer);
@@ -52,8 +49,8 @@ public class DefaultIndexReader implemen
     }
 
     @Override
-    public IndexSearcher getSearcher() {
-        return searcher;
+    public IndexReader getReader() {
+        return reader;
     }
 
     @Override

Modified: jackrabbit/oak/trunk/oak-lucene/src/main/java/org/apache/jackrabbit/oak/plugins/index/lucene/reader/DefaultIndexReaderFactory.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-lucene/src/main/java/org/apache/jackrabbit/oak/plugins/index/lucene/reader/DefaultIndexReaderFactory.java?rev=1755168&r1=1755167&r2=1755168&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-lucene/src/main/java/org/apache/jackrabbit/oak/plugins/index/lucene/reader/DefaultIndexReaderFactory.java (original)
+++ jackrabbit/oak/trunk/oak-lucene/src/main/java/org/apache/jackrabbit/oak/plugins/index/lucene/reader/DefaultIndexReaderFactory.java Thu Aug  4 09:48:31 2016
@@ -70,6 +70,8 @@ public class DefaultIndexReaderFactory i
             indexPath) throws IOException {
         ImmutableList.Builder<LuceneIndexReader> readers = ImmutableList.builder();
         LuceneIndexReader reader = createReader(mountInfoProvider.getDefaultMount(), definition, defnState, indexPath);
+        //Default mount is the first entry. This ensures that suggester, spellcheck can work on that untill they
+        //support multiple readers
         if (reader != null) {
             readers.add(reader);
         }

Modified: jackrabbit/oak/trunk/oak-lucene/src/main/java/org/apache/jackrabbit/oak/plugins/index/lucene/reader/LuceneIndexReader.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-lucene/src/main/java/org/apache/jackrabbit/oak/plugins/index/lucene/reader/LuceneIndexReader.java?rev=1755168&r1=1755167&r2=1755168&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-lucene/src/main/java/org/apache/jackrabbit/oak/plugins/index/lucene/reader/LuceneIndexReader.java (original)
+++ jackrabbit/oak/trunk/oak-lucene/src/main/java/org/apache/jackrabbit/oak/plugins/index/lucene/reader/LuceneIndexReader.java Thu Aug  4 09:48:31 2016
@@ -23,13 +23,13 @@ import java.io.Closeable;
 
 import javax.annotation.CheckForNull;
 
-import org.apache.lucene.search.IndexSearcher;
+import org.apache.lucene.index.IndexReader;
 import org.apache.lucene.search.suggest.analyzing.AnalyzingInfixSuggester;
 import org.apache.lucene.store.Directory;
 
 public interface LuceneIndexReader extends Closeable{
 
-    IndexSearcher getSearcher();
+    IndexReader getReader();
 
     @CheckForNull
     AnalyzingInfixSuggester getLookup();

Modified: jackrabbit/oak/trunk/oak-lucene/src/test/java/org/apache/jackrabbit/oak/plugins/index/lucene/LucenePropertyIndexTest.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-lucene/src/test/java/org/apache/jackrabbit/oak/plugins/index/lucene/LucenePropertyIndexTest.java?rev=1755168&r1=1755167&r2=1755168&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-lucene/src/test/java/org/apache/jackrabbit/oak/plugins/index/lucene/LucenePropertyIndexTest.java (original)
+++ jackrabbit/oak/trunk/oak-lucene/src/test/java/org/apache/jackrabbit/oak/plugins/index/lucene/LucenePropertyIndexTest.java Thu Aug  4 09:48:31 2016
@@ -84,6 +84,7 @@ import java.util.concurrent.Executors;
 import com.google.common.base.Charsets;
 import com.google.common.collect.ComparisonChain;
 import com.google.common.collect.ImmutableList;
+import com.google.common.collect.ImmutableSet;
 import com.google.common.collect.Iterables;
 import com.google.common.collect.Lists;
 import com.google.common.collect.Maps;
@@ -1363,6 +1364,7 @@ public class LucenePropertyIndexTest ext
     @Test
     public void sortQueriesWithStringAndLong() throws Exception {
         Tree idx = createIndex("test1", of("foo", "bar", "baz"));
+        idx.setProperty(createProperty(ORDERED_PROP_NAMES, ImmutableSet.of("foo", "baz"), STRINGS));
         Tree propIdx = idx.addChild(PROP_NODE).addChild("baz");
         propIdx.setProperty(LuceneIndexConstants.PROP_TYPE, PropertyType.TYPENAME_LONG);
         root.commit();
@@ -2394,7 +2396,7 @@ public class LucenePropertyIndexTest ext
         return createIndex(index, name, propNames);
     }
 
-    private Tree createIndex(Tree index, String name, Set<String> propNames) throws CommitFailedException {
+    static Tree createIndex(Tree index, String name, Set<String> propNames) throws CommitFailedException {
         Tree def = index.addChild(INDEX_DEFINITIONS_NAME).addChild(name);
         def.setProperty(JcrConstants.JCR_PRIMARYTYPE,
                 INDEX_DEFINITIONS_NODE_TYPE, Type.NAME);
@@ -2444,7 +2446,7 @@ public class LucenePropertyIndexTest ext
         return paths;
     }
 
-    private static List<String> getSortedPaths(List<Tuple2> tuples) {
+    static List<String> getSortedPaths(List<Tuple2> tuples) {
         Collections.sort(tuples);
         List<String> paths = Lists.newArrayListWithCapacity(tuples.size());
         for (Tuple2 t : tuples) {
@@ -2453,7 +2455,7 @@ public class LucenePropertyIndexTest ext
         return paths;
     }
 
-    private static List<Long> createLongs(int n){
+    static List<Long> createLongs(int n){
         List<Long> values = Lists.newArrayListWithCapacity(n);
         for (long i = 0; i < n; i++){
             values.add(i);
@@ -2472,7 +2474,7 @@ public class LucenePropertyIndexTest ext
         return values;
     }
 
-    private static List<String> createStrings(int n){
+    static List<String> createStrings(int n){
         List<String> values = Lists.newArrayListWithCapacity(n);
         for (long i = 0; i < n; i++){
             values.add(String.format("value%04d",i));
@@ -2514,12 +2516,12 @@ public class LucenePropertyIndexTest ext
         }
     }
 
-    private static class Tuple2 implements Comparable<Tuple2>{
+    static class Tuple2 implements Comparable<Tuple2>{
         final Comparable value;
         final Comparable value2;
         final String path;
 
-        private Tuple2(Comparable value, Comparable value2, String path) {
+        public Tuple2(Comparable value, Comparable value2, String path) {
             this.value = value;
             this.value2 = value2;
             this.path = path;

Added: jackrabbit/oak/trunk/oak-lucene/src/test/java/org/apache/jackrabbit/oak/plugins/index/lucene/MultiplexingLucenePropertyIndexTest.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-lucene/src/test/java/org/apache/jackrabbit/oak/plugins/index/lucene/MultiplexingLucenePropertyIndexTest.java?rev=1755168&view=auto
==============================================================================
--- jackrabbit/oak/trunk/oak-lucene/src/test/java/org/apache/jackrabbit/oak/plugins/index/lucene/MultiplexingLucenePropertyIndexTest.java (added)
+++ jackrabbit/oak/trunk/oak-lucene/src/test/java/org/apache/jackrabbit/oak/plugins/index/lucene/MultiplexingLucenePropertyIndexTest.java Thu Aug  4 09:48:31 2016
@@ -0,0 +1,260 @@
+/*
+ * 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.index.lucene;
+
+import java.io.File;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+import java.util.Random;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+
+import javax.jcr.PropertyType;
+
+import com.google.common.collect.ImmutableSet;
+import com.google.common.collect.Lists;
+import org.apache.commons.io.FileUtils;
+import org.apache.jackrabbit.oak.Oak;
+import org.apache.jackrabbit.oak.api.ContentRepository;
+import org.apache.jackrabbit.oak.api.Result;
+import org.apache.jackrabbit.oak.api.Tree;
+import org.apache.jackrabbit.oak.commons.PathUtils;
+import org.apache.jackrabbit.oak.plugins.index.lucene.reader.DefaultIndexReaderFactory;
+import org.apache.jackrabbit.oak.plugins.index.lucene.reader.LuceneIndexReader;
+import org.apache.jackrabbit.oak.plugins.index.lucene.reader.LuceneIndexReaderFactory;
+import org.apache.jackrabbit.oak.plugins.index.lucene.writer.DefaultIndexWriterFactory;
+import org.apache.jackrabbit.oak.plugins.index.lucene.writer.LuceneIndexWriter;
+import org.apache.jackrabbit.oak.plugins.index.lucene.writer.LuceneIndexWriterFactory;
+import org.apache.jackrabbit.oak.plugins.index.lucene.writer.MultiplexersLucene;
+import org.apache.jackrabbit.oak.plugins.index.nodetype.NodeTypeIndexProvider;
+import org.apache.jackrabbit.oak.plugins.index.property.PropertyIndexEditorProvider;
+import org.apache.jackrabbit.oak.plugins.memory.MemoryNodeStore;
+import org.apache.jackrabbit.oak.plugins.multiplex.SimpleMountInfoProvider;
+import org.apache.jackrabbit.oak.plugins.nodetype.write.InitialContent;
+import org.apache.jackrabbit.oak.query.AbstractQueryTest;
+import org.apache.jackrabbit.oak.query.NodeStateNodeTypeInfoProvider;
+import org.apache.jackrabbit.oak.query.QueryEngineSettings;
+import org.apache.jackrabbit.oak.query.ast.NodeTypeInfo;
+import org.apache.jackrabbit.oak.query.ast.NodeTypeInfoProvider;
+import org.apache.jackrabbit.oak.query.ast.Operator;
+import org.apache.jackrabbit.oak.query.ast.SelectorImpl;
+import org.apache.jackrabbit.oak.query.index.FilterImpl;
+import org.apache.jackrabbit.oak.spi.commit.Observer;
+import org.apache.jackrabbit.oak.spi.mount.MountInfoProvider;
+import org.apache.jackrabbit.oak.spi.query.PropertyValues;
+import org.apache.jackrabbit.oak.spi.query.QueryIndex;
+import org.apache.jackrabbit.oak.spi.query.QueryIndexProvider;
+import org.apache.jackrabbit.oak.spi.security.OpenSecurityProvider;
+import org.apache.jackrabbit.oak.spi.state.NodeBuilder;
+import org.apache.jackrabbit.oak.spi.state.NodeState;
+import org.apache.jackrabbit.oak.spi.state.NodeStateUtils;
+import org.apache.jackrabbit.oak.spi.state.NodeStore;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.rules.TemporaryFolder;
+
+import static com.google.common.collect.ImmutableList.of;
+import static org.apache.jackrabbit.oak.api.QueryEngine.NO_BINDINGS;
+import static org.apache.jackrabbit.oak.api.Type.STRINGS;
+import static org.apache.jackrabbit.oak.plugins.index.lucene.LuceneIndexConstants.ORDERED_PROP_NAMES;
+import static org.apache.jackrabbit.oak.plugins.index.lucene.LuceneIndexConstants.PROP_NODE;
+import static org.apache.jackrabbit.oak.plugins.index.lucene.LucenePropertyIndexTest.createIndex;
+import static org.apache.jackrabbit.oak.plugins.index.lucene.util.LuceneIndexHelper.newLucenePropertyIndexDefinition;
+import static org.apache.jackrabbit.oak.plugins.index.lucene.writer.MultiplexingIndexWriterTest.newDoc;
+import static org.apache.jackrabbit.oak.plugins.memory.EmptyNodeState.EMPTY_NODE;
+import static org.apache.jackrabbit.oak.plugins.memory.PropertyStates.createProperty;
+import static org.apache.jackrabbit.oak.plugins.nodetype.write.InitialContent.INITIAL_CONTENT;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+
+public class MultiplexingLucenePropertyIndexTest extends AbstractQueryTest {
+    private ExecutorService executorService = Executors.newFixedThreadPool(2);
+
+    @Rule
+    public TemporaryFolder temporaryFolder = new TemporaryFolder(new File("target"));
+
+    private NodeState initialContent = INITIAL_CONTENT;
+    private NodeBuilder builder = EMPTY_NODE.builder();
+    private MountInfoProvider mip = SimpleMountInfoProvider.newBuilder()
+            .mount("foo", "/libs", "/apps").build();
+    private NodeStore nodeStore;
+
+    @Override
+    protected ContentRepository createRepository() {
+        IndexCopier copier = null;
+        try {
+            copier = new IndexCopier(executorService, temporaryFolder.getRoot());
+        } catch (IOException e) {
+            throw new RuntimeException(e);
+        }
+        LuceneIndexEditorProvider editorProvider = new LuceneIndexEditorProvider(copier,
+                new ExtractedTextCache(10*FileUtils.ONE_MB, 100),
+                null,
+                mip);
+        LuceneIndexProvider provider = new LuceneIndexProvider(new IndexTracker(new DefaultIndexReaderFactory(mip, copier)));
+        nodeStore = new MemoryNodeStore();
+        return new Oak(nodeStore)
+                .with(new InitialContent())
+                .with(new OpenSecurityProvider())
+                .with((QueryIndexProvider) provider)
+                .with((Observer) provider)
+                .with(editorProvider)
+                .with(new PropertyIndexEditorProvider())
+                .with(new NodeTypeIndexProvider())
+                .createContentRepository();
+    }
+
+    @Test
+    public void numDocsIsSumOfAllReaders() throws Exception{
+        NodeBuilder defnBuilder = newLucenePropertyIndexDefinition(builder, "test", ImmutableSet.of("foo"), "async");
+        IndexDefinition defn = new IndexDefinition(initialContent, defnBuilder.getNodeState());
+
+        //1. Have 2 reader created by writes in 2 diff mounts
+        LuceneIndexWriterFactory factory = new DefaultIndexWriterFactory(mip, null);
+        LuceneIndexWriter writer = factory.newInstance(defn, builder, true);
+
+        writer.updateDocument("/content/en", newDoc("/content/en"));
+        writer.updateDocument("/libs/config", newDoc("/libs/config"));
+        writer.close(0);
+
+        //2. Construct the readers
+        LuceneIndexReaderFactory readerFactory = new DefaultIndexReaderFactory(mip, null);
+        List<LuceneIndexReader> readers = readerFactory.createReaders(defn, builder.getNodeState(),"/foo");
+
+        IndexNode node = new IndexNode("foo", defn, readers);
+
+        //3 Obtain the plan
+        FilterImpl filter = createFilter("nt:base");
+        filter.restrictProperty("foo", Operator.EQUAL, PropertyValues.newString("bar"));
+        IndexPlanner planner = new IndexPlanner(node, "/foo", filter, Collections.<QueryIndex.OrderEntry>emptyList());
+        QueryIndex.IndexPlan plan = planner.getPlan();
+
+        //Count should be sum of both readers
+        assertEquals(2, plan.getEstimatedEntryCount());
+    }
+
+    @Test
+    public void propertyIndex() throws Exception{
+        String idxName = "multitest";
+        createIndex(root.getTree("/"), idxName, Collections.singleton("foo"));
+        root.commit();
+
+        createPath("/libs/a").setProperty("foo", "bar");
+        createPath("/libs/b").setProperty("foo", "bar2");
+        createPath("/content/a").setProperty("foo", "bar");
+        root.commit();
+
+        //There should be 2 index dir due to mount
+        assertEquals(2, getIndexDirNames(idxName).size());
+
+        String barQuery = "select [jcr:path] from [nt:base] where [foo] = 'bar'";
+        assertQuery(barQuery, of("/libs/a", "/content/a"));
+
+        Result result = executeQuery(barQuery, SQL2, NO_BINDINGS);
+        assertTrue(result.getRows().iterator().hasNext());
+        assertEquals(2, result.getSize(Result.SizePrecision.FAST_APPROXIMATION, 100));
+
+        assertQuery("select [jcr:path] from [nt:base] where [foo] = 'bar2'", of("/libs/b"));
+    }
+
+    @Test
+    public void propertyIndexWithBatching() throws Exception{
+        String idxName = "multitest";
+        createIndex(root.getTree("/"), idxName, Collections.singleton("foo"));
+        root.commit();
+
+        int expectedSize = LucenePropertyIndex.LUCENE_QUERY_BATCH_SIZE * 2 * 2;
+        for (int i = 0; i < LucenePropertyIndex.LUCENE_QUERY_BATCH_SIZE * 2; i++) {
+            createPath("/libs/a"+i).setProperty("foo", "bar");
+            createPath("/content/a"+i).setProperty("foo", "bar");
+        }
+
+        root.commit();
+        assertEquals(2, getIndexDirNames(idxName).size());
+        assertResultSize("select [jcr:path] from [nt:base] where [foo] = 'bar'", SQL2, expectedSize);
+    }
+
+    @Test
+    public void sortQueriesWithStringAndLong() throws Exception {
+        Tree idx = createIndex(root.getTree("/"), "test1", ImmutableSet.of("foo", "bar", "baz"));
+        idx.setProperty(createProperty(ORDERED_PROP_NAMES, ImmutableSet.of("foo", "baz"), STRINGS));
+        Tree propIdx = idx.addChild(PROP_NODE).addChild("baz");
+        propIdx.setProperty(LuceneIndexConstants.PROP_TYPE, PropertyType.TYPENAME_LONG);
+        root.commit();
+
+        int firstPropSize = 25;
+        List<String> values = LucenePropertyIndexTest.createStrings(firstPropSize);
+        List<Long> longValues = LucenePropertyIndexTest.createLongs(LucenePropertyIndexTest.NUMBER_OF_NODES);
+        List<LucenePropertyIndexTest.Tuple2> tuples = Lists.newArrayListWithCapacity(values.size());
+        Random r = new Random();
+        Tree libs = createPath("/libs");
+        Tree content = createPath("/content");
+        for(int i = 0; i < values.size(); i++){
+            String val = values.get(r.nextInt(firstPropSize));
+            Tree base = (i % 2 == 0 ? libs : content);
+            Tree child = base.addChild("n"+i);
+            child.setProperty("foo", val);
+            child.setProperty("baz", longValues.get(i));
+            child.setProperty("bar", "baz");
+            tuples.add(new LucenePropertyIndexTest.Tuple2(val, longValues.get(i), child.getPath()));
+        }
+        root.commit();
+
+        assertOrderedQuery("select [jcr:path] from [nt:base] where [bar] = 'baz' order by [foo] asc, [baz] desc",
+                LucenePropertyIndexTest.getSortedPaths(tuples));
+    }
+
+    private List<String> getIndexDirNames(String indexName){
+        NodeState idxDefn = NodeStateUtils.getNode(nodeStore.getRoot(), "/oak:index/"+indexName);
+        List<String> names = new ArrayList<>();
+        for (String childName : idxDefn.getChildNodeNames()){
+            if (MultiplexersLucene.isIndexDirName(childName)){
+                names.add(childName);
+            }
+        }
+        return names;
+    }
+
+    private Tree createPath(String path){
+        Tree base = root.getTree("/");
+        for (String e : PathUtils.elements(path)){
+            base = base.addChild(e);
+        }
+        return base;
+    }
+
+    private FilterImpl createFilter(String nodeTypeName) {
+        NodeTypeInfoProvider nodeTypes = new NodeStateNodeTypeInfoProvider(initialContent);
+        NodeTypeInfo type = nodeTypes.getNodeTypeInfo(nodeTypeName);
+        SelectorImpl selector = new SelectorImpl(type, nodeTypeName);
+        return new FilterImpl(selector, "SELECT * FROM [" + nodeTypeName + "]", new QueryEngineSettings());
+    }
+
+    private void assertOrderedQuery(String sql, List<String> paths) {
+        assertOrderedQuery(sql, paths, SQL2, false);
+    }
+
+    private void assertOrderedQuery(String sql, List<String> paths, String language, boolean skipSort) {
+        List<String> result = executeQuery(sql, language, true, skipSort);
+        assertEquals(paths, result);
+    }
+}

Propchange: jackrabbit/oak/trunk/oak-lucene/src/test/java/org/apache/jackrabbit/oak/plugins/index/lucene/MultiplexingLucenePropertyIndexTest.java
------------------------------------------------------------------------------
    svn:eol-style = native

Modified: jackrabbit/oak/trunk/oak-lucene/src/test/java/org/apache/jackrabbit/oak/plugins/index/lucene/reader/DefaultIndexReaderFactoryTest.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-lucene/src/test/java/org/apache/jackrabbit/oak/plugins/index/lucene/reader/DefaultIndexReaderFactoryTest.java?rev=1755168&r1=1755167&r2=1755168&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-lucene/src/test/java/org/apache/jackrabbit/oak/plugins/index/lucene/reader/DefaultIndexReaderFactoryTest.java (original)
+++ jackrabbit/oak/trunk/oak-lucene/src/test/java/org/apache/jackrabbit/oak/plugins/index/lucene/reader/DefaultIndexReaderFactoryTest.java Thu Aug  4 09:48:31 2016
@@ -69,14 +69,14 @@ public class DefaultIndexReaderFactoryTe
         assertEquals(1, readers.size());
 
         LuceneIndexReader reader = readers.get(0);
-        assertNotNull(reader.getSearcher());
+        assertNotNull(reader.getReader());
         assertNull(reader.getSuggestDirectory());
         assertNull(reader.getLookup());
 
-        assertEquals(1, reader.getSearcher().getIndexReader().numDocs());
+        assertEquals(1, reader.getReader().numDocs());
 
         final AtomicBoolean closed = new AtomicBoolean();
-        reader.getSearcher().getIndexReader().addReaderClosedListener(new IndexReader.ReaderClosedListener() {
+        reader.getReader().addReaderClosedListener(new IndexReader.ReaderClosedListener() {
             @Override
             public void onClose(IndexReader reader) {
                 closed.set(true);
@@ -103,7 +103,7 @@ public class DefaultIndexReaderFactoryTe
         LuceneIndexReaderFactory readerFactory = new DefaultIndexReaderFactory(mip, null);
         List<LuceneIndexReader> readers = readerFactory.createReaders(defn, builder.getNodeState(),"/foo");
         LuceneIndexReader reader = readers.get(0);
-        assertNotNull(reader.getSearcher());
+        assertNotNull(reader.getReader());
         assertNotNull(reader.getSuggestDirectory());
         assertNotNull(reader.getLookup());
     }
@@ -142,7 +142,7 @@ public class DefaultIndexReaderFactoryTe
 
         //Suggester should be present for all though it may be empty
         for (LuceneIndexReader reader : readers){
-            assertNotNull(reader.getSearcher());
+            assertNotNull(reader.getReader());
             assertNotNull(reader.getSuggestDirectory());
             assertNotNull(reader.getLookup());
         }