use of org.opensearch.indices.cluster.IndicesClusterStateService.AllocatedIndices.IndexRemovalReason.NO_LONGER_ASSIGNED in project OpenSearch by opensearch-project.
the class MetadataMappingService method executeRefresh.
/**
* Batch method to apply all the queued refresh operations. The idea is to try and batch as much
* as possible so we won't create the same index all the time for example for the updates on the same mapping
* and generate a single cluster change event out of all of those.
*/
ClusterState executeRefresh(final ClusterState currentState, final List<RefreshTask> allTasks) throws Exception {
// break down to tasks per index, so we can optimize the on demand index service creation
// to only happen for the duration of a single index processing of its respective events
Map<String, List<RefreshTask>> tasksPerIndex = new HashMap<>();
for (RefreshTask task : allTasks) {
if (task.index == null) {
logger.debug("ignoring a mapping task of type [{}] with a null index.", task);
}
tasksPerIndex.computeIfAbsent(task.index, k -> new ArrayList<>()).add(task);
}
boolean dirty = false;
Metadata.Builder mdBuilder = Metadata.builder(currentState.metadata());
for (Map.Entry<String, List<RefreshTask>> entry : tasksPerIndex.entrySet()) {
IndexMetadata indexMetadata = mdBuilder.get(entry.getKey());
if (indexMetadata == null) {
// index got deleted on us, ignore...
logger.debug("[{}] ignoring tasks - index meta data doesn't exist", entry.getKey());
continue;
}
final Index index = indexMetadata.getIndex();
// the tasks lists to iterate over, filled with the list of mapping tasks, trying to keep
// the latest (based on order) update mapping one per node
List<RefreshTask> allIndexTasks = entry.getValue();
boolean hasTaskWithRightUUID = false;
for (RefreshTask task : allIndexTasks) {
if (indexMetadata.isSameUUID(task.indexUUID)) {
hasTaskWithRightUUID = true;
} else {
logger.debug("{} ignoring task [{}] - index meta data doesn't match task uuid", index, task);
}
}
if (hasTaskWithRightUUID == false) {
continue;
}
// construct the actual index if needed, and make sure the relevant mappings are there
boolean removeIndex = false;
IndexService indexService = indicesService.indexService(indexMetadata.getIndex());
if (indexService == null) {
// we need to create the index here, and add the current mapping to it, so we can merge
indexService = indicesService.createIndex(indexMetadata, Collections.emptyList(), false);
removeIndex = true;
indexService.mapperService().merge(indexMetadata, MergeReason.MAPPING_RECOVERY);
}
IndexMetadata.Builder builder = IndexMetadata.builder(indexMetadata);
try {
boolean indexDirty = refreshIndexMapping(indexService, builder);
if (indexDirty) {
mdBuilder.put(builder);
dirty = true;
}
} finally {
if (removeIndex) {
indicesService.removeIndex(index, NO_LONGER_ASSIGNED, "created for mapping processing");
}
}
}
if (!dirty) {
return currentState;
}
return ClusterState.builder(currentState).metadata(mdBuilder).build();
}
use of org.opensearch.indices.cluster.IndicesClusterStateService.AllocatedIndices.IndexRemovalReason.NO_LONGER_ASSIGNED in project OpenSearch by opensearch-project.
the class MetadataIndexAliasesService method applyAliasActions.
/**
* Handles the cluster state transition to a version that reflects the provided {@link AliasAction}s.
*/
public ClusterState applyAliasActions(ClusterState currentState, Iterable<AliasAction> actions) {
List<Index> indicesToClose = new ArrayList<>();
Map<String, IndexService> indices = new HashMap<>();
try {
boolean changed = false;
// Gather all the indexes that must be removed first so:
// 1. We don't cause error when attempting to replace an index with a alias of the same name.
// 2. We don't allow removal of aliases from indexes that we're just going to delete anyway. That'd be silly.
Set<Index> indicesToDelete = new HashSet<>();
for (AliasAction action : actions) {
if (action.removeIndex()) {
IndexMetadata index = currentState.metadata().getIndices().get(action.getIndex());
if (index == null) {
throw new IndexNotFoundException(action.getIndex());
}
validateAliasTargetIsNotDSBackingIndex(currentState, action);
indicesToDelete.add(index.getIndex());
changed = true;
}
}
// Remove the indexes if there are any to remove
if (changed) {
currentState = deleteIndexService.deleteIndices(currentState, indicesToDelete);
}
Metadata.Builder metadata = Metadata.builder(currentState.metadata());
// Run the remaining alias actions
final Set<String> maybeModifiedIndices = new HashSet<>();
for (AliasAction action : actions) {
if (action.removeIndex()) {
// Handled above
continue;
}
IndexMetadata index = metadata.get(action.getIndex());
if (index == null) {
throw new IndexNotFoundException(action.getIndex());
}
validateAliasTargetIsNotDSBackingIndex(currentState, action);
NewAliasValidator newAliasValidator = (alias, indexRouting, filter, writeIndex) -> {
/* It is important that we look up the index using the metadata builder we are modifying so we can remove an
* index and replace it with an alias. */
Function<String, IndexMetadata> indexLookup = name -> metadata.get(name);
aliasValidator.validateAlias(alias, action.getIndex(), indexRouting, indexLookup);
if (Strings.hasLength(filter)) {
IndexService indexService = indices.get(index.getIndex().getName());
if (indexService == null) {
indexService = indicesService.indexService(index.getIndex());
if (indexService == null) {
// temporarily create the index and add mappings so we can parse the filter
try {
indexService = indicesService.createIndex(index, emptyList(), false);
indicesToClose.add(index.getIndex());
} catch (IOException e) {
throw new OpenSearchException("Failed to create temporary index for parsing the alias", e);
}
indexService.mapperService().merge(index, MapperService.MergeReason.MAPPING_RECOVERY);
}
indices.put(action.getIndex(), indexService);
}
// the context is only used for validation so it's fine to pass fake values for the shard id,
// but the current timestamp should be set to real value as we may use `now` in a filtered alias
aliasValidator.validateAliasFilter(alias, filter, indexService.newQueryShardContext(0, null, () -> System.currentTimeMillis(), null), xContentRegistry);
}
};
if (action.apply(newAliasValidator, metadata, index)) {
changed = true;
maybeModifiedIndices.add(index.getIndex().getName());
}
}
for (final String maybeModifiedIndex : maybeModifiedIndices) {
final IndexMetadata currentIndexMetadata = currentState.metadata().index(maybeModifiedIndex);
final IndexMetadata newIndexMetadata = metadata.get(maybeModifiedIndex);
// only increment the aliases version if the aliases actually changed for this index
if (currentIndexMetadata.getAliases().equals(newIndexMetadata.getAliases()) == false) {
assert currentIndexMetadata.getAliasesVersion() == newIndexMetadata.getAliasesVersion();
metadata.put(new IndexMetadata.Builder(newIndexMetadata).aliasesVersion(1 + currentIndexMetadata.getAliasesVersion()));
}
}
if (changed) {
ClusterState updatedState = ClusterState.builder(currentState).metadata(metadata).build();
// i.e. remove and add the same alias to the same index
if (!updatedState.metadata().equalsAliases(currentState.metadata())) {
return updatedState;
}
}
return currentState;
} finally {
for (Index index : indicesToClose) {
indicesService.removeIndex(index, NO_LONGER_ASSIGNED, "created for alias processing");
}
}
}
Aggregations