|
13 | 13 | import org.elasticsearch.action.support.PlainActionFuture;
|
14 | 14 | import org.elasticsearch.cluster.metadata.IndexMetadata;
|
15 | 15 | import org.elasticsearch.common.settings.Settings;
|
| 16 | +import org.elasticsearch.common.util.CollectionUtils; |
| 17 | +import org.elasticsearch.common.util.set.Sets; |
| 18 | +import org.elasticsearch.index.Index; |
| 19 | +import org.elasticsearch.index.IndexSettings; |
| 20 | +import org.elasticsearch.index.engine.EngineException; |
| 21 | +import org.elasticsearch.index.engine.EngineFactory; |
| 22 | +import org.elasticsearch.index.engine.InternalEngine; |
| 23 | +import org.elasticsearch.index.shard.ShardId; |
| 24 | +import org.elasticsearch.plugins.EnginePlugin; |
| 25 | +import org.elasticsearch.plugins.Plugin; |
16 | 26 | import org.elasticsearch.test.ESIntegTestCase;
|
17 | 27 | import org.elasticsearch.xcontent.XContentBuilder;
|
18 | 28 | import org.elasticsearch.xcontent.XContentFactory;
|
| 29 | +import org.junit.Before; |
| 30 | + |
| 31 | +import java.util.Collection; |
| 32 | +import java.util.List; |
| 33 | +import java.util.Optional; |
| 34 | +import java.util.Set; |
| 35 | +import java.util.stream.IntStream; |
19 | 36 |
|
20 | 37 | import static org.hamcrest.Matchers.equalTo;
|
21 | 38 | import static org.hamcrest.Matchers.greaterThan;
|
22 | 39 |
|
23 | 40 | public class IndexDiskUsageAnalyzerIT extends ESIntegTestCase {
|
24 | 41 |
|
| 42 | + @Override |
| 43 | + protected boolean addMockInternalEngine() { |
| 44 | + return false; |
| 45 | + } |
| 46 | + |
| 47 | + @Override |
| 48 | + protected Collection<Class<? extends Plugin>> nodePlugins() { |
| 49 | + return CollectionUtils.appendToCopy(super.nodePlugins(), EngineTestPlugin.class); |
| 50 | + } |
| 51 | + |
| 52 | + private static final Set<ShardId> failOnFlushShards = Sets.newConcurrentHashSet(); |
| 53 | + |
| 54 | + public static class EngineTestPlugin extends Plugin implements EnginePlugin { |
| 55 | + @Override |
| 56 | + public Optional<EngineFactory> getEngineFactory(IndexSettings indexSettings) { |
| 57 | + return Optional.of(config -> new InternalEngine(config) { |
| 58 | + @Override |
| 59 | + public void flush(boolean force, boolean waitIfOngoing) throws EngineException { |
| 60 | + final ShardId shardId = config.getShardId(); |
| 61 | + if (failOnFlushShards.contains(shardId)) { |
| 62 | + throw new EngineException(shardId, "simulated IO"); |
| 63 | + } |
| 64 | + super.flush(force, waitIfOngoing); |
| 65 | + } |
| 66 | + }); |
| 67 | + } |
| 68 | + } |
| 69 | + |
| 70 | + @Before |
| 71 | + public void resetFailOnFlush() throws Exception { |
| 72 | + failOnFlushShards.clear(); |
| 73 | + } |
| 74 | + |
25 | 75 | public void testSimple() throws Exception {
|
26 | 76 | final XContentBuilder mapping = XContentFactory.jsonBuilder();
|
27 | 77 | mapping.startObject();
|
@@ -152,6 +202,43 @@ public void testGeoShape() throws Exception {
|
152 | 202 | assertMetadataFields(stats);
|
153 | 203 | }
|
154 | 204 |
|
| 205 | + public void testFailOnFlush() throws Exception { |
| 206 | + final String indexName = "test-index"; |
| 207 | + int numberOfShards = between(1, 5); |
| 208 | + client().admin() |
| 209 | + .indices() |
| 210 | + .prepareCreate(indexName) |
| 211 | + .setSettings( |
| 212 | + Settings.builder() |
| 213 | + .put(IndexMetadata.SETTING_NUMBER_OF_SHARDS, numberOfShards) |
| 214 | + .put(IndexMetadata.SETTING_NUMBER_OF_REPLICAS, between(0, 1)) |
| 215 | + ) |
| 216 | + .get(); |
| 217 | + ensureYellow(indexName); |
| 218 | + int numDocs = randomIntBetween(1, 10); |
| 219 | + for (int i = 0; i < numDocs; i++) { |
| 220 | + int value = randomIntBetween(1, 10); |
| 221 | + final XContentBuilder doc = XContentFactory.jsonBuilder() |
| 222 | + .startObject() |
| 223 | + .field("english_text", English.intToEnglish(value)) |
| 224 | + .field("value", value) |
| 225 | + .endObject(); |
| 226 | + client().prepareIndex(indexName).setId("id-" + i).setSource(doc).get(); |
| 227 | + } |
| 228 | + Index index = clusterService().state().metadata().index(indexName).getIndex(); |
| 229 | + List<ShardId> failedShards = randomSubsetOf( |
| 230 | + between(1, numberOfShards), |
| 231 | + IntStream.range(0, numberOfShards).mapToObj(n -> new ShardId(index, n)).toList() |
| 232 | + ); |
| 233 | + failOnFlushShards.addAll(failedShards); |
| 234 | + AnalyzeIndexDiskUsageResponse resp = client().execute( |
| 235 | + AnalyzeIndexDiskUsageAction.INSTANCE, |
| 236 | + new AnalyzeIndexDiskUsageRequest(new String[] { indexName }, AnalyzeIndexDiskUsageRequest.DEFAULT_INDICES_OPTIONS, true) |
| 237 | + ).actionGet(); |
| 238 | + assertThat(resp.getTotalShards(), equalTo(numberOfShards)); |
| 239 | + assertThat(resp.getFailedShards(), equalTo(failedShards.size())); |
| 240 | + } |
| 241 | + |
155 | 242 | void assertMetadataFields(IndexDiskUsageStats stats) {
|
156 | 243 | final IndexDiskUsageStats.PerFieldDiskUsage sourceField = stats.getFields().get("_source");
|
157 | 244 | assertThat(sourceField.getInvertedIndexBytes(), equalTo(0L));
|
|
0 commit comments