/* * 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.indexing; import org.elasticsearch.action.bulk.BulkResponse; import org.elasticsearch.action.index.IndexRequestBuilder; import org.elasticsearch.action.index.IndexResponse; import org.elasticsearch.cluster.metadata.MetaDataCreateIndexService; import org.elasticsearch.index.VersionType; import org.elasticsearch.indices.InvalidIndexNameException; import org.elasticsearch.test.ESIntegTestCase; import org.junit.Test; import java.util.ArrayList; import java.util.List; import java.util.Locale; import java.util.Random; import java.util.concurrent.Callable; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.atomic.AtomicIntegerArray; import static org.elasticsearch.test.hamcrest.ElasticsearchAssertions.assertHitCount; import static org.hamcrest.Matchers.equalTo; import static org.hamcrest.Matchers.lessThanOrEqualTo; /** * */ public class IndexActionIT extends ESIntegTestCase { /** * This test tries to simulate load while creating an index and indexing documents * while the index is being created. */ @Test public void testAutoGenerateIdNoDuplicates() throws Exception { int numberOfIterations = scaledRandomIntBetween(10, 50); for (int i = 0; i < numberOfIterations; i++) { Throwable firstError = null; createIndex("test"); int numOfDocs = randomIntBetween(10, 100); logger.info("indexing [{}] docs", numOfDocs); List<IndexRequestBuilder> builders = new ArrayList<>(numOfDocs); for (int j = 0; j < numOfDocs; j++) { builders.add(client().prepareIndex("test", "type").setSource("field", "value")); } indexRandom(true, builders); ensureYellow("test"); logger.info("verifying indexed content"); int numOfChecks = randomIntBetween(8, 12); for (int j = 0; j < numOfChecks; j++) { try { logger.debug("running search with all types"); assertHitCount(client().prepareSearch("test").get(), numOfDocs); } catch (Throwable t) { logger.error("search for all docs types failed", t); if (firstError == null) { firstError = t; } } try { logger.debug("running search with a specific type"); assertHitCount(client().prepareSearch("test").setTypes("type").get(), numOfDocs); } catch (Throwable t) { logger.error("search for all docs of a specific type failed", t); if (firstError == null) { firstError = t; } } } if (firstError != null) { fail(firstError.getMessage()); } internalCluster().wipeIndices("test"); } } @Test public void testCreatedFlag() throws Exception { createIndex("test"); ensureGreen(); IndexResponse indexResponse = client().prepareIndex("test", "type", "1").setSource("field1", "value1_1").execute().actionGet(); assertTrue(indexResponse.isCreated()); indexResponse = client().prepareIndex("test", "type", "1").setSource("field1", "value1_2").execute().actionGet(); assertFalse(indexResponse.isCreated()); client().prepareDelete("test", "type", "1").execute().actionGet(); indexResponse = client().prepareIndex("test", "type", "1").setSource("field1", "value1_2").execute().actionGet(); assertTrue(indexResponse.isCreated()); } @Test public void testCreatedFlagWithFlush() throws Exception { createIndex("test"); ensureGreen(); IndexResponse indexResponse = client().prepareIndex("test", "type", "1").setSource("field1", "value1_1").execute().actionGet(); assertTrue(indexResponse.isCreated()); client().prepareDelete("test", "type", "1").execute().actionGet(); flush(); indexResponse = client().prepareIndex("test", "type", "1").setSource("field1", "value1_2").execute().actionGet(); assertTrue(indexResponse.isCreated()); } @Test public void testCreatedFlagParallelExecution() throws Exception { createIndex("test"); ensureGreen(); int threadCount = 20; final int docCount = 300; int taskCount = docCount * threadCount; final AtomicIntegerArray createdCounts = new AtomicIntegerArray(docCount); ExecutorService threadPool = Executors.newFixedThreadPool(threadCount); List<Callable<Void>> tasks = new ArrayList<>(taskCount); final Random random = getRandom(); for (int i=0;i< taskCount; i++ ) { tasks.add(new Callable<Void>() { @Override public Void call() throws Exception { int docId = random.nextInt(docCount); IndexResponse indexResponse = index("test", "type", Integer.toString(docId), "field1", "value"); if (indexResponse.isCreated()) createdCounts.incrementAndGet(docId); return null; } }); } threadPool.invokeAll(tasks); for (int i=0;i<docCount;i++) { assertThat(createdCounts.get(i), lessThanOrEqualTo(1)); } terminate(threadPool); } @Test public void testCreatedFlagWithExternalVersioning() throws Exception { createIndex("test"); ensureGreen(); IndexResponse indexResponse = client().prepareIndex("test", "type", "1").setSource("field1", "value1_1").setVersion(123) .setVersionType(VersionType.EXTERNAL).execute().actionGet(); assertTrue(indexResponse.isCreated()); } @Test public void testCreateFlagWithBulk() { createIndex("test"); ensureGreen(); BulkResponse bulkResponse = client().prepareBulk().add(client().prepareIndex("test", "type", "1").setSource("field1", "value1_1")).execute().actionGet(); assertThat(bulkResponse.hasFailures(), equalTo(false)); assertThat(bulkResponse.getItems().length, equalTo(1)); IndexResponse indexResponse = bulkResponse.getItems()[0].getResponse(); assertTrue(indexResponse.isCreated()); } @Test public void testCreateIndexWithLongName() { int min = MetaDataCreateIndexService.MAX_INDEX_NAME_BYTES + 1; int max = MetaDataCreateIndexService.MAX_INDEX_NAME_BYTES * 2; try { createIndex(randomAsciiOfLengthBetween(min, max).toLowerCase(Locale.ROOT)); fail("exception should have been thrown on too-long index name"); } catch (InvalidIndexNameException e) { assertThat("exception contains message about index name too long: " + e.getMessage(), e.getMessage().contains("index name is too long,"), equalTo(true)); } try { client().prepareIndex(randomAsciiOfLengthBetween(min, max).toLowerCase(Locale.ROOT), "mytype").setSource("foo", "bar").get(); fail("exception should have been thrown on too-long index name"); } catch (InvalidIndexNameException e) { assertThat("exception contains message about index name too long: " + e.getMessage(), e.getMessage().contains("index name is too long,"), equalTo(true)); } try { // Catch chars that are more than a single byte client().prepareIndex(randomAsciiOfLength(MetaDataCreateIndexService.MAX_INDEX_NAME_BYTES - 1).toLowerCase(Locale.ROOT) + "Ϟ".toLowerCase(Locale.ROOT), "mytype").setSource("foo", "bar").get(); fail("exception should have been thrown on too-long index name"); } catch (InvalidIndexNameException e) { assertThat("exception contains message about index name too long: " + e.getMessage(), e.getMessage().contains("index name is too long,"), equalTo(true)); } // we can create an index of max length createIndex(randomAsciiOfLength(MetaDataCreateIndexService.MAX_INDEX_NAME_BYTES).toLowerCase(Locale.ROOT)); } public void testInvalidIndexName() { try { createIndex("."); fail("exception should have been thrown on dot index name"); } catch (InvalidIndexNameException e) { assertThat("exception contains message about index name is dot " + e.getMessage(), e.getMessage().contains("Invalid index name [.], must not be \'.\' or '..'"), equalTo(true)); } try { createIndex(".."); fail("exception should have been thrown on dot index name"); } catch (InvalidIndexNameException e) { assertThat("exception contains message about index name is dot " + e.getMessage(), e.getMessage().contains("Invalid index name [..], must not be \'.\' or '..'"), equalTo(true)); } } }