Merge branch 'master' into close-index-api-refactoring

This commit is contained in:
Tanguy Leroux 2019-01-09 09:26:05 +01:00
commit 7f6fe14b66
143 changed files with 2572 additions and 732 deletions

View File

@ -223,6 +223,18 @@ if (project != rootProject) {
integTestClass = 'org.elasticsearch.gradle.test.GradleIntegrationTestCase'
}
testingConventions {
naming.clear()
naming {
Tests {
baseClass 'org.elasticsearch.gradle.test.GradleUnitTestCase'
}
IT {
baseClass 'org.elasticsearch.gradle.test.GradleIntegrationTestCase'
}
}
}
/*
* We alread configure publication and we don't need or want this one that
* comes from the java-gradle-plugin.

View File

@ -78,6 +78,19 @@ public class PluginBuildPlugin extends BuildPlugin {
skipIntegTestInDisguise = true
}
}
project.testingConventions {
naming.clear()
naming {
Tests {
baseClass 'org.apache.lucene.util.LuceneTestCase'
}
IT {
baseClass 'org.elasticsearch.test.ESIntegTestCase'
baseClass 'org.elasticsearch.test.rest.ESRestTestCase'
baseClass 'org.elasticsearch.test.ESSingleNodeTestCase'
}
}
}
createIntegTestTask(project)
createBundleTask(project)
project.configurations.getByName('default').extendsFrom(project.configurations.getByName('runtime'))

View File

@ -91,7 +91,17 @@ class PrecommitTasks {
}
static Task configureTestingConventions(Project project) {
project.getTasks().create("testingConventions", TestingConventionsTasks.class)
TestingConventionsTasks task = project.getTasks().create("testingConventions", TestingConventionsTasks.class)
task.naming {
Tests {
baseClass "org.apache.lucene.util.LuceneTestCase"
}
IT {
baseClass "org.elasticsearch.test.ESIntegTestCase"
baseClass 'org.elasticsearch.test.rest.ESRestTestCase'
}
}
return task
}
private static Task configureJarHell(Project project) {

View File

@ -0,0 +1,99 @@
/*
* 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.gradle.precommit;
import java.io.Serializable;
import java.util.Collection;
import java.util.HashSet;
import java.util.Objects;
import java.util.Set;
import java.util.regex.Pattern;
/**
* Represent rules for tests enforced by the @{link {@link TestingConventionsTasks}}
*
* Rules are identified by name, tests must have this name as a suffix and implement one of the base classes
* and be part of all the specified tasks.
*/
public class TestingConventionRule implements Serializable {
private final String suffix;
private Set<String> baseClasses = new HashSet<>();
private Set<Pattern> taskNames = new HashSet<>();
public TestingConventionRule(String suffix) {
this.suffix = suffix;
}
public String getSuffix() {
return suffix;
}
/**
* Alias for @{link getSuffix} as Gradle requires a name property
*
*/
public String getName() {
return suffix;
}
public void baseClass(String clazz) {
baseClasses.add(clazz);
}
public void setBaseClasses(Collection<String> baseClasses) {
this.baseClasses.clear();
this.baseClasses.addAll(baseClasses);
}
public void taskName(Pattern expression) {
taskNames.add(expression);
}
public void taskName(String expression) {
taskNames.add(Pattern.compile(expression));
}
public void setTaskNames(Collection<Pattern> expressions) {
taskNames.clear();
taskNames.addAll(expressions);
}
public Set<String> getBaseClasses() {
return baseClasses;
}
public Set<Pattern> getTaskNames() {
return taskNames;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
TestingConventionRule that = (TestingConventionRule) o;
return Objects.equals(suffix, that.suffix);
}
@Override
public int hashCode() {
return Objects.hash(suffix);
}
}

View File

@ -18,8 +18,10 @@
*/
package org.elasticsearch.gradle.precommit;
import groovy.lang.Closure;
import org.elasticsearch.gradle.tool.Boilerplate;
import org.gradle.api.DefaultTask;
import org.gradle.api.NamedDomainObjectContainer;
import org.gradle.api.Task;
import org.gradle.api.file.FileCollection;
import org.gradle.api.file.FileTree;
@ -54,50 +56,37 @@ import java.util.stream.Stream;
public class TestingConventionsTasks extends DefaultTask {
private static final String TEST_CLASS_SUFIX = "Tests";
private static final String INTEG_TEST_CLASS_SUFIX = "IT";
private static final String TEST_METHOD_PREFIX = "test";
/**
* Are there tests to execute ? Accounts for @Ignore and @AwaitsFix
*/
private Boolean activeTestsExists;
private Map<String, File> testClassNames;
private final NamedDomainObjectContainer<TestingConventionRule> naming;
public TestingConventionsTasks() {
setDescription("Tests various testing conventions");
// Run only after everything is compiled
Boilerplate.getJavaSourceSets(getProject()).all(sourceSet -> dependsOn(sourceSet.getClassesTaskName()));
naming = getProject().container(TestingConventionRule.class);
}
@Input
public Map<String, Set<File>> classFilesPerTask(FileTree testClassFiles) {
public Map<String, Set<File>> classFilesPerEnabledTask(FileTree testClassFiles) {
Map<String, Set<File>> collector = new HashMap<>();
// RandomizedTestingTask
collector.putAll(
Stream.concat(
getProject().getTasks().withType(getRandomizedTestingTask()).stream(),
// Look at sub-projects too. As sometimes tests are implemented in parent but ran in sub-projects against
// different configurations
getProject().getSubprojects().stream().flatMap(subproject ->
subproject.getTasks().withType(getRandomizedTestingTask()).stream()
)
)
getProject().getTasks().withType(getRandomizedTestingTask()).stream()
.filter(Task::getEnabled)
.collect(Collectors.toMap(
Task::getPath,
task -> testClassFiles.matching(getRandomizedTestingPatternSet(task)).getFiles()
))
)
)
);
// Gradle Test
collector.putAll(
Stream.concat(
getProject().getTasks().withType(Test.class).stream(),
getProject().getSubprojects().stream().flatMap(subproject ->
subproject.getTasks().withType(Test.class).stream()
)
)
getProject().getTasks().withType(Test.class).stream()
.filter(Task::getEnabled)
.collect(Collectors.toMap(
Task::getPath,
@ -119,14 +108,22 @@ public class TestingConventionsTasks extends DefaultTask {
return testClassNames;
}
@Input
public NamedDomainObjectContainer<TestingConventionRule> getNaming() {
return naming;
}
@OutputFile
public File getSuccessMarker() {
return new File(getProject().getBuildDir(), "markers/" + getName());
}
public void naming(Closure<TestingConventionRule> action) {
naming.configure(action);
}
@TaskAction
public void doCheck() throws IOException {
activeTestsExists = false;
final String problems;
try (URLClassLoader isolatedClassLoader = new URLClassLoader(
@ -134,62 +131,83 @@ public class TestingConventionsTasks extends DefaultTask {
)) {
Predicate<Class<?>> isStaticClass = clazz -> Modifier.isStatic(clazz.getModifiers());
Predicate<Class<?>> isPublicClass = clazz -> Modifier.isPublic(clazz.getModifiers());
Predicate<Class<?>> implementsNamingConvention = clazz ->
clazz.getName().endsWith(TEST_CLASS_SUFIX) ||
clazz.getName().endsWith(INTEG_TEST_CLASS_SUFIX);
Predicate<Class<?>> isAbstractClass = clazz -> Modifier.isAbstract(clazz.getModifiers());
Map<File, ? extends Class<?>> classes = getTestClassNames().entrySet().stream()
final Map<File, ? extends Class<?>> classes = getTestClassNames().entrySet().stream()
.collect(Collectors.toMap(
Map.Entry::getValue,
entry -> loadClassWithoutInitializing(entry.getKey(), isolatedClassLoader))
);
FileTree allTestClassFiles = getProject().files(
final FileTree allTestClassFiles = getProject().files(
classes.values().stream()
.filter(isStaticClass.negate())
.filter(isPublicClass)
.filter(implementsNamingConvention)
.filter((Predicate<Class<?>>) this::implementsNamingConvention)
.map(clazz -> testClassNames.get(clazz.getName()))
.collect(Collectors.toList())
).getAsFileTree();
final Map<String, Set<File>> classFilesPerTask = classFilesPerTask(allTestClassFiles);
final Map<String, Set<File>> classFilesPerTask = classFilesPerEnabledTask(allTestClassFiles);
Map<String, Set<Class<?>>> testClassesPerTask = classFilesPerTask.entrySet().stream()
final Map<String, Set<Class<?>>> testClassesPerTask = classFilesPerTask.entrySet().stream()
.collect(
Collectors.toMap(
Map.Entry::getKey,
entry -> entry.getValue().stream()
.map(classes::get)
.filter(implementsNamingConvention)
.filter(this::implementsNamingConvention)
.collect(Collectors.toSet())
)
);
final Map<String, Set<Class<?>>> suffixToBaseClass;
if (classes.isEmpty()) {
// Don't load base classes if we don't have any tests.
// This allows defaults to be configured for projects that don't have any tests
//
suffixToBaseClass = Collections.emptyMap();
} else {
suffixToBaseClass = naming.stream()
.collect(
Collectors.toMap(
TestingConventionRule::getSuffix,
rule -> rule.getBaseClasses().stream()
.map(each -> loadClassWithoutInitializing(each, isolatedClassLoader))
.collect(Collectors.toSet())
));
}
problems = collectProblems(
checkNoneExists(
"Test classes implemented by inner classes will not run",
classes.values().stream()
.filter(isStaticClass)
.filter(implementsNamingConvention.or(this::seemsLikeATest))
.filter(isPublicClass)
.filter(((Predicate<Class<?>>) this::implementsNamingConvention).or(this::seemsLikeATest))
),
checkNoneExists(
"Seem like test classes but don't match naming convention",
classes.values().stream()
.filter(isStaticClass.negate())
.filter(isPublicClass)
.filter(this::seemsLikeATest)
.filter(implementsNamingConvention.negate())
.filter(isAbstractClass.negate())
.filter(this::seemsLikeATest) // TODO when base classes are set, check for classes that extend them
.filter(((Predicate<Class<?>>) this::implementsNamingConvention).negate())
),
// TODO: check for non public classes that seem like tests
// TODO: check for abstract classes that implement the naming conventions
// No empty enabled tasks
collectProblems(
testClassesPerTask.entrySet().stream()
.map( entry ->
.map(entry ->
checkAtLeastOneExists(
"test class in " + entry.getKey(),
"test class included in task " + entry.getKey(),
entry.getValue().stream()
)
)
.collect(Collectors.joining())
.sorted()
.collect(Collectors.joining("\n"))
),
checkNoneExists(
"Test classes are not included in any enabled task (" +
@ -201,25 +219,43 @@ public class TestingConventionsTasks extends DefaultTask {
.anyMatch(fileSet -> fileSet.contains(testFile)) == false
)
.map(classes::get)
),
collectProblems(
suffixToBaseClass.entrySet().stream()
.filter(entry -> entry.getValue().isEmpty() == false)
.map(entry -> {
return checkNoneExists(
"Tests classes with suffix `" + entry.getKey() + "` should extend " +
entry.getValue().stream().map(Class::getName).collect(Collectors.joining(" or ")) +
" but the following classes do not",
classes.values().stream()
.filter(clazz -> clazz.getName().endsWith(entry.getKey()))
.filter(clazz -> entry.getValue().stream()
.anyMatch(test -> test.isAssignableFrom(clazz)) == false)
);
}).sorted()
.collect(Collectors.joining("\n"))
)
// TODO: check that the testing tasks are included in the right task based on the name ( from the rule )
// TODO: check to make sure that the main source set doesn't have classes that match
// the naming convention (just the names, don't load classes)
);
}
if (problems.isEmpty()) {
getLogger().error(problems);
throw new IllegalStateException("Testing conventions are not honored");
} else {
getSuccessMarker().getParentFile().mkdirs();
Files.write(getSuccessMarker().toPath(), new byte[]{}, StandardOpenOption.CREATE);
} else {
getLogger().error(problems);
throw new IllegalStateException("Testing conventions are not honored");
}
}
private String collectProblems(String... problems) {
return Stream.of(problems)
.map(String::trim)
.filter(String::isEmpty)
.map(each -> each + "\n")
.collect(Collectors.joining());
.filter(s -> s.isEmpty() == false)
.collect(Collectors.joining("\n"));
}
@SuppressWarnings("unchecked")
@ -251,10 +287,11 @@ public class TestingConventionsTasks extends DefaultTask {
private String checkNoneExists(String message, Stream<? extends Class<?>> stream) {
String problem = stream
.map(each -> " * " + each.getName())
.sorted()
.collect(Collectors.joining("\n"));
if (problem.isEmpty() == false) {
return message + ":\n" + problem;
} else{
} else {
return "";
}
}
@ -263,28 +300,33 @@ public class TestingConventionsTasks extends DefaultTask {
if (stream.findAny().isPresent()) {
return "";
} else {
return "Expected at least one " + message + ", but found none.\n";
return "Expected at least one " + message + ", but found none.";
}
}
private boolean seemsLikeATest(Class<?> clazz) {
try {
ClassLoader classLoader = clazz.getClassLoader();
Class<?> junitTest;
try {
junitTest = classLoader.loadClass("junit.framework.Test");
} catch (ClassNotFoundException e) {
throw new IllegalStateException("Could not load junit.framework.Test. It's expected that this class is " +
"available on the tests classpath");
}
Class<?> junitTest = loadClassWithoutInitializing("org.junit.Assert", classLoader);
if (junitTest.isAssignableFrom(clazz)) {
getLogger().info("{} is a test because it extends junit.framework.Test", clazz.getName());
getLogger().info("{} is a test because it extends {}", clazz.getName(), junitTest.getName());
return true;
}
Class<?> junitAnnotation = loadClassWithoutInitializing("org.junit.Test", classLoader);
for (Method method : clazz.getMethods()) {
if (matchesTestMethodNamingConvention(clazz, method)) return true;
if (isAnnotated(clazz, method, junitTest)) return true;
if (matchesTestMethodNamingConvention(method)) {
getLogger().info("{} is a test because it has method named '{}'", clazz.getName(), method.getName());
return true;
}
if (isAnnotated(method, junitAnnotation)) {
getLogger().info("{} is a test because it has method '{}' annotated with '{}'",
clazz.getName(), method.getName(), junitAnnotation.getName());
return true;
}
}
return false;
} catch (NoClassDefFoundError e) {
// Include the message to get more info to get more a more useful message when running Gradle without -s
@ -294,23 +336,25 @@ public class TestingConventionsTasks extends DefaultTask {
}
}
private boolean matchesTestMethodNamingConvention(Class<?> clazz, Method method) {
if (method.getName().startsWith(TEST_METHOD_PREFIX) &&
Modifier.isStatic(method.getModifiers()) == false &&
method.getReturnType().equals(Void.class)
) {
getLogger().info("{} is a test because it has method: {}", clazz.getName(), method.getName());
private boolean implementsNamingConvention(Class<?> clazz) {
if (naming.stream()
.map(TestingConventionRule::getSuffix)
.anyMatch(suffix -> clazz.getName().endsWith(suffix))) {
getLogger().info("{} is a test because it matches the naming convention", clazz.getName());
return true;
}
return false;
}
private boolean isAnnotated(Class<?> clazz, Method method, Class<?> annotation) {
private boolean matchesTestMethodNamingConvention(Method method) {
return method.getName().startsWith(TEST_METHOD_PREFIX) &&
Modifier.isStatic(method.getModifiers()) == false
;
}
private boolean isAnnotated(Method method, Class<?> annotation) {
for (Annotation presentAnnotation : method.getAnnotations()) {
if (annotation.isAssignableFrom(presentAnnotation.getClass())) {
getLogger().info("{} is a test because {} is annotated with junit.framework.Test",
clazz.getName(), method.getName()
);
return true;
}
}
@ -380,14 +424,14 @@ public class TestingConventionsTasks extends DefaultTask {
private Class<?> loadClassWithoutInitializing(String name, ClassLoader isolatedClassLoader) {
try {
return Class.forName(name,
return Class.forName(
name,
// Don't initialize the class to save time. Not needed for this test and this doesn't share a VM with any other tests.
false,
isolatedClassLoader
);
} catch (ClassNotFoundException e) {
// Will not get here as the exception will be loaded by isolatedClassLoader
throw new RuntimeException("Failed to load class " + name, e);
throw new RuntimeException("Failed to load class " + name + ". Incorrect test runtime classpath?", e);
}
}

View File

@ -21,6 +21,7 @@ package org.elasticsearch.gradle.testfixtures;
import com.avast.gradle.dockercompose.ComposeExtension;
import com.avast.gradle.dockercompose.DockerComposePlugin;
import org.elasticsearch.gradle.precommit.JarHellTask;
import org.elasticsearch.gradle.precommit.TestingConventionsTasks;
import org.elasticsearch.gradle.precommit.ThirdPartyAuditTask;
import org.gradle.api.DefaultTask;
import org.gradle.api.Plugin;
@ -100,6 +101,10 @@ public class TestFixturesPlugin implements Plugin<Project> {
tasks.withType(getTaskClass("com.carrotsearch.gradle.junit4.RandomizedTestingTask"), task ->
task.setEnabled(false)
);
// conventions are not honored when the tasks are disabled
tasks.withType(TestingConventionsTasks.class, task ->
task.setEnabled(false)
);
return;
}
tasks.withType(getTaskClass("com.carrotsearch.gradle.junit4.RandomizedTestingTask"), task ->

View File

@ -48,24 +48,17 @@
<suppress files="server[/\\]src[/\\]main[/\\]java[/\\]org[/\\]elasticsearch[/\\]monitor[/\\]jvm[/\\]GcNames.java" checks="LineLength" />
<suppress files="server[/\\]src[/\\]main[/\\]java[/\\]org[/\\]elasticsearch[/\\]monitor[/\\]jvm[/\\]HotThreads.java" checks="LineLength" />
<suppress files="server[/\\]src[/\\]main[/\\]java[/\\]org[/\\]elasticsearch[/\\]node[/\\]Node.java" checks="LineLength" />
<suppress files="server[/\\]src[/\\]main[/\\]java[/\\]org[/\\]elasticsearch[/\\]repositories[/\\]RepositoriesService.java" checks="LineLength" />
<suppress files="server[/\\]src[/\\]main[/\\]java[/\\]org[/\\]elasticsearch[/\\]repositories[/\\]Repository.java" checks="LineLength" />
<suppress files="server[/\\]src[/\\]main[/\\]java[/\\]org[/\\]elasticsearch[/\\]repositories[/\\]VerifyNodeRepositoryAction.java" checks="LineLength" />
<suppress files="server[/\\]src[/\\]main[/\\]java[/\\]org[/\\]elasticsearch[/\\]repositories[/\\]blobstore[/\\]BlobStoreRepository.java" checks="LineLength" />
<suppress files="server[/\\]src[/\\]main[/\\]java[/\\]org[/\\]elasticsearch[/\\]repositories[/\\]fs[/\\]FsRepository.java" checks="LineLength" />
<suppress files="server[/\\]src[/\\]main[/\\]java[/\\]org[/\\]elasticsearch[/\\]rest[/\\]action[/\\]cat[/\\]RestIndicesAction.java" checks="LineLength" />
<suppress files="server[/\\]src[/\\]main[/\\]java[/\\]org[/\\]elasticsearch[/\\]rest[/\\]action[/\\]cat[/\\]RestShardsAction.java" checks="LineLength" />
<suppress files="server[/\\]src[/\\]main[/\\]java[/\\]org[/\\]elasticsearch[/\\]rest[/\\]action[/\\]cat[/\\]RestThreadPoolAction.java" checks="LineLength" />
<suppress files="server[/\\]src[/\\]main[/\\]java[/\\]org[/\\]elasticsearch[/\\]threadpool[/\\]ThreadPool.java" checks="LineLength" />
<suppress files="server[/\\]src[/\\]test[/\\]java[/\\]org[/\\]elasticsearch[/\\]aliases[/\\]IndexAliasesIT.java" checks="LineLength" />
<suppress files="server[/\\]src[/\\]test[/\\]java[/\\]org[/\\]elasticsearch[/\\]explain[/\\]ExplainActionIT.java" checks="LineLength" />
<suppress files="server[/\\]src[/\\]test[/\\]java[/\\]org[/\\]elasticsearch[/\\]indexing[/\\]IndexActionIT.java" checks="LineLength" />
<suppress files="server[/\\]src[/\\]test[/\\]java[/\\]org[/\\]elasticsearch[/\\]monitor[/\\]jvm[/\\]JvmGcMonitorServiceSettingsTests.java" checks="LineLength" />
<suppress files="server[/\\]src[/\\]test[/\\]java[/\\]org[/\\]elasticsearch[/\\]rest[/\\]BytesRestResponseTests.java" checks="LineLength" />
<suppress files="server[/\\]src[/\\]test[/\\]java[/\\]org[/\\]elasticsearch[/\\]routing[/\\]AliasRoutingIT.java" checks="LineLength" />
<suppress files="server[/\\]src[/\\]test[/\\]java[/\\]org[/\\]elasticsearch[/\\]routing[/\\]SimpleRoutingIT.java" checks="LineLength" />
<suppress files="server[/\\]src[/\\]test[/\\]java[/\\]org[/\\]elasticsearch[/\\]script[/\\]ScriptServiceTests.java" checks="LineLength" />
<!-- Temporarily contains extra-long lines as examples for tests to be written, see https://github.com/elastic/elasticsearch/issues/34829 -->
<suppress files="modules[/\\]lang-painless[/\\]src[/\\]test[/\\]java[/\\]org[/\\]elasticsearch[/\\]painless[/\\]ContextExampleTests.java" checks="LineLength" />
<suppress files="modules[/\\]lang-painless[/\\]src[/\\]test[/\\]java[/\\]org[/\\]elasticsearch[/\\]painless[/\\]ContextExampleTests.java" checks="LineLength" />
<!-- Gradle requires inputs to be seriablizable -->
<suppress files="buildSrc[/\\]src[/\\]main[/\\]java[/\\]org[/\\]elasticsearch[/\\]gradle[/\\]precommit[/\\]TestingConventionRule.java" checks="RegexpSinglelineJava" />
</suppressions>

View File

@ -1 +1 @@
5.0
5.1

View File

@ -0,0 +1,108 @@
/*
* 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.gradle.precommit;
import org.elasticsearch.gradle.test.GradleIntegrationTestCase;
import org.gradle.testkit.runner.BuildResult;
import org.gradle.testkit.runner.GradleRunner;
import org.junit.Before;
public class TestingConventionsTasksIT extends GradleIntegrationTestCase {
@Before
public void setUp() {
}
public void testInnerClasses() {
GradleRunner runner = getGradleRunner("testingConventions")
.withArguments("clean", ":no_tests_in_inner_classes:testingConventions", "-i", "-s");
BuildResult result = runner.buildAndFail();
assertOutputContains(result.getOutput(),
"Test classes implemented by inner classes will not run:",
" * org.elasticsearch.gradle.testkit.NastyInnerClasses$LooksLikeATestWithoutNamingConvention1",
" * org.elasticsearch.gradle.testkit.NastyInnerClasses$LooksLikeATestWithoutNamingConvention2",
" * org.elasticsearch.gradle.testkit.NastyInnerClasses$LooksLikeATestWithoutNamingConvention3",
" * org.elasticsearch.gradle.testkit.NastyInnerClasses$NamingConventionIT",
" * org.elasticsearch.gradle.testkit.NastyInnerClasses$NamingConventionTests"
);
}
public void testNamingConvention() {
GradleRunner runner = getGradleRunner("testingConventions")
.withArguments("clean", ":incorrect_naming_conventions:testingConventions", "-i", "-s");
BuildResult result = runner.buildAndFail();
assertOutputContains(result.getOutput(),
"Seem like test classes but don't match naming convention:",
" * org.elasticsearch.gradle.testkit.LooksLikeATestWithoutNamingConvention1",
" * org.elasticsearch.gradle.testkit.LooksLikeATestWithoutNamingConvention2",
" * org.elasticsearch.gradle.testkit.LooksLikeATestWithoutNamingConvention3"
);
assertOutputDoesNotContain(result.getOutput(), "LooksLikeTestsButAbstract");
}
public void testNoEmptyTasks() {
GradleRunner runner = getGradleRunner("testingConventions")
.withArguments("clean", ":empty_test_task:testingConventions", "-i", "-s");
BuildResult result = runner.buildAndFail();
assertOutputContains(result.getOutput(),
"Expected at least one test class included in task :empty_test_task:emptyTest, but found none.",
"Expected at least one test class included in task :empty_test_task:emptyTestRandomized, but found none."
);
}
public void testAllTestTasksIncluded() {
GradleRunner runner = getGradleRunner("testingConventions")
.withArguments("clean", ":all_classes_in_tasks:testingConventions", "-i", "-s");
BuildResult result = runner.buildAndFail();
assertOutputContains(result.getOutput(),
"Test classes are not included in any enabled task (:all_classes_in_tasks:emptyTestRandomized):",
" * org.elasticsearch.gradle.testkit.NamingConventionIT",
" * org.elasticsearch.gradle.testkit.NamingConventionTests"
);
}
public void testTaskNotImplementBaseClass() {
GradleRunner runner = getGradleRunner("testingConventions")
.withArguments("clean", ":not_implementing_base:testingConventions", "-i", "-s");
BuildResult result = runner.buildAndFail();
assertOutputContains(result.getOutput(),
"Tests classes with suffix `IT` should extend org.elasticsearch.gradle.testkit.Integration but the following classes do not:",
" * org.elasticsearch.gradle.testkit.NamingConventionIT",
" * org.elasticsearch.gradle.testkit.NamingConventionMissmatchIT",
"Tests classes with suffix `Tests` should extend org.elasticsearch.gradle.testkit.Unit but the following classes do not:",
" * org.elasticsearch.gradle.testkit.NamingConventionMissmatchTests",
" * org.elasticsearch.gradle.testkit.NamingConventionTests"
);
}
public void testValidSetupWithoutBaseClass() {
GradleRunner runner = getGradleRunner("testingConventions")
.withArguments("clean", ":valid_setup_no_base:testingConventions", "-i", "-s");
BuildResult result = runner.build();
assertTaskSuccessful(result, ":valid_setup_no_base:testingConventions");
}
public void testValidSetupWithBaseClass() {
GradleRunner runner = getGradleRunner("testingConventions")
.withArguments("clean", ":valid_setup_with_base:testingConventions", "-i", "-s");
BuildResult result = runner.build();
assertTaskSuccessful(result, ":valid_setup_with_base:testingConventions");
}
}

View File

@ -43,7 +43,7 @@ public abstract class GradleIntegrationTestCase extends GradleUnitTestCase {
if (index.equals(index.stream().sorted().collect(Collectors.toList())) == false) {
fail("Expected the following lines to appear in this order:\n" +
Stream.of(lines).map(line -> " - `" + line + "`").collect(Collectors.joining("\n")) +
"\nBut they did not. Output is:\n\n```" + output + "\n```\n"
"\nTBut the order was different. Output is:\n\n```" + output + "\n```\n"
);
}
}

View File

@ -21,9 +21,11 @@ package org.elasticsearch.gradle.testclusters;
import org.elasticsearch.gradle.test.GradleIntegrationTestCase;
import org.gradle.testkit.runner.BuildResult;
import org.gradle.testkit.runner.GradleRunner;
import org.junit.Ignore;
import java.util.Arrays;
@Ignore // https://github.com/elastic/elasticsearch/issues/37218
public class TestClustersPluginIT extends GradleIntegrationTestCase {
public void testListClusters() {

View File

@ -0,0 +1,23 @@
/*
* 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.gradle.testkit;
public class NamingConventionIT {
}

View File

@ -0,0 +1,23 @@
/*
* 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.gradle.testkit;
public class NamingConventionTests {
}

View File

@ -0,0 +1,86 @@
plugins {
id 'elasticsearch.build' apply false
}
allprojects {
apply plugin: 'java'
apply plugin: 'elasticsearch.build'
repositories {
jcenter()
}
dependencies {
testCompile "junit:junit:4.12"
}
ext.licenseFile = file("$buildDir/dummy/license")
ext.noticeFile = file("$buildDir/dummy/notice")
testingConventions.naming {
// Reset default to no baseClass checks
Tests {
baseClasses = []
}
IT {
baseClasses = []
}
}
unitTest.enabled = false
}
project(':empty_test_task') {
task emptyTest(type: Test) {
}
task emptyTestRandomized(type: com.carrotsearch.gradle.junit4.RandomizedTestingTask) {
}
}
project(':all_classes_in_tasks') {
task emptyTestRandomized(type: com.carrotsearch.gradle.junit4.RandomizedTestingTask) {
include "**/Convention*"
}
}
project(':not_implementing_base') {
testingConventions.naming {
Tests {
baseClass 'org.elasticsearch.gradle.testkit.Unit'
}
IT {
baseClass 'org.elasticsearch.gradle.testkit.Integration'
}
}
task randomized(type: com.carrotsearch.gradle.junit4.RandomizedTestingTask) {
include "**/*IT.class"
include "**/*Tests.class"
}
}
project(':valid_setup_no_base') {
task randomized(type: com.carrotsearch.gradle.junit4.RandomizedTestingTask) {
include "**/*IT.class"
include "**/*Tests.class"
}
}
project (':valid_setup_with_base') {
task randomized(type: com.carrotsearch.gradle.junit4.RandomizedTestingTask) {
include "**/*IT.class"
include "**/*Tests.class"
}
testingConventions.naming {
Tests {
baseClass 'org.elasticsearch.gradle.testkit.Unit'
}
IT {
baseClass 'org.elasticsearch.gradle.testkit.Integration'
}
}
}

View File

@ -0,0 +1,30 @@
/*
* 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.gradle.testkit;
import org.junit.Test;
public class LooksLikeATestWithoutNamingConvention1 {
@Test
public void annotatedTestMethod() {
}
}

View File

@ -0,0 +1,25 @@
/*
* 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.gradle.testkit;
import org.junit.Assert;
public class LooksLikeATestWithoutNamingConvention2 extends Assert {
}

View File

@ -0,0 +1,30 @@
/*
* 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.gradle.testkit;
import org.junit.Assert;
import org.junit.Test;
public class LooksLikeATestWithoutNamingConvention3 {
public void testMethod() {
}
}

View File

@ -0,0 +1,30 @@
/*
* 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.gradle.testkit;
import org.junit.Assert;
import org.junit.Test;
public abstract class LooksLikeTestsButAbstract {
public void testMethod() {
}
}

View File

@ -0,0 +1,23 @@
/*
* 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.gradle.testkit;
public class NamingConventionIT {
}

View File

@ -0,0 +1,23 @@
/*
* 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.gradle.testkit;
public class NamingConventionTests {
}

View File

@ -0,0 +1,64 @@
/*
* 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.gradle.testkit;
import org.junit.Assert;
import org.junit.Test;
public class NastyInnerClasses {
public static class NamingConventionTests {
}
public static class NamingConventionIT {
}
public static class LooksLikeATestWithoutNamingConvention1 {
@Test
public void annotatedTestMethod() {
}
}
public static class LooksLikeATestWithoutNamingConvention2 extends Assert {
}
public static class LooksLikeATestWithoutNamingConvention3 {
public void testMethod() {
}
}
static abstract public class NonOffendingAbstractTests {
}
private static class NonOffendingPrivateTests {
}
static class NonOffendingPackageTests {
}
}

View File

@ -0,0 +1,23 @@
/*
* 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.gradle.testkit;
public abstract class AbstractIT {
}

View File

@ -0,0 +1,23 @@
/*
* 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.gradle.testkit;
public class Integration {
}

View File

@ -0,0 +1,23 @@
/*
* 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.gradle.testkit;
public class NamingConventionIT {
}

View File

@ -0,0 +1,23 @@
/*
* 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.gradle.testkit;
public class NamingConventionMissmatchIT extends Unit {
}

View File

@ -0,0 +1,23 @@
/*
* 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.gradle.testkit;
public class NamingConventionMissmatchTests extends Integration {
}

View File

@ -0,0 +1,23 @@
/*
* 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.gradle.testkit;
public class NamingConventionTests {
}

View File

@ -0,0 +1,23 @@
/*
* 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.gradle.testkit;
public class Unit {
}

View File

@ -0,0 +1,7 @@
include 'no_tests_in_inner_classes'
include 'incorrect_naming_conventions'
include 'empty_test_task'
include 'all_classes_in_tasks'
include 'not_implementing_base'
include 'valid_setup_no_base'
include 'valid_setup_with_base'

View File

@ -0,0 +1,23 @@
/*
* 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.gradle.testkit;
public class NamingConventionIT {
}

View File

@ -0,0 +1,23 @@
/*
* 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.gradle.testkit;
public class NamingConventionTests {
}

View File

@ -0,0 +1,23 @@
/*
* 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.gradle.testkit;
public class Integration {
}

View File

@ -0,0 +1,23 @@
/*
* 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.gradle.testkit;
public class NamingConventionIT extends Integration {
}

View File

@ -0,0 +1,23 @@
/*
* 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.gradle.testkit;
public class NamingConventionTests extends Unit {
}

View File

@ -0,0 +1,23 @@
/*
* 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.gradle.testkit;
public class Unit {
}

View File

@ -24,7 +24,7 @@ import org.apache.http.client.methods.HttpDelete;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.client.methods.HttpPut;
import org.apache.http.entity.ByteArrayEntity;
import org.apache.http.nio.entity.NByteArrayEntity;
import org.apache.lucene.util.BytesRef;
import org.elasticsearch.client.RequestConverters.EndpointBuilder;
import org.elasticsearch.client.ml.CloseJobRequest;
@ -462,7 +462,7 @@ final class MLRequestConverters {
BytesReference content = postDataRequest.getContent();
if (content != null) {
BytesRef source = postDataRequest.getContent().toBytesRef();
HttpEntity byteEntity = new ByteArrayEntity(source.bytes,
HttpEntity byteEntity = new NByteArrayEntity(source.bytes,
source.offset,
source.length,
createContentType(postDataRequest.getXContentType()));
@ -686,7 +686,7 @@ final class MLRequestConverters {
BytesReference sample = findFileStructureRequest.getSample();
BytesRef source = sample.toBytesRef();
HttpEntity byteEntity = new ByteArrayEntity(source.bytes, source.offset, source.length, createContentType(XContentType.JSON));
HttpEntity byteEntity = new NByteArrayEntity(source.bytes, source.offset, source.length, createContentType(XContentType.JSON));
request.setEntity(byteEntity);
return request;
}

View File

@ -25,8 +25,8 @@ import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpHead;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.client.methods.HttpPut;
import org.apache.http.entity.ByteArrayEntity;
import org.apache.http.entity.ContentType;
import org.apache.http.nio.entity.NByteArrayEntity;
import org.apache.lucene.util.BytesRef;
import org.elasticsearch.action.DocWriteRequest;
import org.elasticsearch.action.admin.cluster.health.ClusterHealthRequest;
@ -239,7 +239,7 @@ final class RequestConverters {
content.write(separator);
}
}
request.setEntity(new ByteArrayEntity(content.toByteArray(), 0, content.size(), requestContentType));
request.setEntity(new NByteArrayEntity(content.toByteArray(), 0, content.size(), requestContentType));
return request;
}
@ -322,7 +322,7 @@ final class RequestConverters {
BytesRef source = indexRequest.source().toBytesRef();
ContentType contentType = createContentType(indexRequest.getContentType());
request.setEntity(new ByteArrayEntity(source.bytes, source.offset, source.length, contentType));
request.setEntity(new NByteArrayEntity(source.bytes, source.offset, source.length, contentType));
return request;
}
@ -431,7 +431,7 @@ final class RequestConverters {
XContent xContent = REQUEST_BODY_CONTENT_TYPE.xContent();
byte[] source = MultiSearchRequest.writeMultiLineFormat(multiSearchRequest, xContent);
request.setEntity(new ByteArrayEntity(source, createContentType(xContent.type())));
request.setEntity(new NByteArrayEntity(source, createContentType(xContent.type())));
return request;
}
@ -464,7 +464,7 @@ final class RequestConverters {
XContent xContent = REQUEST_BODY_CONTENT_TYPE.xContent();
byte[] source = MultiSearchTemplateRequest.writeMultiLineFormat(multiSearchTemplateRequest, xContent);
request.setEntity(new ByteArrayEntity(source, createContentType(xContent.type())));
request.setEntity(new NByteArrayEntity(source, createContentType(xContent.type())));
return request;
}
@ -694,7 +694,7 @@ final class RequestConverters {
static HttpEntity createEntity(ToXContent toXContent, XContentType xContentType, ToXContent.Params toXContentParams)
throws IOException {
BytesRef source = XContentHelper.toXContent(toXContent, xContentType, toXContentParams, false).toBytesRef();
return new ByteArrayEntity(source.bytes, source.offset, source.length, createContentType(xContentType));
return new NByteArrayEntity(source.bytes, source.offset, source.length, createContentType(xContentType));
}
static String endpoint(String index, String type, String id) {

View File

@ -23,8 +23,8 @@ import org.apache.http.client.methods.HttpDelete;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.client.methods.HttpPut;
import org.apache.http.entity.ByteArrayEntity;
import org.apache.http.entity.ContentType;
import org.apache.http.nio.entity.NByteArrayEntity;
import org.elasticsearch.client.watcher.AckWatchRequest;
import org.elasticsearch.client.watcher.ActivateWatchRequest;
import org.elasticsearch.client.watcher.DeactivateWatchRequest;
@ -75,7 +75,7 @@ final class WatcherRequestConverters {
}
ContentType contentType = RequestConverters.createContentType(putWatchRequest.xContentType());
BytesReference source = putWatchRequest.getSource();
request.setEntity(new ByteArrayEntity(source.toBytesRef().bytes, 0, source.length(), contentType));
request.setEntity(new NByteArrayEntity(source.toBytesRef().bytes, 0, source.length(), contentType));
return request;
}

View File

@ -30,3 +30,7 @@ org.elasticsearch.common.logging.PrefixLogger
@defaultMessage We can't rely on log4j2 being on the classpath so don't log deprecations!
org.elasticsearch.common.xcontent.LoggingDeprecationHandler
@defaultMessage Use Nonblocking org.apache.http.nio.entity.NByteArrayEntity
org.apache.http.entity.ByteArrayEntity
org.apache.http.entity.StringEntity

View File

@ -875,7 +875,7 @@ public class CrudIT extends ESRestHighLevelClientTestCase {
// test1: create one doc in dest
UpdateByQueryRequest updateByQueryRequest = new UpdateByQueryRequest();
updateByQueryRequest.indices(sourceIndex);
updateByQueryRequest.setQuery(new IdsQueryBuilder().addIds("1").types("_doc"));
updateByQueryRequest.setQuery(new IdsQueryBuilder().addIds("1"));
updateByQueryRequest.setRefresh(true);
BulkByScrollResponse bulkResponse =
execute(updateByQueryRequest, highLevelClient()::updateByQuery, highLevelClient()::updateByQueryAsync);
@ -917,7 +917,7 @@ public class CrudIT extends ESRestHighLevelClientTestCase {
// test update-by-query rethrottling
UpdateByQueryRequest updateByQueryRequest = new UpdateByQueryRequest();
updateByQueryRequest.indices(sourceIndex);
updateByQueryRequest.setQuery(new IdsQueryBuilder().addIds("1").types("_doc"));
updateByQueryRequest.setQuery(new IdsQueryBuilder().addIds("1"));
updateByQueryRequest.setRefresh(true);
// this following settings are supposed to halt reindexing after first document
@ -987,7 +987,7 @@ public class CrudIT extends ESRestHighLevelClientTestCase {
// test1: delete one doc
DeleteByQueryRequest deleteByQueryRequest = new DeleteByQueryRequest();
deleteByQueryRequest.indices(sourceIndex);
deleteByQueryRequest.setQuery(new IdsQueryBuilder().addIds("1").types("_doc"));
deleteByQueryRequest.setQuery(new IdsQueryBuilder().addIds("1"));
deleteByQueryRequest.setRefresh(true);
BulkByScrollResponse bulkResponse =
execute(deleteByQueryRequest, highLevelClient()::deleteByQuery, highLevelClient()::deleteByQueryAsync);
@ -1009,7 +1009,7 @@ public class CrudIT extends ESRestHighLevelClientTestCase {
// test delete-by-query rethrottling
DeleteByQueryRequest deleteByQueryRequest = new DeleteByQueryRequest();
deleteByQueryRequest.indices(sourceIndex);
deleteByQueryRequest.setQuery(new IdsQueryBuilder().addIds("2", "3").types("_doc"));
deleteByQueryRequest.setQuery(new IdsQueryBuilder().addIds("2", "3"));
deleteByQueryRequest.setRefresh(true);
// this following settings are supposed to halt reindexing after first document

View File

@ -24,10 +24,10 @@ import org.apache.http.HttpHost;
import org.apache.http.ProtocolVersion;
import org.apache.http.RequestLine;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.entity.ByteArrayEntity;
import org.apache.http.entity.ContentType;
import org.apache.http.message.BasicRequestLine;
import org.apache.http.message.BasicStatusLine;
import org.apache.http.nio.entity.NByteArrayEntity;
import org.apache.lucene.util.BytesRef;
import org.elasticsearch.Build;
import org.elasticsearch.Version;
@ -166,7 +166,7 @@ public class CustomRestHighLevelClientTests extends ESTestCase {
MainResponse response = new MainResponse(httpHeader.getValue(), Version.CURRENT, ClusterName.DEFAULT, "_na", Build.CURRENT);
BytesRef bytesRef = XContentHelper.toXContent(response, XContentType.JSON, false).toBytesRef();
when(mockResponse.getEntity()).thenReturn(new ByteArrayEntity(bytesRef.bytes, ContentType.APPLICATION_JSON));
when(mockResponse.getEntity()).thenReturn(new NByteArrayEntity(bytesRef.bytes, ContentType.APPLICATION_JSON));
RequestLine requestLine = new BasicRequestLine(HttpGet.METHOD_NAME, ENDPOINT, protocol);
when(mockResponse.getRequestLine()).thenReturn(requestLine);

View File

@ -25,7 +25,7 @@ import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpHead;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.client.methods.HttpPut;
import org.apache.http.entity.ByteArrayEntity;
import org.apache.http.nio.entity.NByteArrayEntity;
import org.apache.http.util.EntityUtils;
import org.elasticsearch.action.DocWriteRequest;
import org.elasticsearch.action.admin.cluster.storedscripts.DeleteStoredScriptRequest;
@ -671,7 +671,7 @@ public class RequestConvertersTests extends ESTestCase {
assertEquals(method, request.getMethod());
HttpEntity entity = request.getEntity();
assertTrue(entity instanceof ByteArrayEntity);
assertTrue(entity instanceof NByteArrayEntity);
assertEquals(indexRequest.getContentType().mediaTypeWithoutParameters(), entity.getContentType().getValue());
try (XContentParser parser = createParser(xContentType.xContent(), entity.getContent())) {
assertEquals(nbFields, parser.map().size());
@ -714,7 +714,7 @@ public class RequestConvertersTests extends ESTestCase {
assertEquals(method, request.getMethod());
HttpEntity entity = request.getEntity();
assertTrue(entity instanceof ByteArrayEntity);
assertTrue(entity instanceof NByteArrayEntity);
assertEquals(indexRequest.getContentType().mediaTypeWithoutParameters(), entity.getContentType().getValue());
try (XContentParser parser = createParser(xContentType.xContent(), entity.getContent())) {
assertEquals(nbFields, parser.map().size());
@ -787,7 +787,7 @@ public class RequestConvertersTests extends ESTestCase {
assertEquals(HttpPost.METHOD_NAME, request.getMethod());
HttpEntity entity = request.getEntity();
assertTrue(entity instanceof ByteArrayEntity);
assertTrue(entity instanceof NByteArrayEntity);
UpdateRequest parsedUpdateRequest = new UpdateRequest();

View File

@ -21,7 +21,7 @@ package org.elasticsearch.client;
import org.apache.http.HttpEntity;
import org.apache.http.entity.ContentType;
import org.apache.http.entity.StringEntity;
import org.apache.http.nio.entity.NStringEntity;
import org.elasticsearch.common.ParseField;
import org.elasticsearch.common.xcontent.NamedXContentRegistry;
import org.elasticsearch.common.xcontent.XContentParser;
@ -51,14 +51,14 @@ public class RestHighLevelClientExtTests extends ESTestCase {
public void testParseEntityCustomResponseSection() throws IOException {
{
HttpEntity jsonEntity = new StringEntity("{\"custom1\":{ \"field\":\"value\"}}", ContentType.APPLICATION_JSON);
HttpEntity jsonEntity = new NStringEntity("{\"custom1\":{ \"field\":\"value\"}}", ContentType.APPLICATION_JSON);
BaseCustomResponseSection customSection = restHighLevelClient.parseEntity(jsonEntity, BaseCustomResponseSection::fromXContent);
assertThat(customSection, instanceOf(CustomResponseSection1.class));
CustomResponseSection1 customResponseSection1 = (CustomResponseSection1) customSection;
assertEquals("value", customResponseSection1.value);
}
{
HttpEntity jsonEntity = new StringEntity("{\"custom2\":{ \"array\": [\"item1\", \"item2\"]}}", ContentType.APPLICATION_JSON);
HttpEntity jsonEntity = new NStringEntity("{\"custom2\":{ \"array\": [\"item1\", \"item2\"]}}", ContentType.APPLICATION_JSON);
BaseCustomResponseSection customSection = restHighLevelClient.parseEntity(jsonEntity, BaseCustomResponseSection::fromXContent);
assertThat(customSection, instanceOf(CustomResponseSection2.class));
CustomResponseSection2 customResponseSection2 = (CustomResponseSection2) customSection;

View File

@ -27,12 +27,11 @@ import org.apache.http.ProtocolVersion;
import org.apache.http.RequestLine;
import org.apache.http.StatusLine;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.entity.ByteArrayEntity;
import org.apache.http.entity.ContentType;
import org.apache.http.entity.StringEntity;
import org.apache.http.message.BasicHttpResponse;
import org.apache.http.message.BasicRequestLine;
import org.apache.http.message.BasicStatusLine;
import org.apache.http.nio.entity.NByteArrayEntity;
import org.apache.http.nio.entity.NStringEntity;
import org.elasticsearch.Build;
import org.elasticsearch.ElasticsearchException;
@ -243,11 +242,11 @@ public class RestHighLevelClientTests extends ESTestCase {
}
{
IllegalStateException ise = expectThrows(IllegalStateException.class,
() -> restHighLevelClient.parseEntity(new StringEntity("", (ContentType) null), null));
() -> restHighLevelClient.parseEntity(new NStringEntity("", (ContentType) null), null));
assertEquals("Elasticsearch didn't return the [Content-Type] header, unable to parse response body", ise.getMessage());
}
{
StringEntity entity = new StringEntity("", ContentType.APPLICATION_SVG_XML);
NStringEntity entity = new NStringEntity("", ContentType.APPLICATION_SVG_XML);
IllegalStateException ise = expectThrows(IllegalStateException.class, () -> restHighLevelClient.parseEntity(entity, null));
assertEquals("Unsupported Content-Type: " + entity.getContentType().getValue(), ise.getMessage());
}
@ -260,9 +259,9 @@ public class RestHighLevelClientTests extends ESTestCase {
assertEquals(XContentParser.Token.END_OBJECT, parser.nextToken());
return value;
};
HttpEntity jsonEntity = new StringEntity("{\"field\":\"value\"}", ContentType.APPLICATION_JSON);
HttpEntity jsonEntity = new NStringEntity("{\"field\":\"value\"}", ContentType.APPLICATION_JSON);
assertEquals("value", restHighLevelClient.parseEntity(jsonEntity, entityParser));
HttpEntity yamlEntity = new StringEntity("---\nfield: value\n", ContentType.create("application/yaml"));
HttpEntity yamlEntity = new NStringEntity("---\nfield: value\n", ContentType.create("application/yaml"));
assertEquals("value", restHighLevelClient.parseEntity(yamlEntity, entityParser));
HttpEntity smileEntity = createBinaryEntity(SmileXContent.contentBuilder(), ContentType.create("application/smile"));
assertEquals("value", restHighLevelClient.parseEntity(smileEntity, entityParser));
@ -276,7 +275,7 @@ public class RestHighLevelClientTests extends ESTestCase {
builder.startObject();
builder.field("field", "value");
builder.endObject();
return new ByteArrayEntity(BytesReference.bytes(builder).toBytesRef().bytes, contentType);
return new NByteArrayEntity(BytesReference.bytes(builder).toBytesRef().bytes, contentType);
}
}
@ -302,7 +301,7 @@ public class RestHighLevelClientTests extends ESTestCase {
{
RestStatus restStatus = randomFrom(RestStatus.values());
HttpResponse httpResponse = new BasicHttpResponse(newStatusLine(restStatus));
httpResponse.setEntity(new StringEntity("{\"error\":\"test error message\",\"status\":" + restStatus.getStatus() + "}",
httpResponse.setEntity(new NStringEntity("{\"error\":\"test error message\",\"status\":" + restStatus.getStatus() + "}",
ContentType.APPLICATION_JSON));
Response response = new Response(REQUEST_LINE, new HttpHost("localhost", 9200), httpResponse);
ResponseException responseException = new ResponseException(response);
@ -314,7 +313,7 @@ public class RestHighLevelClientTests extends ESTestCase {
{
RestStatus restStatus = randomFrom(RestStatus.values());
HttpResponse httpResponse = new BasicHttpResponse(newStatusLine(restStatus));
httpResponse.setEntity(new StringEntity("{\"error\":", ContentType.APPLICATION_JSON));
httpResponse.setEntity(new NStringEntity("{\"error\":", ContentType.APPLICATION_JSON));
Response response = new Response(REQUEST_LINE, new HttpHost("localhost", 9200), httpResponse);
ResponseException responseException = new ResponseException(response);
ElasticsearchException elasticsearchException = restHighLevelClient.parseResponseException(responseException);
@ -326,7 +325,7 @@ public class RestHighLevelClientTests extends ESTestCase {
{
RestStatus restStatus = randomFrom(RestStatus.values());
HttpResponse httpResponse = new BasicHttpResponse(newStatusLine(restStatus));
httpResponse.setEntity(new StringEntity("{\"status\":" + restStatus.getStatus() + "}", ContentType.APPLICATION_JSON));
httpResponse.setEntity(new NStringEntity("{\"status\":" + restStatus.getStatus() + "}", ContentType.APPLICATION_JSON));
Response response = new Response(REQUEST_LINE, new HttpHost("localhost", 9200), httpResponse);
ResponseException responseException = new ResponseException(response);
ElasticsearchException elasticsearchException = restHighLevelClient.parseResponseException(responseException);
@ -378,7 +377,7 @@ public class RestHighLevelClientTests extends ESTestCase {
CheckedFunction<MainRequest, Request, IOException> requestConverter = request -> new Request(HttpGet.METHOD_NAME, "/");
RestStatus restStatus = randomFrom(RestStatus.values());
HttpResponse httpResponse = new BasicHttpResponse(newStatusLine(restStatus));
httpResponse.setEntity(new StringEntity("{\"error\":\"test error message\",\"status\":" + restStatus.getStatus() + "}",
httpResponse.setEntity(new NStringEntity("{\"error\":\"test error message\",\"status\":" + restStatus.getStatus() + "}",
ContentType.APPLICATION_JSON));
Response mockResponse = new Response(REQUEST_LINE, new HttpHost("localhost", 9200), httpResponse);
ResponseException responseException = new ResponseException(mockResponse);
@ -396,7 +395,7 @@ public class RestHighLevelClientTests extends ESTestCase {
CheckedFunction<MainRequest, Request, IOException> requestConverter = request -> new Request(HttpGet.METHOD_NAME, "/");
RestStatus restStatus = randomFrom(RestStatus.values());
HttpResponse httpResponse = new BasicHttpResponse(newStatusLine(restStatus));
httpResponse.setEntity(new StringEntity("{\"error\":", ContentType.APPLICATION_JSON));
httpResponse.setEntity(new NStringEntity("{\"error\":", ContentType.APPLICATION_JSON));
Response mockResponse = new Response(REQUEST_LINE, new HttpHost("localhost", 9200), httpResponse);
ResponseException responseException = new ResponseException(mockResponse);
when(restClient.performRequest(any(Request.class))).thenThrow(responseException);
@ -414,7 +413,7 @@ public class RestHighLevelClientTests extends ESTestCase {
CheckedFunction<MainRequest, Request, IOException> requestConverter = request -> new Request(HttpGet.METHOD_NAME, "/");
RestStatus restStatus = randomFrom(RestStatus.values());
HttpResponse httpResponse = new BasicHttpResponse(newStatusLine(restStatus));
httpResponse.setEntity(new StringEntity("{\"status\":" + restStatus.getStatus() + "}", ContentType.APPLICATION_JSON));
httpResponse.setEntity(new NStringEntity("{\"status\":" + restStatus.getStatus() + "}", ContentType.APPLICATION_JSON));
Response mockResponse = new Response(REQUEST_LINE, new HttpHost("localhost", 9200), httpResponse);
ResponseException responseException = new ResponseException(mockResponse);
when(restClient.performRequest(any(Request.class))).thenThrow(responseException);
@ -458,7 +457,7 @@ public class RestHighLevelClientTests extends ESTestCase {
MainRequest mainRequest = new MainRequest();
CheckedFunction<MainRequest, Request, IOException> requestConverter = request -> new Request(HttpGet.METHOD_NAME, "/");
HttpResponse httpResponse = new BasicHttpResponse(newStatusLine(RestStatus.NOT_FOUND));
httpResponse.setEntity(new StringEntity("{\"error\":\"test error message\",\"status\":404}",
httpResponse.setEntity(new NStringEntity("{\"error\":\"test error message\",\"status\":404}",
ContentType.APPLICATION_JSON));
Response mockResponse = new Response(REQUEST_LINE, new HttpHost("localhost", 9200), httpResponse);
ResponseException responseException = new ResponseException(mockResponse);
@ -528,7 +527,7 @@ public class RestHighLevelClientTests extends ESTestCase {
response -> response.getStatusLine().getStatusCode(), trackingActionListener, Collections.emptySet());
RestStatus restStatus = randomFrom(RestStatus.values());
HttpResponse httpResponse = new BasicHttpResponse(newStatusLine(restStatus));
httpResponse.setEntity(new StringEntity("{\"error\":\"test error message\",\"status\":" + restStatus.getStatus() + "}",
httpResponse.setEntity(new NStringEntity("{\"error\":\"test error message\",\"status\":" + restStatus.getStatus() + "}",
ContentType.APPLICATION_JSON));
Response response = new Response(REQUEST_LINE, new HttpHost("localhost", 9200), httpResponse);
ResponseException responseException = new ResponseException(response);
@ -547,7 +546,7 @@ public class RestHighLevelClientTests extends ESTestCase {
response -> response.getStatusLine().getStatusCode(), trackingActionListener, Collections.emptySet());
RestStatus restStatus = randomFrom(RestStatus.values());
HttpResponse httpResponse = new BasicHttpResponse(newStatusLine(restStatus));
httpResponse.setEntity(new StringEntity("{\"error\":", ContentType.APPLICATION_JSON));
httpResponse.setEntity(new NStringEntity("{\"error\":", ContentType.APPLICATION_JSON));
Response response = new Response(REQUEST_LINE, new HttpHost("localhost", 9200), httpResponse);
ResponseException responseException = new ResponseException(response);
responseListener.onFailure(responseException);
@ -564,7 +563,7 @@ public class RestHighLevelClientTests extends ESTestCase {
response -> response.getStatusLine().getStatusCode(), trackingActionListener, Collections.emptySet());
RestStatus restStatus = randomFrom(RestStatus.values());
HttpResponse httpResponse = new BasicHttpResponse(newStatusLine(restStatus));
httpResponse.setEntity(new StringEntity("{\"status\":" + restStatus.getStatus() + "}", ContentType.APPLICATION_JSON));
httpResponse.setEntity(new NStringEntity("{\"status\":" + restStatus.getStatus() + "}", ContentType.APPLICATION_JSON));
Response response = new Response(REQUEST_LINE, new HttpHost("localhost", 9200), httpResponse);
ResponseException responseException = new ResponseException(response);
responseListener.onFailure(responseException);
@ -614,7 +613,7 @@ public class RestHighLevelClientTests extends ESTestCase {
ResponseListener responseListener = restHighLevelClient.wrapResponseListener(
response -> { throw new IllegalStateException(); }, trackingActionListener, Collections.singleton(404));
HttpResponse httpResponse = new BasicHttpResponse(newStatusLine(RestStatus.NOT_FOUND));
httpResponse.setEntity(new StringEntity("{\"error\":\"test error message\",\"status\":404}",
httpResponse.setEntity(new NStringEntity("{\"error\":\"test error message\",\"status\":404}",
ContentType.APPLICATION_JSON));
Response response = new Response(REQUEST_LINE, new HttpHost("localhost", 9200), httpResponse);
ResponseException responseException = new ResponseException(response);

View File

@ -207,11 +207,10 @@ public class QueryDSLDocumentationTests extends ESTestCase {
// Using pre-indexed shapes
GeoShapeQueryBuilder qb = geoShapeQuery(
"pin.location", // <1>
"DEU", // <2>
"countries"); // <3>
qb.relation(ShapeRelation.WITHIN) // <4>
.indexedShapeIndex("shapes") // <5>
.indexedShapePath("location"); // <6>
"DEU"); // <2>
qb.relation(ShapeRelation.WITHIN) // <3>
.indexedShapeIndex("shapes") // <4>
.indexedShapePath("location"); // <5>
// end::indexed_geo_shape
}
}
@ -236,9 +235,6 @@ public class QueryDSLDocumentationTests extends ESTestCase {
public void testIds() {
// tag::ids
idsQuery("my_type", "type2")
.addIds("1", "4", "100");
idsQuery() // <1>
.addIds("1", "4", "100");
// end::ids

View File

@ -77,6 +77,15 @@ namingConventions {
skipIntegTestInDisguise = true
}
testingConventions {
naming.clear()
naming {
Tests {
baseClass 'org.elasticsearch.client.RestClientTestCase'
}
}
}
thirdPartyAudit.ignoreMissingClasses (
//commons-logging optional dependencies
'org.apache.avalon.framework.logger.Logger',

View File

@ -91,7 +91,7 @@ public class RestClientDocumentation {
// end::rest-client-options-singleton
@SuppressWarnings("unused")
public void testUsage() throws IOException, InterruptedException {
public void usage() throws IOException, InterruptedException {
//tag::rest-client-init
RestClient restClient = RestClient.builder(
@ -291,7 +291,7 @@ public class RestClientDocumentation {
}
@SuppressWarnings("unused")
public void testCommonConfiguration() throws Exception {
public void commonConfiguration() throws Exception {
{
//tag::rest-client-config-timeouts
RestClientBuilder builder = RestClient.builder(

View File

@ -78,6 +78,16 @@ namingConventions {
skipIntegTestInDisguise = true
}
testingConventions {
naming.clear()
naming {
Tests {
baseClass 'org.elasticsearch.client.RestClientTestCase'
}
}
}
dependencyLicenses {
dependencies = project.configurations.runtime.fileCollection {
it.group.startsWith('org.elasticsearch') == false

View File

@ -52,7 +52,7 @@ import java.util.concurrent.TimeUnit;
public class SnifferDocumentation {
@SuppressWarnings("unused")
public void testUsage() throws IOException {
public void usage() throws IOException {
{
//tag::sniffer-init
RestClient restClient = RestClient.builder(

View File

@ -52,3 +52,12 @@ namingConventions {
//we don't have integration tests
skipIntegTestInDisguise = true
}
testingConventions {
naming.clear()
naming {
Tests {
baseClass 'com.carrotsearch.randomizedtesting.RandomizedTest'
}
}
}

View File

@ -38,6 +38,15 @@ namingConventions {
skipIntegTestInDisguise = true
}
testingConventions {
naming.clear()
naming {
Tests {
baseClass 'org.elasticsearch.tools.launchers.LaunchersTestCase'
}
}
}
javadoc.enabled = false
loggerUsageCheck.enabled = false
jarHell.enabled = false

View File

@ -51,7 +51,6 @@ include-tagged::{query-dsl-test}[indexed_geo_shape]
--------------------------------------------------
<1> field
<2> The ID of the document that containing the pre-indexed shape.
<3> Index type where the pre-indexed shape is.
<4> relation
<5> Name of the index where the pre-indexed shape is. Defaults to 'shapes'.
<6> The field specified as path containing the pre-indexed shape. Defaults to 'shape'.
<3> relation
<4> Name of the index where the pre-indexed shape is. Defaults to 'shapes'.
<5> The field specified as path containing the pre-indexed shape. Defaults to 'shape'.

View File

@ -8,4 +8,3 @@ See {ref}/query-dsl-ids-query.html[Ids Query]
--------------------------------------------------
include-tagged::{query-dsl-test}[ids]
--------------------------------------------------
<1> type is optional

View File

@ -31,3 +31,11 @@ instead.
==== `standard` filter has been removed
The `standard` token filter has been removed because it doesn't change anything in the stream.
[float]
==== Deprecated standard_html_strip analyzer
The `standard_html_strip` analyzer has been deprecated, and should be replaced
with a combination of the `standard` tokenizer and `html_strip` char_filter.
Indexes created using this analyzer will still be readable in elasticsearch 7.0,
but it will not be possible to create new indexes using it.

View File

@ -1,10 +1,24 @@
[[recovery]]
=== Indices Recovery
The following _expert_ setting can be set to manage the recovery policy.
<<cat-recovery,Peer recovery>> is the process used to build a new copy of a
shard on a node by copying data from the primary. {es} uses this peer recovery
process to rebuild shard copies that were lost if a node has failed, and uses
the same process when migrating a shard copy between nodes to rebalance the
cluster or to honor any changes to the <<modules-cluster,shard allocation
settings>>.
The following _expert_ setting can be set to manage the resources consumed by
peer recoveries:
`indices.recovery.max_bytes_per_sec`::
Defaults to `40mb`.
Limits the total inbound and outbound peer recovery traffic on each node.
Since this limit applies on each node, but there may be many nodes
performing peer recoveries concurrently, the total amount of peer recovery
traffic within a cluster may be much higher than this limit. If you set
this limit too high then there is a risk that ongoing peer recoveries will
consume an excess of bandwidth (or other resources) which could destabilize
the cluster. Defaults to `40mb`.
This setting can be dynamically updated on a live cluster with the
<<cluster-update-settings,cluster-update-settings>> API:
<<cluster-update-settings,cluster-update-settings>> API.

View File

@ -81,7 +81,7 @@ GET /example/_search
==== Pre-Indexed Shape
The Query also supports using a shape which has already been indexed in
another index and/or index type. This is particularly useful for when
another index. This is particularly useful for when
you have a pre-defined list of shapes which are useful to your
application and you want to reference this using a logical name (for
example 'New Zealand') rather than having to provide their coordinates
@ -90,7 +90,6 @@ each time. In this situation it is only necessary to provide:
* `id` - The ID of the document that containing the pre-indexed shape.
* `index` - Name of the index where the pre-indexed shape is. Defaults
to 'shapes'.
* `type` - Index type where the pre-indexed shape is.
* `path` - The field specified as path containing the pre-indexed shape.
Defaults to 'shape'.
* `routing` - The routing of the shape document if required.
@ -130,7 +129,6 @@ GET /example/_search
"location": {
"indexed_shape": {
"index": "shapes",
"type": "_doc",
"id": "deu",
"path": "location"
}

View File

@ -10,13 +10,9 @@ GET /_search
{
"query": {
"ids" : {
"type" : "_doc",
"values" : ["1", "4", "100"]
}
}
}
--------------------------------------------------
// CONSOLE
The `type` is optional and can be omitted, and can also accept an array
of values. If no type is specified, all types defined in the index mapping are tried.

View File

@ -42,12 +42,10 @@ GET /_search
"like" : [
{
"_index" : "imdb",
"_type" : "movies",
"_id" : "1"
},
{
"_index" : "imdb",
"_type" : "movies",
"_id" : "2"
},
"and potentially some more text here as well"
@ -74,7 +72,6 @@ GET /_search
"like" : [
{
"_index" : "marvel",
"_type" : "quotes",
"doc" : {
"name": {
"first": "Ben",
@ -85,7 +82,6 @@ GET /_search
},
{
"_index" : "marvel",
"_type" : "quotes",
"_id" : "2"
}
],

View File

@ -36,9 +36,6 @@ The terms lookup mechanism supports the following options:
`index`::
The index to fetch the term values from.
`type`::
The type to fetch the term values from.
`id`::
The id of the document to fetch the term values from.
@ -93,7 +90,6 @@ GET /tweets/_search
"terms" : {
"user" : {
"index" : "users",
"type" : "_doc",
"id" : "2",
"path" : "followers"
}

Binary file not shown.

View File

@ -1,6 +1,6 @@
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-5.0-all.zip
distributionUrl=https\://services.gradle.org/distributions/gradle-5.1-all.zip
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
distributionSha256Sum=17847c8e12b2bcfce26a79f425f082c31d4ded822f99a66127eee2d96bf18216
distributionSha256Sum=7b8a8b9cce0406733d2d3fab3874386c530657c73c3f4e9a3837d081e26060d8

View File

@ -66,3 +66,12 @@ jarHell.enabled = false
namingConventions {
testClass = 'junit.framework.TestCase'
}
testingConventions {
naming.clear()
naming {
Tests {
baseClass 'junit.framework.TestCase'
}
}
}

View File

@ -171,6 +171,8 @@ public class CommonAnalysisPlugin extends Plugin implements AnalysisPlugin, Scri
public Map<String, AnalysisProvider<AnalyzerProvider<? extends Analyzer>>> getAnalyzers() {
Map<String, AnalysisProvider<AnalyzerProvider<? extends Analyzer>>> analyzers = new TreeMap<>();
analyzers.put("fingerprint", FingerprintAnalyzerProvider::new);
// TODO remove in 8.0
analyzers.put("standard_html_strip", StandardHtmlStripAnalyzerProvider::new);
analyzers.put("pattern", PatternAnalyzerProvider::new);
analyzers.put("snowball", SnowballAnalyzerProvider::new);
@ -320,6 +322,7 @@ public class CommonAnalysisPlugin extends Plugin implements AnalysisPlugin, Scri
@Override
public List<PreBuiltAnalyzerProviderFactory> getPreBuiltAnalyzerProviderFactories() {
List<PreBuiltAnalyzerProviderFactory> analyzers = new ArrayList<>();
// TODO remove in 8.0
analyzers.add(new PreBuiltAnalyzerProviderFactory("standard_html_strip", CachingStrategy.ELASTICSEARCH,
() -> new StandardHtmlStripAnalyzer(CharArraySet.EMPTY_SET)));
analyzers.add(new PreBuiltAnalyzerProviderFactory("pattern", CachingStrategy.ELASTICSEARCH,

View File

@ -37,7 +37,10 @@ public class StandardHtmlStripAnalyzer extends StopwordAnalyzerBase {
public StandardHtmlStripAnalyzer() {
super(EnglishAnalyzer.ENGLISH_STOP_WORDS_SET);
}
/**
* @deprecated in 6.5, can not create in 7.0, and we remove this in 8.0
*/
@Deprecated
StandardHtmlStripAnalyzer(CharArraySet stopwords) {
super(stopwords);
}

View File

@ -19,7 +19,10 @@
package org.elasticsearch.analysis.common;
import org.apache.logging.log4j.LogManager;
import org.apache.lucene.analysis.CharArraySet;
import org.elasticsearch.Version;
import org.elasticsearch.common.logging.DeprecationLogger;
import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.env.Environment;
import org.elasticsearch.index.IndexSettings;
@ -28,14 +31,29 @@ import org.elasticsearch.index.analysis.Analysis;
public class StandardHtmlStripAnalyzerProvider extends AbstractIndexAnalyzerProvider<StandardHtmlStripAnalyzer> {
private static final DeprecationLogger DEPRECATION_LOGGER =
new DeprecationLogger(LogManager.getLogger(StandardHtmlStripAnalyzerProvider.class));
private final StandardHtmlStripAnalyzer analyzer;
/**
* @deprecated in 6.5, can not create in 7.0, and we remove this in 8.0
*/
@Deprecated
StandardHtmlStripAnalyzerProvider(IndexSettings indexSettings, Environment env, String name, Settings settings) {
super(indexSettings, name, settings);
final CharArraySet defaultStopwords = CharArraySet.EMPTY_SET;
CharArraySet stopWords = Analysis.parseStopWords(env, settings, defaultStopwords);
analyzer = new StandardHtmlStripAnalyzer(stopWords);
analyzer.setVersion(version);
if (indexSettings.getIndexVersionCreated().onOrAfter(Version.V_7_0_0)) {
throw new IllegalArgumentException("[standard_html_strip] analyzer is not supported for new indices, " +
"use a custom analyzer using [standard] tokenizer and [html_strip] char_filter, plus [lowercase] filter");
} else {
DEPRECATION_LOGGER.deprecatedAndMaybeLog("standard_html_strip_deprecation",
"Deprecated analyzer [standard_html_strip] used, " +
"replace it with a custom analyzer using [standard] tokenizer and [html_strip] char_filter, plus [lowercase] filter");
}
}
@Override

View File

@ -19,6 +19,7 @@
package org.elasticsearch.analysis.common;
import org.apache.lucene.analysis.Analyzer;
import org.apache.lucene.analysis.MockTokenizer;
import org.apache.lucene.analysis.Tokenizer;
import org.elasticsearch.Version;
@ -26,6 +27,8 @@ import org.elasticsearch.cluster.metadata.IndexMetaData;
import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.env.Environment;
import org.elasticsearch.index.IndexSettings;
import org.elasticsearch.index.analysis.IndexAnalyzers;
import org.elasticsearch.index.analysis.NamedAnalyzer;
import org.elasticsearch.index.analysis.TokenFilterFactory;
import org.elasticsearch.test.ESTestCase;
import org.elasticsearch.test.IndexSettingsModule;
@ -116,4 +119,47 @@ public class CommonAnalysisPluginTests extends ESTestCase {
assertNotNull(tokenFilterFactory.create(tokenizer));
}
}
/**
* Check that the deprecated analyzer name "standard_html_strip" throws exception for indices created since 7.0.0
*/
public void testStandardHtmlStripAnalyzerDeprecationError() throws IOException {
Settings settings = Settings.builder().put(Environment.PATH_HOME_SETTING.getKey(), createTempDir())
.put(IndexMetaData.SETTING_VERSION_CREATED,
VersionUtils.randomVersionBetween(random(), Version.V_7_0_0, Version.CURRENT))
.put("index.analysis.analyzer.custom_analyzer.type", "standard_html_strip")
.putList("index.analysis.analyzer.custom_analyzer.stopwords", "a", "b")
.build();
IndexSettings idxSettings = IndexSettingsModule.newIndexSettings("index", settings);
CommonAnalysisPlugin commonAnalysisPlugin = new CommonAnalysisPlugin();
IllegalArgumentException ex = expectThrows(IllegalArgumentException.class,
() -> createTestAnalysis(idxSettings, settings, commonAnalysisPlugin));
assertEquals("[standard_html_strip] analyzer is not supported for new indices, " +
"use a custom analyzer using [standard] tokenizer and [html_strip] char_filter, plus [lowercase] filter", ex.getMessage());
}
/**
* Check that the deprecated analyzer name "standard_html_strip" issues a deprecation warning for indices created since 6.5.0 until 7
*/
public void testStandardHtmlStripAnalyzerDeprecationWarning() throws IOException {
Settings settings = Settings.builder().put(Environment.PATH_HOME_SETTING.getKey(), createTempDir())
.put(IndexMetaData.SETTING_VERSION_CREATED,
VersionUtils.randomVersionBetween(random(), Version.V_6_0_0,
VersionUtils.getPreviousVersion(Version.V_7_0_0)))
.put("index.analysis.analyzer.custom_analyzer.type", "standard_html_strip")
.putList("index.analysis.analyzer.custom_analyzer.stopwords", "a", "b")
.build();
IndexSettings idxSettings = IndexSettingsModule.newIndexSettings("index", settings);
try (CommonAnalysisPlugin commonAnalysisPlugin = new CommonAnalysisPlugin()) {
IndexAnalyzers analyzers = createTestAnalysis(idxSettings, settings, commonAnalysisPlugin).indexAnalyzers;
Analyzer analyzer = analyzers.get("custom_analyzer");
assertNotNull(((NamedAnalyzer) analyzer).analyzer());
assertWarnings(
"Deprecated analyzer [standard_html_strip] used, " +
"replace it with a custom analyzer using [standard] tokenizer and [html_strip] char_filter, plus [lowercase] filter");
}
}
}

View File

@ -69,14 +69,15 @@
---
"standard_html_strip":
- skip:
version: " - 6.99.99"
reason: only starting from version 7.x this throws an error
- do:
catch: /\[standard_html_strip\] analyzer is not supported for new indices, use a custom analyzer using \[standard\] tokenizer and \[html_strip\] char_filter, plus \[lowercase\] filter/
indices.analyze:
body:
text: <bold/> <italic/>
analyzer: standard_html_strip
- length: { tokens: 2 }
- match: { tokens.0.token: bold }
- match: { tokens.1.token: italic }
---
"pattern":

View File

@ -537,7 +537,7 @@ public class PercolatorFieldMapperTests extends ESSingleNodeTestCase {
public void testQueryWithRewrite() throws Exception {
addQueryFieldMappings();
client().prepareIndex("remote", "doc", "1").setSource("field", "value").get();
QueryBuilder queryBuilder = termsLookupQuery("field", new TermsLookup("remote", "doc", "1", "field"));
QueryBuilder queryBuilder = termsLookupQuery("field", new TermsLookup("remote", "1", "field"));
ParsedDocument doc = mapperService.documentMapper("doc").parse(new SourceToParse("test", "doc", "1",
BytesReference.bytes(XContentFactory
.jsonBuilder()

View File

@ -41,4 +41,10 @@ integTestCluster {
}
integTestRunner {
systemProperty 'external.address', "${ -> exampleFixture.addressAndPort }"
}
testingConventions.naming {
IT {
baseClass 'org.elasticsearch.test.ESTestCase'
}
}

View File

@ -40,3 +40,13 @@ singleNodeIntegTestCluster {
integTestCluster.dependsOn(singleNodeIntegTestRunner, 'singleNodeIntegTestCluster#stop')
check.dependsOn(integTest)
testingConventions {
naming.clear()
naming {
IT {
baseClass 'org.elasticsearch.smoketest.ESSmokeClientTestCase'
}
}
}

View File

@ -27,3 +27,11 @@ dependencies {
testCompile project(path: ':modules:lang-painless', configuration: 'runtime')
testCompile project(path: ':modules:reindex', configuration: 'runtime')
}
testingConventions {
naming {
IT {
baseClass 'org.elasticsearch.ingest.AbstractScriptTestCase'
}
}
}

View File

@ -217,3 +217,14 @@ dependencyLicenses.enabled = false
dependenciesInfo.enabled = false
thirdPartyAudit.enabled = false
testingConventions {
naming.clear()
// We only have one "special" integration test here to connect to wildfly
naming {
IT {
baseClass 'org.apache.lucene.util.LuceneTestCase'
}
}
}

View File

@ -48,7 +48,7 @@
search:
rest_total_hits_as_int: true
index: test_index
body: {"query" : {"terms" : {"user" : {"index" : "test_index", "type" : "test_type", "id" : "u1", "path" : "followers"}}}}
body: {"query" : {"terms" : {"user" : {"index" : "test_index", "id" : "u1", "path" : "followers"}}}}
- match: { hits.total: 2 }
- do:
@ -56,4 +56,4 @@
search:
rest_total_hits_as_int: true
index: test_index
body: {"query" : {"terms" : {"user" : {"index" : "test_index", "type" : "test_type", "id" : "u2", "path" : "followers"}}}}
body: {"query" : {"terms" : {"user" : {"index" : "test_index", "id" : "u2", "path" : "followers"}}}}

View File

@ -0,0 +1,59 @@
---
"Terms Query with No.of terms exceeding index.max_terms_count should FAIL":
- skip:
version: " - 6.99.99"
reason: index.max_terms_count setting has been added in 7.0.0
- do:
indices.create:
index: test_index
body:
settings:
number_of_shards: 1
index.max_terms_count: 2
mappings:
test_type:
properties:
user:
type: keyword
followers:
type: keyword
- do:
bulk:
refresh: true
body:
- '{"index": {"_index": "test_index", "_type": "test_type", "_id": "u1"}}'
- '{"user": "u1", "followers": ["u2", "u3"]}'
- '{"index": {"_index": "test_index", "_type": "test_type", "_id": "u2"}}'
- '{"user": "u2", "followers": ["u1", "u3", "u4"]}'
- '{"index": {"_index": "test_index", "_type": "test_type", "_id": "u3"}}'
- '{"user": "u3", "followers": ["u1"]}'
- '{"index": {"_index": "test_index", "_type": "test_type", "_id": "u4"}}'
- '{"user": "u4", "followers": ["u3"]}'
- do:
search:
rest_total_hits_as_int: true
index: test_index
body: {"query" : {"terms" : {"user" : ["u1", "u2"]}}}
- match: { hits.total: 2 }
- do:
catch: bad_request
search:
rest_total_hits_as_int: true
index: test_index
body: {"query" : {"terms" : {"user" : ["u1", "u2", "u3"]}}}
- do:
search:
rest_total_hits_as_int: true
index: test_index
body: {"query" : {"terms" : {"user" : {"index" : "test_index", "type" : "test_type", "id" : "u1", "path" : "followers"}}}}
- match: { hits.total: 2 }
- do:
catch: bad_request
search:
rest_total_hits_as_int: true
index: test_index
body: {"query" : {"terms" : {"user" : {"index" : "test_index", "type" : "test_type", "id" : "u2", "path" : "followers"}}}}

View File

@ -161,6 +161,19 @@ forbiddenPatterns {
exclude '**/*.st'
}
testingConventions {
naming.clear()
naming {
Tests {
baseClass "org.apache.lucene.util.LuceneTestCase"
}
IT {
baseClass "org.elasticsearch.test.ESIntegTestCase"
baseClass "org.elasticsearch.test.ESSingleNodeTestCase"
}
}
}
task generateModulesList {
List<String> modules = project(':modules').subprojects.collect { it.name }
modules.add('x-pack')

View File

@ -20,6 +20,7 @@ package org.elasticsearch.index.analysis;
import org.apache.lucene.analysis.Analyzer;
import org.apache.lucene.analysis.core.WhitespaceTokenizer;
import org.elasticsearch.Version;
import org.elasticsearch.core.internal.io.IOUtils;
import org.elasticsearch.ElasticsearchException;
import org.elasticsearch.cluster.metadata.IndexMetaData;
@ -130,7 +131,13 @@ public final class AnalysisRegistry implements Closeable {
throw new ElasticsearchException("failed to load analyzer for name " + key, ex);
}}
);
} else if ("standard_html_strip".equals(analyzer)) {
if (Version.CURRENT.onOrAfter(Version.V_7_0_0)) {
throw new IllegalArgumentException("[standard_html_strip] analyzer is not supported for new indices, " +
"use a custom analyzer using [standard] tokenizer and [html_strip] char_filter, plus [lowercase] filter");
}
}
return analyzerProvider.get(environment, analyzer).get();
}

View File

@ -19,6 +19,7 @@
package org.elasticsearch.index.query;
import org.apache.logging.log4j.LogManager;
import org.apache.lucene.document.LatLonShape;
import org.apache.lucene.geo.Line;
import org.apache.lucene.geo.Polygon;
@ -38,6 +39,7 @@ import org.elasticsearch.action.ActionListener;
import org.elasticsearch.action.get.GetRequest;
import org.elasticsearch.action.get.GetResponse;
import org.elasticsearch.client.Client;
import org.elasticsearch.common.Nullable;
import org.elasticsearch.common.ParseField;
import org.elasticsearch.common.ParsingException;
import org.elasticsearch.common.geo.GeoPoint;
@ -48,6 +50,7 @@ import org.elasticsearch.common.geo.builders.ShapeBuilder;
import org.elasticsearch.common.geo.parsers.ShapeParser;
import org.elasticsearch.common.io.stream.StreamInput;
import org.elasticsearch.common.io.stream.StreamOutput;
import org.elasticsearch.common.logging.DeprecationLogger;
import org.elasticsearch.common.xcontent.LoggingDeprecationHandler;
import org.elasticsearch.common.xcontent.NamedXContentRegistry;
import org.elasticsearch.common.xcontent.XContentBuilder;
@ -66,6 +69,10 @@ import java.util.function.Supplier;
*/
public class GeoShapeQueryBuilder extends AbstractQueryBuilder<GeoShapeQueryBuilder> {
public static final String NAME = "geo_shape";
private static final DeprecationLogger deprecationLogger = new DeprecationLogger(
LogManager.getLogger(GeoShapeQueryBuilder.class));
static final String TYPES_DEPRECATION_MESSAGE = "[types removal] Types are deprecated in [geo_shape] queries. " +
"The type should no longer be specified in the [indexed_shape] section.";
public static final String DEFAULT_SHAPE_INDEX_NAME = "shapes";
public static final String DEFAULT_SHAPE_FIELD_NAME = "shape";
@ -119,6 +126,19 @@ public class GeoShapeQueryBuilder extends AbstractQueryBuilder<GeoShapeQueryBuil
this(fieldName, shape, null, null);
}
/**
* Creates a new GeoShapeQueryBuilder whose Query will be against the given
* field name and will use the Shape found with the given ID
*
* @param fieldName
* Name of the field that will be filtered
* @param indexedShapeId
* ID of the indexed Shape that will be used in the Query
*/
public GeoShapeQueryBuilder(String fieldName, String indexedShapeId) {
this(fieldName, (ShapeBuilder) null, indexedShapeId, null);
}
/**
* Creates a new GeoShapeQueryBuilder whose Query will be against the given
* field name and will use the Shape found with the given ID in the given
@ -130,20 +150,19 @@ public class GeoShapeQueryBuilder extends AbstractQueryBuilder<GeoShapeQueryBuil
* ID of the indexed Shape that will be used in the Query
* @param indexedShapeType
* Index type of the indexed Shapes
* @deprecated use {@link #GeoShapeQueryBuilder(String, String)} instead
*/
@Deprecated
public GeoShapeQueryBuilder(String fieldName, String indexedShapeId, String indexedShapeType) {
this(fieldName, (ShapeBuilder) null, indexedShapeId, indexedShapeType);
}
private GeoShapeQueryBuilder(String fieldName, ShapeBuilder shape, String indexedShapeId, String indexedShapeType) {
private GeoShapeQueryBuilder(String fieldName, ShapeBuilder shape, String indexedShapeId, @Nullable String indexedShapeType) {
if (fieldName == null) {
throw new IllegalArgumentException("fieldName is required");
}
if (shape == null && indexedShapeId == null) {
throw new IllegalArgumentException("either shapeBytes or indexedShapeId and indexedShapeType are required");
}
if (indexedShapeId != null && indexedShapeType == null) {
throw new IllegalArgumentException("indexedShapeType is required if indexedShapeId is specified");
throw new IllegalArgumentException("either shape or indexedShapeId is required");
}
this.fieldName = fieldName;
this.shape = shape;
@ -152,7 +171,8 @@ public class GeoShapeQueryBuilder extends AbstractQueryBuilder<GeoShapeQueryBuil
this.supplier = null;
}
private GeoShapeQueryBuilder(String fieldName, Supplier<ShapeBuilder> supplier, String indexedShapeId, String indexedShapeType) {
private GeoShapeQueryBuilder(String fieldName, Supplier<ShapeBuilder> supplier, String indexedShapeId,
@Nullable String indexedShapeType) {
this.fieldName = fieldName;
this.shape = null;
this.supplier = supplier;
@ -238,7 +258,10 @@ public class GeoShapeQueryBuilder extends AbstractQueryBuilder<GeoShapeQueryBuil
/**
* @return the document type of the indexed Shape that will be used in the
* Query
*
* @deprecated Types are in the process of being removed.
*/
@Deprecated
public String indexedShapeType() {
return indexedShapeType;
}
@ -566,8 +589,10 @@ public class GeoShapeQueryBuilder extends AbstractQueryBuilder<GeoShapeQueryBuil
shape.toXContent(builder, params);
} else {
builder.startObject(INDEXED_SHAPE_FIELD.getPreferredName())
.field(SHAPE_ID_FIELD.getPreferredName(), indexedShapeId)
.field(SHAPE_TYPE_FIELD.getPreferredName(), indexedShapeType);
.field(SHAPE_ID_FIELD.getPreferredName(), indexedShapeId);
if (indexedShapeType != null) {
builder.field(SHAPE_TYPE_FIELD.getPreferredName(), indexedShapeType);
}
if (indexedShapeIndex != null) {
builder.field(SHAPE_INDEX_FIELD.getPreferredName(), indexedShapeIndex);
}
@ -677,6 +702,11 @@ public class GeoShapeQueryBuilder extends AbstractQueryBuilder<GeoShapeQueryBuil
}
}
GeoShapeQueryBuilder builder;
if (type != null) {
deprecationLogger.deprecatedAndMaybeLog(
"geo_share_query_with_types", TYPES_DEPRECATION_MESSAGE);
}
if (shape != null) {
builder = new GeoShapeQueryBuilder(fieldName, shape);
} else {
@ -739,7 +769,12 @@ public class GeoShapeQueryBuilder extends AbstractQueryBuilder<GeoShapeQueryBuil
} else if (this.shape == null) {
SetOnce<ShapeBuilder> supplier = new SetOnce<>();
queryRewriteContext.registerAsyncAction((client, listener) -> {
GetRequest getRequest = new GetRequest(indexedShapeIndex, indexedShapeType, indexedShapeId);
GetRequest getRequest;
if (indexedShapeType == null) {
getRequest = new GetRequest(indexedShapeIndex, indexedShapeId);
} else {
getRequest = new GetRequest(indexedShapeIndex, indexedShapeType, indexedShapeId);
}
getRequest.routing(indexedShapeRouting);
fetch(client, getRequest, indexedShapePath, ActionListener.wrap(builder-> {
supplier.set(builder);

View File

@ -19,6 +19,7 @@
package org.elasticsearch.index.query;
import org.apache.logging.log4j.LogManager;
import org.apache.lucene.search.MatchNoDocsQuery;
import org.apache.lucene.search.Query;
import org.elasticsearch.cluster.metadata.MetaData;
@ -27,6 +28,7 @@ import org.elasticsearch.common.ParsingException;
import org.elasticsearch.common.Strings;
import org.elasticsearch.common.io.stream.StreamInput;
import org.elasticsearch.common.io.stream.StreamOutput;
import org.elasticsearch.common.logging.DeprecationLogger;
import org.elasticsearch.common.lucene.search.Queries;
import org.elasticsearch.common.xcontent.ObjectParser;
import org.elasticsearch.common.xcontent.XContentBuilder;
@ -51,6 +53,9 @@ import static org.elasticsearch.common.xcontent.ObjectParser.fromList;
*/
public class IdsQueryBuilder extends AbstractQueryBuilder<IdsQueryBuilder> {
public static final String NAME = "ids";
private static final DeprecationLogger deprecationLogger = new DeprecationLogger(
LogManager.getLogger(IdsQueryBuilder.class));
static final String TYPES_DEPRECATION_MESSAGE = "[types removal] Types are deprecated in [ids] queries.";
private static final ParseField TYPE_FIELD = new ParseField("type");
private static final ParseField VALUES_FIELD = new ParseField("values");
@ -83,8 +88,10 @@ public class IdsQueryBuilder extends AbstractQueryBuilder<IdsQueryBuilder> {
/**
* Add types to query
*
* @deprecated Types are in the process of being removed, prefer to filter on a field instead.
*/
// TODO: Remove
@Deprecated
public IdsQueryBuilder types(String... types) {
if (types == null) {
throw new IllegalArgumentException("[" + NAME + "] types cannot be null");
@ -95,7 +102,10 @@ public class IdsQueryBuilder extends AbstractQueryBuilder<IdsQueryBuilder> {
/**
* Returns the types used in this query
*
* @deprecated Types are in the process of being removed, prefer to filter on a field instead.
*/
@Deprecated
public String[] types() {
return this.types;
}
@ -121,7 +131,9 @@ public class IdsQueryBuilder extends AbstractQueryBuilder<IdsQueryBuilder> {
@Override
protected void doXContent(XContentBuilder builder, Params params) throws IOException {
builder.startObject(NAME);
builder.array(TYPE_FIELD.getPreferredName(), types);
if (types.length > 0) {
builder.array(TYPE_FIELD.getPreferredName(), types);
}
builder.startArray(VALUES_FIELD.getPreferredName());
for (String value : ids) {
builder.value(value);
@ -142,7 +154,11 @@ public class IdsQueryBuilder extends AbstractQueryBuilder<IdsQueryBuilder> {
public static IdsQueryBuilder fromXContent(XContentParser parser) {
try {
return PARSER.apply(parser, null);
IdsQueryBuilder builder = PARSER.apply(parser, null);
if (builder.types().length > 0) {
deprecationLogger.deprecatedAndMaybeLog("ids_query_with_types", TYPES_DEPRECATION_MESSAGE);
}
return builder;
} catch (IllegalArgumentException e) {
throw new ParsingException(parser.getTokenLocation(), e.getMessage(), e);
}

View File

@ -19,6 +19,7 @@
package org.elasticsearch.index.query;
import org.apache.logging.log4j.LogManager;
import org.apache.lucene.analysis.Analyzer;
import org.apache.lucene.index.Fields;
import org.apache.lucene.search.BooleanClause;
@ -41,6 +42,7 @@ import org.elasticsearch.common.bytes.BytesReference;
import org.elasticsearch.common.io.stream.StreamInput;
import org.elasticsearch.common.io.stream.StreamOutput;
import org.elasticsearch.common.io.stream.Writeable;
import org.elasticsearch.common.logging.DeprecationLogger;
import org.elasticsearch.common.lucene.search.MoreLikeThisQuery;
import org.elasticsearch.common.lucene.search.XMoreLikeThis;
import org.elasticsearch.common.lucene.uid.Versions;
@ -53,6 +55,7 @@ import org.elasticsearch.index.VersionType;
import org.elasticsearch.index.mapper.IdFieldMapper;
import org.elasticsearch.index.mapper.KeywordFieldMapper.KeywordFieldType;
import org.elasticsearch.index.mapper.MappedFieldType;
import org.elasticsearch.index.mapper.MapperService;
import org.elasticsearch.index.mapper.TextFieldMapper.TextFieldType;
import java.io.IOException;
@ -66,6 +69,7 @@ import java.util.Map;
import java.util.Objects;
import java.util.Optional;
import java.util.Set;
import java.util.stream.Stream;
import static org.elasticsearch.common.xcontent.XContentFactory.jsonBuilder;
@ -76,6 +80,11 @@ import static org.elasticsearch.common.xcontent.XContentFactory.jsonBuilder;
*/
public class MoreLikeThisQueryBuilder extends AbstractQueryBuilder<MoreLikeThisQueryBuilder> {
public static final String NAME = "more_like_this";
private static final DeprecationLogger deprecationLogger = new DeprecationLogger(
LogManager.getLogger(MoreLikeThisQueryBuilder.class));
static final String TYPES_DEPRECATION_MESSAGE = "[types removal] Types are deprecated in [more_like_this] " +
"queries. The type should no longer be specified in the [like] and [unlike] sections.";
public static final int DEFAULT_MAX_QUERY_TERMS = XMoreLikeThis.DEFAULT_MAX_QUERY_TERMS;
public static final int DEFAULT_MIN_TERM_FREQ = XMoreLikeThis.DEFAULT_MIN_TERM_FREQ;
@ -182,9 +191,41 @@ public class MoreLikeThisQueryBuilder extends AbstractQueryBuilder<MoreLikeThisQ
* Constructor for a given item / document request
*
* @param index the index where the document is located
* @param type the type of the document
* @param id and its id
*/
public Item(@Nullable String index, String id) {
if (id == null) {
throw new IllegalArgumentException("Item requires id to be non-null");
}
this.index = index;
this.id = id;
}
/**
* Constructor for an artificial document request, that is not present in the index.
*
* @param index the index to be used for parsing the doc
* @param doc the document specification
*/
public Item(@Nullable String index, XContentBuilder doc) {
if (doc == null) {
throw new IllegalArgumentException("Item requires doc to be non-null");
}
this.index = index;
this.doc = BytesReference.bytes(doc);
this.xContentType = doc.contentType();
}
/**
* Constructor for a given item / document request
*
* @param index the index where the document is located
* @param type the type of the document
* @param id and its id
*
* @deprecated Types are in the process of being removed, use {@link Item(String, String)} instead.
*/
@Deprecated
public Item(@Nullable String index, @Nullable String type, String id) {
if (id == null) {
throw new IllegalArgumentException("Item requires id to be non-null");
@ -200,7 +241,10 @@ public class MoreLikeThisQueryBuilder extends AbstractQueryBuilder<MoreLikeThisQ
* @param index the index to be used for parsing the doc
* @param type the type to be used for parsing the doc
* @param doc the document specification
*
* @deprecated Types are in the process of being removed, use {@link Item(String, XContentBuilder)} instead.
*/
@Deprecated
public Item(@Nullable String index, @Nullable String type, XContentBuilder doc) {
if (doc == null) {
throw new IllegalArgumentException("Item requires doc to be non-null");
@ -257,10 +301,18 @@ public class MoreLikeThisQueryBuilder extends AbstractQueryBuilder<MoreLikeThisQ
return this;
}
/**
* @deprecated Types are in the process of being removed.
*/
@Deprecated
public String type() {
return type;
}
/**
* @deprecated Types are in the process of being removed.
*/
@Deprecated
public Item type(String type) {
this.type = type;
return this;
@ -912,9 +964,18 @@ public class MoreLikeThisQueryBuilder extends AbstractQueryBuilder<MoreLikeThisQ
if (stopWords != null) {
moreLikeThisQueryBuilder.stopWords(stopWords);
}
if (moreLikeThisQueryBuilder.isTypeless() == false) {
deprecationLogger.deprecatedAndMaybeLog("more_like_this_query_with_types", TYPES_DEPRECATION_MESSAGE);
}
return moreLikeThisQueryBuilder;
}
public boolean isTypeless() {
return Stream.concat(Arrays.stream(likeItems), Arrays.stream(unlikeItems))
.allMatch(item -> item.type == null);
}
private static void parseLikeField(XContentParser parser, List<String> texts, List<Item> items) throws IOException {
if (parser.currentToken().isValue()) {
texts.add(parser.text());
@ -1065,12 +1126,7 @@ public class MoreLikeThisQueryBuilder extends AbstractQueryBuilder<MoreLikeThisQ
item.index(context.index().getName());
}
if (item.type() == null) {
if (context.queryTypes().size() > 1) {
throw new QueryShardException(context,
"ambiguous type for item with id: " + item.id() + " and index: " + item.index());
} else {
item.type(context.queryTypes().iterator().next());
}
item.type(MapperService.SINGLE_MAPPING_NAME);
}
// default fields if not present but don't override for artificial docs
if ((item.fields() == null || item.fields().length == 0) && item.doc() == null) {

View File

@ -121,7 +121,10 @@ public final class QueryBuilders {
* Constructs a query that will match only specific ids within types.
*
* @param types The mapping/doc type
*
* @deprecated Types are in the process of being removed, use {@link #idsQuery()} instead.
*/
@Deprecated
public static IdsQueryBuilder idsQuery(String... types) {
return new IdsQueryBuilder().types(types);
}
@ -646,6 +649,14 @@ public final class QueryBuilders {
return new GeoShapeQueryBuilder(name, shape);
}
public static GeoShapeQueryBuilder geoShapeQuery(String name, String indexedShapeId) {
return new GeoShapeQueryBuilder(name, indexedShapeId);
}
/**
* @deprecated Types are in the process of being removed, use {@link #geoShapeQuery(String, String)} instead.
*/
@Deprecated
public static GeoShapeQueryBuilder geoShapeQuery(String name, String indexedShapeId, String indexedShapeType) {
return new GeoShapeQueryBuilder(name, indexedShapeId, indexedShapeType);
}
@ -662,6 +673,16 @@ public final class QueryBuilders {
return builder;
}
public static GeoShapeQueryBuilder geoIntersectionQuery(String name, String indexedShapeId) {
GeoShapeQueryBuilder builder = geoShapeQuery(name, indexedShapeId);
builder.relation(ShapeRelation.INTERSECTS);
return builder;
}
/**
* @deprecated Types are in the process of being removed, use {@link #geoIntersectionQuery(String, String)} instead.
*/
@Deprecated
public static GeoShapeQueryBuilder geoIntersectionQuery(String name, String indexedShapeId, String indexedShapeType) {
GeoShapeQueryBuilder builder = geoShapeQuery(name, indexedShapeId, indexedShapeType);
builder.relation(ShapeRelation.INTERSECTS);
@ -680,6 +701,16 @@ public final class QueryBuilders {
return builder;
}
public static GeoShapeQueryBuilder geoWithinQuery(String name, String indexedShapeId) {
GeoShapeQueryBuilder builder = geoShapeQuery(name, indexedShapeId);
builder.relation(ShapeRelation.WITHIN);
return builder;
}
/**
* @deprecated Types are in the process of being removed, use {@link #geoWithinQuery(String, String)} instead.
*/
@Deprecated
public static GeoShapeQueryBuilder geoWithinQuery(String name, String indexedShapeId, String indexedShapeType) {
GeoShapeQueryBuilder builder = geoShapeQuery(name, indexedShapeId, indexedShapeType);
builder.relation(ShapeRelation.WITHIN);
@ -698,6 +729,16 @@ public final class QueryBuilders {
return builder;
}
public static GeoShapeQueryBuilder geoDisjointQuery(String name, String indexedShapeId) {
GeoShapeQueryBuilder builder = geoShapeQuery(name, indexedShapeId);
builder.relation(ShapeRelation.DISJOINT);
return builder;
}
/**
* @deprecated Types are in the process of being removed, use {@link #geoDisjointQuery(String, String)} instead.
*/
@Deprecated
public static GeoShapeQueryBuilder geoDisjointQuery(String name, String indexedShapeId, String indexedShapeType) {
GeoShapeQueryBuilder builder = geoShapeQuery(name, indexedShapeId, indexedShapeType);
builder.relation(ShapeRelation.DISJOINT);

View File

@ -19,6 +19,7 @@
package org.elasticsearch.index.query;
import org.apache.logging.log4j.LogManager;
import org.apache.lucene.search.Query;
import org.apache.lucene.search.TermInSetQuery;
import org.apache.lucene.util.BytesRef;
@ -34,6 +35,7 @@ import org.elasticsearch.common.bytes.BytesReference;
import org.elasticsearch.common.io.stream.BytesStreamOutput;
import org.elasticsearch.common.io.stream.StreamInput;
import org.elasticsearch.common.io.stream.StreamOutput;
import org.elasticsearch.common.logging.DeprecationLogger;
import org.elasticsearch.common.lucene.BytesRefs;
import org.elasticsearch.common.lucene.search.Queries;
import org.elasticsearch.common.xcontent.XContentBuilder;
@ -63,6 +65,11 @@ import java.util.stream.IntStream;
public class TermsQueryBuilder extends AbstractQueryBuilder<TermsQueryBuilder> {
public static final String NAME = "terms";
private static final DeprecationLogger deprecationLogger = new DeprecationLogger(
LogManager.getLogger(TermsQueryBuilder.class));
static final String TYPES_DEPRECATION_MESSAGE = "[types removal] Types are deprecated " +
"in [terms] lookup queries.";
private final String fieldName;
private final List<?> values;
private final TermsLookup termsLookup;
@ -211,6 +218,10 @@ public class TermsQueryBuilder extends AbstractQueryBuilder<TermsQueryBuilder> {
return this.termsLookup;
}
public boolean isTypeless() {
return termsLookup == null || termsLookup.type() == null;
}
private static final Set<Class<? extends Number>> INTEGER_TYPES = new HashSet<>(
Arrays.asList(Byte.class, Short.class, Integer.class, Long.class));
private static final Set<Class<?>> STRING_TYPES = new HashSet<>(
@ -391,9 +402,16 @@ public class TermsQueryBuilder extends AbstractQueryBuilder<TermsQueryBuilder> {
throw new ParsingException(parser.getTokenLocation(), "[" + TermsQueryBuilder.NAME + "] query requires a field name, " +
"followed by array of terms or a document lookup specification");
}
return new TermsQueryBuilder(fieldName, values, termsLookup)
.boost(boost)
.queryName(queryName);
TermsQueryBuilder builder = new TermsQueryBuilder(fieldName, values, termsLookup)
.boost(boost)
.queryName(queryName);
if (builder.isTypeless() == false) {
deprecationLogger.deprecatedAndMaybeLog("terms_lookup_with_types", TYPES_DEPRECATION_MESSAGE);
}
return builder;
}
static List<Object> parseValues(XContentParser parser) throws IOException {
@ -442,8 +460,10 @@ public class TermsQueryBuilder extends AbstractQueryBuilder<TermsQueryBuilder> {
}
private void fetch(TermsLookup termsLookup, Client client, ActionListener<List<Object>> actionListener) {
GetRequest getRequest = new GetRequest(termsLookup.index(), termsLookup.type(), termsLookup.id())
.preference("_local").routing(termsLookup.routing());
GetRequest getRequest = termsLookup.type() == null
? new GetRequest(termsLookup.index(), termsLookup.id())
: new GetRequest(termsLookup.index(), termsLookup.type(), termsLookup.id());
getRequest.preference("_local").routing(termsLookup.routing());
client.get(getRequest, new ActionListener<GetResponse>() {
@Override
public void onResponse(GetResponse getResponse) {

View File

@ -20,11 +20,11 @@
package org.elasticsearch.indices;
import org.elasticsearch.Version;
import org.elasticsearch.common.Nullable;
import org.elasticsearch.common.ParsingException;
import org.elasticsearch.common.io.stream.StreamInput;
import org.elasticsearch.common.io.stream.StreamOutput;
import org.elasticsearch.common.io.stream.Writeable;
import org.elasticsearch.common.xcontent.ToXContent.Params;
import org.elasticsearch.common.xcontent.ToXContentFragment;
import org.elasticsearch.common.xcontent.XContentBuilder;
import org.elasticsearch.common.xcontent.XContentParser;
@ -38,18 +38,24 @@ import java.util.Objects;
*/
public class TermsLookup implements Writeable, ToXContentFragment {
private final String index;
private final String type;
private @Nullable String type;
private final String id;
private final String path;
private String routing;
public TermsLookup(String index, String id, String path) {
this(index, null, id, path);
}
/**
* @deprecated Types are in the process of being removed, use {@link TermsLookup(String, String, String)} instead.
*/
@Deprecated
public TermsLookup(String index, String type, String id, String path) {
if (id == null) {
throw new IllegalArgumentException("[" + TermsQueryBuilder.NAME + "] query lookup element requires specifying the id.");
}
if (type == null) {
throw new IllegalArgumentException("[" + TermsQueryBuilder.NAME + "] query lookup element requires specifying the type.");
}
if (path == null) {
throw new IllegalArgumentException("[" + TermsQueryBuilder.NAME + "] query lookup element requires specifying the path.");
}
@ -66,7 +72,12 @@ public class TermsLookup implements Writeable, ToXContentFragment {
* Read from a stream.
*/
public TermsLookup(StreamInput in) throws IOException {
type = in.readString();
if (in.getVersion().onOrAfter(Version.V_7_0_0)) {
type = in.readOptionalString();
} else {
// Before 7.0, the type parameter was always non-null and serialized as a (non-optional) string.
type = in.readString();
}
id = in.readString();
path = in.readString();
if (in.getVersion().onOrAfter(Version.V_6_0_0_beta1)) {
@ -82,7 +93,16 @@ public class TermsLookup implements Writeable, ToXContentFragment {
@Override
public void writeTo(StreamOutput out) throws IOException {
out.writeString(type);
if (out.getVersion().onOrAfter(Version.V_7_0_0)) {
out.writeOptionalString(type);
} else {
if (type == null) {
throw new IllegalArgumentException("Typeless [terms] lookup queries are not supported if any " +
"node is running a version before 7.0.");
}
out.writeString(type);
}
out.writeString(id);
out.writeString(path);
if (out.getVersion().onOrAfter(Version.V_6_0_0_beta1)) {
@ -97,6 +117,10 @@ public class TermsLookup implements Writeable, ToXContentFragment {
return index;
}
/**
* @deprecated Types are in the process of being removed.
*/
@Deprecated
public String type() {
return type;
}
@ -155,18 +179,28 @@ public class TermsLookup implements Writeable, ToXContentFragment {
+ token + "] after [" + currentFieldName + "]");
}
}
return new TermsLookup(index, type, id, path).routing(routing);
if (type == null) {
return new TermsLookup(index, id, path).routing(routing);
} else {
return new TermsLookup(index, type, id, path).routing(routing);
}
}
@Override
public String toString() {
return index + "/" + type + "/" + id + "/" + path;
if (type == null) {
return index + "/" + id + "/" + path;
} else {
return index + "/" + type + "/" + id + "/" + path;
}
}
@Override
public XContentBuilder toXContent(XContentBuilder builder, Params params) throws IOException {
builder.field("index", index);
builder.field("type", type);
if (type != null) {
builder.field("type", type);
}
builder.field("id", id);
builder.field("path", path);
if (routing != null) {

View File

@ -304,9 +304,7 @@ public class PeerRecoveryTargetService implements IndexEventListener {
@Override
public RecoveryResponse read(StreamInput in) throws IOException {
RecoveryResponse recoveryResponse = new RecoveryResponse();
recoveryResponse.readFrom(in);
return recoveryResponse;
return new RecoveryResponse(in);
}
})
);

View File

@ -24,53 +24,46 @@ import org.elasticsearch.common.io.stream.StreamOutput;
import org.elasticsearch.transport.TransportResponse;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
class RecoveryResponse extends TransportResponse {
final class RecoveryResponse extends TransportResponse {
List<String> phase1FileNames = new ArrayList<>();
List<Long> phase1FileSizes = new ArrayList<>();
List<String> phase1ExistingFileNames = new ArrayList<>();
List<Long> phase1ExistingFileSizes = new ArrayList<>();
long phase1TotalSize;
long phase1ExistingTotalSize;
long phase1Time;
long phase1ThrottlingWaitTime;
final List<String> phase1FileNames;
final List<Long> phase1FileSizes;
final List<String> phase1ExistingFileNames;
final List<Long> phase1ExistingFileSizes;
final long phase1TotalSize;
final long phase1ExistingTotalSize;
final long phase1Time;
final long phase1ThrottlingWaitTime;
long startTime;
final long startTime;
int phase2Operations;
long phase2Time;
final int phase2Operations;
final long phase2Time;
RecoveryResponse() {
RecoveryResponse(List<String> phase1FileNames, List<Long> phase1FileSizes, List<String> phase1ExistingFileNames,
List<Long> phase1ExistingFileSizes, long phase1TotalSize, long phase1ExistingTotalSize,
long phase1Time, long phase1ThrottlingWaitTime, long startTime, int phase2Operations, long phase2Time) {
this.phase1FileNames = phase1FileNames;
this.phase1FileSizes = phase1FileSizes;
this.phase1ExistingFileNames = phase1ExistingFileNames;
this.phase1ExistingFileSizes = phase1ExistingFileSizes;
this.phase1TotalSize = phase1TotalSize;
this.phase1ExistingTotalSize = phase1ExistingTotalSize;
this.phase1Time = phase1Time;
this.phase1ThrottlingWaitTime = phase1ThrottlingWaitTime;
this.startTime = startTime;
this.phase2Operations = phase2Operations;
this.phase2Time = phase2Time;
}
@Override
public void readFrom(StreamInput in) throws IOException {
super.readFrom(in);
int size = in.readVInt();
phase1FileNames = new ArrayList<>(size);
for (int i = 0; i < size; i++) {
phase1FileNames.add(in.readString());
}
size = in.readVInt();
phase1FileSizes = new ArrayList<>(size);
for (int i = 0; i < size; i++) {
phase1FileSizes.add(in.readVLong());
}
size = in.readVInt();
phase1ExistingFileNames = new ArrayList<>(size);
for (int i = 0; i < size; i++) {
phase1ExistingFileNames.add(in.readString());
}
size = in.readVInt();
phase1ExistingFileSizes = new ArrayList<>(size);
for (int i = 0; i < size; i++) {
phase1ExistingFileSizes.add(in.readVLong());
}
RecoveryResponse(StreamInput in) throws IOException {
super(in);
phase1FileNames = in.readList(StreamInput::readString);
phase1FileSizes = in.readList(StreamInput::readVLong);
phase1ExistingFileNames = in.readList(StreamInput::readString);
phase1ExistingFileSizes = in.readList(StreamInput::readVLong);
phase1TotalSize = in.readVLong();
phase1ExistingTotalSize = in.readVLong();
phase1Time = in.readVLong();
@ -83,24 +76,10 @@ class RecoveryResponse extends TransportResponse {
@Override
public void writeTo(StreamOutput out) throws IOException {
super.writeTo(out);
out.writeVInt(phase1FileNames.size());
for (String name : phase1FileNames) {
out.writeString(name);
}
out.writeVInt(phase1FileSizes.size());
for (long size : phase1FileSizes) {
out.writeVLong(size);
}
out.writeVInt(phase1ExistingFileNames.size());
for (String name : phase1ExistingFileNames) {
out.writeString(name);
}
out.writeVInt(phase1ExistingFileSizes.size());
for (long size : phase1ExistingFileSizes) {
out.writeVLong(size);
}
out.writeStringList(phase1FileNames);
out.writeCollection(phase1FileSizes, StreamOutput::writeVLong);
out.writeStringList(phase1ExistingFileNames);
out.writeCollection(phase1ExistingFileSizes, StreamOutput::writeVLong);
out.writeVLong(phase1TotalSize);
out.writeVLong(phase1ExistingTotalSize);
out.writeVLong(phase1Time);

View File

@ -41,6 +41,7 @@ import org.elasticsearch.common.lease.Releasable;
import org.elasticsearch.common.logging.Loggers;
import org.elasticsearch.common.lucene.store.InputStreamIndexInput;
import org.elasticsearch.common.unit.ByteSizeValue;
import org.elasticsearch.common.unit.TimeValue;
import org.elasticsearch.common.util.CancellableThreads;
import org.elasticsearch.common.util.concurrent.FutureUtils;
import org.elasticsearch.core.internal.io.IOUtils;
@ -64,6 +65,7 @@ import java.io.Closeable;
import java.io.IOException;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
import java.util.Locale;
@ -95,8 +97,6 @@ public class RecoverySourceHandler {
private final int chunkSizeInBytes;
private final RecoveryTargetHandler recoveryTarget;
protected final RecoveryResponse response;
private final CancellableThreads cancellableThreads = new CancellableThreads() {
@Override
protected void onCancel(String reason, @Nullable Exception suppressedException) {
@ -122,7 +122,6 @@ public class RecoverySourceHandler {
this.shardId = this.request.shardId().id();
this.logger = Loggers.getLogger(getClass(), request.shardId(), "recover to " + request.targetNode().getName());
this.chunkSizeInBytes = fileChunkSizeInBytes;
this.response = new RecoveryResponse();
}
public StartRecoveryRequest getRequest() {
@ -149,10 +148,12 @@ public class RecoverySourceHandler {
final long requiredSeqNoRangeStart;
final boolean isSequenceNumberBasedRecovery = request.startingSeqNo() != SequenceNumbers.UNASSIGNED_SEQ_NO &&
isTargetSameHistory() && shard.hasCompleteHistoryOperations("peer-recovery", request.startingSeqNo());
final SendFileResult sendFileResult;
if (isSequenceNumberBasedRecovery) {
logger.trace("performing sequence numbers based recovery. starting at [{}]", request.startingSeqNo());
startingSeqNo = request.startingSeqNo();
requiredSeqNoRangeStart = startingSeqNo;
sendFileResult = SendFileResult.EMPTY;
} else {
final Engine.IndexCommitRef phase1Snapshot;
try {
@ -169,7 +170,7 @@ public class RecoverySourceHandler {
startingSeqNo = shard.indexSettings().isSoftDeleteEnabled() ? requiredSeqNoRangeStart : 0;
try {
final int estimateNumOps = shard.estimateNumberOfHistoryOperations("peer-recovery", startingSeqNo);
phase1(phase1Snapshot.getIndexCommit(), () -> estimateNumOps);
sendFileResult = phase1(phase1Snapshot.getIndexCommit(), () -> estimateNumOps);
} catch (final Exception e) {
throw new RecoveryEngineException(shard.shardId(), 1, "phase1 failed", e);
} finally {
@ -184,9 +185,10 @@ public class RecoverySourceHandler {
assert requiredSeqNoRangeStart >= startingSeqNo : "requiredSeqNoRangeStart [" + requiredSeqNoRangeStart + "] is lower than ["
+ startingSeqNo + "]";
final TimeValue prepareEngineTime;
try {
// For a sequence based recovery, the target can keep its local translog
prepareTargetForTranslog(isSequenceNumberBasedRecovery == false,
prepareEngineTime = prepareTargetForTranslog(isSequenceNumberBasedRecovery == false,
shard.estimateNumberOfHistoryOperations("peer-recovery", startingSeqNo));
} catch (final Exception e) {
throw new RecoveryEngineException(shard.shardId(), 1, "prepare target for translog failed", e);
@ -213,21 +215,25 @@ public class RecoverySourceHandler {
logger.trace("snapshot translog for recovery; current size is [{}]",
shard.estimateNumberOfHistoryOperations("peer-recovery", startingSeqNo));
}
final long targetLocalCheckpoint;
final SendSnapshotResult sendSnapshotResult;
try (Translog.Snapshot snapshot = shard.getHistoryOperations("peer-recovery", startingSeqNo)) {
// we have to capture the max_seen_auto_id_timestamp and the max_seq_no_of_updates to make sure that these values
// are at least as high as the corresponding values on the primary when any of these operations were executed on it.
final long maxSeenAutoIdTimestamp = shard.getMaxSeenAutoIdTimestamp();
final long maxSeqNoOfUpdatesOrDeletes = shard.getMaxSeqNoOfUpdatesOrDeletes();
targetLocalCheckpoint = phase2(startingSeqNo, requiredSeqNoRangeStart, endingSeqNo, snapshot,
sendSnapshotResult = phase2(startingSeqNo, requiredSeqNoRangeStart, endingSeqNo, snapshot,
maxSeenAutoIdTimestamp, maxSeqNoOfUpdatesOrDeletes);
} catch (Exception e) {
throw new RecoveryEngineException(shard.shardId(), 2, "phase2 failed", e);
}
finalizeRecovery(targetLocalCheckpoint);
finalizeRecovery(sendSnapshotResult.targetLocalCheckpoint);
final long phase1ThrottlingWaitTime = 0L; // TODO: return the actual throttle time
return new RecoveryResponse(sendFileResult.phase1FileNames, sendFileResult.phase1FileSizes,
sendFileResult.phase1ExistingFileNames, sendFileResult.phase1ExistingFileSizes, sendFileResult.totalSize,
sendFileResult.existingTotalSize, sendFileResult.took.millis(), phase1ThrottlingWaitTime, prepareEngineTime.millis(),
sendSnapshotResult.totalOperations, sendSnapshotResult.tookTime.millis());
}
return response;
}
private boolean isTargetSameHistory() {
@ -276,6 +282,32 @@ public class RecoverySourceHandler {
});
}
static final class SendFileResult {
final List<String> phase1FileNames;
final List<Long> phase1FileSizes;
final long totalSize;
final List<String> phase1ExistingFileNames;
final List<Long> phase1ExistingFileSizes;
final long existingTotalSize;
final TimeValue took;
SendFileResult(List<String> phase1FileNames, List<Long> phase1FileSizes, long totalSize,
List<String> phase1ExistingFileNames, List<Long> phase1ExistingFileSizes, long existingTotalSize, TimeValue took) {
this.phase1FileNames = phase1FileNames;
this.phase1FileSizes = phase1FileSizes;
this.totalSize = totalSize;
this.phase1ExistingFileNames = phase1ExistingFileNames;
this.phase1ExistingFileSizes = phase1ExistingFileSizes;
this.existingTotalSize = existingTotalSize;
this.took = took;
}
static final SendFileResult EMPTY = new SendFileResult(Collections.emptyList(), Collections.emptyList(), 0L,
Collections.emptyList(), Collections.emptyList(), 0L, TimeValue.ZERO);
}
/**
* Perform phase1 of the recovery operations. Once this {@link IndexCommit}
* snapshot has been performed no commit operations (files being fsync'd)
@ -285,12 +317,16 @@ public class RecoverySourceHandler {
* segments that are missing. Only segments that have the same size and
* checksum can be reused
*/
public void phase1(final IndexCommit snapshot, final Supplier<Integer> translogOps) {
public SendFileResult phase1(final IndexCommit snapshot, final Supplier<Integer> translogOps) {
cancellableThreads.checkForCancel();
// Total size of segment files that are recovered
long totalSize = 0;
// Total size of segment files that were able to be re-used
long existingTotalSize = 0;
final List<String> phase1FileNames = new ArrayList<>();
final List<Long> phase1FileSizes = new ArrayList<>();
final List<String> phase1ExistingFileNames = new ArrayList<>();
final List<Long> phase1ExistingFileSizes = new ArrayList<>();
final Store store = shard.store();
store.incRef();
try {
@ -331,8 +367,8 @@ public class RecoverySourceHandler {
} else {
final Store.RecoveryDiff diff = recoverySourceMetadata.recoveryDiff(request.metadataSnapshot());
for (StoreFileMetaData md : diff.identical) {
response.phase1ExistingFileNames.add(md.name());
response.phase1ExistingFileSizes.add(md.length());
phase1ExistingFileNames.add(md.name());
phase1ExistingFileSizes.add(md.length());
existingTotalSize += md.length();
if (logger.isTraceEnabled()) {
logger.trace("recovery [phase1]: not recovering [{}], exist in local store and has checksum [{}]," +
@ -350,20 +386,16 @@ public class RecoverySourceHandler {
} else {
logger.trace("recovery [phase1]: recovering [{}], does not exist in remote", md.name());
}
response.phase1FileNames.add(md.name());
response.phase1FileSizes.add(md.length());
phase1FileNames.add(md.name());
phase1FileSizes.add(md.length());
totalSize += md.length();
}
response.phase1TotalSize = totalSize;
response.phase1ExistingTotalSize = existingTotalSize;
logger.trace("recovery [phase1]: recovering_files [{}] with total_size [{}], reusing_files [{}] with total_size [{}]",
response.phase1FileNames.size(),
new ByteSizeValue(totalSize), response.phase1ExistingFileNames.size(), new ByteSizeValue(existingTotalSize));
cancellableThreads.execute(() ->
recoveryTarget.receiveFileInfo(response.phase1FileNames, response.phase1FileSizes, response.phase1ExistingFileNames,
response.phase1ExistingFileSizes, translogOps.get()));
phase1FileNames.size(), new ByteSizeValue(totalSize),
phase1ExistingFileNames.size(), new ByteSizeValue(existingTotalSize));
cancellableThreads.execute(() -> recoveryTarget.receiveFileInfo(
phase1FileNames, phase1FileSizes, phase1ExistingFileNames, phase1ExistingFileSizes, translogOps.get()));
// How many bytes we've copied since we last called RateLimiter.pause
final Function<StoreFileMetaData, OutputStream> outputStreamFactories =
md -> new BufferedOutputStream(new RecoveryOutputStream(md, translogOps), chunkSizeInBytes);
@ -417,27 +449,27 @@ public class RecoverySourceHandler {
}
}
}
logger.trace("recovery [phase1]: took [{}]", stopWatch.totalTime());
response.phase1Time = stopWatch.totalTime().millis();
final TimeValue took = stopWatch.totalTime();
logger.trace("recovery [phase1]: took [{}]", took);
return new SendFileResult(phase1FileNames, phase1FileSizes, totalSize, phase1ExistingFileNames,
phase1ExistingFileSizes, existingTotalSize, took);
} catch (Exception e) {
throw new RecoverFilesRecoveryException(request.shardId(), response.phase1FileNames.size(), new ByteSizeValue(totalSize), e);
throw new RecoverFilesRecoveryException(request.shardId(), phase1FileNames.size(), new ByteSizeValue(totalSize), e);
} finally {
store.decRef();
}
}
void prepareTargetForTranslog(final boolean fileBasedRecovery, final int totalTranslogOps) throws IOException {
TimeValue prepareTargetForTranslog(final boolean fileBasedRecovery, final int totalTranslogOps) throws IOException {
StopWatch stopWatch = new StopWatch().start();
logger.trace("recovery [phase1]: prepare remote engine for translog");
final long startEngineStart = stopWatch.totalTime().millis();
// Send a request preparing the new shard's translog to receive operations. This ensures the shard engine is started and disables
// garbage collection (not the JVM's GC!) of tombstone deletes.
cancellableThreads.executeIO(() -> recoveryTarget.prepareForTranslogOperations(fileBasedRecovery, totalTranslogOps));
stopWatch.stop();
response.startTime = stopWatch.totalTime().millis() - startEngineStart;
logger.trace("recovery [phase1]: remote engine start took [{}]", stopWatch.totalTime());
final TimeValue tookTime = stopWatch.totalTime();
logger.trace("recovery [phase1]: remote engine start took [{}]", tookTime);
return tookTime;
}
/**
@ -454,102 +486,23 @@ public class RecoverySourceHandler {
* @param snapshot a snapshot of the translog
* @param maxSeenAutoIdTimestamp the max auto_id_timestamp of append-only requests on the primary
* @param maxSeqNoOfUpdatesOrDeletes the max seq_no of updates or deletes on the primary after these operations were executed on it.
* @return the local checkpoint on the target
* @return the send snapshot result
*/
long phase2(final long startingSeqNo, long requiredSeqNoRangeStart, long endingSeqNo, final Translog.Snapshot snapshot,
final long maxSeenAutoIdTimestamp, final long maxSeqNoOfUpdatesOrDeletes)
throws IOException {
SendSnapshotResult phase2(long startingSeqNo, long requiredSeqNoRangeStart, long endingSeqNo, Translog.Snapshot snapshot,
long maxSeenAutoIdTimestamp, long maxSeqNoOfUpdatesOrDeletes) throws IOException {
assert requiredSeqNoRangeStart <= endingSeqNo + 1:
"requiredSeqNoRangeStart " + requiredSeqNoRangeStart + " is larger than endingSeqNo " + endingSeqNo;
assert startingSeqNo <= requiredSeqNoRangeStart :
"startingSeqNo " + startingSeqNo + " is larger than requiredSeqNoRangeStart " + requiredSeqNoRangeStart;
if (shard.state() == IndexShardState.CLOSED) {
throw new IndexShardClosedException(request.shardId());
}
cancellableThreads.checkForCancel();
final StopWatch stopWatch = new StopWatch().start();
logger.trace("recovery [phase2]: sending transaction log operations (seq# from [" + startingSeqNo + "], " +
"required [" + requiredSeqNoRangeStart + ":" + endingSeqNo + "]");
// send all the snapshot's translog operations to the target
final SendSnapshotResult result = sendSnapshot(
startingSeqNo, requiredSeqNoRangeStart, endingSeqNo, snapshot, maxSeenAutoIdTimestamp, maxSeqNoOfUpdatesOrDeletes);
stopWatch.stop();
logger.trace("recovery [phase2]: took [{}]", stopWatch.totalTime());
response.phase2Time = stopWatch.totalTime().millis();
response.phase2Operations = result.totalOperations;
return result.targetLocalCheckpoint;
}
/*
* finalizes the recovery process
*/
public void finalizeRecovery(final long targetLocalCheckpoint) throws IOException {
if (shard.state() == IndexShardState.CLOSED) {
throw new IndexShardClosedException(request.shardId());
}
cancellableThreads.checkForCancel();
StopWatch stopWatch = new StopWatch().start();
logger.trace("finalizing recovery");
/*
* Before marking the shard as in-sync we acquire an operation permit. We do this so that there is a barrier between marking a
* shard as in-sync and relocating a shard. If we acquire the permit then no relocation handoff can complete before we are done
* marking the shard as in-sync. If the relocation handoff holds all the permits then after the handoff completes and we acquire
* the permit then the state of the shard will be relocated and this recovery will fail.
*/
runUnderPrimaryPermit(() -> shard.markAllocationIdAsInSync(request.targetAllocationId(), targetLocalCheckpoint),
shardId + " marking " + request.targetAllocationId() + " as in sync", shard, cancellableThreads, logger);
final long globalCheckpoint = shard.getGlobalCheckpoint();
cancellableThreads.executeIO(() -> recoveryTarget.finalizeRecovery(globalCheckpoint));
runUnderPrimaryPermit(() -> shard.updateGlobalCheckpointForShard(request.targetAllocationId(), globalCheckpoint),
shardId + " updating " + request.targetAllocationId() + "'s global checkpoint", shard, cancellableThreads, logger);
if (request.isPrimaryRelocation()) {
logger.trace("performing relocation hand-off");
// this acquires all IndexShard operation permits and will thus delay new recoveries until it is done
cancellableThreads.execute(() -> shard.relocated(recoveryTarget::handoffPrimaryContext));
/*
* if the recovery process fails after disabling primary mode on the source shard, both relocation source and
* target are failed (see {@link IndexShard#updateRoutingEntry}).
*/
}
stopWatch.stop();
logger.trace("finalizing recovery took [{}]", stopWatch.totalTime());
}
static class SendSnapshotResult {
final long targetLocalCheckpoint;
final int totalOperations;
SendSnapshotResult(final long targetLocalCheckpoint, final int totalOperations) {
this.targetLocalCheckpoint = targetLocalCheckpoint;
this.totalOperations = totalOperations;
}
}
/**
* Send the given snapshot's operations with a sequence number greater than the specified staring sequence number to this handler's
* target node.
* <p>
* Operations are bulked into a single request depending on an operation count limit or size-in-bytes limit.
*
* @param startingSeqNo the sequence number for which only operations with a sequence number greater than this will be sent
* @param requiredSeqNoRangeStart the lower sequence number of the required range
* @param endingSeqNo the upper bound of the sequence number range to be sent (inclusive)
* @param snapshot the translog snapshot to replay operations from @return the local checkpoint on the target and the
* total number of operations sent
* @param maxSeenAutoIdTimestamp the max auto_id_timestamp of append-only requests on the primary
* @param maxSeqNoOfUpdatesOrDeletes the max seq_no of updates or deletes on the primary after these operations were executed on it.
* @throws IOException if an I/O exception occurred reading the translog snapshot
*/
protected SendSnapshotResult sendSnapshot(final long startingSeqNo, long requiredSeqNoRangeStart, long endingSeqNo,
final Translog.Snapshot snapshot, final long maxSeenAutoIdTimestamp,
final long maxSeqNoOfUpdatesOrDeletes) throws IOException {
assert requiredSeqNoRangeStart <= endingSeqNo + 1:
"requiredSeqNoRangeStart " + requiredSeqNoRangeStart + " is larger than endingSeqNo " + endingSeqNo;
assert startingSeqNo <= requiredSeqNoRangeStart :
"startingSeqNo " + startingSeqNo + " is larger than requiredSeqNoRangeStart " + requiredSeqNoRangeStart;
int ops = 0;
long size = 0;
int skippedOps = 0;
@ -615,7 +568,58 @@ public class RecoverySourceHandler {
logger.trace("sent final batch of [{}][{}] (total: [{}]) translog operations", ops, new ByteSizeValue(size), expectedTotalOps);
return new SendSnapshotResult(targetLocalCheckpoint.get(), totalSentOps);
stopWatch.stop();
final TimeValue tookTime = stopWatch.totalTime();
logger.trace("recovery [phase2]: took [{}]", tookTime);
return new SendSnapshotResult(targetLocalCheckpoint.get(), totalSentOps, tookTime);
}
/*
* finalizes the recovery process
*/
public void finalizeRecovery(final long targetLocalCheckpoint) throws IOException {
if (shard.state() == IndexShardState.CLOSED) {
throw new IndexShardClosedException(request.shardId());
}
cancellableThreads.checkForCancel();
StopWatch stopWatch = new StopWatch().start();
logger.trace("finalizing recovery");
/*
* Before marking the shard as in-sync we acquire an operation permit. We do this so that there is a barrier between marking a
* shard as in-sync and relocating a shard. If we acquire the permit then no relocation handoff can complete before we are done
* marking the shard as in-sync. If the relocation handoff holds all the permits then after the handoff completes and we acquire
* the permit then the state of the shard will be relocated and this recovery will fail.
*/
runUnderPrimaryPermit(() -> shard.markAllocationIdAsInSync(request.targetAllocationId(), targetLocalCheckpoint),
shardId + " marking " + request.targetAllocationId() + " as in sync", shard, cancellableThreads, logger);
final long globalCheckpoint = shard.getGlobalCheckpoint();
cancellableThreads.executeIO(() -> recoveryTarget.finalizeRecovery(globalCheckpoint));
runUnderPrimaryPermit(() -> shard.updateGlobalCheckpointForShard(request.targetAllocationId(), globalCheckpoint),
shardId + " updating " + request.targetAllocationId() + "'s global checkpoint", shard, cancellableThreads, logger);
if (request.isPrimaryRelocation()) {
logger.trace("performing relocation hand-off");
// this acquires all IndexShard operation permits and will thus delay new recoveries until it is done
cancellableThreads.execute(() -> shard.relocated(recoveryTarget::handoffPrimaryContext));
/*
* if the recovery process fails after disabling primary mode on the source shard, both relocation source and
* target are failed (see {@link IndexShard#updateRoutingEntry}).
*/
}
stopWatch.stop();
logger.trace("finalizing recovery took [{}]", stopWatch.totalTime());
}
static final class SendSnapshotResult {
final long targetLocalCheckpoint;
final int totalOperations;
final TimeValue tookTime;
SendSnapshotResult(final long targetLocalCheckpoint, final int totalOperations, final TimeValue tookTime) {
this.targetLocalCheckpoint = targetLocalCheckpoint;
this.totalOperations = totalOperations;
this.tookTime = tookTime;
}
}
/**

View File

@ -111,62 +111,63 @@ public class RepositoriesService implements ClusterStateApplier {
return;
}
clusterService.submitStateUpdateTask(request.cause, new AckedClusterStateUpdateTask<ClusterStateUpdateResponse>(request, registrationListener) {
@Override
protected ClusterStateUpdateResponse newResponse(boolean acknowledged) {
return new ClusterStateUpdateResponse(acknowledged);
}
@Override
public ClusterState execute(ClusterState currentState) {
ensureRepositoryNotInUse(currentState, request.name);
MetaData metaData = currentState.metaData();
MetaData.Builder mdBuilder = MetaData.builder(currentState.metaData());
RepositoriesMetaData repositories = metaData.custom(RepositoriesMetaData.TYPE);
if (repositories == null) {
logger.info("put repository [{}]", request.name);
repositories = new RepositoriesMetaData(
Collections.singletonList(new RepositoryMetaData(request.name, request.type, request.settings)));
} else {
boolean found = false;
List<RepositoryMetaData> repositoriesMetaData = new ArrayList<>(repositories.repositories().size() + 1);
for (RepositoryMetaData repositoryMetaData : repositories.repositories()) {
if (repositoryMetaData.name().equals(newRepositoryMetaData.name())) {
if (newRepositoryMetaData.equals(repositoryMetaData)) {
// Previous version is the same as this one no update is needed.
return currentState;
}
found = true;
repositoriesMetaData.add(newRepositoryMetaData);
} else {
repositoriesMetaData.add(repositoryMetaData);
}
}
if (!found) {
logger.info("put repository [{}]", request.name);
repositoriesMetaData.add(new RepositoryMetaData(request.name, request.type, request.settings));
} else {
logger.info("update repository [{}]", request.name);
}
repositories = new RepositoriesMetaData(repositoriesMetaData);
clusterService.submitStateUpdateTask(request.cause,
new AckedClusterStateUpdateTask<ClusterStateUpdateResponse>(request, registrationListener) {
@Override
protected ClusterStateUpdateResponse newResponse(boolean acknowledged) {
return new ClusterStateUpdateResponse(acknowledged);
}
mdBuilder.putCustom(RepositoriesMetaData.TYPE, repositories);
return ClusterState.builder(currentState).metaData(mdBuilder).build();
}
@Override
public void onFailure(String source, Exception e) {
logger.warn(() -> new ParameterizedMessage("failed to create repository [{}]", request.name), e);
super.onFailure(source, e);
}
@Override
public ClusterState execute(ClusterState currentState) {
ensureRepositoryNotInUse(currentState, request.name);
MetaData metaData = currentState.metaData();
MetaData.Builder mdBuilder = MetaData.builder(currentState.metaData());
RepositoriesMetaData repositories = metaData.custom(RepositoriesMetaData.TYPE);
if (repositories == null) {
logger.info("put repository [{}]", request.name);
repositories = new RepositoriesMetaData(
Collections.singletonList(new RepositoryMetaData(request.name, request.type, request.settings)));
} else {
boolean found = false;
List<RepositoryMetaData> repositoriesMetaData = new ArrayList<>(repositories.repositories().size() + 1);
@Override
public boolean mustAck(DiscoveryNode discoveryNode) {
// repository is created on both master and data nodes
return discoveryNode.isMasterNode() || discoveryNode.isDataNode();
}
});
for (RepositoryMetaData repositoryMetaData : repositories.repositories()) {
if (repositoryMetaData.name().equals(newRepositoryMetaData.name())) {
if (newRepositoryMetaData.equals(repositoryMetaData)) {
// Previous version is the same as this one no update is needed.
return currentState;
}
found = true;
repositoriesMetaData.add(newRepositoryMetaData);
} else {
repositoriesMetaData.add(repositoryMetaData);
}
}
if (!found) {
logger.info("put repository [{}]", request.name);
repositoriesMetaData.add(new RepositoryMetaData(request.name, request.type, request.settings));
} else {
logger.info("update repository [{}]", request.name);
}
repositories = new RepositoriesMetaData(repositoriesMetaData);
}
mdBuilder.putCustom(RepositoriesMetaData.TYPE, repositories);
return ClusterState.builder(currentState).metaData(mdBuilder).build();
}
@Override
public void onFailure(String source, Exception e) {
logger.warn(() -> new ParameterizedMessage("failed to create repository [{}]", request.name), e);
super.onFailure(source, e);
}
@Override
public boolean mustAck(DiscoveryNode discoveryNode) {
// repository is created on both master and data nodes
return discoveryNode.isMasterNode() || discoveryNode.isDataNode();
}
});
}
/**
* Unregisters repository in the cluster
@ -323,7 +324,8 @@ public class RepositoriesService implements ClusterStateApplier {
} catch (RepositoryException ex) {
// TODO: this catch is bogus, it means the old repo is already closed,
// but we have nothing to replace it
logger.warn(() -> new ParameterizedMessage("failed to change repository [{}]", repositoryMetaData.name()), ex);
logger.warn(() -> new ParameterizedMessage("failed to change repository [{}]",
repositoryMetaData.name()), ex);
}
}
} else {
@ -411,7 +413,8 @@ public class RepositoriesService implements ClusterStateApplier {
repository.start();
return repository;
} catch (Exception e) {
logger.warn(new ParameterizedMessage("failed to create repository [{}][{}]", repositoryMetaData.type(), repositoryMetaData.name()), e);
logger.warn(new ParameterizedMessage("failed to create repository [{}][{}]",
repositoryMetaData.type(), repositoryMetaData.name()), e);
throw new RepositoryException(repositoryMetaData.name(), "failed to create repository", e);
}
}

View File

@ -216,7 +216,8 @@ public interface Repository extends LifecycleComponent {
* @param snapshotShardId shard id (in the snapshot)
* @param recoveryState recovery state
*/
void restoreShard(IndexShard shard, SnapshotId snapshotId, Version version, IndexId indexId, ShardId snapshotShardId, RecoveryState recoveryState);
void restoreShard(IndexShard shard, SnapshotId snapshotId, Version version, IndexId indexId,
ShardId snapshotShardId, RecoveryState recoveryState);
/**
* Retrieve shard snapshot status for the stored snapshot

View File

@ -59,11 +59,13 @@ public class VerifyNodeRepositoryAction {
private final RepositoriesService repositoriesService;
public VerifyNodeRepositoryAction(TransportService transportService, ClusterService clusterService, RepositoriesService repositoriesService) {
public VerifyNodeRepositoryAction(TransportService transportService, ClusterService clusterService,
RepositoriesService repositoriesService) {
this.transportService = transportService;
this.clusterService = clusterService;
this.repositoriesService = repositoriesService;
transportService.registerRequestHandler(ACTION_NAME, VerifyNodeRepositoryRequest::new, ThreadPool.Names.SNAPSHOT, new VerifyNodeRepositoryRequestHandler());
transportService.registerRequestHandler(ACTION_NAME, VerifyNodeRepositoryRequest::new, ThreadPool.Names.SNAPSHOT,
new VerifyNodeRepositoryRequestHandler());
}
public void verify(String repository, String verificationToken, final ActionListener<VerifyResponse> listener) {
@ -90,28 +92,31 @@ public class VerifyNodeRepositoryAction {
finishVerification(listener, nodes, errors);
}
} else {
transportService.sendRequest(node, ACTION_NAME, new VerifyNodeRepositoryRequest(repository, verificationToken), new EmptyTransportResponseHandler(ThreadPool.Names.SAME) {
@Override
public void handleResponse(TransportResponse.Empty response) {
if (counter.decrementAndGet() == 0) {
finishVerification(listener, nodes, errors);
transportService.sendRequest(node, ACTION_NAME, new VerifyNodeRepositoryRequest(repository, verificationToken),
new EmptyTransportResponseHandler(ThreadPool.Names.SAME) {
@Override
public void handleResponse(TransportResponse.Empty response) {
if (counter.decrementAndGet() == 0) {
finishVerification(listener, nodes, errors);
}
}
}
@Override
public void handleException(TransportException exp) {
errors.add(new VerificationFailure(node.getId(), exp));
if (counter.decrementAndGet() == 0) {
finishVerification(listener, nodes, errors);
@Override
public void handleException(TransportException exp) {
errors.add(new VerificationFailure(node.getId(), exp));
if (counter.decrementAndGet() == 0) {
finishVerification(listener, nodes, errors);
}
}
}
});
});
}
}
}
public void finishVerification(ActionListener<VerifyResponse> listener, List<DiscoveryNode> nodes, CopyOnWriteArrayList<VerificationFailure> errors) {
listener.onResponse(new RepositoriesService.VerifyResponse(nodes.toArray(new DiscoveryNode[nodes.size()]), errors.toArray(new VerificationFailure[errors.size()])));
public void finishVerification(ActionListener<VerifyResponse> listener, List<DiscoveryNode> nodes,
CopyOnWriteArrayList<VerificationFailure> errors) {
listener.onResponse(new RepositoriesService.VerifyResponse(nodes.toArray(new DiscoveryNode[nodes.size()]),
errors.toArray(new VerificationFailure[errors.size()])));
}
private void doVerify(String repositoryName, String verificationToken, DiscoveryNode localNode) {

View File

@ -479,12 +479,12 @@ public abstract class BlobStoreRepository extends AbstractLifecycleComponent imp
// we'll ignore that and accept that cleanup didn't fully succeed.
// since we are using UUIDs for path names, this won't be an issue for
// snapshotting indices of the same name
logger.debug(() -> new ParameterizedMessage("[{}] index [{}] no longer part of any snapshots in the repository, but failed to clean up " +
"its index folder due to the directory not being empty.", metadata.name(), indexId), dnee);
logger.debug(() -> new ParameterizedMessage("[{}] index [{}] no longer part of any snapshots in the repository, " +
"but failed to clean up its index folder due to the directory not being empty.", metadata.name(), indexId), dnee);
} catch (IOException ioe) {
// a different IOException occurred while trying to delete - will just log the issue for now
logger.debug(() -> new ParameterizedMessage("[{}] index [{}] no longer part of any snapshots in the repository, but failed to clean up " +
"its index folder.", metadata.name(), indexId), ioe);
logger.debug(() -> new ParameterizedMessage("[{}] index [{}] no longer part of any snapshots in the repository, " +
"but failed to clean up its index folder.", metadata.name(), indexId), ioe);
}
}
} catch (IOException | ResourceNotFoundException ex) {
@ -524,7 +524,8 @@ public abstract class BlobStoreRepository extends AbstractLifecycleComponent imp
try {
indexMetaDataFormat.delete(indexMetaDataBlobContainer, snapshotId.getUUID());
} catch (IOException ex) {
logger.warn(() -> new ParameterizedMessage("[{}] failed to delete metadata for index [{}]", snapshotId, indexId.getName()), ex);
logger.warn(() -> new ParameterizedMessage("[{}] failed to delete metadata for index [{}]",
snapshotId, indexId.getName()), ex);
}
}
@ -861,7 +862,8 @@ public abstract class BlobStoreRepository extends AbstractLifecycleComponent imp
}
@Override
public void restoreShard(IndexShard shard, SnapshotId snapshotId, Version version, IndexId indexId, ShardId snapshotShardId, RecoveryState recoveryState) {
public void restoreShard(IndexShard shard, SnapshotId snapshotId, Version version, IndexId indexId, ShardId snapshotShardId,
RecoveryState recoveryState) {
final RestoreContext snapshotContext = new RestoreContext(shard, snapshotId, indexId, snapshotShardId, recoveryState);
try {
snapshotContext.restore();
@ -898,12 +900,14 @@ public abstract class BlobStoreRepository extends AbstractLifecycleComponent imp
testBlobContainer.writeBlob("data-" + localNode.getId() + ".dat", stream, bytes.length(), true);
}
} catch (IOException exp) {
throw new RepositoryVerificationException(metadata.name(), "store location [" + blobStore() + "] is not accessible on the node [" + localNode + "]", exp);
throw new RepositoryVerificationException(metadata.name(), "store location [" + blobStore() +
"] is not accessible on the node [" + localNode + "]", exp);
}
} else {
throw new RepositoryVerificationException(metadata.name(), "a file written by master to the store [" + blobStore() + "] cannot be accessed on the node [" + localNode + "]. "
+ "This might indicate that the store [" + blobStore() + "] is not shared between this node and the master node or "
+ "that permissions on the store don't allow reading files written by the master node");
throw new RepositoryVerificationException(metadata.name(), "a file written by master to the store [" + blobStore() +
"] cannot be accessed on the node [" + localNode + "]. " +
"This might indicate that the store [" + blobStore() + "] is not shared between this node and the master node or " +
"that permissions on the store don't allow reading files written by the master node");
}
}
}
@ -945,7 +949,8 @@ public abstract class BlobStoreRepository extends AbstractLifecycleComponent imp
Context(SnapshotId snapshotId, IndexId indexId, ShardId shardId, ShardId snapshotShardId) {
this.snapshotId = snapshotId;
this.shardId = shardId;
blobContainer = blobStore().blobContainer(basePath().add("indices").add(indexId.getId()).add(Integer.toString(snapshotShardId.getId())));
blobContainer = blobStore().blobContainer(basePath().add("indices").add(indexId.getId())
.add(Integer.toString(snapshotShardId.getId())));
}
/**
@ -1235,7 +1240,8 @@ public abstract class BlobStoreRepository extends AbstractLifecycleComponent imp
// in a bwc compatible way.
maybeRecalculateMetadataHash(blobContainer, fileInfo, metadata);
} catch (Exception e) {
logger.warn(() -> new ParameterizedMessage("{} Can't calculate hash from blob for file [{}] [{}]", shardId, fileInfo.physicalName(), fileInfo.metadata()), e);
logger.warn(() -> new ParameterizedMessage("{} Can't calculate hash from blob for file [{}] [{}]",
shardId, fileInfo.physicalName(), fileInfo.metadata()), e);
}
if (fileInfo.isSame(md) && snapshotFileExistsInBlobs(fileInfo, blobs)) {
// a commit point file with the same name, size and checksum was already copied to repository
@ -1253,7 +1259,8 @@ public abstract class BlobStoreRepository extends AbstractLifecycleComponent imp
indexIncrementalFileCount++;
indexIncrementalSize += md.length();
// create a new FileInfo
BlobStoreIndexShardSnapshot.FileInfo snapshotFileInfo = new BlobStoreIndexShardSnapshot.FileInfo(fileNameFromGeneration(++generation), md, chunkSize());
BlobStoreIndexShardSnapshot.FileInfo snapshotFileInfo =
new BlobStoreIndexShardSnapshot.FileInfo(fileNameFromGeneration(++generation), md, chunkSize());
indexCommitPointFiles.add(snapshotFileInfo);
filesToSnapshot.add(snapshotFileInfo);
} else {
@ -1411,7 +1418,8 @@ public abstract class BlobStoreRepository extends AbstractLifecycleComponent imp
* The new logic for StoreFileMetaData reads the entire {@code .si} and {@code segments.n} files to strengthen the
* comparison of the files on a per-segment / per-commit level.
*/
private static void maybeRecalculateMetadataHash(final BlobContainer blobContainer, final BlobStoreIndexShardSnapshot.FileInfo fileInfo, Store.MetadataSnapshot snapshot) throws Exception {
private static void maybeRecalculateMetadataHash(final BlobContainer blobContainer, final BlobStoreIndexShardSnapshot.FileInfo fileInfo,
Store.MetadataSnapshot snapshot) throws Exception {
final StoreFileMetaData metadata;
if (fileInfo != null && (metadata = snapshot.get(fileInfo.physicalName())) != null) {
if (metadata.hash().length > 0 && fileInfo.metadata().hash().length == 0) {
@ -1509,7 +1517,8 @@ public abstract class BlobStoreRepository extends AbstractLifecycleComponent imp
logger.trace("[{}] [{}] restoring from to an empty shard", shardId, snapshotId);
recoveryTargetMetadata = Store.MetadataSnapshot.EMPTY;
} catch (IOException e) {
logger.warn(() -> new ParameterizedMessage("{} Can't read metadata from store, will not reuse any local file while restoring", shardId), e);
logger.warn(() -> new ParameterizedMessage("{} Can't read metadata from store, will not reuse any " +
"local file while restoring", shardId), e);
recoveryTargetMetadata = Store.MetadataSnapshot.EMPTY;
}
@ -1525,7 +1534,8 @@ public abstract class BlobStoreRepository extends AbstractLifecycleComponent imp
maybeRecalculateMetadataHash(blobContainer, fileInfo, recoveryTargetMetadata);
} catch (Exception e) {
// if the index is broken we might not be able to read it
logger.warn(() -> new ParameterizedMessage("{} Can't calculate hash from blog for file [{}] [{}]", shardId, fileInfo.physicalName(), fileInfo.metadata()), e);
logger.warn(() -> new ParameterizedMessage("{} Can't calculate hash from blog for file [{}] [{}]",
shardId, fileInfo.physicalName(), fileInfo.metadata()), e);
}
snapshotMetaData.put(fileInfo.metadata().name(), fileInfo.metadata());
fileInfos.put(fileInfo.metadata().name(), fileInfo);
@ -1543,7 +1553,8 @@ public abstract class BlobStoreRepository extends AbstractLifecycleComponent imp
BlobStoreIndexShardSnapshot.FileInfo fileInfo = fileInfos.get(md.name());
recoveryState.getIndex().addFileDetail(fileInfo.name(), fileInfo.length(), true);
if (logger.isTraceEnabled()) {
logger.trace("[{}] [{}] not_recovering [{}] from [{}], exists in local store and is same", shardId, snapshotId, fileInfo.physicalName(), fileInfo.name());
logger.trace("[{}] [{}] not_recovering [{}] from [{}], exists in local store and is same",
shardId, snapshotId, fileInfo.physicalName(), fileInfo.name());
}
}
@ -1634,7 +1645,8 @@ public abstract class BlobStoreRepository extends AbstractLifecycleComponent imp
stream = new RateLimitingInputStream(partSliceStream, restoreRateLimiter, restoreRateLimitingTimeInNanos::inc);
}
try (IndexOutput indexOutput = store.createVerifyingOutput(fileInfo.physicalName(), fileInfo.metadata(), IOContext.DEFAULT)) {
try (IndexOutput indexOutput = store.createVerifyingOutput(fileInfo.physicalName(),
fileInfo.metadata(), IOContext.DEFAULT)) {
final byte[] buffer = new byte[BUFFER_SIZE];
int length;
while ((length = stream.read(buffer)) > 0) {

View File

@ -43,7 +43,8 @@ import java.util.function.Function;
* <dl>
* <dt>{@code location}</dt><dd>Path to the root of repository. This is mandatory parameter.</dd>
* <dt>{@code concurrent_streams}</dt><dd>Number of concurrent read/write stream (per repository on each node). Defaults to 5.</dd>
* <dt>{@code chunk_size}</dt><dd>Large file can be divided into chunks. This parameter specifies the chunk size. Defaults to not chucked.</dd>
* <dt>{@code chunk_size}</dt><dd>Large file can be divided into chunks. This parameter specifies the chunk size.
* Defaults to not chucked.</dd>
* <dt>{@code compress}</dt><dd>If set to true metadata files will be stored compressed. Defaults to false.</dd>
* </dl>
*/

View File

@ -122,7 +122,8 @@ public class RestIndicesAction extends AbstractCatAction {
client.admin().indices().stats(indicesStatsRequest, new RestResponseListener<IndicesStatsResponse>(channel) {
@Override
public RestResponse buildResponse(IndicesStatsResponse indicesStatsResponse) throws Exception {
Table tab = buildTable(request, concreteIndices, clusterHealthResponse, indicesStatsResponse, state.metaData());
Table tab = buildTable(request, concreteIndices, clusterHealthResponse,
indicesStatsResponse, state.metaData());
return RestTable.buildResponse(tab, channel);
}
});
@ -168,28 +169,36 @@ public class RestIndicesAction extends AbstractCatAction {
table.addCell("completion.size", "sibling:pri;alias:cs,completionSize;default:false;text-align:right;desc:size of completion");
table.addCell("pri.completion.size", "default:false;text-align:right;desc:size of completion");
table.addCell("fielddata.memory_size", "sibling:pri;alias:fm,fielddataMemory;default:false;text-align:right;desc:used fielddata cache");
table.addCell("fielddata.memory_size",
"sibling:pri;alias:fm,fielddataMemory;default:false;text-align:right;desc:used fielddata cache");
table.addCell("pri.fielddata.memory_size", "default:false;text-align:right;desc:used fielddata cache");
table.addCell("fielddata.evictions", "sibling:pri;alias:fe,fielddataEvictions;default:false;text-align:right;desc:fielddata evictions");
table.addCell("fielddata.evictions",
"sibling:pri;alias:fe,fielddataEvictions;default:false;text-align:right;desc:fielddata evictions");
table.addCell("pri.fielddata.evictions", "default:false;text-align:right;desc:fielddata evictions");
table.addCell("query_cache.memory_size", "sibling:pri;alias:qcm,queryCacheMemory;default:false;text-align:right;desc:used query cache");
table.addCell("query_cache.memory_size",
"sibling:pri;alias:qcm,queryCacheMemory;default:false;text-align:right;desc:used query cache");
table.addCell("pri.query_cache.memory_size", "default:false;text-align:right;desc:used query cache");
table.addCell("query_cache.evictions", "sibling:pri;alias:qce,queryCacheEvictions;default:false;text-align:right;desc:query cache evictions");
table.addCell("query_cache.evictions",
"sibling:pri;alias:qce,queryCacheEvictions;default:false;text-align:right;desc:query cache evictions");
table.addCell("pri.query_cache.evictions", "default:false;text-align:right;desc:query cache evictions");
table.addCell("request_cache.memory_size", "sibling:pri;alias:rcm,requestCacheMemory;default:false;text-align:right;desc:used request cache");
table.addCell("request_cache.memory_size",
"sibling:pri;alias:rcm,requestCacheMemory;default:false;text-align:right;desc:used request cache");
table.addCell("pri.request_cache.memory_size", "default:false;text-align:right;desc:used request cache");
table.addCell("request_cache.evictions", "sibling:pri;alias:rce,requestCacheEvictions;default:false;text-align:right;desc:request cache evictions");
table.addCell("request_cache.evictions",
"sibling:pri;alias:rce,requestCacheEvictions;default:false;text-align:right;desc:request cache evictions");
table.addCell("pri.request_cache.evictions", "default:false;text-align:right;desc:request cache evictions");
table.addCell("request_cache.hit_count", "sibling:pri;alias:rchc,requestCacheHitCount;default:false;text-align:right;desc:request cache hit count");
table.addCell("request_cache.hit_count",
"sibling:pri;alias:rchc,requestCacheHitCount;default:false;text-align:right;desc:request cache hit count");
table.addCell("pri.request_cache.hit_count", "default:false;text-align:right;desc:request cache hit count");
table.addCell("request_cache.miss_count", "sibling:pri;alias:rcmc,requestCacheMissCount;default:false;text-align:right;desc:request cache miss count");
table.addCell("request_cache.miss_count",
"sibling:pri;alias:rcmc,requestCacheMissCount;default:false;text-align:right;desc:request cache miss count");
table.addCell("pri.request_cache.miss_count", "default:false;text-align:right;desc:request cache miss count");
table.addCell("flush.total", "sibling:pri;alias:ft,flushTotal;default:false;text-align:right;desc:number of flushes");
@ -207,49 +216,64 @@ public class RestIndicesAction extends AbstractCatAction {
table.addCell("get.total", "sibling:pri;alias:gto,getTotal;default:false;text-align:right;desc:number of get ops");
table.addCell("pri.get.total", "default:false;text-align:right;desc:number of get ops");
table.addCell("get.exists_time", "sibling:pri;alias:geti,getExistsTime;default:false;text-align:right;desc:time spent in successful gets");
table.addCell("get.exists_time",
"sibling:pri;alias:geti,getExistsTime;default:false;text-align:right;desc:time spent in successful gets");
table.addCell("pri.get.exists_time", "default:false;text-align:right;desc:time spent in successful gets");
table.addCell("get.exists_total", "sibling:pri;alias:geto,getExistsTotal;default:false;text-align:right;desc:number of successful gets");
table.addCell("get.exists_total",
"sibling:pri;alias:geto,getExistsTotal;default:false;text-align:right;desc:number of successful gets");
table.addCell("pri.get.exists_total", "default:false;text-align:right;desc:number of successful gets");
table.addCell("get.missing_time", "sibling:pri;alias:gmti,getMissingTime;default:false;text-align:right;desc:time spent in failed gets");
table.addCell("get.missing_time",
"sibling:pri;alias:gmti,getMissingTime;default:false;text-align:right;desc:time spent in failed gets");
table.addCell("pri.get.missing_time", "default:false;text-align:right;desc:time spent in failed gets");
table.addCell("get.missing_total", "sibling:pri;alias:gmto,getMissingTotal;default:false;text-align:right;desc:number of failed gets");
table.addCell("get.missing_total",
"sibling:pri;alias:gmto,getMissingTotal;default:false;text-align:right;desc:number of failed gets");
table.addCell("pri.get.missing_total", "default:false;text-align:right;desc:number of failed gets");
table.addCell("indexing.delete_current", "sibling:pri;alias:idc,indexingDeleteCurrent;default:false;text-align:right;desc:number of current deletions");
table.addCell("indexing.delete_current",
"sibling:pri;alias:idc,indexingDeleteCurrent;default:false;text-align:right;desc:number of current deletions");
table.addCell("pri.indexing.delete_current", "default:false;text-align:right;desc:number of current deletions");
table.addCell("indexing.delete_time", "sibling:pri;alias:idti,indexingDeleteTime;default:false;text-align:right;desc:time spent in deletions");
table.addCell("indexing.delete_time",
"sibling:pri;alias:idti,indexingDeleteTime;default:false;text-align:right;desc:time spent in deletions");
table.addCell("pri.indexing.delete_time", "default:false;text-align:right;desc:time spent in deletions");
table.addCell("indexing.delete_total", "sibling:pri;alias:idto,indexingDeleteTotal;default:false;text-align:right;desc:number of delete ops");
table.addCell("indexing.delete_total",
"sibling:pri;alias:idto,indexingDeleteTotal;default:false;text-align:right;desc:number of delete ops");
table.addCell("pri.indexing.delete_total", "default:false;text-align:right;desc:number of delete ops");
table.addCell("indexing.index_current", "sibling:pri;alias:iic,indexingIndexCurrent;default:false;text-align:right;desc:number of current indexing ops");
table.addCell("indexing.index_current",
"sibling:pri;alias:iic,indexingIndexCurrent;default:false;text-align:right;desc:number of current indexing ops");
table.addCell("pri.indexing.index_current", "default:false;text-align:right;desc:number of current indexing ops");
table.addCell("indexing.index_time", "sibling:pri;alias:iiti,indexingIndexTime;default:false;text-align:right;desc:time spent in indexing");
table.addCell("indexing.index_time",
"sibling:pri;alias:iiti,indexingIndexTime;default:false;text-align:right;desc:time spent in indexing");
table.addCell("pri.indexing.index_time", "default:false;text-align:right;desc:time spent in indexing");
table.addCell("indexing.index_total", "sibling:pri;alias:iito,indexingIndexTotal;default:false;text-align:right;desc:number of indexing ops");
table.addCell("indexing.index_total",
"sibling:pri;alias:iito,indexingIndexTotal;default:false;text-align:right;desc:number of indexing ops");
table.addCell("pri.indexing.index_total", "default:false;text-align:right;desc:number of indexing ops");
table.addCell("indexing.index_failed", "sibling:pri;alias:iif,indexingIndexFailed;default:false;text-align:right;desc:number of failed indexing ops");
table.addCell("indexing.index_failed",
"sibling:pri;alias:iif,indexingIndexFailed;default:false;text-align:right;desc:number of failed indexing ops");
table.addCell("pri.indexing.index_failed", "default:false;text-align:right;desc:number of failed indexing ops");
table.addCell("merges.current", "sibling:pri;alias:mc,mergesCurrent;default:false;text-align:right;desc:number of current merges");
table.addCell("merges.current",
"sibling:pri;alias:mc,mergesCurrent;default:false;text-align:right;desc:number of current merges");
table.addCell("pri.merges.current", "default:false;text-align:right;desc:number of current merges");
table.addCell("merges.current_docs", "sibling:pri;alias:mcd,mergesCurrentDocs;default:false;text-align:right;desc:number of current merging docs");
table.addCell("merges.current_docs",
"sibling:pri;alias:mcd,mergesCurrentDocs;default:false;text-align:right;desc:number of current merging docs");
table.addCell("pri.merges.current_docs", "default:false;text-align:right;desc:number of current merging docs");
table.addCell("merges.current_size", "sibling:pri;alias:mcs,mergesCurrentSize;default:false;text-align:right;desc:size of current merges");
table.addCell("merges.current_size",
"sibling:pri;alias:mcs,mergesCurrentSize;default:false;text-align:right;desc:size of current merges");
table.addCell("pri.merges.current_size", "default:false;text-align:right;desc:size of current merges");
table.addCell("merges.total", "sibling:pri;alias:mt,mergesTotal;default:false;text-align:right;desc:number of completed merge ops");
table.addCell("merges.total",
"sibling:pri;alias:mt,mergesTotal;default:false;text-align:right;desc:number of completed merge ops");
table.addCell("pri.merges.total", "default:false;text-align:right;desc:number of completed merge ops");
table.addCell("merges.total_docs", "sibling:pri;alias:mtd,mergesTotalDocs;default:false;text-align:right;desc:docs merged");
@ -258,7 +282,8 @@ public class RestIndicesAction extends AbstractCatAction {
table.addCell("merges.total_size", "sibling:pri;alias:mts,mergesTotalSize;default:false;text-align:right;desc:size merged");
table.addCell("pri.merges.total_size", "default:false;text-align:right;desc:size merged");
table.addCell("merges.total_time", "sibling:pri;alias:mtt,mergesTotalTime;default:false;text-align:right;desc:time spent in merges");
table.addCell("merges.total_time",
"sibling:pri;alias:mtt,mergesTotalTime;default:false;text-align:right;desc:time spent in merges");
table.addCell("pri.merges.total_time", "default:false;text-align:right;desc:time spent in merges");
table.addCell("refresh.total", "sibling:pri;alias:rto,refreshTotal;default:false;text-align:right;desc:total refreshes");
@ -267,37 +292,48 @@ public class RestIndicesAction extends AbstractCatAction {
table.addCell("refresh.time", "sibling:pri;alias:rti,refreshTime;default:false;text-align:right;desc:time spent in refreshes");
table.addCell("pri.refresh.time", "default:false;text-align:right;desc:time spent in refreshes");
table.addCell("refresh.listeners", "sibling:pri;alias:rli,refreshListeners;default:false;text-align:right;desc:number of pending refresh listeners");
table.addCell("refresh.listeners",
"sibling:pri;alias:rli,refreshListeners;default:false;text-align:right;desc:number of pending refresh listeners");
table.addCell("pri.refresh.listeners", "default:false;text-align:right;desc:number of pending refresh listeners");
table.addCell("search.fetch_current", "sibling:pri;alias:sfc,searchFetchCurrent;default:false;text-align:right;desc:current fetch phase ops");
table.addCell("search.fetch_current",
"sibling:pri;alias:sfc,searchFetchCurrent;default:false;text-align:right;desc:current fetch phase ops");
table.addCell("pri.search.fetch_current", "default:false;text-align:right;desc:current fetch phase ops");
table.addCell("search.fetch_time", "sibling:pri;alias:sfti,searchFetchTime;default:false;text-align:right;desc:time spent in fetch phase");
table.addCell("search.fetch_time",
"sibling:pri;alias:sfti,searchFetchTime;default:false;text-align:right;desc:time spent in fetch phase");
table.addCell("pri.search.fetch_time", "default:false;text-align:right;desc:time spent in fetch phase");
table.addCell("search.fetch_total", "sibling:pri;alias:sfto,searchFetchTotal;default:false;text-align:right;desc:total fetch ops");
table.addCell("search.fetch_total",
"sibling:pri;alias:sfto,searchFetchTotal;default:false;text-align:right;desc:total fetch ops");
table.addCell("pri.search.fetch_total", "default:false;text-align:right;desc:total fetch ops");
table.addCell("search.open_contexts", "sibling:pri;alias:so,searchOpenContexts;default:false;text-align:right;desc:open search contexts");
table.addCell("search.open_contexts",
"sibling:pri;alias:so,searchOpenContexts;default:false;text-align:right;desc:open search contexts");
table.addCell("pri.search.open_contexts", "default:false;text-align:right;desc:open search contexts");
table.addCell("search.query_current", "sibling:pri;alias:sqc,searchQueryCurrent;default:false;text-align:right;desc:current query phase ops");
table.addCell("search.query_current",
"sibling:pri;alias:sqc,searchQueryCurrent;default:false;text-align:right;desc:current query phase ops");
table.addCell("pri.search.query_current", "default:false;text-align:right;desc:current query phase ops");
table.addCell("search.query_time", "sibling:pri;alias:sqti,searchQueryTime;default:false;text-align:right;desc:time spent in query phase");
table.addCell("search.query_time",
"sibling:pri;alias:sqti,searchQueryTime;default:false;text-align:right;desc:time spent in query phase");
table.addCell("pri.search.query_time", "default:false;text-align:right;desc:time spent in query phase");
table.addCell("search.query_total", "sibling:pri;alias:sqto,searchQueryTotal;default:false;text-align:right;desc:total query phase ops");
table.addCell("search.query_total",
"sibling:pri;alias:sqto,searchQueryTotal;default:false;text-align:right;desc:total query phase ops");
table.addCell("pri.search.query_total", "default:false;text-align:right;desc:total query phase ops");
table.addCell("search.scroll_current", "sibling:pri;alias:scc,searchScrollCurrent;default:false;text-align:right;desc:open scroll contexts");
table.addCell("search.scroll_current",
"sibling:pri;alias:scc,searchScrollCurrent;default:false;text-align:right;desc:open scroll contexts");
table.addCell("pri.search.scroll_current", "default:false;text-align:right;desc:open scroll contexts");
table.addCell("search.scroll_time", "sibling:pri;alias:scti,searchScrollTime;default:false;text-align:right;desc:time scroll contexts held open");
table.addCell("search.scroll_time",
"sibling:pri;alias:scti,searchScrollTime;default:false;text-align:right;desc:time scroll contexts held open");
table.addCell("pri.search.scroll_time", "default:false;text-align:right;desc:time scroll contexts held open");
table.addCell("search.scroll_total", "sibling:pri;alias:scto,searchScrollTotal;default:false;text-align:right;desc:completed scroll contexts");
table.addCell("search.scroll_total",
"sibling:pri;alias:scto,searchScrollTotal;default:false;text-align:right;desc:completed scroll contexts");
table.addCell("pri.search.scroll_total", "default:false;text-align:right;desc:completed scroll contexts");
table.addCell("segments.count", "sibling:pri;alias:sc,segmentsCount;default:false;text-align:right;desc:number of segments");
@ -306,14 +342,20 @@ public class RestIndicesAction extends AbstractCatAction {
table.addCell("segments.memory", "sibling:pri;alias:sm,segmentsMemory;default:false;text-align:right;desc:memory used by segments");
table.addCell("pri.segments.memory", "default:false;text-align:right;desc:memory used by segments");
table.addCell("segments.index_writer_memory", "sibling:pri;alias:siwm,segmentsIndexWriterMemory;default:false;text-align:right;desc:memory used by index writer");
table.addCell("segments.index_writer_memory",
"sibling:pri;alias:siwm,segmentsIndexWriterMemory;default:false;text-align:right;desc:memory used by index writer");
table.addCell("pri.segments.index_writer_memory", "default:false;text-align:right;desc:memory used by index writer");
table.addCell("segments.version_map_memory", "sibling:pri;alias:svmm,segmentsVersionMapMemory;default:false;text-align:right;desc:memory used by version map");
table.addCell("segments.version_map_memory",
"sibling:pri;alias:svmm,segmentsVersionMapMemory;default:false;text-align:right;desc:memory used by version map");
table.addCell("pri.segments.version_map_memory", "default:false;text-align:right;desc:memory used by version map");
table.addCell("segments.fixed_bitset_memory", "sibling:pri;alias:sfbm,fixedBitsetMemory;default:false;text-align:right;desc:memory used by fixed bit sets for nested object field types and type filters for types referred in _parent fields");
table.addCell("pri.segments.fixed_bitset_memory", "default:false;text-align:right;desc:memory used by fixed bit sets for nested object field types and type filters for types referred in _parent fields");
table.addCell("segments.fixed_bitset_memory",
"sibling:pri;alias:sfbm,fixedBitsetMemory;default:false;text-align:right;desc:memory used by fixed bit sets for" +
" nested object field types and type filters for types referred in _parent fields");
table.addCell("pri.segments.fixed_bitset_memory",
"default:false;text-align:right;desc:memory used by fixed bit sets for nested object" +
" field types and type filters for types referred in _parent fields");
table.addCell("warmer.current", "sibling:pri;alias:wc,warmerCurrent;default:false;text-align:right;desc:current warmer ops");
table.addCell("pri.warmer.current", "default:false;text-align:right;desc:current warmer ops");
@ -321,10 +363,12 @@ public class RestIndicesAction extends AbstractCatAction {
table.addCell("warmer.total", "sibling:pri;alias:wto,warmerTotal;default:false;text-align:right;desc:total warmer ops");
table.addCell("pri.warmer.total", "default:false;text-align:right;desc:total warmer ops");
table.addCell("warmer.total_time", "sibling:pri;alias:wtt,warmerTotalTime;default:false;text-align:right;desc:time spent in warmers");
table.addCell("warmer.total_time",
"sibling:pri;alias:wtt,warmerTotalTime;default:false;text-align:right;desc:time spent in warmers");
table.addCell("pri.warmer.total_time", "default:false;text-align:right;desc:time spent in warmers");
table.addCell("suggest.current", "sibling:pri;alias:suc,suggestCurrent;default:false;text-align:right;desc:number of current suggest ops");
table.addCell("suggest.current",
"sibling:pri;alias:suc,suggestCurrent;default:false;text-align:right;desc:number of current suggest ops");
table.addCell("pri.suggest.current", "default:false;text-align:right;desc:number of current suggest ops");
table.addCell("suggest.time", "sibling:pri;alias:suti,suggestTime;default:false;text-align:right;desc:time spend in suggest");
@ -343,7 +387,8 @@ public class RestIndicesAction extends AbstractCatAction {
}
// package private for testing
Table buildTable(RestRequest request, Index[] indices, ClusterHealthResponse response, IndicesStatsResponse stats, MetaData indexMetaDatas) {
Table buildTable(RestRequest request, Index[] indices, ClusterHealthResponse response,
IndicesStatsResponse stats, MetaData indexMetaDatas) {
final String healthParam = request.param("health");
final ClusterHealthStatus status;
if (healthParam != null) {
@ -374,7 +419,8 @@ public class RestIndicesAction extends AbstractCatAction {
final CommonStats totalStats = indexStats == null ? new CommonStats() : indexStats.getTotal();
table.startRow();
table.addCell(state == IndexMetaData.State.OPEN ? (indexHealth == null ? "red*" : indexHealth.getStatus().toString().toLowerCase(Locale.ROOT)) : null);
table.addCell(state == IndexMetaData.State.OPEN ?
(indexHealth == null ? "red*" : indexHealth.getStatus().toString().toLowerCase(Locale.ROOT)) : null);
table.addCell(state.toString().toLowerCase(Locale.ROOT));
table.addCell(indexName);
table.addCell(index.getUUID());

View File

@ -142,16 +142,20 @@ public class RestShardsAction extends AbstractCatAction {
table.addCell("get.missing_time", "alias:gmti,getMissingTime;default:false;text-align:right;desc:time spent in failed gets");
table.addCell("get.missing_total", "alias:gmto,getMissingTotal;default:false;text-align:right;desc:number of failed gets");
table.addCell("indexing.delete_current", "alias:idc,indexingDeleteCurrent;default:false;text-align:right;desc:number of current deletions");
table.addCell("indexing.delete_current",
"alias:idc,indexingDeleteCurrent;default:false;text-align:right;desc:number of current deletions");
table.addCell("indexing.delete_time", "alias:idti,indexingDeleteTime;default:false;text-align:right;desc:time spent in deletions");
table.addCell("indexing.delete_total", "alias:idto,indexingDeleteTotal;default:false;text-align:right;desc:number of delete ops");
table.addCell("indexing.index_current", "alias:iic,indexingIndexCurrent;default:false;text-align:right;desc:number of current indexing ops");
table.addCell("indexing.index_current",
"alias:iic,indexingIndexCurrent;default:false;text-align:right;desc:number of current indexing ops");
table.addCell("indexing.index_time", "alias:iiti,indexingIndexTime;default:false;text-align:right;desc:time spent in indexing");
table.addCell("indexing.index_total", "alias:iito,indexingIndexTotal;default:false;text-align:right;desc:number of indexing ops");
table.addCell("indexing.index_failed", "alias:iif,indexingIndexFailed;default:false;text-align:right;desc:number of failed indexing ops");
table.addCell("indexing.index_failed",
"alias:iif,indexingIndexFailed;default:false;text-align:right;desc:number of failed indexing ops");
table.addCell("merges.current", "alias:mc,mergesCurrent;default:false;text-align:right;desc:number of current merges");
table.addCell("merges.current_docs", "alias:mcd,mergesCurrentDocs;default:false;text-align:right;desc:number of current merging docs");
table.addCell("merges.current_docs",
"alias:mcd,mergesCurrentDocs;default:false;text-align:right;desc:number of current merging docs");
table.addCell("merges.current_size", "alias:mcs,mergesCurrentSize;default:false;text-align:right;desc:size of current merges");
table.addCell("merges.total", "alias:mt,mergesTotal;default:false;text-align:right;desc:number of completed merge ops");
table.addCell("merges.total_docs", "alias:mtd,mergesTotalDocs;default:false;text-align:right;desc:docs merged");
@ -160,7 +164,8 @@ public class RestShardsAction extends AbstractCatAction {
table.addCell("refresh.total", "alias:rto,refreshTotal;default:false;text-align:right;desc:total refreshes");
table.addCell("refresh.time", "alias:rti,refreshTime;default:false;text-align:right;desc:time spent in refreshes");
table.addCell("refresh.listeners", "alias:rli,refreshListeners;default:false;text-align:right;desc:number of pending refresh listeners");
table.addCell("refresh.listeners",
"alias:rli,refreshListeners;default:false;text-align:right;desc:number of pending refresh listeners");
table.addCell("search.fetch_current", "alias:sfc,searchFetchCurrent;default:false;text-align:right;desc:current fetch phase ops");
table.addCell("search.fetch_time", "alias:sfti,searchFetchTime;default:false;text-align:right;desc:time spent in fetch phase");
@ -170,14 +175,19 @@ public class RestShardsAction extends AbstractCatAction {
table.addCell("search.query_time", "alias:sqti,searchQueryTime;default:false;text-align:right;desc:time spent in query phase");
table.addCell("search.query_total", "alias:sqto,searchQueryTotal;default:false;text-align:right;desc:total query phase ops");
table.addCell("search.scroll_current", "alias:scc,searchScrollCurrent;default:false;text-align:right;desc:open scroll contexts");
table.addCell("search.scroll_time", "alias:scti,searchScrollTime;default:false;text-align:right;desc:time scroll contexts held open");
table.addCell("search.scroll_time",
"alias:scti,searchScrollTime;default:false;text-align:right;desc:time scroll contexts held open");
table.addCell("search.scroll_total", "alias:scto,searchScrollTotal;default:false;text-align:right;desc:completed scroll contexts");
table.addCell("segments.count", "alias:sc,segmentsCount;default:false;text-align:right;desc:number of segments");
table.addCell("segments.memory", "alias:sm,segmentsMemory;default:false;text-align:right;desc:memory used by segments");
table.addCell("segments.index_writer_memory", "alias:siwm,segmentsIndexWriterMemory;default:false;text-align:right;desc:memory used by index writer");
table.addCell("segments.version_map_memory", "alias:svmm,segmentsVersionMapMemory;default:false;text-align:right;desc:memory used by version map");
table.addCell("segments.fixed_bitset_memory", "alias:sfbm,fixedBitsetMemory;default:false;text-align:right;desc:memory used by fixed bit sets for nested object field types and type filters for types referred in _parent fields");
table.addCell("segments.index_writer_memory",
"alias:siwm,segmentsIndexWriterMemory;default:false;text-align:right;desc:memory used by index writer");
table.addCell("segments.version_map_memory",
"alias:svmm,segmentsVersionMapMemory;default:false;text-align:right;desc:memory used by version map");
table.addCell("segments.fixed_bitset_memory",
"alias:sfbm,fixedBitsetMemory;default:false;text-align:right;desc:memory used by fixed bit sets for nested object" +
" field types and type filters for types referred in _parent fields");
table.addCell("seq_no.max", "alias:sqm,maxSeqNo;default:false;text-align:right;desc:max sequence number");
table.addCell("seq_no.local_checkpoint", "alias:sql,localCheckpoint;default:false;text-align:right;desc:local checkpoint");

View File

@ -88,7 +88,8 @@ public class RestThreadPoolAction extends AbstractCatAction {
client.admin().cluster().nodesStats(nodesStatsRequest, new RestResponseListener<NodesStatsResponse>(channel) {
@Override
public RestResponse buildResponse(NodesStatsResponse nodesStatsResponse) throws Exception {
return RestTable.buildResponse(buildTable(request, clusterStateResponse, nodesInfoResponse, nodesStatsResponse), channel);
return RestTable.buildResponse(
buildTable(request, clusterStateResponse, nodesInfoResponse, nodesStatsResponse), channel);
}
});
}

View File

@ -166,7 +166,6 @@ public class QueryPhase implements SearchPhase {
}
// ... and stop collecting after ${size} matches
searchContext.terminateAfter(searchContext.size());
searchContext.trackTotalHitsUpTo(SearchContext.TRACK_TOTAL_HITS_DISABLED);
} else if (canEarlyTerminate(reader, searchContext.sort())) {
// now this gets interesting: since the search sort is a prefix of the index sort, we can directly
// skip to the desired doc
@ -177,7 +176,6 @@ public class QueryPhase implements SearchPhase {
.build();
query = bq;
}
searchContext.trackTotalHitsUpTo(SearchContext.TRACK_TOTAL_HITS_DISABLED);
}
}
}

View File

@ -217,8 +217,6 @@ abstract class TopDocsCollectorContext extends QueryCollectorContext {
super(REASON_SEARCH_TOP_HITS, numHits);
this.sortAndFormats = sortAndFormats;
// implicit total hit counts are valid only when there is no filter collector in the chain
final int hitCount = hasFilterCollector ? -1 : shortcutTotalHitCount(reader, query);
final TopDocsCollector<?> topDocsCollector;
if (trackTotalHitsUpTo == SearchContext.TRACK_TOTAL_HITS_DISABLED) {
// don't compute hit counts via the collector
@ -226,6 +224,8 @@ abstract class TopDocsCollectorContext extends QueryCollectorContext {
topDocsSupplier = new CachedSupplier<>(topDocsCollector::topDocs);
totalHitsSupplier = () -> new TotalHits(0, TotalHits.Relation.GREATER_THAN_OR_EQUAL_TO);
} else {
// implicit total hit counts are valid only when there is no filter collector in the chain
final int hitCount = hasFilterCollector ? -1 : shortcutTotalHitCount(reader, query);
if (hitCount == -1) {
topDocsCollector = createCollector(sortAndFormats, numHits, searchAfter, trackTotalHitsUpTo);
topDocsSupplier = new CachedSupplier<>(topDocsCollector::topDocs);
@ -293,12 +293,11 @@ abstract class TopDocsCollectorContext extends QueryCollectorContext {
@Override
void postProcess(QuerySearchResult result) throws IOException {
final TopDocs topDocs = topDocsSupplier.get();
topDocs.totalHits = totalHitsSupplier.get();
float maxScore = maxScoreSupplier.get();
final float maxScore;
if (scrollContext.totalHits == null) {
// first round
scrollContext.totalHits = topDocs.totalHits;
scrollContext.maxScore = maxScore;
topDocs.totalHits = scrollContext.totalHits = totalHitsSupplier.get();
maxScore = scrollContext.maxScore = maxScoreSupplier.get();
} else {
// subsequent round: the total number of hits and
// the maximum score were computed on the first round
@ -367,7 +366,7 @@ abstract class TopDocsCollectorContext extends QueryCollectorContext {
// we can disable the tracking of total hits after the initial scroll query
// since the total hits is preserved in the scroll context.
int trackTotalHitsUpTo = searchContext.scrollContext().totalHits != null ?
SearchContext.TRACK_TOTAL_HITS_DISABLED : searchContext.trackTotalHitsUpTo();
SearchContext.TRACK_TOTAL_HITS_DISABLED : SearchContext.TRACK_TOTAL_HITS_ACCURATE;
// no matter what the value of from is
int numDocs = Math.min(searchContext.size(), totalNumDocs);
return new ScrollingTopDocsCollectorContext(reader, query, searchContext.scrollContext(),

View File

@ -257,7 +257,8 @@ public class ExplainActionIT extends ESIntegTestCase {
refresh();
ExplainResponse explainResponse = client().prepareExplain("test", "type", "1").setQuery(queryStringQuery("past:[now-2M/d TO now/d]")).get();
ExplainResponse explainResponse = client().prepareExplain("test", "type", "1")
.setQuery(queryStringQuery("past:[now-2M/d TO now/d]")).get();
assertThat(explainResponse.isExists(), equalTo(true));
assertThat(explainResponse.isMatch(), equalTo(true));
}

View File

@ -36,8 +36,10 @@ import org.elasticsearch.common.io.stream.BytesStreamOutput;
import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.common.xcontent.XContentBuilder;
import org.elasticsearch.common.xcontent.XContentFactory;
import org.elasticsearch.common.xcontent.XContentParser;
import org.elasticsearch.common.xcontent.json.JsonXContent;
import org.elasticsearch.index.get.GetResult;
import org.elasticsearch.index.mapper.MapperService;
import org.elasticsearch.search.internal.SearchContext;
import org.elasticsearch.test.AbstractQueryTestCase;
import org.elasticsearch.test.VersionUtils;
@ -94,7 +96,7 @@ public class GeoShapeQueryBuilderTests extends AbstractQueryTestCase<GeoShapeQue
} else {
indexedShapeToReturn = shape;
indexedShapeId = randomAlphaOfLengthBetween(3, 20);
indexedShapeType = randomAlphaOfLengthBetween(3, 20);
indexedShapeType = randomBoolean() ? randomAlphaOfLengthBetween(3, 20) : null;
builder = new GeoShapeQueryBuilder(fieldName(), indexedShapeId, indexedShapeType);
if (randomBoolean()) {
indexedShapeIndex = randomAlphaOfLengthBetween(3, 20);
@ -126,15 +128,17 @@ public class GeoShapeQueryBuilderTests extends AbstractQueryTestCase<GeoShapeQue
@Override
protected GetResponse executeGet(GetRequest getRequest) {
String indexedType = indexedShapeType != null ? indexedShapeType : MapperService.SINGLE_MAPPING_NAME;
assertThat(indexedShapeToReturn, notNullValue());
assertThat(indexedShapeId, notNullValue());
assertThat(indexedShapeType, notNullValue());
assertThat(getRequest.id(), equalTo(indexedShapeId));
assertThat(getRequest.type(), equalTo(indexedShapeType));
assertThat(getRequest.type(), equalTo(indexedType));
assertThat(getRequest.routing(), equalTo(indexedShapeRouting));
String expectedShapeIndex = indexedShapeIndex == null ? GeoShapeQueryBuilder.DEFAULT_SHAPE_INDEX_NAME : indexedShapeIndex;
assertThat(getRequest.index(), equalTo(expectedShapeIndex));
String expectedShapePath = indexedShapePath == null ? GeoShapeQueryBuilder.DEFAULT_SHAPE_FIELD_NAME : indexedShapePath;
String json;
try {
XContentBuilder builder = XContentFactory.jsonBuilder().prettyPrint();
@ -146,7 +150,7 @@ public class GeoShapeQueryBuilderTests extends AbstractQueryTestCase<GeoShapeQue
} catch (IOException ex) {
throw new ElasticsearchException("boom", ex);
}
return new GetResponse(new GetResult(indexedShapeIndex, indexedShapeType, indexedShapeId, 0, 1, 0, true, new BytesArray(json),
return new GetResponse(new GetResult(indexedShapeIndex, indexedType, indexedShapeId, 0, 1, 0, true, new BytesArray(json),
null));
}
@ -176,19 +180,13 @@ public class GeoShapeQueryBuilderTests extends AbstractQueryTestCase<GeoShapeQue
}
public void testNoShape() throws IOException {
expectThrows(IllegalArgumentException.class, () -> new GeoShapeQueryBuilder(fieldName(), null));
expectThrows(IllegalArgumentException.class, () -> new GeoShapeQueryBuilder(fieldName(), (ShapeBuilder) null));
}
public void testNoIndexedShape() throws IOException {
IllegalArgumentException e = expectThrows(IllegalArgumentException.class,
() -> new GeoShapeQueryBuilder(fieldName(), null, "type"));
assertEquals("either shapeBytes or indexedShapeId and indexedShapeType are required", e.getMessage());
}
public void testNoIndexedShapeType() throws IOException {
IllegalArgumentException e = expectThrows(IllegalArgumentException.class,
() -> new GeoShapeQueryBuilder(fieldName(), "id", null));
assertEquals("indexedShapeType is required if indexedShapeId is specified", e.getMessage());
assertEquals("either shape or indexedShapeId is required", e.getMessage());
}
public void testNoRelation() throws IOException {
@ -286,4 +284,16 @@ public class GeoShapeQueryBuilderTests extends AbstractQueryTestCase<GeoShapeQue
builder = rewriteAndFetch(builder, createShardContext());
builder.writeTo(new BytesStreamOutput(10));
}
@Override
protected QueryBuilder parseQuery(XContentParser parser) throws IOException {
QueryBuilder query = super.parseQuery(parser);
assertThat(query, instanceOf(GeoShapeQueryBuilder.class));
GeoShapeQueryBuilder shapeQuery = (GeoShapeQueryBuilder) query;
if (shapeQuery.indexedShapeType() != null) {
assertWarnings(GeoShapeQueryBuilder.TYPES_DEPRECATION_MESSAGE);
}
return query;
}
}

View File

@ -25,6 +25,7 @@ import org.apache.lucene.search.Query;
import org.apache.lucene.search.TermInSetQuery;
import org.elasticsearch.cluster.metadata.MetaData;
import org.elasticsearch.common.ParsingException;
import org.elasticsearch.common.xcontent.XContentParser;
import org.elasticsearch.index.mapper.IdFieldMapper;
import org.elasticsearch.search.internal.SearchContext;
import org.elasticsearch.test.AbstractQueryTestCase;
@ -48,7 +49,7 @@ public class IdsQueryBuilderTests extends AbstractQueryTestCase<IdsQueryBuilder>
type = randomAlphaOfLengthBetween(1, 10);
}
} else if (randomBoolean()) {
type = MetaData.ALL;
type = MetaData.ALL;
} else {
type = null;
}
@ -152,4 +153,16 @@ public class IdsQueryBuilderTests extends AbstractQueryTestCase<IdsQueryBuilder>
assertThat(parsed.ids(), contains("1","100","4"));
assertEquals(json, 0, parsed.types().length);
}
@Override
protected QueryBuilder parseQuery(XContentParser parser) throws IOException {
QueryBuilder query = super.parseQuery(parser);
assertThat(query, instanceOf(IdsQueryBuilder.class));
IdsQueryBuilder idsQuery = (IdsQueryBuilder) query;
if (idsQuery.types().length > 0) {
assertWarnings(IdsQueryBuilder.TYPES_DEPRECATION_MESSAGE);
}
return query;
}
}

View File

@ -59,8 +59,7 @@ public class LegacyGeoShapeFieldQueryTests extends GeoShapeQueryBuilderTests {
} else {
indexedShapeToReturn = shape;
indexedShapeId = randomAlphaOfLengthBetween(3, 20);
indexedShapeType = randomAlphaOfLengthBetween(3, 20);
builder = new GeoShapeQueryBuilder(fieldName(), indexedShapeId, indexedShapeType);
builder = new GeoShapeQueryBuilder(fieldName(), indexedShapeId);
if (randomBoolean()) {
indexedShapeIndex = randomAlphaOfLengthBetween(3, 20);
builder.indexedShapeIndex(indexedShapeIndex);

Some files were not shown because too many files have changed in this diff Show More