@Override protected void masterOperation( final SnapshotsStatusRequest request, final ClusterState state, final ActionListener<SnapshotsStatusResponse> listener) throws Exception { ImmutableList<SnapshotMetaData.Entry> currentSnapshots = snapshotsService.currentSnapshots(request.repository(), request.snapshots()); if (currentSnapshots.isEmpty()) { listener.onResponse(buildResponse(request, currentSnapshots, null)); return; } Set<String> nodesIds = newHashSet(); for (SnapshotMetaData.Entry entry : currentSnapshots) { for (SnapshotMetaData.ShardSnapshotStatus status : entry.shards().values()) { if (status.nodeId() != null) { nodesIds.add(status.nodeId()); } } } if (!nodesIds.isEmpty()) { // There are still some snapshots running - check their progress SnapshotId[] snapshotIds = new SnapshotId[currentSnapshots.size()]; for (int i = 0; i < currentSnapshots.size(); i++) { snapshotIds[i] = currentSnapshots.get(i).snapshotId(); } transportNodesSnapshotsStatus.status( nodesIds.toArray(new String[nodesIds.size()]), snapshotIds, request.masterNodeTimeout(), new ActionListener<TransportNodesSnapshotsStatus.NodesSnapshotStatus>() { @Override public void onResponse( TransportNodesSnapshotsStatus.NodesSnapshotStatus nodeSnapshotStatuses) { try { ImmutableList<SnapshotMetaData.Entry> currentSnapshots = snapshotsService.currentSnapshots(request.repository(), request.snapshots()); listener.onResponse(buildResponse(request, currentSnapshots, nodeSnapshotStatuses)); } catch (Throwable e) { listener.onFailure(e); } } @Override public void onFailure(Throwable e) { listener.onFailure(e); } }); } else { // We don't have any in-progress shards, just return current stats listener.onResponse(buildResponse(request, currentSnapshots, null)); } }
private SnapshotsStatusResponse buildResponse( SnapshotsStatusRequest request, ImmutableList<SnapshotMetaData.Entry> currentSnapshots, TransportNodesSnapshotsStatus.NodesSnapshotStatus nodeSnapshotStatuses) throws IOException { // First process snapshot that are currently processed ImmutableList.Builder<SnapshotStatus> builder = ImmutableList.builder(); Set<SnapshotId> currentSnapshotIds = newHashSet(); if (!currentSnapshots.isEmpty()) { Map<String, TransportNodesSnapshotsStatus.NodeSnapshotStatus> nodeSnapshotStatusMap; if (nodeSnapshotStatuses != null) { nodeSnapshotStatusMap = nodeSnapshotStatuses.getNodesMap(); } else { nodeSnapshotStatusMap = newHashMap(); } for (SnapshotMetaData.Entry entry : currentSnapshots) { currentSnapshotIds.add(entry.snapshotId()); ImmutableList.Builder<SnapshotIndexShardStatus> shardStatusBuilder = ImmutableList.builder(); for (ImmutableMap.Entry<ShardId, SnapshotMetaData.ShardSnapshotStatus> shardEntry : entry.shards().entrySet()) { SnapshotMetaData.ShardSnapshotStatus status = shardEntry.getValue(); if (status.nodeId() != null) { // We should have information about this shard from the shard: TransportNodesSnapshotsStatus.NodeSnapshotStatus nodeStatus = nodeSnapshotStatusMap.get(status.nodeId()); if (nodeStatus != null) { ImmutableMap<ShardId, SnapshotIndexShardStatus> shardStatues = nodeStatus.status().get(entry.snapshotId()); if (shardStatues != null) { SnapshotIndexShardStatus shardStatus = shardStatues.get(shardEntry.getKey()); if (shardStatus != null) { // We have full information about this shard shardStatusBuilder.add(shardStatus); continue; } } } } final SnapshotIndexShardStage stage; switch (shardEntry.getValue().state()) { case FAILED: case ABORTED: case MISSING: stage = SnapshotIndexShardStage.FAILURE; break; case INIT: case WAITING: case STARTED: stage = SnapshotIndexShardStage.STARTED; break; case SUCCESS: stage = SnapshotIndexShardStage.DONE; break; default: throw new ElasticsearchIllegalArgumentException( "Unknown snapshot state " + shardEntry.getValue().state()); } SnapshotIndexShardStatus shardStatus = new SnapshotIndexShardStatus(shardEntry.getKey(), stage); shardStatusBuilder.add(shardStatus); } builder.add( new SnapshotStatus(entry.snapshotId(), entry.state(), shardStatusBuilder.build())); } } // Now add snapshots on disk that are not currently running if (Strings.hasText(request.repository())) { if (request.snapshots() != null && request.snapshots().length > 0) { for (String snapshotName : request.snapshots()) { SnapshotId snapshotId = new SnapshotId(request.repository(), snapshotName); if (currentSnapshotIds.contains(snapshotId)) { // This is a snapshot the is currently running - skipping continue; } Snapshot snapshot = snapshotsService.snapshot(snapshotId); ImmutableList.Builder<SnapshotIndexShardStatus> shardStatusBuilder = ImmutableList.builder(); if (snapshot.state().completed()) { ImmutableMap<ShardId, IndexShardSnapshotStatus> shardStatues = snapshotsService.snapshotShards(snapshotId); for (ImmutableMap.Entry<ShardId, IndexShardSnapshotStatus> shardStatus : shardStatues.entrySet()) { shardStatusBuilder.add( new SnapshotIndexShardStatus(shardStatus.getKey(), shardStatus.getValue())); } final SnapshotMetaData.State state; switch (snapshot.state()) { case FAILED: state = SnapshotMetaData.State.FAILED; break; case SUCCESS: case PARTIAL: // Translating both PARTIAL and SUCCESS to SUCCESS for now // TODO: add the differentiation on the metadata level in the next major release state = SnapshotMetaData.State.SUCCESS; break; default: throw new ElasticsearchIllegalArgumentException( "Unknown snapshot state " + snapshot.state()); } builder.add(new SnapshotStatus(snapshotId, state, shardStatusBuilder.build())); } } } } return new SnapshotsStatusResponse(builder.build()); }