private ClusterHealthResponse clusterHealth( ClusterHealthRequest request, ClusterState clusterState) { if (logger.isTraceEnabled()) { logger.trace("Calculating health based on state version [{}]", clusterState.version()); } String[] concreteIndices; try { concreteIndices = clusterState.metaData().concreteIndices(request.indicesOptions(), request.indices()); } catch (IndexMissingException e) { // one of the specified indices is not there - treat it as RED. ClusterHealthResponse response = new ClusterHealthResponse(clusterName.value(), Strings.EMPTY_ARRAY, clusterState); response.status = ClusterHealthStatus.RED; return response; } return new ClusterHealthResponse(clusterName.value(), concreteIndices, clusterState); }
@Override protected void masterOperation( final ClusterHealthRequest request, final ClusterState unusedState, final ActionListener<ClusterHealthResponse> listener) throws ElasticsearchException { long endTime = System.currentTimeMillis() + request.timeout().millis(); if (request.waitForEvents() != null) { final CountDownLatch latch = new CountDownLatch(1); final AtomicReference<ElasticsearchException> failure = new AtomicReference<>(); clusterService.submitStateUpdateTask( "cluster_health (wait_for_events [" + request.waitForEvents() + "])", request.waitForEvents(), new ProcessedClusterStateUpdateTask() { @Override public ClusterState execute(ClusterState currentState) { return currentState; } @Override public void clusterStateProcessed( String source, ClusterState oldState, ClusterState newState) { latch.countDown(); } @Override public void onFailure(String source, Throwable t) { logger.error("unexpected failure during [{}]", t, source); failure.set(new ElasticsearchException("Error while waiting for events", t)); latch.countDown(); } @Override public boolean runOnlyOnMaster() { return !request.local(); } }); try { latch.await(request.timeout().millis(), TimeUnit.MILLISECONDS); } catch (InterruptedException e) { // ignore } if (failure.get() != null) { throw failure.get(); } } int waitFor = 5; if (request.waitForStatus() == null) { waitFor--; } if (request.waitForRelocatingShards() == -1) { waitFor--; } if (request.waitForActiveShards() == -1) { waitFor--; } if (request.waitForNodes().isEmpty()) { waitFor--; } if (request.indices().length == 0) { // check that they actually exists in the meta data waitFor--; } if (waitFor == 0) { // no need to wait for anything ClusterState clusterState = clusterService.state(); listener.onResponse(clusterHealth(request, clusterState)); return; } while (true) { int waitForCounter = 0; ClusterState clusterState = clusterService.state(); ClusterHealthResponse response = clusterHealth(request, clusterState); if (request.waitForStatus() != null && response.getStatus().value() <= request.waitForStatus().value()) { waitForCounter++; } if (request.waitForRelocatingShards() != -1 && response.getRelocatingShards() <= request.waitForRelocatingShards()) { waitForCounter++; } if (request.waitForActiveShards() != -1 && response.getActiveShards() >= request.waitForActiveShards()) { waitForCounter++; } if (request.indices().length > 0) { try { clusterState.metaData().concreteIndices(IndicesOptions.strictExpand(), request.indices()); waitForCounter++; } catch (IndexMissingException e) { response.status = ClusterHealthStatus.RED; // no indices, make sure its RED // missing indices, wait a bit more... } } if (!request.waitForNodes().isEmpty()) { if (request.waitForNodes().startsWith(">=")) { int expected = Integer.parseInt(request.waitForNodes().substring(2)); if (response.getNumberOfNodes() >= expected) { waitForCounter++; } } else if (request.waitForNodes().startsWith("ge(")) { int expected = Integer.parseInt( request.waitForNodes().substring(3, request.waitForNodes().length() - 1)); if (response.getNumberOfNodes() >= expected) { waitForCounter++; } } else if (request.waitForNodes().startsWith("<=")) { int expected = Integer.parseInt(request.waitForNodes().substring(2)); if (response.getNumberOfNodes() <= expected) { waitForCounter++; } } else if (request.waitForNodes().startsWith("le(")) { int expected = Integer.parseInt( request.waitForNodes().substring(3, request.waitForNodes().length() - 1)); if (response.getNumberOfNodes() <= expected) { waitForCounter++; } } else if (request.waitForNodes().startsWith(">")) { int expected = Integer.parseInt(request.waitForNodes().substring(1)); if (response.getNumberOfNodes() > expected) { waitForCounter++; } } else if (request.waitForNodes().startsWith("gt(")) { int expected = Integer.parseInt( request.waitForNodes().substring(3, request.waitForNodes().length() - 1)); if (response.getNumberOfNodes() > expected) { waitForCounter++; } } else if (request.waitForNodes().startsWith("<")) { int expected = Integer.parseInt(request.waitForNodes().substring(1)); if (response.getNumberOfNodes() < expected) { waitForCounter++; } } else if (request.waitForNodes().startsWith("lt(")) { int expected = Integer.parseInt( request.waitForNodes().substring(3, request.waitForNodes().length() - 1)); if (response.getNumberOfNodes() < expected) { waitForCounter++; } } else { int expected = Integer.parseInt(request.waitForNodes()); if (response.getNumberOfNodes() == expected) { waitForCounter++; } } } if (waitForCounter == waitFor) { listener.onResponse(response); return; } if (System.currentTimeMillis() > endTime) { response.timedOut = true; listener.onResponse(response); return; } try { Thread.sleep(200); } catch (InterruptedException e) { response.timedOut = true; listener.onResponse(response); return; } } }
@Override protected ClusterHealthResponse masterOperation(ClusterHealthRequest request, ClusterState state) throws ElasticSearchException { int waitFor = 4; if (request.waitForStatus() == null) { waitFor--; } if (request.waitForRelocatingShards() == -1) { waitFor--; } if (request.waitForActiveShards() == -1) { waitFor--; } if (request.waitForNodes().isEmpty()) { waitFor--; } if (waitFor == 0) { // no need to wait for anything return clusterHealth(request); } long endTime = System.currentTimeMillis() + request.timeout().millis(); while (true) { int waitForCounter = 0; ClusterHealthResponse response = clusterHealth(request); if (request.waitForStatus() != null && response.status().value() <= request.waitForStatus().value()) { waitForCounter++; } if (request.waitForRelocatingShards() != -1 && response.relocatingShards() <= request.waitForRelocatingShards()) { waitForCounter++; } if (request.waitForActiveShards() != -1 && response.activeShards() >= request.waitForActiveShards()) { waitForCounter++; } if (!request.waitForNodes().isEmpty()) { if (request.waitForNodes().startsWith(">=")) { int expected = Integer.parseInt(request.waitForNodes().substring(2)); if (response.numberOfNodes() >= expected) { waitForCounter++; } } else if (request.waitForNodes().startsWith("ge(")) { int expected = Integer.parseInt( request.waitForNodes().substring(3, request.waitForNodes().length() - 1)); if (response.numberOfNodes() >= expected) { waitForCounter++; } } else if (request.waitForNodes().startsWith("<=")) { int expected = Integer.parseInt(request.waitForNodes().substring(2)); if (response.numberOfNodes() <= expected) { waitForCounter++; } } else if (request.waitForNodes().startsWith("le(")) { int expected = Integer.parseInt( request.waitForNodes().substring(3, request.waitForNodes().length() - 1)); if (response.numberOfNodes() <= expected) { waitForCounter++; } } else if (request.waitForNodes().startsWith(">")) { int expected = Integer.parseInt(request.waitForNodes().substring(1)); if (response.numberOfNodes() > expected) { waitForCounter++; } } else if (request.waitForNodes().startsWith("gt(")) { int expected = Integer.parseInt( request.waitForNodes().substring(3, request.waitForNodes().length() - 1)); if (response.numberOfNodes() > expected) { waitForCounter++; } } else if (request.waitForNodes().startsWith("<")) { int expected = Integer.parseInt(request.waitForNodes().substring(1)); if (response.numberOfNodes() < expected) { waitForCounter++; } } else if (request.waitForNodes().startsWith("lt(")) { int expected = Integer.parseInt( request.waitForNodes().substring(3, request.waitForNodes().length() - 1)); if (response.numberOfNodes() < expected) { waitForCounter++; } } else { int expected = Integer.parseInt(request.waitForNodes()); if (response.numberOfNodes() == expected) { waitForCounter++; } } } if (waitForCounter == waitFor) { return response; } if (timerService.estimatedTimeInMillis() > endTime) { response.timedOut = true; return response; } try { Thread.sleep(200); } catch (InterruptedException e) { response.timedOut = true; // we got interrupted, bail return response; } } }
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; }