Modified: jackrabbit/oak/trunk/oak-search/src/main/java/org/apache/jackrabbit/oak/plugins/index/search/spi/editor/FulltextIndexEditorContext.java URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-search/src/main/java/org/apache/jackrabbit/oak/plugins/index/search/spi/editor/FulltextIndexEditorContext.java?rev=1841291&r1=1841290&r2=1841291&view=diff ============================================================================== --- jackrabbit/oak/trunk/oak-search/src/main/java/org/apache/jackrabbit/oak/plugins/index/search/spi/editor/FulltextIndexEditorContext.java (original) +++ jackrabbit/oak/trunk/oak-search/src/main/java/org/apache/jackrabbit/oak/plugins/index/search/spi/editor/FulltextIndexEditorContext.java Wed Sep 19 06:46:42 2018 @@ -29,9 +29,10 @@ import org.apache.jackrabbit.oak.plugins import org.apache.jackrabbit.oak.plugins.index.IndexingContext; import org.apache.jackrabbit.oak.plugins.index.search.ExtractedTextCache; import org.apache.jackrabbit.oak.plugins.index.search.IndexDefinition; -import org.apache.jackrabbit.oak.plugins.index.search.NodeStateCloner; import org.apache.jackrabbit.oak.plugins.index.search.PropertyUpdateCallback; import org.apache.jackrabbit.oak.plugins.index.search.ReindexOperations; +import org.apache.jackrabbit.oak.plugins.index.search.spi.binary.FulltextBinaryTextExtractor; +import org.apache.jackrabbit.oak.plugins.index.search.util.NodeStateCloner; import org.apache.jackrabbit.oak.spi.commit.CommitInfo; import org.apache.jackrabbit.oak.spi.state.NodeBuilder; import org.apache.jackrabbit.oak.spi.state.NodeState; @@ -57,13 +58,13 @@ public abstract class FulltextIndexEdito private static final PerfLogger PERF_LOGGER = new PerfLogger(LoggerFactory.getLogger(FulltextIndexEditorContext.class.getName() + ".perf")); - private IndexDefinition definition; + protected IndexDefinition definition; - private final NodeBuilder definitionBuilder; + protected final NodeBuilder definitionBuilder; - private final FulltextIndexWriterFactory indexWriterFactory; + private final FulltextIndexWriterFactory<D> indexWriterFactory; - private FulltextIndexWriter writer = null; + private FulltextIndexWriter<D> writer = null; private long indexedNodes; @@ -90,11 +91,11 @@ public abstract class FulltextIndexEdito private PropertyUpdateCallback propertyUpdateCallback; protected FulltextIndexEditorContext(NodeState root, NodeBuilder definition, - @Nullable IndexDefinition indexDefinition, - IndexUpdateCallback updateCallback, - FulltextIndexWriterFactory indexWriterFactory, - ExtractedTextCache extractedTextCache, - IndexingContext indexingContext, boolean asyncIndexing) { + @Nullable IndexDefinition indexDefinition, + IndexUpdateCallback updateCallback, + FulltextIndexWriterFactory indexWriterFactory, + ExtractedTextCache extractedTextCache, + IndexingContext indexingContext, boolean asyncIndexing) { this.root = root; this.indexingContext = checkNotNull(indexingContext); this.definitionBuilder = definition; @@ -113,12 +114,16 @@ public abstract class FulltextIndexEdito } } + public abstract IndexDefinition.Builder newDefinitionBuilder(); - protected abstract DocumentMaker<D> newDocumentMaker(IndexDefinition.IndexingRule rule, String path); + public abstract DocumentMaker<D> newDocumentMaker(IndexDefinition.IndexingRule rule, String path); - protected abstract FulltextBinaryTextExtractor createBinaryTextExtractor(ExtractedTextCache extractedTextCache, IndexDefinition definition, boolean reindex); + protected FulltextBinaryTextExtractor createBinaryTextExtractor(ExtractedTextCache extractedTextCache, + IndexDefinition definition, boolean reindex) { + return new FulltextBinaryTextExtractor(extractedTextCache, definition, reindex); + } - FulltextIndexWriter getWriter() throws IOException { + public FulltextIndexWriter<D> getWriter() throws IOException { if (writer == null) { //Lazy initialization so as to ensure that definition is based //on latest NodeBuilder state specially in case of reindexing @@ -136,14 +141,14 @@ public abstract class FulltextIndexEdito return propertyUpdateCallback; } - void setPropertyUpdateCallback(PropertyUpdateCallback propertyUpdateCallback) { + public void setPropertyUpdateCallback(PropertyUpdateCallback propertyUpdateCallback) { this.propertyUpdateCallback = propertyUpdateCallback; } /** * close writer if it's not null */ - void closeWriter() throws IOException { + public void closeWriter() throws IOException { Calendar currentTime = getCalendar(); final long start = PERF_LOGGER.start(); boolean indexUpdated = getWriter().close(currentTime.getTimeInMillis()); @@ -175,7 +180,7 @@ public abstract class FulltextIndexEdito } /** Only set for testing */ - static void setClock(Clock c) { + protected static void setClock(Clock c) { checkNotNull(c); clock = c; } @@ -188,7 +193,8 @@ public abstract class FulltextIndexEdito public void enableReindexMode(){ reindex = true; - ReindexOperations reindexOps = new ReindexOperations(root, definitionBuilder, definition.getIndexPath()); + ReindexOperations reindexOps = + new ReindexOperations(root, definitionBuilder, definition.getIndexPath(), newDefinitionBuilder()); definition = reindexOps.apply(indexDefnRewritten); } @@ -197,7 +203,7 @@ public abstract class FulltextIndexEdito return indexedNodes; } - boolean isAsyncIndexing() { + public boolean isAsyncIndexing() { return asyncIndexing; } @@ -205,7 +211,7 @@ public abstract class FulltextIndexEdito return indexedNodes; } - void indexUpdate() throws CommitFailedException { + public void indexUpdate() throws CommitFailedException { updateCallback.indexUpdate(); } @@ -213,7 +219,7 @@ public abstract class FulltextIndexEdito return definition; } - private FulltextBinaryTextExtractor getTextExtractor(){ + protected FulltextBinaryTextExtractor getTextExtractor(){ if (textExtractor == null && isAsyncIndexing()){ //Create lazily to ensure that if its reindex case then update definition is picked textExtractor = createBinaryTextExtractor(extractedTextCache, definition, reindex); @@ -240,7 +246,7 @@ public abstract class FulltextIndexEdito return uid; } - private static IndexDefinition createIndexDefinition(NodeState root, NodeBuilder definition, IndexingContext + private IndexDefinition createIndexDefinition(NodeState root, NodeBuilder definition, IndexingContext indexingContext, boolean asyncIndexing) { NodeState defnState = definition.getBaseState(); if (asyncIndexing && !IndexDefinition.isDisableStoredIndexDefinition()){ @@ -258,6 +264,10 @@ public abstract class FulltextIndexEdito "effective post reindexing", indexingContext.getIndexPath()); } } - return new IndexDefinition(root, defnState,indexingContext.getIndexPath()); + return newDefinitionBuilder() + .root(root) + .defn(defnState) + .indexPath(indexingContext.getIndexPath()) + .build(); } }
Modified: jackrabbit/oak/trunk/oak-search/src/main/java/org/apache/jackrabbit/oak/plugins/index/search/spi/editor/FulltextIndexWriterFactory.java URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-search/src/main/java/org/apache/jackrabbit/oak/plugins/index/search/spi/editor/FulltextIndexWriterFactory.java?rev=1841291&r1=1841290&r2=1841291&view=diff ============================================================================== --- jackrabbit/oak/trunk/oak-search/src/main/java/org/apache/jackrabbit/oak/plugins/index/search/spi/editor/FulltextIndexWriterFactory.java (original) +++ jackrabbit/oak/trunk/oak-search/src/main/java/org/apache/jackrabbit/oak/plugins/index/search/spi/editor/FulltextIndexWriterFactory.java Wed Sep 19 06:46:42 2018 @@ -25,7 +25,7 @@ import org.apache.jackrabbit.oak.spi.sta /** * Factory class for {@link FulltextIndexWriter}s */ -public interface FulltextIndexWriterFactory { +public interface FulltextIndexWriterFactory<D> { /** * create a new index writer instance @@ -34,6 +34,6 @@ public interface FulltextIndexWriterFact * @param reindex whether or not reindex should be performed * @return an index writer */ - FulltextIndexWriter newInstance(IndexDefinition definition, NodeBuilder definitionBuilder, boolean reindex); + FulltextIndexWriter<D> newInstance(IndexDefinition definition, NodeBuilder definitionBuilder, boolean reindex); } Modified: jackrabbit/oak/trunk/oak-search/src/main/java/org/apache/jackrabbit/oak/plugins/index/search/spi/query/FulltextIndex.java URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-search/src/main/java/org/apache/jackrabbit/oak/plugins/index/search/spi/query/FulltextIndex.java?rev=1841291&r1=1841290&r2=1841291&view=diff ============================================================================== --- jackrabbit/oak/trunk/oak-search/src/main/java/org/apache/jackrabbit/oak/plugins/index/search/spi/query/FulltextIndex.java (original) +++ jackrabbit/oak/trunk/oak-search/src/main/java/org/apache/jackrabbit/oak/plugins/index/search/spi/query/FulltextIndex.java Wed Sep 19 06:46:42 2018 @@ -18,10 +18,12 @@ */ package org.apache.jackrabbit.oak.plugins.index.search.spi.query; +import java.io.IOException; import java.util.Collection; import java.util.Iterator; import java.util.List; import java.util.Map; +import java.util.function.Predicate; import javax.jcr.PropertyType; @@ -42,7 +44,6 @@ import org.apache.jackrabbit.oak.plugins import org.apache.jackrabbit.oak.plugins.index.search.SizeEstimator; import org.apache.jackrabbit.oak.plugins.index.search.spi.query.FulltextIndexPlanner.PlanResult; import org.apache.jackrabbit.oak.plugins.memory.PropertyValues; -import org.apache.jackrabbit.oak.query.facet.FacetResult; import org.apache.jackrabbit.oak.spi.query.Cursor; import org.apache.jackrabbit.oak.spi.query.Filter; import org.apache.jackrabbit.oak.spi.query.Filter.PropertyRestriction; @@ -53,6 +54,7 @@ import org.apache.jackrabbit.oak.spi.que import org.apache.jackrabbit.oak.spi.query.QueryLimits; import org.apache.jackrabbit.oak.spi.query.fulltext.FullTextExpression; import org.apache.jackrabbit.oak.spi.state.NodeState; +import org.jetbrains.annotations.NotNull; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -67,31 +69,34 @@ import static org.apache.jackrabbit.oak. * */ public abstract class FulltextIndex implements AdvancedQueryIndex, QueryIndex, NativeQueryIndex, - AdvanceFulltextQueryIndex { + AdvanceFulltextQueryIndex { private final Logger LOG = LoggerFactory .getLogger(getClass()); private final PerfLogger PERF_LOGGER = new PerfLogger(LoggerFactory.getLogger(getClass() + ".perf")); - static final String ATTR_PLAN_RESULT = "oak.fulltext.planResult"; + public static final String ATTR_PLAN_RESULT = "oak.fulltext.planResult"; - protected abstract FulltextIndexTracker getIndexTracker(); + protected abstract IndexNode acquireIndexNode(String indexPath); protected abstract String getType(); protected abstract SizeEstimator getSizeEstimator(IndexPlan plan); + protected abstract Predicate<NodeState> getIndexDefinitionPredicate(); + protected abstract String getFulltextRequestString(IndexPlan plan, IndexNode indexNode); @Override public List<IndexPlan> getPlans(Filter filter, List<OrderEntry> sortOrder, NodeState rootState) { - Collection<String> indexPaths = new IndexLookup(rootState).collectIndexNodePaths(filter, getType()); + Collection<String> indexPaths = new IndexLookup(rootState, getIndexDefinitionPredicate()) + .collectIndexNodePaths(filter); List<IndexPlan> plans = Lists.newArrayListWithCapacity(indexPaths.size()); for (String path : indexPaths) { IndexNode indexNode = null; try { - indexNode = getIndexTracker().acquireIndexNode(path, getType()); + indexNode = acquireIndexNode(path); if (indexNode != null) { IndexPlan plan = new FulltextIndexPlanner(indexNode, path, filter, sortOrder).getPlan(); @@ -124,8 +129,8 @@ public abstract class FulltextIndex impl @Override public String getPlanDescription(IndexPlan plan, NodeState root) { Filter filter = plan.getFilter(); - IndexNode index = getIndexTracker().acquireIndexNode(getPlanResult(plan).indexPath, getType()); - checkState(index != null, "The Fulltext of type " + getType() + " index is not available"); + IndexNode index = acquireIndexNode(plan); + checkState(index != null, "The fulltext index of type " + getType() + " index is not available"); try { FullTextExpression ft = filter.getFullTextConstraint(); StringBuilder sb = new StringBuilder(getType()).append(":"); @@ -148,7 +153,7 @@ public abstract class FulltextIndex impl } } - private static void addSyncIndexPlan(IndexPlan plan, StringBuilder sb) { + protected static void addSyncIndexPlan(IndexPlan plan, StringBuilder sb) { FulltextIndexPlanner.PlanResult pr = getPlanResult(plan); if (pr.hasPropertyIndexResult()) { FulltextIndexPlanner.PropertyIndexResult pres = pr.getPropertyIndexResult(); @@ -176,7 +181,7 @@ public abstract class FulltextIndex impl throw new UnsupportedOperationException("Not supported as implementing AdvancedQueryIndex"); } - private static boolean shouldInclude(String docPath, IndexPlan plan) { + protected static boolean shouldInclude(String docPath, IndexPlan plan) { String path = getPathRestriction(plan); boolean include = true; @@ -214,7 +219,7 @@ public abstract class FulltextIndex impl } protected IndexNode acquireIndexNode(IndexPlan plan) { - return getIndexTracker().acquireIndexNode(getPlanResult(plan).indexPath, getType()); + return acquireIndexNode(getPlanResult(plan).indexPath); } protected static String getIndexName(IndexPlan plan) { @@ -237,7 +242,7 @@ public abstract class FulltextIndex impl return getPropertyType(defn, pr.propertyName, typeFromRestriction); } - private static int getPropertyType(PropertyDefinition defn, String name, int defaultVal) { + protected static int getPropertyType(PropertyDefinition defn, String name, int defaultVal) { if (defn.isTypeDefined()) { return defn.getType(); } @@ -256,7 +261,7 @@ public abstract class FulltextIndex impl /** * Following logic is taken from org.apache.jackrabbit.core.query.lucene.JackrabbitQueryParser#parse(java.lang.String) */ - static String rewriteQueryText(String textsearch) { + protected static String rewriteQueryText(String textsearch) { // replace escaped ' with just ' StringBuilder rewritten = new StringBuilder(); // most query parsers recognize 'AND' and 'NOT' as @@ -301,36 +306,37 @@ public abstract class FulltextIndex impl return "/" + relativePath; } - static class FulltextResultRow { - final String path; - final double score; - final String suggestion; - final boolean isVirutal; - final Map<String, String> excerpts; - final String explanation; - final List<FacetResult.Facet> facets; + public static class FulltextResultRow { + public final String path; + public final double score; + public final String suggestion; + public final boolean isVirutal; + public final Map<String, String> excerpts; + public final String explanation; + private final FacetProvider facetProvider; - FulltextResultRow(String path, double score, Map<String, String> excerpts, List<FacetResult.Facet> facets, String explanation) { + public FulltextResultRow(String path, double score, Map<String, String> excerpts, + FacetProvider facetProvider, String explanation) { this.explanation = explanation; this.excerpts = excerpts; - this.facets = facets; + this.facetProvider = facetProvider; this.isVirutal = false; this.path = path; this.score = score; this.suggestion = null; } - FulltextResultRow(String suggestion, long weight) { + public FulltextResultRow(String suggestion, long weight) { this.isVirutal = true; this.path = "/"; this.score = weight; this.suggestion = suggestion; this.excerpts = null; - this.facets = null; + this.facetProvider = null; this.explanation = null; } - FulltextResultRow(String suggestion) { + public FulltextResultRow(String suggestion) { this(suggestion, 1); } @@ -338,13 +344,25 @@ public abstract class FulltextIndex impl public String toString() { return String.format("%s (%1.2f)", path, score); } + + public List<Facet> getFacets(int numberOfFacets, String columnName) throws IOException { + if (facetProvider == null) { + return null; + } + + return facetProvider.getFacets(numberOfFacets, columnName); + } + } + + public interface FacetProvider { + List<Facet> getFacets(int numberOfFacets, String columnName) throws IOException; } /** * A cursor over Fulltext results. The result includes the path, * and the jcr:score pseudo-property as returned by Lucene. */ - static class FulltextPathCursor implements Cursor { + protected static class FulltextPathCursor implements Cursor { private final Logger log = LoggerFactory.getLogger(getClass()); private static final int TRAVERSING_WARNING = Integer.getInteger("oak.traversing.warning", 10000); @@ -354,9 +372,9 @@ public abstract class FulltextIndex impl FulltextResultRow currentRow; private final SizeEstimator sizeEstimator; private long estimatedSize; - private int numberOfFacets; + private final int numberOfFacets; - FulltextPathCursor(final Iterator<FulltextResultRow> it, final IndexPlan plan, QueryLimits settings, SizeEstimator sizeEstimator) { + public FulltextPathCursor(final Iterator<FulltextResultRow> it, final IndexPlan plan, QueryLimits settings, SizeEstimator sizeEstimator) { pathPrefix = plan.getPathPrefix(); this.sizeEstimator = sizeEstimator; Iterator<String> pathIterator = new Iterator<String>() { @@ -445,18 +463,16 @@ public abstract class FulltextIndex impl } } if (columnName.startsWith(QueryConstants.REP_FACET)) { - List<FacetResult.Facet> facets = currentRow.facets; try { + List<Facet> facets = currentRow.getFacets(numberOfFacets, columnName); if (facets != null) { JsopWriter writer = new JsopBuilder(); writer.object(); - for (FacetResult.Facet f : facets) { + for (Facet f : facets) { writer.key(f.getLabel()).value(f.getCount()); } writer.endObject(); return PropertyValues.newString(writer.toString()); - } else { - return null; } } catch (Exception e) { throw new RuntimeException(e); @@ -477,7 +493,38 @@ public abstract class FulltextIndex impl } } - static String parseFacetField(String columnName) { + /** + * A query result facet, composed by its label and count. + */ + public static class Facet { + + private final String label; + private final int count; + + public Facet(String label, int count) { + this.label = label; + this.count = count; + } + + /** + * get the facet label + * @return a label + */ + @NotNull + public String getLabel() { + return label; + } + + /** + * get the facet count + * @return an integer + */ + public int getCount() { + return count; + } + } + + public static String parseFacetField(String columnName) { return columnName.substring(QueryConstants.REP_FACET.length() + 1, columnName.length() - 1); } } Modified: jackrabbit/oak/trunk/oak-search/src/main/java/org/apache/jackrabbit/oak/plugins/index/search/spi/query/IndexNodeManager.java URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-search/src/main/java/org/apache/jackrabbit/oak/plugins/index/search/spi/query/IndexNodeManager.java?rev=1841291&r1=1841290&r2=1841291&view=diff ============================================================================== --- jackrabbit/oak/trunk/oak-search/src/main/java/org/apache/jackrabbit/oak/plugins/index/search/spi/query/IndexNodeManager.java (original) +++ jackrabbit/oak/trunk/oak-search/src/main/java/org/apache/jackrabbit/oak/plugins/index/search/spi/query/IndexNodeManager.java Wed Sep 19 06:46:42 2018 @@ -25,7 +25,7 @@ import java.util.concurrent.locks.Reentr import org.apache.jackrabbit.oak.commons.PerfLogger; import org.apache.jackrabbit.oak.plugins.index.search.IndexDefinition; import org.apache.jackrabbit.oak.plugins.index.search.IndexNode; -import org.apache.jackrabbit.oak.plugins.index.search.ReaderRefreshPolicy; +import org.apache.jackrabbit.oak.plugins.index.search.update.ReaderRefreshPolicy; import org.apache.jackrabbit.oak.spi.state.NodeState; import org.jetbrains.annotations.Nullable; import org.slf4j.Logger; @@ -35,6 +35,9 @@ import static com.google.common.base.Pre import static org.apache.jackrabbit.oak.plugins.index.IndexConstants.ASYNC_PROPERTY_NAME; import static org.apache.jackrabbit.oak.plugins.index.IndexUtils.getAsyncLaneName; +/** + * Keeps track of the open read sessions for an index. + */ public abstract class IndexNodeManager { /** * Name of the hidden node under which information about the checkpoints Added: jackrabbit/oak/trunk/oak-search/src/main/java/org/apache/jackrabbit/oak/plugins/index/search/update/IndexUpdateListener.java URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-search/src/main/java/org/apache/jackrabbit/oak/plugins/index/search/update/IndexUpdateListener.java?rev=1841291&view=auto ============================================================================== --- jackrabbit/oak/trunk/oak-search/src/main/java/org/apache/jackrabbit/oak/plugins/index/search/update/IndexUpdateListener.java (added) +++ jackrabbit/oak/trunk/oak-search/src/main/java/org/apache/jackrabbit/oak/plugins/index/search/update/IndexUpdateListener.java Wed Sep 19 06:46:42 2018 @@ -0,0 +1,25 @@ +/* + * 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.search.update; + +public interface IndexUpdateListener extends ReaderRefreshPolicy { + + void updated(); +} Propchange: jackrabbit/oak/trunk/oak-search/src/main/java/org/apache/jackrabbit/oak/plugins/index/search/update/IndexUpdateListener.java ------------------------------------------------------------------------------ svn:eol-style = native Added: jackrabbit/oak/trunk/oak-search/src/main/java/org/apache/jackrabbit/oak/plugins/index/search/update/ReaderRefreshPolicy.java URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-search/src/main/java/org/apache/jackrabbit/oak/plugins/index/search/update/ReaderRefreshPolicy.java?rev=1841291&view=auto ============================================================================== --- jackrabbit/oak/trunk/oak-search/src/main/java/org/apache/jackrabbit/oak/plugins/index/search/update/ReaderRefreshPolicy.java (added) +++ jackrabbit/oak/trunk/oak-search/src/main/java/org/apache/jackrabbit/oak/plugins/index/search/update/ReaderRefreshPolicy.java Wed Sep 19 06:46:42 2018 @@ -0,0 +1,61 @@ +/* + * 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.search.update; + +/** + * The refresh policy interface. + * + * A class that implements this interface decides when to refresh an index, if + * there was a change. + */ +public interface ReaderRefreshPolicy { + + ReaderRefreshPolicy NEVER = new ReaderRefreshPolicy() { + @Override + public void refreshOnReadIfRequired(Runnable refreshCallback) { + //Never refresh + } + + @Override + public void refreshOnWriteIfRequired(Runnable refreshCallback) { + //Never refresh + } + }; + + /** + * Invoked before any query is performed to provide a chance for IndexNode + * to refresh the readers + * + * The index may or may not be updated when this method is invoked. + * + * @param refreshCallback callback to refresh the readers + */ + void refreshOnReadIfRequired(Runnable refreshCallback); + + /** + * Invoked after some writes have been performed and as a final step refresh + * request is being made. + * + * If invoked, it can be assumed that index has been updated. + * + * @param refreshCallback callback to refresh the readers + */ + void refreshOnWriteIfRequired(Runnable refreshCallback); +} Propchange: jackrabbit/oak/trunk/oak-search/src/main/java/org/apache/jackrabbit/oak/plugins/index/search/update/ReaderRefreshPolicy.java ------------------------------------------------------------------------------ svn:eol-style = native Added: jackrabbit/oak/trunk/oak-search/src/main/java/org/apache/jackrabbit/oak/plugins/index/search/update/RefreshOnReadPolicy.java URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-search/src/main/java/org/apache/jackrabbit/oak/plugins/index/search/update/RefreshOnReadPolicy.java?rev=1841291&view=auto ============================================================================== --- jackrabbit/oak/trunk/oak-search/src/main/java/org/apache/jackrabbit/oak/plugins/index/search/update/RefreshOnReadPolicy.java (added) +++ jackrabbit/oak/trunk/oak-search/src/main/java/org/apache/jackrabbit/oak/plugins/index/search/update/RefreshOnReadPolicy.java Wed Sep 19 06:46:42 2018 @@ -0,0 +1,102 @@ +/* + * 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.search.update; + +import java.util.concurrent.TimeUnit; +import java.util.concurrent.atomic.AtomicBoolean; + +import org.apache.jackrabbit.oak.stats.Clock; + +/** + * This policy ensures that any writes that have been done to index are made + * visible *before* any read is performed. + * + * Its meant as an alternative to {@link RefreshOnWritePolicy} and for "sync" + * indexes. For "nrt" indexes {@link TimedRefreshPolicy} should be preferred + * + * <p> + * The readers are not refreshed immediately upon write. Instead they would be + * refreshed if + * + * <ul> + * <li>Upon write if refreshDelta time has elapsed then readers would be + * refreshed</li> + * <li>Upon read if index is found to be updated then again readers would be + * refreshed</li> + * </ul> + * + * <p> + * This policy can result in some contention if index is being frequently + * updated and queried. + * + * *This is an experimental policy. Currently it causes high contention* + */ +public class RefreshOnReadPolicy implements ReaderRefreshPolicy, IndexUpdateListener { + private final AtomicBoolean dirty = new AtomicBoolean(); + private final Object lock = new Object(); + private final Clock clock; + private final long refreshDelta; + private volatile long lastRefreshTime; + + public RefreshOnReadPolicy(Clock clock, TimeUnit unit, long refreshDelta) { + this.clock = clock; + this.refreshDelta = unit.toMillis(refreshDelta); + } + + @Override + public void refreshOnReadIfRequired(Runnable refreshCallback) { + if (dirty.get()){ + refreshWithLock(refreshCallback, false); + } + } + + @Override + public void refreshOnWriteIfRequired(Runnable refreshCallback) { + long currentTime = clock.getTime(); + if (currentTime - lastRefreshTime > refreshDelta) { + //Do not set dirty instead directly refresh + refreshWithLock(refreshCallback, true); + } else { + synchronized (lock){ + //Needs to be done in a lock otherwise + //refreshWithLock would override this + dirty.set(true); + } + } + } + + @Override + public void updated() { + //Detect dirty based on call from refreshOnWriteIfRequired + //as that would *always* be called if the index has been updated + //And ensures that it gets calls after all changes for that index + //for that transaction got committed + } + + private void refreshWithLock(Runnable refreshCallback, boolean forceRefresh) { + synchronized (lock){ + if (dirty.get() || forceRefresh) { + refreshCallback.run(); + dirty.set(false); + lastRefreshTime = clock.getTime(); + } + } + } +} Propchange: jackrabbit/oak/trunk/oak-search/src/main/java/org/apache/jackrabbit/oak/plugins/index/search/update/RefreshOnReadPolicy.java ------------------------------------------------------------------------------ svn:eol-style = native Added: jackrabbit/oak/trunk/oak-search/src/main/java/org/apache/jackrabbit/oak/plugins/index/search/update/RefreshOnWritePolicy.java URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-search/src/main/java/org/apache/jackrabbit/oak/plugins/index/search/update/RefreshOnWritePolicy.java?rev=1841291&view=auto ============================================================================== --- jackrabbit/oak/trunk/oak-search/src/main/java/org/apache/jackrabbit/oak/plugins/index/search/update/RefreshOnWritePolicy.java (added) +++ jackrabbit/oak/trunk/oak-search/src/main/java/org/apache/jackrabbit/oak/plugins/index/search/update/RefreshOnWritePolicy.java Wed Sep 19 06:46:42 2018 @@ -0,0 +1,52 @@ +/* + * 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.search.update; + +import java.util.concurrent.atomic.AtomicBoolean; + +/** + * Policy which performs immediate refresh upon completion of writes. + * + * This is the default policy for synchronous indexes. + */ +public class RefreshOnWritePolicy implements ReaderRefreshPolicy, IndexUpdateListener { + private final AtomicBoolean dirty = new AtomicBoolean(); + + @Override + public void refreshOnReadIfRequired(Runnable refreshCallback) { + //As writer itself refreshes the index. No refresh done + //on read + } + + @Override + public void refreshOnWriteIfRequired(Runnable refreshCallback) { + //For sync indexing mode we refresh the reader immediately + //on the writer thread. So that any read call later sees upto date index + if (dirty.get()) { + refreshCallback.run(); + dirty.set(false); + } + } + + @Override + public void updated() { + dirty.set(true); + } +} Propchange: jackrabbit/oak/trunk/oak-search/src/main/java/org/apache/jackrabbit/oak/plugins/index/search/update/RefreshOnWritePolicy.java ------------------------------------------------------------------------------ svn:eol-style = native Added: jackrabbit/oak/trunk/oak-search/src/main/java/org/apache/jackrabbit/oak/plugins/index/search/update/TimedRefreshPolicy.java URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-search/src/main/java/org/apache/jackrabbit/oak/plugins/index/search/update/TimedRefreshPolicy.java?rev=1841291&view=auto ============================================================================== --- jackrabbit/oak/trunk/oak-search/src/main/java/org/apache/jackrabbit/oak/plugins/index/search/update/TimedRefreshPolicy.java (added) +++ jackrabbit/oak/trunk/oak-search/src/main/java/org/apache/jackrabbit/oak/plugins/index/search/update/TimedRefreshPolicy.java Wed Sep 19 06:46:42 2018 @@ -0,0 +1,69 @@ +/* + * 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.search.update; + +import java.util.concurrent.TimeUnit; +import java.util.concurrent.atomic.AtomicBoolean; + +import org.apache.jackrabbit.oak.stats.Clock; + +/** + * This policy refreshes the index (if changed) if it wasn't refreshed for a + * configured time. For example once per second. + * + * It is the default policy for asynchronous indexes. + */ +public class TimedRefreshPolicy implements ReaderRefreshPolicy, IndexUpdateListener { + private final AtomicBoolean dirty = new AtomicBoolean(); + private final Clock clock; + private final long refreshDelta; + private volatile long lastRefreshTime; + + public TimedRefreshPolicy(Clock clock, TimeUnit unit, long refreshDelta) { + this.clock = clock; + this.refreshDelta = unit.toMillis(refreshDelta); + } + + @Override + public void refreshOnReadIfRequired(Runnable refreshCallback) { + refreshIfRequired(refreshCallback); + } + + @Override + public void refreshOnWriteIfRequired(Runnable refreshCallback) { + refreshIfRequired(refreshCallback); + } + + @Override + public void updated() { + dirty.set(true); + } + + private void refreshIfRequired(Runnable refreshCallback) { + if (dirty.get()){ + long currentTime = clock.getTime(); + if (currentTime - lastRefreshTime > refreshDelta + && dirty.compareAndSet(true, false)){ + lastRefreshTime = currentTime; + refreshCallback.run(); + } + } + } +} Propchange: jackrabbit/oak/trunk/oak-search/src/main/java/org/apache/jackrabbit/oak/plugins/index/search/update/TimedRefreshPolicy.java ------------------------------------------------------------------------------ svn:eol-style = native Modified: jackrabbit/oak/trunk/oak-search/src/main/java/org/apache/jackrabbit/oak/plugins/index/search/util/ConfigUtil.java URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-search/src/main/java/org/apache/jackrabbit/oak/plugins/index/search/util/ConfigUtil.java?rev=1841291&r1=1841290&r2=1841291&view=diff ============================================================================== --- jackrabbit/oak/trunk/oak-search/src/main/java/org/apache/jackrabbit/oak/plugins/index/search/util/ConfigUtil.java (original) +++ jackrabbit/oak/trunk/oak-search/src/main/java/org/apache/jackrabbit/oak/plugins/index/search/util/ConfigUtil.java Wed Sep 19 06:46:42 2018 @@ -32,7 +32,7 @@ import org.jetbrains.annotations.Nullabl import static com.google.common.base.Preconditions.checkArgument; /** - * Utility class to retrieve configuration values for index definitions + * Utility class to retrieve configuration values for index definitions. */ public class ConfigUtil { Added: jackrabbit/oak/trunk/oak-search/src/main/java/org/apache/jackrabbit/oak/plugins/index/search/util/DataConversionUtil.java URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-search/src/main/java/org/apache/jackrabbit/oak/plugins/index/search/util/DataConversionUtil.java?rev=1841291&view=auto ============================================================================== --- jackrabbit/oak/trunk/oak-search/src/main/java/org/apache/jackrabbit/oak/plugins/index/search/util/DataConversionUtil.java (added) +++ jackrabbit/oak/trunk/oak-search/src/main/java/org/apache/jackrabbit/oak/plugins/index/search/util/DataConversionUtil.java Wed Sep 19 06:46:42 2018 @@ -0,0 +1,42 @@ +/* + * 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.search.util; + +import org.apache.jackrabbit.util.ISO8601; + +/** + * Utility class to convert data from one to another format. + */ +public class DataConversionUtil { + + /** + * Date values are saved with sec resolution + * @param date jcr data string + * @return date value in seconds + */ + public static Long dateToLong(String date){ + if( date == null){ + return null; + } + //TODO OAK-2204 - Should we change the precision to lower resolution + return ISO8601.parse(date).getTimeInMillis(); + } + +} + Propchange: jackrabbit/oak/trunk/oak-search/src/main/java/org/apache/jackrabbit/oak/plugins/index/search/util/DataConversionUtil.java ------------------------------------------------------------------------------ svn:eol-style = native Modified: jackrabbit/oak/trunk/oak-search/src/main/java/org/apache/jackrabbit/oak/plugins/index/search/util/FunctionIndexProcessor.java URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-search/src/main/java/org/apache/jackrabbit/oak/plugins/index/search/util/FunctionIndexProcessor.java?rev=1841291&r1=1841290&r2=1841291&view=diff ============================================================================== --- jackrabbit/oak/trunk/oak-search/src/main/java/org/apache/jackrabbit/oak/plugins/index/search/util/FunctionIndexProcessor.java (original) +++ jackrabbit/oak/trunk/oak-search/src/main/java/org/apache/jackrabbit/oak/plugins/index/search/util/FunctionIndexProcessor.java Wed Sep 19 06:46:42 2018 @@ -56,7 +56,7 @@ public class FunctionIndexProcessor { * @return the list of properties, for example ["name"] */ public static String[] getProperties(String[] functionCode) { - ArrayList<String> properties = new ArrayList<String>(); + ArrayList<String> properties = new ArrayList<>(); for(String token : functionCode) { if (token.startsWith("@")) { String propertyName = token.substring(1); @@ -75,7 +75,7 @@ public class FunctionIndexProcessor { * @return null, or the calculated value */ public static PropertyState tryCalculateValue(String path, NodeState state, String[] functionCode) { - Deque<PropertyState> stack = new ArrayDeque<PropertyState>(); + Deque<PropertyState> stack = new ArrayDeque<>(); for (int i = functionCode.length - 1; i > 0; i--) { String token = functionCode[i]; PropertyState ps; @@ -108,8 +108,8 @@ public class FunctionIndexProcessor { return functionDescription.split("\\*"); } - private static PropertyState calculateFunction(String functionName, - Deque<PropertyState> stack) { + private static PropertyState calculateFunction(String functionName, + Deque<PropertyState> stack) { PropertyState ps = stack.pop(); if ("coalesce".equals(functionName)) { // coalesce (a, b) => (a != null ? a : b) @@ -124,7 +124,7 @@ public class FunctionIndexProcessor { return ps; } Type<?> type = null; - ArrayList<Object> values = new ArrayList<Object>(ps.count()); + ArrayList<Object> values = new ArrayList<>(ps.count()); for (int i = 0; i < ps.count(); i++) { String s = ps.getValue(Type.STRING, i); Object x; @@ -156,8 +156,8 @@ public class FunctionIndexProcessor { return result; } - private static PropertyState getProperty(String path, NodeState state, - String propertyName) { + private static PropertyState getProperty(String path, NodeState state, + String propertyName) { if (PathUtils.getDepth(propertyName) != 1) { for(String n : PathUtils.elements(PathUtils.getParentPath(propertyName))) { state = state.getChildNode(n); @@ -169,10 +169,10 @@ public class FunctionIndexProcessor { } PropertyState ps; if (":localname".equals(propertyName)) { - ps = PropertyStates.createProperty("value", + ps = PropertyStates.createProperty("value", getLocalName(PathUtils.getName(path)), Type.STRING); } else if (":name".equals(propertyName)) { - ps = PropertyStates.createProperty("value", + ps = PropertyStates.createProperty("value", PathUtils.getName(path), Type.STRING); } else { ps = state.getProperty(propertyName); Modified: jackrabbit/oak/trunk/oak-search/src/main/java/org/apache/jackrabbit/oak/plugins/index/search/util/IndexDefinitionBuilder.java URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-search/src/main/java/org/apache/jackrabbit/oak/plugins/index/search/util/IndexDefinitionBuilder.java?rev=1841291&r1=1841290&r2=1841291&view=diff ============================================================================== --- jackrabbit/oak/trunk/oak-search/src/main/java/org/apache/jackrabbit/oak/plugins/index/search/util/IndexDefinitionBuilder.java (original) +++ jackrabbit/oak/trunk/oak-search/src/main/java/org/apache/jackrabbit/oak/plugins/index/search/util/IndexDefinitionBuilder.java Wed Sep 19 06:46:42 2018 @@ -32,8 +32,8 @@ import org.apache.jackrabbit.oak.api.Pro import org.apache.jackrabbit.oak.api.Tree; import org.apache.jackrabbit.oak.api.Type; import org.apache.jackrabbit.oak.commons.PathUtils; -import org.apache.jackrabbit.oak.plugins.index.search.FulltextIndexConstants; import org.apache.jackrabbit.oak.plugins.index.IndexConstants; +import org.apache.jackrabbit.oak.plugins.index.search.FulltextIndexConstants; import org.apache.jackrabbit.oak.plugins.tree.factories.TreeFactory; import org.apache.jackrabbit.oak.spi.filter.PathFilter; import org.apache.jackrabbit.oak.spi.state.EqualsDiff; @@ -47,6 +47,9 @@ import static org.apache.jackrabbit.oak. import static org.apache.jackrabbit.oak.api.Type.STRINGS; import static org.apache.jackrabbit.oak.plugins.memory.EmptyNodeState.EMPTY_NODE; +/** + * A utility to build index definitions. + */ public final class IndexDefinitionBuilder { private final NodeBuilder builder; private final Tree tree; @@ -72,6 +75,7 @@ public final class IndexDefinitionBuilde this.builder = nodeBuilder; this.initial = nodeBuilder.getNodeState(); this.tree = TreeFactory.createTree(builder); + tree.setProperty(FulltextIndexConstants.COMPAT_MODE, 2); tree.setProperty("async", "async"); setType(); tree.setProperty(JCR_PRIMARYTYPE, "oak:QueryIndexDefinition", NAME); Added: jackrabbit/oak/trunk/oak-search/src/main/java/org/apache/jackrabbit/oak/plugins/index/search/util/IndexDefinitionUtils.java URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-search/src/main/java/org/apache/jackrabbit/oak/plugins/index/search/util/IndexDefinitionUtils.java?rev=1841291&view=auto ============================================================================== --- jackrabbit/oak/trunk/oak-search/src/main/java/org/apache/jackrabbit/oak/plugins/index/search/util/IndexDefinitionUtils.java (added) +++ jackrabbit/oak/trunk/oak-search/src/main/java/org/apache/jackrabbit/oak/plugins/index/search/util/IndexDefinitionUtils.java Wed Sep 19 06:46:42 2018 @@ -0,0 +1,130 @@ +package org.apache.jackrabbit.oak.plugins.index.search.util; + +import java.util.Set; + +import org.apache.jackrabbit.oak.plugins.index.search.FulltextIndexConstants; +import org.apache.jackrabbit.oak.spi.state.NodeBuilder; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import static com.google.common.base.Preconditions.checkArgument; +import static org.apache.jackrabbit.JcrConstants.JCR_PRIMARYTYPE; +import static org.apache.jackrabbit.oak.api.Type.NAME; +import static org.apache.jackrabbit.oak.api.Type.STRINGS; +import static org.apache.jackrabbit.oak.plugins.index.IndexConstants.ASYNC_PROPERTY_NAME; +import static org.apache.jackrabbit.oak.plugins.index.IndexConstants.INDEX_DEFINITIONS_NODE_TYPE; +import static org.apache.jackrabbit.oak.plugins.index.IndexConstants.REINDEX_PROPERTY_NAME; +import static org.apache.jackrabbit.oak.plugins.index.IndexConstants.TYPE_PROPERTY_NAME; +import static org.apache.jackrabbit.oak.plugins.index.search.FulltextIndexConstants.EXCLUDE_PROPERTY_NAMES; +import static org.apache.jackrabbit.oak.plugins.index.search.FulltextIndexConstants.EXPERIMENTAL_STORAGE; +import static org.apache.jackrabbit.oak.plugins.index.search.FulltextIndexConstants.INCLUDE_PROPERTY_NAMES; +import static org.apache.jackrabbit.oak.plugins.index.search.FulltextIndexConstants.INCLUDE_PROPERTY_TYPES; +import static org.apache.jackrabbit.oak.plugins.index.search.FulltextIndexConstants.PERSISTENCE_FILE; +import static org.apache.jackrabbit.oak.plugins.index.search.FulltextIndexConstants.PERSISTENCE_NAME; +import static org.apache.jackrabbit.oak.plugins.index.search.FulltextIndexConstants.PERSISTENCE_PATH; +import static org.apache.jackrabbit.oak.plugins.memory.PropertyStates.createProperty; + +/** + * A second utility to build index definitions. + */ +public class IndexDefinitionUtils { + + public static NodeBuilder newFTIndexDefinition( + @NotNull NodeBuilder index, @NotNull String name, String type, + @Nullable Set<String> propertyTypes) { + return newFTIndexDefinition(index, name, type, propertyTypes, null, null, null); + } + + public static NodeBuilder newFTIndexDefinition( + @NotNull NodeBuilder index, @NotNull String name, String type, + @Nullable Set<String> propertyTypes, + @Nullable Set<String> excludes, @Nullable String async) { + return newFTIndexDefinition(index, type, name, propertyTypes, excludes, + async, null); + } + + public static NodeBuilder newFTIndexDefinition( + @NotNull NodeBuilder index, @NotNull String name, String type, + @Nullable Set<String> propertyTypes, + @Nullable Set<String> excludes, @Nullable String async, + @Nullable Boolean stored) { + if (index.hasChildNode(name)) { + return index.child(name); + } + index = index.child(name); + index.setProperty(JCR_PRIMARYTYPE, INDEX_DEFINITIONS_NODE_TYPE, NAME) + .setProperty(TYPE_PROPERTY_NAME, type) + .setProperty(REINDEX_PROPERTY_NAME, true); + if (async != null) { + index.setProperty(ASYNC_PROPERTY_NAME, async); + } + if (propertyTypes != null && !propertyTypes.isEmpty()) { + index.setProperty(createProperty(INCLUDE_PROPERTY_TYPES, + propertyTypes, STRINGS)); + } + if (excludes != null && !excludes.isEmpty()) { + index.setProperty(createProperty(EXCLUDE_PROPERTY_NAMES, excludes, + STRINGS)); + } + if (stored != null) { + index.setProperty(createProperty(EXPERIMENTAL_STORAGE, stored)); + } + return index; + } + + public static NodeBuilder newFTFileIndexDefinition( + @NotNull NodeBuilder index, @NotNull String name, String type, + @Nullable Set<String> propertyTypes, @NotNull String path) { + return newFTFileIndexDefinition(index, type, name, propertyTypes, null, + path, null); + } + + public static NodeBuilder newFTFileIndexDefinition( + @NotNull NodeBuilder index, @NotNull String name, String type, + @Nullable Set<String> propertyTypes, + @Nullable Set<String> excludes, @NotNull String path, + @Nullable String async) { + if (index.hasChildNode(name)) { + return index.child(name); + } + index = index.child(name); + index.setProperty(JCR_PRIMARYTYPE, INDEX_DEFINITIONS_NODE_TYPE, NAME) + .setProperty(TYPE_PROPERTY_NAME, type) + .setProperty(PERSISTENCE_NAME, PERSISTENCE_FILE) + .setProperty(PERSISTENCE_PATH, path) + .setProperty(REINDEX_PROPERTY_NAME, true); + if (async != null) { + index.setProperty(ASYNC_PROPERTY_NAME, async); + } + if (propertyTypes != null && !propertyTypes.isEmpty()) { + index.setProperty(createProperty(INCLUDE_PROPERTY_TYPES, + propertyTypes, STRINGS)); + } + if (excludes != null && !excludes.isEmpty()) { + index.setProperty(createProperty(EXCLUDE_PROPERTY_NAMES, excludes, + STRINGS)); + } + return index; + } + + public static NodeBuilder newFTPropertyIndexDefinition( + @NotNull NodeBuilder index, @NotNull String name, String type, + @NotNull Set<String> includes, + @NotNull String async) { + checkArgument(!includes.isEmpty(), "Fulltext property index " + + "requires explicit list of property names to be indexed"); + + index = index.child(name); + index.setProperty(JCR_PRIMARYTYPE, INDEX_DEFINITIONS_NODE_TYPE, NAME) + .setProperty(TYPE_PROPERTY_NAME, type) + .setProperty(REINDEX_PROPERTY_NAME, true); + index.setProperty(FulltextIndexConstants.FULL_TEXT_ENABLED, false); + index.setProperty(createProperty(INCLUDE_PROPERTY_NAMES, includes, STRINGS)); + + if (async != null) { + index.setProperty(ASYNC_PROPERTY_NAME, async); + } + return index; + } + +} Propchange: jackrabbit/oak/trunk/oak-search/src/main/java/org/apache/jackrabbit/oak/plugins/index/search/util/IndexDefinitionUtils.java ------------------------------------------------------------------------------ svn:eol-style = native Modified: jackrabbit/oak/trunk/oak-search/src/main/java/org/apache/jackrabbit/oak/plugins/index/search/util/IndexHelper.java URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-search/src/main/java/org/apache/jackrabbit/oak/plugins/index/search/util/IndexHelper.java?rev=1841291&r1=1841290&r2=1841291&view=diff ============================================================================== --- jackrabbit/oak/trunk/oak-search/src/main/java/org/apache/jackrabbit/oak/plugins/index/search/util/IndexHelper.java (original) +++ jackrabbit/oak/trunk/oak-search/src/main/java/org/apache/jackrabbit/oak/plugins/index/search/util/IndexHelper.java Wed Sep 19 06:46:42 2018 @@ -48,15 +48,17 @@ import static org.apache.jackrabbit.oak. import static org.apache.jackrabbit.oak.spi.security.user.UserConstants.GROUP_PROPERTY_NAMES; import static org.apache.jackrabbit.oak.spi.security.user.UserConstants.USER_PROPERTY_NAMES; +/** + * A helper class that helps decide what to (not) index. + */ public class IndexHelper { public static final Set<String> JR_PROPERTY_INCLUDES = of(TYPENAME_STRING, TYPENAME_BINARY); /** - * Nodes that represent content that shold not be tokenized (like UUIDs, + * Nodes that represent content that should not be tokenized (like UUIDs, * etc) - * */ private final static Set<String> NOT_TOKENIZED = newHashSet(JCR_UUID); @@ -69,24 +71,24 @@ public class IndexHelper { } public static NodeBuilder newFTIndexDefinition( - @NotNull NodeBuilder index, @NotNull String name, String type, - @Nullable Set<String> propertyTypes) { + @NotNull NodeBuilder index, @NotNull String name, String type, + @Nullable Set<String> propertyTypes) { return newFTIndexDefinition(index, name, type, propertyTypes, null, null, null); } public static NodeBuilder newFTIndexDefinition( - @NotNull NodeBuilder index, @NotNull String name, String type, - @Nullable Set<String> propertyTypes, - @Nullable Set<String> excludes, @Nullable String async) { + @NotNull NodeBuilder index, @NotNull String name, String type, + @Nullable Set<String> propertyTypes, + @Nullable Set<String> excludes, @Nullable String async) { return newFTIndexDefinition(index, type, name, propertyTypes, excludes, async, null); } public static NodeBuilder newFTIndexDefinition( - @NotNull NodeBuilder index, @NotNull String name, String type, - @Nullable Set<String> propertyTypes, - @Nullable Set<String> excludes, @Nullable String async, - @Nullable Boolean stored) { + @NotNull NodeBuilder index, @NotNull String name, String type, + @Nullable Set<String> propertyTypes, + @Nullable Set<String> excludes, @Nullable String async, + @Nullable Boolean stored) { if (index.hasChildNode(name)) { return index.child(name); } @@ -112,17 +114,17 @@ public class IndexHelper { } public static NodeBuilder newFTFileIndexDefinition( - @NotNull NodeBuilder index, @NotNull String name, String type, - @Nullable Set<String> propertyTypes, @NotNull String path) { + @NotNull NodeBuilder index, @NotNull String name, String type, + @Nullable Set<String> propertyTypes, @NotNull String path) { return newFTFileIndexDefinition(index, type, name, propertyTypes, null, path, null); } public static NodeBuilder newFTFileIndexDefinition( - @NotNull NodeBuilder index, @NotNull String name, String type, - @Nullable Set<String> propertyTypes, - @Nullable Set<String> excludes, @NotNull String path, - @Nullable String async) { + @NotNull NodeBuilder index, @NotNull String name, String type, + @Nullable Set<String> propertyTypes, + @Nullable Set<String> excludes, @NotNull String path, + @Nullable String async) { if (index.hasChildNode(name)) { return index.child(name); } @@ -147,9 +149,9 @@ public class IndexHelper { } public static NodeBuilder newFTPropertyIndexDefinition( - @NotNull NodeBuilder index, @NotNull String name, String type, - @NotNull Set<String> includes, - @NotNull String async) { + @NotNull NodeBuilder index, @NotNull String name, String type, + @NotNull Set<String> includes, + @NotNull String async) { checkArgument(!includes.isEmpty(), "Fulltext property index " + "requires explicit list of property names to be indexed"); @@ -167,8 +169,7 @@ public class IndexHelper { } /** - * Nodes that represent UUIDs and shold not be tokenized - * + * Nodes that represent UUIDs and should not be tokenized */ public static boolean skipTokenization(String name) { return NOT_TOKENIZED.contains(name); Added: jackrabbit/oak/trunk/oak-search/src/main/java/org/apache/jackrabbit/oak/plugins/index/search/util/NodeStateCloner.java URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-search/src/main/java/org/apache/jackrabbit/oak/plugins/index/search/util/NodeStateCloner.java?rev=1841291&view=auto ============================================================================== --- jackrabbit/oak/trunk/oak-search/src/main/java/org/apache/jackrabbit/oak/plugins/index/search/util/NodeStateCloner.java (added) +++ jackrabbit/oak/trunk/oak-search/src/main/java/org/apache/jackrabbit/oak/plugins/index/search/util/NodeStateCloner.java Wed Sep 19 06:46:42 2018 @@ -0,0 +1,58 @@ +/* + * 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.search.util; + +import org.apache.jackrabbit.oak.spi.state.ApplyDiff; +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 static org.apache.jackrabbit.oak.plugins.memory.EmptyNodeState.EMPTY_NODE; + +/** + * A utility class that allows to clone a node structure, excluding hidden nodes. + */ +public class NodeStateCloner { + + private NodeStateCloner() { + // a utility class + } + + public static NodeState cloneVisibleState(NodeState state){ + NodeBuilder builder = EMPTY_NODE.builder(); + new ApplyVisibleDiff(builder).apply(state); + return builder.getNodeState(); + } + + private static class ApplyVisibleDiff extends ApplyDiff { + public ApplyVisibleDiff(NodeBuilder builder) { + super(builder); + } + + @Override + public boolean childNodeAdded(String name, NodeState after) { + if (NodeStateUtils.isHidden(name)){ + return true; + } + return after.compareAgainstBaseState( + EMPTY_NODE, new ApplyVisibleDiff(builder.child(name))); + } + } +} Propchange: jackrabbit/oak/trunk/oak-search/src/main/java/org/apache/jackrabbit/oak/plugins/index/search/util/NodeStateCloner.java ------------------------------------------------------------------------------ svn:eol-style = native Modified: jackrabbit/oak/trunk/oak-search/src/main/java/org/apache/jackrabbit/oak/plugins/index/search/util/NodeStateCopyUtils.java URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-search/src/main/java/org/apache/jackrabbit/oak/plugins/index/search/util/NodeStateCopyUtils.java?rev=1841291&r1=1841290&r2=1841291&view=diff ============================================================================== --- jackrabbit/oak/trunk/oak-search/src/main/java/org/apache/jackrabbit/oak/plugins/index/search/util/NodeStateCopyUtils.java (original) +++ jackrabbit/oak/trunk/oak-search/src/main/java/org/apache/jackrabbit/oak/plugins/index/search/util/NodeStateCopyUtils.java Wed Sep 19 06:46:42 2018 @@ -39,9 +39,17 @@ import org.apache.jackrabbit.oak.spi.sta import static com.google.common.base.Preconditions.checkNotNull; import static org.apache.jackrabbit.oak.api.Type.NAMES; -final class NodeStateCopyUtils { +/** + * A utility class that allows to copy a new state (including children). + */ +public final class NodeStateCopyUtils { + private static final String OAK_CHILD_ORDER = ":childOrder"; + NodeStateCopyUtils() { + // a utility class + } + public static void copyToTree(NodeState state, Tree tree){ tree.setOrderableChildren(state.hasProperty(OAK_CHILD_ORDER)); copyProps(state, tree); Modified: jackrabbit/oak/trunk/oak-search/src/test/java/org/apache/jackrabbit/oak/plugins/index/search/AggregateTest.java URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-search/src/test/java/org/apache/jackrabbit/oak/plugins/index/search/AggregateTest.java?rev=1841291&r1=1841290&r2=1841291&view=diff ============================================================================== --- jackrabbit/oak/trunk/oak-search/src/test/java/org/apache/jackrabbit/oak/plugins/index/search/AggregateTest.java (original) +++ jackrabbit/oak/trunk/oak-search/src/test/java/org/apache/jackrabbit/oak/plugins/index/search/AggregateTest.java Wed Sep 19 06:46:42 2018 @@ -66,7 +66,7 @@ public class AggregateTest { private final TestCollector col = new TestCollector(); private final SimpleMapper mapper = new SimpleMapper(); private final NodeState root = INITIAL_CONTENT; - private NodeBuilder builder = root.builder(); + private final NodeBuilder builder = root.builder(); //~---------------------------------< Node Includes > Modified: jackrabbit/oak/trunk/oak-search/src/test/java/org/apache/jackrabbit/oak/plugins/index/search/ExtractedTextCacheTest.java URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-search/src/test/java/org/apache/jackrabbit/oak/plugins/index/search/ExtractedTextCacheTest.java?rev=1841291&r1=1841290&r2=1841291&view=diff ============================================================================== --- jackrabbit/oak/trunk/oak-search/src/test/java/org/apache/jackrabbit/oak/plugins/index/search/ExtractedTextCacheTest.java (original) +++ jackrabbit/oak/trunk/oak-search/src/test/java/org/apache/jackrabbit/oak/plugins/index/search/ExtractedTextCacheTest.java Wed Sep 19 06:46:42 2018 @@ -24,6 +24,7 @@ import org.apache.jackrabbit.oak.api.Blo import org.apache.jackrabbit.oak.plugins.index.fulltext.ExtractedText; import org.apache.jackrabbit.oak.plugins.index.fulltext.ExtractedText.ExtractionResult; import org.apache.jackrabbit.oak.plugins.index.fulltext.PreExtractedTextProvider; +import org.apache.jackrabbit.oak.plugins.index.search.ExtractedTextCache; import org.apache.jackrabbit.oak.plugins.index.search.spi.editor.FulltextIndexEditor; import org.apache.jackrabbit.oak.plugins.memory.ArrayBasedBlob; import org.junit.Test; @@ -122,7 +123,7 @@ public class ExtractedTextCacheTest { cache.setExtractedTextProvider(provider); when(provider.getText(anyString(), any(Blob.class))) - .thenReturn(new ExtractedText(ExtractionResult.SUCCESS, "bar")); + .thenReturn(new ExtractedText(ExtractionResult.SUCCESS, "bar")); Blob b = new IdBlob("hello", "a"); String text = cache.get("/a", "foo", b, true); assertEquals("bar", text); @@ -135,7 +136,7 @@ public class ExtractedTextCacheTest { cache.setExtractedTextProvider(provider); when(provider.getText(anyString(), any(Blob.class))) - .thenReturn(new ExtractedText(ExtractionResult.SUCCESS, "bar")); + .thenReturn(new ExtractedText(ExtractionResult.SUCCESS, "bar")); Blob b = new IdBlob("hello", "a"); String text = cache.get("/a", "foo", b, false); assertEquals("bar", text); @@ -194,7 +195,7 @@ public class ExtractedTextCacheTest { assertNull(cache.get("/a", "foo", b, false)); cache.putTimeout(b, ExtractedText.ERROR); assertNull("Cache returned non null text for blob with null content identity", - cache.get("/a", "foo", b, false)); + cache.get("/a", "foo", b, false)); } private static class IdBlob extends ArrayBasedBlob { Added: jackrabbit/oak/trunk/oak-search/src/test/java/org/apache/jackrabbit/oak/plugins/index/search/FieldNamesTest.java URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-search/src/test/java/org/apache/jackrabbit/oak/plugins/index/search/FieldNamesTest.java?rev=1841291&view=auto ============================================================================== --- jackrabbit/oak/trunk/oak-search/src/test/java/org/apache/jackrabbit/oak/plugins/index/search/FieldNamesTest.java (added) +++ jackrabbit/oak/trunk/oak-search/src/test/java/org/apache/jackrabbit/oak/plugins/index/search/FieldNamesTest.java Wed Sep 19 06:46:42 2018 @@ -0,0 +1,47 @@ +/* + * 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.search; + +import org.junit.Assert; +import org.junit.Test; + +public class FieldNamesTest { + @Test + public void checkPropertyFieldNames() { + assertPropertyFieldName("abc", true); + assertPropertyFieldName("a:b", true); + assertPropertyFieldName("a/b", true); + assertPropertyFieldName("a/b:c", true); + assertPropertyFieldName("a:b/c", true); + + assertPropertyFieldName(FieldNames.FULLTEXT_RELATIVE_NODE + "a", false); + assertPropertyFieldName(FieldNames.ANALYZED_FIELD_PREFIX + "a", false); + assertPropertyFieldName(FieldNames.FULLTEXT, false); + assertPropertyFieldName(":abc", false); + assertPropertyFieldName("abc_facet", false); + assertPropertyFieldName("a:b_facet", false); + assertPropertyFieldName("a/b_facet", false); + assertPropertyFieldName("a/b:c_facet", false); + assertPropertyFieldName("a:b/c_facet", false); + } + + private void assertPropertyFieldName(String name, boolean expected) { + Assert.assertEquals("Check for field name " + name + " doesn't meet expectation - " + expected, FieldNames.isPropertyField(name), expected); + } +} Propchange: jackrabbit/oak/trunk/oak-search/src/test/java/org/apache/jackrabbit/oak/plugins/index/search/FieldNamesTest.java ------------------------------------------------------------------------------ svn:eol-style = native Modified: jackrabbit/oak/trunk/oak-search/src/test/java/org/apache/jackrabbit/oak/plugins/index/search/IndexDefinitionTest.java URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-search/src/test/java/org/apache/jackrabbit/oak/plugins/index/search/IndexDefinitionTest.java?rev=1841291&r1=1841290&r2=1841291&view=diff ============================================================================== --- jackrabbit/oak/trunk/oak-search/src/test/java/org/apache/jackrabbit/oak/plugins/index/search/IndexDefinitionTest.java (original) +++ jackrabbit/oak/trunk/oak-search/src/test/java/org/apache/jackrabbit/oak/plugins/index/search/IndexDefinitionTest.java Wed Sep 19 06:46:42 2018 @@ -69,7 +69,7 @@ public class IndexDefinitionTest { private NodeState root = INITIAL_CONTENT; - private NodeBuilder builder = root.builder(); + private final NodeBuilder builder = root.builder(); @Test public void defaultConfig() throws Exception{ @@ -833,7 +833,7 @@ public class IndexDefinitionTest { //~----------------------------------< nodetype > - String testNodeTypeDefn = "[oak:TestMixA]\n" + + final String testNodeTypeDefn = "[oak:TestMixA]\n" + " mixin\n" + "\n" + "[oak:TestSuperType]\n" + Added: jackrabbit/oak/trunk/oak-search/src/test/java/org/apache/jackrabbit/oak/plugins/index/search/spi/binary/FulltextBinaryTextExtractorTest.java URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-search/src/test/java/org/apache/jackrabbit/oak/plugins/index/search/spi/binary/FulltextBinaryTextExtractorTest.java?rev=1841291&view=auto ============================================================================== --- jackrabbit/oak/trunk/oak-search/src/test/java/org/apache/jackrabbit/oak/plugins/index/search/spi/binary/FulltextBinaryTextExtractorTest.java (added) +++ jackrabbit/oak/trunk/oak-search/src/test/java/org/apache/jackrabbit/oak/plugins/index/search/spi/binary/FulltextBinaryTextExtractorTest.java Wed Sep 19 06:46:42 2018 @@ -0,0 +1,44 @@ +/* + * 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.search.spi.binary; + +import org.apache.jackrabbit.oak.plugins.index.search.ExtractedTextCache; +import org.apache.jackrabbit.oak.plugins.index.search.IndexDefinition; +import org.apache.jackrabbit.oak.spi.state.NodeBuilder; +import org.apache.jackrabbit.oak.spi.state.NodeState; +import org.junit.Test; + +import static org.apache.jackrabbit.oak.InitialContentHelper.INITIAL_CONTENT; +import static org.junit.Assert.assertTrue; + +public class FulltextBinaryTextExtractorTest { + private final NodeState root = INITIAL_CONTENT; + + private final NodeBuilder builder = root.builder(); + private final ExtractedTextCache cache = new ExtractedTextCache(1000, 10000); + + @Test + public void tikaConfigServiceLoader() throws Exception { + IndexDefinition idxDefn = new IndexDefinition(root, builder.getNodeState(), "/foo"); + FulltextBinaryTextExtractor extractor = new FulltextBinaryTextExtractor(cache, idxDefn, false); + assertTrue(extractor.getTikaConfig().getServiceLoader().isDynamic()); + } + +} \ No newline at end of file Propchange: jackrabbit/oak/trunk/oak-search/src/test/java/org/apache/jackrabbit/oak/plugins/index/search/spi/binary/FulltextBinaryTextExtractorTest.java ------------------------------------------------------------------------------ svn:eol-style = native Added: jackrabbit/oak/trunk/oak-search/src/test/java/org/apache/jackrabbit/oak/plugins/index/search/spi/binary/TikaParserConfigTest.java URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-search/src/test/java/org/apache/jackrabbit/oak/plugins/index/search/spi/binary/TikaParserConfigTest.java?rev=1841291&view=auto ============================================================================== --- jackrabbit/oak/trunk/oak-search/src/test/java/org/apache/jackrabbit/oak/plugins/index/search/spi/binary/TikaParserConfigTest.java (added) +++ jackrabbit/oak/trunk/oak-search/src/test/java/org/apache/jackrabbit/oak/plugins/index/search/spi/binary/TikaParserConfigTest.java Wed Sep 19 06:46:42 2018 @@ -0,0 +1,56 @@ +/* + * 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.search.spi.binary; + +import java.io.StringReader; +import java.util.Set; + +import org.apache.commons.io.input.ReaderInputStream; +import org.apache.tika.mime.MediaType; +import org.junit.Test; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; + +public class TikaParserConfigTest { + + @Test + public void emptyParser() throws Exception{ + String xml = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" + + "<properties>\n" + + " <detectors>\n" + + " <detector class=\"org.apache.tika.detect.TypeDetector\"/>\n" + + " </detectors>\n" + + " <parsers>\n" + + " <parser class=\"org.apache.tika.parser.DefaultParser\"/>\n" + + " <parser class=\"org.apache.tika.parser.EmptyParser\">\n" + + " <mime>application/x-archive</mime>\n" + + " <mime>application/x-bzip</mime>\n" + + " </parser>\n" + + " </parsers>\n" + + "</properties>"; + + Set<MediaType> types = TikaParserConfig.getNonIndexedMediaTypes( + new ReaderInputStream(new StringReader(xml), "UTF-8")); + assertEquals(2, types.size()); + assertTrue(types.contains(MediaType.parse("application/x-archive"))); + } + +} Propchange: jackrabbit/oak/trunk/oak-search/src/test/java/org/apache/jackrabbit/oak/plugins/index/search/spi/binary/TikaParserConfigTest.java ------------------------------------------------------------------------------ svn:eol-style = native Added: jackrabbit/oak/trunk/oak-search/src/test/java/org/apache/jackrabbit/oak/plugins/index/search/spi/query/FulltextIndexTest.java URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-search/src/test/java/org/apache/jackrabbit/oak/plugins/index/search/spi/query/FulltextIndexTest.java?rev=1841291&view=auto ============================================================================== --- jackrabbit/oak/trunk/oak-search/src/test/java/org/apache/jackrabbit/oak/plugins/index/search/spi/query/FulltextIndexTest.java (added) +++ jackrabbit/oak/trunk/oak-search/src/test/java/org/apache/jackrabbit/oak/plugins/index/search/spi/query/FulltextIndexTest.java Wed Sep 19 06:46:42 2018 @@ -0,0 +1,42 @@ +/* + * 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.search.spi.query; + +import org.junit.Test; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; + +public class FulltextIndexTest { + + @Test + public void testParseFacetField() { + String field = FulltextIndex.parseFacetField("rep:facet(text)"); + assertNotNull(field); + assertEquals("text", field); + field = FulltextIndex.parseFacetField("rep:facet(jcr:title)"); + assertNotNull(field); + assertEquals("jcr:title", field); + field = FulltextIndex.parseFacetField("rep:facet(jcr:primaryType)"); + assertNotNull(field); + assertEquals("jcr:primaryType", field); + + } +} + Propchange: jackrabbit/oak/trunk/oak-search/src/test/java/org/apache/jackrabbit/oak/plugins/index/search/spi/query/FulltextIndexTest.java ------------------------------------------------------------------------------ svn:eol-style = native Added: jackrabbit/oak/trunk/oak-search/src/test/java/org/apache/jackrabbit/oak/plugins/index/search/update/RecordingRunnable.java URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-search/src/test/java/org/apache/jackrabbit/oak/plugins/index/search/update/RecordingRunnable.java?rev=1841291&view=auto ============================================================================== --- jackrabbit/oak/trunk/oak-search/src/test/java/org/apache/jackrabbit/oak/plugins/index/search/update/RecordingRunnable.java (added) +++ jackrabbit/oak/trunk/oak-search/src/test/java/org/apache/jackrabbit/oak/plugins/index/search/update/RecordingRunnable.java Wed Sep 19 06:46:42 2018 @@ -0,0 +1,45 @@ +/* + * 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.search.update; + +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; + +class RecordingRunnable implements Runnable { + private boolean invoked; + @Override + public void run() { + invoked = true; + } + + public void assertInvokedAndReset(){ + assertTrue(invoked); + reset(); + } + + public void assertNotInvokedAndReset(){ + assertFalse(invoked); + reset(); + } + + public void reset(){ + invoked = false; + } +} Propchange: jackrabbit/oak/trunk/oak-search/src/test/java/org/apache/jackrabbit/oak/plugins/index/search/update/RecordingRunnable.java ------------------------------------------------------------------------------ svn:eol-style = native Added: jackrabbit/oak/trunk/oak-search/src/test/java/org/apache/jackrabbit/oak/plugins/index/search/update/RefreshOnReadPolicyTest.java URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-search/src/test/java/org/apache/jackrabbit/oak/plugins/index/search/update/RefreshOnReadPolicyTest.java?rev=1841291&view=auto ============================================================================== --- jackrabbit/oak/trunk/oak-search/src/test/java/org/apache/jackrabbit/oak/plugins/index/search/update/RefreshOnReadPolicyTest.java (added) +++ jackrabbit/oak/trunk/oak-search/src/test/java/org/apache/jackrabbit/oak/plugins/index/search/update/RefreshOnReadPolicyTest.java Wed Sep 19 06:46:42 2018 @@ -0,0 +1,83 @@ +/* + * 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.search.update; + +import java.util.concurrent.TimeUnit; + +import org.apache.jackrabbit.oak.stats.Clock; +import org.junit.Test; + +public class RefreshOnReadPolicyTest { + private final Clock clock = new Clock.Virtual(); + private final RecordingRunnable refreshCallback = new RecordingRunnable(); + private final RefreshOnReadPolicy policy = new RefreshOnReadPolicy(clock, TimeUnit.SECONDS, 1); + private final long refreshDelta = TimeUnit.SECONDS.toMillis(1) + 1; + + @Test + public void noRefreshOnReadIfNotUpdated() throws Exception{ + policy.refreshOnReadIfRequired(refreshCallback); + refreshCallback.assertNotInvokedAndReset(); + } + + @Test + public void refreshOnFirstWrite() throws Exception{ + clock.waitUntil(System.currentTimeMillis()); + + policy.refreshOnWriteIfRequired(refreshCallback); + refreshCallback.assertInvokedAndReset(); + } + + @Test + public void refreshOnReadAfterWrite() throws Exception{ + clock.waitUntil(System.currentTimeMillis()); + + policy.refreshOnWriteIfRequired(refreshCallback); + refreshCallback.reset(); + //Call again without change in time + policy.refreshOnWriteIfRequired(refreshCallback); + + //This time callback should not be invoked + refreshCallback.assertNotInvokedAndReset(); + + policy.refreshOnReadIfRequired(refreshCallback); + //On read the callback should be invoked + refreshCallback.assertInvokedAndReset(); + } + + @Test + public void refreshOnWriteWithTimeElapsed() throws Exception{ + clock.waitUntil(System.currentTimeMillis()); + + policy.refreshOnWriteIfRequired(refreshCallback); + refreshCallback.reset(); + + //Call again without change in time + policy.refreshOnWriteIfRequired(refreshCallback); + + //This time callback should not be invoked + refreshCallback.assertNotInvokedAndReset(); + + clock.waitUntil(clock.getTime() + refreshDelta); + + policy.refreshOnWriteIfRequired(refreshCallback); + refreshCallback.assertInvokedAndReset(); + } + +} \ No newline at end of file Propchange: jackrabbit/oak/trunk/oak-search/src/test/java/org/apache/jackrabbit/oak/plugins/index/search/update/RefreshOnReadPolicyTest.java ------------------------------------------------------------------------------ svn:eol-style = native
