private void writeIndex( String reason, IndexMetaData indexMetaData, @Nullable IndexMetaData previousIndexMetaData) throws Exception { logger.trace("[{}] writing state, reason [{}]", indexMetaData.index(), reason); XContentBuilder builder = XContentFactory.contentBuilder(format, new BytesStreamOutput()); builder.startObject(); IndexMetaData.Builder.toXContent(indexMetaData, builder, formatParams); builder.endObject(); builder.flush(); String stateFileName = "state-" + indexMetaData.version(); Exception lastFailure = null; boolean wroteAtLeastOnce = false; for (File indexLocation : nodeEnv.indexLocations(new Index(indexMetaData.index()))) { File stateLocation = new File(indexLocation, "_state"); FileSystemUtils.mkdirs(stateLocation); File stateFile = new File(stateLocation, stateFileName); FileOutputStream fos = null; try { fos = new FileOutputStream(stateFile); BytesReference bytes = builder.bytes(); fos.write(bytes.array(), bytes.arrayOffset(), bytes.length()); fos.getChannel().force(true); fos.close(); wroteAtLeastOnce = true; } catch (Exception e) { lastFailure = e; } finally { IOUtils.closeWhileHandlingException(fos); } } if (!wroteAtLeastOnce) { logger.warn("[{}]: failed to state", lastFailure, indexMetaData.index()); throw new IOException( "failed to write state for [" + indexMetaData.index() + "]", lastFailure); } // delete the old files if (previousIndexMetaData != null && previousIndexMetaData.version() != indexMetaData.version()) { for (File indexLocation : nodeEnv.indexLocations(new Index(indexMetaData.index()))) { File[] files = new File(indexLocation, "_state").listFiles(); if (files == null) { continue; } for (File file : files) { if (!file.getName().startsWith("state-")) { continue; } if (file.getName().equals(stateFileName)) { continue; } file.delete(); } } } }
@Test public void testPutWarmerAcknowledgement() { createIndex("test"); // make sure one shard is started so the search during put warmer will not fail index("test", "type", "1", "f", 1); assertAcked( client() .admin() .indices() .preparePutWarmer("custom_warmer") .setSearchRequest( client() .prepareSearch("test") .setTypes("test") .setQuery(QueryBuilders.matchAllQuery()))); for (Client client : clients()) { GetWarmersResponse getWarmersResponse = client.admin().indices().prepareGetWarmers().setLocal(true).get(); assertThat(getWarmersResponse.warmers().size(), equalTo(1)); ObjectObjectCursor<String, List<IndexWarmersMetaData.Entry>> entry = getWarmersResponse.warmers().iterator().next(); assertThat(entry.key, equalTo("test")); assertThat(entry.value.size(), equalTo(1)); assertThat(entry.value.get(0).name(), equalTo("custom_warmer")); } }
/** Initializes an index, to be restored from snapshot */ private Builder initializeAsRestore( IndexMetaData indexMetaData, RestoreSource restoreSource, boolean asNew) { if (!shards.isEmpty()) { throw new ElasticSearchIllegalStateException( "trying to initialize an index with fresh shards, but already has shards created"); } for (int shardId = 0; shardId < indexMetaData.numberOfShards(); shardId++) { IndexShardRoutingTable.Builder indexShardRoutingBuilder = new IndexShardRoutingTable.Builder( new ShardId(indexMetaData.index(), shardId), asNew ? false : true); for (int i = 0; i <= indexMetaData.numberOfReplicas(); i++) { indexShardRoutingBuilder.addShard( new ImmutableShardRouting( index, shardId, null, null, i == 0 ? restoreSource : null, i == 0, ShardRoutingState.UNASSIGNED, 0)); } shards.put(shardId, indexShardRoutingBuilder.build()); } return this; }
@Test public void testDeleteWarmerAcknowledgement() { createIndex("test"); index("test", "type", "1", "f", 1); assertAcked( client() .admin() .indices() .preparePutWarmer("custom_warmer") .setSearchRequest( client() .prepareSearch("test") .setTypes("test") .setQuery(QueryBuilders.matchAllQuery()))); assertAcked( client() .admin() .indices() .prepareDeleteWarmer() .setIndices("test") .setNames("custom_warmer")); for (Client client : clients()) { GetWarmersResponse getWarmersResponse = client.admin().indices().prepareGetWarmers().setLocal(true).get(); assertThat(getWarmersResponse.warmers().size(), equalTo(0)); } }
public Builder(IndexMetaData indexMetaData) { this(indexMetaData.index()); settings(indexMetaData.settings()); mappings.putAll(indexMetaData.mappings); aliases.putAll(indexMetaData.aliases); customs.putAll(indexMetaData.customs); this.state = indexMetaData.state; this.version = indexMetaData.version; }
private void applyDeletedIndices(final ClusterChangedEvent event) { final ClusterState previousState = event.previousState(); final String localNodeId = event.state().nodes().localNodeId(); assert localNodeId != null; for (IndexService indexService : indicesService) { IndexMetaData indexMetaData = event.state().metaData().index(indexService.index().name()); if (indexMetaData != null) { if (!indexMetaData.isSameUUID(indexService.indexUUID())) { logger.debug( "[{}] mismatch on index UUIDs between cluster state and local state, cleaning the index so it will be recreated", indexMetaData.index()); deleteIndex( indexMetaData.index(), "mismatch on index UUIDs between cluster state and local state, cleaning the index so it will be recreated"); } } } for (String index : event.indicesDeleted()) { if (logger.isDebugEnabled()) { logger.debug("[{}] cleaning index, no longer part of the metadata", index); } final Settings indexSettings; final IndexService idxService = indicesService.indexService(index); if (idxService != null) { indexSettings = idxService.getIndexSettings(); deleteIndex(index, "index no longer part of the metadata"); } else { final IndexMetaData metaData = previousState.metaData().index(index); assert metaData != null; indexSettings = metaData.settings(); indicesService.deleteClosedIndex( "closed index no longer part of the metadata", metaData, event.state()); } try { nodeIndexDeletedAction.nodeIndexDeleted(event.state(), index, indexSettings, localNodeId); } catch (Throwable e) { logger.debug("failed to send to master index {} deleted event", e, index); } } }
/** * Finds new dangling indices by iterating over the indices and trying to find indices that have * state on disk, but are not part of the provided meta data, or not detected as dangled already. */ Map<String, IndexMetaData> findNewDanglingIndices(MetaData metaData) { final Set<String> indices; try { indices = nodeEnv.findAllIndices(); } catch (Throwable e) { logger.warn("failed to list dangling indices", e); return ImmutableMap.of(); } Map<String, IndexMetaData> newIndices = Maps.newHashMap(); for (String indexName : indices) { if (metaData.hasIndex(indexName) == false && danglingIndices.containsKey(indexName) == false) { try { IndexMetaData indexMetaData = metaStateService.loadIndexState(indexName); if (indexMetaData != null) { logger.info( "[{}] dangling index, exists on local file system, but not in cluster metadata, auto import to cluster state", indexName); if (!indexMetaData.index().equals(indexName)) { logger.info( "dangled index directory name is [{}], state name is [{}], renaming to directory name", indexName, indexMetaData.index()); indexMetaData = IndexMetaData.builder(indexMetaData).index(indexName).build(); } newIndices.put(indexName, indexMetaData); } else { logger.debug("[{}] dangling index directory detected, but no state found", indexName); } } catch (Throwable t) { logger.warn("[{}] failed to load index state for detected dangled index", t, indexName); } } } return newIndices; }
private void applyNewIndices(final ClusterChangedEvent event) { // we only create indices for shards that are allocated RoutingNodes.RoutingNodeIterator routingNode = event.state().readOnlyRoutingNodes().routingNodeIter(event.state().nodes().localNodeId()); if (routingNode == null) { return; } for (ShardRouting shard : routingNode) { if (!indicesService.hasIndex(shard.index())) { final IndexMetaData indexMetaData = event.state().metaData().index(shard.index()); if (logger.isDebugEnabled()) { logger.debug("[{}] creating index", indexMetaData.index()); } try { indicesService.createIndex( indexMetaData.index(), indexMetaData.settings(), event.state().nodes().localNode().id()); } catch (Throwable e) { sendFailShard(shard, indexMetaData.getIndexUUID(), "failed to create index", e); } } } }
@Override public void clusterChanged(ClusterChangedEvent event) { if (event.state().blocks().disableStatePersistence()) { // reset the current metadata, we need to start fresh... this.currentMetaData = null; return; } MetaData newMetaData = event.state().metaData(); // delete indices that were there before, but are deleted now // we need to do it so they won't be detected as dangling if (currentMetaData != null) { // only delete indices when we already received a state (currentMetaData != null) for (IndexMetaData current : currentMetaData) { if (!newMetaData.hasIndex(current.index())) { logger.debug( "[{}] deleting index that is no longer part of the metadata (indices: [{}])", current.index(), newMetaData.indices().keys()); if (nodeEnv.hasNodeFile()) { FileSystemUtils.deleteRecursively(nodeEnv.indexLocations(new Index(current.index()))); } try { nodeIndexDeletedAction.nodeIndexStoreDeleted( event.state(), current.index(), event.state().nodes().localNodeId()); } catch (Exception e) { logger.debug( "[{}] failed to notify master on local index store deletion", e, current.index()); } } } } currentMetaData = newMetaData; }
private void applySettings(ClusterChangedEvent event) { if (!event.metaDataChanged()) { return; } for (IndexMetaData indexMetaData : event.state().metaData()) { if (!indicesService.hasIndex(indexMetaData.index())) { // we only create / update here continue; } // if the index meta data didn't change, no need check for refreshed settings if (!event.indexMetaDataChanged(indexMetaData)) { continue; } String index = indexMetaData.index(); IndexService indexService = indicesService.indexService(index); if (indexService == null) { // already deleted on us, ignore it continue; } IndexSettingsService indexSettingsService = indexService.injector().getInstance(IndexSettingsService.class); indexSettingsService.refreshSettings(indexMetaData.settings()); } }
private void applyAliases(ClusterChangedEvent event) { // check if aliases changed if (aliasesChanged(event)) { // go over and update aliases for (IndexMetaData indexMetaData : event.state().metaData()) { String index = indexMetaData.index(); IndexService indexService = indicesService.indexService(index); if (indexService == null) { // we only create / update here continue; } IndexAliasesService indexAliasesService = indexService.aliasesService(); indexAliasesService.setAliases(indexMetaData.getAliases()); } } }
@Test public void testPutWarmerNoAcknowledgement() throws InterruptedException { createIndex("test"); // make sure one shard is started so the search during put warmer will not fail index("test", "type", "1", "f", 1); PutWarmerResponse putWarmerResponse = client() .admin() .indices() .preparePutWarmer("custom_warmer") .setTimeout("0s") .setSearchRequest( client() .prepareSearch("test") .setTypes("test") .setQuery(QueryBuilders.matchAllQuery())) .get(); assertThat(putWarmerResponse.isAcknowledged(), equalTo(false)); /* Since we don't wait for the ack here we have to wait until the search request has been executed from the master * otherwise the test infra might have already deleted the index and the search request fails on all shards causing * the test to fail too. We simply wait until the the warmer has been installed and also clean it up afterwards.*/ assertTrue( awaitBusy( new Predicate<Object>() { @Override public boolean apply(Object input) { for (Client client : clients()) { GetWarmersResponse getWarmersResponse = client.admin().indices().prepareGetWarmers().setLocal(true).get(); if (getWarmersResponse.warmers().size() != 1) { return false; } } return true; } })); assertAcked( client() .admin() .indices() .prepareDeleteWarmer() .setIndices("test") .setNames("custom_warmer")); }
public static void toXContent( IndexMetaData indexMetaData, XContentBuilder builder, ToXContent.Params params) throws IOException { builder.startObject(indexMetaData.index(), XContentBuilder.FieldCaseConversion.NONE); builder.field("version", indexMetaData.version()); builder.field("state", indexMetaData.state().toString().toLowerCase(Locale.ENGLISH)); boolean binary = params.paramAsBoolean("binary", false); builder.startObject("settings"); for (Map.Entry<String, String> entry : indexMetaData.settings().getAsMap().entrySet()) { builder.field(entry.getKey(), entry.getValue()); } builder.endObject(); builder.startArray("mappings"); for (Map.Entry<String, MappingMetaData> entry : indexMetaData.mappings().entrySet()) { if (binary) { builder.value(entry.getValue().source().compressed()); } else { byte[] data = entry.getValue().source().uncompressed(); XContentParser parser = XContentFactory.xContent(data).createParser(data); Map<String, Object> mapping = parser.mapOrdered(); parser.close(); builder.map(mapping); } } builder.endArray(); for (Map.Entry<String, Custom> entry : indexMetaData.customs().entrySet()) { builder.startObject(entry.getKey(), XContentBuilder.FieldCaseConversion.NONE); lookupFactorySafe(entry.getKey()).toXContent(entry.getValue(), builder, params); builder.endObject(); } builder.startObject("aliases"); for (AliasMetaData alias : indexMetaData.aliases().values()) { AliasMetaData.Builder.toXContent(alias, builder, params); } builder.endObject(); builder.endObject(); }
public static void writeTo(IndexMetaData indexMetaData, StreamOutput out) throws IOException { out.writeUTF(indexMetaData.index()); out.writeLong(indexMetaData.version()); out.writeByte(indexMetaData.state().id()); writeSettingsToStream(indexMetaData.settings(), out); out.writeVInt(indexMetaData.mappings().size()); for (MappingMetaData mappingMd : indexMetaData.mappings().values()) { MappingMetaData.writeTo(mappingMd, out); } out.writeVInt(indexMetaData.aliases().size()); for (AliasMetaData aliasMd : indexMetaData.aliases().values()) { AliasMetaData.Builder.writeTo(aliasMd, out); } out.writeVInt(indexMetaData.customs().size()); for (Map.Entry<String, Custom> entry : indexMetaData.customs().entrySet()) { out.writeUTF(entry.getKey()); lookupFactorySafe(entry.getKey()).writeTo(entry.getValue(), out); } }
@Test public void testDeleteWarmerNoAcknowledgement() throws InterruptedException { createIndex("test"); index("test", "type", "1", "f", 1); assertAcked( client() .admin() .indices() .preparePutWarmer("custom_warmer") .setSearchRequest( client() .prepareSearch("test") .setTypes("test") .setQuery(QueryBuilders.matchAllQuery()))); DeleteWarmerResponse deleteWarmerResponse = client() .admin() .indices() .prepareDeleteWarmer() .setIndices("test") .setNames("custom_warmer") .setTimeout("0s") .get(); assertFalse(deleteWarmerResponse.isAcknowledged()); assertTrue( awaitBusy( new Predicate<Object>() { // wait until they are all deleted @Override public boolean apply(Object input) { for (Client client : clients()) { GetWarmersResponse getWarmersResponse = client.admin().indices().prepareGetWarmers().setLocal(true).get(); if (getWarmersResponse.warmers().size() > 0) { return false; } } return true; } })); }
/** @return the name of the underlying index even if this table is referenced by alias */ public String concreteIndexName() { return metaData.index(); }
private void applyMappings(ClusterChangedEvent event) { // go over and update mappings for (IndexMetaData indexMetaData : event.state().metaData()) { if (!indicesService.hasIndex(indexMetaData.index())) { // we only create / update here continue; } List<String> typesToRefresh = Lists.newArrayList(); String index = indexMetaData.index(); IndexService indexService = indicesService.indexService(index); if (indexService == null) { // got deleted on us, ignore (closing the node) return; } try { MapperService mapperService = indexService.mapperService(); // first, go over and update the _default_ mapping (if exists) if (indexMetaData.mappings().containsKey(MapperService.DEFAULT_MAPPING)) { boolean requireRefresh = processMapping( index, mapperService, MapperService.DEFAULT_MAPPING, indexMetaData.mapping(MapperService.DEFAULT_MAPPING).source()); if (requireRefresh) { typesToRefresh.add(MapperService.DEFAULT_MAPPING); } } // go over and add the relevant mappings (or update them) for (ObjectCursor<MappingMetaData> cursor : indexMetaData.mappings().values()) { MappingMetaData mappingMd = cursor.value; String mappingType = mappingMd.type(); CompressedXContent mappingSource = mappingMd.source(); if (mappingType.equals(MapperService.DEFAULT_MAPPING)) { // we processed _default_ first continue; } boolean requireRefresh = processMapping(index, mapperService, mappingType, mappingSource); if (requireRefresh) { typesToRefresh.add(mappingType); } } if (!typesToRefresh.isEmpty() && sendRefreshMapping) { nodeMappingRefreshAction.nodeMappingRefresh( event.state(), new NodeMappingRefreshAction.NodeMappingRefreshRequest( index, indexMetaData.indexUUID(), typesToRefresh.toArray(new String[typesToRefresh.size()]), event.state().nodes().localNodeId())); } } catch (Throwable t) { // if we failed the mappings anywhere, we need to fail the shards for this index, note, we // safeguard // by creating the processing the mappings on the master, or on the node the mapping was // introduced on, // so this failure typically means wrong node level configuration or something similar for (IndexShard indexShard : indexService) { ShardRouting shardRouting = indexShard.routingEntry(); failAndRemoveShard(shardRouting, indexService, true, "failed to update mappings", t); } } } }
@Override public void clusterChanged(ClusterChangedEvent event) { if (event.state().blocks().disableStatePersistence()) { // reset the current metadata, we need to start fresh... this.currentMetaData = null; return; } MetaData newMetaData = event.state().metaData(); // we don't check if metaData changed, since we might be called several times and we need to // check dangling... boolean success = true; // only applied to master node, writing the global and index level states if (event.state().nodes().localNode().masterNode()) { // check if the global state changed? if (currentMetaData == null || !MetaData.isGlobalStateEquals(currentMetaData, newMetaData)) { try { writeGlobalState("changed", newMetaData, currentMetaData); } catch (Exception e) { success = false; } } // check and write changes in indices for (IndexMetaData indexMetaData : newMetaData) { String writeReason = null; IndexMetaData currentIndexMetaData; if (currentMetaData == null) { // a new event..., check from the state stored currentIndexMetaData = loadIndex(indexMetaData.index()); } else { currentIndexMetaData = currentMetaData.index(indexMetaData.index()); } if (currentIndexMetaData == null) { writeReason = "freshly created"; } else if (currentIndexMetaData.version() != indexMetaData.version()) { writeReason = "version changed from [" + currentIndexMetaData.version() + "] to [" + indexMetaData.version() + "]"; } // we update the writeReason only if we really need to write it if (writeReason == null) { continue; } try { writeIndex(writeReason, indexMetaData, currentIndexMetaData); } catch (Exception e) { success = false; } } } // delete indices that were there before, but are deleted now // we need to do it so they won't be detected as dangling if (nodeEnv.hasNodeFile()) { if (currentMetaData != null) { // only delete indices when we already received a state (currentMetaData != null) // and we had a go at processing dangling indices at least once // this will also delete the _state of the index itself for (IndexMetaData current : currentMetaData) { if (danglingIndices.containsKey(current.index())) { continue; } if (!newMetaData.hasIndex(current.index())) { logger.debug( "[{}] deleting index that is no longer part of the metadata (indices: [{}])", current.index(), newMetaData.indices().keySet()); FileSystemUtils.deleteRecursively(nodeEnv.indexLocations(new Index(current.index()))); } } } } // handle dangling indices, we handle those for all nodes that have a node file (data or master) if (nodeEnv.hasNodeFile()) { if (danglingTimeout.millis() >= 0) { synchronized (danglingMutex) { for (String danglingIndex : danglingIndices.keySet()) { if (newMetaData.hasIndex(danglingIndex)) { logger.debug("[{}] no longer dangling (created), removing", danglingIndex); DanglingIndex removed = danglingIndices.remove(danglingIndex); removed.future.cancel(false); } } // delete indices that are no longer part of the metadata try { for (String indexName : nodeEnv.findAllIndices()) { // if we have the index on the metadata, don't delete it if (newMetaData.hasIndex(indexName)) { continue; } if (danglingIndices.containsKey(indexName)) { // already dangling, continue continue; } IndexMetaData indexMetaData = loadIndex(indexName); if (indexMetaData != null) { if (danglingTimeout.millis() == 0) { logger.info( "[{}] dangling index, exists on local file system, but not in cluster metadata, timeout set to 0, deleting now", indexName); FileSystemUtils.deleteRecursively(nodeEnv.indexLocations(new Index(indexName))); } else { logger.info( "[{}] dangling index, exists on local file system, but not in cluster metadata, scheduling to delete in [{}], auto import to cluster state [{}]", indexName, danglingTimeout, autoImportDangled); danglingIndices.put( indexName, new DanglingIndex( indexName, threadPool.schedule( danglingTimeout, ThreadPool.Names.SAME, new RemoveDanglingIndex(indexName)))); } } } } catch (Exception e) { logger.warn("failed to find dangling indices", e); } } } if (autoImportDangled.shouldImport() && !danglingIndices.isEmpty()) { final List<IndexMetaData> dangled = Lists.newArrayList(); for (String indexName : danglingIndices.keySet()) { IndexMetaData indexMetaData = loadIndex(indexName); if (indexMetaData == null) { logger.debug("failed to find state for dangling index [{}]", indexName); continue; } // we might have someone copying over an index, renaming the directory, handle that if (!indexMetaData.index().equals(indexName)) { logger.info( "dangled index directory name is [{}], state name is [{}], renaming to directory name", indexName, indexMetaData.index()); indexMetaData = IndexMetaData.newIndexMetaDataBuilder(indexMetaData).index(indexName).build(); } if (autoImportDangled == AutoImportDangledState.CLOSED) { indexMetaData = IndexMetaData.newIndexMetaDataBuilder(indexMetaData) .state(IndexMetaData.State.CLOSE) .build(); } if (indexMetaData != null) { dangled.add(indexMetaData); } } IndexMetaData[] dangledIndices = dangled.toArray(new IndexMetaData[dangled.size()]); try { allocateDangledIndices.allocateDangled( dangledIndices, new LocalAllocateDangledIndices.Listener() { @Override public void onResponse( LocalAllocateDangledIndices.AllocateDangledResponse response) { logger.trace("allocated dangled"); } @Override public void onFailure(Throwable e) { logger.info("failed to send allocated dangled", e); } }); } catch (Exception e) { logger.warn("failed to send allocate dangled", e); } } } if (success) { currentMetaData = newMetaData; } }
@Override protected void delete(IndexMetaData indexMetaData) throws ElasticSearchException { BlobPath indexPath = basePath().add("indices").add(indexMetaData.index()); blobStore.delete(indexPath); }
public ClusterIndexHealth(IndexMetaData indexMetaData, IndexRoutingTable indexRoutingTable) { this.index = indexMetaData.index(); this.numberOfShards = indexMetaData.getNumberOfShards(); this.numberOfReplicas = indexMetaData.getNumberOfReplicas(); this.validationFailures = indexRoutingTable.validate(indexMetaData); for (IndexShardRoutingTable shardRoutingTable : indexRoutingTable) { ClusterShardHealth shardHealth = new ClusterShardHealth(shardRoutingTable.shardId().id()); for (ShardRouting shardRouting : shardRoutingTable) { if (shardRouting.active()) { shardHealth.activeShards++; if (shardRouting.relocating()) { // the shard is relocating, the one it is relocating to will be in initializing state, // so we don't count it shardHealth.relocatingShards++; } if (shardRouting.primary()) { shardHealth.primaryActive = true; } } else if (shardRouting.initializing()) { shardHealth.initializingShards++; } else if (shardRouting.unassigned()) { shardHealth.unassignedShards++; } } if (shardHealth.primaryActive) { if (shardHealth.activeShards == shardRoutingTable.size()) { shardHealth.status = ClusterHealthStatus.GREEN; } else { shardHealth.status = ClusterHealthStatus.YELLOW; } } else { shardHealth.status = ClusterHealthStatus.RED; } shards.put(shardHealth.getId(), shardHealth); } // update the index status status = ClusterHealthStatus.GREEN; for (ClusterShardHealth shardHealth : shards.values()) { if (shardHealth.isPrimaryActive()) { activePrimaryShards++; } activeShards += shardHealth.activeShards; relocatingShards += shardHealth.relocatingShards; initializingShards += shardHealth.initializingShards; unassignedShards += shardHealth.unassignedShards; if (shardHealth.getStatus() == ClusterHealthStatus.RED) { status = ClusterHealthStatus.RED; } else if (shardHealth.getStatus() == ClusterHealthStatus.YELLOW && status != ClusterHealthStatus.RED) { // do not override an existing red status = ClusterHealthStatus.YELLOW; } } if (!validationFailures.isEmpty()) { status = ClusterHealthStatus.RED; } else if (shards .isEmpty()) { // might be since none has been created yet (two phase index creation) status = ClusterHealthStatus.RED; } }
private ClusterHealthResponse clusterHealth(ClusterHealthRequest request) { ClusterState clusterState = clusterService.state(); RoutingTableValidation validation = clusterState.routingTable().validate(clusterState.metaData()); ClusterHealthResponse response = new ClusterHealthResponse(clusterName.value(), validation.failures()); response.numberOfNodes = clusterState.nodes().size(); response.numberOfDataNodes = clusterState.nodes().dataNodes().size(); for (String index : clusterState.metaData().concreteIndices(request.indices())) { IndexRoutingTable indexRoutingTable = clusterState.routingTable().index(index); IndexMetaData indexMetaData = clusterState.metaData().index(index); if (indexRoutingTable == null) { continue; } ClusterIndexHealth indexHealth = new ClusterIndexHealth( index, indexMetaData.numberOfShards(), indexMetaData.numberOfReplicas(), validation.indexFailures(indexMetaData.index())); for (IndexShardRoutingTable shardRoutingTable : indexRoutingTable) { ClusterShardHealth shardHealth = new ClusterShardHealth(shardRoutingTable.shardId().id()); for (ShardRouting shardRouting : shardRoutingTable) { if (shardRouting.active()) { shardHealth.activeShards++; if (shardRouting.relocating()) { // the shard is relocating, the one he is relocating to will be in initializing state, // so we don't count it shardHealth.relocatingShards++; } if (shardRouting.primary()) { shardHealth.primaryActive = true; } } else if (shardRouting.initializing()) { shardHealth.initializingShards++; } else if (shardRouting.unassigned()) { shardHealth.unassignedShards++; } } if (shardHealth.primaryActive) { if (shardHealth.activeShards == shardRoutingTable.size()) { shardHealth.status = ClusterHealthStatus.GREEN; } else { shardHealth.status = ClusterHealthStatus.YELLOW; } } else { shardHealth.status = ClusterHealthStatus.RED; } indexHealth.shards.put(shardHealth.id(), shardHealth); } for (ClusterShardHealth shardHealth : indexHealth) { if (shardHealth.primaryActive()) { indexHealth.activePrimaryShards++; } indexHealth.activeShards += shardHealth.activeShards; indexHealth.relocatingShards += shardHealth.relocatingShards; indexHealth.initializingShards += shardHealth.initializingShards; indexHealth.unassignedShards += shardHealth.unassignedShards; } // update the index status indexHealth.status = ClusterHealthStatus.GREEN; if (!indexHealth.validationFailures().isEmpty()) { indexHealth.status = ClusterHealthStatus.RED; } else if (indexHealth .shards() .isEmpty()) { // might be since none has been created yet (two phase index creation) indexHealth.status = ClusterHealthStatus.RED; } else { for (ClusterShardHealth shardHealth : indexHealth) { if (shardHealth.status() == ClusterHealthStatus.RED) { indexHealth.status = ClusterHealthStatus.RED; break; } if (shardHealth.status() == ClusterHealthStatus.YELLOW) { indexHealth.status = ClusterHealthStatus.YELLOW; } } } response.indices.put(indexHealth.index(), indexHealth); } for (ClusterIndexHealth indexHealth : response) { response.activePrimaryShards += indexHealth.activePrimaryShards; response.activeShards += indexHealth.activeShards; response.relocatingShards += indexHealth.relocatingShards; response.initializingShards += indexHealth.initializingShards; response.unassignedShards += indexHealth.unassignedShards; } response.status = ClusterHealthStatus.GREEN; if (!response.validationFailures().isEmpty()) { response.status = ClusterHealthStatus.RED; } else if (clusterState .blocks() .hasGlobalBlock(GatewayService.NOT_RECOVERED_FROM_GATEWAY_BLOCK)) { response.status = ClusterHealthStatus.RED; } else { for (ClusterIndexHealth indexHealth : response) { if (indexHealth.status() == ClusterHealthStatus.RED) { response.status = ClusterHealthStatus.RED; break; } if (indexHealth.status() == ClusterHealthStatus.YELLOW) { response.status = ClusterHealthStatus.YELLOW; } } } return response; }