use of org.opensearch.action.admin.indices.readonly.AddIndexBlockResponse.AddBlockResult in project OpenSearch by opensearch-project.
the class MetadataIndexStateService method finalizeBlock.
/**
* Finalizes the addition of blocks by turning the temporary UUID-based blocks into full blocks.
* @param currentState the cluster state to update
* @param blockedIndices the indices and their temporary UUID-based blocks to convert
* @param verifyResult the index-level results for adding the block
* @param block the full block to convert to
* @return the updated cluster state, as well as the (failed and successful) index-level results for adding the block
*/
static Tuple<ClusterState, Collection<AddBlockResult>> finalizeBlock(final ClusterState currentState, final Map<Index, ClusterBlock> blockedIndices, final Map<Index, AddBlockResult> verifyResult, final APIBlock block) {
final Metadata.Builder metadata = Metadata.builder(currentState.metadata());
final ClusterBlocks.Builder blocks = ClusterBlocks.builder().blocks(currentState.blocks());
final RoutingTable.Builder routingTable = RoutingTable.builder(currentState.routingTable());
final Set<String> effectivelyBlockedIndices = new HashSet<>();
Map<Index, AddBlockResult> blockingResults = new HashMap<>(verifyResult);
for (Map.Entry<Index, AddBlockResult> result : verifyResult.entrySet()) {
final Index index = result.getKey();
final boolean acknowledged = result.getValue().hasFailures() == false;
try {
if (acknowledged == false) {
logger.debug("verification of shards before blocking {} failed [{}]", index, result);
continue;
}
final IndexMetadata indexMetadata = metadata.getSafe(index);
final ClusterBlock tempBlock = blockedIndices.get(index);
assert tempBlock != null;
assert tempBlock.uuid() != null;
final ClusterBlock currentBlock = currentState.blocks().getIndexBlockWithId(index.getName(), tempBlock.id());
if (currentBlock != null && currentBlock.equals(block.block)) {
logger.debug("verification of shards for {} succeeded, but block finalization already occurred" + " (possibly for another block) [{}]", index, result);
continue;
}
if (currentBlock == null || currentBlock.equals(tempBlock) == false) {
// we should report error in this case as the index can be left as open.
blockingResults.put(result.getKey(), new AddBlockResult(result.getKey(), new IllegalStateException("verification of shards before blocking " + index + " succeeded but block has been removed in the meantime")));
logger.debug("verification of shards before blocking {} succeeded but block has been removed in the meantime", index);
continue;
}
assert currentBlock != null && currentBlock.equals(tempBlock) && currentBlock.id() == block.block.id();
blocks.removeIndexBlockWithId(index.getName(), tempBlock.id());
blocks.addIndexBlock(index.getName(), block.block);
logger.debug("add block {} to index {} succeeded", block.block, index);
effectivelyBlockedIndices.add(index.getName());
} catch (final IndexNotFoundException e) {
logger.debug("index {} has been deleted since blocking it started, ignoring", index);
}
}
logger.info("completed adding block {} to indices {}", block.name, effectivelyBlockedIndices);
return Tuple.tuple(ClusterState.builder(currentState).blocks(blocks).metadata(metadata).routingTable(routingTable.build()).build(), blockingResults.values());
}
use of org.opensearch.action.admin.indices.readonly.AddIndexBlockResponse.AddBlockResult in project OpenSearch by opensearch-project.
the class MetadataIndexStateService method addIndexBlock.
/**
* Adds an index block based on the given request, and notifies the listener upon completion.
* Adding blocks is done in three steps:
* - First, a temporary UUID-based block is added to the index
* (see {@link #addIndexBlock(Index[], ClusterState, APIBlock)}.
* - Second, shards are checked to have properly applied the UUID-based block.
* (see {@link WaitForBlocksApplied}).
* - Third, the temporary UUID-based block is turned into a full block
* (see {@link #finalizeBlock(ClusterState, Map, Map, APIBlock)}.
* Using this three-step process ensures non-interference by other operations in case where
* we notify successful completion here.
*/
public void addIndexBlock(AddIndexBlockClusterStateUpdateRequest request, ActionListener<AddIndexBlockResponse> listener) {
final Index[] concreteIndices = request.indices();
if (concreteIndices == null || concreteIndices.length == 0) {
throw new IllegalArgumentException("Index name is required");
}
List<String> writeIndices = new ArrayList<>();
SortedMap<String, IndexAbstraction> lookup = clusterService.state().metadata().getIndicesLookup();
for (Index index : concreteIndices) {
IndexAbstraction ia = lookup.get(index.getName());
if (ia != null && ia.getParentDataStream() != null && ia.getParentDataStream().getWriteIndex().getIndex().equals(index)) {
writeIndices.add(index.getName());
}
}
if (writeIndices.size() > 0) {
throw new IllegalArgumentException("cannot add a block to the following data stream write indices [" + Strings.collectionToCommaDelimitedString(writeIndices) + "]");
}
clusterService.submitStateUpdateTask("add-index-block-[" + request.getBlock().name + "]-" + Arrays.toString(concreteIndices), new ClusterStateUpdateTask(Priority.URGENT) {
private Map<Index, ClusterBlock> blockedIndices;
@Override
public ClusterState execute(final ClusterState currentState) {
final Tuple<ClusterState, Map<Index, ClusterBlock>> tup = addIndexBlock(concreteIndices, currentState, request.getBlock());
blockedIndices = tup.v2();
return tup.v1();
}
@Override
public void clusterStateProcessed(final String source, final ClusterState oldState, final ClusterState newState) {
if (oldState == newState) {
assert blockedIndices.isEmpty() : "List of blocked indices is not empty but cluster state wasn't changed";
listener.onResponse(new AddIndexBlockResponse(true, false, Collections.emptyList()));
} else {
assert blockedIndices.isEmpty() == false : "List of blocked indices is empty but cluster state was changed";
threadPool.executor(ThreadPool.Names.MANAGEMENT).execute(new WaitForBlocksApplied(blockedIndices, request, ActionListener.wrap(verifyResults -> clusterService.submitStateUpdateTask("finalize-index-block-[" + request.getBlock().name + "]-[" + blockedIndices.keySet().stream().map(Index::getName).collect(Collectors.joining(", ")) + "]", new ClusterStateUpdateTask(Priority.URGENT) {
private final List<AddBlockResult> indices = new ArrayList<>();
@Override
public ClusterState execute(final ClusterState currentState) throws Exception {
Tuple<ClusterState, Collection<AddBlockResult>> addBlockResult = finalizeBlock(currentState, blockedIndices, verifyResults, request.getBlock());
assert verifyResults.size() == addBlockResult.v2().size();
indices.addAll(addBlockResult.v2());
return addBlockResult.v1();
}
@Override
public void onFailure(final String source, final Exception e) {
listener.onFailure(e);
}
@Override
public void clusterStateProcessed(final String source, final ClusterState oldState, final ClusterState newState) {
final boolean acknowledged = indices.stream().noneMatch(AddBlockResult::hasFailures);
listener.onResponse(new AddIndexBlockResponse(acknowledged, acknowledged, indices));
}
}), listener::onFailure)));
}
}
@Override
public void onFailure(final String source, final Exception e) {
listener.onFailure(e);
}
@Override
public TimeValue timeout() {
return request.masterNodeTimeout();
}
});
}
Aggregations