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 to...@apache.org on 2018/05/24 13:07:54 UTC
svn commit: r1832166 [1/2] - in
/jackrabbit/oak/trunk/oak-search/src/main/java/org/apache/jackrabbit/oak/plugins/index/search:
./ spi/editor/ spi/query/
Author: tommaso
Date: Thu May 24 13:07:54 2018
New Revision: 1832166
URL: http://svn.apache.org/viewvc?rev=1832166&view=rev
Log:
OAK-7410 - added the first draft of the query part
Added:
jackrabbit/oak/trunk/oak-search/src/main/java/org/apache/jackrabbit/oak/plugins/index/search/IndexStatistics.java (with props)
jackrabbit/oak/trunk/oak-search/src/main/java/org/apache/jackrabbit/oak/plugins/index/search/IndexUpdateListener.java (with props)
jackrabbit/oak/trunk/oak-search/src/main/java/org/apache/jackrabbit/oak/plugins/index/search/ReaderRefreshPolicy.java (with props)
jackrabbit/oak/trunk/oak-search/src/main/java/org/apache/jackrabbit/oak/plugins/index/search/RefreshOnReadPolicy.java (with props)
jackrabbit/oak/trunk/oak-search/src/main/java/org/apache/jackrabbit/oak/plugins/index/search/RefreshOnWritePolicy.java (with props)
jackrabbit/oak/trunk/oak-search/src/main/java/org/apache/jackrabbit/oak/plugins/index/search/TimedRefreshPolicy.java (with props)
jackrabbit/oak/trunk/oak-search/src/main/java/org/apache/jackrabbit/oak/plugins/index/search/spi/query/
jackrabbit/oak/trunk/oak-search/src/main/java/org/apache/jackrabbit/oak/plugins/index/search/spi/query/FulltextIndex.java (with props)
jackrabbit/oak/trunk/oak-search/src/main/java/org/apache/jackrabbit/oak/plugins/index/search/spi/query/FulltextIndexPlanner.java (with props)
jackrabbit/oak/trunk/oak-search/src/main/java/org/apache/jackrabbit/oak/plugins/index/search/spi/query/FulltextIndexTracker.java (with props)
jackrabbit/oak/trunk/oak-search/src/main/java/org/apache/jackrabbit/oak/plugins/index/search/spi/query/IndexNodeManager.java (with props)
Modified:
jackrabbit/oak/trunk/oak-search/src/main/java/org/apache/jackrabbit/oak/plugins/index/search/BadIndexTracker.java
jackrabbit/oak/trunk/oak-search/src/main/java/org/apache/jackrabbit/oak/plugins/index/search/FulltextIndexConstants.java
jackrabbit/oak/trunk/oak-search/src/main/java/org/apache/jackrabbit/oak/plugins/index/search/IndexDefinition.java
jackrabbit/oak/trunk/oak-search/src/main/java/org/apache/jackrabbit/oak/plugins/index/search/IndexNode.java
jackrabbit/oak/trunk/oak-search/src/main/java/org/apache/jackrabbit/oak/plugins/index/search/PropertyDefinition.java
jackrabbit/oak/trunk/oak-search/src/main/java/org/apache/jackrabbit/oak/plugins/index/search/spi/editor/BlobByteSource.java
jackrabbit/oak/trunk/oak-search/src/main/java/org/apache/jackrabbit/oak/plugins/index/search/spi/editor/DocumentMaker.java
jackrabbit/oak/trunk/oak-search/src/main/java/org/apache/jackrabbit/oak/plugins/index/search/spi/editor/FulltextDocumentMaker.java
jackrabbit/oak/trunk/oak-search/src/main/java/org/apache/jackrabbit/oak/plugins/index/search/spi/editor/FulltextIndexEditor.java
jackrabbit/oak/trunk/oak-search/src/main/java/org/apache/jackrabbit/oak/plugins/index/search/spi/editor/FulltextIndexEditorContext.java
jackrabbit/oak/trunk/oak-search/src/main/java/org/apache/jackrabbit/oak/plugins/index/search/spi/editor/FulltextIndexWriter.java
jackrabbit/oak/trunk/oak-search/src/main/java/org/apache/jackrabbit/oak/plugins/index/search/spi/editor/FulltextIndexWriterFactory.java
jackrabbit/oak/trunk/oak-search/src/main/java/org/apache/jackrabbit/oak/plugins/index/search/spi/editor/TikaParserConfig.java
Modified: jackrabbit/oak/trunk/oak-search/src/main/java/org/apache/jackrabbit/oak/plugins/index/search/BadIndexTracker.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-search/src/main/java/org/apache/jackrabbit/oak/plugins/index/search/BadIndexTracker.java?rev=1832166&r1=1832165&r2=1832166&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-search/src/main/java/org/apache/jackrabbit/oak/plugins/index/search/BadIndexTracker.java (original)
+++ jackrabbit/oak/trunk/oak-search/src/main/java/org/apache/jackrabbit/oak/plugins/index/search/BadIndexTracker.java Thu May 24 13:07:54 2018
@@ -30,7 +30,7 @@ import com.google.common.collect.Maps;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
-class BadIndexTracker {
+public class BadIndexTracker {
/**
* Time interval in millis after which a bad index would be accessed again
* to check if it has been fixed
Modified: jackrabbit/oak/trunk/oak-search/src/main/java/org/apache/jackrabbit/oak/plugins/index/search/FulltextIndexConstants.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-search/src/main/java/org/apache/jackrabbit/oak/plugins/index/search/FulltextIndexConstants.java?rev=1832166&r1=1832165&r2=1832166&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-search/src/main/java/org/apache/jackrabbit/oak/plugins/index/search/FulltextIndexConstants.java (original)
+++ jackrabbit/oak/trunk/oak-search/src/main/java/org/apache/jackrabbit/oak/plugins/index/search/FulltextIndexConstants.java Thu May 24 13:07:54 2018
@@ -19,7 +19,7 @@ package org.apache.jackrabbit.oak.plugin
public interface FulltextIndexConstants {
- enum IndexingMode {
+ enum IndexingMode {
SYNC,
NRT,
ASYNC;
@@ -49,6 +49,8 @@ public interface FulltextIndexConstants
String PERSISTENCE_OAK = "repository";
+ String TEST_MODE = "testMode";
+
String PERSISTENCE_FILE = "file";
String PERSISTENCE_PATH = "path";
Modified: jackrabbit/oak/trunk/oak-search/src/main/java/org/apache/jackrabbit/oak/plugins/index/search/IndexDefinition.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-search/src/main/java/org/apache/jackrabbit/oak/plugins/index/search/IndexDefinition.java?rev=1832166&r1=1832165&r2=1832166&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-search/src/main/java/org/apache/jackrabbit/oak/plugins/index/search/IndexDefinition.java (original)
+++ jackrabbit/oak/trunk/oak-search/src/main/java/org/apache/jackrabbit/oak/plugins/index/search/IndexDefinition.java Thu May 24 13:07:54 2018
@@ -179,7 +179,7 @@ public final class IndexDefinition imple
/**
* native sort order
*/
- static final OrderEntry NATIVE_SORT_ORDER = new OrderEntry(JCR_SCORE, Type.UNDEFINED,
+ public static final OrderEntry NATIVE_SORT_ORDER = new OrderEntry(JCR_SCORE, Type.UNDEFINED,
OrderEntry.Order.DESCENDING);
private final boolean fullTextEnabled;
@@ -260,12 +260,18 @@ public final class IndexDefinition imple
private final boolean syncPropertyIndexes;
+ private final boolean testMode;
+
//~--------------------------------------------------------< Builder >
public static Builder newBuilder(NodeState root, NodeState defn, String indexPath){
return new Builder(root, defn, indexPath);
}
+ public boolean isTestMode() {
+ return false;
+ }
+
public static class Builder {
/**
* Default unique id used when no existing uid is defined
@@ -343,6 +349,7 @@ public final class IndexDefinition imple
rulesState = createIndexRules(defn).getNodeState();
}
+ this.testMode = getOptionalValue(defn, FulltextIndexConstants.TEST_MODE, false);
List<IndexingRule> definedIndexRules = newArrayList();
this.indexRules = collectIndexRules(rulesState, definedIndexRules);
this.definedRules = ImmutableList.copyOf(definedIndexRules);
@@ -828,7 +835,7 @@ public final class IndexDefinition imple
final boolean inherited;
final int propertyTypes;
final boolean fulltextEnabled;
- final boolean propertyIndexEnabled;
+ public final boolean propertyIndexEnabled;
final boolean nodeFullTextIndexed;
final Aggregate aggregate;
Modified: jackrabbit/oak/trunk/oak-search/src/main/java/org/apache/jackrabbit/oak/plugins/index/search/IndexNode.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-search/src/main/java/org/apache/jackrabbit/oak/plugins/index/search/IndexNode.java?rev=1832166&r1=1832165&r2=1832166&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-search/src/main/java/org/apache/jackrabbit/oak/plugins/index/search/IndexNode.java (original)
+++ jackrabbit/oak/trunk/oak-search/src/main/java/org/apache/jackrabbit/oak/plugins/index/search/IndexNode.java Thu May 24 13:07:54 2018
@@ -27,5 +27,6 @@ public interface IndexNode {
int getIndexNodeId();
- void refreshReadersOnWriteIfRequired();
+ IndexStatistics getIndexStatistics();
+
}
Added: jackrabbit/oak/trunk/oak-search/src/main/java/org/apache/jackrabbit/oak/plugins/index/search/IndexStatistics.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-search/src/main/java/org/apache/jackrabbit/oak/plugins/index/search/IndexStatistics.java?rev=1832166&view=auto
==============================================================================
--- jackrabbit/oak/trunk/oak-search/src/main/java/org/apache/jackrabbit/oak/plugins/index/search/IndexStatistics.java (added)
+++ jackrabbit/oak/trunk/oak-search/src/main/java/org/apache/jackrabbit/oak/plugins/index/search/IndexStatistics.java Thu May 24 13:07:54 2018
@@ -0,0 +1,28 @@
+/*
+ * 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;
+
+/**
+ *
+ */
+public interface IndexStatistics {
+ int numDocs();
+
+ int getDocCountFor(String key);
+}
Propchange: jackrabbit/oak/trunk/oak-search/src/main/java/org/apache/jackrabbit/oak/plugins/index/search/IndexStatistics.java
------------------------------------------------------------------------------
svn:eol-style = native
Added: jackrabbit/oak/trunk/oak-search/src/main/java/org/apache/jackrabbit/oak/plugins/index/search/IndexUpdateListener.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-search/src/main/java/org/apache/jackrabbit/oak/plugins/index/search/IndexUpdateListener.java?rev=1832166&view=auto
==============================================================================
--- jackrabbit/oak/trunk/oak-search/src/main/java/org/apache/jackrabbit/oak/plugins/index/search/IndexUpdateListener.java (added)
+++ jackrabbit/oak/trunk/oak-search/src/main/java/org/apache/jackrabbit/oak/plugins/index/search/IndexUpdateListener.java Thu May 24 13:07:54 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;
+
+interface IndexUpdateListener extends ReaderRefreshPolicy {
+
+ void updated();
+}
Propchange: jackrabbit/oak/trunk/oak-search/src/main/java/org/apache/jackrabbit/oak/plugins/index/search/IndexUpdateListener.java
------------------------------------------------------------------------------
svn:eol-style = native
Modified: jackrabbit/oak/trunk/oak-search/src/main/java/org/apache/jackrabbit/oak/plugins/index/search/PropertyDefinition.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-search/src/main/java/org/apache/jackrabbit/oak/plugins/index/search/PropertyDefinition.java?rev=1832166&r1=1832165&r2=1832166&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-search/src/main/java/org/apache/jackrabbit/oak/plugins/index/search/PropertyDefinition.java (original)
+++ jackrabbit/oak/trunk/oak-search/src/main/java/org/apache/jackrabbit/oak/plugins/index/search/PropertyDefinition.java Thu May 24 13:07:54 2018
@@ -80,7 +80,7 @@ public class PropertyDefinition {
public final boolean ordered;
- final boolean nullCheckEnabled;
+ public final boolean nullCheckEnabled;
final boolean notNullCheckEnabled;
@@ -98,7 +98,7 @@ public class PropertyDefinition {
public final boolean excludeFromAggregate;
- final int weight;
+ public final int weight;
/**
* Property name excluding the relativePath. For regular expression based definition
Added: jackrabbit/oak/trunk/oak-search/src/main/java/org/apache/jackrabbit/oak/plugins/index/search/ReaderRefreshPolicy.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-search/src/main/java/org/apache/jackrabbit/oak/plugins/index/search/ReaderRefreshPolicy.java?rev=1832166&view=auto
==============================================================================
--- jackrabbit/oak/trunk/oak-search/src/main/java/org/apache/jackrabbit/oak/plugins/index/search/ReaderRefreshPolicy.java (added)
+++ jackrabbit/oak/trunk/oak-search/src/main/java/org/apache/jackrabbit/oak/plugins/index/search/ReaderRefreshPolicy.java Thu May 24 13:07:54 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;
+
+public interface ReaderRefreshPolicy {
+ ReaderRefreshPolicy NEVER = new ReaderRefreshPolicy() {
+ @Override
+ public void refreshOnReadIfRequired(Runnable refreshCallback) {
+ //Never refresh
+ }
+
+ @Override
+ public void refreshOnWriteIfRequired(Runnable refreshCallback) {
+ //Never refresh
+ }
+ };
+
+ /**
+ * This would be invoked before any query is performed
+ * to provide a chance for IndexNode to refresh the readers
+ *
+ * <p>The index may or may not be updated when this method
+ * is invoked
+ *
+ * @param refreshCallback callback to refresh the readers
+ */
+ void refreshOnReadIfRequired(Runnable refreshCallback);
+
+ /**
+ * This would invoked after some writes have been performed
+ * and as a final step refresh request is being made.
+ *
+ * <p>Any time its 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/ReaderRefreshPolicy.java
------------------------------------------------------------------------------
svn:eol-style = native
Added: jackrabbit/oak/trunk/oak-search/src/main/java/org/apache/jackrabbit/oak/plugins/index/search/RefreshOnReadPolicy.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-search/src/main/java/org/apache/jackrabbit/oak/plugins/index/search/RefreshOnReadPolicy.java?rev=1832166&view=auto
==============================================================================
--- jackrabbit/oak/trunk/oak-search/src/main/java/org/apache/jackrabbit/oak/plugins/index/search/RefreshOnReadPolicy.java (added)
+++ jackrabbit/oak/trunk/oak-search/src/main/java/org/apache/jackrabbit/oak/plugins/index/search/RefreshOnReadPolicy.java Thu May 24 13:07:54 2018
@@ -0,0 +1,95 @@
+/*
+ * 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 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/RefreshOnReadPolicy.java
------------------------------------------------------------------------------
svn:eol-style = native
Added: jackrabbit/oak/trunk/oak-search/src/main/java/org/apache/jackrabbit/oak/plugins/index/search/RefreshOnWritePolicy.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-search/src/main/java/org/apache/jackrabbit/oak/plugins/index/search/RefreshOnWritePolicy.java?rev=1832166&view=auto
==============================================================================
--- jackrabbit/oak/trunk/oak-search/src/main/java/org/apache/jackrabbit/oak/plugins/index/search/RefreshOnWritePolicy.java (added)
+++ jackrabbit/oak/trunk/oak-search/src/main/java/org/apache/jackrabbit/oak/plugins/index/search/RefreshOnWritePolicy.java Thu May 24 13:07:54 2018
@@ -0,0 +1,50 @@
+/*
+ * 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 java.util.concurrent.atomic.AtomicBoolean;
+
+/**
+ * Policy which performs immediate refresh upon completion of writes
+ */
+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/RefreshOnWritePolicy.java
------------------------------------------------------------------------------
svn:eol-style = native
Added: jackrabbit/oak/trunk/oak-search/src/main/java/org/apache/jackrabbit/oak/plugins/index/search/TimedRefreshPolicy.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-search/src/main/java/org/apache/jackrabbit/oak/plugins/index/search/TimedRefreshPolicy.java?rev=1832166&view=auto
==============================================================================
--- jackrabbit/oak/trunk/oak-search/src/main/java/org/apache/jackrabbit/oak/plugins/index/search/TimedRefreshPolicy.java (added)
+++ jackrabbit/oak/trunk/oak-search/src/main/java/org/apache/jackrabbit/oak/plugins/index/search/TimedRefreshPolicy.java Thu May 24 13:07:54 2018
@@ -0,0 +1,63 @@
+/*
+ * 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 java.util.concurrent.TimeUnit;
+import java.util.concurrent.atomic.AtomicBoolean;
+
+import org.apache.jackrabbit.oak.stats.Clock;
+
+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/TimedRefreshPolicy.java
------------------------------------------------------------------------------
svn:eol-style = native
Modified: jackrabbit/oak/trunk/oak-search/src/main/java/org/apache/jackrabbit/oak/plugins/index/search/spi/editor/BlobByteSource.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-search/src/main/java/org/apache/jackrabbit/oak/plugins/index/search/spi/editor/BlobByteSource.java?rev=1832166&r1=1832165&r2=1832166&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-search/src/main/java/org/apache/jackrabbit/oak/plugins/index/search/spi/editor/BlobByteSource.java (original)
+++ jackrabbit/oak/trunk/oak-search/src/main/java/org/apache/jackrabbit/oak/plugins/index/search/spi/editor/BlobByteSource.java Thu May 24 13:07:54 2018
@@ -25,6 +25,9 @@ import java.io.InputStream;
import com.google.common.io.ByteSource;
import org.apache.jackrabbit.oak.api.Blob;
+/**
+ * {@link ByteSource} extension to work with Oak {@link Blob}s
+ */
public final class BlobByteSource extends ByteSource {
private final Blob blob;
Modified: jackrabbit/oak/trunk/oak-search/src/main/java/org/apache/jackrabbit/oak/plugins/index/search/spi/editor/DocumentMaker.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-search/src/main/java/org/apache/jackrabbit/oak/plugins/index/search/spi/editor/DocumentMaker.java?rev=1832166&r1=1832165&r2=1832166&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-search/src/main/java/org/apache/jackrabbit/oak/plugins/index/search/spi/editor/DocumentMaker.java (original)
+++ jackrabbit/oak/trunk/oak-search/src/main/java/org/apache/jackrabbit/oak/plugins/index/search/spi/editor/DocumentMaker.java Thu May 24 13:07:54 2018
@@ -25,7 +25,7 @@ import org.apache.jackrabbit.oak.api.Pro
import org.apache.jackrabbit.oak.spi.state.NodeState;
/**
- * A {@link DocumentMaker} is responsible for creating an instance of a document {@link D} which depends on implementor implementation.
+ * A {@link DocumentMaker} is responsible for creating an instance of a document {@link D} to be indexed.
* For Apache Lucene that would be a Lucene {@code Document}, for Apache Solr that might be a {@code SolrInputDocument}, etc.
*/
public interface DocumentMaker<D> {
Modified: jackrabbit/oak/trunk/oak-search/src/main/java/org/apache/jackrabbit/oak/plugins/index/search/spi/editor/FulltextDocumentMaker.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-search/src/main/java/org/apache/jackrabbit/oak/plugins/index/search/spi/editor/FulltextDocumentMaker.java?rev=1832166&r1=1832165&r2=1832166&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-search/src/main/java/org/apache/jackrabbit/oak/plugins/index/search/spi/editor/FulltextDocumentMaker.java (original)
+++ jackrabbit/oak/trunk/oak-search/src/main/java/org/apache/jackrabbit/oak/plugins/index/search/spi/editor/FulltextDocumentMaker.java Thu May 24 13:07:54 2018
@@ -61,15 +61,15 @@ public abstract class FulltextDocumentMa
private IndexDefinition.IndexingRule indexingRule;
private String path;
- abstract D initDoc();
+ protected abstract D initDoc();
- abstract D finalizeDoc(D fields, boolean dirty, boolean facet);
+ protected abstract D finalizeDoc(D fields, boolean dirty, boolean facet);
- abstract StringPropertyState createNodeNamePS();
+ protected abstract StringPropertyState createNodeNamePS();
- abstract boolean isFacetingEnabled();
+ protected abstract boolean isFacetingEnabled();
- abstract boolean isNodeName(String pname);
+ protected abstract boolean isNodeName(String pname);
protected abstract boolean indexTypeOrderedFields(String pname, int tag, PropertyState property, PropertyDefinition pd);
Modified: jackrabbit/oak/trunk/oak-search/src/main/java/org/apache/jackrabbit/oak/plugins/index/search/spi/editor/FulltextIndexEditor.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-search/src/main/java/org/apache/jackrabbit/oak/plugins/index/search/spi/editor/FulltextIndexEditor.java?rev=1832166&r1=1832165&r2=1832166&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-search/src/main/java/org/apache/jackrabbit/oak/plugins/index/search/spi/editor/FulltextIndexEditor.java (original)
+++ jackrabbit/oak/trunk/oak-search/src/main/java/org/apache/jackrabbit/oak/plugins/index/search/spi/editor/FulltextIndexEditor.java Thu May 24 13:07:54 2018
@@ -44,7 +44,7 @@ import org.slf4j.LoggerFactory;
import static org.apache.jackrabbit.oak.commons.PathUtils.concat;
/**
- * Abstract implementation of an {@link IndexEditor} which supports index time aggregation.
+ * Generic implementation of an {@link IndexEditor} which supports index time aggregation.
*/
public class FulltextIndexEditor<D> implements IndexEditor, Aggregate.AggregateRoot {
@@ -195,7 +195,7 @@ public class FulltextIndexEditor<D> impl
public Editor childNodeAdded(String name, NodeState after) {
PathFilter.Result filterResult = getPathFilterResult(name);
if (filterResult != PathFilter.Result.EXCLUDE) {
- return new FulltextIndexEditor(this, name, getMatcherState(name, after), filterResult, false);
+ return new FulltextIndexEditor<>(this, name, getMatcherState(name, after), filterResult, false);
}
return null;
}
@@ -205,7 +205,7 @@ public class FulltextIndexEditor<D> impl
String name, NodeState before, NodeState after) {
PathFilter.Result filterResult = getPathFilterResult(name);
if (filterResult != PathFilter.Result.EXCLUDE) {
- return new FulltextIndexEditor(this, name, getMatcherState(name, after), filterResult, false);
+ return new FulltextIndexEditor<>(this, name, getMatcherState(name, after), filterResult, false);
}
return null;
}
@@ -236,7 +236,7 @@ public class FulltextIndexEditor<D> impl
MatcherState ms = getMatcherState(name, before);
if (!ms.isEmpty()){
- return new FulltextIndexEditor(this, name, ms, filterResult, true);
+ return new FulltextIndexEditor<>(this, name, ms, filterResult, true);
}
return null; // no need to recurse down the removed subtree
}
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=1832166&r1=1832165&r2=1832166&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 Thu May 24 13:07:54 2018
@@ -52,6 +52,7 @@ import static org.apache.jackrabbit.oak.
*
*/
public abstract class FulltextIndexEditorContext<D> {
+
private static final Logger log = LoggerFactory
.getLogger(FulltextIndexEditorContext.class);
Modified: jackrabbit/oak/trunk/oak-search/src/main/java/org/apache/jackrabbit/oak/plugins/index/search/spi/editor/FulltextIndexWriter.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-search/src/main/java/org/apache/jackrabbit/oak/plugins/index/search/spi/editor/FulltextIndexWriter.java?rev=1832166&r1=1832165&r2=1832166&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-search/src/main/java/org/apache/jackrabbit/oak/plugins/index/search/spi/editor/FulltextIndexWriter.java (original)
+++ jackrabbit/oak/trunk/oak-search/src/main/java/org/apache/jackrabbit/oak/plugins/index/search/spi/editor/FulltextIndexWriter.java Thu May 24 13:07:54 2018
@@ -21,6 +21,12 @@ package org.apache.jackrabbit.oak.plugin
import java.io.IOException;
+/**
+ * A {@link FulltextIndexWriter} is responsible for writing / deleting documents of type {@code D} to the index
+ * implementation underlying persistence layer.
+ *
+ * @param <D>
+ */
public interface FulltextIndexWriter<D> {
/**
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=1832166&r1=1832165&r2=1832166&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 Thu May 24 13:07:54 2018
@@ -27,6 +27,13 @@ import org.apache.jackrabbit.oak.spi.sta
*/
public interface FulltextIndexWriterFactory {
+ /**
+ * create a new index writer instance
+ * @param definition the index definition
+ * @param definitionBuilder the node builder associated with the index definition
+ * @param reindex whether or not reindex should be performed
+ * @return an index writer
+ */
FulltextIndexWriter newInstance(IndexDefinition definition, NodeBuilder definitionBuilder, boolean reindex);
}
Modified: jackrabbit/oak/trunk/oak-search/src/main/java/org/apache/jackrabbit/oak/plugins/index/search/spi/editor/TikaParserConfig.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-search/src/main/java/org/apache/jackrabbit/oak/plugins/index/search/spi/editor/TikaParserConfig.java?rev=1832166&r1=1832165&r2=1832166&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-search/src/main/java/org/apache/jackrabbit/oak/plugins/index/search/spi/editor/TikaParserConfig.java (original)
+++ jackrabbit/oak/trunk/oak-search/src/main/java/org/apache/jackrabbit/oak/plugins/index/search/spi/editor/TikaParserConfig.java Thu May 24 13:07:54 2018
@@ -36,6 +36,7 @@ import org.w3c.dom.NodeList;
import org.xml.sax.SAXException;
public class TikaParserConfig {
+
private static final String EMPTY_PARSER = "org.apache.tika.parser.EmptyParser";
/**
Added: 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=1832166&view=auto
==============================================================================
--- jackrabbit/oak/trunk/oak-search/src/main/java/org/apache/jackrabbit/oak/plugins/index/search/spi/query/FulltextIndex.java (added)
+++ jackrabbit/oak/trunk/oak-search/src/main/java/org/apache/jackrabbit/oak/plugins/index/search/spi/query/FulltextIndex.java Thu May 24 13:07:54 2018
@@ -0,0 +1,483 @@
+/*
+ * 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 java.util.Collection;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+
+import javax.jcr.PropertyType;
+
+import com.google.common.collect.Lists;
+import com.google.common.primitives.Chars;
+import org.apache.jackrabbit.oak.api.PropertyValue;
+import org.apache.jackrabbit.oak.api.Result.SizePrecision;
+import org.apache.jackrabbit.oak.api.Type;
+import org.apache.jackrabbit.oak.commons.PathUtils;
+import org.apache.jackrabbit.oak.commons.PerfLogger;
+import org.apache.jackrabbit.oak.commons.json.JsopBuilder;
+import org.apache.jackrabbit.oak.commons.json.JsopWriter;
+import org.apache.jackrabbit.oak.plugins.index.Cursors;
+import org.apache.jackrabbit.oak.plugins.index.Cursors.PathCursor;
+import org.apache.jackrabbit.oak.plugins.index.search.IndexLookup;
+import org.apache.jackrabbit.oak.plugins.index.search.IndexNode;
+import org.apache.jackrabbit.oak.plugins.index.search.PropertyDefinition;
+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;
+import org.apache.jackrabbit.oak.spi.query.IndexRow;
+import org.apache.jackrabbit.oak.spi.query.QueryConstants;
+import org.apache.jackrabbit.oak.spi.query.QueryIndex;
+import org.apache.jackrabbit.oak.spi.query.QueryIndex.AdvanceFulltextQueryIndex;
+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.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import static com.google.common.base.Preconditions.checkState;
+import static org.apache.jackrabbit.oak.spi.query.QueryIndex.AdvancedQueryIndex;
+import static org.apache.jackrabbit.oak.spi.query.QueryIndex.NativeQueryIndex;
+
+/**
+ * Provides an abstract QueryIndex that does lookups against a fulltext index
+ *
+ * @see QueryIndex
+ *
+ */
+public abstract class FulltextIndex implements AdvancedQueryIndex, QueryIndex, NativeQueryIndex,
+ 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";
+
+ protected abstract FulltextIndexTracker getIndexTracker();
+
+ protected abstract String getType();
+
+ protected abstract SizeEstimator getSizeEstimator(IndexPlan plan);
+
+ 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());
+ List<IndexPlan> plans = Lists.newArrayListWithCapacity(indexPaths.size());
+ for (String path : indexPaths) {
+ IndexNode indexNode = null;
+ try {
+ indexNode = getIndexTracker().acquireIndexNode(path, getType());
+
+ if (indexNode != null) {
+ IndexPlan plan = new FulltextIndexPlanner(indexNode, path, filter, sortOrder).getPlan();
+ if (plan != null) {
+ plans.add(plan);
+ }
+ }
+ } catch (Exception e) {
+ LOG.error("Error getting plan for {}", path);
+ LOG.error("Exception:", e);
+ } finally {
+ if (indexNode != null) {
+ indexNode.release();
+ }
+ }
+ }
+ return plans;
+ }
+
+ @Override
+ public double getCost(Filter filter, NodeState root) {
+ throw new UnsupportedOperationException("Not supported as implementing AdvancedQueryIndex");
+ }
+
+ @Override
+ public String getPlan(Filter filter, NodeState root) {
+ throw new UnsupportedOperationException("Not supported as implementing AdvancedQueryIndex");
+ }
+
+ @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");
+ try {
+ FullTextExpression ft = filter.getFullTextConstraint();
+ StringBuilder sb = new StringBuilder(getType()).append(":");
+ String path = getPlanResult(plan).indexPath;
+ sb.append(getIndexName(plan))
+ .append("(")
+ .append(path)
+ .append(") ");
+ sb.append(getFulltextRequestString(plan, index));
+ if (plan.getSortOrder() != null && !plan.getSortOrder().isEmpty()) {
+ sb.append(" ordering:").append(plan.getSortOrder());
+ }
+ if (ft != null) {
+ sb.append(" ft:(").append(ft).append(")");
+ }
+ addSyncIndexPlan(plan, sb);
+ return sb.toString();
+ } finally {
+ index.release();
+ }
+ }
+
+ private static void addSyncIndexPlan(IndexPlan plan, StringBuilder sb) {
+ FulltextIndexPlanner.PlanResult pr = getPlanResult(plan);
+ if (pr.hasPropertyIndexResult()) {
+ FulltextIndexPlanner.PropertyIndexResult pres = pr.getPropertyIndexResult();
+ sb.append(" sync:(")
+ .append(pres.propertyName);
+
+ if (!pres.propertyName.equals(pres.pr.propertyName)) {
+ sb.append("[").append(pres.pr.propertyName).append("]");
+ }
+
+ sb.append(" ").append(pres.pr);
+ sb.append(")");
+ }
+
+ if (pr.evaluateSyncNodeTypeRestriction()) {
+ sb.append(" sync:(nodeType");
+ sb.append(" primaryTypes : ").append(plan.getFilter().getPrimaryTypes());
+ sb.append(" mixinTypes : ").append(plan.getFilter().getMixinTypes());
+ sb.append(")");
+ }
+ }
+
+ @Override
+ public Cursor query(final Filter filter, final NodeState root) {
+ throw new UnsupportedOperationException("Not supported as implementing AdvancedQueryIndex");
+ }
+
+ private static boolean shouldInclude(String docPath, IndexPlan plan) {
+ String path = getPathRestriction(plan);
+
+ boolean include = true;
+
+ Filter filter = plan.getFilter();
+ switch (filter.getPathRestriction()) {
+ case EXACT:
+ include = path.equals(docPath);
+ break;
+ case DIRECT_CHILDREN:
+ include = PathUtils.getParentPath(docPath).equals(path);
+ break;
+ case ALL_CHILDREN:
+ include = PathUtils.isAncestor(path, docPath);
+ break;
+ }
+
+ return include;
+ }
+
+ @Override
+ public NodeAggregator getNodeAggregator() {
+ return null;
+ }
+
+ /**
+ * In a fulltext term for jcr:contains(foo, 'bar') 'foo'
+ * is the property name. While in jcr:contains(foo/*, 'bar')
+ * 'foo' is node name
+ *
+ * @return true if the term is related to node
+ */
+ public static boolean isNodePath(String fulltextTermPath) {
+ return fulltextTermPath.endsWith("/*");
+ }
+
+ protected IndexNode acquireIndexNode(IndexPlan plan) {
+ return getIndexTracker().acquireIndexNode(getPlanResult(plan).indexPath, getType());
+ }
+
+ protected static String getIndexName(IndexPlan plan) {
+ return PathUtils.getName(getPlanResult(plan).indexPath);
+ }
+
+ protected static int determinePropertyType(PropertyDefinition defn, PropertyRestriction pr) {
+ int typeFromRestriction = pr.propertyType;
+ if (typeFromRestriction == PropertyType.UNDEFINED) {
+ //If no explicit type defined then determine the type from restriction
+ //value
+ if (pr.first != null && pr.first.getType() != Type.UNDEFINED) {
+ typeFromRestriction = pr.first.getType().tag();
+ } else if (pr.last != null && pr.last.getType() != Type.UNDEFINED) {
+ typeFromRestriction = pr.last.getType().tag();
+ } else if (pr.list != null && !pr.list.isEmpty()) {
+ typeFromRestriction = pr.list.get(0).getType().tag();
+ }
+ }
+ return getPropertyType(defn, pr.propertyName, typeFromRestriction);
+ }
+
+ private static int getPropertyType(PropertyDefinition defn, String name, int defaultVal) {
+ if (defn.isTypeDefined()) {
+ return defn.getType();
+ }
+ return defaultVal;
+ }
+
+ protected static PlanResult getPlanResult(IndexPlan plan) {
+ return (PlanResult) plan.getAttribute(ATTR_PLAN_RESULT);
+ }
+
+ /**
+ * Following chars are used as operators in Lucene Query and should be escaped
+ */
+ private static final char[] QUERY_OPERATORS = {':' , '/', '!', '&', '|', '='};
+
+ /**
+ * Following logic is taken from org.apache.jackrabbit.core.query.lucene.JackrabbitQueryParser#parse(java.lang.String)
+ */
+ static String rewriteQueryText(String textsearch) {
+ // replace escaped ' with just '
+ StringBuilder rewritten = new StringBuilder();
+ // most query parsers recognize 'AND' and 'NOT' as
+ // keywords.
+ textsearch = textsearch.replaceAll("AND", "and");
+ textsearch = textsearch.replaceAll("NOT", "not");
+ boolean escaped = false;
+ for (int i = 0; i < textsearch.length(); i++) {
+ char c = textsearch.charAt(i);
+ if (c == '\\') {
+ if (escaped) {
+ rewritten.append("\\\\");
+ escaped = false;
+ } else {
+ escaped = true;
+ }
+ } else if (c == '\'') {
+ if (escaped) {
+ escaped = false;
+ }
+ rewritten.append(c);
+ } else if (Chars.contains(QUERY_OPERATORS, c)) {
+ rewritten.append('\\').append(c);
+ } else {
+ if (escaped) {
+ rewritten.append('\\');
+ escaped = false;
+ }
+ rewritten.append(c);
+ }
+ }
+ return rewritten.toString();
+ }
+
+ protected static String getPathRestriction(IndexPlan plan) {
+ Filter f = plan.getFilter();
+ String pathPrefix = plan.getPathPrefix();
+ if (pathPrefix.isEmpty()) {
+ return f.getPath();
+ }
+ String relativePath = PathUtils.relativize(pathPrefix, f.getPath());
+ 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;
+
+ FulltextResultRow(String path, double score, Map<String, String> excerpts, List<FacetResult.Facet> facets, String explanation) {
+ this.explanation = explanation;
+ this.excerpts = excerpts;
+ this.facets = facets;
+ this.isVirutal = false;
+ this.path = path;
+ this.score = score;
+ this.suggestion = null;
+ }
+
+ FulltextResultRow(String suggestion, long weight) {
+ this.isVirutal = true;
+ this.path = "/";
+ this.score = weight;
+ this.suggestion = suggestion;
+ this.excerpts = null;
+ this.facets = null;
+ this.explanation = null;
+ }
+
+ FulltextResultRow(String suggestion) {
+ this(suggestion, 1);
+ }
+
+ @Override
+ public String toString() {
+ return String.format("%s (%1.2f)", path, score);
+ }
+ }
+
+ /**
+ * 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 {
+
+ private final Logger log = LoggerFactory.getLogger(getClass());
+ private static final int TRAVERSING_WARNING = Integer.getInteger("oak.traversing.warning", 10000);
+
+ private final Cursor pathCursor;
+ private final String pathPrefix;
+ FulltextResultRow currentRow;
+ private final SizeEstimator sizeEstimator;
+ private long estimatedSize;
+ private int numberOfFacets;
+
+ FulltextPathCursor(final Iterator<FulltextResultRow> it, final IndexPlan plan, QueryLimits settings, SizeEstimator sizeEstimator) {
+ pathPrefix = plan.getPathPrefix();
+ this.sizeEstimator = sizeEstimator;
+ Iterator<String> pathIterator = new Iterator<String>() {
+
+ private int readCount;
+
+ @Override
+ public boolean hasNext() {
+ return it.hasNext();
+ }
+
+ @Override
+ public String next() {
+ currentRow = it.next();
+ readCount++;
+ if (readCount % TRAVERSING_WARNING == 0) {
+ Cursors.checkReadLimit(readCount, settings);
+ log.warn("Index-Traversed {} nodes with filter {}", readCount, plan.getFilter());
+ }
+ return currentRow.path;
+ }
+
+ @Override
+ public void remove() {
+ it.remove();
+ }
+
+ };
+
+ PlanResult planResult = getPlanResult(plan);
+ pathCursor = new PathCursor(pathIterator, planResult.isUniquePathsRequired(), settings);
+ numberOfFacets = planResult.indexDefinition.getNumberOfTopFacets();
+ }
+
+
+ @Override
+ public boolean hasNext() {
+ return pathCursor.hasNext();
+ }
+
+ @Override
+ public void remove() {
+ pathCursor.remove();
+ }
+
+ @Override
+ public IndexRow next() {
+ final IndexRow pathRow = pathCursor.next();
+ return new IndexRow() {
+
+ @Override
+ public boolean isVirtualRow() {
+ return currentRow.isVirutal;
+ }
+
+ @Override
+ public String getPath() {
+ String sub = pathRow.getPath();
+ if (isVirtualRow()) {
+ return sub;
+ } else if (!"".equals(pathPrefix) && PathUtils.denotesRoot(sub)) {
+ return pathPrefix;
+ } else if (PathUtils.isAbsolute(sub)) {
+ return pathPrefix + sub;
+ } else {
+ return PathUtils.concat(pathPrefix, sub);
+ }
+ }
+
+ @Override
+ public PropertyValue getValue(String columnName) {
+ // overlay the score
+ if (QueryConstants.JCR_SCORE.equals(columnName)) {
+ return PropertyValues.newDouble(currentRow.score);
+ }
+ if (QueryConstants.REP_SPELLCHECK.equals(columnName) || QueryConstants.REP_SUGGEST.equals(columnName)) {
+ return PropertyValues.newString(currentRow.suggestion);
+ }
+ if (QueryConstants.OAK_SCORE_EXPLANATION.equals(columnName)) {
+ return PropertyValues.newString(currentRow.explanation);
+ }
+ if (columnName.startsWith(QueryConstants.REP_EXCERPT)) {
+ String excerpt = currentRow.excerpts.get(columnName);
+ if (excerpt != null) {
+ return PropertyValues.newString(excerpt);
+ }
+ }
+ if (columnName.startsWith(QueryConstants.REP_FACET)) {
+ List<FacetResult.Facet> facets = currentRow.facets;
+ try {
+ if (facets != null) {
+ JsopWriter writer = new JsopBuilder();
+ writer.object();
+ for (FacetResult.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);
+ }
+ }
+ return pathRow.getValue(columnName);
+ }
+
+ };
+ }
+
+ @Override
+ public long getSize(SizePrecision precision, long max) {
+ if (estimatedSize != 0) {
+ return estimatedSize;
+ }
+ return estimatedSize = sizeEstimator.getSize();
+ }
+ }
+
+ static String parseFacetField(String columnName) {
+ return columnName.substring(QueryConstants.REP_FACET.length() + 1, columnName.length() - 1);
+ }
+}
Propchange: jackrabbit/oak/trunk/oak-search/src/main/java/org/apache/jackrabbit/oak/plugins/index/search/spi/query/FulltextIndex.java
------------------------------------------------------------------------------
svn:eol-style = native