diff --git a/Vagrantfile b/Vagrantfile index 454d114f1a2..4f8ee7164f6 100644 --- a/Vagrantfile +++ b/Vagrantfile @@ -23,15 +23,15 @@ Vagrant.configure(2) do |config| config.vm.define "ubuntu-1204" do |config| - config.vm.box = "ubuntu/precise64" + config.vm.box = "elastic/ubuntu-12.04-x86_64" ubuntu_common config end config.vm.define "ubuntu-1404" do |config| - config.vm.box = "ubuntu/trusty64" + config.vm.box = "elastic/ubuntu-14.04-x86_64" ubuntu_common config end config.vm.define "ubuntu-1504" do |config| - config.vm.box = "ubuntu/vivid64" + config.vm.box = "elastic/ubuntu-15.04-x86_64" ubuntu_common config, extra: <<-SHELL # Install Jayatana so we can work around it being present. [ -f /usr/share/java/jayatanaag.jar ] || install jayatana @@ -41,44 +41,35 @@ Vagrant.configure(2) do |config| # get the sun jdk on there just aren't worth it. We have jessie for testing # debian and it works fine. config.vm.define "debian-8" do |config| - config.vm.box = "debian/jessie64" - deb_common config, - 'echo deb http://http.debian.net/debian jessie-backports main > /etc/apt/sources.list.d/backports.list', 'backports' + config.vm.box = "elastic/debian-8-x86_64" + deb_common config, 'echo deb http://http.debian.net/debian jessie-backports main > /etc/apt/sources.list.d/backports.list', 'backports' end config.vm.define "centos-6" do |config| - config.vm.box = "boxcutter/centos67" + config.vm.box = "elastic/centos-6-x86_64" rpm_common config end config.vm.define "centos-7" do |config| - # There is a centos/7 box but it doesn't have rsync or virtualbox guest - # stuff on there so its slow to use. So chef it is.... - config.vm.box = "boxcutter/centos71" + config.vm.box = "elastic/centos-7-x86_64" + rpm_common config + end + config.vm.define "oel-6" do |config| + config.vm.box = "elastic/oraclelinux-6-x86_64" rpm_common config end - # This box hangs _forever_ on ```yum check-update```. I have no idea why. - # config.vm.define "oel-6", autostart: false do |config| - # config.vm.box = "boxcutter/oel66" - # rpm_common(config) - # end config.vm.define "oel-7" do |config| - config.vm.box = "boxcutter/oel70" + config.vm.box = "elastic/oraclelinux-7-x86_64" rpm_common config end config.vm.define "fedora-22" do |config| - # Fedora hosts their own 'cloud' images that aren't in Vagrant's Atlas but - # and are missing required stuff like rsync. It'd be nice if we could use - # them but they much slower to get up and running then the boxcutter image. - config.vm.box = "boxcutter/fedora22" + config.vm.box = "elastic/fedora-22-x86_64" dnf_common config end config.vm.define "opensuse-13" do |config| - config.vm.box = "chef/opensuse-13" - config.vm.box_url = "http://opscode-vm-bento.s3.amazonaws.com/vagrant/virtualbox/opscode_opensuse-13.2-x86_64_chef-provisionerless.box" + config.vm.box = "elastic/opensuse-13-x86_64" opensuse_common config end - # The SLES boxes are not considered to be highest quality, but seem to be sufficient for a test run config.vm.define "sles-12" do |config| - config.vm.box = "idar/sles12" + config.vm.box = "elastic/sles-12-x86_64" sles_common config end # Switch the default share for the project root from /vagrant to diff --git a/buildSrc/src/main/resources/checkstyle_suppressions.xml b/buildSrc/src/main/resources/checkstyle_suppressions.xml index b9039f92659..07dd29a33ad 100644 --- a/buildSrc/src/main/resources/checkstyle_suppressions.xml +++ b/buildSrc/src/main/resources/checkstyle_suppressions.xml @@ -273,7 +273,6 @@ - @@ -390,7 +389,6 @@ - @@ -421,7 +419,6 @@ - @@ -438,7 +435,6 @@ - @@ -461,7 +457,6 @@ - @@ -606,7 +601,6 @@ - @@ -614,7 +608,6 @@ - @@ -666,10 +659,7 @@ - - - @@ -1329,14 +1319,9 @@ - - - - - diff --git a/core/src/main/java/org/apache/lucene/index/memory/ExtendedMemoryIndex.java b/core/src/main/java/org/apache/lucene/index/memory/ExtendedMemoryIndex.java deleted file mode 100644 index aec1bc75519..00000000000 --- a/core/src/main/java/org/apache/lucene/index/memory/ExtendedMemoryIndex.java +++ /dev/null @@ -1,31 +0,0 @@ -/* - * Licensed to Elasticsearch under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch 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.lucene.index.memory; - -/** - * This class overwrites {@link MemoryIndex} to make the reuse constructor visible. - */ -public final class ExtendedMemoryIndex extends MemoryIndex { - - public ExtendedMemoryIndex(boolean storeOffsets, boolean storePayloads, long maxReusedBytes) { - super(storeOffsets, storePayloads, maxReusedBytes); - } - -} diff --git a/core/src/main/java/org/elasticsearch/ElasticsearchException.java b/core/src/main/java/org/elasticsearch/ElasticsearchException.java index d069bddfdfe..7fd81f5ddfe 100644 --- a/core/src/main/java/org/elasticsearch/ElasticsearchException.java +++ b/core/src/main/java/org/elasticsearch/ElasticsearchException.java @@ -645,8 +645,6 @@ public class ElasticsearchException extends RuntimeException implements ToXConte // 87 used to be for MergeMappingException INVALID_INDEX_TEMPLATE_EXCEPTION(org.elasticsearch.indices.InvalidIndexTemplateException.class, org.elasticsearch.indices.InvalidIndexTemplateException::new, 88), - PERCOLATE_EXCEPTION(org.elasticsearch.percolator.PercolateException.class, - org.elasticsearch.percolator.PercolateException::new, 89), REFRESH_FAILED_ENGINE_EXCEPTION(org.elasticsearch.index.engine.RefreshFailedEngineException.class, org.elasticsearch.index.engine.RefreshFailedEngineException::new, 90), AGGREGATION_INITIALIZATION_EXCEPTION(org.elasticsearch.search.aggregations.AggregationInitializationException.class, diff --git a/core/src/main/java/org/elasticsearch/action/ActionModule.java b/core/src/main/java/org/elasticsearch/action/ActionModule.java index 491202e7c7a..be9387f9a8a 100644 --- a/core/src/main/java/org/elasticsearch/action/ActionModule.java +++ b/core/src/main/java/org/elasticsearch/action/ActionModule.java @@ -165,7 +165,6 @@ import org.elasticsearch.action.percolate.MultiPercolateAction; import org.elasticsearch.action.percolate.PercolateAction; import org.elasticsearch.action.percolate.TransportMultiPercolateAction; import org.elasticsearch.action.percolate.TransportPercolateAction; -import org.elasticsearch.action.percolate.TransportShardMultiPercolateAction; import org.elasticsearch.action.search.ClearScrollAction; import org.elasticsearch.action.search.MultiSearchAction; import org.elasticsearch.action.search.SearchAction; @@ -331,7 +330,7 @@ public class ActionModule extends AbstractModule { registerAction(SearchScrollAction.INSTANCE, TransportSearchScrollAction.class); registerAction(MultiSearchAction.INSTANCE, TransportMultiSearchAction.class); registerAction(PercolateAction.INSTANCE, TransportPercolateAction.class); - registerAction(MultiPercolateAction.INSTANCE, TransportMultiPercolateAction.class, TransportShardMultiPercolateAction.class); + registerAction(MultiPercolateAction.INSTANCE, TransportMultiPercolateAction.class); registerAction(ExplainAction.INSTANCE, TransportExplainAction.class); registerAction(ClearScrollAction.INSTANCE, TransportClearScrollAction.class); registerAction(RecoveryAction.INSTANCE, TransportRecoveryAction.class); diff --git a/core/src/main/java/org/elasticsearch/action/admin/cluster/health/TransportClusterHealthAction.java b/core/src/main/java/org/elasticsearch/action/admin/cluster/health/TransportClusterHealthAction.java index 39d6a8daeb0..069f0ebe1b8 100644 --- a/core/src/main/java/org/elasticsearch/action/admin/cluster/health/TransportClusterHealthAction.java +++ b/core/src/main/java/org/elasticsearch/action/admin/cluster/health/TransportClusterHealthAction.java @@ -24,7 +24,6 @@ import org.elasticsearch.action.support.ActionFilters; import org.elasticsearch.action.support.IndicesOptions; import org.elasticsearch.action.support.master.TransportMasterNodeReadAction; import org.elasticsearch.cluster.ClusterName; -import org.elasticsearch.cluster.ClusterService; import org.elasticsearch.cluster.ClusterState; import org.elasticsearch.cluster.ClusterStateObserver; import org.elasticsearch.cluster.ClusterStateUpdateTask; @@ -32,6 +31,7 @@ import org.elasticsearch.cluster.block.ClusterBlockException; import org.elasticsearch.cluster.health.ClusterHealthStatus; import org.elasticsearch.cluster.metadata.IndexNameExpressionResolver; import org.elasticsearch.cluster.routing.UnassignedInfo; +import org.elasticsearch.cluster.service.ClusterService; import org.elasticsearch.common.Strings; import org.elasticsearch.common.inject.Inject; import org.elasticsearch.common.settings.Settings; diff --git a/core/src/main/java/org/elasticsearch/action/admin/cluster/node/hotthreads/TransportNodesHotThreadsAction.java b/core/src/main/java/org/elasticsearch/action/admin/cluster/node/hotthreads/TransportNodesHotThreadsAction.java index c743a1d2a91..d53f651da45 100644 --- a/core/src/main/java/org/elasticsearch/action/admin/cluster/node/hotthreads/TransportNodesHotThreadsAction.java +++ b/core/src/main/java/org/elasticsearch/action/admin/cluster/node/hotthreads/TransportNodesHotThreadsAction.java @@ -24,8 +24,8 @@ import org.elasticsearch.action.support.ActionFilters; import org.elasticsearch.action.support.nodes.BaseNodeRequest; import org.elasticsearch.action.support.nodes.TransportNodesAction; import org.elasticsearch.cluster.ClusterName; -import org.elasticsearch.cluster.ClusterService; import org.elasticsearch.cluster.metadata.IndexNameExpressionResolver; +import org.elasticsearch.cluster.service.ClusterService; import org.elasticsearch.common.inject.Inject; import org.elasticsearch.common.io.stream.StreamInput; import org.elasticsearch.common.io.stream.StreamOutput; diff --git a/core/src/main/java/org/elasticsearch/action/admin/cluster/node/info/TransportNodesInfoAction.java b/core/src/main/java/org/elasticsearch/action/admin/cluster/node/info/TransportNodesInfoAction.java index b14450f9eb1..f52729faa4f 100644 --- a/core/src/main/java/org/elasticsearch/action/admin/cluster/node/info/TransportNodesInfoAction.java +++ b/core/src/main/java/org/elasticsearch/action/admin/cluster/node/info/TransportNodesInfoAction.java @@ -23,8 +23,8 @@ import org.elasticsearch.action.support.ActionFilters; import org.elasticsearch.action.support.nodes.BaseNodeRequest; import org.elasticsearch.action.support.nodes.TransportNodesAction; import org.elasticsearch.cluster.ClusterName; -import org.elasticsearch.cluster.ClusterService; import org.elasticsearch.cluster.metadata.IndexNameExpressionResolver; +import org.elasticsearch.cluster.service.ClusterService; import org.elasticsearch.common.inject.Inject; import org.elasticsearch.common.io.stream.StreamInput; import org.elasticsearch.common.io.stream.StreamOutput; diff --git a/core/src/main/java/org/elasticsearch/action/admin/cluster/node/liveness/TransportLivenessAction.java b/core/src/main/java/org/elasticsearch/action/admin/cluster/node/liveness/TransportLivenessAction.java index 65913bc4b28..8b29b9379ac 100644 --- a/core/src/main/java/org/elasticsearch/action/admin/cluster/node/liveness/TransportLivenessAction.java +++ b/core/src/main/java/org/elasticsearch/action/admin/cluster/node/liveness/TransportLivenessAction.java @@ -20,7 +20,7 @@ package org.elasticsearch.action.admin.cluster.node.liveness; import org.elasticsearch.cluster.ClusterName; -import org.elasticsearch.cluster.ClusterService; +import org.elasticsearch.cluster.service.ClusterService; import org.elasticsearch.common.inject.Inject; import org.elasticsearch.threadpool.ThreadPool; import org.elasticsearch.transport.TransportChannel; diff --git a/core/src/main/java/org/elasticsearch/action/admin/cluster/node/stats/TransportNodesStatsAction.java b/core/src/main/java/org/elasticsearch/action/admin/cluster/node/stats/TransportNodesStatsAction.java index a8554090473..8ba3d00558b 100644 --- a/core/src/main/java/org/elasticsearch/action/admin/cluster/node/stats/TransportNodesStatsAction.java +++ b/core/src/main/java/org/elasticsearch/action/admin/cluster/node/stats/TransportNodesStatsAction.java @@ -23,8 +23,8 @@ import org.elasticsearch.action.support.ActionFilters; import org.elasticsearch.action.support.nodes.BaseNodeRequest; import org.elasticsearch.action.support.nodes.TransportNodesAction; import org.elasticsearch.cluster.ClusterName; -import org.elasticsearch.cluster.ClusterService; import org.elasticsearch.cluster.metadata.IndexNameExpressionResolver; +import org.elasticsearch.cluster.service.ClusterService; import org.elasticsearch.common.inject.Inject; import org.elasticsearch.common.io.stream.StreamInput; import org.elasticsearch.common.io.stream.StreamOutput; diff --git a/core/src/main/java/org/elasticsearch/action/admin/cluster/node/tasks/cancel/TransportCancelTasksAction.java b/core/src/main/java/org/elasticsearch/action/admin/cluster/node/tasks/cancel/TransportCancelTasksAction.java index 874f230587d..336f4c84596 100644 --- a/core/src/main/java/org/elasticsearch/action/admin/cluster/node/tasks/cancel/TransportCancelTasksAction.java +++ b/core/src/main/java/org/elasticsearch/action/admin/cluster/node/tasks/cancel/TransportCancelTasksAction.java @@ -26,10 +26,10 @@ import org.elasticsearch.action.admin.cluster.node.tasks.list.TaskInfo; import org.elasticsearch.action.support.ActionFilters; import org.elasticsearch.action.support.tasks.TransportTasksAction; import org.elasticsearch.cluster.ClusterName; -import org.elasticsearch.cluster.ClusterService; import org.elasticsearch.cluster.ClusterState; import org.elasticsearch.cluster.metadata.IndexNameExpressionResolver; import org.elasticsearch.cluster.node.DiscoveryNode; +import org.elasticsearch.cluster.service.ClusterService; import org.elasticsearch.common.inject.Inject; import org.elasticsearch.common.io.stream.StreamInput; import org.elasticsearch.common.io.stream.StreamOutput; diff --git a/core/src/main/java/org/elasticsearch/action/admin/cluster/node/tasks/list/TransportListTasksAction.java b/core/src/main/java/org/elasticsearch/action/admin/cluster/node/tasks/list/TransportListTasksAction.java index d867d9d8555..d5175e263e7 100644 --- a/core/src/main/java/org/elasticsearch/action/admin/cluster/node/tasks/list/TransportListTasksAction.java +++ b/core/src/main/java/org/elasticsearch/action/admin/cluster/node/tasks/list/TransportListTasksAction.java @@ -26,8 +26,8 @@ import org.elasticsearch.action.TaskOperationFailure; import org.elasticsearch.action.support.ActionFilters; import org.elasticsearch.action.support.tasks.TransportTasksAction; import org.elasticsearch.cluster.ClusterName; -import org.elasticsearch.cluster.ClusterService; import org.elasticsearch.cluster.metadata.IndexNameExpressionResolver; +import org.elasticsearch.cluster.service.ClusterService; import org.elasticsearch.common.inject.Inject; import org.elasticsearch.common.io.stream.StreamInput; import org.elasticsearch.common.settings.Settings; diff --git a/core/src/main/java/org/elasticsearch/action/admin/cluster/repositories/delete/TransportDeleteRepositoryAction.java b/core/src/main/java/org/elasticsearch/action/admin/cluster/repositories/delete/TransportDeleteRepositoryAction.java index 79e51f9a46e..a17d2aac892 100644 --- a/core/src/main/java/org/elasticsearch/action/admin/cluster/repositories/delete/TransportDeleteRepositoryAction.java +++ b/core/src/main/java/org/elasticsearch/action/admin/cluster/repositories/delete/TransportDeleteRepositoryAction.java @@ -22,12 +22,12 @@ package org.elasticsearch.action.admin.cluster.repositories.delete; import org.elasticsearch.action.ActionListener; import org.elasticsearch.action.support.ActionFilters; import org.elasticsearch.action.support.master.TransportMasterNodeAction; -import org.elasticsearch.cluster.ClusterService; import org.elasticsearch.cluster.ClusterState; import org.elasticsearch.cluster.ack.ClusterStateUpdateResponse; import org.elasticsearch.cluster.block.ClusterBlockException; import org.elasticsearch.cluster.block.ClusterBlockLevel; import org.elasticsearch.cluster.metadata.IndexNameExpressionResolver; +import org.elasticsearch.cluster.service.ClusterService; import org.elasticsearch.common.inject.Inject; import org.elasticsearch.common.settings.Settings; import org.elasticsearch.repositories.RepositoriesService; diff --git a/core/src/main/java/org/elasticsearch/action/admin/cluster/repositories/get/TransportGetRepositoriesAction.java b/core/src/main/java/org/elasticsearch/action/admin/cluster/repositories/get/TransportGetRepositoriesAction.java index 39d9cacbda3..490d20f086c 100644 --- a/core/src/main/java/org/elasticsearch/action/admin/cluster/repositories/get/TransportGetRepositoriesAction.java +++ b/core/src/main/java/org/elasticsearch/action/admin/cluster/repositories/get/TransportGetRepositoriesAction.java @@ -22,7 +22,6 @@ package org.elasticsearch.action.admin.cluster.repositories.get; import org.elasticsearch.action.ActionListener; import org.elasticsearch.action.support.ActionFilters; import org.elasticsearch.action.support.master.TransportMasterNodeReadAction; -import org.elasticsearch.cluster.ClusterService; import org.elasticsearch.cluster.ClusterState; import org.elasticsearch.cluster.block.ClusterBlockException; import org.elasticsearch.cluster.block.ClusterBlockLevel; @@ -30,6 +29,7 @@ import org.elasticsearch.cluster.metadata.IndexNameExpressionResolver; import org.elasticsearch.cluster.metadata.MetaData; import org.elasticsearch.cluster.metadata.RepositoriesMetaData; import org.elasticsearch.cluster.metadata.RepositoryMetaData; +import org.elasticsearch.cluster.service.ClusterService; import org.elasticsearch.common.inject.Inject; import org.elasticsearch.common.regex.Regex; import org.elasticsearch.common.settings.Settings; diff --git a/core/src/main/java/org/elasticsearch/action/admin/cluster/repositories/put/TransportPutRepositoryAction.java b/core/src/main/java/org/elasticsearch/action/admin/cluster/repositories/put/TransportPutRepositoryAction.java index efc45f16cbd..d1639001352 100644 --- a/core/src/main/java/org/elasticsearch/action/admin/cluster/repositories/put/TransportPutRepositoryAction.java +++ b/core/src/main/java/org/elasticsearch/action/admin/cluster/repositories/put/TransportPutRepositoryAction.java @@ -22,12 +22,12 @@ package org.elasticsearch.action.admin.cluster.repositories.put; import org.elasticsearch.action.ActionListener; import org.elasticsearch.action.support.ActionFilters; import org.elasticsearch.action.support.master.TransportMasterNodeAction; -import org.elasticsearch.cluster.ClusterService; import org.elasticsearch.cluster.ClusterState; import org.elasticsearch.cluster.ack.ClusterStateUpdateResponse; import org.elasticsearch.cluster.block.ClusterBlockException; import org.elasticsearch.cluster.block.ClusterBlockLevel; import org.elasticsearch.cluster.metadata.IndexNameExpressionResolver; +import org.elasticsearch.cluster.service.ClusterService; import org.elasticsearch.common.inject.Inject; import org.elasticsearch.common.settings.Settings; import org.elasticsearch.repositories.RepositoriesService; diff --git a/core/src/main/java/org/elasticsearch/action/admin/cluster/repositories/verify/TransportVerifyRepositoryAction.java b/core/src/main/java/org/elasticsearch/action/admin/cluster/repositories/verify/TransportVerifyRepositoryAction.java index 8b1d9816004..2c75335dcaa 100644 --- a/core/src/main/java/org/elasticsearch/action/admin/cluster/repositories/verify/TransportVerifyRepositoryAction.java +++ b/core/src/main/java/org/elasticsearch/action/admin/cluster/repositories/verify/TransportVerifyRepositoryAction.java @@ -23,11 +23,11 @@ import org.elasticsearch.action.ActionListener; import org.elasticsearch.action.support.ActionFilters; import org.elasticsearch.action.support.master.TransportMasterNodeAction; import org.elasticsearch.cluster.ClusterName; -import org.elasticsearch.cluster.ClusterService; import org.elasticsearch.cluster.ClusterState; import org.elasticsearch.cluster.block.ClusterBlockException; import org.elasticsearch.cluster.block.ClusterBlockLevel; import org.elasticsearch.cluster.metadata.IndexNameExpressionResolver; +import org.elasticsearch.cluster.service.ClusterService; import org.elasticsearch.common.inject.Inject; import org.elasticsearch.common.settings.Settings; import org.elasticsearch.repositories.RepositoriesService; diff --git a/core/src/main/java/org/elasticsearch/action/admin/cluster/reroute/TransportClusterRerouteAction.java b/core/src/main/java/org/elasticsearch/action/admin/cluster/reroute/TransportClusterRerouteAction.java index d7ec84fb7a5..e6116dbfbc4 100644 --- a/core/src/main/java/org/elasticsearch/action/admin/cluster/reroute/TransportClusterRerouteAction.java +++ b/core/src/main/java/org/elasticsearch/action/admin/cluster/reroute/TransportClusterRerouteAction.java @@ -23,7 +23,6 @@ import org.elasticsearch.action.ActionListener; import org.elasticsearch.action.support.ActionFilters; import org.elasticsearch.action.support.master.TransportMasterNodeAction; import org.elasticsearch.cluster.AckedClusterStateUpdateTask; -import org.elasticsearch.cluster.ClusterService; import org.elasticsearch.cluster.ClusterState; import org.elasticsearch.cluster.block.ClusterBlockException; import org.elasticsearch.cluster.block.ClusterBlockLevel; @@ -31,6 +30,7 @@ import org.elasticsearch.cluster.metadata.IndexNameExpressionResolver; import org.elasticsearch.cluster.routing.allocation.AllocationService; import org.elasticsearch.cluster.routing.allocation.RoutingAllocation; import org.elasticsearch.cluster.routing.allocation.RoutingExplanations; +import org.elasticsearch.cluster.service.ClusterService; import org.elasticsearch.common.Priority; import org.elasticsearch.common.inject.Inject; import org.elasticsearch.common.settings.Settings; diff --git a/core/src/main/java/org/elasticsearch/action/admin/cluster/settings/TransportClusterUpdateSettingsAction.java b/core/src/main/java/org/elasticsearch/action/admin/cluster/settings/TransportClusterUpdateSettingsAction.java index 75f94921e61..60a0e7a8046 100644 --- a/core/src/main/java/org/elasticsearch/action/admin/cluster/settings/TransportClusterUpdateSettingsAction.java +++ b/core/src/main/java/org/elasticsearch/action/admin/cluster/settings/TransportClusterUpdateSettingsAction.java @@ -24,7 +24,6 @@ import org.elasticsearch.action.ActionListener; import org.elasticsearch.action.support.ActionFilters; import org.elasticsearch.action.support.master.TransportMasterNodeAction; import org.elasticsearch.cluster.AckedClusterStateUpdateTask; -import org.elasticsearch.cluster.ClusterService; import org.elasticsearch.cluster.ClusterState; import org.elasticsearch.cluster.block.ClusterBlockException; import org.elasticsearch.cluster.block.ClusterBlockLevel; @@ -33,6 +32,7 @@ import org.elasticsearch.cluster.metadata.MetaData; import org.elasticsearch.cluster.node.DiscoveryNode; import org.elasticsearch.cluster.routing.allocation.AllocationService; import org.elasticsearch.cluster.routing.allocation.RoutingAllocation; +import org.elasticsearch.cluster.service.ClusterService; import org.elasticsearch.common.Nullable; import org.elasticsearch.common.Priority; import org.elasticsearch.common.inject.Inject; diff --git a/core/src/main/java/org/elasticsearch/action/admin/cluster/shards/TransportClusterSearchShardsAction.java b/core/src/main/java/org/elasticsearch/action/admin/cluster/shards/TransportClusterSearchShardsAction.java index f8868e94bf0..8b26fd6c04f 100644 --- a/core/src/main/java/org/elasticsearch/action/admin/cluster/shards/TransportClusterSearchShardsAction.java +++ b/core/src/main/java/org/elasticsearch/action/admin/cluster/shards/TransportClusterSearchShardsAction.java @@ -22,7 +22,6 @@ package org.elasticsearch.action.admin.cluster.shards; import org.elasticsearch.action.ActionListener; import org.elasticsearch.action.support.ActionFilters; import org.elasticsearch.action.support.master.TransportMasterNodeReadAction; -import org.elasticsearch.cluster.ClusterService; import org.elasticsearch.cluster.ClusterState; import org.elasticsearch.cluster.block.ClusterBlockException; import org.elasticsearch.cluster.block.ClusterBlockLevel; @@ -31,6 +30,7 @@ import org.elasticsearch.cluster.node.DiscoveryNode; import org.elasticsearch.cluster.routing.GroupShardsIterator; import org.elasticsearch.cluster.routing.ShardIterator; import org.elasticsearch.cluster.routing.ShardRouting; +import org.elasticsearch.cluster.service.ClusterService; import org.elasticsearch.common.inject.Inject; import org.elasticsearch.common.settings.Settings; import org.elasticsearch.index.Index; diff --git a/core/src/main/java/org/elasticsearch/action/admin/cluster/snapshots/create/TransportCreateSnapshotAction.java b/core/src/main/java/org/elasticsearch/action/admin/cluster/snapshots/create/TransportCreateSnapshotAction.java index 3bee1a74e1d..2654ac0c269 100644 --- a/core/src/main/java/org/elasticsearch/action/admin/cluster/snapshots/create/TransportCreateSnapshotAction.java +++ b/core/src/main/java/org/elasticsearch/action/admin/cluster/snapshots/create/TransportCreateSnapshotAction.java @@ -22,12 +22,12 @@ package org.elasticsearch.action.admin.cluster.snapshots.create; import org.elasticsearch.action.ActionListener; import org.elasticsearch.action.support.ActionFilters; import org.elasticsearch.action.support.master.TransportMasterNodeAction; -import org.elasticsearch.cluster.ClusterService; import org.elasticsearch.cluster.ClusterState; import org.elasticsearch.cluster.block.ClusterBlockException; import org.elasticsearch.cluster.block.ClusterBlockLevel; import org.elasticsearch.cluster.metadata.IndexNameExpressionResolver; import org.elasticsearch.cluster.metadata.SnapshotId; +import org.elasticsearch.cluster.service.ClusterService; import org.elasticsearch.common.inject.Inject; import org.elasticsearch.common.settings.Settings; import org.elasticsearch.snapshots.SnapshotInfo; diff --git a/core/src/main/java/org/elasticsearch/action/admin/cluster/snapshots/delete/TransportDeleteSnapshotAction.java b/core/src/main/java/org/elasticsearch/action/admin/cluster/snapshots/delete/TransportDeleteSnapshotAction.java index 4e3c777b7d1..423e38cd258 100644 --- a/core/src/main/java/org/elasticsearch/action/admin/cluster/snapshots/delete/TransportDeleteSnapshotAction.java +++ b/core/src/main/java/org/elasticsearch/action/admin/cluster/snapshots/delete/TransportDeleteSnapshotAction.java @@ -22,12 +22,12 @@ package org.elasticsearch.action.admin.cluster.snapshots.delete; import org.elasticsearch.action.ActionListener; import org.elasticsearch.action.support.ActionFilters; import org.elasticsearch.action.support.master.TransportMasterNodeAction; -import org.elasticsearch.cluster.ClusterService; import org.elasticsearch.cluster.ClusterState; import org.elasticsearch.cluster.block.ClusterBlockException; import org.elasticsearch.cluster.block.ClusterBlockLevel; import org.elasticsearch.cluster.metadata.IndexNameExpressionResolver; import org.elasticsearch.cluster.metadata.SnapshotId; +import org.elasticsearch.cluster.service.ClusterService; import org.elasticsearch.common.inject.Inject; import org.elasticsearch.common.settings.Settings; import org.elasticsearch.snapshots.SnapshotsService; diff --git a/core/src/main/java/org/elasticsearch/action/admin/cluster/snapshots/get/TransportGetSnapshotsAction.java b/core/src/main/java/org/elasticsearch/action/admin/cluster/snapshots/get/TransportGetSnapshotsAction.java index 478146de357..0198102a200 100644 --- a/core/src/main/java/org/elasticsearch/action/admin/cluster/snapshots/get/TransportGetSnapshotsAction.java +++ b/core/src/main/java/org/elasticsearch/action/admin/cluster/snapshots/get/TransportGetSnapshotsAction.java @@ -22,12 +22,12 @@ package org.elasticsearch.action.admin.cluster.snapshots.get; import org.elasticsearch.action.ActionListener; import org.elasticsearch.action.support.ActionFilters; import org.elasticsearch.action.support.master.TransportMasterNodeAction; -import org.elasticsearch.cluster.ClusterService; import org.elasticsearch.cluster.ClusterState; import org.elasticsearch.cluster.block.ClusterBlockException; import org.elasticsearch.cluster.block.ClusterBlockLevel; import org.elasticsearch.cluster.metadata.IndexNameExpressionResolver; import org.elasticsearch.cluster.metadata.SnapshotId; +import org.elasticsearch.cluster.service.ClusterService; import org.elasticsearch.common.inject.Inject; import org.elasticsearch.common.regex.Regex; import org.elasticsearch.common.settings.Settings; diff --git a/core/src/main/java/org/elasticsearch/action/admin/cluster/snapshots/restore/TransportRestoreSnapshotAction.java b/core/src/main/java/org/elasticsearch/action/admin/cluster/snapshots/restore/TransportRestoreSnapshotAction.java index ae802342824..cbbc195370c 100644 --- a/core/src/main/java/org/elasticsearch/action/admin/cluster/snapshots/restore/TransportRestoreSnapshotAction.java +++ b/core/src/main/java/org/elasticsearch/action/admin/cluster/snapshots/restore/TransportRestoreSnapshotAction.java @@ -22,12 +22,12 @@ package org.elasticsearch.action.admin.cluster.snapshots.restore; import org.elasticsearch.action.ActionListener; import org.elasticsearch.action.support.ActionFilters; import org.elasticsearch.action.support.master.TransportMasterNodeAction; -import org.elasticsearch.cluster.ClusterService; import org.elasticsearch.cluster.ClusterState; import org.elasticsearch.cluster.block.ClusterBlockException; import org.elasticsearch.cluster.block.ClusterBlockLevel; import org.elasticsearch.cluster.metadata.IndexNameExpressionResolver; import org.elasticsearch.cluster.metadata.SnapshotId; +import org.elasticsearch.cluster.service.ClusterService; import org.elasticsearch.common.inject.Inject; import org.elasticsearch.common.settings.Settings; import org.elasticsearch.snapshots.RestoreInfo; diff --git a/core/src/main/java/org/elasticsearch/action/admin/cluster/snapshots/status/TransportNodesSnapshotsStatus.java b/core/src/main/java/org/elasticsearch/action/admin/cluster/snapshots/status/TransportNodesSnapshotsStatus.java index 45c3f89919e..0bc13db9644 100644 --- a/core/src/main/java/org/elasticsearch/action/admin/cluster/snapshots/status/TransportNodesSnapshotsStatus.java +++ b/core/src/main/java/org/elasticsearch/action/admin/cluster/snapshots/status/TransportNodesSnapshotsStatus.java @@ -28,10 +28,10 @@ import org.elasticsearch.action.support.nodes.BaseNodesRequest; import org.elasticsearch.action.support.nodes.BaseNodesResponse; import org.elasticsearch.action.support.nodes.TransportNodesAction; import org.elasticsearch.cluster.ClusterName; -import org.elasticsearch.cluster.ClusterService; import org.elasticsearch.cluster.metadata.IndexNameExpressionResolver; import org.elasticsearch.cluster.metadata.SnapshotId; import org.elasticsearch.cluster.node.DiscoveryNode; +import org.elasticsearch.cluster.service.ClusterService; import org.elasticsearch.common.inject.Inject; import org.elasticsearch.common.io.stream.StreamInput; import org.elasticsearch.common.io.stream.StreamOutput; diff --git a/core/src/main/java/org/elasticsearch/action/admin/cluster/snapshots/status/TransportSnapshotsStatusAction.java b/core/src/main/java/org/elasticsearch/action/admin/cluster/snapshots/status/TransportSnapshotsStatusAction.java index fc19dd986de..efa156eaa0c 100644 --- a/core/src/main/java/org/elasticsearch/action/admin/cluster/snapshots/status/TransportSnapshotsStatusAction.java +++ b/core/src/main/java/org/elasticsearch/action/admin/cluster/snapshots/status/TransportSnapshotsStatusAction.java @@ -24,13 +24,13 @@ import com.carrotsearch.hppc.cursors.ObjectObjectCursor; import org.elasticsearch.action.ActionListener; import org.elasticsearch.action.support.ActionFilters; import org.elasticsearch.action.support.master.TransportMasterNodeAction; -import org.elasticsearch.cluster.ClusterService; import org.elasticsearch.cluster.ClusterState; import org.elasticsearch.cluster.SnapshotsInProgress; import org.elasticsearch.cluster.block.ClusterBlockException; import org.elasticsearch.cluster.block.ClusterBlockLevel; import org.elasticsearch.cluster.metadata.IndexNameExpressionResolver; import org.elasticsearch.cluster.metadata.SnapshotId; +import org.elasticsearch.cluster.service.ClusterService; import org.elasticsearch.common.Strings; import org.elasticsearch.common.inject.Inject; import org.elasticsearch.common.settings.Settings; diff --git a/core/src/main/java/org/elasticsearch/action/admin/cluster/state/TransportClusterStateAction.java b/core/src/main/java/org/elasticsearch/action/admin/cluster/state/TransportClusterStateAction.java index 1dd88033f82..4bd826237c5 100644 --- a/core/src/main/java/org/elasticsearch/action/admin/cluster/state/TransportClusterStateAction.java +++ b/core/src/main/java/org/elasticsearch/action/admin/cluster/state/TransportClusterStateAction.java @@ -24,7 +24,6 @@ import org.elasticsearch.action.ActionListener; import org.elasticsearch.action.support.ActionFilters; import org.elasticsearch.action.support.master.TransportMasterNodeReadAction; import org.elasticsearch.cluster.ClusterName; -import org.elasticsearch.cluster.ClusterService; import org.elasticsearch.cluster.ClusterState; import org.elasticsearch.cluster.block.ClusterBlockException; import org.elasticsearch.cluster.metadata.IndexMetaData; @@ -32,6 +31,7 @@ import org.elasticsearch.cluster.metadata.IndexNameExpressionResolver; import org.elasticsearch.cluster.metadata.MetaData; import org.elasticsearch.cluster.metadata.MetaData.Custom; import org.elasticsearch.cluster.routing.RoutingTable; +import org.elasticsearch.cluster.service.ClusterService; import org.elasticsearch.common.inject.Inject; import org.elasticsearch.common.settings.Settings; import org.elasticsearch.threadpool.ThreadPool; diff --git a/core/src/main/java/org/elasticsearch/action/admin/cluster/stats/ClusterStatsIndices.java b/core/src/main/java/org/elasticsearch/action/admin/cluster/stats/ClusterStatsIndices.java index ec7017160c0..f8304bf76a9 100644 --- a/core/src/main/java/org/elasticsearch/action/admin/cluster/stats/ClusterStatsIndices.java +++ b/core/src/main/java/org/elasticsearch/action/admin/cluster/stats/ClusterStatsIndices.java @@ -31,7 +31,7 @@ import org.elasticsearch.common.xcontent.XContentBuilderString; import org.elasticsearch.index.cache.query.QueryCacheStats; import org.elasticsearch.index.engine.SegmentsStats; import org.elasticsearch.index.fielddata.FieldDataStats; -import org.elasticsearch.index.percolator.PercolateStats; +import org.elasticsearch.index.percolator.PercolatorQueryCacheStats; import org.elasticsearch.index.shard.DocsStats; import org.elasticsearch.index.store.StoreStats; import org.elasticsearch.search.suggest.completion.CompletionStats; @@ -48,7 +48,7 @@ public class ClusterStatsIndices implements ToXContent, Streamable { private QueryCacheStats queryCache; private CompletionStats completion; private SegmentsStats segments; - private PercolateStats percolate; + private PercolatorQueryCacheStats percolatorCache; private ClusterStatsIndices() { } @@ -62,7 +62,7 @@ public class ClusterStatsIndices implements ToXContent, Streamable { this.queryCache = new QueryCacheStats(); this.completion = new CompletionStats(); this.segments = new SegmentsStats(); - this.percolate = new PercolateStats(); + this.percolatorCache = new PercolatorQueryCacheStats(); for (ClusterStatsNodeResponse r : nodeResponses) { for (org.elasticsearch.action.admin.indices.stats.ShardStats shardStats : r.shardsStats()) { @@ -85,7 +85,7 @@ public class ClusterStatsIndices implements ToXContent, Streamable { queryCache.add(shardCommonStats.queryCache); completion.add(shardCommonStats.completion); segments.add(shardCommonStats.segments); - percolate.add(shardCommonStats.percolate); + percolatorCache.add(shardCommonStats.percolatorCache); } } @@ -128,8 +128,8 @@ public class ClusterStatsIndices implements ToXContent, Streamable { return segments; } - public PercolateStats getPercolate() { - return percolate; + public PercolatorQueryCacheStats getPercolatorCache() { + return percolatorCache; } @Override @@ -142,7 +142,7 @@ public class ClusterStatsIndices implements ToXContent, Streamable { queryCache = QueryCacheStats.readQueryCacheStats(in); completion = CompletionStats.readCompletionStats(in); segments = SegmentsStats.readSegmentsStats(in); - percolate = PercolateStats.readPercolateStats(in); + percolatorCache = PercolatorQueryCacheStats.readPercolateStats(in); } @Override @@ -155,7 +155,7 @@ public class ClusterStatsIndices implements ToXContent, Streamable { queryCache.writeTo(out); completion.writeTo(out); segments.writeTo(out); - percolate.writeTo(out); + percolatorCache.writeTo(out); } public static ClusterStatsIndices readIndicesStats(StreamInput in) throws IOException { @@ -178,7 +178,7 @@ public class ClusterStatsIndices implements ToXContent, Streamable { queryCache.toXContent(builder, params); completion.toXContent(builder, params); segments.toXContent(builder, params); - percolate.toXContent(builder, params); + percolatorCache.toXContent(builder, params); return builder; } diff --git a/core/src/main/java/org/elasticsearch/action/admin/cluster/stats/TransportClusterStatsAction.java b/core/src/main/java/org/elasticsearch/action/admin/cluster/stats/TransportClusterStatsAction.java index c70122920f5..6d1614eb485 100644 --- a/core/src/main/java/org/elasticsearch/action/admin/cluster/stats/TransportClusterStatsAction.java +++ b/core/src/main/java/org/elasticsearch/action/admin/cluster/stats/TransportClusterStatsAction.java @@ -28,10 +28,10 @@ import org.elasticsearch.action.support.ActionFilters; import org.elasticsearch.action.support.nodes.BaseNodeRequest; import org.elasticsearch.action.support.nodes.TransportNodesAction; import org.elasticsearch.cluster.ClusterName; -import org.elasticsearch.cluster.ClusterService; import org.elasticsearch.cluster.health.ClusterHealthStatus; import org.elasticsearch.cluster.health.ClusterStateHealth; import org.elasticsearch.cluster.metadata.IndexNameExpressionResolver; +import org.elasticsearch.cluster.service.ClusterService; import org.elasticsearch.common.inject.Inject; import org.elasticsearch.common.io.stream.StreamInput; import org.elasticsearch.common.io.stream.StreamOutput; @@ -56,7 +56,7 @@ public class TransportClusterStatsAction extends TransportNodesActiontrue iff the settings update should only add but not update settings. If the setting already exists + * it should not be overwritten by this update. The default is false + */ + public boolean isPreserveExisting() { + return preserveExisting; + } + + /** + * Iff set to true this settings update will only add settings not already set on an index. Existing settings remain + * unchanged. + */ + public UpdateSettingsClusterStateUpdateRequest setPreserveExisting(boolean preserveExisting) { + this.preserveExisting = preserveExisting; + return this; } /** diff --git a/core/src/main/java/org/elasticsearch/action/admin/indices/settings/put/UpdateSettingsRequest.java b/core/src/main/java/org/elasticsearch/action/admin/indices/settings/put/UpdateSettingsRequest.java index c654d6926fa..fb4525a6842 100644 --- a/core/src/main/java/org/elasticsearch/action/admin/indices/settings/put/UpdateSettingsRequest.java +++ b/core/src/main/java/org/elasticsearch/action/admin/indices/settings/put/UpdateSettingsRequest.java @@ -47,6 +47,7 @@ public class UpdateSettingsRequest extends AcknowledgedRequesttrue iff the settings update should only add but not update settings. If the setting already exists + * it should not be overwritten by this update. The default is false + */ + public boolean isPreserveExisting() { + return preserveExisting; + } + + /** + * Iff set to true this settings update will only add settings not already set on an index. Existing settings remain + * unchanged. + */ + public UpdateSettingsRequest setPreserveExisting(boolean preserveExisting) { + this.preserveExisting = preserveExisting; + return this; + } + /** * Sets the settings to be updated (either json/yaml/properties format) */ @@ -149,6 +167,7 @@ public class UpdateSettingsRequest extends AcknowledgedRequest { } public IndicesStatsRequest percolate(boolean percolate) { - flags.set(Flag.Percolate, percolate); + flags.set(Flag.PercolatorCache, percolate); return this; } public boolean percolate() { - return flags.isSet(Flag.Percolate); + return flags.isSet(Flag.PercolatorCache); } public IndicesStatsRequest segments(boolean segments) { diff --git a/core/src/main/java/org/elasticsearch/action/admin/indices/stats/TransportIndicesStatsAction.java b/core/src/main/java/org/elasticsearch/action/admin/indices/stats/TransportIndicesStatsAction.java index 2189973d9b7..8c12dfa9fda 100644 --- a/core/src/main/java/org/elasticsearch/action/admin/indices/stats/TransportIndicesStatsAction.java +++ b/core/src/main/java/org/elasticsearch/action/admin/indices/stats/TransportIndicesStatsAction.java @@ -22,13 +22,13 @@ package org.elasticsearch.action.admin.indices.stats; import org.elasticsearch.action.ShardOperationFailedException; import org.elasticsearch.action.support.ActionFilters; import org.elasticsearch.action.support.broadcast.node.TransportBroadcastByNodeAction; -import org.elasticsearch.cluster.ClusterService; import org.elasticsearch.cluster.ClusterState; import org.elasticsearch.cluster.block.ClusterBlockException; import org.elasticsearch.cluster.block.ClusterBlockLevel; import org.elasticsearch.cluster.metadata.IndexNameExpressionResolver; import org.elasticsearch.cluster.routing.ShardRouting; import org.elasticsearch.cluster.routing.ShardsIterator; +import org.elasticsearch.cluster.service.ClusterService; import org.elasticsearch.common.inject.Inject; import org.elasticsearch.common.io.stream.StreamInput; import org.elasticsearch.common.settings.Settings; @@ -140,7 +140,7 @@ public class TransportIndicesStatsAction extends TransportBroadcastByNodeAction< flags.fieldDataFields(request.fieldDataFields()); } if (request.percolate()) { - flags.set(CommonStatsFlags.Flag.Percolate); + flags.set(CommonStatsFlags.Flag.PercolatorCache); } if (request.segments()) { flags.set(CommonStatsFlags.Flag.Segments); @@ -163,6 +163,6 @@ public class TransportIndicesStatsAction extends TransportBroadcastByNodeAction< flags.set(CommonStatsFlags.Flag.Recovery); } - return new ShardStats(indexShard.routingEntry(), indexShard.shardPath(), new CommonStats(indicesService.getIndicesQueryCache(), indexShard, flags), indexShard.commitStats()); + return new ShardStats(indexShard.routingEntry(), indexShard.shardPath(), new CommonStats(indicesService.getIndicesQueryCache(), indexService.cache().getPercolatorQueryCache(), indexShard, flags), indexShard.commitStats()); } } diff --git a/core/src/main/java/org/elasticsearch/action/admin/indices/template/delete/TransportDeleteIndexTemplateAction.java b/core/src/main/java/org/elasticsearch/action/admin/indices/template/delete/TransportDeleteIndexTemplateAction.java index 9eab0f80e50..0763f232711 100644 --- a/core/src/main/java/org/elasticsearch/action/admin/indices/template/delete/TransportDeleteIndexTemplateAction.java +++ b/core/src/main/java/org/elasticsearch/action/admin/indices/template/delete/TransportDeleteIndexTemplateAction.java @@ -21,12 +21,12 @@ package org.elasticsearch.action.admin.indices.template.delete; import org.elasticsearch.action.ActionListener; import org.elasticsearch.action.support.ActionFilters; import org.elasticsearch.action.support.master.TransportMasterNodeAction; -import org.elasticsearch.cluster.ClusterService; import org.elasticsearch.cluster.ClusterState; import org.elasticsearch.cluster.block.ClusterBlockException; import org.elasticsearch.cluster.block.ClusterBlockLevel; import org.elasticsearch.cluster.metadata.IndexNameExpressionResolver; import org.elasticsearch.cluster.metadata.MetaDataIndexTemplateService; +import org.elasticsearch.cluster.service.ClusterService; import org.elasticsearch.common.inject.Inject; import org.elasticsearch.common.settings.Settings; import org.elasticsearch.threadpool.ThreadPool; diff --git a/core/src/main/java/org/elasticsearch/action/admin/indices/template/get/TransportGetIndexTemplatesAction.java b/core/src/main/java/org/elasticsearch/action/admin/indices/template/get/TransportGetIndexTemplatesAction.java index a43397e48dc..672ca1a9080 100644 --- a/core/src/main/java/org/elasticsearch/action/admin/indices/template/get/TransportGetIndexTemplatesAction.java +++ b/core/src/main/java/org/elasticsearch/action/admin/indices/template/get/TransportGetIndexTemplatesAction.java @@ -22,12 +22,12 @@ import com.carrotsearch.hppc.cursors.ObjectObjectCursor; import org.elasticsearch.action.ActionListener; import org.elasticsearch.action.support.ActionFilters; import org.elasticsearch.action.support.master.TransportMasterNodeReadAction; -import org.elasticsearch.cluster.ClusterService; import org.elasticsearch.cluster.ClusterState; import org.elasticsearch.cluster.block.ClusterBlockException; import org.elasticsearch.cluster.block.ClusterBlockLevel; import org.elasticsearch.cluster.metadata.IndexNameExpressionResolver; import org.elasticsearch.cluster.metadata.IndexTemplateMetaData; +import org.elasticsearch.cluster.service.ClusterService; import org.elasticsearch.common.inject.Inject; import org.elasticsearch.common.regex.Regex; import org.elasticsearch.common.settings.Settings; diff --git a/core/src/main/java/org/elasticsearch/action/admin/indices/template/put/TransportPutIndexTemplateAction.java b/core/src/main/java/org/elasticsearch/action/admin/indices/template/put/TransportPutIndexTemplateAction.java index c5fed57d013..02aad2f7ff4 100644 --- a/core/src/main/java/org/elasticsearch/action/admin/indices/template/put/TransportPutIndexTemplateAction.java +++ b/core/src/main/java/org/elasticsearch/action/admin/indices/template/put/TransportPutIndexTemplateAction.java @@ -21,13 +21,13 @@ package org.elasticsearch.action.admin.indices.template.put; import org.elasticsearch.action.ActionListener; import org.elasticsearch.action.support.ActionFilters; import org.elasticsearch.action.support.master.TransportMasterNodeAction; -import org.elasticsearch.cluster.ClusterService; import org.elasticsearch.cluster.ClusterState; import org.elasticsearch.cluster.block.ClusterBlockException; import org.elasticsearch.cluster.block.ClusterBlockLevel; import org.elasticsearch.cluster.metadata.IndexMetaData; import org.elasticsearch.cluster.metadata.IndexNameExpressionResolver; import org.elasticsearch.cluster.metadata.MetaDataIndexTemplateService; +import org.elasticsearch.cluster.service.ClusterService; import org.elasticsearch.common.inject.Inject; import org.elasticsearch.common.settings.IndexScopedSettings; import org.elasticsearch.common.settings.Settings; diff --git a/core/src/main/java/org/elasticsearch/action/admin/indices/upgrade/get/TransportUpgradeStatusAction.java b/core/src/main/java/org/elasticsearch/action/admin/indices/upgrade/get/TransportUpgradeStatusAction.java index 6b37f56ed4a..cf288e0cc6f 100644 --- a/core/src/main/java/org/elasticsearch/action/admin/indices/upgrade/get/TransportUpgradeStatusAction.java +++ b/core/src/main/java/org/elasticsearch/action/admin/indices/upgrade/get/TransportUpgradeStatusAction.java @@ -23,13 +23,13 @@ import org.elasticsearch.Version; import org.elasticsearch.action.ShardOperationFailedException; import org.elasticsearch.action.support.ActionFilters; import org.elasticsearch.action.support.broadcast.node.TransportBroadcastByNodeAction; -import org.elasticsearch.cluster.ClusterService; import org.elasticsearch.cluster.ClusterState; import org.elasticsearch.cluster.block.ClusterBlockException; import org.elasticsearch.cluster.block.ClusterBlockLevel; import org.elasticsearch.cluster.metadata.IndexNameExpressionResolver; import org.elasticsearch.cluster.routing.ShardRouting; import org.elasticsearch.cluster.routing.ShardsIterator; +import org.elasticsearch.cluster.service.ClusterService; import org.elasticsearch.common.inject.Inject; import org.elasticsearch.common.io.stream.StreamInput; import org.elasticsearch.common.settings.Settings; diff --git a/core/src/main/java/org/elasticsearch/action/admin/indices/upgrade/post/TransportUpgradeAction.java b/core/src/main/java/org/elasticsearch/action/admin/indices/upgrade/post/TransportUpgradeAction.java index f3cf2da9fdd..cdf6f585e53 100644 --- a/core/src/main/java/org/elasticsearch/action/admin/indices/upgrade/post/TransportUpgradeAction.java +++ b/core/src/main/java/org/elasticsearch/action/admin/indices/upgrade/post/TransportUpgradeAction.java @@ -25,7 +25,6 @@ import org.elasticsearch.action.PrimaryMissingActionException; import org.elasticsearch.action.ShardOperationFailedException; import org.elasticsearch.action.support.ActionFilters; import org.elasticsearch.action.support.broadcast.node.TransportBroadcastByNodeAction; -import org.elasticsearch.cluster.ClusterService; import org.elasticsearch.cluster.ClusterState; import org.elasticsearch.cluster.block.ClusterBlockException; import org.elasticsearch.cluster.block.ClusterBlockLevel; @@ -35,6 +34,7 @@ import org.elasticsearch.cluster.routing.IndexRoutingTable; import org.elasticsearch.cluster.routing.RoutingTable; import org.elasticsearch.cluster.routing.ShardRouting; import org.elasticsearch.cluster.routing.ShardsIterator; +import org.elasticsearch.cluster.service.ClusterService; import org.elasticsearch.common.collect.Tuple; import org.elasticsearch.common.inject.Inject; import org.elasticsearch.common.io.stream.StreamInput; diff --git a/core/src/main/java/org/elasticsearch/action/admin/indices/upgrade/post/TransportUpgradeSettingsAction.java b/core/src/main/java/org/elasticsearch/action/admin/indices/upgrade/post/TransportUpgradeSettingsAction.java index 527adeaa3e5..403456cb903 100644 --- a/core/src/main/java/org/elasticsearch/action/admin/indices/upgrade/post/TransportUpgradeSettingsAction.java +++ b/core/src/main/java/org/elasticsearch/action/admin/indices/upgrade/post/TransportUpgradeSettingsAction.java @@ -22,13 +22,13 @@ package org.elasticsearch.action.admin.indices.upgrade.post; import org.elasticsearch.action.ActionListener; import org.elasticsearch.action.support.ActionFilters; import org.elasticsearch.action.support.master.TransportMasterNodeAction; -import org.elasticsearch.cluster.ClusterService; import org.elasticsearch.cluster.ClusterState; import org.elasticsearch.cluster.ack.ClusterStateUpdateResponse; import org.elasticsearch.cluster.block.ClusterBlockException; import org.elasticsearch.cluster.block.ClusterBlockLevel; import org.elasticsearch.cluster.metadata.IndexNameExpressionResolver; import org.elasticsearch.cluster.metadata.MetaDataUpdateSettingsService; +import org.elasticsearch.cluster.service.ClusterService; import org.elasticsearch.common.inject.Inject; import org.elasticsearch.common.settings.Settings; import org.elasticsearch.threadpool.ThreadPool; diff --git a/core/src/main/java/org/elasticsearch/action/admin/indices/validate/query/TransportValidateQueryAction.java b/core/src/main/java/org/elasticsearch/action/admin/indices/validate/query/TransportValidateQueryAction.java index fe02a1541a0..320f0696605 100644 --- a/core/src/main/java/org/elasticsearch/action/admin/indices/validate/query/TransportValidateQueryAction.java +++ b/core/src/main/java/org/elasticsearch/action/admin/indices/validate/query/TransportValidateQueryAction.java @@ -29,13 +29,13 @@ import org.elasticsearch.action.support.DefaultShardOperationFailedException; import org.elasticsearch.action.support.broadcast.BroadcastShardOperationFailedException; import org.elasticsearch.action.support.broadcast.TransportBroadcastAction; import org.elasticsearch.cache.recycler.PageCacheRecycler; -import org.elasticsearch.cluster.ClusterService; import org.elasticsearch.cluster.ClusterState; import org.elasticsearch.cluster.block.ClusterBlockException; import org.elasticsearch.cluster.block.ClusterBlockLevel; import org.elasticsearch.cluster.metadata.IndexNameExpressionResolver; import org.elasticsearch.cluster.routing.GroupShardsIterator; import org.elasticsearch.cluster.routing.ShardRouting; +import org.elasticsearch.cluster.service.ClusterService; import org.elasticsearch.common.ParsingException; import org.elasticsearch.common.Randomness; import org.elasticsearch.common.inject.Inject; diff --git a/core/src/main/java/org/elasticsearch/action/bulk/TransportBulkAction.java b/core/src/main/java/org/elasticsearch/action/bulk/TransportBulkAction.java index 135147d824c..9d9b36ba072 100644 --- a/core/src/main/java/org/elasticsearch/action/bulk/TransportBulkAction.java +++ b/core/src/main/java/org/elasticsearch/action/bulk/TransportBulkAction.java @@ -37,13 +37,13 @@ import org.elasticsearch.action.support.AutoCreateIndex; import org.elasticsearch.action.support.HandledTransportAction; import org.elasticsearch.action.update.TransportUpdateAction; import org.elasticsearch.action.update.UpdateRequest; -import org.elasticsearch.cluster.ClusterService; import org.elasticsearch.cluster.ClusterState; import org.elasticsearch.cluster.block.ClusterBlockLevel; import org.elasticsearch.cluster.metadata.IndexMetaData; import org.elasticsearch.cluster.metadata.IndexNameExpressionResolver; import org.elasticsearch.cluster.metadata.MappingMetaData; import org.elasticsearch.cluster.metadata.MetaData; +import org.elasticsearch.cluster.service.ClusterService; import org.elasticsearch.common.inject.Inject; import org.elasticsearch.common.settings.Settings; import org.elasticsearch.common.util.concurrent.AtomicArray; diff --git a/core/src/main/java/org/elasticsearch/action/bulk/TransportShardBulkAction.java b/core/src/main/java/org/elasticsearch/action/bulk/TransportShardBulkAction.java index 463f4ac23ac..76402df8aa4 100644 --- a/core/src/main/java/org/elasticsearch/action/bulk/TransportShardBulkAction.java +++ b/core/src/main/java/org/elasticsearch/action/bulk/TransportShardBulkAction.java @@ -35,12 +35,12 @@ import org.elasticsearch.action.support.replication.TransportReplicationAction; import org.elasticsearch.action.update.UpdateHelper; import org.elasticsearch.action.update.UpdateRequest; import org.elasticsearch.action.update.UpdateResponse; -import org.elasticsearch.cluster.ClusterService; import org.elasticsearch.cluster.action.index.MappingUpdatedAction; import org.elasticsearch.cluster.action.shard.ShardStateAction; import org.elasticsearch.cluster.metadata.IndexNameExpressionResolver; import org.elasticsearch.cluster.metadata.MappingMetaData; import org.elasticsearch.cluster.metadata.MetaData; +import org.elasticsearch.cluster.service.ClusterService; import org.elasticsearch.common.bytes.BytesReference; import org.elasticsearch.common.collect.Tuple; import org.elasticsearch.common.inject.Inject; diff --git a/core/src/main/java/org/elasticsearch/action/delete/TransportDeleteAction.java b/core/src/main/java/org/elasticsearch/action/delete/TransportDeleteAction.java index ec7a04ccc3f..783fab08bae 100644 --- a/core/src/main/java/org/elasticsearch/action/delete/TransportDeleteAction.java +++ b/core/src/main/java/org/elasticsearch/action/delete/TransportDeleteAction.java @@ -28,13 +28,12 @@ import org.elasticsearch.action.admin.indices.create.TransportCreateIndexAction; import org.elasticsearch.action.support.ActionFilters; import org.elasticsearch.action.support.AutoCreateIndex; import org.elasticsearch.action.support.replication.TransportReplicationAction; -import org.elasticsearch.cluster.ClusterService; import org.elasticsearch.cluster.ClusterState; -import org.elasticsearch.cluster.action.index.MappingUpdatedAction; import org.elasticsearch.cluster.action.shard.ShardStateAction; import org.elasticsearch.cluster.metadata.IndexNameExpressionResolver; import org.elasticsearch.cluster.metadata.MappingMetaData; import org.elasticsearch.cluster.metadata.MetaData; +import org.elasticsearch.cluster.service.ClusterService; import org.elasticsearch.common.collect.Tuple; import org.elasticsearch.common.inject.Inject; import org.elasticsearch.common.settings.Settings; diff --git a/core/src/main/java/org/elasticsearch/action/explain/TransportExplainAction.java b/core/src/main/java/org/elasticsearch/action/explain/TransportExplainAction.java index 5969e20065e..284e31406e2 100644 --- a/core/src/main/java/org/elasticsearch/action/explain/TransportExplainAction.java +++ b/core/src/main/java/org/elasticsearch/action/explain/TransportExplainAction.java @@ -27,10 +27,10 @@ import org.elasticsearch.action.RoutingMissingException; import org.elasticsearch.action.support.ActionFilters; import org.elasticsearch.action.support.single.shard.TransportSingleShardAction; import org.elasticsearch.cache.recycler.PageCacheRecycler; -import org.elasticsearch.cluster.ClusterService; import org.elasticsearch.cluster.ClusterState; import org.elasticsearch.cluster.metadata.IndexNameExpressionResolver; import org.elasticsearch.cluster.routing.ShardIterator; +import org.elasticsearch.cluster.service.ClusterService; import org.elasticsearch.common.inject.Inject; import org.elasticsearch.common.settings.Settings; import org.elasticsearch.common.util.BigArrays; diff --git a/core/src/main/java/org/elasticsearch/action/fieldstats/FieldStats.java b/core/src/main/java/org/elasticsearch/action/fieldstats/FieldStats.java index 2893b16a251..f661c4a8b58 100644 --- a/core/src/main/java/org/elasticsearch/action/fieldstats/FieldStats.java +++ b/core/src/main/java/org/elasticsearch/action/fieldstats/FieldStats.java @@ -28,6 +28,8 @@ import org.elasticsearch.common.joda.Joda; import org.elasticsearch.common.xcontent.ToXContent; import org.elasticsearch.common.xcontent.XContentBuilder; import org.elasticsearch.common.xcontent.XContentBuilderString; +import org.elasticsearch.index.mapper.ip.IpFieldMapper; +import org.joda.time.DateTime; import java.io.IOException; @@ -146,6 +148,17 @@ public abstract class FieldStats> implements Streamable, */ protected abstract T valueOf(String value, String optionalFormat); + /** + * @param value + * The value to be converted to a String + * @param optionalFormat + * A string describing how to print the specified value. Whether + * this parameter is supported depends on the implementation. If + * optionalFormat is specified and the implementation doesn't + * support it an {@link UnsupportedOperationException} is thrown + */ + public abstract String stringValueOf(Object value, String optionalFormat); + /** * Merges the provided stats into this stats instance. */ @@ -274,6 +287,18 @@ public abstract class FieldStats> implements Streamable, return java.lang.Long.valueOf(value); } + @Override + public String stringValueOf(Object value, String optionalFormat) { + if (optionalFormat != null) { + throw new UnsupportedOperationException("custom format isn't supported"); + } + if (value instanceof Number) { + return java.lang.Long.toString(((Number) value).longValue()); + } else { + throw new IllegalArgumentException("value must be a Long: " + value); + } + } + @Override public void readFrom(StreamInput in) throws IOException { super.readFrom(in); @@ -327,6 +352,18 @@ public abstract class FieldStats> implements Streamable, return java.lang.Float.valueOf(value); } + @Override + public String stringValueOf(Object value, String optionalFormat) { + if (optionalFormat != null) { + throw new UnsupportedOperationException("custom format isn't supported"); + } + if (value instanceof Number) { + return java.lang.Float.toString(((Number) value).floatValue()); + } else { + throw new IllegalArgumentException("value must be a Float: " + value); + } + } + @Override public void readFrom(StreamInput in) throws IOException { super.readFrom(in); @@ -380,6 +417,18 @@ public abstract class FieldStats> implements Streamable, return java.lang.Double.valueOf(value); } + @Override + public String stringValueOf(Object value, String optionalFormat) { + if (optionalFormat != null) { + throw new UnsupportedOperationException("custom format isn't supported"); + } + if (value instanceof Number) { + return java.lang.Double.toString(((Number) value).doubleValue()); + } else { + throw new IllegalArgumentException("value must be a Double: " + value); + } + } + @Override public void readFrom(StreamInput in) throws IOException { super.readFrom(in); @@ -437,6 +486,18 @@ public abstract class FieldStats> implements Streamable, return new BytesRef(value); } + @Override + public String stringValueOf(Object value, String optionalFormat) { + if (optionalFormat != null) { + throw new UnsupportedOperationException("custom format isn't supported"); + } + if (value instanceof BytesRef) { + return ((BytesRef) value).utf8ToString(); + } else { + throw new IllegalArgumentException("value must be a BytesRef: " + value); + } + } + @Override protected void toInnerXContent(XContentBuilder builder) throws IOException { builder.field(Fields.MIN_VALUE, getMinValueAsString()); @@ -490,6 +551,25 @@ public abstract class FieldStats> implements Streamable, return dateFormatter.parser().parseMillis(value); } + @Override + public String stringValueOf(Object value, String optionalFormat) { + FormatDateTimeFormatter dateFormatter = this.dateFormatter; + if (optionalFormat != null) { + dateFormatter = Joda.forPattern(optionalFormat); + } + long millis; + if (value instanceof java.lang.Long) { + millis = ((java.lang.Long) value).longValue(); + } else if (value instanceof DateTime) { + millis = ((DateTime) value).getMillis(); + } else if (value instanceof BytesRef) { + millis = dateFormatter.parser().parseMillis(((BytesRef) value).utf8ToString()); + } else { + throw new IllegalArgumentException("value must be either a DateTime or a long: " + value); + } + return dateFormatter.printer().print(millis); + } + @Override public void readFrom(StreamInput in) throws IOException { super.readFrom(in); @@ -504,6 +584,28 @@ public abstract class FieldStats> implements Streamable, } + public static class Ip extends Long { + + public Ip(int maxDoc, int docCount, long sumDocFreq, long sumTotalTermFreq, long minValue, long maxValue) { + super(maxDoc, docCount, sumDocFreq, sumTotalTermFreq, minValue, maxValue); + } + + protected Ip(int type, long maxDoc, long docCount, long sumDocFreq, long sumTotalTermFreq, long minValue, long maxValue) { + super(type, maxDoc, docCount, sumDocFreq, sumTotalTermFreq, minValue, maxValue); + } + + public Ip() { + } + + @Override + public String stringValueOf(Object value, String optionalFormat) { + if (value instanceof BytesRef) { + return super.stringValueOf(IpFieldMapper.ipToLong(((BytesRef) value).utf8ToString()), optionalFormat); + } + return super.stringValueOf(value, optionalFormat); + } + } + public static FieldStats read(StreamInput in) throws IOException { FieldStats stats; byte type = in.readByte(); diff --git a/core/src/main/java/org/elasticsearch/action/fieldstats/TransportFieldStatsTransportAction.java b/core/src/main/java/org/elasticsearch/action/fieldstats/TransportFieldStatsTransportAction.java index 42360c5e0eb..de56a0f5c2e 100644 --- a/core/src/main/java/org/elasticsearch/action/fieldstats/TransportFieldStatsTransportAction.java +++ b/core/src/main/java/org/elasticsearch/action/fieldstats/TransportFieldStatsTransportAction.java @@ -28,13 +28,13 @@ import org.elasticsearch.action.support.ActionFilters; import org.elasticsearch.action.support.DefaultShardOperationFailedException; import org.elasticsearch.action.support.broadcast.BroadcastShardOperationFailedException; import org.elasticsearch.action.support.broadcast.TransportBroadcastAction; -import org.elasticsearch.cluster.ClusterService; import org.elasticsearch.cluster.ClusterState; import org.elasticsearch.cluster.block.ClusterBlockException; import org.elasticsearch.cluster.block.ClusterBlockLevel; import org.elasticsearch.cluster.metadata.IndexNameExpressionResolver; import org.elasticsearch.cluster.routing.GroupShardsIterator; import org.elasticsearch.cluster.routing.ShardRouting; +import org.elasticsearch.cluster.service.ClusterService; import org.elasticsearch.common.inject.Inject; import org.elasticsearch.common.settings.Settings; import org.elasticsearch.index.IndexService; diff --git a/core/src/main/java/org/elasticsearch/action/get/TransportGetAction.java b/core/src/main/java/org/elasticsearch/action/get/TransportGetAction.java index 2d6bafc9623..b84493c4dca 100644 --- a/core/src/main/java/org/elasticsearch/action/get/TransportGetAction.java +++ b/core/src/main/java/org/elasticsearch/action/get/TransportGetAction.java @@ -22,12 +22,12 @@ package org.elasticsearch.action.get; import org.elasticsearch.action.RoutingMissingException; import org.elasticsearch.action.support.ActionFilters; import org.elasticsearch.action.support.single.shard.TransportSingleShardAction; -import org.elasticsearch.cluster.ClusterService; import org.elasticsearch.cluster.ClusterState; import org.elasticsearch.cluster.metadata.IndexMetaData; import org.elasticsearch.cluster.metadata.IndexNameExpressionResolver; import org.elasticsearch.cluster.routing.Preference; import org.elasticsearch.cluster.routing.ShardIterator; +import org.elasticsearch.cluster.service.ClusterService; import org.elasticsearch.common.inject.Inject; import org.elasticsearch.common.settings.Settings; import org.elasticsearch.index.IndexService; diff --git a/core/src/main/java/org/elasticsearch/action/get/TransportMultiGetAction.java b/core/src/main/java/org/elasticsearch/action/get/TransportMultiGetAction.java index 62d21c283b8..1858ac8ba71 100644 --- a/core/src/main/java/org/elasticsearch/action/get/TransportMultiGetAction.java +++ b/core/src/main/java/org/elasticsearch/action/get/TransportMultiGetAction.java @@ -22,10 +22,10 @@ package org.elasticsearch.action.get; import org.elasticsearch.action.ActionListener; import org.elasticsearch.action.support.ActionFilters; import org.elasticsearch.action.support.HandledTransportAction; -import org.elasticsearch.cluster.ClusterService; import org.elasticsearch.cluster.ClusterState; import org.elasticsearch.cluster.block.ClusterBlockLevel; import org.elasticsearch.cluster.metadata.IndexNameExpressionResolver; +import org.elasticsearch.cluster.service.ClusterService; import org.elasticsearch.common.inject.Inject; import org.elasticsearch.common.settings.Settings; import org.elasticsearch.common.util.concurrent.AtomicArray; diff --git a/core/src/main/java/org/elasticsearch/action/get/TransportShardMultiGetAction.java b/core/src/main/java/org/elasticsearch/action/get/TransportShardMultiGetAction.java index 1f07a5e79e6..05b672105f8 100644 --- a/core/src/main/java/org/elasticsearch/action/get/TransportShardMultiGetAction.java +++ b/core/src/main/java/org/elasticsearch/action/get/TransportShardMultiGetAction.java @@ -23,10 +23,10 @@ import org.elasticsearch.ElasticsearchException; import org.elasticsearch.action.support.ActionFilters; import org.elasticsearch.action.support.TransportActions; import org.elasticsearch.action.support.single.shard.TransportSingleShardAction; -import org.elasticsearch.cluster.ClusterService; import org.elasticsearch.cluster.ClusterState; import org.elasticsearch.cluster.metadata.IndexNameExpressionResolver; import org.elasticsearch.cluster.routing.ShardIterator; +import org.elasticsearch.cluster.service.ClusterService; import org.elasticsearch.common.inject.Inject; import org.elasticsearch.common.settings.Settings; import org.elasticsearch.index.IndexService; diff --git a/core/src/main/java/org/elasticsearch/action/index/TransportIndexAction.java b/core/src/main/java/org/elasticsearch/action/index/TransportIndexAction.java index 0d2e7c2e074..9be8e4cef89 100644 --- a/core/src/main/java/org/elasticsearch/action/index/TransportIndexAction.java +++ b/core/src/main/java/org/elasticsearch/action/index/TransportIndexAction.java @@ -28,7 +28,6 @@ import org.elasticsearch.action.admin.indices.create.TransportCreateIndexAction; import org.elasticsearch.action.support.ActionFilters; import org.elasticsearch.action.support.AutoCreateIndex; import org.elasticsearch.action.support.replication.TransportReplicationAction; -import org.elasticsearch.cluster.ClusterService; import org.elasticsearch.cluster.ClusterState; import org.elasticsearch.cluster.action.index.MappingUpdatedAction; import org.elasticsearch.cluster.action.shard.ShardStateAction; @@ -36,6 +35,7 @@ import org.elasticsearch.cluster.metadata.IndexMetaData; import org.elasticsearch.cluster.metadata.IndexNameExpressionResolver; import org.elasticsearch.cluster.metadata.MappingMetaData; import org.elasticsearch.cluster.metadata.MetaData; +import org.elasticsearch.cluster.service.ClusterService; import org.elasticsearch.common.collect.Tuple; import org.elasticsearch.common.inject.Inject; import org.elasticsearch.common.settings.Settings; diff --git a/core/src/main/java/org/elasticsearch/action/ingest/DeletePipelineTransportAction.java b/core/src/main/java/org/elasticsearch/action/ingest/DeletePipelineTransportAction.java index 6378eb5757b..74ce894b053 100644 --- a/core/src/main/java/org/elasticsearch/action/ingest/DeletePipelineTransportAction.java +++ b/core/src/main/java/org/elasticsearch/action/ingest/DeletePipelineTransportAction.java @@ -22,11 +22,11 @@ package org.elasticsearch.action.ingest; import org.elasticsearch.action.ActionListener; import org.elasticsearch.action.support.ActionFilters; import org.elasticsearch.action.support.master.TransportMasterNodeAction; -import org.elasticsearch.cluster.ClusterService; import org.elasticsearch.cluster.ClusterState; import org.elasticsearch.cluster.block.ClusterBlockException; import org.elasticsearch.cluster.block.ClusterBlockLevel; import org.elasticsearch.cluster.metadata.IndexNameExpressionResolver; +import org.elasticsearch.cluster.service.ClusterService; import org.elasticsearch.common.inject.Inject; import org.elasticsearch.common.settings.Settings; import org.elasticsearch.ingest.PipelineStore; diff --git a/core/src/main/java/org/elasticsearch/action/ingest/GetPipelineTransportAction.java b/core/src/main/java/org/elasticsearch/action/ingest/GetPipelineTransportAction.java index e762d0b8d33..8bac5c7b804 100644 --- a/core/src/main/java/org/elasticsearch/action/ingest/GetPipelineTransportAction.java +++ b/core/src/main/java/org/elasticsearch/action/ingest/GetPipelineTransportAction.java @@ -22,11 +22,11 @@ package org.elasticsearch.action.ingest; import org.elasticsearch.action.ActionListener; import org.elasticsearch.action.support.ActionFilters; import org.elasticsearch.action.support.master.TransportMasterNodeReadAction; -import org.elasticsearch.cluster.ClusterService; import org.elasticsearch.cluster.ClusterState; import org.elasticsearch.cluster.block.ClusterBlockException; import org.elasticsearch.cluster.block.ClusterBlockLevel; import org.elasticsearch.cluster.metadata.IndexNameExpressionResolver; +import org.elasticsearch.cluster.service.ClusterService; import org.elasticsearch.common.inject.Inject; import org.elasticsearch.common.settings.Settings; import org.elasticsearch.ingest.PipelineStore; diff --git a/core/src/main/java/org/elasticsearch/action/ingest/IngestProxyActionFilter.java b/core/src/main/java/org/elasticsearch/action/ingest/IngestProxyActionFilter.java index 39a4b1fa4e8..62716c6dc0d 100644 --- a/core/src/main/java/org/elasticsearch/action/ingest/IngestProxyActionFilter.java +++ b/core/src/main/java/org/elasticsearch/action/ingest/IngestProxyActionFilter.java @@ -29,9 +29,9 @@ import org.elasticsearch.action.index.IndexAction; import org.elasticsearch.action.index.IndexRequest; import org.elasticsearch.action.support.ActionFilter; import org.elasticsearch.action.support.ActionFilterChain; -import org.elasticsearch.cluster.ClusterService; import org.elasticsearch.cluster.node.DiscoveryNode; import org.elasticsearch.cluster.node.DiscoveryNodes; +import org.elasticsearch.cluster.service.ClusterService; import org.elasticsearch.common.Randomness; import org.elasticsearch.common.Strings; import org.elasticsearch.common.inject.Inject; diff --git a/core/src/main/java/org/elasticsearch/action/ingest/PutPipelineTransportAction.java b/core/src/main/java/org/elasticsearch/action/ingest/PutPipelineTransportAction.java index aafd9ee75a4..e1a34413e2c 100644 --- a/core/src/main/java/org/elasticsearch/action/ingest/PutPipelineTransportAction.java +++ b/core/src/main/java/org/elasticsearch/action/ingest/PutPipelineTransportAction.java @@ -26,12 +26,12 @@ import org.elasticsearch.action.admin.cluster.node.info.NodesInfoResponse; import org.elasticsearch.action.admin.cluster.node.info.TransportNodesInfoAction; import org.elasticsearch.action.support.ActionFilters; import org.elasticsearch.action.support.master.TransportMasterNodeAction; -import org.elasticsearch.cluster.ClusterService; import org.elasticsearch.cluster.ClusterState; import org.elasticsearch.cluster.block.ClusterBlockException; import org.elasticsearch.cluster.block.ClusterBlockLevel; import org.elasticsearch.cluster.metadata.IndexNameExpressionResolver; import org.elasticsearch.cluster.node.DiscoveryNode; +import org.elasticsearch.cluster.service.ClusterService; import org.elasticsearch.common.inject.Inject; import org.elasticsearch.common.settings.Settings; import org.elasticsearch.ingest.PipelineStore; diff --git a/core/src/main/java/org/elasticsearch/action/percolate/MultiPercolateRequest.java b/core/src/main/java/org/elasticsearch/action/percolate/MultiPercolateRequest.java index 74537379d1d..ac49fed763a 100644 --- a/core/src/main/java/org/elasticsearch/action/percolate/MultiPercolateRequest.java +++ b/core/src/main/java/org/elasticsearch/action/percolate/MultiPercolateRequest.java @@ -163,11 +163,7 @@ public class MultiPercolateRequest extends ActionRequest @Override public List subRequests() { - List indicesRequests = new ArrayList<>(); - for (PercolateRequest percolateRequest : this.requests) { - indicesRequests.addAll(percolateRequest.subRequests()); - } - return indicesRequests; + return requests; } private void parsePercolateAction(XContentParser parser, PercolateRequest percolateRequest, boolean allowExplicitIndex) throws IOException { diff --git a/core/src/main/java/org/elasticsearch/action/percolate/PercolateRequest.java b/core/src/main/java/org/elasticsearch/action/percolate/PercolateRequest.java index e69da6bf519..c9887cba03f 100644 --- a/core/src/main/java/org/elasticsearch/action/percolate/PercolateRequest.java +++ b/core/src/main/java/org/elasticsearch/action/percolate/PercolateRequest.java @@ -19,10 +19,12 @@ package org.elasticsearch.action.percolate; import org.elasticsearch.ElasticsearchGenerationException; +import org.elasticsearch.action.ActionRequest; import org.elasticsearch.action.ActionRequestValidationException; import org.elasticsearch.action.CompositeIndicesRequest; import org.elasticsearch.action.IndicesRequest; import org.elasticsearch.action.get.GetRequest; +import org.elasticsearch.action.support.IndicesOptions; import org.elasticsearch.action.support.broadcast.BroadcastRequest; import org.elasticsearch.client.Requests; import org.elasticsearch.common.bytes.BytesArray; @@ -43,49 +45,37 @@ import static org.elasticsearch.action.ValidateActions.addValidationError; /** * A request to execute a percolate operation. */ -public class PercolateRequest extends BroadcastRequest implements CompositeIndicesRequest { +public class PercolateRequest extends ActionRequest implements IndicesRequest.Replaceable { + protected String[] indices; + private IndicesOptions indicesOptions = IndicesOptions.strictExpandOpenAndForbidClosed(); private String documentType; private String routing; private String preference; - private GetRequest getRequest; private boolean onlyCount; + private GetRequest getRequest; private BytesReference source; - private BytesReference docSource; - - // Used internally in order to compute tookInMillis, TransportBroadcastAction itself doesn't allow - // to hold it temporarily in an easy way - long startTime; - - /** - * Constructor only for internal usage. - */ - public PercolateRequest() { + public String[] indices() { + return indices; } - PercolateRequest(PercolateRequest request, BytesReference docSource) { - this.indices = request.indices(); - this.documentType = request.documentType(); - this.routing = request.routing(); - this.preference = request.preference(); - this.source = request.source; - this.docSource = docSource; - this.onlyCount = request.onlyCount; - this.startTime = request.startTime; + public final PercolateRequest indices(String... indices) { + this.indices = indices; + return this; } - @Override - public List subRequests() { - List requests = new ArrayList<>(); - requests.add(this); - if (getRequest != null) { - requests.add(getRequest); - } - return requests; + public IndicesOptions indicesOptions() { + return indicesOptions; } + public PercolateRequest indicesOptions(IndicesOptions indicesOptions) { + this.indicesOptions = indicesOptions; + return this; + } + + /** * Getter for {@link #documentType(String)} */ @@ -244,13 +234,9 @@ public class PercolateRequest extends BroadcastRequest impleme return this; } - BytesReference docSource() { - return docSource; - } - @Override public ActionRequestValidationException validate() { - ActionRequestValidationException validationException = super.validate(); + ActionRequestValidationException validationException = null; if (documentType == null) { validationException = addValidationError("type is missing", validationException); } @@ -266,12 +252,12 @@ public class PercolateRequest extends BroadcastRequest impleme @Override public void readFrom(StreamInput in) throws IOException { super.readFrom(in); - startTime = in.readVLong(); + indices = in.readStringArray(); + indicesOptions = IndicesOptions.readIndicesOptions(in); documentType = in.readString(); routing = in.readOptionalString(); preference = in.readOptionalString(); source = in.readBytesReference(); - docSource = in.readBytesReference(); if (in.readBoolean()) { getRequest = new GetRequest(); getRequest.readFrom(in); @@ -282,12 +268,12 @@ public class PercolateRequest extends BroadcastRequest impleme @Override public void writeTo(StreamOutput out) throws IOException { super.writeTo(out); - out.writeVLong(startTime); + out.writeStringArrayNullable(indices); + indicesOptions.writeIndicesOptions(out); out.writeString(documentType); out.writeOptionalString(routing); out.writeOptionalString(preference); out.writeBytesReference(source); - out.writeBytesReference(docSource); if (getRequest != null) { out.writeBoolean(true); getRequest.writeTo(out); diff --git a/core/src/main/java/org/elasticsearch/action/percolate/PercolateRequestBuilder.java b/core/src/main/java/org/elasticsearch/action/percolate/PercolateRequestBuilder.java index 472938cfbf1..83757dab089 100644 --- a/core/src/main/java/org/elasticsearch/action/percolate/PercolateRequestBuilder.java +++ b/core/src/main/java/org/elasticsearch/action/percolate/PercolateRequestBuilder.java @@ -18,7 +18,9 @@ */ package org.elasticsearch.action.percolate; +import org.elasticsearch.action.ActionRequestBuilder; import org.elasticsearch.action.get.GetRequest; +import org.elasticsearch.action.support.IndicesOptions; import org.elasticsearch.action.support.broadcast.BroadcastOperationRequestBuilder; import org.elasticsearch.client.ElasticsearchClient; import org.elasticsearch.common.Strings; @@ -36,7 +38,7 @@ import java.util.Map; /** * A builder the easy to use of defining a percolate request. */ -public class PercolateRequestBuilder extends BroadcastOperationRequestBuilder { +public class PercolateRequestBuilder extends ActionRequestBuilder { private PercolateSourceBuilder sourceBuilder; @@ -44,6 +46,16 @@ public class PercolateRequestBuilder extends BroadcastOperationRequestBuilder, ToXContent { public static final Match[] EMPTY = new Match[0]; + // PercolatorQuery emits this score if no 'query' is defined in the percolate request + public final static float NO_SCORE = 0.0f; private long tookInMillis; private Match[] matches; @@ -65,15 +66,6 @@ public class PercolateResponse extends BroadcastResponse implements Iterable shardFailures, long tookInMillis, Match[] matches) { - super(totalShards, successfulShards, failedShards, shardFailures); - if (tookInMillis < 0) { - throw new IllegalArgumentException("tookInMillis must be positive but was: " + tookInMillis); - } - this.tookInMillis = tookInMillis; - this.matches = matches; - } - PercolateResponse() { } @@ -136,10 +128,10 @@ public class PercolateResponse extends BroadcastResponse implements Iterable ids; - private Map> hls; - private boolean onlyCount; - private int requestedSize; - - private InternalAggregations aggregations; - private List pipelineAggregators; - - PercolateShardResponse() { - } - - public PercolateShardResponse(TopDocs topDocs, Map ids, Map> hls, PercolateContext context) { - super(context.indexShard().shardId()); - this.topDocs = topDocs; - this.ids = ids; - this.hls = hls; - this.onlyCount = context.isOnlyCount(); - this.requestedSize = context.size(); - QuerySearchResult result = context.queryResult(); - if (result != null) { - if (result.aggregations() != null) { - this.aggregations = (InternalAggregations) result.aggregations(); - } - this.pipelineAggregators = result.pipelineAggregators(); - } - } - - public TopDocs topDocs() { - return topDocs; - } - - /** - * Returns per match the percolator query id. The key is the Lucene docId of the matching percolator query. - */ - public Map ids() { - return ids; - } - - public int requestedSize() { - return requestedSize; - } - - /** - * Returns per match the highlight snippets. The key is the Lucene docId of the matching percolator query. - */ - public Map> hls() { - return hls; - } - - public InternalAggregations aggregations() { - return aggregations; - } - - public List pipelineAggregators() { - return pipelineAggregators; - } - - public boolean onlyCount() { - return onlyCount; - } - - public boolean isEmpty() { - return topDocs.totalHits == 0; - } - - @Override - public void readFrom(StreamInput in) throws IOException { - super.readFrom(in); - onlyCount = in.readBoolean(); - requestedSize = in.readVInt(); - topDocs = Lucene.readTopDocs(in); - int size = in.readVInt(); - ids = new HashMap<>(size); - for (int i = 0; i < size; i++) { - ids.put(in.readVInt(), in.readString()); - } - size = in.readVInt(); - hls = new HashMap<>(size); - for (int i = 0; i < size; i++) { - int docId = in.readVInt(); - int mSize = in.readVInt(); - Map fields = new HashMap<>(); - for (int j = 0; j < mSize; j++) { - fields.put(in.readString(), HighlightField.readHighlightField(in)); - } - hls.put(docId, fields); - } - aggregations = InternalAggregations.readOptionalAggregations(in); - if (in.readBoolean()) { - int pipelineAggregatorsSize = in.readVInt(); - List pipelineAggregators = new ArrayList<>(pipelineAggregatorsSize); - for (int i = 0; i < pipelineAggregatorsSize; i++) { - BytesReference type = in.readBytesReference(); - PipelineAggregator pipelineAggregator = PipelineAggregatorStreams.stream(type).readResult(in); - pipelineAggregators.add((SiblingPipelineAggregator) pipelineAggregator); - } - this.pipelineAggregators = pipelineAggregators; - } - } - - @Override - public void writeTo(StreamOutput out) throws IOException { - super.writeTo(out); - out.writeBoolean(onlyCount); - out.writeVLong(requestedSize); - Lucene.writeTopDocs(out, topDocs); - out.writeVInt(ids.size()); - for (Map.Entry entry : ids.entrySet()) { - out.writeVInt(entry.getKey()); - out.writeString(entry.getValue()); - } - out.writeVInt(hls.size()); - for (Map.Entry> entry1 : hls.entrySet()) { - out.writeVInt(entry1.getKey()); - out.writeVInt(entry1.getValue().size()); - for (Map.Entry entry2 : entry1.getValue().entrySet()) { - out.writeString(entry2.getKey()); - entry2.getValue().writeTo(out); - } - } - out.writeOptionalStreamable(aggregations); - if (pipelineAggregators == null) { - out.writeBoolean(false); - } else { - out.writeBoolean(true); - out.writeVInt(pipelineAggregators.size()); - for (PipelineAggregator pipelineAggregator : pipelineAggregators) { - out.writeBytesReference(pipelineAggregator.type().stream()); - pipelineAggregator.writeTo(out); - } - } - } -} diff --git a/core/src/main/java/org/elasticsearch/action/percolate/TransportMultiPercolateAction.java b/core/src/main/java/org/elasticsearch/action/percolate/TransportMultiPercolateAction.java index 907cae969b4..bf0d79d884e 100644 --- a/core/src/main/java/org/elasticsearch/action/percolate/TransportMultiPercolateAction.java +++ b/core/src/main/java/org/elasticsearch/action/percolate/TransportMultiPercolateAction.java @@ -19,114 +19,91 @@ package org.elasticsearch.action.percolate; -import com.carrotsearch.hppc.IntArrayList; +import org.elasticsearch.ResourceNotFoundException; import org.elasticsearch.action.ActionListener; -import org.elasticsearch.action.UnavailableShardsException; import org.elasticsearch.action.get.GetRequest; -import org.elasticsearch.action.get.GetResponse; import org.elasticsearch.action.get.MultiGetItemResponse; import org.elasticsearch.action.get.MultiGetRequest; import org.elasticsearch.action.get.MultiGetResponse; -import org.elasticsearch.action.get.TransportMultiGetAction; +import org.elasticsearch.action.search.MultiSearchRequest; +import org.elasticsearch.action.search.MultiSearchResponse; +import org.elasticsearch.action.search.SearchRequest; import org.elasticsearch.action.support.ActionFilters; import org.elasticsearch.action.support.HandledTransportAction; -import org.elasticsearch.action.support.broadcast.BroadcastShardOperationFailedException; -import org.elasticsearch.cluster.ClusterService; -import org.elasticsearch.cluster.ClusterState; -import org.elasticsearch.cluster.block.ClusterBlockLevel; +import org.elasticsearch.client.Client; import org.elasticsearch.cluster.metadata.IndexNameExpressionResolver; -import org.elasticsearch.cluster.routing.GroupShardsIterator; -import org.elasticsearch.cluster.routing.ShardIterator; +import org.elasticsearch.common.ParseFieldMatcher; +import org.elasticsearch.common.bytes.BytesReference; +import org.elasticsearch.common.collect.Tuple; import org.elasticsearch.common.inject.Inject; import org.elasticsearch.common.settings.Settings; -import org.elasticsearch.common.util.concurrent.AtomicArray; -import org.elasticsearch.index.IndexNotFoundException; -import org.elasticsearch.index.engine.DocumentMissingException; -import org.elasticsearch.index.shard.ShardId; -import org.elasticsearch.percolator.PercolatorService; +import org.elasticsearch.indices.query.IndicesQueriesRegistry; +import org.elasticsearch.search.aggregations.AggregatorParsers; import org.elasticsearch.threadpool.ThreadPool; import org.elasticsearch.transport.TransportService; +import java.io.IOException; import java.util.ArrayList; +import java.util.Collections; import java.util.HashMap; import java.util.List; import java.util.Map; -import java.util.Set; -import java.util.concurrent.atomic.AtomicInteger; -import java.util.concurrent.atomic.AtomicReferenceArray; -/** - */ public class TransportMultiPercolateAction extends HandledTransportAction { - private final ClusterService clusterService; - private final PercolatorService percolatorService; - - private final TransportMultiGetAction multiGetAction; - private final TransportShardMultiPercolateAction shardMultiPercolateAction; + private final Client client; + private final ParseFieldMatcher parseFieldMatcher; + private final IndicesQueriesRegistry queryRegistry; + private final AggregatorParsers aggParsers; @Inject - public TransportMultiPercolateAction(Settings settings, ThreadPool threadPool, TransportShardMultiPercolateAction shardMultiPercolateAction, - ClusterService clusterService, TransportService transportService, PercolatorService percolatorService, - TransportMultiGetAction multiGetAction, ActionFilters actionFilters, IndexNameExpressionResolver indexNameExpressionResolver) { + public TransportMultiPercolateAction(Settings settings, ThreadPool threadPool, TransportService transportService, ActionFilters actionFilters, + IndexNameExpressionResolver indexNameExpressionResolver, Client client, IndicesQueriesRegistry queryRegistry, + AggregatorParsers aggParsers) { super(settings, MultiPercolateAction.NAME, threadPool, transportService, actionFilters, indexNameExpressionResolver, MultiPercolateRequest::new); - this.shardMultiPercolateAction = shardMultiPercolateAction; - this.clusterService = clusterService; - this.percolatorService = percolatorService; - this.multiGetAction = multiGetAction; + this.client = client; + this.aggParsers = aggParsers; + this.parseFieldMatcher = new ParseFieldMatcher(settings); + this.queryRegistry = queryRegistry; } @Override - protected void doExecute(final MultiPercolateRequest request, final ActionListener listener) { - final ClusterState clusterState = clusterService.state(); - clusterState.blocks().globalBlockedRaiseException(ClusterBlockLevel.READ); - - final List percolateRequests = new ArrayList<>(request.requests().size()); - // Can have a mixture of percolate requests. (normal percolate requests & percolate existing doc), - // so we need to keep track for what percolate request we had a get request - final IntArrayList getRequestSlots = new IntArrayList(); - List existingDocsRequests = new ArrayList<>(); - for (int slot = 0; slot < request.requests().size(); slot++) { - PercolateRequest percolateRequest = request.requests().get(slot); - percolateRequest.startTime = System.currentTimeMillis(); - percolateRequests.add(percolateRequest); - if (percolateRequest.getRequest() != null) { - existingDocsRequests.add(percolateRequest.getRequest()); - getRequestSlots.add(slot); + protected void doExecute(MultiPercolateRequest request, ActionListener listener) { + List> getRequests = new ArrayList<>(); + for (int i = 0; i < request.requests().size(); i++) { + GetRequest getRequest = request.requests().get(i).getRequest(); + if (getRequest != null) { + getRequests.add(new Tuple<>(i, getRequest)); } } - - if (!existingDocsRequests.isEmpty()) { - final MultiGetRequest multiGetRequest = new MultiGetRequest(); - for (GetRequest getRequest : existingDocsRequests) { - multiGetRequest.add( - new MultiGetRequest.Item(getRequest.index(), getRequest.type(), getRequest.id()) - .routing(getRequest.routing()) - ); + if (getRequests.isEmpty()) { + innerDoExecute(request, listener, Collections.emptyMap(), new HashMap<>()); + } else { + MultiGetRequest multiGetRequest = new MultiGetRequest(); + for (Tuple tuple : getRequests) { + GetRequest getRequest = tuple.v2(); + multiGetRequest.add(new MultiGetRequest.Item(getRequest.index(), getRequest.type(), getRequest.id())); } - - multiGetAction.execute(multiGetRequest, new ActionListener() { - + client.multiGet(multiGetRequest, new ActionListener() { @Override - public void onResponse(MultiGetResponse multiGetItemResponses) { - for (int i = 0; i < multiGetItemResponses.getResponses().length; i++) { - MultiGetItemResponse itemResponse = multiGetItemResponses.getResponses()[i]; - int slot = getRequestSlots.get(i); - if (!itemResponse.isFailed()) { - GetResponse getResponse = itemResponse.getResponse(); - if (getResponse.isExists()) { - PercolateRequest originalRequest = (PercolateRequest) percolateRequests.get(slot); - percolateRequests.set(slot, new PercolateRequest(originalRequest, getResponse.getSourceAsBytesRef())); - } else { - logger.trace("mpercolate existing doc, item[{}] doesn't exist", slot); - percolateRequests.set(slot, new DocumentMissingException(null, getResponse.getType(), getResponse.getId())); - } + public void onResponse(MultiGetResponse response) { + Map getResponseSources = new HashMap<>(response.getResponses().length); + Map preFailures = new HashMap<>(); + for (int i = 0; i < response.getResponses().length; i++) { + MultiGetItemResponse itemResponse = response.getResponses()[i]; + int originalSlot = getRequests.get(i).v1(); + if (itemResponse.isFailed()) { + preFailures.put(originalSlot, new MultiPercolateResponse.Item(itemResponse.getFailure().getFailure())); } else { - logger.trace("mpercolate existing doc, item[{}] failure {}", slot, itemResponse.getFailure()); - percolateRequests.set(slot, itemResponse.getFailure()); + if (itemResponse.getResponse().isExists()) { + getResponseSources.put(originalSlot, itemResponse.getResponse().getSourceAsBytesRef()); + } else { + GetRequest getRequest = getRequests.get(i).v2(); + preFailures.put(originalSlot, new MultiPercolateResponse.Item(new ResourceNotFoundException("percolate document [{}/{}/{}] doesn't exist", getRequest.index(), getRequest.type(), getRequest.id()))); + } } } - new ASyncAction(request, percolateRequests, listener, clusterState).run(); + innerDoExecute(request, listener, getResponseSources, preFailures); } @Override @@ -134,200 +111,81 @@ public class TransportMultiPercolateAction extends HandledTransportAction finalListener; - final Map requestsByShard; - final MultiPercolateRequest multiPercolateRequest; - final List percolateRequests; - - final Map shardToSlots; - final AtomicInteger expectedOperations; - final AtomicArray reducedResponses; - final AtomicReferenceArray expectedOperationsPerItem; - final AtomicReferenceArray responsesByItemAndShard; - - ASyncAction(MultiPercolateRequest multiPercolateRequest, List percolateRequests, ActionListener finalListener, ClusterState clusterState) { - this.finalListener = finalListener; - this.multiPercolateRequest = multiPercolateRequest; - this.percolateRequests = percolateRequests; - responsesByItemAndShard = new AtomicReferenceArray<>(percolateRequests.size()); - expectedOperationsPerItem = new AtomicReferenceArray<>(percolateRequests.size()); - reducedResponses = new AtomicArray<>(percolateRequests.size()); - - // Resolving concrete indices and routing and grouping the requests by shard - requestsByShard = new HashMap<>(); - // Keep track what slots belong to what shard, in case a request to a shard fails on all copies - shardToSlots = new HashMap<>(); - int expectedResults = 0; - for (int slot = 0; slot < percolateRequests.size(); slot++) { - Object element = percolateRequests.get(slot); - assert element != null; - if (element instanceof PercolateRequest) { - PercolateRequest percolateRequest = (PercolateRequest) element; - String[] concreteIndices; - try { - concreteIndices = indexNameExpressionResolver.concreteIndexNames(clusterState, percolateRequest); - } catch (IndexNotFoundException e) { - reducedResponses.set(slot, e); - responsesByItemAndShard.set(slot, new AtomicReferenceArray(0)); - expectedOperationsPerItem.set(slot, new AtomicInteger(0)); - continue; - } - Map> routing = indexNameExpressionResolver.resolveSearchRouting(clusterState, percolateRequest.routing(), percolateRequest.indices()); - // TODO: I only need shardIds, ShardIterator(ShardRouting) is only needed in TransportShardMultiPercolateAction - GroupShardsIterator shards = clusterService.operationRouting().searchShards( - clusterState, concreteIndices, routing, percolateRequest.preference() - ); - if (shards.size() == 0) { - reducedResponses.set(slot, new UnavailableShardsException(null, "No shards available")); - responsesByItemAndShard.set(slot, new AtomicReferenceArray(0)); - expectedOperationsPerItem.set(slot, new AtomicInteger(0)); - continue; - } - - // The shard id is used as index in the atomic ref array, so we need to find out how many shards there are regardless of routing: - int numShards = clusterService.operationRouting().searchShardsCount(clusterState, concreteIndices, null); - responsesByItemAndShard.set(slot, new AtomicReferenceArray(numShards)); - expectedOperationsPerItem.set(slot, new AtomicInteger(shards.size())); - for (ShardIterator shard : shards) { - ShardId shardId = shard.shardId(); - TransportShardMultiPercolateAction.Request requests = requestsByShard.get(shardId); - if (requests == null) { - requestsByShard.put(shardId, requests = new TransportShardMultiPercolateAction.Request(shardId.getIndexName(), shardId.getId(), percolateRequest.preference())); - } - logger.trace("Adding shard[{}] percolate request for item[{}]", shardId, slot); - requests.add(new TransportShardMultiPercolateAction.Request.Item(slot, new PercolateShardRequest(shardId, percolateRequest))); - - IntArrayList items = shardToSlots.get(shardId); - if (items == null) { - shardToSlots.put(shardId, items = new IntArrayList()); - } - items.add(slot); - } - expectedResults++; - } else if (element instanceof Throwable || element instanceof MultiGetResponse.Failure) { - logger.trace("item[{}] won't be executed, reason: {}", slot, element); - reducedResponses.set(slot, element); - responsesByItemAndShard.set(slot, new AtomicReferenceArray(0)); - expectedOperationsPerItem.set(slot, new AtomicInteger(0)); - } - } - expectedOperations = new AtomicInteger(expectedResults); - } - - void run() { - if (expectedOperations.get() == 0) { - finish(); - return; - } - - logger.trace("mpercolate executing for shards {}", requestsByShard.keySet()); - for (Map.Entry entry : requestsByShard.entrySet()) { - final ShardId shardId = entry.getKey(); - TransportShardMultiPercolateAction.Request shardRequest = entry.getValue(); - shardMultiPercolateAction.execute(shardRequest, new ActionListener() { - + private void innerDoExecute(MultiPercolateRequest request, ActionListener listener, Map getResponseSources, Map preFailures) { + try { + MultiSearchRequest multiSearchRequest = createMultiSearchRequest(request, getResponseSources, preFailures); + if (multiSearchRequest.requests().isEmpty()) { + // we may failed to turn all percolate requests into search requests, + // in that case just return the response... + listener.onResponse( + createMultiPercolateResponse(new MultiSearchResponse(new MultiSearchResponse.Item[0]), request, preFailures) + ); + } else { + client.multiSearch(multiSearchRequest, new ActionListener() { @Override - public void onResponse(TransportShardMultiPercolateAction.Response response) { - onShardResponse(shardId, response); + public void onResponse(MultiSearchResponse response) { + try { + listener.onResponse(createMultiPercolateResponse(response, request, preFailures)); + } catch (Exception e) { + onFailure(e); + } } @Override public void onFailure(Throwable e) { - onShardFailure(shardId, e); + listener.onFailure(e); } - }); } + } catch (Exception e) { + listener.onFailure(e); } + } - @SuppressWarnings("unchecked") - void onShardResponse(ShardId shardId, TransportShardMultiPercolateAction.Response response) { - logger.trace("{} Percolate shard response", shardId); + private MultiSearchRequest createMultiSearchRequest(MultiPercolateRequest multiPercolateRequest, Map getResponseSources, Map preFailures) throws IOException { + MultiSearchRequest multiSearchRequest = new MultiSearchRequest(); + multiSearchRequest.indicesOptions(multiPercolateRequest.indicesOptions()); + + for (int i = 0; i < multiPercolateRequest.requests().size(); i++) { + if (preFailures.keySet().contains(i)) { + continue; + } + + PercolateRequest percolateRequest = multiPercolateRequest.requests().get(i); + BytesReference docSource = getResponseSources.get(i); try { - for (TransportShardMultiPercolateAction.Response.Item item : response.items()) { - AtomicReferenceArray shardResults = responsesByItemAndShard.get(item.slot()); - if (shardResults == null) { - assert false : "shardResults can't be null"; - continue; - } - - if (item.failed()) { - shardResults.set(shardId.id(), new BroadcastShardOperationFailedException(shardId, item.error())); - } else { - shardResults.set(shardId.id(), item.response()); - } - - assert expectedOperationsPerItem.get(item.slot()).get() >= 1 : "slot[" + item.slot() + "] can't be lower than one"; - if (expectedOperationsPerItem.get(item.slot()).decrementAndGet() == 0) { - // Failure won't bubble up, since we fail the whole request now via the catch clause below, - // so expectedOperationsPerItem will not be decremented twice. - reduce(item.slot()); - } - } - } catch (Throwable e) { - logger.error("{} Percolate original reduce error", e, shardId); - finalListener.onFailure(e); + SearchRequest searchRequest = TransportPercolateAction.createSearchRequest( + percolateRequest, docSource, queryRegistry, aggParsers, parseFieldMatcher + ); + multiSearchRequest.add(searchRequest); + } catch (Exception e) { + preFailures.put(i, new MultiPercolateResponse.Item(e)); } } - @SuppressWarnings("unchecked") - void onShardFailure(ShardId shardId, Throwable e) { - logger.debug("{} Shard multi percolate failure", e, shardId); - try { - IntArrayList slots = shardToSlots.get(shardId); - for (int i = 0; i < slots.size(); i++) { - int slot = slots.get(i); - AtomicReferenceArray shardResults = responsesByItemAndShard.get(slot); - if (shardResults == null) { - continue; - } + return multiSearchRequest; + } - shardResults.set(shardId.id(), new BroadcastShardOperationFailedException(shardId, e)); - assert expectedOperationsPerItem.get(slot).get() >= 1 : "slot[" + slot + "] can't be lower than one. Caused by: " + e.getMessage(); - if (expectedOperationsPerItem.get(slot).decrementAndGet() == 0) { - reduce(slot); - } - } - } catch (Throwable t) { - logger.error("{} Percolate original reduce error, original error {}", t, shardId, e); - finalListener.onFailure(t); - } - } - - void reduce(int slot) { - AtomicReferenceArray shardResponses = responsesByItemAndShard.get(slot); - PercolateResponse reducedResponse = TransportPercolateAction.reduce((PercolateRequest) percolateRequests.get(slot), shardResponses, percolatorService); - reducedResponses.set(slot, reducedResponse); - assert expectedOperations.get() >= 1 : "slot[" + slot + "] expected options should be >= 1 but is " + expectedOperations.get(); - if (expectedOperations.decrementAndGet() == 0) { - finish(); - } - } - - void finish() { - MultiPercolateResponse.Item[] finalResponse = new MultiPercolateResponse.Item[reducedResponses.length()]; - for (int slot = 0; slot < reducedResponses.length(); slot++) { - Object element = reducedResponses.get(slot); - assert element != null : "Element[" + slot + "] shouldn't be null"; - if (element instanceof PercolateResponse) { - finalResponse[slot] = new MultiPercolateResponse.Item((PercolateResponse) element); - } else if (element instanceof Throwable) { - finalResponse[slot] = new MultiPercolateResponse.Item((Throwable)element); - } else if (element instanceof MultiGetResponse.Failure) { - finalResponse[slot] = new MultiPercolateResponse.Item(((MultiGetResponse.Failure)element).getFailure()); + private MultiPercolateResponse createMultiPercolateResponse(MultiSearchResponse multiSearchResponse, MultiPercolateRequest request, Map preFailures) { + int searchResponseIndex = 0; + MultiPercolateResponse.Item[] percolateItems = new MultiPercolateResponse.Item[request.requests().size()]; + for (int i = 0; i < percolateItems.length; i++) { + if (preFailures.keySet().contains(i)) { + percolateItems[i] = preFailures.get(i); + } else { + MultiSearchResponse.Item searchItem = multiSearchResponse.getResponses()[searchResponseIndex++]; + if (searchItem.isFailure()) { + percolateItems[i] = new MultiPercolateResponse.Item(searchItem.getFailure()); + } else { + PercolateRequest percolateRequest = request.requests().get(i); + percolateItems[i] = new MultiPercolateResponse.Item(TransportPercolateAction.createPercolateResponse(searchItem.getResponse(), percolateRequest.onlyCount())); } } - finalListener.onResponse(new MultiPercolateResponse(finalResponse)); } - + return new MultiPercolateResponse(percolateItems); } } diff --git a/core/src/main/java/org/elasticsearch/action/percolate/TransportPercolateAction.java b/core/src/main/java/org/elasticsearch/action/percolate/TransportPercolateAction.java index 2a8f1a4ed24..b23ef04021e 100644 --- a/core/src/main/java/org/elasticsearch/action/percolate/TransportPercolateAction.java +++ b/core/src/main/java/org/elasticsearch/action/percolate/TransportPercolateAction.java @@ -18,71 +18,74 @@ */ package org.elasticsearch.action.percolate; -import org.elasticsearch.ElasticsearchException; +import org.elasticsearch.ResourceNotFoundException; import org.elasticsearch.action.ActionListener; -import org.elasticsearch.action.ShardOperationFailedException; import org.elasticsearch.action.get.GetResponse; -import org.elasticsearch.action.get.TransportGetAction; +import org.elasticsearch.action.search.SearchRequest; +import org.elasticsearch.action.search.SearchResponse; import org.elasticsearch.action.support.ActionFilters; -import org.elasticsearch.action.support.DefaultShardOperationFailedException; -import org.elasticsearch.action.support.broadcast.BroadcastShardOperationFailedException; -import org.elasticsearch.action.support.broadcast.TransportBroadcastAction; -import org.elasticsearch.cluster.ClusterService; -import org.elasticsearch.cluster.ClusterState; -import org.elasticsearch.cluster.block.ClusterBlockException; -import org.elasticsearch.cluster.block.ClusterBlockLevel; +import org.elasticsearch.action.support.HandledTransportAction; +import org.elasticsearch.client.Client; import org.elasticsearch.cluster.metadata.IndexNameExpressionResolver; -import org.elasticsearch.cluster.routing.GroupShardsIterator; -import org.elasticsearch.cluster.routing.ShardRouting; +import org.elasticsearch.common.ParseFieldMatcher; import org.elasticsearch.common.bytes.BytesReference; import org.elasticsearch.common.inject.Inject; import org.elasticsearch.common.settings.Settings; -import org.elasticsearch.index.engine.DocumentMissingException; -import org.elasticsearch.percolator.PercolateException; -import org.elasticsearch.percolator.PercolatorService; -import org.elasticsearch.tasks.Task; +import org.elasticsearch.common.text.Text; +import org.elasticsearch.common.xcontent.XContentBuilder; +import org.elasticsearch.common.xcontent.XContentFactory; +import org.elasticsearch.common.xcontent.XContentHelper; +import org.elasticsearch.common.xcontent.XContentParser; +import org.elasticsearch.common.xcontent.XContentType; +import org.elasticsearch.index.query.BoolQueryBuilder; +import org.elasticsearch.index.query.PercolatorQueryBuilder; +import org.elasticsearch.index.query.QueryBuilder; +import org.elasticsearch.index.query.QueryBuilders; +import org.elasticsearch.index.query.QueryParseContext; +import org.elasticsearch.index.query.TemplateQueryParser; +import org.elasticsearch.indices.query.IndicesQueriesRegistry; +import org.elasticsearch.rest.action.support.RestActions; +import org.elasticsearch.script.Template; +import org.elasticsearch.search.SearchHit; +import org.elasticsearch.search.SearchHits; +import org.elasticsearch.search.aggregations.AggregatorParsers; +import org.elasticsearch.search.aggregations.InternalAggregations; +import org.elasticsearch.search.builder.SearchSourceBuilder; import org.elasticsearch.threadpool.ThreadPool; import org.elasticsearch.transport.TransportService; import java.io.IOException; -import java.util.ArrayList; -import java.util.List; -import java.util.Map; -import java.util.Set; -import java.util.concurrent.atomic.AtomicReferenceArray; +import java.util.Arrays; -/** - * - */ -public class TransportPercolateAction extends TransportBroadcastAction { +public class TransportPercolateAction extends HandledTransportAction { - private final PercolatorService percolatorService; - private final TransportGetAction getAction; + private final Client client; + private final ParseFieldMatcher parseFieldMatcher; + private final IndicesQueriesRegistry queryRegistry; + private final AggregatorParsers aggParsers; @Inject - public TransportPercolateAction(Settings settings, ThreadPool threadPool, ClusterService clusterService, - TransportService transportService, PercolatorService percolatorService, - TransportGetAction getAction, ActionFilters actionFilters, IndexNameExpressionResolver indexNameExpressionResolver) { - super(settings, PercolateAction.NAME, threadPool, clusterService, transportService, actionFilters, - indexNameExpressionResolver, PercolateRequest::new, PercolateShardRequest::new, ThreadPool.Names.PERCOLATE); - this.percolatorService = percolatorService; - this.getAction = getAction; + public TransportPercolateAction(Settings settings, ThreadPool threadPool, TransportService transportService, + ActionFilters actionFilters, IndexNameExpressionResolver indexNameExpressionResolver, + Client client, IndicesQueriesRegistry indicesQueriesRegistry, AggregatorParsers aggParsers) { + super(settings, PercolateAction.NAME, threadPool, transportService, actionFilters, indexNameExpressionResolver, PercolateRequest::new); + this.client = client; + this.aggParsers = aggParsers; + this.parseFieldMatcher = new ParseFieldMatcher(settings); + this.queryRegistry = indicesQueriesRegistry; } @Override - protected void doExecute(Task task, final PercolateRequest request, final ActionListener listener) { - request.startTime = System.currentTimeMillis(); + protected void doExecute(PercolateRequest request, ActionListener listener) { if (request.getRequest() != null) { - getAction.execute(request.getRequest(), new ActionListener() { + client.get(request.getRequest(), new ActionListener() { @Override public void onResponse(GetResponse getResponse) { - if (!getResponse.isExists()) { - onFailure(new DocumentMissingException(null, request.getRequest().type(), request.getRequest().id())); - return; + if (getResponse.isExists()) { + innerDoExecute(request, getResponse.getSourceAsBytesRef(), listener); + } else { + onFailure(new ResourceNotFoundException("percolate document [{}/{}/{}] doesn't exist", request.getRequest().index(), request.getRequest().type(), request.getRequest().id())); } - - BytesReference docSource = getResponse.getSourceAsBytesRef(); - TransportPercolateAction.super.doExecute(task, new PercolateRequest(request, docSource), listener); } @Override @@ -91,99 +94,153 @@ public class TransportPercolateAction extends TransportBroadcastAction shardResults = null; - List shardFailures = null; - - boolean onlyCount = false; - for (int i = 0; i < shardsResponses.length(); i++) { - Object shardResponse = shardsResponses.get(i); - if (shardResponse == null) { - // simply ignore non active shards - } else if (shardResponse instanceof BroadcastShardOperationFailedException) { - failedShards++; - if (shardFailures == null) { - shardFailures = new ArrayList<>(); - } - shardFailures.add(new DefaultShardOperationFailedException((BroadcastShardOperationFailedException) shardResponse)); - } else { - PercolateShardResponse percolateShardResponse = (PercolateShardResponse) shardResponse; - successfulShards++; - if (!percolateShardResponse.isEmpty()) { - if (shardResults == null) { - onlyCount = percolateShardResponse.onlyCount(); - shardResults = new ArrayList<>(); - } - shardResults.add(percolateShardResponse); - } - } - } - - if (shardResults == null) { - long tookInMillis = Math.max(1, System.currentTimeMillis() - request.startTime); - PercolateResponse.Match[] matches = request.onlyCount() ? null : PercolateResponse.EMPTY; - return new PercolateResponse(shardsResponses.length(), successfulShards, failedShards, shardFailures, tookInMillis, matches); - } else { - PercolatorService.ReduceResult result = null; - try { - result = percolatorService.reduce(onlyCount, shardResults); - } catch (IOException e) { - throw new ElasticsearchException("error during reduce phase", e); - } - long tookInMillis = Math.max(1, System.currentTimeMillis() - request.startTime); - return new PercolateResponse( - shardsResponses.length(), successfulShards, failedShards, shardFailures, - result.matches(), result.count(), tookInMillis, result.reducedAggregations() - ); - } - } - - @Override - protected PercolateShardRequest newShardRequest(int numShards, ShardRouting shard, PercolateRequest request) { - return new PercolateShardRequest(shard.shardId(), numShards, request); - } - - @Override - protected PercolateShardResponse newShardResponse() { - return new PercolateShardResponse(); - } - - @Override - protected GroupShardsIterator shards(ClusterState clusterState, PercolateRequest request, String[] concreteIndices) { - Map> routingMap = indexNameExpressionResolver.resolveSearchRouting(clusterState, request.routing(), request.indices()); - return clusterService.operationRouting().searchShards(clusterState, concreteIndices, routingMap, request.preference()); - } - - @Override - protected PercolateShardResponse shardOperation(PercolateShardRequest request) { + private void innerDoExecute(PercolateRequest request, BytesReference docSource, ActionListener listener) { + SearchRequest searchRequest; try { - return percolatorService.percolate(request); - } catch (Throwable e) { - logger.trace("{} failed to percolate", e, request.shardId()); - throw new PercolateException(request.shardId(), "failed to percolate", e); + searchRequest = createSearchRequest(request, docSource, queryRegistry, aggParsers, parseFieldMatcher); + } catch (IOException e) { + listener.onFailure(e); + return; } + client.search(searchRequest, new ActionListener() { + @Override + public void onResponse(SearchResponse searchResponse) { + try { + listener.onResponse(createPercolateResponse(searchResponse, request.onlyCount())); + } catch (Exception e) { + onFailure(e); + } + } + + @Override + public void onFailure(Throwable e) { + listener.onFailure(e); + } + }); + } + + public static SearchRequest createSearchRequest(PercolateRequest percolateRequest, BytesReference documentSource, IndicesQueriesRegistry queryRegistry, AggregatorParsers aggParsers, ParseFieldMatcher parseFieldMatcher) throws IOException { + SearchRequest searchRequest = new SearchRequest(); + if (percolateRequest.indices() != null) { + searchRequest.indices(percolateRequest.indices()); + } + searchRequest.indicesOptions(percolateRequest.indicesOptions()); + searchRequest.routing(percolateRequest.routing()); + searchRequest.preference(percolateRequest.preference()); + + BytesReference querySource = null; + XContentBuilder searchSource = XContentFactory.jsonBuilder().startObject(); + if (percolateRequest.source() != null && percolateRequest.source().length() > 0) { + try (XContentParser parser = XContentHelper.createParser(percolateRequest.source())) { + String currentFieldName = null; + XContentParser.Token token = parser.nextToken(); + if (token != XContentParser.Token.START_OBJECT) { + throw new IllegalArgumentException("Unknown token [" + token+ "]"); + } + + while ((token = parser.nextToken()) != XContentParser.Token.END_OBJECT) { + if (token == XContentParser.Token.FIELD_NAME) { + currentFieldName = parser.currentName(); + } else if (token == XContentParser.Token.START_OBJECT) { + if ("doc".equals(currentFieldName)) { + XContentBuilder builder = XContentFactory.jsonBuilder(); + builder.copyCurrentStructure(parser); + builder.flush(); + documentSource = builder.bytes(); + } else if ("query".equals(currentFieldName) || "filter".equals(currentFieldName)) { + XContentBuilder builder = XContentFactory.jsonBuilder(); + builder.copyCurrentStructure(parser); + builder.flush(); + querySource = builder.bytes(); + } else if ("sort".equals(currentFieldName)) { + searchSource.field("sort"); + searchSource.copyCurrentStructure(parser); + } else if ("aggregations".equals(currentFieldName)) { + searchSource.field("aggregations"); + searchSource.copyCurrentStructure(parser); + } else if ("highlight".equals(currentFieldName)) { + searchSource.field("highlight"); + searchSource.copyCurrentStructure(parser); + } else { + throw new IllegalArgumentException("Unknown field [" + currentFieldName+ "]"); + } + } else if (token == XContentParser.Token.START_ARRAY) { + if ("sort".equals(currentFieldName)) { + searchSource.field("sort"); + searchSource.copyCurrentStructure(parser); + } else { + throw new IllegalArgumentException("Unknown field [" + currentFieldName+ "]"); + } + } else if (token.isValue()) { + if ("size".equals(currentFieldName)) { + searchSource.field("size", parser.intValue()); + } else if ("sort".equals(currentFieldName)) { + searchSource.field("sort", parser.text()); + } else if ("track_scores".equals(currentFieldName) || "trackScores".equals(currentFieldName)) { + searchSource.field("track_scores", parser.booleanValue()); + } else { + throw new IllegalArgumentException("Unknown field [" + currentFieldName+ "]"); + } + } else { + throw new IllegalArgumentException("Unknown token [" + token + "]"); + } + } + } + } + + if (percolateRequest.onlyCount()) { + searchSource.field("size", 0); + } + + PercolatorQueryBuilder percolatorQueryBuilder = new PercolatorQueryBuilder(percolateRequest.documentType(), documentSource); + if (querySource != null) { + QueryParseContext queryParseContext = new QueryParseContext(queryRegistry); + queryParseContext.reset(XContentHelper.createParser(querySource)); + queryParseContext.parseFieldMatcher(parseFieldMatcher); + QueryBuilder queryBuilder = queryParseContext.parseInnerQueryBuilder(); + BoolQueryBuilder boolQueryBuilder = QueryBuilders.boolQuery(); + boolQueryBuilder.must(queryBuilder); + boolQueryBuilder.filter(percolatorQueryBuilder); + searchSource.field("query", boolQueryBuilder); + } else { + searchSource.field("query", percolatorQueryBuilder); + } + + searchSource.endObject(); + searchSource.flush(); + BytesReference source = searchSource.bytes(); + SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder(); + QueryParseContext context = new QueryParseContext(queryRegistry); + try (XContentParser parser = XContentFactory.xContent(XContentType.JSON).createParser(source)) { + context.reset(parser); + context.parseFieldMatcher(parseFieldMatcher); + searchSourceBuilder.parseXContent(parser, context, aggParsers, null); + searchRequest.source(searchSourceBuilder); + return searchRequest; + } + } + + public static PercolateResponse createPercolateResponse(SearchResponse searchResponse, boolean onlyCount) { + SearchHits hits = searchResponse.getHits(); + PercolateResponse.Match[] matches; + if (onlyCount) { + matches = null; + } else { + matches = new PercolateResponse.Match[hits.getHits().length]; + for (int i = 0; i < hits.getHits().length; i++) { + SearchHit hit = hits.getHits()[i]; + matches[i] = new PercolateResponse.Match(new Text(hit.getIndex()), new Text(hit.getId()), hit.getScore(), hit.getHighlightFields()); + } + } + + return new PercolateResponse( + searchResponse.getTotalShards(), searchResponse.getSuccessfulShards(), searchResponse.getFailedShards(), + Arrays.asList(searchResponse.getShardFailures()), matches, hits.getTotalHits(), searchResponse.getTookInMillis(), (InternalAggregations) searchResponse.getAggregations() + ); } } diff --git a/core/src/main/java/org/elasticsearch/action/percolate/TransportShardMultiPercolateAction.java b/core/src/main/java/org/elasticsearch/action/percolate/TransportShardMultiPercolateAction.java deleted file mode 100644 index 0732d4d4066..00000000000 --- a/core/src/main/java/org/elasticsearch/action/percolate/TransportShardMultiPercolateAction.java +++ /dev/null @@ -1,281 +0,0 @@ -/* - * Licensed to Elasticsearch under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch 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.elasticsearch.action.percolate; - -import org.elasticsearch.ElasticsearchException; -import org.elasticsearch.action.ActionRequestValidationException; -import org.elasticsearch.action.ActionResponse; -import org.elasticsearch.action.IndicesRequest; -import org.elasticsearch.action.support.ActionFilters; -import org.elasticsearch.action.support.TransportActions; -import org.elasticsearch.action.support.single.shard.SingleShardRequest; -import org.elasticsearch.action.support.single.shard.TransportSingleShardAction; -import org.elasticsearch.cluster.ClusterService; -import org.elasticsearch.cluster.ClusterState; -import org.elasticsearch.cluster.metadata.IndexNameExpressionResolver; -import org.elasticsearch.cluster.routing.ShardIterator; -import org.elasticsearch.common.inject.Inject; -import org.elasticsearch.common.io.stream.StreamInput; -import org.elasticsearch.common.io.stream.StreamOutput; -import org.elasticsearch.common.settings.Settings; -import org.elasticsearch.index.shard.ShardId; -import org.elasticsearch.percolator.PercolatorService; -import org.elasticsearch.threadpool.ThreadPool; -import org.elasticsearch.transport.TransportService; - -import java.io.IOException; -import java.util.ArrayList; -import java.util.Collections; -import java.util.List; - -/** - */ -public class TransportShardMultiPercolateAction extends TransportSingleShardAction { - - private final PercolatorService percolatorService; - - private static final String ACTION_NAME = MultiPercolateAction.NAME + "[shard]"; - - @Inject - public TransportShardMultiPercolateAction(Settings settings, ThreadPool threadPool, ClusterService clusterService, - TransportService transportService, PercolatorService percolatorService, - ActionFilters actionFilters, IndexNameExpressionResolver indexNameExpressionResolver) { - super(settings, ACTION_NAME, threadPool, clusterService, transportService, actionFilters, indexNameExpressionResolver, - Request::new, ThreadPool.Names.PERCOLATE); - this.percolatorService = percolatorService; - } - - @Override - protected boolean isSubAction() { - return true; - } - - @Override - protected Response newResponse() { - return new Response(); - } - - @Override - protected boolean resolveIndex(Request request) { - return false; - } - - @Override - protected ShardIterator shards(ClusterState state, InternalRequest request) { - return clusterService.operationRouting().getShards( - state, request.concreteIndex(), request.request().shardId(), request.request().preference - ); - } - - @Override - protected Response shardOperation(Request request, ShardId shardId) { - // TODO: Look into combining the shard req's docs into one in memory index. - Response response = new Response(); - response.items = new ArrayList<>(request.items.size()); - for (Request.Item item : request.items) { - Response.Item responseItem; - int slot = item.slot; - try { - responseItem = new Response.Item(slot, percolatorService.percolate(item.request)); - } catch (Throwable t) { - if (TransportActions.isShardNotAvailableException(t)) { - throw (ElasticsearchException) t; - } else { - logger.debug("{} failed to multi percolate", t, request.shardId()); - responseItem = new Response.Item(slot, t); - } - } - response.items.add(responseItem); - } - return response; - } - - - public static class Request extends SingleShardRequest implements IndicesRequest { - - private int shardId; - private String preference; - private List items; - - public Request() { - } - - Request(String concreteIndex, int shardId, String preference) { - super(concreteIndex); - this.shardId = shardId; - this.preference = preference; - this.items = new ArrayList<>(); - } - - @Override - public ActionRequestValidationException validate() { - return super.validateNonNullIndex(); - } - - @Override - public String[] indices() { - List indices = new ArrayList<>(); - for (Item item : items) { - Collections.addAll(indices, item.request.indices()); - } - return indices.toArray(new String[indices.size()]); - } - - public int shardId() { - return shardId; - } - - public void add(Item item) { - items.add(item); - } - - public List items() { - return items; - } - - @Override - public void readFrom(StreamInput in) throws IOException { - super.readFrom(in); - shardId = in.readVInt(); - preference = in.readOptionalString(); - int size = in.readVInt(); - items = new ArrayList<>(size); - for (int i = 0; i < size; i++) { - int slot = in.readVInt(); - PercolateShardRequest shardRequest = new PercolateShardRequest(); - shardRequest.readFrom(in); - Item item = new Item(slot, shardRequest); - items.add(item); - } - } - - @Override - public void writeTo(StreamOutput out) throws IOException { - super.writeTo(out); - out.writeVInt(shardId); - out.writeOptionalString(preference); - out.writeVInt(items.size()); - for (Item item : items) { - out.writeVInt(item.slot); - item.request.writeTo(out); - } - } - - static class Item { - - private final int slot; - private final PercolateShardRequest request; - - public Item(int slot, PercolateShardRequest request) { - this.slot = slot; - this.request = request; - } - - public int slot() { - return slot; - } - - public PercolateShardRequest request() { - return request; - } - - } - - } - - public static class Response extends ActionResponse { - - private List items; - - public List items() { - return items; - } - - @Override - public void writeTo(StreamOutput out) throws IOException { - super.writeTo(out); - out.writeVInt(items.size()); - for (Item item : items) { - out.writeVInt(item.slot); - if (item.response != null) { - out.writeBoolean(true); - item.response.writeTo(out); - } else { - out.writeBoolean(false); - out.writeThrowable(item.error); - } - } - } - - @Override - public void readFrom(StreamInput in) throws IOException { - super.readFrom(in); - int size = in.readVInt(); - items = new ArrayList<>(size); - for (int i = 0; i < size; i++) { - int slot = in.readVInt(); - if (in.readBoolean()) { - PercolateShardResponse shardResponse = new PercolateShardResponse(); - shardResponse.readFrom(in); - items.add(new Item(slot, shardResponse)); - } else { - items.add(new Item(slot, in.readThrowable())); - } - } - } - - public static class Item { - - private final int slot; - private final PercolateShardResponse response; - private final Throwable error; - - public Item(Integer slot, PercolateShardResponse response) { - this.slot = slot; - this.response = response; - this.error = null; - } - - public Item(Integer slot, Throwable error) { - this.slot = slot; - this.error = error; - this.response = null; - } - - public int slot() { - return slot; - } - - public PercolateShardResponse response() { - return response; - } - - public Throwable error() { - return error; - } - - public boolean failed() { - return error != null; - } - } - - } - -} diff --git a/core/src/main/java/org/elasticsearch/action/search/AbstractSearchAsyncAction.java b/core/src/main/java/org/elasticsearch/action/search/AbstractSearchAsyncAction.java index e928e681bbf..732e9098ee7 100644 --- a/core/src/main/java/org/elasticsearch/action/search/AbstractSearchAsyncAction.java +++ b/core/src/main/java/org/elasticsearch/action/search/AbstractSearchAsyncAction.java @@ -25,7 +25,6 @@ import org.apache.lucene.search.TopDocs; import org.elasticsearch.action.ActionListener; import org.elasticsearch.action.NoShardAvailableActionException; import org.elasticsearch.action.support.TransportActions; -import org.elasticsearch.cluster.ClusterService; import org.elasticsearch.cluster.ClusterState; import org.elasticsearch.cluster.block.ClusterBlockLevel; import org.elasticsearch.cluster.metadata.IndexNameExpressionResolver; @@ -34,6 +33,7 @@ import org.elasticsearch.cluster.node.DiscoveryNodes; import org.elasticsearch.cluster.routing.GroupShardsIterator; import org.elasticsearch.cluster.routing.ShardIterator; import org.elasticsearch.cluster.routing.ShardRouting; +import org.elasticsearch.cluster.service.ClusterService; import org.elasticsearch.common.Nullable; import org.elasticsearch.common.logging.ESLogger; import org.elasticsearch.common.util.concurrent.AtomicArray; diff --git a/core/src/main/java/org/elasticsearch/action/search/SearchDfsQueryAndFetchAsyncAction.java b/core/src/main/java/org/elasticsearch/action/search/SearchDfsQueryAndFetchAsyncAction.java index 56d0fedd40c..f7cb72b22e9 100644 --- a/core/src/main/java/org/elasticsearch/action/search/SearchDfsQueryAndFetchAsyncAction.java +++ b/core/src/main/java/org/elasticsearch/action/search/SearchDfsQueryAndFetchAsyncAction.java @@ -21,9 +21,9 @@ package org.elasticsearch.action.search; import org.elasticsearch.action.ActionListener; import org.elasticsearch.action.ActionRunnable; -import org.elasticsearch.cluster.ClusterService; import org.elasticsearch.cluster.metadata.IndexNameExpressionResolver; import org.elasticsearch.cluster.node.DiscoveryNode; +import org.elasticsearch.cluster.service.ClusterService; import org.elasticsearch.common.logging.ESLogger; import org.elasticsearch.common.util.concurrent.AtomicArray; import org.elasticsearch.search.action.SearchTransportService; diff --git a/core/src/main/java/org/elasticsearch/action/search/SearchDfsQueryThenFetchAsyncAction.java b/core/src/main/java/org/elasticsearch/action/search/SearchDfsQueryThenFetchAsyncAction.java index f2dcefa7554..c5f320f1b33 100644 --- a/core/src/main/java/org/elasticsearch/action/search/SearchDfsQueryThenFetchAsyncAction.java +++ b/core/src/main/java/org/elasticsearch/action/search/SearchDfsQueryThenFetchAsyncAction.java @@ -23,9 +23,9 @@ import com.carrotsearch.hppc.IntArrayList; import org.apache.lucene.search.ScoreDoc; import org.elasticsearch.action.ActionListener; import org.elasticsearch.action.ActionRunnable; -import org.elasticsearch.cluster.ClusterService; import org.elasticsearch.cluster.metadata.IndexNameExpressionResolver; import org.elasticsearch.cluster.node.DiscoveryNode; +import org.elasticsearch.cluster.service.ClusterService; import org.elasticsearch.common.logging.ESLogger; import org.elasticsearch.common.util.concurrent.AtomicArray; import org.elasticsearch.search.SearchShardTarget; diff --git a/core/src/main/java/org/elasticsearch/action/search/SearchQueryAndFetchAsyncAction.java b/core/src/main/java/org/elasticsearch/action/search/SearchQueryAndFetchAsyncAction.java index dcbf9b5091f..1b338847762 100644 --- a/core/src/main/java/org/elasticsearch/action/search/SearchQueryAndFetchAsyncAction.java +++ b/core/src/main/java/org/elasticsearch/action/search/SearchQueryAndFetchAsyncAction.java @@ -21,9 +21,9 @@ package org.elasticsearch.action.search; import org.elasticsearch.action.ActionListener; import org.elasticsearch.action.ActionRunnable; -import org.elasticsearch.cluster.ClusterService; import org.elasticsearch.cluster.metadata.IndexNameExpressionResolver; import org.elasticsearch.cluster.node.DiscoveryNode; +import org.elasticsearch.cluster.service.ClusterService; import org.elasticsearch.common.logging.ESLogger; import org.elasticsearch.search.action.SearchTransportService; import org.elasticsearch.search.controller.SearchPhaseController; diff --git a/core/src/main/java/org/elasticsearch/action/search/SearchQueryThenFetchAsyncAction.java b/core/src/main/java/org/elasticsearch/action/search/SearchQueryThenFetchAsyncAction.java index e15b9da8acb..3feb40411f9 100644 --- a/core/src/main/java/org/elasticsearch/action/search/SearchQueryThenFetchAsyncAction.java +++ b/core/src/main/java/org/elasticsearch/action/search/SearchQueryThenFetchAsyncAction.java @@ -23,9 +23,9 @@ import com.carrotsearch.hppc.IntArrayList; import org.apache.lucene.search.ScoreDoc; import org.elasticsearch.action.ActionListener; import org.elasticsearch.action.ActionRunnable; -import org.elasticsearch.cluster.ClusterService; import org.elasticsearch.cluster.metadata.IndexNameExpressionResolver; import org.elasticsearch.cluster.node.DiscoveryNode; +import org.elasticsearch.cluster.service.ClusterService; import org.elasticsearch.common.logging.ESLogger; import org.elasticsearch.common.util.concurrent.AtomicArray; import org.elasticsearch.search.SearchShardTarget; diff --git a/core/src/main/java/org/elasticsearch/action/search/SearchScrollQueryAndFetchAsyncAction.java b/core/src/main/java/org/elasticsearch/action/search/SearchScrollQueryAndFetchAsyncAction.java index b5b95dc5cbe..4e0ee3ff5e5 100644 --- a/core/src/main/java/org/elasticsearch/action/search/SearchScrollQueryAndFetchAsyncAction.java +++ b/core/src/main/java/org/elasticsearch/action/search/SearchScrollQueryAndFetchAsyncAction.java @@ -21,9 +21,9 @@ package org.elasticsearch.action.search; import org.apache.lucene.search.ScoreDoc; import org.elasticsearch.action.ActionListener; -import org.elasticsearch.cluster.ClusterService; import org.elasticsearch.cluster.node.DiscoveryNode; import org.elasticsearch.cluster.node.DiscoveryNodes; +import org.elasticsearch.cluster.service.ClusterService; import org.elasticsearch.common.logging.ESLogger; import org.elasticsearch.common.util.concurrent.AtomicArray; import org.elasticsearch.search.action.SearchTransportService; diff --git a/core/src/main/java/org/elasticsearch/action/search/SearchScrollQueryThenFetchAsyncAction.java b/core/src/main/java/org/elasticsearch/action/search/SearchScrollQueryThenFetchAsyncAction.java index 864f17eee2c..8e822302d2f 100644 --- a/core/src/main/java/org/elasticsearch/action/search/SearchScrollQueryThenFetchAsyncAction.java +++ b/core/src/main/java/org/elasticsearch/action/search/SearchScrollQueryThenFetchAsyncAction.java @@ -22,9 +22,9 @@ package org.elasticsearch.action.search; import com.carrotsearch.hppc.IntArrayList; import org.apache.lucene.search.ScoreDoc; import org.elasticsearch.action.ActionListener; -import org.elasticsearch.cluster.ClusterService; import org.elasticsearch.cluster.node.DiscoveryNode; import org.elasticsearch.cluster.node.DiscoveryNodes; +import org.elasticsearch.cluster.service.ClusterService; import org.elasticsearch.common.logging.ESLogger; import org.elasticsearch.common.util.concurrent.AtomicArray; import org.elasticsearch.search.action.SearchTransportService; diff --git a/core/src/main/java/org/elasticsearch/action/search/TransportClearScrollAction.java b/core/src/main/java/org/elasticsearch/action/search/TransportClearScrollAction.java index 95f0796ba4f..fb021fdd9f9 100644 --- a/core/src/main/java/org/elasticsearch/action/search/TransportClearScrollAction.java +++ b/core/src/main/java/org/elasticsearch/action/search/TransportClearScrollAction.java @@ -22,11 +22,11 @@ package org.elasticsearch.action.search; import org.elasticsearch.action.ActionListener; import org.elasticsearch.action.support.ActionFilters; import org.elasticsearch.action.support.HandledTransportAction; -import org.elasticsearch.cluster.ClusterService; import org.elasticsearch.cluster.ClusterState; import org.elasticsearch.cluster.metadata.IndexNameExpressionResolver; import org.elasticsearch.cluster.node.DiscoveryNode; import org.elasticsearch.cluster.node.DiscoveryNodes; +import org.elasticsearch.cluster.service.ClusterService; import org.elasticsearch.common.inject.Inject; import org.elasticsearch.common.settings.Settings; import org.elasticsearch.common.util.concurrent.CountDown; diff --git a/core/src/main/java/org/elasticsearch/action/search/TransportMultiSearchAction.java b/core/src/main/java/org/elasticsearch/action/search/TransportMultiSearchAction.java index 43754427598..c0428cd531f 100644 --- a/core/src/main/java/org/elasticsearch/action/search/TransportMultiSearchAction.java +++ b/core/src/main/java/org/elasticsearch/action/search/TransportMultiSearchAction.java @@ -22,10 +22,10 @@ package org.elasticsearch.action.search; import org.elasticsearch.action.ActionListener; import org.elasticsearch.action.support.ActionFilters; import org.elasticsearch.action.support.HandledTransportAction; -import org.elasticsearch.cluster.ClusterService; import org.elasticsearch.cluster.ClusterState; import org.elasticsearch.cluster.block.ClusterBlockLevel; import org.elasticsearch.cluster.metadata.IndexNameExpressionResolver; +import org.elasticsearch.cluster.service.ClusterService; import org.elasticsearch.common.inject.Inject; import org.elasticsearch.common.settings.Settings; import org.elasticsearch.common.util.concurrent.AtomicArray; diff --git a/core/src/main/java/org/elasticsearch/action/search/TransportSearchAction.java b/core/src/main/java/org/elasticsearch/action/search/TransportSearchAction.java index 0b53008ddf5..8fe99c1e590 100644 --- a/core/src/main/java/org/elasticsearch/action/search/TransportSearchAction.java +++ b/core/src/main/java/org/elasticsearch/action/search/TransportSearchAction.java @@ -22,9 +22,9 @@ package org.elasticsearch.action.search; import org.elasticsearch.action.ActionListener; import org.elasticsearch.action.support.ActionFilters; import org.elasticsearch.action.support.HandledTransportAction; -import org.elasticsearch.cluster.ClusterService; import org.elasticsearch.cluster.ClusterState; import org.elasticsearch.cluster.metadata.IndexNameExpressionResolver; +import org.elasticsearch.cluster.service.ClusterService; import org.elasticsearch.common.inject.Inject; import org.elasticsearch.common.settings.Settings; import org.elasticsearch.index.IndexNotFoundException; diff --git a/core/src/main/java/org/elasticsearch/action/search/TransportSearchScrollAction.java b/core/src/main/java/org/elasticsearch/action/search/TransportSearchScrollAction.java index 03009cc0102..3bcadda1725 100644 --- a/core/src/main/java/org/elasticsearch/action/search/TransportSearchScrollAction.java +++ b/core/src/main/java/org/elasticsearch/action/search/TransportSearchScrollAction.java @@ -22,8 +22,8 @@ package org.elasticsearch.action.search; import org.elasticsearch.action.ActionListener; import org.elasticsearch.action.support.ActionFilters; import org.elasticsearch.action.support.HandledTransportAction; -import org.elasticsearch.cluster.ClusterService; import org.elasticsearch.cluster.metadata.IndexNameExpressionResolver; +import org.elasticsearch.cluster.service.ClusterService; import org.elasticsearch.common.inject.Inject; import org.elasticsearch.common.settings.Settings; import org.elasticsearch.search.action.SearchTransportService; diff --git a/core/src/main/java/org/elasticsearch/action/suggest/TransportSuggestAction.java b/core/src/main/java/org/elasticsearch/action/suggest/TransportSuggestAction.java index af6890e045e..95bf111ed71 100644 --- a/core/src/main/java/org/elasticsearch/action/suggest/TransportSuggestAction.java +++ b/core/src/main/java/org/elasticsearch/action/suggest/TransportSuggestAction.java @@ -25,13 +25,13 @@ import org.elasticsearch.action.support.ActionFilters; import org.elasticsearch.action.support.DefaultShardOperationFailedException; import org.elasticsearch.action.support.broadcast.BroadcastShardOperationFailedException; import org.elasticsearch.action.support.broadcast.TransportBroadcastAction; -import org.elasticsearch.cluster.ClusterService; import org.elasticsearch.cluster.ClusterState; import org.elasticsearch.cluster.block.ClusterBlockException; import org.elasticsearch.cluster.block.ClusterBlockLevel; import org.elasticsearch.cluster.metadata.IndexNameExpressionResolver; import org.elasticsearch.cluster.routing.GroupShardsIterator; import org.elasticsearch.cluster.routing.ShardRouting; +import org.elasticsearch.cluster.service.ClusterService; import org.elasticsearch.common.inject.Inject; import org.elasticsearch.common.settings.Settings; import org.elasticsearch.index.IndexService; diff --git a/core/src/main/java/org/elasticsearch/action/support/broadcast/TransportBroadcastAction.java b/core/src/main/java/org/elasticsearch/action/support/broadcast/TransportBroadcastAction.java index f2d7e306c38..182d922fc39 100644 --- a/core/src/main/java/org/elasticsearch/action/support/broadcast/TransportBroadcastAction.java +++ b/core/src/main/java/org/elasticsearch/action/support/broadcast/TransportBroadcastAction.java @@ -24,7 +24,6 @@ import org.elasticsearch.action.NoShardAvailableActionException; import org.elasticsearch.action.support.ActionFilters; import org.elasticsearch.action.support.HandledTransportAction; import org.elasticsearch.action.support.TransportActions; -import org.elasticsearch.cluster.ClusterService; import org.elasticsearch.cluster.ClusterState; import org.elasticsearch.cluster.block.ClusterBlockException; import org.elasticsearch.cluster.metadata.IndexNameExpressionResolver; @@ -33,6 +32,7 @@ import org.elasticsearch.cluster.node.DiscoveryNodes; import org.elasticsearch.cluster.routing.GroupShardsIterator; import org.elasticsearch.cluster.routing.ShardIterator; import org.elasticsearch.cluster.routing.ShardRouting; +import org.elasticsearch.cluster.service.ClusterService; import org.elasticsearch.common.Nullable; import org.elasticsearch.common.settings.Settings; import org.elasticsearch.tasks.Task; diff --git a/core/src/main/java/org/elasticsearch/action/support/broadcast/node/TransportBroadcastByNodeAction.java b/core/src/main/java/org/elasticsearch/action/support/broadcast/node/TransportBroadcastByNodeAction.java index 37b101e1935..3ed3e8ffb7a 100644 --- a/core/src/main/java/org/elasticsearch/action/support/broadcast/node/TransportBroadcastByNodeAction.java +++ b/core/src/main/java/org/elasticsearch/action/support/broadcast/node/TransportBroadcastByNodeAction.java @@ -33,7 +33,6 @@ import org.elasticsearch.action.support.TransportActions; import org.elasticsearch.action.support.broadcast.BroadcastRequest; import org.elasticsearch.action.support.broadcast.BroadcastResponse; import org.elasticsearch.action.support.broadcast.BroadcastShardOperationFailedException; -import org.elasticsearch.cluster.ClusterService; import org.elasticsearch.cluster.ClusterState; import org.elasticsearch.cluster.block.ClusterBlockException; import org.elasticsearch.cluster.metadata.IndexNameExpressionResolver; @@ -41,6 +40,7 @@ import org.elasticsearch.cluster.node.DiscoveryNode; import org.elasticsearch.cluster.node.DiscoveryNodes; import org.elasticsearch.cluster.routing.ShardRouting; import org.elasticsearch.cluster.routing.ShardsIterator; +import org.elasticsearch.cluster.service.ClusterService; import org.elasticsearch.common.io.stream.StreamInput; import org.elasticsearch.common.io.stream.StreamOutput; import org.elasticsearch.common.io.stream.Streamable; diff --git a/core/src/main/java/org/elasticsearch/action/support/master/TransportMasterNodeAction.java b/core/src/main/java/org/elasticsearch/action/support/master/TransportMasterNodeAction.java index 4b19c3e6eba..1a7092c3a97 100644 --- a/core/src/main/java/org/elasticsearch/action/support/master/TransportMasterNodeAction.java +++ b/core/src/main/java/org/elasticsearch/action/support/master/TransportMasterNodeAction.java @@ -26,7 +26,6 @@ import org.elasticsearch.action.ActionRunnable; import org.elasticsearch.action.support.ActionFilters; import org.elasticsearch.action.support.HandledTransportAction; import org.elasticsearch.action.support.ThreadedActionListener; -import org.elasticsearch.cluster.ClusterService; import org.elasticsearch.cluster.ClusterState; import org.elasticsearch.cluster.ClusterStateObserver; import org.elasticsearch.cluster.MasterNodeChangePredicate; @@ -34,6 +33,7 @@ import org.elasticsearch.cluster.NotMasterException; import org.elasticsearch.cluster.block.ClusterBlockException; import org.elasticsearch.cluster.metadata.IndexNameExpressionResolver; import org.elasticsearch.cluster.node.DiscoveryNodes; +import org.elasticsearch.cluster.service.ClusterService; import org.elasticsearch.common.settings.Settings; import org.elasticsearch.common.unit.TimeValue; import org.elasticsearch.discovery.Discovery; diff --git a/core/src/main/java/org/elasticsearch/action/support/master/TransportMasterNodeReadAction.java b/core/src/main/java/org/elasticsearch/action/support/master/TransportMasterNodeReadAction.java index f53355f24e3..5a6ddcfb34e 100644 --- a/core/src/main/java/org/elasticsearch/action/support/master/TransportMasterNodeReadAction.java +++ b/core/src/main/java/org/elasticsearch/action/support/master/TransportMasterNodeReadAction.java @@ -21,8 +21,8 @@ package org.elasticsearch.action.support.master; import org.elasticsearch.action.ActionResponse; import org.elasticsearch.action.support.ActionFilters; -import org.elasticsearch.cluster.ClusterService; import org.elasticsearch.cluster.metadata.IndexNameExpressionResolver; +import org.elasticsearch.cluster.service.ClusterService; import org.elasticsearch.common.settings.Setting; import org.elasticsearch.common.settings.Setting.Property; import org.elasticsearch.common.settings.Settings; diff --git a/core/src/main/java/org/elasticsearch/action/support/master/info/TransportClusterInfoAction.java b/core/src/main/java/org/elasticsearch/action/support/master/info/TransportClusterInfoAction.java index 829f90bfc51..66b9fce5d71 100644 --- a/core/src/main/java/org/elasticsearch/action/support/master/info/TransportClusterInfoAction.java +++ b/core/src/main/java/org/elasticsearch/action/support/master/info/TransportClusterInfoAction.java @@ -22,9 +22,9 @@ import org.elasticsearch.action.ActionListener; import org.elasticsearch.action.ActionResponse; import org.elasticsearch.action.support.ActionFilters; import org.elasticsearch.action.support.master.TransportMasterNodeReadAction; -import org.elasticsearch.cluster.ClusterService; import org.elasticsearch.cluster.ClusterState; import org.elasticsearch.cluster.metadata.IndexNameExpressionResolver; +import org.elasticsearch.cluster.service.ClusterService; import org.elasticsearch.common.settings.Settings; import org.elasticsearch.threadpool.ThreadPool; import org.elasticsearch.transport.TransportService; diff --git a/core/src/main/java/org/elasticsearch/action/support/nodes/TransportNodesAction.java b/core/src/main/java/org/elasticsearch/action/support/nodes/TransportNodesAction.java index 7e2702afd8a..9c021efbe40 100644 --- a/core/src/main/java/org/elasticsearch/action/support/nodes/TransportNodesAction.java +++ b/core/src/main/java/org/elasticsearch/action/support/nodes/TransportNodesAction.java @@ -26,11 +26,11 @@ import org.elasticsearch.action.support.ActionFilters; import org.elasticsearch.action.support.ChildTaskRequest; import org.elasticsearch.action.support.HandledTransportAction; import org.elasticsearch.cluster.ClusterName; -import org.elasticsearch.cluster.ClusterService; import org.elasticsearch.cluster.ClusterState; import org.elasticsearch.cluster.metadata.IndexNameExpressionResolver; import org.elasticsearch.cluster.node.DiscoveryNode; import org.elasticsearch.cluster.node.DiscoveryNodes; +import org.elasticsearch.cluster.service.ClusterService; import org.elasticsearch.common.collect.ImmutableOpenMap; import org.elasticsearch.common.settings.Settings; import org.elasticsearch.tasks.Task; diff --git a/core/src/main/java/org/elasticsearch/action/support/replication/TransportBroadcastReplicationAction.java b/core/src/main/java/org/elasticsearch/action/support/replication/TransportBroadcastReplicationAction.java index 8ace072fa88..25de821e227 100644 --- a/core/src/main/java/org/elasticsearch/action/support/replication/TransportBroadcastReplicationAction.java +++ b/core/src/main/java/org/elasticsearch/action/support/replication/TransportBroadcastReplicationAction.java @@ -20,7 +20,6 @@ package org.elasticsearch.action.support.replication; import com.carrotsearch.hppc.cursors.IntObjectCursor; - import org.elasticsearch.ExceptionsHelper; import org.elasticsearch.action.ActionListener; import org.elasticsearch.action.ReplicationResponse; @@ -32,11 +31,11 @@ import org.elasticsearch.action.support.TransportActions; import org.elasticsearch.action.support.broadcast.BroadcastRequest; import org.elasticsearch.action.support.broadcast.BroadcastResponse; import org.elasticsearch.action.support.broadcast.BroadcastShardOperationFailedException; -import org.elasticsearch.cluster.ClusterService; import org.elasticsearch.cluster.ClusterState; import org.elasticsearch.cluster.metadata.IndexMetaData; import org.elasticsearch.cluster.metadata.IndexNameExpressionResolver; import org.elasticsearch.cluster.routing.IndexShardRoutingTable; +import org.elasticsearch.cluster.service.ClusterService; import org.elasticsearch.common.settings.Settings; import org.elasticsearch.common.util.concurrent.CountDown; import org.elasticsearch.index.shard.ShardId; diff --git a/core/src/main/java/org/elasticsearch/action/support/replication/TransportReplicationAction.java b/core/src/main/java/org/elasticsearch/action/support/replication/TransportReplicationAction.java index 28d21c6dbd9..1ddddbf8888 100644 --- a/core/src/main/java/org/elasticsearch/action/support/replication/TransportReplicationAction.java +++ b/core/src/main/java/org/elasticsearch/action/support/replication/TransportReplicationAction.java @@ -28,10 +28,8 @@ import org.elasticsearch.action.WriteConsistencyLevel; import org.elasticsearch.action.support.ActionFilters; import org.elasticsearch.action.support.TransportAction; import org.elasticsearch.action.support.TransportActions; -import org.elasticsearch.cluster.ClusterService; import org.elasticsearch.cluster.ClusterState; import org.elasticsearch.cluster.ClusterStateObserver; -import org.elasticsearch.cluster.action.index.MappingUpdatedAction; import org.elasticsearch.cluster.action.shard.ShardStateAction; import org.elasticsearch.cluster.block.ClusterBlockException; import org.elasticsearch.cluster.block.ClusterBlockLevel; @@ -43,6 +41,7 @@ import org.elasticsearch.cluster.node.DiscoveryNodes; import org.elasticsearch.cluster.routing.IndexRoutingTable; import org.elasticsearch.cluster.routing.IndexShardRoutingTable; import org.elasticsearch.cluster.routing.ShardRouting; +import org.elasticsearch.cluster.service.ClusterService; import org.elasticsearch.common.Nullable; import org.elasticsearch.common.collect.Tuple; import org.elasticsearch.common.io.stream.StreamInput; diff --git a/core/src/main/java/org/elasticsearch/action/support/single/instance/TransportInstanceSingleOperationAction.java b/core/src/main/java/org/elasticsearch/action/support/single/instance/TransportInstanceSingleOperationAction.java index dd1b4260a3c..fba7d80299b 100644 --- a/core/src/main/java/org/elasticsearch/action/support/single/instance/TransportInstanceSingleOperationAction.java +++ b/core/src/main/java/org/elasticsearch/action/support/single/instance/TransportInstanceSingleOperationAction.java @@ -24,7 +24,6 @@ import org.elasticsearch.action.ActionResponse; import org.elasticsearch.action.UnavailableShardsException; import org.elasticsearch.action.support.ActionFilters; import org.elasticsearch.action.support.HandledTransportAction; -import org.elasticsearch.cluster.ClusterService; import org.elasticsearch.cluster.ClusterState; import org.elasticsearch.cluster.ClusterStateObserver; import org.elasticsearch.cluster.block.ClusterBlockException; @@ -34,6 +33,7 @@ import org.elasticsearch.cluster.node.DiscoveryNode; import org.elasticsearch.cluster.node.DiscoveryNodes; import org.elasticsearch.cluster.routing.ShardIterator; import org.elasticsearch.cluster.routing.ShardRouting; +import org.elasticsearch.cluster.service.ClusterService; import org.elasticsearch.common.Nullable; import org.elasticsearch.common.settings.Settings; import org.elasticsearch.common.unit.TimeValue; diff --git a/core/src/main/java/org/elasticsearch/action/support/single/shard/TransportSingleShardAction.java b/core/src/main/java/org/elasticsearch/action/support/single/shard/TransportSingleShardAction.java index 649ef1e8575..0c7f0627c66 100644 --- a/core/src/main/java/org/elasticsearch/action/support/single/shard/TransportSingleShardAction.java +++ b/core/src/main/java/org/elasticsearch/action/support/single/shard/TransportSingleShardAction.java @@ -25,7 +25,6 @@ import org.elasticsearch.action.NoShardAvailableActionException; import org.elasticsearch.action.support.ActionFilters; import org.elasticsearch.action.support.TransportAction; import org.elasticsearch.action.support.TransportActions; -import org.elasticsearch.cluster.ClusterService; import org.elasticsearch.cluster.ClusterState; import org.elasticsearch.cluster.block.ClusterBlockException; import org.elasticsearch.cluster.block.ClusterBlockLevel; @@ -34,6 +33,7 @@ import org.elasticsearch.cluster.node.DiscoveryNode; import org.elasticsearch.cluster.node.DiscoveryNodes; import org.elasticsearch.cluster.routing.ShardRouting; import org.elasticsearch.cluster.routing.ShardsIterator; +import org.elasticsearch.cluster.service.ClusterService; import org.elasticsearch.common.Nullable; import org.elasticsearch.common.logging.LoggerMessageFormat; import org.elasticsearch.common.settings.Settings; diff --git a/core/src/main/java/org/elasticsearch/action/support/tasks/TransportTasksAction.java b/core/src/main/java/org/elasticsearch/action/support/tasks/TransportTasksAction.java index 53c0d851997..a14c6e00e14 100644 --- a/core/src/main/java/org/elasticsearch/action/support/tasks/TransportTasksAction.java +++ b/core/src/main/java/org/elasticsearch/action/support/tasks/TransportTasksAction.java @@ -28,11 +28,11 @@ import org.elasticsearch.action.support.ActionFilters; import org.elasticsearch.action.support.ChildTaskRequest; import org.elasticsearch.action.support.HandledTransportAction; import org.elasticsearch.cluster.ClusterName; -import org.elasticsearch.cluster.ClusterService; import org.elasticsearch.cluster.ClusterState; import org.elasticsearch.cluster.metadata.IndexNameExpressionResolver; import org.elasticsearch.cluster.node.DiscoveryNode; import org.elasticsearch.cluster.node.DiscoveryNodes; +import org.elasticsearch.cluster.service.ClusterService; import org.elasticsearch.common.collect.ImmutableOpenMap; import org.elasticsearch.common.io.stream.StreamInput; import org.elasticsearch.common.io.stream.StreamOutput; diff --git a/core/src/main/java/org/elasticsearch/action/termvectors/TransportMultiTermVectorsAction.java b/core/src/main/java/org/elasticsearch/action/termvectors/TransportMultiTermVectorsAction.java index 4f617876e20..d71958cefde 100644 --- a/core/src/main/java/org/elasticsearch/action/termvectors/TransportMultiTermVectorsAction.java +++ b/core/src/main/java/org/elasticsearch/action/termvectors/TransportMultiTermVectorsAction.java @@ -20,13 +20,12 @@ package org.elasticsearch.action.termvectors; import org.elasticsearch.action.ActionListener; -import org.elasticsearch.action.DocumentRequest; import org.elasticsearch.action.support.ActionFilters; import org.elasticsearch.action.support.HandledTransportAction; -import org.elasticsearch.cluster.ClusterService; import org.elasticsearch.cluster.ClusterState; import org.elasticsearch.cluster.block.ClusterBlockLevel; import org.elasticsearch.cluster.metadata.IndexNameExpressionResolver; +import org.elasticsearch.cluster.service.ClusterService; import org.elasticsearch.common.inject.Inject; import org.elasticsearch.common.settings.Settings; import org.elasticsearch.common.util.concurrent.AtomicArray; diff --git a/core/src/main/java/org/elasticsearch/action/termvectors/TransportShardMultiTermsVectorAction.java b/core/src/main/java/org/elasticsearch/action/termvectors/TransportShardMultiTermsVectorAction.java index 94b0e745a8e..197ab4260b2 100644 --- a/core/src/main/java/org/elasticsearch/action/termvectors/TransportShardMultiTermsVectorAction.java +++ b/core/src/main/java/org/elasticsearch/action/termvectors/TransportShardMultiTermsVectorAction.java @@ -23,10 +23,10 @@ import org.elasticsearch.ElasticsearchException; import org.elasticsearch.action.support.ActionFilters; import org.elasticsearch.action.support.TransportActions; import org.elasticsearch.action.support.single.shard.TransportSingleShardAction; -import org.elasticsearch.cluster.ClusterService; import org.elasticsearch.cluster.ClusterState; import org.elasticsearch.cluster.metadata.IndexNameExpressionResolver; import org.elasticsearch.cluster.routing.ShardIterator; +import org.elasticsearch.cluster.service.ClusterService; import org.elasticsearch.common.inject.Inject; import org.elasticsearch.common.settings.Settings; import org.elasticsearch.index.IndexService; diff --git a/core/src/main/java/org/elasticsearch/action/termvectors/TransportTermVectorsAction.java b/core/src/main/java/org/elasticsearch/action/termvectors/TransportTermVectorsAction.java index 5b0b9fd2726..da8754542ab 100644 --- a/core/src/main/java/org/elasticsearch/action/termvectors/TransportTermVectorsAction.java +++ b/core/src/main/java/org/elasticsearch/action/termvectors/TransportTermVectorsAction.java @@ -23,10 +23,10 @@ import org.elasticsearch.action.ActionListener; import org.elasticsearch.action.RoutingMissingException; import org.elasticsearch.action.support.ActionFilters; import org.elasticsearch.action.support.single.shard.TransportSingleShardAction; -import org.elasticsearch.cluster.ClusterService; import org.elasticsearch.cluster.ClusterState; import org.elasticsearch.cluster.metadata.IndexNameExpressionResolver; import org.elasticsearch.cluster.routing.ShardIterator; +import org.elasticsearch.cluster.service.ClusterService; import org.elasticsearch.common.inject.Inject; import org.elasticsearch.common.settings.Settings; import org.elasticsearch.index.IndexService; diff --git a/core/src/main/java/org/elasticsearch/action/update/TransportUpdateAction.java b/core/src/main/java/org/elasticsearch/action/update/TransportUpdateAction.java index 75feeb8fbca..0363ef8fe43 100644 --- a/core/src/main/java/org/elasticsearch/action/update/TransportUpdateAction.java +++ b/core/src/main/java/org/elasticsearch/action/update/TransportUpdateAction.java @@ -35,13 +35,13 @@ import org.elasticsearch.action.support.ActionFilters; import org.elasticsearch.action.support.AutoCreateIndex; import org.elasticsearch.action.support.TransportActions; import org.elasticsearch.action.support.single.instance.TransportInstanceSingleOperationAction; -import org.elasticsearch.cluster.ClusterService; import org.elasticsearch.cluster.ClusterState; import org.elasticsearch.cluster.metadata.IndexNameExpressionResolver; import org.elasticsearch.cluster.metadata.MetaData; import org.elasticsearch.cluster.routing.PlainShardIterator; import org.elasticsearch.cluster.routing.ShardIterator; import org.elasticsearch.cluster.routing.ShardRouting; +import org.elasticsearch.cluster.service.ClusterService; import org.elasticsearch.common.bytes.BytesReference; import org.elasticsearch.common.collect.Tuple; import org.elasticsearch.common.inject.Inject; diff --git a/core/src/main/java/org/elasticsearch/action/update/UpdateRequest.java b/core/src/main/java/org/elasticsearch/action/update/UpdateRequest.java index 14c127c0703..0877ea1c66b 100644 --- a/core/src/main/java/org/elasticsearch/action/update/UpdateRequest.java +++ b/core/src/main/java/org/elasticsearch/action/update/UpdateRequest.java @@ -44,6 +44,7 @@ import org.elasticsearch.script.ScriptService; import org.elasticsearch.script.ScriptService.ScriptType; import java.io.IOException; +import java.util.Collections; import java.util.HashMap; import java.util.List; import java.util.Map; @@ -671,9 +672,15 @@ public class UpdateRequest extends InstanceShardOperationRequest } else if ("detect_noop".equals(currentFieldName)) { detectNoop(parser.booleanValue()); } else if ("fields".equals(currentFieldName)) { - List values = parser.list(); - String[] fields = values.toArray(new String[values.size()]); - fields(fields); + List fields = null; + if (token == XContentParser.Token.START_ARRAY) { + fields = (List) parser.list(); + } else if (token.isValue()) { + fields = Collections.singletonList(parser.text()); + } + if (fields != null) { + fields(fields.toArray(new String[fields.size()])); + } } else { //here we don't have settings available, unable to throw deprecation exceptions scriptParameterParser.token(currentFieldName, token, parser, ParseFieldMatcher.EMPTY); diff --git a/core/src/main/java/org/elasticsearch/cluster/ClusterModule.java b/core/src/main/java/org/elasticsearch/cluster/ClusterModule.java index 42290e71779..47dd2ce9ae6 100644 --- a/core/src/main/java/org/elasticsearch/cluster/ClusterModule.java +++ b/core/src/main/java/org/elasticsearch/cluster/ClusterModule.java @@ -53,7 +53,7 @@ import org.elasticsearch.cluster.routing.allocation.decider.SameShardAllocationD import org.elasticsearch.cluster.routing.allocation.decider.ShardsLimitAllocationDecider; import org.elasticsearch.cluster.routing.allocation.decider.SnapshotInProgressAllocationDecider; import org.elasticsearch.cluster.routing.allocation.decider.ThrottlingAllocationDecider; -import org.elasticsearch.cluster.service.InternalClusterService; +import org.elasticsearch.cluster.service.ClusterService; import org.elasticsearch.common.inject.AbstractModule; import org.elasticsearch.common.logging.ESLogger; import org.elasticsearch.common.logging.Loggers; @@ -137,7 +137,7 @@ public class ClusterModule extends AbstractModule { bind(GatewayAllocator.class).asEagerSingleton(); bind(AllocationService.class).asEagerSingleton(); bind(DiscoveryNodeService.class).asEagerSingleton(); - bind(ClusterService.class).to(InternalClusterService.class).asEagerSingleton(); + bind(ClusterService.class).asEagerSingleton(); bind(NodeConnectionsService.class).asEagerSingleton(); bind(OperationRouting.class).asEagerSingleton(); bind(MetaDataCreateIndexService.class).asEagerSingleton(); diff --git a/core/src/main/java/org/elasticsearch/cluster/ClusterService.java b/core/src/main/java/org/elasticsearch/cluster/ClusterService.java deleted file mode 100644 index 10d547afc5c..00000000000 --- a/core/src/main/java/org/elasticsearch/cluster/ClusterService.java +++ /dev/null @@ -1,156 +0,0 @@ -/* - * Licensed to Elasticsearch under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch 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.elasticsearch.cluster; - -import org.elasticsearch.cluster.block.ClusterBlock; -import org.elasticsearch.cluster.node.DiscoveryNode; -import org.elasticsearch.cluster.routing.OperationRouting; -import org.elasticsearch.cluster.service.PendingClusterTask; -import org.elasticsearch.common.Nullable; -import org.elasticsearch.common.component.LifecycleComponent; -import org.elasticsearch.common.unit.TimeValue; - -import java.util.List; - -/** - * The cluster service allowing to both register for cluster state events ({@link ClusterStateListener}) - * and submit state update tasks ({@link ClusterStateUpdateTask}. - */ -public interface ClusterService extends LifecycleComponent { - - /** - * The local node. - */ - DiscoveryNode localNode(); - - /** - * The current state. - */ - ClusterState state(); - - /** - * Adds an initial block to be set on the first cluster state created. - */ - void addInitialStateBlock(ClusterBlock block) throws IllegalStateException; - - /** - * Remove an initial block to be set on the first cluster state created. - */ - void removeInitialStateBlock(ClusterBlock block) throws IllegalStateException; - - /** - * Remove an initial block to be set on the first cluster state created. - */ - void removeInitialStateBlock(int blockId) throws IllegalStateException; - - /** - * The operation routing. - */ - OperationRouting operationRouting(); - - /** - * Adds a priority listener for updated cluster states. - */ - void addFirst(ClusterStateListener listener); - - /** - * Adds last listener. - */ - void addLast(ClusterStateListener listener); - - /** - * Adds a listener for updated cluster states. - */ - void add(ClusterStateListener listener); - - /** - * Removes a listener for updated cluster states. - */ - void remove(ClusterStateListener listener); - - /** - * Add a listener for on/off local node master events - */ - void add(LocalNodeMasterListener listener); - - /** - * Remove the given listener for on/off local master events - */ - void remove(LocalNodeMasterListener listener); - - /** - * Adds a cluster state listener that will timeout after the provided timeout, - * and is executed after the clusterstate has been successfully applied ie. is - * in state {@link org.elasticsearch.cluster.ClusterState.ClusterStateStatus#APPLIED} - * NOTE: a {@code null} timeout means that the listener will never be removed - * automatically - */ - void add(@Nullable TimeValue timeout, TimeoutClusterStateListener listener); - - /** - * Submits a cluster state update task; submitted updates will be - * batched across the same instance of executor. The exact batching - * semantics depend on the underlying implementation but a rough - * guideline is that if the update task is submitted while there - * are pending update tasks for the same executor, these update - * tasks will all be executed on the executor in a single batch - * - * @param source the source of the cluster state update task - * @param task the state needed for the cluster state update task - * @param config the cluster state update task configuration - * @param executor the cluster state update task executor; tasks - * that share the same executor will be executed - * batches on this executor - * @param listener callback after the cluster state update task - * completes - * @param the type of the cluster state update task state - */ - void submitStateUpdateTask(final String source, final T task, - final ClusterStateTaskConfig config, - final ClusterStateTaskExecutor executor, - final ClusterStateTaskListener listener); - - /** - * Submits a cluster state update task; unlike {@link #submitStateUpdateTask(String, Object, ClusterStateTaskConfig, ClusterStateTaskExecutor, ClusterStateTaskListener)}, - * submitted updates will not be batched. - * - * @param source the source of the cluster state update task - * @param updateTask the full context for the cluster state update - * task - */ - void submitStateUpdateTask(final String source, final ClusterStateUpdateTask updateTask); - - /** - * Returns the tasks that are pending. - */ - List pendingTasks(); - - /** - * Returns the number of currently pending tasks. - */ - int numberOfPendingTasks(); - - /** - * Returns the maximum wait time for tasks in the queue - * - * @return A zero time value if the queue is empty, otherwise the time value oldest task waiting in the queue - */ - TimeValue getMaxTaskWaitTime(); -} diff --git a/core/src/main/java/org/elasticsearch/cluster/ClusterState.java b/core/src/main/java/org/elasticsearch/cluster/ClusterState.java index 1b3ddcfebf9..e6cc335a478 100644 --- a/core/src/main/java/org/elasticsearch/cluster/ClusterState.java +++ b/core/src/main/java/org/elasticsearch/cluster/ClusterState.java @@ -37,7 +37,7 @@ import org.elasticsearch.cluster.routing.RoutingNodes; import org.elasticsearch.cluster.routing.RoutingTable; import org.elasticsearch.cluster.routing.ShardRouting; import org.elasticsearch.cluster.routing.allocation.RoutingAllocation; -import org.elasticsearch.cluster.service.InternalClusterService; +import org.elasticsearch.cluster.service.ClusterService; import org.elasticsearch.common.Nullable; import org.elasticsearch.common.Strings; import org.elasticsearch.common.collect.ImmutableOpenMap; @@ -68,7 +68,7 @@ import java.util.Set; * exception of the {@link RoutingNodes} structure, which is built on demand from the {@link RoutingTable}, * and cluster state {@link #status}, which is updated during cluster state publishing and applying * processing. The cluster state can be updated only on the master node. All updates are performed by on a - * single thread and controlled by the {@link InternalClusterService}. After every update the + * single thread and controlled by the {@link ClusterService}. After every update the * {@link Discovery#publish} method publishes new version of the cluster state to all other nodes in the * cluster. The actual publishing mechanism is delegated to the {@link Discovery#publish} method and depends on * the type of discovery. For example, for local discovery it is implemented by the {@link LocalDiscovery#publish} diff --git a/core/src/main/java/org/elasticsearch/cluster/ClusterStateObserver.java b/core/src/main/java/org/elasticsearch/cluster/ClusterStateObserver.java index dd30a711688..d79a00dc3fe 100644 --- a/core/src/main/java/org/elasticsearch/cluster/ClusterStateObserver.java +++ b/core/src/main/java/org/elasticsearch/cluster/ClusterStateObserver.java @@ -20,6 +20,7 @@ package org.elasticsearch.cluster; import org.elasticsearch.ElasticsearchException; +import org.elasticsearch.cluster.service.ClusterService; import org.elasticsearch.common.Nullable; import org.elasticsearch.common.logging.ESLogger; import org.elasticsearch.common.unit.TimeValue; @@ -44,7 +45,7 @@ public class ClusterStateObserver { } }; - private final ClusterService clusterService; + private final ClusterService clusterService; private final ThreadContext contextHolder; volatile TimeValue timeOutValue; diff --git a/core/src/main/java/org/elasticsearch/cluster/InternalClusterInfoService.java b/core/src/main/java/org/elasticsearch/cluster/InternalClusterInfoService.java index 896793f1bf3..9a9ee06ce19 100644 --- a/core/src/main/java/org/elasticsearch/cluster/InternalClusterInfoService.java +++ b/core/src/main/java/org/elasticsearch/cluster/InternalClusterInfoService.java @@ -33,6 +33,7 @@ import org.elasticsearch.cluster.block.ClusterBlockException; import org.elasticsearch.cluster.node.DiscoveryNode; import org.elasticsearch.cluster.routing.ShardRouting; import org.elasticsearch.cluster.routing.allocation.decider.DiskThresholdDecider; +import org.elasticsearch.cluster.service.ClusterService; import org.elasticsearch.common.collect.ImmutableOpenMap; import org.elasticsearch.common.component.AbstractComponent; import org.elasticsearch.common.inject.Inject; diff --git a/core/src/main/java/org/elasticsearch/cluster/action/shard/ShardStateAction.java b/core/src/main/java/org/elasticsearch/cluster/action/shard/ShardStateAction.java index 3baf91a9dc8..68926368ddb 100644 --- a/core/src/main/java/org/elasticsearch/cluster/action/shard/ShardStateAction.java +++ b/core/src/main/java/org/elasticsearch/cluster/action/shard/ShardStateAction.java @@ -21,7 +21,6 @@ package org.elasticsearch.cluster.action.shard; import org.elasticsearch.ElasticsearchException; import org.elasticsearch.ExceptionsHelper; -import org.elasticsearch.cluster.ClusterService; import org.elasticsearch.cluster.ClusterState; import org.elasticsearch.cluster.ClusterStateObserver; import org.elasticsearch.cluster.ClusterStateTaskConfig; @@ -30,7 +29,6 @@ import org.elasticsearch.cluster.ClusterStateTaskListener; import org.elasticsearch.cluster.MasterNodeChangePredicate; import org.elasticsearch.cluster.NotMasterException; import org.elasticsearch.cluster.node.DiscoveryNode; -import org.elasticsearch.cluster.routing.IndexRoutingTable; import org.elasticsearch.cluster.routing.IndexShardRoutingTable; import org.elasticsearch.cluster.routing.RoutingNodes; import org.elasticsearch.cluster.routing.RoutingService; @@ -38,6 +36,7 @@ import org.elasticsearch.cluster.routing.ShardRouting; import org.elasticsearch.cluster.routing.allocation.AllocationService; import org.elasticsearch.cluster.routing.allocation.FailedRerouteAllocation; import org.elasticsearch.cluster.routing.allocation.RoutingAllocation; +import org.elasticsearch.cluster.service.ClusterService; import org.elasticsearch.common.Nullable; import org.elasticsearch.common.Priority; import org.elasticsearch.common.component.AbstractComponent; diff --git a/core/src/main/java/org/elasticsearch/cluster/metadata/IndexMetaData.java b/core/src/main/java/org/elasticsearch/cluster/metadata/IndexMetaData.java index 8c093a72ff3..20ba36dd910 100644 --- a/core/src/main/java/org/elasticsearch/cluster/metadata/IndexMetaData.java +++ b/core/src/main/java/org/elasticsearch/cluster/metadata/IndexMetaData.java @@ -46,6 +46,8 @@ import org.elasticsearch.common.xcontent.ToXContent; import org.elasticsearch.common.xcontent.XContentBuilder; import org.elasticsearch.common.xcontent.XContentFactory; import org.elasticsearch.common.xcontent.XContentParser; +import org.elasticsearch.common.xcontent.XContentType; +import org.elasticsearch.gateway.MetaDataStateFormat; import org.elasticsearch.index.Index; import org.elasticsearch.index.mapper.MapperService; import org.elasticsearch.rest.RestStatus; @@ -215,6 +217,7 @@ public class IndexMetaData implements Diffable, FromXContentBuild .numberOfShards(1).numberOfReplicas(0).build(); public static final String KEY_ACTIVE_ALLOCATIONS = "active_allocations"; + public static final String INDEX_STATE_FILE_PREFIX = "state-"; private final int numberOfShards; private final int numberOfReplicas; @@ -1023,4 +1026,21 @@ public class IndexMetaData implements Diffable, FromXContentBuild return builder.build(); } + private static final ToXContent.Params FORMAT_PARAMS = new MapParams(Collections.singletonMap("binary", "true")); + + /** + * State format for {@link IndexMetaData} to write to and load from disk + */ + public static final MetaDataStateFormat FORMAT = new MetaDataStateFormat(XContentType.SMILE, INDEX_STATE_FILE_PREFIX) { + + @Override + public void toXContent(XContentBuilder builder, IndexMetaData state) throws IOException { + Builder.toXContent(state, builder, FORMAT_PARAMS); + } + + @Override + public IndexMetaData fromXContent(XContentParser parser) throws IOException { + return Builder.fromXContent(parser); + } + }; } diff --git a/core/src/main/java/org/elasticsearch/cluster/metadata/MetaData.java b/core/src/main/java/org/elasticsearch/cluster/metadata/MetaData.java index 0beae6a77e8..db6871b0645 100644 --- a/core/src/main/java/org/elasticsearch/cluster/metadata/MetaData.java +++ b/core/src/main/java/org/elasticsearch/cluster/metadata/MetaData.java @@ -30,7 +30,7 @@ import org.elasticsearch.cluster.InternalClusterInfoService; import org.elasticsearch.cluster.block.ClusterBlock; import org.elasticsearch.cluster.block.ClusterBlockLevel; import org.elasticsearch.cluster.routing.allocation.decider.DiskThresholdDecider; -import org.elasticsearch.cluster.service.InternalClusterService; +import org.elasticsearch.cluster.service.ClusterService; import org.elasticsearch.common.Nullable; import org.elasticsearch.common.ParseFieldMatcher; import org.elasticsearch.common.Strings; @@ -51,6 +51,7 @@ import org.elasticsearch.common.xcontent.XContentFactory; import org.elasticsearch.common.xcontent.XContentParser; import org.elasticsearch.common.xcontent.XContentType; import org.elasticsearch.discovery.DiscoverySettings; +import org.elasticsearch.gateway.MetaDataStateFormat; import org.elasticsearch.index.Index; import org.elasticsearch.index.IndexNotFoundException; import org.elasticsearch.index.store.IndexStoreConfig; @@ -153,6 +154,8 @@ public class MetaData implements Iterable, Diffable, Fr public static final String CONTEXT_MODE_GATEWAY = XContentContext.GATEWAY.toString(); + public static final String GLOBAL_STATE_FILE_PREFIX = "global-"; + private final String clusterUUID; private final long version; @@ -735,7 +738,7 @@ public class MetaData implements Iterable, Diffable, Fr InternalClusterInfoService.INTERNAL_CLUSTER_INFO_UPDATE_INTERVAL_SETTING.getKey(), InternalClusterInfoService.INTERNAL_CLUSTER_INFO_TIMEOUT_SETTING.getKey(), DiscoverySettings.PUBLISH_TIMEOUT_SETTING.getKey(), - InternalClusterService.CLUSTER_SERVICE_SLOW_TASK_LOGGING_THRESHOLD_SETTING.getKey())); + ClusterService.CLUSTER_SERVICE_SLOW_TASK_LOGGING_THRESHOLD_SETTING.getKey())); /** As of 2.0 we require units for time and byte-sized settings. This methods adds default units to any cluster settings that don't * specify a unit. */ @@ -1160,4 +1163,28 @@ public class MetaData implements Iterable, Diffable, Fr return PROTO.readFrom(in); } } + + private final static ToXContent.Params FORMAT_PARAMS; + static { + Map params = new HashMap<>(2); + params.put("binary", "true"); + params.put(MetaData.CONTEXT_MODE_PARAM, MetaData.CONTEXT_MODE_GATEWAY); + FORMAT_PARAMS = new MapParams(params); + } + + /** + * State format for {@link MetaData} to write to and load from disk + */ + public final static MetaDataStateFormat FORMAT = new MetaDataStateFormat(XContentType.SMILE, GLOBAL_STATE_FILE_PREFIX) { + + @Override + public void toXContent(XContentBuilder builder, MetaData state) throws IOException { + Builder.toXContent(state, builder, FORMAT_PARAMS); + } + + @Override + public MetaData fromXContent(XContentParser parser) throws IOException { + return Builder.fromXContent(parser); + } + }; } diff --git a/core/src/main/java/org/elasticsearch/cluster/metadata/MetaDataCreateIndexService.java b/core/src/main/java/org/elasticsearch/cluster/metadata/MetaDataCreateIndexService.java index 177c46e5537..e0db19cb516 100644 --- a/core/src/main/java/org/elasticsearch/cluster/metadata/MetaDataCreateIndexService.java +++ b/core/src/main/java/org/elasticsearch/cluster/metadata/MetaDataCreateIndexService.java @@ -28,7 +28,6 @@ import org.elasticsearch.action.ActionListener; import org.elasticsearch.action.admin.indices.alias.Alias; import org.elasticsearch.action.admin.indices.create.CreateIndexClusterStateUpdateRequest; import org.elasticsearch.cluster.AckedClusterStateUpdateTask; -import org.elasticsearch.cluster.ClusterService; import org.elasticsearch.cluster.ClusterState; import org.elasticsearch.cluster.ack.ClusterStateUpdateResponse; import org.elasticsearch.cluster.block.ClusterBlock; @@ -39,6 +38,7 @@ import org.elasticsearch.cluster.node.DiscoveryNodes; import org.elasticsearch.cluster.routing.RoutingTable; import org.elasticsearch.cluster.routing.allocation.AllocationService; import org.elasticsearch.cluster.routing.allocation.RoutingAllocation; +import org.elasticsearch.cluster.service.ClusterService; import org.elasticsearch.common.Priority; import org.elasticsearch.common.Strings; import org.elasticsearch.common.ValidationException; diff --git a/core/src/main/java/org/elasticsearch/cluster/metadata/MetaDataDeleteIndexService.java b/core/src/main/java/org/elasticsearch/cluster/metadata/MetaDataDeleteIndexService.java index 5492325b651..5e6d35aacfe 100644 --- a/core/src/main/java/org/elasticsearch/cluster/metadata/MetaDataDeleteIndexService.java +++ b/core/src/main/java/org/elasticsearch/cluster/metadata/MetaDataDeleteIndexService.java @@ -20,7 +20,6 @@ package org.elasticsearch.cluster.metadata; import org.elasticsearch.action.support.master.MasterNodeRequest; -import org.elasticsearch.cluster.ClusterService; import org.elasticsearch.cluster.ClusterState; import org.elasticsearch.cluster.ClusterStateUpdateTask; import org.elasticsearch.cluster.action.index.NodeIndexDeletedAction; @@ -28,19 +27,17 @@ import org.elasticsearch.cluster.block.ClusterBlocks; import org.elasticsearch.cluster.routing.RoutingTable; import org.elasticsearch.cluster.routing.allocation.AllocationService; import org.elasticsearch.cluster.routing.allocation.RoutingAllocation; +import org.elasticsearch.cluster.service.ClusterService; import org.elasticsearch.common.Priority; import org.elasticsearch.common.component.AbstractComponent; import org.elasticsearch.common.inject.Inject; import org.elasticsearch.common.settings.Settings; import org.elasticsearch.common.unit.TimeValue; import org.elasticsearch.common.util.concurrent.FutureUtils; -import org.elasticsearch.common.util.set.Sets; import org.elasticsearch.index.Index; -import org.elasticsearch.index.IndexNotFoundException; import org.elasticsearch.snapshots.SnapshotsService; import org.elasticsearch.threadpool.ThreadPool; -import java.util.HashSet; import java.util.Set; import java.util.concurrent.ScheduledFuture; import java.util.concurrent.atomic.AtomicBoolean; diff --git a/core/src/main/java/org/elasticsearch/cluster/metadata/MetaDataIndexAliasesService.java b/core/src/main/java/org/elasticsearch/cluster/metadata/MetaDataIndexAliasesService.java index 1f0eaf0cda0..e39b86a1611 100644 --- a/core/src/main/java/org/elasticsearch/cluster/metadata/MetaDataIndexAliasesService.java +++ b/core/src/main/java/org/elasticsearch/cluster/metadata/MetaDataIndexAliasesService.java @@ -23,9 +23,9 @@ import com.carrotsearch.hppc.cursors.ObjectCursor; import org.elasticsearch.action.ActionListener; import org.elasticsearch.action.admin.indices.alias.IndicesAliasesClusterStateUpdateRequest; import org.elasticsearch.cluster.AckedClusterStateUpdateTask; -import org.elasticsearch.cluster.ClusterService; import org.elasticsearch.cluster.ClusterState; import org.elasticsearch.cluster.ack.ClusterStateUpdateResponse; +import org.elasticsearch.cluster.service.ClusterService; import org.elasticsearch.common.Priority; import org.elasticsearch.common.Strings; import org.elasticsearch.common.component.AbstractComponent; diff --git a/core/src/main/java/org/elasticsearch/cluster/metadata/MetaDataIndexStateService.java b/core/src/main/java/org/elasticsearch/cluster/metadata/MetaDataIndexStateService.java index e68b0be36b6..e6e7084e4d9 100644 --- a/core/src/main/java/org/elasticsearch/cluster/metadata/MetaDataIndexStateService.java +++ b/core/src/main/java/org/elasticsearch/cluster/metadata/MetaDataIndexStateService.java @@ -19,11 +19,11 @@ package org.elasticsearch.cluster.metadata; +import org.elasticsearch.ElasticsearchException; import org.elasticsearch.action.ActionListener; import org.elasticsearch.action.admin.indices.close.CloseIndexClusterStateUpdateRequest; import org.elasticsearch.action.admin.indices.open.OpenIndexClusterStateUpdateRequest; import org.elasticsearch.cluster.AckedClusterStateUpdateTask; -import org.elasticsearch.cluster.ClusterService; import org.elasticsearch.cluster.ClusterState; import org.elasticsearch.cluster.ack.ClusterStateUpdateResponse; import org.elasticsearch.cluster.block.ClusterBlock; @@ -32,12 +32,14 @@ import org.elasticsearch.cluster.block.ClusterBlocks; import org.elasticsearch.cluster.routing.RoutingTable; import org.elasticsearch.cluster.routing.allocation.AllocationService; import org.elasticsearch.cluster.routing.allocation.RoutingAllocation; +import org.elasticsearch.cluster.service.ClusterService; import org.elasticsearch.common.Priority; import org.elasticsearch.common.component.AbstractComponent; import org.elasticsearch.common.inject.Inject; import org.elasticsearch.common.settings.Settings; import org.elasticsearch.index.Index; -import org.elasticsearch.index.IndexNotFoundException; +import org.elasticsearch.index.NodeServicesProvider; +import org.elasticsearch.indices.IndicesService; import org.elasticsearch.rest.RestStatus; import org.elasticsearch.snapshots.RestoreService; import org.elasticsearch.snapshots.SnapshotsService; @@ -60,10 +62,16 @@ public class MetaDataIndexStateService extends AbstractComponent { private final AllocationService allocationService; private final MetaDataIndexUpgradeService metaDataIndexUpgradeService; + private final NodeServicesProvider nodeServiceProvider; + private final IndicesService indicesService; @Inject - public MetaDataIndexStateService(Settings settings, ClusterService clusterService, AllocationService allocationService, MetaDataIndexUpgradeService metaDataIndexUpgradeService) { + public MetaDataIndexStateService(Settings settings, ClusterService clusterService, AllocationService allocationService, + MetaDataIndexUpgradeService metaDataIndexUpgradeService, + NodeServicesProvider nodeServicesProvider, IndicesService indicesService) { super(settings); + this.nodeServiceProvider = nodeServicesProvider; + this.indicesService = indicesService; this.clusterService = clusterService; this.allocationService = allocationService; this.metaDataIndexUpgradeService = metaDataIndexUpgradeService; @@ -163,6 +171,12 @@ public class MetaDataIndexStateService extends AbstractComponent { // The index might be closed because we couldn't import it due to old incompatible version // We need to check that this index can be upgraded to the current version indexMetaData = metaDataIndexUpgradeService.upgradeIndexMetaData(indexMetaData); + try { + indicesService.verifyIndexMetadata(nodeServiceProvider, indexMetaData); + } catch (Exception e) { + throw new ElasticsearchException("Failed to verify index " + indexMetaData.getIndex(), e); + } + mdBuilder.put(indexMetaData, true); blocksBuilder.removeIndexBlock(indexName, INDEX_CLOSED_BLOCK); } diff --git a/core/src/main/java/org/elasticsearch/cluster/metadata/MetaDataIndexTemplateService.java b/core/src/main/java/org/elasticsearch/cluster/metadata/MetaDataIndexTemplateService.java index da2fc064dc4..1206185a609 100644 --- a/core/src/main/java/org/elasticsearch/cluster/metadata/MetaDataIndexTemplateService.java +++ b/core/src/main/java/org/elasticsearch/cluster/metadata/MetaDataIndexTemplateService.java @@ -21,9 +21,9 @@ package org.elasticsearch.cluster.metadata; import com.carrotsearch.hppc.cursors.ObjectCursor; import org.elasticsearch.action.admin.indices.alias.Alias; import org.elasticsearch.action.support.master.MasterNodeRequest; -import org.elasticsearch.cluster.ClusterService; import org.elasticsearch.cluster.ClusterState; import org.elasticsearch.cluster.ClusterStateUpdateTask; +import org.elasticsearch.cluster.service.ClusterService; import org.elasticsearch.common.Priority; import org.elasticsearch.common.Strings; import org.elasticsearch.common.ValidationException; diff --git a/core/src/main/java/org/elasticsearch/cluster/metadata/MetaDataMappingService.java b/core/src/main/java/org/elasticsearch/cluster/metadata/MetaDataMappingService.java index a4dbe058395..cafdc4581a1 100644 --- a/core/src/main/java/org/elasticsearch/cluster/metadata/MetaDataMappingService.java +++ b/core/src/main/java/org/elasticsearch/cluster/metadata/MetaDataMappingService.java @@ -23,12 +23,12 @@ import com.carrotsearch.hppc.cursors.ObjectCursor; import org.elasticsearch.action.ActionListener; import org.elasticsearch.action.admin.indices.mapping.put.PutMappingClusterStateUpdateRequest; import org.elasticsearch.cluster.AckedClusterStateTaskListener; -import org.elasticsearch.cluster.ClusterService; import org.elasticsearch.cluster.ClusterState; import org.elasticsearch.cluster.ClusterStateTaskConfig; import org.elasticsearch.cluster.ClusterStateTaskExecutor; import org.elasticsearch.cluster.ack.ClusterStateUpdateResponse; import org.elasticsearch.cluster.node.DiscoveryNode; +import org.elasticsearch.cluster.service.ClusterService; import org.elasticsearch.common.Nullable; import org.elasticsearch.common.Priority; import org.elasticsearch.common.collect.Tuple; @@ -38,14 +38,13 @@ import org.elasticsearch.common.inject.Inject; import org.elasticsearch.common.settings.Settings; import org.elasticsearch.common.unit.TimeValue; import org.elasticsearch.index.Index; -import org.elasticsearch.index.IndexNotFoundException; import org.elasticsearch.index.IndexService; import org.elasticsearch.index.NodeServicesProvider; import org.elasticsearch.index.mapper.DocumentMapper; import org.elasticsearch.index.mapper.MapperService; +import org.elasticsearch.index.percolator.PercolatorFieldMapper; import org.elasticsearch.indices.IndicesService; import org.elasticsearch.indices.InvalidTypeNameException; -import org.elasticsearch.percolator.PercolatorService; import java.io.IOException; import java.util.ArrayList; @@ -297,7 +296,7 @@ public class MetaDataMappingService extends AbstractComponent { } assert mappingType != null; - if (!MapperService.DEFAULT_MAPPING.equals(mappingType) && !PercolatorService.TYPE_NAME.equals(mappingType) && mappingType.charAt(0) == '_') { + if (!MapperService.DEFAULT_MAPPING.equals(mappingType) && !PercolatorFieldMapper.TYPE_NAME.equals(mappingType) && mappingType.charAt(0) == '_') { throw new InvalidTypeNameException("Document mapping type name can't start with '_'"); } MetaData.Builder builder = MetaData.builder(metaData); diff --git a/core/src/main/java/org/elasticsearch/cluster/metadata/MetaDataUpdateSettingsService.java b/core/src/main/java/org/elasticsearch/cluster/metadata/MetaDataUpdateSettingsService.java index b2764734469..c925b43056b 100644 --- a/core/src/main/java/org/elasticsearch/cluster/metadata/MetaDataUpdateSettingsService.java +++ b/core/src/main/java/org/elasticsearch/cluster/metadata/MetaDataUpdateSettingsService.java @@ -25,7 +25,6 @@ import org.elasticsearch.action.admin.indices.settings.put.UpdateSettingsCluster import org.elasticsearch.action.admin.indices.upgrade.post.UpgradeSettingsClusterStateUpdateRequest; import org.elasticsearch.cluster.AckedClusterStateUpdateTask; import org.elasticsearch.cluster.ClusterChangedEvent; -import org.elasticsearch.cluster.ClusterService; import org.elasticsearch.cluster.ClusterState; import org.elasticsearch.cluster.ClusterStateListener; import org.elasticsearch.cluster.ack.ClusterStateUpdateResponse; @@ -34,6 +33,7 @@ import org.elasticsearch.cluster.block.ClusterBlocks; import org.elasticsearch.cluster.routing.RoutingTable; import org.elasticsearch.cluster.routing.allocation.AllocationService; import org.elasticsearch.cluster.routing.allocation.RoutingAllocation; +import org.elasticsearch.cluster.service.ClusterService; import org.elasticsearch.common.Priority; import org.elasticsearch.common.collect.Tuple; import org.elasticsearch.common.component.AbstractComponent; @@ -176,6 +176,7 @@ public class MetaDataUpdateSettingsService extends AbstractComponent implements final Settings skippedSettigns = skipppedSettings.build(); final Settings closedSettings = settingsForClosedIndices.build(); final Settings openSettings = settingsForOpenIndices.build(); + final boolean preserveExisting = request.isPreserveExisting(); clusterService.submitStateUpdateTask("update-settings", new AckedClusterStateUpdateTask(Priority.URGENT, request, listener) { @@ -221,7 +222,7 @@ public class MetaDataUpdateSettingsService extends AbstractComponent implements } int updatedNumberOfReplicas = openSettings.getAsInt(IndexMetaData.SETTING_NUMBER_OF_REPLICAS, -1); - if (updatedNumberOfReplicas != -1) { + if (updatedNumberOfReplicas != -1 && preserveExisting == false) { routingTableBuilder.updateNumberOfReplicas(updatedNumberOfReplicas, actualIndices); metaDataBuilder.updateNumberOfReplicas(updatedNumberOfReplicas, actualIndices); logger.info("updating number_of_replicas to [{}] for indices {}", updatedNumberOfReplicas, actualIndices); @@ -239,6 +240,9 @@ public class MetaDataUpdateSettingsService extends AbstractComponent implements Settings.Builder updates = Settings.builder(); Settings.Builder indexSettings = Settings.builder().put(indexMetaData.getSettings()); if (indexScopedSettings.updateDynamicSettings(openSettings, indexSettings, updates, index.getName())) { + if (preserveExisting) { + indexSettings.put(indexMetaData.getSettings()); + } metaDataBuilder.put(IndexMetaData.builder(indexMetaData).settings(indexSettings)); } } @@ -250,6 +254,9 @@ public class MetaDataUpdateSettingsService extends AbstractComponent implements Settings.Builder updates = Settings.builder(); Settings.Builder indexSettings = Settings.builder().put(indexMetaData.getSettings()); if (indexScopedSettings.updateSettings(closedSettings, indexSettings, updates, index.getName())) { + if (preserveExisting) { + indexSettings.put(indexMetaData.getSettings()); + } metaDataBuilder.put(IndexMetaData.builder(indexMetaData).settings(indexSettings)); } } diff --git a/core/src/main/java/org/elasticsearch/cluster/routing/RoutingService.java b/core/src/main/java/org/elasticsearch/cluster/routing/RoutingService.java index c683f0200dc..90565a6569d 100644 --- a/core/src/main/java/org/elasticsearch/cluster/routing/RoutingService.java +++ b/core/src/main/java/org/elasticsearch/cluster/routing/RoutingService.java @@ -20,12 +20,12 @@ package org.elasticsearch.cluster.routing; import org.elasticsearch.cluster.ClusterChangedEvent; -import org.elasticsearch.cluster.ClusterService; import org.elasticsearch.cluster.ClusterState; import org.elasticsearch.cluster.ClusterStateListener; import org.elasticsearch.cluster.ClusterStateUpdateTask; import org.elasticsearch.cluster.routing.allocation.AllocationService; import org.elasticsearch.cluster.routing.allocation.RoutingAllocation; +import org.elasticsearch.cluster.service.ClusterService; import org.elasticsearch.common.Priority; import org.elasticsearch.common.component.AbstractLifecycleComponent; import org.elasticsearch.common.inject.Inject; diff --git a/core/src/main/java/org/elasticsearch/cluster/service/InternalClusterService.java b/core/src/main/java/org/elasticsearch/cluster/service/ClusterService.java similarity index 85% rename from core/src/main/java/org/elasticsearch/cluster/service/InternalClusterService.java rename to core/src/main/java/org/elasticsearch/cluster/service/ClusterService.java index c57cfd5a57c..fa9b3492685 100644 --- a/core/src/main/java/org/elasticsearch/cluster/service/InternalClusterService.java +++ b/core/src/main/java/org/elasticsearch/cluster/service/ClusterService.java @@ -22,7 +22,6 @@ package org.elasticsearch.cluster.service; import org.elasticsearch.cluster.AckedClusterStateTaskListener; import org.elasticsearch.cluster.ClusterChangedEvent; import org.elasticsearch.cluster.ClusterName; -import org.elasticsearch.cluster.ClusterService; import org.elasticsearch.cluster.ClusterState; import org.elasticsearch.cluster.ClusterState.Builder; import org.elasticsearch.cluster.ClusterStateListener; @@ -88,11 +87,11 @@ import static org.elasticsearch.common.util.concurrent.EsExecutors.daemonThreadF /** * */ -public class InternalClusterService extends AbstractLifecycleComponent implements ClusterService { +public class ClusterService extends AbstractLifecycleComponent { public static final Setting CLUSTER_SERVICE_SLOW_TASK_LOGGING_THRESHOLD_SETTING = - Setting.positiveTimeSetting("cluster.service.slow_task_logging_threshold", TimeValue.timeValueSeconds(30), - Property.Dynamic, Property.NodeScope); + Setting.positiveTimeSetting("cluster.service.slow_task_logging_threshold", TimeValue.timeValueSeconds(30), + Property.Dynamic, Property.NodeScope); public static final String UPDATE_THREAD_NAME = "clusterService#updateTask"; private final ThreadPool threadPool; @@ -116,7 +115,8 @@ public class InternalClusterService extends AbstractLifecycleComponent> updateTasksPerExecutor = new HashMap<>(); // TODO this is rather frequently changing I guess a Synced Set would be better here and a dedicated remove API private final Collection postAppliedListeners = new CopyOnWriteArrayList<>(); - private final Iterable preAppliedListeners = Iterables.concat(priorityClusterStateListeners, clusterStateListeners, lastClusterStateListeners); + private final Iterable preAppliedListeners = Iterables.concat(priorityClusterStateListeners, + clusterStateListeners, lastClusterStateListeners); private final LocalNodeMasterListeners localNodeMasterListeners; @@ -129,8 +129,8 @@ public class InternalClusterService extends AbstractLifecycleComponent the type of the cluster state update task state + */ public void submitStateUpdateTask(final String source, final T task, final ClusterStateTaskConfig config, final ClusterStateTaskExecutor executor, @@ -317,9 +370,9 @@ public class InternalClusterService extends AbstractLifecycleComponent void innerSubmitStateUpdateTask(final String source, final T task, - final ClusterStateTaskConfig config, - final ClusterStateTaskExecutor executor, - final SafeClusterStateTaskListener listener) { + final ClusterStateTaskConfig config, + final ClusterStateTaskExecutor executor, + final SafeClusterStateTaskListener listener) { if (!lifecycle.started()) { return; } @@ -335,7 +388,8 @@ public class InternalClusterService extends AbstractLifecycleComponent pendingTasks() { PrioritizedEsThreadPoolExecutor.Pending[] pendings = updateTasksExecutor.getPending(); List pendingClusterTasks = new ArrayList<>(pendings.length); @@ -369,24 +425,32 @@ public class InternalClusterService extends AbstractLifecycleComponentbuilder().failures(toExecute.stream().map(updateTask -> updateTask.task)::iterator, e).build(previousClusterState); + batchResult = ClusterStateTaskExecutor.BatchResult.builder() + .failures(toExecute.stream().map(updateTask -> updateTask.task)::iterator, e) + .build(previousClusterState); } assert batchResult.executionResults != null; assert batchResult.executionResults.size() == toExecute.size() - : String.format(Locale.ROOT, "expected [%d] task result%s but was [%d]", toExecute.size(), toExecute.size() == 1 ? "" : "s", batchResult.executionResults.size()); + : String.format(Locale.ROOT, "expected [%d] task result%s but was [%d]", toExecute.size(), + toExecute.size() == 1 ? "" : "s", batchResult.executionResults.size()); boolean assertsEnabled = false; assert (assertsEnabled = true); if (assertsEnabled) { @@ -469,11 +537,11 @@ public class InternalClusterService extends AbstractLifecycleComponent proccessedListeners.add(updateTask), - ex -> { - logger.debug("cluster state update task [{}] failed", ex, updateTask.source); - updateTask.listener.onFailure(updateTask.source, ex); - } + () -> proccessedListeners.add(updateTask), + ex -> { + logger.debug("cluster state update task [{}] failed", ex, updateTask.source); + updateTask.listener.onFailure(updateTask.source, ex); + } ); } @@ -497,7 +565,8 @@ public class InternalClusterService extends AbstractLifecycleComponent executor, ClusterStateTaskListener listener) { + UpdateTask(String source, T task, ClusterStateTaskConfig config, ClusterStateTaskExecutor executor, + ClusterStateTaskListener listener) { super(config.priority(), source); this.task = task; this.config = config; @@ -738,7 +811,8 @@ public class InternalClusterService extends AbstractLifecycleComponent slowTaskLoggingThreshold.getMillis()) { - logger.warn("cluster state update task [{}] took [{}] above the warn threshold of {}", source, executionTime, slowTaskLoggingThreshold); + logger.warn("cluster state update task [{}] took [{}] above the warn threshold of {}", source, executionTime, + slowTaskLoggingThreshold); } } @@ -873,7 +947,8 @@ public class InternalClusterService extends AbstractLifecycleComponent ackTimeoutCallback; private Throwable lastFailure; - AckCountDownListener(AckedClusterStateTaskListener ackedTaskListener, long clusterStateVersion, DiscoveryNodes nodes, ThreadPool threadPool) { + AckCountDownListener(AckedClusterStateTaskListener ackedTaskListener, long clusterStateVersion, DiscoveryNodes nodes, + ThreadPool threadPool) { this.ackedTaskListener = ackedTaskListener; this.clusterStateVersion = clusterStateVersion; this.nodes = nodes; diff --git a/core/src/main/java/org/elasticsearch/common/settings/AbstractScopedSettings.java b/core/src/main/java/org/elasticsearch/common/settings/AbstractScopedSettings.java index baed9c0849f..410adc82da1 100644 --- a/core/src/main/java/org/elasticsearch/common/settings/AbstractScopedSettings.java +++ b/core/src/main/java/org/elasticsearch/common/settings/AbstractScopedSettings.java @@ -19,7 +19,11 @@ package org.elasticsearch.common.settings; +import org.apache.lucene.search.spell.LevensteinDistance; +import org.apache.lucene.util.ArrayUtil; +import org.apache.lucene.util.CollectionUtil; import org.elasticsearch.ExceptionsHelper; +import org.elasticsearch.common.collect.Tuple; import org.elasticsearch.common.component.AbstractComponent; import org.elasticsearch.common.regex.Regex; @@ -30,10 +34,14 @@ import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.Set; +import java.util.SortedMap; +import java.util.SortedSet; +import java.util.TreeMap; import java.util.concurrent.CopyOnWriteArrayList; import java.util.function.BiConsumer; import java.util.function.Consumer; import java.util.regex.Pattern; +import java.util.stream.Collectors; /** * A basic setting service that can be used for per-index and per-cluster settings. @@ -58,9 +66,8 @@ public abstract class AbstractScopedSettings extends AbstractComponent { if (setting.getProperties().contains(scope) == false) { throw new IllegalArgumentException("Setting must be a " + scope + " setting but has: " + setting.getProperties()); } - if (isValidKey(setting.getKey()) == false && (setting.isGroupSetting() && isValidGroupKey(setting.getKey())) == false) { - throw new IllegalArgumentException("illegal settings key: [" + setting.getKey() + "]"); - } + validateSettingKey(setting); + if (setting.hasComplexMatcher()) { Setting overlappingSetting = findOverlappingSetting(setting, complexMatchers); if (overlappingSetting != null) { @@ -76,6 +83,12 @@ public abstract class AbstractScopedSettings extends AbstractComponent { this.keySettings = Collections.unmodifiableMap(keySettings); } + protected void validateSettingKey(Setting setting) { + if (isValidKey(setting.getKey()) == false && (setting.isGroupSetting() && isValidGroupKey(setting.getKey())) == false) { + throw new IllegalArgumentException("illegal settings key: [" + setting.getKey() + "]"); + } + } + protected AbstractScopedSettings(Settings nodeSettings, Settings scopeSettings, AbstractScopedSettings other) { super(nodeSettings); this.lastSettingsApplied = scopeSettings; @@ -216,9 +229,17 @@ public abstract class AbstractScopedSettings extends AbstractComponent { * * Validates that all given settings are registered and valid */ public final void validate(Settings settings) { - for (Map.Entry entry : settings.getAsMap().entrySet()) { - validate(entry.getKey(), settings); + List exceptions = new ArrayList<>(); + // we want them sorted for deterministic error messages + SortedMap sortedSettings = new TreeMap<>(settings.getAsMap()); + for (Map.Entry entry : sortedSettings.entrySet()) { + try { + validate(entry.getKey(), settings); + } catch (RuntimeException ex) { + exceptions.add(ex); + } } + ExceptionsHelper.rethrowAndSuppress(exceptions); } @@ -228,7 +249,21 @@ public abstract class AbstractScopedSettings extends AbstractComponent { public final void validate(String key, Settings settings) { Setting setting = get(key); if (setting == null) { - throw new IllegalArgumentException("unknown setting [" + key + "]"); + LevensteinDistance ld = new LevensteinDistance(); + List> scoredKeys = new ArrayList<>(); + for (String k : this.keySettings.keySet()) { + float distance = ld.getDistance(key, k); + if (distance > 0.7f) { + scoredKeys.add(new Tuple<>(distance, k)); + } + } + CollectionUtil.timSort(scoredKeys, (a,b) -> b.v1().compareTo(a.v1())); + String msg = "unknown setting [" + key + "]"; + List keys = scoredKeys.stream().map((a) -> a.v2()).collect(Collectors.toList()); + if (keys.isEmpty() == false) { + msg += " did you mean " + (keys.size() == 1 ? "[" + keys.get(0) + "]": "any of " + keys.toString()) + "?"; + } + throw new IllegalArgumentException(msg); } setting.get(settings); } diff --git a/core/src/main/java/org/elasticsearch/common/settings/ClusterSettings.java b/core/src/main/java/org/elasticsearch/common/settings/ClusterSettings.java index af3504cd8aa..14e79586617 100644 --- a/core/src/main/java/org/elasticsearch/common/settings/ClusterSettings.java +++ b/core/src/main/java/org/elasticsearch/common/settings/ClusterSettings.java @@ -43,7 +43,7 @@ import org.elasticsearch.cluster.routing.allocation.decider.FilterAllocationDeci import org.elasticsearch.cluster.routing.allocation.decider.ShardsLimitAllocationDecider; import org.elasticsearch.cluster.routing.allocation.decider.SnapshotInProgressAllocationDecider; import org.elasticsearch.cluster.routing.allocation.decider.ThrottlingAllocationDecider; -import org.elasticsearch.cluster.service.InternalClusterService; +import org.elasticsearch.cluster.service.ClusterService; import org.elasticsearch.common.logging.ESLoggerFactory; import org.elasticsearch.common.network.NetworkModule; import org.elasticsearch.common.network.NetworkService; @@ -255,7 +255,7 @@ public final class ClusterSettings extends AbstractScopedSettings { HierarchyCircuitBreakerService.FIELDDATA_CIRCUIT_BREAKER_OVERHEAD_SETTING, HierarchyCircuitBreakerService.REQUEST_CIRCUIT_BREAKER_LIMIT_SETTING, HierarchyCircuitBreakerService.REQUEST_CIRCUIT_BREAKER_OVERHEAD_SETTING, - InternalClusterService.CLUSTER_SERVICE_SLOW_TASK_LOGGING_THRESHOLD_SETTING, + ClusterService.CLUSTER_SERVICE_SLOW_TASK_LOGGING_THRESHOLD_SETTING, SearchService.DEFAULT_SEARCH_TIMEOUT_SETTING, ElectMasterService.DISCOVERY_ZEN_MINIMUM_MASTER_NODES_SETTING, TransportService.TRACE_LOG_EXCLUDE_SETTING, diff --git a/core/src/main/java/org/elasticsearch/common/settings/IndexScopedSettings.java b/core/src/main/java/org/elasticsearch/common/settings/IndexScopedSettings.java index da6c34bdf4a..322ac4de799 100644 --- a/core/src/main/java/org/elasticsearch/common/settings/IndexScopedSettings.java +++ b/core/src/main/java/org/elasticsearch/common/settings/IndexScopedSettings.java @@ -35,7 +35,7 @@ import org.elasticsearch.index.engine.EngineConfig; import org.elasticsearch.index.fielddata.IndexFieldDataService; import org.elasticsearch.index.mapper.FieldMapper; import org.elasticsearch.index.mapper.MapperService; -import org.elasticsearch.index.percolator.PercolatorQueriesRegistry; +import org.elasticsearch.index.percolator.PercolatorQueryCache; import org.elasticsearch.index.similarity.SimilarityService; import org.elasticsearch.index.store.FsDirectoryService; import org.elasticsearch.index.store.IndexStore; @@ -125,7 +125,7 @@ public final class IndexScopedSettings extends AbstractScopedSettings { FieldMapper.IGNORE_MALFORMED_SETTING, FieldMapper.COERCE_SETTING, Store.INDEX_STORE_STATS_REFRESH_INTERVAL_SETTING, - PercolatorQueriesRegistry.INDEX_MAP_UNMAPPED_FIELDS_AS_STRING_SETTING, + PercolatorQueryCache.INDEX_MAP_UNMAPPED_FIELDS_AS_STRING_SETTING, MapperService.INDEX_MAPPER_DYNAMIC_SETTING, MapperService.INDEX_MAPPING_NESTED_FIELDS_LIMIT_SETTING, BitsetFilterCache.INDEX_LOAD_RANDOM_ACCESS_FILTERS_EAGERLY_SETTING, @@ -163,6 +163,14 @@ public final class IndexScopedSettings extends AbstractScopedSettings { return new IndexScopedSettings(settings, this, metaData); } + @Override + protected void validateSettingKey(Setting setting) { + if (setting.getKey().startsWith("index.") == false) { + throw new IllegalArgumentException("illegal settings key: [" + setting.getKey() + "] must start with [index.]"); + } + super.validateSettingKey(setting); + } + public boolean isPrivateSetting(String key) { switch (key) { case IndexMetaData.SETTING_CREATION_DATE: diff --git a/core/src/main/java/org/elasticsearch/common/settings/Settings.java b/core/src/main/java/org/elasticsearch/common/settings/Settings.java index e06e4ad893b..a6784e561d2 100644 --- a/core/src/main/java/org/elasticsearch/common/settings/Settings.java +++ b/core/src/main/java/org/elasticsearch/common/settings/Settings.java @@ -761,6 +761,14 @@ public final class Settings implements ToXContent { return builder; } + /** + * Returns true if this settings object contains no settings + * @return true if this settings object contains no settings + */ + public boolean isEmpty() { + return this.settings.isEmpty(); + } + /** * A builder allowing to put different settings and then {@link #build()} an immutable * settings implementation. Use {@link Settings#settingsBuilder()} in order to diff --git a/core/src/main/java/org/elasticsearch/common/settings/SettingsModule.java b/core/src/main/java/org/elasticsearch/common/settings/SettingsModule.java index 9fc2ee257a0..2e7acd6ae8c 100644 --- a/core/src/main/java/org/elasticsearch/common/settings/SettingsModule.java +++ b/core/src/main/java/org/elasticsearch/common/settings/SettingsModule.java @@ -20,13 +20,22 @@ package org.elasticsearch.common.settings; import org.elasticsearch.common.inject.AbstractModule; +import org.elasticsearch.common.logging.ESLogger; +import org.elasticsearch.common.logging.Loggers; +import org.elasticsearch.common.xcontent.ToXContent; +import org.elasticsearch.common.xcontent.XContentBuilder; +import org.elasticsearch.common.xcontent.XContentType; import org.elasticsearch.tribe.TribeService; +import java.io.IOException; +import java.util.Collections; import java.util.HashMap; import java.util.HashSet; import java.util.Map; import java.util.Set; import java.util.function.Predicate; +import java.util.stream.Collectors; +import java.util.stream.IntStream; /** * A module that binds the provided settings to the {@link Settings} interface. @@ -37,9 +46,12 @@ public class SettingsModule extends AbstractModule { private final Set settingsFilterPattern = new HashSet<>(); private final Map> nodeSettings = new HashMap<>(); private final Map> indexSettings = new HashMap<>(); - private static final Predicate TRIBE_CLIENT_NODE_SETTINGS_PREDICATE = (s) -> s.startsWith("tribe.") && TribeService.TRIBE_SETTING_KEYS.contains(s) == false; + private static final Predicate TRIBE_CLIENT_NODE_SETTINGS_PREDICATE = (s) -> s.startsWith("tribe.") + && TribeService.TRIBE_SETTING_KEYS.contains(s) == false; + private final ESLogger logger; public SettingsModule(Settings settings) { + logger = Loggers.getLogger(getClass(), settings); this.settings = settings; for (Setting setting : ClusterSettings.BUILT_IN_CLUSTER_SETTINGS) { registerSetting(setting); @@ -53,9 +65,58 @@ public class SettingsModule extends AbstractModule { protected void configure() { final IndexScopedSettings indexScopedSettings = new IndexScopedSettings(settings, new HashSet<>(this.indexSettings.values())); final ClusterSettings clusterSettings = new ClusterSettings(settings, new HashSet<>(this.nodeSettings.values())); + Settings indexSettings = settings.filter((s) -> s.startsWith("index.") && clusterSettings.get(s) == null); + if (indexSettings.isEmpty() == false) { + try { + String separator = IntStream.range(0, 85).mapToObj(s -> "*").collect(Collectors.joining("")).trim(); + StringBuilder builder = new StringBuilder(); + builder.append(System.lineSeparator()); + builder.append(separator); + builder.append(System.lineSeparator()); + builder.append("Found index level settings on node level configuration."); + builder.append(System.lineSeparator()); + builder.append(System.lineSeparator()); + int count = 0; + for (String word : ("Since elasticsearch 5.x index level settings can NOT be set on the nodes configuration like " + + "the elasticsearch.yaml, in system properties or command line arguments." + + "In order to upgrade all indices the settings must be updated via the /${index}/_settings API. " + + "Unless all settings are dynamic all indices must be closed in order to apply the upgrade" + + "Indices created in the future should use index templates to set default values." + ).split(" ")) { + if (count + word.length() > 85) { + builder.append(System.lineSeparator()); + count = 0; + } + count += word.length() + 1; + builder.append(word).append(" "); + } + + builder.append(System.lineSeparator()); + builder.append(System.lineSeparator()); + builder.append("Please ensure all required values are updated on all indices by executing: "); + builder.append(System.lineSeparator()); + builder.append(System.lineSeparator()); + builder.append("curl -XPUT 'http://localhost:9200/_all/_settings?preserve_existing=true' -d '"); + try (XContentBuilder xContentBuilder = XContentBuilder.builder(XContentType.JSON.xContent())) { + xContentBuilder.prettyPrint(); + xContentBuilder.startObject(); + indexSettings.toXContent(xContentBuilder, new ToXContent.MapParams(Collections.singletonMap("flat_settings", "true"))); + xContentBuilder.endObject(); + builder.append(xContentBuilder.string()); + } + builder.append("'"); + builder.append(System.lineSeparator()); + builder.append(separator); + builder.append(System.lineSeparator()); + + logger.warn(builder.toString()); + throw new IllegalArgumentException("node settings must not contain any index level settings"); + } catch (IOException e) { + throw new RuntimeException(e); + } + } // by now we are fully configured, lets check node level settings for unregistered index settings - indexScopedSettings.validate(settings.filter(IndexScopedSettings.INDEX_SETTINGS_KEY_PREDICATE)); - final Predicate acceptOnlyClusterSettings = TRIBE_CLIENT_NODE_SETTINGS_PREDICATE.or(IndexScopedSettings.INDEX_SETTINGS_KEY_PREDICATE).negate(); + final Predicate acceptOnlyClusterSettings = TRIBE_CLIENT_NODE_SETTINGS_PREDICATE.negate(); clusterSettings.validate(settings.filter(acceptOnlyClusterSettings)); validateTribeSettings(settings, clusterSettings); bind(Settings.class).toInstance(settings); @@ -76,21 +137,19 @@ public class SettingsModule extends AbstractModule { registerSettingsFilter(setting.getKey()); } } - - // We validate scope settings. We should have one and only one scope. - if (setting.hasNodeScope() && setting.hasIndexScope()) { - throw new IllegalArgumentException("More than one scope has been added to the setting [" + setting.getKey() + "]"); - } - if (setting.hasNodeScope()) { - if (nodeSettings.containsKey(setting.getKey())) { - throw new IllegalArgumentException("Cannot register setting [" + setting.getKey() + "] twice"); + if (setting.hasNodeScope() || setting.hasIndexScope()) { + if (setting.hasNodeScope()) { + if (nodeSettings.containsKey(setting.getKey())) { + throw new IllegalArgumentException("Cannot register setting [" + setting.getKey() + "] twice"); + } + nodeSettings.put(setting.getKey(), setting); } - nodeSettings.put(setting.getKey(), setting); - } else if (setting.hasIndexScope()) { - if (indexSettings.containsKey(setting.getKey())) { - throw new IllegalArgumentException("Cannot register setting [" + setting.getKey() + "] twice"); + if (setting.hasIndexScope()) { + if (indexSettings.containsKey(setting.getKey())) { + throw new IllegalArgumentException("Cannot register setting [" + setting.getKey() + "] twice"); + } + indexSettings.put(setting.getKey(), setting); } - indexSettings.put(setting.getKey(), setting); } else { throw new IllegalArgumentException("No scope found for setting [" + setting.getKey() + "]"); } diff --git a/core/src/main/java/org/elasticsearch/common/util/IndexFolderUpgrader.java b/core/src/main/java/org/elasticsearch/common/util/IndexFolderUpgrader.java index 54dac7447eb..3640d3e4bec 100644 --- a/core/src/main/java/org/elasticsearch/common/util/IndexFolderUpgrader.java +++ b/core/src/main/java/org/elasticsearch/common/util/IndexFolderUpgrader.java @@ -47,7 +47,6 @@ public class IndexFolderUpgrader { private final NodeEnvironment nodeEnv; private final Settings settings; private final ESLogger logger = Loggers.getLogger(IndexFolderUpgrader.class); - private final MetaDataStateFormat indexStateFormat = readOnlyIndexMetaDataStateFormat(); /** * Creates a new upgrader instance @@ -90,7 +89,7 @@ public class IndexFolderUpgrader { void upgrade(final String indexFolderName) throws IOException { for (NodeEnvironment.NodePath nodePath : nodeEnv.nodePaths()) { final Path indexFolderPath = nodePath.indicesPath.resolve(indexFolderName); - final IndexMetaData indexMetaData = indexStateFormat.loadLatestState(logger, indexFolderPath); + final IndexMetaData indexMetaData = IndexMetaData.FORMAT.loadLatestState(logger, indexFolderPath); if (indexMetaData != null) { final Index index = indexMetaData.getIndex(); if (needsUpgrade(index, indexFolderName)) { @@ -135,20 +134,4 @@ public class IndexFolderUpgrader { static boolean needsUpgrade(Index index, String indexFolderName) { return indexFolderName.equals(index.getUUID()) == false; } - - static MetaDataStateFormat readOnlyIndexMetaDataStateFormat() { - // NOTE: XContentType param is not used as we use the format read from the serialized index state - return new MetaDataStateFormat(XContentType.SMILE, MetaStateService.INDEX_STATE_FILE_PREFIX) { - - @Override - public void toXContent(XContentBuilder builder, IndexMetaData state) throws IOException { - throw new UnsupportedOperationException(); - } - - @Override - public IndexMetaData fromXContent(XContentParser parser) throws IOException { - return IndexMetaData.Builder.fromXContent(parser); - } - }; - } } diff --git a/core/src/main/java/org/elasticsearch/common/util/concurrent/EsThreadPoolExecutor.java b/core/src/main/java/org/elasticsearch/common/util/concurrent/EsThreadPoolExecutor.java index fde8d828295..2f664679bb4 100644 --- a/core/src/main/java/org/elasticsearch/common/util/concurrent/EsThreadPoolExecutor.java +++ b/core/src/main/java/org/elasticsearch/common/util/concurrent/EsThreadPoolExecutor.java @@ -40,11 +40,14 @@ public class EsThreadPoolExecutor extends ThreadPoolExecutor { */ private final String name; - EsThreadPoolExecutor(String name, int corePoolSize, int maximumPoolSize, long keepAliveTime, TimeUnit unit, BlockingQueue workQueue, ThreadFactory threadFactory, ThreadContext contextHolder) { + EsThreadPoolExecutor(String name, int corePoolSize, int maximumPoolSize, long keepAliveTime, TimeUnit unit, + BlockingQueue workQueue, ThreadFactory threadFactory, ThreadContext contextHolder) { this(name, corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue, threadFactory, new EsAbortPolicy(), contextHolder); } - EsThreadPoolExecutor(String name, int corePoolSize, int maximumPoolSize, long keepAliveTime, TimeUnit unit, BlockingQueue workQueue, ThreadFactory threadFactory, XRejectedExecutionHandler handler, ThreadContext contextHolder) { + EsThreadPoolExecutor(String name, int corePoolSize, int maximumPoolSize, long keepAliveTime, TimeUnit unit, + BlockingQueue workQueue, ThreadFactory threadFactory, XRejectedExecutionHandler handler, + ThreadContext contextHolder) { super(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue, threadFactory, handler); this.name = name; this.contextHolder = contextHolder; @@ -133,112 +136,10 @@ public class EsThreadPoolExecutor extends ThreadPoolExecutor { } protected Runnable wrapRunnable(Runnable command) { - final Runnable wrappedCommand; - if (command instanceof AbstractRunnable) { - wrappedCommand = new FilterAbstractRunnable(contextHolder, (AbstractRunnable) command); - } else { - wrappedCommand = new FilterRunnable(contextHolder, command); - } - return wrappedCommand; + return contextHolder.preserveContext(command); } protected Runnable unwrap(Runnable runnable) { - if (runnable instanceof FilterAbstractRunnable) { - return ((FilterAbstractRunnable) runnable).in; - } else if (runnable instanceof FilterRunnable) { - return ((FilterRunnable) runnable).in; - } - return runnable; + return contextHolder.unwrap(runnable); } - - private class FilterAbstractRunnable extends AbstractRunnable { - private final ThreadContext contextHolder; - private final AbstractRunnable in; - private final ThreadContext.StoredContext ctx; - - FilterAbstractRunnable(ThreadContext contextHolder, AbstractRunnable in) { - this.contextHolder = contextHolder; - ctx = contextHolder.newStoredContext(); - this.in = in; - } - - @Override - public boolean isForceExecution() { - return in.isForceExecution(); - } - - @Override - public void onAfter() { - in.onAfter(); - } - - @Override - public void onFailure(Throwable t) { - in.onFailure(t); - } - - @Override - public void onRejection(Throwable t) { - in.onRejection(t); - } - - @Override - protected void doRun() throws Exception { - boolean whileRunning = false; - try (ThreadContext.StoredContext ingore = contextHolder.stashContext()){ - ctx.restore(); - whileRunning = true; - in.doRun(); - whileRunning = false; - } catch (IllegalStateException ex) { - if (whileRunning || isShutdown() == false) { - throw ex; - } - // if we hit an ISE here we have been shutting down - // this comes from the threadcontext and barfs if - // our threadpool has been shutting down - } - } - - @Override - public String toString() { - return in.toString(); - } - - } - - private class FilterRunnable implements Runnable { - private final ThreadContext contextHolder; - private final Runnable in; - private final ThreadContext.StoredContext ctx; - - FilterRunnable(ThreadContext contextHolder, Runnable in) { - this.contextHolder = contextHolder; - ctx = contextHolder.newStoredContext(); - this.in = in; - } - - @Override - public void run() { - boolean whileRunning = false; - try (ThreadContext.StoredContext ingore = contextHolder.stashContext()){ - ctx.restore(); - whileRunning = true; - in.run(); - whileRunning = false; - } catch (IllegalStateException ex) { - if (whileRunning || isShutdown() == false) { - throw ex; - } - // if we hit an ISE here we have been shutting down - // this comes from the threadcontext and barfs if - // our threadpool has been shutting down - } - } - @Override - public String toString() { - return in.toString(); - } - } - } diff --git a/core/src/main/java/org/elasticsearch/common/util/concurrent/ThreadContext.java b/core/src/main/java/org/elasticsearch/common/util/concurrent/ThreadContext.java index 2ac6082e85d..462b4f539dc 100644 --- a/core/src/main/java/org/elasticsearch/common/util/concurrent/ThreadContext.java +++ b/core/src/main/java/org/elasticsearch/common/util/concurrent/ThreadContext.java @@ -200,6 +200,36 @@ public final class ThreadContext implements Closeable, Writeablecommand has already been passed through this method then it is returned unaltered rather than wrapped twice. + */ + public Runnable preserveContext(Runnable command) { + if (command instanceof ContextPreservingAbstractRunnable) { + return command; + } + if (command instanceof ContextPreservingRunnable) { + return command; + } + if (command instanceof AbstractRunnable) { + return new ContextPreservingAbstractRunnable((AbstractRunnable) command); + } + return new ContextPreservingRunnable(command); + } + + /** + * Unwraps a command that was previously wrapped by {@link #preserveContext(Runnable)}. + */ + public Runnable unwrap(Runnable command) { + if (command instanceof ContextPreservingAbstractRunnable) { + return ((ContextPreservingAbstractRunnable) command).unwrap(); + } + if (command instanceof ContextPreservingRunnable) { + return ((ContextPreservingRunnable) command).unwrap(); + } + return command; + } + public interface StoredContext extends AutoCloseable { @Override void close(); @@ -356,4 +386,104 @@ public final class ThreadContext implements Closeable, Writeable readList(XContentParser parser, MapFactory mapFactory) throws IOException { XContentParser.Token token = parser.currentToken(); + if (token == null) { + token = parser.nextToken(); + } if (token == XContentParser.Token.FIELD_NAME) { token = parser.nextToken(); } if (token == XContentParser.Token.START_ARRAY) { token = parser.nextToken(); + } else { + throw new ElasticsearchParseException("Failed to parse list: expecting " + + XContentParser.Token.START_ARRAY + " but got " + token); } + ArrayList list = new ArrayList<>(); - for (; token != XContentParser.Token.END_ARRAY; token = parser.nextToken()) { + for (; token != null && token != XContentParser.Token.END_ARRAY; token = parser.nextToken()) { list.add(readValue(parser, mapFactory, token)); } return list; diff --git a/core/src/main/java/org/elasticsearch/discovery/local/LocalDiscovery.java b/core/src/main/java/org/elasticsearch/discovery/local/LocalDiscovery.java index 0462d6a8d8d..cf697871d35 100644 --- a/core/src/main/java/org/elasticsearch/discovery/local/LocalDiscovery.java +++ b/core/src/main/java/org/elasticsearch/discovery/local/LocalDiscovery.java @@ -21,7 +21,6 @@ package org.elasticsearch.discovery.local; import org.elasticsearch.cluster.ClusterChangedEvent; import org.elasticsearch.cluster.ClusterName; -import org.elasticsearch.cluster.ClusterService; import org.elasticsearch.cluster.ClusterState; import org.elasticsearch.cluster.ClusterStateUpdateTask; import org.elasticsearch.cluster.Diff; @@ -31,6 +30,7 @@ import org.elasticsearch.cluster.node.DiscoveryNode; import org.elasticsearch.cluster.node.DiscoveryNodes; import org.elasticsearch.cluster.routing.RoutingService; import org.elasticsearch.cluster.routing.allocation.RoutingAllocation; +import org.elasticsearch.cluster.service.ClusterService; import org.elasticsearch.common.component.AbstractLifecycleComponent; import org.elasticsearch.common.inject.Inject; import org.elasticsearch.common.io.stream.BytesStreamOutput; diff --git a/core/src/main/java/org/elasticsearch/discovery/zen/NodeJoinController.java b/core/src/main/java/org/elasticsearch/discovery/zen/NodeJoinController.java index 19a2cf06bf4..0edbf8841ad 100644 --- a/core/src/main/java/org/elasticsearch/discovery/zen/NodeJoinController.java +++ b/core/src/main/java/org/elasticsearch/discovery/zen/NodeJoinController.java @@ -19,7 +19,6 @@ package org.elasticsearch.discovery.zen; import org.elasticsearch.ElasticsearchTimeoutException; -import org.elasticsearch.cluster.ClusterService; import org.elasticsearch.cluster.ClusterState; import org.elasticsearch.cluster.ClusterStateUpdateTask; import org.elasticsearch.cluster.NotMasterException; @@ -28,7 +27,7 @@ import org.elasticsearch.cluster.node.DiscoveryNode; import org.elasticsearch.cluster.node.DiscoveryNodes; import org.elasticsearch.cluster.routing.RoutingService; import org.elasticsearch.cluster.routing.allocation.RoutingAllocation; -import org.elasticsearch.cluster.service.InternalClusterService; +import org.elasticsearch.cluster.service.ClusterService; import org.elasticsearch.common.Priority; import org.elasticsearch.common.component.AbstractComponent; import org.elasticsearch.common.settings.Settings; @@ -346,7 +345,7 @@ public class NodeJoinController extends AbstractComponent { } private void assertClusterStateThread() { - assert clusterService instanceof InternalClusterService == false || ((InternalClusterService) clusterService).assertClusterStateThread(); + assert clusterService instanceof ClusterService == false || ((ClusterService) clusterService).assertClusterStateThread(); } } diff --git a/core/src/main/java/org/elasticsearch/discovery/zen/ZenDiscovery.java b/core/src/main/java/org/elasticsearch/discovery/zen/ZenDiscovery.java index a19f4fa4af1..07cd3853cb6 100644 --- a/core/src/main/java/org/elasticsearch/discovery/zen/ZenDiscovery.java +++ b/core/src/main/java/org/elasticsearch/discovery/zen/ZenDiscovery.java @@ -24,7 +24,6 @@ import org.elasticsearch.ExceptionsHelper; import org.elasticsearch.Version; import org.elasticsearch.cluster.ClusterChangedEvent; import org.elasticsearch.cluster.ClusterName; -import org.elasticsearch.cluster.ClusterService; import org.elasticsearch.cluster.ClusterState; import org.elasticsearch.cluster.ClusterStateUpdateTask; import org.elasticsearch.cluster.NotMasterException; @@ -35,7 +34,7 @@ import org.elasticsearch.cluster.node.DiscoveryNode; import org.elasticsearch.cluster.node.DiscoveryNodes; import org.elasticsearch.cluster.routing.RoutingService; import org.elasticsearch.cluster.routing.allocation.RoutingAllocation; -import org.elasticsearch.cluster.service.InternalClusterService; +import org.elasticsearch.cluster.service.ClusterService; import org.elasticsearch.common.Priority; import org.elasticsearch.common.component.AbstractLifecycleComponent; import org.elasticsearch.common.component.Lifecycle; @@ -929,7 +928,7 @@ public class ZenDiscovery extends AbstractLifecycleComponent implemen protected ClusterState rejoin(ClusterState clusterState, String reason) { // *** called from within an cluster state update task *** // - assert Thread.currentThread().getName().contains(InternalClusterService.UPDATE_THREAD_NAME); + assert Thread.currentThread().getName().contains(ClusterService.UPDATE_THREAD_NAME); logger.warn("{}, current nodes: {}", reason, clusterState.nodes()); nodesFD.stop(); @@ -959,7 +958,7 @@ public class ZenDiscovery extends AbstractLifecycleComponent implemen private ClusterState handleAnotherMaster(ClusterState localClusterState, final DiscoveryNode otherMaster, long otherClusterStateVersion, String reason) { assert localClusterState.nodes().localNodeMaster() : "handleAnotherMaster called but current node is not a master"; - assert Thread.currentThread().getName().contains(InternalClusterService.UPDATE_THREAD_NAME) : "not called from the cluster state update thread"; + assert Thread.currentThread().getName().contains(ClusterService.UPDATE_THREAD_NAME) : "not called from the cluster state update thread"; if (otherClusterStateVersion > localClusterState.version()) { return rejoin(localClusterState, "zen-disco-discovered another master with a new cluster_state [" + otherMaster + "][" + reason + "]"); @@ -1197,7 +1196,7 @@ public class ZenDiscovery extends AbstractLifecycleComponent implemen } private void assertClusterStateThread() { - assert clusterService instanceof InternalClusterService == false || ((InternalClusterService) clusterService).assertClusterStateThread(); + assert clusterService instanceof ClusterService == false || ((ClusterService) clusterService).assertClusterStateThread(); } } diff --git a/core/src/main/java/org/elasticsearch/discovery/zen/fd/MasterFaultDetection.java b/core/src/main/java/org/elasticsearch/discovery/zen/fd/MasterFaultDetection.java index 73be1d3bb28..96ed7f76419 100644 --- a/core/src/main/java/org/elasticsearch/discovery/zen/fd/MasterFaultDetection.java +++ b/core/src/main/java/org/elasticsearch/discovery/zen/fd/MasterFaultDetection.java @@ -21,12 +21,12 @@ package org.elasticsearch.discovery.zen.fd; import org.elasticsearch.ElasticsearchException; import org.elasticsearch.cluster.ClusterName; -import org.elasticsearch.cluster.ClusterService; import org.elasticsearch.cluster.ClusterState; import org.elasticsearch.cluster.ClusterStateUpdateTask; import org.elasticsearch.cluster.NotMasterException; import org.elasticsearch.cluster.node.DiscoveryNode; import org.elasticsearch.cluster.node.DiscoveryNodes; +import org.elasticsearch.cluster.service.ClusterService; import org.elasticsearch.common.Nullable; import org.elasticsearch.common.io.stream.StreamInput; import org.elasticsearch.common.io.stream.StreamOutput; diff --git a/core/src/main/java/org/elasticsearch/discovery/zen/membership/MembershipAction.java b/core/src/main/java/org/elasticsearch/discovery/zen/membership/MembershipAction.java index 04af8207c37..de4caf664ea 100644 --- a/core/src/main/java/org/elasticsearch/discovery/zen/membership/MembershipAction.java +++ b/core/src/main/java/org/elasticsearch/discovery/zen/membership/MembershipAction.java @@ -19,9 +19,9 @@ package org.elasticsearch.discovery.zen.membership; -import org.elasticsearch.cluster.ClusterService; import org.elasticsearch.cluster.ClusterState; import org.elasticsearch.cluster.node.DiscoveryNode; +import org.elasticsearch.cluster.service.ClusterService; import org.elasticsearch.common.component.AbstractComponent; import org.elasticsearch.common.io.stream.StreamInput; import org.elasticsearch.common.io.stream.StreamOutput; diff --git a/core/src/main/java/org/elasticsearch/gateway/Gateway.java b/core/src/main/java/org/elasticsearch/gateway/Gateway.java index 2d1d48cbd83..c879e6ab710 100644 --- a/core/src/main/java/org/elasticsearch/gateway/Gateway.java +++ b/core/src/main/java/org/elasticsearch/gateway/Gateway.java @@ -19,24 +19,23 @@ package org.elasticsearch.gateway; -import com.carrotsearch.hppc.ObjectFloatHashMap; -import com.carrotsearch.hppc.ObjectHashSet; -import com.carrotsearch.hppc.cursors.ObjectCursor; import org.apache.lucene.util.IOUtils; import org.elasticsearch.action.FailedNodeException; import org.elasticsearch.cluster.ClusterChangedEvent; -import org.elasticsearch.cluster.ClusterService; import org.elasticsearch.cluster.ClusterState; import org.elasticsearch.cluster.ClusterStateListener; import org.elasticsearch.cluster.metadata.IndexMetaData; import org.elasticsearch.cluster.metadata.MetaData; +import org.elasticsearch.cluster.service.ClusterService; import org.elasticsearch.common.component.AbstractComponent; import org.elasticsearch.common.settings.Settings; import org.elasticsearch.discovery.Discovery; import org.elasticsearch.env.NodeEnvironment; -import org.elasticsearch.index.Index; +import org.elasticsearch.index.NodeServicesProvider; +import org.elasticsearch.indices.IndicesService; import java.nio.file.Path; +import java.util.Arrays; import java.util.function.Supplier; /** @@ -53,10 +52,15 @@ public class Gateway extends AbstractComponent implements ClusterStateListener { private final TransportNodesListGatewayMetaState listGatewayMetaState; private final Supplier minimumMasterNodesProvider; + private final IndicesService indicesService; + private final NodeServicesProvider nodeServicesProvider; public Gateway(Settings settings, ClusterService clusterService, NodeEnvironment nodeEnv, GatewayMetaState metaState, - TransportNodesListGatewayMetaState listGatewayMetaState, Discovery discovery) { + TransportNodesListGatewayMetaState listGatewayMetaState, Discovery discovery, + NodeServicesProvider nodeServicesProvider, IndicesService indicesService) { super(settings); + this.nodeServicesProvider = nodeServicesProvider; + this.indicesService = indicesService; this.clusterService = clusterService; this.nodeEnv = nodeEnv; this.metaState = metaState; @@ -66,9 +70,9 @@ public class Gateway extends AbstractComponent implements ClusterStateListener { } public void performStateRecovery(final GatewayStateRecoveredListener listener) throws GatewayException { - ObjectHashSet nodesIds = new ObjectHashSet<>(clusterService.state().nodes().masterNodes().keys()); - logger.trace("performing state recovery from {}", nodesIds); - TransportNodesListGatewayMetaState.NodesGatewayMetaState nodesState = listGatewayMetaState.list(nodesIds.toArray(String.class), null).actionGet(); + String[] nodesIds = clusterService.state().nodes().masterNodes().keys().toArray(String.class); + logger.trace("performing state recovery from {}", Arrays.toString(nodesIds)); + TransportNodesListGatewayMetaState.NodesGatewayMetaState nodesState = listGatewayMetaState.list(nodesIds, null).actionGet(); int requiredAllocation = Math.max(1, minimumMasterNodesProvider.get()); @@ -80,7 +84,6 @@ public class Gateway extends AbstractComponent implements ClusterStateListener { } } - ObjectFloatHashMap indices = new ObjectFloatHashMap<>(); MetaData electedGlobalState = null; int found = 0; for (TransportNodesListGatewayMetaState.NodeGatewayMetaState nodeState : nodesState) { @@ -93,55 +96,34 @@ public class Gateway extends AbstractComponent implements ClusterStateListener { } else if (nodeState.metaData().version() > electedGlobalState.version()) { electedGlobalState = nodeState.metaData(); } - for (ObjectCursor cursor : nodeState.metaData().indices().values()) { - indices.addTo(cursor.value.getIndex(), 1); - } } if (found < requiredAllocation) { listener.onFailure("found [" + found + "] metadata states, required [" + requiredAllocation + "]"); return; } - // update the global state, and clean the indices, we elect them in the next phase - MetaData.Builder metaDataBuilder = MetaData.builder(electedGlobalState).removeAllIndices(); - - assert !indices.containsKey(null); - final Object[] keys = indices.keys; - for (int i = 0; i < keys.length; i++) { - if (keys[i] != null) { - Index index = (Index) keys[i]; - IndexMetaData electedIndexMetaData = null; - int indexMetaDataCount = 0; - for (TransportNodesListGatewayMetaState.NodeGatewayMetaState nodeState : nodesState) { - if (nodeState.metaData() == null) { - continue; - } - IndexMetaData indexMetaData = nodeState.metaData().index(index); - if (indexMetaData == null) { - continue; - } - if (electedIndexMetaData == null) { - electedIndexMetaData = indexMetaData; - } else if (indexMetaData.getVersion() > electedIndexMetaData.getVersion()) { - electedIndexMetaData = indexMetaData; - } - indexMetaDataCount++; - } - if (electedIndexMetaData != null) { - if (indexMetaDataCount < requiredAllocation) { - logger.debug("[{}] found [{}], required [{}], not adding", index, indexMetaDataCount, requiredAllocation); - } - metaDataBuilder.put(electedIndexMetaData, false); + // verify index metadata + MetaData.Builder metaDataBuilder = MetaData.builder(electedGlobalState); + for (IndexMetaData indexMetaData : electedGlobalState) { + try { + if (indexMetaData.getState() == IndexMetaData.State.OPEN) { + // verify that we can actually create this index - if not we recover it as closed with lots of warn logs + indicesService.verifyIndexMetadata(nodeServicesProvider, indexMetaData); } + } catch (Exception e) { + logger.warn("recovering index {} failed - recovering as closed", e, indexMetaData.getIndex()); + indexMetaData = IndexMetaData.builder(indexMetaData).state(IndexMetaData.State.CLOSE).build(); + metaDataBuilder.put(indexMetaData, true); } } ClusterState.Builder builder = ClusterState.builder(clusterService.state().getClusterName()); builder.metaData(metaDataBuilder); listener.onSuccess(builder.build()); } + public void reset() throws Exception { try { Path[] dataPaths = nodeEnv.nodeDataPaths(); - logger.trace("removing node data paths: [{}]", (Object)dataPaths); + logger.trace("removing node data paths: [{}]", (Object) dataPaths); IOUtils.rm(dataPaths); } catch (Exception ex) { logger.debug("failed to delete shard locations", ex); diff --git a/core/src/main/java/org/elasticsearch/gateway/GatewayAllocator.java b/core/src/main/java/org/elasticsearch/gateway/GatewayAllocator.java index acd650bc6f7..0059a0ef61b 100644 --- a/core/src/main/java/org/elasticsearch/gateway/GatewayAllocator.java +++ b/core/src/main/java/org/elasticsearch/gateway/GatewayAllocator.java @@ -22,7 +22,6 @@ package org.elasticsearch.gateway; import org.elasticsearch.action.support.nodes.BaseNodeResponse; import org.elasticsearch.action.support.nodes.BaseNodesResponse; import org.elasticsearch.cluster.ClusterChangedEvent; -import org.elasticsearch.cluster.ClusterService; import org.elasticsearch.cluster.ClusterStateListener; import org.elasticsearch.cluster.node.DiscoveryNode; import org.elasticsearch.cluster.routing.RoutingNodes; @@ -31,6 +30,7 @@ import org.elasticsearch.cluster.routing.ShardRouting; import org.elasticsearch.cluster.routing.allocation.FailedRerouteAllocation; import org.elasticsearch.cluster.routing.allocation.RoutingAllocation; import org.elasticsearch.cluster.routing.allocation.StartedRerouteAllocation; +import org.elasticsearch.cluster.service.ClusterService; import org.elasticsearch.common.component.AbstractComponent; import org.elasticsearch.common.inject.Inject; import org.elasticsearch.common.lease.Releasables; diff --git a/core/src/main/java/org/elasticsearch/gateway/GatewayMetaState.java b/core/src/main/java/org/elasticsearch/gateway/GatewayMetaState.java index 950b4351e1d..1da82468997 100644 --- a/core/src/main/java/org/elasticsearch/gateway/GatewayMetaState.java +++ b/core/src/main/java/org/elasticsearch/gateway/GatewayMetaState.java @@ -86,8 +86,8 @@ public class GatewayMetaState extends AbstractComponent implements ClusterStateL if (DiscoveryNode.masterNode(settings) || DiscoveryNode.dataNode(settings)) { try { ensureNoPre019State(); - pre20Upgrade(); IndexFolderUpgrader.upgradeIndicesIfNeeded(settings, nodeEnv); + upgradeMetaData(); long startNS = System.nanoTime(); metaStateService.loadFullState(); logger.debug("took {} to load state", TimeValue.timeValueMillis(TimeValue.nsecToMSec(System.nanoTime() - startNS))); @@ -222,7 +222,7 @@ public class GatewayMetaState extends AbstractComponent implements ClusterStateL * MetaDataIndexUpgradeService might also update obsolete settings if needed. When this happens we rewrite * index metadata with new settings. */ - private void pre20Upgrade() throws Exception { + private void upgradeMetaData() throws Exception { MetaData metaData = loadMetaState(); List updateIndexMetaData = new ArrayList<>(); for (IndexMetaData indexMetaData : metaData) { @@ -235,7 +235,7 @@ public class GatewayMetaState extends AbstractComponent implements ClusterStateL // means the upgrade can continue. Now it's safe to overwrite index metadata with the new version. for (IndexMetaData indexMetaData : updateIndexMetaData) { // since we still haven't upgraded the index folders, we write index state in the old folder - metaStateService.writeIndex("upgrade", indexMetaData, nodeEnv.resolveIndexFolder(indexMetaData.getIndex().getName())); + metaStateService.writeIndex("upgrade", indexMetaData, nodeEnv.resolveIndexFolder(indexMetaData.getIndex().getUUID())); } } diff --git a/core/src/main/java/org/elasticsearch/gateway/GatewayService.java b/core/src/main/java/org/elasticsearch/gateway/GatewayService.java index 6d85fb2f41d..7dcc45f1c0a 100644 --- a/core/src/main/java/org/elasticsearch/gateway/GatewayService.java +++ b/core/src/main/java/org/elasticsearch/gateway/GatewayService.java @@ -21,7 +21,6 @@ package org.elasticsearch.gateway; import com.carrotsearch.hppc.cursors.ObjectCursor; import org.elasticsearch.cluster.ClusterChangedEvent; -import org.elasticsearch.cluster.ClusterService; import org.elasticsearch.cluster.ClusterState; import org.elasticsearch.cluster.ClusterStateListener; import org.elasticsearch.cluster.ClusterStateUpdateTask; @@ -34,6 +33,7 @@ import org.elasticsearch.cluster.node.DiscoveryNodes; import org.elasticsearch.cluster.routing.RoutingTable; import org.elasticsearch.cluster.routing.allocation.AllocationService; import org.elasticsearch.cluster.routing.allocation.RoutingAllocation; +import org.elasticsearch.cluster.service.ClusterService; import org.elasticsearch.common.component.AbstractLifecycleComponent; import org.elasticsearch.common.inject.Inject; import org.elasticsearch.common.settings.Setting; @@ -43,6 +43,8 @@ import org.elasticsearch.common.unit.TimeValue; import org.elasticsearch.common.util.concurrent.AbstractRunnable; import org.elasticsearch.discovery.Discovery; import org.elasticsearch.env.NodeEnvironment; +import org.elasticsearch.index.NodeServicesProvider; +import org.elasticsearch.indices.IndicesService; import org.elasticsearch.rest.RestStatus; import org.elasticsearch.threadpool.ThreadPool; @@ -95,9 +97,11 @@ public class GatewayService extends AbstractLifecycleComponent i @Inject public GatewayService(Settings settings, AllocationService allocationService, ClusterService clusterService, ThreadPool threadPool, NodeEnvironment nodeEnvironment, GatewayMetaState metaState, - TransportNodesListGatewayMetaState listGatewayMetaState, Discovery discovery) { + TransportNodesListGatewayMetaState listGatewayMetaState, Discovery discovery, + NodeServicesProvider nodeServicesProvider, IndicesService indicesService) { super(settings); - this.gateway = new Gateway(settings, clusterService, nodeEnvironment, metaState, listGatewayMetaState, discovery); + this.gateway = new Gateway(settings, clusterService, nodeEnvironment, metaState, listGatewayMetaState, discovery, + nodeServicesProvider, indicesService); this.allocationService = allocationService; this.clusterService = clusterService; this.threadPool = threadPool; diff --git a/core/src/main/java/org/elasticsearch/gateway/LocalAllocateDangledIndices.java b/core/src/main/java/org/elasticsearch/gateway/LocalAllocateDangledIndices.java index 041b8cafecc..b14dcc6d1a4 100644 --- a/core/src/main/java/org/elasticsearch/gateway/LocalAllocateDangledIndices.java +++ b/core/src/main/java/org/elasticsearch/gateway/LocalAllocateDangledIndices.java @@ -19,7 +19,6 @@ package org.elasticsearch.gateway; -import org.elasticsearch.cluster.ClusterService; import org.elasticsearch.cluster.ClusterState; import org.elasticsearch.cluster.ClusterStateUpdateTask; import org.elasticsearch.cluster.block.ClusterBlocks; @@ -30,6 +29,7 @@ import org.elasticsearch.cluster.node.DiscoveryNode; import org.elasticsearch.cluster.routing.RoutingTable; import org.elasticsearch.cluster.routing.allocation.AllocationService; import org.elasticsearch.cluster.routing.allocation.RoutingAllocation; +import org.elasticsearch.cluster.service.ClusterService; import org.elasticsearch.common.component.AbstractComponent; import org.elasticsearch.common.inject.Inject; import org.elasticsearch.common.io.stream.StreamInput; diff --git a/core/src/main/java/org/elasticsearch/gateway/MetaStateService.java b/core/src/main/java/org/elasticsearch/gateway/MetaStateService.java index 1f4cc310fdb..0edfb563174 100644 --- a/core/src/main/java/org/elasticsearch/gateway/MetaStateService.java +++ b/core/src/main/java/org/elasticsearch/gateway/MetaStateService.java @@ -25,19 +25,13 @@ import org.elasticsearch.common.Nullable; import org.elasticsearch.common.component.AbstractComponent; import org.elasticsearch.common.inject.Inject; import org.elasticsearch.common.settings.Settings; -import org.elasticsearch.common.xcontent.ToXContent; -import org.elasticsearch.common.xcontent.XContentBuilder; -import org.elasticsearch.common.xcontent.XContentParser; -import org.elasticsearch.common.xcontent.XContentType; import org.elasticsearch.env.NodeEnvironment; import org.elasticsearch.index.Index; import java.io.IOException; import java.nio.file.Path; import java.util.ArrayList; -import java.util.HashMap; import java.util.List; -import java.util.Map; import java.util.function.Predicate; /** @@ -45,41 +39,12 @@ import java.util.function.Predicate; */ public class MetaStateService extends AbstractComponent { - static final String FORMAT_SETTING = "gateway.format"; - - static final String GLOBAL_STATE_FILE_PREFIX = "global-"; - public static final String INDEX_STATE_FILE_PREFIX = "state-"; - private final NodeEnvironment nodeEnv; - private final XContentType format; - private final ToXContent.Params formatParams; - private final ToXContent.Params gatewayModeFormatParams; - private final MetaDataStateFormat indexStateFormat; - private final MetaDataStateFormat globalStateFormat; - @Inject public MetaStateService(Settings settings, NodeEnvironment nodeEnv) { super(settings); this.nodeEnv = nodeEnv; - this.format = XContentType.fromMediaTypeOrFormat(settings.get(FORMAT_SETTING, "smile")); - if (this.format == XContentType.SMILE) { - Map params = new HashMap<>(); - params.put("binary", "true"); - formatParams = new ToXContent.MapParams(params); - Map gatewayModeParams = new HashMap<>(); - gatewayModeParams.put("binary", "true"); - gatewayModeParams.put(MetaData.CONTEXT_MODE_PARAM, MetaData.CONTEXT_MODE_GATEWAY); - gatewayModeFormatParams = new ToXContent.MapParams(gatewayModeParams); - } else { - formatParams = ToXContent.EMPTY_PARAMS; - Map gatewayModeParams = new HashMap<>(); - gatewayModeParams.put(MetaData.CONTEXT_MODE_PARAM, MetaData.CONTEXT_MODE_GATEWAY); - gatewayModeFormatParams = new ToXContent.MapParams(gatewayModeParams); - } - indexStateFormat = indexStateFormat(format, formatParams); - globalStateFormat = globalStateFormat(format, gatewayModeFormatParams); - } /** @@ -95,7 +60,7 @@ public class MetaStateService extends AbstractComponent { metaDataBuilder = MetaData.builder(); } for (String indexFolderName : nodeEnv.availableIndexFolders()) { - IndexMetaData indexMetaData = indexStateFormat.loadLatestState(logger, nodeEnv.resolveIndexFolder(indexFolderName)); + IndexMetaData indexMetaData = IndexMetaData.FORMAT.loadLatestState(logger, nodeEnv.resolveIndexFolder(indexFolderName)); if (indexMetaData != null) { metaDataBuilder.put(indexMetaData, false); } else { @@ -110,7 +75,7 @@ public class MetaStateService extends AbstractComponent { */ @Nullable IndexMetaData loadIndexState(Index index) throws IOException { - return indexStateFormat.loadLatestState(logger, nodeEnv.indexPaths(index)); + return IndexMetaData.FORMAT.loadLatestState(logger, nodeEnv.indexPaths(index)); } /** @@ -122,7 +87,7 @@ public class MetaStateService extends AbstractComponent { if (excludeIndexPathIdsPredicate.test(indexFolderName)) { continue; } - IndexMetaData indexMetaData = indexStateFormat.loadLatestState(logger, + IndexMetaData indexMetaData = IndexMetaData.FORMAT.loadLatestState(logger, nodeEnv.resolveIndexFolder(indexFolderName)); if (indexMetaData != null) { final String indexPathId = indexMetaData.getIndex().getUUID(); @@ -142,7 +107,7 @@ public class MetaStateService extends AbstractComponent { * Loads the global state, *without* index state, see {@link #loadFullState()} for that. */ MetaData loadGlobalState() throws IOException { - MetaData globalState = globalStateFormat.loadLatestState(logger, nodeEnv.nodeDataPaths()); + MetaData globalState = MetaData.FORMAT.loadLatestState(logger, nodeEnv.nodeDataPaths()); // ES 2.0 now requires units for all time and byte-sized settings, so we add the default unit if it's missing // TODO: can we somehow only do this for pre-2.0 cluster state? if (globalState != null) { @@ -167,7 +132,7 @@ public class MetaStateService extends AbstractComponent { final Index index = indexMetaData.getIndex(); logger.trace("[{}] writing state, reason [{}]", index, reason); try { - indexStateFormat.write(indexMetaData, indexMetaData.getVersion(), locations); + IndexMetaData.FORMAT.write(indexMetaData, indexMetaData.getVersion(), locations); } catch (Throwable ex) { logger.warn("[{}]: failed to write index state", ex, index); throw new IOException("failed to write state for [" + index + "]", ex); @@ -180,45 +145,10 @@ public class MetaStateService extends AbstractComponent { void writeGlobalState(String reason, MetaData metaData) throws Exception { logger.trace("[_global] writing state, reason [{}]", reason); try { - globalStateFormat.write(metaData, metaData.version(), nodeEnv.nodeDataPaths()); + MetaData.FORMAT.write(metaData, metaData.version(), nodeEnv.nodeDataPaths()); } catch (Throwable ex) { logger.warn("[_global]: failed to write global state", ex); throw new IOException("failed to write global state", ex); } } - - /** - * Returns a StateFormat that can read and write {@link MetaData} - */ - static MetaDataStateFormat globalStateFormat(XContentType format, final ToXContent.Params formatParams) { - return new MetaDataStateFormat(format, GLOBAL_STATE_FILE_PREFIX) { - - @Override - public void toXContent(XContentBuilder builder, MetaData state) throws IOException { - MetaData.Builder.toXContent(state, builder, formatParams); - } - - @Override - public MetaData fromXContent(XContentParser parser) throws IOException { - return MetaData.Builder.fromXContent(parser); - } - }; - } - - /** - * Returns a StateFormat that can read and write {@link IndexMetaData} - */ - static MetaDataStateFormat indexStateFormat(XContentType format, final ToXContent.Params formatParams) { - return new MetaDataStateFormat(format, INDEX_STATE_FILE_PREFIX) { - - @Override - public void toXContent(XContentBuilder builder, IndexMetaData state) throws IOException { - IndexMetaData.Builder.toXContent(state, builder, formatParams); } - - @Override - public IndexMetaData fromXContent(XContentParser parser) throws IOException { - return IndexMetaData.Builder.fromXContent(parser); - } - }; - } } diff --git a/core/src/main/java/org/elasticsearch/gateway/TransportNodesListGatewayMetaState.java b/core/src/main/java/org/elasticsearch/gateway/TransportNodesListGatewayMetaState.java index fb174f4bd45..0fd1fd35809 100644 --- a/core/src/main/java/org/elasticsearch/gateway/TransportNodesListGatewayMetaState.java +++ b/core/src/main/java/org/elasticsearch/gateway/TransportNodesListGatewayMetaState.java @@ -29,10 +29,10 @@ import org.elasticsearch.action.support.nodes.BaseNodesRequest; import org.elasticsearch.action.support.nodes.BaseNodesResponse; import org.elasticsearch.action.support.nodes.TransportNodesAction; import org.elasticsearch.cluster.ClusterName; -import org.elasticsearch.cluster.ClusterService; import org.elasticsearch.cluster.metadata.IndexNameExpressionResolver; import org.elasticsearch.cluster.metadata.MetaData; import org.elasticsearch.cluster.node.DiscoveryNode; +import org.elasticsearch.cluster.service.ClusterService; import org.elasticsearch.common.Nullable; import org.elasticsearch.common.inject.Inject; import org.elasticsearch.common.io.stream.StreamInput; diff --git a/core/src/main/java/org/elasticsearch/gateway/TransportNodesListGatewayStartedShards.java b/core/src/main/java/org/elasticsearch/gateway/TransportNodesListGatewayStartedShards.java index d1aa2a8b383..7a090208818 100644 --- a/core/src/main/java/org/elasticsearch/gateway/TransportNodesListGatewayStartedShards.java +++ b/core/src/main/java/org/elasticsearch/gateway/TransportNodesListGatewayStartedShards.java @@ -29,11 +29,11 @@ import org.elasticsearch.action.support.nodes.BaseNodesRequest; import org.elasticsearch.action.support.nodes.BaseNodesResponse; import org.elasticsearch.action.support.nodes.TransportNodesAction; import org.elasticsearch.cluster.ClusterName; -import org.elasticsearch.cluster.ClusterService; import org.elasticsearch.cluster.ClusterState; import org.elasticsearch.cluster.metadata.IndexMetaData; import org.elasticsearch.cluster.metadata.IndexNameExpressionResolver; import org.elasticsearch.cluster.node.DiscoveryNode; +import org.elasticsearch.cluster.service.ClusterService; import org.elasticsearch.common.inject.Inject; import org.elasticsearch.common.io.stream.StreamInput; import org.elasticsearch.common.io.stream.StreamOutput; diff --git a/core/src/main/java/org/elasticsearch/index/IndexModule.java b/core/src/main/java/org/elasticsearch/index/IndexModule.java index b6120bd9d78..48230e6ec1e 100644 --- a/core/src/main/java/org/elasticsearch/index/IndexModule.java +++ b/core/src/main/java/org/elasticsearch/index/IndexModule.java @@ -67,12 +67,13 @@ import java.util.function.Function; public final class IndexModule { public static final Setting INDEX_STORE_TYPE_SETTING = - new Setting<>("index.store.type", "", Function.identity(), Property.IndexScope); + new Setting<>("index.store.type", "", Function.identity(), Property.IndexScope, Property.NodeScope); public static final String SIMILARITY_SETTINGS_PREFIX = "index.similarity"; public static final String INDEX_QUERY_CACHE = "index"; public static final String NONE_QUERY_CACHE = "none"; public static final Setting INDEX_QUERY_CACHE_TYPE_SETTING = new Setting<>("index.queries.cache.type", INDEX_QUERY_CACHE, Function.identity(), Property.IndexScope); + // for test purposes only public static final Setting INDEX_QUERY_CACHE_EVERYTHING_SETTING = Setting.boolSetting("index.queries.cache.everything", false, Property.IndexScope); @@ -87,7 +88,7 @@ public final class IndexModule { private final Map> similarities = new HashMap<>(); private final Map> storeTypes = new HashMap<>(); private final Map> queryCaches = new HashMap<>(); - + private final SetOnce forceQueryCacheType = new SetOnce<>(); public IndexModule(IndexSettings indexSettings, IndexStoreConfig indexStoreConfig, AnalysisRegistry analysisRegistry) { this.indexStoreConfig = indexStoreConfig; @@ -265,11 +266,23 @@ public final class IndexModule { } indexSettings.getScopedSettings().addSettingsUpdateConsumer(IndexStore.INDEX_STORE_THROTTLE_TYPE_SETTING, store::setType); indexSettings.getScopedSettings().addSettingsUpdateConsumer(IndexStore.INDEX_STORE_THROTTLE_MAX_BYTES_PER_SEC_SETTING, store::setMaxRate); - final String queryCacheType = indexSettings.getValue(INDEX_QUERY_CACHE_TYPE_SETTING); + final String queryCacheType = forceQueryCacheType.get() != null ? forceQueryCacheType.get() : indexSettings.getValue(INDEX_QUERY_CACHE_TYPE_SETTING); final BiFunction queryCacheProvider = queryCaches.get(queryCacheType); final QueryCache queryCache = queryCacheProvider.apply(indexSettings, indicesQueryCache); return new IndexService(indexSettings, environment, new SimilarityService(indexSettings, similarities), shardStoreDeleter, analysisRegistry, engineFactory.get(), servicesProvider, queryCache, store, eventListener, searcherWrapperFactory, mapperRegistry, indicesFieldDataCache, listeners); } + /** + * Forces a certain query cache type. If this is set + * the given cache type is overriding the default as well as the type + * set on the index level. + * NOTE: this can only be set once + * + * @see #INDEX_QUERY_CACHE_TYPE_SETTING + */ + public void forceQueryCacheType(String type) { + this.forceQueryCacheType.set(type); + } + } diff --git a/core/src/main/java/org/elasticsearch/index/IndexService.java b/core/src/main/java/org/elasticsearch/index/IndexService.java index 6b4a1851ab5..1b55adf78cc 100644 --- a/core/src/main/java/org/elasticsearch/index/IndexService.java +++ b/core/src/main/java/org/elasticsearch/index/IndexService.java @@ -44,6 +44,7 @@ import org.elasticsearch.common.Nullable; import org.elasticsearch.common.collect.ImmutableOpenMap; import org.elasticsearch.common.settings.Settings; import org.elasticsearch.common.unit.TimeValue; +import org.elasticsearch.common.util.BigArrays; import org.elasticsearch.common.util.concurrent.FutureUtils; import org.elasticsearch.common.xcontent.XContentFactory; import org.elasticsearch.common.xcontent.XContentParser; @@ -61,6 +62,7 @@ import org.elasticsearch.index.fielddata.FieldDataType; import org.elasticsearch.index.fielddata.IndexFieldDataCache; import org.elasticsearch.index.fielddata.IndexFieldDataService; import org.elasticsearch.index.mapper.MapperService; +import org.elasticsearch.index.percolator.PercolatorQueryCache; import org.elasticsearch.index.query.ParsedQuery; import org.elasticsearch.index.query.QueryShardContext; import org.elasticsearch.index.shard.IndexEventListener; @@ -113,6 +115,8 @@ public final class IndexService extends AbstractIndexComponent implements IndexC private volatile AsyncRefreshTask refreshTask; private volatile AsyncTranslogFSync fsyncTask; private final SearchSlowLog searchSlowLog; + private final ThreadPool threadPool; + private final BigArrays bigArrays; public IndexService(IndexSettings indexSettings, NodeEnvironment nodeEnv, SimilarityService similarityService, @@ -131,17 +135,24 @@ public final class IndexService extends AbstractIndexComponent implements IndexC this.indexSettings = indexSettings; this.analysisService = registry.build(indexSettings); this.similarityService = similarityService; - this.mapperService = new MapperService(indexSettings, analysisService, similarityService, mapperRegistry, IndexService.this::newQueryShardContext); - this.indexFieldData = new IndexFieldDataService(indexSettings, indicesFieldDataCache, nodeServicesProvider.getCircuitBreakerService(), mapperService); + this.mapperService = new MapperService(indexSettings, analysisService, similarityService, mapperRegistry, + IndexService.this::newQueryShardContext); + this.indexFieldData = new IndexFieldDataService(indexSettings, indicesFieldDataCache, + nodeServicesProvider.getCircuitBreakerService(), mapperService); this.shardStoreDeleter = shardStoreDeleter; + this.bigArrays = nodeServicesProvider.getBigArrays(); + this.threadPool = nodeServicesProvider.getThreadPool(); this.eventListener = eventListener; this.nodeEnv = nodeEnv; this.nodeServicesProvider = nodeServicesProvider; this.indexStore = indexStore; indexFieldData.setListener(new FieldDataCacheListener(this)); this.bitsetFilterCache = new BitsetFilterCache(indexSettings, new BitsetCacheListener(this)); - this.warmer = new IndexWarmer(indexSettings.getSettings(), nodeServicesProvider.getThreadPool(), bitsetFilterCache.createListener(nodeServicesProvider.getThreadPool())); - this.indexCache = new IndexCache(indexSettings, queryCache, bitsetFilterCache); + PercolatorQueryCache percolatorQueryCache = new PercolatorQueryCache(indexSettings, IndexService.this::newQueryShardContext); + this.warmer = new IndexWarmer(indexSettings.getSettings(), threadPool, + bitsetFilterCache.createListener(threadPool), + percolatorQueryCache.createListener(threadPool)); + this.indexCache = new IndexCache(indexSettings, queryCache, bitsetFilterCache, percolatorQueryCache); this.engineFactory = engineFactory; // initialize this last -- otherwise if the wrapper requires any other member to be non-null we fail with an NPE this.searcherWrapper = wrapperFactory.newWrapper(this); @@ -230,7 +241,8 @@ public final class IndexService extends AbstractIndexComponent implements IndexC } } } finally { - IOUtils.close(bitsetFilterCache, indexCache, mapperService, indexFieldData, analysisService, refreshTask, fsyncTask); + IOUtils.close(bitsetFilterCache, indexCache, mapperService, indexFieldData, analysisService, refreshTask, fsyncTask, + cache().getPercolatorQueryCache()); } } } @@ -300,7 +312,9 @@ public final class IndexService extends AbstractIndexComponent implements IndexC } dataPathToShardCount.put(dataPath, curCount + 1); } - path = ShardPath.selectNewPathForShard(nodeEnv, shardId, this.indexSettings, routing.getExpectedShardSize() == ShardRouting.UNAVAILABLE_EXPECTED_SHARD_SIZE ? getAvgShardSizeInBytes() : routing.getExpectedShardSize(), + path = ShardPath.selectNewPathForShard(nodeEnv, shardId, this.indexSettings, + routing.getExpectedShardSize() == ShardRouting.UNAVAILABLE_EXPECTED_SHARD_SIZE + ? getAvgShardSizeInBytes() : routing.getExpectedShardSize(), dataPathToShardCount); logger.debug("{} creating using a new path [{}]", shardId, path); } else { @@ -321,11 +335,16 @@ public final class IndexService extends AbstractIndexComponent implements IndexC warmer.warm(searcher, shard, IndexService.this.indexSettings, toLevel); } }; - store = new Store(shardId, this.indexSettings, indexStore.newDirectoryService(path), lock, new StoreCloseListener(shardId, canDeleteShardContent, () -> eventListener.onStoreClosed(shardId))); + store = new Store(shardId, this.indexSettings, indexStore.newDirectoryService(path), lock, + new StoreCloseListener(shardId, canDeleteShardContent, () -> eventListener.onStoreClosed(shardId))); if (useShadowEngine(primary, indexSettings)) { - indexShard = new ShadowIndexShard(shardId, this.indexSettings, path, store, indexCache, mapperService, similarityService, indexFieldData, engineFactory, eventListener, searcherWrapper, nodeServicesProvider, searchSlowLog, engineWarmer); // no indexing listeners - shadow engines don't index + indexShard = new ShadowIndexShard(shardId, this.indexSettings, path, store, indexCache, mapperService, similarityService, + indexFieldData, engineFactory, eventListener, searcherWrapper, threadPool, bigArrays, searchSlowLog, engineWarmer); + // no indexing listeners - shadow engines don't index } else { - indexShard = new IndexShard(shardId, this.indexSettings, path, store, indexCache, mapperService, similarityService, indexFieldData, engineFactory, eventListener, searcherWrapper, nodeServicesProvider, searchSlowLog, engineWarmer, listeners); + indexShard = new IndexShard(shardId, this.indexSettings, path, store, indexCache, mapperService, similarityService, + indexFieldData, engineFactory, eventListener, searcherWrapper, threadPool, bigArrays, searchSlowLog, engineWarmer, + listeners); } eventListener.indexShardStateChanged(indexShard, null, indexShard.state(), "shard created"); eventListener.afterIndexShardCreated(indexShard); @@ -370,7 +389,8 @@ public final class IndexService extends AbstractIndexComponent implements IndexC // and close the shard so no operations are allowed to it if (indexShard != null) { try { - final boolean flushEngine = deleted.get() == false && closed.get(); // only flush we are we closed (closed index or shutdown) and if we are not deleted + // only flush we are we closed (closed index or shutdown) and if we are not deleted + final boolean flushEngine = deleted.get() == false && closed.get(); indexShard.close(reason, flushEngine); } catch (Throwable e) { logger.debug("[{}] failed to close index shard", e, shardId); @@ -417,14 +437,23 @@ public final class IndexService extends AbstractIndexComponent implements IndexC } /** - * Creates a new QueryShardContext. The context has not types set yet, if types are required set them via {@link QueryShardContext#setTypes(String...)} + * Creates a new QueryShardContext. The context has not types set yet, if types are required set them via + * {@link QueryShardContext#setTypes(String...)} */ public QueryShardContext newQueryShardContext() { - return new QueryShardContext(indexSettings, indexCache.bitsetFilterCache(), indexFieldData, mapperService(), similarityService(), nodeServicesProvider.getScriptService(), nodeServicesProvider.getIndicesQueriesRegistry()); + return new QueryShardContext( + indexSettings, indexCache.bitsetFilterCache(), indexFieldData, mapperService(), + similarityService(), nodeServicesProvider.getScriptService(), nodeServicesProvider.getIndicesQueriesRegistry(), + indexCache.getPercolatorQueryCache() + ); } - ThreadPool getThreadPool() { - return nodeServicesProvider.getThreadPool(); + public ThreadPool getThreadPool() { + return threadPool; + } + + public BigArrays getBigArrays() { + return bigArrays; } public SearchSlowLog getSearchSlowLog() { @@ -541,7 +570,8 @@ public final class IndexService extends AbstractIndexComponent implements IndexC AliasMetaData alias = aliases.get(aliasName); if (alias == null) { // This shouldn't happen unless alias disappeared after filteringAliases was called. - throw new InvalidAliasNameException(indexSettings.getIndex(), aliasNames[0], "Unknown alias name was passed to alias Filter"); + throw new InvalidAliasNameException(indexSettings.getIndex(), aliasNames[0], + "Unknown alias name was passed to alias Filter"); } Query parsedFilter = parse(alias, context); if (parsedFilter != null) { @@ -717,7 +747,8 @@ public final class IndexService extends AbstractIndexComponent implements IndexC } catch (Exception ex) { if (lastThrownException == null || sameException(lastThrownException, ex) == false) { // prevent the annoying fact of logging the same stuff all the time with an interval of 1 sec will spam all your logs - indexService.logger.warn("failed to run task {} - suppressing re-occurring exceptions unless the exception changes", ex, toString()); + indexService.logger.warn("failed to run task {} - suppressing re-occurring exceptions unless the exception changes", + ex, toString()); lastThrownException = ex; } } finally { diff --git a/core/src/main/java/org/elasticsearch/index/analysis/AnalysisRegistry.java b/core/src/main/java/org/elasticsearch/index/analysis/AnalysisRegistry.java index a8a7b4fe004..3c2d6bfb260 100644 --- a/core/src/main/java/org/elasticsearch/index/analysis/AnalysisRegistry.java +++ b/core/src/main/java/org/elasticsearch/index/analysis/AnalysisRegistry.java @@ -85,6 +85,10 @@ public final class AnalysisRegistry implements Closeable { this.analyzers = Collections.unmodifiableMap(analyzerBuilder); } + public HunspellService getHunspellService() { + return hunspellService; + } + /** * Returns a registered {@link TokenizerFactory} provider by name or null if the tokenizer was not registered */ diff --git a/core/src/main/java/org/elasticsearch/index/cache/IndexCache.java b/core/src/main/java/org/elasticsearch/index/cache/IndexCache.java index 61733f24695..b41f5bc0125 100644 --- a/core/src/main/java/org/elasticsearch/index/cache/IndexCache.java +++ b/core/src/main/java/org/elasticsearch/index/cache/IndexCache.java @@ -24,6 +24,7 @@ import org.elasticsearch.index.AbstractIndexComponent; import org.elasticsearch.index.IndexSettings; import org.elasticsearch.index.cache.bitset.BitsetFilterCache; import org.elasticsearch.index.cache.query.QueryCache; +import org.elasticsearch.index.percolator.PercolatorQueryCache; import java.io.Closeable; import java.io.IOException; @@ -35,11 +36,14 @@ public class IndexCache extends AbstractIndexComponent implements Closeable { private final QueryCache queryCache; private final BitsetFilterCache bitsetFilterCache; + private final PercolatorQueryCache percolatorQueryCache; - public IndexCache(IndexSettings indexSettings, QueryCache queryCache, BitsetFilterCache bitsetFilterCache) { + public IndexCache(IndexSettings indexSettings, QueryCache queryCache, BitsetFilterCache bitsetFilterCache, + PercolatorQueryCache percolatorQueryCache) { super(indexSettings); this.queryCache = queryCache; this.bitsetFilterCache = bitsetFilterCache; + this.percolatorQueryCache = percolatorQueryCache; } public QueryCache query() { @@ -53,9 +57,13 @@ public class IndexCache extends AbstractIndexComponent implements Closeable { return bitsetFilterCache; } + public PercolatorQueryCache getPercolatorQueryCache() { + return percolatorQueryCache; + } + @Override public void close() throws IOException { - IOUtils.close(queryCache, bitsetFilterCache); + IOUtils.close(queryCache, bitsetFilterCache, percolatorQueryCache); } public void clear(String reason) { diff --git a/core/src/main/java/org/elasticsearch/index/engine/EngineConfig.java b/core/src/main/java/org/elasticsearch/index/engine/EngineConfig.java index 14a8f043234..a290e98f3f7 100644 --- a/core/src/main/java/org/elasticsearch/index/engine/EngineConfig.java +++ b/core/src/main/java/org/elasticsearch/index/engine/EngineConfig.java @@ -40,6 +40,8 @@ import org.elasticsearch.index.translog.TranslogConfig; import org.elasticsearch.indices.IndexingMemoryController; import org.elasticsearch.threadpool.ThreadPool; +import java.util.function.Function; + /* * Holds all the configuration that is used to create an {@link Engine}. * Once {@link Engine} has been created with this object, changes to this @@ -69,20 +71,23 @@ public final class EngineConfig { /** * Index setting to change the low level lucene codec used for writing new segments. * This setting is not realtime updateable. + * This setting is also settable on the node and the index level, it's commonly used in hot/cold node archs where index is likely + * allocated on both `kind` of nodes. */ - public static final Setting INDEX_CODEC_SETTING = new Setting<>("index.codec", "default", (s) -> { - switch(s) { + public static final Setting INDEX_CODEC_SETTING = new Setting<>("index.codec", "default", s -> { + switch (s) { case "default": case "best_compression": case "lucene_default": return s; default: if (Codec.availableCodecs().contains(s) == false) { // we don't error message the not officially supported ones - throw new IllegalArgumentException("unknown value for [index.codec] must be one of [default, best_compression] but was: " + s); + throw new IllegalArgumentException( + "unknown value for [index.codec] must be one of [default, best_compression] but was: " + s); } return s; } - }, Property.IndexScope); + }, Property.IndexScope, Property.NodeScope); /** if set to true the engine will start even if the translog id in the commit point can not be found */ public static final String INDEX_FORCE_NEW_TRANSLOG = "index.engine.force_new_translog"; @@ -97,7 +102,8 @@ public final class EngineConfig { IndexSettings indexSettings, Engine.Warmer warmer, Store store, SnapshotDeletionPolicy deletionPolicy, MergePolicy mergePolicy,Analyzer analyzer, Similarity similarity, CodecService codecService, Engine.EventListener eventListener, - TranslogRecoveryPerformer translogRecoveryPerformer, QueryCache queryCache, QueryCachingPolicy queryCachingPolicy, TranslogConfig translogConfig, TimeValue flushMergesAfter) { + TranslogRecoveryPerformer translogRecoveryPerformer, QueryCache queryCache, QueryCachingPolicy queryCachingPolicy, + TranslogConfig translogConfig, TimeValue flushMergesAfter) { this.shardId = shardId; final Settings settings = indexSettings.getSettings(); this.indexSettings = indexSettings; @@ -138,7 +144,8 @@ public final class EngineConfig { } /** - * Returns the initial index buffer size. This setting is only read on startup and otherwise controlled by {@link IndexingMemoryController} + * Returns the initial index buffer size. This setting is only read on startup and otherwise controlled + * by {@link IndexingMemoryController} */ public ByteSizeValue getIndexingBufferSize() { return indexingBufferSize; @@ -146,11 +153,12 @@ public final class EngineConfig { /** * Returns true iff delete garbage collection in the engine should be enabled. This setting is updateable - * in realtime and forces a volatile read. Consumers can safely read this value directly go fetch it's latest value. The default is true + * in realtime and forces a volatile read. Consumers can safely read this value directly go fetch it's latest value. + * The default is true *

* Engine GC deletion if enabled collects deleted documents from in-memory realtime data structures after a certain amount of - * time ({@link IndexSettings#getGcDeletesInMillis()} if enabled. Before deletes are GCed they will cause re-adding the document that was deleted - * to fail. + * time ({@link IndexSettings#getGcDeletesInMillis()} if enabled. Before deletes are GCed they will cause re-adding the document + * that was deleted to fail. *

*/ public boolean isEnableGcDeletes() { @@ -168,7 +176,8 @@ public final class EngineConfig { } /** - * Returns a thread-pool mainly used to get estimated time stamps from {@link org.elasticsearch.threadpool.ThreadPool#estimatedTimeInMillis()} and to schedule + * Returns a thread-pool mainly used to get estimated time stamps from + * {@link org.elasticsearch.threadpool.ThreadPool#estimatedTimeInMillis()} and to schedule * async force merge calls on the {@link org.elasticsearch.threadpool.ThreadPool.Names#FORCE_MERGE} thread-pool */ public ThreadPool getThreadPool() { @@ -183,8 +192,9 @@ public final class EngineConfig { } /** - * Returns the {@link org.elasticsearch.index.store.Store} instance that provides access to the {@link org.apache.lucene.store.Directory} - * used for the engines {@link org.apache.lucene.index.IndexWriter} to write it's index files to. + * Returns the {@link org.elasticsearch.index.store.Store} instance that provides access to the + * {@link org.apache.lucene.store.Directory} used for the engines {@link org.apache.lucene.index.IndexWriter} to write it's index files + * to. *

* Note: In order to use this instance the consumer needs to increment the stores reference before it's used the first time and hold * it's reference until it's not needed anymore. diff --git a/core/src/main/java/org/elasticsearch/index/fieldstats/FieldStatsProvider.java b/core/src/main/java/org/elasticsearch/index/fieldstats/FieldStatsProvider.java new file mode 100644 index 00000000000..066d1207e3f --- /dev/null +++ b/core/src/main/java/org/elasticsearch/index/fieldstats/FieldStatsProvider.java @@ -0,0 +1,181 @@ +/* + * Licensed to Elasticsearch under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch 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.elasticsearch.index.fieldstats; + +import org.apache.lucene.index.IndexReader; +import org.apache.lucene.index.MultiFields; +import org.apache.lucene.index.Terms; +import org.apache.lucene.util.BytesRef; +import org.elasticsearch.action.fieldstats.FieldStats; +import org.elasticsearch.action.fieldstats.IndexConstraint; +import org.elasticsearch.action.fieldstats.IndexConstraint.Comparison; +import org.elasticsearch.action.fieldstats.IndexConstraint.Property; +import org.elasticsearch.common.joda.DateMathParser; +import org.elasticsearch.index.engine.Engine.Searcher; +import org.elasticsearch.index.mapper.MappedFieldType; +import org.elasticsearch.index.mapper.MapperService; +import org.elasticsearch.index.mapper.core.DateFieldMapper.DateFieldType; +import org.elasticsearch.index.mapper.ip.IpFieldMapper.IpFieldType; +import org.joda.time.DateTimeZone; + +import java.io.IOException; + +/** + * Provides a service for gettings the {@link FieldStats} for a given field from + * the index. + */ +public class FieldStatsProvider { + + private final Searcher searcher; + private final MapperService mapperService; + + /** + * @param searcher + * the {@link Searcher}to use when retrieving the + * {@link FieldStats} + * @param mapperService + * the {@link MapperService} + */ + public FieldStatsProvider(Searcher searcher, MapperService mapperService) { + this.searcher = searcher; + this.mapperService = mapperService; + } + + /** + * @param field + * the name of the field to return {@link FieldStats} for. + * @return a {@link FieldStats} object for the given field + * @throws IOException + * if the field statistics cannot be read + */ + public > FieldStats get(String field) throws IOException { + MappedFieldType mappedFieldType = mapperService.fullName(field); + if (mappedFieldType != null) { + IndexReader reader = searcher.reader(); + Terms terms = MultiFields.getTerms(reader, field); + if (terms != null) { + return mappedFieldType.stats(terms, reader.maxDoc()); + } + } + return null; + } + + /** + * @param fieldName + * the fieldName to check + * @param from + * the minimum value for the query + * @param to + * the maximum value for the query + * @param includeLower + * whether the from value is inclusive + * @param includeUpper + * whether the to value is inclusive + * @param timeZone + * the timeZone to use for date fields + * @param dateMathParser + * the {@link DateMathParser} to use for date fields + * @return A {@link Relation} indicating the overlap of the range of terms + * for the field with the query range. This method will return: + *

    + *
  • {@link Relation#WITHIN} if the range of terms for the field + * in the shard is completely within the query range
  • + *
  • {@link Relation#DISJOINT} if the range of terms for the field + * in the shard is completely outside the query range
  • + *
  • {@link Relation#INTERSECTS} if the range of terms for the + * field in the shard intersects with the query range
  • + *
+ * @throws IOException + * if the index cannot be read + */ + public Relation isFieldWithinQuery(String fieldName, Object from, Object to, boolean includeLower, boolean includeUpper, + DateTimeZone timeZone, DateMathParser dateMathParser) throws IOException { + MappedFieldType mappedFieldType = mapperService.fullName(fieldName); + FieldStats fieldStats = get(fieldName); + if (fieldStats == null) { + // No fieldStats for the field so the field doesn't exist on + // this shard, so relation is DISJOINT + return Relation.DISJOINT; + } else { + // Convert the from and to values to Strings so they can be used + // in the IndexConstraints. Since DateTime is represented as a + // Long field in Lucene we need to use the millisecond value of + // the DateTime in that case + String fromString = null; + if (from != null) { + if (mappedFieldType instanceof DateFieldType) { + long millis = ((DateFieldType) mappedFieldType).parseToMilliseconds(from, !includeLower, timeZone, dateMathParser); + fromString = fieldStats.stringValueOf(millis, null); + } else if (mappedFieldType instanceof IpFieldType) { + if (from instanceof BytesRef) { + from = ((BytesRef) from).utf8ToString(); + } + long ipAsLong = ((IpFieldType) mappedFieldType).value(from); + fromString = fieldStats.stringValueOf(ipAsLong, null); + } else { + fromString = fieldStats.stringValueOf(from, null); + } + } + String toString = null; + if (to != null) { + if (mappedFieldType instanceof DateFieldType) { + long millis = ((DateFieldType) mappedFieldType).parseToMilliseconds(to, includeUpper, timeZone, dateMathParser); + toString = fieldStats.stringValueOf(millis, null); + } else if (mappedFieldType instanceof IpFieldType) { + if (to instanceof BytesRef) { + to = ((BytesRef) to).utf8ToString(); + } + long ipAsLong = ((IpFieldType) mappedFieldType).value(to); + toString = fieldStats.stringValueOf(ipAsLong, null); + } else { + toString = fieldStats.stringValueOf(to, null); + } + } + if ((from == null || fieldStats + .match(new IndexConstraint(fieldName, Property.MIN, includeLower ? Comparison.GTE : Comparison.GT, fromString))) + && (to == null || fieldStats.match( + new IndexConstraint(fieldName, Property.MAX, includeUpper ? Comparison.LTE : Comparison.LT, toString)))) { + // If the min and max terms for the field are both within + // the query range then all documents will match so relation is + // WITHIN + return Relation.WITHIN; + } else if ((to != null && fieldStats + .match(new IndexConstraint(fieldName, Property.MIN, includeUpper ? Comparison.GT : Comparison.GTE, toString))) + || (from != null && fieldStats.match( + new IndexConstraint(fieldName, Property.MAX, includeLower ? Comparison.LT : Comparison.LTE, fromString)))) { + // If the min and max terms are both outside the query range + // then no document will match so relation is DISJOINT (N.B. + // since from <= to we only need + // to check one bould for each side of the query range) + return Relation.DISJOINT; + } + } + // Range of terms doesn't match any of the constraints so must INTERSECT + return Relation.INTERSECTS; + } + + /** + * An enum used to describe the relation between the range of terms in a + * shard when compared with a query range + */ + public static enum Relation { + WITHIN, INTERSECTS, DISJOINT; + } +} diff --git a/core/src/main/java/org/elasticsearch/index/mapper/MapperService.java b/core/src/main/java/org/elasticsearch/index/mapper/MapperService.java index 414ea0f7e9c..eaf897e7fbd 100755 --- a/core/src/main/java/org/elasticsearch/index/mapper/MapperService.java +++ b/core/src/main/java/org/elasticsearch/index/mapper/MapperService.java @@ -33,12 +33,12 @@ import org.elasticsearch.index.IndexSettings; import org.elasticsearch.index.analysis.AnalysisService; import org.elasticsearch.index.mapper.Mapper.BuilderContext; import org.elasticsearch.index.mapper.object.ObjectMapper; +import org.elasticsearch.index.percolator.PercolatorFieldMapper; import org.elasticsearch.index.query.QueryShardContext; import org.elasticsearch.index.similarity.SimilarityService; import org.elasticsearch.indices.InvalidTypeNameException; import org.elasticsearch.indices.TypeMissingException; import org.elasticsearch.indices.mapper.MapperRegistry; -import org.elasticsearch.percolator.PercolatorService; import org.elasticsearch.script.ScriptService; import java.io.Closeable; @@ -333,7 +333,7 @@ public class MapperService extends AbstractIndexComponent implements Closeable { } private boolean typeNameStartsWithIllegalDot(DocumentMapper mapper) { - return mapper.type().startsWith(".") && !PercolatorService.TYPE_NAME.equals(mapper.type()); + return mapper.type().startsWith(".") && !PercolatorFieldMapper.TYPE_NAME.equals(mapper.type()); } private boolean assertSerialization(DocumentMapper mapper) { @@ -405,7 +405,7 @@ public class MapperService extends AbstractIndexComponent implements Closeable { public DocumentMapper parse(String mappingType, CompressedXContent mappingSource, boolean applyDefault) throws MapperParsingException { String defaultMappingSource; - if (PercolatorService.TYPE_NAME.equals(mappingType)) { + if (PercolatorFieldMapper.TYPE_NAME.equals(mappingType)) { defaultMappingSource = this.defaultPercolatorMappingSource; } else { defaultMappingSource = this.defaultMappingSource; diff --git a/core/src/main/java/org/elasticsearch/index/mapper/core/DateFieldMapper.java b/core/src/main/java/org/elasticsearch/index/mapper/core/DateFieldMapper.java index 048c58297cb..724c37fcfcd 100644 --- a/core/src/main/java/org/elasticsearch/index/mapper/core/DateFieldMapper.java +++ b/core/src/main/java/org/elasticsearch/index/mapper/core/DateFieldMapper.java @@ -417,10 +417,15 @@ public class DateFieldMapper extends NumberFieldMapper { } public long parseToMilliseconds(Object value, boolean inclusive, @Nullable DateTimeZone zone, @Nullable DateMathParser forcedDateParser) { + if (value instanceof Long) { + return ((Long) value).longValue(); + } + DateMathParser dateParser = dateMathParser(); if (forcedDateParser != null) { dateParser = forcedDateParser; } + String strValue; if (value instanceof BytesRef) { strValue = ((BytesRef) value).utf8ToString(); diff --git a/core/src/main/java/org/elasticsearch/index/mapper/ip/IpFieldMapper.java b/core/src/main/java/org/elasticsearch/index/mapper/ip/IpFieldMapper.java index 9a4cf70782b..2ffb5d4ecf5 100644 --- a/core/src/main/java/org/elasticsearch/index/mapper/ip/IpFieldMapper.java +++ b/core/src/main/java/org/elasticsearch/index/mapper/ip/IpFieldMapper.java @@ -22,12 +22,14 @@ package org.elasticsearch.index.mapper.ip; import org.apache.lucene.analysis.LegacyNumericTokenStream; import org.apache.lucene.document.Field; import org.apache.lucene.index.IndexOptions; +import org.apache.lucene.index.Terms; import org.apache.lucene.search.LegacyNumericRangeQuery; import org.apache.lucene.search.Query; import org.apache.lucene.util.BytesRef; import org.apache.lucene.util.BytesRefBuilder; import org.apache.lucene.util.LegacyNumericUtils; import org.elasticsearch.Version; +import org.elasticsearch.action.fieldstats.FieldStats; import org.elasticsearch.common.Explicit; import org.elasticsearch.common.Nullable; import org.elasticsearch.common.Numbers; @@ -262,6 +264,13 @@ public class IpFieldMapper extends NumberFieldMapper { iValue + iSim, true, true); } + + @Override + public FieldStats stats(Terms terms, int maxDoc) throws IOException { + long minValue = LegacyNumericUtils.getMinLong(terms); + long maxValue = LegacyNumericUtils.getMaxLong(terms); + return new FieldStats.Ip(maxDoc, terms.getDocCount(), terms.getSumDocFreq(), terms.getSumTotalTermFreq(), minValue, maxValue); + } } protected IpFieldMapper(String simpleName, MappedFieldType fieldType, MappedFieldType defaultFieldType, diff --git a/core/src/main/java/org/elasticsearch/index/percolator/PercolateStats.java b/core/src/main/java/org/elasticsearch/index/percolator/PercolateStats.java deleted file mode 100644 index f4c899dff9a..00000000000 --- a/core/src/main/java/org/elasticsearch/index/percolator/PercolateStats.java +++ /dev/null @@ -1,164 +0,0 @@ -/* - * Licensed to Elasticsearch under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch 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.elasticsearch.index.percolator; - -import org.elasticsearch.common.io.stream.StreamInput; -import org.elasticsearch.common.io.stream.StreamOutput; -import org.elasticsearch.common.io.stream.Streamable; -import org.elasticsearch.common.unit.ByteSizeValue; -import org.elasticsearch.common.unit.TimeValue; -import org.elasticsearch.common.xcontent.ToXContent; -import org.elasticsearch.common.xcontent.XContentBuilder; -import org.elasticsearch.common.xcontent.XContentBuilderString; - -import java.io.IOException; - -/** - * Exposes percolator related statistics. - */ -public class PercolateStats implements Streamable, ToXContent { - - private long percolateCount; - private long percolateTimeInMillis; - private long current; - private long memorySizeInBytes = -1; - private long numQueries; - - /** - * Noop constructor for serialization purposes. - */ - public PercolateStats() { - } - - PercolateStats(long percolateCount, long percolateTimeInMillis, long current, long memorySizeInBytes, long numQueries) { - this.percolateCount = percolateCount; - this.percolateTimeInMillis = percolateTimeInMillis; - this.current = current; - this.memorySizeInBytes = memorySizeInBytes; - this.numQueries = numQueries; - } - - /** - * @return The number of times the percolate api has been invoked. - */ - public long getCount() { - return percolateCount; - } - - /** - * @return The total amount of time spend in the percolate api - */ - public long getTimeInMillis() { - return percolateTimeInMillis; - } - - /** - * @return The total amount of time spend in the percolate api - */ - public TimeValue getTime() { - return new TimeValue(getTimeInMillis()); - } - - /** - * @return The total amount of active percolate api invocations. - */ - public long getCurrent() { - return current; - } - - /** - * @return The total number of loaded percolate queries. - */ - public long getNumQueries() { - return numQueries; - } - - /** - * @return Temporarily returns -1, but this used to return the total size the loaded queries take in - * memory, but this is disabled now because the size estimation was too expensive cpu wise. This will be enabled - * again when a cheaper size estimation can be found. - */ - public long getMemorySizeInBytes() { - return memorySizeInBytes; - } - - /** - * @return The total size the loaded queries take in memory. - */ - public ByteSizeValue getMemorySize() { - return new ByteSizeValue(memorySizeInBytes); - } - - @Override - public XContentBuilder toXContent(XContentBuilder builder, Params params) throws IOException { - builder.startObject(Fields.PERCOLATE); - builder.field(Fields.TOTAL, percolateCount); - builder.timeValueField(Fields.TIME_IN_MILLIS, Fields.TIME, percolateTimeInMillis); - builder.field(Fields.CURRENT, current); - builder.field(Fields.MEMORY_SIZE_IN_BYTES, memorySizeInBytes); - builder.field(Fields.MEMORY_SIZE, getMemorySize()); - builder.field(Fields.QUERIES, getNumQueries()); - builder.endObject(); - return builder; - } - - public void add(PercolateStats percolate) { - if (percolate == null) { - return; - } - - percolateCount += percolate.getCount(); - percolateTimeInMillis += percolate.getTimeInMillis(); - current += percolate.getCurrent(); - numQueries += percolate.getNumQueries(); - } - - static final class Fields { - static final XContentBuilderString PERCOLATE = new XContentBuilderString("percolate"); - static final XContentBuilderString TOTAL = new XContentBuilderString("total"); - static final XContentBuilderString TIME = new XContentBuilderString("time"); - static final XContentBuilderString TIME_IN_MILLIS = new XContentBuilderString("time_in_millis"); - static final XContentBuilderString CURRENT = new XContentBuilderString("current"); - static final XContentBuilderString MEMORY_SIZE_IN_BYTES = new XContentBuilderString("memory_size_in_bytes"); - static final XContentBuilderString MEMORY_SIZE = new XContentBuilderString("memory_size"); - static final XContentBuilderString QUERIES = new XContentBuilderString("queries"); - } - - public static PercolateStats readPercolateStats(StreamInput in) throws IOException { - PercolateStats stats = new PercolateStats(); - stats.readFrom(in); - return stats; - } - - @Override - public void readFrom(StreamInput in) throws IOException { - percolateCount = in.readVLong(); - percolateTimeInMillis = in.readVLong(); - current = in.readVLong(); - numQueries = in.readVLong(); - } - - @Override - public void writeTo(StreamOutput out) throws IOException { - out.writeVLong(percolateCount); - out.writeVLong(percolateTimeInMillis); - out.writeVLong(current); - out.writeVLong(numQueries); - } -} diff --git a/core/src/main/java/org/elasticsearch/index/percolator/PercolatorFieldMapper.java b/core/src/main/java/org/elasticsearch/index/percolator/PercolatorFieldMapper.java index f44d454655e..338de5c333d 100644 --- a/core/src/main/java/org/elasticsearch/index/percolator/PercolatorFieldMapper.java +++ b/core/src/main/java/org/elasticsearch/index/percolator/PercolatorFieldMapper.java @@ -19,34 +19,50 @@ package org.elasticsearch.index.percolator; import org.apache.lucene.document.Field; +import org.apache.lucene.document.FieldType; +import org.apache.lucene.document.StoredField; import org.apache.lucene.index.DocValuesType; import org.apache.lucene.index.IndexOptions; import org.apache.lucene.search.Query; +import org.elasticsearch.common.ParsingException; import org.elasticsearch.common.settings.Settings; +import org.elasticsearch.common.xcontent.XContentBuilder; +import org.elasticsearch.common.xcontent.XContentFactory; +import org.elasticsearch.common.xcontent.XContentParser; import org.elasticsearch.index.mapper.FieldMapper; import org.elasticsearch.index.mapper.MappedFieldType; import org.elasticsearch.index.mapper.Mapper; import org.elasticsearch.index.mapper.MapperParsingException; import org.elasticsearch.index.mapper.ParseContext; +import org.elasticsearch.index.mapper.core.BinaryFieldMapper; import org.elasticsearch.index.mapper.core.KeywordFieldMapper; +import org.elasticsearch.index.mapper.core.StringFieldMapper; +import org.elasticsearch.index.query.ParsedQuery; +import org.elasticsearch.index.query.QueryBuilder; +import org.elasticsearch.index.query.QueryParseContext; import org.elasticsearch.index.query.QueryShardContext; import java.io.IOException; import java.util.Arrays; +import java.util.Collections; import java.util.Iterator; import java.util.List; import java.util.Map; public class PercolatorFieldMapper extends FieldMapper { + public static final String TYPE_NAME = ".percolator"; public static final String NAME = "query"; public static final String CONTENT_TYPE = "percolator"; public static final PercolatorFieldType FIELD_TYPE = new PercolatorFieldType(); private static final String EXTRACTED_TERMS_FIELD_NAME = "extracted_terms"; private static final String UNKNOWN_QUERY_FIELD_NAME = "unknown_query"; + private static final String QUERY_BUILDER_FIELD_NAME = "query_builder_field"; + public static final String EXTRACTED_TERMS_FULL_FIELD_NAME = NAME + "." + EXTRACTED_TERMS_FIELD_NAME; public static final String UNKNOWN_QUERY_FULL_FIELD_NAME = NAME + "." + UNKNOWN_QUERY_FIELD_NAME; + public static final String QUERY_BUILDER_FULL_FIELD_NAME = NAME + "." + QUERY_BUILDER_FIELD_NAME; public static class Builder extends FieldMapper.Builder { @@ -60,19 +76,29 @@ public class PercolatorFieldMapper extends FieldMapper { @Override public PercolatorFieldMapper build(BuilderContext context) { context.path().add(name); - KeywordFieldMapper extractedTermsField = createStringFieldBuilder(EXTRACTED_TERMS_FIELD_NAME).build(context); - KeywordFieldMapper unknownQueryField = createStringFieldBuilder(UNKNOWN_QUERY_FIELD_NAME).build(context); + KeywordFieldMapper extractedTermsField = createExtractQueryFieldBuilder(EXTRACTED_TERMS_FIELD_NAME).build(context); + KeywordFieldMapper unknownQueryField = createExtractQueryFieldBuilder(UNKNOWN_QUERY_FIELD_NAME).build(context); + BinaryFieldMapper queryBuilderField = createQueryBuilderFieldBuilder().build(context); context.path().remove(); - return new PercolatorFieldMapper(name(), fieldType, defaultFieldType, context.indexSettings(), multiFieldsBuilder.build(this, context), copyTo, queryShardContext, extractedTermsField, unknownQueryField); + return new PercolatorFieldMapper(name(), fieldType, defaultFieldType, context.indexSettings(), multiFieldsBuilder.build(this, context), copyTo, queryShardContext, extractedTermsField, unknownQueryField, queryBuilderField); } - static KeywordFieldMapper.Builder createStringFieldBuilder(String name) { + static KeywordFieldMapper.Builder createExtractQueryFieldBuilder(String name) { KeywordFieldMapper.Builder queryMetaDataFieldBuilder = new KeywordFieldMapper.Builder(name); queryMetaDataFieldBuilder.docValues(false); queryMetaDataFieldBuilder.store(false); queryMetaDataFieldBuilder.indexOptions(IndexOptions.DOCS); return queryMetaDataFieldBuilder; } + + static BinaryFieldMapper.Builder createQueryBuilderFieldBuilder() { + BinaryFieldMapper.Builder builder = new BinaryFieldMapper.Builder(QUERY_BUILDER_FIELD_NAME); + builder.docValues(true); + builder.indexOptions(IndexOptions.NONE); + builder.store(false); + builder.fieldType().setDocValuesType(DocValuesType.BINARY); + return builder; + } } public static class TypeParser implements FieldMapper.TypeParser { @@ -111,26 +137,81 @@ public class PercolatorFieldMapper extends FieldMapper { private final QueryShardContext queryShardContext; private final KeywordFieldMapper queryTermsField; private final KeywordFieldMapper unknownQueryField; + private final BinaryFieldMapper queryBuilderField; - public PercolatorFieldMapper(String simpleName, MappedFieldType fieldType, MappedFieldType defaultFieldType, Settings indexSettings, MultiFields multiFields, CopyTo copyTo, QueryShardContext queryShardContext, KeywordFieldMapper queryTermsField, KeywordFieldMapper unknownQueryField) { + public PercolatorFieldMapper(String simpleName, MappedFieldType fieldType, MappedFieldType defaultFieldType, + Settings indexSettings, MultiFields multiFields, CopyTo copyTo, QueryShardContext queryShardContext, + KeywordFieldMapper queryTermsField, KeywordFieldMapper unknownQueryField, + BinaryFieldMapper queryBuilderField) { super(simpleName, fieldType, defaultFieldType, indexSettings, multiFields, copyTo); this.queryShardContext = queryShardContext; this.queryTermsField = queryTermsField; this.unknownQueryField = unknownQueryField; - this.mapUnmappedFieldAsString = PercolatorQueriesRegistry.INDEX_MAP_UNMAPPED_FIELDS_AS_STRING_SETTING.get(indexSettings); + this.queryBuilderField = queryBuilderField; + this.mapUnmappedFieldAsString = PercolatorQueryCache.INDEX_MAP_UNMAPPED_FIELDS_AS_STRING_SETTING.get(indexSettings); } @Override public Mapper parse(ParseContext context) throws IOException { QueryShardContext queryShardContext = new QueryShardContext(this.queryShardContext); - Query query = PercolatorQueriesRegistry.parseQuery(queryShardContext, mapUnmappedFieldAsString, context.parser()); + QueryBuilder queryBuilder = parseQueryBuilder(queryShardContext.parseContext(), context.parser()); + // Fetching of terms, shapes and indexed scripts happen during this rewrite: + queryBuilder = queryBuilder.rewrite(queryShardContext); + + try (XContentBuilder builder = XContentFactory.contentBuilder(PercolatorQueryCache.QUERY_BUILDER_CONTENT_TYPE)) { + queryBuilder.toXContent(builder, new MapParams(Collections.emptyMap())); + builder.flush(); + byte[] queryBuilderAsBytes = builder.bytes().toBytes(); + context.doc().add(new Field(queryBuilderField.name(), queryBuilderAsBytes, queryBuilderField.fieldType())); + } + + Query query = toQuery(queryShardContext, mapUnmappedFieldAsString, queryBuilder); ExtractQueryTermsService.extractQueryTerms(query, context.doc(), queryTermsField.name(), unknownQueryField.name(), queryTermsField.fieldType()); return null; } + public static Query parseQuery(QueryShardContext context, boolean mapUnmappedFieldsAsString, XContentParser parser) throws IOException { + return toQuery(context, mapUnmappedFieldsAsString, parseQueryBuilder(context.parseContext(), parser)); + } + + static Query toQuery(QueryShardContext context, boolean mapUnmappedFieldsAsString, QueryBuilder queryBuilder) throws IOException { + context.reset(); + // This means that fields in the query need to exist in the mapping prior to registering this query + // The reason that this is required, is that if a field doesn't exist then the query assumes defaults, which may be undesired. + // + // Even worse when fields mentioned in percolator queries do go added to map after the queries have been registered + // then the percolator queries don't work as expected any more. + // + // Query parsing can't introduce new fields in mappings (which happens when registering a percolator query), + // because field type can't be inferred from queries (like document do) so the best option here is to disallow + // the usage of unmapped fields in percolator queries to avoid unexpected behaviour + // + // if index.percolator.map_unmapped_fields_as_string is set to true, query can contain unmapped fields which will be mapped + // as an analyzed string. + context.setAllowUnmappedFields(false); + context.setMapUnmappedFieldAsString(mapUnmappedFieldsAsString); + context.parseFieldMatcher(context.getIndexSettings().getParseFieldMatcher()); + try { + return queryBuilder.toQuery(context); + } finally { + context.reset(); + } + } + + static QueryBuilder parseQueryBuilder(QueryParseContext context, XContentParser parser) { + context.reset(parser); + try { + return context.parseInnerQueryBuilder(); + } catch (IOException e) { + throw new ParsingException(parser.getTokenLocation(), "Failed to parse", e); + } finally { + context.reset(null); + } + } + @Override public Iterator iterator() { - return Arrays.asList(queryTermsField, unknownQueryField).iterator(); + return Arrays.asList(queryTermsField, unknownQueryField, queryBuilderField).iterator(); } @Override diff --git a/core/src/main/java/org/elasticsearch/index/percolator/PercolatorHighlightSubFetchPhase.java b/core/src/main/java/org/elasticsearch/index/percolator/PercolatorHighlightSubFetchPhase.java new file mode 100644 index 00000000000..c1f9720b53b --- /dev/null +++ b/core/src/main/java/org/elasticsearch/index/percolator/PercolatorHighlightSubFetchPhase.java @@ -0,0 +1,141 @@ +/* + * Licensed to Elasticsearch under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch 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.elasticsearch.index.percolator; + +import org.apache.lucene.index.LeafReaderContext; +import org.apache.lucene.index.ReaderUtil; +import org.apache.lucene.search.BooleanClause; +import org.apache.lucene.search.BooleanQuery; +import org.apache.lucene.search.BoostQuery; +import org.apache.lucene.search.ConstantScoreQuery; +import org.apache.lucene.search.IndexSearcher; +import org.apache.lucene.search.Query; +import org.elasticsearch.common.bytes.BytesReference; +import org.elasticsearch.common.inject.Inject; +import org.elasticsearch.common.text.Text; +import org.elasticsearch.index.percolator.PercolatorFieldMapper; +import org.elasticsearch.index.percolator.PercolatorQueryCache; +import org.elasticsearch.index.query.ParsedQuery; +import org.elasticsearch.index.query.PercolatorQuery; +import org.elasticsearch.search.SearchParseElement; +import org.elasticsearch.search.fetch.FetchSubPhase; +import org.elasticsearch.search.highlight.HighlightPhase; +import org.elasticsearch.search.highlight.SearchContextHighlight; +import org.elasticsearch.search.internal.InternalSearchHit; +import org.elasticsearch.search.internal.SearchContext; +import org.elasticsearch.search.internal.SubSearchContext; + +import java.util.Collections; +import java.util.List; +import java.util.Map; + +// Highlighting in the case of the percolator query is a bit different, because the PercolatorQuery itself doesn't get highlighted, +// but the source of the PercolatorQuery gets highlighted by each hit with type '.percolator' (percolator queries). +public class PercolatorHighlightSubFetchPhase implements FetchSubPhase { + + private final HighlightPhase highlightPhase; + + @Inject + public PercolatorHighlightSubFetchPhase(HighlightPhase highlightPhase) { + this.highlightPhase = highlightPhase; + } + + @Override + public boolean hitsExecutionNeeded(SearchContext context) { + return context.highlight() != null && locatePercolatorQuery(context.query()) != null; + } + + @Override + public void hitsExecute(SearchContext context, InternalSearchHit[] hits) { + PercolatorQuery percolatorQuery = locatePercolatorQuery(context.query()); + if (percolatorQuery == null) { + // shouldn't happen as we checked for the existence of a percolator query in hitsExecutionNeeded(...) + throw new IllegalStateException("couldn't locate percolator query"); + } + + List ctxs = context.searcher().getIndexReader().leaves(); + PercolatorQueryCache queriesRegistry = context.percolatorQueryCache(); + IndexSearcher percolatorIndexSearcher = percolatorQuery.getPercolatorIndexSearcher(); + + LeafReaderContext percolatorLeafReaderContext = percolatorIndexSearcher.getIndexReader().leaves().get(0); + FetchSubPhase.HitContext hitContext = new FetchSubPhase.HitContext(); + SubSearchContext subSearchContext = + createSubSearchContext(context, percolatorLeafReaderContext, percolatorQuery.getDocumentSource()); + + for (InternalSearchHit hit : hits) { + if (PercolatorFieldMapper.TYPE_NAME.equals(hit.getType())) { + LeafReaderContext ctx = ctxs.get(ReaderUtil.subIndex(hit.docId(), ctxs)); + Query query = queriesRegistry.getQueries(ctx).getQuery(hit.docId() - ctx.docBase); + subSearchContext.parsedQuery(new ParsedQuery(query)); + hitContext.reset( + new InternalSearchHit(0, "unknown", new Text(percolatorQuery.getDocumentType()), Collections.emptyMap()), + percolatorLeafReaderContext, 0, percolatorIndexSearcher + ); + hitContext.cache().clear(); + highlightPhase.hitExecute(subSearchContext, hitContext); + hit.highlightFields().putAll(hitContext.hit().getHighlightFields()); + } + } + + } + + @Override + public Map parseElements() { + return Collections.emptyMap(); + } + + @Override + public boolean hitExecutionNeeded(SearchContext context) { + return false; + } + + @Override + public void hitExecute(SearchContext context, HitContext hitContext) { + } + + static PercolatorQuery locatePercolatorQuery(Query query) { + if (query instanceof PercolatorQuery) { + return (PercolatorQuery) query; + } else if (query instanceof BooleanQuery) { + for (BooleanClause clause : ((BooleanQuery) query).clauses()) { + PercolatorQuery result = locatePercolatorQuery(clause.getQuery()); + if (result != null) { + return result; + } + } + } else if (query instanceof ConstantScoreQuery) { + return locatePercolatorQuery(((ConstantScoreQuery) query).getQuery()); + } else if (query instanceof BoostQuery) { + return locatePercolatorQuery(((BoostQuery) query).getQuery()); + } + + return null; + } + + private SubSearchContext createSubSearchContext(SearchContext context, LeafReaderContext leafReaderContext, BytesReference source) { + SubSearchContext subSearchContext = new SubSearchContext(context); + subSearchContext.highlight(new SearchContextHighlight(context.highlight().fields())); + // Enforce highlighting by source, because MemoryIndex doesn't support stored fields. + subSearchContext.highlight().globalForceSource(true); + subSearchContext.lookup().source().setSegmentAndDocument(leafReaderContext, 0); + subSearchContext.lookup().source().setSource(source); + return subSearchContext; + } +} diff --git a/core/src/main/java/org/elasticsearch/index/percolator/PercolatorQueriesRegistry.java b/core/src/main/java/org/elasticsearch/index/percolator/PercolatorQueriesRegistry.java deleted file mode 100644 index 0a0cb9e96d9..00000000000 --- a/core/src/main/java/org/elasticsearch/index/percolator/PercolatorQueriesRegistry.java +++ /dev/null @@ -1,236 +0,0 @@ -/* - * Licensed to Elasticsearch under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch 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.elasticsearch.index.percolator; - -import org.apache.lucene.index.IndexReader; -import org.apache.lucene.index.Term; -import org.apache.lucene.search.IndexSearcher; -import org.apache.lucene.search.Query; -import org.apache.lucene.search.TermQuery; -import org.apache.lucene.util.BytesRef; -import org.elasticsearch.ElasticsearchException; -import org.elasticsearch.common.ParsingException; -import org.elasticsearch.common.bytes.BytesReference; -import org.elasticsearch.common.metrics.CounterMetric; -import org.elasticsearch.common.metrics.MeanMetric; -import org.elasticsearch.common.settings.Setting; -import org.elasticsearch.common.settings.Setting.Property; -import org.elasticsearch.common.util.concurrent.ConcurrentCollections; -import org.elasticsearch.common.xcontent.XContentHelper; -import org.elasticsearch.common.xcontent.XContentParser; -import org.elasticsearch.index.IndexSettings; -import org.elasticsearch.index.engine.Engine; -import org.elasticsearch.index.mapper.Uid; -import org.elasticsearch.index.mapper.internal.TypeFieldMapper; -import org.elasticsearch.index.mapper.internal.UidFieldMapper; -import org.elasticsearch.index.query.QueryShardContext; -import org.elasticsearch.index.shard.AbstractIndexShardComponent; -import org.elasticsearch.index.shard.ShardId; -import org.elasticsearch.percolator.PercolatorService; - -import java.io.Closeable; -import java.io.IOException; -import java.util.Map; -import java.util.concurrent.ConcurrentMap; -import java.util.concurrent.TimeUnit; - -/** - * Each shard will have a percolator registry even if there isn't a {@link PercolatorService#TYPE_NAME} document type in the index. - * For shards with indices that have no {@link PercolatorService#TYPE_NAME} document type, this will hold no percolate queries. - *

- * Once a document type has been created, the real-time percolator will start to listen to write events and update the - * this registry with queries in real time. - */ -public final class PercolatorQueriesRegistry extends AbstractIndexShardComponent implements Closeable { - - public final static Setting INDEX_MAP_UNMAPPED_FIELDS_AS_STRING_SETTING = - Setting.boolSetting("index.percolator.map_unmapped_fields_as_string", false, Property.IndexScope); - - private final ConcurrentMap percolateQueries = ConcurrentCollections.newConcurrentMapWithAggressiveConcurrency(); - private final QueryShardContext queryShardContext; - private boolean mapUnmappedFieldsAsString; - private final MeanMetric percolateMetric = new MeanMetric(); - private final CounterMetric currentMetric = new CounterMetric(); - private final CounterMetric numberOfQueries = new CounterMetric(); - - public PercolatorQueriesRegistry(ShardId shardId, IndexSettings indexSettings, QueryShardContext queryShardContext) { - super(shardId, indexSettings); - this.queryShardContext = queryShardContext; - this.mapUnmappedFieldsAsString = indexSettings.getValue(INDEX_MAP_UNMAPPED_FIELDS_AS_STRING_SETTING); - } - - public ConcurrentMap getPercolateQueries() { - return percolateQueries; - } - - @Override - public void close() { - clear(); - } - - public void clear() { - percolateQueries.clear(); - } - - - public void addPercolateQuery(String idAsString, BytesReference source) { - Query newquery = parsePercolatorDocument(idAsString, source); - BytesRef id = new BytesRef(idAsString); - percolateQueries.put(id, newquery); - numberOfQueries.inc(); - - } - - public void removePercolateQuery(String idAsString) { - BytesRef id = new BytesRef(idAsString); - Query query = percolateQueries.remove(id); - if (query != null) { - numberOfQueries.dec(); - } - } - - public Query parsePercolatorDocument(String id, BytesReference source) { - try (XContentParser sourceParser = XContentHelper.createParser(source)) { - String currentFieldName = null; - XContentParser.Token token = sourceParser.nextToken(); // move the START_OBJECT - if (token != XContentParser.Token.START_OBJECT) { - throw new ElasticsearchException("failed to parse query [" + id + "], not starting with OBJECT"); - } - while ((token = sourceParser.nextToken()) != XContentParser.Token.END_OBJECT) { - if (token == XContentParser.Token.FIELD_NAME) { - currentFieldName = sourceParser.currentName(); - } else if (token == XContentParser.Token.START_OBJECT) { - if ("query".equals(currentFieldName)) { - return parseQuery(queryShardContext, mapUnmappedFieldsAsString, sourceParser); - } else { - sourceParser.skipChildren(); - } - } else if (token == XContentParser.Token.START_ARRAY) { - sourceParser.skipChildren(); - } - } - } catch (Exception e) { - throw new PercolatorException(shardId().getIndex(), "failed to parse query [" + id + "]", e); - } - return null; - } - - public static Query parseQuery(QueryShardContext queryShardContext, boolean mapUnmappedFieldsAsString, XContentParser parser) { - QueryShardContext context = new QueryShardContext(queryShardContext); - try { - context.reset(parser); - // This means that fields in the query need to exist in the mapping prior to registering this query - // The reason that this is required, is that if a field doesn't exist then the query assumes defaults, which may be undesired. - // - // Even worse when fields mentioned in percolator queries do go added to map after the queries have been registered - // then the percolator queries don't work as expected any more. - // - // Query parsing can't introduce new fields in mappings (which happens when registering a percolator query), - // because field type can't be inferred from queries (like document do) so the best option here is to disallow - // the usage of unmapped fields in percolator queries to avoid unexpected behaviour - // - // if index.percolator.map_unmapped_fields_as_string is set to true, query can contain unmapped fields which will be mapped - // as an analyzed string. - context.setAllowUnmappedFields(false); - context.setMapUnmappedFieldAsString(mapUnmappedFieldsAsString); - return context.parseInnerQuery(); - } catch (IOException e) { - throw new ParsingException(parser.getTokenLocation(), "Failed to parse", e); - } finally { - context.reset(null); - } - } - - public void loadQueries(IndexReader reader) { - logger.trace("loading percolator queries..."); - final int loadedQueries; - try { - Query query = new TermQuery(new Term(TypeFieldMapper.NAME, PercolatorService.TYPE_NAME)); - QueriesLoaderCollector queryCollector = new QueriesLoaderCollector(PercolatorQueriesRegistry.this, logger); - IndexSearcher indexSearcher = new IndexSearcher(reader); - indexSearcher.setQueryCache(null); - indexSearcher.search(query, queryCollector); - Map queries = queryCollector.queries(); - for (Map.Entry entry : queries.entrySet()) { - percolateQueries.put(entry.getKey(), entry.getValue()); - numberOfQueries.inc(); - } - loadedQueries = queries.size(); - } catch (Exception e) { - throw new PercolatorException(shardId.getIndex(), "failed to load queries from percolator index", e); - } - logger.debug("done loading [{}] percolator queries", loadedQueries); - } - - public boolean isPercolatorQuery(Engine.Index operation) { - if (PercolatorService.TYPE_NAME.equals(operation.type())) { - parsePercolatorDocument(operation.id(), operation.source()); - return true; - } - return false; - } - - public boolean isPercolatorQuery(Engine.Delete operation) { - return PercolatorService.TYPE_NAME.equals(operation.type()); - } - - public synchronized void updatePercolateQuery(Engine engine, String id) { - // this can be called out of order as long as for every change to a percolator document it's invoked. This will always - // fetch the latest change but might fetch the same change twice if updates / deletes happen concurrently. - try (Engine.GetResult getResult = engine.get(new Engine.Get(true, new Term(UidFieldMapper.NAME, Uid.createUidAsBytes(PercolatorService.TYPE_NAME, id))))) { - if (getResult.exists()) { - addPercolateQuery(id, getResult.source().source); - } else { - removePercolateQuery(id); - } - } - } - - public void prePercolate() { - currentMetric.inc(); - } - - public void postPercolate(long tookInNanos) { - currentMetric.dec(); - percolateMetric.inc(tookInNanos); - } - - /** - * @return The current metrics - */ - public PercolateStats stats() { - return new PercolateStats(percolateMetric.count(), TimeUnit.NANOSECONDS.toMillis(percolateMetric.sum()), currentMetric.count(), -1, numberOfQueries.count()); - } - - // Enable when a more efficient manner is found for estimating the size of a Lucene query. - /*private static long computeSizeInMemory(HashedBytesRef id, Query query) { - long size = (3 * RamUsageEstimator.NUM_BYTES_INT) + RamUsageEstimator.NUM_BYTES_OBJECT_REF + RamUsageEstimator.NUM_BYTES_OBJECT_HEADER + id.bytes.bytes.length; - size += RamEstimator.sizeOf(query); - return size; - } - - private static final class RamEstimator { - // we move this into it's own class to exclude it from the forbidden API checks - // it's fine to use here! - static long sizeOf(Query query) { - return RamUsageEstimator.sizeOf(query); - } - }*/ -} diff --git a/core/src/main/java/org/elasticsearch/index/percolator/PercolatorQueryCache.java b/core/src/main/java/org/elasticsearch/index/percolator/PercolatorQueryCache.java new file mode 100644 index 00000000000..7c9602b4909 --- /dev/null +++ b/core/src/main/java/org/elasticsearch/index/percolator/PercolatorQueryCache.java @@ -0,0 +1,266 @@ +/* + * Licensed to Elasticsearch under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch 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.elasticsearch.index.percolator; + +import com.carrotsearch.hppc.IntObjectHashMap; +import org.apache.lucene.index.BinaryDocValues; +import org.apache.lucene.index.FieldInfo; +import org.apache.lucene.index.LeafReader; +import org.apache.lucene.index.LeafReaderContext; +import org.apache.lucene.index.PostingsEnum; +import org.apache.lucene.index.StoredFieldVisitor; +import org.apache.lucene.index.Term; +import org.apache.lucene.search.DocIdSetIterator; +import org.apache.lucene.search.Query; +import org.apache.lucene.util.Bits; +import org.apache.lucene.util.BytesRef; +import org.elasticsearch.ElasticsearchException; +import org.elasticsearch.Version; +import org.elasticsearch.common.bytes.BytesArray; +import org.elasticsearch.common.bytes.BytesReference; +import org.elasticsearch.common.cache.Cache; +import org.elasticsearch.common.cache.CacheBuilder; +import org.elasticsearch.common.lucene.index.ElasticsearchLeafReader; +import org.elasticsearch.common.settings.Setting; +import org.elasticsearch.common.unit.TimeValue; +import org.elasticsearch.common.xcontent.XContent; +import org.elasticsearch.common.xcontent.XContentFactory; +import org.elasticsearch.common.xcontent.XContentHelper; +import org.elasticsearch.common.xcontent.XContentParser; +import org.elasticsearch.common.xcontent.XContentType; +import org.elasticsearch.index.AbstractIndexComponent; +import org.elasticsearch.index.IndexSettings; +import org.elasticsearch.index.IndexWarmer; +import org.elasticsearch.index.engine.Engine; +import org.elasticsearch.index.mapper.internal.SourceFieldMapper; +import org.elasticsearch.index.mapper.internal.TypeFieldMapper; +import org.elasticsearch.index.query.PercolatorQuery; +import org.elasticsearch.index.query.QueryShardContext; +import org.elasticsearch.index.shard.IndexShard; +import org.elasticsearch.index.shard.ShardId; +import org.elasticsearch.index.shard.ShardUtils; +import org.elasticsearch.threadpool.ThreadPool; + +import java.io.Closeable; +import java.io.IOException; +import java.util.concurrent.CountDownLatch; +import java.util.concurrent.Executor; +import java.util.function.Supplier; + +public final class PercolatorQueryCache extends AbstractIndexComponent + implements Closeable, LeafReader.CoreClosedListener, PercolatorQuery.QueryRegistry { + + public final static Setting INDEX_MAP_UNMAPPED_FIELDS_AS_STRING_SETTING = + Setting.boolSetting("index.percolator.map_unmapped_fields_as_string", false, Setting.Property.IndexScope); + + public final static XContentType QUERY_BUILDER_CONTENT_TYPE = XContentType.SMILE; + + private final Supplier queryShardContextSupplier; + private final Cache cache; + private final boolean mapUnmappedFieldsAsString; + + public PercolatorQueryCache(IndexSettings indexSettings, Supplier queryShardContextSupplier) { + super(indexSettings); + this.queryShardContextSupplier = queryShardContextSupplier; + cache = CacheBuilder.builder().build(); + this.mapUnmappedFieldsAsString = indexSettings.getValue(INDEX_MAP_UNMAPPED_FIELDS_AS_STRING_SETTING); + } + + @Override + public Leaf getQueries(LeafReaderContext ctx) { + QueriesLeaf percolatorQueries = cache.get(ctx.reader().getCoreCacheKey()); + if (percolatorQueries == null) { + throw new IllegalStateException("queries not loaded, queries should be have been preloaded during index warming..."); + } + return percolatorQueries; + } + + public IndexWarmer.Listener createListener(ThreadPool threadPool) { + return new IndexWarmer.Listener() { + + final Executor executor = threadPool.executor(ThreadPool.Names.WARMER); + + @Override + public IndexWarmer.TerminationHandle warmNewReaders(IndexShard indexShard, Engine.Searcher searcher) { + final CountDownLatch latch = new CountDownLatch(searcher.reader().leaves().size()); + for (final LeafReaderContext ctx : searcher.reader().leaves()) { + executor.execute(() -> { + try { + final long start = System.nanoTime(); + QueriesLeaf queries = loadQueries(ctx, indexShard.indexSettings().getIndexVersionCreated()); + cache.put(ctx.reader().getCoreCacheKey(), queries); + if (indexShard.warmerService().logger().isTraceEnabled()) { + indexShard.warmerService().logger().trace( + "loading percolator queries took [{}]", + TimeValue.timeValueNanos(System.nanoTime() - start) + ); + } + } catch (Throwable t) { + indexShard.warmerService().logger().warn("failed to load percolator queries", t); + } finally { + latch.countDown(); + } + }); + } + return () -> latch.await(); + } + + @Override + public IndexWarmer.TerminationHandle warmTopReader(IndexShard indexShard, Engine.Searcher searcher) { + return IndexWarmer.TerminationHandle.NO_WAIT; + } + }; + } + + QueriesLeaf loadQueries(LeafReaderContext context, Version indexVersionCreated) throws IOException { + LeafReader leafReader = context.reader(); + ShardId shardId = ShardUtils.extractShardId(leafReader); + if (shardId == null) { + throw new IllegalStateException("can't resolve shard id"); + } + if (indexSettings.getIndex().equals(shardId.getIndex()) == false) { + // percolator cache insanity + String message = "Trying to load queries for index " + shardId.getIndex() + " with cache of index " + indexSettings.getIndex(); + throw new IllegalStateException(message); + } + + IntObjectHashMap queries = new IntObjectHashMap<>(); + boolean legacyLoading = indexVersionCreated.before(Version.V_5_0_0); + PostingsEnum postings = leafReader.postings(new Term(TypeFieldMapper.NAME, PercolatorFieldMapper.TYPE_NAME), PostingsEnum.NONE); + if (postings != null) { + if (legacyLoading) { + LegacyQueryFieldVisitor visitor = new LegacyQueryFieldVisitor(); + for (int docId = postings.nextDoc(); docId != DocIdSetIterator.NO_MORE_DOCS; docId = postings.nextDoc()) { + leafReader.document(docId, visitor); + queries.put(docId, parseLegacyPercolatorDocument(docId, visitor.source)); + visitor.source = null; // reset + } + } else { + BinaryDocValues binaryDocValues = leafReader.getBinaryDocValues(PercolatorFieldMapper.QUERY_BUILDER_FULL_FIELD_NAME); + if (binaryDocValues != null) { + for (int docId = postings.nextDoc(); docId != DocIdSetIterator.NO_MORE_DOCS; docId = postings.nextDoc()) { + BytesRef queryBuilder = binaryDocValues.get(docId); + if (queryBuilder.length > 0) { + queries.put(docId, parseQueryBuilder(docId, queryBuilder)); + } + } + } + } + } + leafReader.addCoreClosedListener(this); + return new QueriesLeaf(shardId, queries); + } + + private Query parseQueryBuilder(int docId, BytesRef queryBuilder) { + XContent xContent = QUERY_BUILDER_CONTENT_TYPE.xContent(); + try (XContentParser sourceParser = xContent.createParser(queryBuilder.bytes, queryBuilder.offset, queryBuilder.length)) { + QueryShardContext context = queryShardContextSupplier.get(); + return PercolatorFieldMapper.parseQuery(context, mapUnmappedFieldsAsString, sourceParser); + } catch (IOException e) { + throw new PercolatorException(index(), "failed to parse query builder for document [" + docId + "]", e); + } + } + + private Query parseLegacyPercolatorDocument(int docId, BytesReference source) { + try (XContentParser sourceParser = XContentHelper.createParser(source)) { + String currentFieldName = null; + XContentParser.Token token = sourceParser.nextToken(); // move the START_OBJECT + if (token != XContentParser.Token.START_OBJECT) { + throw new ElasticsearchException("failed to parse query [" + docId + "], not starting with OBJECT"); + } + while ((token = sourceParser.nextToken()) != XContentParser.Token.END_OBJECT) { + if (token == XContentParser.Token.FIELD_NAME) { + currentFieldName = sourceParser.currentName(); + } else if (token == XContentParser.Token.START_OBJECT) { + if ("query".equals(currentFieldName)) { + QueryShardContext context = queryShardContextSupplier.get(); + return PercolatorFieldMapper.parseQuery(context, mapUnmappedFieldsAsString, sourceParser); + } else { + sourceParser.skipChildren(); + } + } else if (token == XContentParser.Token.START_ARRAY) { + sourceParser.skipChildren(); + } + } + } catch (Exception e) { + throw new PercolatorException(index(), "failed to parse query [" + docId + "]", e); + } + return null; + } + + public PercolatorQueryCacheStats getStats(ShardId shardId) { + int numberOfQueries = 0; + for (QueriesLeaf queries : cache.values()) { + if (shardId.equals(queries.shardId)) { + numberOfQueries += queries.queries.size(); + } + } + return new PercolatorQueryCacheStats(numberOfQueries); + } + + @Override + public void onClose(Object cacheKey) throws IOException { + cache.invalidate(cacheKey); + } + + @Override + public void close() throws IOException { + cache.invalidateAll(); + } + + final static class LegacyQueryFieldVisitor extends StoredFieldVisitor { + + private BytesArray source; + + @Override + public void binaryField(FieldInfo fieldInfo, byte[] bytes) throws IOException { + source = new BytesArray(bytes); + } + + @Override + public Status needsField(FieldInfo fieldInfo) throws IOException { + if (source != null) { + return Status.STOP; + } + if (SourceFieldMapper.NAME.equals(fieldInfo.name)) { + return Status.YES; + } else { + return Status.NO; + } + } + + } + + final static class QueriesLeaf implements Leaf { + + final ShardId shardId; + final IntObjectHashMap queries; + + QueriesLeaf(ShardId shardId, IntObjectHashMap queries) { + this.shardId = shardId; + this.queries = queries; + } + + @Override + public Query getQuery(int docId) { + return queries.get(docId); + } + } +} diff --git a/core/src/main/java/org/elasticsearch/index/percolator/PercolatorQueryCacheStats.java b/core/src/main/java/org/elasticsearch/index/percolator/PercolatorQueryCacheStats.java new file mode 100644 index 00000000000..a8e3b7f4799 --- /dev/null +++ b/core/src/main/java/org/elasticsearch/index/percolator/PercolatorQueryCacheStats.java @@ -0,0 +1,90 @@ +/* + * Licensed to Elasticsearch under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch 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.elasticsearch.index.percolator; + +import org.elasticsearch.common.io.stream.StreamInput; +import org.elasticsearch.common.io.stream.StreamOutput; +import org.elasticsearch.common.io.stream.Streamable; +import org.elasticsearch.common.xcontent.ToXContent; +import org.elasticsearch.common.xcontent.XContentBuilder; +import org.elasticsearch.common.xcontent.XContentBuilderString; + +import java.io.IOException; + +/** + * Exposes percolator query cache statistics. + */ +public class PercolatorQueryCacheStats implements Streamable, ToXContent { + + private long numQueries; + + /** + * Noop constructor for serialization purposes. + */ + public PercolatorQueryCacheStats() { + } + + PercolatorQueryCacheStats(long numQueries) { + this.numQueries = numQueries; + } + + /** + * @return The total number of loaded percolate queries. + */ + public long getNumQueries() { + return numQueries; + } + + @Override + public XContentBuilder toXContent(XContentBuilder builder, Params params) throws IOException { + builder.startObject(Fields.PERCOLATOR); + builder.field(Fields.QUERIES, getNumQueries()); + builder.endObject(); + return builder; + } + + public void add(PercolatorQueryCacheStats percolate) { + if (percolate == null) { + return; + } + + numQueries += percolate.getNumQueries(); + } + + static final class Fields { + static final XContentBuilderString PERCOLATOR = new XContentBuilderString("percolator"); + static final XContentBuilderString QUERIES = new XContentBuilderString("num_queries"); + } + + public static PercolatorQueryCacheStats readPercolateStats(StreamInput in) throws IOException { + PercolatorQueryCacheStats stats = new PercolatorQueryCacheStats(); + stats.readFrom(in); + return stats; + } + + @Override + public void readFrom(StreamInput in) throws IOException { + numQueries = in.readVLong(); + } + + @Override + public void writeTo(StreamOutput out) throws IOException { + out.writeVLong(numQueries); + } +} diff --git a/core/src/main/java/org/elasticsearch/index/percolator/QueriesLoaderCollector.java b/core/src/main/java/org/elasticsearch/index/percolator/QueriesLoaderCollector.java deleted file mode 100644 index 1bea43e4ea1..00000000000 --- a/core/src/main/java/org/elasticsearch/index/percolator/QueriesLoaderCollector.java +++ /dev/null @@ -1,94 +0,0 @@ -/* - * Licensed to Elasticsearch under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch 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.elasticsearch.index.percolator; - -import org.apache.lucene.index.LeafReader; -import org.apache.lucene.index.LeafReaderContext; -import org.apache.lucene.search.Query; -import org.apache.lucene.search.Scorer; -import org.apache.lucene.search.SimpleCollector; -import org.apache.lucene.util.BytesRef; -import org.elasticsearch.common.logging.ESLogger; -import org.elasticsearch.index.fielddata.IndexFieldData; -import org.elasticsearch.index.fielddata.IndexFieldDataService; -import org.elasticsearch.index.fielddata.SortedBinaryDocValues; -import org.elasticsearch.index.fieldvisitor.FieldsVisitor; -import org.elasticsearch.index.mapper.MappedFieldType; -import org.elasticsearch.index.mapper.MapperService; -import org.elasticsearch.index.mapper.Uid; -import org.elasticsearch.index.mapper.internal.UidFieldMapper; - -import java.io.IOException; -import java.util.HashMap; -import java.util.Map; - -/** - */ -final class QueriesLoaderCollector extends SimpleCollector { - - private final Map queries = new HashMap<>(); - private final FieldsVisitor fieldsVisitor = new FieldsVisitor(true); - private final PercolatorQueriesRegistry percolator; - private final ESLogger logger; - - private LeafReader reader; - - QueriesLoaderCollector(PercolatorQueriesRegistry percolator, ESLogger logger) { - this.percolator = percolator; - this.logger = logger; - } - - public Map queries() { - return this.queries; - } - - @Override - public void collect(int doc) throws IOException { - fieldsVisitor.reset(); - reader.document(doc, fieldsVisitor); - final Uid uid = fieldsVisitor.uid(); - - try { - // id is only used for logging, if we fail we log the id in the catch statement - final Query parseQuery = percolator.parsePercolatorDocument(null, fieldsVisitor.source()); - if (parseQuery != null) { - queries.put(new BytesRef(uid.id()), parseQuery); - } else { - logger.warn("failed to add query [{}] - parser returned null", uid); - } - - } catch (Exception e) { - logger.warn("failed to add query [{}]", e, uid); - } - } - - @Override - protected void doSetNextReader(LeafReaderContext context) throws IOException { - reader = context.reader(); - } - - @Override - public void setScorer(Scorer scorer) throws IOException { - } - - @Override - public boolean needsScores() { - return false; - } -} diff --git a/core/src/main/java/org/elasticsearch/index/query/HasChildQueryBuilder.java b/core/src/main/java/org/elasticsearch/index/query/HasChildQueryBuilder.java index 3c5ca1ce444..324552d7b54 100644 --- a/core/src/main/java/org/elasticsearch/index/query/HasChildQueryBuilder.java +++ b/core/src/main/java/org/elasticsearch/index/query/HasChildQueryBuilder.java @@ -189,7 +189,7 @@ public class HasChildQueryBuilder extends AbstractQueryBuilderhas_child queries. @@ -104,12 +105,21 @@ public class HasChildQueryParser implements QueryParser { return ScoreMode.Max; } else if ("avg".equals(scoreModeString)) { return ScoreMode.Avg; - } else if ("total".equals(scoreModeString)) { + } else if ("sum".equals(scoreModeString)) { return ScoreMode.Total; } throw new IllegalArgumentException("No score mode for child query [" + scoreModeString + "] found"); } + public static String scoreModeAsString(ScoreMode scoreMode) { + if (scoreMode == ScoreMode.Total) { + // Lucene uses 'total' but 'sum' is more consistent with other elasticsearch APIs + return "sum"; + } else { + return scoreMode.name().toLowerCase(Locale.ROOT); + } + } + @Override public HasChildQueryBuilder getBuilderPrototype() { return HasChildQueryBuilder.PROTOTYPE; diff --git a/core/src/main/java/org/elasticsearch/index/query/NestedQueryBuilder.java b/core/src/main/java/org/elasticsearch/index/query/NestedQueryBuilder.java index 596c2499211..bd5f348db33 100644 --- a/core/src/main/java/org/elasticsearch/index/query/NestedQueryBuilder.java +++ b/core/src/main/java/org/elasticsearch/index/query/NestedQueryBuilder.java @@ -121,7 +121,7 @@ public class NestedQueryBuilder extends AbstractQueryBuilder query.toXContent(builder, params); builder.field(NestedQueryParser.PATH_FIELD.getPreferredName(), path); if (scoreMode != null) { - builder.field(NestedQueryParser.SCORE_MODE_FIELD.getPreferredName(), scoreMode.name().toLowerCase(Locale.ROOT)); + builder.field(NestedQueryParser.SCORE_MODE_FIELD.getPreferredName(), HasChildQueryParser.scoreModeAsString(scoreMode)); } printBoostAndQueryName(builder); if (queryInnerHits != null) { diff --git a/core/src/main/java/org/elasticsearch/index/query/NestedQueryParser.java b/core/src/main/java/org/elasticsearch/index/query/NestedQueryParser.java index ba5d7c2447e..218919f7ed2 100644 --- a/core/src/main/java/org/elasticsearch/index/query/NestedQueryParser.java +++ b/core/src/main/java/org/elasticsearch/index/query/NestedQueryParser.java @@ -68,20 +68,7 @@ public class NestedQueryParser implements QueryParser { } else if (parseContext.parseFieldMatcher().match(currentFieldName, AbstractQueryBuilder.BOOST_FIELD)) { boost = parser.floatValue(); } else if (parseContext.parseFieldMatcher().match(currentFieldName, SCORE_MODE_FIELD)) { - String sScoreMode = parser.text(); - if ("avg".equals(sScoreMode)) { - scoreMode = ScoreMode.Avg; - } else if ("min".equals(sScoreMode)) { - scoreMode = ScoreMode.Min; - } else if ("max".equals(sScoreMode)) { - scoreMode = ScoreMode.Max; - } else if ("total".equals(sScoreMode) || "sum".equals(sScoreMode)) { - scoreMode = ScoreMode.Total; - } else if ("none".equals(sScoreMode)) { - scoreMode = ScoreMode.None; - } else { - throw new ParsingException(parser.getTokenLocation(), "illegal score_mode for nested query [" + sScoreMode + "]"); - } + scoreMode = HasChildQueryParser.parseScoreMode(parser.text()); } else if (parseContext.parseFieldMatcher().match(currentFieldName, AbstractQueryBuilder.NAME_FIELD)) { queryName = parser.text(); } else { diff --git a/core/src/main/java/org/elasticsearch/index/query/ParentIdQueryBuilder.java b/core/src/main/java/org/elasticsearch/index/query/ParentIdQueryBuilder.java index f9bd7623f35..4a2efa95c9a 100644 --- a/core/src/main/java/org/elasticsearch/index/query/ParentIdQueryBuilder.java +++ b/core/src/main/java/org/elasticsearch/index/query/ParentIdQueryBuilder.java @@ -19,13 +19,18 @@ package org.elasticsearch.index.query; +import org.apache.lucene.index.Term; +import org.apache.lucene.search.BooleanClause; +import org.apache.lucene.search.BooleanQuery; import org.apache.lucene.search.DocValuesTermsQuery; import org.apache.lucene.search.Query; +import org.apache.lucene.search.TermQuery; import org.elasticsearch.common.io.stream.StreamInput; import org.elasticsearch.common.io.stream.StreamOutput; import org.elasticsearch.common.xcontent.XContentBuilder; import org.elasticsearch.index.mapper.DocumentMapper; import org.elasticsearch.index.mapper.internal.ParentFieldMapper; +import org.elasticsearch.index.mapper.internal.TypeFieldMapper; import java.io.IOException; import java.util.Objects; @@ -71,7 +76,12 @@ public final class ParentIdQueryBuilder extends AbstractQueryBuilder percolatorQueries; - private Query percolateQuery; private Query queriesMetaDataQuery; private final Query percolateTypeQuery; /** - * @param percolatorIndexSearcher The index searcher on top of the in-memory index that holds the document being percolated - * @param percolatorQueries All the registered percolator queries - * @param percolateTypeQuery A query that identifies all document containing percolator queries + * @param docType The type of the document being percolated + * @param queryRegistry The registry holding all the percolator queries as Lucene queries. + * @param documentSource The source of the document being percolated + * @param percolatorIndexSearcher The index searcher on top of the in-memory index that holds the document being percolated + * @param percolateTypeQuery A query that identifies all document containing percolator queries */ - Builder(IndexSearcher percolatorIndexSearcher, Map percolatorQueries, Query percolateTypeQuery) { - this.percolatorIndexSearcher = percolatorIndexSearcher; - this.percolatorQueries = percolatorQueries; - this.percolateTypeQuery = percolateTypeQuery; - } - - /** - * Optionally sets a query that reduces the number of queries to percolate based on custom metadata attached - * on the percolator documents. - */ - void setPercolateQuery(Query percolateQuery) { - this.percolateQuery = percolateQuery; + public Builder(String docType, QueryRegistry queryRegistry, BytesReference documentSource, IndexSearcher percolatorIndexSearcher, + Query percolateTypeQuery) { + this.docType = Objects.requireNonNull(docType); + this.documentSource = Objects.requireNonNull(documentSource); + this.percolatorIndexSearcher = Objects.requireNonNull(percolatorIndexSearcher); + this.queryRegistry = Objects.requireNonNull(queryRegistry); + this.percolateTypeQuery = Objects.requireNonNull(percolateTypeQuery); } /** @@ -85,39 +81,43 @@ final class PercolatorQuery extends Query { * @param extractedTermsFieldName The name of the field to get the extracted terms from * @param unknownQueryFieldname The field used to mark documents whose queries couldn't all get extracted */ - void extractQueryTermsQuery(String extractedTermsFieldName, String unknownQueryFieldname) throws IOException { - this.queriesMetaDataQuery = ExtractQueryTermsService.createQueryTermsQuery(percolatorIndexSearcher.getIndexReader(), extractedTermsFieldName, unknownQueryFieldname); + public void extractQueryTermsQuery(String extractedTermsFieldName, String unknownQueryFieldname) throws IOException { + this.queriesMetaDataQuery = ExtractQueryTermsService.createQueryTermsQuery( + percolatorIndexSearcher.getIndexReader(), extractedTermsFieldName, unknownQueryFieldname + ); } - PercolatorQuery build() { + public PercolatorQuery build() { BooleanQuery.Builder builder = new BooleanQuery.Builder(); builder.add(percolateTypeQuery, FILTER); if (queriesMetaDataQuery != null) { builder.add(queriesMetaDataQuery, FILTER); } - if (percolateQuery != null){ - builder.add(percolateQuery, MUST); - } - return new PercolatorQuery(builder.build(), percolatorIndexSearcher, percolatorQueries); + return new PercolatorQuery(docType, queryRegistry, documentSource, builder.build(), percolatorIndexSearcher); } } + private final String documentType; + private final QueryRegistry queryRegistry; + private final BytesReference documentSource; private final Query percolatorQueriesQuery; private final IndexSearcher percolatorIndexSearcher; - private final Map percolatorQueries; - private PercolatorQuery(Query percolatorQueriesQuery, IndexSearcher percolatorIndexSearcher, Map percolatorQueries) { + private PercolatorQuery(String documentType, QueryRegistry queryRegistry, BytesReference documentSource, + Query percolatorQueriesQuery, IndexSearcher percolatorIndexSearcher) { + this.documentType = documentType; + this.documentSource = documentSource; this.percolatorQueriesQuery = percolatorQueriesQuery; + this.queryRegistry = queryRegistry; this.percolatorIndexSearcher = percolatorIndexSearcher; - this.percolatorQueries = percolatorQueries; } @Override public Query rewrite(IndexReader reader) throws IOException { Query rewritten = percolatorQueriesQuery.rewrite(reader); if (rewritten != percolatorQueriesQuery) { - return new PercolatorQuery(rewritten, percolatorIndexSearcher, percolatorQueries); + return new PercolatorQuery(documentType, queryRegistry, documentSource, rewritten, percolatorIndexSearcher); } else { return this; } @@ -160,7 +160,7 @@ final class PercolatorQuery extends Query { return null; } - final LeafReader leafReader = leafReaderContext.reader(); + final QueryRegistry.Leaf percolatorQueries = queryRegistry.getQueries(leafReaderContext); return new Scorer(this) { @Override @@ -173,7 +173,7 @@ final class PercolatorQuery extends Query { return new TwoPhaseIterator(approximation.iterator()) { @Override public boolean matches() throws IOException { - return matchDocId(approximation.docID(), leafReader); + return matchDocId(approximation.docID()); } @Override @@ -198,27 +198,30 @@ final class PercolatorQuery extends Query { return approximation.docID(); } - boolean matchDocId(int docId, LeafReader leafReader) throws IOException { - SingleFieldsVisitor singleFieldsVisitor = new SingleFieldsVisitor(UidFieldMapper.NAME); - leafReader.document(docId, singleFieldsVisitor); - BytesRef percolatorQueryId = new BytesRef(singleFieldsVisitor.uid().id()); - return matchQuery(percolatorQueryId); + boolean matchDocId(int docId) throws IOException { + Query query = percolatorQueries.getQuery(docId); + if (query != null) { + return Lucene.exists(percolatorIndexSearcher, query); + } else { + return false; + } } }; } }; } - boolean matchQuery(BytesRef percolatorQueryId) throws IOException { - Query percolatorQuery = percolatorQueries.get(percolatorQueryId); - if (percolatorQuery != null) { - return Lucene.exists(percolatorIndexSearcher, percolatorQuery); - } else { - return false; - } + public IndexSearcher getPercolatorIndexSearcher() { + return percolatorIndexSearcher; } - private final Object instance = new Object(); + public String getDocumentType() { + return documentType; + } + + public BytesReference getDocumentSource() { + return documentSource; + } @Override public boolean equals(Object o) { @@ -228,19 +231,46 @@ final class PercolatorQuery extends Query { PercolatorQuery that = (PercolatorQuery) o; - return instance.equals(that.instance); + if (!documentType.equals(that.documentType)) return false; + return documentSource.equals(that.documentSource); } @Override public int hashCode() { int result = super.hashCode(); - result = 31 * result + instance.hashCode(); + result = 31 * result + documentType.hashCode(); + result = 31 * result + documentSource.hashCode(); return result; } @Override public String toString(String s) { - return "PercolatorQuery{inner={" + percolatorQueriesQuery.toString(s) + "}}"; + return "PercolatorQuery{document_type={" + documentType + "},document_source={" + documentSource.toUtf8() + + "},inner={" + percolatorQueriesQuery.toString(s) + "}}"; } + + @Override + public long ramBytesUsed() { + long sizeInBytes = 0; + if (documentSource.hasArray()) { + sizeInBytes += documentSource.array().length; + } else { + sizeInBytes += documentSource.length(); + } + return sizeInBytes; + } + + public interface QueryRegistry { + + Leaf getQueries(LeafReaderContext ctx); + + interface Leaf { + + Query getQuery(int docId); + + } + + } + } diff --git a/core/src/main/java/org/elasticsearch/index/query/PercolatorQueryBuilder.java b/core/src/main/java/org/elasticsearch/index/query/PercolatorQueryBuilder.java new file mode 100644 index 00000000000..5cb1e54d203 --- /dev/null +++ b/core/src/main/java/org/elasticsearch/index/query/PercolatorQueryBuilder.java @@ -0,0 +1,375 @@ +/* + * Licensed to Elasticsearch under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch 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.elasticsearch.index.query; + +import org.apache.lucene.analysis.Analyzer; +import org.apache.lucene.analysis.TokenStream; +import org.apache.lucene.index.IndexOptions; +import org.apache.lucene.index.IndexReader; +import org.apache.lucene.index.IndexableField; +import org.apache.lucene.index.LeafReader; +import org.apache.lucene.index.MultiReader; +import org.apache.lucene.index.SlowCompositeReaderWrapper; +import org.apache.lucene.index.Term; +import org.apache.lucene.index.memory.MemoryIndex; +import org.apache.lucene.search.BooleanClause; +import org.apache.lucene.search.BooleanQuery; +import org.apache.lucene.search.IndexSearcher; +import org.apache.lucene.search.Query; +import org.apache.lucene.search.TermQuery; +import org.apache.lucene.search.Weight; +import org.elasticsearch.ElasticsearchException; +import org.elasticsearch.ResourceNotFoundException; +import org.elasticsearch.Version; +import org.elasticsearch.action.get.GetRequest; +import org.elasticsearch.action.get.GetResponse; +import org.elasticsearch.cluster.metadata.IndexMetaData; +import org.elasticsearch.common.bytes.BytesReference; +import org.elasticsearch.common.io.stream.StreamInput; +import org.elasticsearch.common.io.stream.StreamOutput; +import org.elasticsearch.common.lucene.search.Queries; +import org.elasticsearch.common.settings.Settings; +import org.elasticsearch.common.xcontent.XContentBuilder; +import org.elasticsearch.common.xcontent.XContentFactory; +import org.elasticsearch.common.xcontent.XContentParser; +import org.elasticsearch.common.xcontent.XContentType; +import org.elasticsearch.index.mapper.DocumentMapper; +import org.elasticsearch.index.mapper.DocumentMapperForType; +import org.elasticsearch.index.mapper.MapperService; +import org.elasticsearch.index.mapper.ParseContext; +import org.elasticsearch.index.mapper.ParsedDocument; +import org.elasticsearch.index.mapper.internal.TypeFieldMapper; +import org.elasticsearch.index.mapper.internal.UidFieldMapper; +import org.elasticsearch.index.percolator.PercolatorFieldMapper; +import org.elasticsearch.index.percolator.PercolatorQueryCache; + +import java.io.IOException; +import java.util.List; +import java.util.Objects; + +import static org.elasticsearch.index.mapper.SourceToParse.source; + +public class PercolatorQueryBuilder extends AbstractQueryBuilder { + + public static final String NAME = "percolator"; + static final PercolatorQueryBuilder PROTO = new PercolatorQueryBuilder(null, null, null, null, null, null, null, null); + + private final String documentType; + private final BytesReference document; + + private final String indexedDocumentIndex; + private final String indexedDocumentType; + private final String indexedDocumentId; + private final String indexedDocumentRouting; + private final String indexedDocumentPreference; + private final Long indexedDocumentVersion; + + public PercolatorQueryBuilder(String documentType, BytesReference document) { + if (documentType == null) { + throw new IllegalArgumentException("[document_type] is a required argument"); + } + if (document == null) { + throw new IllegalArgumentException("[document] is a required argument"); + } + this.documentType = documentType; + this.document = document; + indexedDocumentIndex = null; + indexedDocumentType = null; + indexedDocumentId = null; + indexedDocumentRouting = null; + indexedDocumentPreference = null; + indexedDocumentVersion = null; + } + + public PercolatorQueryBuilder(String documentType, String indexedDocumentIndex, String indexedDocumentType, + String indexedDocumentId, String indexedDocumentRouting, String indexedDocumentPreference, + Long indexedDocumentVersion) { + if (documentType == null) { + throw new IllegalArgumentException("[document_type] is a required argument"); + } + if (indexedDocumentIndex == null) { + throw new IllegalArgumentException("[index] is a required argument"); + } + if (indexedDocumentType == null) { + throw new IllegalArgumentException("[type] is a required argument"); + } + if (indexedDocumentId == null) { + throw new IllegalArgumentException("[id] is a required argument"); + } + this.documentType = documentType; + this.indexedDocumentIndex = indexedDocumentIndex; + this.indexedDocumentType = indexedDocumentType; + this.indexedDocumentId = indexedDocumentId; + this.indexedDocumentRouting = indexedDocumentRouting; + this.indexedDocumentPreference = indexedDocumentPreference; + this.indexedDocumentVersion = indexedDocumentVersion; + this.document = null; + } + + private PercolatorQueryBuilder(String documentType, BytesReference document, String indexedDocumentIndex, String indexedDocumentType, + String indexedDocumentId, String indexedDocumentRouting, String indexedDocumentPreference, + Long indexedDocumentVersion) { + this.documentType = documentType; + this.document = document; + this.indexedDocumentIndex = indexedDocumentIndex; + this.indexedDocumentType = indexedDocumentType; + this.indexedDocumentId = indexedDocumentId; + this.indexedDocumentRouting = indexedDocumentRouting; + this.indexedDocumentPreference = indexedDocumentPreference; + this.indexedDocumentVersion = indexedDocumentVersion; + } + + @Override + protected void doXContent(XContentBuilder builder, Params params) throws IOException { + builder.startObject(NAME); + builder.field(PercolatorQueryParser.DOCUMENT_TYPE_FIELD.getPreferredName(), documentType); + if (document != null) { + XContentType contentType = XContentFactory.xContentType(document); + if (contentType == builder.contentType()) { + builder.rawField(PercolatorQueryParser.DOCUMENT_FIELD.getPreferredName(), document); + } else { + XContentParser parser = XContentFactory.xContent(contentType).createParser(document); + parser.nextToken(); + builder.field(PercolatorQueryParser.DOCUMENT_FIELD.getPreferredName()); + builder.copyCurrentStructure(parser); + } + } + if (indexedDocumentIndex != null || indexedDocumentType != null || indexedDocumentId != null) { + if (indexedDocumentIndex != null) { + builder.field(PercolatorQueryParser.INDEXED_DOCUMENT_FIELD_INDEX.getPreferredName(), indexedDocumentIndex); + } + if (indexedDocumentType != null) { + builder.field(PercolatorQueryParser.INDEXED_DOCUMENT_FIELD_TYPE.getPreferredName(), indexedDocumentType); + } + if (indexedDocumentId != null) { + builder.field(PercolatorQueryParser.INDEXED_DOCUMENT_FIELD_ID.getPreferredName(), indexedDocumentId); + } + if (indexedDocumentRouting != null) { + builder.field(PercolatorQueryParser.INDEXED_DOCUMENT_FIELD_ROUTING.getPreferredName(), indexedDocumentRouting); + } + if (indexedDocumentPreference != null) { + builder.field(PercolatorQueryParser.INDEXED_DOCUMENT_FIELD_PREFERENCE.getPreferredName(), indexedDocumentPreference); + } + if (indexedDocumentVersion != null) { + builder.field(PercolatorQueryParser.INDEXED_DOCUMENT_FIELD_VERSION.getPreferredName(), indexedDocumentVersion); + } + } + printBoostAndQueryName(builder); + builder.endObject(); + } + + @Override + protected PercolatorQueryBuilder doReadFrom(StreamInput in) throws IOException { + String docType = in.readString(); + String documentIndex = in.readOptionalString(); + String documentType = in.readOptionalString(); + String documentId = in.readOptionalString(); + String documentRouting = in.readOptionalString(); + String documentPreference = in.readOptionalString(); + Long documentVersion = null; + if (in.readBoolean()) { + documentVersion = in.readVLong(); + } + BytesReference documentSource = null; + if (in.readBoolean()) { + documentSource = in.readBytesReference(); + } + return new PercolatorQueryBuilder(docType, documentSource, documentIndex, documentType, documentId, + documentRouting, documentPreference, documentVersion); + } + + @Override + protected void doWriteTo(StreamOutput out) throws IOException { + out.writeString(documentType); + out.writeOptionalString(indexedDocumentIndex); + out.writeOptionalString(indexedDocumentType); + out.writeOptionalString(indexedDocumentId); + out.writeOptionalString(indexedDocumentRouting); + out.writeOptionalString(indexedDocumentPreference); + if (indexedDocumentVersion != null) { + out.writeBoolean(true); + out.writeVLong(indexedDocumentVersion); + } else { + out.writeBoolean(false); + } + if (document != null) { + out.writeBoolean(true); + out.writeBytesReference(document); + } else { + out.writeBoolean(false); + } + } + + @Override + protected boolean doEquals(PercolatorQueryBuilder other) { + return Objects.equals(documentType, other.documentType) + && Objects.equals(document, other.document) + && Objects.equals(indexedDocumentIndex, other.indexedDocumentIndex) + && Objects.equals(indexedDocumentType, other.indexedDocumentType) + && Objects.equals(indexedDocumentId, other.indexedDocumentId); + } + + @Override + protected int doHashCode() { + return Objects.hash(documentType, document, indexedDocumentIndex, indexedDocumentType, indexedDocumentId); + } + + @Override + public String getWriteableName() { + return NAME; + } + + @Override + protected QueryBuilder doRewrite(QueryRewriteContext queryShardContext) throws IOException { + if (document != null) { + return this; + } + + GetRequest getRequest = new GetRequest(indexedDocumentIndex, indexedDocumentType, indexedDocumentId); + getRequest.preference("_local"); + getRequest.routing(indexedDocumentRouting); + getRequest.preference(indexedDocumentPreference); + if (indexedDocumentVersion != null) { + getRequest.version(indexedDocumentVersion); + } + GetResponse getResponse = queryShardContext.getClient().get(getRequest).actionGet(); + if (getResponse.isExists() == false) { + throw new ResourceNotFoundException( + "indexed document [{}/{}/{}] couldn't be found", indexedDocumentIndex, indexedDocumentType, indexedDocumentId + ); + } + return new PercolatorQueryBuilder(documentType, getResponse.getSourceAsBytesRef()); + } + + @Override + protected Query doToQuery(QueryShardContext context) throws IOException { + if (indexedDocumentIndex != null || indexedDocumentType != null || indexedDocumentId != null) { + throw new IllegalStateException("query builder must be rewritten first"); + } + + if (document == null) { + throw new IllegalStateException("nothing to percolator"); + } + + MapperService mapperService = context.getMapperService(); + DocumentMapperForType docMapperForType = mapperService.documentMapperWithAutoCreate(documentType); + DocumentMapper docMapper = docMapperForType.getDocumentMapper(); + + ParsedDocument doc = docMapper.parse(source(document) + .index(context.index().getName()) + .id("_temp_id") + .type(documentType)); + + Analyzer defaultAnalyzer = context.getAnalysisService().defaultIndexAnalyzer(); + final IndexSearcher docSearcher; + if (doc.docs().size() > 1) { + assert docMapper.hasNestedObjects(); + docSearcher = createMultiDocumentSearcher(docMapper, defaultAnalyzer, doc); + } else { + // TODO: we may want to bring to MemoryIndex thread local cache back... + // but I'm unsure about the real benefits. + MemoryIndex memoryIndex = new MemoryIndex(true); + indexDoc(docMapper, defaultAnalyzer, doc.rootDoc(), memoryIndex); + docSearcher = memoryIndex.createSearcher(); + docSearcher.setQueryCache(null); + } + + PercolatorQueryCache registry = context.getPercolatorQueryCache(); + if (registry == null) { + throw new QueryShardException(context, "no percolator query registry"); + } + + Query percolateTypeQuery = new TermQuery(new Term(TypeFieldMapper.NAME, PercolatorFieldMapper.TYPE_NAME)); + PercolatorQuery.Builder builder = new PercolatorQuery.Builder( + documentType, registry, document, docSearcher, percolateTypeQuery + ); + Settings indexSettings = registry.getIndexSettings().getSettings(); + if (indexSettings.getAsVersion(IndexMetaData.SETTING_VERSION_CREATED, null).onOrAfter(Version.V_5_0_0)) { + builder.extractQueryTermsQuery( + PercolatorFieldMapper.EXTRACTED_TERMS_FULL_FIELD_NAME, PercolatorFieldMapper.UNKNOWN_QUERY_FULL_FIELD_NAME + ); + } + return builder.build(); + } + + public String getDocumentType() { + return documentType; + } + + public BytesReference getDocument() { + return document; + } + + private IndexSearcher createMultiDocumentSearcher(DocumentMapper docMapper, Analyzer defaultAnalyzer, ParsedDocument doc) { + IndexReader[] memoryIndices = new IndexReader[doc.docs().size()]; + List docs = doc.docs(); + int rootDocIndex = docs.size() - 1; + assert rootDocIndex > 0; + for (int i = 0; i < docs.size(); i++) { + ParseContext.Document d = docs.get(i); + MemoryIndex memoryIndex = new MemoryIndex(true); + indexDoc(docMapper, defaultAnalyzer, d, memoryIndex); + memoryIndices[i] = memoryIndex.createSearcher().getIndexReader(); + } + try { + MultiReader mReader = new MultiReader(memoryIndices, true); + LeafReader slowReader = SlowCompositeReaderWrapper.wrap(mReader); + final IndexSearcher slowSearcher = new IndexSearcher(slowReader) { + + @Override + public Weight createNormalizedWeight(Query query, boolean needsScores) throws IOException { + BooleanQuery.Builder bq = new BooleanQuery.Builder(); + bq.add(query, BooleanClause.Occur.MUST); + bq.add(Queries.newNestedFilter(), BooleanClause.Occur.MUST_NOT); + return super.createNormalizedWeight(bq.build(), needsScores); + } + + }; + slowSearcher.setQueryCache(null); + return slowSearcher; + } catch (IOException e) { + throw new ElasticsearchException("Failed to create index for percolator with nested document ", e); + } + } + + private void indexDoc(DocumentMapper documentMapper, Analyzer defaultAnalyzer, ParseContext.Document document, + MemoryIndex memoryIndex) { + for (IndexableField field : document.getFields()) { + if (field.fieldType().indexOptions() == IndexOptions.NONE && field.name().equals(UidFieldMapper.NAME)) { + continue; + } + + Analyzer analyzer = defaultAnalyzer; + if (documentMapper != null && documentMapper.mappers().getMapper(field.name()) != null) { + analyzer = documentMapper.mappers().indexAnalyzer(); + } + try { + try (TokenStream tokenStream = field.tokenStream(analyzer, null)) { + if (tokenStream != null) { + memoryIndex.addField(field.name(), tokenStream, field.boost()); + } + } + } catch (IOException e) { + throw new ElasticsearchException("Failed to create token stream", e); + } + } + } + +} diff --git a/core/src/main/java/org/elasticsearch/index/query/PercolatorQueryParser.java b/core/src/main/java/org/elasticsearch/index/query/PercolatorQueryParser.java new file mode 100644 index 00000000000..a559db59927 --- /dev/null +++ b/core/src/main/java/org/elasticsearch/index/query/PercolatorQueryParser.java @@ -0,0 +1,134 @@ +/* + * Licensed to Elasticsearch under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch 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.elasticsearch.index.query; + +import org.elasticsearch.common.ParseField; +import org.elasticsearch.common.ParsingException; +import org.elasticsearch.common.bytes.BytesReference; +import org.elasticsearch.common.xcontent.XContentBuilder; +import org.elasticsearch.common.xcontent.XContentFactory; +import org.elasticsearch.common.xcontent.XContentParser; + +import java.io.IOException; + +public class PercolatorQueryParser implements QueryParser { + + public static final ParseField DOCUMENT_FIELD = new ParseField("document"); + public static final ParseField DOCUMENT_TYPE_FIELD = new ParseField("document_type"); + public static final ParseField INDEXED_DOCUMENT_FIELD_INDEX = new ParseField("index"); + public static final ParseField INDEXED_DOCUMENT_FIELD_TYPE = new ParseField("type"); + public static final ParseField INDEXED_DOCUMENT_FIELD_ID = new ParseField("id"); + public static final ParseField INDEXED_DOCUMENT_FIELD_ROUTING = new ParseField("routing"); + public static final ParseField INDEXED_DOCUMENT_FIELD_PREFERENCE = new ParseField("preference"); + public static final ParseField INDEXED_DOCUMENT_FIELD_VERSION = new ParseField("version"); + + @Override + public String[] names() { + return new String[]{PercolatorQueryBuilder.NAME}; + } + + @Override + public PercolatorQueryBuilder fromXContent(QueryParseContext parseContext) throws IOException { + XContentParser parser = parseContext.parser(); + float boost = AbstractQueryBuilder.DEFAULT_BOOST; + + String documentType = null; + + String indexedDocumentIndex = null; + String indexedDocumentType = null; + String indexedDocumentId = null; + String indexedDocumentRouting = null; + String indexedDocumentPreference = null; + Long indexedDocumentVersion = null; + + BytesReference source = null; + + String queryName = null; + String currentFieldName = null; + + XContentParser.Token token; + while ((token = parser.nextToken()) != XContentParser.Token.END_OBJECT) { + if (token == XContentParser.Token.FIELD_NAME) { + currentFieldName = parser.currentName(); + } else if (token == XContentParser.Token.START_OBJECT) { + if (parseContext.parseFieldMatcher().match(currentFieldName, DOCUMENT_FIELD)) { + try (XContentBuilder builder = XContentFactory.jsonBuilder()) { + builder.copyCurrentStructure(parser); + builder.flush(); + source = builder.bytes(); + } + } else { + throw new ParsingException(parser.getTokenLocation(), "[" + PercolatorQueryBuilder.NAME + + "] query does not support [" + token + "]"); + } + } else if (token.isValue()) { + if (parseContext.parseFieldMatcher().match(currentFieldName, DOCUMENT_TYPE_FIELD)) { + documentType = parser.text(); + } else if (parseContext.parseFieldMatcher().match(currentFieldName, INDEXED_DOCUMENT_FIELD_INDEX)) { + indexedDocumentIndex = parser.text(); + } else if (parseContext.parseFieldMatcher().match(currentFieldName, INDEXED_DOCUMENT_FIELD_TYPE)) { + indexedDocumentType = parser.text(); + } else if (parseContext.parseFieldMatcher().match(currentFieldName, INDEXED_DOCUMENT_FIELD_ID)) { + indexedDocumentId = parser.text(); + } else if (parseContext.parseFieldMatcher().match(currentFieldName, INDEXED_DOCUMENT_FIELD_ROUTING)) { + indexedDocumentRouting = parser.text(); + } else if (parseContext.parseFieldMatcher().match(currentFieldName, INDEXED_DOCUMENT_FIELD_PREFERENCE)) { + indexedDocumentPreference = parser.text(); + } else if (parseContext.parseFieldMatcher().match(currentFieldName, INDEXED_DOCUMENT_FIELD_VERSION)) { + indexedDocumentVersion = parser.longValue(); + } else if (parseContext.parseFieldMatcher().match(currentFieldName, AbstractQueryBuilder.BOOST_FIELD)) { + boost = parser.floatValue(); + } else if (parseContext.parseFieldMatcher().match(currentFieldName, AbstractQueryBuilder.NAME_FIELD)) { + queryName = parser.text(); + } else { + throw new ParsingException(parser.getTokenLocation(), "[" + PercolatorQueryBuilder.NAME + + "] query does not support [" + currentFieldName + "]"); + } + } else { + throw new ParsingException(parser.getTokenLocation(), "[" + PercolatorQueryBuilder.NAME + + "] query does not support [" + token + "]"); + } + } + + if (documentType == null) { + throw new IllegalArgumentException("[" + PercolatorQueryBuilder.NAME + "] query is missing required [" + + DOCUMENT_TYPE_FIELD.getPreferredName() + "] parameter"); + } + + PercolatorQueryBuilder queryBuilder; + if (source != null) { + queryBuilder = new PercolatorQueryBuilder(documentType, source); + } else if (indexedDocumentId != null) { + queryBuilder = new PercolatorQueryBuilder(documentType, indexedDocumentIndex, indexedDocumentType, + indexedDocumentId, indexedDocumentRouting, indexedDocumentPreference, indexedDocumentVersion); + } else { + throw new IllegalArgumentException("[" + PercolatorQueryBuilder.NAME + "] query, nothing to percolate"); + } + queryBuilder.queryName(queryName); + queryBuilder.boost(boost); + return queryBuilder; + } + + @Override + public PercolatorQueryBuilder getBuilderPrototype() { + return PercolatorQueryBuilder.PROTO; + } + +} diff --git a/core/src/main/java/org/elasticsearch/index/query/QueryBuilders.java b/core/src/main/java/org/elasticsearch/index/query/QueryBuilders.java index 21c1f3ff695..f04f03fcbcd 100644 --- a/core/src/main/java/org/elasticsearch/index/query/QueryBuilders.java +++ b/core/src/main/java/org/elasticsearch/index/query/QueryBuilders.java @@ -832,6 +832,18 @@ public abstract class QueryBuilders { return new ExistsQueryBuilder(name); } + public static PercolatorQueryBuilder percolatorQuery(String documentType, BytesReference document) { + return new PercolatorQueryBuilder(documentType, document); + } + + public static PercolatorQueryBuilder percolatorQuery(String documentType, String indexedDocumentIndex, + String indexedDocumentType, String indexedDocumentId, + String indexedDocumentRouting, String indexedDocumentPreference, + Long indexedDocumentVersion) { + return new PercolatorQueryBuilder(documentType, indexedDocumentIndex, indexedDocumentType, indexedDocumentId, + indexedDocumentRouting, indexedDocumentPreference, indexedDocumentVersion); + } + private QueryBuilders() { } diff --git a/core/src/main/java/org/elasticsearch/index/query/QueryRewriteContext.java b/core/src/main/java/org/elasticsearch/index/query/QueryRewriteContext.java index e057aff06b1..11164659b3f 100644 --- a/core/src/main/java/org/elasticsearch/index/query/QueryRewriteContext.java +++ b/core/src/main/java/org/elasticsearch/index/query/QueryRewriteContext.java @@ -20,6 +20,7 @@ package org.elasticsearch.index.query; import org.elasticsearch.client.Client; import org.elasticsearch.index.IndexSettings; +import org.elasticsearch.index.fieldstats.FieldStatsProvider; import org.elasticsearch.indices.query.IndicesQueriesRegistry; import org.elasticsearch.script.ScriptService; @@ -31,6 +32,7 @@ public class QueryRewriteContext { protected final IndexSettings indexSettings; protected final IndicesQueriesRegistry indicesQueriesRegistry; protected final QueryParseContext parseContext; + protected FieldStatsProvider fieldStatsProvider; public QueryRewriteContext(IndexSettings indexSettings, ScriptService scriptService, IndicesQueriesRegistry indicesQueriesRegistry) { this.scriptService = scriptService; @@ -39,6 +41,14 @@ public class QueryRewriteContext { this.parseContext = new QueryParseContext(indicesQueriesRegistry); } + public void setFieldStatsProvider(FieldStatsProvider fieldStatsProvider) { + this.fieldStatsProvider = fieldStatsProvider; + } + + public FieldStatsProvider getFieldStatsProvider() { + return fieldStatsProvider; + } + /** * Returns a clients to fetch resources from local or remove nodes. */ diff --git a/core/src/main/java/org/elasticsearch/index/query/QueryShardContext.java b/core/src/main/java/org/elasticsearch/index/query/QueryShardContext.java index 6acd5272f89..a21b53cdf51 100644 --- a/core/src/main/java/org/elasticsearch/index/query/QueryShardContext.java +++ b/core/src/main/java/org/elasticsearch/index/query/QueryShardContext.java @@ -44,9 +44,9 @@ import org.elasticsearch.index.mapper.ContentPath; import org.elasticsearch.index.mapper.MappedFieldType; import org.elasticsearch.index.mapper.Mapper; import org.elasticsearch.index.mapper.MapperService; -import org.elasticsearch.index.mapper.core.StringFieldMapper; import org.elasticsearch.index.mapper.core.TextFieldMapper; import org.elasticsearch.index.mapper.object.ObjectMapper; +import org.elasticsearch.index.percolator.PercolatorQueryCache; import org.elasticsearch.index.query.support.InnerHitsQueryParserHelper; import org.elasticsearch.index.query.support.NestedScope; import org.elasticsearch.index.similarity.SimilarityService; @@ -87,13 +87,15 @@ public class QueryShardContext extends QueryRewriteContext { private final Map namedQueries = new HashMap<>(); private final MapperQueryParser queryParser = new MapperQueryParser(this); + private final IndicesQueriesRegistry indicesQueriesRegistry; + private final PercolatorQueryCache percolatorQueryCache; private boolean allowUnmappedFields; private boolean mapUnmappedFieldAsString; private NestedScope nestedScope; boolean isFilter; // pkg private for testing public QueryShardContext(IndexSettings indexSettings, BitsetFilterCache bitsetFilterCache, IndexFieldDataService indexFieldDataService, MapperService mapperService, SimilarityService similarityService, ScriptService scriptService, - final IndicesQueriesRegistry indicesQueriesRegistry) { + final IndicesQueriesRegistry indicesQueriesRegistry, PercolatorQueryCache percolatorQueryCache) { super(indexSettings, scriptService, indicesQueriesRegistry); this.indexSettings = indexSettings; this.similarityService = similarityService; @@ -101,17 +103,18 @@ public class QueryShardContext extends QueryRewriteContext { this.bitsetFilterCache = bitsetFilterCache; this.indexFieldDataService = indexFieldDataService; this.allowUnmappedFields = indexSettings.isDefaultAllowUnmappedFields(); - + this.indicesQueriesRegistry = indicesQueriesRegistry; + this.percolatorQueryCache = percolatorQueryCache; } public QueryShardContext(QueryShardContext source) { - this(source.indexSettings, source.bitsetFilterCache, source.indexFieldDataService, source.mapperService, source.similarityService, source.scriptService, source.indicesQueriesRegistry); + this(source.indexSettings, source.bitsetFilterCache, source.indexFieldDataService, source.mapperService, source.similarityService, source.scriptService, source.indicesQueriesRegistry, source.percolatorQueryCache); this.types = source.getTypes(); } public QueryShardContext clone() { - return new QueryShardContext(indexSettings, bitsetFilterCache, indexFieldDataService, mapperService, similarityService, scriptService, indicesQueriesRegistry); + return new QueryShardContext(indexSettings, bitsetFilterCache, indexFieldDataService, mapperService, similarityService, scriptService, indicesQueriesRegistry, percolatorQueryCache); } public void parseFieldMatcher(ParseFieldMatcher parseFieldMatcher) { @@ -148,6 +151,10 @@ public class QueryShardContext extends QueryRewriteContext { return mapperService; } + public PercolatorQueryCache getPercolatorQueryCache() { + return percolatorQueryCache; + } + public Similarity getSearchSimilarity() { return similarityService != null ? similarityService.similarity(mapperService) : null; } diff --git a/core/src/main/java/org/elasticsearch/index/query/RangeQueryBuilder.java b/core/src/main/java/org/elasticsearch/index/query/RangeQueryBuilder.java index cd99bec0f74..c3953a51170 100644 --- a/core/src/main/java/org/elasticsearch/index/query/RangeQueryBuilder.java +++ b/core/src/main/java/org/elasticsearch/index/query/RangeQueryBuilder.java @@ -22,6 +22,10 @@ package org.elasticsearch.index.query; import org.apache.lucene.search.Query; import org.apache.lucene.search.TermRangeQuery; import org.apache.lucene.util.BytesRef; +import org.elasticsearch.action.fieldstats.FieldStats; +import org.elasticsearch.action.fieldstats.IndexConstraint; +import org.elasticsearch.action.fieldstats.IndexConstraint.Comparison; +import org.elasticsearch.action.fieldstats.IndexConstraint.Property; import org.elasticsearch.common.Strings; import org.elasticsearch.common.io.stream.StreamInput; import org.elasticsearch.common.io.stream.StreamOutput; @@ -30,6 +34,7 @@ import org.elasticsearch.common.joda.FormatDateTimeFormatter; import org.elasticsearch.common.joda.Joda; import org.elasticsearch.common.lucene.BytesRefs; import org.elasticsearch.common.xcontent.XContentBuilder; +import org.elasticsearch.index.fieldstats.FieldStatsProvider; import org.elasticsearch.index.mapper.MappedFieldType; import org.elasticsearch.index.mapper.core.DateFieldMapper; import org.joda.time.DateTimeZone; @@ -253,6 +258,43 @@ public class RangeQueryBuilder extends AbstractQueryBuilder i return NAME; } + @Override + protected QueryBuilder doRewrite(QueryRewriteContext queryShardContext) throws IOException { + FieldStatsProvider fieldStatsProvider = queryShardContext.getFieldStatsProvider(); + // If the fieldStatsProvider is null we are not on the shard and cannot + // rewrite so just return without rewriting + if (fieldStatsProvider != null) { + DateMathParser dateMathParser = format == null ? null : new DateMathParser(format); + FieldStatsProvider.Relation relation = fieldStatsProvider.isFieldWithinQuery(fieldName, from, to, includeLower, includeUpper, + timeZone, dateMathParser); + switch (relation) { + case DISJOINT: + return new MatchNoneQueryBuilder(); + case WITHIN: + FieldStats fieldStats = fieldStatsProvider.get(fieldName); + if (!(fieldStats.getMinValue().equals(from) && fieldStats.getMaxValue().equals(to) && includeUpper && includeLower)) { + // Rebuild the range query with the bounds for this shard. + // The includeLower/Upper values are preserved only if the + // bound has not been changed by the rewrite + RangeQueryBuilder newRangeQuery = new RangeQueryBuilder(fieldName); + String dateFormatString = format == null ? null : format.format(); + newRangeQuery.from(fieldStats.getMinValue(), includeLower || fieldStats.match( + new IndexConstraint(fieldName, Property.MIN, Comparison.GT, fieldStats.stringValueOf(from, dateFormatString)))); + newRangeQuery.to(fieldStats.getMaxValue(), includeUpper || fieldStats.match( + new IndexConstraint(fieldName, Property.MAX, Comparison.LT, fieldStats.stringValueOf(to, dateFormatString)))); + newRangeQuery.format = format; + newRangeQuery.timeZone = timeZone; + return newRangeQuery; + } else { + return this; + } + case INTERSECTS: + break; + } + } + return this; + } + @Override protected Query doToQuery(QueryShardContext context) throws IOException { Query query = null; diff --git a/core/src/main/java/org/elasticsearch/index/query/support/NestedInnerQueryParseSupport.java b/core/src/main/java/org/elasticsearch/index/query/support/NestedInnerQueryParseSupport.java index 86983026b19..5c65a57d532 100644 --- a/core/src/main/java/org/elasticsearch/index/query/support/NestedInnerQueryParseSupport.java +++ b/core/src/main/java/org/elasticsearch/index/query/support/NestedInnerQueryParseSupport.java @@ -20,9 +20,7 @@ package org.elasticsearch.index.query.support; import org.apache.lucene.search.Query; -import org.apache.lucene.search.join.BitSetProducer; import org.elasticsearch.common.bytes.BytesReference; -import org.elasticsearch.common.lucene.search.Queries; import org.elasticsearch.common.xcontent.XContentFactory; import org.elasticsearch.common.xcontent.XContentHelper; import org.elasticsearch.common.xcontent.XContentParser; @@ -45,46 +43,18 @@ public class NestedInnerQueryParseSupport { protected final QueryParseContext parseContext; private BytesReference source; - private Query innerQuery; private Query innerFilter; protected String path; private boolean filterParsed = false; - private boolean queryParsed = false; - protected boolean queryFound = false; protected boolean filterFound = false; - protected BitSetProducer parentFilter; - protected Query childFilter; - protected ObjectMapper nestedObjectMapper; - private ObjectMapper parentObjectMapper; public NestedInnerQueryParseSupport(XContentParser parser, QueryShardContext context) { shardContext = context; parseContext = shardContext.parseContext(); shardContext.reset(parser); - - } - - public NestedInnerQueryParseSupport(QueryShardContext context) { - this.parseContext = context.parseContext(); - this.shardContext = context; - } - - public void query() throws IOException { - if (path != null) { - setPathLevel(); - try { - innerQuery = parseContext.parseInnerQueryBuilder().toQuery(this.shardContext); - } finally { - resetPathLevel(); - } - queryParsed = true; - } else { - source = XContentFactory.smileBuilder().copyCurrentStructure(parseContext.parser()).bytes(); - } - queryFound = true; } public void filter() throws IOException { @@ -103,35 +73,6 @@ public class NestedInnerQueryParseSupport { filterFound = true; } - public Query getInnerQuery() throws IOException { - if (queryParsed) { - return innerQuery; - } else { - if (path == null) { - throw new QueryShardException(shardContext, "[nested] requires 'path' field"); - } - if (!queryFound) { - throw new QueryShardException(shardContext, "[nested] requires either 'query' or 'filter' field"); - } - - XContentParser old = parseContext.parser(); - try { - XContentParser innerParser = XContentHelper.createParser(source); - parseContext.parser(innerParser); - setPathLevel(); - try { - innerQuery = parseContext.parseInnerQueryBuilder().toQuery(this.shardContext); - } finally { - resetPathLevel(); - } - queryParsed = true; - return innerQuery; - } finally { - parseContext.parser(old); - } - } - } - public Query getInnerFilter() throws IOException { if (filterParsed) { return innerFilter; @@ -178,27 +119,12 @@ public class NestedInnerQueryParseSupport { return nestedObjectMapper; } - public boolean queryFound() { - return queryFound; - } - public boolean filterFound() { return filterFound; } - public ObjectMapper getParentObjectMapper() { - return parentObjectMapper; - } - private void setPathLevel() { - ObjectMapper objectMapper = shardContext.nestedScope().getObjectMapper(); - if (objectMapper == null) { - parentFilter = shardContext.bitsetFilter(Queries.newNonNestedFilter()); - } else { - parentFilter = shardContext.bitsetFilter(objectMapper.nestedTypeFilter()); - } - childFilter = nestedObjectMapper.nestedTypeFilter(); - parentObjectMapper = shardContext.nestedScope().nextLevel(nestedObjectMapper); + shardContext.nestedScope().nextLevel(nestedObjectMapper); } private void resetPathLevel() { diff --git a/core/src/main/java/org/elasticsearch/index/shard/IndexShard.java b/core/src/main/java/org/elasticsearch/index/shard/IndexShard.java index 5e2df030001..7b19a12bbaa 100644 --- a/core/src/main/java/org/elasticsearch/index/shard/IndexShard.java +++ b/core/src/main/java/org/elasticsearch/index/shard/IndexShard.java @@ -46,14 +46,12 @@ import org.elasticsearch.common.metrics.MeanMetric; import org.elasticsearch.common.settings.Settings; import org.elasticsearch.common.unit.ByteSizeValue; import org.elasticsearch.common.unit.TimeValue; +import org.elasticsearch.common.util.BigArrays; import org.elasticsearch.common.util.Callback; import org.elasticsearch.common.util.concurrent.AbstractRunnable; -import org.elasticsearch.common.util.concurrent.FutureUtils; import org.elasticsearch.common.util.concurrent.SuspendableRefContainer; -import org.elasticsearch.gateway.MetaDataStateFormat; import org.elasticsearch.index.IndexModule; import org.elasticsearch.index.IndexSettings; -import org.elasticsearch.index.NodeServicesProvider; import org.elasticsearch.index.SearchSlowLog; import org.elasticsearch.index.VersionType; import org.elasticsearch.index.cache.IndexCache; @@ -83,9 +81,7 @@ import org.elasticsearch.index.mapper.ParsedDocument; import org.elasticsearch.index.mapper.SourceToParse; import org.elasticsearch.index.mapper.Uid; import org.elasticsearch.index.merge.MergeStats; -import org.elasticsearch.index.percolator.PercolateStats; -import org.elasticsearch.index.percolator.PercolatorQueriesRegistry; -import org.elasticsearch.index.query.QueryShardContext; +import org.elasticsearch.index.percolator.PercolatorFieldMapper; import org.elasticsearch.index.recovery.RecoveryStats; import org.elasticsearch.index.refresh.RefreshStats; import org.elasticsearch.index.search.stats.SearchStats; @@ -106,7 +102,6 @@ import org.elasticsearch.index.warmer.WarmerStats; import org.elasticsearch.indices.IndexingMemoryController; import org.elasticsearch.indices.recovery.RecoveryFailedException; import org.elasticsearch.indices.recovery.RecoveryState; -import org.elasticsearch.percolator.PercolatorService; import org.elasticsearch.search.suggest.completion.CompletionFieldStats; import org.elasticsearch.search.suggest.completion.CompletionStats; import org.elasticsearch.threadpool.ThreadPool; @@ -122,7 +117,6 @@ import java.util.List; import java.util.Map; import java.util.Objects; import java.util.concurrent.CopyOnWriteArrayList; -import java.util.concurrent.ScheduledFuture; import java.util.concurrent.TimeUnit; import java.util.concurrent.atomic.AtomicBoolean; import java.util.concurrent.atomic.AtomicLong; @@ -140,7 +134,6 @@ public class IndexShard extends AbstractIndexShardComponent { private final ShardIndexWarmerService shardWarmerService; private final ShardRequestCache shardQueryCache; private final ShardFieldData shardFieldData; - private final PercolatorQueriesRegistry percolatorQueriesRegistry; private final IndexFieldDataService indexFieldDataService; private final ShardSuggestMetric shardSuggestMetric = new ShardSuggestMetric(); private final ShardBitsetFilterCache shardBitsetFilterCache; @@ -159,7 +152,6 @@ public class IndexShard extends AbstractIndexShardComponent { * being indexed/deleted. */ private final AtomicLong writingBytes = new AtomicLong(); - private volatile ScheduledFuture refreshScheduledFuture; protected volatile ShardRouting shardRouting; protected volatile IndexShardState state; protected final AtomicReference currentEngineReference = new AtomicReference<>(); @@ -201,7 +193,8 @@ public class IndexShard extends AbstractIndexShardComponent { public IndexShard(ShardId shardId, IndexSettings indexSettings, ShardPath path, Store store, IndexCache indexCache, MapperService mapperService, SimilarityService similarityService, IndexFieldDataService indexFieldDataService, @Nullable EngineFactory engineFactory, - IndexEventListener indexEventListener, IndexSearcherWrapper indexSearcherWrapper, NodeServicesProvider provider, SearchSlowLog slowLog, Engine.Warmer warmer, IndexingOperationListener... listeners) { + IndexEventListener indexEventListener, IndexSearcherWrapper indexSearcherWrapper, ThreadPool threadPool, BigArrays bigArrays, + SearchSlowLog slowLog, Engine.Warmer warmer, IndexingOperationListener... listeners) { super(shardId, indexSettings); final Settings settings = indexSettings.getSettings(); this.codecService = new CodecService(mapperService, logger); @@ -212,7 +205,7 @@ public class IndexShard extends AbstractIndexShardComponent { this.engineFactory = engineFactory == null ? new InternalEngineFactory() : engineFactory; this.store = store; this.indexEventListener = indexEventListener; - this.threadPool = provider.getThreadPool(); + this.threadPool = threadPool; this.mapperService = mapperService; this.indexCache = indexCache; this.internalIndexingStats = new InternalIndexingStats(); @@ -233,7 +226,7 @@ public class IndexShard extends AbstractIndexShardComponent { this.checkIndexOnStartup = indexSettings.getValue(IndexSettings.INDEX_CHECK_ON_STARTUP); this.translogConfig = new TranslogConfig(shardId, shardPath().resolveTranslog(), indexSettings, - provider.getBigArrays()); + bigArrays); final QueryCachingPolicy cachingPolicy; // the query cache is a node-level thing, however we want the most popular filters // to be computed on a per-shard basis @@ -246,8 +239,6 @@ public class IndexShard extends AbstractIndexShardComponent { this.engineConfig = newEngineConfig(translogConfig, cachingPolicy); this.suspendableRefContainer = new SuspendableRefContainer(); this.searcherWrapper = indexSearcherWrapper; - QueryShardContext queryShardContext = new QueryShardContext(indexSettings, indexCache.bitsetFilterCache(), indexFieldDataService, mapperService, similarityService, provider.getScriptService(), provider.getIndicesQueriesRegistry()); - this.percolatorQueriesRegistry = new PercolatorQueriesRegistry(shardId, indexSettings, queryShardContext); } public Store store() { @@ -476,12 +467,8 @@ public class IndexShard extends AbstractIndexShardComponent { if (logger.isTraceEnabled()) { logger.trace("index [{}][{}]{}", index.type(), index.id(), index.docs()); } - final boolean isPercolatorQuery = percolatorQueriesRegistry.isPercolatorQuery(index); Engine engine = getEngine(); created = engine.index(index); - if (isPercolatorQuery) { - percolatorQueriesRegistry.updatePercolateQuery(engine, index.id()); - } index.endTime(System.nanoTime()); } catch (Throwable ex) { indexingOperationListeners.postIndex(index, ex); @@ -519,12 +506,8 @@ public class IndexShard extends AbstractIndexShardComponent { if (logger.isTraceEnabled()) { logger.trace("delete [{}]", delete.uid().text()); } - final boolean isPercolatorQuery = percolatorQueriesRegistry.isPercolatorQuery(delete); Engine engine = getEngine(); engine.delete(delete); - if (isPercolatorQuery) { - percolatorQueriesRegistry.updatePercolateQuery(engine, delete.id()); - } delete.endTime(System.nanoTime()); } catch (Throwable ex) { indexingOperationListeners.postDelete(delete, ex); @@ -644,10 +627,6 @@ public class IndexShard extends AbstractIndexShardComponent { return shardFieldData.stats(fields); } - public PercolatorQueriesRegistry percolateRegistry() { - return percolatorQueriesRegistry; - } - public TranslogStats translogStats() { return getEngine().getTranslog().stats(); } @@ -784,10 +763,6 @@ public class IndexShard extends AbstractIndexShardComponent { public void close(String reason, boolean flushEngine) throws IOException { synchronized (mutex) { try { - if (state != IndexShardState.CLOSED) { - FutureUtils.cancel(refreshScheduledFuture); - refreshScheduledFuture = null; - } changeState(IndexShardState.CLOSED, reason); } finally { final Engine engine = this.currentEngineReference.getAndSet(null); @@ -796,18 +771,15 @@ public class IndexShard extends AbstractIndexShardComponent { engine.flushAndClose(); } } finally { // playing safe here and close the engine even if the above succeeds - close can be called multiple times - IOUtils.close(engine, percolatorQueriesRegistry); + IOUtils.close(engine); } } } } public IndexShard postRecovery(String reason) throws IndexShardStartedException, IndexShardRelocatedException, IndexShardClosedException { - if (mapperService.hasMapping(PercolatorService.TYPE_NAME)) { + if (mapperService.hasMapping(PercolatorFieldMapper.TYPE_NAME)) { refresh("percolator_load_queries"); - try (Engine.Searcher searcher = getEngine().acquireSearcher("percolator_load_queries")) { - this.percolatorQueriesRegistry.loadQueries(searcher.reader()); - } } synchronized (mutex) { if (state == IndexShardState.CLOSED) { @@ -1104,10 +1076,6 @@ public class IndexShard extends AbstractIndexShardComponent { return getEngine().getTranslog(); } - public PercolateStats percolateStats() { - return percolatorQueriesRegistry.stats(); - } - public IndexEventListener getIndexEventListener() { return indexEventListener; } diff --git a/core/src/main/java/org/elasticsearch/index/shard/ShadowIndexShard.java b/core/src/main/java/org/elasticsearch/index/shard/ShadowIndexShard.java index 5518d1b1273..774052b3a5f 100644 --- a/core/src/main/java/org/elasticsearch/index/shard/ShadowIndexShard.java +++ b/core/src/main/java/org/elasticsearch/index/shard/ShadowIndexShard.java @@ -20,8 +20,8 @@ package org.elasticsearch.index.shard; import org.elasticsearch.cluster.routing.ShardRouting; import org.elasticsearch.common.Nullable; +import org.elasticsearch.common.util.BigArrays; import org.elasticsearch.index.IndexSettings; -import org.elasticsearch.index.NodeServicesProvider; import org.elasticsearch.index.cache.IndexCache; import org.elasticsearch.index.engine.Engine; import org.elasticsearch.index.engine.EngineConfig; @@ -33,6 +33,7 @@ import org.elasticsearch.index.SearchSlowLog; import org.elasticsearch.index.similarity.SimilarityService; import org.elasticsearch.index.store.Store; import org.elasticsearch.index.translog.TranslogStats; +import org.elasticsearch.threadpool.ThreadPool; import java.io.IOException; @@ -44,9 +45,13 @@ import java.io.IOException; */ public final class ShadowIndexShard extends IndexShard { - public ShadowIndexShard(ShardId shardId, IndexSettings indexSettings, ShardPath path, Store store, IndexCache indexCache, MapperService mapperService, SimilarityService similarityService, IndexFieldDataService indexFieldDataService, @Nullable EngineFactory engineFactory, - IndexEventListener indexEventListener, IndexSearcherWrapper wrapper, NodeServicesProvider provider, SearchSlowLog searchSlowLog, Engine.Warmer engineWarmer) throws IOException { - super(shardId, indexSettings, path, store, indexCache, mapperService, similarityService, indexFieldDataService, engineFactory, indexEventListener, wrapper, provider, searchSlowLog, engineWarmer); + public ShadowIndexShard(ShardId shardId, IndexSettings indexSettings, ShardPath path, Store store, IndexCache indexCache, + MapperService mapperService, SimilarityService similarityService, IndexFieldDataService indexFieldDataService, + @Nullable EngineFactory engineFactory, IndexEventListener indexEventListener, IndexSearcherWrapper wrapper, + ThreadPool threadPool, BigArrays bigArrays, SearchSlowLog searchSlowLog, Engine.Warmer engineWarmer) + throws IOException { + super(shardId, indexSettings, path, store, indexCache, mapperService, similarityService, indexFieldDataService, engineFactory, + indexEventListener, wrapper, threadPool, bigArrays, searchSlowLog, engineWarmer); } /** diff --git a/core/src/main/java/org/elasticsearch/index/shard/ShardStateMetaData.java b/core/src/main/java/org/elasticsearch/index/shard/ShardStateMetaData.java index 315371c7286..407f271fd65 100644 --- a/core/src/main/java/org/elasticsearch/index/shard/ShardStateMetaData.java +++ b/core/src/main/java/org/elasticsearch/index/shard/ShardStateMetaData.java @@ -102,7 +102,7 @@ public final class ShardStateMetaData { return "version [" + legacyVersion + "], primary [" + primary + "], allocation [" + allocationId + "]"; } - public static final MetaDataStateFormat FORMAT = new MetaDataStateFormat(XContentType.JSON, SHARD_STATE_FILE_PREFIX) { + public static final MetaDataStateFormat FORMAT = new MetaDataStateFormat(XContentType.SMILE, SHARD_STATE_FILE_PREFIX) { @Override protected XContentBuilder newXContentBuilder(XContentType type, OutputStream stream) throws IOException { diff --git a/core/src/main/java/org/elasticsearch/index/snapshots/blobstore/BlobStoreIndexShardRepository.java b/core/src/main/java/org/elasticsearch/index/snapshots/blobstore/BlobStoreIndexShardRepository.java index 330787a68a3..c15d2cfcdbe 100644 --- a/core/src/main/java/org/elasticsearch/index/snapshots/blobstore/BlobStoreIndexShardRepository.java +++ b/core/src/main/java/org/elasticsearch/index/snapshots/blobstore/BlobStoreIndexShardRepository.java @@ -32,9 +32,9 @@ import org.apache.lucene.util.BytesRef; import org.apache.lucene.util.BytesRefBuilder; import org.elasticsearch.ExceptionsHelper; import org.elasticsearch.Version; -import org.elasticsearch.cluster.ClusterService; import org.elasticsearch.cluster.metadata.SnapshotId; import org.elasticsearch.cluster.node.DiscoveryNode; +import org.elasticsearch.cluster.service.ClusterService; import org.elasticsearch.common.ParseFieldMatcher; import org.elasticsearch.common.blobstore.BlobContainer; import org.elasticsearch.common.blobstore.BlobMetaData; diff --git a/core/src/main/java/org/elasticsearch/index/store/FsDirectoryService.java b/core/src/main/java/org/elasticsearch/index/store/FsDirectoryService.java index 933fd784588..584b98cff33 100644 --- a/core/src/main/java/org/elasticsearch/index/store/FsDirectoryService.java +++ b/core/src/main/java/org/elasticsearch/index/store/FsDirectoryService.java @@ -61,8 +61,9 @@ public class FsDirectoryService extends DirectoryService implements StoreRateLim return SimpleFSLockFactory.INSTANCE; default: throw new IllegalArgumentException("unrecognized [index.store.fs.fs_lock] \"" + s + "\": must be native or simple"); - } - }, Property.IndexScope); + } // can we set on both - node and index level, some nodes might be running on NFS so they might need simple rather than native + }, Property.IndexScope, Property.NodeScope); + private final CounterMetric rateLimitingTimeInNanos = new CounterMetric(); private final ShardPath path; @@ -108,7 +109,8 @@ public class FsDirectoryService extends DirectoryService implements StoreRateLim protected Directory newFSDirectory(Path location, LockFactory lockFactory) throws IOException { - final String storeType = indexSettings.getSettings().get(IndexModule.INDEX_STORE_TYPE_SETTING.getKey(), IndexModule.Type.DEFAULT.getSettingsKey()); + final String storeType = indexSettings.getSettings().get(IndexModule.INDEX_STORE_TYPE_SETTING.getKey(), + IndexModule.Type.DEFAULT.getSettingsKey()); if (IndexModule.Type.FS.match(storeType) || IndexModule.Type.DEFAULT.match(storeType)) { final FSDirectory open = FSDirectory.open(location, lockFactory); // use lucene defaults if (open instanceof MMapDirectory && Constants.WINDOWS == false) { diff --git a/core/src/main/java/org/elasticsearch/indices/IndicesRequestCache.java b/core/src/main/java/org/elasticsearch/indices/IndicesRequestCache.java index 9129a3b1360..4b4aa4e8df2 100644 --- a/core/src/main/java/org/elasticsearch/indices/IndicesRequestCache.java +++ b/core/src/main/java/org/elasticsearch/indices/IndicesRequestCache.java @@ -70,7 +70,7 @@ public final class IndicesRequestCache extends AbstractComponent implements Remo * since we are checking on the cluster state IndexMetaData always. */ public static final Setting INDEX_CACHE_REQUEST_ENABLED_SETTING = - Setting.boolSetting("index.requests.cache.enable", false, Property.Dynamic, Property.IndexScope); + Setting.boolSetting("index.requests.cache.enable", true, Property.Dynamic, Property.IndexScope); public static final Setting INDICES_CACHE_QUERY_SIZE = Setting.byteSizeSetting("indices.requests.cache.size", "1%", Property.NodeScope); public static final Setting INDICES_CACHE_QUERY_EXPIRE = diff --git a/core/src/main/java/org/elasticsearch/indices/IndicesService.java b/core/src/main/java/org/elasticsearch/indices/IndicesService.java index b0e1bbdbd2b..a0dba7089a9 100644 --- a/core/src/main/java/org/elasticsearch/indices/IndicesService.java +++ b/core/src/main/java/org/elasticsearch/indices/IndicesService.java @@ -19,6 +19,7 @@ package org.elasticsearch.indices; +import com.carrotsearch.hppc.cursors.ObjectCursor; import org.apache.lucene.index.DirectoryReader; import org.apache.lucene.store.LockObtainFailedException; import org.apache.lucene.util.CollectionUtil; @@ -30,10 +31,11 @@ import org.elasticsearch.action.admin.indices.stats.CommonStatsFlags.Flag; import org.elasticsearch.action.admin.indices.stats.IndexShardStats; import org.elasticsearch.action.admin.indices.stats.ShardStats; import org.elasticsearch.action.search.SearchType; -import org.elasticsearch.cluster.ClusterService; import org.elasticsearch.cluster.ClusterState; import org.elasticsearch.cluster.metadata.IndexMetaData; import org.elasticsearch.cluster.metadata.IndexNameExpressionResolver; +import org.elasticsearch.cluster.metadata.MappingMetaData; +import org.elasticsearch.cluster.service.ClusterService; import org.elasticsearch.common.Nullable; import org.elasticsearch.common.breaker.CircuitBreaker; import org.elasticsearch.common.bytes.BytesReference; @@ -66,6 +68,7 @@ import org.elasticsearch.index.fielddata.FieldDataType; import org.elasticsearch.index.fielddata.IndexFieldDataCache; import org.elasticsearch.index.flush.FlushStats; import org.elasticsearch.index.get.GetStats; +import org.elasticsearch.index.mapper.MapperService; import org.elasticsearch.index.merge.MergeStats; import org.elasticsearch.index.recovery.RecoveryStats; import org.elasticsearch.index.refresh.RefreshStats; @@ -74,6 +77,7 @@ import org.elasticsearch.index.shard.IllegalIndexShardStateException; import org.elasticsearch.index.shard.IndexEventListener; import org.elasticsearch.index.shard.IndexShard; import org.elasticsearch.index.shard.IndexShardState; +import org.elasticsearch.index.shard.IndexingOperationListener; import org.elasticsearch.index.shard.IndexingStats; import org.elasticsearch.index.shard.ShardId; import org.elasticsearch.index.store.IndexStoreConfig; @@ -88,12 +92,13 @@ import org.elasticsearch.search.query.QueryPhase; import org.elasticsearch.search.query.QuerySearchResult; import org.elasticsearch.threadpool.ThreadPool; +import java.io.Closeable; import java.io.IOException; import java.nio.file.Files; import java.util.ArrayList; +import java.util.Collections; import java.util.EnumSet; import java.util.HashMap; -import java.util.HashSet; import java.util.Iterator; import java.util.List; import java.util.Map; @@ -265,7 +270,7 @@ public class IndicesService extends AbstractLifecycleComponent i if (indexShard.routingEntry() == null) { continue; } - IndexShardStats indexShardStats = new IndexShardStats(indexShard.shardId(), new ShardStats[] { new ShardStats(indexShard.routingEntry(), indexShard.shardPath(), new CommonStats(indicesQueryCache, indexShard, flags), indexShard.commitStats()) }); + IndexShardStats indexShardStats = new IndexShardStats(indexShard.shardId(), new ShardStats[] { new ShardStats(indexShard.routingEntry(), indexShard.shardPath(), new CommonStats(indicesQueryCache, indexService.cache().getPercolatorQueryCache(), indexShard, flags), indexShard.commitStats()) }); if (!statsByShard.containsKey(indexService.index())) { statsByShard.put(indexService.index(), arrayAsArrayList(indexShardStats)); } else { @@ -325,6 +330,7 @@ public class IndicesService extends AbstractLifecycleComponent i * @throws IndexAlreadyExistsException if the index already exists. */ public synchronized IndexService createIndex(final NodeServicesProvider nodeServicesProvider, IndexMetaData indexMetaData, List builtInListeners) throws IOException { + if (!lifecycle.started()) { throw new IllegalStateException("Can't create an index [" + indexMetaData.getIndex() + "], node is closed"); } @@ -332,37 +338,22 @@ public class IndicesService extends AbstractLifecycleComponent i throw new IllegalArgumentException("index must have a real UUID found value: [" + indexMetaData.getIndexUUID() + "]"); } final Index index = indexMetaData.getIndex(); - final Predicate indexNameMatcher = (indexExpression) -> indexNameExpressionResolver.matchesIndex(index.getName(), indexExpression, clusterService.state()); - final IndexSettings idxSettings = new IndexSettings(indexMetaData, this.settings, indexNameMatcher, indexScopeSetting); if (hasIndex(index)) { throw new IndexAlreadyExistsException(index); } - logger.debug("creating Index [{}], shards [{}]/[{}{}]", - indexMetaData.getIndex(), - idxSettings.getNumberOfShards(), - idxSettings.getNumberOfReplicas(), - idxSettings.isShadowReplicaIndex() ? "s" : ""); - - final IndexModule indexModule = new IndexModule(idxSettings, indexStoreConfig, analysisRegistry); - pluginsService.onIndexModule(indexModule); - for (IndexEventListener listener : builtInListeners) { - indexModule.addIndexEventListener(listener); - } + List finalListeners = new ArrayList<>(builtInListeners); final IndexEventListener onStoreClose = new IndexEventListener() { @Override public void onStoreClosed(ShardId shardId) { indicesQueryCache.onClose(shardId); } }; - indexModule.addIndexEventListener(onStoreClose); - indexModule.addIndexEventListener(oldShardsStats); - final IndexEventListener listener = indexModule.freeze(); - listener.beforeIndexCreated(index, idxSettings.getSettings()); - final IndexService indexService = indexModule.newIndexService(nodeEnv, this, nodeServicesProvider, indicesQueryCache, mapperRegistry, indicesFieldDataCache, indexingMemoryController); + finalListeners.add(onStoreClose); + finalListeners.add(oldShardsStats); + final IndexService indexService = createIndexService("create index", nodeServicesProvider, indexMetaData, indicesQueryCache, indicesFieldDataCache, finalListeners, indexingMemoryController); boolean success = false; try { - assert indexService.getIndexEventListener() == listener; - listener.afterIndexCreated(indexService); + indexService.getIndexEventListener().afterIndexCreated(indexService); indices = newMapBuilder(indices).put(index.getUUID(), indexService).immutableMap(); success = true; return indexService; @@ -371,7 +362,54 @@ public class IndicesService extends AbstractLifecycleComponent i indexService.close("plugins_failed", true); } } + } + /** + * This creates a new IndexService without registering it + */ + private synchronized IndexService createIndexService(final String reason, final NodeServicesProvider nodeServicesProvider, IndexMetaData indexMetaData, IndicesQueryCache indicesQueryCache, IndicesFieldDataCache indicesFieldDataCache, List builtInListeners, IndexingOperationListener... indexingOperationListeners) throws IOException { + final Index index = indexMetaData.getIndex(); + final Predicate indexNameMatcher = (indexExpression) -> indexNameExpressionResolver.matchesIndex(index.getName(), indexExpression, clusterService.state()); + final IndexSettings idxSettings = new IndexSettings(indexMetaData, this.settings, indexNameMatcher, indexScopeSetting); + logger.debug("creating Index [{}], shards [{}]/[{}{}] - reason [{}]", + indexMetaData.getIndex(), + idxSettings.getNumberOfShards(), + idxSettings.getNumberOfReplicas(), + idxSettings.isShadowReplicaIndex() ? "s" : "", reason); + + final IndexModule indexModule = new IndexModule(idxSettings, indexStoreConfig, analysisRegistry); + pluginsService.onIndexModule(indexModule); + for (IndexEventListener listener : builtInListeners) { + indexModule.addIndexEventListener(listener); + } + final IndexEventListener listener = indexModule.freeze(); + listener.beforeIndexCreated(index, idxSettings.getSettings()); + return indexModule.newIndexService(nodeEnv, this, nodeServicesProvider, indicesQueryCache, mapperRegistry, indicesFieldDataCache, indexingOperationListeners); + } + + /** + * This method verifies that the given {@link IndexMetaData} holds sane values to create an {@link IndexService}. This method will throw an + * exception if the creation fails. The created {@link IndexService} will not be registered and will be closed immediately. + */ + public synchronized void verifyIndexMetadata(final NodeServicesProvider nodeServicesProvider, IndexMetaData metaData) throws IOException { + final List closeables = new ArrayList<>(); + try { + IndicesFieldDataCache indicesFieldDataCache = new IndicesFieldDataCache(settings, new IndexFieldDataCache.Listener() {}); + closeables.add(indicesFieldDataCache); + IndicesQueryCache indicesQueryCache = new IndicesQueryCache(settings); + closeables.add(indicesQueryCache); + // this will also fail if some plugin fails etc. which is nice since we can verify that early + final IndexService service = createIndexService("metadata verification", nodeServicesProvider, + metaData, indicesQueryCache, indicesFieldDataCache, Collections.emptyList()); + for (ObjectCursor typeMapping : metaData.getMappings().values()) { + // don't apply the default mapping, it has been applied when the mapping was created + service.mapperService().merge(typeMapping.value.type(), typeMapping.value.source(), + MapperService.MergeReason.MAPPING_RECOVERY, true); + } + closeables.add(() -> service.close("metadata verification", false)); + } finally { + IOUtils.close(closeables); + } } /** @@ -542,6 +580,7 @@ public class IndicesService extends AbstractLifecycleComponent i * @param indexSettings the shards index settings. * @throws IOException if an IOException occurs */ + @Override public void deleteShardStore(String reason, ShardLock lock, IndexSettings indexSettings) throws IOException { ShardId shardId = lock.getShardId(); logger.trace("{} deleting shard reason [{}]", shardId, reason); @@ -654,6 +693,7 @@ public class IndicesService extends AbstractLifecycleComponent i /** * Adds a pending delete for the given index shard. */ + @Override public void addPendingDelete(ShardId shardId, IndexSettings settings) { if (shardId == null) { throw new IllegalArgumentException("shardId must not be null"); diff --git a/core/src/main/java/org/elasticsearch/indices/NodeIndicesStats.java b/core/src/main/java/org/elasticsearch/indices/NodeIndicesStats.java index da8e617759d..fce4e8411db 100644 --- a/core/src/main/java/org/elasticsearch/indices/NodeIndicesStats.java +++ b/core/src/main/java/org/elasticsearch/indices/NodeIndicesStats.java @@ -38,7 +38,7 @@ import org.elasticsearch.index.flush.FlushStats; import org.elasticsearch.index.get.GetStats; import org.elasticsearch.index.shard.IndexingStats; import org.elasticsearch.index.merge.MergeStats; -import org.elasticsearch.index.percolator.PercolateStats; +import org.elasticsearch.index.percolator.PercolatorQueryCacheStats; import org.elasticsearch.index.recovery.RecoveryStats; import org.elasticsearch.index.refresh.RefreshStats; import org.elasticsearch.index.search.stats.SearchStats; @@ -105,8 +105,8 @@ public class NodeIndicesStats implements Streamable, ToXContent { } @Nullable - public PercolateStats getPercolate() { - return stats.getPercolate(); + public PercolatorQueryCacheStats getPercolate() { + return stats.getPercolatorCache(); } @Nullable diff --git a/core/src/main/java/org/elasticsearch/indices/analysis/AnalysisModule.java b/core/src/main/java/org/elasticsearch/indices/analysis/AnalysisModule.java index e73396fcd7f..20a1d341cf9 100644 --- a/core/src/main/java/org/elasticsearch/indices/analysis/AnalysisModule.java +++ b/core/src/main/java/org/elasticsearch/indices/analysis/AnalysisModule.java @@ -160,15 +160,21 @@ public final class AnalysisModule extends AbstractModule { @Override protected void configure() { try { - HunspellService service = new HunspellService(environment.settings(), environment, knownDictionaries); - AnalysisRegistry registry = new AnalysisRegistry(service, environment, charFilters, tokenFilters, tokenizers, analyzers); - bind(HunspellService.class).toInstance(service); + AnalysisRegistry registry = buildRegistry(); + bind(HunspellService.class).toInstance(registry.getHunspellService()); bind(AnalysisRegistry.class).toInstance(registry); } catch (IOException e) { throw new ElasticsearchException("failed to load hunspell service", e); } } + /** + * Builds an {@link AnalysisRegistry} from the current configuration. + */ + public AnalysisRegistry buildRegistry() throws IOException { + return new AnalysisRegistry(new HunspellService(environment.settings(), environment, knownDictionaries), environment, charFilters, tokenFilters, tokenizers, analyzers); + } + /** * AnalysisProvider is the basic factory interface for registering analysis components like: *

    diff --git a/core/src/main/java/org/elasticsearch/indices/cluster/IndicesClusterStateService.java b/core/src/main/java/org/elasticsearch/indices/cluster/IndicesClusterStateService.java index 5d501b65686..46ead3fbf36 100644 --- a/core/src/main/java/org/elasticsearch/indices/cluster/IndicesClusterStateService.java +++ b/core/src/main/java/org/elasticsearch/indices/cluster/IndicesClusterStateService.java @@ -22,7 +22,6 @@ package org.elasticsearch.indices.cluster; import com.carrotsearch.hppc.IntHashSet; import com.carrotsearch.hppc.cursors.ObjectCursor; import org.elasticsearch.cluster.ClusterChangedEvent; -import org.elasticsearch.cluster.ClusterService; import org.elasticsearch.cluster.ClusterState; import org.elasticsearch.cluster.ClusterStateListener; import org.elasticsearch.cluster.action.index.NodeIndexDeletedAction; @@ -38,6 +37,7 @@ import org.elasticsearch.cluster.routing.RestoreSource; import org.elasticsearch.cluster.routing.RoutingNodes; import org.elasticsearch.cluster.routing.RoutingTable; import org.elasticsearch.cluster.routing.ShardRouting; +import org.elasticsearch.cluster.service.ClusterService; import org.elasticsearch.common.Nullable; import org.elasticsearch.common.component.AbstractLifecycleComponent; import org.elasticsearch.common.compress.CompressedXContent; diff --git a/core/src/main/java/org/elasticsearch/indices/flush/SyncedFlushService.java b/core/src/main/java/org/elasticsearch/indices/flush/SyncedFlushService.java index 6943ecd7504..b1d7af7ff9c 100644 --- a/core/src/main/java/org/elasticsearch/indices/flush/SyncedFlushService.java +++ b/core/src/main/java/org/elasticsearch/indices/flush/SyncedFlushService.java @@ -23,7 +23,6 @@ import org.elasticsearch.action.ActionListener; import org.elasticsearch.action.admin.indices.flush.FlushRequest; import org.elasticsearch.action.admin.indices.flush.SyncedFlushResponse; import org.elasticsearch.action.support.IndicesOptions; -import org.elasticsearch.cluster.ClusterService; import org.elasticsearch.cluster.ClusterState; import org.elasticsearch.cluster.metadata.IndexMetaData; import org.elasticsearch.cluster.metadata.IndexNameExpressionResolver; @@ -31,6 +30,7 @@ import org.elasticsearch.cluster.node.DiscoveryNode; import org.elasticsearch.cluster.routing.IndexRoutingTable; import org.elasticsearch.cluster.routing.IndexShardRoutingTable; import org.elasticsearch.cluster.routing.ShardRouting; +import org.elasticsearch.cluster.service.ClusterService; import org.elasticsearch.common.Strings; import org.elasticsearch.common.component.AbstractComponent; import org.elasticsearch.common.inject.Inject; diff --git a/core/src/main/java/org/elasticsearch/indices/recovery/RecoverySource.java b/core/src/main/java/org/elasticsearch/indices/recovery/RecoverySource.java index 934730c7c93..aaf351f6056 100644 --- a/core/src/main/java/org/elasticsearch/indices/recovery/RecoverySource.java +++ b/core/src/main/java/org/elasticsearch/indices/recovery/RecoverySource.java @@ -20,9 +20,9 @@ package org.elasticsearch.indices.recovery; import org.elasticsearch.ExceptionsHelper; -import org.elasticsearch.cluster.ClusterService; import org.elasticsearch.cluster.routing.RoutingNode; import org.elasticsearch.cluster.routing.ShardRouting; +import org.elasticsearch.cluster.service.ClusterService; import org.elasticsearch.common.Nullable; import org.elasticsearch.common.component.AbstractComponent; import org.elasticsearch.common.inject.Inject; diff --git a/core/src/main/java/org/elasticsearch/indices/recovery/RecoveryTargetService.java b/core/src/main/java/org/elasticsearch/indices/recovery/RecoveryTargetService.java index ab8c87cd636..d57cfbb98c8 100644 --- a/core/src/main/java/org/elasticsearch/indices/recovery/RecoveryTargetService.java +++ b/core/src/main/java/org/elasticsearch/indices/recovery/RecoveryTargetService.java @@ -24,10 +24,10 @@ import org.apache.lucene.store.RateLimiter; import org.elasticsearch.ElasticsearchException; import org.elasticsearch.ElasticsearchTimeoutException; import org.elasticsearch.ExceptionsHelper; -import org.elasticsearch.cluster.ClusterService; import org.elasticsearch.cluster.ClusterState; import org.elasticsearch.cluster.ClusterStateObserver; import org.elasticsearch.cluster.node.DiscoveryNode; +import org.elasticsearch.cluster.service.ClusterService; import org.elasticsearch.common.Nullable; import org.elasticsearch.common.component.AbstractComponent; import org.elasticsearch.common.inject.Inject; diff --git a/core/src/main/java/org/elasticsearch/indices/store/IndicesStore.java b/core/src/main/java/org/elasticsearch/indices/store/IndicesStore.java index 5dc8af41e80..d2db41a7a0c 100644 --- a/core/src/main/java/org/elasticsearch/indices/store/IndicesStore.java +++ b/core/src/main/java/org/elasticsearch/indices/store/IndicesStore.java @@ -21,7 +21,6 @@ package org.elasticsearch.indices.store; import org.elasticsearch.cluster.ClusterChangedEvent; import org.elasticsearch.cluster.ClusterName; -import org.elasticsearch.cluster.ClusterService; import org.elasticsearch.cluster.ClusterState; import org.elasticsearch.cluster.ClusterStateListener; import org.elasticsearch.cluster.ClusterStateObserver; @@ -31,6 +30,7 @@ import org.elasticsearch.cluster.node.DiscoveryNode; import org.elasticsearch.cluster.routing.IndexRoutingTable; import org.elasticsearch.cluster.routing.IndexShardRoutingTable; import org.elasticsearch.cluster.routing.ShardRouting; +import org.elasticsearch.cluster.service.ClusterService; import org.elasticsearch.common.collect.Tuple; import org.elasticsearch.common.component.AbstractComponent; import org.elasticsearch.common.inject.Inject; diff --git a/core/src/main/java/org/elasticsearch/indices/store/TransportNodesListShardStoreMetaData.java b/core/src/main/java/org/elasticsearch/indices/store/TransportNodesListShardStoreMetaData.java index 0422c0944e2..35a34ebea1b 100644 --- a/core/src/main/java/org/elasticsearch/indices/store/TransportNodesListShardStoreMetaData.java +++ b/core/src/main/java/org/elasticsearch/indices/store/TransportNodesListShardStoreMetaData.java @@ -29,11 +29,11 @@ import org.elasticsearch.action.support.nodes.BaseNodesRequest; import org.elasticsearch.action.support.nodes.BaseNodesResponse; import org.elasticsearch.action.support.nodes.TransportNodesAction; import org.elasticsearch.cluster.ClusterName; -import org.elasticsearch.cluster.ClusterService; import org.elasticsearch.cluster.ClusterState; import org.elasticsearch.cluster.metadata.IndexMetaData; import org.elasticsearch.cluster.metadata.IndexNameExpressionResolver; import org.elasticsearch.cluster.node.DiscoveryNode; +import org.elasticsearch.cluster.service.ClusterService; import org.elasticsearch.common.inject.Inject; import org.elasticsearch.common.io.stream.StreamInput; import org.elasticsearch.common.io.stream.StreamOutput; diff --git a/core/src/main/java/org/elasticsearch/indices/ttl/IndicesTTLService.java b/core/src/main/java/org/elasticsearch/indices/ttl/IndicesTTLService.java index 422a08042ce..a30ae49ff7b 100644 --- a/core/src/main/java/org/elasticsearch/indices/ttl/IndicesTTLService.java +++ b/core/src/main/java/org/elasticsearch/indices/ttl/IndicesTTLService.java @@ -30,9 +30,9 @@ import org.elasticsearch.action.bulk.BulkRequest; import org.elasticsearch.action.bulk.BulkResponse; import org.elasticsearch.action.bulk.TransportBulkAction; import org.elasticsearch.action.delete.DeleteRequest; -import org.elasticsearch.cluster.ClusterService; import org.elasticsearch.cluster.metadata.IndexMetaData; import org.elasticsearch.cluster.metadata.MetaData; +import org.elasticsearch.cluster.service.ClusterService; import org.elasticsearch.common.component.AbstractLifecycleComponent; import org.elasticsearch.common.inject.Inject; import org.elasticsearch.common.lucene.uid.Versions; diff --git a/core/src/main/java/org/elasticsearch/ingest/PipelineStore.java b/core/src/main/java/org/elasticsearch/ingest/PipelineStore.java index ac2df419f55..7e0dc1b4ffa 100644 --- a/core/src/main/java/org/elasticsearch/ingest/PipelineStore.java +++ b/core/src/main/java/org/elasticsearch/ingest/PipelineStore.java @@ -28,11 +28,11 @@ import org.elasticsearch.action.ingest.PutPipelineRequest; import org.elasticsearch.action.ingest.WritePipelineResponse; import org.elasticsearch.cluster.AckedClusterStateUpdateTask; import org.elasticsearch.cluster.ClusterChangedEvent; -import org.elasticsearch.cluster.ClusterService; import org.elasticsearch.cluster.ClusterState; import org.elasticsearch.cluster.ClusterStateListener; import org.elasticsearch.cluster.metadata.MetaData; import org.elasticsearch.cluster.node.DiscoveryNode; +import org.elasticsearch.cluster.service.ClusterService; import org.elasticsearch.common.component.AbstractComponent; import org.elasticsearch.common.regex.Regex; import org.elasticsearch.common.settings.Settings; @@ -40,7 +40,6 @@ import org.elasticsearch.common.xcontent.XContentHelper; import org.elasticsearch.ingest.core.IngestInfo; import org.elasticsearch.ingest.core.Pipeline; import org.elasticsearch.ingest.core.Processor; -import org.elasticsearch.ingest.core.ProcessorInfo; import org.elasticsearch.ingest.core.TemplateService; import org.elasticsearch.script.ScriptService; @@ -51,7 +50,6 @@ import java.util.Collections; import java.util.HashMap; import java.util.List; import java.util.Map; -import java.util.Objects; public class PipelineStore extends AbstractComponent implements Closeable, ClusterStateListener { diff --git a/core/src/main/java/org/elasticsearch/ingest/processor/ForEachProcessor.java b/core/src/main/java/org/elasticsearch/ingest/processor/ForEachProcessor.java index 5b101fbfb32..b6f6a85d219 100644 --- a/core/src/main/java/org/elasticsearch/ingest/processor/ForEachProcessor.java +++ b/core/src/main/java/org/elasticsearch/ingest/processor/ForEachProcessor.java @@ -59,11 +59,8 @@ public final class ForEachProcessor extends AbstractProcessor { List values = ingestDocument.getFieldValue(field, List.class); List newValues = new ArrayList<>(values.size()); for (Object value : values) { - Map innerSource = new HashMap<>(); - innerSource.put("_value", value); - for (IngestDocument.MetaData metaData : IngestDocument.MetaData.values()) { - innerSource.put(metaData.getFieldName(), ingestDocument.getSourceAndMetadata().get(metaData.getFieldName())); - } + Map innerSource = new HashMap<>(ingestDocument.getSourceAndMetadata()); + innerSource.put("_value", value); // scalar value to access the list item being evaluated IngestDocument innerIngestDocument = new IngestDocument(innerSource, ingestDocument.getIngestMetadata()); for (Processor processor : processors) { processor.execute(innerIngestDocument); diff --git a/core/src/main/java/org/elasticsearch/node/Node.java b/core/src/main/java/org/elasticsearch/node/Node.java index 3388fb1e2c0..6e270ffc3ff 100644 --- a/core/src/main/java/org/elasticsearch/node/Node.java +++ b/core/src/main/java/org/elasticsearch/node/Node.java @@ -30,7 +30,6 @@ import org.elasticsearch.client.Client; import org.elasticsearch.client.node.NodeClientModule; import org.elasticsearch.cluster.ClusterModule; import org.elasticsearch.cluster.ClusterNameModule; -import org.elasticsearch.cluster.ClusterService; import org.elasticsearch.cluster.ClusterState; import org.elasticsearch.cluster.ClusterStateObserver; import org.elasticsearch.cluster.MasterNodeChangePredicate; @@ -39,7 +38,7 @@ import org.elasticsearch.cluster.action.index.MappingUpdatedAction; import org.elasticsearch.cluster.node.DiscoveryNode; import org.elasticsearch.cluster.node.DiscoveryNodeService; import org.elasticsearch.cluster.routing.RoutingService; -import org.elasticsearch.cluster.service.InternalClusterService; +import org.elasticsearch.cluster.service.ClusterService; import org.elasticsearch.common.StopWatch; import org.elasticsearch.common.component.Lifecycle; import org.elasticsearch.common.component.LifecycleComponent; @@ -84,8 +83,6 @@ import org.elasticsearch.monitor.MonitorService; import org.elasticsearch.monitor.jvm.JvmInfo; import org.elasticsearch.node.internal.InternalSettingsPreparer; import org.elasticsearch.node.service.NodeService; -import org.elasticsearch.percolator.PercolatorModule; -import org.elasticsearch.percolator.PercolatorService; import org.elasticsearch.plugins.Plugin; import org.elasticsearch.plugins.PluginsModule; import org.elasticsearch.plugins.PluginsService; @@ -226,7 +223,6 @@ public class Node implements Closeable { modules.add(new ActionModule(DiscoveryNode.ingestNode(settings), false)); modules.add(new GatewayModule(settings)); modules.add(new NodeClientModule()); - modules.add(new PercolatorModule()); modules.add(new ResourceWatcherModule()); modules.add(new RepositoriesModule()); modules.add(new TribeModule()); @@ -299,9 +295,7 @@ public class Node implements Closeable { injector.getInstance(MonitorService.class).start(); injector.getInstance(RestController.class).start(); - assert injector.getInstance(ClusterService.class) instanceof InternalClusterService : - "node cluster service implementation must inherit from InternalClusterService"; - final InternalClusterService clusterService = (InternalClusterService) injector.getInstance(ClusterService.class); + final ClusterService clusterService = injector.getInstance(ClusterService.class); final NodeConnectionsService nodeConnectionsService = injector.getInstance(NodeConnectionsService.class); nodeConnectionsService.start(); @@ -486,8 +480,6 @@ public class Node implements Closeable { toClose.add(injector.getInstance(RestController.class)); toClose.add(() -> stopWatch.stop().start("transport")); toClose.add(injector.getInstance(TransportService.class)); - toClose.add(() -> stopWatch.stop().start("percolator_service")); - toClose.add(injector.getInstance(PercolatorService.class)); for (Class plugin : pluginsService.nodeServices()) { toClose.add(() -> stopWatch.stop().start("plugin(" + plugin.getName() + ")")); diff --git a/core/src/main/java/org/elasticsearch/node/service/NodeService.java b/core/src/main/java/org/elasticsearch/node/service/NodeService.java index 7096b7cc56c..cb11fc02443 100644 --- a/core/src/main/java/org/elasticsearch/node/service/NodeService.java +++ b/core/src/main/java/org/elasticsearch/node/service/NodeService.java @@ -24,7 +24,7 @@ import org.elasticsearch.Version; import org.elasticsearch.action.admin.cluster.node.info.NodeInfo; import org.elasticsearch.action.admin.cluster.node.stats.NodeStats; import org.elasticsearch.action.admin.indices.stats.CommonStatsFlags; -import org.elasticsearch.cluster.ClusterService; +import org.elasticsearch.cluster.service.ClusterService; import org.elasticsearch.common.Nullable; import org.elasticsearch.common.component.AbstractComponent; import org.elasticsearch.common.inject.Inject; diff --git a/core/src/main/java/org/elasticsearch/percolator/MultiDocumentPercolatorIndex.java b/core/src/main/java/org/elasticsearch/percolator/MultiDocumentPercolatorIndex.java deleted file mode 100644 index 9d091a4c0bd..00000000000 --- a/core/src/main/java/org/elasticsearch/percolator/MultiDocumentPercolatorIndex.java +++ /dev/null @@ -1,150 +0,0 @@ -/* - * Licensed to Elasticsearch under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch 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.elasticsearch.percolator; - -import org.apache.lucene.analysis.Analyzer; -import org.apache.lucene.analysis.TokenStream; -import org.apache.lucene.index.IndexOptions; -import org.apache.lucene.index.IndexReader; -import org.apache.lucene.index.IndexableField; -import org.apache.lucene.index.LeafReader; -import org.apache.lucene.index.MultiReader; -import org.apache.lucene.index.SlowCompositeReaderWrapper; -import org.apache.lucene.index.memory.MemoryIndex; -import org.apache.lucene.search.BooleanClause; -import org.apache.lucene.search.BooleanQuery; -import org.apache.lucene.search.Collector; -import org.apache.lucene.search.IndexSearcher; -import org.apache.lucene.search.Query; -import org.apache.lucene.search.Weight; -import org.apache.lucene.util.CloseableThreadLocal; -import org.elasticsearch.ElasticsearchException; -import org.elasticsearch.common.lucene.search.Queries; -import org.elasticsearch.index.engine.Engine; -import org.elasticsearch.index.mapper.DocumentMapper; -import org.elasticsearch.index.mapper.MapperService; -import org.elasticsearch.index.mapper.ParseContext; -import org.elasticsearch.index.mapper.ParsedDocument; -import org.elasticsearch.index.mapper.internal.UidFieldMapper; - -import java.io.IOException; -import java.util.List; - - -/** - * Implementation of {@link PercolatorIndex} that can hold multiple Lucene documents by - * opening multiple {@link MemoryIndex} based IndexReaders and wrapping them via a single top level reader. - */ -class MultiDocumentPercolatorIndex implements PercolatorIndex { - - private final CloseableThreadLocal cache; - - MultiDocumentPercolatorIndex(CloseableThreadLocal cache) { - this.cache = cache; - } - - @Override - public void prepare(PercolateContext context, ParsedDocument parsedDocument) { - IndexReader[] memoryIndices = new IndexReader[parsedDocument.docs().size()]; - List docs = parsedDocument.docs(); - int rootDocIndex = docs.size() - 1; - assert rootDocIndex > 0; - MemoryIndex rootDocMemoryIndex = null; - for (int i = 0; i < docs.size(); i++) { - ParseContext.Document d = docs.get(i); - MemoryIndex memoryIndex; - if (rootDocIndex == i) { - // the last doc is always the rootDoc, since that is usually the biggest document it make sense - // to reuse the MemoryIndex it uses - memoryIndex = rootDocMemoryIndex = cache.get(); - } else { - memoryIndex = new MemoryIndex(true); - } - memoryIndices[i] = indexDoc(d, memoryIndex, context, parsedDocument).createSearcher().getIndexReader(); - } - try { - MultiReader mReader = new MultiReader(memoryIndices, true); - LeafReader slowReader = SlowCompositeReaderWrapper.wrap(mReader); - final IndexSearcher slowSearcher = new IndexSearcher(slowReader) { - - @Override - public Weight createNormalizedWeight(Query query, boolean needsScores) throws IOException { - BooleanQuery.Builder bq = new BooleanQuery.Builder(); - bq.add(query, BooleanClause.Occur.MUST); - bq.add(Queries.newNestedFilter(), BooleanClause.Occur.MUST_NOT); - return super.createNormalizedWeight(bq.build(), needsScores); - } - - }; - slowSearcher.setQueryCache(null); - DocSearcher docSearcher = new DocSearcher(slowSearcher, rootDocMemoryIndex); - context.initialize(docSearcher, parsedDocument); - } catch (IOException e) { - throw new ElasticsearchException("Failed to create index for percolator with nested document ", e); - } - } - - MemoryIndex indexDoc(ParseContext.Document d, MemoryIndex memoryIndex, PercolateContext context, ParsedDocument parsedDocument) { - for (IndexableField field : d.getFields()) { - Analyzer analyzer = context.analysisService().defaultIndexAnalyzer(); - DocumentMapper documentMapper = context.mapperService().documentMapper(parsedDocument.type()); - if (documentMapper != null && documentMapper.mappers().getMapper(field.name()) != null) { - analyzer = documentMapper.mappers().indexAnalyzer(); - } - if (field.fieldType().indexOptions() == IndexOptions.NONE && field.name().equals(UidFieldMapper.NAME)) { - continue; - } - try { - // TODO: instead of passing null here, we can have a CTL> and pass previous, - // like the indexer does - try (TokenStream tokenStream = field.tokenStream(analyzer, null)) { - if (tokenStream != null) { - memoryIndex.addField(field.name(), tokenStream, field.boost()); - } - } - } catch (IOException e) { - throw new ElasticsearchException("Failed to create token stream", e); - } - } - return memoryIndex; - } - - private class DocSearcher extends Engine.Searcher { - - private final MemoryIndex rootDocMemoryIndex; - - private DocSearcher(IndexSearcher searcher, MemoryIndex rootDocMemoryIndex) { - super("percolate", searcher); - this.rootDocMemoryIndex = rootDocMemoryIndex; - } - - @Override - public void close() { - try { - this.reader().close(); - rootDocMemoryIndex.reset(); - } catch (IOException e) { - throw new ElasticsearchException("failed to close IndexReader in percolator with nested doc", e); - } - } - - } -} diff --git a/core/src/main/java/org/elasticsearch/percolator/PercolateContext.java b/core/src/main/java/org/elasticsearch/percolator/PercolateContext.java deleted file mode 100644 index f73c8f31a07..00000000000 --- a/core/src/main/java/org/elasticsearch/percolator/PercolateContext.java +++ /dev/null @@ -1,691 +0,0 @@ -/* - * Licensed to Elasticsearch under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch 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.elasticsearch.percolator; - - -import org.apache.lucene.index.IndexReader; -import org.apache.lucene.index.IndexableField; -import org.apache.lucene.index.LeafReaderContext; -import org.apache.lucene.search.Collector; -import org.apache.lucene.search.IndexSearcher; -import org.apache.lucene.search.Query; -import org.apache.lucene.search.Sort; -import org.apache.lucene.search.FieldDoc; -import org.apache.lucene.util.Counter; -import org.elasticsearch.action.percolate.PercolateShardRequest; -import org.elasticsearch.action.search.SearchType; -import org.elasticsearch.cache.recycler.PageCacheRecycler; -import org.elasticsearch.common.ParseFieldMatcher; -import org.elasticsearch.common.lease.Releasables; -import org.elasticsearch.common.text.Text; -import org.elasticsearch.common.util.BigArrays; -import org.elasticsearch.index.IndexService; -import org.elasticsearch.index.analysis.AnalysisService; -import org.elasticsearch.index.cache.bitset.BitsetFilterCache; -import org.elasticsearch.index.engine.Engine; -import org.elasticsearch.index.fielddata.IndexFieldDataService; -import org.elasticsearch.index.mapper.MappedFieldType; -import org.elasticsearch.index.mapper.MapperService; -import org.elasticsearch.index.mapper.ParsedDocument; -import org.elasticsearch.index.mapper.object.ObjectMapper; -import org.elasticsearch.index.query.ParsedQuery; -import org.elasticsearch.index.query.QueryShardContext; -import org.elasticsearch.index.shard.IndexShard; -import org.elasticsearch.index.similarity.SimilarityService; -import org.elasticsearch.script.ScriptService; -import org.elasticsearch.search.SearchHitField; -import org.elasticsearch.search.SearchShardTarget; -import org.elasticsearch.search.aggregations.SearchContextAggregations; -import org.elasticsearch.search.dfs.DfsSearchResult; -import org.elasticsearch.search.fetch.FetchPhase; -import org.elasticsearch.search.fetch.FetchSearchResult; -import org.elasticsearch.search.fetch.FetchSubPhase; -import org.elasticsearch.search.fetch.FetchSubPhaseContext; -import org.elasticsearch.search.fetch.innerhits.InnerHitsContext; -import org.elasticsearch.search.fetch.script.ScriptFieldsContext; -import org.elasticsearch.search.fetch.source.FetchSourceContext; -import org.elasticsearch.search.highlight.SearchContextHighlight; -import org.elasticsearch.search.internal.ContextIndexSearcher; -import org.elasticsearch.search.internal.InternalSearchHit; -import org.elasticsearch.search.internal.InternalSearchHitField; -import org.elasticsearch.search.internal.ScrollContext; -import org.elasticsearch.search.internal.SearchContext; -import org.elasticsearch.search.internal.ShardSearchRequest; -import org.elasticsearch.search.lookup.LeafSearchLookup; -import org.elasticsearch.search.lookup.SearchLookup; -import org.elasticsearch.search.profile.Profilers; -import org.elasticsearch.search.query.QuerySearchResult; -import org.elasticsearch.search.rescore.RescoreSearchContext; -import org.elasticsearch.search.suggest.SuggestionSearchContext; - -import java.util.Arrays; -import java.util.Collections; -import java.util.HashMap; -import java.util.List; -import java.util.Map; - -/** - */ -public class PercolateContext extends SearchContext { - - private int size = 10; - private boolean trackScores; - - private final SearchShardTarget searchShardTarget; - private final IndexService indexService; - private final IndexFieldDataService fieldDataService; - private final IndexShard indexShard; - private final PageCacheRecycler pageCacheRecycler; - private final BigArrays bigArrays; - private final ScriptService scriptService; - private final MapperService mapperService; - private final int numberOfShards; - private final Query aliasFilter; - private final long originNanoTime = System.nanoTime(); - private final long startTime; - private final boolean onlyCount; - private Engine.Searcher docSearcher; - private Engine.Searcher engineSearcher; - private ContextIndexSearcher searcher; - - private SearchContextHighlight highlight; - private ParsedQuery parsedQuery; - private Query query; - private Query percolateQuery; - private FetchSubPhase.HitContext hitContext; - private SearchContextAggregations aggregations; - private QuerySearchResult querySearchResult; - private Sort sort; - private final Map subPhaseContexts = new HashMap<>(); - private final QueryShardContext queryShardContext; - private final Map, Collector> queryCollectors = new HashMap<>(); - private SearchLookup searchLookup; - private final FetchPhase fetchPhase; - - public PercolateContext(PercolateShardRequest request, SearchShardTarget searchShardTarget, IndexShard indexShard, - IndexService indexService, PageCacheRecycler pageCacheRecycler, BigArrays bigArrays, ScriptService scriptService, - Query aliasFilter, ParseFieldMatcher parseFieldMatcher, FetchPhase fetchPhase) { - super(parseFieldMatcher); - this.indexShard = indexShard; - this.indexService = indexService; - this.fetchPhase = fetchPhase; - this.fieldDataService = indexService.fieldData(); - this.mapperService = indexService.mapperService(); - this.searchShardTarget = searchShardTarget; - this.pageCacheRecycler = pageCacheRecycler; - this.bigArrays = bigArrays.withCircuitBreaking(); - this.querySearchResult = new QuerySearchResult(0, searchShardTarget); - this.engineSearcher = indexShard.acquireSearcher("percolate"); - this.searcher = new ContextIndexSearcher(engineSearcher, indexService.cache().query(), indexShard.getQueryCachingPolicy()); - this.scriptService = scriptService; - this.numberOfShards = request.getNumberOfShards(); - this.aliasFilter = aliasFilter; - this.startTime = request.getStartTime(); - this.onlyCount = request.onlyCount(); - queryShardContext = indexService.newQueryShardContext(); - queryShardContext.setTypes(request.documentType()); - } - - // for testing: - PercolateContext(PercolateShardRequest request, SearchShardTarget searchShardTarget, MapperService mapperService, QueryShardContext queryShardContext) { - super(null); - this.searchShardTarget = searchShardTarget; - this.mapperService = mapperService; - this.indexService = null; - this.indexShard = null; - this.fieldDataService = null; - this.pageCacheRecycler = null; - this.bigArrays = null; - this.scriptService = null; - this.aliasFilter = null; - this.startTime = 0; - this.numberOfShards = 0; - this.onlyCount = true; - this.queryShardContext = queryShardContext; - this.fetchPhase = null; - } - - public IndexSearcher docSearcher() { - return docSearcher.searcher(); - } - - public void initialize(Engine.Searcher docSearcher, ParsedDocument parsedDocument) { - this.docSearcher = docSearcher; - IndexReader indexReader = docSearcher.reader(); - LeafReaderContext atomicReaderContext = indexReader.leaves().get(0); - this.searchLookup = new SearchLookup(mapperService(), fieldData(), queryShardContext.getTypes()); - LeafSearchLookup leafLookup = searchLookup.getLeafSearchLookup(atomicReaderContext); - leafLookup.setDocument(0); - leafLookup.source().setSource(parsedDocument.source()); - - Map fields = new HashMap<>(); - for (IndexableField field : parsedDocument.rootDoc().getFields()) { - fields.put(field.name(), new InternalSearchHitField(field.name(), Collections.emptyList())); - } - hitContext().reset( - new InternalSearchHit(0, "unknown", new Text(parsedDocument.type()), fields), - atomicReaderContext, 0, docSearcher.searcher() - ); - } - - @Override - public IndexShard indexShard() { - return indexShard; - } - - public IndexService indexService() { - return indexService; - } - - public Query percolateQuery() { - return percolateQuery; - } - - public void percolateQuery(Query percolateQuery) { - this.percolateQuery = percolateQuery; - } - - public FetchSubPhase.HitContext hitContext() { - if (hitContext == null) { - hitContext = new FetchSubPhase.HitContext(); - } - return hitContext; - } - - public boolean isOnlyCount() { - return onlyCount; - } - - public Query percolatorTypeFilter(){ - return indexService().mapperService().documentMapper(PercolatorService.TYPE_NAME).typeFilter(); - } - - @Override - public SearchContextHighlight highlight() { - return highlight; - } - - @Override - public void highlight(SearchContextHighlight highlight) { - if (highlight != null) { - // Enforce highlighting by source, because MemoryIndex doesn't support stored fields. - highlight.globalForceSource(true); - } - this.highlight = highlight; - } - - @Override - public SearchShardTarget shardTarget() { - return searchShardTarget; - } - - @Override - public SearchLookup lookup() { - // we cache this since it's really just a single document lookup - check the init method for details - assert searchLookup != null : "context is not initialized"; - assert Arrays.equals(searchLookup.doc().getTypes(), getQueryShardContext().getTypes()) : "types mismatch - can't return lookup"; - return this.searchLookup; - } - - @Override - protected void doClose() { - Releasables.close(engineSearcher, docSearcher); - } - - @Override - public MapperService mapperService() { - return mapperService; - } - - @Override - public SearchContext parsedQuery(ParsedQuery query) { - this.parsedQuery = query; - this.query = query.query(); - return this; - } - - @Override - public ParsedQuery parsedQuery() { - return parsedQuery; - } - - @Override - public Query query() { - return query; - } - - @Override - public IndexFieldDataService fieldData() { - return fieldDataService; - } - - @Override - public SearchContextAggregations aggregations() { - return aggregations; - } - - @Override - public SearchContext aggregations(SearchContextAggregations aggregations) { - this.aggregations = aggregations; - return this; - } - - @Override - public SubPhaseContext getFetchSubPhaseContext(FetchSubPhase.ContextFactory contextFactory) { - String subPhaseName = contextFactory.getName(); - if (subPhaseContexts.get(subPhaseName) == null) { - subPhaseContexts.put(subPhaseName, contextFactory.newContextInstance()); - } - return (SubPhaseContext) subPhaseContexts.get(subPhaseName); - } - - // Unused: - @Override - public void preProcess() { - throw new UnsupportedOperationException(); - } - - @Override - public Query searchFilter(String[] types) { - return aliasFilter(); - } - - @Override - public long id() { - throw new UnsupportedOperationException(); - } - - @Override - public String source() { - throw new UnsupportedOperationException(); - } - - @Override - public ShardSearchRequest request() { - throw new UnsupportedOperationException(); - } - - @Override - public SearchType searchType() { - throw new UnsupportedOperationException(); - } - - @Override - public SearchContext searchType(SearchType searchType) { - throw new UnsupportedOperationException(); - } - - @Override - public int numberOfShards() { - return numberOfShards; - } - - @Override - public float queryBoost() { - throw new UnsupportedOperationException(); - } - - @Override - public SearchContext queryBoost(float queryBoost) { - throw new UnsupportedOperationException(); - } - - @Override - public long getOriginNanoTime() { - return originNanoTime; - } - - @Override - protected long nowInMillisImpl() { - return startTime; - } - - @Override - public ScrollContext scrollContext() { - throw new UnsupportedOperationException(); - } - - @Override - public SearchContext scrollContext(ScrollContext scroll) { - throw new UnsupportedOperationException(); - } - - @Override - public SuggestionSearchContext suggest() { - throw new UnsupportedOperationException(); - } - - @Override - public void suggest(SuggestionSearchContext suggest) { - throw new UnsupportedOperationException(); - } - - @Override - public List rescore() { - throw new UnsupportedOperationException(); - } - - @Override - public void addRescore(RescoreSearchContext rescore) { - throw new UnsupportedOperationException(); - } - - @Override - public boolean hasScriptFields() { - throw new UnsupportedOperationException(); - } - - @Override - public ScriptFieldsContext scriptFields() { - throw new UnsupportedOperationException(); - } - - @Override - public boolean sourceRequested() { - throw new UnsupportedOperationException(); - } - - @Override - public boolean hasFetchSourceContext() { - throw new UnsupportedOperationException(); - } - - @Override - public FetchSourceContext fetchSourceContext() { - throw new UnsupportedOperationException(); - } - - @Override - public SearchContext fetchSourceContext(FetchSourceContext fetchSourceContext) { - throw new UnsupportedOperationException(); - } - - @Override - public ContextIndexSearcher searcher() { - return searcher; - } - - @Override - public AnalysisService analysisService() { - return indexService.analysisService(); - } - - @Override - public SimilarityService similarityService() { - return indexService.similarityService(); - } - - @Override - public ScriptService scriptService() { - return scriptService; - } - - @Override - public PageCacheRecycler pageCacheRecycler() { - return pageCacheRecycler; - } - - @Override - public BigArrays bigArrays() { - return bigArrays; - } - - @Override - public BitsetFilterCache bitsetFilterCache() { - return indexService.cache().bitsetFilterCache(); - } - - @Override - public long timeoutInMillis() { - return -1; - } - - @Override - public void timeoutInMillis(long timeoutInMillis) { - throw new UnsupportedOperationException(); - } - - @Override - public int terminateAfter() { - return DEFAULT_TERMINATE_AFTER; - } - - @Override - public void terminateAfter(int terminateAfter) { - throw new UnsupportedOperationException(); - } - - @Override - public SearchContext minimumScore(float minimumScore) { - throw new UnsupportedOperationException(); - } - - @Override - public Float minimumScore() { - return null; - } - - @Override - public SearchContext sort(Sort sort) { - this.sort = sort; - return this; - } - - @Override - public Sort sort() { - return sort; - } - - @Override - public SearchContext trackScores(boolean trackScores) { - this.trackScores = trackScores; - return this; - } - - @Override - public boolean trackScores() { - return trackScores; - } - - @Override - public SearchContext searchAfter(FieldDoc searchAfter) { - throw new UnsupportedOperationException(); - } - - @Override - public FieldDoc searchAfter() { - return null; - } - - @Override - public SearchContext parsedPostFilter(ParsedQuery postFilter) { - throw new UnsupportedOperationException(); - } - - @Override - public ParsedQuery parsedPostFilter() { - return null; - } - - @Override - public Query aliasFilter() { - return aliasFilter; - } - - @Override - public int from() { - return 0; - } - - @Override - public SearchContext from(int from) { - throw new UnsupportedOperationException(); - } - - @Override - public int size() { - return size; - } - - @Override - public SearchContext size(int size) { - this.size = size; - return this; - } - - @Override - public boolean hasFieldNames() { - throw new UnsupportedOperationException(); - } - - @Override - public List fieldNames() { - throw new UnsupportedOperationException(); - } - - @Override - public void emptyFieldNames() { - throw new UnsupportedOperationException(); - } - - @Override - public boolean explain() { - throw new UnsupportedOperationException(); - } - - @Override - public void explain(boolean explain) { - throw new UnsupportedOperationException(); - } - - @Override - public List groupStats() { - throw new UnsupportedOperationException(); - } - - @Override - public void groupStats(List groupStats) { - throw new UnsupportedOperationException(); - } - - @Override - public boolean version() { - throw new UnsupportedOperationException(); - } - - @Override - public void version(boolean version) { - throw new UnsupportedOperationException(); - } - - @Override - public int[] docIdsToLoad() { - throw new UnsupportedOperationException(); - } - - @Override - public int docIdsToLoadFrom() { - throw new UnsupportedOperationException(); - } - - @Override - public int docIdsToLoadSize() { - throw new UnsupportedOperationException(); - } - - @Override - public SearchContext docIdsToLoad(int[] docIdsToLoad, int docsIdsToLoadFrom, int docsIdsToLoadSize) { - throw new UnsupportedOperationException(); - } - - @Override - public void accessed(long accessTime) { - throw new UnsupportedOperationException(); - } - - @Override - public long lastAccessTime() { - throw new UnsupportedOperationException(); - } - - @Override - public long keepAlive() { - throw new UnsupportedOperationException(); - } - - @Override - public void keepAlive(long keepAlive) { - throw new UnsupportedOperationException(); - } - - @Override - public DfsSearchResult dfsResult() { - throw new UnsupportedOperationException(); - } - - @Override - public QuerySearchResult queryResult() { - return querySearchResult; - } - - @Override - public FetchSearchResult fetchResult() { - throw new UnsupportedOperationException(); - } - - @Override - public FetchPhase fetchPhase() { - return fetchPhase; - } - - @Override - public MappedFieldType smartNameFieldType(String name) { - return mapperService().fullName(name); - } - - @Override - public ObjectMapper getObjectMapper(String name) { - throw new UnsupportedOperationException(); - } - - @Override - public Counter timeEstimateCounter() { - throw new UnsupportedOperationException(); - } - - @Override - public InnerHitsContext innerHits() { - throw new UnsupportedOperationException(); - } - - @Override - public Map, Collector> queryCollectors() { - return queryCollectors; - } - - @Override - public QueryShardContext getQueryShardContext() { - return queryShardContext; - } - - @Override - public Profilers getProfilers() { - throw new UnsupportedOperationException(); - } -} diff --git a/core/src/main/java/org/elasticsearch/percolator/PercolateDocumentParser.java b/core/src/main/java/org/elasticsearch/percolator/PercolateDocumentParser.java deleted file mode 100644 index 50db3cecaa6..00000000000 --- a/core/src/main/java/org/elasticsearch/percolator/PercolateDocumentParser.java +++ /dev/null @@ -1,215 +0,0 @@ -/* - * Licensed to Elasticsearch under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch 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.elasticsearch.percolator; - -import org.apache.lucene.search.ConstantScoreQuery; -import org.apache.lucene.search.Query; -import org.elasticsearch.ElasticsearchParseException; -import org.elasticsearch.action.percolate.PercolateShardRequest; -import org.elasticsearch.common.bytes.BytesReference; -import org.elasticsearch.common.inject.Inject; -import org.elasticsearch.common.io.stream.BytesStreamOutput; -import org.elasticsearch.common.xcontent.XContentBuilder; -import org.elasticsearch.common.xcontent.XContentFactory; -import org.elasticsearch.common.xcontent.XContentParser; -import org.elasticsearch.common.xcontent.XContentType; -import org.elasticsearch.index.mapper.DocumentMapperForType; -import org.elasticsearch.index.mapper.MapperService; -import org.elasticsearch.index.mapper.ParsedDocument; -import org.elasticsearch.index.query.QueryShardContext; -import org.elasticsearch.search.SearchParseElement; -import org.elasticsearch.search.aggregations.AggregationPhase; -import org.elasticsearch.search.highlight.HighlightPhase; -import org.elasticsearch.search.sort.SortParseElement; - -import java.util.Map; - -import static org.elasticsearch.index.mapper.SourceToParse.source; - -public class PercolateDocumentParser { - - private final HighlightPhase highlightPhase; - private final SortParseElement sortParseElement; - private final AggregationPhase aggregationPhase; - - @Inject - public PercolateDocumentParser(HighlightPhase highlightPhase, SortParseElement sortParseElement, - AggregationPhase aggregationPhase) { - this.highlightPhase = highlightPhase; - this.sortParseElement = sortParseElement; - this.aggregationPhase = aggregationPhase; - } - - public ParsedDocument parse(final PercolateShardRequest request, final PercolateContext context, final MapperService mapperService) { - BytesReference source = request.source(); - if (source == null || source.length() == 0) { - if (request.docSource() != null && request.docSource().length() != 0) { - return parseFetchedDoc(context, request.docSource(), mapperService, request.shardId().getIndexName(), request.documentType()); - } else { - return null; - } - } - - // TODO: combine all feature parse elements into one map - Map hlElements = highlightPhase.parseElements(); - Map aggregationElements = aggregationPhase.parseElements(); - final QueryShardContext queryShardContext = context.getQueryShardContext(); - ParsedDocument doc = null; - // Some queries (function_score query when for decay functions) rely on a SearchContext being set: - // We switch types because this context needs to be in the context of the percolate queries in the shard and - // not the in memory percolate doc - final String[] previousTypes = queryShardContext.getTypes(); - queryShardContext.setTypes(PercolatorService.TYPE_NAME); - try (XContentParser parser = XContentFactory.xContent(source).createParser(source);) { - String currentFieldName = null; - XContentParser.Token token; - while ((token = parser.nextToken()) != XContentParser.Token.END_OBJECT) { - if (token == XContentParser.Token.FIELD_NAME) { - currentFieldName = parser.currentName(); - // we need to check the "doc" here, so the next token will be START_OBJECT which is - // the actual document starting - if ("doc".equals(currentFieldName)) { - if (doc != null) { - throw new ElasticsearchParseException("Either specify doc or get, not both"); - } - - DocumentMapperForType docMapper = mapperService.documentMapperWithAutoCreate(request.documentType()); - String index = context.shardTarget().index(); - doc = docMapper.getDocumentMapper().parse(source(parser).index(index).type(request.documentType()).id("_id_for_percolate_api")); - if (docMapper.getMapping() != null) { - doc.addDynamicMappingsUpdate(docMapper.getMapping()); - } - // the document parsing exists the "doc" object, so we need to set the new current field. - currentFieldName = parser.currentName(); - } - } else if (token == XContentParser.Token.START_OBJECT) { - SearchParseElement element = hlElements.get(currentFieldName); - if (element == null) { - element = aggregationElements.get(currentFieldName); - } - - if ("query".equals(currentFieldName)) { - if (context.percolateQuery() != null) { - throw new ElasticsearchParseException("Either specify query or filter, not both"); - } - context.percolateQuery(queryShardContext.parse(parser).query()); - } else if ("filter".equals(currentFieldName)) { - if (context.percolateQuery() != null) { - throw new ElasticsearchParseException("Either specify query or filter, not both"); - } - Query filter = queryShardContext.parseInnerFilter(parser).query(); - context.percolateQuery(new ConstantScoreQuery(filter)); - } else if ("sort".equals(currentFieldName)) { - parseSort(parser, context); - } else if (element != null) { - element.parse(parser, context); - } - } else if (token == XContentParser.Token.START_ARRAY) { - if ("sort".equals(currentFieldName)) { - parseSort(parser, context); - } - } else if (token == null) { - break; - } else if (token.isValue()) { - if ("size".equals(currentFieldName)) { - context.size(parser.intValue()); - if (context.size() < 0) { - throw new ElasticsearchParseException("size is set to [{}] and is expected to be higher or equal to 0", context.size()); - } - } else if ("sort".equals(currentFieldName)) { - parseSort(parser, context); - } else if ("track_scores".equals(currentFieldName) || "trackScores".equals(currentFieldName)) { - context.trackScores(parser.booleanValue()); - } - } - } - - // We need to get the actual source from the request body for highlighting, so parse the request body again - // and only get the doc source. - if (context.highlight() != null) { - parser.close(); - currentFieldName = null; - try (XContentParser parserForHighlighter = XContentFactory.xContent(source).createParser(source)) { - token = parserForHighlighter.nextToken(); - assert token == XContentParser.Token.START_OBJECT; - while ((token = parserForHighlighter.nextToken()) != XContentParser.Token.END_OBJECT) { - if (token == XContentParser.Token.FIELD_NAME) { - currentFieldName = parserForHighlighter.currentName(); - } else if (token == XContentParser.Token.START_OBJECT) { - if ("doc".equals(currentFieldName)) { - BytesStreamOutput bStream = new BytesStreamOutput(); - XContentBuilder builder = XContentFactory.contentBuilder(XContentType.SMILE, bStream); - builder.copyCurrentStructure(parserForHighlighter); - builder.close(); - doc.setSource(bStream.bytes()); - break; - } else { - parserForHighlighter.skipChildren(); - } - } else if (token == null) { - break; - } - } - } - } - - } catch (Throwable e) { - throw new ElasticsearchParseException("failed to parse request", e); - } finally { - queryShardContext.setTypes(previousTypes); - } - - if (request.docSource() != null && request.docSource().length() != 0) { - if (doc != null) { - throw new IllegalArgumentException("Can't specify the document to percolate in the source of the request and as document id"); - } - - doc = parseFetchedDoc(context, request.docSource(), mapperService, request.shardId().getIndexName(), request.documentType()); - } - - if (doc == null) { - throw new IllegalArgumentException("Nothing to percolate"); - } - - return doc; - } - - private void parseSort(XContentParser parser, PercolateContext context) throws Exception { - context.trackScores(true); - sortParseElement.parse(parser, context); - // null, means default sorting by relevancy - if (context.sort() != null) { - throw new ElasticsearchParseException("Only _score desc is supported"); - } - } - - private ParsedDocument parseFetchedDoc(PercolateContext context, BytesReference fetchedDoc, MapperService mapperService, String index, String type) { - DocumentMapperForType docMapper = mapperService.documentMapperWithAutoCreate(type); - ParsedDocument doc = docMapper.getDocumentMapper().parse(source(fetchedDoc).index(index).type(type).id("_id_for_percolate_api")); - if (doc == null) { - throw new ElasticsearchParseException("No doc to percolate in the request"); - } - if (context.highlight() != null) { - doc.setSource(fetchedDoc); - } - return doc; - } - -} diff --git a/core/src/main/java/org/elasticsearch/percolator/PercolateException.java b/core/src/main/java/org/elasticsearch/percolator/PercolateException.java deleted file mode 100644 index 81a708a75ec..00000000000 --- a/core/src/main/java/org/elasticsearch/percolator/PercolateException.java +++ /dev/null @@ -1,58 +0,0 @@ -/* - * Licensed to Elasticsearch under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch 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.elasticsearch.percolator; - -import org.elasticsearch.ElasticsearchException; -import org.elasticsearch.ElasticsearchWrapperException; -import org.elasticsearch.common.io.stream.StreamInput; -import org.elasticsearch.common.io.stream.StreamOutput; -import org.elasticsearch.index.shard.ShardId; - -import java.io.IOException; -import java.util.Objects; - -/** - * Exception during percolating document(s) at runtime. - */ -public class PercolateException extends ElasticsearchException implements ElasticsearchWrapperException { - - private final ShardId shardId; - - public PercolateException(ShardId shardId, String msg, Throwable cause) { - super(msg, cause); - Objects.requireNonNull(shardId, "shardId must not be null"); - this.shardId = shardId; - } - - public ShardId getShardId() { - return shardId; - } - - public PercolateException(StreamInput in) throws IOException{ - super(in); - shardId = ShardId.readShardId(in); - } - - @Override - public void writeTo(StreamOutput out) throws IOException { - super.writeTo(out); - shardId.writeTo(out); - } -} diff --git a/core/src/main/java/org/elasticsearch/percolator/PercolatorIndex.java b/core/src/main/java/org/elasticsearch/percolator/PercolatorIndex.java deleted file mode 100644 index 6f9a7104834..00000000000 --- a/core/src/main/java/org/elasticsearch/percolator/PercolatorIndex.java +++ /dev/null @@ -1,37 +0,0 @@ -/* - * Licensed to Elasticsearch under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch 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.elasticsearch.percolator; - -import org.elasticsearch.index.mapper.ParsedDocument; - -/** - * Abstraction on how to index the percolator document. - */ -interface PercolatorIndex { - - /** - * Indexes the document(s) and initializes the PercolateContext - * - * @param context Initialized with document related properties for fetch phase. - * @param document Document that is percolated. Can contain several documents. - * */ - void prepare(PercolateContext context, ParsedDocument document); - -} diff --git a/core/src/main/java/org/elasticsearch/percolator/PercolatorService.java b/core/src/main/java/org/elasticsearch/percolator/PercolatorService.java deleted file mode 100644 index 1160aec969b..00000000000 --- a/core/src/main/java/org/elasticsearch/percolator/PercolatorService.java +++ /dev/null @@ -1,376 +0,0 @@ -/* - * Licensed to Elasticsearch under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch 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.elasticsearch.percolator; - - -import org.apache.lucene.index.LeafReaderContext; -import org.apache.lucene.index.ReaderUtil; -import org.apache.lucene.index.memory.ExtendedMemoryIndex; -import org.apache.lucene.index.memory.MemoryIndex; -import org.apache.lucene.search.BooleanQuery; -import org.apache.lucene.search.MultiCollector; -import org.apache.lucene.search.Query; -import org.apache.lucene.search.ScoreDoc; -import org.apache.lucene.search.TopDocs; -import org.apache.lucene.search.TopScoreDocCollector; -import org.apache.lucene.search.TotalHitCountCollector; -import org.apache.lucene.util.BytesRef; -import org.apache.lucene.util.CloseableThreadLocal; -import org.elasticsearch.Version; -import org.elasticsearch.action.percolate.PercolateResponse; -import org.elasticsearch.action.percolate.PercolateShardRequest; -import org.elasticsearch.action.percolate.PercolateShardResponse; -import org.elasticsearch.cache.recycler.PageCacheRecycler; -import org.elasticsearch.cluster.ClusterService; -import org.elasticsearch.cluster.metadata.IndexMetaData; -import org.elasticsearch.cluster.metadata.IndexNameExpressionResolver; -import org.elasticsearch.common.Nullable; -import org.elasticsearch.common.ParseFieldMatcher; -import org.elasticsearch.common.component.AbstractComponent; -import org.elasticsearch.common.inject.Inject; -import org.elasticsearch.common.lease.Releasable; -import org.elasticsearch.common.lucene.Lucene; -import org.elasticsearch.common.settings.Settings; -import org.elasticsearch.common.text.Text; -import org.elasticsearch.common.unit.ByteSizeUnit; -import org.elasticsearch.common.unit.ByteSizeValue; -import org.elasticsearch.common.util.BigArrays; -import org.elasticsearch.index.IndexService; -import org.elasticsearch.index.fieldvisitor.SingleFieldsVisitor; -import org.elasticsearch.index.mapper.DocumentMapper; -import org.elasticsearch.index.mapper.ParsedDocument; -import org.elasticsearch.index.mapper.internal.UidFieldMapper; -import org.elasticsearch.index.percolator.PercolatorFieldMapper; -import org.elasticsearch.index.percolator.PercolatorQueriesRegistry; -import org.elasticsearch.index.query.ParsedQuery; -import org.elasticsearch.index.shard.IndexShard; -import org.elasticsearch.indices.IndicesService; -import org.elasticsearch.script.ScriptService; -import org.elasticsearch.search.SearchShardTarget; -import org.elasticsearch.search.aggregations.AggregationPhase; -import org.elasticsearch.search.aggregations.Aggregator; -import org.elasticsearch.search.aggregations.BucketCollector; -import org.elasticsearch.search.aggregations.InternalAggregation; -import org.elasticsearch.search.aggregations.InternalAggregations; -import org.elasticsearch.search.aggregations.bucket.global.GlobalAggregator; -import org.elasticsearch.search.aggregations.pipeline.SiblingPipelineAggregator; -import org.elasticsearch.search.aggregations.support.AggregationContext; -import org.elasticsearch.search.fetch.FetchPhase; -import org.elasticsearch.search.highlight.HighlightField; -import org.elasticsearch.search.highlight.HighlightPhase; -import org.elasticsearch.search.internal.SearchContext; - -import java.io.IOException; -import java.util.ArrayList; -import java.util.Collections; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.stream.Collectors; -import java.util.stream.StreamSupport; - -import static org.apache.lucene.search.BooleanClause.Occur.FILTER; -import static org.apache.lucene.search.BooleanClause.Occur.MUST; - -public class PercolatorService extends AbstractComponent implements Releasable { - - public final static float NO_SCORE = Float.NEGATIVE_INFINITY; - public final static String TYPE_NAME = ".percolator"; - - private final BigArrays bigArrays; - private final ScriptService scriptService; - private final IndicesService indicesService; - private final ClusterService clusterService; - private final HighlightPhase highlightPhase; - private final AggregationPhase aggregationPhase; - private final PageCacheRecycler pageCacheRecycler; - private final CloseableThreadLocal cache; - private final IndexNameExpressionResolver indexNameExpressionResolver; - private final PercolateDocumentParser percolateDocumentParser; - - private final PercolatorIndex single; - private final PercolatorIndex multi; - private final ParseFieldMatcher parseFieldMatcher; - private final FetchPhase fetchPhase; - - @Inject - public PercolatorService(Settings settings, IndexNameExpressionResolver indexNameExpressionResolver, IndicesService indicesService, - PageCacheRecycler pageCacheRecycler, BigArrays bigArrays, - HighlightPhase highlightPhase, ClusterService clusterService, - AggregationPhase aggregationPhase, ScriptService scriptService, - PercolateDocumentParser percolateDocumentParser, FetchPhase fetchPhase) { - super(settings); - this.indexNameExpressionResolver = indexNameExpressionResolver; - this.percolateDocumentParser = percolateDocumentParser; - this.fetchPhase = fetchPhase; - this.parseFieldMatcher = new ParseFieldMatcher(settings); - this.indicesService = indicesService; - this.pageCacheRecycler = pageCacheRecycler; - this.bigArrays = bigArrays; - this.clusterService = clusterService; - this.scriptService = scriptService; - this.aggregationPhase = aggregationPhase; - this.highlightPhase = highlightPhase; - - final long maxReuseBytes = settings.getAsBytesSize("indices.memory.memory_index.size_per_thread", new ByteSizeValue(1, ByteSizeUnit.MB)).bytes(); - cache = new CloseableThreadLocal() { - @Override - protected MemoryIndex initialValue() { - // TODO: should we expose payloads as an option? should offsets be turned on always? - return new ExtendedMemoryIndex(true, false, maxReuseBytes); - } - }; - single = new SingleDocumentPercolatorIndex(cache); - multi = new MultiDocumentPercolatorIndex(cache); - } - - public ReduceResult reduce(boolean onlyCount, List shardResponses) throws IOException { - if (onlyCount) { - long finalCount = 0; - for (PercolateShardResponse shardResponse : shardResponses) { - finalCount += shardResponse.topDocs().totalHits; - } - - InternalAggregations reducedAggregations = reduceAggregations(shardResponses); - return new PercolatorService.ReduceResult(finalCount, reducedAggregations); - } else { - int requestedSize = shardResponses.get(0).requestedSize(); - TopDocs[] shardResults = new TopDocs[shardResponses.size()]; - long foundMatches = 0; - for (int i = 0; i < shardResults.length; i++) { - TopDocs shardResult = shardResponses.get(i).topDocs(); - foundMatches += shardResult.totalHits; - shardResults[i] = shardResult; - } - TopDocs merged = TopDocs.merge(requestedSize, shardResults); - PercolateResponse.Match[] matches = new PercolateResponse.Match[merged.scoreDocs.length]; - for (int i = 0; i < merged.scoreDocs.length; i++) { - ScoreDoc doc = merged.scoreDocs[i]; - PercolateShardResponse shardResponse = shardResponses.get(doc.shardIndex); - String id = shardResponse.ids().get(doc.doc); - Map hl = shardResponse.hls().get(doc.doc); - matches[i] = new PercolateResponse.Match(new Text(shardResponse.getIndex()), new Text(id), doc.score, hl); - } - InternalAggregations reducedAggregations = reduceAggregations(shardResponses); - return new PercolatorService.ReduceResult(foundMatches, matches, reducedAggregations); - } - } - - public PercolateShardResponse percolate(PercolateShardRequest request) throws IOException { - final IndexService percolateIndexService = indicesService.indexServiceSafe(request.shardId().getIndex()); - final IndexShard indexShard = percolateIndexService.getShard(request.shardId().id()); - indexShard.readAllowed(); // check if we can read the shard... - PercolatorQueriesRegistry percolateQueryRegistry = indexShard.percolateRegistry(); - percolateQueryRegistry.prePercolate(); - long startTime = System.nanoTime(); - - // TODO: The filteringAliases should be looked up at the coordinating node and serialized with all shard request, - // just like is done in other apis. - String[] filteringAliases = indexNameExpressionResolver.filteringAliases( - clusterService.state(), - indexShard.shardId().getIndex().getName(), - request.indices() - ); - Query aliasFilter = percolateIndexService.aliasFilter(percolateIndexService.newQueryShardContext(), filteringAliases); - - SearchShardTarget searchShardTarget = new SearchShardTarget(clusterService.localNode().id(), request.shardId().getIndex(), - request.shardId().id()); - final PercolateContext context = new PercolateContext(request, searchShardTarget, indexShard, percolateIndexService, - pageCacheRecycler, bigArrays, scriptService, aliasFilter, parseFieldMatcher, fetchPhase); - SearchContext.setCurrent(context); - try { - ParsedDocument parsedDocument = percolateDocumentParser.parse(request, context, percolateIndexService.mapperService()); - if (context.searcher().getIndexReader().maxDoc() == 0) { - return new PercolateShardResponse(Lucene.EMPTY_TOP_DOCS, Collections.emptyMap(), Collections.emptyMap(), context); - } - if (context.size() < 0) { - context.size(0); - } - - // parse the source either into one MemoryIndex, if it is a single document or index multiple docs if nested - PercolatorIndex percolatorIndex; - DocumentMapper documentMapper = indexShard.mapperService().documentMapper(request.documentType()); - boolean isNested = documentMapper != null && documentMapper.hasNestedObjects(); - if (parsedDocument.docs().size() > 1) { - assert isNested; - percolatorIndex = multi; - } else { - percolatorIndex = single; - } - percolatorIndex.prepare(context, parsedDocument); - - BucketCollector aggregatorCollector = null; - if (context.aggregations() != null) { - AggregationContext aggregationContext = new AggregationContext(context); - context.aggregations().aggregationContext(aggregationContext); - Aggregator[] aggregators = context.aggregations().factories().createTopLevelAggregators(); - List aggregatorCollectors = new ArrayList<>(aggregators.length); - for (int i = 0; i < aggregators.length; i++) { - if (!(aggregators[i] instanceof GlobalAggregator)) { - Aggregator aggregator = aggregators[i]; - aggregatorCollectors.add(aggregator); - } - } - context.aggregations().aggregators(aggregators); - aggregatorCollector = BucketCollector.wrap(aggregatorCollectors); - aggregatorCollector.preCollection(); - } - PercolatorQueriesRegistry queriesRegistry = indexShard.percolateRegistry(); - return doPercolate(context, queriesRegistry, aggregationPhase, aggregatorCollector, highlightPhase); - } finally { - SearchContext.removeCurrent(); - context.close(); - percolateQueryRegistry.postPercolate(System.nanoTime() - startTime); - } - } - - // moved the core percolation logic to a pck protected method to make testing easier: - static PercolateShardResponse doPercolate(PercolateContext context, PercolatorQueriesRegistry queriesRegistry, AggregationPhase aggregationPhase, @Nullable BucketCollector aggregatorCollector, HighlightPhase highlightPhase) throws IOException { - PercolatorQuery.Builder builder = new PercolatorQuery.Builder(context.docSearcher(), queriesRegistry.getPercolateQueries(), context.percolatorTypeFilter()); - if (queriesRegistry.indexSettings().getSettings().getAsVersion(IndexMetaData.SETTING_VERSION_CREATED, null).onOrAfter(Version.V_5_0_0)) { - builder.extractQueryTermsQuery(PercolatorFieldMapper.EXTRACTED_TERMS_FULL_FIELD_NAME, PercolatorFieldMapper.UNKNOWN_QUERY_FULL_FIELD_NAME); - } - if (context.percolateQuery() != null || context.aliasFilter() != null) { - BooleanQuery.Builder bq = new BooleanQuery.Builder(); - if (context.percolateQuery() != null) { - bq.add(context.percolateQuery(), MUST); - } - if (context.aliasFilter() != null) { - bq.add(context.aliasFilter(), FILTER); - } - builder.setPercolateQuery(bq.build()); - } - PercolatorQuery percolatorQuery = builder.build(); - - if (context.isOnlyCount() || context.size() == 0) { - TotalHitCountCollector collector = new TotalHitCountCollector(); - context.searcher().search(percolatorQuery, MultiCollector.wrap(collector, aggregatorCollector)); - if (aggregatorCollector != null) { - aggregatorCollector.postCollection(); - aggregationPhase.execute(context); - } - return new PercolateShardResponse(new TopDocs(collector.getTotalHits(), Lucene.EMPTY_SCORE_DOCS, 0f), Collections.emptyMap(), Collections.emptyMap(), context); - } else { - int size = context.size(); - if (size > context.searcher().getIndexReader().maxDoc()) { - // prevent easy OOM if more than the total number of docs that - // exist is requested... - size = context.searcher().getIndexReader().maxDoc(); - } - TopScoreDocCollector collector = TopScoreDocCollector.create(size); - context.searcher().search(percolatorQuery, MultiCollector.wrap(collector, aggregatorCollector)); - if (aggregatorCollector != null) { - aggregatorCollector.postCollection(); - aggregationPhase.execute(context); - } - - TopDocs topDocs = collector.topDocs(); - Map ids = new HashMap<>(topDocs.scoreDocs.length); - Map> hls = new HashMap<>(topDocs.scoreDocs.length); - for (ScoreDoc scoreDoc : topDocs.scoreDocs) { - if (context.trackScores() == false) { - // No sort or tracking scores was provided, so use special - // value to indicate to not show the scores: - scoreDoc.score = NO_SCORE; - } - - int segmentIdx = ReaderUtil.subIndex(scoreDoc.doc, context.searcher().getIndexReader().leaves()); - LeafReaderContext atomicReaderContext = context.searcher().getIndexReader().leaves().get(segmentIdx); - final int segmentDocId = scoreDoc.doc - atomicReaderContext.docBase; - SingleFieldsVisitor fieldsVisitor = new SingleFieldsVisitor(UidFieldMapper.NAME); - atomicReaderContext.reader().document(segmentDocId, fieldsVisitor); - String id = fieldsVisitor.uid().id(); - ids.put(scoreDoc.doc, id); - if (context.highlight() != null) { - Query query = queriesRegistry.getPercolateQueries().get(new BytesRef(id)); - context.parsedQuery(new ParsedQuery(query)); - context.hitContext().cache().clear(); - highlightPhase.hitExecute(context, context.hitContext()); - hls.put(scoreDoc.doc, context.hitContext().hit().getHighlightFields()); - } - } - return new PercolateShardResponse(topDocs, ids, hls, context); - } - } - - @Override - public void close() { - cache.close(); - } - - private InternalAggregations reduceAggregations(List shardResults) { - if (shardResults.get(0).aggregations() == null) { - return null; - } - - List aggregationsList = new ArrayList<>(shardResults.size()); - for (PercolateShardResponse shardResult : shardResults) { - aggregationsList.add(shardResult.aggregations()); - } - InternalAggregations aggregations = InternalAggregations.reduce(aggregationsList, new InternalAggregation.ReduceContext(bigArrays, scriptService)); - if (aggregations != null) { - List pipelineAggregators = shardResults.get(0).pipelineAggregators(); - if (pipelineAggregators != null) { - List newAggs = StreamSupport.stream(aggregations.spliterator(), false).map((p) -> { - return (InternalAggregation) p; - }).collect(Collectors.toList()); - for (SiblingPipelineAggregator pipelineAggregator : pipelineAggregators) { - InternalAggregation newAgg = pipelineAggregator.doReduce(new InternalAggregations(newAggs), - new InternalAggregation.ReduceContext(bigArrays, scriptService)); - newAggs.add(newAgg); - } - aggregations = new InternalAggregations(newAggs); - } - } - return aggregations; - } - - public final static class ReduceResult { - - private final long count; - private final PercolateResponse.Match[] matches; - private final InternalAggregations reducedAggregations; - - ReduceResult(long count, PercolateResponse.Match[] matches, InternalAggregations reducedAggregations) { - this.count = count; - this.matches = matches; - this.reducedAggregations = reducedAggregations; - } - - public ReduceResult(long count, InternalAggregations reducedAggregations) { - this.count = count; - this.matches = null; - this.reducedAggregations = reducedAggregations; - } - - public long count() { - return count; - } - - public PercolateResponse.Match[] matches() { - return matches; - } - - public InternalAggregations reducedAggregations() { - return reducedAggregations; - } - } - - -} diff --git a/core/src/main/java/org/elasticsearch/percolator/SingleDocumentPercolatorIndex.java b/core/src/main/java/org/elasticsearch/percolator/SingleDocumentPercolatorIndex.java deleted file mode 100644 index 1d5268e3794..00000000000 --- a/core/src/main/java/org/elasticsearch/percolator/SingleDocumentPercolatorIndex.java +++ /dev/null @@ -1,95 +0,0 @@ -/* - * Licensed to Elasticsearch under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch 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.elasticsearch.percolator; - -import org.apache.lucene.analysis.Analyzer; -import org.apache.lucene.analysis.TokenStream; -import org.apache.lucene.index.IndexOptions; -import org.apache.lucene.index.IndexableField; -import org.apache.lucene.index.memory.MemoryIndex; -import org.apache.lucene.util.CloseableThreadLocal; -import org.elasticsearch.ElasticsearchException; -import org.elasticsearch.index.engine.Engine; -import org.elasticsearch.index.mapper.DocumentMapper; -import org.elasticsearch.index.mapper.ParsedDocument; -import org.elasticsearch.index.mapper.internal.UidFieldMapper; - -import java.io.IOException; - -/** - * Implementation of {@link PercolatorIndex} that can only hold a single Lucene document - * and is optimized for that - */ -class SingleDocumentPercolatorIndex implements PercolatorIndex { - - private final CloseableThreadLocal cache; - - SingleDocumentPercolatorIndex(CloseableThreadLocal cache) { - this.cache = cache; - } - - @Override - public void prepare(PercolateContext context, ParsedDocument parsedDocument) { - MemoryIndex memoryIndex = cache.get(); - for (IndexableField field : parsedDocument.rootDoc().getFields()) { - Analyzer analyzer = context.analysisService().defaultIndexAnalyzer(); - DocumentMapper documentMapper = context.mapperService().documentMapper(parsedDocument.type()); - if (documentMapper != null && documentMapper.mappers().getMapper(field.name()) != null) { - analyzer = documentMapper.mappers().indexAnalyzer(); - } - if (field.fieldType().indexOptions() == IndexOptions.NONE && field.name().equals(UidFieldMapper.NAME)) { - continue; - } - try { - // TODO: instead of passing null here, we can have a CTL> and pass previous, - // like the indexer does - try (TokenStream tokenStream = field.tokenStream(analyzer, null)) { - if (tokenStream != null) { - memoryIndex.addField(field.name(), tokenStream, field.boost()); - } - } - } catch (Exception e) { - throw new ElasticsearchException("Failed to create token stream for [" + field.name() + "]", e); - } - } - context.initialize(new DocEngineSearcher(memoryIndex), parsedDocument); - } - - private class DocEngineSearcher extends Engine.Searcher { - - private final MemoryIndex memoryIndex; - - public DocEngineSearcher(MemoryIndex memoryIndex) { - super("percolate", memoryIndex.createSearcher()); - this.memoryIndex = memoryIndex; - } - - @Override - public void close() { - try { - this.reader().close(); - memoryIndex.reset(); - } catch (IOException e) { - throw new ElasticsearchException("failed to close percolator in-memory index", e); - } - } - } -} diff --git a/core/src/main/java/org/elasticsearch/plugins/InstallPluginCommand.java b/core/src/main/java/org/elasticsearch/plugins/InstallPluginCommand.java index e72eb2100f6..a260876db49 100644 --- a/core/src/main/java/org/elasticsearch/plugins/InstallPluginCommand.java +++ b/core/src/main/java/org/elasticsearch/plugins/InstallPluginCommand.java @@ -21,6 +21,7 @@ package org.elasticsearch.plugins; import joptsimple.OptionSet; import joptsimple.OptionSpec; +import org.apache.lucene.util.Constants; import org.apache.lucene.util.IOUtils; import org.elasticsearch.Build; import org.elasticsearch.Version; @@ -46,7 +47,9 @@ import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.StandardCopyOption; import java.nio.file.attribute.PosixFileAttributeView; +import java.nio.file.attribute.PosixFileAttributes; import java.nio.file.attribute.PosixFilePermission; +import java.nio.file.attribute.PosixFilePermissions; import java.util.ArrayList; import java.util.Arrays; import java.util.HashSet; @@ -66,9 +69,9 @@ import static org.elasticsearch.common.util.set.Sets.newHashSet; * * The install command takes a plugin id, which may be any of the following: *
      - *
    • An official elasticsearch plugin name
    • - *
    • Maven coordinates to a plugin zip
    • - *
    • A URL to a plugin zip
    • + *
    • An official elasticsearch plugin name
    • + *
    • Maven coordinates to a plugin zip
    • + *
    • A URL to a plugin zip
    • *
    * * Plugins are packaged as zip files. Each packaged plugin must contain a @@ -77,9 +80,9 @@ import static org.elasticsearch.common.util.set.Sets.newHashSet; * The installation process first extracts the plugin files into a temporary * directory in order to verify the plugin satisfies the following requirements: *
      - *
    • Jar hell does not exist, either between the plugin's own jars, or with elasticsearch
    • - *
    • The plugin is not a module already provided with elasticsearch
    • - *
    • If the plugin contains extra security permissions, the policy file is validated
    • + *
    • Jar hell does not exist, either between the plugin's own jars, or with elasticsearch
    • + *
    • The plugin is not a module already provided with elasticsearch
    • + *
    • If the plugin contains extra security permissions, the policy file is validated
    • *
    *

    * A plugin may also contain an optional {@code bin} directory which contains scripts. The @@ -97,30 +100,35 @@ class InstallPluginCommand extends Command { // TODO: make this a resource file generated by gradle static final Set MODULES = unmodifiableSet(newHashSet( - "lang-expression", - "lang-groovy")); + "ingest-grok", + "lang-expression", + "lang-groovy", + "lang-painless", + "reindex")); // TODO: make this a resource file generated by gradle static final Set OFFICIAL_PLUGINS = unmodifiableSet(new LinkedHashSet<>(Arrays.asList( - "analysis-icu", - "analysis-kuromoji", - "analysis-phonetic", - "analysis-smartcn", - "analysis-stempel", - "delete-by-query", - "discovery-azure", - "discovery-ec2", - "discovery-gce", - "lang-javascript", - "lang-painless", - "lang-python", - "mapper-attachments", - "mapper-murmur3", - "mapper-size", - "repository-azure", - "repository-hdfs", - "repository-s3", - "store-smb"))); + "analysis-icu", + "analysis-kuromoji", + "analysis-phonetic", + "analysis-smartcn", + "analysis-stempel", + "delete-by-query", + "discovery-azure", + "discovery-ec2", + "discovery-gce", + "ingest-attachment", + "ingest-geoip", + "lang-javascript", + "lang-python", + "mapper-attachments", + "mapper-murmur3", + "mapper-size", + "repository-azure", + "repository-hdfs", + "repository-s3", + "store-smb", + "xpack"))); private final Environment env; private final OptionSpec batchOption; @@ -130,7 +138,7 @@ class InstallPluginCommand extends Command { super("Install a plugin"); this.env = env; this.batchOption = parser.acceptsAll(Arrays.asList("b", "batch"), - "Enable batch mode explicitly, automatic confirmation of security permission"); + "Enable batch mode explicitly, automatic confirmation of security permission"); this.arguments = parser.nonOptions("plugin id"); } @@ -176,10 +184,10 @@ class InstallPluginCommand extends Command { final String url; if (System.getProperty(PROPERTY_SUPPORT_STAGING_URLS, "false").equals("true")) { url = String.format(Locale.ROOT, "https://download.elastic.co/elasticsearch/staging/%1$s-%2$s/org/elasticsearch/plugin/%3$s/%1$s/%3$s-%1$s.zip", - version, Build.CURRENT.shortHash(), pluginId); + version, Build.CURRENT.shortHash(), pluginId); } else { url = String.format(Locale.ROOT, "https://download.elastic.co/elasticsearch/release/org/elasticsearch/plugin/%1$s/%2$s/%1$s-%2$s.zip", - pluginId, version); + pluginId, version); } terminal.println("-> Downloading " + pluginId + " from elastic"); return downloadZipAndChecksum(url, tmpDir); @@ -189,7 +197,7 @@ class InstallPluginCommand extends Command { String[] coordinates = pluginId.split(":"); if (coordinates.length == 3 && pluginId.contains("/") == false) { String mavenUrl = String.format(Locale.ROOT, "https://repo1.maven.org/maven2/%1$s/%2$s/%3$s/%2$s-%3$s.zip", - coordinates[0].replace(".", "/") /* groupId */, coordinates[1] /* artifactId */, coordinates[2] /* version */); + coordinates[0].replace(".", "/") /* groupId */, coordinates[1] /* artifactId */, coordinates[2] /* version */); terminal.println("-> Downloading " + pluginId + " from maven central"); return downloadZipAndChecksum(mavenUrl, tmpDir); } @@ -235,7 +243,20 @@ class InstallPluginCommand extends Command { private Path unzip(Path zip, Path pluginsDir) throws IOException, UserError { // unzip plugin to a staging temp dir - Path target = Files.createTempDirectory(pluginsDir, ".installing-"); + final Path target; + if (Constants.WINDOWS) { + target = Files.createTempDirectory(pluginsDir, ".installing-"); + } else { + Set perms = new HashSet<>(); + perms.add(PosixFilePermission.OWNER_EXECUTE); + perms.add(PosixFilePermission.OWNER_READ); + perms.add(PosixFilePermission.OWNER_WRITE); + perms.add(PosixFilePermission.GROUP_READ); + perms.add(PosixFilePermission.GROUP_EXECUTE); + perms.add(PosixFilePermission.OTHERS_READ); + perms.add(PosixFilePermission.OTHERS_EXECUTE); + target = Files.createTempDirectory(pluginsDir, ".installing-", PosixFilePermissions.asFileAttribute(perms)); + } Files.createDirectories(target); boolean hasEsDir = false; @@ -265,7 +286,7 @@ class InstallPluginCommand extends Command { if (entry.isDirectory() == false) { try (OutputStream out = Files.newOutputStream(targetFile)) { int len; - while((len = zipInput.read(buffer)) >= 0) { + while ((len = zipInput.read(buffer)) >= 0) { out.write(buffer, 0, len); } } @@ -383,18 +404,20 @@ class InstallPluginCommand extends Command { } Files.createDirectory(destBinDir); - // setup file attributes for the installed files to those of the parent dir Set perms = new HashSet<>(); - PosixFileAttributeView binAttrs = Files.getFileAttributeView(destBinDir.getParent(), PosixFileAttributeView.class); - if (binAttrs != null) { - perms = new HashSet<>(binAttrs.readAttributes().permissions()); - // setting execute bits, since this just means "the file is executable", and actual execution requires read - perms.add(PosixFilePermission.OWNER_EXECUTE); - perms.add(PosixFilePermission.GROUP_EXECUTE); - perms.add(PosixFilePermission.OTHERS_EXECUTE); + if (Constants.WINDOWS == false) { + // setup file attributes for the installed files to those of the parent dir + PosixFileAttributeView binAttrs = Files.getFileAttributeView(destBinDir.getParent(), PosixFileAttributeView.class); + if (binAttrs != null) { + perms = new HashSet<>(binAttrs.readAttributes().permissions()); + // setting execute bits, since this just means "the file is executable", and actual execution requires read + perms.add(PosixFilePermission.OWNER_EXECUTE); + perms.add(PosixFilePermission.GROUP_EXECUTE); + perms.add(PosixFilePermission.OTHERS_EXECUTE); + } } - try (DirectoryStream stream = Files.newDirectoryStream(tmpBinDir)) { + try (DirectoryStream stream = Files.newDirectoryStream(tmpBinDir)) { for (Path srcFile : stream) { if (Files.isDirectory(srcFile)) { throw new UserError(ExitCodes.DATA_ERROR, "Directories not allowed in bin dir for plugin " + info.getName() + ", found " + srcFile.getFileName()); @@ -424,7 +447,17 @@ class InstallPluginCommand extends Command { // create the plugin's config dir "if necessary" Files.createDirectories(destConfigDir); - try (DirectoryStream stream = Files.newDirectoryStream(tmpConfigDir)) { + final PosixFileAttributes destConfigDirAttributes; + if (Constants.WINDOWS) { + destConfigDirAttributes = null; + } else { + destConfigDirAttributes = + Files.getFileAttributeView(destConfigDir.getParent(), PosixFileAttributeView.class).readAttributes(); + setOwnerGroup(destConfigDir, destConfigDirAttributes); + + } + + try (DirectoryStream stream = Files.newDirectoryStream(tmpConfigDir)) { for (Path srcFile : stream) { if (Files.isDirectory(srcFile)) { throw new UserError(ExitCodes.DATA_ERROR, "Directories not allowed in config dir for plugin " + info.getName()); @@ -433,9 +466,19 @@ class InstallPluginCommand extends Command { Path destFile = destConfigDir.resolve(tmpConfigDir.relativize(srcFile)); if (Files.exists(destFile) == false) { Files.copy(srcFile, destFile); + if (Constants.WINDOWS == false) { + setOwnerGroup(destFile, destConfigDirAttributes); + } } } } IOUtils.rm(tmpConfigDir); // clean up what we just copied } + + private static void setOwnerGroup(Path path, PosixFileAttributes attributes) throws IOException { + PosixFileAttributeView fileAttributeView = Files.getFileAttributeView(path, PosixFileAttributeView.class); + fileAttributeView.setOwner(attributes.owner()); + fileAttributeView.setGroup(attributes.group()); + } + } diff --git a/core/src/main/java/org/elasticsearch/plugins/PluginCli.java b/core/src/main/java/org/elasticsearch/plugins/PluginCli.java index 323b872044e..be06ea7db1c 100644 --- a/core/src/main/java/org/elasticsearch/plugins/PluginCli.java +++ b/core/src/main/java/org/elasticsearch/plugins/PluginCli.java @@ -19,10 +19,9 @@ package org.elasticsearch.plugins; -import org.apache.log4j.BasicConfigurator; -import org.apache.log4j.varia.NullAppender; import org.elasticsearch.cli.MultiCommand; import org.elasticsearch.cli.Terminal; +import org.elasticsearch.common.logging.LogConfigurator; import org.elasticsearch.common.settings.Settings; import org.elasticsearch.env.Environment; import org.elasticsearch.node.internal.InternalSettingsPreparer; @@ -40,7 +39,20 @@ public class PluginCli extends MultiCommand { } public static void main(String[] args) throws Exception { - BasicConfigurator.configure(new NullAppender()); + // initialize default for es.logger.level because we will not read the logging.yml + String loggerLevel = System.getProperty("es.logger.level", "INFO"); + // Set the appender for all potential log files to terminal so that other components that use the logger print out the + // same terminal. + // The reason for this is that the plugin cli cannot be configured with a file appender because when the plugin command is + // executed there is no way of knowing where the logfiles should be placed. For example, if elasticsearch + // is run as service then the logs should be at /var/log/elasticsearch but when started from the tar they should be at es.home/logs. + // Therefore we print to Terminal. + Environment loggingEnvironment = InternalSettingsPreparer.prepareEnvironment(Settings.builder() + .put("appender.terminal.type", "terminal") + .put("rootLogger", "${es.logger.level}, terminal") + .put("es.logger.level", loggerLevel) + .build(), Terminal.DEFAULT); + LogConfigurator.configure(loggingEnvironment.settings(), false); Environment env = InternalSettingsPreparer.prepareEnvironment(Settings.EMPTY, Terminal.DEFAULT); exit(new PluginCli(env).main(args, Terminal.DEFAULT)); } diff --git a/core/src/main/java/org/elasticsearch/repositories/RepositoriesService.java b/core/src/main/java/org/elasticsearch/repositories/RepositoriesService.java index 6eb32cfb06f..da2d9688095 100644 --- a/core/src/main/java/org/elasticsearch/repositories/RepositoriesService.java +++ b/core/src/main/java/org/elasticsearch/repositories/RepositoriesService.java @@ -22,7 +22,6 @@ package org.elasticsearch.repositories; import org.elasticsearch.action.ActionListener; import org.elasticsearch.cluster.AckedClusterStateUpdateTask; import org.elasticsearch.cluster.ClusterChangedEvent; -import org.elasticsearch.cluster.ClusterService; import org.elasticsearch.cluster.ClusterState; import org.elasticsearch.cluster.ClusterStateListener; import org.elasticsearch.cluster.ack.ClusterStateUpdateRequest; @@ -31,6 +30,7 @@ import org.elasticsearch.cluster.metadata.MetaData; import org.elasticsearch.cluster.metadata.RepositoriesMetaData; import org.elasticsearch.cluster.metadata.RepositoryMetaData; import org.elasticsearch.cluster.node.DiscoveryNode; +import org.elasticsearch.cluster.service.ClusterService; import org.elasticsearch.common.component.AbstractComponent; import org.elasticsearch.common.inject.Inject; import org.elasticsearch.common.inject.Injector; diff --git a/core/src/main/java/org/elasticsearch/repositories/VerifyNodeRepositoryAction.java b/core/src/main/java/org/elasticsearch/repositories/VerifyNodeRepositoryAction.java index 91600488332..48ffbd5c1cb 100644 --- a/core/src/main/java/org/elasticsearch/repositories/VerifyNodeRepositoryAction.java +++ b/core/src/main/java/org/elasticsearch/repositories/VerifyNodeRepositoryAction.java @@ -22,9 +22,9 @@ package org.elasticsearch.repositories; import com.carrotsearch.hppc.ObjectContainer; import com.carrotsearch.hppc.cursors.ObjectCursor; import org.elasticsearch.action.ActionListener; -import org.elasticsearch.cluster.ClusterService; import org.elasticsearch.cluster.node.DiscoveryNode; import org.elasticsearch.cluster.node.DiscoveryNodes; +import org.elasticsearch.cluster.service.ClusterService; import org.elasticsearch.common.component.AbstractComponent; import org.elasticsearch.common.io.stream.StreamInput; import org.elasticsearch.common.io.stream.StreamOutput; diff --git a/core/src/main/java/org/elasticsearch/repositories/uri/URLIndexShardRepository.java b/core/src/main/java/org/elasticsearch/repositories/uri/URLIndexShardRepository.java index ab9ec72463a..616a36d5066 100644 --- a/core/src/main/java/org/elasticsearch/repositories/uri/URLIndexShardRepository.java +++ b/core/src/main/java/org/elasticsearch/repositories/uri/URLIndexShardRepository.java @@ -19,7 +19,7 @@ package org.elasticsearch.repositories.uri; -import org.elasticsearch.cluster.ClusterService; +import org.elasticsearch.cluster.service.ClusterService; import org.elasticsearch.common.inject.Inject; import org.elasticsearch.common.settings.Settings; import org.elasticsearch.index.snapshots.blobstore.BlobStoreIndexShardRepository; diff --git a/core/src/main/java/org/elasticsearch/rest/action/admin/indices/settings/RestUpdateSettingsAction.java b/core/src/main/java/org/elasticsearch/rest/action/admin/indices/settings/RestUpdateSettingsAction.java index bcf43a4baa6..4477ff25011 100644 --- a/core/src/main/java/org/elasticsearch/rest/action/admin/indices/settings/RestUpdateSettingsAction.java +++ b/core/src/main/java/org/elasticsearch/rest/action/admin/indices/settings/RestUpdateSettingsAction.java @@ -47,6 +47,7 @@ public class RestUpdateSettingsAction extends BaseRestHandler { "timeout", "master_timeout", "index", + "preserve_existing", "expand_wildcards", "ignore_unavailable", "allow_no_indices")); @@ -62,6 +63,7 @@ public class RestUpdateSettingsAction extends BaseRestHandler { public void handleRequest(final RestRequest request, final RestChannel channel, final Client client) { UpdateSettingsRequest updateSettingsRequest = updateSettingsRequest(Strings.splitStringByCommaToArray(request.param("index"))); updateSettingsRequest.timeout(request.paramAsTime("timeout", updateSettingsRequest.timeout())); + updateSettingsRequest.setPreserveExisting(request.paramAsBoolean("preserve_existing", updateSettingsRequest.isPreserveExisting())); updateSettingsRequest.masterNodeTimeout(request.paramAsTime("master_timeout", updateSettingsRequest.masterNodeTimeout())); updateSettingsRequest.indicesOptions(IndicesOptions.fromRequest(request, updateSettingsRequest.indicesOptions())); diff --git a/core/src/main/java/org/elasticsearch/rest/action/admin/indices/stats/RestIndicesStatsAction.java b/core/src/main/java/org/elasticsearch/rest/action/admin/indices/stats/RestIndicesStatsAction.java index fa4371846f6..92fb21db38c 100644 --- a/core/src/main/java/org/elasticsearch/rest/action/admin/indices/stats/RestIndicesStatsAction.java +++ b/core/src/main/java/org/elasticsearch/rest/action/admin/indices/stats/RestIndicesStatsAction.java @@ -78,7 +78,7 @@ public class RestIndicesStatsAction extends BaseRestHandler { indicesStatsRequest.flush(metrics.contains("flush")); indicesStatsRequest.warmer(metrics.contains("warmer")); indicesStatsRequest.queryCache(metrics.contains("query_cache")); - indicesStatsRequest.percolate(metrics.contains("percolate")); + indicesStatsRequest.percolate(metrics.contains("percolator_cache")); indicesStatsRequest.segments(metrics.contains("segments")); indicesStatsRequest.fieldData(metrics.contains("fielddata")); indicesStatsRequest.completion(metrics.contains("completion")); diff --git a/core/src/main/java/org/elasticsearch/rest/action/cat/RestIndicesAction.java b/core/src/main/java/org/elasticsearch/rest/action/cat/RestIndicesAction.java index 0e2e26164a8..77366e1cc81 100644 --- a/core/src/main/java/org/elasticsearch/rest/action/cat/RestIndicesAction.java +++ b/core/src/main/java/org/elasticsearch/rest/action/cat/RestIndicesAction.java @@ -222,21 +222,9 @@ public class RestIndicesAction extends AbstractCatAction { table.addCell("merges.total_time", "sibling:pri;alias:mtt,mergesTotalTime;default:false;text-align:right;desc:time spent in merges"); table.addCell("pri.merges.total_time", "default:false;text-align:right;desc:time spent in merges"); - table.addCell("percolate.current", "sibling:pri;alias:pc,percolateCurrent;default:false;text-align:right;desc:number of current percolations"); - table.addCell("pri.percolate.current", "default:false;text-align:right;desc:number of current percolations"); - - table.addCell("percolate.memory_size", "sibling:pri;alias:pm,percolateMemory;default:false;text-align:right;desc:memory used by percolations"); - table.addCell("pri.percolate.memory_size", "default:false;text-align:right;desc:memory used by percolations"); - table.addCell("percolate.queries", "sibling:pri;alias:pq,percolateQueries;default:false;text-align:right;desc:number of registered percolation queries"); table.addCell("pri.percolate.queries", "default:false;text-align:right;desc:number of registered percolation queries"); - table.addCell("percolate.time", "sibling:pri;alias:pti,percolateTime;default:false;text-align:right;desc:time spent percolating"); - table.addCell("pri.percolate.time", "default:false;text-align:right;desc:time spent percolating"); - - table.addCell("percolate.total", "sibling:pri;alias:pto,percolateTotal;default:false;text-align:right;desc:total percolations"); - table.addCell("pri.percolate.total", "default:false;text-align:right;desc:total percolations"); - table.addCell("refresh.total", "sibling:pri;alias:rto,refreshTotal;default:false;text-align:right;desc:total refreshes"); table.addCell("pri.refresh.total", "default:false;text-align:right;desc:total refreshes"); @@ -436,20 +424,8 @@ public class RestIndicesAction extends AbstractCatAction { table.addCell(indexStats == null ? null : indexStats.getTotal().getMerge().getTotalTime()); table.addCell(indexStats == null ? null : indexStats.getPrimaries().getMerge().getTotalTime()); - table.addCell(indexStats == null ? null : indexStats.getTotal().getPercolate().getCurrent()); - table.addCell(indexStats == null ? null : indexStats.getPrimaries().getPercolate().getCurrent()); - - table.addCell(indexStats == null ? null : indexStats.getTotal().getPercolate().getMemorySize()); - table.addCell(indexStats == null ? null : indexStats.getPrimaries().getPercolate().getMemorySize()); - - table.addCell(indexStats == null ? null : indexStats.getTotal().getPercolate().getNumQueries()); - table.addCell(indexStats == null ? null : indexStats.getPrimaries().getPercolate().getNumQueries()); - - table.addCell(indexStats == null ? null : indexStats.getTotal().getPercolate().getTime()); - table.addCell(indexStats == null ? null : indexStats.getPrimaries().getPercolate().getTime()); - - table.addCell(indexStats == null ? null : indexStats.getTotal().getPercolate().getCount()); - table.addCell(indexStats == null ? null : indexStats.getPrimaries().getPercolate().getCount()); + table.addCell(indexStats == null ? null : indexStats.getTotal().getPercolatorCache().getNumQueries()); + table.addCell(indexStats == null ? null : indexStats.getPrimaries().getPercolatorCache().getNumQueries()); table.addCell(indexStats == null ? null : indexStats.getTotal().getRefresh().getTotal()); table.addCell(indexStats == null ? null : indexStats.getPrimaries().getRefresh().getTotal()); diff --git a/core/src/main/java/org/elasticsearch/rest/action/cat/RestNodesAction.java b/core/src/main/java/org/elasticsearch/rest/action/cat/RestNodesAction.java index 0605bc4dcab..4b97f8a942b 100644 --- a/core/src/main/java/org/elasticsearch/rest/action/cat/RestNodesAction.java +++ b/core/src/main/java/org/elasticsearch/rest/action/cat/RestNodesAction.java @@ -46,7 +46,7 @@ import org.elasticsearch.index.flush.FlushStats; import org.elasticsearch.index.get.GetStats; import org.elasticsearch.index.shard.IndexingStats; import org.elasticsearch.index.merge.MergeStats; -import org.elasticsearch.index.percolator.PercolateStats; +import org.elasticsearch.index.percolator.PercolatorQueryCacheStats; import org.elasticsearch.index.refresh.RefreshStats; import org.elasticsearch.index.search.stats.SearchStats; import org.elasticsearch.index.suggest.stats.SuggestStats; @@ -67,7 +67,6 @@ import org.elasticsearch.script.ScriptStats; import org.elasticsearch.search.suggest.completion.CompletionStats; import java.util.Locale; -import java.util.Map; import static org.elasticsearch.rest.RestRequest.Method.GET; @@ -186,11 +185,7 @@ public class RestNodesAction extends AbstractCatAction { table.addCell("merges.total_size", "alias:mts,mergesTotalSize;default:false;text-align:right;desc:size merged"); table.addCell("merges.total_time", "alias:mtt,mergesTotalTime;default:false;text-align:right;desc:time spent in merges"); - table.addCell("percolate.current", "alias:pc,percolateCurrent;default:false;text-align:right;desc:number of current percolations"); - table.addCell("percolate.memory_size", "alias:pm,percolateMemory;default:false;text-align:right;desc:memory used by percolations"); table.addCell("percolate.queries", "alias:pq,percolateQueries;default:false;text-align:right;desc:number of registered percolation queries"); - table.addCell("percolate.time", "alias:pti,percolateTime;default:false;text-align:right;desc:time spent percolating"); - table.addCell("percolate.total", "alias:pto,percolateTotal;default:false;text-align:right;desc:total percolations"); table.addCell("refresh.total", "alias:rto,refreshTotal;default:false;text-align:right;desc:total refreshes"); table.addCell("refresh.time", "alias:rti,refreshTime;default:false;text-align:right;desc:time spent in refreshes"); @@ -336,12 +331,8 @@ public class RestNodesAction extends AbstractCatAction { table.addCell(mergeStats == null ? null : mergeStats.getTotalSize()); table.addCell(mergeStats == null ? null : mergeStats.getTotalTime()); - PercolateStats percolateStats = indicesStats == null ? null : indicesStats.getPercolate(); - table.addCell(percolateStats == null ? null : percolateStats.getCurrent()); - table.addCell(percolateStats == null ? null : percolateStats.getMemorySize()); - table.addCell(percolateStats == null ? null : percolateStats.getNumQueries()); - table.addCell(percolateStats == null ? null : percolateStats.getTime()); - table.addCell(percolateStats == null ? null : percolateStats.getCount()); + PercolatorQueryCacheStats percolatorQueryCacheStats = indicesStats == null ? null : indicesStats.getPercolate(); + table.addCell(percolatorQueryCacheStats == null ? null : percolatorQueryCacheStats.getNumQueries()); RefreshStats refreshStats = indicesStats == null ? null : indicesStats.getRefresh(); table.addCell(refreshStats == null ? null : refreshStats.getTotal()); diff --git a/core/src/main/java/org/elasticsearch/rest/action/cat/RestShardsAction.java b/core/src/main/java/org/elasticsearch/rest/action/cat/RestShardsAction.java index 445f7099fef..1b3f239ae5f 100644 --- a/core/src/main/java/org/elasticsearch/rest/action/cat/RestShardsAction.java +++ b/core/src/main/java/org/elasticsearch/rest/action/cat/RestShardsAction.java @@ -139,11 +139,7 @@ public class RestShardsAction extends AbstractCatAction { table.addCell("merges.total_size", "alias:mts,mergesTotalSize;default:false;text-align:right;desc:size merged"); table.addCell("merges.total_time", "alias:mtt,mergesTotalTime;default:false;text-align:right;desc:time spent in merges"); - table.addCell("percolate.current", "alias:pc,percolateCurrent;default:false;text-align:right;desc:number of current percolations"); - table.addCell("percolate.memory_size", "alias:pm,percolateMemory;default:false;text-align:right;desc:memory used by percolations"); table.addCell("percolate.queries", "alias:pq,percolateQueries;default:false;text-align:right;desc:number of registered percolation queries"); - table.addCell("percolate.time", "alias:pti,percolateTime;default:false;text-align:right;desc:time spent percolating"); - table.addCell("percolate.total", "alias:pto,percolateTotal;default:false;text-align:right;desc:total percolations"); table.addCell("refresh.total", "alias:rto,refreshTotal;default:false;text-align:right;desc:total refreshes"); table.addCell("refresh.time", "alias:rti,refreshTime;default:false;text-align:right;desc:time spent in refreshes"); @@ -282,11 +278,7 @@ public class RestShardsAction extends AbstractCatAction { table.addCell(commonStats == null ? null : commonStats.getMerge().getTotalSize()); table.addCell(commonStats == null ? null : commonStats.getMerge().getTotalTime()); - table.addCell(commonStats == null ? null : commonStats.getPercolate().getCurrent()); - table.addCell(commonStats == null ? null : commonStats.getPercolate().getMemorySize()); - table.addCell(commonStats == null ? null : commonStats.getPercolate().getNumQueries()); - table.addCell(commonStats == null ? null : commonStats.getPercolate().getTime()); - table.addCell(commonStats == null ? null : commonStats.getPercolate().getCount()); + table.addCell(commonStats == null ? null : commonStats.getPercolatorCache().getNumQueries()); table.addCell(commonStats == null ? null : commonStats.getRefresh().getTotal()); table.addCell(commonStats == null ? null : commonStats.getRefresh().getTotalTime()); diff --git a/core/src/main/java/org/elasticsearch/rest/action/cat/RestThreadPoolAction.java b/core/src/main/java/org/elasticsearch/rest/action/cat/RestThreadPoolAction.java index fa2e662c738..a0812f3e9a4 100644 --- a/core/src/main/java/org/elasticsearch/rest/action/cat/RestThreadPoolAction.java +++ b/core/src/main/java/org/elasticsearch/rest/action/cat/RestThreadPoolAction.java @@ -63,7 +63,6 @@ public class RestThreadPoolAction extends AbstractCatAction { ThreadPool.Names.INDEX, ThreadPool.Names.MANAGEMENT, ThreadPool.Names.FORCE_MERGE, - ThreadPool.Names.PERCOLATE, ThreadPool.Names.REFRESH, ThreadPool.Names.SEARCH, ThreadPool.Names.SNAPSHOT, @@ -79,7 +78,6 @@ public class RestThreadPoolAction extends AbstractCatAction { "i", "ma", "fm", - "p", "r", "s", "sn", diff --git a/core/src/main/java/org/elasticsearch/rest/action/main/RestMainAction.java b/core/src/main/java/org/elasticsearch/rest/action/main/RestMainAction.java index bf3f0a3e5df..205bea92f96 100644 --- a/core/src/main/java/org/elasticsearch/rest/action/main/RestMainAction.java +++ b/core/src/main/java/org/elasticsearch/rest/action/main/RestMainAction.java @@ -23,7 +23,7 @@ import org.elasticsearch.Build; import org.elasticsearch.Version; import org.elasticsearch.client.Client; import org.elasticsearch.cluster.ClusterName; -import org.elasticsearch.cluster.ClusterService; +import org.elasticsearch.cluster.service.ClusterService; import org.elasticsearch.common.inject.Inject; import org.elasticsearch.common.settings.Settings; import org.elasticsearch.common.xcontent.XContentBuilder; diff --git a/core/src/main/java/org/elasticsearch/rest/action/search/RestSearchAction.java b/core/src/main/java/org/elasticsearch/rest/action/search/RestSearchAction.java index 6eedb0aea04..9d533d15ff2 100644 --- a/core/src/main/java/org/elasticsearch/rest/action/search/RestSearchAction.java +++ b/core/src/main/java/org/elasticsearch/rest/action/search/RestSearchAction.java @@ -92,7 +92,7 @@ public class RestSearchAction extends BaseRestHandler { @Override public void handleRequest(final RestRequest request, final RestChannel channel, final Client client) throws IOException { SearchRequest searchRequest = new SearchRequest(); - RestSearchAction.parseSearchRequest(searchRequest, queryRegistry, request, parseFieldMatcher, aggParsers, suggesters, null); + parseSearchRequest(searchRequest, queryRegistry, request, parseFieldMatcher, aggParsers, suggesters, null); client.search(searchRequest, new RestStatusToXContentListener<>(channel)); } @@ -123,16 +123,15 @@ public class RestSearchAction extends BaseRestHandler { } if (restContent != null) { QueryParseContext context = new QueryParseContext(indicesQueriesRegistry); - if (isTemplateRequest) { - try (XContentParser parser = XContentFactory.xContent(restContent).createParser(restContent)) { - context.reset(parser); - context.parseFieldMatcher(parseFieldMatcher); + try (XContentParser parser = XContentFactory.xContent(restContent).createParser(restContent)) { + context.reset(parser); + context.parseFieldMatcher(parseFieldMatcher); + if (isTemplateRequest) { Template template = TemplateQueryParser.parse(parser, context.parseFieldMatcher(), "params", "template"); searchRequest.template(template); + } else { + searchRequest.source().parseXContent(parser, context, aggParsers, suggesters); } - } else { - RestActions.parseRestSearchSource(searchRequest.source(), restContent, indicesQueriesRegistry, parseFieldMatcher, - aggParsers, suggesters); } } diff --git a/core/src/main/java/org/elasticsearch/rest/action/suggest/RestSuggestAction.java b/core/src/main/java/org/elasticsearch/rest/action/suggest/RestSuggestAction.java index 291eb69254b..53d9e668de1 100644 --- a/core/src/main/java/org/elasticsearch/rest/action/suggest/RestSuggestAction.java +++ b/core/src/main/java/org/elasticsearch/rest/action/suggest/RestSuggestAction.java @@ -97,7 +97,7 @@ public class RestSuggestAction extends BaseRestHandler { buildBroadcastShardsHeader(builder, request, response); Suggest suggest = response.getSuggest(); if (suggest != null) { - suggest.toXContent(builder, request); + suggest.toInnerXContent(builder, request); } builder.endObject(); return new BytesRestResponse(restStatus, builder); diff --git a/core/src/main/java/org/elasticsearch/rest/action/support/RestActions.java b/core/src/main/java/org/elasticsearch/rest/action/support/RestActions.java index 950828639f7..55063664343 100644 --- a/core/src/main/java/org/elasticsearch/rest/action/support/RestActions.java +++ b/core/src/main/java/org/elasticsearch/rest/action/support/RestActions.java @@ -115,17 +115,6 @@ public class RestActions { return queryBuilder; } - public static void parseRestSearchSource(SearchSourceBuilder source, BytesReference sourceBytes, - IndicesQueriesRegistry queryRegistry, ParseFieldMatcher parseFieldMatcher, - AggregatorParsers aggParsers, Suggesters suggesters) - throws IOException { - XContentParser parser = XContentFactory.xContent(sourceBytes).createParser(sourceBytes); - QueryParseContext queryParseContext = new QueryParseContext(queryRegistry); - queryParseContext.reset(parser); - queryParseContext.parseFieldMatcher(parseFieldMatcher); - source.parseXContent(parser, queryParseContext, aggParsers, suggesters); - } - /** * Get Rest content from either payload or source parameter * @param request Rest request diff --git a/core/src/main/java/org/elasticsearch/search/SearchModule.java b/core/src/main/java/org/elasticsearch/search/SearchModule.java index 55c343ba874..ae6d5aaf4be 100644 --- a/core/src/main/java/org/elasticsearch/search/SearchModule.java +++ b/core/src/main/java/org/elasticsearch/search/SearchModule.java @@ -62,6 +62,7 @@ import org.elasticsearch.index.query.MoreLikeThisQueryParser; import org.elasticsearch.index.query.MultiMatchQueryParser; import org.elasticsearch.index.query.NestedQueryParser; import org.elasticsearch.index.query.ParentIdQueryParser; +import org.elasticsearch.index.query.PercolatorQueryParser; import org.elasticsearch.index.query.PrefixQueryParser; import org.elasticsearch.index.query.QueryBuilder; import org.elasticsearch.index.query.QueryParser; @@ -215,6 +216,7 @@ import org.elasticsearch.search.fetch.fielddata.FieldDataFieldsFetchSubPhase; import org.elasticsearch.search.fetch.innerhits.InnerHitsFetchSubPhase; import org.elasticsearch.search.fetch.matchedqueries.MatchedQueriesFetchSubPhase; import org.elasticsearch.search.fetch.parent.ParentFieldSubFetchPhase; +import org.elasticsearch.index.percolator.PercolatorHighlightSubFetchPhase; import org.elasticsearch.search.fetch.script.ScriptFieldsFetchSubPhase; import org.elasticsearch.search.fetch.source.FetchSourceSubPhase; import org.elasticsearch.search.fetch.version.VersionFetchSubPhase; @@ -356,6 +358,7 @@ public class SearchModule extends AbstractModule { fetchSubPhaseMultibinder.addBinding().to(MatchedQueriesFetchSubPhase.class); fetchSubPhaseMultibinder.addBinding().to(HighlightPhase.class); fetchSubPhaseMultibinder.addBinding().to(ParentFieldSubFetchPhase.class); + fetchSubPhaseMultibinder.addBinding().to(PercolatorHighlightSubFetchPhase.class); for (Class clazz : fetchSubPhases) { fetchSubPhaseMultibinder.addBinding().to(clazz); } @@ -546,6 +549,7 @@ public class SearchModule extends AbstractModule { registerQueryParser(ExistsQueryParser::new); registerQueryParser(MatchNoneQueryParser::new); registerQueryParser(ParentIdQueryParser::new); + registerQueryParser(PercolatorQueryParser::new); if (ShapesAvailability.JTS_AVAILABLE && ShapesAvailability.SPATIAL4J_AVAILABLE) { registerQueryParser(GeoShapeQueryParser::new); } diff --git a/core/src/main/java/org/elasticsearch/search/SearchService.java b/core/src/main/java/org/elasticsearch/search/SearchService.java index 8a400418eb7..be2e52b5aa3 100644 --- a/core/src/main/java/org/elasticsearch/search/SearchService.java +++ b/core/src/main/java/org/elasticsearch/search/SearchService.java @@ -20,13 +20,12 @@ package org.elasticsearch.search; import com.carrotsearch.hppc.ObjectFloatHashMap; - import org.apache.lucene.search.FieldDoc; import org.apache.lucene.search.TopDocs; import org.elasticsearch.ExceptionsHelper; import org.elasticsearch.cache.recycler.PageCacheRecycler; -import org.elasticsearch.cluster.ClusterService; import org.elasticsearch.cluster.metadata.IndexMetaData; +import org.elasticsearch.cluster.service.ClusterService; import org.elasticsearch.common.Nullable; import org.elasticsearch.common.ParseFieldMatcher; import org.elasticsearch.common.bytes.BytesReference; @@ -49,6 +48,7 @@ import org.elasticsearch.common.xcontent.XContentParser; import org.elasticsearch.index.Index; import org.elasticsearch.index.IndexService; import org.elasticsearch.index.engine.Engine; +import org.elasticsearch.index.fieldstats.FieldStatsProvider; import org.elasticsearch.index.query.QueryParseContext; import org.elasticsearch.index.query.QueryShardContext; import org.elasticsearch.index.search.stats.ShardSearchStats; @@ -241,7 +241,7 @@ public class SearchService extends AbstractLifecycleComponent imp FutureUtils.cancel(keepAliveReaper); } - public DfsSearchResult executeDfsPhase(ShardSearchRequest request) { + public DfsSearchResult executeDfsPhase(ShardSearchRequest request) throws IOException { final SearchContext context = createAndPutContext(request); try { contextProcessing(context); @@ -270,7 +270,7 @@ public class SearchService extends AbstractLifecycleComponent imp } } - public QuerySearchResultProvider executeQueryPhase(ShardSearchRequest request) { + public QuerySearchResultProvider executeQueryPhase(ShardSearchRequest request) throws IOException { final SearchContext context = createAndPutContext(request); final ShardSearchStats shardSearchStats = context.indexShard().searchService(); try { @@ -362,7 +362,7 @@ public class SearchService extends AbstractLifecycleComponent imp } } - public QueryFetchSearchResult executeFetchPhase(ShardSearchRequest request) { + public QueryFetchSearchResult executeFetchPhase(ShardSearchRequest request) throws IOException { final SearchContext context = createAndPutContext(request); contextProcessing(context); try { @@ -519,7 +519,7 @@ public class SearchService extends AbstractLifecycleComponent imp return context; } - final SearchContext createAndPutContext(ShardSearchRequest request) { + final SearchContext createAndPutContext(ShardSearchRequest request) throws IOException { SearchContext context = createContext(request, null); boolean success = false; try { @@ -537,7 +537,7 @@ public class SearchService extends AbstractLifecycleComponent imp } } - final SearchContext createContext(ShardSearchRequest request, @Nullable Engine.Searcher searcher) { + final SearchContext createContext(ShardSearchRequest request, @Nullable Engine.Searcher searcher) throws IOException { IndexService indexService = indicesService.indexServiceSafe(request.shardId().getIndex()); IndexShard indexShard = indexService.getShard(request.shardId().getId()); SearchShardTarget shardTarget = new SearchShardTarget(clusterService.localNode().id(), indexShard.shardId()); @@ -548,6 +548,8 @@ public class SearchService extends AbstractLifecycleComponent imp indexService, indexShard, scriptService, pageCacheRecycler, bigArrays, threadPool.estimatedTimeInMillisCounter(), parseFieldMatcher, defaultSearchTimeout, fetchPhase); + context.getQueryShardContext().setFieldStatsProvider(new FieldStatsProvider(engineSearcher, indexService.mapperService())); + request.rewrite(context.getQueryShardContext()); SearchContext.setCurrent(context); try { if (request.scroll() != null) { diff --git a/core/src/main/java/org/elasticsearch/search/aggregations/metrics/percentiles/PercentileRanksAggregatorBuilder.java b/core/src/main/java/org/elasticsearch/search/aggregations/metrics/percentiles/PercentileRanksAggregatorBuilder.java index cd43777959e..de66f68103f 100644 --- a/core/src/main/java/org/elasticsearch/search/aggregations/metrics/percentiles/PercentileRanksAggregatorBuilder.java +++ b/core/src/main/java/org/elasticsearch/search/aggregations/metrics/percentiles/PercentileRanksAggregatorBuilder.java @@ -48,7 +48,7 @@ public class PercentileRanksAggregatorBuilder extends LeafOnly queryBuilder = null; + if (this.queryBuilder != null) { + queryBuilder = this.queryBuilder.rewrite(context); + } + QueryBuilder postQueryBuilder = null; + if (this.postQueryBuilder != null) { + postQueryBuilder = this.postQueryBuilder.rewrite(context); + } + boolean rewritten = queryBuilder != this.queryBuilder || postQueryBuilder != this.postQueryBuilder; + if (rewritten) { + return shallowCopy(queryBuilder, postQueryBuilder); + } + return this; + } + + private SearchSourceBuilder shallowCopy(QueryBuilder queryBuilder, QueryBuilder postQueryBuilder) { + SearchSourceBuilder rewrittenBuilder = new SearchSourceBuilder(); + rewrittenBuilder.aggregations = aggregations; + rewrittenBuilder.explain = explain; + rewrittenBuilder.ext = ext; + rewrittenBuilder.fetchSourceContext = fetchSourceContext; + rewrittenBuilder.fieldDataFields = fieldDataFields; + rewrittenBuilder.fieldNames = fieldNames; + rewrittenBuilder.from = from; + rewrittenBuilder.highlightBuilder = highlightBuilder; + rewrittenBuilder.indexBoost = indexBoost; + rewrittenBuilder.innerHitsBuilder = innerHitsBuilder; + rewrittenBuilder.minScore = minScore; + rewrittenBuilder.postQueryBuilder = postQueryBuilder; + rewrittenBuilder.profile = profile; + rewrittenBuilder.queryBuilder = queryBuilder; + rewrittenBuilder.rescoreBuilders = rescoreBuilders; + rewrittenBuilder.scriptFields = scriptFields; + rewrittenBuilder.searchAfterBuilder = searchAfterBuilder; + rewrittenBuilder.size = size; + rewrittenBuilder.sorts = sorts; + rewrittenBuilder.stats = stats; + rewrittenBuilder.suggestBuilder = suggestBuilder; + rewrittenBuilder.terminateAfter = terminateAfter; + rewrittenBuilder.timeoutInMillis = timeoutInMillis; + rewrittenBuilder.trackScores = trackScores; + rewrittenBuilder.version = version; + return rewrittenBuilder; + } + /** * Create a new SearchSourceBuilder with attributes set by an xContent. */ diff --git a/core/src/main/java/org/elasticsearch/search/controller/SearchPhaseController.java b/core/src/main/java/org/elasticsearch/search/controller/SearchPhaseController.java index 68343ba5959..d5d4607fba9 100644 --- a/core/src/main/java/org/elasticsearch/search/controller/SearchPhaseController.java +++ b/core/src/main/java/org/elasticsearch/search/controller/SearchPhaseController.java @@ -386,7 +386,7 @@ public class SearchPhaseController extends AbstractComponent { Suggest.group(groupedSuggestions, shardResult); } - suggest = hasSuggestions ? new Suggest(Suggest.Fields.SUGGEST, Suggest.reduce(groupedSuggestions)) : null; + suggest = hasSuggestions ? new Suggest(Suggest.reduce(groupedSuggestions)) : null; } // merge addAggregation diff --git a/core/src/main/java/org/elasticsearch/search/internal/DefaultSearchContext.java b/core/src/main/java/org/elasticsearch/search/internal/DefaultSearchContext.java index 8c3c19343b4..71a289331f8 100644 --- a/core/src/main/java/org/elasticsearch/search/internal/DefaultSearchContext.java +++ b/core/src/main/java/org/elasticsearch/search/internal/DefaultSearchContext.java @@ -49,6 +49,7 @@ import org.elasticsearch.index.mapper.MappedFieldType; import org.elasticsearch.index.mapper.MapperService; import org.elasticsearch.index.mapper.internal.TypeFieldMapper; import org.elasticsearch.index.mapper.object.ObjectMapper; +import org.elasticsearch.index.percolator.PercolatorQueryCache; import org.elasticsearch.index.query.AbstractQueryBuilder; import org.elasticsearch.index.query.ParsedQuery; import org.elasticsearch.index.query.QueryShardContext; @@ -487,6 +488,11 @@ public class DefaultSearchContext extends SearchContext { return indexService.fieldData(); } + @Override + public PercolatorQueryCache percolatorQueryCache() { + return indexService.cache().getPercolatorQueryCache(); + } + @Override public long timeoutInMillis() { return timeoutInMillis; diff --git a/core/src/main/java/org/elasticsearch/search/internal/FilteredSearchContext.java b/core/src/main/java/org/elasticsearch/search/internal/FilteredSearchContext.java index 83ea2b1ccd8..fedab3f9782 100644 --- a/core/src/main/java/org/elasticsearch/search/internal/FilteredSearchContext.java +++ b/core/src/main/java/org/elasticsearch/search/internal/FilteredSearchContext.java @@ -34,6 +34,7 @@ import org.elasticsearch.index.fielddata.IndexFieldDataService; import org.elasticsearch.index.mapper.MappedFieldType; import org.elasticsearch.index.mapper.MapperService; import org.elasticsearch.index.mapper.object.ObjectMapper; +import org.elasticsearch.index.percolator.PercolatorQueryCache; import org.elasticsearch.index.query.ParsedQuery; import org.elasticsearch.index.query.QueryShardContext; import org.elasticsearch.index.shard.IndexShard; @@ -274,6 +275,11 @@ public abstract class FilteredSearchContext extends SearchContext { return in.fieldData(); } + @Override + public PercolatorQueryCache percolatorQueryCache() { + return in.percolatorQueryCache(); + } + @Override public long timeoutInMillis() { return in.timeoutInMillis(); diff --git a/core/src/main/java/org/elasticsearch/search/internal/InternalSearchResponse.java b/core/src/main/java/org/elasticsearch/search/internal/InternalSearchResponse.java index b8255e0bb52..1a2e1f70191 100644 --- a/core/src/main/java/org/elasticsearch/search/internal/InternalSearchResponse.java +++ b/core/src/main/java/org/elasticsearch/search/internal/InternalSearchResponse.java @@ -134,7 +134,7 @@ public class InternalSearchResponse implements Streamable, ToXContent { aggregations = InternalAggregations.readAggregations(in); } if (in.readBoolean()) { - suggest = Suggest.readSuggest(Suggest.Fields.SUGGEST, in); + suggest = Suggest.readSuggest(in); } timedOut = in.readBoolean(); diff --git a/core/src/main/java/org/elasticsearch/search/internal/SearchContext.java b/core/src/main/java/org/elasticsearch/search/internal/SearchContext.java index 2b35e182161..ec47c6327cf 100644 --- a/core/src/main/java/org/elasticsearch/search/internal/SearchContext.java +++ b/core/src/main/java/org/elasticsearch/search/internal/SearchContext.java @@ -38,6 +38,7 @@ import org.elasticsearch.index.fielddata.IndexFieldDataService; import org.elasticsearch.index.mapper.MappedFieldType; import org.elasticsearch.index.mapper.MapperService; import org.elasticsearch.index.mapper.object.ObjectMapper; +import org.elasticsearch.index.percolator.PercolatorQueryCache; import org.elasticsearch.index.query.ParsedQuery; import org.elasticsearch.index.query.QueryShardContext; import org.elasticsearch.index.shard.IndexShard; @@ -217,6 +218,8 @@ public abstract class SearchContext implements Releasable { public abstract IndexFieldDataService fieldData(); + public abstract PercolatorQueryCache percolatorQueryCache(); + public abstract long timeoutInMillis(); public abstract void timeoutInMillis(long timeoutInMillis); diff --git a/core/src/main/java/org/elasticsearch/search/internal/ShardSearchLocalRequest.java b/core/src/main/java/org/elasticsearch/search/internal/ShardSearchLocalRequest.java index 56ad8ed9467..31192350308 100644 --- a/core/src/main/java/org/elasticsearch/search/internal/ShardSearchLocalRequest.java +++ b/core/src/main/java/org/elasticsearch/search/internal/ShardSearchLocalRequest.java @@ -27,6 +27,7 @@ import org.elasticsearch.common.bytes.BytesReference; import org.elasticsearch.common.io.stream.BytesStreamOutput; import org.elasticsearch.common.io.stream.StreamInput; import org.elasticsearch.common.io.stream.StreamOutput; +import org.elasticsearch.index.query.QueryShardContext; import org.elasticsearch.index.shard.ShardId; import org.elasticsearch.script.Template; import org.elasticsearch.search.Scroll; @@ -224,4 +225,15 @@ public class ShardSearchLocalRequest implements ShardSearchRequest { // we could potentially keep it without copying, but then pay the price of extra unused bytes up to a page return out.bytes().copyBytesArray(); } + + @Override + public void rewrite(QueryShardContext context) throws IOException { + SearchSourceBuilder source = this.source; + SearchSourceBuilder rewritten = null; + while (rewritten != source) { + rewritten = source.rewrite(context); + source = rewritten; + } + this.source = source; + } } diff --git a/core/src/main/java/org/elasticsearch/search/internal/ShardSearchRequest.java b/core/src/main/java/org/elasticsearch/search/internal/ShardSearchRequest.java index 82ff69078aa..aa148e215c8 100644 --- a/core/src/main/java/org/elasticsearch/search/internal/ShardSearchRequest.java +++ b/core/src/main/java/org/elasticsearch/search/internal/ShardSearchRequest.java @@ -21,6 +21,7 @@ package org.elasticsearch.search.internal; import org.elasticsearch.action.search.SearchType; import org.elasticsearch.common.bytes.BytesReference; +import org.elasticsearch.index.query.QueryShardContext; import org.elasticsearch.index.shard.ShardId; import org.elasticsearch.script.Template; import org.elasticsearch.search.Scroll; @@ -72,4 +73,10 @@ public interface ShardSearchRequest { * Returns the cache key for this shard search request, based on its content */ BytesReference cacheKey() throws IOException; + + /** + * Rewrites this request into its primitive form. e.g. by rewriting the + * QueryBuilder. + */ + void rewrite(QueryShardContext context) throws IOException; } diff --git a/core/src/main/java/org/elasticsearch/search/internal/ShardSearchTransportRequest.java b/core/src/main/java/org/elasticsearch/search/internal/ShardSearchTransportRequest.java index dc19f84c7a7..cd6460a686f 100644 --- a/core/src/main/java/org/elasticsearch/search/internal/ShardSearchTransportRequest.java +++ b/core/src/main/java/org/elasticsearch/search/internal/ShardSearchTransportRequest.java @@ -28,6 +28,7 @@ import org.elasticsearch.cluster.routing.ShardRouting; import org.elasticsearch.common.bytes.BytesReference; import org.elasticsearch.common.io.stream.StreamInput; import org.elasticsearch.common.io.stream.StreamOutput; +import org.elasticsearch.index.query.QueryShardContext; import org.elasticsearch.index.shard.ShardId; import org.elasticsearch.script.Template; import org.elasticsearch.search.Scroll; @@ -156,4 +157,16 @@ public class ShardSearchTransportRequest extends TransportRequest implements Sha public boolean isProfile() { return shardSearchLocalRequest.isProfile(); } + + @Override + public void rewrite(QueryShardContext context) throws IOException { + shardSearchLocalRequest.rewrite(context); + } + + private ShardSearchTransportRequest shallowCopy(ShardSearchLocalRequest rewritten) { + ShardSearchTransportRequest newRequest = new ShardSearchTransportRequest(); + newRequest.originalIndices = originalIndices; + newRequest.shardSearchLocalRequest = rewritten; + return newRequest; + } } diff --git a/core/src/main/java/org/elasticsearch/search/query/QuerySearchResult.java b/core/src/main/java/org/elasticsearch/search/query/QuerySearchResult.java index 9223eb5a82d..2b82633ebfd 100644 --- a/core/src/main/java/org/elasticsearch/search/query/QuerySearchResult.java +++ b/core/src/main/java/org/elasticsearch/search/query/QuerySearchResult.java @@ -207,7 +207,7 @@ public class QuerySearchResult extends QuerySearchResultProvider { this.pipelineAggregators = pipelineAggregators; } if (in.readBoolean()) { - suggest = Suggest.readSuggest(Suggest.Fields.SUGGEST, in); + suggest = Suggest.readSuggest(in); } searchTimedOut = in.readBoolean(); terminatedEarly = in.readOptionalBoolean(); diff --git a/core/src/main/java/org/elasticsearch/search/suggest/Suggest.java b/core/src/main/java/org/elasticsearch/search/suggest/Suggest.java index f2a217b14c8..f9c7092fbf1 100644 --- a/core/src/main/java/org/elasticsearch/search/suggest/Suggest.java +++ b/core/src/main/java/org/elasticsearch/search/suggest/Suggest.java @@ -46,9 +46,7 @@ import java.util.Map; */ public class Suggest implements Iterable>>, Streamable, ToXContent { - public static class Fields { - public static final XContentBuilderString SUGGEST = new XContentBuilderString("suggest"); - } + private static final XContentBuilderString NAME = new XContentBuilderString("suggest"); private static final Comparator