/* * 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.cluster.health; import org.elasticsearch.cluster.metadata.IndexMetaData; import org.elasticsearch.cluster.routing.IndexRoutingTable; import org.elasticsearch.cluster.routing.IndexShardRoutingTable; 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; import org.elasticsearch.common.xcontent.XContentBuilder; import java.io.IOException; import java.util.HashMap; import java.util.Iterator; import java.util.Locale; import java.util.Map; public final class ClusterIndexHealth implements Iterable<ClusterShardHealth>, Writeable, ToXContent { private final String index; private final int numberOfShards; private final int numberOfReplicas; private final int activeShards; private final int relocatingShards; private final int initializingShards; private final int unassignedShards; private final int activePrimaryShards; private final ClusterHealthStatus status; private final Map<Integer, ClusterShardHealth> shards = new HashMap<>(); public ClusterIndexHealth(final IndexMetaData indexMetaData, final IndexRoutingTable indexRoutingTable) { this.index = indexMetaData.getIndex().getName(); this.numberOfShards = indexMetaData.getNumberOfShards(); this.numberOfReplicas = indexMetaData.getNumberOfReplicas(); for (IndexShardRoutingTable shardRoutingTable : indexRoutingTable) { int shardId = shardRoutingTable.shardId().id(); shards.put(shardId, new ClusterShardHealth(shardId, shardRoutingTable)); } // update the index status ClusterHealthStatus computeStatus = ClusterHealthStatus.GREEN; int computeActivePrimaryShards = 0; int computeActiveShards = 0; int computeRelocatingShards = 0; int computeInitializingShards = 0; int computeUnassignedShards = 0; for (ClusterShardHealth shardHealth : shards.values()) { if (shardHealth.isPrimaryActive()) { computeActivePrimaryShards++; } computeActiveShards += shardHealth.getActiveShards(); computeRelocatingShards += shardHealth.getRelocatingShards(); computeInitializingShards += shardHealth.getInitializingShards(); computeUnassignedShards += shardHealth.getUnassignedShards(); if (shardHealth.getStatus() == ClusterHealthStatus.RED) { computeStatus = ClusterHealthStatus.RED; } else if (shardHealth.getStatus() == ClusterHealthStatus.YELLOW && computeStatus != ClusterHealthStatus.RED) { // do not override an existing red computeStatus = ClusterHealthStatus.YELLOW; } } if (shards.isEmpty()) { // might be since none has been created yet (two phase index creation) computeStatus = ClusterHealthStatus.RED; } this.status = computeStatus; this.activePrimaryShards = computeActivePrimaryShards; this.activeShards = computeActiveShards; this.relocatingShards = computeRelocatingShards; this.initializingShards = computeInitializingShards; this.unassignedShards = computeUnassignedShards; } public ClusterIndexHealth(final StreamInput in) throws IOException { index = in.readString(); numberOfShards = in.readVInt(); numberOfReplicas = in.readVInt(); activePrimaryShards = in.readVInt(); activeShards = in.readVInt(); relocatingShards = in.readVInt(); initializingShards = in.readVInt(); unassignedShards = in.readVInt(); status = ClusterHealthStatus.fromValue(in.readByte()); int size = in.readVInt(); for (int i = 0; i < size; i++) { ClusterShardHealth shardHealth = new ClusterShardHealth(in); shards.put(shardHealth.getId(), shardHealth); } } public String getIndex() { return index; } public int getNumberOfShards() { return numberOfShards; } public int getNumberOfReplicas() { return numberOfReplicas; } public int getActiveShards() { return activeShards; } public int getRelocatingShards() { return relocatingShards; } public int getActivePrimaryShards() { return activePrimaryShards; } public int getInitializingShards() { return initializingShards; } public int getUnassignedShards() { return unassignedShards; } public ClusterHealthStatus getStatus() { return status; } public Map<Integer, ClusterShardHealth> getShards() { return this.shards; } @Override public Iterator<ClusterShardHealth> iterator() { return shards.values().iterator(); } @Override public void writeTo(final StreamOutput out) throws IOException { out.writeString(index); out.writeVInt(numberOfShards); out.writeVInt(numberOfReplicas); out.writeVInt(activePrimaryShards); out.writeVInt(activeShards); out.writeVInt(relocatingShards); out.writeVInt(initializingShards); out.writeVInt(unassignedShards); out.writeByte(status.value()); out.writeVInt(shards.size()); for (ClusterShardHealth shardHealth : this) { shardHealth.writeTo(out); } } private static final String STATUS = "status"; private static final String NUMBER_OF_SHARDS = "number_of_shards"; private static final String NUMBER_OF_REPLICAS = "number_of_replicas"; private static final String ACTIVE_PRIMARY_SHARDS = "active_primary_shards"; private static final String ACTIVE_SHARDS = "active_shards"; private static final String RELOCATING_SHARDS = "relocating_shards"; private static final String INITIALIZING_SHARDS = "initializing_shards"; private static final String UNASSIGNED_SHARDS = "unassigned_shards"; private static final String SHARDS = "shards"; private static final String PRIMARY_ACTIVE = "primary_active"; @Override public XContentBuilder toXContent(final XContentBuilder builder, final Params params) throws IOException { builder.field(STATUS, getStatus().name().toLowerCase(Locale.ROOT)); builder.field(NUMBER_OF_SHARDS, getNumberOfShards()); builder.field(NUMBER_OF_REPLICAS, getNumberOfReplicas()); builder.field(ACTIVE_PRIMARY_SHARDS, getActivePrimaryShards()); builder.field(ACTIVE_SHARDS, getActiveShards()); builder.field(RELOCATING_SHARDS, getRelocatingShards()); builder.field(INITIALIZING_SHARDS, getInitializingShards()); builder.field(UNASSIGNED_SHARDS, getUnassignedShards()); if ("shards".equals(params.param("level", "indices"))) { builder.startObject(SHARDS); for (ClusterShardHealth shardHealth : shards.values()) { builder.startObject(Integer.toString(shardHealth.getId())); builder.field(STATUS, shardHealth.getStatus().name().toLowerCase(Locale.ROOT)); builder.field(PRIMARY_ACTIVE, shardHealth.isPrimaryActive()); builder.field(ACTIVE_SHARDS, shardHealth.getActiveShards()); builder.field(RELOCATING_SHARDS, shardHealth.getRelocatingShards()); builder.field(INITIALIZING_SHARDS, shardHealth.getInitializingShards()); builder.field(UNASSIGNED_SHARDS, shardHealth.getUnassignedShards()); builder.endObject(); } builder.endObject(); } return builder; } }