org.elasticsearch.cluster.health.ClusterShardHealth Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of elasticsearch Show documentation
Show all versions of elasticsearch Show documentation
Elasticsearch subproject :server
/*
* 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.routing.IndexShardRoutingTable;
import org.elasticsearch.cluster.routing.RecoverySource;
import org.elasticsearch.cluster.routing.ShardRouting;
import org.elasticsearch.cluster.routing.UnassignedInfo;
import org.elasticsearch.cluster.routing.UnassignedInfo.AllocationStatus;
import org.elasticsearch.common.io.stream.StreamInput;
import org.elasticsearch.common.io.stream.StreamOutput;
import org.elasticsearch.common.io.stream.Writeable;
import java.io.IOException;
public final class ClusterShardHealth implements Writeable {
private final int shardId;
private final ClusterHealthStatus status;
private final int activeShards;
private final int relocatingShards;
private final int initializingShards;
private final int unassignedShards;
private final boolean primaryActive;
public ClusterShardHealth(final int shardId, final IndexShardRoutingTable shardRoutingTable) {
this.shardId = shardId;
int computeActiveShards = 0;
int computeRelocatingShards = 0;
int computeInitializingShards = 0;
int computeUnassignedShards = 0;
for (ShardRouting shardRouting : shardRoutingTable) {
if (shardRouting.active()) {
computeActiveShards++;
if (shardRouting.relocating()) {
// the shard is relocating, the one it is relocating to will be in initializing state, so we don't count it
computeRelocatingShards++;
}
} else if (shardRouting.initializing()) {
computeInitializingShards++;
} else if (shardRouting.unassigned()) {
computeUnassignedShards++;
}
}
ClusterHealthStatus computeStatus;
final ShardRouting primaryRouting = shardRoutingTable.primaryShard();
if (primaryRouting.active()) {
if (computeActiveShards == shardRoutingTable.size()) {
computeStatus = ClusterHealthStatus.GREEN;
} else {
computeStatus = ClusterHealthStatus.YELLOW;
}
} else {
computeStatus = getInactivePrimaryHealth(primaryRouting);
}
this.status = computeStatus;
this.activeShards = computeActiveShards;
this.relocatingShards = computeRelocatingShards;
this.initializingShards = computeInitializingShards;
this.unassignedShards = computeUnassignedShards;
this.primaryActive = primaryRouting.active();
}
public ClusterShardHealth(final StreamInput in) throws IOException {
shardId = in.readVInt();
status = ClusterHealthStatus.fromValue(in.readByte());
activeShards = in.readVInt();
relocatingShards = in.readVInt();
initializingShards = in.readVInt();
unassignedShards = in.readVInt();
primaryActive = in.readBoolean();
}
public int getId() {
return shardId;
}
public ClusterHealthStatus getStatus() {
return status;
}
public int getRelocatingShards() {
return relocatingShards;
}
public int getActiveShards() {
return activeShards;
}
public boolean isPrimaryActive() {
return primaryActive;
}
public int getInitializingShards() {
return initializingShards;
}
public int getUnassignedShards() {
return unassignedShards;
}
@Override
public void writeTo(final StreamOutput out) throws IOException {
out.writeVInt(shardId);
out.writeByte(status.value());
out.writeVInt(activeShards);
out.writeVInt(relocatingShards);
out.writeVInt(initializingShards);
out.writeVInt(unassignedShards);
out.writeBoolean(primaryActive);
}
/**
* Checks if an inactive primary shard should cause the cluster health to go RED.
*
* An inactive primary shard in an index should cause the cluster health to be RED to make it visible that some of the existing data is
* unavailable. In case of index creation, snapshot restore or index shrinking, which are unexceptional events in the cluster lifecycle,
* cluster health should not turn RED for the time where primaries are still in the initializing state but go to YELLOW instead.
* However, in case of exceptional events, for example when the primary shard cannot be assigned to a node or initialization fails at
* some point, cluster health should still turn RED.
*
* NB: this method should *not* be called on active shards nor on non-primary shards.
*/
public static ClusterHealthStatus getInactivePrimaryHealth(final ShardRouting shardRouting) {
assert shardRouting.primary() : "cannot invoke on a replica shard: " + shardRouting;
assert shardRouting.active() == false : "cannot invoke on an active shard: " + shardRouting;
assert shardRouting.unassignedInfo() != null : "cannot invoke on a shard with no UnassignedInfo: " + shardRouting;
assert shardRouting.recoverySource() != null : "cannot invoke on a shard that has no recovery source" + shardRouting;
final UnassignedInfo unassignedInfo = shardRouting.unassignedInfo();
RecoverySource.Type recoveryType = shardRouting.recoverySource().getType();
if (unassignedInfo.getLastAllocationStatus() != AllocationStatus.DECIDERS_NO && unassignedInfo.getNumFailedAllocations() == 0
&& (recoveryType == RecoverySource.Type.EMPTY_STORE
|| recoveryType == RecoverySource.Type.LOCAL_SHARDS
|| recoveryType == RecoverySource.Type.SNAPSHOT)) {
return ClusterHealthStatus.YELLOW;
} else {
return ClusterHealthStatus.RED;
}
}
}