From 60721b2a176bf74e6b07a65745628ad4aa44bbcb Mon Sep 17 00:00:00 2001 From: Igor Motov Date: Thu, 26 Feb 2015 11:30:02 -0500 Subject: [PATCH 01/14] Snapshot/Restore: remove obsolete expand_wildcards_open and expand_wildcards_close options In #6097 we made snapshot/restore index option consistent with other API. Now we can remove old style options from master. Closes #10743 --- docs/reference/migration/migrate_2_0.asciidoc | 7 +++++++ .../snapshots/create/CreateSnapshotRequest.java | 10 +--------- .../snapshots/restore/RestoreSnapshotRequest.java | 11 +---------- 3 files changed, 9 insertions(+), 19 deletions(-) diff --git a/docs/reference/migration/migrate_2_0.asciidoc b/docs/reference/migration/migrate_2_0.asciidoc index b20e1960fee..37471d32a0b 100644 --- a/docs/reference/migration/migrate_2_0.asciidoc +++ b/docs/reference/migration/migrate_2_0.asciidoc @@ -389,3 +389,10 @@ favour or `bool`. The `execution` option of the `terms` filter is now deprecated and ignored if provided. + +=== Snapshot and Restore + +The obsolete parameters `expand_wildcards_open` and `expand_wildcards_close` are no longer +supported by the snapshot and restore operations. These parameters have been replaced by +a single `expand_wildcards` parameter. See <> for more. + diff --git a/src/main/java/org/elasticsearch/action/admin/cluster/snapshots/create/CreateSnapshotRequest.java b/src/main/java/org/elasticsearch/action/admin/cluster/snapshots/create/CreateSnapshotRequest.java index 284e02e3bc1..0bc0e75b4e5 100644 --- a/src/main/java/org/elasticsearch/action/admin/cluster/snapshots/create/CreateSnapshotRequest.java +++ b/src/main/java/org/elasticsearch/action/admin/cluster/snapshots/create/CreateSnapshotRequest.java @@ -371,10 +371,6 @@ public class CreateSnapshotRequest extends MasterNodeOperationRequest entry : ((Map) source).entrySet()) { String name = entry.getKey(); if (name.equals("indices")) { @@ -385,10 +381,6 @@ public class CreateSnapshotRequest extends MasterNodeOperationRequest) source, IndicesOptions.fromOptions(ignoreUnavailable, allowNoIndices, expandWildcardsOpen, expandWildcardsClosed))); + indicesOptions(IndicesOptions.fromMap((Map) source, IndicesOptions.lenientExpandOpen())); return this; } diff --git a/src/main/java/org/elasticsearch/action/admin/cluster/snapshots/restore/RestoreSnapshotRequest.java b/src/main/java/org/elasticsearch/action/admin/cluster/snapshots/restore/RestoreSnapshotRequest.java index 95582ca65bd..27dd0672ca5 100644 --- a/src/main/java/org/elasticsearch/action/admin/cluster/snapshots/restore/RestoreSnapshotRequest.java +++ b/src/main/java/org/elasticsearch/action/admin/cluster/snapshots/restore/RestoreSnapshotRequest.java @@ -504,11 +504,6 @@ public class RestoreSnapshotRequest extends MasterNodeOperationRequest entry : ((Map) source).entrySet()) { String name = entry.getKey(); if (name.equals("indices")) { @@ -519,10 +514,6 @@ public class RestoreSnapshotRequest extends MasterNodeOperationRequest) source, IndicesOptions.fromOptions(ignoreUnavailable, allowNoIndices, expandWildcardsOpen, expandWildcardsClosed))); + indicesOptions(IndicesOptions.fromMap((Map) source, IndicesOptions.lenientExpandOpen())); return this; } From 4a94e1f14bc272d1d3584fc387deadea48331e7d Mon Sep 17 00:00:00 2001 From: Benoit Delbosc Date: Fri, 17 Apr 2015 14:59:24 +0200 Subject: [PATCH 02/14] Docs: Warning about the conflict with the Standard Tokenizer The examples given requires a specific Tokenizer to work. Closes: 10645 --- .../word-delimiter-tokenfilter.asciidoc | 28 +++++++++++-------- 1 file changed, 17 insertions(+), 11 deletions(-) diff --git a/docs/reference/analysis/tokenfilters/word-delimiter-tokenfilter.asciidoc b/docs/reference/analysis/tokenfilters/word-delimiter-tokenfilter.asciidoc index 9ce81e1ac9f..edb3f3b5590 100644 --- a/docs/reference/analysis/tokenfilters/word-delimiter-tokenfilter.asciidoc +++ b/docs/reference/analysis/tokenfilters/word-delimiter-tokenfilter.asciidoc @@ -16,27 +16,27 @@ ignored: "//hello---there, 'dude'" -> "hello", "there", "dude" Parameters include: -`generate_word_parts`:: +`generate_word_parts`:: If `true` causes parts of words to be generated: "PowerShot" => "Power" "Shot". Defaults to `true`. -`generate_number_parts`:: +`generate_number_parts`:: If `true` causes number subwords to be generated: "500-42" => "500" "42". Defaults to `true`. -`catenate_words`:: +`catenate_words`:: If `true` causes maximum runs of word parts to be catenated: "wi-fi" => "wifi". Defaults to `false`. -`catenate_numbers`:: +`catenate_numbers`:: If `true` causes maximum runs of number parts to be catenated: "500-42" => "50042". Defaults to `false`. -`catenate_all`:: +`catenate_all`:: If `true` causes all subword parts to be catenated: "wi-fi-4000" => "wifi4000". Defaults to `false`. -`split_on_case_change`:: +`split_on_case_change`:: If `true` causes "PowerShot" to be two tokens; ("Power-Shot" remains two parts regards). Defaults to `true`. @@ -44,29 +44,29 @@ Parameters include: If `true` includes original words in subwords: "500-42" => "500-42" "500" "42". Defaults to `false`. -`split_on_numerics`:: +`split_on_numerics`:: If `true` causes "j2se" to be three tokens; "j" "2" "se". Defaults to `true`. -`stem_english_possessive`:: +`stem_english_possessive`:: If `true` causes trailing "'s" to be removed for each subword: "O'Neil's" => "O", "Neil". Defaults to `true`. Advance settings include: -`protected_words`:: +`protected_words`:: A list of protected words from being delimiter. Either an array, or also can set `protected_words_path` which resolved to a file configured with protected words (one on each line). Automatically resolves to `config/` based location if exists. -`type_table`:: +`type_table`:: A custom type mapping table, for example (when configured using `type_table_path`): [source,js] -------------------------------------------------- - # Map the $, %, '.', and ',' characters to DIGIT + # Map the $, %, '.', and ',' characters to DIGIT # This might be useful for financial data. $ => DIGIT % => DIGIT @@ -78,3 +78,9 @@ Advance settings include: # see http://en.wikipedia.org/wiki/Zero-width_joiner \\u200D => ALPHANUM -------------------------------------------------- + +NOTE: Using a tokenizer like the `standard` tokenizer may interfere with +the `catenate_*` and `preserve_original` parameters, as the original +string may already have lost punctuation during tokenization. Instead, +you may want to use the `whitespace` tokenizer. + From 1f5bdca8cca1791d8028bf57829337e466e88921 Mon Sep 17 00:00:00 2001 From: Ryan Ernst Date: Wed, 22 Apr 2015 13:27:15 -0700 Subject: [PATCH 03/14] Mappings: Restrict murmur3 field type to sane options Disabling doc values or trying to index hash values are not correct uses of this the murmur3 field type, and just cause problems. This disallows changing doc values or index options for 2.0+. closes #10465 --- docs/reference/migration/migrate_2_0.asciidoc | 4 + .../index/mapper/core/Murmur3FieldMapper.java | 13 ++ .../mapper/core/Murmur3FieldMapperTests.java | 132 ++++++++++++++++++ 3 files changed, 149 insertions(+) create mode 100644 src/test/java/org/elasticsearch/index/mapper/core/Murmur3FieldMapperTests.java diff --git a/docs/reference/migration/migrate_2_0.asciidoc b/docs/reference/migration/migrate_2_0.asciidoc index 37471d32a0b..91462645bd5 100644 --- a/docs/reference/migration/migrate_2_0.asciidoc +++ b/docs/reference/migration/migrate_2_0.asciidoc @@ -302,6 +302,10 @@ the user-friendly representation of boolean fields: `false`/`true`: ] --------------- +=== Murmur3 Fields +Fields of type `murmur3` can no longer change `doc_values` or `index` setting. +They are always stored with doc values, and not indexed. + === Codecs It is no longer possible to specify per-field postings and doc values formats diff --git a/src/main/java/org/elasticsearch/index/mapper/core/Murmur3FieldMapper.java b/src/main/java/org/elasticsearch/index/mapper/core/Murmur3FieldMapper.java index 68158c6a316..7c9c920a3c6 100644 --- a/src/main/java/org/elasticsearch/index/mapper/core/Murmur3FieldMapper.java +++ b/src/main/java/org/elasticsearch/index/mapper/core/Murmur3FieldMapper.java @@ -22,6 +22,7 @@ package org.elasticsearch.index.mapper.core; import org.apache.lucene.document.Field; import org.apache.lucene.document.FieldType; import org.apache.lucene.util.BytesRef; +import org.elasticsearch.Version; import org.elasticsearch.common.Explicit; import org.elasticsearch.common.Nullable; import org.elasticsearch.common.hash.MurmurHash3; @@ -35,6 +36,7 @@ import java.io.IOException; import java.util.List; import java.util.Map; +import static org.elasticsearch.common.xcontent.support.XContentMapValues.nodeBooleanValue; import static org.elasticsearch.index.mapper.MapperBuilders.murmur3Field; import static org.elasticsearch.index.mapper.core.TypeParsers.parseNumberField; @@ -69,6 +71,17 @@ public class Murmur3FieldMapper extends LongFieldMapper { @SuppressWarnings("unchecked") public Mapper.Builder parse(String name, Map node, ParserContext parserContext) throws MapperParsingException { Builder builder = murmur3Field(name); + + // tweaking these settings is no longer allowed, the entire purpose of murmur3 fields is to store a hash + if (parserContext.indexVersionCreated().onOrAfter(Version.V_2_0_0)) { + if (node.get("doc_values") != null) { + throw new MapperParsingException("Setting [doc_values] cannot be modified for field [" + name + "]"); + } + if (node.get("index") != null) { + throw new MapperParsingException("Setting [index] cannot be modified for field [" + name + "]"); + } + } + parseNumberField(builder, name, node, parserContext); // Because this mapper extends LongFieldMapper the null_value field will be added to the JSON when transferring cluster state // between nodes so we have to remove the entry here so that the validation doesn't fail diff --git a/src/test/java/org/elasticsearch/index/mapper/core/Murmur3FieldMapperTests.java b/src/test/java/org/elasticsearch/index/mapper/core/Murmur3FieldMapperTests.java new file mode 100644 index 00000000000..fd502a04ed9 --- /dev/null +++ b/src/test/java/org/elasticsearch/index/mapper/core/Murmur3FieldMapperTests.java @@ -0,0 +1,132 @@ +/* + * 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.mapper.core; + +import org.apache.lucene.index.IndexOptions; +import org.elasticsearch.Version; +import org.elasticsearch.cluster.metadata.IndexMetaData; +import org.elasticsearch.common.settings.ImmutableSettings; +import org.elasticsearch.common.settings.Settings; +import org.elasticsearch.common.xcontent.XContentFactory; +import org.elasticsearch.index.IndexService; +import org.elasticsearch.index.mapper.DocumentMapper; +import org.elasticsearch.index.mapper.DocumentMapperParser; +import org.elasticsearch.index.mapper.Mapper; +import org.elasticsearch.index.mapper.MapperParsingException; +import org.elasticsearch.test.ElasticsearchSingleNodeTest; +import org.junit.Before; + +public class Murmur3FieldMapperTests extends ElasticsearchSingleNodeTest { + + IndexService indexService; + DocumentMapperParser parser; + + @Before + public void before() { + indexService = createIndex("test"); + parser = indexService.mapperService().documentMapperParser(); + } + + public void testDocValuesSettingNotAllowed() throws Exception { + String mapping = XContentFactory.jsonBuilder().startObject().startObject("type") + .startObject("properties").startObject("field") + .field("type", "murmur3") + .field("doc_values", false) + .endObject().endObject().endObject().endObject().string(); + try { + parser.parse(mapping); + fail("expected a mapper parsing exception"); + } catch (MapperParsingException e) { + assertTrue(e.getMessage().contains("Setting [doc_values] cannot be modified")); + } + + // even setting to the default is not allowed, the setting is invalid + mapping = XContentFactory.jsonBuilder().startObject().startObject("type") + .startObject("properties").startObject("field") + .field("type", "murmur3") + .field("doc_values", true) + .endObject().endObject().endObject().endObject().string(); + try { + parser.parse(mapping); + fail("expected a mapper parsing exception"); + } catch (MapperParsingException e) { + assertTrue(e.getMessage().contains("Setting [doc_values] cannot be modified")); + } + } + + public void testIndexSettingNotAllowed() throws Exception { + String mapping = XContentFactory.jsonBuilder().startObject().startObject("type") + .startObject("properties").startObject("field") + .field("type", "murmur3") + .field("index", "not_analyzed") + .endObject().endObject().endObject().endObject().string(); + try { + parser.parse(mapping); + fail("expected a mapper parsing exception"); + } catch (MapperParsingException e) { + assertTrue(e.getMessage().contains("Setting [index] cannot be modified")); + } + + // even setting to the default is not allowed, the setting is invalid + mapping = XContentFactory.jsonBuilder().startObject().startObject("type") + .startObject("properties").startObject("field") + .field("type", "murmur3") + .field("index", "no") + .endObject().endObject().endObject().endObject().string(); + try { + parser.parse(mapping); + fail("expected a mapper parsing exception"); + } catch (MapperParsingException e) { + assertTrue(e.getMessage().contains("Setting [index] cannot be modified")); + } + } + + public void testDocValuesSettingBackcompat() throws Exception { + Settings settings = ImmutableSettings.builder().put(IndexMetaData.SETTING_VERSION_CREATED, Version.V_1_4_2.id).build(); + indexService = createIndex("test_bwc", settings); + parser = indexService.mapperService().documentMapperParser(); + String mapping = XContentFactory.jsonBuilder().startObject().startObject("type") + .startObject("properties").startObject("field") + .field("type", "murmur3") + .field("doc_values", false) + .endObject().endObject().endObject().endObject().string(); + + DocumentMapper docMapper = parser.parse(mapping); + Murmur3FieldMapper mapper = (Murmur3FieldMapper)docMapper.mappers().getMapper("field"); + assertFalse(mapper.hasDocValues()); + } + + public void testIndexSettingBackcompat() throws Exception { + Settings settings = ImmutableSettings.builder().put(IndexMetaData.SETTING_VERSION_CREATED, Version.V_1_4_2.id).build(); + indexService = createIndex("test_bwc", settings); + parser = indexService.mapperService().documentMapperParser(); + String mapping = XContentFactory.jsonBuilder().startObject().startObject("type") + .startObject("properties").startObject("field") + .field("type", "murmur3") + .field("index", "not_analyzed") + .endObject().endObject().endObject().endObject().string(); + + DocumentMapper docMapper = parser.parse(mapping); + Murmur3FieldMapper mapper = (Murmur3FieldMapper)docMapper.mappers().getMapper("field"); + assertEquals(IndexOptions.DOCS, mapper.fieldType().indexOptions()); + } + + // TODO: add more tests +} From c9d72431a3277786f3d597d2b90d4cafbc455687 Mon Sep 17 00:00:00 2001 From: Boaz Leskes Date: Wed, 22 Apr 2015 16:34:28 +0200 Subject: [PATCH 04/14] Test: add afterIfFailed & afterIfSuccessful to ElasticsearchTestCase Also use afterIfFailed to log more info from the rest tests --- .../test/ElasticsearchTestCase.java | 208 ++++++++++-------- .../test/rest/ElasticsearchRestTestCase.java | 7 + 2 files changed, 129 insertions(+), 86 deletions(-) diff --git a/src/test/java/org/elasticsearch/test/ElasticsearchTestCase.java b/src/test/java/org/elasticsearch/test/ElasticsearchTestCase.java index 1f3d0eaa54b..55b4b15af01 100644 --- a/src/test/java/org/elasticsearch/test/ElasticsearchTestCase.java +++ b/src/test/java/org/elasticsearch/test/ElasticsearchTestCase.java @@ -28,8 +28,8 @@ import com.carrotsearch.randomizedtesting.annotations.TimeoutSuite; import com.carrotsearch.randomizedtesting.generators.RandomInts; import com.carrotsearch.randomizedtesting.generators.RandomPicks; import com.carrotsearch.randomizedtesting.generators.RandomStrings; +import com.carrotsearch.randomizedtesting.rules.TestRuleAdapter; import com.google.common.base.Predicate; - import org.apache.lucene.search.IndexSearcher; import org.apache.lucene.uninverting.UninvertingReader; import org.apache.lucene.util.LuceneTestCase; @@ -57,23 +57,15 @@ import org.elasticsearch.test.junit.listeners.LoggingListener; import org.elasticsearch.test.junit.listeners.ReproduceInfoPrinter; import org.elasticsearch.test.search.MockSearchService; import org.elasticsearch.threadpool.ThreadPool; -import org.junit.After; -import org.junit.AfterClass; -import org.junit.Before; -import org.junit.BeforeClass; +import org.junit.*; +import org.junit.rules.RuleChain; import java.io.Closeable; import java.io.IOException; import java.lang.reflect.Field; import java.nio.file.FileSystem; import java.nio.file.Path; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Formatter; -import java.util.List; -import java.util.Locale; -import java.util.Map; -import java.util.Random; +import java.util.*; import java.util.concurrent.Callable; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; @@ -86,8 +78,8 @@ import static org.elasticsearch.test.hamcrest.ElasticsearchAssertions.assertAllS * Base testcase for randomized unit testing with Elasticsearch */ @Listeners({ - ReproduceInfoPrinter.class, - LoggingListener.class + ReproduceInfoPrinter.class, + LoggingListener.class }) @ThreadLeakScope(Scope.SUITE) @ThreadLeakLingering(linger = 5000) // 5 sec lingering @@ -96,39 +88,63 @@ import static org.elasticsearch.test.hamcrest.ElasticsearchAssertions.assertAllS // we suppress pretty much all the lucene codecs for now, except asserting // assertingcodec is the winner for a codec here: it finds bugs and gives clear exceptions. @SuppressCodecs({ - "SimpleText", "Memory", "CheapBastard", "Direct", "Compressing", "FST50", "FSTOrd50", - "TestBloomFilteredLucenePostings", "MockRandom", "BlockTreeOrds", "LuceneFixedGap", - "LuceneVarGapFixedInterval", "LuceneVarGapDocFreqInterval", "Lucene50" + "SimpleText", "Memory", "CheapBastard", "Direct", "Compressing", "FST50", "FSTOrd50", + "TestBloomFilteredLucenePostings", "MockRandom", "BlockTreeOrds", "LuceneFixedGap", + "LuceneVarGapFixedInterval", "LuceneVarGapDocFreqInterval", "Lucene50" }) @LuceneTestCase.SuppressReproduceLine public abstract class ElasticsearchTestCase extends LuceneTestCase { - + static { SecurityHack.ensureInitialized(); } - + protected final ESLogger logger = Loggers.getLogger(getClass()); // ----------------------------------------------------------------- // Suite and test case setup/cleanup. // ----------------------------------------------------------------- + @Rule + public RuleChain failureAndSuccessEvents = RuleChain.outerRule(new TestRuleAdapter() { + @Override + protected void afterIfSuccessful() throws Throwable { + ElasticsearchTestCase.this.afterIfSuccessful(); + } + + @Override + protected void afterAlways(List errors) throws Throwable { + if (errors != null && errors.isEmpty() == false) { + ElasticsearchTestCase.this.afterIfFailed(errors); + } + super.afterAlways(errors); + } + }); + + /** called when a test fails, supplying the errors it generated */ + protected void afterIfFailed(List errors) { + } + + /** called after a test is finished, but only if succesfull */ + protected void afterIfSuccessful() { + } + // TODO: Parent/child and other things does not work with the query cache // We must disable query cache for both suite and test to override lucene, but LTC resets it after the suite - + @BeforeClass public static void disableQueryCacheSuite() { IndexSearcher.setDefaultQueryCache(null); } - + @Before public final void disableQueryCache() { IndexSearcher.setDefaultQueryCache(null); } - + // setup mock filesystems for this test run. we change PathUtils // so that all accesses are plumbed thru any mock wrappers - + @BeforeClass public static void setFileSystem() throws Exception { Field field = PathUtils.class.getDeclaredField("DEFAULT"); @@ -137,7 +153,7 @@ public abstract class ElasticsearchTestCase extends LuceneTestCase { field.set(null, mock); assertEquals(mock, PathUtils.getDefaultFileSystem()); } - + @AfterClass public static void restoreFileSystem() throws Exception { Field field1 = PathUtils.class.getDeclaredField("ACTUAL_DEFAULT"); @@ -149,41 +165,41 @@ public abstract class ElasticsearchTestCase extends LuceneTestCase { // setup a default exception handler which knows when and how to print a stacktrace private static Thread.UncaughtExceptionHandler defaultHandler; - + @BeforeClass public static void setDefaultExceptionHandler() throws Exception { defaultHandler = Thread.getDefaultUncaughtExceptionHandler(); Thread.setDefaultUncaughtExceptionHandler(new ElasticsearchUncaughtExceptionHandler(defaultHandler)); } - + @AfterClass public static void restoreDefaultExceptionHandler() throws Exception { Thread.setDefaultUncaughtExceptionHandler(defaultHandler); } // randomize content type for request builders - + @BeforeClass public static void setContentType() throws Exception { Requests.CONTENT_TYPE = randomFrom(XContentType.values()); Requests.INDEX_CONTENT_TYPE = randomFrom(XContentType.values()); } - + @AfterClass public static void restoreContentType() { Requests.CONTENT_TYPE = XContentType.SMILE; Requests.INDEX_CONTENT_TYPE = XContentType.JSON; } - + // randomize and override the number of cpus so tests reproduce regardless of real number of cpus - + @BeforeClass public static void setProcessors() { int numCpu = TestUtil.nextInt(random(), 1, 4); System.setProperty(EsExecutors.DEFAULT_SYSPROP, Integer.toString(numCpu)); assertEquals(numCpu, EsExecutors.boundedNumberOfProcessors(ImmutableSettings.EMPTY)); } - + @AfterClass public static void restoreProcessors() { System.clearProperty(EsExecutors.DEFAULT_SYSPROP); @@ -192,7 +208,7 @@ public abstract class ElasticsearchTestCase extends LuceneTestCase { // check some things (like MockDirectoryWrappers) are closed where we currently // manage them. TODO: can we add these to LuceneTestCase.closeAfterSuite directly? // or something else simpler instead of the fake closeables? - + @BeforeClass public static void setAfterSuiteAssertions() throws Exception { closeAfterSuite(new Closeable() { @@ -208,7 +224,7 @@ public abstract class ElasticsearchTestCase extends LuceneTestCase { } }); } - + @After public final void ensureCleanedUp() throws Exception { MockPageCacheRecycler.ensureAllPagesAreReleased(); @@ -228,18 +244,18 @@ public abstract class ElasticsearchTestCase extends LuceneTestCase { } }); } - + // mockdirectorywrappers currently set this boolean if checkindex fails // TODO: can we do this cleaner??? - + /** MockFSDirectoryService sets this: */ public static boolean checkIndexFailed; - + @Before public final void resetCheckIndexStatus() throws Exception { checkIndexFailed = false; } - + @After public final void ensureCheckIndexPassed() throws Exception { assertFalse("at least one shard failed CheckIndex", checkIndexFailed); @@ -248,7 +264,7 @@ public abstract class ElasticsearchTestCase extends LuceneTestCase { // ----------------------------------------------------------------- // Test facilities and facades for subclasses. // ----------------------------------------------------------------- - + // TODO: replaces uses of getRandom() with random() // TODO: decide on one set of naming for between/scaledBetween and remove others // TODO: replace frequently() with usually() @@ -258,114 +274,133 @@ public abstract class ElasticsearchTestCase extends LuceneTestCase { // TODO: replace uses of this function with random() return random(); } - + /** * Returns a "scaled" random number between min and max (inclusive). + * * @see RandomizedTest#scaledRandomIntBetween(int, int); */ public static int scaledRandomIntBetween(int min, int max) { return RandomizedTest.scaledRandomIntBetween(min, max); } - - /** + + /** * A random integer from min to max (inclusive). + * * @see #scaledRandomIntBetween(int, int) */ public static int randomIntBetween(int min, int max) { - return RandomInts.randomIntBetween(random(), min, max); + return RandomInts.randomIntBetween(random(), min, max); } - + /** * Returns a "scaled" number of iterations for loops which can have a variable - * iteration count. This method is effectively + * iteration count. This method is effectively * an alias to {@link #scaledRandomIntBetween(int, int)}. */ public static int iterations(int min, int max) { return scaledRandomIntBetween(min, max); } - - /** - * An alias for {@link #randomIntBetween(int, int)}. - * + + /** + * An alias for {@link #randomIntBetween(int, int)}. + * * @see #scaledRandomIntBetween(int, int) */ public static int between(int min, int max) { - return randomIntBetween(min, max); + return randomIntBetween(min, max); } - + /** * The exact opposite of {@link #rarely()}. */ public static boolean frequently() { - return !rarely(); + return !rarely(); } - + public static boolean randomBoolean() { return random().nextBoolean(); } - - public static byte randomByte() { return (byte) random().nextInt(); } - public static short randomShort() { return (short) random().nextInt(); } - public static int randomInt() { return random().nextInt(); } - public static float randomFloat() { return random().nextFloat(); } - public static double randomDouble() { return random().nextDouble(); } - public static long randomLong() { return random().nextLong(); } + + public static byte randomByte() { + return (byte) random().nextInt(); + } + + public static short randomShort() { + return (short) random().nextInt(); + } + + public static int randomInt() { + return random().nextInt(); + } + + public static float randomFloat() { + return random().nextFloat(); + } + + public static double randomDouble() { + return random().nextDouble(); + } + + public static long randomLong() { + return random().nextLong(); + } /** A random integer from 0..max (inclusive). */ public static int randomInt(int max) { return RandomizedTest.randomInt(max); } - + /** Pick a random object from the given array. The array must not be empty. */ public static T randomFrom(T... array) { - return RandomPicks.randomFrom(random(), array); + return RandomPicks.randomFrom(random(), array); } /** Pick a random object from the given list. */ public static T randomFrom(List list) { - return RandomPicks.randomFrom(random(), list); + return RandomPicks.randomFrom(random(), list); } - + public static String randomAsciiOfLengthBetween(int minCodeUnits, int maxCodeUnits) { - return RandomizedTest.randomAsciiOfLengthBetween(minCodeUnits, maxCodeUnits); + return RandomizedTest.randomAsciiOfLengthBetween(minCodeUnits, maxCodeUnits); } - + public static String randomAsciiOfLength(int codeUnits) { - return RandomizedTest.randomAsciiOfLength(codeUnits); + return RandomizedTest.randomAsciiOfLength(codeUnits); } - + public static String randomUnicodeOfLengthBetween(int minCodeUnits, int maxCodeUnits) { - return RandomizedTest.randomUnicodeOfLengthBetween(minCodeUnits, maxCodeUnits); + return RandomizedTest.randomUnicodeOfLengthBetween(minCodeUnits, maxCodeUnits); } - + public static String randomUnicodeOfLength(int codeUnits) { - return RandomizedTest.randomUnicodeOfLength(codeUnits); + return RandomizedTest.randomUnicodeOfLength(codeUnits); } public static String randomUnicodeOfCodepointLengthBetween(int minCodePoints, int maxCodePoints) { - return RandomizedTest.randomUnicodeOfCodepointLengthBetween(minCodePoints, maxCodePoints); + return RandomizedTest.randomUnicodeOfCodepointLengthBetween(minCodePoints, maxCodePoints); } - + public static String randomUnicodeOfCodepointLength(int codePoints) { - return RandomizedTest.randomUnicodeOfCodepointLength(codePoints); + return RandomizedTest.randomUnicodeOfCodepointLength(codePoints); } public static String randomRealisticUnicodeOfLengthBetween(int minCodeUnits, int maxCodeUnits) { - return RandomizedTest.randomRealisticUnicodeOfLengthBetween(minCodeUnits, maxCodeUnits); + return RandomizedTest.randomRealisticUnicodeOfLengthBetween(minCodeUnits, maxCodeUnits); } - + public static String randomRealisticUnicodeOfLength(int codeUnits) { - return RandomizedTest.randomRealisticUnicodeOfLength(codeUnits); + return RandomizedTest.randomRealisticUnicodeOfLength(codeUnits); } public static String randomRealisticUnicodeOfCodepointLengthBetween(int minCodePoints, int maxCodePoints) { - return RandomizedTest.randomRealisticUnicodeOfCodepointLengthBetween(minCodePoints, maxCodePoints); + return RandomizedTest.randomRealisticUnicodeOfCodepointLengthBetween(minCodePoints, maxCodePoints); } - + public static String randomRealisticUnicodeOfCodepointLength(int codePoints) { - return RandomizedTest.randomRealisticUnicodeOfCodepointLength(codePoints); + return RandomizedTest.randomRealisticUnicodeOfCodepointLength(codePoints); } - + public static String[] generateRandomStringArray(int maxArraySize, int maxStringSize, boolean allowNull) { if (allowNull && random().nextBoolean()) { return null; @@ -425,7 +460,7 @@ public abstract class ElasticsearchTestCase extends LuceneTestCase { throw e; } } - + public static boolean awaitBusy(Predicate breakPredicate) throws InterruptedException { return awaitBusy(breakPredicate, 10, TimeUnit.SECONDS); } @@ -497,9 +532,9 @@ public abstract class ElasticsearchTestCase extends LuceneTestCase { public NodeEnvironment newNodeEnvironment(Settings settings) throws IOException { Settings build = ImmutableSettings.builder() - .put(settings) - .put("path.home", createTempDir().toAbsolutePath()) - .putArray("path.data", tmpPaths()).build(); + .put(settings) + .put("path.home", createTempDir().toAbsolutePath()) + .putArray("path.data", tmpPaths()).build(); return new NodeEnvironment(build, new Environment(build)); } @@ -524,7 +559,7 @@ public abstract class ElasticsearchTestCase extends LuceneTestCase { private ElasticsearchUncaughtExceptionHandler(Thread.UncaughtExceptionHandler parent) { this.parent = parent; } - + @Override public void uncaughtException(Thread t, Throwable e) { if (e instanceof EsRejectedExecutionException) { @@ -552,8 +587,9 @@ public abstract class ElasticsearchTestCase extends LuceneTestCase { int cnt = 1; final Formatter f = new Formatter(message, Locale.ENGLISH); for (Map.Entry e : threads.entrySet()) { - if (e.getKey().isAlive()) + if (e.getKey().isAlive()) { f.format(Locale.ENGLISH, "\n %2d) %s", cnt++, threadName(e.getKey())).flush(); + } if (e.getValue().length == 0) { message.append("\n at (empty stack)"); } else { diff --git a/src/test/java/org/elasticsearch/test/rest/ElasticsearchRestTestCase.java b/src/test/java/org/elasticsearch/test/rest/ElasticsearchRestTestCase.java index 5e1d5084e41..78a29610d33 100644 --- a/src/test/java/org/elasticsearch/test/rest/ElasticsearchRestTestCase.java +++ b/src/test/java/org/elasticsearch/test/rest/ElasticsearchRestTestCase.java @@ -33,6 +33,7 @@ import org.elasticsearch.common.Strings; import org.elasticsearch.common.io.PathUtils; import org.elasticsearch.common.settings.ImmutableSettings; import org.elasticsearch.common.settings.Settings; +import org.elasticsearch.common.xcontent.XContentHelper; import org.elasticsearch.node.Node; import org.elasticsearch.test.ElasticsearchIntegrationTest; import org.elasticsearch.test.ElasticsearchIntegrationTest.ClusterScope; @@ -123,6 +124,12 @@ public abstract class ElasticsearchRestTestCase extends ElasticsearchIntegration } } + @Override + protected void afterIfFailed(List errors) { + logger.info("Stash dump on failure [{}]", XContentHelper.toString(restTestExecutionContext.stash())); + super.afterIfFailed(errors); + } + @Override protected Settings nodeSettings(int nodeOrdinal) { return ImmutableSettings.builder() From 15d58d91f1abb75764428fdb5e436edbe0f4181d Mon Sep 17 00:00:00 2001 From: Simon Willnauer Date: Fri, 24 Apr 2015 09:36:10 +0200 Subject: [PATCH 05/14] [REST] Render REST errors in a structural way This commit adds support for structural errors / failures / exceptions on the elasticsearch REST layer. Exceptions are rendering with at least a `type` and a `reason` corresponding to the exception name and the message. Some expcetions like the ones associated with an index or a shard will have additional information about the index the exception was triggered on or the shard respectivly. Each rendered response will also contain a list of root causes which is a list of distinct shard level errors returned for the request. Root causes are the lowest level elasticsearch exception found per shard response and are intended to be displayed to the user to indicate the soruce of the exception. Shard level response are by-default grouped by their type and reason to reduce the amount of duplicates retunred. Yet, the same exception retunred from different indices will not be grouped. Closes #3303 --- rest-api-spec/test/create/50_parent.yaml | 2 +- rest-api-spec/test/create/75_ttl.yaml | 2 +- .../test/delete/42_missing_parent.yml | 2 +- rest-api-spec/test/index/50_parent.yaml | 2 +- rest-api-spec/test/index/75_ttl.yaml | 2 +- .../test/mget/13_missing_metadata.yaml | 8 +- rest-api-spec/test/mget/15_ids.yaml | 4 +- rest-api-spec/test/mpercolate/10_basic.yaml | 2 +- rest-api-spec/test/msearch/10_basic.yaml | 2 +- rest-api-spec/test/script/10_basic.yaml | 4 +- rest-api-spec/test/template/10_basic.yaml | 2 +- rest-api-spec/test/template/20_search.yaml | 2 +- rest-api-spec/test/update/50_parent.yaml | 2 +- rest-api-spec/test/update/75_ttl.yaml | 2 +- .../elasticsearch/ElasticsearchException.java | 136 ++++++++--- .../org/elasticsearch/ExceptionsHelper.java | 8 +- .../action/ActionWriteResponse.java | 20 +- .../action/bulk/BulkItemResponse.java | 2 +- .../action/bulk/TransportShardBulkAction.java | 8 +- .../search/SearchPhaseExecutionException.java | 101 ++++++++- .../action/search/ShardSearchFailure.java | 36 ++- .../DefaultShardOperationFailedException.java | 22 +- ...nsportIndexReplicationOperationAction.java | 10 +- ...nsportShardReplicationOperationAction.java | 5 +- .../common/io/stream/BytesStreamOutput.java | 5 - .../common/io/stream/StreamInput.java | 11 + .../common/io/stream/StreamOutput.java | 11 +- .../elasticsearch/index/IndexException.java | 24 +- .../index/percolator/PercolatorException.java | 4 - .../index/query/QueryParsingException.java | 1 + .../index/shard/IndexShardException.java | 18 +- .../indices/AliasFilterParsingException.java | 4 - .../indices/IndexMissingException.java | 2 +- .../indices/TypeMissingException.java | 5 - .../elasticsearch/rest/BytesRestResponse.java | 25 ++- .../search/SearchContextException.java | 15 +- .../search/SearchParseException.java | 4 +- .../ElasticsearchExceptionTests.java | 212 ++++++++++++++++++ .../BulkProcessorClusterSettingsTests.java | 2 +- .../cluster/metadata/MetaDataTests.java | 3 +- .../deleteByQuery/DeleteByQueryTests.java | 2 +- .../org/elasticsearch/document/BulkTests.java | 8 +- .../query/SimpleIndexQueryParserTests.java | 4 +- .../breaker/CircuitBreakerServiceTests.java | 12 +- .../template/SimpleIndexTemplateTests.java | 4 +- .../nested/SimpleNestedTests.java | 2 +- .../rest/BytesRestResponseTests.java | 64 +++++- .../script/GroovySandboxScriptTests.java | 3 +- .../script/GroovyScriptTests.java | 24 +- .../script/IndexLookupTests.java | 4 +- .../script/IndexedScriptTests.java | 6 +- .../script/OnDiskScriptTests.java | 8 +- .../script/SandboxDisabledTests.java | 2 +- .../expression/ExpressionScriptTests.java | 58 ++--- .../AggregationsIntegrationTests.java | 2 +- .../bucket/DateHistogramTests.java | 2 +- .../aggregations/bucket/HistogramTests.java | 2 +- .../aggregations/bucket/NestedTests.java | 2 +- .../aggregations/bucket/TopHitsTests.java | 4 +- .../child/SimpleChildQuerySearchTests.java | 25 +-- .../DecayFunctionScoreTests.java | 16 +- .../search/query/SearchQueryTests.java | 8 +- .../search/simple/SimpleSearchTests.java | 2 +- .../search/sort/SimpleSortTests.java | 2 +- .../suggest/CompletionSuggestSearchTests.java | 12 +- .../hamcrest/ElasticsearchAssertions.java | 2 +- 66 files changed, 737 insertions(+), 275 deletions(-) diff --git a/rest-api-spec/test/create/50_parent.yaml b/rest-api-spec/test/create/50_parent.yaml index dcd24d99346..6fe64b7bbed 100644 --- a/rest-api-spec/test/create/50_parent.yaml +++ b/rest-api-spec/test/create/50_parent.yaml @@ -14,7 +14,7 @@ wait_for_status: yellow - do: - catch: /RoutingMissingException/ + catch: /routing_missing_exception/ create: index: test_1 type: test diff --git a/rest-api-spec/test/create/75_ttl.yaml b/rest-api-spec/test/create/75_ttl.yaml index 099ed279020..3354e3b0517 100644 --- a/rest-api-spec/test/create/75_ttl.yaml +++ b/rest-api-spec/test/create/75_ttl.yaml @@ -89,7 +89,7 @@ type: test id: 1 - do: - catch: /AlreadyExpiredException/ + catch: /already_expired_exception/ create: index: test_1 type: test diff --git a/rest-api-spec/test/delete/42_missing_parent.yml b/rest-api-spec/test/delete/42_missing_parent.yml index 8247f8885e9..d72c5a83d59 100644 --- a/rest-api-spec/test/delete/42_missing_parent.yml +++ b/rest-api-spec/test/delete/42_missing_parent.yml @@ -21,7 +21,7 @@ body: { foo: bar } - do: - catch: /RoutingMissingException/ + catch: /routing_missing_exception/ delete: index: test_1 type: test diff --git a/rest-api-spec/test/index/50_parent.yaml b/rest-api-spec/test/index/50_parent.yaml index 551d30d95d7..28ab61cb49b 100644 --- a/rest-api-spec/test/index/50_parent.yaml +++ b/rest-api-spec/test/index/50_parent.yaml @@ -13,7 +13,7 @@ wait_for_status: yellow - do: - catch: /RoutingMissingException/ + catch: /routing_missing_exception/ index: index: test_1 type: test diff --git a/rest-api-spec/test/index/75_ttl.yaml b/rest-api-spec/test/index/75_ttl.yaml index 1d73d4ed40f..554933654fb 100644 --- a/rest-api-spec/test/index/75_ttl.yaml +++ b/rest-api-spec/test/index/75_ttl.yaml @@ -74,7 +74,7 @@ # with timestamp - do: - catch: /AlreadyExpiredException/ + catch: /already_expired_exception/ index: index: test_1 type: test diff --git a/rest-api-spec/test/mget/13_missing_metadata.yaml b/rest-api-spec/test/mget/13_missing_metadata.yaml index 11b4a129406..8d986a330bf 100644 --- a/rest-api-spec/test/mget/13_missing_metadata.yaml +++ b/rest-api-spec/test/mget/13_missing_metadata.yaml @@ -13,27 +13,27 @@ wait_for_status: yellow - do: - catch: /ActionRequestValidationException.+ id is missing/ + catch: /action_request_validation_exception.+ id is missing/ mget: body: docs: - { _index: test_1, _type: test} - do: - catch: /ActionRequestValidationException.+ index is missing/ + catch: /action_request_validation_exception.+ index is missing/ mget: body: docs: - { _type: test, _id: 1} - do: - catch: /ActionRequestValidationException.+ no documents to get/ + catch: /action_request_validation_exception.+ no documents to get/ mget: body: docs: [] - do: - catch: /ActionRequestValidationException.+ no documents to get/ + catch: /action_request_validation_exception.+ no documents to get/ mget: body: {} diff --git a/rest-api-spec/test/mget/15_ids.yaml b/rest-api-spec/test/mget/15_ids.yaml index a86fc2cdc6e..cdd6c5724fe 100644 --- a/rest-api-spec/test/mget/15_ids.yaml +++ b/rest-api-spec/test/mget/15_ids.yaml @@ -59,14 +59,14 @@ - do: - catch: /ActionRequestValidationException.+ no documents to get/ + catch: /action_request_validation_exception.+ no documents to get/ mget: index: test_1 body: ids: [] - do: - catch: /ActionRequestValidationException.+ no documents to get/ + catch: /action_request_validation_exception.+ no documents to get/ mget: index: test_1 body: {} diff --git a/rest-api-spec/test/mpercolate/10_basic.yaml b/rest-api-spec/test/mpercolate/10_basic.yaml index 70118c93da1..9f949c21cd6 100644 --- a/rest-api-spec/test/mpercolate/10_basic.yaml +++ b/rest-api-spec/test/mpercolate/10_basic.yaml @@ -37,5 +37,5 @@ foo: bar - match: { responses.0.total: 1 } - - match: { responses.1.error: "IndexMissingException[[percolator_index1] missing]" } + - match: { responses.1.error: "/IndexMissingException.no.such.index./" } - match: { responses.2.total: 1 } diff --git a/rest-api-spec/test/msearch/10_basic.yaml b/rest-api-spec/test/msearch/10_basic.yaml index c0786229926..a028853429e 100644 --- a/rest-api-spec/test/msearch/10_basic.yaml +++ b/rest-api-spec/test/msearch/10_basic.yaml @@ -39,7 +39,7 @@ match: {foo: bar} - match: { responses.0.hits.total: 3 } - - match: { responses.1.error: "IndexMissingException[[test_2] missing]" } + - match: { responses.1.error: "/IndexMissingException.no.such.index./" } - match: { responses.2.hits.total: 1 } diff --git a/rest-api-spec/test/script/10_basic.yaml b/rest-api-spec/test/script/10_basic.yaml index 822d8879771..ee977429b59 100644 --- a/rest-api-spec/test/script/10_basic.yaml +++ b/rest-api-spec/test/script/10_basic.yaml @@ -60,7 +60,7 @@ - do: - catch: /ElasticsearchIllegalArgumentException.Unable.to.parse.*/ + catch: /Unable.to.parse.*/ put_script: id: "1" lang: "groovy" @@ -74,7 +74,7 @@ body: { "script" : "_score * doc[\"myParent.weight\"].value" } - do: - catch: /ElasticsearchIllegalArgumentException.script_lang.not.supported/ + catch: /script_lang.not.supported/ put_script: id: "1" lang: "foobar" diff --git a/rest-api-spec/test/template/10_basic.yaml b/rest-api-spec/test/template/10_basic.yaml index 838a21d5a56..bd1fd436648 100644 --- a/rest-api-spec/test/template/10_basic.yaml +++ b/rest-api-spec/test/template/10_basic.yaml @@ -50,7 +50,7 @@ body: { "template": { "query": { "match{{}}_all": {}}, "size": "{{my_size}}" } } - do: - catch: /ElasticsearchIllegalArgumentException\SUnable\sto\sparse.*/ + catch: /Unable\sto\sparse.*/ put_template: id: "1" body: { "template": { "query": { "match{{}}_all": {}}, "size": "{{my_size}}" } } diff --git a/rest-api-spec/test/template/20_search.yaml b/rest-api-spec/test/template/20_search.yaml index 55f886c6412..d8e7364d545 100644 --- a/rest-api-spec/test/template/20_search.yaml +++ b/rest-api-spec/test/template/20_search.yaml @@ -37,7 +37,7 @@ - match: { hits.total: 1 } - do: - catch: /ElasticsearchIllegalArgumentException.Unable.to.find.on.disk.script.simple1/ + catch: /Unable.to.find.on.disk.script.simple1/ search_template: body: { "template" : "simple1" } diff --git a/rest-api-spec/test/update/50_parent.yaml b/rest-api-spec/test/update/50_parent.yaml index 3d15ea9f2a8..bc64665e919 100644 --- a/rest-api-spec/test/update/50_parent.yaml +++ b/rest-api-spec/test/update/50_parent.yaml @@ -15,7 +15,7 @@ setup: "Parent": - do: - catch: /RoutingMissingException/ + catch: /routing_missing_exception/ update: index: test_1 type: test diff --git a/rest-api-spec/test/update/75_ttl.yaml b/rest-api-spec/test/update/75_ttl.yaml index f6b05b9eca2..8072c4d400f 100644 --- a/rest-api-spec/test/update/75_ttl.yaml +++ b/rest-api-spec/test/update/75_ttl.yaml @@ -81,7 +81,7 @@ # with timestamp - do: - catch: /AlreadyExpiredException/ + catch: /already_expired_exception/ index: index: test_1 type: test diff --git a/src/main/java/org/elasticsearch/ElasticsearchException.java b/src/main/java/org/elasticsearch/ElasticsearchException.java index fd7c9186875..eed4040793c 100644 --- a/src/main/java/org/elasticsearch/ElasticsearchException.java +++ b/src/main/java/org/elasticsearch/ElasticsearchException.java @@ -22,18 +22,23 @@ package org.elasticsearch; import com.google.common.collect.ImmutableMap; import com.google.common.collect.Lists; import com.google.common.collect.Maps; -import org.elasticsearch.common.Nullable; +import org.elasticsearch.common.Strings; import org.elasticsearch.common.collect.Tuple; +import org.elasticsearch.common.xcontent.ToXContent; +import org.elasticsearch.common.xcontent.XContentBuilder; import org.elasticsearch.rest.HasRestHeaders; import org.elasticsearch.rest.RestStatus; +import java.io.IOException; import java.util.List; import java.util.Map; /** * A base class for all elasticsearch exceptions. */ -public class ElasticsearchException extends RuntimeException { +public class ElasticsearchException extends RuntimeException implements ToXContent { + + public static final String REST_EXCEPTION_SKIP_CAUSE = "rest.exception.skip_cause"; /** * Construct a ElasticsearchException with the specified detail message. @@ -62,12 +67,8 @@ public class ElasticsearchException extends RuntimeException { Throwable cause = unwrapCause(); if (cause == this) { return RestStatus.INTERNAL_SERVER_ERROR; - } else if (cause instanceof ElasticsearchException) { - return ((ElasticsearchException) cause).status(); - } else if (cause instanceof IllegalArgumentException) { - return RestStatus.BAD_REQUEST; } else { - return RestStatus.INTERNAL_SERVER_ERROR; + return ExceptionsHelper.status(cause); } } @@ -114,19 +115,6 @@ public class ElasticsearchException extends RuntimeException { return rootCause; } - /** - * Retrieve the most specific cause of this exception, that is, - * either the innermost cause (root cause) or this exception itself. - *

Differs from {@link #getRootCause()} in that it falls back - * to the present exception if there is no root cause. - * - * @return the most specific cause (never null) - */ - public Throwable getMostSpecificCause() { - Throwable rootCause = getRootCause(); - return (rootCause != null ? rootCause : this); - } - /** * Check whether this exception contains an exception of the given type: * either it is of the given class itself or it contains a nested cause @@ -175,21 +163,6 @@ public class ElasticsearchException extends RuntimeException { this.headers = headers(headers); } - public WithRestHeaders(String msg, @Nullable ImmutableMap> headers) { - super(msg); - this.headers = headers != null ? headers : ImmutableMap.>of(); - } - - public WithRestHeaders(String msg, Throwable cause, Tuple... headers) { - super(msg, cause); - this.headers = headers(headers); - } - - public WithRestHeaders(String msg, Throwable cause, @Nullable ImmutableMap> headers) { - super(msg, cause); - this.headers = headers != null ? headers : ImmutableMap.>of(); - } - @Override public ImmutableMap> getHeaders() { return headers; @@ -215,4 +188,97 @@ public class ElasticsearchException extends RuntimeException { return ImmutableMap.copyOf(map); } } + + @Override + public XContentBuilder toXContent(XContentBuilder builder, Params params) throws IOException { + if (this instanceof ElasticsearchWrapperException) { + toXContent(builder, params, this); + } else { + builder.field("type", getExceptionName(this)); + builder.field("reason", getMessage()); + innerToXContent(builder, params); + } + return builder; + } + + /** + * Renders additional per exception information into the xcontent + */ + protected void innerToXContent(XContentBuilder builder, Params params) throws IOException { + causeToXContent(builder, params); + } + + /** + * Renders a cause exception as xcontent + */ + protected final void causeToXContent(XContentBuilder builder, Params params) throws IOException { + final Throwable cause = getCause(); + if (cause != null && params.paramAsBoolean(REST_EXCEPTION_SKIP_CAUSE, false) == false) { + builder.field("caused_by"); + builder.startObject(); + toXContent(builder, params, cause); + builder.endObject(); + } + } + + /** + * Statis toXContent helper method that also renders non {@link org.elasticsearch.ElasticsearchException} instances as XContent. + */ + public static void toXContent(XContentBuilder builder, Params params, Throwable ex) throws IOException { + ex = ExceptionsHelper.unwrapCause(ex); + if (ex instanceof ElasticsearchException) { + ((ElasticsearchException) ex).toXContent(builder, params); + } else { + builder.field("type", getExceptionName(ex)); + builder.field("reason", ex.getMessage()); + if (ex.getCause() != null) { + builder.field("caused_by"); + builder.startObject(); + toXContent(builder, params, ex.getCause()); + builder.endObject(); + } + } + } + + /** + * Returns the root cause of this exception or mupltiple if different shards caused different exceptions + */ + public ElasticsearchException[] guessRootCauses() { + final Throwable cause = getCause(); + if (cause != null && cause instanceof ElasticsearchException) { + return ((ElasticsearchException) cause).guessRootCauses(); + } + return new ElasticsearchException[] {this}; + } + + /** + * Returns the root cause of this exception or mupltiple if different shards caused different exceptions. + * If the given exception is not an instance of {@link org.elasticsearch.ElasticsearchException} an empty array + * is returned. + */ + public static ElasticsearchException[] guessRootCauses(Throwable t) { + Throwable ex = ExceptionsHelper.unwrapCause(t); + if (ex instanceof ElasticsearchException) { + return ((ElasticsearchException) ex).guessRootCauses(); + } + return new ElasticsearchException[0]; + } + + /** + * Returns a underscore case name for the given exception. This method strips Elasticsearch prefixes from exception names. + */ + public static String getExceptionName(Throwable ex) { + String simpleName = ex.getClass().getSimpleName(); + if (simpleName.startsWith("Elasticsearch")) { + simpleName = simpleName.substring("Elasticsearch".length()); + } + return Strings.toUnderscoreCase(simpleName); + } + + @Override + public String toString() { + return ExceptionsHelper.detailedMessage(this).trim(); + } + + } diff --git a/src/main/java/org/elasticsearch/ExceptionsHelper.java b/src/main/java/org/elasticsearch/ExceptionsHelper.java index 552d339301e..9c29a4dc0aa 100644 --- a/src/main/java/org/elasticsearch/ExceptionsHelper.java +++ b/src/main/java/org/elasticsearch/ExceptionsHelper.java @@ -54,8 +54,12 @@ public final class ExceptionsHelper { } public static RestStatus status(Throwable t) { - if (t instanceof ElasticsearchException) { - return ((ElasticsearchException) t).status(); + if (t != null) { + if (t instanceof ElasticsearchException) { + return ((ElasticsearchException) t).status(); + } else if (t instanceof IllegalArgumentException) { + return RestStatus.BAD_REQUEST; + } } return RestStatus.INTERNAL_SERVER_ERROR; } diff --git a/src/main/java/org/elasticsearch/action/ActionWriteResponse.java b/src/main/java/org/elasticsearch/action/ActionWriteResponse.java index 63b1f06a9f9..5ddefaf99b2 100644 --- a/src/main/java/org/elasticsearch/action/ActionWriteResponse.java +++ b/src/main/java/org/elasticsearch/action/ActionWriteResponse.java @@ -19,6 +19,9 @@ package org.elasticsearch.action; +import org.elasticsearch.ElasticsearchException; +import org.elasticsearch.ExceptionsHelper; +import org.elasticsearch.bootstrap.Elasticsearch; import org.elasticsearch.common.Nullable; import org.elasticsearch.common.io.stream.StreamInput; import org.elasticsearch.common.io.stream.StreamOutput; @@ -164,15 +167,15 @@ public abstract class ActionWriteResponse extends ActionResponse { private String index; private int shardId; private String nodeId; - private String reason; + private Throwable cause; private RestStatus status; private boolean primary; - public Failure(String index, int shardId, @Nullable String nodeId, String reason, RestStatus status, boolean primary) { + public Failure(String index, int shardId, @Nullable String nodeId, Throwable cause, RestStatus status, boolean primary) { this.index = index; this.shardId = shardId; this.nodeId = nodeId; - this.reason = reason; + this.cause = cause; this.status = status; this.primary = primary; } @@ -209,7 +212,7 @@ public abstract class ActionWriteResponse extends ActionResponse { */ @Override public String reason() { - return reason; + return ExceptionsHelper.detailedMessage(cause); } /** @@ -233,7 +236,7 @@ public abstract class ActionWriteResponse extends ActionResponse { index = in.readString(); shardId = in.readVInt(); nodeId = in.readOptionalString(); - reason = in.readString(); + cause = in.readThrowable(); status = RestStatus.readFrom(in); primary = in.readBoolean(); } @@ -243,7 +246,7 @@ public abstract class ActionWriteResponse extends ActionResponse { out.writeString(index); out.writeVInt(shardId); out.writeOptionalString(nodeId); - out.writeString(reason); + out.writeThrowable(cause); RestStatus.writeTo(out, status); out.writeBoolean(primary); } @@ -254,7 +257,10 @@ public abstract class ActionWriteResponse extends ActionResponse { builder.field(Fields._INDEX, index); builder.field(Fields._SHARD, shardId); builder.field(Fields._NODE, nodeId); - builder.field(Fields.REASON, reason); + builder.field(Fields.REASON); + builder.startObject(); + ElasticsearchException.toXContent(builder, params, cause); + builder.endObject(); builder.field(Fields.STATUS, status); builder.field(Fields.PRIMARY, primary); builder.endObject(); diff --git a/src/main/java/org/elasticsearch/action/bulk/BulkItemResponse.java b/src/main/java/org/elasticsearch/action/bulk/BulkItemResponse.java index 3ffa1ddcb62..c32f02f0022 100644 --- a/src/main/java/org/elasticsearch/action/bulk/BulkItemResponse.java +++ b/src/main/java/org/elasticsearch/action/bulk/BulkItemResponse.java @@ -51,7 +51,7 @@ public class BulkItemResponse implements Streamable { this.index = index; this.type = type; this.id = id; - this.message = ExceptionsHelper.detailedMessage(t); + this.message = t.toString(); this.status = ExceptionsHelper.status(t); } diff --git a/src/main/java/org/elasticsearch/action/bulk/TransportShardBulkAction.java b/src/main/java/org/elasticsearch/action/bulk/TransportShardBulkAction.java index 9e354e82836..4a29cfae58a 100644 --- a/src/main/java/org/elasticsearch/action/bulk/TransportShardBulkAction.java +++ b/src/main/java/org/elasticsearch/action/bulk/TransportShardBulkAction.java @@ -157,7 +157,7 @@ public class TransportShardBulkAction extends TransportShardReplicationOperation } throw (ElasticsearchException) e; } - if (e instanceof ElasticsearchException && ((ElasticsearchException) e).status() == RestStatus.CONFLICT) { + if (ExceptionsHelper.status(e) == RestStatus.CONFLICT) { logger.trace("{} failed to execute bulk item (index) {}", e, shardRequest.shardId, indexRequest); } else { logger.debug("{} failed to execute bulk item (index) {}", e, shardRequest.shardId, indexRequest); @@ -190,7 +190,7 @@ public class TransportShardBulkAction extends TransportShardReplicationOperation } throw (ElasticsearchException) e; } - if (e instanceof ElasticsearchException && ((ElasticsearchException) e).status() == RestStatus.CONFLICT) { + if (ExceptionsHelper.status(e) == RestStatus.CONFLICT) { logger.trace("{} failed to execute bulk item (delete) {}", e, shardRequest.shardId, deleteRequest); } else { logger.debug("{} failed to execute bulk item (delete) {}", e, shardRequest.shardId, deleteRequest); @@ -279,7 +279,7 @@ public class TransportShardBulkAction extends TransportShardReplicationOperation case UPSERT: case INDEX: IndexRequest indexRequest = updateResult.request(); - if (t instanceof ElasticsearchException && ((ElasticsearchException) t).status() == RestStatus.CONFLICT) { + if (ExceptionsHelper.status(t) == RestStatus.CONFLICT) { logger.trace("{} failed to execute bulk item (index) {}", t, shardRequest.shardId, indexRequest); } else { logger.debug("{} failed to execute bulk item (index) {}", t, shardRequest.shardId, indexRequest); @@ -289,7 +289,7 @@ public class TransportShardBulkAction extends TransportShardReplicationOperation break; case DELETE: DeleteRequest deleteRequest = updateResult.request(); - if (t instanceof ElasticsearchException && ((ElasticsearchException) t).status() == RestStatus.CONFLICT) { + if (ExceptionsHelper.status(t) == RestStatus.CONFLICT) { logger.trace("{} failed to execute bulk item (delete) {}", t, shardRequest.shardId, deleteRequest); } else { logger.debug("{} failed to execute bulk item (delete) {}", t, shardRequest.shardId, deleteRequest); diff --git a/src/main/java/org/elasticsearch/action/search/SearchPhaseExecutionException.java b/src/main/java/org/elasticsearch/action/search/SearchPhaseExecutionException.java index 9e3de989bbf..d0202ba219d 100644 --- a/src/main/java/org/elasticsearch/action/search/SearchPhaseExecutionException.java +++ b/src/main/java/org/elasticsearch/action/search/SearchPhaseExecutionException.java @@ -20,25 +20,30 @@ package org.elasticsearch.action.search; import org.elasticsearch.ElasticsearchException; +import org.elasticsearch.common.xcontent.XContentBuilder; +import org.elasticsearch.index.Index; +import org.elasticsearch.index.IndexException; import org.elasticsearch.rest.RestStatus; +import java.io.IOException; +import java.util.*; + /** * */ public class SearchPhaseExecutionException extends ElasticsearchException { - private final String phaseName; private ShardSearchFailure[] shardFailures; public SearchPhaseExecutionException(String phaseName, String msg, ShardSearchFailure[] shardFailures) { - super(buildMessage(phaseName, msg, shardFailures)); + super(msg); this.phaseName = phaseName; this.shardFailures = shardFailures; } public SearchPhaseExecutionException(String phaseName, String msg, Throwable cause, ShardSearchFailure[] shardFailures) { - super(buildMessage(phaseName, msg, shardFailures), cause); + super(msg, cause); this.phaseName = phaseName; this.shardFailures = shardFailures; } @@ -60,10 +65,6 @@ public class SearchPhaseExecutionException extends ElasticsearchException { return status; } - public String phaseName() { - return phaseName; - } - public ShardSearchFailure[] shardFailures() { return shardFailures; } @@ -83,4 +84,90 @@ public class SearchPhaseExecutionException extends ElasticsearchException { } return sb.toString(); } + + @Override + protected void innerToXContent(XContentBuilder builder, Params params) throws IOException { + builder.field("phase", phaseName); + final boolean group = params.paramAsBoolean("group_shard_failures", true); // we group by default + builder.field("grouped", group); // notify that it's grouped + builder.field("failed_shards"); + builder.startArray(); + ShardSearchFailure[] failures = params.paramAsBoolean("group_shard_failures", true) ? groupBy(shardFailures) : shardFailures; + for (ShardSearchFailure failure : failures) { + builder.startObject(); + failure.toXContent(builder, params); + builder.endObject(); + } + builder.endArray(); + super.innerToXContent(builder, params); + + } + + private ShardSearchFailure[] groupBy(ShardSearchFailure[] failures) { + List uniqueFailures = new ArrayList<>(); + Set reasons = new HashSet<>(); + for (ShardSearchFailure failure : failures) { + GroupBy reason = new GroupBy(failure.getCause()); + if (reasons.contains(reason) == false) { + reasons.add(reason); + uniqueFailures.add(failure); + } + } + return uniqueFailures.toArray(new ShardSearchFailure[0]); + + } + + @Override + public ElasticsearchException[] guessRootCauses() { + ShardSearchFailure[] failures = groupBy(shardFailures); + List rootCauses = new ArrayList<>(failures.length); + for (ShardSearchFailure failure : failures) { + ElasticsearchException[] guessRootCauses = ElasticsearchException.guessRootCauses(failure.getCause()); + rootCauses.addAll(Arrays.asList(guessRootCauses)); + } + return rootCauses.toArray(new ElasticsearchException[0]); + } + + @Override + public String toString() { + return buildMessage(phaseName, getMessage(), shardFailures); + } + + static class GroupBy { + final String reason; + final Index index; + final Class causeType; + + public GroupBy(Throwable t) { + if (t instanceof IndexException) { + index = ((IndexException) t).index(); + } else { + index = null; + } + reason = t.getMessage(); + causeType = t.getClass(); + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + + GroupBy groupBy = (GroupBy) o; + + if (!causeType.equals(groupBy.causeType)) return false; + if (index != null ? !index.equals(groupBy.index) : groupBy.index != null) return false; + if (reason != null ? !reason.equals(groupBy.reason) : groupBy.reason != null) return false; + + return true; + } + + @Override + public int hashCode() { + int result = reason != null ? reason.hashCode() : 0; + result = 31 * result + (index != null ? index.hashCode() : 0); + result = 31 * result + causeType.hashCode(); + return result; + } + } } diff --git a/src/main/java/org/elasticsearch/action/search/ShardSearchFailure.java b/src/main/java/org/elasticsearch/action/search/ShardSearchFailure.java index 38bf5693c08..4a6e073e288 100644 --- a/src/main/java/org/elasticsearch/action/search/ShardSearchFailure.java +++ b/src/main/java/org/elasticsearch/action/search/ShardSearchFailure.java @@ -25,24 +25,29 @@ import org.elasticsearch.action.ShardOperationFailedException; import org.elasticsearch.common.Nullable; import org.elasticsearch.common.io.stream.StreamInput; import org.elasticsearch.common.io.stream.StreamOutput; +import org.elasticsearch.common.xcontent.ToXContent; +import org.elasticsearch.common.xcontent.XContentBuilder; import org.elasticsearch.rest.RestStatus; import org.elasticsearch.search.SearchException; import org.elasticsearch.search.SearchShardTarget; import java.io.IOException; +import java.io.ObjectInputStream; +import java.io.ObjectOutputStream; import static org.elasticsearch.search.SearchShardTarget.readSearchShardTarget; /** * Represents a failure to search on a specific shard. */ -public class ShardSearchFailure implements ShardOperationFailedException { +public class ShardSearchFailure implements ShardOperationFailedException, ToXContent { public static final ShardSearchFailure[] EMPTY_ARRAY = new ShardSearchFailure[0]; private SearchShardTarget shardTarget; private String reason; private RestStatus status; + private Throwable cause; private ShardSearchFailure() { @@ -59,12 +64,9 @@ public class ShardSearchFailure implements ShardOperationFailedException { } else if (shardTarget != null) { this.shardTarget = shardTarget; } - if (actual != null && actual instanceof ElasticsearchException) { - status = ((ElasticsearchException) actual).status(); - } else { - status = RestStatus.INTERNAL_SERVER_ERROR; - } + status = ExceptionsHelper.status(actual); this.reason = ExceptionsHelper.detailedMessage(t); + this.cause = actual; } public ShardSearchFailure(String reason, SearchShardTarget shardTarget) { @@ -138,6 +140,7 @@ public class ShardSearchFailure implements ShardOperationFailedException { } reason = in.readString(); status = RestStatus.readFrom(in); + cause = in.readThrowable(); } @Override @@ -150,5 +153,26 @@ public class ShardSearchFailure implements ShardOperationFailedException { } out.writeString(reason); RestStatus.writeTo(out, status); + out.writeThrowable(cause); + } + + @Override + public XContentBuilder toXContent(XContentBuilder builder, Params params) throws IOException { + builder.field("shard", shardId()); + builder.field("index", index()); + if (shardTarget != null) { + builder.field("node", shardTarget.nodeId()); + } + if (cause != null) { + builder.field("reason"); + builder.startObject(); + ElasticsearchException.toXContent(builder, params, cause); + builder.endObject(); + } + return builder; + } + + public Throwable getCause() { + return cause; } } diff --git a/src/main/java/org/elasticsearch/action/support/DefaultShardOperationFailedException.java b/src/main/java/org/elasticsearch/action/support/DefaultShardOperationFailedException.java index 3a7e90096c1..3be7b7d2aee 100644 --- a/src/main/java/org/elasticsearch/action/support/DefaultShardOperationFailedException.java +++ b/src/main/java/org/elasticsearch/action/support/DefaultShardOperationFailedException.java @@ -20,6 +20,7 @@ package org.elasticsearch.action.support; import org.elasticsearch.ElasticsearchException; +import org.elasticsearch.ExceptionsHelper; import org.elasticsearch.action.ShardOperationFailedException; import org.elasticsearch.common.io.stream.StreamInput; import org.elasticsearch.common.io.stream.StreamOutput; @@ -39,30 +40,25 @@ public class DefaultShardOperationFailedException implements ShardOperationFaile private int shardId; - private String reason; + private Throwable reason; private RestStatus status; private DefaultShardOperationFailedException() { - } public DefaultShardOperationFailedException(IndexShardException e) { this.index = e.shardId().index().name(); this.shardId = e.shardId().id(); - this.reason = detailedMessage(e); + this.reason = e; this.status = e.status(); } public DefaultShardOperationFailedException(String index, int shardId, Throwable t) { this.index = index; this.shardId = shardId; - this.reason = detailedMessage(t); - if (t != null && t instanceof ElasticsearchException) { - status = ((ElasticsearchException) t).status(); - } else { - status = RestStatus.INTERNAL_SERVER_ERROR; - } + this.reason = t; + status = ExceptionsHelper.status(t); } @Override @@ -77,7 +73,7 @@ public class DefaultShardOperationFailedException implements ShardOperationFaile @Override public String reason() { - return this.reason; + return detailedMessage(reason); } @Override @@ -97,7 +93,7 @@ public class DefaultShardOperationFailedException implements ShardOperationFaile index = in.readString(); } shardId = in.readVInt(); - reason = in.readString(); + reason = in.readThrowable(); status = RestStatus.readFrom(in); } @@ -110,12 +106,12 @@ public class DefaultShardOperationFailedException implements ShardOperationFaile out.writeString(index); } out.writeVInt(shardId); - out.writeString(reason); + out.writeThrowable(reason); RestStatus.writeTo(out, status); } @Override public String toString() { - return "[" + index + "][" + shardId + "] failed, reason [" + reason + "]"; + return "[" + index + "][" + shardId + "] failed, reason [" + reason() + "]"; } } diff --git a/src/main/java/org/elasticsearch/action/support/replication/TransportIndexReplicationOperationAction.java b/src/main/java/org/elasticsearch/action/support/replication/TransportIndexReplicationOperationAction.java index 53c4984bfc8..5d0cba209d0 100644 --- a/src/main/java/org/elasticsearch/action/support/replication/TransportIndexReplicationOperationAction.java +++ b/src/main/java/org/elasticsearch/action/support/replication/TransportIndexReplicationOperationAction.java @@ -103,14 +103,8 @@ public abstract class TransportIndexReplicationOperationAction entry : shardReplicaFailures.entrySet()) { - String reason = ExceptionsHelper.detailedMessage(entry.getValue()); RestStatus restStatus = ExceptionsHelper.status(entry.getValue()); failuresArray[slot++] = new ActionWriteResponse.ShardInfo.Failure( - shardId.getIndex(), shardId.getId(), entry.getKey(), reason, restStatus, false + shardId.getIndex(), shardId.getId(), entry.getKey(), entry.getValue(), restStatus, false ); } } else { diff --git a/src/main/java/org/elasticsearch/common/io/stream/BytesStreamOutput.java b/src/main/java/org/elasticsearch/common/io/stream/BytesStreamOutput.java index 4235d38a21d..2107a9958da 100644 --- a/src/main/java/org/elasticsearch/common/io/stream/BytesStreamOutput.java +++ b/src/main/java/org/elasticsearch/common/io/stream/BytesStreamOutput.java @@ -60,11 +60,6 @@ public class BytesStreamOutput extends StreamOutput implements BytesStream { this.bytes = bigarrays.newByteArray(expectedSize); } - @Override - public boolean seekPositionSupported() { - return true; - } - @Override public long position() throws IOException { return count; diff --git a/src/main/java/org/elasticsearch/common/io/stream/StreamInput.java b/src/main/java/org/elasticsearch/common/io/stream/StreamInput.java index b05d463c58d..fea34cd94c3 100644 --- a/src/main/java/org/elasticsearch/common/io/stream/StreamInput.java +++ b/src/main/java/org/elasticsearch/common/io/stream/StreamInput.java @@ -21,6 +21,7 @@ package org.elasticsearch.common.io.stream; import org.apache.lucene.util.BytesRef; import org.apache.lucene.util.CharsRefBuilder; +import org.elasticsearch.ElasticsearchException; import org.elasticsearch.Version; import org.elasticsearch.common.Nullable; import org.elasticsearch.common.Strings; @@ -32,6 +33,7 @@ import org.joda.time.DateTime; import java.io.IOException; import java.io.InputStream; +import java.io.ObjectInputStream; import java.util.*; /** @@ -463,4 +465,13 @@ public abstract class StreamInput extends InputStream { return null; } } + + public T readThrowable() throws IOException { + try { + ObjectInputStream oin = new ObjectInputStream(this); + return (T) oin.readObject(); + } catch (ClassNotFoundException e) { + throw new IOException("failed to deserialize exception", e); + } + } } diff --git a/src/main/java/org/elasticsearch/common/io/stream/StreamOutput.java b/src/main/java/org/elasticsearch/common/io/stream/StreamOutput.java index 208b98ea8a7..754e38ceadb 100644 --- a/src/main/java/org/elasticsearch/common/io/stream/StreamOutput.java +++ b/src/main/java/org/elasticsearch/common/io/stream/StreamOutput.java @@ -28,6 +28,7 @@ import org.elasticsearch.common.text.Text; import org.joda.time.ReadableInstant; import java.io.IOException; +import java.io.ObjectOutputStream; import java.io.OutputStream; import java.util.Date; import java.util.LinkedHashMap; @@ -50,10 +51,6 @@ public abstract class StreamOutput extends OutputStream { return this; } - public boolean seekPositionSupported() { - return false; - } - public long position() throws IOException { throw new UnsupportedOperationException(); } @@ -432,4 +429,10 @@ public abstract class StreamOutput extends OutputStream { writeBoolean(false); } } + + public void writeThrowable(Throwable throwable) throws IOException { + ObjectOutputStream out = new ObjectOutputStream(this); + out.writeObject(throwable); + out.flush(); + } } diff --git a/src/main/java/org/elasticsearch/index/IndexException.java b/src/main/java/org/elasticsearch/index/IndexException.java index a3d18cfd86e..0f100dcd4f0 100644 --- a/src/main/java/org/elasticsearch/index/IndexException.java +++ b/src/main/java/org/elasticsearch/index/IndexException.java @@ -20,6 +20,9 @@ package org.elasticsearch.index; import org.elasticsearch.ElasticsearchException; +import org.elasticsearch.common.xcontent.XContentBuilder; + +import java.io.IOException; /** * @@ -32,16 +35,25 @@ public class IndexException extends ElasticsearchException { this(index, msg, null); } - public IndexException(Index index, String msg, Throwable cause) { - this(index, true, msg, cause); - } - - protected IndexException(Index index, boolean withSpace, String msg, Throwable cause) { - super("[" + (index == null ? "_na" : index.name()) + "]" + (withSpace ? " " : "") + msg, cause); + protected IndexException(Index index, String msg, Throwable cause) { + super(msg, cause); this.index = index; } public Index index() { return index; } + + @Override + protected void innerToXContent(XContentBuilder builder, Params params) throws IOException { + if (index != null) { + builder.field("index", index.getName()); + } + super.innerToXContent(builder, params); + } + + @Override + public String toString() { + return "[" + (index == null ? "_na" : index.name()) + "] " + getMessage(); + } } diff --git a/src/main/java/org/elasticsearch/index/percolator/PercolatorException.java b/src/main/java/org/elasticsearch/index/percolator/PercolatorException.java index 462b9104d03..6e0f1d1827c 100644 --- a/src/main/java/org/elasticsearch/index/percolator/PercolatorException.java +++ b/src/main/java/org/elasticsearch/index/percolator/PercolatorException.java @@ -26,10 +26,6 @@ import org.elasticsearch.index.IndexException; */ public class PercolatorException extends IndexException { - public PercolatorException(Index index, String msg) { - super(index, msg); - } - public PercolatorException(Index index, String msg, Throwable cause) { super(index, msg, cause); } diff --git a/src/main/java/org/elasticsearch/index/query/QueryParsingException.java b/src/main/java/org/elasticsearch/index/query/QueryParsingException.java index 8c3a0fbccbe..5bf1407a107 100644 --- a/src/main/java/org/elasticsearch/index/query/QueryParsingException.java +++ b/src/main/java/org/elasticsearch/index/query/QueryParsingException.java @@ -40,4 +40,5 @@ public class QueryParsingException extends IndexException { public RestStatus status() { return RestStatus.BAD_REQUEST; } + } diff --git a/src/main/java/org/elasticsearch/index/shard/IndexShardException.java b/src/main/java/org/elasticsearch/index/shard/IndexShardException.java index e9217fda4cb..019b4d13bb4 100644 --- a/src/main/java/org/elasticsearch/index/shard/IndexShardException.java +++ b/src/main/java/org/elasticsearch/index/shard/IndexShardException.java @@ -19,8 +19,11 @@ package org.elasticsearch.index.shard; +import org.elasticsearch.common.xcontent.XContentBuilder; import org.elasticsearch.index.IndexException; +import java.io.IOException; + /** * */ @@ -33,11 +36,24 @@ public class IndexShardException extends IndexException { } public IndexShardException(ShardId shardId, String msg, Throwable cause) { - super(shardId == null ? null : shardId.index(), false, "[" + (shardId == null ? "_na" : shardId.id()) + "] " + msg, cause); + super(shardId == null ? null : shardId.index(), msg, cause); this.shardId = shardId; } public ShardId shardId() { return shardId; } + + @Override + public String toString() { + return (shardId == null ? "_na" : shardId) + getMessage(); + } + + @Override + protected void innerToXContent(XContentBuilder builder, Params params) throws IOException { + if (shardId != null) { + builder.field("shard", shardId.getId()); + } + super.innerToXContent(builder, params); + } } diff --git a/src/main/java/org/elasticsearch/indices/AliasFilterParsingException.java b/src/main/java/org/elasticsearch/indices/AliasFilterParsingException.java index aa7b559bb30..95d1c0f4d6d 100644 --- a/src/main/java/org/elasticsearch/indices/AliasFilterParsingException.java +++ b/src/main/java/org/elasticsearch/indices/AliasFilterParsingException.java @@ -27,10 +27,6 @@ import org.elasticsearch.index.IndexException; */ public class AliasFilterParsingException extends IndexException { - public AliasFilterParsingException(Index index, String name, String desc) { - super(index, "[" + name + "], " + desc); - } - public AliasFilterParsingException(Index index, String name, String desc, Throwable ex) { super(index, "[" + name + "], " + desc, ex); } diff --git a/src/main/java/org/elasticsearch/indices/IndexMissingException.java b/src/main/java/org/elasticsearch/indices/IndexMissingException.java index dbadef5a076..1bec1585a7c 100644 --- a/src/main/java/org/elasticsearch/indices/IndexMissingException.java +++ b/src/main/java/org/elasticsearch/indices/IndexMissingException.java @@ -29,7 +29,7 @@ import org.elasticsearch.rest.RestStatus; public class IndexMissingException extends IndexException { public IndexMissingException(Index index) { - super(index, "missing"); + super(index, "no such index"); } @Override diff --git a/src/main/java/org/elasticsearch/indices/TypeMissingException.java b/src/main/java/org/elasticsearch/indices/TypeMissingException.java index ae2830b9575..eb80c057a45 100644 --- a/src/main/java/org/elasticsearch/indices/TypeMissingException.java +++ b/src/main/java/org/elasticsearch/indices/TypeMissingException.java @@ -34,11 +34,6 @@ public class TypeMissingException extends IndexException { super(index, "type[" + Arrays.toString(types) + "] missing"); } - public TypeMissingException(Index index, String[] types, String message) { - super(index, "type[" + Arrays.toString(types) + "] missing: " + message); - } - - @Override public RestStatus status() { return RestStatus.NOT_FOUND; diff --git a/src/main/java/org/elasticsearch/rest/BytesRestResponse.java b/src/main/java/org/elasticsearch/rest/BytesRestResponse.java index b72008cf63e..693188307e3 100644 --- a/src/main/java/org/elasticsearch/rest/BytesRestResponse.java +++ b/src/main/java/org/elasticsearch/rest/BytesRestResponse.java @@ -20,13 +20,16 @@ package org.elasticsearch.rest; import org.elasticsearch.ElasticsearchException; +import org.elasticsearch.ExceptionsHelper; import org.elasticsearch.common.bytes.BytesArray; import org.elasticsearch.common.bytes.BytesReference; +import org.elasticsearch.common.collect.Tuple; +import org.elasticsearch.common.xcontent.ToXContent; import org.elasticsearch.common.xcontent.XContentBuilder; import java.io.IOException; +import java.util.Collections; -import static org.elasticsearch.ExceptionsHelper.detailedMessage; public class BytesRestResponse extends RestResponse { @@ -78,7 +81,7 @@ public class BytesRestResponse extends RestResponse { } public BytesRestResponse(RestChannel channel, Throwable t) throws IOException { - this(channel, ((t instanceof ElasticsearchException) ? ((ElasticsearchException) t).status() : RestStatus.INTERNAL_SERVER_ERROR), t); + this(channel, ExceptionsHelper.status(t), t); } public BytesRestResponse(RestChannel channel, RestStatus status, Throwable t) throws IOException { @@ -114,9 +117,22 @@ public class BytesRestResponse extends RestResponse { private static XContentBuilder convert(RestChannel channel, RestStatus status, Throwable t) throws IOException { XContentBuilder builder = channel.newBuilder().startObject(); if (t == null) { - builder.field("error", "Unknown"); + builder.field("error", "unknown"); } else if (channel.detailedErrorsEnabled()) { - builder.field("error", detailedMessage(t)); + builder.field("error"); + builder.startObject(); + final ElasticsearchException[] rootCauses = ElasticsearchException.guessRootCauses(t); + builder.field("root_cause"); + builder.startArray(); + for (ElasticsearchException rootCause : rootCauses){ + builder.startObject(); + rootCause.toXContent(builder, new ToXContent.DelegatingMapParams(Collections.singletonMap(ElasticsearchException.REST_EXCEPTION_SKIP_CAUSE, "true"), channel.request())); + builder.endObject(); + } + builder.endArray(); + + ElasticsearchException.toXContent(builder, channel.request(), t); + builder.endObject(); if (channel.request().paramAsBoolean("error_trace", false)) { buildErrorTrace(t, builder); } @@ -128,6 +144,7 @@ public class BytesRestResponse extends RestResponse { return builder; } + private static void buildErrorTrace(Throwable t, XContentBuilder builder) throws IOException { builder.startObject("error_trace"); boolean first = true; diff --git a/src/main/java/org/elasticsearch/search/SearchContextException.java b/src/main/java/org/elasticsearch/search/SearchContextException.java index 39bea64188f..599515830e1 100644 --- a/src/main/java/org/elasticsearch/search/SearchContextException.java +++ b/src/main/java/org/elasticsearch/search/SearchContextException.java @@ -35,19 +35,6 @@ public class SearchContextException extends SearchException { } private static String buildMessage(SearchContext context, String msg) { - StringBuilder sb = new StringBuilder(); - sb.append('[').append(context.shardTarget().index()).append("][").append(context.shardTarget().shardId()).append("]: "); - if (context.parsedQuery() != null) { - try { - sb.append("query[").append(context.parsedQuery().query()).append("],"); - } catch (Exception e) { - sb.append("query[_failed_to_string_],"); - } - } - sb.append("from[").append(context.from()).append("],size[").append(context.size()).append("]"); - if (context.sort() != null) { - sb.append(",sort[").append(context.sort()).append("]"); - } - return sb.append(": ").append(msg).toString(); + return msg; } } diff --git a/src/main/java/org/elasticsearch/search/SearchParseException.java b/src/main/java/org/elasticsearch/search/SearchParseException.java index 5f528f2d57a..923532373a5 100644 --- a/src/main/java/org/elasticsearch/search/SearchParseException.java +++ b/src/main/java/org/elasticsearch/search/SearchParseException.java @@ -28,11 +28,11 @@ import org.elasticsearch.search.internal.SearchContext; public class SearchParseException extends SearchContextException { public SearchParseException(SearchContext context, String msg) { - super(context, "Parse Failure [" + msg + "]"); + super(context, msg); } public SearchParseException(SearchContext context, String msg, Throwable cause) { - super(context, "Parse Failure [" + msg + "]", cause); + super(context, msg, cause); } @Override diff --git a/src/test/java/org/elasticsearch/ElasticsearchExceptionTests.java b/src/test/java/org/elasticsearch/ElasticsearchExceptionTests.java index 2c605f889aa..26447471c2c 100644 --- a/src/test/java/org/elasticsearch/ElasticsearchExceptionTests.java +++ b/src/test/java/org/elasticsearch/ElasticsearchExceptionTests.java @@ -19,13 +19,27 @@ package org.elasticsearch; +import org.elasticsearch.action.search.SearchPhaseExecutionException; +import org.elasticsearch.action.search.ShardSearchFailure; +import org.elasticsearch.common.io.BytesStream; +import org.elasticsearch.common.io.stream.BytesStreamInput; +import org.elasticsearch.common.io.stream.BytesStreamOutput; +import org.elasticsearch.common.xcontent.ToXContent; +import org.elasticsearch.common.xcontent.XContentBuilder; +import org.elasticsearch.common.xcontent.XContentFactory; import org.elasticsearch.index.Index; +import org.elasticsearch.index.query.QueryParsingException; import org.elasticsearch.indices.IndexMissingException; import org.elasticsearch.rest.RestStatus; +import org.elasticsearch.search.SearchShardTarget; import org.elasticsearch.test.ElasticsearchTestCase; import org.elasticsearch.transport.RemoteTransportException; import org.junit.Test; +import java.io.EOFException; +import java.io.FileNotFoundException; +import java.io.IOException; + import static org.hamcrest.Matchers.equalTo; public class ElasticsearchExceptionTests extends ElasticsearchTestCase { @@ -43,5 +57,203 @@ public class ElasticsearchExceptionTests extends ElasticsearchTestCase { exception = new RemoteTransportException("test", new IndexMissingException(new Index("test"))); assertThat(exception.status(), equalTo(RestStatus.NOT_FOUND)); + + exception = new RemoteTransportException("test", new IllegalArgumentException("foobar")); + assertThat(exception.status(), equalTo(RestStatus.BAD_REQUEST)); + + exception = new RemoteTransportException("test", new IllegalStateException("foobar")); + assertThat(exception.status(), equalTo(RestStatus.INTERNAL_SERVER_ERROR)); } + + public void testGuessRootCause() { + { + ElasticsearchException exception = new ElasticsearchException("foo", new ElasticsearchException("bar", new ElasticsearchIllegalArgumentException("index is closed", new RuntimeException("foobar")))); + ElasticsearchException[] rootCauses = exception.guessRootCauses(); + assertEquals(rootCauses.length, 1); + assertEquals(ElasticsearchException.getExceptionName(rootCauses[0]), "illegal_argument_exception"); + assertEquals(rootCauses[0].getMessage(), "index is closed"); + ShardSearchFailure failure = new ShardSearchFailure(new QueryParsingException(new Index("foo"), "foobar"), new SearchShardTarget("node_1", "foo", 1)); + ShardSearchFailure failure1 = new ShardSearchFailure(new QueryParsingException(new Index("foo"), "foobar"), new SearchShardTarget("node_1", "foo", 2)); + SearchPhaseExecutionException ex = new SearchPhaseExecutionException("search", "all shards failed", new ShardSearchFailure[]{failure, failure1}); + if (randomBoolean()) { + rootCauses = (randomBoolean() ? new RemoteTransportException("remoteboom", ex) : ex).guessRootCauses(); + } else { + rootCauses = ElasticsearchException.guessRootCauses(randomBoolean() ? new RemoteTransportException("remoteboom", ex) : ex); + } + assertEquals(ElasticsearchException.getExceptionName(rootCauses[0]), "query_parsing_exception"); + assertEquals(rootCauses[0].getMessage(), "foobar"); + + ElasticsearchException oneLevel = new ElasticsearchException("foo", new RuntimeException("foobar")); + rootCauses = oneLevel.guessRootCauses(); + assertEquals(ElasticsearchException.getExceptionName(rootCauses[0]), "exception"); + assertEquals(rootCauses[0].getMessage(), "foo"); + } + { + ShardSearchFailure failure = new ShardSearchFailure(new QueryParsingException(new Index("foo"), "foobar"), new SearchShardTarget("node_1", "foo", 1)); + ShardSearchFailure failure1 = new ShardSearchFailure(new QueryParsingException(new Index("foo1"), "foobar"), new SearchShardTarget("node_1", "foo1", 1)); + ShardSearchFailure failure2 = new ShardSearchFailure(new QueryParsingException(new Index("foo1"), "foobar"), new SearchShardTarget("node_1", "foo1", 2)); + SearchPhaseExecutionException ex = new SearchPhaseExecutionException("search", "all shards failed", new ShardSearchFailure[]{failure, failure1, failure2}); + final ElasticsearchException[] rootCauses = ex.guessRootCauses(); + assertEquals(rootCauses.length, 2); + assertEquals(ElasticsearchException.getExceptionName(rootCauses[0]), "query_parsing_exception"); + assertEquals(rootCauses[0].getMessage(), "foobar"); + assertEquals(((QueryParsingException)rootCauses[0]).index().name(), "foo"); + assertEquals(ElasticsearchException.getExceptionName(rootCauses[1]), "query_parsing_exception"); + assertEquals(rootCauses[1].getMessage(), "foobar"); + assertEquals(((QueryParsingException)rootCauses[1]).index().name(), "foo1"); + + } + + } + + public void testDeduplicate() throws IOException { + { + ShardSearchFailure failure = new ShardSearchFailure(new QueryParsingException(new Index("foo"), "foobar"), new SearchShardTarget("node_1", "foo", 1)); + ShardSearchFailure failure1 = new ShardSearchFailure(new QueryParsingException(new Index("foo"), "foobar"), new SearchShardTarget("node_1", "foo", 2)); + SearchPhaseExecutionException ex = new SearchPhaseExecutionException("search", "all shards failed", new ShardSearchFailure[]{failure, failure1}); + XContentBuilder builder = XContentFactory.jsonBuilder().prettyPrint(); + builder.startObject(); + ex.toXContent(builder, ToXContent.EMPTY_PARAMS); + builder.endObject(); + String expected = "{\n" + + " \"type\" : \"search_phase_execution_exception\",\n" + + " \"reason\" : \"all shards failed\",\n" + + " \"phase\" : \"search\",\n" + + " \"grouped\" : true,\n" + + " \"failed_shards\" : [ {\n" + + " \"shard\" : 1,\n" + + " \"index\" : \"foo\",\n" + + " \"node\" : \"node_1\",\n" + + " \"reason\" : {\n" + + " \"type\" : \"query_parsing_exception\",\n" + + " \"reason\" : \"foobar\",\n" + + " \"index\" : \"foo\"\n" + + " }\n" + + " } ]\n" + + "}"; + assertEquals(expected, builder.string()); + } + { + ShardSearchFailure failure = new ShardSearchFailure(new QueryParsingException(new Index("foo"), "foobar"), new SearchShardTarget("node_1", "foo", 1)); + ShardSearchFailure failure1 = new ShardSearchFailure(new QueryParsingException(new Index("foo1"), "foobar"), new SearchShardTarget("node_1", "foo1", 1)); + ShardSearchFailure failure2 = new ShardSearchFailure(new QueryParsingException(new Index("foo1"), "foobar"), new SearchShardTarget("node_1", "foo1", 2)); + SearchPhaseExecutionException ex = new SearchPhaseExecutionException("search", "all shards failed", new ShardSearchFailure[]{failure, failure1, failure2}); + XContentBuilder builder = XContentFactory.jsonBuilder().prettyPrint(); + builder.startObject(); + ex.toXContent(builder, ToXContent.EMPTY_PARAMS); + builder.endObject(); + String expected = "{\n" + + " \"type\" : \"search_phase_execution_exception\",\n" + + " \"reason\" : \"all shards failed\",\n" + + " \"phase\" : \"search\",\n" + + " \"grouped\" : true,\n" + + " \"failed_shards\" : [ {\n" + + " \"shard\" : 1,\n" + + " \"index\" : \"foo\",\n" + + " \"node\" : \"node_1\",\n" + + " \"reason\" : {\n" + + " \"type\" : \"query_parsing_exception\",\n" + + " \"reason\" : \"foobar\",\n" + + " \"index\" : \"foo\"\n" + + " }\n" + + " }, {\n" + + " \"shard\" : 1,\n" + + " \"index\" : \"foo1\",\n" + + " \"node\" : \"node_1\",\n" + + " \"reason\" : {\n" + + " \"type\" : \"query_parsing_exception\",\n" + + " \"reason\" : \"foobar\",\n" + + " \"index\" : \"foo1\"\n" + + " }\n" + + " } ]\n" + + "}"; + assertEquals(expected, builder.string()); + } + } + + public void testGetRootCause() { + Exception root = new RuntimeException("foobar"); + ElasticsearchException exception = new ElasticsearchException("foo", new ElasticsearchException("bar", new ElasticsearchIllegalArgumentException("index is closed", root))); + assertEquals(root, exception.getRootCause()); + assertTrue(exception.contains(RuntimeException.class)); + assertFalse(exception.contains(EOFException.class)); + } + + public void testToString() { + ElasticsearchException exception = new ElasticsearchException("foo", new ElasticsearchException("bar", new ElasticsearchIllegalArgumentException("index is closed", new RuntimeException("foobar")))); + assertEquals("ElasticsearchException[foo]; nested: ElasticsearchException[bar]; nested: ElasticsearchIllegalArgumentException[index is closed]; nested: RuntimeException[foobar];", exception.toString()); + } + + public void testToXContent() throws IOException { + { + ElasticsearchException ex = new ElasticsearchException("foo", new ElasticsearchException("bar", new ElasticsearchIllegalArgumentException("index is closed", new RuntimeException("foobar")))); + XContentBuilder builder = XContentFactory.jsonBuilder().prettyPrint(); + builder.startObject(); + ex.toXContent(builder, ToXContent.EMPTY_PARAMS); + builder.endObject(); + + String expected = "{\n" + + " \"type\" : \"exception\",\n" + + " \"reason\" : \"foo\",\n" + + " \"caused_by\" : {\n" + + " \"type\" : \"exception\",\n" + + " \"reason\" : \"bar\",\n" + + " \"caused_by\" : {\n" + + " \"type\" : \"illegal_argument_exception\",\n" + + " \"reason\" : \"index is closed\",\n" + + " \"caused_by\" : {\n" + + " \"type\" : \"runtime_exception\",\n" + + " \"reason\" : \"foobar\"\n" + + " }\n" + + " }\n" + + " }\n" + + "}"; + assertEquals(expected, builder.string()); + } + + { + Exception ex = new FileNotFoundException("foo not found"); + if (randomBoolean()) { + // just a wrapper which is omitted + ex = new RemoteTransportException("foobar", ex); + } + XContentBuilder builder = XContentFactory.jsonBuilder().prettyPrint(); + builder.startObject(); + ElasticsearchException.toXContent(builder, ToXContent.EMPTY_PARAMS, ex); + builder.endObject(); + + String expected = "{\n" + + " \"type\" : \"file_not_found_exception\",\n" + + " \"reason\" : \"foo not found\"\n" + + "}"; + assertEquals(expected, builder.string()); + } + + { // test equivalence + ElasticsearchException ex = new RemoteTransportException("foobar", new FileNotFoundException("foo not found")); + XContentBuilder builder = XContentFactory.jsonBuilder().prettyPrint(); + builder.startObject(); + ElasticsearchException.toXContent(builder, ToXContent.EMPTY_PARAMS, ex); + builder.endObject(); + + XContentBuilder otherBuilder = XContentFactory.jsonBuilder().prettyPrint(); + + otherBuilder.startObject(); + ex.toXContent(otherBuilder, ToXContent.EMPTY_PARAMS); + otherBuilder.endObject(); + assertEquals(otherBuilder.string(), builder.string()); + } + } + + public void testSerializeElasticsearchException() throws IOException { + BytesStreamOutput out = new BytesStreamOutput(); + QueryParsingException ex = new QueryParsingException(new Index("foo"), "foobar"); + out.writeThrowable(ex); + + BytesStreamInput in = new BytesStreamInput(out.bytes()); + QueryParsingException e = in.readThrowable(); + assertEquals(ex.index(), e.index()); + assertEquals(ex.getMessage(), e.getMessage()); + } + } \ No newline at end of file diff --git a/src/test/java/org/elasticsearch/action/bulk/BulkProcessorClusterSettingsTests.java b/src/test/java/org/elasticsearch/action/bulk/BulkProcessorClusterSettingsTests.java index 6b9379fe052..5140df378dd 100644 --- a/src/test/java/org/elasticsearch/action/bulk/BulkProcessorClusterSettingsTests.java +++ b/src/test/java/org/elasticsearch/action/bulk/BulkProcessorClusterSettingsTests.java @@ -48,7 +48,7 @@ public class BulkProcessorClusterSettingsTests extends ElasticsearchIntegrationT assertEquals(3, responses.length); assertFalse("Operation on existing index should succeed", responses[0].isFailed()); assertTrue("Missing index should have been flagged", responses[1].isFailed()); - assertEquals("IndexMissingException[[wontwork] missing]", responses[1].getFailureMessage()); + assertEquals("[wontwork] no such index", responses[1].getFailureMessage()); assertFalse("Operation on existing index should succeed", responses[2].isFailed()); } } diff --git a/src/test/java/org/elasticsearch/cluster/metadata/MetaDataTests.java b/src/test/java/org/elasticsearch/cluster/metadata/MetaDataTests.java index e63927c7933..3349b33ed60 100644 --- a/src/test/java/org/elasticsearch/cluster/metadata/MetaDataTests.java +++ b/src/test/java/org/elasticsearch/cluster/metadata/MetaDataTests.java @@ -441,7 +441,8 @@ public class MetaDataTests extends ElasticsearchTestCase { md.concreteIndices(IndicesOptions.strictSingleIndexNoExpandForbidClosed(), "foofoo-closed", "foofoobar"); fail(); } catch(IndexClosedException e) { - assertThat(e.getMessage(), containsString("[foofoo-closed] closed")); + assertThat(e.getMessage(), equalTo("closed")); + assertEquals(e.index().getName(), "foofoo-closed"); } String[] results = md.concreteIndices(IndicesOptions.strictSingleIndexNoExpandForbidClosed(), "foo", "barbaz"); diff --git a/src/test/java/org/elasticsearch/deleteByQuery/DeleteByQueryTests.java b/src/test/java/org/elasticsearch/deleteByQuery/DeleteByQueryTests.java index ffc8db1d36b..877714681c6 100644 --- a/src/test/java/org/elasticsearch/deleteByQuery/DeleteByQueryTests.java +++ b/src/test/java/org/elasticsearch/deleteByQuery/DeleteByQueryTests.java @@ -120,7 +120,7 @@ public class DeleteByQueryTests extends ElasticsearchIntegrationTest { assertThat(response.getIndices().size(), equalTo(1)); assertThat(response.getIndices().get("test").getShardInfo().getFailures().length, equalTo(twitter.numPrimaries)); for (ActionWriteResponse.ShardInfo.Failure failure : response.getIndices().get("test").getShardInfo().getFailures()) { - assertThat(failure.reason(), containsString("[test] [has_child] query and filter unsupported in delete_by_query api")); + assertThat(failure.reason(), containsString("[has_child] query and filter unsupported in delete_by_query api")); assertThat(failure.status(), equalTo(RestStatus.BAD_REQUEST)); assertThat(failure.shardId(), greaterThan(-1)); } diff --git a/src/test/java/org/elasticsearch/document/BulkTests.java b/src/test/java/org/elasticsearch/document/BulkTests.java index f49914606dd..380828372bb 100644 --- a/src/test/java/org/elasticsearch/document/BulkTests.java +++ b/src/test/java/org/elasticsearch/document/BulkTests.java @@ -133,7 +133,7 @@ public class BulkTests extends ElasticsearchIntegrationTest { assertThat(bulkResponse.getItems()[1].getResponse(), nullValue()); assertThat(bulkResponse.getItems()[1].getFailure().getIndex(), equalTo("test")); assertThat(bulkResponse.getItems()[1].getFailure().getId(), equalTo("7")); - assertThat(bulkResponse.getItems()[1].getFailure().getMessage(), containsString("DocumentMissingException")); + assertThat(bulkResponse.getItems()[1].getFailure().getMessage(), containsString("document missing")); assertThat(((UpdateResponse) bulkResponse.getItems()[2].getResponse()).getId(), equalTo("2")); assertThat(((UpdateResponse) bulkResponse.getItems()[2].getResponse()).getIndex(), equalTo("test")); assertThat(((UpdateResponse) bulkResponse.getItems()[2].getResponse()).getVersion(), equalTo(3l)); @@ -173,7 +173,7 @@ public class BulkTests extends ElasticsearchIntegrationTest { .add(client().prepareUpdate("test", "type", "2").setDoc("field", "2")) .add(client().prepareUpdate("test", "type", "1").setVersion(2l).setDoc("field", "3")).get(); - assertThat(bulkResponse.getItems()[0].getFailureMessage(), containsString("Version")); + assertThat(bulkResponse.getItems()[0].getFailureMessage(), containsString("version conflict")); assertThat(((UpdateResponse) bulkResponse.getItems()[1].getResponse()).getVersion(), equalTo(2l)); assertThat(((UpdateResponse) bulkResponse.getItems()[2].getResponse()).getVersion(), equalTo(3l)); @@ -194,7 +194,7 @@ public class BulkTests extends ElasticsearchIntegrationTest { .add(client().prepareUpdate("test", "type", "e1").setDoc("field", "3").setVersion(20).setVersionType(VersionType.FORCE)) .add(client().prepareUpdate("test", "type", "e1").setDoc("field", "3").setVersion(20).setVersionType(VersionType.INTERNAL)).get(); - assertThat(bulkResponse.getItems()[0].getFailureMessage(), containsString("Version")); + assertThat(bulkResponse.getItems()[0].getFailureMessage(), containsString("version conflict")); assertThat(((UpdateResponse) bulkResponse.getItems()[1].getResponse()).getVersion(), equalTo(20l)); assertThat(((UpdateResponse) bulkResponse.getItems()[2].getResponse()).getVersion(), equalTo(21l)); } @@ -325,7 +325,7 @@ public class BulkTests extends ElasticsearchIntegrationTest { int id = i + (numDocs / 2); if (i >= (numDocs / 2)) { assertThat(response.getItems()[i].getFailure().getId(), equalTo(Integer.toString(id))); - assertThat(response.getItems()[i].getFailure().getMessage(), containsString("DocumentMissingException")); + assertThat(response.getItems()[i].getFailure().getMessage(), containsString("document missing")); } else { assertThat(response.getItems()[i].getId(), equalTo(Integer.toString(id))); assertThat(response.getItems()[i].getVersion(), equalTo(3l)); diff --git a/src/test/java/org/elasticsearch/index/query/SimpleIndexQueryParserTests.java b/src/test/java/org/elasticsearch/index/query/SimpleIndexQueryParserTests.java index 6e928ca4f81..b258420a245 100644 --- a/src/test/java/org/elasticsearch/index/query/SimpleIndexQueryParserTests.java +++ b/src/test/java/org/elasticsearch/index/query/SimpleIndexQueryParserTests.java @@ -1191,7 +1191,7 @@ public class SimpleIndexQueryParserTests extends ElasticsearchSingleNodeTest { queryParser.parse(query).query(); fail(); } catch (QueryParsingException ex) { - assertThat(ex.getMessage(), equalTo("[test] [terms] query does not support multiple fields")); + assertThat(ex.getMessage(), equalTo("[terms] query does not support multiple fields")); } } @@ -1207,7 +1207,7 @@ public class SimpleIndexQueryParserTests extends ElasticsearchSingleNodeTest { queryParser.parse(query).query(); fail(); } catch (QueryParsingException ex) { - assertThat(ex.getMessage(), equalTo("[test] [terms] filter does not support multiple fields")); + assertThat(ex.getMessage(), equalTo("[terms] filter does not support multiple fields")); } } diff --git a/src/test/java/org/elasticsearch/indices/memory/breaker/CircuitBreakerServiceTests.java b/src/test/java/org/elasticsearch/indices/memory/breaker/CircuitBreakerServiceTests.java index 311449aaece..f09562f690e 100644 --- a/src/test/java/org/elasticsearch/indices/memory/breaker/CircuitBreakerServiceTests.java +++ b/src/test/java/org/elasticsearch/indices/memory/breaker/CircuitBreakerServiceTests.java @@ -241,8 +241,8 @@ public class CircuitBreakerServiceTests extends ElasticsearchIntegrationTest { fail("should have thrown an exception"); } catch (Exception e) { String errMsg = "[fielddata] Data too large, data for [test] would be larger than limit of [10/10b]"; - assertThat("Exception: " + ExceptionsHelper.unwrapCause(e) + " should contain a CircuitBreakingException", - ExceptionsHelper.unwrapCause(e).getMessage().contains(errMsg), equalTo(true)); + assertThat("Exception: " + e.toString() + " should contain a CircuitBreakingException", + e.toString().contains(errMsg), equalTo(true)); } assertFailures(client.prepareSearch("cb-test").setQuery(matchAllQuery()).addSort("test", SortOrder.DESC), @@ -263,8 +263,8 @@ public class CircuitBreakerServiceTests extends ElasticsearchIntegrationTest { fail("should have thrown an exception"); } catch (Exception e) { String errMsg = "[parent] Data too large, data for [test] would be larger than limit of [15/15b]"; - assertThat("Exception: " + ExceptionsHelper.unwrapCause(e) + " should contain a CircuitBreakingException", - ExceptionsHelper.unwrapCause(e).getMessage().contains(errMsg), equalTo(true)); + assertThat("Exception: " +e.toString() + " should contain a CircuitBreakingException", + e.toString().contains(errMsg), equalTo(true)); } } @@ -297,8 +297,8 @@ public class CircuitBreakerServiceTests extends ElasticsearchIntegrationTest { fail("aggregation should have tripped the breaker"); } catch (Exception e) { String errMsg = "CircuitBreakingException[[request] Data too large, data for [] would be larger than limit of [10/10b]]"; - assertThat("Exception: " + ExceptionsHelper.unwrapCause(e) + " should contain a CircuitBreakingException", - ExceptionsHelper.unwrapCause(e).getMessage().contains(errMsg), equalTo(true)); + assertThat("Exception: " + e.toString() + " should contain a CircuitBreakingException", + e.toString().contains(errMsg), equalTo(true)); } } diff --git a/src/test/java/org/elasticsearch/indices/template/SimpleIndexTemplateTests.java b/src/test/java/org/elasticsearch/indices/template/SimpleIndexTemplateTests.java index 39a54516e9b..e02c2bef8b4 100644 --- a/src/test/java/org/elasticsearch/indices/template/SimpleIndexTemplateTests.java +++ b/src/test/java/org/elasticsearch/indices/template/SimpleIndexTemplateTests.java @@ -495,7 +495,7 @@ public class SimpleIndexTemplateTests extends ElasticsearchIntegrationTest { } catch(ElasticsearchIllegalArgumentException e) { assertThat(e.getMessage(), equalTo("failed to parse filter for alias [invalid_alias]")); assertThat(e.getCause(), instanceOf(QueryParsingException.class)); - assertThat(e.getCause().getMessage(), equalTo("[test] No filter registered for [invalid]")); + assertThat(e.getCause().getMessage(), equalTo("No filter registered for [invalid]")); } } @@ -530,7 +530,7 @@ public class SimpleIndexTemplateTests extends ElasticsearchIntegrationTest { createIndex("test"); fail("index creation should have failed due to alias with existing index name in mathching index template"); } catch(InvalidAliasNameException e) { - assertThat(e.getMessage(), equalTo("[test] Invalid alias name [index], an index exists with the same name as the alias")); + assertThat(e.getMessage(), equalTo("Invalid alias name [index], an index exists with the same name as the alias")); } } diff --git a/src/test/java/org/elasticsearch/nested/SimpleNestedTests.java b/src/test/java/org/elasticsearch/nested/SimpleNestedTests.java index 9ee0ecba47f..fc95131d250 100644 --- a/src/test/java/org/elasticsearch/nested/SimpleNestedTests.java +++ b/src/test/java/org/elasticsearch/nested/SimpleNestedTests.java @@ -707,7 +707,7 @@ public class SimpleNestedTests extends ElasticsearchIntegrationTest { .execute().actionGet(); Assert.fail("SearchPhaseExecutionException should have been thrown"); } catch (SearchPhaseExecutionException e) { - assertThat(e.getMessage(), containsString("type [string] doesn't support mode [SUM]")); + assertThat(e.toString(), containsString("type [string] doesn't support mode [SUM]")); } } diff --git a/src/test/java/org/elasticsearch/rest/BytesRestResponseTests.java b/src/test/java/org/elasticsearch/rest/BytesRestResponseTests.java index 989ea7194fc..784015e9db0 100644 --- a/src/test/java/org/elasticsearch/rest/BytesRestResponseTests.java +++ b/src/test/java/org/elasticsearch/rest/BytesRestResponseTests.java @@ -20,11 +20,18 @@ package org.elasticsearch.rest; import org.elasticsearch.ElasticsearchException; +import org.elasticsearch.action.search.SearchPhaseExecutionException; +import org.elasticsearch.action.search.ShardSearchFailure; +import org.elasticsearch.index.Index; +import org.elasticsearch.index.query.QueryParsingException; +import org.elasticsearch.search.SearchShardTarget; import org.elasticsearch.test.ElasticsearchTestCase; import org.elasticsearch.test.rest.FakeRestRequest; +import org.elasticsearch.transport.RemoteTransportException; import org.junit.Test; import java.io.FileNotFoundException; +import java.io.IOException; import static org.hamcrest.Matchers.contains; import static org.hamcrest.Matchers.containsString; @@ -70,8 +77,8 @@ public class BytesRestResponseTests extends ElasticsearchTestCase { Throwable t = new ElasticsearchException("an error occurred reading data", new FileNotFoundException("/foo/bar")); BytesRestResponse response = new BytesRestResponse(channel, t); String text = response.content().toUtf8(); - assertThat(text, containsString("ElasticsearchException[an error occurred reading data]")); - assertThat(text, containsString("FileNotFoundException[/foo/bar]")); + assertThat(text, containsString("{\"type\":\"exception\",\"reason\":\"an error occurred reading data\"}")); + assertThat(text, containsString("{\"type\":\"file_not_found_exception\",\"reason\":\"/foo/bar\"}")); } @Test @@ -97,11 +104,21 @@ public class BytesRestResponseTests extends ElasticsearchTestCase { Throwable t = new Throwable("an error occurred reading data", new FileNotFoundException("/foo/bar")); BytesRestResponse response = new BytesRestResponse(channel, t); String text = response.content().toUtf8(); - assertThat(text, containsString("\"error\":\"Throwable[an error occurred reading data]")); - assertThat(text, containsString("FileNotFoundException[/foo/bar]")); + assertThat(text, containsString("\"type\":\"throwable\",\"reason\":\"an error occurred reading data\"")); + assertThat(text, containsString("{\"type\":\"file_not_found_exception\",\"reason\":\"/foo/bar\"}")); assertThat(text, containsString("\"error_trace\":{\"message\":\"an error occurred reading data\"")); } + public void testGuessRootCause() throws IOException { + RestRequest request = new FakeRestRequest(); + RestChannel channel = new DetailedExceptionRestChannel(request); + + Throwable t = new ElasticsearchException("an error occurred reading data", new FileNotFoundException("/foo/bar")); + BytesRestResponse response = new BytesRestResponse(channel, t); + String text = response.content().toUtf8(); + assertThat(text, containsString("{\"root_cause\":[{\"type\":\"exception\",\"reason\":\"an error occurred reading data\"}]")); + } + @Test public void testNullThrowable() throws Exception { RestRequest request = new FakeRestRequest(); @@ -109,10 +126,47 @@ public class BytesRestResponseTests extends ElasticsearchTestCase { BytesRestResponse response = new BytesRestResponse(channel, null); String text = response.content().toUtf8(); - assertThat(text, containsString("\"error\":\"Unknown\"")); + assertThat(text, containsString("\"error\":\"unknown\"")); assertThat(text, not(containsString("error_trace"))); } + @Test + public void testConvert() throws IOException { + RestRequest request = new FakeRestRequest(); + request.params().put("pretty", "true"); + RestChannel channel = new DetailedExceptionRestChannel(request); + ShardSearchFailure failure = new ShardSearchFailure(new QueryParsingException(new Index("foo"), "foobar"), new SearchShardTarget("node_1", "foo", 1)); + ShardSearchFailure failure1 = new ShardSearchFailure(new QueryParsingException(new Index("foo"), "foobar"), new SearchShardTarget("node_1", "foo", 2)); + SearchPhaseExecutionException ex = new SearchPhaseExecutionException("search", "all shards failed", new ShardSearchFailure[] {failure, failure1}); + BytesRestResponse response = new BytesRestResponse(channel, new RemoteTransportException("foo", ex)); + String text = response.content().toUtf8(); + String expected = "{\n" + + " \"error\" : {\n" + + " \"root_cause\" : [ {\n" + + " \"type\" : \"query_parsing_exception\",\n" + + " \"reason\" : \"foobar\",\n" + + " \"index\" : \"foo\"\n" + + " } ],\n" + + " \"type\" : \"search_phase_execution_exception\",\n" + + " \"reason\" : \"all shards failed\",\n" + + " \"phase\" : \"search\",\n" + + " \"grouped\" : true,\n" + + " \"failed_shards\" : [ {\n" + + " \"shard\" : 1,\n" + + " \"index\" : \"foo\",\n" + + " \"node\" : \"node_1\",\n" + + " \"reason\" : {\n" + + " \"type\" : \"query_parsing_exception\",\n" + + " \"reason\" : \"foobar\",\n" + + " \"index\" : \"foo\"\n" + + " }\n" + + " } ]\n" + + " },\n" + + " \"status\" : 400\n" + + "}"; + assertEquals(expected.trim(), text.trim()); + } + private static class ExceptionWithHeaders extends ElasticsearchException.WithRestHeaders { ExceptionWithHeaders() { diff --git a/src/test/java/org/elasticsearch/script/GroovySandboxScriptTests.java b/src/test/java/org/elasticsearch/script/GroovySandboxScriptTests.java index 8e521a6f392..c575d9152a1 100644 --- a/src/test/java/org/elasticsearch/script/GroovySandboxScriptTests.java +++ b/src/test/java/org/elasticsearch/script/GroovySandboxScriptTests.java @@ -153,8 +153,7 @@ public class GroovySandboxScriptTests extends ElasticsearchIntegrationTest { "; doc['foo'].value + 2\", \"type\": \"number\", \"lang\": \"groovy\"}}}").get(); fail("script: " + script + " failed to be caught be the sandbox!"); } catch (SearchPhaseExecutionException e) { - String msg = ExceptionsHelper.detailedMessage(ExceptionsHelper.unwrapCause(e)); - assertThat("script failed, but with incorrect message: " + msg, msg.contains(failMessage), equalTo(true)); + assertThat("script failed, but with incorrect message: " + e.toString(), e.toString().contains(failMessage), equalTo(true)); } } } diff --git a/src/test/java/org/elasticsearch/script/GroovyScriptTests.java b/src/test/java/org/elasticsearch/script/GroovyScriptTests.java index 801f4b36e40..657d2bc361e 100644 --- a/src/test/java/org/elasticsearch/script/GroovyScriptTests.java +++ b/src/test/java/org/elasticsearch/script/GroovyScriptTests.java @@ -76,12 +76,12 @@ public class GroovyScriptTests extends ElasticsearchIntegrationTest { client().prepareSearch("test").setQuery(constantScoreQuery(scriptFilter("1 == not_found").lang(GroovyScriptEngineService.NAME))).get(); fail("should have thrown an exception"); } catch (SearchPhaseExecutionException e) { - assertThat(ExceptionsHelper.detailedMessage(e) + "should not contained NotSerializableTransportException", - ExceptionsHelper.detailedMessage(e).contains("NotSerializableTransportException"), equalTo(false)); - assertThat(ExceptionsHelper.detailedMessage(e) + "should have contained GroovyScriptExecutionException", - ExceptionsHelper.detailedMessage(e).contains("GroovyScriptExecutionException"), equalTo(true)); - assertThat(ExceptionsHelper.detailedMessage(e) + "should have contained not_found", - ExceptionsHelper.detailedMessage(e).contains("No such property: not_found"), equalTo(true)); + assertThat(e.toString()+ "should not contained NotSerializableTransportException", + e.toString().contains("NotSerializableTransportException"), equalTo(false)); + assertThat(e.toString()+ "should have contained GroovyScriptExecutionException", + e.toString().contains("GroovyScriptExecutionException"), equalTo(true)); + assertThat(e.toString()+ "should have contained not_found", + e.toString().contains("No such property: not_found"), equalTo(true)); } try { @@ -89,12 +89,12 @@ public class GroovyScriptTests extends ElasticsearchIntegrationTest { scriptFilter("assert false").lang("groovy"))).get(); fail("should have thrown an exception"); } catch (SearchPhaseExecutionException e) { - assertThat(ExceptionsHelper.detailedMessage(e) + "should not contained NotSerializableTransportException", - ExceptionsHelper.detailedMessage(e).contains("NotSerializableTransportException"), equalTo(false)); - assertThat(ExceptionsHelper.detailedMessage(e) + "should have contained GroovyScriptExecutionException", - ExceptionsHelper.detailedMessage(e).contains("GroovyScriptExecutionException"), equalTo(true)); - assertThat(ExceptionsHelper.detailedMessage(e) + "should have contained an assert error", - ExceptionsHelper.detailedMessage(e).contains("PowerAssertionError[assert false"), equalTo(true)); + assertThat(e.toString()+ "should not contained NotSerializableTransportException", + e.toString().contains("NotSerializableTransportException"), equalTo(false)); + assertThat(e.toString()+ "should have contained GroovyScriptExecutionException", + e.toString().contains("GroovyScriptExecutionException"), equalTo(true)); + assertThat(e.toString()+ "should have contained an assert error", + e.toString().contains("PowerAssertionError[assert false"), equalTo(true)); } } diff --git a/src/test/java/org/elasticsearch/script/IndexLookupTests.java b/src/test/java/org/elasticsearch/script/IndexLookupTests.java index 85940106a35..a9a61555b3a 100644 --- a/src/test/java/org/elasticsearch/script/IndexLookupTests.java +++ b/src/test/java/org/elasticsearch/script/IndexLookupTests.java @@ -178,8 +178,8 @@ public class IndexLookupTests extends ElasticsearchIntegrationTest { client().prepareSearch("test").setQuery(QueryBuilders.matchAllQuery()).addScriptField("tvtest", script).execute().actionGet(); } catch (SearchPhaseExecutionException e) { assertThat( - "got: " + e.getDetailedMessage(), - e.getDetailedMessage() + "got: " + e.toString(), + e.toString() .indexOf( "You must call get with all required flags! Instead of _index['int_payload_field'].get('b', _FREQUENCIES) and _index['int_payload_field'].get('b', _POSITIONS) call _index['int_payload_field'].get('b', _FREQUENCIES | _POSITIONS) once]"), Matchers.greaterThan(-1)); diff --git a/src/test/java/org/elasticsearch/script/IndexedScriptTests.java b/src/test/java/org/elasticsearch/script/IndexedScriptTests.java index ac44e4d6dbc..1064bf464c7 100644 --- a/src/test/java/org/elasticsearch/script/IndexedScriptTests.java +++ b/src/test/java/org/elasticsearch/script/IndexedScriptTests.java @@ -158,20 +158,20 @@ public class IndexedScriptTests extends ElasticsearchIntegrationTest { fail("update script should have been rejected"); } catch(Exception e) { assertThat(e.getMessage(), containsString("failed to execute script")); - assertThat(ExceptionsHelper.detailedMessage(e), containsString("scripts of type [indexed], operation [update] and lang [expression] are disabled")); + assertThat(e.toString(), containsString("scripts of type [indexed], operation [update] and lang [expression] are disabled")); } try { String query = "{ \"script_fields\" : { \"test1\" : { \"script_id\" : \"script1\", \"lang\":\"expression\" }}}"; client().prepareSearch().setSource(query).setIndices("test").setTypes("scriptTest").get(); fail("search script should have been rejected"); } catch(Exception e) { - assertThat(e.getMessage(), containsString("scripts of type [indexed], operation [search] and lang [expression] are disabled")); + assertThat(e.toString(), containsString("scripts of type [indexed], operation [search] and lang [expression] are disabled")); } try { String source = "{\"aggs\": {\"test\": { \"terms\" : { \"script_id\":\"script1\", \"script_lang\":\"expression\" } } } }"; client().prepareSearch("test").setSource(source).get(); } catch(Exception e) { - assertThat(e.getMessage(), containsString("scripts of type [indexed], operation [aggs] and lang [expression] are disabled")); + assertThat(e.toString(), containsString("scripts of type [indexed], operation [aggs] and lang [expression] are disabled")); } } } diff --git a/src/test/java/org/elasticsearch/script/OnDiskScriptTests.java b/src/test/java/org/elasticsearch/script/OnDiskScriptTests.java index 78a28520d4a..88471f712b4 100644 --- a/src/test/java/org/elasticsearch/script/OnDiskScriptTests.java +++ b/src/test/java/org/elasticsearch/script/OnDiskScriptTests.java @@ -107,7 +107,7 @@ public class OnDiskScriptTests extends ElasticsearchIntegrationTest { client().prepareSearch("test").setSource(source).get(); fail("aggs script should have been rejected"); } catch(Exception e) { - assertThat(ExceptionsHelper.detailedMessage(e), containsString("scripts of type [file], operation [aggs] and lang [expression] are disabled")); + assertThat(e.toString(), containsString("scripts of type [file], operation [aggs] and lang [expression] are disabled")); } String query = "{ \"query\" : { \"match_all\": {}} , \"script_fields\" : { \"test1\" : { \"script_file\" : \"script1\", \"lang\":\"expression\" }}, size:1}"; @@ -128,21 +128,21 @@ public class OnDiskScriptTests extends ElasticsearchIntegrationTest { client().prepareSearch("test").setSource(source).get(); fail("aggs script should have been rejected"); } catch(Exception e) { - assertThat(ExceptionsHelper.detailedMessage(e), containsString("scripts of type [file], operation [aggs] and lang [mustache] are disabled")); + assertThat(e.toString(), containsString("scripts of type [file], operation [aggs] and lang [mustache] are disabled")); } String query = "{ \"query\" : { \"match_all\": {}} , \"script_fields\" : { \"test1\" : { \"script_file\" : \"script1\", \"lang\":\"mustache\" }}, size:1}"; try { client().prepareSearch().setSource(query).setIndices("test").setTypes("scriptTest").get(); fail("search script should have been rejected"); } catch(Exception e) { - assertThat(ExceptionsHelper.detailedMessage(e), containsString("scripts of type [file], operation [search] and lang [mustache] are disabled")); + assertThat(e.toString(), containsString("scripts of type [file], operation [search] and lang [mustache] are disabled")); } try { client().prepareUpdate("test", "scriptTest", "1").setScript("script1", ScriptService.ScriptType.FILE).setScriptLang(MustacheScriptEngineService.NAME).get(); fail("update script should have been rejected"); } catch(Exception e) { assertThat(e.getMessage(), containsString("failed to execute script")); - assertThat(ExceptionsHelper.detailedMessage(e), containsString("scripts of type [file], operation [update] and lang [mustache] are disabled")); + assertThat(e.getCause().toString(), containsString("scripts of type [file], operation [update] and lang [mustache] are disabled")); } } } diff --git a/src/test/java/org/elasticsearch/script/SandboxDisabledTests.java b/src/test/java/org/elasticsearch/script/SandboxDisabledTests.java index 0a759c07b98..0799fa0ddbd 100644 --- a/src/test/java/org/elasticsearch/script/SandboxDisabledTests.java +++ b/src/test/java/org/elasticsearch/script/SandboxDisabledTests.java @@ -51,7 +51,7 @@ public class SandboxDisabledTests extends ElasticsearchIntegrationTest { "\"sort\":{\"_script\": {\"script\": \"doc['foo'].value + 2\", \"type\": \"number\", \"lang\": \"groovy\"}}}").get(); fail("shards should fail because the sandbox and dynamic scripting are disabled"); } catch (Exception e) { - assertThat(ExceptionsHelper.detailedMessage(e), containsString("scripts of type [inline], operation [search] and lang [groovy] are disabled")); + assertThat(e.toString(), containsString("scripts of type [inline], operation [search] and lang [groovy] are disabled")); } } } diff --git a/src/test/java/org/elasticsearch/script/expression/ExpressionScriptTests.java b/src/test/java/org/elasticsearch/script/expression/ExpressionScriptTests.java index 9ef64d82477..8ee8d1dcbf1 100644 --- a/src/test/java/org/elasticsearch/script/expression/ExpressionScriptTests.java +++ b/src/test/java/org/elasticsearch/script/expression/ExpressionScriptTests.java @@ -111,10 +111,10 @@ public class ExpressionScriptTests extends ElasticsearchIntegrationTest { buildRequest("doc['bogus'].value").get(); fail("Expected missing field to cause failure"); } catch (SearchPhaseExecutionException e) { - assertThat(ExceptionsHelper.detailedMessage(e) + "should have contained ExpressionScriptCompilationException", - ExceptionsHelper.detailedMessage(e).contains("ExpressionScriptCompilationException"), equalTo(true)); - assertThat(ExceptionsHelper.detailedMessage(e) + "should have contained missing field error", - ExceptionsHelper.detailedMessage(e).contains("does not exist in mappings"), equalTo(true)); + assertThat(e.toString() + "should have contained ExpressionScriptCompilationException", + e.toString().contains("ExpressionScriptCompilationException"), equalTo(true)); + assertThat(e.toString() + "should have contained missing field error", + e.toString().contains("does not exist in mappings"), equalTo(true)); } } @@ -141,10 +141,10 @@ public class ExpressionScriptTests extends ElasticsearchIntegrationTest { buildRequest("garbage%@#%@").get(); fail("Expected expression compilation failure"); } catch (SearchPhaseExecutionException e) { - assertThat(ExceptionsHelper.detailedMessage(e) + "should have contained ExpressionScriptCompilationException", - ExceptionsHelper.detailedMessage(e).contains("ExpressionScriptCompilationException"), equalTo(true)); - assertThat(ExceptionsHelper.detailedMessage(e) + "should have contained compilation failure", - ExceptionsHelper.detailedMessage(e).contains("Failed to parse expression"), equalTo(true)); + assertThat(e.toString() + "should have contained ExpressionScriptCompilationException", + e.toString().contains("ExpressionScriptCompilationException"), equalTo(true)); + assertThat(e.toString() + "should have contained compilation failure", + e.toString().contains("Failed to parse expression"), equalTo(true)); } } @@ -154,10 +154,10 @@ public class ExpressionScriptTests extends ElasticsearchIntegrationTest { buildRequest("a", "a", "astring").get(); fail("Expected string parameter to cause failure"); } catch (SearchPhaseExecutionException e) { - assertThat(ExceptionsHelper.detailedMessage(e) + "should have contained ExpressionScriptCompilationException", - ExceptionsHelper.detailedMessage(e).contains("ExpressionScriptCompilationException"), equalTo(true)); - assertThat(ExceptionsHelper.detailedMessage(e) + "should have contained non-numeric parameter error", - ExceptionsHelper.detailedMessage(e).contains("must be a numeric type"), equalTo(true)); + assertThat(e.toString() + "should have contained ExpressionScriptCompilationException", + e.toString().contains("ExpressionScriptCompilationException"), equalTo(true)); + assertThat(e.toString() + "should have contained non-numeric parameter error", + e.toString().contains("must be a numeric type"), equalTo(true)); } } @@ -167,10 +167,10 @@ public class ExpressionScriptTests extends ElasticsearchIntegrationTest { buildRequest("doc['text'].value").get(); fail("Expected text field to cause execution failure"); } catch (SearchPhaseExecutionException e) { - assertThat(ExceptionsHelper.detailedMessage(e) + "should have contained ExpressionScriptCompilationException", - ExceptionsHelper.detailedMessage(e).contains("ExpressionScriptCompilationException"), equalTo(true)); - assertThat(ExceptionsHelper.detailedMessage(e) + "should have contained non-numeric field error", - ExceptionsHelper.detailedMessage(e).contains("must be numeric"), equalTo(true)); + assertThat(e.toString() + "should have contained ExpressionScriptCompilationException", + e.toString().contains("ExpressionScriptCompilationException"), equalTo(true)); + assertThat(e.toString() + "should have contained non-numeric field error", + e.toString().contains("must be numeric"), equalTo(true)); } } @@ -180,10 +180,10 @@ public class ExpressionScriptTests extends ElasticsearchIntegrationTest { buildRequest("bogus").get(); fail("Expected bogus variable to cause execution failure"); } catch (SearchPhaseExecutionException e) { - assertThat(ExceptionsHelper.detailedMessage(e) + "should have contained ExpressionScriptCompilationException", - ExceptionsHelper.detailedMessage(e).contains("ExpressionScriptCompilationException"), equalTo(true)); - assertThat(ExceptionsHelper.detailedMessage(e) + "should have contained unknown variable error", - ExceptionsHelper.detailedMessage(e).contains("Unknown variable"), equalTo(true)); + assertThat(e.toString() + "should have contained ExpressionScriptCompilationException", + e.toString().contains("ExpressionScriptCompilationException"), equalTo(true)); + assertThat(e.toString() + "should have contained unknown variable error", + e.toString().contains("Unknown variable"), equalTo(true)); } } @@ -193,10 +193,10 @@ public class ExpressionScriptTests extends ElasticsearchIntegrationTest { buildRequest("doc").get(); fail("Expected doc variable without field to cause execution failure"); } catch (SearchPhaseExecutionException e) { - assertThat(ExceptionsHelper.detailedMessage(e) + "should have contained ExpressionScriptCompilationException", - ExceptionsHelper.detailedMessage(e).contains("ExpressionScriptCompilationException"), equalTo(true)); - assertThat(ExceptionsHelper.detailedMessage(e) + "should have contained a missing specific field error", - ExceptionsHelper.detailedMessage(e).contains("must be used with a specific field"), equalTo(true)); + assertThat(e.toString() + "should have contained ExpressionScriptCompilationException", + e.toString().contains("ExpressionScriptCompilationException"), equalTo(true)); + assertThat(e.toString() + "should have contained a missing specific field error", + e.toString().contains("must be used with a specific field"), equalTo(true)); } } @@ -206,10 +206,10 @@ public class ExpressionScriptTests extends ElasticsearchIntegrationTest { buildRequest("doc['foo'].bogus").get(); fail("Expected bogus field member to cause execution failure"); } catch (SearchPhaseExecutionException e) { - assertThat(ExceptionsHelper.detailedMessage(e) + "should have contained ExpressionScriptCompilationException", - ExceptionsHelper.detailedMessage(e).contains("ExpressionScriptCompilationException"), equalTo(true)); - assertThat(ExceptionsHelper.detailedMessage(e) + "should have contained field member error", - ExceptionsHelper.detailedMessage(e).contains("Invalid member for field"), equalTo(true)); + assertThat(e.toString() + "should have contained ExpressionScriptCompilationException", + e.toString().contains("ExpressionScriptCompilationException"), equalTo(true)); + assertThat(e.toString() + "should have contained field member error", + e.toString().contains("Invalid member for field"), equalTo(true)); } } @@ -260,7 +260,7 @@ public class ExpressionScriptTests extends ElasticsearchIntegrationTest { assertThat(rsp.getShardFailures().length, greaterThan(0)); // at least the shards containing the docs should have failed message = rsp.getShardFailures()[0].reason(); } catch (SearchPhaseExecutionException e) { - message = ExceptionsHelper.detailedMessage(e); + message = e.toString(); } assertThat(message + "should have contained ExpressionScriptExecutionException", message.contains("ExpressionScriptExecutionException"), equalTo(true)); diff --git a/src/test/java/org/elasticsearch/search/aggregations/AggregationsIntegrationTests.java b/src/test/java/org/elasticsearch/search/aggregations/AggregationsIntegrationTests.java index e7b1d8fbc59..640ac7ffb81 100644 --- a/src/test/java/org/elasticsearch/search/aggregations/AggregationsIntegrationTests.java +++ b/src/test/java/org/elasticsearch/search/aggregations/AggregationsIntegrationTests.java @@ -57,7 +57,7 @@ public class AggregationsIntegrationTests extends ElasticsearchIntegrationTest { client().prepareSearch("index").setSearchType(SearchType.SCAN).setScroll(new TimeValue(500)).addAggregation(terms("f").field("f")).get(); fail(); } catch (SearchPhaseExecutionException e) { - assertTrue(e.getMessage(), e.getMessage().contains("aggregations are not supported with search_type=scan")); + assertTrue(e.toString(), e.toString().contains("aggregations are not supported with search_type=scan")); } } diff --git a/src/test/java/org/elasticsearch/search/aggregations/bucket/DateHistogramTests.java b/src/test/java/org/elasticsearch/search/aggregations/bucket/DateHistogramTests.java index b34d09bfc1a..b9f7e3e511d 100644 --- a/src/test/java/org/elasticsearch/search/aggregations/bucket/DateHistogramTests.java +++ b/src/test/java/org/elasticsearch/search/aggregations/bucket/DateHistogramTests.java @@ -1314,7 +1314,7 @@ public class DateHistogramTests extends ElasticsearchIntegrationTest { .actionGet(); fail(); } catch (SearchPhaseExecutionException e) { - assertThat(e.getMessage(), containsString("IllegalArgumentException")); + assertThat(e.toString(), containsString("IllegalArgumentException")); } } } diff --git a/src/test/java/org/elasticsearch/search/aggregations/bucket/HistogramTests.java b/src/test/java/org/elasticsearch/search/aggregations/bucket/HistogramTests.java index 58a50e8938a..9a6c7c0f9f1 100644 --- a/src/test/java/org/elasticsearch/search/aggregations/bucket/HistogramTests.java +++ b/src/test/java/org/elasticsearch/search/aggregations/bucket/HistogramTests.java @@ -1017,7 +1017,7 @@ public class HistogramTests extends ElasticsearchIntegrationTest { .addAggregation(histogram("histo").field(SINGLE_VALUED_FIELD_NAME).interval(-1).minDocCount(0)).execute().actionGet(); fail(); } catch (SearchPhaseExecutionException e) { - assertThat(e.getMessage(), containsString("Missing required field [interval]")); + assertThat(e.toString(), containsString("Missing required field [interval]")); } } diff --git a/src/test/java/org/elasticsearch/search/aggregations/bucket/NestedTests.java b/src/test/java/org/elasticsearch/search/aggregations/bucket/NestedTests.java index ac28cd4c8e4..d437eb34915 100644 --- a/src/test/java/org/elasticsearch/search/aggregations/bucket/NestedTests.java +++ b/src/test/java/org/elasticsearch/search/aggregations/bucket/NestedTests.java @@ -365,7 +365,7 @@ public class NestedTests extends ElasticsearchIntegrationTest { .execute().actionGet(); fail(); } catch (SearchPhaseExecutionException e) { - assertThat(e.getMessage(), containsString("[nested] nested path [incorrect] is not nested")); + assertThat(e.toString(), containsString("[nested] nested path [incorrect] is not nested")); } } diff --git a/src/test/java/org/elasticsearch/search/aggregations/bucket/TopHitsTests.java b/src/test/java/org/elasticsearch/search/aggregations/bucket/TopHitsTests.java index 0322b6cc8a7..70bedbdb40f 100644 --- a/src/test/java/org/elasticsearch/search/aggregations/bucket/TopHitsTests.java +++ b/src/test/java/org/elasticsearch/search/aggregations/bucket/TopHitsTests.java @@ -520,7 +520,7 @@ public class TopHitsTests extends ElasticsearchIntegrationTest { ).get(); fail(); } catch (SearchPhaseExecutionException e) { - assertThat(e.getMessage(), containsString("No mapping found for [xyz] in order to sort on")); + assertThat(e.toString(), containsString("No mapping found for [xyz] in order to sort on")); } } @@ -553,7 +553,7 @@ public class TopHitsTests extends ElasticsearchIntegrationTest { .get(); fail(); } catch (SearchPhaseExecutionException e) { - assertThat(e.getMessage(), containsString("Aggregator [top_tags_hits] of type [top_hits] cannot accept sub-aggregations")); + assertThat(e.toString(), containsString("Aggregator [top_tags_hits] of type [top_hits] cannot accept sub-aggregations")); } } diff --git a/src/test/java/org/elasticsearch/search/child/SimpleChildQuerySearchTests.java b/src/test/java/org/elasticsearch/search/child/SimpleChildQuerySearchTests.java index 00aad548d64..a536f64260d 100644 --- a/src/test/java/org/elasticsearch/search/child/SimpleChildQuerySearchTests.java +++ b/src/test/java/org/elasticsearch/search/child/SimpleChildQuerySearchTests.java @@ -108,14 +108,7 @@ import static org.elasticsearch.test.hamcrest.ElasticsearchAssertions.assertNoFa import static org.elasticsearch.test.hamcrest.ElasticsearchAssertions.assertSearchHit; import static org.elasticsearch.test.hamcrest.ElasticsearchAssertions.assertSearchHits; import static org.elasticsearch.test.hamcrest.ElasticsearchAssertions.hasId; -import static org.hamcrest.Matchers.anyOf; -import static org.hamcrest.Matchers.containsString; -import static org.hamcrest.Matchers.equalTo; -import static org.hamcrest.Matchers.greaterThan; -import static org.hamcrest.Matchers.greaterThanOrEqualTo; -import static org.hamcrest.Matchers.is; -import static org.hamcrest.Matchers.notNullValue; -import static org.hamcrest.Matchers.startsWith; +import static org.hamcrest.Matchers.*; /** * @@ -1612,13 +1605,13 @@ public class SimpleChildQuerySearchTests extends ElasticsearchIntegrationTest { client().prepareIndex("test", "child1", "c1").setParent("p1").setSource("c_field", "blue").get(); fail(); } catch (ElasticsearchIllegalArgumentException e) { - assertThat(e.getMessage(), equalTo("Can't specify parent if no parent field has been configured")); + assertThat(e.toString(), containsString("Can't specify parent if no parent field has been configured")); } try { client().prepareIndex("test", "child2", "c2").setParent("p1").setSource("c_field", "blue").get(); fail(); } catch (ElasticsearchIllegalArgumentException e) { - assertThat(e.getMessage(), equalTo("Can't specify parent if no parent field has been configured")); + assertThat(e.toString(), containsString("Can't specify parent if no parent field has been configured")); } refresh(); @@ -1645,7 +1638,7 @@ public class SimpleChildQuerySearchTests extends ElasticsearchIntegrationTest { .endObject().endObject()).get(); fail(); } catch (MergeMappingException e) { - assertThat(e.getMessage(), equalTo("Merge failed with failures {[The _parent field's type option can't be changed: [null]->[parent]]}")); + assertThat(e.toString(), containsString("Merge failed with failures {[The _parent field's type option can't be changed: [null]->[parent]]}")); } } @@ -2332,7 +2325,7 @@ public class SimpleChildQuerySearchTests extends ElasticsearchIntegrationTest { response = minMaxQuery("none", 3, 2, cutoff); fail(); } catch (SearchPhaseExecutionException e) { - assertThat(e.getMessage(), containsString("[has_child] 'max_children' is less than 'min_children'")); + assertThat(e.toString(), containsString("[has_child] 'max_children' is less than 'min_children'")); } // Score mode = SUM @@ -2412,7 +2405,7 @@ public class SimpleChildQuerySearchTests extends ElasticsearchIntegrationTest { response = minMaxQuery("sum", 3, 2, cutoff); fail(); } catch (SearchPhaseExecutionException e) { - assertThat(e.getMessage(), containsString("[has_child] 'max_children' is less than 'min_children'")); + assertThat(e.toString(), containsString("[has_child] 'max_children' is less than 'min_children'")); } // Score mode = MAX @@ -2492,7 +2485,7 @@ public class SimpleChildQuerySearchTests extends ElasticsearchIntegrationTest { response = minMaxQuery("max", 3, 2, cutoff); fail(); } catch (SearchPhaseExecutionException e) { - assertThat(e.getMessage(), containsString("[has_child] 'max_children' is less than 'min_children'")); + assertThat(e.toString(), containsString("[has_child] 'max_children' is less than 'min_children'")); } // Score mode = AVG @@ -2572,7 +2565,7 @@ public class SimpleChildQuerySearchTests extends ElasticsearchIntegrationTest { response = minMaxQuery("avg", 3, 2, cutoff); fail(); } catch (SearchPhaseExecutionException e) { - assertThat(e.getMessage(), containsString("[has_child] 'max_children' is less than 'min_children'")); + assertThat(e.toString(), containsString("[has_child] 'max_children' is less than 'min_children'")); } // HasChildFilter @@ -2652,7 +2645,7 @@ public class SimpleChildQuerySearchTests extends ElasticsearchIntegrationTest { response = minMaxFilter(3, 2, cutoff); fail(); } catch (SearchPhaseExecutionException e) { - assertThat(e.getMessage(), containsString("[has_child] 'max_children' is less than 'min_children'")); + assertThat(e.toString(), containsString("[has_child] 'max_children' is less than 'min_children'")); } } diff --git a/src/test/java/org/elasticsearch/search/functionscore/DecayFunctionScoreTests.java b/src/test/java/org/elasticsearch/search/functionscore/DecayFunctionScoreTests.java index 59ff93d27d8..315442a0022 100644 --- a/src/test/java/org/elasticsearch/search/functionscore/DecayFunctionScoreTests.java +++ b/src/test/java/org/elasticsearch/search/functionscore/DecayFunctionScoreTests.java @@ -874,8 +874,8 @@ public class DecayFunctionScoreTests extends ElasticsearchIntegrationTest { searchSource().query(query))).actionGet(); fail("Should fail with SearchPhaseExecutionException"); } catch (SearchPhaseExecutionException failure) { - assertTrue(failure.getMessage().contains("SearchParseException")); - assertFalse(failure.getMessage().contains("NullPointerException")); + assertTrue(failure.toString().contains("SearchParseException")); + assertFalse(failure.toString().contains("NullPointerException")); } query = "{\n" + @@ -908,26 +908,26 @@ public class DecayFunctionScoreTests extends ElasticsearchIntegrationTest { searchSource().query(query))).actionGet(); fail("Should fail with SearchPhaseExecutionException"); } catch (SearchPhaseExecutionException failure) { - assertTrue(failure.getMessage().contains("SearchParseException")); - assertFalse(failure.getMessage().contains("NullPointerException")); - assertTrue(failure.getMessage().contains("One entry in functions list is missing a function")); + assertTrue(failure.toString().contains("SearchParseException")); + assertFalse(failure.toString().contains("NullPointerException")); + assertTrue(failure.toString().contains("One entry in functions list is missing a function")); } // next test java client try { client().prepareSearch("t").setQuery(QueryBuilders.functionScoreQuery(FilterBuilders.matchAllFilter(), null)).get(); } catch (ElasticsearchIllegalArgumentException failure) { - assertTrue(failure.getMessage().contains("function must not be null")); + assertTrue(failure.toString().contains("function must not be null")); } try { client().prepareSearch("t").setQuery(QueryBuilders.functionScoreQuery().add(FilterBuilders.matchAllFilter(), null)).get(); } catch (ElasticsearchIllegalArgumentException failure) { - assertTrue(failure.getMessage().contains("function must not be null")); + assertTrue(failure.toString().contains("function must not be null")); } try { client().prepareSearch("t").setQuery(QueryBuilders.functionScoreQuery().add(null)).get(); } catch (ElasticsearchIllegalArgumentException failure) { - assertTrue(failure.getMessage().contains("function must not be null")); + assertTrue(failure.toString().contains("function must not be null")); } } diff --git a/src/test/java/org/elasticsearch/search/query/SearchQueryTests.java b/src/test/java/org/elasticsearch/search/query/SearchQueryTests.java index d0a5a6b357b..9d3b887fd19 100644 --- a/src/test/java/org/elasticsearch/search/query/SearchQueryTests.java +++ b/src/test/java/org/elasticsearch/search/query/SearchQueryTests.java @@ -483,7 +483,7 @@ public class SearchQueryTests extends ElasticsearchIntegrationTest { client().prepareSearch().setQuery(matchQuery("field1", "quick brown").type(MatchQueryBuilder.Type.PHRASE).slop(0)).get(); fail("SearchPhaseExecutionException should have been thrown"); } catch (SearchPhaseExecutionException e) { - assertTrue(e.getMessage().contains("IllegalStateException[field \"field1\" was indexed without position data; cannot run PhraseQuery")); + assertTrue(e.toString().contains("IllegalStateException[field \"field1\" was indexed without position data; cannot run PhraseQuery")); } cluster().wipeIndices("test"); } catch (MapperParsingException ex) { @@ -563,7 +563,7 @@ public class SearchQueryTests extends ElasticsearchIntegrationTest { fail("expected SearchPhaseExecutionException (total failure)"); } catch (SearchPhaseExecutionException e) { assertThat(e.status(), equalTo(RestStatus.BAD_REQUEST)); - assertThat(e.getMessage(), containsString("unit [D] not supported for date math")); + assertThat(e.toString(), containsString("unit [D] not supported for date math")); } } @@ -2493,8 +2493,8 @@ public class SearchQueryTests extends ElasticsearchIntegrationTest { .get(); fail("query is invalid and should have produced a parse exception"); } catch (Exception e) { - assertThat("query could not be parsed due to bad format: " + e.getMessage(), - e.getMessage().contains("Illegal value for id, expecting a string or number, got: START_ARRAY"), + assertThat("query could not be parsed due to bad format: " + e.toString(), + e.toString().contains("Illegal value for id, expecting a string or number, got: START_ARRAY"), equalTo(true)); } } diff --git a/src/test/java/org/elasticsearch/search/simple/SimpleSearchTests.java b/src/test/java/org/elasticsearch/search/simple/SimpleSearchTests.java index 2e3276107fa..f4a2e81df61 100644 --- a/src/test/java/org/elasticsearch/search/simple/SimpleSearchTests.java +++ b/src/test/java/org/elasticsearch/search/simple/SimpleSearchTests.java @@ -234,7 +234,7 @@ public class SimpleSearchTests extends ElasticsearchIntegrationTest { client().prepareSearch("idx").setFrom(Integer.MAX_VALUE).get(); fail(); } catch (SearchPhaseExecutionException e) { - assertThat(e.getMessage(), containsString("Result window is too large, from + size must be less than or equal to:")); + assertThat(e.toString(), containsString("Result window is too large, from + size must be less than or equal to:")); } } } diff --git a/src/test/java/org/elasticsearch/search/sort/SimpleSortTests.java b/src/test/java/org/elasticsearch/search/sort/SimpleSortTests.java index b40e5547b1a..7972df64741 100644 --- a/src/test/java/org/elasticsearch/search/sort/SimpleSortTests.java +++ b/src/test/java/org/elasticsearch/search/sort/SimpleSortTests.java @@ -1131,7 +1131,7 @@ public class SimpleSortTests extends ElasticsearchIntegrationTest { } catch (SearchPhaseExecutionException e) { //we check that it's a parse failure rather than a different shard failure for (ShardSearchFailure shardSearchFailure : e.shardFailures()) { - assertThat(shardSearchFailure.reason(), containsString("Parse Failure [No mapping found for [kkk] in order to sort on]")); + assertThat(shardSearchFailure.toString(), containsString("[No mapping found for [kkk] in order to sort on]")); } } diff --git a/src/test/java/org/elasticsearch/search/suggest/CompletionSuggestSearchTests.java b/src/test/java/org/elasticsearch/search/suggest/CompletionSuggestSearchTests.java index b2528428297..f4c7c74933f 100644 --- a/src/test/java/org/elasticsearch/search/suggest/CompletionSuggestSearchTests.java +++ b/src/test/java/org/elasticsearch/search/suggest/CompletionSuggestSearchTests.java @@ -23,7 +23,6 @@ import com.carrotsearch.randomizedtesting.generators.RandomStrings; import com.google.common.collect.Lists; import org.apache.lucene.util.LuceneTestCase.SuppressCodecs; -import org.elasticsearch.ExceptionsHelper; import org.elasticsearch.action.admin.indices.mapping.put.PutMappingResponse; import org.elasticsearch.action.admin.indices.optimize.OptimizeResponse; import org.elasticsearch.action.admin.indices.segments.IndexShardSegments; @@ -50,7 +49,6 @@ import org.elasticsearch.search.suggest.completion.CompletionSuggestion; import org.elasticsearch.search.suggest.completion.CompletionSuggestionBuilder; import org.elasticsearch.search.suggest.completion.CompletionSuggestionFuzzyBuilder; import org.elasticsearch.test.ElasticsearchIntegrationTest; -import org.elasticsearch.test.hamcrest.ElasticsearchAssertions; import org.junit.Test; import java.io.IOException; @@ -177,7 +175,7 @@ public class CompletionSuggestSearchTests extends ElasticsearchIntegrationTest { ).get(); fail("Indexing with a float weight was successful, but should not be"); } catch (MapperParsingException e) { - assertThat(ExceptionsHelper.detailedMessage(e), containsString("2.5")); + assertThat(e.toString(), containsString("2.5")); } } @@ -221,7 +219,7 @@ public class CompletionSuggestSearchTests extends ElasticsearchIntegrationTest { ).get(); fail("Indexing with a non-number representing string as weight was successful, but should not be"); } catch (MapperParsingException e) { - assertThat(ExceptionsHelper.detailedMessage(e), containsString("thisIsNotValid")); + assertThat(e.toString(), containsString("thisIsNotValid")); } } @@ -239,7 +237,7 @@ public class CompletionSuggestSearchTests extends ElasticsearchIntegrationTest { ).get(); fail("Indexing with weight string representing value > Int.MAX_VALUE was successful, but should not be"); } catch (MapperParsingException e) { - assertThat(ExceptionsHelper.detailedMessage(e), containsString(weight)); + assertThat(e.toString(), containsString(weight)); } } @@ -774,7 +772,7 @@ public class CompletionSuggestSearchTests extends ElasticsearchIntegrationTest { fail("Expected an exception due to trying to sort on completion field, but did not happen"); } catch (SearchPhaseExecutionException e) { assertThat(e.status().getStatus(), is(400)); - assertThat(e.getMessage(), containsString("Sorting not supported for field[" + FIELD + "]")); + assertThat(e.toString(), containsString("Sorting not supported for field[" + FIELD + "]")); } } @@ -1096,7 +1094,7 @@ public class CompletionSuggestSearchTests extends ElasticsearchIntegrationTest { // Exception must be thrown assertFalse(true); } catch (SearchPhaseExecutionException e) { - assertTrue(e.getDetailedMessage().contains("found no fielddata type for field [" + FIELD + "]")); + assertTrue(e.toString().contains("found no fielddata type for field [" + FIELD + "]")); } } diff --git a/src/test/java/org/elasticsearch/test/hamcrest/ElasticsearchAssertions.java b/src/test/java/org/elasticsearch/test/hamcrest/ElasticsearchAssertions.java index c691f3c5834..0a52c36ce32 100644 --- a/src/test/java/org/elasticsearch/test/hamcrest/ElasticsearchAssertions.java +++ b/src/test/java/org/elasticsearch/test/hamcrest/ElasticsearchAssertions.java @@ -310,7 +310,7 @@ public class ElasticsearchAssertions { assertVersionSerializable(searchResponse); } catch (SearchPhaseExecutionException e) { assertThat(e.status(), equalTo(restStatus)); - assertThat(e.getMessage(), reasonMatcher); + assertThat(e.toString(), reasonMatcher); for (ShardSearchFailure shardSearchFailure : e.shardFailures()) { assertThat(shardSearchFailure.status(), equalTo(restStatus)); assertThat(shardSearchFailure.reason(), reasonMatcher); From dd4a22bfedf4a3c0c34ea598dfd97903d09b6396 Mon Sep 17 00:00:00 2001 From: Martijn van Groningen Date: Fri, 24 Apr 2015 00:39:31 +0200 Subject: [PATCH 06/14] bulk: Fields defined in the `_default_` mapping of an index template should be picked up when an index alias filter is parsed if a new index is introduced when a document is indexed into an index that doesn't exist yet via the bulk api. Closes #10609 --- .../action/bulk/TransportBulkAction.java | 24 +++++++--- .../template/SimpleIndexTemplateTests.java | 46 +++++++++++++++---- 2 files changed, 55 insertions(+), 15 deletions(-) diff --git a/src/main/java/org/elasticsearch/action/bulk/TransportBulkAction.java b/src/main/java/org/elasticsearch/action/bulk/TransportBulkAction.java index 4cdc4887060..8d3ad3de9cd 100644 --- a/src/main/java/org/elasticsearch/action/bulk/TransportBulkAction.java +++ b/src/main/java/org/elasticsearch/action/bulk/TransportBulkAction.java @@ -21,7 +21,6 @@ package org.elasticsearch.action.bulk; import com.google.common.collect.Lists; import com.google.common.collect.Maps; -import com.google.common.collect.Sets; import org.elasticsearch.ElasticsearchException; import org.elasticsearch.ElasticsearchParseException; import org.elasticsearch.ExceptionsHelper; @@ -100,22 +99,33 @@ public class TransportBulkAction extends HandledTransportAction responses = new AtomicArray<>(bulkRequest.requests.size()); if (autoCreateIndex.needToCheck()) { - final Set indices = Sets.newHashSet(); + // Keep track of all unique indices and all unique types per index for the create index requests: + final Map> indicesAndTypes = new HashMap<>(); for (ActionRequest request : bulkRequest.requests) { if (request instanceof DocumentRequest) { DocumentRequest req = (DocumentRequest) request; - if (!indices.contains(req.index())) { - indices.add(req.index()); + Set types = indicesAndTypes.get(req.index()); + if (types == null) { + indicesAndTypes.put(req.index(), types = new HashSet<>()); } + types.add(req.type()); } else { throw new ElasticsearchException("Parsed unknown request in bulk actions: " + request.getClass().getSimpleName()); } } - final AtomicInteger counter = new AtomicInteger(indices.size()); + final AtomicInteger counter = new AtomicInteger(indicesAndTypes.size()); ClusterState state = clusterService.state(); - for (final String index : indices) { + for (Map.Entry> entry : indicesAndTypes.entrySet()) { + final String index = entry.getKey(); if (autoCreateIndex.shouldAutoCreate(index, state)) { - createIndexAction.execute(new CreateIndexRequest(bulkRequest).index(index).cause("auto(bulk api)").masterNodeTimeout(bulkRequest.timeout()), new ActionListener() { + CreateIndexRequest createIndexRequest = new CreateIndexRequest(bulkRequest); + createIndexRequest.index(index); + for (String type : entry.getValue()) { + createIndexRequest.mapping(type); + } + createIndexRequest.cause("auto(bulk api)"); + createIndexRequest.masterNodeTimeout(bulkRequest.timeout()); + createIndexAction.execute(createIndexRequest, new ActionListener() { @Override public void onResponse(CreateIndexResponse result) { if (counter.decrementAndGet() == 0) { diff --git a/src/test/java/org/elasticsearch/indices/template/SimpleIndexTemplateTests.java b/src/test/java/org/elasticsearch/indices/template/SimpleIndexTemplateTests.java index e02c2bef8b4..1c3f8f8c9ca 100644 --- a/src/test/java/org/elasticsearch/indices/template/SimpleIndexTemplateTests.java +++ b/src/test/java/org/elasticsearch/indices/template/SimpleIndexTemplateTests.java @@ -29,6 +29,8 @@ import org.elasticsearch.action.admin.indices.alias.get.GetAliasesResponse; import org.elasticsearch.action.admin.indices.settings.get.GetSettingsResponse; import org.elasticsearch.action.admin.indices.template.get.GetIndexTemplatesResponse; import org.elasticsearch.action.admin.indices.template.put.PutIndexTemplateRequestBuilder; +import org.elasticsearch.action.bulk.BulkResponse; +import org.elasticsearch.action.index.IndexRequest; import org.elasticsearch.action.search.SearchResponse; import org.elasticsearch.cluster.metadata.AliasMetaData; import org.elasticsearch.common.Priority; @@ -604,38 +606,66 @@ public class SimpleIndexTemplateTests extends ElasticsearchIntegrationTest { public void testStrictAliasParsingInIndicesCreatedViaTemplates() throws Exception { // Indexing into a should succeed, because the field mapping for field 'field' is defined in the test mapping. client().admin().indices().preparePutTemplate("template1") - .setTemplate("a") + .setTemplate("a*") .setOrder(0) .addMapping("test", "field", "type=string") .addAlias(new Alias("alias1").filter(termFilter("field", "value"))).get(); // Indexing into b should succeed, because the field mapping for field 'field' is defined in the _default_ mapping and the test type exists. client().admin().indices().preparePutTemplate("template2") - .setTemplate("b") + .setTemplate("b*") .setOrder(0) .addMapping("_default_", "field", "type=string") .addMapping("test") .addAlias(new Alias("alias2").filter(termFilter("field", "value"))).get(); // Indexing into c should succeed, because the field mapping for field 'field' is defined in the _default_ mapping. client().admin().indices().preparePutTemplate("template3") - .setTemplate("c") + .setTemplate("c*") .setOrder(0) .addMapping("_default_", "field", "type=string") .addAlias(new Alias("alias3").filter(termFilter("field", "value"))).get(); // Indexing into d index should fail, since there is field with name 'field' in the mapping client().admin().indices().preparePutTemplate("template4") - .setTemplate("d") + .setTemplate("d*") .setOrder(0) .addAlias(new Alias("alias4").filter(termFilter("field", "value"))).get(); - client().prepareIndex("a", "test", "test").setSource("{}").get(); - client().prepareIndex("b", "test", "test").setSource("{}").get(); - client().prepareIndex("c", "test", "test").setSource("{}").get(); + client().prepareIndex("a1", "test", "test").setSource("{}").get(); + BulkResponse response = client().prepareBulk().add(new IndexRequest("a2", "test", "test").source("{}")).get(); + assertThat(response.hasFailures(), is(false)); + assertThat(response.getItems()[0].isFailed(), equalTo(false)); + assertThat(response.getItems()[0].getIndex(), equalTo("a2")); + assertThat(response.getItems()[0].getType(), equalTo("test")); + assertThat(response.getItems()[0].getId(), equalTo("test")); + assertThat(response.getItems()[0].getVersion(), equalTo(1l)); + + client().prepareIndex("b1", "test", "test").setSource("{}").get(); + response = client().prepareBulk().add(new IndexRequest("b2", "test", "test").source("{}")).get(); + assertThat(response.hasFailures(), is(false)); + assertThat(response.getItems()[0].isFailed(), equalTo(false)); + assertThat(response.getItems()[0].getIndex(), equalTo("b2")); + assertThat(response.getItems()[0].getType(), equalTo("test")); + assertThat(response.getItems()[0].getId(), equalTo("test")); + assertThat(response.getItems()[0].getVersion(), equalTo(1l)); + + client().prepareIndex("c1", "test", "test").setSource("{}").get(); + response = client().prepareBulk().add(new IndexRequest("c2", "test", "test").source("{}")).get(); + assertThat(response.hasFailures(), is(false)); + assertThat(response.getItems()[0].isFailed(), equalTo(false)); + assertThat(response.getItems()[0].getIndex(), equalTo("c2")); + assertThat(response.getItems()[0].getType(), equalTo("test")); + assertThat(response.getItems()[0].getId(), equalTo("test")); + assertThat(response.getItems()[0].getVersion(), equalTo(1l)); + try { - client().prepareIndex("d", "test", "test").setSource("{}").get(); + client().prepareIndex("d1", "test", "test").setSource("{}").get(); fail(); } catch (Exception e) { assertThat(ExceptionsHelper.unwrapCause(e), instanceOf(ElasticsearchIllegalArgumentException.class)); assertThat(e.getMessage(), containsString("failed to parse filter for alias [alias4]")); } + response = client().prepareBulk().add(new IndexRequest("d2", "test", "test").source("{}")).get(); + assertThat(response.hasFailures(), is(true)); + assertThat(response.getItems()[0].isFailed(), equalTo(true)); + assertThat(response.getItems()[0].getFailureMessage(), containsString("failed to parse filter for alias [alias4]")); } } From 84549f334d99aad394b41d60b558135712d4591a Mon Sep 17 00:00:00 2001 From: Simon Willnauer Date: Fri, 24 Apr 2015 10:09:24 +0200 Subject: [PATCH 07/14] [TEST] use toString rather than getDetailedMessage() --- src/test/java/org/elasticsearch/script/IndexLookupTests.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/test/java/org/elasticsearch/script/IndexLookupTests.java b/src/test/java/org/elasticsearch/script/IndexLookupTests.java index a9a61555b3a..cc1900a3fb2 100644 --- a/src/test/java/org/elasticsearch/script/IndexLookupTests.java +++ b/src/test/java/org/elasticsearch/script/IndexLookupTests.java @@ -581,8 +581,8 @@ public class IndexLookupTests extends ElasticsearchIntegrationTest { } } catch (SearchPhaseExecutionException ex) { assertThat( - "got " + ex.getDetailedMessage(), - ex.getDetailedMessage().indexOf("Cannot iterate twice! If you want to iterate more that once, add _CACHE explicitly."), + "got " + ex.toString(), + ex.toString().indexOf("Cannot iterate twice! If you want to iterate more that once, add _CACHE explicitly."), Matchers.greaterThan(-1)); } } From 3ff0b21c21f7843ecced4b0042bfbc31fb8070b2 Mon Sep 17 00:00:00 2001 From: Simon Willnauer Date: Fri, 24 Apr 2015 10:37:55 +0200 Subject: [PATCH 08/14] Remove dead code --- .../TransportShardReplicationOperationAction.java | 10 ++-------- 1 file changed, 2 insertions(+), 8 deletions(-) diff --git a/src/main/java/org/elasticsearch/action/support/replication/TransportShardReplicationOperationAction.java b/src/main/java/org/elasticsearch/action/support/replication/TransportShardReplicationOperationAction.java index 6b9e4ca14d8..9c7b65bc939 100644 --- a/src/main/java/org/elasticsearch/action/support/replication/TransportShardReplicationOperationAction.java +++ b/src/main/java/org/elasticsearch/action/support/replication/TransportShardReplicationOperationAction.java @@ -247,8 +247,8 @@ public abstract class TransportShardReplicationOperationAction= 0; - //older nodes will send the concrete index as part of the request - shardId = new ShardId(request.index(), shard); - } } @Override From b444d2c31a9f7bfc9a200592e4c1db7881a7791c Mon Sep 17 00:00:00 2001 From: Martijn van Groningen Date: Fri, 24 Apr 2015 12:05:58 +0200 Subject: [PATCH 09/14] Test: wait for green --- .../elasticsearch/fieldstats/FieldStatsIntegrationTests.java | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/test/java/org/elasticsearch/fieldstats/FieldStatsIntegrationTests.java b/src/test/java/org/elasticsearch/fieldstats/FieldStatsIntegrationTests.java index e31b60a2380..491b281b9f9 100644 --- a/src/test/java/org/elasticsearch/fieldstats/FieldStatsIntegrationTests.java +++ b/src/test/java/org/elasticsearch/fieldstats/FieldStatsIntegrationTests.java @@ -45,6 +45,7 @@ public class FieldStatsIntegrationTests extends ElasticsearchIntegrationTest { "test", "string", "type=string", "date", "type=date", "double", "type=double", "double", "type=double", "float", "type=float", "long", "type=long", "integer", "type=integer", "short", "type=short", "byte", "type=byte" )); + ensureGreen("test"); byte minByte = Byte.MAX_VALUE; byte maxByte = Byte.MIN_VALUE; @@ -129,6 +130,7 @@ public class FieldStatsIntegrationTests extends ElasticsearchIntegrationTest { assertAcked(prepareCreate("test3").addMapping( "test", "value", "type=long" )); + ensureGreen("test1", "test2", "test3"); indexRange("test1", -10, 100); indexRange("test2", 101, 200); @@ -180,6 +182,7 @@ public class FieldStatsIntegrationTests extends ElasticsearchIntegrationTest { assertAcked(prepareCreate("test2").addMapping( "test", "value", "type=string" )); + ensureGreen("test1", "test2"); client().prepareIndex("test1", "test").setSource("value", 1l).get(); client().prepareIndex("test1", "test").setSource("value", 2l).get(); From 5bdfdc42d99b12e7999fb36c8f1a72d43d7b5606 Mon Sep 17 00:00:00 2001 From: Boaz Leskes Date: Tue, 21 Apr 2015 15:52:44 +0200 Subject: [PATCH 10/14] Refactor TransportShardReplicationOperationAction Refactor TransportShardReplicationOperationAction state management into clear separate Primary phase and Replication phase. The primary phase is responsible for routing the request to the node holding the primary, validating it and performing the operation on the primary. The Replication phase is responsible for sending the request to the replicas and managing their responses. This also adds unit test infrastructure for this class, and some basic tests. We can extend later as we continue developing. Closes #10749 --- ...nsportShardReplicationOperationAction.java | 790 ++++++++++-------- .../transport/DummyTransportAddress.java | 5 + .../ShardReplicationOperationTests.java | 586 +++++++++++++ .../test/cluster/TestClusterService.java | 249 ++++++ .../test/transport/CapturingTransport.java | 180 ++++ 5 files changed, 1458 insertions(+), 352 deletions(-) create mode 100644 src/test/java/org/elasticsearch/action/support/replication/ShardReplicationOperationTests.java create mode 100644 src/test/java/org/elasticsearch/test/cluster/TestClusterService.java create mode 100644 src/test/java/org/elasticsearch/test/transport/CapturingTransport.java diff --git a/src/main/java/org/elasticsearch/action/support/replication/TransportShardReplicationOperationAction.java b/src/main/java/org/elasticsearch/action/support/replication/TransportShardReplicationOperationAction.java index 9c7b65bc939..529586927fd 100644 --- a/src/main/java/org/elasticsearch/action/support/replication/TransportShardReplicationOperationAction.java +++ b/src/main/java/org/elasticsearch/action/support/replication/TransportShardReplicationOperationAction.java @@ -20,7 +20,6 @@ package org.elasticsearch.action.support.replication; import org.elasticsearch.ElasticsearchException; -import org.elasticsearch.ElasticsearchIllegalStateException; import org.elasticsearch.ExceptionsHelper; import org.elasticsearch.Version; import org.elasticsearch.action.*; @@ -100,7 +99,7 @@ public abstract class TransportShardReplicationOperationAction listener) { - new AsyncShardOperationAction(request, listener).start(); + new PrimaryPhase(request, listener).run(); } protected abstract Request newRequestInstance(); @@ -112,10 +111,10 @@ public abstract class TransportShardReplicationOperationAction shardOperationOnPrimary(ClusterState clusterState, PrimaryOperationRequest shardRequest) throws Throwable; + protected abstract Tuple shardOperationOnPrimary(ClusterState clusterState, PrimaryOperationRequest shardRequest) throws Throwable; protected abstract void shardOperationOnReplica(ReplicaOperationRequest shardRequest) throws Exception; @@ -296,149 +295,163 @@ public abstract class TransportShardReplicationOperationAction + * Note that as soon as we start sending request to replicas, state responsibility is transferred to {@link ReplicationPhase} + */ + final class PrimaryPhase extends AbstractRunnable { private final ActionListener listener; private final InternalRequest internalRequest; - private volatile ShardIterator shardIt; - private final AtomicBoolean primaryOperationStarted = new AtomicBoolean(); - private volatile ClusterStateObserver observer; + private final ClusterStateObserver observer; + private final AtomicBoolean finished = new AtomicBoolean(false); - AsyncShardOperationAction(Request request, ActionListener listener) { + + PrimaryPhase(Request request, ActionListener listener) { this.internalRequest = new InternalRequest(request); this.listener = listener; - } - - public void start() { this.observer = new ClusterStateObserver(clusterService, internalRequest.request().timeout(), logger); - doStart(); } - /** - * Returns true if the action starting to be performed on the primary (or is done). - */ - protected void doStart() throws ElasticsearchException { - try { - ClusterBlockException blockException = checkGlobalBlock(observer.observedState()); - if (blockException != null) { - if (blockException.retryable()) { - logger.trace("cluster is blocked ({}), scheduling a retry", blockException.getMessage()); - retry(blockException); - return; - } else { - throw blockException; - } - } - if (resolveIndex()) { - internalRequest.concreteIndex(observer.observedState().metaData().concreteSingleIndex(internalRequest.request().index(), internalRequest.request().indicesOptions())); - } else { - internalRequest.concreteIndex(internalRequest.request().index()); - } + @Override + public void onFailure(Throwable e) { + finishWithUnexpectedFailure(e); + } - resolveRequest(observer.observedState(), internalRequest, listener); - - blockException = checkRequestBlock(observer.observedState(), internalRequest); - if (blockException != null) { - if (blockException.retryable()) { - logger.trace("cluster is blocked ({}), scheduling a retry", blockException.getMessage()); - retry(blockException); - return; - } else { - throw blockException; - } - } - shardIt = shards(observer.observedState(), internalRequest); - } catch (Throwable e) { - listener.onFailure(e); + protected void doRun() { + if (checkBlocks() == false) { return; } - - // no shardIt, might be in the case between index gateway recovery and shardIt initialization - if (shardIt.size() == 0) { - logger.trace("no shard instances known for shard [{}], scheduling a retry", shardIt.shardId()); + final ShardIterator shardIt = shards(observer.observedState(), internalRequest); + final ShardRouting primary = resolvePrimary(shardIt); + if (primary == null) { retryBecauseUnavailable(shardIt.shardId(), "No active shards."); return; } + if (primary.active() == false) { + logger.trace("primary shard [{}] is not yet active, scheduling a retry.", primary.shardId()); + retryBecauseUnavailable(shardIt.shardId(), "Primary shard is not active or isn't assigned to a known node."); + return; + } + if (observer.observedState().nodes().nodeExists(primary.currentNodeId()) == false) { + logger.trace("primary shard [{}] is assigned to anode we do not know the node, scheduling a retry.", primary.shardId(), primary.currentNodeId()); + retryBecauseUnavailable(shardIt.shardId(), "Primary shard is not active or isn't assigned to a known node."); + return; + } + routeRequestOrPerformLocally(primary, shardIt); + } - boolean foundPrimary = false; - ShardRouting shardX; - while ((shardX = shardIt.nextOrNull()) != null) { - final ShardRouting shard = shardX; - // we only deal with primary shardIt here... - if (!shard.primary()) { - continue; - } - if (!shard.active() || !observer.observedState().nodes().nodeExists(shard.currentNodeId())) { - logger.trace("primary shard [{}] is not yet active or we do not know the node it is assigned to [{}], scheduling a retry.", shard.shardId(), shard.currentNodeId()); - retryBecauseUnavailable(shardIt.shardId(), "Primary shard is not active or isn't assigned to a known node."); - return; - } - - if (!primaryOperationStarted.compareAndSet(false, true)) { - return; - } - - foundPrimary = true; - if (shard.currentNodeId().equals(observer.observedState().nodes().localNodeId())) { - try { - if (internalRequest.request().operationThreaded()) { - threadPool.executor(executor).execute(new Runnable() { - @Override - public void run() { - try { - performOnPrimary(shard.id(), shard); - } catch (Throwable t) { - listener.onFailure(t); - } - } - }); - } else { - performOnPrimary(shard.id(), shard); - } - } catch (Throwable t) { - listener.onFailure(t); - } + /** + * checks for any cluster state blocks. Returns true if operation is OK to proceeded. + * if false is return, no further action is needed. The method takes care of any continuation, by either + * responding to the listener or scheduling a retry + */ + protected boolean checkBlocks() { + ClusterBlockException blockException = checkGlobalBlock(observer.observedState()); + if (blockException != null) { + if (blockException.retryable()) { + logger.trace("cluster is blocked ({}), scheduling a retry", blockException.getMessage()); + retry(blockException); } else { - DiscoveryNode node = observer.observedState().nodes().get(shard.currentNodeId()); - transportService.sendRequest(node, actionName, internalRequest.request(), transportOptions, new BaseTransportResponseHandler() { + finishAsFailed(blockException); + } + return false; + } + if (resolveIndex()) { + internalRequest.concreteIndex(observer.observedState().metaData().concreteSingleIndex(internalRequest.request().index(), internalRequest.request().indicesOptions())); + } else { + internalRequest.concreteIndex(internalRequest.request().index()); + } - @Override - public Response newInstance() { - return newResponseInstance(); - } + resolveRequest(observer.observedState(), internalRequest, listener); - @Override - public String executor() { - return ThreadPool.Names.SAME; - } + blockException = checkRequestBlock(observer.observedState(), internalRequest); + if (blockException != null) { + if (blockException.retryable()) { + logger.trace("cluster is blocked ({}), scheduling a retry", blockException.getMessage()); + retry(blockException); + } else { + finishAsFailed(blockException); + } + return false; + } + return true; + } - @Override - public void handleResponse(Response response) { - listener.onResponse(response); - } + protected ShardRouting resolvePrimary(ShardIterator shardIt) { + // no shardIt, might be in the case between index gateway recovery and shardIt initialization + ShardRouting shard; + while ((shard = shardIt.nextOrNull()) != null) { + // we only deal with primary shardIt here... + if (shard.primary()) { + return shard; + } + } + return null; + } - @Override - public void handleException(TransportException exp) { + /** send the request to the node holding the primary or execute if local */ + protected void routeRequestOrPerformLocally(final ShardRouting primary, final ShardIterator shardsIt) { + if (primary.currentNodeId().equals(observer.observedState().nodes().localNodeId())) { + try { + if (internalRequest.request().operationThreaded()) { + threadPool.executor(executor).execute(new AbstractRunnable() { + @Override + public void onFailure(Throwable t) { + finishAsFailed(t); + } + + @Override + protected void doRun() throws Exception { + performOnPrimary(primary, shardsIt); + } + }); + } else { + performOnPrimary(primary, shardsIt); + } + } catch (Throwable t) { + // no commit: check threadpool rejection. + finishAsFailed(t); + } + } else { + DiscoveryNode node = observer.observedState().nodes().get(primary.currentNodeId()); + transportService.sendRequest(node, actionName, internalRequest.request(), transportOptions, new BaseTransportResponseHandler() { + + @Override + public Response newInstance() { + return newResponseInstance(); + } + + @Override + public String executor() { + return ThreadPool.Names.SAME; + } + + @Override + public void handleResponse(Response response) { + finishOnRemoteSuccess(response); + } + + @Override + public void handleException(TransportException exp) { + try { // if we got disconnected from the node, or the node / shard is not in the right state (being closed) if (exp.unwrapCause() instanceof ConnectTransportException || exp.unwrapCause() instanceof NodeClosedException || retryPrimaryException(exp)) { - primaryOperationStarted.set(false); internalRequest.request().setCanHaveDuplicates(); // we already marked it as started when we executed it (removed the listener) so pass false // to re-add to the cluster listener logger.trace("received an error from node the primary was assigned to ({}), scheduling a retry", exp.getMessage()); retry(exp); } else { - listener.onFailure(exp); + finishAsFailed(exp); } + } catch (Throwable t) { + finishWithUnexpectedFailure(t); } - }); - } - break; - } - // we won't find a primary if there are no shards in the shard iterator, retry... - if (!foundPrimary) { - logger.trace("couldn't find a eligible primary shard, scheduling for retry."); - retryBecauseUnavailable(shardIt.shardId(), "No active shards."); + } + }); } } @@ -446,7 +459,7 @@ public abstract class TransportShardReplicationOperationAction primaryResponse = shardOperationOnPrimary(clusterState, por); - performReplicas(por, primaryResponse); + PrimaryOperationRequest por = new PrimaryOperationRequest(primary.id(), internalRequest.concreteIndex(), internalRequest.request()); + Tuple primaryResponse = shardOperationOnPrimary(observer.observedState(), por); + logger.trace("operation completed on primary [{}]", primary); + replicationPhase = new ReplicationPhase(shardsIt, primaryResponse.v2(), primaryResponse.v1(), observer, primary, internalRequest, listener); } catch (Throwable e) { internalRequest.request.setCanHaveDuplicates(); // shard has not been allocated yet, retry it here if (retryPrimaryException(e)) { - primaryOperationStarted.set(false); logger.trace("had an error while performing operation on primary ({}), scheduling a retry.", e.getMessage()); retry(e); return; } if (ExceptionsHelper.status(e) == RestStatus.CONFLICT) { if (logger.isTraceEnabled()) { - logger.trace(shard.shortSummary() + ": Failed to execute [" + internalRequest.request() + "]", e); + logger.trace(primary.shortSummary() + ": Failed to execute [" + internalRequest.request() + "]", e); } } else { if (logger.isDebugEnabled()) { - logger.debug(shard.shortSummary() + ": Failed to execute [" + internalRequest.request() + "]", e); + logger.debug(primary.shortSummary() + ": Failed to execute [" + internalRequest.request() + "]", e); } } - listener.onFailure(e); - } - } - - void performReplicas(PrimaryOperationRequest por, Tuple primaryResponse) { - ShardRouting shard; - // we double check on the state, if it got changed we need to make sure we take the latest one cause - // maybe a replica shard started its recovery process and we need to apply it there... - - // we also need to make sure if the new state has a new primary shard (that we indexed to before) started - // and assigned to another node (while the indexing happened). In that case, we want to apply it on the - // new primary shard as well... - ClusterState newState = clusterService.state(); - ShardRouting newPrimaryShard = null; - int numberOfUnassignedReplicas = 0; - if (observer.observedState() != newState) { - shardIt.reset(); - ShardRouting originalPrimaryShard = null; - while ((shard = shardIt.nextOrNull()) != null) { - if (shard.primary()) { - originalPrimaryShard = shard; - break; - } - } - if (originalPrimaryShard == null || !originalPrimaryShard.active()) { - throw new ElasticsearchIllegalStateException("unexpected state, failed to find primary shard on an index operation that succeeded"); - } - - observer.reset(newState); - shardIt = shards(newState, internalRequest); - while ((shard = shardIt.nextOrNull()) != null) { - if (shard.primary()) { - if (originalPrimaryShard.currentNodeId().equals(shard.currentNodeId())) { - newPrimaryShard = null; - } else { - newPrimaryShard = shard; - } - } - - if (!shard.primary() && shard.unassigned()) { - numberOfUnassignedReplicas++; - } - } - shardIt.reset(); - internalRequest.request().setCanHaveDuplicates(); // safe side, cluster state changed, we might have dups - } else { - shardIt.reset(); - while ((shard = shardIt.nextOrNull()) != null) { - if (shard.state() != ShardRoutingState.STARTED) { - internalRequest.request().setCanHaveDuplicates(); - } - if (!shard.primary() && shard.unassigned()) { - numberOfUnassignedReplicas++; - } - } - shardIt.reset(); - } - - int numberOfPendingShardInstances = shardIt.assignedReplicasIncludingRelocating(); - if (newPrimaryShard != null) { - numberOfPendingShardInstances++; - } - ReplicationState replicationState = new ReplicationState(por, shardIt, primaryResponse.v1(), primaryResponse.v2(), listener, numberOfPendingShardInstances, numberOfUnassignedReplicas); - if (numberOfPendingShardInstances == 0) { - replicationState.forceFinish(); + finishAsFailed(e); return; } - IndexMetaData indexMetaData = observer.observedState().metaData().index(internalRequest.concreteIndex()); - if (newPrimaryShard != null) { - performOnReplica(replicationState, newPrimaryShard, newPrimaryShard.currentNodeId(), indexMetaData); - } - - shardIt.reset(); // reset the iterator - while ((shard = shardIt.nextOrNull()) != null) { - // if its unassigned, nothing to do here... - if (shard.unassigned()) { - continue; - } - - // if the shard is primary and relocating, add one to the counter since we perform it on the replica as well - // (and we already did it on the primary) - boolean doOnlyOnRelocating = false; - if (shard.primary()) { - if (shard.relocating()) { - doOnlyOnRelocating = true; - } else { - continue; - } - } - // we index on a replica that is initializing as well since we might not have got the event - // yet that it was started. We will get an exception IllegalShardState exception if its not started - // and that's fine, we will ignore it - if (!doOnlyOnRelocating) { - performOnReplica(replicationState, shard, shard.currentNodeId(), indexMetaData); - } - if (shard.relocating()) { - performOnReplica(replicationState, shard, shard.relocatingNodeId(), indexMetaData); - } - } + finishAndMoveToReplication(replicationPhase); } - void performOnReplica(final ReplicationState state, final ShardRouting shard, final String nodeId, final IndexMetaData indexMetaData) { - // if we don't have that node, it means that it might have failed and will be created again, in - // this case, we don't have to do the operation, and just let it failover - if (!observer.observedState().nodes().nodeExists(nodeId)) { - state.onReplicaFailure(nodeId, null); - return; - } - - final ReplicaOperationRequest shardRequest = new ReplicaOperationRequest(shardIt.shardId(), state.replicaRequest()); - - // If the replicas use shadow replicas, there is no reason to - // perform the action on the replica, so skip it and - // immediately return - if (IndexMetaData.isIndexUsingShadowReplicas(indexMetaData.settings())) { - // this delays mapping updates on replicas because they have - // to wait until they get the new mapping through the cluster - // state, which is why we recommend pre-defined mappings for - // indices using shadow replicas - state.onReplicaSuccess(); - return; - } - - if (!nodeId.equals(observer.observedState().nodes().localNodeId())) { - final DiscoveryNode node = observer.observedState().nodes().get(nodeId); - transportService.sendRequest(node, transportReplicaAction, shardRequest, - transportOptions, new EmptyTransportResponseHandler(ThreadPool.Names.SAME) { - @Override - public void handleResponse(TransportResponse.Empty vResponse) { - state.onReplicaSuccess(); - } - - @Override - public void handleException(TransportException exp) { - state.onReplicaFailure(nodeId, exp); - logger.trace("[{}] Transport failure during replica request [{}] ", exp, node, internalRequest.request()); - if (!ignoreReplicaException(exp)) { - logger.warn("Failed to perform " + actionName + " on remote replica " + node + shardIt.shardId(), exp); - shardStateAction.shardFailed(shard, indexMetaData.getUUID(), - "Failed to perform [" + actionName + "] on replica, message [" + ExceptionsHelper.detailedMessage(exp) + "]"); - } - } - - }); - } else { - if (internalRequest.request().operationThreaded()) { - try { - threadPool.executor(executor).execute(new AbstractRunnable() { - @Override - protected void doRun() { - try { - shardOperationOnReplica(shardRequest); - state.onReplicaSuccess(); - } catch (Throwable e) { - state.onReplicaFailure(nodeId, e); - failReplicaIfNeeded(shard.index(), shard.id(), e); - } - } - - // we must never reject on because of thread pool capacity on replicas - @Override - public boolean isForceExecution() { - return true; - } - - @Override - public void onFailure(Throwable t) { - state.onReplicaFailure(nodeId, t); - } - }); - } catch (Throwable e) { - failReplicaIfNeeded(shard.index(), shard.id(), e); - state.onReplicaFailure(nodeId, e); - } - } else { - try { - shardOperationOnReplica(shardRequest); - state.onReplicaSuccess(); - } catch (Throwable e) { - failReplicaIfNeeded(shard.index(), shard.id(), e); - state.onReplicaFailure(nodeId, e); - } - } - } - } - - boolean raiseFailureIfHaveNotEnoughActiveShardCopies(ShardRouting shard, ClusterState state) { - if (!checkWriteConsistency) { - return false; + /** + * checks whether we can perform a write based on the write consistency setting + * returns **null* if OK to proceed, or a string describing the reason to stop + */ + String checkWriteConsistency(ShardRouting shard) { + if (checkWriteConsistency == false) { + return null; } final WriteConsistencyLevel consistencyLevel; @@ -697,11 +574,11 @@ public abstract class TransportShardReplicationOperationAction 2) { // only for more than 2 in the number of shardIt it makes sense, otherwise its 1 shard with 1 replica, quorum is 1 (which is what it is initialized to) requiredNumber = (shardRoutingTable.getSize() / 2) + 1; @@ -722,24 +599,21 @@ public abstract class TransportShardReplicationOperationAction listener; private final AtomicBoolean finished = new AtomicBoolean(false); private final AtomicInteger success = new AtomicInteger(1); // We already wrote into the primary shard private final ConcurrentMap shardReplicaFailures = ConcurrentCollections.newConcurrentMap(); - + private final IndexMetaData indexMetaData; + private final ShardRouting originalPrimaryShard; private final AtomicInteger pending; - private final int numberOfShardInstances; + private final int totalShards; + private final ClusterStateObserver observer; - public ReplicationState(PrimaryOperationRequest por, ShardIterator shardsIter, Response finalResponse, ReplicaRequest replicaRequest, ActionListener listener, int numberOfPendingShardInstances, int numberOfUnassignedReplicas) { - this.request = por.request; - this.finalResponse = finalResponse; + /** + * the constructor doesn't take any action, just calculates state. Call {@link #run()} to start + * replicating. + */ + public ReplicationPhase(ShardIterator originalShardIt, ReplicaRequest replicaRequest, Response finalResponse, + ClusterStateObserver observer, ShardRouting originalPrimaryShard, + InternalRequest internalRequest, ActionListener listener) { this.replicaRequest = replicaRequest; - this.shardId = shardsIter.shardId(); this.listener = listener; - this.numberOfShardInstances = 1 + numberOfPendingShardInstances + numberOfUnassignedReplicas; + this.finalResponse = finalResponse; + this.originalPrimaryShard = originalPrimaryShard; + this.observer = observer; + indexMetaData = observer.observedState().metaData().index(internalRequest.concreteIndex()); + + ShardRouting shard; + // we double check on the state, if it got changed we need to make sure we take the latest one cause + // maybe a replica shard started its recovery process and we need to apply it there... + + // we also need to make sure if the new state has a new primary shard (that we indexed to before) started + // and assigned to another node (while the indexing happened). In that case, we want to apply it on the + // new primary shard as well... + ClusterState newState = clusterService.state(); + + int numberOfUnassignedOrShadowReplicas = 0; + int numberOfPendingShardInstances = 0; + if (observer.observedState() != newState) { + observer.reset(newState); + shardIt = shards(newState, internalRequest); + while ((shard = shardIt.nextOrNull()) != null) { + if (shard.primary()) { + if (originalPrimaryShard.currentNodeId().equals(shard.currentNodeId()) == false) { + // there is a new primary, we'll have to replicate to it. + numberOfPendingShardInstances++; + } + if (shard.relocating()) { + numberOfPendingShardInstances++; + } + } else if (IndexMetaData.isIndexUsingShadowReplicas(indexMetaData.settings())) { + // If the replicas use shadow replicas, there is no reason to + // perform the action on the replica, so skip it and + // immediately return + + // this delays mapping updates on replicas because they have + // to wait until they get the new mapping through the cluster + // state, which is why we recommend pre-defined mappings for + // indices using shadow replicas + numberOfUnassignedOrShadowReplicas++; + } else if (shard.unassigned()) { + numberOfUnassignedOrShadowReplicas++; + } else if (shard.relocating()) { + // we need to send to two copies + numberOfPendingShardInstances += 2; + } else { + numberOfPendingShardInstances++; + } + } + internalRequest.request().setCanHaveDuplicates(); // safe side, cluster state changed, we might have dups + } else { + shardIt = originalShardIt; + shardIt.reset(); + while ((shard = shardIt.nextOrNull()) != null) { + if (shard.state() != ShardRoutingState.STARTED) { + replicaRequest.setCanHaveDuplicates(); + } + if (shard.unassigned()) { + numberOfUnassignedOrShadowReplicas++; + } else if (shard.primary()) { + if (shard.relocating()) { + // we have to replicate to the other copy + numberOfPendingShardInstances += 1; + } + } else if (IndexMetaData.isIndexUsingShadowReplicas(indexMetaData.settings())) { + // If the replicas use shadow replicas, there is no reason to + // perform the action on the replica, so skip it and + // immediately return + + // this delays mapping updates on replicas because they have + // to wait until they get the new mapping through the cluster + // state, which is why we recommend pre-defined mappings for + // indices using shadow replicas + numberOfUnassignedOrShadowReplicas++; + } else if (shard.relocating()) { + // we need to send to two copies + numberOfPendingShardInstances += 2; + } else { + numberOfPendingShardInstances++; + } + } + } + + // one for the primary already done + this.totalShards = 1 + numberOfPendingShardInstances + numberOfUnassignedOrShadowReplicas; this.pending = new AtomicInteger(numberOfPendingShardInstances); } - public Request request() { - return this.request; + /** total shard copies */ + int totalShards() { + return totalShards; } - public ReplicaRequest replicaRequest() { - return this.replicaRequest; + /** total successful operations so far */ + int successful() { + return success.get(); } - public void onReplicaFailure(String nodeId, @Nullable Throwable e) { + /** number of pending operations */ + int pending() { + return pending.get(); + } + + @Override + public void onFailure(Throwable t) { + logger.error("unexpected error while replicating for action [{}]. shard [{}]. ", t, actionName, shardIt.shardId()); + forceFinishAsFailed(t); + } + + /** start sending current requests to replicas */ + @Override + protected void doRun() { + if (pending.get() == 0) { + doFinish(); + return; + } + ShardRouting shard; + shardIt.reset(); // reset the iterator + while ((shard = shardIt.nextOrNull()) != null) { + // if its unassigned, nothing to do here... + if (shard.unassigned()) { + continue; + } + + // we index on a replica that is initializing as well since we might not have got the event + // yet that it was started. We will get an exception IllegalShardState exception if its not started + // and that's fine, we will ignore it + if (shard.primary()) { + if (originalPrimaryShard.currentNodeId().equals(shard.currentNodeId()) == false) { + // there is a new primary, we'll have to replicate to it. + performOnReplica(shard, shard.currentNodeId()); + } + if (shard.relocating()) { + performOnReplica(shard, shard.relocatingNodeId()); + } + } else if (IndexMetaData.isIndexUsingShadowReplicas(indexMetaData.settings()) == false) { + performOnReplica(shard, shard.currentNodeId()); + if (shard.relocating()) { + performOnReplica(shard, shard.relocatingNodeId()); + } + } + } + } + + /** send operation to the given node or perform it if local */ + void performOnReplica(final ShardRouting shard, final String nodeId) { + // if we don't have that node, it means that it might have failed and will be created again, in + // this case, we don't have to do the operation, and just let it failover + if (!observer.observedState().nodes().nodeExists(nodeId)) { + onReplicaFailure(nodeId, null); + return; + } + + final ReplicaOperationRequest shardRequest = new ReplicaOperationRequest(shardIt.shardId(), replicaRequest); + + if (!nodeId.equals(observer.observedState().nodes().localNodeId())) { + final DiscoveryNode node = observer.observedState().nodes().get(nodeId); + transportService.sendRequest(node, transportReplicaAction, shardRequest, + transportOptions, new EmptyTransportResponseHandler(ThreadPool.Names.SAME) { + @Override + public void handleResponse(TransportResponse.Empty vResponse) { + onReplicaSuccess(); + } + + @Override + public void handleException(TransportException exp) { + onReplicaFailure(nodeId, exp); + logger.trace("[{}] transport failure during replica request [{}] ", exp, node, replicaRequest); + if (ignoreReplicaException(exp) == false) { + logger.warn("failed to perform " + actionName + " on remote replica " + node + shardIt.shardId(), exp); + shardStateAction.shardFailed(shard, indexMetaData.getUUID(), + "Failed to perform [" + actionName + "] on replica, message [" + ExceptionsHelper.detailedMessage(exp) + "]"); + } + } + + }); + } else { + if (replicaRequest.operationThreaded()) { + try { + threadPool.executor(executor).execute(new AbstractRunnable() { + @Override + protected void doRun() { + try { + shardOperationOnReplica(shardRequest); + onReplicaSuccess(); + } catch (Throwable e) { + onReplicaFailure(nodeId, e); + failReplicaIfNeeded(shard.index(), shard.id(), e); + } + } + + // we must never reject on because of thread pool capacity on replicas + @Override + public boolean isForceExecution() { + return true; + } + + @Override + public void onFailure(Throwable t) { + onReplicaFailure(nodeId, t); + } + }); + } catch (Throwable e) { + failReplicaIfNeeded(shard.index(), shard.id(), e); + onReplicaFailure(nodeId, e); + } + } else { + try { + shardOperationOnReplica(shardRequest); + onReplicaSuccess(); + } catch (Throwable e) { + failReplicaIfNeeded(shard.index(), shard.id(), e); + onReplicaFailure(nodeId, e); + } + } + } + } + + + void onReplicaFailure(String nodeId, @Nullable Throwable e) { // Only version conflict should be ignored from being put into the _shards header? - if (e != null && !ignoreReplicaException(e)) { + if (e != null && ignoreReplicaException(e) == false) { shardReplicaFailures.put(nodeId, e); } - finishIfNeeded(); + decPendingAndFinishIfNeeded(); } - public void onReplicaSuccess() { + void onReplicaSuccess() { success.incrementAndGet(); - finishIfNeeded(); + decPendingAndFinishIfNeeded(); } - public void forceFinish() { - doFinish(); - } - - private void finishIfNeeded() { - if (pending.decrementAndGet() == 0) { + private void decPendingAndFinishIfNeeded() { + if (pending.decrementAndGet() <= 0) { doFinish(); } } + private void forceFinishAsFailed(Throwable t) { + if (finished.compareAndSet(false, true)) { + listener.onFailure(t); + } + } + private void doFinish() { if (finished.compareAndSet(false, true)) { + final ShardId shardId = shardIt.shardId(); final ActionWriteResponse.ShardInfo.Failure[] failuresArray; if (!shardReplicaFailures.isEmpty()) { int slot = 0; @@ -824,9 +911,8 @@ public abstract class TransportShardReplicationOperationAction void assertListenerThrows(String msg, PlainActionFuture listener, Class klass) throws InterruptedException { + try { + listener.get(); + fail(msg); + } catch (ExecutionException ex) { + assertThat(ex.getCause(), instanceOf(klass)); + } + + } + + @Test + public void testBlocks() throws ExecutionException, InterruptedException { + Request request = new Request(); + PlainActionFuture listener = new PlainActionFuture<>(); + + ClusterBlocks.Builder block = ClusterBlocks.builder() + .addGlobalBlock(new ClusterBlock(1, "non retryable", false, true, RestStatus.SERVICE_UNAVAILABLE, ClusterBlockLevel.ALL)); + clusterService.setState(ClusterState.builder(clusterService.state()).blocks(block)); + TransportShardReplicationOperationAction.PrimaryPhase primaryPhase = action.new PrimaryPhase(request, listener); + assertFalse("primary phase should stop execution", primaryPhase.checkBlocks()); + assertListenerThrows("primary phase should fail operation", listener, ClusterBlockException.class); + + block = ClusterBlocks.builder() + .addGlobalBlock(new ClusterBlock(1, "retryable", true, true, RestStatus.SERVICE_UNAVAILABLE, ClusterBlockLevel.ALL)); + clusterService.setState(ClusterState.builder(clusterService.state()).blocks(block)); + listener = new PlainActionFuture<>(); + primaryPhase = action.new PrimaryPhase(new Request().timeout("5ms"), listener); + assertFalse("primary phase should stop execution on retryable block", primaryPhase.checkBlocks()); + assertListenerThrows("failed to timeout on retryable block", listener, ClusterBlockException.class); + + + listener = new PlainActionFuture<>(); + primaryPhase = action.new PrimaryPhase(new Request(), listener); + assertFalse("primary phase should stop execution on retryable block", primaryPhase.checkBlocks()); + assertFalse("primary phase should wait on retryable block", listener.isDone()); + + block = ClusterBlocks.builder() + .addGlobalBlock(new ClusterBlock(1, "non retryable", false, true, RestStatus.SERVICE_UNAVAILABLE, ClusterBlockLevel.ALL)); + clusterService.setState(ClusterState.builder(clusterService.state()).blocks(block)); + assertListenerThrows("primary phase should fail operation when moving from a retryable block a non-retryable one", listener, ClusterBlockException.class); + } + + ClusterState stateWithStartedPrimary(String index, boolean primaryLocal, int numberOfReplicas) { + int assignedReplicas = randomIntBetween(0, numberOfReplicas); + return stateWithStartedPrimary(index, primaryLocal, assignedReplicas, numberOfReplicas - assignedReplicas); + } + + ClusterState stateWithStartedPrimary(String index, boolean primaryLocal, int assignedReplicas, int unassignedReplicas) { + ShardRoutingState[] replicaStates = new ShardRoutingState[assignedReplicas + unassignedReplicas]; + // no point in randomizing - node assignment later on does it too. + for (int i = 0; i < assignedReplicas; i++) { + replicaStates[i] = randomFrom(ShardRoutingState.INITIALIZING, ShardRoutingState.STARTED, ShardRoutingState.RELOCATING); + } + for (int i = assignedReplicas; i < replicaStates.length; i++) { + replicaStates[i] = ShardRoutingState.UNASSIGNED; + } + return state(index, primaryLocal, randomFrom(ShardRoutingState.STARTED, ShardRoutingState.RELOCATING), replicaStates); + + } + + ClusterState state(String index, boolean primaryLocal, ShardRoutingState primaryState, ShardRoutingState... replicaStates) { + final int numberOfReplicas = replicaStates.length; + + int numberOfNodes = numberOfReplicas + 1; + if (primaryState == ShardRoutingState.RELOCATING) { + numberOfNodes++; + } + for (ShardRoutingState state : replicaStates) { + if (state == ShardRoutingState.RELOCATING) { + numberOfNodes++; + } + } + numberOfNodes = Math.max(2, numberOfNodes); // we need a non-local master to test shard failures + final ShardId shardId = new ShardId(index, 0); + DiscoveryNodes.Builder discoBuilder = DiscoveryNodes.builder(); + Set unassignedNodes = new HashSet<>(); + for (int i = 0; i < numberOfNodes + 1; i++) { + final DiscoveryNode node = newNode(i); + discoBuilder = discoBuilder.put(node); + unassignedNodes.add(node.id()); + } + discoBuilder.localNodeId(newNode(0).id()); + discoBuilder.masterNodeId(newNode(1).id()); // we need a non-local master to test shard failures + IndexMetaData indexMetaData = IndexMetaData.builder(index).settings(ImmutableSettings.builder() + .put(SETTING_VERSION_CREATED, Version.CURRENT) + .put(SETTING_NUMBER_OF_SHARDS, 1).put(SETTING_NUMBER_OF_REPLICAS, numberOfReplicas) + .put(SETTING_CREATION_DATE, System.currentTimeMillis())).build(); + + RoutingTable.Builder routing = new RoutingTable.Builder(); + routing.addAsNew(indexMetaData); + IndexShardRoutingTable.Builder indexShardRoutingBuilder = new IndexShardRoutingTable.Builder(shardId, false); + + String primaryNode = null; + String relocatingNode = null; + if (primaryState != ShardRoutingState.UNASSIGNED) { + if (primaryLocal) { + primaryNode = newNode(0).id(); + unassignedNodes.remove(primaryNode); + } else { + primaryNode = selectAndRemove(unassignedNodes); + } + if (primaryState == ShardRoutingState.RELOCATING) { + relocatingNode = selectAndRemove(unassignedNodes); + } + } + indexShardRoutingBuilder.addShard(new ImmutableShardRouting(index, 0, primaryNode, relocatingNode, true, primaryState, 0)); + + for (ShardRoutingState replicaState : replicaStates) { + String replicaNode = null; + relocatingNode = null; + if (replicaState != ShardRoutingState.UNASSIGNED) { + assert primaryNode != null : "a replica is assigned but the primary isn't"; + replicaNode = selectAndRemove(unassignedNodes); + if (replicaState == ShardRoutingState.RELOCATING) { + relocatingNode = selectAndRemove(unassignedNodes); + } + } + indexShardRoutingBuilder.addShard( + new ImmutableShardRouting(index, shardId.id(), replicaNode, relocatingNode, false, replicaState, 0)); + + } + + ClusterState.Builder state = ClusterState.builder(new ClusterName("test")); + state.nodes(discoBuilder); + state.metaData(MetaData.builder().put(indexMetaData, false).generateUuidIfNeeded()); + state.routingTable(RoutingTable.builder().add(IndexRoutingTable.builder(index).addIndexShard(indexShardRoutingBuilder.build()))); + return state.build(); + } + + private String selectAndRemove(Set strings) { + String selection = randomFrom(strings.toArray(new String[strings.size()])); + strings.remove(selection); + return selection; + } + + @Test + public void testNotStartedPrimary() throws InterruptedException, ExecutionException { + final String index = "test"; + final ShardId shardId = new ShardId(index, 0); + // no replicas in oder to skip the replication part + clusterService.setState(state(index, true, + randomBoolean() ? ShardRoutingState.INITIALIZING : ShardRoutingState.UNASSIGNED)); + + logger.debug("--> using initial state:\n{}", clusterService.state().prettyPrint()); + + Request request = new Request(shardId).timeout("1ms"); + PlainActionFuture listener = new PlainActionFuture<>(); + TransportShardReplicationOperationAction.PrimaryPhase primaryPhase = action.new PrimaryPhase(request, listener); + primaryPhase.run(); + assertListenerThrows("unassigned primary didn't cause a timeout", listener, UnavailableShardsException.class); + + request = new Request(shardId); + listener = new PlainActionFuture<>(); + primaryPhase = action.new PrimaryPhase(request, listener); + primaryPhase.run(); + assertFalse("unassigned primary didn't cause a retry", listener.isDone()); + + clusterService.setState(state(index, true, ShardRoutingState.STARTED)); + logger.debug("--> primary assigned state:\n{}", clusterService.state().prettyPrint()); + + listener.get(); + assertTrue("request wasn't processed on primary, despite of it being assigned", request.processedOnPrimary.get()); + } + + @Test + public void testRoutingToPrimary() { + final String index = "test"; + final ShardId shardId = new ShardId(index, 0); + + clusterService.setState(stateWithStartedPrimary(index, randomBoolean(), 3)); + + logger.debug("using state: \n{}", clusterService.state().prettyPrint()); + + final IndexShardRoutingTable shardRoutingTable = clusterService.state().routingTable().index(index).shard(shardId.id()); + final String primaryNodeId = shardRoutingTable.primaryShard().currentNodeId(); + Request request = new Request(shardId); + PlainActionFuture listener = new PlainActionFuture<>(); + + TransportShardReplicationOperationAction.PrimaryPhase primaryPhase = action.new PrimaryPhase(request, listener); + assertTrue(primaryPhase.checkBlocks()); + primaryPhase.routeRequestOrPerformLocally(shardRoutingTable.primaryShard(), shardRoutingTable.shardsIt()); + if (primaryNodeId.equals(clusterService.localNode().id())) { + logger.info("--> primary is assigned locally, testing for execution"); + assertTrue("request failed to be processed on a local primary", request.processedOnPrimary.get()); + } else { + logger.info("--> primary is assigned to [{}], checking request forwarded", primaryNodeId); + final List capturedRequests = transport.capturedRequestsByTargetNode().get(primaryNodeId); + assertThat(capturedRequests, notNullValue()); + assertThat(capturedRequests.size(), equalTo(1)); + assertThat(capturedRequests.get(0).action, equalTo("testAction")); + } + } + + @Test + public void testWriteConsistency() { + action = new ActionWithConsistency(ImmutableSettings.EMPTY, "testActionWithConsistency", transportService, clusterService, threadPool); + final String index = "test"; + final ShardId shardId = new ShardId(index, 0); + final int assignedReplicas = randomInt(2); + final int unassignedReplicas = randomInt(2); + final int totalShards = 1 + assignedReplicas + unassignedReplicas; + final boolean passesWriteConsistency; + Request request = new Request(shardId).consistencyLevel(randomFrom(WriteConsistencyLevel.values())); + switch (request.consistencyLevel()) { + case ONE: + passesWriteConsistency = true; + break; + case DEFAULT: + case QUORUM: + if (totalShards <= 2) { + passesWriteConsistency = true; // primary is enough + } else { + passesWriteConsistency = assignedReplicas + 1 >= (totalShards / 2) + 1; + } + break; + case ALL: + passesWriteConsistency = unassignedReplicas == 0; + break; + default: + throw new RuntimeException("unknown consistency level [" + request.consistencyLevel() + "]"); + } + ShardRoutingState[] replicaStates = new ShardRoutingState[assignedReplicas + unassignedReplicas]; + for (int i = 0; i < assignedReplicas; i++) { + replicaStates[i] = randomFrom(ShardRoutingState.STARTED, ShardRoutingState.RELOCATING); + } + for (int i = assignedReplicas; i < replicaStates.length; i++) { + replicaStates[i] = ShardRoutingState.UNASSIGNED; + } + + clusterService.setState(state(index, true, ShardRoutingState.STARTED, replicaStates)); + logger.debug("using consistency level of [{}], assigned shards [{}], total shards [{}]. expecting op to [{}]. using state: \n{}", + request.consistencyLevel(), 1 + assignedReplicas, 1 + assignedReplicas + unassignedReplicas, passesWriteConsistency ? "succeed" : "retry", + clusterService.state().prettyPrint()); + + final IndexShardRoutingTable shardRoutingTable = clusterService.state().routingTable().index(index).shard(shardId.id()); + PlainActionFuture listener = new PlainActionFuture<>(); + + TransportShardReplicationOperationAction.PrimaryPhase primaryPhase = action.new PrimaryPhase(request, listener); + if (passesWriteConsistency) { + assertThat(primaryPhase.checkWriteConsistency(shardRoutingTable.primaryShard()), nullValue()); + primaryPhase.run(); + assertTrue("operations should have been perform, consistency level is met", request.processedOnPrimary.get()); + } else { + assertThat(primaryPhase.checkWriteConsistency(shardRoutingTable.primaryShard()), notNullValue()); + primaryPhase.run(); + assertFalse("operations should not have been perform, consistency level is *NOT* met", request.processedOnPrimary.get()); + for (int i = 0; i < replicaStates.length; i++) { + replicaStates[i] = ShardRoutingState.STARTED; + } + clusterService.setState(state(index, true, ShardRoutingState.STARTED, replicaStates)); + assertTrue("once the consistency level met, operation should continue", request.processedOnPrimary.get()); + } + + } + + @Test + public void testReplication() throws ExecutionException, InterruptedException { + final String index = "test"; + final ShardId shardId = new ShardId(index, 0); + + clusterService.setState(stateWithStartedPrimary(index, true, randomInt(5))); + + final IndexShardRoutingTable shardRoutingTable = clusterService.state().routingTable().index(index).shard(shardId.id()); + int assignedReplicas = 0; + int totalShards = 0; + for (ShardRouting shard : shardRoutingTable) { + totalShards++; + if (shard.primary() == false && shard.assignedToNode()) { + assignedReplicas++; + } + if (shard.relocating()) { + assignedReplicas++; + totalShards++; + } + } + + runReplicateTest(shardRoutingTable, assignedReplicas, totalShards); + } + + @Test + public void testReplicationWithShadowIndex() throws ExecutionException, InterruptedException { + final String index = "test"; + final ShardId shardId = new ShardId(index, 0); + + ClusterState state = stateWithStartedPrimary(index, true, randomInt(5)); + MetaData.Builder metaData = MetaData.builder(state.metaData()); + ImmutableSettings.Builder settings = ImmutableSettings.builder().put(metaData.get(index).settings()); + settings.put(IndexMetaData.SETTING_SHADOW_REPLICAS, true); + metaData.put(IndexMetaData.builder(metaData.get(index)).settings(settings)); + clusterService.setState(ClusterState.builder(state).metaData(metaData)); + + final IndexShardRoutingTable shardRoutingTable = clusterService.state().routingTable().index(index).shard(shardId.id()); + int assignedReplicas = 0; + int totalShards = 0; + for (ShardRouting shard : shardRoutingTable) { + totalShards++; + if (shard.primary() && shard.relocating()) { + assignedReplicas++; + totalShards++; + } + } + + runReplicateTest(shardRoutingTable, assignedReplicas, totalShards); + } + + + protected void runReplicateTest(IndexShardRoutingTable shardRoutingTable, int assignedReplicas, int totalShards) throws InterruptedException, ExecutionException { + final ShardRouting primaryShard = shardRoutingTable.primaryShard(); + final ShardIterator shardIt = shardRoutingTable.shardsIt(); + final ShardId shardId = shardIt.shardId(); + final Request request = new Request(); + PlainActionFuture listener = new PlainActionFuture<>(); + + logger.debug("expecting [{}] assigned replicas, [{}] total shards. using state: \n{}", assignedReplicas, totalShards, clusterService.state().prettyPrint()); + + + final TransportShardReplicationOperationAction.InternalRequest internalRequest = action.new InternalRequest(request); + internalRequest.concreteIndex(shardId.index().name()); + TransportShardReplicationOperationAction.ReplicationPhase replicationPhase = + action.new ReplicationPhase(shardIt, request, + new Response(), new ClusterStateObserver(clusterService, logger), + primaryShard, internalRequest, listener); + + assertThat(replicationPhase.totalShards(), equalTo(totalShards)); + assertThat(replicationPhase.pending(), equalTo(assignedReplicas)); + replicationPhase.run(); + final CapturingTransport.CapturedRequest[] capturedRequests = transport.capturedRequests(); + transport.clear(); + assertThat(capturedRequests.length, equalTo(assignedReplicas)); + if (assignedReplicas > 0) { + assertThat("listener is done, but there are outstanding replicas", listener.isDone(), equalTo(false)); + } + int pending = replicationPhase.pending(); + int criticalFailures = 0; // failures that should fail the shard + int successfull = 1; + for (CapturingTransport.CapturedRequest capturedRequest : capturedRequests) { + if (randomBoolean()) { + Throwable t; + if (randomBoolean()) { + t = new CorruptIndexException("simulated", (String) null); + criticalFailures++; + } else { + t = new IndexShardNotStartedException(shardId, IndexShardState.RECOVERING); + } + logger.debug("--> simulating failure on {} with [{}]", capturedRequest.node, t.getClass().getSimpleName()); + transport.handleResponse(capturedRequest.requestId, t); + } else { + successfull++; + transport.handleResponse(capturedRequest.requestId, TransportResponse.Empty.INSTANCE); + } + pending--; + assertThat(replicationPhase.pending(), equalTo(pending)); + assertThat(replicationPhase.successful(), equalTo(successfull)); + } + assertThat(listener.isDone(), equalTo(true)); + Response response = listener.get(); + final ActionWriteResponse.ShardInfo shardInfo = response.getShardInfo(); + assertThat(shardInfo.getFailed(), equalTo(criticalFailures)); + assertThat(shardInfo.getFailures(), arrayWithSize(criticalFailures)); + assertThat(shardInfo.getSuccessful(), equalTo(successfull)); + assertThat(shardInfo.getTotal(), equalTo(totalShards)); + + assertThat("failed to see enough shard failures", transport.capturedRequests().length, equalTo(criticalFailures)); + for (CapturingTransport.CapturedRequest capturedRequest : transport.capturedRequests()) { + assertThat(capturedRequest.action, equalTo(ShardStateAction.SHARD_FAILED_ACTION_NAME)); + } + } + + + static class Request extends ShardReplicationOperationRequest { + int shardId; + public AtomicBoolean processedOnPrimary = new AtomicBoolean(); + public AtomicInteger processedOnReplicas = new AtomicInteger(); + + Request() { + this.operationThreaded(false); + } + + Request(ShardId shardId) { + this(); + this.shardId = shardId.id(); + this.index(shardId.index().name()); + // keep things simple + } + + @Override + public void writeTo(StreamOutput out) throws IOException { + super.writeTo(out); + out.writeVInt(shardId); + } + + @Override + public void readFrom(StreamInput in) throws IOException { + super.readFrom(in); + shardId = in.readVInt(); + } + } + + static class Response extends ActionWriteResponse { + + } + + static class Action extends TransportShardReplicationOperationAction { + + Action(Settings settings, String actionName, TransportService transportService, + ClusterService clusterService, + ThreadPool threadPool) { + super(settings, actionName, transportService, clusterService, null, threadPool, + new ShardStateAction(settings, clusterService, transportService, null, null), + new ActionFilters(new HashSet())); + } + + @Override + protected Request newRequestInstance() { + return new Request(); + } + + @Override + protected Request newReplicaRequestInstance() { + return new Request(); + } + + @Override + protected Response newResponseInstance() { + return new Response(); + } + + @Override + protected String executor() { + return ThreadPool.Names.SAME; + } + + @Override + protected Tuple shardOperationOnPrimary(ClusterState clusterState, PrimaryOperationRequest shardRequest) throws Throwable { + boolean executedBefore = shardRequest.request.processedOnPrimary.getAndSet(true); + assert executedBefore == false : "request has already been executed on the primary"; + return new Tuple<>(new Response(), shardRequest.request); + } + + @Override + protected void shardOperationOnReplica(ReplicaOperationRequest shardRequest) { + shardRequest.request.processedOnReplicas.incrementAndGet(); + } + + @Override + protected ShardIterator shards(ClusterState clusterState, InternalRequest request) throws ElasticsearchException { + return clusterState.getRoutingTable().index(request.concreteIndex()).shard(request.request().shardId).shardsIt(); + } + + @Override + protected boolean checkWriteConsistency() { + return false; + } + + @Override + protected boolean resolveIndex() { + return false; + } + } + + static class ActionWithConsistency extends Action { + + ActionWithConsistency(Settings settings, String actionName, TransportService transportService, ClusterService clusterService, ThreadPool threadPool) { + super(settings, actionName, transportService, clusterService, threadPool); + } + + @Override + protected boolean checkWriteConsistency() { + return true; + } + } + + static DiscoveryNode newNode(int nodeId) { + return new DiscoveryNode("node_" + nodeId, DummyTransportAddress.INSTANCE, Version.CURRENT); + } + + +} diff --git a/src/test/java/org/elasticsearch/test/cluster/TestClusterService.java b/src/test/java/org/elasticsearch/test/cluster/TestClusterService.java new file mode 100644 index 00000000000..27f09489763 --- /dev/null +++ b/src/test/java/org/elasticsearch/test/cluster/TestClusterService.java @@ -0,0 +1,249 @@ +/* + * 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.test.cluster; + +import org.elasticsearch.ElasticsearchException; +import org.elasticsearch.ElasticsearchIllegalStateException; +import org.elasticsearch.Version; +import org.elasticsearch.cluster.*; +import org.elasticsearch.cluster.block.ClusterBlock; +import org.elasticsearch.cluster.node.DiscoveryNode; +import org.elasticsearch.cluster.node.DiscoveryNodes; +import org.elasticsearch.cluster.routing.OperationRouting; +import org.elasticsearch.cluster.service.PendingClusterTask; +import org.elasticsearch.common.Nullable; +import org.elasticsearch.common.Priority; +import org.elasticsearch.common.component.Lifecycle; +import org.elasticsearch.common.component.LifecycleListener; +import org.elasticsearch.common.transport.DummyTransportAddress; +import org.elasticsearch.common.unit.TimeValue; +import org.elasticsearch.common.util.concurrent.ConcurrentCollections; +import org.elasticsearch.common.util.concurrent.FutureUtils; +import org.elasticsearch.threadpool.ThreadPool; + +import java.util.Collection; +import java.util.Iterator; +import java.util.List; +import java.util.Queue; +import java.util.concurrent.CopyOnWriteArrayList; +import java.util.concurrent.ScheduledFuture; + +/** a class that simulate simple cluster service features, like state storage and listeners */ +public class TestClusterService implements ClusterService { + + volatile ClusterState state; + private final Collection listeners = new CopyOnWriteArrayList<>(); + private final Queue onGoingTimeouts = ConcurrentCollections.newQueue(); + private final ThreadPool threadPool; + + public TestClusterService() { + this(ClusterState.builder(new ClusterName("test")).build()); + } + + public TestClusterService(ThreadPool threadPool) { + this(ClusterState.builder(new ClusterName("test")).build(), threadPool); + } + + public TestClusterService(ClusterState state) { + this(state, null); + } + + public TestClusterService(ClusterState state, @Nullable ThreadPool threadPool) { + if (state.getNodes().size() == 0) { + state = ClusterState.builder(state).nodes( + DiscoveryNodes.builder() + .put(new DiscoveryNode("test_id", DummyTransportAddress.INSTANCE, Version.CURRENT)) + .localNodeId("test_id")).build(); + } + + assert state.getNodes().localNode() != null; + this.state = state; + this.threadPool = threadPool; + + } + + + /** set the current state and trigger any registered listeners about the change */ + public void setState(ClusterState state) { + assert state.getNodes().localNode() != null; + // make sure we have a version increment + state = ClusterState.builder(state).version(this.state.version() + 1).build(); + ClusterChangedEvent event = new ClusterChangedEvent("test", state, this.state); + this.state = state; + for (ClusterStateListener listener : listeners) { + listener.clusterChanged(event); + } + } + + /** set the current state and trigger any registered listeners about the change */ + public void setState(ClusterState.Builder state) { + setState(state.build()); + } + + @Override + public DiscoveryNode localNode() { + return state.getNodes().localNode(); + } + + @Override + public ClusterState state() { + return state; + } + + @Override + public void addInitialStateBlock(ClusterBlock block) throws ElasticsearchIllegalStateException { + throw new UnsupportedOperationException(); + + } + + @Override + public void removeInitialStateBlock(ClusterBlock block) throws ElasticsearchIllegalStateException { + throw new UnsupportedOperationException(); + + } + + @Override + public OperationRouting operationRouting() { + return null; + } + + @Override + public void addFirst(ClusterStateListener listener) { + throw new UnsupportedOperationException(); + } + + @Override + public void addLast(ClusterStateListener listener) { + listeners.add(listener); + } + + @Override + public void add(ClusterStateListener listener) { + listeners.add(listener); + } + + @Override + public void remove(ClusterStateListener listener) { + listeners.remove(listener); + for (Iterator it = onGoingTimeouts.iterator(); it.hasNext(); ) { + NotifyTimeout timeout = it.next(); + if (timeout.listener.equals(listener)) { + timeout.cancel(); + it.remove(); + } + } + } + + @Override + public void add(LocalNodeMasterListener listener) { + throw new UnsupportedOperationException(); + } + + @Override + public void remove(LocalNodeMasterListener listener) { + throw new UnsupportedOperationException(); + } + + @Override + public void add(final TimeValue timeout, final TimeoutClusterStateListener listener) { + if (threadPool == null) { + throw new UnsupportedOperationException("TestClusterService wasn't initialized with a thread pool"); + } + NotifyTimeout notifyTimeout = new NotifyTimeout(listener, timeout); + notifyTimeout.future = threadPool.schedule(timeout, ThreadPool.Names.GENERIC, notifyTimeout); + onGoingTimeouts.add(notifyTimeout); + listeners.add(listener); + listener.postAdded(); + } + + @Override + public void submitStateUpdateTask(String source, Priority priority, ClusterStateUpdateTask updateTask) { + throw new UnsupportedOperationException(); + } + + @Override + public void submitStateUpdateTask(String source, ClusterStateUpdateTask updateTask) { + throw new UnsupportedOperationException(); + } + + @Override + public List pendingTasks() { + throw new UnsupportedOperationException(); + + } + + @Override + public int numberOfPendingTasks() { + throw new UnsupportedOperationException(); + } + + @Override + public Lifecycle.State lifecycleState() { + throw new UnsupportedOperationException(); + } + + @Override + public void addLifecycleListener(LifecycleListener listener) { + throw new UnsupportedOperationException(); + } + + @Override + public void removeLifecycleListener(LifecycleListener listener) { + throw new UnsupportedOperationException(); + } + + @Override + public ClusterService start() throws ElasticsearchException { + throw new UnsupportedOperationException(); + } + + @Override + public ClusterService stop() throws ElasticsearchException { + throw new UnsupportedOperationException(); + } + + @Override + public void close() throws ElasticsearchException { + throw new UnsupportedOperationException(); + } + + class NotifyTimeout implements Runnable { + final TimeoutClusterStateListener listener; + final TimeValue timeout; + volatile ScheduledFuture future; + + NotifyTimeout(TimeoutClusterStateListener listener, TimeValue timeout) { + this.listener = listener; + this.timeout = timeout; + } + + public void cancel() { + FutureUtils.cancel(future); + } + + @Override + public void run() { + if (future != null && future.isCancelled()) { + return; + } + listener.onTimeout(this.timeout); + // note, we rely on the listener to remove itself in case of timeout if needed + } + } +} diff --git a/src/test/java/org/elasticsearch/test/transport/CapturingTransport.java b/src/test/java/org/elasticsearch/test/transport/CapturingTransport.java new file mode 100644 index 00000000000..ca4c7950345 --- /dev/null +++ b/src/test/java/org/elasticsearch/test/transport/CapturingTransport.java @@ -0,0 +1,180 @@ +/* + * 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.test.transport; + +import org.elasticsearch.ElasticsearchException; +import org.elasticsearch.cluster.node.DiscoveryNode; +import org.elasticsearch.common.component.Lifecycle; +import org.elasticsearch.common.component.LifecycleListener; +import org.elasticsearch.common.transport.BoundTransportAddress; +import org.elasticsearch.common.transport.TransportAddress; +import org.elasticsearch.common.util.concurrent.ConcurrentCollections; +import org.elasticsearch.transport.*; + +import java.io.IOException; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.concurrent.BlockingQueue; + +/** A transport class that doesn't send anything but rather captures all requests for inspection from tests */ +public class CapturingTransport implements Transport { + private TransportServiceAdapter adapter; + + static public class CapturedRequest { + final public DiscoveryNode node; + final public long requestId; + final public String action; + final public TransportRequest request; + + public CapturedRequest(DiscoveryNode node, long requestId, String action, TransportRequest request) { + this.node = node; + this.requestId = requestId; + this.action = action; + this.request = request; + } + } + + private BlockingQueue capturedRequests = ConcurrentCollections.newBlockingQueue(); + + /** returns all requests captured so far. Doesn't clear the captured request list. See {@link #clear()} */ + public CapturedRequest[] capturedRequests() { + return capturedRequests.toArray(new CapturedRequest[0]); + } + + /** + * returns all requests captured so far, grouped by target node. + * Doesn't clear the captured request list. See {@link #clear()} + */ + public Map> capturedRequestsByTargetNode() { + Map> map = new HashMap<>(); + for (CapturedRequest request : capturedRequests) { + List nodeList = map.get(request.node.id()); + if (nodeList == null) { + nodeList = new ArrayList<>(); + map.put(request.node.id(), nodeList); + } + nodeList.add(request); + } + return map; + } + + /** clears captured requests */ + public void clear() { + capturedRequests.clear(); + } + + /** simulate a response for the given requestId */ + public void handleResponse(final long requestId, final TransportResponse response) { + adapter.onResponseReceived(requestId).handleResponse(response); + } + + /** simulate a remote error for the given requesTId */ + public void handleResponse(final long requestId, final Throwable t) { + adapter.onResponseReceived(requestId).handleException(new RemoteTransportException("remote failure", t)); + } + + + @Override + public void sendRequest(DiscoveryNode node, long requestId, String action, TransportRequest request, TransportRequestOptions options) throws IOException, TransportException { + capturedRequests.add(new CapturedRequest(node, requestId, action, request)); + } + + + @Override + public void transportServiceAdapter(TransportServiceAdapter adapter) { + this.adapter = adapter; + } + + @Override + public BoundTransportAddress boundAddress() { + return null; + } + + @Override + public Map profileBoundAddresses() { + return null; + } + + @Override + public TransportAddress[] addressesFromString(String address) throws Exception { + return new TransportAddress[0]; + } + + @Override + public boolean addressSupported(Class address) { + return false; + } + + @Override + public boolean nodeConnected(DiscoveryNode node) { + return true; + } + + @Override + public void connectToNode(DiscoveryNode node) throws ConnectTransportException { + + } + + @Override + public void connectToNodeLight(DiscoveryNode node) throws ConnectTransportException { + + } + + @Override + public void disconnectFromNode(DiscoveryNode node) { + + } + + @Override + public long serverOpen() { + return 0; + } + + @Override + public Lifecycle.State lifecycleState() { + return null; + } + + @Override + public void addLifecycleListener(LifecycleListener listener) { + + } + + @Override + public void removeLifecycleListener(LifecycleListener listener) { + + } + + @Override + public Transport start() throws ElasticsearchException { + return null; + } + + @Override + public Transport stop() throws ElasticsearchException { + return null; + } + + @Override + public void close() throws ElasticsearchException { + + } +} From c25ca1ebfb6e2b408ca0ed352d73dc6b6fc30727 Mon Sep 17 00:00:00 2001 From: Simon Willnauer Date: Fri, 24 Apr 2015 11:43:23 +0200 Subject: [PATCH 11/14] [CORE] Simplify IndexStore and friends Today we have a lot of bloat in the IndexStore and related classes. THe IndexStore interface is unneeded as we always subclass AbstractIndexStore and it hides circular dependencies that are problematic when added. Guice proxies them if you have an interface which is bad in general. This commit removes most of the bloat classes and unifies all the classes we have into a single one since they all just structural and don't encode any functionality. --- .../org/elasticsearch/index/IndexService.java | 9 +- .../settings/IndexDynamicSettingsModule.java | 6 +- .../store/{fs => }/FsDirectoryService.java | 52 +++++++- .../elasticsearch/index/store/IndexStore.java | 89 +++++++++++-- .../index/store/IndexStoreModule.java | 50 +++---- .../store/fs/DefaultFsDirectoryService.java | 63 --------- .../index/store/fs/DefaultFsIndexStore.java | 46 ------- .../store/fs/DefaultFsIndexStoreModule.java | 34 ----- .../store/fs/MmapFsDirectoryService.java | 49 ------- .../index/store/fs/MmapFsIndexStore.java | 46 ------- .../store/fs/MmapFsIndexStoreModule.java | 34 ----- .../index/store/fs/NioFsDirectoryService.java | 49 ------- .../index/store/fs/NioFsIndexStore.java | 46 ------- .../index/store/fs/NioFsIndexStoreModule.java | 34 ----- .../store/fs/SimpleFsDirectoryService.java | 49 ------- .../index/store/fs/SimpleFsIndexStore.java | 46 ------- .../store/fs/SimpleFsIndexStoreModule.java | 34 ----- .../store/support/AbstractIndexStore.java | 126 ------------------ .../indices/store/IndicesStore.java | 6 +- .../TransportNodesListShardStoreMetaData.java | 3 +- .../transport/TransportClientTests.java | 2 +- .../index/store/IndexStoreTests.java | 86 ++++++++++++ .../indices/settings/UpdateSettingsTests.java | 13 +- .../indices/stats/IndexStatsTests.java | 6 +- .../DedicatedClusterSnapshotRestoreTests.java | 10 +- .../SharedClusterSnapshotRestoreTests.java | 9 +- .../test/InternalTestCluster.java | 3 +- .../test/store/MockDirectoryHelper.java | 31 ++--- .../test/store/MockFSDirectoryService.java | 6 +- .../test/store/MockFSIndexStore.java | 11 +- 30 files changed, 273 insertions(+), 775 deletions(-) rename src/main/java/org/elasticsearch/index/store/{fs => }/FsDirectoryService.java (52%) delete mode 100644 src/main/java/org/elasticsearch/index/store/fs/DefaultFsDirectoryService.java delete mode 100644 src/main/java/org/elasticsearch/index/store/fs/DefaultFsIndexStore.java delete mode 100644 src/main/java/org/elasticsearch/index/store/fs/DefaultFsIndexStoreModule.java delete mode 100644 src/main/java/org/elasticsearch/index/store/fs/MmapFsDirectoryService.java delete mode 100644 src/main/java/org/elasticsearch/index/store/fs/MmapFsIndexStore.java delete mode 100644 src/main/java/org/elasticsearch/index/store/fs/MmapFsIndexStoreModule.java delete mode 100644 src/main/java/org/elasticsearch/index/store/fs/NioFsDirectoryService.java delete mode 100644 src/main/java/org/elasticsearch/index/store/fs/NioFsIndexStore.java delete mode 100644 src/main/java/org/elasticsearch/index/store/fs/NioFsIndexStoreModule.java delete mode 100644 src/main/java/org/elasticsearch/index/store/fs/SimpleFsDirectoryService.java delete mode 100644 src/main/java/org/elasticsearch/index/store/fs/SimpleFsIndexStore.java delete mode 100644 src/main/java/org/elasticsearch/index/store/fs/SimpleFsIndexStoreModule.java delete mode 100644 src/main/java/org/elasticsearch/index/store/support/AbstractIndexStore.java create mode 100644 src/test/java/org/elasticsearch/index/store/IndexStoreTests.java diff --git a/src/main/java/org/elasticsearch/index/IndexService.java b/src/main/java/org/elasticsearch/index/IndexService.java index 0ce365c2036..878d8162437 100644 --- a/src/main/java/org/elasticsearch/index/IndexService.java +++ b/src/main/java/org/elasticsearch/index/IndexService.java @@ -115,8 +115,6 @@ public class IndexService extends AbstractIndexComponent implements IndexCompone private final BitsetFilterCache bitsetFilterCache; - private final IndexStore indexStore; - private final IndexSettingsService settingsService; private final NodeEnvironment nodeEnv; @@ -131,7 +129,7 @@ public class IndexService extends AbstractIndexComponent implements IndexCompone public IndexService(Injector injector, Index index, @IndexSettings Settings indexSettings, NodeEnvironment nodeEnv, AnalysisService analysisService, MapperService mapperService, IndexQueryParserService queryParserService, SimilarityService similarityService, IndexAliasesService aliasesService, IndexCache indexCache, - IndexStore indexStore, IndexSettingsService settingsService, + IndexSettingsService settingsService, IndexFieldDataService indexFieldData, BitsetFilterCache bitSetFilterCache, IndicesService indicesServices) { super(index, indexSettings); this.injector = injector; @@ -143,7 +141,6 @@ public class IndexService extends AbstractIndexComponent implements IndexCompone this.aliasesService = aliasesService; this.indexCache = indexCache; this.indexFieldData = indexFieldData; - this.indexStore = indexStore; this.settingsService = settingsService; this.bitsetFilterCache = bitSetFilterCache; @@ -214,10 +211,6 @@ public class IndexService extends AbstractIndexComponent implements IndexCompone return this.settingsService; } - public IndexStore store() { - return indexStore; - } - public IndexCache cache() { return indexCache; } diff --git a/src/main/java/org/elasticsearch/index/settings/IndexDynamicSettingsModule.java b/src/main/java/org/elasticsearch/index/settings/IndexDynamicSettingsModule.java index 91f8ac4f3bf..3fa975a31ed 100644 --- a/src/main/java/org/elasticsearch/index/settings/IndexDynamicSettingsModule.java +++ b/src/main/java/org/elasticsearch/index/settings/IndexDynamicSettingsModule.java @@ -36,7 +36,7 @@ import org.elasticsearch.index.merge.policy.TieredMergePolicyProvider; import org.elasticsearch.index.merge.scheduler.ConcurrentMergeSchedulerProvider; import org.elasticsearch.index.search.slowlog.ShardSlowLogSearchService; import org.elasticsearch.index.shard.IndexShard; -import org.elasticsearch.index.store.support.AbstractIndexStore; +import org.elasticsearch.index.store.IndexStore; import org.elasticsearch.index.translog.TranslogService; import org.elasticsearch.index.translog.fs.FsTranslog; import org.elasticsearch.indices.IndicesWarmer; @@ -51,8 +51,8 @@ public class IndexDynamicSettingsModule extends AbstractModule { public IndexDynamicSettingsModule() { indexDynamicSettings = new DynamicSettings(); - indexDynamicSettings.addDynamicSetting(AbstractIndexStore.INDEX_STORE_THROTTLE_MAX_BYTES_PER_SEC, Validator.BYTES_SIZE); - indexDynamicSettings.addDynamicSetting(AbstractIndexStore.INDEX_STORE_THROTTLE_TYPE); + indexDynamicSettings.addDynamicSetting(IndexStore.INDEX_STORE_THROTTLE_MAX_BYTES_PER_SEC, Validator.BYTES_SIZE); + indexDynamicSettings.addDynamicSetting(IndexStore.INDEX_STORE_THROTTLE_TYPE); indexDynamicSettings.addDynamicSetting(ConcurrentMergeSchedulerProvider.MAX_THREAD_COUNT); indexDynamicSettings.addDynamicSetting(ConcurrentMergeSchedulerProvider.MAX_MERGE_COUNT); indexDynamicSettings.addDynamicSetting(ConcurrentMergeSchedulerProvider.AUTO_THROTTLE); diff --git a/src/main/java/org/elasticsearch/index/store/fs/FsDirectoryService.java b/src/main/java/org/elasticsearch/index/store/FsDirectoryService.java similarity index 52% rename from src/main/java/org/elasticsearch/index/store/fs/FsDirectoryService.java rename to src/main/java/org/elasticsearch/index/store/FsDirectoryService.java index dab9346413e..f67bc340125 100644 --- a/src/main/java/org/elasticsearch/index/store/fs/FsDirectoryService.java +++ b/src/main/java/org/elasticsearch/index/store/FsDirectoryService.java @@ -17,13 +17,18 @@ * under the License. */ -package org.elasticsearch.index.store.fs; +package org.elasticsearch.index.store; import java.io.IOException; import java.nio.file.Files; import java.nio.file.Path; +import java.util.Collections; +import java.util.Set; +import com.google.common.collect.Sets; import org.apache.lucene.store.*; +import org.apache.lucene.util.Constants; +import org.elasticsearch.common.inject.Inject; import org.elasticsearch.common.metrics.CounterMetric; import org.elasticsearch.common.settings.Settings; import org.elasticsearch.index.settings.IndexSettings; @@ -31,19 +36,21 @@ import org.elasticsearch.index.shard.ShardId; import org.elasticsearch.index.shard.ShardPath; import org.elasticsearch.index.store.DirectoryService; import org.elasticsearch.index.store.IndexStore; +import org.elasticsearch.index.store.IndexStoreModule; import org.elasticsearch.index.store.StoreException; /** */ -public abstract class FsDirectoryService extends DirectoryService implements StoreRateLimiting.Listener, StoreRateLimiting.Provider { +public class FsDirectoryService extends DirectoryService implements StoreRateLimiting.Listener, StoreRateLimiting.Provider { protected final IndexStore indexStore; private final CounterMetric rateLimitingTimeInNanos = new CounterMetric(); private final ShardPath path; - public FsDirectoryService(ShardId shardId, @IndexSettings Settings indexSettings, IndexStore indexStore, ShardPath path) { - super(shardId, indexSettings); + @Inject + public FsDirectoryService(@IndexSettings Settings indexSettings, IndexStore indexStore, ShardPath path) { + super(path.getShardId(), indexSettings); this.path = path; this.indexStore = indexStore; } @@ -79,10 +86,45 @@ public abstract class FsDirectoryService extends DirectoryService implements Sto return new RateLimitedFSDirectory(wrapped, this, this) ; } - protected abstract Directory newFSDirectory(Path location, LockFactory lockFactory) throws IOException; @Override public void onPause(long nanos) { rateLimitingTimeInNanos.inc(nanos); } + + /* + * We are mmapping docvalues as well as term dictionaries, all other files are served through NIOFS + * this provides good random access performance while not creating unnecessary mmaps for files like stored + * fields etc. + */ + private static final Set PRIMARY_EXTENSIONS = Collections.unmodifiableSet(Sets.newHashSet("dvd", "tim")); + + + protected Directory newFSDirectory(Path location, LockFactory lockFactory) throws IOException { + final String storeType = indexSettings.get(IndexStoreModule.STORE_TYPE, IndexStoreModule.Type.DEFAULT.name()); + if (IndexStoreModule.Type.FS.match(storeType) || IndexStoreModule.Type.DEFAULT.match(storeType)) { + final FSDirectory open = FSDirectory.open(location, lockFactory); // use lucene defaults + if (open instanceof MMapDirectory && Constants.WINDOWS == false) { + return newDefaultDir(location, (MMapDirectory) open, lockFactory); + } + return open; + } else if (IndexStoreModule.Type.SIMPLEFS.match(storeType)) { + return new SimpleFSDirectory(location, lockFactory); + } else if (IndexStoreModule.Type.NIOFS.match(storeType)) { + return new NIOFSDirectory(location, lockFactory); + } else if (IndexStoreModule.Type.MMAPFS.match(storeType)) { + return new MMapDirectory(location, lockFactory); + } + throw new IllegalArgumentException("No directory found for type [" + storeType + "]"); + } + + private Directory newDefaultDir(Path location, final MMapDirectory mmapDir, LockFactory lockFactory) throws IOException { + return new FileSwitchDirectory(PRIMARY_EXTENSIONS, mmapDir, new NIOFSDirectory(location, lockFactory), true) { + @Override + public String[] listAll() throws IOException { + // Avoid doing listAll twice: + return mmapDir.listAll(); + } + }; + } } diff --git a/src/main/java/org/elasticsearch/index/store/IndexStore.java b/src/main/java/org/elasticsearch/index/store/IndexStore.java index 161b915e508..0cae510f87b 100644 --- a/src/main/java/org/elasticsearch/index/store/IndexStore.java +++ b/src/main/java/org/elasticsearch/index/store/IndexStore.java @@ -20,28 +20,101 @@ package org.elasticsearch.index.store; import org.apache.lucene.store.StoreRateLimiting; +import org.elasticsearch.ElasticsearchException; +import org.elasticsearch.common.inject.Inject; import org.elasticsearch.common.settings.Settings; +import org.elasticsearch.common.unit.ByteSizeValue; +import org.elasticsearch.index.AbstractIndexComponent; +import org.elasticsearch.index.Index; +import org.elasticsearch.index.IndexService; import org.elasticsearch.index.settings.IndexSettings; -import org.elasticsearch.index.shard.ShardId; +import org.elasticsearch.index.settings.IndexSettingsService; +import org.elasticsearch.indices.store.IndicesStore; import java.io.Closeable; -import java.io.IOException; -import java.nio.file.Path; /** - * Index store is an index level information of the {@link Store} each shard will use. + * */ -public interface IndexStore extends Closeable { +public class IndexStore extends AbstractIndexComponent implements Closeable { + + public static final String INDEX_STORE_THROTTLE_TYPE = "index.store.throttle.type"; + public static final String INDEX_STORE_THROTTLE_MAX_BYTES_PER_SEC = "index.store.throttle.max_bytes_per_sec"; + + private final IndexSettingsService settingsService; + + class ApplySettings implements IndexSettingsService.Listener { + @Override + public void onRefreshSettings(Settings settings) { + String rateLimitingType = settings.get(INDEX_STORE_THROTTLE_TYPE, IndexStore.this.rateLimitingType); + if (!rateLimitingType.equals(IndexStore.this.rateLimitingType)) { + logger.info("updating index.store.throttle.type from [{}] to [{}]", IndexStore.this.rateLimitingType, rateLimitingType); + if (rateLimitingType.equalsIgnoreCase("node")) { + IndexStore.this.rateLimitingType = rateLimitingType; + IndexStore.this.nodeRateLimiting = true; + } else { + StoreRateLimiting.Type.fromString(rateLimitingType); + IndexStore.this.rateLimitingType = rateLimitingType; + IndexStore.this.nodeRateLimiting = false; + IndexStore.this.rateLimiting.setType(rateLimitingType); + } + } + + ByteSizeValue rateLimitingThrottle = settings.getAsBytesSize(INDEX_STORE_THROTTLE_MAX_BYTES_PER_SEC, IndexStore.this.rateLimitingThrottle); + if (!rateLimitingThrottle.equals(IndexStore.this.rateLimitingThrottle)) { + logger.info("updating index.store.throttle.max_bytes_per_sec from [{}] to [{}], note, type is [{}]", IndexStore.this.rateLimitingThrottle, rateLimitingThrottle, IndexStore.this.rateLimitingType); + IndexStore.this.rateLimitingThrottle = rateLimitingThrottle; + IndexStore.this.rateLimiting.setMaxRate(rateLimitingThrottle); + } + } + } + protected final IndicesStore indicesStore; + + private volatile String rateLimitingType; + private volatile ByteSizeValue rateLimitingThrottle; + private volatile boolean nodeRateLimiting; + + private final StoreRateLimiting rateLimiting = new StoreRateLimiting(); + + private final ApplySettings applySettings = new ApplySettings(); + + @Inject + public IndexStore(Index index, @IndexSettings Settings indexSettings, IndexSettingsService settingsService, IndicesStore indicesStore) { + super(index, indexSettings); + this.indicesStore = indicesStore; + + this.rateLimitingType = indexSettings.get(INDEX_STORE_THROTTLE_TYPE, "none"); + if (rateLimitingType.equalsIgnoreCase("node")) { + nodeRateLimiting = true; + } else { + nodeRateLimiting = false; + rateLimiting.setType(rateLimitingType); + } + this.rateLimitingThrottle = indexSettings.getAsBytesSize(INDEX_STORE_THROTTLE_MAX_BYTES_PER_SEC, new ByteSizeValue(0)); + rateLimiting.setMaxRate(rateLimitingThrottle); + + logger.debug("using index.store.throttle.type [{}], with index.store.throttle.max_bytes_per_sec [{}]", rateLimitingType, rateLimitingThrottle); + this.settingsService = settingsService; + this.settingsService.addListener(applySettings); + } + + @Override + public void close() throws ElasticsearchException { + settingsService.removeListener(applySettings); + } /** * Returns the rate limiting, either of the index is explicitly configured, or * the node level one (defaults to the node level one). */ - StoreRateLimiting rateLimiting(); + public StoreRateLimiting rateLimiting() { + return nodeRateLimiting ? indicesStore.rateLimiting() : this.rateLimiting; + } /** * The shard store class that should be used for each shard. */ - Class shardDirectory(); - + public Class shardDirectory() { + return FsDirectoryService.class; + } } diff --git a/src/main/java/org/elasticsearch/index/store/IndexStoreModule.java b/src/main/java/org/elasticsearch/index/store/IndexStoreModule.java index a4aa4d694a2..c40301d560b 100644 --- a/src/main/java/org/elasticsearch/index/store/IndexStoreModule.java +++ b/src/main/java/org/elasticsearch/index/store/IndexStoreModule.java @@ -20,23 +20,16 @@ package org.elasticsearch.index.store; import com.google.common.collect.ImmutableList; -import org.apache.lucene.store.MMapDirectory; -import org.apache.lucene.util.Constants; -import org.elasticsearch.common.inject.AbstractModule; -import org.elasticsearch.common.inject.Module; -import org.elasticsearch.common.inject.Modules; -import org.elasticsearch.common.inject.SpawnModules; +import org.elasticsearch.common.inject.*; import org.elasticsearch.common.settings.Settings; -import org.elasticsearch.index.store.fs.DefaultFsIndexStoreModule; -import org.elasticsearch.index.store.fs.MmapFsIndexStoreModule; -import org.elasticsearch.index.store.fs.NioFsIndexStoreModule; -import org.elasticsearch.index.store.fs.SimpleFsIndexStoreModule; /** * */ public class IndexStoreModule extends AbstractModule implements SpawnModules { + public static final String STORE_TYPE = "index.store.type"; + private final Settings settings; public static enum Type { @@ -75,36 +68,23 @@ public class IndexStoreModule extends AbstractModule implements SpawnModules { @Override public Iterable spawnModules() { - Class indexStoreModule = NioFsIndexStoreModule.class; - if ((Constants.WINDOWS || Constants.SUN_OS || Constants.LINUX) - && Constants.JRE_IS_64BIT && MMapDirectory.UNMAP_SUPPORTED) { - if (Constants.WINDOWS) { - indexStoreModule = MmapFsIndexStoreModule.class; - } else { - // on linux and friends we only mmap dedicated files - indexStoreModule = DefaultFsIndexStoreModule.class; + final String storeType = settings.get(STORE_TYPE, Type.DEFAULT.name()); + for (Type type : Type.values()) { + if (type.match(storeType)) { + return ImmutableList.of(new DefaultStoreModule()); } - } else if (Constants.WINDOWS) { - indexStoreModule = SimpleFsIndexStoreModule.class; - } - String storeType = settings.get("index.store.type"); - if (Type.FS.match(storeType)) { - // nothing to set here ... (we default to fs) - } else if (Type.SIMPLEFS.match(storeType)) { - indexStoreModule = SimpleFsIndexStoreModule.class; - } else if (Type.NIOFS.match(storeType)) { - indexStoreModule = NioFsIndexStoreModule.class; - } else if (Type.MMAPFS.match(storeType)) { - indexStoreModule = MmapFsIndexStoreModule.class; - } else if (Type.DEFAULT.match(storeType)) { - indexStoreModule = DefaultFsIndexStoreModule.class; - } else if (storeType != null) { - indexStoreModule = settings.getAsClass("index.store.type", indexStoreModule, "org.elasticsearch.index.store.", "IndexStoreModule"); } + final Class indexStoreModule = settings.getAsClass(STORE_TYPE, null, "org.elasticsearch.index.store.", "IndexStoreModule"); return ImmutableList.of(Modules.createModule(indexStoreModule, settings)); } @Override - protected void configure() { + protected void configure() {} + + private static class DefaultStoreModule extends AbstractModule { + @Override + protected void configure() { + bind(IndexStore.class).asEagerSingleton(); + } } } \ No newline at end of file diff --git a/src/main/java/org/elasticsearch/index/store/fs/DefaultFsDirectoryService.java b/src/main/java/org/elasticsearch/index/store/fs/DefaultFsDirectoryService.java deleted file mode 100644 index ee1ed85f1e7..00000000000 --- a/src/main/java/org/elasticsearch/index/store/fs/DefaultFsDirectoryService.java +++ /dev/null @@ -1,63 +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.store.fs; - -import com.google.common.collect.Sets; -import org.apache.lucene.store.*; -import org.elasticsearch.common.inject.Inject; -import org.elasticsearch.common.settings.Settings; -import org.elasticsearch.index.settings.IndexSettings; -import org.elasticsearch.index.shard.ShardId; -import org.elasticsearch.index.shard.ShardPath; -import org.elasticsearch.index.store.IndexStore; - -import java.io.File; -import java.io.IOException; -import java.nio.file.Path; -import java.util.Collections; -import java.util.Set; - -/** - */ -public class DefaultFsDirectoryService extends FsDirectoryService { - /* - * We are mmapping docvalues as well as term dictionaries, all other files are served through NIOFS - * this provides good random access performance while not creating unnecessary mmaps for files like stored - * fields etc. - */ - private static final Set PRIMARY_EXTENSIONS = Collections.unmodifiableSet(Sets.newHashSet("dvd", "tim")); - - @Inject - public DefaultFsDirectoryService(ShardId shardId, @IndexSettings Settings indexSettings, IndexStore indexStore, ShardPath shardPath) { - super(shardId, indexSettings, indexStore, shardPath); - } - - @Override - protected Directory newFSDirectory(Path location, LockFactory lockFactory) throws IOException { - final MMapDirectory mmapDir = new MMapDirectory(location, lockFactory); - return new FileSwitchDirectory(PRIMARY_EXTENSIONS, mmapDir, new NIOFSDirectory(location, lockFactory), true) { - @Override - public String[] listAll() throws IOException { - // Avoid doing listAll twice: - return mmapDir.listAll(); - } - }; - } -} diff --git a/src/main/java/org/elasticsearch/index/store/fs/DefaultFsIndexStore.java b/src/main/java/org/elasticsearch/index/store/fs/DefaultFsIndexStore.java deleted file mode 100644 index ccd8369a58e..00000000000 --- a/src/main/java/org/elasticsearch/index/store/fs/DefaultFsIndexStore.java +++ /dev/null @@ -1,46 +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.store.fs; - -import org.elasticsearch.common.inject.Inject; -import org.elasticsearch.common.settings.Settings; -import org.elasticsearch.env.NodeEnvironment; -import org.elasticsearch.index.Index; -import org.elasticsearch.index.IndexService; -import org.elasticsearch.index.settings.IndexSettings; -import org.elasticsearch.index.store.DirectoryService; -import org.elasticsearch.index.store.support.AbstractIndexStore; -import org.elasticsearch.indices.store.IndicesStore; - -/** - * - */ -public final class DefaultFsIndexStore extends AbstractIndexStore { - - @Inject - public DefaultFsIndexStore(Index index, @IndexSettings Settings indexSettings, IndexService indexService, IndicesStore indicesStore, NodeEnvironment nodeEnv) { - super(index, indexSettings, indexService, indicesStore, nodeEnv); - } - - @Override - public Class shardDirectory() { - return DefaultFsDirectoryService.class; - } -} \ No newline at end of file diff --git a/src/main/java/org/elasticsearch/index/store/fs/DefaultFsIndexStoreModule.java b/src/main/java/org/elasticsearch/index/store/fs/DefaultFsIndexStoreModule.java deleted file mode 100644 index 895ba668a0e..00000000000 --- a/src/main/java/org/elasticsearch/index/store/fs/DefaultFsIndexStoreModule.java +++ /dev/null @@ -1,34 +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.store.fs; - -import org.elasticsearch.common.inject.AbstractModule; -import org.elasticsearch.index.store.IndexStore; - -/** - * - */ -public class DefaultFsIndexStoreModule extends AbstractModule { - - @Override - protected void configure() { - bind(IndexStore.class).to(DefaultFsIndexStore.class).asEagerSingleton(); - } -} \ No newline at end of file diff --git a/src/main/java/org/elasticsearch/index/store/fs/MmapFsDirectoryService.java b/src/main/java/org/elasticsearch/index/store/fs/MmapFsDirectoryService.java deleted file mode 100644 index 9f9102eba4d..00000000000 --- a/src/main/java/org/elasticsearch/index/store/fs/MmapFsDirectoryService.java +++ /dev/null @@ -1,49 +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.store.fs; - -import org.apache.lucene.store.Directory; -import org.apache.lucene.store.LockFactory; -import org.apache.lucene.store.MMapDirectory; -import org.elasticsearch.common.inject.Inject; -import org.elasticsearch.common.settings.Settings; -import org.elasticsearch.index.settings.IndexSettings; -import org.elasticsearch.index.shard.ShardId; -import org.elasticsearch.index.shard.ShardPath; -import org.elasticsearch.index.store.IndexStore; - -import java.io.File; -import java.io.IOException; -import java.nio.file.Path; - -/** - */ -public class MmapFsDirectoryService extends FsDirectoryService { - - @Inject - public MmapFsDirectoryService(ShardId shardId, @IndexSettings Settings indexSettings, IndexStore indexStore, ShardPath shardPath) { - super(shardId, indexSettings, indexStore, shardPath); - } - - @Override - protected Directory newFSDirectory(Path location, LockFactory lockFactory) throws IOException { - return new MMapDirectory(location, buildLockFactory()); - } -} diff --git a/src/main/java/org/elasticsearch/index/store/fs/MmapFsIndexStore.java b/src/main/java/org/elasticsearch/index/store/fs/MmapFsIndexStore.java deleted file mode 100644 index 444cd67b713..00000000000 --- a/src/main/java/org/elasticsearch/index/store/fs/MmapFsIndexStore.java +++ /dev/null @@ -1,46 +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.store.fs; - -import org.elasticsearch.common.inject.Inject; -import org.elasticsearch.common.settings.Settings; -import org.elasticsearch.env.NodeEnvironment; -import org.elasticsearch.index.Index; -import org.elasticsearch.index.IndexService; -import org.elasticsearch.index.settings.IndexSettings; -import org.elasticsearch.index.store.DirectoryService; -import org.elasticsearch.index.store.support.AbstractIndexStore; -import org.elasticsearch.indices.store.IndicesStore; - -/** - * - */ -public final class MmapFsIndexStore extends AbstractIndexStore { - - @Inject - public MmapFsIndexStore(Index index, @IndexSettings Settings indexSettings, IndexService indexService, IndicesStore indicesStore, NodeEnvironment nodeEnv) { - super(index, indexSettings, indexService, indicesStore, nodeEnv); - } - - @Override - public Class shardDirectory() { - return MmapFsDirectoryService.class; - } -} \ No newline at end of file diff --git a/src/main/java/org/elasticsearch/index/store/fs/MmapFsIndexStoreModule.java b/src/main/java/org/elasticsearch/index/store/fs/MmapFsIndexStoreModule.java deleted file mode 100644 index 7f655908355..00000000000 --- a/src/main/java/org/elasticsearch/index/store/fs/MmapFsIndexStoreModule.java +++ /dev/null @@ -1,34 +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.store.fs; - -import org.elasticsearch.common.inject.AbstractModule; -import org.elasticsearch.index.store.IndexStore; - -/** - * - */ -public class MmapFsIndexStoreModule extends AbstractModule { - - @Override - protected void configure() { - bind(IndexStore.class).to(MmapFsIndexStore.class).asEagerSingleton(); - } -} \ No newline at end of file diff --git a/src/main/java/org/elasticsearch/index/store/fs/NioFsDirectoryService.java b/src/main/java/org/elasticsearch/index/store/fs/NioFsDirectoryService.java deleted file mode 100644 index b2d99fa3b82..00000000000 --- a/src/main/java/org/elasticsearch/index/store/fs/NioFsDirectoryService.java +++ /dev/null @@ -1,49 +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.store.fs; - -import org.apache.lucene.store.Directory; -import org.apache.lucene.store.LockFactory; -import org.apache.lucene.store.NIOFSDirectory; -import org.elasticsearch.common.inject.Inject; -import org.elasticsearch.common.settings.Settings; -import org.elasticsearch.index.settings.IndexSettings; -import org.elasticsearch.index.shard.ShardId; -import org.elasticsearch.index.shard.ShardPath; -import org.elasticsearch.index.store.IndexStore; - -import java.io.File; -import java.io.IOException; -import java.nio.file.Path; - -/** - */ -public class NioFsDirectoryService extends FsDirectoryService { - - @Inject - public NioFsDirectoryService(ShardId shardId, @IndexSettings Settings indexSettings, IndexStore indexStore, ShardPath shardPath) { - super(shardId, indexSettings, indexStore, shardPath); - } - - @Override - protected Directory newFSDirectory(Path location, LockFactory lockFactory) throws IOException { - return new NIOFSDirectory(location, lockFactory); - } -} diff --git a/src/main/java/org/elasticsearch/index/store/fs/NioFsIndexStore.java b/src/main/java/org/elasticsearch/index/store/fs/NioFsIndexStore.java deleted file mode 100644 index 7f5cece99b6..00000000000 --- a/src/main/java/org/elasticsearch/index/store/fs/NioFsIndexStore.java +++ /dev/null @@ -1,46 +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.store.fs; - -import org.elasticsearch.common.inject.Inject; -import org.elasticsearch.common.settings.Settings; -import org.elasticsearch.env.NodeEnvironment; -import org.elasticsearch.index.Index; -import org.elasticsearch.index.IndexService; -import org.elasticsearch.index.settings.IndexSettings; -import org.elasticsearch.index.store.DirectoryService; -import org.elasticsearch.index.store.support.AbstractIndexStore; -import org.elasticsearch.indices.store.IndicesStore; - -/** - * - */ -public final class NioFsIndexStore extends AbstractIndexStore { - - @Inject - public NioFsIndexStore(Index index, @IndexSettings Settings indexSettings, IndexService indexService, IndicesStore indicesStore, NodeEnvironment nodeEnv) { - super(index, indexSettings, indexService, indicesStore, nodeEnv); - } - - @Override - public Class shardDirectory() { - return NioFsDirectoryService.class; - } -} \ No newline at end of file diff --git a/src/main/java/org/elasticsearch/index/store/fs/NioFsIndexStoreModule.java b/src/main/java/org/elasticsearch/index/store/fs/NioFsIndexStoreModule.java deleted file mode 100644 index 9db1cbdec6b..00000000000 --- a/src/main/java/org/elasticsearch/index/store/fs/NioFsIndexStoreModule.java +++ /dev/null @@ -1,34 +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.store.fs; - -import org.elasticsearch.common.inject.AbstractModule; -import org.elasticsearch.index.store.IndexStore; - -/** - * - */ -public class NioFsIndexStoreModule extends AbstractModule { - - @Override - protected void configure() { - bind(IndexStore.class).to(NioFsIndexStore.class).asEagerSingleton(); - } -} \ No newline at end of file diff --git a/src/main/java/org/elasticsearch/index/store/fs/SimpleFsDirectoryService.java b/src/main/java/org/elasticsearch/index/store/fs/SimpleFsDirectoryService.java deleted file mode 100644 index 051b278cd11..00000000000 --- a/src/main/java/org/elasticsearch/index/store/fs/SimpleFsDirectoryService.java +++ /dev/null @@ -1,49 +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.store.fs; - -import org.apache.lucene.store.Directory; -import org.apache.lucene.store.LockFactory; -import org.apache.lucene.store.SimpleFSDirectory; -import org.elasticsearch.common.inject.Inject; -import org.elasticsearch.common.settings.Settings; -import org.elasticsearch.index.settings.IndexSettings; -import org.elasticsearch.index.shard.ShardId; -import org.elasticsearch.index.shard.ShardPath; -import org.elasticsearch.index.store.IndexStore; - -import java.io.File; -import java.io.IOException; -import java.nio.file.Path; - -/** - */ -public class SimpleFsDirectoryService extends FsDirectoryService { - - @Inject - public SimpleFsDirectoryService(ShardId shardId, @IndexSettings Settings indexSettings, IndexStore indexStore, ShardPath shardPath) { - super(shardId, indexSettings, indexStore, shardPath); - } - - @Override - protected Directory newFSDirectory(Path location, LockFactory lockFactory) throws IOException { - return new SimpleFSDirectory(location, lockFactory); - } -} diff --git a/src/main/java/org/elasticsearch/index/store/fs/SimpleFsIndexStore.java b/src/main/java/org/elasticsearch/index/store/fs/SimpleFsIndexStore.java deleted file mode 100644 index 1a9f40b9779..00000000000 --- a/src/main/java/org/elasticsearch/index/store/fs/SimpleFsIndexStore.java +++ /dev/null @@ -1,46 +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.store.fs; - -import org.elasticsearch.common.inject.Inject; -import org.elasticsearch.common.settings.Settings; -import org.elasticsearch.env.NodeEnvironment; -import org.elasticsearch.index.Index; -import org.elasticsearch.index.IndexService; -import org.elasticsearch.index.settings.IndexSettings; -import org.elasticsearch.index.store.DirectoryService; -import org.elasticsearch.index.store.support.AbstractIndexStore; -import org.elasticsearch.indices.store.IndicesStore; - -/** - * - */ -public final class SimpleFsIndexStore extends AbstractIndexStore { - - @Inject - public SimpleFsIndexStore(Index index, @IndexSettings Settings indexSettings, IndexService indexService, IndicesStore indicesStore, NodeEnvironment nodeEnv) { - super(index, indexSettings, indexService, indicesStore, nodeEnv); - } - - @Override - public Class shardDirectory() { - return SimpleFsDirectoryService.class; - } -} diff --git a/src/main/java/org/elasticsearch/index/store/fs/SimpleFsIndexStoreModule.java b/src/main/java/org/elasticsearch/index/store/fs/SimpleFsIndexStoreModule.java deleted file mode 100644 index c35997aaf0d..00000000000 --- a/src/main/java/org/elasticsearch/index/store/fs/SimpleFsIndexStoreModule.java +++ /dev/null @@ -1,34 +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.store.fs; - -import org.elasticsearch.common.inject.AbstractModule; -import org.elasticsearch.index.store.IndexStore; - -/** - * - */ -public class SimpleFsIndexStoreModule extends AbstractModule { - - @Override - protected void configure() { - bind(IndexStore.class).to(SimpleFsIndexStore.class).asEagerSingleton(); - } -} \ No newline at end of file diff --git a/src/main/java/org/elasticsearch/index/store/support/AbstractIndexStore.java b/src/main/java/org/elasticsearch/index/store/support/AbstractIndexStore.java deleted file mode 100644 index f4e63c55ebf..00000000000 --- a/src/main/java/org/elasticsearch/index/store/support/AbstractIndexStore.java +++ /dev/null @@ -1,126 +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.store.support; - -import org.apache.lucene.store.StoreRateLimiting; -import org.elasticsearch.ElasticsearchException; -import org.elasticsearch.ElasticsearchIllegalStateException; -import org.elasticsearch.common.io.FileSystemUtils; -import org.elasticsearch.common.settings.Settings; -import org.elasticsearch.common.unit.ByteSizeValue; -import org.elasticsearch.env.NodeEnvironment; -import org.elasticsearch.index.AbstractIndexComponent; -import org.elasticsearch.index.Index; -import org.elasticsearch.index.IndexService; -import org.elasticsearch.index.settings.IndexSettings; -import org.elasticsearch.index.settings.IndexSettingsService; -import org.elasticsearch.index.shard.ShardId; -import org.elasticsearch.index.store.IndexStore; -import org.elasticsearch.indices.store.IndicesStore; - -import java.io.IOException; -import java.nio.file.Path; - -/** - * - */ -public abstract class AbstractIndexStore extends AbstractIndexComponent implements IndexStore { - - public static final String INDEX_STORE_THROTTLE_TYPE = "index.store.throttle.type"; - public static final String INDEX_STORE_THROTTLE_MAX_BYTES_PER_SEC = "index.store.throttle.max_bytes_per_sec"; - - class ApplySettings implements IndexSettingsService.Listener { - @Override - public void onRefreshSettings(Settings settings) { - String rateLimitingType = settings.get(INDEX_STORE_THROTTLE_TYPE, AbstractIndexStore.this.rateLimitingType); - if (!rateLimitingType.equals(AbstractIndexStore.this.rateLimitingType)) { - logger.info("updating index.store.throttle.type from [{}] to [{}]", AbstractIndexStore.this.rateLimitingType, rateLimitingType); - if (rateLimitingType.equalsIgnoreCase("node")) { - AbstractIndexStore.this.rateLimitingType = rateLimitingType; - AbstractIndexStore.this.nodeRateLimiting = true; - } else { - StoreRateLimiting.Type.fromString(rateLimitingType); - AbstractIndexStore.this.rateLimitingType = rateLimitingType; - AbstractIndexStore.this.nodeRateLimiting = false; - AbstractIndexStore.this.rateLimiting.setType(rateLimitingType); - } - } - - ByteSizeValue rateLimitingThrottle = settings.getAsBytesSize(INDEX_STORE_THROTTLE_MAX_BYTES_PER_SEC, AbstractIndexStore.this.rateLimitingThrottle); - if (!rateLimitingThrottle.equals(AbstractIndexStore.this.rateLimitingThrottle)) { - logger.info("updating index.store.throttle.max_bytes_per_sec from [{}] to [{}], note, type is [{}]", AbstractIndexStore.this.rateLimitingThrottle, rateLimitingThrottle, AbstractIndexStore.this.rateLimitingType); - AbstractIndexStore.this.rateLimitingThrottle = rateLimitingThrottle; - AbstractIndexStore.this.rateLimiting.setMaxRate(rateLimitingThrottle); - } - } - } - private final NodeEnvironment nodeEnv; - - private final Path[] locations; - - protected final IndexService indexService; - - protected final IndicesStore indicesStore; - - private volatile String rateLimitingType; - private volatile ByteSizeValue rateLimitingThrottle; - private volatile boolean nodeRateLimiting; - - private final StoreRateLimiting rateLimiting = new StoreRateLimiting(); - - private final ApplySettings applySettings = new ApplySettings(); - - protected AbstractIndexStore(Index index, @IndexSettings Settings indexSettings, IndexService indexService, IndicesStore indicesStore, NodeEnvironment nodeEnv) { - super(index, indexSettings); - this.indexService = indexService; - this.indicesStore = indicesStore; - - this.rateLimitingType = indexSettings.get(INDEX_STORE_THROTTLE_TYPE, "none"); - if (rateLimitingType.equalsIgnoreCase("node")) { - nodeRateLimiting = true; - } else { - nodeRateLimiting = false; - rateLimiting.setType(rateLimitingType); - } - this.rateLimitingThrottle = indexSettings.getAsBytesSize(INDEX_STORE_THROTTLE_MAX_BYTES_PER_SEC, new ByteSizeValue(0)); - rateLimiting.setMaxRate(rateLimitingThrottle); - - logger.debug("using index.store.throttle.type [{}], with index.store.throttle.max_bytes_per_sec [{}]", rateLimitingType, rateLimitingThrottle); - - indexService.settingsService().addListener(applySettings); - this.nodeEnv = nodeEnv; - if (nodeEnv.hasNodeFile()) { - this.locations = nodeEnv.indexPaths(index); - } else { - this.locations = null; - } - - } - - @Override - public void close() throws ElasticsearchException { - indexService.settingsService().removeListener(applySettings); - } - - @Override - public StoreRateLimiting rateLimiting() { - return nodeRateLimiting ? indicesStore.rateLimiting() : this.rateLimiting; - } -} diff --git a/src/main/java/org/elasticsearch/indices/store/IndicesStore.java b/src/main/java/org/elasticsearch/indices/store/IndicesStore.java index 643f91172b2..4737271c203 100644 --- a/src/main/java/org/elasticsearch/indices/store/IndicesStore.java +++ b/src/main/java/org/elasticsearch/indices/store/IndicesStore.java @@ -89,8 +89,6 @@ public class IndicesStore extends AbstractComponent implements ClusterStateListe } } - private final NodeEnvironment nodeEnv; - private final NodeSettingsService nodeSettingsService; private final IndicesService indicesService; @@ -107,10 +105,9 @@ public class IndicesStore extends AbstractComponent implements ClusterStateListe private TimeValue deleteShardTimeout; @Inject - public IndicesStore(Settings settings, NodeEnvironment nodeEnv, NodeSettingsService nodeSettingsService, IndicesService indicesService, + public IndicesStore(Settings settings, NodeSettingsService nodeSettingsService, IndicesService indicesService, ClusterService clusterService, TransportService transportService) { super(settings); - this.nodeEnv = nodeEnv; this.nodeSettingsService = nodeSettingsService; this.indicesService = indicesService; this.clusterService = clusterService; @@ -133,7 +130,6 @@ public class IndicesStore extends AbstractComponent implements ClusterStateListe IndicesStore() { super(ImmutableSettings.EMPTY); - nodeEnv = null; nodeSettingsService = null; indicesService = null; this.clusterService = null; diff --git a/src/main/java/org/elasticsearch/indices/store/TransportNodesListShardStoreMetaData.java b/src/main/java/org/elasticsearch/indices/store/TransportNodesListShardStoreMetaData.java index 1f0bf84a2f4..26223aac2ea 100644 --- a/src/main/java/org/elasticsearch/indices/store/TransportNodesListShardStoreMetaData.java +++ b/src/main/java/org/elasticsearch/indices/store/TransportNodesListShardStoreMetaData.java @@ -43,6 +43,7 @@ import org.elasticsearch.index.IndexService; import org.elasticsearch.index.shard.IndexShard; import org.elasticsearch.index.shard.ShardId; import org.elasticsearch.index.shard.ShardPath; +import org.elasticsearch.index.store.IndexStoreModule; import org.elasticsearch.index.store.Store; import org.elasticsearch.index.store.StoreFileMetaData; import org.elasticsearch.indices.IndicesService; @@ -168,7 +169,7 @@ public class TransportNodesListShardStoreMetaData extends TransportNodesOperatio if (metaData == null) { return new StoreFilesMetaData(false, shardId, ImmutableMap.of()); } - String storeType = metaData.settings().get("index.store.type", "fs"); + String storeType = metaData.settings().get(IndexStoreModule.STORE_TYPE, "fs"); if (!storeType.contains("fs")) { return new StoreFilesMetaData(false, shardId, ImmutableMap.of()); } diff --git a/src/test/java/org/elasticsearch/client/transport/TransportClientTests.java b/src/test/java/org/elasticsearch/client/transport/TransportClientTests.java index dcf35d2dff6..8e347935241 100644 --- a/src/test/java/org/elasticsearch/client/transport/TransportClientTests.java +++ b/src/test/java/org/elasticsearch/client/transport/TransportClientTests.java @@ -25,6 +25,7 @@ import org.elasticsearch.cluster.node.DiscoveryNode; import org.elasticsearch.common.settings.ImmutableSettings; import org.elasticsearch.common.settings.Settings; import org.elasticsearch.common.transport.TransportAddress; +import org.elasticsearch.index.store.IndexStoreModule; import org.elasticsearch.node.Node; import org.elasticsearch.test.ElasticsearchIntegrationTest; import org.elasticsearch.test.ElasticsearchIntegrationTest.ClusterScope; @@ -57,7 +58,6 @@ public class TransportClientTests extends ElasticsearchIntegrationTest { .put("path.home", createTempDir()) .put("node.name", "testNodeVersionIsUpdated") .put("http.enabled", false) - .put("index.store.type", "ram") .put("config.ignore_system_properties", true) // make sure we get what we set :) .build()).clusterName("foobar").build(); node.start(); diff --git a/src/test/java/org/elasticsearch/index/store/IndexStoreTests.java b/src/test/java/org/elasticsearch/index/store/IndexStoreTests.java new file mode 100644 index 00000000000..a063edf7a8f --- /dev/null +++ b/src/test/java/org/elasticsearch/index/store/IndexStoreTests.java @@ -0,0 +1,86 @@ +/* + * 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.store; + +import com.carrotsearch.randomizedtesting.generators.RandomPicks; +import org.apache.lucene.store.*; +import org.apache.lucene.util.Constants; +import org.elasticsearch.common.settings.ImmutableSettings; +import org.elasticsearch.common.settings.Settings; +import org.elasticsearch.index.shard.ShardId; +import org.elasticsearch.index.shard.ShardPath; +import org.elasticsearch.test.ElasticsearchTestCase; + +import java.io.IOException; +import java.nio.file.Path; + +/** + */ +public class IndexStoreTests extends ElasticsearchTestCase { + + public void testStoreDirectory() throws IOException { + final Path tempDir = createTempDir(); + final IndexStoreModule.Type[] values = IndexStoreModule.Type.values(); + final IndexStoreModule.Type type = RandomPicks.randomFrom(random(), values); + Settings settings = ImmutableSettings.settingsBuilder().put(IndexStoreModule.STORE_TYPE, type.name()).build(); + FsDirectoryService service = new FsDirectoryService(settings, null, new ShardPath(tempDir, tempDir, "foo", new ShardId("foo", 0))); + try (final Directory directory = service.newFSDirectory(tempDir, NoLockFactory.INSTANCE)) { + switch (type) { + case NIOFS: + assertTrue(type + " " + directory.toString(), directory instanceof NIOFSDirectory); + break; + case MMAPFS: + assertTrue(type + " " + directory.toString(), directory instanceof MMapDirectory); + break; + case SIMPLEFS: + assertTrue(type + " " + directory.toString(), directory instanceof SimpleFSDirectory); + break; + case FS: + case DEFAULT: + if (Constants.WINDOWS) { + if (Constants.JRE_IS_64BIT && MMapDirectory.UNMAP_SUPPORTED) { + assertTrue(type + " " + directory.toString(), directory instanceof MMapDirectory); + } else { + assertTrue(type + " " + directory.toString(), directory instanceof SimpleFSDirectory); + } + } else if (Constants.JRE_IS_64BIT && MMapDirectory.UNMAP_SUPPORTED) { + assertTrue(type + " " + directory.toString(), directory instanceof FileSwitchDirectory); + } else { + assertTrue(type + " " + directory.toString(), directory instanceof NIOFSDirectory); + } + break; + } + } + } + + public void testStoreDirectoryDefault() throws IOException { + final Path tempDir = createTempDir(); + Settings settings = ImmutableSettings.EMPTY; + FsDirectoryService service = new FsDirectoryService(settings, null, new ShardPath(tempDir, tempDir, "foo", new ShardId("foo", 0))); + try (final Directory directory = service.newFSDirectory(tempDir, NoLockFactory.INSTANCE)) { + if (Constants.WINDOWS) { + assertTrue(directory.toString(), directory instanceof MMapDirectory || directory instanceof SimpleFSDirectory); + } else { + assertTrue(directory.toString(), directory instanceof FileSwitchDirectory); + } + } + } + + +} diff --git a/src/test/java/org/elasticsearch/indices/settings/UpdateSettingsTests.java b/src/test/java/org/elasticsearch/indices/settings/UpdateSettingsTests.java index 73d08959622..0d00ea5291e 100644 --- a/src/test/java/org/elasticsearch/indices/settings/UpdateSettingsTests.java +++ b/src/test/java/org/elasticsearch/indices/settings/UpdateSettingsTests.java @@ -23,7 +23,6 @@ import org.apache.log4j.AppenderSkeleton; import org.apache.log4j.Level; import org.apache.log4j.Logger; import org.apache.log4j.spi.LoggingEvent; -import org.apache.lucene.util.LuceneTestCase.Slow; import org.elasticsearch.ElasticsearchIllegalArgumentException; import org.elasticsearch.action.admin.cluster.health.ClusterHealthResponse; import org.elasticsearch.action.admin.cluster.node.stats.NodeStats; @@ -37,8 +36,8 @@ import org.elasticsearch.index.engine.VersionConflictEngineException; import org.elasticsearch.index.merge.policy.TieredMergePolicyProvider; import org.elasticsearch.index.merge.scheduler.ConcurrentMergeSchedulerProvider; import org.elasticsearch.index.merge.scheduler.MergeSchedulerModule; +import org.elasticsearch.index.store.IndexStore; import org.elasticsearch.index.store.Store; -import org.elasticsearch.index.store.support.AbstractIndexStore; import org.elasticsearch.test.ElasticsearchIntegrationTest; import org.junit.Test; @@ -137,7 +136,7 @@ public class UpdateSettingsTests extends ElasticsearchIntegrationTest { // No throttling at first, only 1 non-replicated shard, force lots of merging: assertAcked(prepareCreate("test") .setSettings(ImmutableSettings.builder() - .put(AbstractIndexStore.INDEX_STORE_THROTTLE_TYPE, "none") + .put(IndexStore.INDEX_STORE_THROTTLE_TYPE, "none") .put(IndexMetaData.SETTING_NUMBER_OF_SHARDS, "1") .put(IndexMetaData.SETTING_NUMBER_OF_REPLICAS, "0") .put(TieredMergePolicyProvider.INDEX_MERGE_POLICY_MAX_MERGE_AT_ONCE, "2") @@ -175,13 +174,13 @@ public class UpdateSettingsTests extends ElasticsearchIntegrationTest { .indices() .prepareUpdateSettings("test") .setSettings(ImmutableSettings.builder() - .put(AbstractIndexStore.INDEX_STORE_THROTTLE_TYPE, "merge") - .put(AbstractIndexStore.INDEX_STORE_THROTTLE_MAX_BYTES_PER_SEC, "1mb")) + .put(IndexStore.INDEX_STORE_THROTTLE_TYPE, "merge") + .put(IndexStore.INDEX_STORE_THROTTLE_MAX_BYTES_PER_SEC, "1mb")) .get(); // Make sure setting says it is in fact changed: GetSettingsResponse getSettingsResponse = client().admin().indices().prepareGetSettings("test").get(); - assertThat(getSettingsResponse.getSetting("test", AbstractIndexStore.INDEX_STORE_THROTTLE_TYPE), equalTo("merge")); + assertThat(getSettingsResponse.getSetting("test", IndexStore.INDEX_STORE_THROTTLE_TYPE), equalTo("merge")); // Also make sure we see throttling kicking in: boolean done = false; @@ -215,7 +214,7 @@ public class UpdateSettingsTests extends ElasticsearchIntegrationTest { .indices() .prepareUpdateSettings("test") .setSettings(ImmutableSettings.builder() - .put(AbstractIndexStore.INDEX_STORE_THROTTLE_TYPE, "none")) + .put(IndexStore.INDEX_STORE_THROTTLE_TYPE, "none")) .get(); // Optimize does a waitForMerges, which we must do to make sure all in-flight (throttled) merges finish: diff --git a/src/test/java/org/elasticsearch/indices/stats/IndexStatsTests.java b/src/test/java/org/elasticsearch/indices/stats/IndexStatsTests.java index df7ba00d390..4ba7f711429 100644 --- a/src/test/java/org/elasticsearch/indices/stats/IndexStatsTests.java +++ b/src/test/java/org/elasticsearch/indices/stats/IndexStatsTests.java @@ -44,7 +44,7 @@ import org.elasticsearch.index.cache.filter.weighted.WeightedFilterCache; import org.elasticsearch.index.merge.policy.TieredMergePolicyProvider; import org.elasticsearch.index.merge.scheduler.ConcurrentMergeSchedulerProvider; import org.elasticsearch.index.query.FilterBuilders; -import org.elasticsearch.index.store.support.AbstractIndexStore; +import org.elasticsearch.index.store.IndexStore; import org.elasticsearch.indices.cache.query.IndicesQueryCache; import org.elasticsearch.search.sort.SortOrder; import org.elasticsearch.test.ElasticsearchIntegrationTest; @@ -308,7 +308,7 @@ public class IndexStatsTests extends ElasticsearchIntegrationTest { public void nonThrottleStats() throws Exception { assertAcked(prepareCreate("test") .setSettings(ImmutableSettings.builder() - .put(AbstractIndexStore.INDEX_STORE_THROTTLE_TYPE, "merge") + .put(IndexStore.INDEX_STORE_THROTTLE_TYPE, "merge") .put(IndexMetaData.SETTING_NUMBER_OF_SHARDS, "1") .put(IndexMetaData.SETTING_NUMBER_OF_REPLICAS, "0") .put(TieredMergePolicyProvider.INDEX_MERGE_POLICY_MAX_MERGE_AT_ONCE, "2") @@ -341,7 +341,7 @@ public class IndexStatsTests extends ElasticsearchIntegrationTest { public void throttleStats() throws Exception { assertAcked(prepareCreate("test") .setSettings(ImmutableSettings.builder() - .put(AbstractIndexStore.INDEX_STORE_THROTTLE_TYPE, "merge") + .put(IndexStore.INDEX_STORE_THROTTLE_TYPE, "merge") .put(IndexMetaData.SETTING_NUMBER_OF_SHARDS, "1") .put(IndexMetaData.SETTING_NUMBER_OF_REPLICAS, "0") .put(TieredMergePolicyProvider.INDEX_MERGE_POLICY_MAX_MERGE_AT_ONCE, "2") diff --git a/src/test/java/org/elasticsearch/snapshots/DedicatedClusterSnapshotRestoreTests.java b/src/test/java/org/elasticsearch/snapshots/DedicatedClusterSnapshotRestoreTests.java index 6cbff427afb..ff8264fdc03 100644 --- a/src/test/java/org/elasticsearch/snapshots/DedicatedClusterSnapshotRestoreTests.java +++ b/src/test/java/org/elasticsearch/snapshots/DedicatedClusterSnapshotRestoreTests.java @@ -21,11 +21,9 @@ package org.elasticsearch.snapshots; import com.carrotsearch.hppc.IntOpenHashSet; import com.carrotsearch.hppc.IntSet; -import com.carrotsearch.randomizedtesting.LifecycleScope; import com.google.common.base.Predicate; import com.google.common.collect.ImmutableList; import com.google.common.util.concurrent.ListenableFuture; -import org.apache.lucene.util.LuceneTestCase; import org.elasticsearch.ElasticsearchParseException; import org.elasticsearch.action.ListenableActionFuture; import org.elasticsearch.action.admin.cluster.repositories.put.PutRepositoryResponse; @@ -52,7 +50,7 @@ import org.elasticsearch.common.xcontent.ToXContent; import org.elasticsearch.common.xcontent.XContentBuilder; import org.elasticsearch.common.xcontent.XContentParser; import org.elasticsearch.discovery.zen.elect.ElectMasterService; -import org.elasticsearch.index.store.support.AbstractIndexStore; +import org.elasticsearch.index.store.IndexStore; import org.elasticsearch.indices.ttl.IndicesTTLService; import org.elasticsearch.repositories.RepositoryMissingException; import org.elasticsearch.snapshots.mockstore.MockRepositoryModule; @@ -699,7 +697,7 @@ public class DedicatedClusterSnapshotRestoreTests extends AbstractSnapshotTests logger.info("--> update index settings to back to normal"); assertAcked(client().admin().indices().prepareUpdateSettings("test-*").setSettings(ImmutableSettings.builder() - .put(AbstractIndexStore.INDEX_STORE_THROTTLE_TYPE, "node") + .put(IndexStore.INDEX_STORE_THROTTLE_TYPE, "node") )); // Make sure that snapshot finished - doesn't matter if it failed or succeeded @@ -745,8 +743,8 @@ public class DedicatedClusterSnapshotRestoreTests extends AbstractSnapshotTests } assertAcked(client().admin().indices().prepareUpdateSettings(name).setSettings(ImmutableSettings.builder() - .put(AbstractIndexStore.INDEX_STORE_THROTTLE_TYPE, "all") - .put(AbstractIndexStore.INDEX_STORE_THROTTLE_MAX_BYTES_PER_SEC, between(100, 50000)) + .put(IndexStore.INDEX_STORE_THROTTLE_TYPE, "all") + .put(IndexStore.INDEX_STORE_THROTTLE_MAX_BYTES_PER_SEC, between(100, 50000)) )); } diff --git a/src/test/java/org/elasticsearch/snapshots/SharedClusterSnapshotRestoreTests.java b/src/test/java/org/elasticsearch/snapshots/SharedClusterSnapshotRestoreTests.java index 947527376b4..be3c44e9cc6 100644 --- a/src/test/java/org/elasticsearch/snapshots/SharedClusterSnapshotRestoreTests.java +++ b/src/test/java/org/elasticsearch/snapshots/SharedClusterSnapshotRestoreTests.java @@ -52,11 +52,10 @@ import org.elasticsearch.common.settings.ImmutableSettings; import org.elasticsearch.common.settings.Settings; import org.elasticsearch.common.unit.TimeValue; import org.elasticsearch.index.shard.ShardId; -import org.elasticsearch.index.store.support.AbstractIndexStore; +import org.elasticsearch.index.store.IndexStore; import org.elasticsearch.indices.InvalidIndexNameException; import org.elasticsearch.repositories.RepositoriesService; import org.elasticsearch.snapshots.mockstore.MockRepositoryModule; -import org.elasticsearch.test.junit.annotations.TestLogging; import org.junit.Test; import java.nio.channels.SeekableByteChannel; @@ -1486,8 +1485,8 @@ public class SharedClusterSnapshotRestoreTests extends AbstractSnapshotTests { // Update settings to make sure that relocation is slow so we can start snapshot before relocation is finished assertAcked(client.admin().indices().prepareUpdateSettings("test-idx").setSettings(ImmutableSettings.builder() - .put(AbstractIndexStore.INDEX_STORE_THROTTLE_TYPE, "all") - .put(AbstractIndexStore.INDEX_STORE_THROTTLE_MAX_BYTES_PER_SEC, 100) + .put(IndexStore.INDEX_STORE_THROTTLE_TYPE, "all") + .put(IndexStore.INDEX_STORE_THROTTLE_MAX_BYTES_PER_SEC, 100) )); logger.info("--> start relocations"); @@ -1502,7 +1501,7 @@ public class SharedClusterSnapshotRestoreTests extends AbstractSnapshotTests { // Update settings to back to normal assertAcked(client.admin().indices().prepareUpdateSettings("test-idx").setSettings(ImmutableSettings.builder() - .put(AbstractIndexStore.INDEX_STORE_THROTTLE_TYPE, "node") + .put(IndexStore.INDEX_STORE_THROTTLE_TYPE, "node") )); logger.info("--> wait for snapshot to complete"); diff --git a/src/test/java/org/elasticsearch/test/InternalTestCluster.java b/src/test/java/org/elasticsearch/test/InternalTestCluster.java index b685448881b..660d228a43e 100644 --- a/src/test/java/org/elasticsearch/test/InternalTestCluster.java +++ b/src/test/java/org/elasticsearch/test/InternalTestCluster.java @@ -83,6 +83,7 @@ import org.elasticsearch.index.cache.filter.none.NoneFilterCache; import org.elasticsearch.index.cache.filter.weighted.WeightedFilterCache; import org.elasticsearch.index.shard.IndexShardModule; import org.elasticsearch.index.shard.ShardId; +import org.elasticsearch.index.store.IndexStoreModule; import org.elasticsearch.indices.IndicesService; import org.elasticsearch.indices.breaker.CircuitBreakerService; import org.elasticsearch.indices.breaker.HierarchyCircuitBreakerService; @@ -383,7 +384,7 @@ public final class InternalTestCluster extends TestCluster { .put("cluster.routing.schedule", (30 + random.nextInt(50)) + "ms") .put(SETTING_CLUSTER_NODE_SEED, seed); if (ENABLE_MOCK_MODULES && usually(random)) { - builder.put("index.store.type", MockFSIndexStoreModule.class.getName()); // no RAM dir for now! + builder.put(IndexStoreModule.STORE_TYPE, MockFSIndexStoreModule.class.getName()); // no RAM dir for now! builder.put(IndexShardModule.ENGINE_FACTORY, MockEngineFactory.class); builder.put(PageCacheRecyclerModule.CACHE_IMPL, MockPageCacheRecyclerModule.class.getName()); builder.put(BigArraysModule.IMPL, MockBigArraysModule.class.getName()); diff --git a/src/test/java/org/elasticsearch/test/store/MockDirectoryHelper.java b/src/test/java/org/elasticsearch/test/store/MockDirectoryHelper.java index 06b844b950a..90e06d6a5df 100644 --- a/src/test/java/org/elasticsearch/test/store/MockDirectoryHelper.java +++ b/src/test/java/org/elasticsearch/test/store/MockDirectoryHelper.java @@ -19,22 +19,21 @@ package org.elasticsearch.test.store; +import com.carrotsearch.randomizedtesting.generators.RandomPicks; import org.apache.lucene.store.Directory; import org.apache.lucene.store.FilterDirectory; -import org.apache.lucene.store.MMapDirectory; import org.apache.lucene.store.MockDirectoryWrapper.Throttling; import org.apache.lucene.store.MockDirectoryWrapper; import org.apache.lucene.store.NRTCachingDirectory; -import org.apache.lucene.util.Constants; -import org.apache.lucene.util.LuceneTestCase; import org.elasticsearch.common.logging.ESLogger; +import org.elasticsearch.common.settings.ImmutableSettings; import org.elasticsearch.common.settings.Settings; import org.elasticsearch.common.util.concurrent.ConcurrentCollections; import org.elasticsearch.index.shard.ShardId; import org.elasticsearch.index.shard.ShardPath; -import org.elasticsearch.index.store.DirectoryService; +import org.elasticsearch.index.store.FsDirectoryService; import org.elasticsearch.index.store.IndexStore; -import org.elasticsearch.index.store.fs.*; +import org.elasticsearch.index.store.IndexStoreModule; import com.carrotsearch.randomizedtesting.SeedUtils; import java.io.IOException; @@ -98,24 +97,10 @@ public class MockDirectoryHelper { } public FsDirectoryService randomDirectorService(IndexStore indexStore, ShardPath path) { - if ((Constants.WINDOWS || Constants.SUN_OS) && Constants.JRE_IS_64BIT && MMapDirectory.UNMAP_SUPPORTED) { - return new MmapFsDirectoryService(shardId, indexSettings, indexStore, path); - } else if (Constants.WINDOWS) { - return new SimpleFsDirectoryService(shardId, indexSettings, indexStore, path); - } - switch (random.nextInt(4)) { - case 2: - return new DefaultFsDirectoryService(shardId, indexSettings, indexStore, path); - case 1: - return new MmapFsDirectoryService(shardId, indexSettings, indexStore, path); - case 0: - if (random.nextInt(10) == 0) { - // use simplefs less, it synchronizes all threads reads - return new SimpleFsDirectoryService(shardId, indexSettings, indexStore, path); - } - default: - return new NioFsDirectoryService(shardId, indexSettings, indexStore, path); - } + ImmutableSettings.Builder builder = ImmutableSettings.settingsBuilder(); + builder.put(indexSettings); + builder.put(IndexStoreModule.STORE_TYPE, RandomPicks.randomFrom(random, IndexStoreModule.Type.values())); + return new FsDirectoryService(builder.build(), indexStore, path); } public static final class ElasticsearchMockDirectoryWrapper extends MockDirectoryWrapper { diff --git a/src/test/java/org/elasticsearch/test/store/MockFSDirectoryService.java b/src/test/java/org/elasticsearch/test/store/MockFSDirectoryService.java index 23825b3b3ae..c10c2863db1 100644 --- a/src/test/java/org/elasticsearch/test/store/MockFSDirectoryService.java +++ b/src/test/java/org/elasticsearch/test/store/MockFSDirectoryService.java @@ -37,7 +37,7 @@ import org.elasticsearch.index.settings.IndexSettings; import org.elasticsearch.index.shard.*; import org.elasticsearch.index.store.IndexStore; import org.elasticsearch.index.store.Store; -import org.elasticsearch.index.store.fs.FsDirectoryService; +import org.elasticsearch.index.store.FsDirectoryService; import org.elasticsearch.indices.IndicesLifecycle; import org.elasticsearch.indices.IndicesService; import org.elasticsearch.test.ElasticsearchTestCase; @@ -62,8 +62,8 @@ public class MockFSDirectoryService extends FsDirectoryService { private final boolean checkIndexOnClose; @Inject - public MockFSDirectoryService(final ShardId shardId, @IndexSettings Settings indexSettings, IndexStore indexStore, final IndicesService service, final ShardPath path) { - super(shardId, indexSettings, indexStore, path); + public MockFSDirectoryService(@IndexSettings Settings indexSettings, IndexStore indexStore, final IndicesService service, final ShardPath path) { + super(indexSettings, indexStore, path); final long seed = indexSettings.getAsLong(ElasticsearchIntegrationTest.SETTING_INDEX_SEED, 0l); Random random = new Random(seed); helper = new MockDirectoryHelper(shardId, indexSettings, logger, random, seed); diff --git a/src/test/java/org/elasticsearch/test/store/MockFSIndexStore.java b/src/test/java/org/elasticsearch/test/store/MockFSIndexStore.java index 27adcc09f46..ade21f3182b 100644 --- a/src/test/java/org/elasticsearch/test/store/MockFSIndexStore.java +++ b/src/test/java/org/elasticsearch/test/store/MockFSIndexStore.java @@ -25,16 +25,17 @@ import org.elasticsearch.env.NodeEnvironment; import org.elasticsearch.index.Index; import org.elasticsearch.index.IndexService; import org.elasticsearch.index.settings.IndexSettings; +import org.elasticsearch.index.settings.IndexSettingsService; import org.elasticsearch.index.store.DirectoryService; -import org.elasticsearch.index.store.support.AbstractIndexStore; +import org.elasticsearch.index.store.IndexStore; import org.elasticsearch.indices.store.IndicesStore; -public class MockFSIndexStore extends AbstractIndexStore { +public class MockFSIndexStore extends IndexStore { @Inject - public MockFSIndexStore(Index index, @IndexSettings Settings indexSettings, IndexService indexService, - IndicesStore indicesStore, NodeEnvironment nodeEnv) { - super(index, indexSettings, indexService, indicesStore, nodeEnv); + public MockFSIndexStore(Index index, @IndexSettings Settings indexSettings, IndexSettingsService indexSettingsService, + IndicesStore indicesStore) { + super(index, indexSettings, indexSettingsService, indicesStore); } @Override From cb615ffecfbc7849bcd83386d5f7cb7bd57ea4ba Mon Sep 17 00:00:00 2001 From: Simon Willnauer Date: Fri, 24 Apr 2015 13:18:35 +0200 Subject: [PATCH 12/14] [TEST] Don't use pretty print in tests Windowns has slight differences --- .../ElasticsearchExceptionTests.java | 77 +++---------------- .../rest/BytesRestResponseTests.java | 26 +------ 2 files changed, 11 insertions(+), 92 deletions(-) diff --git a/src/test/java/org/elasticsearch/ElasticsearchExceptionTests.java b/src/test/java/org/elasticsearch/ElasticsearchExceptionTests.java index 26447471c2c..74ea5f6e460 100644 --- a/src/test/java/org/elasticsearch/ElasticsearchExceptionTests.java +++ b/src/test/java/org/elasticsearch/ElasticsearchExceptionTests.java @@ -111,26 +111,11 @@ public class ElasticsearchExceptionTests extends ElasticsearchTestCase { ShardSearchFailure failure = new ShardSearchFailure(new QueryParsingException(new Index("foo"), "foobar"), new SearchShardTarget("node_1", "foo", 1)); ShardSearchFailure failure1 = new ShardSearchFailure(new QueryParsingException(new Index("foo"), "foobar"), new SearchShardTarget("node_1", "foo", 2)); SearchPhaseExecutionException ex = new SearchPhaseExecutionException("search", "all shards failed", new ShardSearchFailure[]{failure, failure1}); - XContentBuilder builder = XContentFactory.jsonBuilder().prettyPrint(); + XContentBuilder builder = XContentFactory.jsonBuilder(); builder.startObject(); ex.toXContent(builder, ToXContent.EMPTY_PARAMS); builder.endObject(); - String expected = "{\n" + - " \"type\" : \"search_phase_execution_exception\",\n" + - " \"reason\" : \"all shards failed\",\n" + - " \"phase\" : \"search\",\n" + - " \"grouped\" : true,\n" + - " \"failed_shards\" : [ {\n" + - " \"shard\" : 1,\n" + - " \"index\" : \"foo\",\n" + - " \"node\" : \"node_1\",\n" + - " \"reason\" : {\n" + - " \"type\" : \"query_parsing_exception\",\n" + - " \"reason\" : \"foobar\",\n" + - " \"index\" : \"foo\"\n" + - " }\n" + - " } ]\n" + - "}"; + String expected = "{\"type\":\"search_phase_execution_exception\",\"reason\":\"all shards failed\",\"phase\":\"search\",\"grouped\":true,\"failed_shards\":[{\"shard\":1,\"index\":\"foo\",\"node\":\"node_1\",\"reason\":{\"type\":\"query_parsing_exception\",\"reason\":\"foobar\",\"index\":\"foo\"}}]}"; assertEquals(expected, builder.string()); } { @@ -138,35 +123,11 @@ public class ElasticsearchExceptionTests extends ElasticsearchTestCase { ShardSearchFailure failure1 = new ShardSearchFailure(new QueryParsingException(new Index("foo1"), "foobar"), new SearchShardTarget("node_1", "foo1", 1)); ShardSearchFailure failure2 = new ShardSearchFailure(new QueryParsingException(new Index("foo1"), "foobar"), new SearchShardTarget("node_1", "foo1", 2)); SearchPhaseExecutionException ex = new SearchPhaseExecutionException("search", "all shards failed", new ShardSearchFailure[]{failure, failure1, failure2}); - XContentBuilder builder = XContentFactory.jsonBuilder().prettyPrint(); + XContentBuilder builder = XContentFactory.jsonBuilder(); builder.startObject(); ex.toXContent(builder, ToXContent.EMPTY_PARAMS); builder.endObject(); - String expected = "{\n" + - " \"type\" : \"search_phase_execution_exception\",\n" + - " \"reason\" : \"all shards failed\",\n" + - " \"phase\" : \"search\",\n" + - " \"grouped\" : true,\n" + - " \"failed_shards\" : [ {\n" + - " \"shard\" : 1,\n" + - " \"index\" : \"foo\",\n" + - " \"node\" : \"node_1\",\n" + - " \"reason\" : {\n" + - " \"type\" : \"query_parsing_exception\",\n" + - " \"reason\" : \"foobar\",\n" + - " \"index\" : \"foo\"\n" + - " }\n" + - " }, {\n" + - " \"shard\" : 1,\n" + - " \"index\" : \"foo1\",\n" + - " \"node\" : \"node_1\",\n" + - " \"reason\" : {\n" + - " \"type\" : \"query_parsing_exception\",\n" + - " \"reason\" : \"foobar\",\n" + - " \"index\" : \"foo1\"\n" + - " }\n" + - " } ]\n" + - "}"; + String expected = "{\"type\":\"search_phase_execution_exception\",\"reason\":\"all shards failed\",\"phase\":\"search\",\"grouped\":true,\"failed_shards\":[{\"shard\":1,\"index\":\"foo\",\"node\":\"node_1\",\"reason\":{\"type\":\"query_parsing_exception\",\"reason\":\"foobar\",\"index\":\"foo\"}},{\"shard\":1,\"index\":\"foo1\",\"node\":\"node_1\",\"reason\":{\"type\":\"query_parsing_exception\",\"reason\":\"foobar\",\"index\":\"foo1\"}}]}"; assertEquals(expected, builder.string()); } } @@ -187,27 +148,12 @@ public class ElasticsearchExceptionTests extends ElasticsearchTestCase { public void testToXContent() throws IOException { { ElasticsearchException ex = new ElasticsearchException("foo", new ElasticsearchException("bar", new ElasticsearchIllegalArgumentException("index is closed", new RuntimeException("foobar")))); - XContentBuilder builder = XContentFactory.jsonBuilder().prettyPrint(); + XContentBuilder builder = XContentFactory.jsonBuilder(); builder.startObject(); ex.toXContent(builder, ToXContent.EMPTY_PARAMS); builder.endObject(); - String expected = "{\n" + - " \"type\" : \"exception\",\n" + - " \"reason\" : \"foo\",\n" + - " \"caused_by\" : {\n" + - " \"type\" : \"exception\",\n" + - " \"reason\" : \"bar\",\n" + - " \"caused_by\" : {\n" + - " \"type\" : \"illegal_argument_exception\",\n" + - " \"reason\" : \"index is closed\",\n" + - " \"caused_by\" : {\n" + - " \"type\" : \"runtime_exception\",\n" + - " \"reason\" : \"foobar\"\n" + - " }\n" + - " }\n" + - " }\n" + - "}"; + String expected = "{\"type\":\"exception\",\"reason\":\"foo\",\"caused_by\":{\"type\":\"exception\",\"reason\":\"bar\",\"caused_by\":{\"type\":\"illegal_argument_exception\",\"reason\":\"index is closed\",\"caused_by\":{\"type\":\"runtime_exception\",\"reason\":\"foobar\"}}}}"; assertEquals(expected, builder.string()); } @@ -217,26 +163,23 @@ public class ElasticsearchExceptionTests extends ElasticsearchTestCase { // just a wrapper which is omitted ex = new RemoteTransportException("foobar", ex); } - XContentBuilder builder = XContentFactory.jsonBuilder().prettyPrint(); + XContentBuilder builder = XContentFactory.jsonBuilder(); builder.startObject(); ElasticsearchException.toXContent(builder, ToXContent.EMPTY_PARAMS, ex); builder.endObject(); - String expected = "{\n" + - " \"type\" : \"file_not_found_exception\",\n" + - " \"reason\" : \"foo not found\"\n" + - "}"; + String expected = "{\"type\":\"file_not_found_exception\",\"reason\":\"foo not found\"}"; assertEquals(expected, builder.string()); } { // test equivalence ElasticsearchException ex = new RemoteTransportException("foobar", new FileNotFoundException("foo not found")); - XContentBuilder builder = XContentFactory.jsonBuilder().prettyPrint(); + XContentBuilder builder = XContentFactory.jsonBuilder(); builder.startObject(); ElasticsearchException.toXContent(builder, ToXContent.EMPTY_PARAMS, ex); builder.endObject(); - XContentBuilder otherBuilder = XContentFactory.jsonBuilder().prettyPrint(); + XContentBuilder otherBuilder = XContentFactory.jsonBuilder(); otherBuilder.startObject(); ex.toXContent(otherBuilder, ToXContent.EMPTY_PARAMS); diff --git a/src/test/java/org/elasticsearch/rest/BytesRestResponseTests.java b/src/test/java/org/elasticsearch/rest/BytesRestResponseTests.java index 784015e9db0..8c0203e58de 100644 --- a/src/test/java/org/elasticsearch/rest/BytesRestResponseTests.java +++ b/src/test/java/org/elasticsearch/rest/BytesRestResponseTests.java @@ -133,37 +133,13 @@ public class BytesRestResponseTests extends ElasticsearchTestCase { @Test public void testConvert() throws IOException { RestRequest request = new FakeRestRequest(); - request.params().put("pretty", "true"); RestChannel channel = new DetailedExceptionRestChannel(request); ShardSearchFailure failure = new ShardSearchFailure(new QueryParsingException(new Index("foo"), "foobar"), new SearchShardTarget("node_1", "foo", 1)); ShardSearchFailure failure1 = new ShardSearchFailure(new QueryParsingException(new Index("foo"), "foobar"), new SearchShardTarget("node_1", "foo", 2)); SearchPhaseExecutionException ex = new SearchPhaseExecutionException("search", "all shards failed", new ShardSearchFailure[] {failure, failure1}); BytesRestResponse response = new BytesRestResponse(channel, new RemoteTransportException("foo", ex)); String text = response.content().toUtf8(); - String expected = "{\n" + - " \"error\" : {\n" + - " \"root_cause\" : [ {\n" + - " \"type\" : \"query_parsing_exception\",\n" + - " \"reason\" : \"foobar\",\n" + - " \"index\" : \"foo\"\n" + - " } ],\n" + - " \"type\" : \"search_phase_execution_exception\",\n" + - " \"reason\" : \"all shards failed\",\n" + - " \"phase\" : \"search\",\n" + - " \"grouped\" : true,\n" + - " \"failed_shards\" : [ {\n" + - " \"shard\" : 1,\n" + - " \"index\" : \"foo\",\n" + - " \"node\" : \"node_1\",\n" + - " \"reason\" : {\n" + - " \"type\" : \"query_parsing_exception\",\n" + - " \"reason\" : \"foobar\",\n" + - " \"index\" : \"foo\"\n" + - " }\n" + - " } ]\n" + - " },\n" + - " \"status\" : 400\n" + - "}"; + String expected = "{\"error\":{\"root_cause\":[{\"type\":\"query_parsing_exception\",\"reason\":\"foobar\",\"index\":\"foo\"}],\"type\":\"search_phase_execution_exception\",\"reason\":\"all shards failed\",\"phase\":\"search\",\"grouped\":true,\"failed_shards\":[{\"shard\":1,\"index\":\"foo\",\"node\":\"node_1\",\"reason\":{\"type\":\"query_parsing_exception\",\"reason\":\"foobar\",\"index\":\"foo\"}}]},\"status\":400}"; assertEquals(expected.trim(), text.trim()); } From 8dbb79c96af8b2d7efc10c8dc3552cf0e2042407 Mon Sep 17 00:00:00 2001 From: Shay Banon Date: Tue, 21 Apr 2015 10:20:34 +0200 Subject: [PATCH 13/14] refactor and cleanup transport request handling This refactoring and cleanup is that each request handler ends up implementing too many methods that can be provided when the request handler itself is registered, including a prototype like class that can be used to instantiate new request instances for streaming. closes #10730 --- .../health/TransportClusterHealthAction.java | 7 +- .../hotthreads/NodesHotThreadsRequest.java | 5 + .../TransportNodesHotThreadsAction.java | 18 +- .../node/info/TransportNodesInfoAction.java | 18 +- .../liveness/TransportLivenessAction.java | 14 +- .../TransportNodesShutdownAction.java | 21 +- .../node/stats/TransportNodesStatsAction.java | 18 +- .../TransportDeleteRepositoryAction.java | 7 +- .../get/TransportGetRepositoriesAction.java | 7 +- .../put/TransportPutRepositoryAction.java | 7 +- .../TransportVerifyRepositoryAction.java | 7 +- .../TransportClusterRerouteAction.java | 7 +- .../TransportClusterUpdateSettingsAction.java | 7 +- .../TransportClusterSearchShardsAction.java | 7 +- .../create/TransportCreateSnapshotAction.java | 7 +- .../delete/TransportDeleteSnapshotAction.java | 7 +- .../get/TransportGetSnapshotsAction.java | 7 +- .../TransportRestoreSnapshotAction.java | 7 +- .../status/TransportNodesSnapshotsStatus.java | 18 +- .../TransportSnapshotsStatusAction.java | 7 +- .../state/TransportClusterStateAction.java | 7 +- .../cluster/stats/ClusterStatsRequest.java | 3 + .../stats/TransportClusterStatsAction.java | 18 +- .../TransportPendingClusterTasksAction.java | 7 +- .../alias/TransportIndicesAliasesAction.java | 7 +- .../exists/TransportAliasesExistAction.java | 7 +- .../alias/get/TransportGetAliasesAction.java | 7 +- .../analyze/TransportAnalyzeAction.java | 56 +---- .../TransportClearIndicesCacheAction.java | 18 +- .../close/TransportCloseIndexAction.java | 7 +- .../create/TransportCreateIndexAction.java | 7 +- .../delete/TransportDeleteIndexAction.java | 7 +- .../exists/indices/IndicesExistsRequest.java | 5 + .../indices/TransportIndicesExistsAction.java | 7 +- .../types/TransportTypesExistsAction.java | 7 +- .../indices/flush/TransportFlushAction.java | 18 +- .../indices/get/TransportGetIndexAction.java | 7 +- .../get/TransportGetFieldMappingsAction.java | 8 +- .../TransportGetFieldMappingsIndexAction.java | 13 +- .../get/TransportGetMappingsAction.java | 7 +- .../put/TransportPutMappingAction.java | 7 +- .../open/TransportOpenIndexAction.java | 7 +- .../optimize/TransportOptimizeAction.java | 18 +- .../recovery/TransportRecoveryAction.java | 25 +- .../refresh/TransportRefreshAction.java | 18 +- .../TransportIndicesSegmentsAction.java | 18 +- .../get/TransportGetSettingsAction.java | 7 +- .../put/TransportUpdateSettingsAction.java | 7 +- .../stats/TransportIndicesStatsAction.java | 18 +- .../TransportDeleteIndexTemplateAction.java | 7 +- .../get/TransportGetIndexTemplatesAction.java | 7 +- .../put/TransportPutIndexTemplateAction.java | 7 +- .../query/TransportValidateQueryAction.java | 18 +- .../delete/TransportDeleteWarmerAction.java | 7 +- .../warmer/get/TransportGetWarmersAction.java | 7 +- .../warmer/put/TransportPutWarmerAction.java | 7 +- .../action/bulk/TransportBulkAction.java | 11 +- .../action/bulk/TransportShardBulkAction.java | 27 +-- .../action/count/TransportCountAction.java | 21 +- .../action/delete/TransportDeleteAction.java | 25 +- .../TransportDeleteByQueryAction.java | 7 +- .../TransportShardDeleteByQueryAction.java | 26 +-- .../action/exists/TransportExistsAction.java | 21 +- .../explain/TransportExplainAction.java | 13 +- .../TransportFieldStatsTransportAction.java | 17 +- .../action/get/TransportGetAction.java | 13 +- .../action/get/TransportMultiGetAction.java | 7 +- .../get/TransportShardMultiGetAction.java | 13 +- .../action/index/TransportIndexAction.java | 29 +-- .../TransportDeleteIndexedScriptAction.java | 7 +- .../get/TransportGetIndexedScriptAction.java | 7 +- .../put/TransportPutIndexedScriptAction.java | 7 +- .../mlt/TransportMoreLikeThisAction.java | 11 +- .../TransportMultiPercolateAction.java | 7 +- .../percolate/TransportPercolateAction.java | 18 +- .../TransportShardMultiPercolateAction.java | 13 +- .../search/TransportClearScrollAction.java | 10 +- .../search/TransportMultiSearchAction.java | 8 +- .../action/search/TransportSearchAction.java | 7 +- .../search/TransportSearchScrollAction.java | 12 +- .../suggest/TransportSuggestAction.java | 19 +- .../support/HandledTransportAction.java | 32 +-- .../TransportBroadcastOperationAction.java | 26 +-- .../TransportMasterNodeOperationAction.java | 52 +---- ...ransportMasterNodeReadOperationAction.java | 4 +- .../info/TransportClusterInfoAction.java | 4 +- .../nodes/TransportNodesOperationAction.java | 31 +-- .../ShardReplicationOperationRequest.java | 8 +- ...portIndicesReplicationOperationAction.java | 52 +---- ...nsportShardReplicationOperationAction.java | 104 ++------- .../custom/SingleCustomOperationRequest.java | 7 + .../TransportSingleCustomOperationAction.java | 96 ++------ ...ransportInstanceSingleOperationAction.java | 51 +--- .../shard/SingleShardOperationRequest.java | 9 +- .../TransportShardSingleOperationAction.java | 102 +------- .../TransportMultiTermVectorsAction.java | 7 +- .../TransportShardMultiTermsVectorAction.java | 13 +- .../TransportTermVectorsAction.java | 14 +- .../dfs/TransportDfsOnlyAction.java | 18 +- .../action/update/TransportUpdateAction.java | 7 +- .../action/index/NodeIndexDeletedAction.java | 30 +-- .../index/NodeMappingRefreshAction.java | 14 +- .../action/shard/ShardStateAction.java | 30 +-- .../discovery/zen/ZenDiscovery.java | 15 +- .../zen/fd/MasterFaultDetection.java | 14 +- .../discovery/zen/fd/NodesFaultDetection.java | 15 +- .../zen/membership/MembershipAction.java | 44 +--- .../zen/ping/multicast/MulticastZenPing.java | 15 +- .../zen/ping/unicast/UnicastZenPing.java | 16 +- .../publish/PublishClusterStateAction.java | 18 +- .../gateway/LocalAllocateDangledIndices.java | 15 +- .../TransportNodesListGatewayMetaState.java | 18 +- ...ransportNodesListGatewayStartedShards.java | 18 +- .../indices/recovery/RecoverySource.java | 17 +- .../indices/recovery/RecoveryTarget.java | 85 +------ .../indices/store/IndicesStore.java | 14 +- .../TransportNodesListShardStoreMetaData.java | 18 +- .../VerifyNodeRepositoryAction.java | 24 +- .../PublishRiverClusterStateAction.java | 21 +- .../action/SearchServiceTransportAction.java | 211 +++-------------- .../snapshots/RestoreService.java | 17 +- .../snapshots/SnapshotsService.java | 17 +- .../BaseTransportRequestHandler.java | 34 --- .../transport/RequestHandlerRegistry.java | 74 ++++++ .../transport/TransportRequestHandler.java | 9 - .../transport/TransportService.java | 60 +++-- .../transport/TransportServiceAdapter.java | 2 +- .../transport/local/LocalTransport.java | 16 +- .../netty/MessageChannelHandler.java | 26 +-- .../action/IndicesRequestTests.java | 19 +- .../ShardReplicationOperationTests.java | 21 +- .../BenchmarkNettyLargeMessages.java | 12 +- .../transport/TransportBenchmark.java | 12 +- .../test/transport/MockTransportService.java | 4 +- .../AbstractSimpleTransportTests.java | 218 ++---------------- .../transport/ActionNamesTests.java | 10 +- .../netty/NettyScheduledPingTests.java | 14 +- .../transport/netty/NettyTransportTests.java | 31 ++- 138 files changed, 518 insertions(+), 2334 deletions(-) delete mode 100644 src/main/java/org/elasticsearch/transport/BaseTransportRequestHandler.java create mode 100644 src/main/java/org/elasticsearch/transport/RequestHandlerRegistry.java diff --git a/src/main/java/org/elasticsearch/action/admin/cluster/health/TransportClusterHealthAction.java b/src/main/java/org/elasticsearch/action/admin/cluster/health/TransportClusterHealthAction.java index 04bb0afae06..9d5812a3810 100644 --- a/src/main/java/org/elasticsearch/action/admin/cluster/health/TransportClusterHealthAction.java +++ b/src/main/java/org/elasticsearch/action/admin/cluster/health/TransportClusterHealthAction.java @@ -45,7 +45,7 @@ public class TransportClusterHealthAction extends TransportMasterNodeReadOperati @Inject public TransportClusterHealthAction(Settings settings, TransportService transportService, ClusterService clusterService, ThreadPool threadPool, ClusterName clusterName, ActionFilters actionFilters) { - super(settings, ClusterHealthAction.NAME, transportService, clusterService, threadPool, actionFilters); + super(settings, ClusterHealthAction.NAME, transportService, clusterService, threadPool, actionFilters, ClusterHealthRequest.class); this.clusterName = clusterName; } @@ -60,11 +60,6 @@ public class TransportClusterHealthAction extends TransportMasterNodeReadOperati return null; // we want users to be able to call this even when there are global blocks, just to check the health (are there blocks?) } - @Override - protected ClusterHealthRequest newRequest() { - return new ClusterHealthRequest(); - } - @Override protected ClusterHealthResponse newResponse() { return new ClusterHealthResponse(); diff --git a/src/main/java/org/elasticsearch/action/admin/cluster/node/hotthreads/NodesHotThreadsRequest.java b/src/main/java/org/elasticsearch/action/admin/cluster/node/hotthreads/NodesHotThreadsRequest.java index 8db432b11e3..fe092d7dc81 100644 --- a/src/main/java/org/elasticsearch/action/admin/cluster/node/hotthreads/NodesHotThreadsRequest.java +++ b/src/main/java/org/elasticsearch/action/admin/cluster/node/hotthreads/NodesHotThreadsRequest.java @@ -38,6 +38,11 @@ public class NodesHotThreadsRequest extends NodesOperationRequest nodesInfos = new ArrayList<>(); @@ -70,16 +66,6 @@ public class TransportNodesInfoAction extends TransportNodesOperationAction { +public final class TransportLivenessAction implements TransportRequestHandler { private final ClusterService clusterService; private final ClusterName clusterName; @@ -37,21 +37,11 @@ public final class TransportLivenessAction extends BaseTransportRequestHandler { - - @Override - public NodeShutdownRequest newInstance() { - return new NodeShutdownRequest(); - } - - @Override - public String executor() { - return ThreadPool.Names.SAME; - } + private class NodeShutdownRequestHandler implements TransportRequestHandler { @Override public void messageReceived(final NodeShutdownRequest request, TransportChannel channel) throws Exception { diff --git a/src/main/java/org/elasticsearch/action/admin/cluster/node/stats/TransportNodesStatsAction.java b/src/main/java/org/elasticsearch/action/admin/cluster/node/stats/TransportNodesStatsAction.java index 339b8c4717d..ee9814eab6b 100644 --- a/src/main/java/org/elasticsearch/action/admin/cluster/node/stats/TransportNodesStatsAction.java +++ b/src/main/java/org/elasticsearch/action/admin/cluster/node/stats/TransportNodesStatsAction.java @@ -49,15 +49,11 @@ public class TransportNodesStatsAction extends TransportNodesOperationAction nodeStats = Lists.newArrayList(); @@ -70,16 +66,6 @@ public class TransportNodesStatsAction extends TransportNodesOperationAction { + ClusterStatsRequest() { + } + /** * Get stats from nodes based on the nodes ids specified. If none are passed, stats * based on all nodes will be returned. diff --git a/src/main/java/org/elasticsearch/action/admin/cluster/stats/TransportClusterStatsAction.java b/src/main/java/org/elasticsearch/action/admin/cluster/stats/TransportClusterStatsAction.java index a123bccf6b8..fd689945a58 100644 --- a/src/main/java/org/elasticsearch/action/admin/cluster/stats/TransportClusterStatsAction.java +++ b/src/main/java/org/elasticsearch/action/admin/cluster/stats/TransportClusterStatsAction.java @@ -67,16 +67,12 @@ public class TransportClusterStatsAction extends TransportNodesOperationAction nodeStats = new ArrayList<>(responses.length()); @@ -90,16 +86,6 @@ public class TransportClusterStatsAction extends TransportNodesOperationAction { private final IndicesService indicesService; - private final IndicesAnalysisService indicesAnalysisService; private static final Settings DEFAULT_SETTINGS = ImmutableSettings.builder().put(IndexMetaData.SETTING_VERSION_CREATED, Version.CURRENT).build(); @@ -68,20 +65,9 @@ public class TransportAnalyzeAction extends TransportSingleCustomOperationAction @Inject public TransportAnalyzeAction(Settings settings, ThreadPool threadPool, ClusterService clusterService, TransportService transportService, IndicesService indicesService, IndicesAnalysisService indicesAnalysisService, ActionFilters actionFilters) { - super(settings, AnalyzeAction.NAME, threadPool, clusterService, transportService, actionFilters); + super(settings, AnalyzeAction.NAME, threadPool, clusterService, transportService, actionFilters, AnalyzeRequest.class, ThreadPool.Names.INDEX); this.indicesService = indicesService; this.indicesAnalysisService = indicesAnalysisService; - transportService.registerHandler(AnalyzeAction.NAME, new TransportHandler()); - } - - @Override - protected String executor() { - return ThreadPool.Names.INDEX; - } - - @Override - protected AnalyzeRequest newRequest() { - return new AnalyzeRequest(); } @Override @@ -260,44 +246,4 @@ public class TransportAnalyzeAction extends TransportSingleCustomOperationAction return new AnalyzeResponse(tokens); } - - private class TransportHandler extends BaseTransportRequestHandler { - - @Override - public AnalyzeRequest newInstance() { - return newRequest(); - } - - @Override - public void messageReceived(AnalyzeRequest request, final TransportChannel channel) throws Exception { - // no need to have a threaded listener since we just send back a response - request.listenerThreaded(false); - // if we have a local operation, execute it on a thread since we don't spawn - request.operationThreaded(true); - execute(request, new ActionListener() { - @Override - public void onResponse(AnalyzeResponse result) { - try { - channel.sendResponse(result); - } catch (Throwable e) { - onFailure(e); - } - } - - @Override - public void onFailure(Throwable e) { - try { - channel.sendResponse(e); - } catch (Exception e1) { - logger.warn("Failed to send response for get", e1); - } - } - }); - } - - @Override - public String executor() { - return ThreadPool.Names.SAME; - } - } } diff --git a/src/main/java/org/elasticsearch/action/admin/indices/cache/clear/TransportClearIndicesCacheAction.java b/src/main/java/org/elasticsearch/action/admin/indices/cache/clear/TransportClearIndicesCacheAction.java index 2b79f98aca5..ef162e205ca 100644 --- a/src/main/java/org/elasticsearch/action/admin/indices/cache/clear/TransportClearIndicesCacheAction.java +++ b/src/main/java/org/elasticsearch/action/admin/indices/cache/clear/TransportClearIndicesCacheAction.java @@ -58,21 +58,12 @@ public class TransportClearIndicesCacheAction extends TransportBroadcastOperatio public TransportClearIndicesCacheAction(Settings settings, ThreadPool threadPool, ClusterService clusterService, TransportService transportService, IndicesService indicesService, IndicesQueryCache indicesQueryCache, ActionFilters actionFilters) { - super(settings, ClearIndicesCacheAction.NAME, threadPool, clusterService, transportService, actionFilters); + super(settings, ClearIndicesCacheAction.NAME, threadPool, clusterService, transportService, actionFilters, + ClearIndicesCacheRequest.class, ShardClearIndicesCacheRequest.class, ThreadPool.Names.MANAGEMENT); this.indicesService = indicesService; this.indicesQueryCache = indicesQueryCache; } - @Override - protected String executor() { - return ThreadPool.Names.MANAGEMENT; - } - - @Override - protected ClearIndicesCacheRequest newRequestInstance() { - return new ClearIndicesCacheRequest(); - } - @Override protected ClearIndicesCacheResponse newResponse(ClearIndicesCacheRequest request, AtomicReferenceArray shardsResponses, ClusterState clusterState) { int successfulShards = 0; @@ -95,11 +86,6 @@ public class TransportClearIndicesCacheAction extends TransportBroadcastOperatio return new ClearIndicesCacheResponse(shardsResponses.length(), successfulShards, failedShards, shardFailures); } - @Override - protected ShardClearIndicesCacheRequest newShardRequest() { - return new ShardClearIndicesCacheRequest(); - } - @Override protected ShardClearIndicesCacheRequest newShardRequest(int numShards, ShardRouting shard, ClearIndicesCacheRequest request) { return new ShardClearIndicesCacheRequest(shard.shardId(), request); diff --git a/src/main/java/org/elasticsearch/action/admin/indices/close/TransportCloseIndexAction.java b/src/main/java/org/elasticsearch/action/admin/indices/close/TransportCloseIndexAction.java index 4be9d842d26..c0afb720e89 100644 --- a/src/main/java/org/elasticsearch/action/admin/indices/close/TransportCloseIndexAction.java +++ b/src/main/java/org/elasticsearch/action/admin/indices/close/TransportCloseIndexAction.java @@ -47,7 +47,7 @@ public class TransportCloseIndexAction extends TransportMasterNodeOperationActio @Inject public TransportCloseIndexAction(Settings settings, TransportService transportService, ClusterService clusterService, ThreadPool threadPool, MetaDataIndexStateService indexStateService, NodeSettingsService nodeSettingsService, ActionFilters actionFilters) { - super(settings, CloseIndexAction.NAME, transportService, clusterService, threadPool, actionFilters); + super(settings, CloseIndexAction.NAME, transportService, clusterService, threadPool, actionFilters, CloseIndexRequest.class); this.indexStateService = indexStateService; this.destructiveOperations = new DestructiveOperations(logger, settings, nodeSettingsService); } @@ -58,11 +58,6 @@ public class TransportCloseIndexAction extends TransportMasterNodeOperationActio return ThreadPool.Names.SAME; } - @Override - protected CloseIndexRequest newRequest() { - return new CloseIndexRequest(); - } - @Override protected CloseIndexResponse newResponse() { return new CloseIndexResponse(); diff --git a/src/main/java/org/elasticsearch/action/admin/indices/create/TransportCreateIndexAction.java b/src/main/java/org/elasticsearch/action/admin/indices/create/TransportCreateIndexAction.java index 9edd9b74664..14e8e1c9a24 100644 --- a/src/main/java/org/elasticsearch/action/admin/indices/create/TransportCreateIndexAction.java +++ b/src/main/java/org/elasticsearch/action/admin/indices/create/TransportCreateIndexAction.java @@ -45,7 +45,7 @@ public class TransportCreateIndexAction extends TransportMasterNodeOperationActi @Inject public TransportCreateIndexAction(Settings settings, TransportService transportService, ClusterService clusterService, ThreadPool threadPool, MetaDataCreateIndexService createIndexService, ActionFilters actionFilters) { - super(settings, CreateIndexAction.NAME, transportService, clusterService, threadPool, actionFilters); + super(settings, CreateIndexAction.NAME, transportService, clusterService, threadPool, actionFilters, CreateIndexRequest.class); this.createIndexService = createIndexService; } @@ -55,11 +55,6 @@ public class TransportCreateIndexAction extends TransportMasterNodeOperationActi return ThreadPool.Names.SAME; } - @Override - protected CreateIndexRequest newRequest() { - return new CreateIndexRequest(); - } - @Override protected CreateIndexResponse newResponse() { return new CreateIndexResponse(); diff --git a/src/main/java/org/elasticsearch/action/admin/indices/delete/TransportDeleteIndexAction.java b/src/main/java/org/elasticsearch/action/admin/indices/delete/TransportDeleteIndexAction.java index 72d27374614..67ffc22c400 100644 --- a/src/main/java/org/elasticsearch/action/admin/indices/delete/TransportDeleteIndexAction.java +++ b/src/main/java/org/elasticsearch/action/admin/indices/delete/TransportDeleteIndexAction.java @@ -48,7 +48,7 @@ public class TransportDeleteIndexAction extends TransportMasterNodeOperationActi public TransportDeleteIndexAction(Settings settings, TransportService transportService, ClusterService clusterService, ThreadPool threadPool, MetaDataDeleteIndexService deleteIndexService, NodeSettingsService nodeSettingsService, ActionFilters actionFilters) { - super(settings, DeleteIndexAction.NAME, transportService, clusterService, threadPool, actionFilters); + super(settings, DeleteIndexAction.NAME, transportService, clusterService, threadPool, actionFilters, DeleteIndexRequest.class); this.deleteIndexService = deleteIndexService; this.destructiveOperations = new DestructiveOperations(logger, settings, nodeSettingsService); } @@ -58,11 +58,6 @@ public class TransportDeleteIndexAction extends TransportMasterNodeOperationActi return ThreadPool.Names.SAME; } - @Override - protected DeleteIndexRequest newRequest() { - return new DeleteIndexRequest(); - } - @Override protected DeleteIndexResponse newResponse() { return new DeleteIndexResponse(); diff --git a/src/main/java/org/elasticsearch/action/admin/indices/exists/indices/IndicesExistsRequest.java b/src/main/java/org/elasticsearch/action/admin/indices/exists/indices/IndicesExistsRequest.java index c5b533df1b7..e104090e962 100644 --- a/src/main/java/org/elasticsearch/action/admin/indices/exists/indices/IndicesExistsRequest.java +++ b/src/main/java/org/elasticsearch/action/admin/indices/exists/indices/IndicesExistsRequest.java @@ -37,6 +37,11 @@ public class IndicesExistsRequest extends MasterNodeReadOperationRequest { +public class TransportRecoveryAction extends TransportBroadcastOperationAction { private final IndicesService indicesService; @Inject public TransportRecoveryAction(Settings settings, ThreadPool threadPool, ClusterService clusterService, TransportService transportService, IndicesService indicesService, ActionFilters actionFilters) { - - super(settings, RecoveryAction.NAME, threadPool, clusterService, transportService, actionFilters); + super(settings, RecoveryAction.NAME, threadPool, clusterService, transportService, actionFilters, + RecoveryRequest.class, ShardRecoveryRequest.class, ThreadPool.Names.MANAGEMENT); this.indicesService = indicesService; } - @Override - protected String executor() { - return ThreadPool.Names.MANAGEMENT; - } - - @Override - protected RecoveryRequest newRequestInstance() { - return new RecoveryRequest(); - } - @Override protected RecoveryResponse newResponse(RecoveryRequest request, AtomicReferenceArray shardsResponses, ClusterState clusterState) { @@ -120,14 +109,8 @@ public class TransportRecoveryAction extends } } - RecoveryResponse response = new RecoveryResponse(shardsResponses.length(), successfulShards, + return new RecoveryResponse(shardsResponses.length(), successfulShards, failedShards, request.detailed(), shardResponses, shardFailures); - return response; - } - - @Override - protected ShardRecoveryRequest newShardRequest() { - return new ShardRecoveryRequest(); } @Override diff --git a/src/main/java/org/elasticsearch/action/admin/indices/refresh/TransportRefreshAction.java b/src/main/java/org/elasticsearch/action/admin/indices/refresh/TransportRefreshAction.java index 6e75bebefa4..73af682f4ff 100644 --- a/src/main/java/org/elasticsearch/action/admin/indices/refresh/TransportRefreshAction.java +++ b/src/main/java/org/elasticsearch/action/admin/indices/refresh/TransportRefreshAction.java @@ -53,20 +53,11 @@ public class TransportRefreshAction extends TransportBroadcastOperationAction { private final AutoCreateIndex autoCreateIndex; - private final boolean allowIdGeneration; - private final ClusterService clusterService; - private final TransportShardBulkAction shardBulkAction; - private final TransportCreateIndexAction createIndexAction; @Inject public TransportBulkAction(Settings settings, ThreadPool threadPool, TransportService transportService, ClusterService clusterService, TransportShardBulkAction shardBulkAction, TransportCreateIndexAction createIndexAction, ActionFilters actionFilters) { - super(settings, BulkAction.NAME, threadPool, transportService, actionFilters); + super(settings, BulkAction.NAME, threadPool, transportService, actionFilters, BulkRequest.class); this.clusterService = clusterService; this.shardBulkAction = shardBulkAction; this.createIndexAction = createIndexAction; @@ -88,11 +84,6 @@ public class TransportBulkAction extends HandledTransportAction listener) { final long startTime = System.currentTimeMillis(); diff --git a/src/main/java/org/elasticsearch/action/bulk/TransportShardBulkAction.java b/src/main/java/org/elasticsearch/action/bulk/TransportShardBulkAction.java index 4a29cfae58a..6fac03ac5c9 100644 --- a/src/main/java/org/elasticsearch/action/bulk/TransportShardBulkAction.java +++ b/src/main/java/org/elasticsearch/action/bulk/TransportShardBulkAction.java @@ -56,6 +56,7 @@ import org.elasticsearch.index.mapper.MapperService; import org.elasticsearch.index.mapper.Mapping; import org.elasticsearch.index.mapper.SourceToParse; import org.elasticsearch.index.shard.IndexShard; +import org.elasticsearch.index.shard.ShardId; import org.elasticsearch.indices.IndicesService; import org.elasticsearch.rest.RestStatus; import org.elasticsearch.river.RiverIndexName; @@ -83,17 +84,13 @@ public class TransportShardBulkAction extends TransportShardReplicationOperation public TransportShardBulkAction(Settings settings, TransportService transportService, ClusterService clusterService, IndicesService indicesService, ThreadPool threadPool, ShardStateAction shardStateAction, MappingUpdatedAction mappingUpdatedAction, UpdateHelper updateHelper, ActionFilters actionFilters) { - super(settings, ACTION_NAME, transportService, clusterService, indicesService, threadPool, shardStateAction, actionFilters); + super(settings, ACTION_NAME, transportService, clusterService, indicesService, threadPool, shardStateAction, actionFilters, + BulkShardRequest.class, BulkShardRequest.class, ThreadPool.Names.BULK); this.mappingUpdatedAction = mappingUpdatedAction; this.updateHelper = updateHelper; this.allowIdGeneration = settings.getAsBoolean("action.allow_id_generation", true); } - @Override - protected String executor() { - return ThreadPool.Names.BULK; - } - @Override protected boolean checkWriteConsistency() { return true; @@ -103,17 +100,6 @@ public class TransportShardBulkAction extends TransportShardReplicationOperation protected TransportRequestOptions transportOptions() { return BulkAction.INSTANCE.transportOptions(settings); } - - @Override - protected BulkShardRequest newRequestInstance() { - return new BulkShardRequest(); - } - - @Override - protected BulkShardRequest newReplicaRequestInstance() { - return newRequestInstance(); - } - @Override protected BulkShardResponse newResponseInstance() { return new BulkShardResponse(); @@ -546,10 +532,9 @@ public class TransportShardBulkAction extends TransportShardReplicationOperation @Override - protected void shardOperationOnReplica(ReplicaOperationRequest shardRequest) throws Exception { - IndexService indexService = indicesService.indexServiceSafe(shardRequest.shardId.getIndex()); - IndexShard indexShard = indexService.shardSafe(shardRequest.shardId.id()); - final BulkShardRequest request = shardRequest.request; + protected void shardOperationOnReplica(ShardId shardId, BulkShardRequest request) throws Exception { + IndexService indexService = indicesService.indexServiceSafe(shardId.getIndex()); + IndexShard indexShard = indexService.shardSafe(shardId.id()); for (int i = 0; i < request.items().length; i++) { BulkItemRequest item = request.items()[i]; if (item == null || item.isIgnoreOnReplica()) { diff --git a/src/main/java/org/elasticsearch/action/count/TransportCountAction.java b/src/main/java/org/elasticsearch/action/count/TransportCountAction.java index adc78226688..0c2496cda1a 100644 --- a/src/main/java/org/elasticsearch/action/count/TransportCountAction.java +++ b/src/main/java/org/elasticsearch/action/count/TransportCountAction.java @@ -65,18 +65,16 @@ import static org.elasticsearch.search.internal.SearchContext.DEFAULT_TERMINATE_ public class TransportCountAction extends TransportBroadcastOperationAction { private final IndicesService indicesService; - private final ScriptService scriptService; - private final PageCacheRecycler pageCacheRecycler; - private final BigArrays bigArrays; @Inject public TransportCountAction(Settings settings, ThreadPool threadPool, ClusterService clusterService, TransportService transportService, IndicesService indicesService, ScriptService scriptService, PageCacheRecycler pageCacheRecycler, BigArrays bigArrays, ActionFilters actionFilters) { - super(settings, CountAction.NAME, threadPool, clusterService, transportService, actionFilters); + super(settings, CountAction.NAME, threadPool, clusterService, transportService, actionFilters, + CountRequest.class, ShardCountRequest.class, ThreadPool.Names.SEARCH); this.indicesService = indicesService; this.scriptService = scriptService; this.pageCacheRecycler = pageCacheRecycler; @@ -89,21 +87,6 @@ public class TransportCountAction extends TransportBroadcastOperationAction { private final AutoCreateIndex autoCreateIndex; - private final TransportCreateIndexAction createIndexAction; @Inject public TransportDeleteAction(Settings settings, TransportService transportService, ClusterService clusterService, IndicesService indicesService, ThreadPool threadPool, ShardStateAction shardStateAction, TransportCreateIndexAction createIndexAction, ActionFilters actionFilters) { - super(settings, DeleteAction.NAME, transportService, clusterService, indicesService, threadPool, shardStateAction, actionFilters); + super(settings, DeleteAction.NAME, transportService, clusterService, indicesService, threadPool, shardStateAction, actionFilters, + DeleteRequest.class, DeleteRequest.class, ThreadPool.Names.INDEX); this.createIndexAction = createIndexAction; this.autoCreateIndex = new AutoCreateIndex(settings); } - @Override - protected String executor() { - return ThreadPool.Names.INDEX; - } - @Override protected void doExecute(final DeleteRequest request, final ActionListener listener) { if (autoCreateIndex.shouldAutoCreate(request.index(), clusterService.state())) { @@ -125,16 +121,6 @@ public class TransportDeleteAction extends TransportShardReplicationOperationAct return true; } - @Override - protected DeleteRequest newRequestInstance() { - return new DeleteRequest(); - } - - @Override - protected DeleteRequest newReplicaRequestInstance() { - return newRequestInstance(); - } - @Override protected DeleteResponse newResponseInstance() { return new DeleteResponse(); @@ -165,9 +151,8 @@ public class TransportDeleteAction extends TransportShardReplicationOperationAct } @Override - protected void shardOperationOnReplica(ReplicaOperationRequest shardRequest) { - DeleteRequest request = shardRequest.request; - IndexShard indexShard = indicesService.indexServiceSafe(shardRequest.shardId.getIndex()).shardSafe(shardRequest.shardId.id()); + protected void shardOperationOnReplica(ShardId shardId, DeleteRequest request) { + IndexShard indexShard = indicesService.indexServiceSafe(shardId.getIndex()).shardSafe(shardId.id()); Engine.Delete delete = indexShard.prepareDelete(request.type(), request.id(), request.version(), request.versionType(), Engine.Operation.Origin.REPLICA); indexShard.delete(delete); diff --git a/src/main/java/org/elasticsearch/action/deletebyquery/TransportDeleteByQueryAction.java b/src/main/java/org/elasticsearch/action/deletebyquery/TransportDeleteByQueryAction.java index 0800a639a81..8566e32ea26 100644 --- a/src/main/java/org/elasticsearch/action/deletebyquery/TransportDeleteByQueryAction.java +++ b/src/main/java/org/elasticsearch/action/deletebyquery/TransportDeleteByQueryAction.java @@ -48,7 +48,7 @@ public class TransportDeleteByQueryAction extends TransportIndicesReplicationOpe public TransportDeleteByQueryAction(Settings settings, ClusterService clusterService, TransportService transportService, ThreadPool threadPool, TransportIndexDeleteByQueryAction indexDeleteByQueryAction, NodeSettingsService nodeSettingsService, ActionFilters actionFilters) { - super(settings, DeleteByQueryAction.NAME, transportService, clusterService, threadPool, indexDeleteByQueryAction, actionFilters); + super(settings, DeleteByQueryAction.NAME, transportService, clusterService, threadPool, indexDeleteByQueryAction, actionFilters, DeleteByQueryRequest.class); this.destructiveOperations = new DestructiveOperations(logger, settings, nodeSettingsService); } @@ -63,11 +63,6 @@ public class TransportDeleteByQueryAction extends TransportIndicesReplicationOpe return clusterState.metaData().resolveSearchRouting(request.routing(), request.indices()); } - @Override - protected DeleteByQueryRequest newRequestInstance() { - return new DeleteByQueryRequest(); - } - @Override protected DeleteByQueryResponse newResponseInstance(DeleteByQueryRequest request, AtomicReferenceArray indexResponses) { DeleteByQueryResponse response = new DeleteByQueryResponse(); diff --git a/src/main/java/org/elasticsearch/action/deletebyquery/TransportShardDeleteByQueryAction.java b/src/main/java/org/elasticsearch/action/deletebyquery/TransportShardDeleteByQueryAction.java index 6e364302e83..99add9e6504 100644 --- a/src/main/java/org/elasticsearch/action/deletebyquery/TransportShardDeleteByQueryAction.java +++ b/src/main/java/org/elasticsearch/action/deletebyquery/TransportShardDeleteByQueryAction.java @@ -36,6 +36,7 @@ import org.elasticsearch.index.engine.Engine; import org.elasticsearch.index.query.ParsedQuery; import org.elasticsearch.index.IndexService; import org.elasticsearch.index.shard.IndexShard; +import org.elasticsearch.index.shard.ShardId; import org.elasticsearch.indices.IndicesService; import org.elasticsearch.script.ScriptService; import org.elasticsearch.search.internal.DefaultSearchContext; @@ -62,7 +63,8 @@ public class TransportShardDeleteByQueryAction extends TransportShardReplication ClusterService clusterService, IndicesService indicesService, ThreadPool threadPool, ShardStateAction shardStateAction, ScriptService scriptService, PageCacheRecycler pageCacheRecycler, BigArrays bigArrays, ActionFilters actionFilters) { - super(settings, ACTION_NAME, transportService, clusterService, indicesService, threadPool, shardStateAction, actionFilters); + super(settings, ACTION_NAME, transportService, clusterService, indicesService, threadPool, shardStateAction, actionFilters, + ShardDeleteByQueryRequest.class, ShardDeleteByQueryRequest.class, ThreadPool.Names.INDEX); this.scriptService = scriptService; this.pageCacheRecycler = pageCacheRecycler; this.bigArrays = bigArrays; @@ -73,21 +75,6 @@ public class TransportShardDeleteByQueryAction extends TransportShardReplication return true; } - @Override - protected String executor() { - return ThreadPool.Names.INDEX; - } - - @Override - protected ShardDeleteByQueryRequest newRequestInstance() { - return new ShardDeleteByQueryRequest(); - } - - @Override - protected ShardDeleteByQueryRequest newReplicaRequestInstance() { - return newRequestInstance(); - } - @Override protected ShardDeleteByQueryResponse newResponseInstance() { return new ShardDeleteByQueryResponse(); @@ -121,10 +108,9 @@ public class TransportShardDeleteByQueryAction extends TransportShardReplication @Override - protected void shardOperationOnReplica(ReplicaOperationRequest shardRequest) { - ShardDeleteByQueryRequest request = shardRequest.request; - IndexService indexService = indicesService.indexServiceSafe(shardRequest.shardId.getIndex()); - IndexShard indexShard = indexService.shardSafe(shardRequest.shardId.id()); + protected void shardOperationOnReplica(ShardId shardId, ShardDeleteByQueryRequest request) { + IndexService indexService = indicesService.indexServiceSafe(shardId.getIndex()); + IndexShard indexShard = indexService.shardSafe(shardId.id()); SearchContext.setCurrent(new DefaultSearchContext(0, new ShardSearchLocalRequest(request.types(), request.nowInMillis()), null, indexShard.acquireSearcher(DELETE_BY_QUERY_API, true), indexService, indexShard, scriptService, diff --git a/src/main/java/org/elasticsearch/action/exists/TransportExistsAction.java b/src/main/java/org/elasticsearch/action/exists/TransportExistsAction.java index 9c9dbdb8a8b..8d782012931 100644 --- a/src/main/java/org/elasticsearch/action/exists/TransportExistsAction.java +++ b/src/main/java/org/elasticsearch/action/exists/TransportExistsAction.java @@ -65,18 +65,16 @@ import static org.elasticsearch.action.exists.ExistsRequest.DEFAULT_MIN_SCORE; public class TransportExistsAction extends TransportBroadcastOperationAction { private final IndicesService indicesService; - private final ScriptService scriptService; - private final PageCacheRecycler pageCacheRecycler; - private final BigArrays bigArrays; @Inject public TransportExistsAction(Settings settings, ThreadPool threadPool, ClusterService clusterService, TransportService transportService, IndicesService indicesService, ScriptService scriptService, PageCacheRecycler pageCacheRecycler, BigArrays bigArrays, ActionFilters actionFilters) { - super(settings, ExistsAction.NAME, threadPool, clusterService, transportService, actionFilters); + super(settings, ExistsAction.NAME, threadPool, clusterService, transportService, actionFilters, + ExistsRequest.class, ShardExistsRequest.class, ThreadPool.Names.SEARCH); this.indicesService = indicesService; this.scriptService = scriptService; this.pageCacheRecycler = pageCacheRecycler; @@ -89,21 +87,6 @@ public class TransportExistsAction extends TransportBroadcastOperationAction listener) { ClusterState clusterState = clusterService.state(); diff --git a/src/main/java/org/elasticsearch/action/get/TransportShardMultiGetAction.java b/src/main/java/org/elasticsearch/action/get/TransportShardMultiGetAction.java index dc93cd935b1..246ba1f93d8 100644 --- a/src/main/java/org/elasticsearch/action/get/TransportShardMultiGetAction.java +++ b/src/main/java/org/elasticsearch/action/get/TransportShardMultiGetAction.java @@ -48,7 +48,8 @@ public class TransportShardMultiGetAction extends TransportShardSingleOperationA @Inject public TransportShardMultiGetAction(Settings settings, ClusterService clusterService, TransportService transportService, IndicesService indicesService, ThreadPool threadPool, ActionFilters actionFilters) { - super(settings, ACTION_NAME, threadPool, clusterService, transportService, actionFilters); + super(settings, ACTION_NAME, threadPool, clusterService, transportService, actionFilters, + MultiGetShardRequest.class, ThreadPool.Names.GET); this.indicesService = indicesService; this.realtime = settings.getAsBoolean("action.get.realtime", true); @@ -59,16 +60,6 @@ public class TransportShardMultiGetAction extends TransportShardSingleOperationA return true; } - @Override - protected String executor() { - return ThreadPool.Names.GET; - } - - @Override - protected MultiGetShardRequest newRequest() { - return new MultiGetShardRequest(); - } - @Override protected MultiGetShardResponse newResponse() { return new MultiGetShardResponse(); diff --git a/src/main/java/org/elasticsearch/action/index/TransportIndexAction.java b/src/main/java/org/elasticsearch/action/index/TransportIndexAction.java index 494f70708cb..5a8c96f352c 100644 --- a/src/main/java/org/elasticsearch/action/index/TransportIndexAction.java +++ b/src/main/java/org/elasticsearch/action/index/TransportIndexAction.java @@ -47,6 +47,7 @@ import org.elasticsearch.index.mapper.MapperService; import org.elasticsearch.index.mapper.Mapping; import org.elasticsearch.index.mapper.SourceToParse; import org.elasticsearch.index.shard.IndexShard; +import org.elasticsearch.index.shard.ShardId; import org.elasticsearch.indices.IndexAlreadyExistsException; import org.elasticsearch.indices.IndicesService; import org.elasticsearch.river.RiverIndexName; @@ -68,18 +69,16 @@ import java.io.IOException; public class TransportIndexAction extends TransportShardReplicationOperationAction { private final AutoCreateIndex autoCreateIndex; - private final boolean allowIdGeneration; - private final TransportCreateIndexAction createIndexAction; - private final MappingUpdatedAction mappingUpdatedAction; @Inject public TransportIndexAction(Settings settings, TransportService transportService, ClusterService clusterService, IndicesService indicesService, ThreadPool threadPool, ShardStateAction shardStateAction, TransportCreateIndexAction createIndexAction, MappingUpdatedAction mappingUpdatedAction, ActionFilters actionFilters) { - super(settings, IndexAction.NAME, transportService, clusterService, indicesService, threadPool, shardStateAction, actionFilters); + super(settings, IndexAction.NAME, transportService, clusterService, indicesService, threadPool, shardStateAction, actionFilters, + IndexRequest.class, IndexRequest.class, ThreadPool.Names.INDEX); this.createIndexAction = createIndexAction; this.mappingUpdatedAction = mappingUpdatedAction; this.autoCreateIndex = new AutoCreateIndex(settings); @@ -145,26 +144,11 @@ public class TransportIndexAction extends TransportShardReplicationOperationActi return true; } - @Override - protected IndexRequest newRequestInstance() { - return new IndexRequest(); - } - - @Override - protected IndexRequest newReplicaRequestInstance() { - return newRequestInstance(); - } - @Override protected IndexResponse newResponseInstance() { return new IndexResponse(); } - @Override - protected String executor() { - return ThreadPool.Names.INDEX; - } - @Override protected ShardIterator shards(ClusterState clusterState, InternalRequest request) { return clusterService.operationRouting() @@ -260,10 +244,9 @@ public class TransportIndexAction extends TransportShardReplicationOperationActi } @Override - protected void shardOperationOnReplica(ReplicaOperationRequest shardRequest) throws IOException { - IndexService indexService = indicesService.indexServiceSafe(shardRequest.shardId.getIndex()); - IndexShard indexShard = indexService.shardSafe(shardRequest.shardId.id()); - IndexRequest request = shardRequest.request; + protected void shardOperationOnReplica(ShardId shardId, IndexRequest request) throws IOException { + IndexService indexService = indicesService.indexServiceSafe(shardId.getIndex()); + IndexShard indexShard = indexService.shardSafe(shardId.id()); SourceToParse sourceToParse = SourceToParse.source(SourceToParse.Origin.REPLICA, request.source()).type(request.type()).id(request.id()) .routing(request.routing()).parent(request.parent()).timestamp(request.timestamp()).ttl(request.ttl()); if (request.opType() == IndexRequest.OpType.INDEX) { diff --git a/src/main/java/org/elasticsearch/action/indexedscripts/delete/TransportDeleteIndexedScriptAction.java b/src/main/java/org/elasticsearch/action/indexedscripts/delete/TransportDeleteIndexedScriptAction.java index f8c14d6d97a..fc205916e43 100644 --- a/src/main/java/org/elasticsearch/action/indexedscripts/delete/TransportDeleteIndexedScriptAction.java +++ b/src/main/java/org/elasticsearch/action/indexedscripts/delete/TransportDeleteIndexedScriptAction.java @@ -40,15 +40,10 @@ public class TransportDeleteIndexedScriptAction extends HandledTransportAction listener) { scriptService.deleteScriptFromIndex(request, new DelegatingActionListener(listener) { diff --git a/src/main/java/org/elasticsearch/action/indexedscripts/get/TransportGetIndexedScriptAction.java b/src/main/java/org/elasticsearch/action/indexedscripts/get/TransportGetIndexedScriptAction.java index 90a24968d94..1777258af59 100644 --- a/src/main/java/org/elasticsearch/action/indexedscripts/get/TransportGetIndexedScriptAction.java +++ b/src/main/java/org/elasticsearch/action/indexedscripts/get/TransportGetIndexedScriptAction.java @@ -39,15 +39,10 @@ public class TransportGetIndexedScriptAction extends HandledTransportAction listener){ // forward the handling to the script service we are running on a network thread here... diff --git a/src/main/java/org/elasticsearch/action/indexedscripts/put/TransportPutIndexedScriptAction.java b/src/main/java/org/elasticsearch/action/indexedscripts/put/TransportPutIndexedScriptAction.java index 3fcb60992f5..44c6e3679eb 100644 --- a/src/main/java/org/elasticsearch/action/indexedscripts/put/TransportPutIndexedScriptAction.java +++ b/src/main/java/org/elasticsearch/action/indexedscripts/put/TransportPutIndexedScriptAction.java @@ -40,15 +40,10 @@ public class TransportPutIndexedScriptAction extends HandledTransportAction listener) { scriptService.putScriptToIndex(request, new DelegatingActionListener(listener) { diff --git a/src/main/java/org/elasticsearch/action/mlt/TransportMoreLikeThisAction.java b/src/main/java/org/elasticsearch/action/mlt/TransportMoreLikeThisAction.java index eb656e96c1a..d78745e3667 100644 --- a/src/main/java/org/elasticsearch/action/mlt/TransportMoreLikeThisAction.java +++ b/src/main/java/org/elasticsearch/action/mlt/TransportMoreLikeThisAction.java @@ -69,19 +69,15 @@ import static org.elasticsearch.search.builder.SearchSourceBuilder.searchSource; public class TransportMoreLikeThisAction extends HandledTransportAction { private final TransportSearchAction searchAction; - private final TransportGetAction getAction; - private final IndicesService indicesService; - private final ClusterService clusterService; - private final TransportService transportService; @Inject public TransportMoreLikeThisAction(Settings settings, ThreadPool threadPool, TransportSearchAction searchAction, TransportGetAction getAction, ClusterService clusterService, IndicesService indicesService, TransportService transportService, ActionFilters actionFilters) { - super(settings, MoreLikeThisAction.NAME, threadPool, transportService, actionFilters); + super(settings, MoreLikeThisAction.NAME, threadPool, transportService, actionFilters, MoreLikeThisRequest.class); this.searchAction = searchAction; this.getAction = getAction; this.indicesService = indicesService; @@ -89,11 +85,6 @@ public class TransportMoreLikeThisAction extends HandledTransportAction listener) { // update to actual index name diff --git a/src/main/java/org/elasticsearch/action/percolate/TransportMultiPercolateAction.java b/src/main/java/org/elasticsearch/action/percolate/TransportMultiPercolateAction.java index 3992221b0f9..50476176c47 100644 --- a/src/main/java/org/elasticsearch/action/percolate/TransportMultiPercolateAction.java +++ b/src/main/java/org/elasticsearch/action/percolate/TransportMultiPercolateAction.java @@ -60,18 +60,13 @@ public class TransportMultiPercolateAction extends HandledTransportAction listener) { final ClusterState clusterState = clusterService.state(); diff --git a/src/main/java/org/elasticsearch/action/percolate/TransportPercolateAction.java b/src/main/java/org/elasticsearch/action/percolate/TransportPercolateAction.java index 7733ccf5069..46005f30dc8 100644 --- a/src/main/java/org/elasticsearch/action/percolate/TransportPercolateAction.java +++ b/src/main/java/org/elasticsearch/action/percolate/TransportPercolateAction.java @@ -62,7 +62,8 @@ public class TransportPercolateAction extends TransportBroadcastOperationAction< public TransportPercolateAction(Settings settings, ThreadPool threadPool, ClusterService clusterService, TransportService transportService, PercolatorService percolatorService, TransportGetAction getAction, ActionFilters actionFilters) { - super(settings, PercolateAction.NAME, threadPool, clusterService, transportService, actionFilters); + super(settings, PercolateAction.NAME, threadPool, clusterService, transportService, actionFilters, + PercolateRequest.class, PercolateShardRequest.class, ThreadPool.Names.PERCOLATE); this.percolatorService = percolatorService; this.getAction = getAction; } @@ -95,16 +96,6 @@ public class TransportPercolateAction extends TransportBroadcastOperationAction< } } - @Override - protected String executor() { - return ThreadPool.Names.PERCOLATE; - } - - @Override - protected PercolateRequest newRequestInstance() { - return new PercolateRequest(); - } - @Override protected ClusterBlockException checkGlobalBlock(ClusterState state, PercolateRequest request) { return state.blocks().globalBlockedException(ClusterBlockLevel.READ); @@ -165,11 +156,6 @@ public class TransportPercolateAction extends TransportBroadcastOperationAction< } } - @Override - protected PercolateShardRequest newShardRequest() { - return new PercolateShardRequest(); - } - @Override protected PercolateShardRequest newShardRequest(int numShards, ShardRouting shard, PercolateRequest request) { return new PercolateShardRequest(shard.shardId(), numShards, request); diff --git a/src/main/java/org/elasticsearch/action/percolate/TransportShardMultiPercolateAction.java b/src/main/java/org/elasticsearch/action/percolate/TransportShardMultiPercolateAction.java index 6795a4ed549..f221f758233 100644 --- a/src/main/java/org/elasticsearch/action/percolate/TransportShardMultiPercolateAction.java +++ b/src/main/java/org/elasticsearch/action/percolate/TransportShardMultiPercolateAction.java @@ -57,7 +57,8 @@ public class TransportShardMultiPercolateAction extends TransportShardSingleOper @Inject public TransportShardMultiPercolateAction(Settings settings, ThreadPool threadPool, ClusterService clusterService, TransportService transportService, PercolatorService percolatorService, ActionFilters actionFilters) { - super(settings, ACTION_NAME, threadPool, clusterService, transportService, actionFilters); + super(settings, ACTION_NAME, threadPool, clusterService, transportService, actionFilters, + Request.class, ThreadPool.Names.PERCOLATE); this.percolatorService = percolatorService; } @@ -66,16 +67,6 @@ public class TransportShardMultiPercolateAction extends TransportShardSingleOper return true; } - @Override - protected String executor() { - return ThreadPool.Names.PERCOLATE; - } - - @Override - protected Request newRequest() { - return new Request(); - } - @Override protected Response newResponse() { return new Response(); diff --git a/src/main/java/org/elasticsearch/action/search/TransportClearScrollAction.java b/src/main/java/org/elasticsearch/action/search/TransportClearScrollAction.java index f81b476a4b5..6312bc2bca2 100644 --- a/src/main/java/org/elasticsearch/action/search/TransportClearScrollAction.java +++ b/src/main/java/org/elasticsearch/action/search/TransportClearScrollAction.java @@ -22,7 +22,6 @@ 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.action.support.TransportAction; import org.elasticsearch.cluster.ClusterService; import org.elasticsearch.cluster.ClusterState; import org.elasticsearch.cluster.node.DiscoveryNode; @@ -33,8 +32,6 @@ import org.elasticsearch.common.settings.Settings; import org.elasticsearch.common.util.concurrent.CountDown; import org.elasticsearch.search.action.SearchServiceTransportAction; import org.elasticsearch.threadpool.ThreadPool; -import org.elasticsearch.transport.BaseTransportRequestHandler; -import org.elasticsearch.transport.TransportChannel; import org.elasticsearch.transport.TransportResponse; import org.elasticsearch.transport.TransportService; @@ -54,7 +51,7 @@ public class TransportClearScrollAction extends HandledTransportAction { private final ClusterService clusterService; - private final TransportSearchAction searchAction; @Inject public TransportMultiSearchAction(Settings settings, ThreadPool threadPool, TransportService transportService, ClusterService clusterService, TransportSearchAction searchAction, ActionFilters actionFilters) { - super(settings, MultiSearchAction.NAME, threadPool, transportService, actionFilters); + super(settings, MultiSearchAction.NAME, threadPool, transportService, actionFilters, MultiSearchRequest.class); this.clusterService = clusterService; this.searchAction = searchAction; } @@ -82,9 +81,4 @@ public class TransportMultiSearchAction extends HandledTransportAction { private final TransportSearchScrollQueryThenFetchAction queryThenFetchAction; - private final TransportSearchScrollQueryAndFetchAction queryAndFetchAction; - private final TransportSearchScrollScanAction scanAction; @Inject @@ -54,7 +49,7 @@ public class TransportSearchScrollAction extends HandledTransportAction { private final IndicesService indicesService; - private final SuggestPhase suggestPhase; @Inject public TransportSuggestAction(Settings settings, ThreadPool threadPool, ClusterService clusterService, TransportService transportService, IndicesService indicesService, SuggestPhase suggestPhase, ActionFilters actionFilters) { - super(settings, SuggestAction.NAME, threadPool, clusterService, transportService, actionFilters); + super(settings, SuggestAction.NAME, threadPool, clusterService, transportService, actionFilters, + SuggestRequest.class, ShardSuggestRequest.class, ThreadPool.Names.SUGGEST); this.indicesService = indicesService; this.suggestPhase = suggestPhase; } - @Override - protected String executor() { - return ThreadPool.Names.SUGGEST; - } - - @Override - protected SuggestRequest newRequestInstance() { - return new SuggestRequest(); - } - - @Override - protected ShardSuggestRequest newShardRequest() { - return new ShardSuggestRequest(); - } - @Override protected ShardSuggestRequest newShardRequest(int numShards, ShardRouting shard, SuggestRequest request) { return new ShardSuggestRequest(shard.shardId(), request); diff --git a/src/main/java/org/elasticsearch/action/support/HandledTransportAction.java b/src/main/java/org/elasticsearch/action/support/HandledTransportAction.java index b69032f3cdf..f939893a98e 100644 --- a/src/main/java/org/elasticsearch/action/support/HandledTransportAction.java +++ b/src/main/java/org/elasticsearch/action/support/HandledTransportAction.java @@ -23,8 +23,8 @@ import org.elasticsearch.action.ActionRequest; import org.elasticsearch.action.ActionResponse; import org.elasticsearch.common.settings.Settings; import org.elasticsearch.threadpool.ThreadPool; -import org.elasticsearch.transport.BaseTransportRequestHandler; import org.elasticsearch.transport.TransportChannel; +import org.elasticsearch.transport.TransportRequestHandler; import org.elasticsearch.transport.TransportService; /** @@ -32,30 +32,12 @@ import org.elasticsearch.transport.TransportService; */ public abstract class HandledTransportAction extends TransportAction{ - /** - * Sub classes implement this call to get new instance of a Request object - * @return Request - */ - protected abstract Request newRequestInstance(); - - protected HandledTransportAction(Settings settings, String actionName, ThreadPool threadPool, TransportService transportService, ActionFilters actionFilters){ + protected HandledTransportAction(Settings settings, String actionName, ThreadPool threadPool, TransportService transportService, ActionFilters actionFilters, Class request) { super(settings, actionName, threadPool, actionFilters); - transportService.registerHandler(actionName, new TransportHandler() { - @Override - public Request newInstance(){ - return newRequestInstance(); - } - }); + transportService.registerRequestHandler(actionName, request, ThreadPool.Names.SAME, new TransportHandler()); } - abstract class TransportHandler extends BaseTransportRequestHandler{ - - /** - * Call to get an instance of type Request - * @return Request - */ - @Override - public abstract Request newInstance(); + class TransportHandler implements TransportRequestHandler { @Override public final void messageReceived(final Request request, final TransportChannel channel) throws Exception { @@ -82,12 +64,6 @@ public abstract class HandledTransportAction request, Class shardRequest, String shardExecutor) { + super(settings, actionName, threadPool, transportService, actionFilters, request); this.clusterService = clusterService; this.transportService = transportService; this.threadPool = threadPool; this.transportShardAction = actionName + "[s]"; - this.executor = executor(); - transportService.registerHandler(transportShardAction, new ShardTransportHandler()); + transportService.registerRequestHandler(transportShardAction, shardRequest, shardExecutor, new ShardTransportHandler()); } @Override @@ -71,12 +69,8 @@ public abstract class TransportBroadcastOperationAction { - - @Override - public ShardRequest newInstance() { - return newShardRequest(); - } - - @Override - public String executor() { - return executor; - } + class ShardTransportHandler implements TransportRequestHandler { @Override public void messageReceived(final ShardRequest request, final TransportChannel channel) throws Exception { diff --git a/src/main/java/org/elasticsearch/action/support/master/TransportMasterNodeOperationAction.java b/src/main/java/org/elasticsearch/action/support/master/TransportMasterNodeOperationAction.java index 6a459e50d49..15e90c0784d 100644 --- a/src/main/java/org/elasticsearch/action/support/master/TransportMasterNodeOperationAction.java +++ b/src/main/java/org/elasticsearch/action/support/master/TransportMasterNodeOperationAction.java @@ -24,6 +24,7 @@ import org.elasticsearch.action.ActionListener; import org.elasticsearch.action.ActionResponse; import org.elasticsearch.action.ActionRunnable; import org.elasticsearch.action.support.ActionFilters; +import org.elasticsearch.action.support.HandledTransportAction; import org.elasticsearch.action.support.TransportAction; import org.elasticsearch.cluster.ClusterChangedEvent; import org.elasticsearch.cluster.ClusterService; @@ -42,28 +43,23 @@ import org.elasticsearch.transport.*; /** * A base class for operations that needs to be performed on the master node. */ -public abstract class TransportMasterNodeOperationAction extends TransportAction { +public abstract class TransportMasterNodeOperationAction extends HandledTransportAction { protected final TransportService transportService; - protected final ClusterService clusterService; final String executor; - protected TransportMasterNodeOperationAction(Settings settings, String actionName, TransportService transportService, ClusterService clusterService, ThreadPool threadPool, ActionFilters actionFilters) { - super(settings, actionName, threadPool, actionFilters); + protected TransportMasterNodeOperationAction(Settings settings, String actionName, TransportService transportService, ClusterService clusterService, ThreadPool threadPool, ActionFilters actionFilters, + Class request) { + super(settings, actionName, threadPool, transportService, actionFilters, request); this.transportService = transportService; this.clusterService = clusterService; - this.executor = executor(); - - transportService.registerHandler(actionName, new TransportHandler()); } protected abstract String executor(); - protected abstract Request newRequest(); - protected abstract Response newResponse(); protected abstract void masterOperation(Request request, ClusterState state, ActionListener listener) throws Exception; @@ -225,42 +221,4 @@ public abstract class TransportMasterNodeOperationAction { - - @Override - public Request newInstance() { - return newRequest(); - } - - @Override - public String executor() { - return ThreadPool.Names.SAME; - } - - @Override - public void messageReceived(final Request request, final TransportChannel channel) throws Exception { - // we just send back a response, no need to fork a listener - request.listenerThreaded(false); - execute(request, new ActionListener() { - @Override - public void onResponse(Response response) { - try { - channel.sendResponse(response); - } catch (Throwable e) { - onFailure(e); - } - } - - @Override - public void onFailure(Throwable e) { - try { - channel.sendResponse(e); - } catch (Exception e1) { - logger.warn("Failed to send response", e1); - } - } - }); - } - } } diff --git a/src/main/java/org/elasticsearch/action/support/master/TransportMasterNodeReadOperationAction.java b/src/main/java/org/elasticsearch/action/support/master/TransportMasterNodeReadOperationAction.java index 7d7453f581d..383de7ceb53 100644 --- a/src/main/java/org/elasticsearch/action/support/master/TransportMasterNodeReadOperationAction.java +++ b/src/main/java/org/elasticsearch/action/support/master/TransportMasterNodeReadOperationAction.java @@ -36,8 +36,8 @@ public abstract class TransportMasterNodeReadOperationAction request) { + super(settings, actionName, transportService, clusterService, threadPool, actionFilters,request); this.forceLocal = settings.getAsBoolean(FORCE_LOCAL_SETTING, null); } diff --git a/src/main/java/org/elasticsearch/action/support/master/info/TransportClusterInfoAction.java b/src/main/java/org/elasticsearch/action/support/master/info/TransportClusterInfoAction.java index 00d3e566bc6..45a21a60ea3 100644 --- a/src/main/java/org/elasticsearch/action/support/master/info/TransportClusterInfoAction.java +++ b/src/main/java/org/elasticsearch/action/support/master/info/TransportClusterInfoAction.java @@ -33,8 +33,8 @@ import org.elasticsearch.transport.TransportService; */ public abstract class TransportClusterInfoAction extends TransportMasterNodeReadOperationAction { - public TransportClusterInfoAction(Settings settings, String actionName, TransportService transportService, ClusterService clusterService, ThreadPool threadPool, ActionFilters actionFilters) { - super(settings, actionName, transportService, clusterService, threadPool, actionFilters); + public TransportClusterInfoAction(Settings settings, String actionName, TransportService transportService, ClusterService clusterService, ThreadPool threadPool, ActionFilters actionFilters, Class request) { + super(settings, actionName, transportService, clusterService, threadPool, actionFilters, request); } @Override diff --git a/src/main/java/org/elasticsearch/action/support/nodes/TransportNodesOperationAction.java b/src/main/java/org/elasticsearch/action/support/nodes/TransportNodesOperationAction.java index 358f7d0860f..65bdaeb7c26 100644 --- a/src/main/java/org/elasticsearch/action/support/nodes/TransportNodesOperationAction.java +++ b/src/main/java/org/elasticsearch/action/support/nodes/TransportNodesOperationAction.java @@ -25,7 +25,6 @@ import org.elasticsearch.action.FailedNodeException; import org.elasticsearch.action.NoSuchNodeException; import org.elasticsearch.action.support.ActionFilters; import org.elasticsearch.action.support.HandledTransportAction; -import org.elasticsearch.action.support.TransportAction; import org.elasticsearch.cluster.ClusterName; import org.elasticsearch.cluster.ClusterService; import org.elasticsearch.cluster.ClusterState; @@ -48,19 +47,18 @@ public abstract class TransportNodesOperationAction request, Class nodeRequest, String nodeExecutor) { + super(settings, actionName, threadPool, transportService, actionFilters, request); this.clusterName = clusterName; this.clusterService = clusterService; this.transportService = transportService; this.transportNodeAction = actionName + "[n]"; - this.executor = executor(); - transportService.registerHandler(transportNodeAction, new NodeTransportHandler()); + transportService.registerRequestHandler(transportNodeAction, nodeRequest, nodeExecutor, new NodeTransportHandler()); } @Override @@ -72,12 +70,8 @@ public abstract class TransportNodesOperationAction { - - @Override - public NodeRequest newInstance() { - return newNodeRequest(); - } + class NodeTransportHandler implements TransportRequestHandler { @Override public void messageReceived(final NodeRequest request, final TransportChannel channel) throws Exception { channel.sendResponse(nodeOperation(request)); } - - @Override - public String toString() { - return transportNodeAction; - } - - @Override - public String executor() { - return executor; - } } } diff --git a/src/main/java/org/elasticsearch/action/support/replication/ShardReplicationOperationRequest.java b/src/main/java/org/elasticsearch/action/support/replication/ShardReplicationOperationRequest.java index dc7461020be..0d9730c246a 100644 --- a/src/main/java/org/elasticsearch/action/support/replication/ShardReplicationOperationRequest.java +++ b/src/main/java/org/elasticsearch/action/support/replication/ShardReplicationOperationRequest.java @@ -27,6 +27,7 @@ import org.elasticsearch.action.support.IndicesOptions; import org.elasticsearch.common.io.stream.StreamInput; import org.elasticsearch.common.io.stream.StreamOutput; import org.elasticsearch.common.unit.TimeValue; +import org.elasticsearch.index.shard.ShardId; import java.io.IOException; import java.util.concurrent.TimeUnit; @@ -40,8 +41,9 @@ public abstract class ShardReplicationOperationRequest - extends TransportAction { + extends HandledTransportAction { protected final ClusterService clusterService; protected final TransportIndexReplicationOperationAction indexAction; protected TransportIndicesReplicationOperationAction(Settings settings, String actionName, TransportService transportService, ClusterService clusterService, ThreadPool threadPool, - TransportIndexReplicationOperationAction indexAction, ActionFilters actionFilters) { - super(settings, actionName, threadPool, actionFilters); + TransportIndexReplicationOperationAction indexAction, ActionFilters actionFilters, + Class request) { + super(settings, actionName, threadPool, transportService, actionFilters, request); this.clusterService = clusterService; this.indexAction = indexAction; - - transportService.registerHandler(actionName, new TransportHandler()); } @@ -116,8 +114,6 @@ public abstract class TransportIndicesReplicationOperationAction routing, long startTimeInMillis); @@ -127,42 +123,4 @@ public abstract class TransportIndicesReplicationOperationAction { - - @Override - public Request newInstance() { - return newRequestInstance(); - } - - @Override - public String executor() { - return ThreadPool.Names.SAME; - } - - @Override - public void messageReceived(final Request request, final TransportChannel channel) throws Exception { - // no need for a threaded listener, since we just send a response - request.listenerThreaded(false); - execute(request, new ActionListener() { - @Override - public void onResponse(Response result) { - try { - channel.sendResponse(result); - } catch (Throwable e) { - onFailure(e); - } - } - - @Override - public void onFailure(Throwable e) { - try { - channel.sendResponse(e); - } catch (Exception e1) { - logger.warn("Failed to send error response for action [" + actionName + "] and request [" + request + "]", e1); - } - } - }); - } - } } diff --git a/src/main/java/org/elasticsearch/action/support/replication/TransportShardReplicationOperationAction.java b/src/main/java/org/elasticsearch/action/support/replication/TransportShardReplicationOperationAction.java index 529586927fd..bde8a67b098 100644 --- a/src/main/java/org/elasticsearch/action/support/replication/TransportShardReplicationOperationAction.java +++ b/src/main/java/org/elasticsearch/action/support/replication/TransportShardReplicationOperationAction.java @@ -78,7 +78,8 @@ public abstract class TransportShardReplicationOperationAction request, Class replicaRequest, String executor) { super(settings, actionName, threadPool, actionFilters); this.transportService = transportService; this.clusterService = clusterService; @@ -86,11 +87,12 @@ public abstract class TransportShardReplicationOperationAction shardOperationOnPrimary(ClusterState clusterState, PrimaryOperationRequest shardRequest) throws Throwable; - protected abstract void shardOperationOnReplica(ReplicaOperationRequest shardRequest) throws Exception; + protected abstract void shardOperationOnReplica(ShardId shardId, ReplicaRequest shardRequest) throws Exception; protected abstract ShardIterator shards(ClusterState clusterState, InternalRequest request) throws ElasticsearchException; @@ -175,18 +171,7 @@ public abstract class TransportShardReplicationOperationAction { - - @Override - public Request newInstance() { - return newRequestInstance(); - } - - @Override - public String executor() { - return ThreadPool.Names.SAME; - } - + class OperationTransportHandler implements TransportRequestHandler { @Override public void messageReceived(final Request request, final TransportChannel channel) throws Exception { // no need to have a threaded listener since we just send back a response @@ -215,30 +200,13 @@ public abstract class TransportShardReplicationOperationAction { - + class ReplicaOperationTransportHandler implements TransportRequestHandler { @Override - public ReplicaOperationRequest newInstance() { - return new ReplicaOperationRequest(); - } - - @Override - public String executor() { - return executor; - } - - // we must never reject on because of thread pool capacity on replicas - @Override - public boolean isForceExecution() { - return true; - } - - @Override - public void messageReceived(final ReplicaOperationRequest request, final TransportChannel channel) throws Exception { + public void messageReceived(final ReplicaRequest request, final TransportChannel channel) throws Exception { try { - shardOperationOnReplica(request); + shardOperationOnReplica(request.internalShardId, request); } catch (Throwable t) { - failReplicaIfNeeded(request.shardId.getIndex(), request.shardId.id(), t); + failReplicaIfNeeded(request.internalShardId.getIndex(), request.internalShardId.id(), t); throw t; } channel.sendResponse(TransportResponse.Empty.INSTANCE); @@ -255,46 +223,6 @@ public abstract class TransportShardReplicationOperationAction extends ActionRequest implements IndicesRequest { + ShardId internalShardId; + private boolean threadedOperation = true; private boolean preferLocal = true; private String index; @@ -113,6 +116,9 @@ public abstract class SingleCustomOperationRequest extends TransportAction { +public abstract class TransportSingleCustomOperationAction extends HandledTransportAction { protected final ClusterService clusterService; - protected final TransportService transportService; final String transportShardAction; final String executor; - protected TransportSingleCustomOperationAction(Settings settings, String actionName, ThreadPool threadPool, ClusterService clusterService, TransportService transportService, ActionFilters actionFilters) { - super(settings, actionName, threadPool, actionFilters); + protected TransportSingleCustomOperationAction(Settings settings, String actionName, ThreadPool threadPool, ClusterService clusterService, TransportService transportService, ActionFilters actionFilters, + Class request, String executor) { + super(settings, actionName, threadPool, transportService, actionFilters, request); this.clusterService = clusterService; this.transportService = transportService; this.transportShardAction = actionName + "[s]"; - this.executor = executor(); + this.executor = executor; - transportService.registerHandler(transportShardAction, new ShardTransportHandler()); + transportService.registerRequestHandler(transportShardAction, request, executor, new ShardTransportHandler()); } @Override @@ -73,8 +66,6 @@ public abstract class TransportSingleCustomOperationAction() { + internalRequest.request().internalShardId = shard.shardId(); + transportService.sendRequest(node, transportShardAction, internalRequest.request(), new BaseTransportResponseHandler() { @Override public Response newInstance() { return newResponse(); @@ -290,73 +280,15 @@ public abstract class TransportSingleCustomOperationAction { + private class ShardTransportHandler implements TransportRequestHandler { @Override - public ShardSingleOperationRequest newInstance() { - return new ShardSingleOperationRequest(); - } - - @Override - public String executor() { - return executor; - } - - @Override - public void messageReceived(final ShardSingleOperationRequest request, final TransportChannel channel) throws Exception { - Response response = shardOperation(request.request(), request.shardId()); + public void messageReceived(final Request request, final TransportChannel channel) throws Exception { + Response response = shardOperation(request, request.internalShardId); channel.sendResponse(response); } } - protected class ShardSingleOperationRequest extends TransportRequest implements IndicesRequest { - - private Request request; - private ShardId shardId; - - ShardSingleOperationRequest() { - } - - public ShardSingleOperationRequest(Request request, ShardId shardId) { - super(request); - this.request = request; - this.shardId = shardId; - } - - public Request request() { - return request; - } - - @Override - public String[] indices() { - return request.indices(); - } - - @Override - public IndicesOptions indicesOptions() { - return request.indicesOptions(); - } - - public ShardId shardId() { - return shardId; - } - - @Override - public void readFrom(StreamInput in) throws IOException { - super.readFrom(in); - request = newRequest(); - request.readFrom(in); - shardId = ShardId.readShardId(in); - } - - @Override - public void writeTo(StreamOutput out) throws IOException { - super.writeTo(out); - request.writeTo(out); - shardId.writeTo(out); - } - } - /** * Internal request class that gets built on each node. Holds the original request plus additional info. */ diff --git a/src/main/java/org/elasticsearch/action/support/single/instance/TransportInstanceSingleOperationAction.java b/src/main/java/org/elasticsearch/action/support/single/instance/TransportInstanceSingleOperationAction.java index 3e2ec365c37..2c54b3ef8e8 100644 --- a/src/main/java/org/elasticsearch/action/support/single/instance/TransportInstanceSingleOperationAction.java +++ b/src/main/java/org/elasticsearch/action/support/single/instance/TransportInstanceSingleOperationAction.java @@ -24,6 +24,7 @@ import org.elasticsearch.action.ActionListener; 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.action.support.TransportAction; import org.elasticsearch.cluster.ClusterService; import org.elasticsearch.cluster.ClusterState; @@ -47,22 +48,18 @@ import java.util.concurrent.atomic.AtomicBoolean; /** * */ -public abstract class TransportInstanceSingleOperationAction extends TransportAction { +public abstract class TransportInstanceSingleOperationAction extends HandledTransportAction { protected final ClusterService clusterService; - protected final TransportService transportService; final String executor; - protected TransportInstanceSingleOperationAction(Settings settings, String actionName, ThreadPool threadPool, ClusterService clusterService, TransportService transportService, ActionFilters actionFilters) { - super(settings, actionName, threadPool, actionFilters); + protected TransportInstanceSingleOperationAction(Settings settings, String actionName, ThreadPool threadPool, ClusterService clusterService, TransportService transportService, ActionFilters actionFilters, Class request) { + super(settings, actionName, threadPool, transportService, actionFilters, request); this.clusterService = clusterService; this.transportService = transportService; - this.executor = executor(); - - transportService.registerHandler(actionName, new TransportHandler()); } @Override @@ -74,8 +71,6 @@ public abstract class TransportInstanceSingleOperationAction listener) throws ElasticsearchException; - protected abstract Request newRequest(); - protected abstract Response newResponse(); protected ClusterBlockException checkGlobalBlock(ClusterState state) { @@ -279,44 +274,6 @@ public abstract class TransportInstanceSingleOperationAction { - - @Override - public Request newInstance() { - return newRequest(); - } - - @Override - public String executor() { - return ThreadPool.Names.SAME; - } - - @Override - public void messageReceived(Request request, final TransportChannel channel) throws Exception { - // no need to have a threaded listener since we just send back a response - request.listenerThreaded(false); - execute(request, new ActionListener() { - @Override - public void onResponse(Response result) { - try { - channel.sendResponse(result); - } catch (Throwable e) { - onFailure(e); - } - } - - @Override - public void onFailure(Throwable e) { - try { - channel.sendResponse(e); - } catch (Exception e1) { - logger.warn("Failed to send response for get", e1); - } - } - }); - } - } - /** * Internal request class that gets built on each node. Holds the original request plus additional info. */ diff --git a/src/main/java/org/elasticsearch/action/support/single/shard/SingleShardOperationRequest.java b/src/main/java/org/elasticsearch/action/support/single/shard/SingleShardOperationRequest.java index 8a0263fd0d5..74db0435709 100644 --- a/src/main/java/org/elasticsearch/action/support/single/shard/SingleShardOperationRequest.java +++ b/src/main/java/org/elasticsearch/action/support/single/shard/SingleShardOperationRequest.java @@ -26,6 +26,7 @@ import org.elasticsearch.action.ValidateActions; import org.elasticsearch.action.support.IndicesOptions; import org.elasticsearch.common.io.stream.StreamInput; import org.elasticsearch.common.io.stream.StreamOutput; +import org.elasticsearch.index.shard.ShardId; import java.io.IOException; @@ -34,10 +35,10 @@ import java.io.IOException; */ public abstract class SingleShardOperationRequest extends ActionRequest implements IndicesRequest { + ShardId internalShardId; + protected String index; - public static final IndicesOptions INDICES_OPTIONS = IndicesOptions.strictSingleIndexNoExpandForbidClosed(); - private boolean threadedOperation = true; protected SingleShardOperationRequest() { @@ -107,6 +108,9 @@ public abstract class SingleShardOperationRequest request, String executor) { super(settings, actionName, threadPool, actionFilters); this.clusterService = clusterService; this.transportService = transportService; this.transportShardAction = actionName + "[s]"; - this.executor = executor(); + this.executor = executor; if (!isSubAction()) { - transportService.registerHandler(actionName, new TransportHandler()); + transportService.registerRequestHandler(actionName, request, ThreadPool.Names.SAME, new TransportHandler()); } - transportService.registerHandler(transportShardAction, new ShardTransportHandler()); + transportService.registerRequestHandler(transportShardAction, request, executor, new ShardTransportHandler()); } /** @@ -89,12 +83,8 @@ public abstract class TransportShardSingleOperationAction() { + internalRequest.request().internalShardId = shardRouting.shardId(); + transportService.sendRequest(node, transportShardAction, internalRequest.request(), new BaseTransportResponseHandler() { @Override public Response newInstance() { @@ -237,17 +228,7 @@ public abstract class TransportShardSingleOperationAction { - - @Override - public Request newInstance() { - return newRequest(); - } - - @Override - public String executor() { - return ThreadPool.Names.SAME; - } + private class TransportHandler implements TransportRequestHandler { @Override public void messageReceived(Request request, final TransportChannel channel) throws Exception { @@ -277,77 +258,18 @@ public abstract class TransportShardSingleOperationAction { + private class ShardTransportHandler implements TransportRequestHandler { @Override - public ShardSingleOperationRequest newInstance() { - return new ShardSingleOperationRequest(); - } - - @Override - public String executor() { - return executor; - } - - @Override - public void messageReceived(final ShardSingleOperationRequest request, final TransportChannel channel) throws Exception { + public void messageReceived(final Request request, final TransportChannel channel) throws Exception { if (logger.isTraceEnabled()) { - logger.trace("executing [{}] on shard [{}]", request.request(), request.shardId()); + logger.trace("executing [{}] on shard [{}]", request, request.internalShardId); } - Response response = shardOperation(request.request(), request.shardId()); + Response response = shardOperation(request, request.internalShardId); channel.sendResponse(response); } } - class ShardSingleOperationRequest extends TransportRequest implements IndicesRequest { - - private Request request; - - private ShardId shardId; - - ShardSingleOperationRequest() { - } - - ShardSingleOperationRequest(Request request, ShardId shardId) { - super(request); - this.request = request; - this.shardId = shardId; - } - - public Request request() { - return request; - } - - public ShardId shardId() { - return shardId; - } - - @Override - public String[] indices() { - return request.indices(); - } - - @Override - public IndicesOptions indicesOptions() { - return request.indicesOptions(); - } - - @Override - public void readFrom(StreamInput in) throws IOException { - super.readFrom(in); - request = newRequest(); - request.readFrom(in); - shardId = ShardId.readShardId(in); - } - - @Override - public void writeTo(StreamOutput out) throws IOException { - super.writeTo(out); - request.writeTo(out); - shardId.writeTo(out); - } - } - /** * Internal request class that gets built on each node. Holds the original request plus additional info. */ diff --git a/src/main/java/org/elasticsearch/action/termvectors/TransportMultiTermVectorsAction.java b/src/main/java/org/elasticsearch/action/termvectors/TransportMultiTermVectorsAction.java index 96b3d8d04ed..91c924e6027 100644 --- a/src/main/java/org/elasticsearch/action/termvectors/TransportMultiTermVectorsAction.java +++ b/src/main/java/org/elasticsearch/action/termvectors/TransportMultiTermVectorsAction.java @@ -46,7 +46,7 @@ public class TransportMultiTermVectorsAction extends HandledTransportAction { - - @Override - public NodeIndexDeletedMessage newInstance() { - return new NodeIndexDeletedMessage(); - } + private class NodeIndexDeletedTransportHandler implements TransportRequestHandler { @Override public void messageReceived(NodeIndexDeletedMessage message, TransportChannel channel) throws Exception { @@ -127,19 +122,9 @@ public class NodeIndexDeletedAction extends AbstractComponent { } channel.sendResponse(TransportResponse.Empty.INSTANCE); } - - @Override - public String executor() { - return ThreadPool.Names.SAME; - } } - private class NodeIndexStoreDeletedTransportHandler extends BaseTransportRequestHandler { - - @Override - public NodeIndexStoreDeletedMessage newInstance() { - return new NodeIndexStoreDeletedMessage(); - } + private class NodeIndexStoreDeletedTransportHandler implements TransportRequestHandler { @Override public void messageReceived(NodeIndexStoreDeletedMessage message, TransportChannel channel) throws Exception { @@ -148,11 +133,6 @@ public class NodeIndexDeletedAction extends AbstractComponent { } channel.sendResponse(TransportResponse.Empty.INSTANCE); } - - @Override - public String executor() { - return ThreadPool.Names.SAME; - } } static class NodeIndexDeletedMessage extends TransportRequest { diff --git a/src/main/java/org/elasticsearch/cluster/action/index/NodeMappingRefreshAction.java b/src/main/java/org/elasticsearch/cluster/action/index/NodeMappingRefreshAction.java index c14452a0fef..794e5775852 100644 --- a/src/main/java/org/elasticsearch/cluster/action/index/NodeMappingRefreshAction.java +++ b/src/main/java/org/elasticsearch/cluster/action/index/NodeMappingRefreshAction.java @@ -52,7 +52,7 @@ public class NodeMappingRefreshAction extends AbstractComponent { super(settings); this.transportService = transportService; this.metaDataMappingService = metaDataMappingService; - transportService.registerHandler(ACTION_NAME, new NodeMappingRefreshTransportHandler()); + transportService.registerRequestHandler(ACTION_NAME, NodeMappingRefreshRequest.class, ThreadPool.Names.SAME, new NodeMappingRefreshTransportHandler()); } public void nodeMappingRefresh(final ClusterState state, final NodeMappingRefreshRequest request) throws ElasticsearchException { @@ -64,23 +64,13 @@ public class NodeMappingRefreshAction extends AbstractComponent { transportService.sendRequest(nodes.masterNode(), ACTION_NAME, request, EmptyTransportResponseHandler.INSTANCE_SAME); } - private class NodeMappingRefreshTransportHandler extends BaseTransportRequestHandler { - - @Override - public NodeMappingRefreshRequest newInstance() { - return new NodeMappingRefreshRequest(); - } + private class NodeMappingRefreshTransportHandler implements TransportRequestHandler { @Override public void messageReceived(NodeMappingRefreshRequest request, TransportChannel channel) throws Exception { metaDataMappingService.refreshMapping(request.index(), request.indexUUID(), request.types()); channel.sendResponse(TransportResponse.Empty.INSTANCE); } - - @Override - public String executor() { - return ThreadPool.Names.SAME; - } } public static class NodeMappingRefreshRequest extends TransportRequest implements IndicesRequest { diff --git a/src/main/java/org/elasticsearch/cluster/action/shard/ShardStateAction.java b/src/main/java/org/elasticsearch/cluster/action/shard/ShardStateAction.java index feb72fc7078..7630306ebe1 100644 --- a/src/main/java/org/elasticsearch/cluster/action/shard/ShardStateAction.java +++ b/src/main/java/org/elasticsearch/cluster/action/shard/ShardStateAction.java @@ -72,8 +72,8 @@ public class ShardStateAction extends AbstractComponent { this.allocationService = allocationService; this.routingService = routingService; - transportService.registerHandler(SHARD_STARTED_ACTION_NAME, new ShardStartedTransportHandler()); - transportService.registerHandler(SHARD_FAILED_ACTION_NAME, new ShardFailedTransportHandler()); + transportService.registerRequestHandler(SHARD_STARTED_ACTION_NAME, ShardRoutingEntry.class, ThreadPool.Names.SAME, new ShardStartedTransportHandler()); + transportService.registerRequestHandler(SHARD_FAILED_ACTION_NAME, ShardRoutingEntry.class, ThreadPool.Names.SAME, new ShardFailedTransportHandler()); } public void shardFailed(final ShardRouting shardRouting, final String indexUUID, final String reason) throws ElasticsearchException { @@ -287,42 +287,22 @@ public class ShardStateAction extends AbstractComponent { }); } - private class ShardFailedTransportHandler extends BaseTransportRequestHandler { - - @Override - public ShardRoutingEntry newInstance() { - return new ShardRoutingEntry(); - } + private class ShardFailedTransportHandler implements TransportRequestHandler { @Override public void messageReceived(ShardRoutingEntry request, TransportChannel channel) throws Exception { handleShardFailureOnMaster(request); channel.sendResponse(TransportResponse.Empty.INSTANCE); } - - @Override - public String executor() { - return ThreadPool.Names.SAME; - } } - class ShardStartedTransportHandler extends BaseTransportRequestHandler { - - @Override - public ShardRoutingEntry newInstance() { - return new ShardRoutingEntry(); - } + class ShardStartedTransportHandler implements TransportRequestHandler { @Override public void messageReceived(ShardRoutingEntry request, TransportChannel channel) throws Exception { shardStartedOnMaster(request); channel.sendResponse(TransportResponse.Empty.INSTANCE); } - - @Override - public String executor() { - return ThreadPool.Names.SAME; - } } static class ShardRoutingEntry extends TransportRequest { @@ -335,7 +315,7 @@ public class ShardStateAction extends AbstractComponent { volatile boolean processed; // state field, no need to serialize - private ShardRoutingEntry() { + ShardRoutingEntry() { } private ShardRoutingEntry(ShardRouting shardRouting, String indexUUID, String reason) { diff --git a/src/main/java/org/elasticsearch/discovery/zen/ZenDiscovery.java b/src/main/java/org/elasticsearch/discovery/zen/ZenDiscovery.java index b9279d7e832..92354785856 100644 --- a/src/main/java/org/elasticsearch/discovery/zen/ZenDiscovery.java +++ b/src/main/java/org/elasticsearch/discovery/zen/ZenDiscovery.java @@ -195,7 +195,7 @@ public class ZenDiscovery extends AbstractLifecycleComponent implemen this.joinThreadControl = new JoinThreadControl(threadPool); - transportService.registerHandler(DISCOVERY_REJOIN_ACTION_NAME, new RejoinClusterRequestHandler()); + transportService.registerRequestHandler(DISCOVERY_REJOIN_ACTION_NAME, RejoinClusterRequest.class, ThreadPool.Names.SAME, new RejoinClusterRequestHandler()); dynamicSettings.addDynamicSetting(ElectMasterService.DISCOVERY_ZEN_MINIMUM_MASTER_NODES, new Validator() { @Override @@ -1242,13 +1242,7 @@ public class ZenDiscovery extends AbstractLifecycleComponent implemen } } - class RejoinClusterRequestHandler extends BaseTransportRequestHandler { - - @Override - public RejoinClusterRequest newInstance() { - return new RejoinClusterRequest(); - } - + class RejoinClusterRequestHandler implements TransportRequestHandler { @Override public void messageReceived(final RejoinClusterRequest request, final TransportChannel channel) throws Exception { clusterService.submitStateUpdateTask("received a request to rejoin the cluster from [" + request.fromNodeId + "]", Priority.IMMEDIATE, new ClusterStateNonMasterUpdateTask() { @@ -1273,11 +1267,6 @@ public class ZenDiscovery extends AbstractLifecycleComponent implemen } }); } - - @Override - public String executor() { - return ThreadPool.Names.SAME; - } } class ApplySettings implements NodeSettingsService.Listener { diff --git a/src/main/java/org/elasticsearch/discovery/zen/fd/MasterFaultDetection.java b/src/main/java/org/elasticsearch/discovery/zen/fd/MasterFaultDetection.java index 867866b8b2b..d713b6d0b39 100644 --- a/src/main/java/org/elasticsearch/discovery/zen/fd/MasterFaultDetection.java +++ b/src/main/java/org/elasticsearch/discovery/zen/fd/MasterFaultDetection.java @@ -77,7 +77,7 @@ public class MasterFaultDetection extends FaultDetection { logger.debug("[master] uses ping_interval [{}], ping_timeout [{}], ping_retries [{}]", pingInterval, pingRetryTimeout, pingRetryCount); - transportService.registerHandler(MASTER_PING_ACTION_NAME, new MasterPingRequestHandler()); + transportService.registerRequestHandler(MASTER_PING_ACTION_NAME, MasterPingRequest.class, ThreadPool.Names.SAME, new MasterPingRequestHandler()); } public DiscoveryNode masterNode() { @@ -317,12 +317,7 @@ public class MasterFaultDetection extends FaultDetection { } } - private class MasterPingRequestHandler extends BaseTransportRequestHandler { - - @Override - public MasterPingRequest newInstance() { - return new MasterPingRequest(); - } + private class MasterPingRequestHandler implements TransportRequestHandler { @Override public void messageReceived(final MasterPingRequest request, final TransportChannel channel) throws Exception { @@ -390,11 +385,6 @@ public class MasterFaultDetection extends FaultDetection { channel.sendResponse(new MasterPingResponseResponse()); } } - - @Override - public String executor() { - return ThreadPool.Names.SAME; - } } diff --git a/src/main/java/org/elasticsearch/discovery/zen/fd/NodesFaultDetection.java b/src/main/java/org/elasticsearch/discovery/zen/fd/NodesFaultDetection.java index 8cbb863dd80..f367db8ca8c 100644 --- a/src/main/java/org/elasticsearch/discovery/zen/fd/NodesFaultDetection.java +++ b/src/main/java/org/elasticsearch/discovery/zen/fd/NodesFaultDetection.java @@ -65,7 +65,7 @@ public class NodesFaultDetection extends FaultDetection { logger.debug("[node ] uses ping_interval [{}], ping_timeout [{}], ping_retries [{}]", pingInterval, pingRetryTimeout, pingRetryCount); - transportService.registerHandler(PING_ACTION_NAME, new PingRequestHandler()); + transportService.registerRequestHandler(PING_ACTION_NAME, PingRequest.class, ThreadPool.Names.SAME, new PingRequestHandler()); } public void setLocalNode(DiscoveryNode localNode) { @@ -239,13 +239,7 @@ public class NodesFaultDetection extends FaultDetection { } } - class PingRequestHandler extends BaseTransportRequestHandler { - - @Override - public PingRequest newInstance() { - return new PingRequest(); - } - + class PingRequestHandler implements TransportRequestHandler { @Override public void messageReceived(PingRequest request, TransportChannel channel) throws Exception { // if we are not the node we are supposed to be pinged, send an exception @@ -264,11 +258,6 @@ public class NodesFaultDetection extends FaultDetection { channel.sendResponse(new PingResponse()); } - - @Override - public String executor() { - return ThreadPool.Names.SAME; - } } diff --git a/src/main/java/org/elasticsearch/discovery/zen/membership/MembershipAction.java b/src/main/java/org/elasticsearch/discovery/zen/membership/MembershipAction.java index 36fcde3ddcc..b245a6a0d35 100644 --- a/src/main/java/org/elasticsearch/discovery/zen/membership/MembershipAction.java +++ b/src/main/java/org/elasticsearch/discovery/zen/membership/MembershipAction.java @@ -72,9 +72,9 @@ public class MembershipAction extends AbstractComponent { this.listener = listener; this.clusterService = clusterService; - transportService.registerHandler(DISCOVERY_JOIN_ACTION_NAME, new JoinRequestRequestHandler()); - transportService.registerHandler(DISCOVERY_JOIN_VALIDATE_ACTION_NAME, new ValidateJoinRequestRequestHandler()); - transportService.registerHandler(DISCOVERY_LEAVE_ACTION_NAME, new LeaveRequestRequestHandler()); + transportService.registerRequestHandler(DISCOVERY_JOIN_ACTION_NAME, JoinRequest.class, ThreadPool.Names.GENERIC, new JoinRequestRequestHandler()); + transportService.registerRequestHandler(DISCOVERY_JOIN_VALIDATE_ACTION_NAME, ValidateJoinRequest.class, ThreadPool.Names.GENERIC, new ValidateJoinRequestRequestHandler()); + transportService.registerRequestHandler(DISCOVERY_LEAVE_ACTION_NAME, LeaveRequest.class, ThreadPool.Names.GENERIC, new LeaveRequestRequestHandler()); } public void close() { @@ -133,12 +133,7 @@ public class MembershipAction extends AbstractComponent { } - private class JoinRequestRequestHandler extends BaseTransportRequestHandler { - - @Override - public JoinRequest newInstance() { - return new JoinRequest(); - } + private class JoinRequestRequestHandler implements TransportRequestHandler { @Override public void messageReceived(final JoinRequest request, final TransportChannel channel) throws Exception { @@ -162,36 +157,21 @@ public class MembershipAction extends AbstractComponent { } }); } - - @Override - public String executor() { - return ThreadPool.Names.GENERIC; - } } - class ValidateJoinRequest extends TransportRequest { + static class ValidateJoinRequest extends TransportRequest { ValidateJoinRequest() { } } - private class ValidateJoinRequestRequestHandler extends BaseTransportRequestHandler { - - @Override - public ValidateJoinRequest newInstance() { - return new ValidateJoinRequest(); - } + class ValidateJoinRequestRequestHandler implements TransportRequestHandler { @Override public void messageReceived(ValidateJoinRequest request, TransportChannel channel) throws Exception { // for now, the mere fact that we can serialize the cluster state acts as validation.... channel.sendResponse(TransportResponse.Empty.INSTANCE); } - - @Override - public String executor() { - return ThreadPool.Names.GENERIC; - } } static class LeaveRequest extends TransportRequest { @@ -218,22 +198,12 @@ public class MembershipAction extends AbstractComponent { } } - private class LeaveRequestRequestHandler extends BaseTransportRequestHandler { - - @Override - public LeaveRequest newInstance() { - return new LeaveRequest(); - } + private class LeaveRequestRequestHandler implements TransportRequestHandler { @Override public void messageReceived(LeaveRequest request, TransportChannel channel) throws Exception { listener.onLeave(request.node); channel.sendResponse(TransportResponse.Empty.INSTANCE); } - - @Override - public String executor() { - return ThreadPool.Names.GENERIC; - } } } diff --git a/src/main/java/org/elasticsearch/discovery/zen/ping/multicast/MulticastZenPing.java b/src/main/java/org/elasticsearch/discovery/zen/ping/multicast/MulticastZenPing.java index de56bdc3730..e5f0f2ffad3 100644 --- a/src/main/java/org/elasticsearch/discovery/zen/ping/multicast/MulticastZenPing.java +++ b/src/main/java/org/elasticsearch/discovery/zen/ping/multicast/MulticastZenPing.java @@ -107,7 +107,7 @@ public class MulticastZenPing extends AbstractLifecycleComponent implem logger.debug("using group [{}], with port [{}], ttl [{}], and address [{}]", group, port, ttl, address); - this.transportService.registerHandler(ACTION_NAME, new MulticastPingResponseRequestHandler()); + this.transportService.registerRequestHandler(ACTION_NAME, MulticastPingResponse.class, ThreadPool.Names.SAME, new MulticastPingResponseRequestHandler()); } @Override @@ -326,13 +326,7 @@ public class MulticastZenPing extends AbstractLifecycleComponent implem } } - class MulticastPingResponseRequestHandler extends BaseTransportRequestHandler { - - @Override - public MulticastPingResponse newInstance() { - return new MulticastPingResponse(); - } - + class MulticastPingResponseRequestHandler implements TransportRequestHandler { @Override public void messageReceived(MulticastPingResponse request, TransportChannel channel) throws Exception { if (logger.isTraceEnabled()) { @@ -346,11 +340,6 @@ public class MulticastZenPing extends AbstractLifecycleComponent implem } channel.sendResponse(TransportResponse.Empty.INSTANCE); } - - @Override - public String executor() { - return ThreadPool.Names.SAME; - } } static class MulticastPingResponse extends TransportRequest { diff --git a/src/main/java/org/elasticsearch/discovery/zen/ping/unicast/UnicastZenPing.java b/src/main/java/org/elasticsearch/discovery/zen/ping/unicast/UnicastZenPing.java index 5fcba119281..de7a5e309f0 100644 --- a/src/main/java/org/elasticsearch/discovery/zen/ping/unicast/UnicastZenPing.java +++ b/src/main/java/org/elasticsearch/discovery/zen/ping/unicast/UnicastZenPing.java @@ -135,7 +135,7 @@ public class UnicastZenPing extends AbstractLifecycleComponent implemen } this.configuredTargetNodes = configuredTargetNodes.toArray(new DiscoveryNode[configuredTargetNodes.size()]); - transportService.registerHandler(ACTION_NAME, new UnicastPingRequestHandler()); + transportService.registerRequestHandler(ACTION_NAME, UnicastPingRequest.class, ThreadPool.Names.SAME, new UnicastPingRequestHandler()); ThreadFactory threadFactory = EsExecutors.daemonThreadFactory(settings, "[unicast_connect]"); unicastConnectExecutor = EsExecutors.newScaling(0, concurrentConnects, 60, TimeUnit.SECONDS, threadFactory); @@ -483,17 +483,7 @@ public class UnicastZenPing extends AbstractLifecycleComponent implemen return unicastPingResponse; } - class UnicastPingRequestHandler extends BaseTransportRequestHandler { - - @Override - public UnicastPingRequest newInstance() { - return new UnicastPingRequest(); - } - - @Override - public String executor() { - return ThreadPool.Names.SAME; - } + class UnicastPingRequestHandler implements TransportRequestHandler { @Override public void messageReceived(UnicastPingRequest request, TransportChannel channel) throws Exception { @@ -504,9 +494,7 @@ public class UnicastZenPing extends AbstractLifecycleComponent implemen static class UnicastPingRequest extends TransportRequest { int id; - TimeValue timeout; - PingResponse pingResponse; UnicastPingRequest() { diff --git a/src/main/java/org/elasticsearch/discovery/zen/publish/PublishClusterStateAction.java b/src/main/java/org/elasticsearch/discovery/zen/publish/PublishClusterStateAction.java index e8352f389c5..fd1ba85c25c 100644 --- a/src/main/java/org/elasticsearch/discovery/zen/publish/PublishClusterStateAction.java +++ b/src/main/java/org/elasticsearch/discovery/zen/publish/PublishClusterStateAction.java @@ -52,9 +52,9 @@ public class PublishClusterStateAction extends AbstractComponent { public static final String ACTION_NAME = "internal:discovery/zen/publish"; - public static interface NewClusterStateListener { + public interface NewClusterStateListener { - static interface NewStateProcessed { + interface NewStateProcessed { void onNewClusterStateProcessed(); @@ -76,7 +76,7 @@ public class PublishClusterStateAction extends AbstractComponent { this.nodesProvider = nodesProvider; this.listener = listener; this.discoverySettings = discoverySettings; - transportService.registerHandler(ACTION_NAME, new PublishClusterStateRequestHandler()); + transportService.registerRequestHandler(ACTION_NAME, BytesTransportRequest.class, ThreadPool.Names.SAME, new PublishClusterStateRequestHandler()); } public void close() { @@ -171,12 +171,7 @@ public class PublishClusterStateAction extends AbstractComponent { } } - private class PublishClusterStateRequestHandler extends BaseTransportRequestHandler { - - @Override - public BytesTransportRequest newInstance() { - return new BytesTransportRequest(); - } + private class PublishClusterStateRequestHandler implements TransportRequestHandler { @Override public void messageReceived(BytesTransportRequest request, final TransportChannel channel) throws Exception { @@ -220,10 +215,5 @@ public class PublishClusterStateAction extends AbstractComponent { } } } - - @Override - public String executor() { - return ThreadPool.Names.SAME; - } } } diff --git a/src/main/java/org/elasticsearch/gateway/LocalAllocateDangledIndices.java b/src/main/java/org/elasticsearch/gateway/LocalAllocateDangledIndices.java index 622652d1c56..43dec7edb51 100644 --- a/src/main/java/org/elasticsearch/gateway/LocalAllocateDangledIndices.java +++ b/src/main/java/org/elasticsearch/gateway/LocalAllocateDangledIndices.java @@ -60,7 +60,7 @@ public class LocalAllocateDangledIndices extends AbstractComponent { this.transportService = transportService; this.clusterService = clusterService; this.allocationService = allocationService; - transportService.registerHandler(ACTION_NAME, new AllocateDangledRequestHandler()); + transportService.registerRequestHandler(ACTION_NAME, AllocateDangledRequest.class, ThreadPool.Names.SAME, new AllocateDangledRequestHandler()); } public void allocateDangled(Collection indices, final Listener listener) { @@ -100,13 +100,7 @@ public class LocalAllocateDangledIndices extends AbstractComponent { void onFailure(Throwable e); } - class AllocateDangledRequestHandler extends BaseTransportRequestHandler { - - @Override - public AllocateDangledRequest newInstance() { - return new AllocateDangledRequest(); - } - + class AllocateDangledRequestHandler implements TransportRequestHandler { @Override public void messageReceived(final AllocateDangledRequest request, final TransportChannel channel) throws Exception { String[] indexNames = new String[request.indices.length]; @@ -173,11 +167,6 @@ public class LocalAllocateDangledIndices extends AbstractComponent { } }); } - - @Override - public String executor() { - return ThreadPool.Names.SAME; - } } static class AllocateDangledRequest extends TransportRequest { diff --git a/src/main/java/org/elasticsearch/gateway/TransportNodesListGatewayMetaState.java b/src/main/java/org/elasticsearch/gateway/TransportNodesListGatewayMetaState.java index 5f5c73873e7..77ab900ce90 100644 --- a/src/main/java/org/elasticsearch/gateway/TransportNodesListGatewayMetaState.java +++ b/src/main/java/org/elasticsearch/gateway/TransportNodesListGatewayMetaState.java @@ -53,7 +53,8 @@ public class TransportNodesListGatewayMetaState extends TransportNodesOperationA @Inject public TransportNodesListGatewayMetaState(Settings settings, ClusterName clusterName, ThreadPool threadPool, ClusterService clusterService, TransportService transportService, ActionFilters actionFilters) { - super(settings, ACTION_NAME, clusterName, threadPool, clusterService, transportService, actionFilters); + super(settings, ACTION_NAME, clusterName, threadPool, clusterService, transportService, actionFilters, + Request.class, NodeRequest.class, ThreadPool.Names.GENERIC); } TransportNodesListGatewayMetaState init(GatewayMetaState metaState) { @@ -65,26 +66,11 @@ public class TransportNodesListGatewayMetaState extends TransportNodesOperationA return execute(new Request(nodesIds).timeout(timeout)); } - @Override - protected String executor() { - return ThreadPool.Names.GENERIC; - } - @Override protected boolean transportCompress() { return true; // compress since the metadata can become large } - @Override - protected Request newRequestInstance() { - return new Request(); - } - - @Override - protected NodeRequest newNodeRequest() { - return new NodeRequest(); - } - @Override protected NodeRequest newNodeRequest(String nodeId, Request request) { return new NodeRequest(nodeId, request); diff --git a/src/main/java/org/elasticsearch/gateway/TransportNodesListGatewayStartedShards.java b/src/main/java/org/elasticsearch/gateway/TransportNodesListGatewayStartedShards.java index 87edb9cc3c1..4a812784e20 100644 --- a/src/main/java/org/elasticsearch/gateway/TransportNodesListGatewayStartedShards.java +++ b/src/main/java/org/elasticsearch/gateway/TransportNodesListGatewayStartedShards.java @@ -55,7 +55,8 @@ public class TransportNodesListGatewayStartedShards extends TransportNodesOperat @Inject public TransportNodesListGatewayStartedShards(Settings settings, ClusterName clusterName, ThreadPool threadPool, ClusterService clusterService, TransportService transportService, ActionFilters actionFilters, NodeEnvironment env) { - super(settings, ACTION_NAME, clusterName, threadPool, clusterService, transportService, actionFilters); + super(settings, ACTION_NAME, clusterName, threadPool, clusterService, transportService, actionFilters, + Request.class, NodeRequest.class, ThreadPool.Names.GENERIC); this.nodeEnv = env; } @@ -63,26 +64,11 @@ public class TransportNodesListGatewayStartedShards extends TransportNodesOperat return execute(new Request(shardId, indexUUID, nodesIds).timeout(timeout)); } - @Override - protected String executor() { - return ThreadPool.Names.GENERIC; - } - @Override protected boolean transportCompress() { return true; // this can become big... } - @Override - protected Request newRequestInstance() { - return new Request(); - } - - @Override - protected NodeRequest newNodeRequest() { - return new NodeRequest(); - } - @Override protected NodeRequest newNodeRequest(String nodeId, Request request) { return new NodeRequest(nodeId, request); diff --git a/src/main/java/org/elasticsearch/indices/recovery/RecoverySource.java b/src/main/java/org/elasticsearch/indices/recovery/RecoverySource.java index 6878ab863d9..ced38423e54 100644 --- a/src/main/java/org/elasticsearch/indices/recovery/RecoverySource.java +++ b/src/main/java/org/elasticsearch/indices/recovery/RecoverySource.java @@ -36,8 +36,8 @@ import org.elasticsearch.index.shard.ShardId; import org.elasticsearch.indices.IndicesLifecycle; import org.elasticsearch.indices.IndicesService; import org.elasticsearch.threadpool.ThreadPool; -import org.elasticsearch.transport.BaseTransportRequestHandler; import org.elasticsearch.transport.TransportChannel; +import org.elasticsearch.transport.TransportRequestHandler; import org.elasticsearch.transport.TransportService; import java.util.*; @@ -82,7 +82,7 @@ public class RecoverySource extends AbstractComponent { this.recoverySettings = recoverySettings; - transportService.registerHandler(Actions.START_RECOVERY, new StartRecoveryTransportRequestHandler()); + transportService.registerRequestHandler(Actions.START_RECOVERY, StartRecoveryRequest.class, ThreadPool.Names.GENERIC, new StartRecoveryTransportRequestHandler()); } private RecoveryResponse recover(final StartRecoveryRequest request) { @@ -129,18 +129,7 @@ public class RecoverySource extends AbstractComponent { return handler.getResponse(); } - class StartRecoveryTransportRequestHandler extends BaseTransportRequestHandler { - - @Override - public StartRecoveryRequest newInstance() { - return new StartRecoveryRequest(); - } - - @Override - public String executor() { - return ThreadPool.Names.GENERIC; - } - + class StartRecoveryTransportRequestHandler implements TransportRequestHandler { @Override public void messageReceived(final StartRecoveryRequest request, final TransportChannel channel) throws Exception { RecoveryResponse response = recover(request); diff --git a/src/main/java/org/elasticsearch/indices/recovery/RecoveryTarget.java b/src/main/java/org/elasticsearch/indices/recovery/RecoveryTarget.java index 4382f6bdb29..fcfc9722a03 100644 --- a/src/main/java/org/elasticsearch/indices/recovery/RecoveryTarget.java +++ b/src/main/java/org/elasticsearch/indices/recovery/RecoveryTarget.java @@ -95,12 +95,12 @@ public class RecoveryTarget extends AbstractComponent { this.clusterService = clusterService; this.onGoingRecoveries = new RecoveriesCollection(logger, threadPool); - transportService.registerHandler(Actions.FILES_INFO, new FilesInfoRequestHandler()); - transportService.registerHandler(Actions.FILE_CHUNK, new FileChunkTransportRequestHandler()); - transportService.registerHandler(Actions.CLEAN_FILES, new CleanFilesRequestHandler()); - transportService.registerHandler(Actions.PREPARE_TRANSLOG, new PrepareForTranslogOperationsRequestHandler()); - transportService.registerHandler(Actions.TRANSLOG_OPS, new TranslogOperationsRequestHandler()); - transportService.registerHandler(Actions.FINALIZE, new FinalizeRecoveryRequestHandler()); + transportService.registerRequestHandler(Actions.FILES_INFO, RecoveryFilesInfoRequest.class, ThreadPool.Names.GENERIC, new FilesInfoRequestHandler()); + transportService.registerRequestHandler(Actions.FILE_CHUNK, RecoveryFileChunkRequest.class, ThreadPool.Names.GENERIC, new FileChunkTransportRequestHandler()); + transportService.registerRequestHandler(Actions.CLEAN_FILES, RecoveryCleanFilesRequest.class, ThreadPool.Names.GENERIC, new CleanFilesRequestHandler()); + transportService.registerRequestHandler(Actions.PREPARE_TRANSLOG, RecoveryPrepareForTranslogOperationsRequest.class, ThreadPool.Names.GENERIC, new PrepareForTranslogOperationsRequestHandler()); + transportService.registerRequestHandler(Actions.TRANSLOG_OPS, RecoveryTranslogOperationsRequest.class, ThreadPool.Names.GENERIC, new TranslogOperationsRequestHandler()); + transportService.registerRequestHandler(Actions.FINALIZE, RecoveryFinalizeRecoveryRequest.class, ThreadPool.Names.GENERIC, new FinalizeRecoveryRequestHandler()); indicesLifecycle.addListener(new IndicesLifecycle.Listener() { @Override @@ -267,17 +267,7 @@ public class RecoveryTarget extends AbstractComponent { void onRecoveryFailure(RecoveryState state, RecoveryFailedException e, boolean sendShardFailure); } - class PrepareForTranslogOperationsRequestHandler extends BaseTransportRequestHandler { - - @Override - public RecoveryPrepareForTranslogOperationsRequest newInstance() { - return new RecoveryPrepareForTranslogOperationsRequest(); - } - - @Override - public String executor() { - return ThreadPool.Names.GENERIC; - } + class PrepareForTranslogOperationsRequestHandler implements TransportRequestHandler { @Override public void messageReceived(RecoveryPrepareForTranslogOperationsRequest request, TransportChannel channel) throws Exception { @@ -290,17 +280,7 @@ public class RecoveryTarget extends AbstractComponent { } } - class FinalizeRecoveryRequestHandler extends BaseTransportRequestHandler { - - @Override - public RecoveryFinalizeRecoveryRequest newInstance() { - return new RecoveryFinalizeRecoveryRequest(); - } - - @Override - public String executor() { - return ThreadPool.Names.GENERIC; - } + class FinalizeRecoveryRequestHandler implements TransportRequestHandler { @Override public void messageReceived(RecoveryFinalizeRecoveryRequest request, TransportChannel channel) throws Exception { @@ -312,18 +292,7 @@ public class RecoveryTarget extends AbstractComponent { } } - class TranslogOperationsRequestHandler extends BaseTransportRequestHandler { - - - @Override - public RecoveryTranslogOperationsRequest newInstance() { - return new RecoveryTranslogOperationsRequest(); - } - - @Override - public String executor() { - return ThreadPool.Names.GENERIC; - } + class TranslogOperationsRequestHandler implements TransportRequestHandler { @Override public void messageReceived(RecoveryTranslogOperationsRequest request, TransportChannel channel) throws Exception { @@ -339,17 +308,7 @@ public class RecoveryTarget extends AbstractComponent { } } - class FilesInfoRequestHandler extends BaseTransportRequestHandler { - - @Override - public RecoveryFilesInfoRequest newInstance() { - return new RecoveryFilesInfoRequest(); - } - - @Override - public String executor() { - return ThreadPool.Names.GENERIC; - } + class FilesInfoRequestHandler implements TransportRequestHandler { @Override public void messageReceived(RecoveryFilesInfoRequest request, TransportChannel channel) throws Exception { @@ -370,17 +329,7 @@ public class RecoveryTarget extends AbstractComponent { } } - class CleanFilesRequestHandler extends BaseTransportRequestHandler { - - @Override - public RecoveryCleanFilesRequest newInstance() { - return new RecoveryCleanFilesRequest(); - } - - @Override - public String executor() { - return ThreadPool.Names.GENERIC; - } + class CleanFilesRequestHandler implements TransportRequestHandler { @Override public void messageReceived(RecoveryCleanFilesRequest request, TransportChannel channel) throws Exception { @@ -419,21 +368,11 @@ public class RecoveryTarget extends AbstractComponent { } } - class FileChunkTransportRequestHandler extends BaseTransportRequestHandler { + class FileChunkTransportRequestHandler implements TransportRequestHandler { // How many bytes we've copied since we last called RateLimiter.pause final AtomicLong bytesSinceLastPause = new AtomicLong(); - @Override - public RecoveryFileChunkRequest newInstance() { - return new RecoveryFileChunkRequest(); - } - - @Override - public String executor() { - return ThreadPool.Names.GENERIC; - } - @Override public void messageReceived(final RecoveryFileChunkRequest request, TransportChannel channel) throws Exception { try (RecoveriesCollection.StatusRef statusRef = onGoingRecoveries.getStatusSafe(request.recoveryId(), request.shardId())) { diff --git a/src/main/java/org/elasticsearch/indices/store/IndicesStore.java b/src/main/java/org/elasticsearch/indices/store/IndicesStore.java index 4737271c203..32e695a828c 100644 --- a/src/main/java/org/elasticsearch/indices/store/IndicesStore.java +++ b/src/main/java/org/elasticsearch/indices/store/IndicesStore.java @@ -112,7 +112,7 @@ public class IndicesStore extends AbstractComponent implements ClusterStateListe this.indicesService = indicesService; this.clusterService = clusterService; this.transportService = transportService; - transportService.registerHandler(ACTION_SHARD_EXISTS, new ShardActiveRequestHandler()); + transportService.registerRequestHandler(ACTION_SHARD_EXISTS, ShardActiveRequest.class, ThreadPool.Names.SAME, new ShardActiveRequestHandler()); // we don't limit by default (we default to CMS's auto throttle instead): this.rateLimitingType = settings.get("indices.store.throttle.type", StoreRateLimiting.Type.NONE.name()); @@ -324,17 +324,7 @@ public class IndicesStore extends AbstractComponent implements ClusterStateListe } - private class ShardActiveRequestHandler extends BaseTransportRequestHandler { - - @Override - public ShardActiveRequest newInstance() { - return new ShardActiveRequest(); - } - - @Override - public String executor() { - return ThreadPool.Names.SAME; - } + private class ShardActiveRequestHandler implements TransportRequestHandler { @Override public void messageReceived(final ShardActiveRequest request, final TransportChannel channel) throws Exception { diff --git a/src/main/java/org/elasticsearch/indices/store/TransportNodesListShardStoreMetaData.java b/src/main/java/org/elasticsearch/indices/store/TransportNodesListShardStoreMetaData.java index 26223aac2ea..ab1ba9232aa 100644 --- a/src/main/java/org/elasticsearch/indices/store/TransportNodesListShardStoreMetaData.java +++ b/src/main/java/org/elasticsearch/indices/store/TransportNodesListShardStoreMetaData.java @@ -71,7 +71,8 @@ public class TransportNodesListShardStoreMetaData extends TransportNodesOperatio @Inject public TransportNodesListShardStoreMetaData(Settings settings, ClusterName clusterName, ThreadPool threadPool, ClusterService clusterService, TransportService transportService, IndicesService indicesService, NodeEnvironment nodeEnv, ActionFilters actionFilters) { - super(settings, ACTION_NAME, clusterName, threadPool, clusterService, transportService, actionFilters); + super(settings, ACTION_NAME, clusterName, threadPool, clusterService, transportService, actionFilters, + Request.class, NodeRequest.class, ThreadPool.Names.GENERIC); this.indicesService = indicesService; this.nodeEnv = nodeEnv; } @@ -80,21 +81,6 @@ public class TransportNodesListShardStoreMetaData extends TransportNodesOperatio return execute(new Request(shardId, onlyUnallocated, nodesIds).timeout(timeout)); } - @Override - protected String executor() { - return ThreadPool.Names.GENERIC; - } - - @Override - protected Request newRequestInstance() { - return new Request(); - } - - @Override - protected NodeRequest newNodeRequest() { - return new NodeRequest(); - } - @Override protected NodeRequest newNodeRequest(String nodeId, Request request) { return new NodeRequest(nodeId, request); diff --git a/src/main/java/org/elasticsearch/repositories/VerifyNodeRepositoryAction.java b/src/main/java/org/elasticsearch/repositories/VerifyNodeRepositoryAction.java index 3150c8e6b29..11fb1cb3225 100644 --- a/src/main/java/org/elasticsearch/repositories/VerifyNodeRepositoryAction.java +++ b/src/main/java/org/elasticsearch/repositories/VerifyNodeRepositoryAction.java @@ -22,7 +22,6 @@ package org.elasticsearch.repositories; import com.carrotsearch.hppc.ObjectContainer; import com.carrotsearch.hppc.cursors.ObjectCursor; import org.elasticsearch.ExceptionsHelper; -import org.elasticsearch.Version; import org.elasticsearch.action.ActionListener; import org.elasticsearch.cluster.ClusterService; import org.elasticsearch.cluster.node.DiscoveryNode; @@ -30,7 +29,6 @@ import org.elasticsearch.cluster.node.DiscoveryNodes; import org.elasticsearch.common.component.AbstractComponent; 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.settings.Settings; import org.elasticsearch.index.snapshots.IndexShardRepository; import org.elasticsearch.threadpool.ThreadPool; @@ -58,7 +56,7 @@ public class VerifyNodeRepositoryAction extends AbstractComponent { this.transportService = transportService; this.clusterService = clusterService; this.repositoriesService = repositoriesService; - transportService.registerHandler(ACTION_NAME, new VerifyNodeRepositoryRequestHandler()); + transportService.registerRequestHandler(ACTION_NAME, VerifyNodeRepositoryRequest.class, ThreadPool.Names.SAME, new VerifyNodeRepositoryRequestHandler()); } public void close() { @@ -117,16 +115,15 @@ public class VerifyNodeRepositoryAction extends AbstractComponent { blobStoreIndexShardRepository.verify(verificationToken); } - private class VerifyNodeRepositoryRequest extends TransportRequest { + static class VerifyNodeRepositoryRequest extends TransportRequest { private String repository; - private String verificationToken; - private VerifyNodeRepositoryRequest() { + VerifyNodeRepositoryRequest() { } - private VerifyNodeRepositoryRequest(String repository, String verificationToken) { + VerifyNodeRepositoryRequest(String repository, String verificationToken) { this.repository = repository; this.verificationToken = verificationToken; } @@ -146,18 +143,7 @@ public class VerifyNodeRepositoryAction extends AbstractComponent { } } - private class VerifyNodeRepositoryRequestHandler extends BaseTransportRequestHandler { - - @Override - public VerifyNodeRepositoryRequest newInstance() { - return new VerifyNodeRepositoryRequest(); - } - - @Override - public String executor() { - return ThreadPool.Names.SAME; - } - + class VerifyNodeRepositoryRequestHandler implements TransportRequestHandler { @Override public void messageReceived(VerifyNodeRepositoryRequest request, TransportChannel channel) throws Exception { doVerify(request.repository, request.verificationToken); diff --git a/src/main/java/org/elasticsearch/river/cluster/PublishRiverClusterStateAction.java b/src/main/java/org/elasticsearch/river/cluster/PublishRiverClusterStateAction.java index 0b39d50d4bf..d783adee752 100644 --- a/src/main/java/org/elasticsearch/river/cluster/PublishRiverClusterStateAction.java +++ b/src/main/java/org/elasticsearch/river/cluster/PublishRiverClusterStateAction.java @@ -38,7 +38,7 @@ public class PublishRiverClusterStateAction extends AbstractComponent { public static final String ACTION_NAME = "internal:river/state/publish"; - public static interface NewClusterStateListener { + public interface NewClusterStateListener { void onNewClusterState(RiverClusterState clusterState); } @@ -54,7 +54,7 @@ public class PublishRiverClusterStateAction extends AbstractComponent { this.transportService = transportService; this.clusterService = clusterService; this.listener = listener; - transportService.registerHandler(ACTION_NAME, new PublishClusterStateRequestHandler()); + transportService.registerRequestHandler(ACTION_NAME, PublishClusterStateRequest.class, ThreadPool.Names.SAME, new PublishClusterStateRequestHandler()); } public void close() { @@ -87,11 +87,11 @@ public class PublishRiverClusterStateAction extends AbstractComponent { } } - private class PublishClusterStateRequest extends TransportRequest { + static class PublishClusterStateRequest extends TransportRequest { private RiverClusterState clusterState; - private PublishClusterStateRequest() { + PublishClusterStateRequest() { } private PublishClusterStateRequest(RiverClusterState clusterState) { @@ -111,18 +111,7 @@ public class PublishRiverClusterStateAction extends AbstractComponent { } } - private class PublishClusterStateRequestHandler extends BaseTransportRequestHandler { - - @Override - public PublishClusterStateRequest newInstance() { - return new PublishClusterStateRequest(); - } - - @Override - public String executor() { - return ThreadPool.Names.SAME; - } - + private class PublishClusterStateRequestHandler implements TransportRequestHandler { @Override public void messageReceived(PublishClusterStateRequest request, TransportChannel channel) throws Exception { listener.onNewClusterState(request.clusterState); diff --git a/src/main/java/org/elasticsearch/search/action/SearchServiceTransportAction.java b/src/main/java/org/elasticsearch/search/action/SearchServiceTransportAction.java index 13fe4bd15fb..5730a023554 100644 --- a/src/main/java/org/elasticsearch/search/action/SearchServiceTransportAction.java +++ b/src/main/java/org/elasticsearch/search/action/SearchServiceTransportAction.java @@ -76,20 +76,20 @@ public class SearchServiceTransportAction extends AbstractComponent { this.transportService = transportService; this.searchService = searchService; - transportService.registerHandler(FREE_CONTEXT_SCROLL_ACTION_NAME, new ScrollFreeContextTransportHandler()); - transportService.registerHandler(FREE_CONTEXT_ACTION_NAME, new SearchFreeContextTransportHandler()); - transportService.registerHandler(CLEAR_SCROLL_CONTEXTS_ACTION_NAME, new ClearScrollContextsTransportHandler()); - transportService.registerHandler(DFS_ACTION_NAME, new SearchDfsTransportHandler()); - transportService.registerHandler(QUERY_ACTION_NAME, new SearchQueryTransportHandler()); - transportService.registerHandler(QUERY_ID_ACTION_NAME, new SearchQueryByIdTransportHandler()); - transportService.registerHandler(QUERY_SCROLL_ACTION_NAME, new SearchQueryScrollTransportHandler()); - transportService.registerHandler(QUERY_FETCH_ACTION_NAME, new SearchQueryFetchTransportHandler()); - transportService.registerHandler(QUERY_QUERY_FETCH_ACTION_NAME, new SearchQueryQueryFetchTransportHandler()); - transportService.registerHandler(QUERY_FETCH_SCROLL_ACTION_NAME, new SearchQueryFetchScrollTransportHandler()); - transportService.registerHandler(FETCH_ID_SCROLL_ACTION_NAME, new ScrollFetchByIdTransportHandler()); - transportService.registerHandler(FETCH_ID_ACTION_NAME, new SearchFetchByIdTransportHandler()); - transportService.registerHandler(SCAN_ACTION_NAME, new SearchScanTransportHandler()); - transportService.registerHandler(SCAN_SCROLL_ACTION_NAME, new SearchScanScrollTransportHandler()); + transportService.registerRequestHandler(FREE_CONTEXT_SCROLL_ACTION_NAME, ScrollFreeContextRequest.class, ThreadPool.Names.SAME, new FreeContextTransportHandler<>()); + transportService.registerRequestHandler(FREE_CONTEXT_ACTION_NAME, SearchFreeContextRequest.class, ThreadPool.Names.SAME, new FreeContextTransportHandler()); + transportService.registerRequestHandler(CLEAR_SCROLL_CONTEXTS_ACTION_NAME, ClearScrollContextsRequest.class, ThreadPool.Names.SAME, new ClearScrollContextsTransportHandler()); + transportService.registerRequestHandler(DFS_ACTION_NAME, ShardSearchTransportRequest.class, ThreadPool.Names.SEARCH, new SearchDfsTransportHandler()); + transportService.registerRequestHandler(QUERY_ACTION_NAME, ShardSearchTransportRequest.class, ThreadPool.Names.SEARCH, new SearchQueryTransportHandler()); + transportService.registerRequestHandler(QUERY_ID_ACTION_NAME, QuerySearchRequest.class, ThreadPool.Names.SEARCH, new SearchQueryByIdTransportHandler()); + transportService.registerRequestHandler(QUERY_SCROLL_ACTION_NAME, InternalScrollSearchRequest.class, ThreadPool.Names.SEARCH, new SearchQueryScrollTransportHandler()); + transportService.registerRequestHandler(QUERY_FETCH_ACTION_NAME, ShardSearchTransportRequest.class, ThreadPool.Names.SEARCH, new SearchQueryFetchTransportHandler()); + transportService.registerRequestHandler(QUERY_QUERY_FETCH_ACTION_NAME, QuerySearchRequest.class, ThreadPool.Names.SEARCH, new SearchQueryQueryFetchTransportHandler()); + transportService.registerRequestHandler(QUERY_FETCH_SCROLL_ACTION_NAME, InternalScrollSearchRequest.class, ThreadPool.Names.SEARCH, new SearchQueryFetchScrollTransportHandler()); + transportService.registerRequestHandler(FETCH_ID_SCROLL_ACTION_NAME, ShardFetchRequest.class, ThreadPool.Names.SEARCH, new FetchByIdTransportHandler<>()); + transportService.registerRequestHandler(FETCH_ID_ACTION_NAME, ShardFetchSearchRequest.class, ThreadPool.Names.SEARCH, new FetchByIdTransportHandler()); + transportService.registerRequestHandler(SCAN_ACTION_NAME, ShardSearchTransportRequest.class, ThreadPool.Names.SEARCH, new SearchScanTransportHandler()); + transportService.registerRequestHandler(SCAN_SCROLL_ACTION_NAME, InternalScrollSearchRequest.class, ThreadPool.Names.SEARCH, new SearchScanScrollTransportHandler()); } public void sendFreeContext(DiscoveryNode node, final long contextId, SearchRequest request) { @@ -327,36 +327,12 @@ public class SearchServiceTransportAction extends AbstractComponent { } } - private abstract class BaseFreeContextTransportHandler extends BaseTransportRequestHandler { - @Override - public abstract FreeContextRequest newInstance(); - + class FreeContextTransportHandler implements TransportRequestHandler { @Override public void messageReceived(FreeContextRequest request, TransportChannel channel) throws Exception { boolean freed = searchService.freeContext(request.id()); channel.sendResponse(new SearchFreeContextResponse(freed)); } - - @Override - public String executor() { - // freeing the context is cheap, - // no need for fork it to another thread - return ThreadPool.Names.SAME; - } - } - - class ScrollFreeContextTransportHandler extends BaseFreeContextTransportHandler { - @Override - public ScrollFreeContextRequest newInstance() { - return new ScrollFreeContextRequest(); - } - } - - class SearchFreeContextTransportHandler extends BaseFreeContextTransportHandler { - @Override - public SearchFreeContextRequest newInstance() { - return new SearchFreeContextRequest(); - } } static class ClearScrollContextsRequest extends TransportRequest { @@ -370,226 +346,91 @@ public class SearchServiceTransportAction extends AbstractComponent { } - class ClearScrollContextsTransportHandler extends BaseTransportRequestHandler { - - @Override - public ClearScrollContextsRequest newInstance() { - return new ClearScrollContextsRequest(); - } - + class ClearScrollContextsTransportHandler implements TransportRequestHandler { @Override public void messageReceived(ClearScrollContextsRequest request, TransportChannel channel) throws Exception { searchService.freeAllScrollContexts(); channel.sendResponse(TransportResponse.Empty.INSTANCE); } - - @Override - public String executor() { - // freeing the context is cheap, - // no need for fork it to another thread - return ThreadPool.Names.SAME; - } } - private class SearchDfsTransportHandler extends BaseTransportRequestHandler { - - @Override - public ShardSearchTransportRequest newInstance() { - return new ShardSearchTransportRequest(); - } - + class SearchDfsTransportHandler implements TransportRequestHandler { @Override public void messageReceived(ShardSearchTransportRequest request, TransportChannel channel) throws Exception { DfsSearchResult result = searchService.executeDfsPhase(request); channel.sendResponse(result); } - - @Override - public String executor() { - return ThreadPool.Names.SEARCH; - } } - private class SearchQueryTransportHandler extends BaseTransportRequestHandler { - - @Override - public ShardSearchTransportRequest newInstance() { - return new ShardSearchTransportRequest(); - } - + class SearchQueryTransportHandler implements TransportRequestHandler { @Override public void messageReceived(ShardSearchTransportRequest request, TransportChannel channel) throws Exception { QuerySearchResultProvider result = searchService.executeQueryPhase(request); channel.sendResponse(result); } - - @Override - public String executor() { - return ThreadPool.Names.SEARCH; - } } - private class SearchQueryByIdTransportHandler extends BaseTransportRequestHandler { - - @Override - public QuerySearchRequest newInstance() { - return new QuerySearchRequest(); - } - + class SearchQueryByIdTransportHandler implements TransportRequestHandler { @Override public void messageReceived(QuerySearchRequest request, TransportChannel channel) throws Exception { QuerySearchResult result = searchService.executeQueryPhase(request); channel.sendResponse(result); } - - @Override - public String executor() { - return ThreadPool.Names.SEARCH; - } } - private class SearchQueryScrollTransportHandler extends BaseTransportRequestHandler { - - @Override - public InternalScrollSearchRequest newInstance() { - return new InternalScrollSearchRequest(); - } - + class SearchQueryScrollTransportHandler implements TransportRequestHandler { @Override public void messageReceived(InternalScrollSearchRequest request, TransportChannel channel) throws Exception { ScrollQuerySearchResult result = searchService.executeQueryPhase(request); channel.sendResponse(result); } - - @Override - public String executor() { - return ThreadPool.Names.SEARCH; - } } - private class SearchQueryFetchTransportHandler extends BaseTransportRequestHandler { - - @Override - public ShardSearchTransportRequest newInstance() { - return new ShardSearchTransportRequest(); - } - + class SearchQueryFetchTransportHandler implements TransportRequestHandler { @Override public void messageReceived(ShardSearchTransportRequest request, TransportChannel channel) throws Exception { QueryFetchSearchResult result = searchService.executeFetchPhase(request); channel.sendResponse(result); } - - @Override - public String executor() { - return ThreadPool.Names.SEARCH; - } } - private class SearchQueryQueryFetchTransportHandler extends BaseTransportRequestHandler { - - @Override - public QuerySearchRequest newInstance() { - return new QuerySearchRequest(); - } - + class SearchQueryQueryFetchTransportHandler implements TransportRequestHandler { @Override public void messageReceived(QuerySearchRequest request, TransportChannel channel) throws Exception { QueryFetchSearchResult result = searchService.executeFetchPhase(request); channel.sendResponse(result); } - - @Override - public String executor() { - return ThreadPool.Names.SEARCH; - } } - private abstract class FetchByIdTransportHandler extends BaseTransportRequestHandler { - - @Override - public abstract Request newInstance(); - + class FetchByIdTransportHandler implements TransportRequestHandler { @Override public void messageReceived(Request request, TransportChannel channel) throws Exception { FetchSearchResult result = searchService.executeFetchPhase(request); channel.sendResponse(result); } - - @Override - public String executor() { - return ThreadPool.Names.SEARCH; - } } - private class ScrollFetchByIdTransportHandler extends FetchByIdTransportHandler { - @Override - public ShardFetchRequest newInstance() { - return new ShardFetchRequest(); - } - } - - private class SearchFetchByIdTransportHandler extends FetchByIdTransportHandler { - @Override - public ShardFetchSearchRequest newInstance() { - return new ShardFetchSearchRequest(); - } - } - - private class SearchQueryFetchScrollTransportHandler extends BaseTransportRequestHandler { - - @Override - public InternalScrollSearchRequest newInstance() { - return new InternalScrollSearchRequest(); - } - + class SearchQueryFetchScrollTransportHandler implements TransportRequestHandler { @Override public void messageReceived(InternalScrollSearchRequest request, TransportChannel channel) throws Exception { ScrollQueryFetchSearchResult result = searchService.executeFetchPhase(request); channel.sendResponse(result); } - - @Override - public String executor() { - return ThreadPool.Names.SEARCH; - } } - private class SearchScanTransportHandler extends BaseTransportRequestHandler { - - @Override - public ShardSearchTransportRequest newInstance() { - return new ShardSearchTransportRequest(); - } - + class SearchScanTransportHandler implements TransportRequestHandler { @Override public void messageReceived(ShardSearchTransportRequest request, TransportChannel channel) throws Exception { QuerySearchResult result = searchService.executeScan(request); channel.sendResponse(result); } - - @Override - public String executor() { - return ThreadPool.Names.SEARCH; - } } - private class SearchScanScrollTransportHandler extends BaseTransportRequestHandler { - - @Override - public InternalScrollSearchRequest newInstance() { - return new InternalScrollSearchRequest(); - } - + class SearchScanScrollTransportHandler implements TransportRequestHandler { @Override public void messageReceived(InternalScrollSearchRequest request, TransportChannel channel) throws Exception { ScrollQueryFetchSearchResult result = searchService.executeScan(request); channel.sendResponse(result); } - - @Override - public String executor() { - return ThreadPool.Names.SEARCH; - } } } diff --git a/src/main/java/org/elasticsearch/snapshots/RestoreService.java b/src/main/java/org/elasticsearch/snapshots/RestoreService.java index d0f3a35bcfa..6790991c298 100644 --- a/src/main/java/org/elasticsearch/snapshots/RestoreService.java +++ b/src/main/java/org/elasticsearch/snapshots/RestoreService.java @@ -128,7 +128,7 @@ public class RestoreService extends AbstractComponent implements ClusterStateLis this.allocationService = allocationService; this.createIndexService = createIndexService; this.dynamicSettings = dynamicSettings; - transportService.registerHandler(UPDATE_RESTORE_ACTION_NAME, new UpdateRestoreStateRequestHandler()); + transportService.registerRequestHandler(UPDATE_RESTORE_ACTION_NAME, UpdateIndexShardRestoreStatusRequest.class, ThreadPool.Names.SAME, new UpdateRestoreStateRequestHandler()); clusterService.add(this); } @@ -937,7 +937,7 @@ public class RestoreService extends AbstractComponent implements ClusterStateLis /** * Internal class that is used to send notifications about finished shard restore operations to master node */ - private static class UpdateIndexShardRestoreStatusRequest extends TransportRequest { + static class UpdateIndexShardRestoreStatusRequest extends TransportRequest { private SnapshotId snapshotId; private ShardId shardId; private ShardRestoreStatus status; @@ -984,22 +984,11 @@ public class RestoreService extends AbstractComponent implements ClusterStateLis /** * Internal class that is used to send notifications about finished shard restore operations to master node */ - private class UpdateRestoreStateRequestHandler extends BaseTransportRequestHandler { - - @Override - public UpdateIndexShardRestoreStatusRequest newInstance() { - return new UpdateIndexShardRestoreStatusRequest(); - } - + class UpdateRestoreStateRequestHandler implements TransportRequestHandler { @Override public void messageReceived(UpdateIndexShardRestoreStatusRequest request, final TransportChannel channel) throws Exception { updateRestoreStateOnMaster(request); channel.sendResponse(TransportResponse.Empty.INSTANCE); } - - @Override - public String executor() { - return ThreadPool.Names.SAME; - } } } diff --git a/src/main/java/org/elasticsearch/snapshots/SnapshotsService.java b/src/main/java/org/elasticsearch/snapshots/SnapshotsService.java index ab7ec1e1755..54693726d6d 100644 --- a/src/main/java/org/elasticsearch/snapshots/SnapshotsService.java +++ b/src/main/java/org/elasticsearch/snapshots/SnapshotsService.java @@ -118,7 +118,7 @@ public class SnapshotsService extends AbstractLifecycleComponent { - - @Override - public UpdateIndexShardSnapshotStatusRequest newInstance() { - return new UpdateIndexShardSnapshotStatusRequest(); - } - + class UpdateSnapshotStateRequestHandler implements TransportRequestHandler { @Override public void messageReceived(UpdateIndexShardSnapshotStatusRequest request, final TransportChannel channel) throws Exception { innerUpdateSnapshotState(request); channel.sendResponse(TransportResponse.Empty.INSTANCE); } - - @Override - public String executor() { - return ThreadPool.Names.SAME; - } } - - } diff --git a/src/main/java/org/elasticsearch/transport/BaseTransportRequestHandler.java b/src/main/java/org/elasticsearch/transport/BaseTransportRequestHandler.java deleted file mode 100644 index 98c6f784d3b..00000000000 --- a/src/main/java/org/elasticsearch/transport/BaseTransportRequestHandler.java +++ /dev/null @@ -1,34 +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.transport; - -/** - * A simple based class that always spawns. - */ -public abstract class BaseTransportRequestHandler implements TransportRequestHandler { - - /** - * Default force execution to false. - */ - @Override - public boolean isForceExecution() { - return false; - } -} \ No newline at end of file diff --git a/src/main/java/org/elasticsearch/transport/RequestHandlerRegistry.java b/src/main/java/org/elasticsearch/transport/RequestHandlerRegistry.java new file mode 100644 index 00000000000..422cb6d27b6 --- /dev/null +++ b/src/main/java/org/elasticsearch/transport/RequestHandlerRegistry.java @@ -0,0 +1,74 @@ +/* + * 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.transport; + +import org.elasticsearch.ElasticsearchIllegalStateException; + +import java.lang.reflect.Constructor; + +/** + * + */ +public class RequestHandlerRegistry { + + private final String action; + private final Constructor requestConstructor; + private final TransportRequestHandler handler; + private final boolean forceExecution; + private final String executor; + + RequestHandlerRegistry(String action, Class request, TransportRequestHandler handler, + String executor, boolean forceExecution) { + this.action = action; + try { + this.requestConstructor = request.getDeclaredConstructor(); + } catch (NoSuchMethodException e) { + throw new ElasticsearchIllegalStateException("failed to create constructor (does it have a default constructor?) for request " + request, e); + } + this.requestConstructor.setAccessible(true); + this.handler = handler; + this.forceExecution = forceExecution; + this.executor = executor; + } + + public String getAction() { + return action; + } + + public Request newRequest() { + try { + return requestConstructor.newInstance(); + } catch (Exception e) { + throw new ElasticsearchIllegalStateException("failed to instantiate request ", e); + } + } + + public TransportRequestHandler getHandler() { + return handler; + } + + public boolean isForceExecution() { + return forceExecution; + } + + public String getExecutor() { + return executor; + } +} diff --git a/src/main/java/org/elasticsearch/transport/TransportRequestHandler.java b/src/main/java/org/elasticsearch/transport/TransportRequestHandler.java index fd62f30418b..5b5e58de06d 100644 --- a/src/main/java/org/elasticsearch/transport/TransportRequestHandler.java +++ b/src/main/java/org/elasticsearch/transport/TransportRequestHandler.java @@ -24,14 +24,5 @@ package org.elasticsearch.transport; */ public interface TransportRequestHandler { - T newInstance(); - void messageReceived(T request, TransportChannel channel) throws Exception; - - String executor(); - - /** - * See {@link org.elasticsearch.common.util.concurrent.AbstractRunnable#isForceExecution()}. - */ - boolean isForceExecution(); } diff --git a/src/main/java/org/elasticsearch/transport/TransportService.java b/src/main/java/org/elasticsearch/transport/TransportService.java index 975f669a592..ad17baa908d 100644 --- a/src/main/java/org/elasticsearch/transport/TransportService.java +++ b/src/main/java/org/elasticsearch/transport/TransportService.java @@ -61,8 +61,8 @@ public class TransportService extends AbstractLifecycleComponent serverHandlers = ImmutableMap.of(); - final Object serverHandlersMutex = new Object(); + volatile ImmutableMap requestHandlers = ImmutableMap.of(); + final Object requestHandlerMutex = new Object(); final ConcurrentMapLong clientHandlers = ConcurrentCollections.newConcurrentMapLongWithAggressiveConcurrency(); @@ -324,25 +324,25 @@ public class TransportService extends AbstractLifecycleComponent void registerRequestHandler(String action, Class request, String executor, TransportRequestHandler handler) { + registerRequestHandler(action, request, executor, false, handler); + } + + /** + * Registers a new request handler + * @param action The action the request handler is associated with + * @param request The request class that will be used to constrcut new instances for streaming + * @param executor The executor the request handling will be executed on + * @param forceExecution Force execution on the executor queue and never reject it + * @param handler The handler itself that implements the request handling + */ + public void registerRequestHandler(String action, Class request, String executor, boolean forceExecution, TransportRequestHandler handler) { + synchronized (requestHandlerMutex) { + RequestHandlerRegistry reg = new RequestHandlerRegistry<>(action, request, handler, executor, forceExecution); + RequestHandlerRegistry replaced = requestHandlers.get(reg.getAction()); + requestHandlers = MapBuilder.newMapBuilder(requestHandlers).put(reg.getAction(), reg).immutableMap(); + if (replaced != null) { + logger.warn("registered two transport handlers for action {}, handlers: {}, {}", reg.getAction(), reg.getHandler(), replaced.getHandler()); } } } public void removeHandler(String action) { - synchronized (serverHandlersMutex) { - serverHandlers = MapBuilder.newMapBuilder(serverHandlers).remove(action).immutableMap(); + synchronized (requestHandlerMutex) { + requestHandlers = MapBuilder.newMapBuilder(requestHandlers).remove(action).immutableMap(); } } - protected TransportRequestHandler getHandler(String action) { - return serverHandlers.get(action); + protected RequestHandlerRegistry getRequestHandler(String action) { + return requestHandlers.get(action); } protected class Adapter implements TransportServiceAdapter { @@ -460,8 +480,8 @@ public class TransportService extends AbstractLifecycleComponent implem transportServiceAdapter.onRequestReceived(requestId, action); final LocalTransportChannel transportChannel = new LocalTransportChannel(this, transportServiceAdapter, sourceTransport, action, requestId, version); try { - final TransportRequestHandler handler = transportServiceAdapter.handler(action); - if (handler == null) { + final RequestHandlerRegistry reg = transportServiceAdapter.getRequestHandler(action); + if (reg == null) { throw new ActionNotFoundTransportException("Action [" + action + "] not found"); } - final TransportRequest request = handler.newInstance(); + final TransportRequest request = reg.newRequest(); request.remoteAddress(sourceTransport.boundAddress.publishAddress()); request.readFrom(stream); - if (ThreadPool.Names.SAME.equals(handler.executor())) { + if (ThreadPool.Names.SAME.equals(reg.getExecutor())) { //noinspection unchecked - handler.messageReceived(request, transportChannel); + reg.getHandler().messageReceived(request, transportChannel); } else { - threadPool.executor(handler.executor()).execute(new AbstractRunnable() { + threadPool.executor(reg.getExecutor()).execute(new AbstractRunnable() { @Override protected void doRun() throws Exception { //noinspection unchecked - handler.messageReceived(request, transportChannel); + reg.getHandler().messageReceived(request, transportChannel); } @Override public boolean isForceExecution() { - return handler.isForceExecution(); + return reg.isForceExecution(); } @Override diff --git a/src/main/java/org/elasticsearch/transport/netty/MessageChannelHandler.java b/src/main/java/org/elasticsearch/transport/netty/MessageChannelHandler.java index 426030aef2a..0201829fe08 100644 --- a/src/main/java/org/elasticsearch/transport/netty/MessageChannelHandler.java +++ b/src/main/java/org/elasticsearch/transport/netty/MessageChannelHandler.java @@ -209,18 +209,18 @@ public class MessageChannelHandler extends SimpleChannelUpstreamHandler { transportServiceAdapter.onRequestReceived(requestId, action); final NettyTransportChannel transportChannel = new NettyTransportChannel(transport, transportServiceAdapter, action, channel, requestId, version, profileName); try { - final TransportRequestHandler handler = transportServiceAdapter.handler(action); - if (handler == null) { + final RequestHandlerRegistry reg = transportServiceAdapter.getRequestHandler(action); + if (reg == null) { throw new ActionNotFoundTransportException(action); } - final TransportRequest request = handler.newInstance(); + final TransportRequest request = reg.newRequest(); request.remoteAddress(new InetSocketTransportAddress((InetSocketAddress) channel.getRemoteAddress())); request.readFrom(buffer); - if (ThreadPool.Names.SAME.equals(handler.executor())) { + if (ThreadPool.Names.SAME.equals(reg.getExecutor())) { //noinspection unchecked - handler.messageReceived(request, transportChannel); + reg.getHandler().messageReceived(request, transportChannel); } else { - threadPool.executor(handler.executor()).execute(new RequestHandler(handler, request, transportChannel, action)); + threadPool.executor(reg.getExecutor()).execute(new RequestHandler(reg, request, transportChannel)); } } catch (Throwable e) { try { @@ -260,27 +260,25 @@ public class MessageChannelHandler extends SimpleChannelUpstreamHandler { } class RequestHandler extends AbstractRunnable { - private final TransportRequestHandler handler; + private final RequestHandlerRegistry reg; private final TransportRequest request; private final NettyTransportChannel transportChannel; - private final String action; - public RequestHandler(TransportRequestHandler handler, TransportRequest request, NettyTransportChannel transportChannel, String action) { - this.handler = handler; + public RequestHandler(RequestHandlerRegistry reg, TransportRequest request, NettyTransportChannel transportChannel) { + this.reg = reg; this.request = request; this.transportChannel = transportChannel; - this.action = action; } @SuppressWarnings({"unchecked"}) @Override protected void doRun() throws Exception { - handler.messageReceived(request, transportChannel); + reg.getHandler().messageReceived(request, transportChannel); } @Override public boolean isForceExecution() { - return handler.isForceExecution(); + return reg.isForceExecution(); } @Override @@ -290,7 +288,7 @@ public class MessageChannelHandler extends SimpleChannelUpstreamHandler { try { transportChannel.sendResponse(e); } catch (Throwable e1) { - logger.warn("Failed to send error message back to client for action [" + action + "]", e1); + logger.warn("Failed to send error message back to client for action [" + reg.getAction() + "]", e1); logger.warn("Actual Exception", e); } } diff --git a/src/test/java/org/elasticsearch/action/IndicesRequestTests.java b/src/test/java/org/elasticsearch/action/IndicesRequestTests.java index 4cf46150904..90118aab371 100644 --- a/src/test/java/org/elasticsearch/action/IndicesRequestTests.java +++ b/src/test/java/org/elasticsearch/action/IndicesRequestTests.java @@ -914,8 +914,8 @@ public class IndicesRequestTests extends ElasticsearchIntegrationTest { } @Override - public void registerHandler(String action, TransportRequestHandler handler) { - super.registerHandler(action, new InterceptingRequestHandler(action, handler)); + public void registerRequestHandler(String action, Class request, String executor, boolean forceExecution, TransportRequestHandler handler) { + super.registerRequestHandler(action, request, executor, forceExecution, new InterceptingRequestHandler(action, handler)); } private class InterceptingRequestHandler implements TransportRequestHandler { @@ -928,11 +928,6 @@ public class IndicesRequestTests extends ElasticsearchIntegrationTest { this.action = action; } - @Override - public TransportRequest newInstance() { - return requestHandler.newInstance(); - } - @Override public void messageReceived(TransportRequest request, TransportChannel channel) throws Exception { synchronized (InterceptingTransportService.this) { @@ -949,16 +944,6 @@ public class IndicesRequestTests extends ElasticsearchIntegrationTest { } requestHandler.messageReceived(request, channel); } - - @Override - public String executor() { - return requestHandler.executor(); - } - - @Override - public boolean isForceExecution() { - return requestHandler.isForceExecution(); - } } } } diff --git a/src/test/java/org/elasticsearch/action/support/replication/ShardReplicationOperationTests.java b/src/test/java/org/elasticsearch/action/support/replication/ShardReplicationOperationTests.java index efbfdf395f2..9503e053331 100644 --- a/src/test/java/org/elasticsearch/action/support/replication/ShardReplicationOperationTests.java +++ b/src/test/java/org/elasticsearch/action/support/replication/ShardReplicationOperationTests.java @@ -515,17 +515,7 @@ public class ShardReplicationOperationTests extends ElasticsearchTestCase { ThreadPool threadPool) { super(settings, actionName, transportService, clusterService, null, threadPool, new ShardStateAction(settings, clusterService, transportService, null, null), - new ActionFilters(new HashSet())); - } - - @Override - protected Request newRequestInstance() { - return new Request(); - } - - @Override - protected Request newReplicaRequestInstance() { - return new Request(); + new ActionFilters(new HashSet()), Request.class, Request.class, ThreadPool.Names.SAME); } @Override @@ -533,11 +523,6 @@ public class ShardReplicationOperationTests extends ElasticsearchTestCase { return new Response(); } - @Override - protected String executor() { - return ThreadPool.Names.SAME; - } - @Override protected Tuple shardOperationOnPrimary(ClusterState clusterState, PrimaryOperationRequest shardRequest) throws Throwable { boolean executedBefore = shardRequest.request.processedOnPrimary.getAndSet(true); @@ -546,8 +531,8 @@ public class ShardReplicationOperationTests extends ElasticsearchTestCase { } @Override - protected void shardOperationOnReplica(ReplicaOperationRequest shardRequest) { - shardRequest.request.processedOnReplicas.incrementAndGet(); + protected void shardOperationOnReplica(ShardId shardId, Request request) { + request.processedOnReplicas.incrementAndGet(); } @Override diff --git a/src/test/java/org/elasticsearch/benchmark/transport/BenchmarkNettyLargeMessages.java b/src/test/java/org/elasticsearch/benchmark/transport/BenchmarkNettyLargeMessages.java index 2abd71a7662..5a127c44a60 100644 --- a/src/test/java/org/elasticsearch/benchmark/transport/BenchmarkNettyLargeMessages.java +++ b/src/test/java/org/elasticsearch/benchmark/transport/BenchmarkNettyLargeMessages.java @@ -73,17 +73,7 @@ public class BenchmarkNettyLargeMessages { transportServiceClient.connectToNode(bigNode); transportServiceClient.connectToNode(smallNode); - transportServiceServer.registerHandler("benchmark", new BaseTransportRequestHandler() { - @Override - public BenchmarkMessageRequest newInstance() { - return new BenchmarkMessageRequest(); - } - - @Override - public String executor() { - return ThreadPool.Names.GENERIC; - } - + transportServiceServer.registerRequestHandler("benchmark", BenchmarkMessageRequest.class, ThreadPool.Names.GENERIC, new TransportRequestHandler() { @Override public void messageReceived(BenchmarkMessageRequest request, TransportChannel channel) throws Exception { channel.sendResponse(new BenchmarkMessageResponse(request)); diff --git a/src/test/java/org/elasticsearch/benchmark/transport/TransportBenchmark.java b/src/test/java/org/elasticsearch/benchmark/transport/TransportBenchmark.java index be3717b65d3..4fb24db7f91 100644 --- a/src/test/java/org/elasticsearch/benchmark/transport/TransportBenchmark.java +++ b/src/test/java/org/elasticsearch/benchmark/transport/TransportBenchmark.java @@ -80,17 +80,7 @@ public class TransportBenchmark { final DiscoveryNode node = new DiscoveryNode("server", serverTransportService.boundAddress().publishAddress(), Version.CURRENT); - serverTransportService.registerHandler("benchmark", new BaseTransportRequestHandler() { - @Override - public BenchmarkMessageRequest newInstance() { - return new BenchmarkMessageRequest(); - } - - @Override - public String executor() { - return executor; - } - + serverTransportService.registerRequestHandler("benchmark", BenchmarkMessageRequest.class, executor, new TransportRequestHandler() { @Override public void messageReceived(BenchmarkMessageRequest request, TransportChannel channel) throws Exception { channel.sendResponse(new BenchmarkMessageResponse(request)); diff --git a/src/test/java/org/elasticsearch/test/transport/MockTransportService.java b/src/test/java/org/elasticsearch/test/transport/MockTransportService.java index cfb7284f749..d7cc1ed1ca1 100644 --- a/src/test/java/org/elasticsearch/test/transport/MockTransportService.java +++ b/src/test/java/org/elasticsearch/test/transport/MockTransportService.java @@ -228,10 +228,10 @@ public class MockTransportService extends TransportService { } // poor mans request cloning... - TransportRequestHandler handler = MockTransportService.this.getHandler(action); + RequestHandlerRegistry reg = MockTransportService.this.getRequestHandler(action); BytesStreamOutput bStream = new BytesStreamOutput(); request.writeTo(bStream); - final TransportRequest clonedRequest = handler.newInstance(); + final TransportRequest clonedRequest = reg.newRequest(); clonedRequest.readFrom(new BytesStreamInput(bStream.bytes())); threadPool.schedule(delay, ThreadPool.Names.GENERIC, new AbstractRunnable() { diff --git a/src/test/java/org/elasticsearch/transport/AbstractSimpleTransportTests.java b/src/test/java/org/elasticsearch/transport/AbstractSimpleTransportTests.java index 38ef0285179..09bdd79c70a 100644 --- a/src/test/java/org/elasticsearch/transport/AbstractSimpleTransportTests.java +++ b/src/test/java/org/elasticsearch/transport/AbstractSimpleTransportTests.java @@ -125,17 +125,7 @@ public abstract class AbstractSimpleTransportTests extends ElasticsearchTestCase @Test public void testHelloWorld() { - serviceA.registerHandler("sayHello", new BaseTransportRequestHandler() { - @Override - public StringMessageRequest newInstance() { - return new StringMessageRequest(); - } - - @Override - public String executor() { - return ThreadPool.Names.GENERIC; - } - + serviceA.registerRequestHandler("sayHello", StringMessageRequest.class, ThreadPool.Names.GENERIC, new TransportRequestHandler() { @Override public void messageReceived(StringMessageRequest request, TransportChannel channel) { assertThat("moshe", equalTo(request.message)); @@ -221,17 +211,7 @@ public abstract class AbstractSimpleTransportTests extends ElasticsearchTestCase serviceA.disconnectFromNode(nodeA); } final AtomicReference exception = new AtomicReference<>(); - serviceA.registerHandler("localNode", new BaseTransportRequestHandler() { - @Override - public StringMessageRequest newInstance() { - return new StringMessageRequest(); - } - - @Override - public String executor() { - return ThreadPool.Names.GENERIC; - } - + serviceA.registerRequestHandler("localNode", StringMessageRequest.class, ThreadPool.Names.GENERIC, new TransportRequestHandler() { @Override public void messageReceived(StringMessageRequest request, TransportChannel channel) { try { @@ -273,17 +253,7 @@ public abstract class AbstractSimpleTransportTests extends ElasticsearchTestCase @Test public void testVoidMessageCompressed() { - serviceA.registerHandler("sayHello", new BaseTransportRequestHandler() { - @Override - public TransportRequest.Empty newInstance() { - return TransportRequest.Empty.INSTANCE; - } - - @Override - public String executor() { - return ThreadPool.Names.GENERIC; - } - + serviceA.registerRequestHandler("sayHello", TransportRequest.Empty.class, ThreadPool.Names.GENERIC, new TransportRequestHandler() { @Override public void messageReceived(TransportRequest.Empty request, TransportChannel channel) { try { @@ -330,17 +300,7 @@ public abstract class AbstractSimpleTransportTests extends ElasticsearchTestCase @Test public void testHelloWorldCompressed() { - serviceA.registerHandler("sayHello", new BaseTransportRequestHandler() { - @Override - public StringMessageRequest newInstance() { - return new StringMessageRequest(); - } - - @Override - public String executor() { - return ThreadPool.Names.GENERIC; - } - + serviceA.registerRequestHandler("sayHello", StringMessageRequest.class, ThreadPool.Names.GENERIC, new TransportRequestHandler() { @Override public void messageReceived(StringMessageRequest request, TransportChannel channel) { assertThat("moshe", equalTo(request.message)); @@ -389,17 +349,7 @@ public abstract class AbstractSimpleTransportTests extends ElasticsearchTestCase @Test public void testErrorMessage() { - serviceA.registerHandler("sayHelloException", new BaseTransportRequestHandler() { - @Override - public StringMessageRequest newInstance() { - return new StringMessageRequest(); - } - - @Override - public String executor() { - return ThreadPool.Names.GENERIC; - } - + serviceA.registerRequestHandler("sayHelloException", StringMessageRequest.class, ThreadPool.Names.GENERIC, new TransportRequestHandler() { @Override public void messageReceived(StringMessageRequest request, TransportChannel channel) throws Exception { assertThat("moshe", equalTo(request.message)); @@ -463,20 +413,9 @@ public abstract class AbstractSimpleTransportTests extends ElasticsearchTestCase public void testNotifyOnShutdown() throws Exception { final CountDownLatch latch2 = new CountDownLatch(1); - serviceA.registerHandler("foobar", new BaseTransportRequestHandler() { - @Override - public StringMessageRequest newInstance() { - return new StringMessageRequest(); - } - - @Override - public String executor() { - return ThreadPool.Names.GENERIC; - } - + serviceA.registerRequestHandler("foobar", StringMessageRequest.class, ThreadPool.Names.GENERIC, new TransportRequestHandler() { @Override public void messageReceived(StringMessageRequest request, TransportChannel channel) { - try { latch2.await(); logger.info("Stop ServiceB now"); @@ -500,17 +439,7 @@ public abstract class AbstractSimpleTransportTests extends ElasticsearchTestCase @Test public void testTimeoutSendExceptionWithNeverSendingBackResponse() throws Exception { - serviceA.registerHandler("sayHelloTimeoutNoResponse", new BaseTransportRequestHandler() { - @Override - public StringMessageRequest newInstance() { - return new StringMessageRequest(); - } - - @Override - public String executor() { - return ThreadPool.Names.GENERIC; - } - + serviceA.registerRequestHandler("sayHelloTimeoutNoResponse", StringMessageRequest.class, ThreadPool.Names.GENERIC, new TransportRequestHandler() { @Override public void messageReceived(StringMessageRequest request, TransportChannel channel) { assertThat("moshe", equalTo(request.message)); @@ -559,17 +488,7 @@ public abstract class AbstractSimpleTransportTests extends ElasticsearchTestCase @Test public void testTimeoutSendExceptionWithDelayedResponse() throws Exception { - serviceA.registerHandler("sayHelloTimeoutDelayedResponse", new BaseTransportRequestHandler() { - @Override - public StringMessageRequest newInstance() { - return new StringMessageRequest(); - } - - @Override - public String executor() { - return ThreadPool.Names.GENERIC; - } - + serviceA.registerRequestHandler("sayHelloTimeoutDelayedResponse", StringMessageRequest.class, ThreadPool.Names.GENERIC, new TransportRequestHandler() { @Override public void messageReceived(StringMessageRequest request, TransportChannel channel) { TimeValue sleep = TimeValue.parseTimeValue(request.message, null); @@ -658,29 +577,14 @@ public abstract class AbstractSimpleTransportTests extends ElasticsearchTestCase @Test @TestLogging(value = "test. transport.tracer:TRACE") public void testTracerLog() throws InterruptedException { - TransportRequestHandler handler = new BaseTransportRequestHandler() { - @Override - public StringMessageRequest newInstance() { - return new StringMessageRequest(""); - } - + TransportRequestHandler handler = new TransportRequestHandler() { @Override public void messageReceived(StringMessageRequest request, TransportChannel channel) throws Exception { channel.sendResponse(new StringMessageResponse("")); } - - @Override - public String executor() { - return ThreadPool.Names.SAME; - } }; - TransportRequestHandler handlerWithError = new BaseTransportRequestHandler() { - @Override - public StringMessageRequest newInstance() { - return new StringMessageRequest(""); - } - + TransportRequestHandler handlerWithError = new TransportRequestHandler() { @Override public void messageReceived(StringMessageRequest request, TransportChannel channel) throws Exception { if (request.timeout() > 0) { @@ -689,11 +593,6 @@ public abstract class AbstractSimpleTransportTests extends ElasticsearchTestCase channel.sendResponse(new RuntimeException("")); } - - @Override - public String executor() { - return ThreadPool.Names.SAME; - } }; final Semaphore requestCompleted = new Semaphore(0); @@ -720,10 +619,10 @@ public abstract class AbstractSimpleTransportTests extends ElasticsearchTestCase } }; - serviceA.registerHandler("test", handler); - serviceA.registerHandler("testError", handlerWithError); - serviceB.registerHandler("test", handler); - serviceB.registerHandler("testError", handlerWithError); + serviceA.registerRequestHandler("test", StringMessageRequest.class, ThreadPool.Names.SAME, handler); + serviceA.registerRequestHandler("testError", StringMessageRequest.class, ThreadPool.Names.SAME, handlerWithError); + serviceB.registerRequestHandler("test", StringMessageRequest.class, ThreadPool.Names.SAME, handler); + serviceB.registerRequestHandler("testError", StringMessageRequest.class, ThreadPool.Names.SAME, handlerWithError); final Tracer tracer = new Tracer(); serviceA.addTracer(tracer); @@ -983,12 +882,7 @@ public abstract class AbstractSimpleTransportTests extends ElasticsearchTestCase @Test public void testVersion_from0to1() throws Exception { - serviceB.registerHandler("/version", new BaseTransportRequestHandler() { - @Override - public Version1Request newInstance() { - return new Version1Request(); - } - + serviceB.registerRequestHandler("/version", Version1Request.class, ThreadPool.Names.SAME, new TransportRequestHandler() { @Override public void messageReceived(Version1Request request, TransportChannel channel) throws Exception { assertThat(request.value1, equalTo(1)); @@ -998,11 +892,6 @@ public abstract class AbstractSimpleTransportTests extends ElasticsearchTestCase response.value2 = 2; channel.sendResponse(response); } - - @Override - public String executor() { - return ThreadPool.Names.SAME; - } }); Version0Request version0Request = new Version0Request(); @@ -1035,12 +924,7 @@ public abstract class AbstractSimpleTransportTests extends ElasticsearchTestCase @Test public void testVersion_from1to0() throws Exception { - serviceA.registerHandler("/version", new BaseTransportRequestHandler() { - @Override - public Version0Request newInstance() { - return new Version0Request(); - } - + serviceA.registerRequestHandler("/version", Version0Request.class, ThreadPool.Names.SAME, new TransportRequestHandler() { @Override public void messageReceived(Version0Request request, TransportChannel channel) throws Exception { assertThat(request.value1, equalTo(1)); @@ -1048,11 +932,6 @@ public abstract class AbstractSimpleTransportTests extends ElasticsearchTestCase response.value1 = 1; channel.sendResponse(response); } - - @Override - public String executor() { - return ThreadPool.Names.SAME; - } }); Version1Request version1Request = new Version1Request(); @@ -1088,12 +967,7 @@ public abstract class AbstractSimpleTransportTests extends ElasticsearchTestCase @Test public void testVersion_from1to1() throws Exception { - serviceB.registerHandler("/version", new BaseTransportRequestHandler() { - @Override - public Version1Request newInstance() { - return new Version1Request(); - } - + serviceB.registerRequestHandler("/version", Version1Request.class, ThreadPool.Names.SAME, new TransportRequestHandler() { @Override public void messageReceived(Version1Request request, TransportChannel channel) throws Exception { assertThat(request.value1, equalTo(1)); @@ -1103,11 +977,6 @@ public abstract class AbstractSimpleTransportTests extends ElasticsearchTestCase response.value2 = 2; channel.sendResponse(response); } - - @Override - public String executor() { - return ThreadPool.Names.SAME; - } }); Version1Request version1Request = new Version1Request(); @@ -1143,12 +1012,7 @@ public abstract class AbstractSimpleTransportTests extends ElasticsearchTestCase @Test public void testVersion_from0to0() throws Exception { - serviceA.registerHandler("/version", new BaseTransportRequestHandler() { - @Override - public Version0Request newInstance() { - return new Version0Request(); - } - + serviceA.registerRequestHandler("/version", Version0Request.class, ThreadPool.Names.SAME, new TransportRequestHandler() { @Override public void messageReceived(Version0Request request, TransportChannel channel) throws Exception { assertThat(request.value1, equalTo(1)); @@ -1156,11 +1020,6 @@ public abstract class AbstractSimpleTransportTests extends ElasticsearchTestCase response.value1 = 1; channel.sendResponse(response); } - - @Override - public String executor() { - return ThreadPool.Names.SAME; - } }); Version0Request version0Request = new Version0Request(); @@ -1193,17 +1052,7 @@ public abstract class AbstractSimpleTransportTests extends ElasticsearchTestCase @Test public void testMockFailToSendNoConnectRule() { - serviceA.registerHandler("sayHello", new BaseTransportRequestHandler() { - @Override - public StringMessageRequest newInstance() { - return new StringMessageRequest(); - } - - @Override - public String executor() { - return ThreadPool.Names.GENERIC; - } - + serviceA.registerRequestHandler("sayHello", StringMessageRequest.class, ThreadPool.Names.GENERIC, new TransportRequestHandler() { @Override public void messageReceived(StringMessageRequest request, TransportChannel channel) throws Exception { assertThat("moshe", equalTo(request.message)); @@ -1262,17 +1111,7 @@ public abstract class AbstractSimpleTransportTests extends ElasticsearchTestCase @Test public void testMockUnresponsiveRule() { - serviceA.registerHandler("sayHello", new BaseTransportRequestHandler() { - @Override - public StringMessageRequest newInstance() { - return new StringMessageRequest(); - } - - @Override - public String executor() { - return ThreadPool.Names.GENERIC; - } - + serviceA.registerRequestHandler("sayHello", StringMessageRequest.class, ThreadPool.Names.GENERIC, new TransportRequestHandler() { @Override public void messageReceived(StringMessageRequest request, TransportChannel channel) throws Exception { assertThat("moshe", equalTo(request.message)); @@ -1335,28 +1174,13 @@ public abstract class AbstractSimpleTransportTests extends ElasticsearchTestCase final CountDownLatch latch = new CountDownLatch(2); final AtomicReference addressA = new AtomicReference<>(); final AtomicReference addressB = new AtomicReference<>(); - serviceB.registerHandler("action1", new TransportRequestHandler() { - @Override - public TestRequest newInstance() { - return new TestRequest(); - } - + serviceB.registerRequestHandler("action1", TestRequest.class, ThreadPool.Names.SAME, new TransportRequestHandler() { @Override public void messageReceived(TestRequest request, TransportChannel channel) throws Exception { addressA.set(request.remoteAddress()); channel.sendResponse(new TestResponse()); latch.countDown(); } - - @Override - public String executor() { - return ThreadPool.Names.SAME; - } - - @Override - public boolean isForceExecution() { - return false; - } }); serviceA.sendRequest(nodeB, "action1", new TestRequest(), new TransportResponseHandler() { @Override diff --git a/src/test/java/org/elasticsearch/transport/ActionNamesTests.java b/src/test/java/org/elasticsearch/transport/ActionNamesTests.java index f1e98801d41..69be9f8fdf2 100644 --- a/src/test/java/org/elasticsearch/transport/ActionNamesTests.java +++ b/src/test/java/org/elasticsearch/transport/ActionNamesTests.java @@ -19,14 +19,6 @@ package org.elasticsearch.transport; -import com.google.common.collect.Lists; -import org.elasticsearch.Version; -import org.elasticsearch.action.admin.indices.get.GetIndexAction; -import org.elasticsearch.action.admin.cluster.repositories.verify.VerifyRepositoryAction; -import org.elasticsearch.action.exists.ExistsAction; -import org.elasticsearch.discovery.zen.ping.unicast.UnicastZenPing; -import org.elasticsearch.search.action.SearchServiceTransportAction; -import org.elasticsearch.repositories.VerifyNodeRepositoryAction; import org.elasticsearch.test.ElasticsearchIntegrationTest; import org.junit.Test; @@ -55,7 +47,7 @@ public class ActionNamesTests extends ElasticsearchIntegrationTest { @SuppressWarnings("unchecked") public void testActionNamesCategories() throws NoSuchFieldException, IllegalAccessException { TransportService transportService = internalCluster().getInstance(TransportService.class); - for (String action : transportService.serverHandlers.keySet()) { + for (String action : transportService.requestHandlers.keySet()) { assertThat("action doesn't belong to known category", action, either(startsWith("indices:admin")).or(startsWith("indices:monitor")) .or(startsWith("indices:data/read")).or(startsWith("indices:data/write")) .or(startsWith("cluster:admin")).or(startsWith("cluster:monitor")) diff --git a/src/test/java/org/elasticsearch/transport/netty/NettyScheduledPingTests.java b/src/test/java/org/elasticsearch/transport/netty/NettyScheduledPingTests.java index 9e323f809ee..8fe32cfc27e 100644 --- a/src/test/java/org/elasticsearch/transport/netty/NettyScheduledPingTests.java +++ b/src/test/java/org/elasticsearch/transport/netty/NettyScheduledPingTests.java @@ -30,8 +30,6 @@ import org.elasticsearch.test.ElasticsearchTestCase; import org.elasticsearch.test.transport.MockTransportService; import org.elasticsearch.threadpool.ThreadPool; import org.elasticsearch.transport.*; -import org.hamcrest.Matchers; -import org.junit.Before; import org.junit.Test; import java.io.IOException; @@ -75,17 +73,7 @@ public class NettyScheduledPingTests extends ElasticsearchTestCase { assertThat(nettyA.scheduledPing.failedPings.count(), equalTo(0l)); assertThat(nettyB.scheduledPing.failedPings.count(), equalTo(0l)); - serviceA.registerHandler("sayHello", new BaseTransportRequestHandler() { - @Override - public TransportRequest.Empty newInstance() { - return TransportRequest.Empty.INSTANCE; - } - - @Override - public String executor() { - return ThreadPool.Names.GENERIC; - } - + serviceA.registerRequestHandler("sayHello", TransportRequest.Empty.class, ThreadPool.Names.GENERIC, new TransportRequestHandler() { @Override public void messageReceived(TransportRequest.Empty request, TransportChannel channel) { try { diff --git a/src/test/java/org/elasticsearch/transport/netty/NettyTransportTests.java b/src/test/java/org/elasticsearch/transport/netty/NettyTransportTests.java index 785aaf40abc..5edc6b0dfa7 100644 --- a/src/test/java/org/elasticsearch/transport/netty/NettyTransportTests.java +++ b/src/test/java/org/elasticsearch/transport/netty/NettyTransportTests.java @@ -34,10 +34,7 @@ import org.elasticsearch.common.util.BigArrays; import org.elasticsearch.common.util.concurrent.AbstractRunnable; import org.elasticsearch.test.ElasticsearchIntegrationTest; import org.elasticsearch.threadpool.ThreadPool; -import org.elasticsearch.transport.ActionNotFoundTransportException; -import org.elasticsearch.transport.TransportModule; -import org.elasticsearch.transport.TransportRequest; -import org.elasticsearch.transport.TransportRequestHandler; +import org.elasticsearch.transport.*; import org.jboss.netty.channel.Channel; import org.jboss.netty.channel.ChannelPipeline; import org.jboss.netty.channel.ChannelPipelineFactory; @@ -115,21 +112,21 @@ public class NettyTransportTests extends ElasticsearchIntegrationTest { final NettyTransportChannel transportChannel = new NettyTransportChannel(transport, transportServiceAdapter, action, channel, requestId, version, name); try { - final TransportRequestHandler handler = transportServiceAdapter.handler(action); - if (handler == null) { + final RequestHandlerRegistry reg = transportServiceAdapter.getRequestHandler(action); + if (reg == null) { throw new ActionNotFoundTransportException(action); } - final TransportRequest request = handler.newInstance(); + final TransportRequest request = reg.newRequest(); request.remoteAddress(new InetSocketTransportAddress((InetSocketAddress) channel.getRemoteAddress())); request.readFrom(buffer); if (request.hasHeader("ERROR")) { throw new ElasticsearchException((String) request.getHeader("ERROR")); } - if (handler.executor() == ThreadPool.Names.SAME) { + if (reg.getExecutor() == ThreadPool.Names.SAME) { //noinspection unchecked - handler.messageReceived(request, transportChannel); + reg.getHandler().messageReceived(request, transportChannel); } else { - threadPool.executor(handler.executor()).execute(new RequestHandler(handler, request, transportChannel, action)); + threadPool.executor(reg.getExecutor()).execute(new RequestHandler(reg, request, transportChannel)); } } catch (Throwable e) { try { @@ -144,27 +141,25 @@ public class NettyTransportTests extends ElasticsearchIntegrationTest { } class RequestHandler extends AbstractRunnable { - private final TransportRequestHandler handler; + private final RequestHandlerRegistry reg; private final TransportRequest request; private final NettyTransportChannel transportChannel; - private final String action; - public RequestHandler(TransportRequestHandler handler, TransportRequest request, NettyTransportChannel transportChannel, String action) { - this.handler = handler; + public RequestHandler(RequestHandlerRegistry reg, TransportRequest request, NettyTransportChannel transportChannel) { + this.reg = reg; this.request = request; this.transportChannel = transportChannel; - this.action = action; } @SuppressWarnings({"unchecked"}) @Override protected void doRun() throws Exception { - handler.messageReceived(request, transportChannel); + reg.getHandler().messageReceived(request, transportChannel); } @Override public boolean isForceExecution() { - return handler.isForceExecution(); + return reg.isForceExecution(); } @Override @@ -174,7 +169,7 @@ public class NettyTransportTests extends ElasticsearchIntegrationTest { try { transportChannel.sendResponse(e); } catch (Throwable e1) { - logger.warn("Failed to send error message back to client for action [" + action + "]", e1); + logger.warn("Failed to send error message back to client for action [" + reg.getAction() + "]", e1); logger.warn("Actual Exception", e); } } } From 209b8cf952226e8b5b099a0978c0f9b3c69e63f1 Mon Sep 17 00:00:00 2001 From: Shay Banon Date: Fri, 24 Apr 2015 15:04:25 +0200 Subject: [PATCH 14/14] TEST: assert we can create an instance of request --- .../java/org/elasticsearch/transport/RequestHandlerRegistry.java | 1 + 1 file changed, 1 insertion(+) diff --git a/src/main/java/org/elasticsearch/transport/RequestHandlerRegistry.java b/src/main/java/org/elasticsearch/transport/RequestHandlerRegistry.java index 422cb6d27b6..24cea195224 100644 --- a/src/main/java/org/elasticsearch/transport/RequestHandlerRegistry.java +++ b/src/main/java/org/elasticsearch/transport/RequestHandlerRegistry.java @@ -43,6 +43,7 @@ public class RequestHandlerRegistry { throw new ElasticsearchIllegalStateException("failed to create constructor (does it have a default constructor?) for request " + request, e); } this.requestConstructor.setAccessible(true); + assert newRequest() != null; this.handler = handler; this.forceExecution = forceExecution; this.executor = executor;