use of org.opensearch.common.collect.Tuple in project OpenSearch by opensearch-project.
the class SettingsUpdater method partitionKnownAndValidSettings.
/**
* Partitions the settings into those that are known and valid versus those that are unknown or invalid. The resulting tuple contains
* the known and valid settings in the first component and the unknown or invalid settings in the second component. Note that archived
* settings contained in the settings to partition are included in the first component.
*
* @param settings the settings to partition
* @param settingsType a string to identify the settings (for logging)
* @param logger a logger to sending warnings to
* @return the partitioned settings
*/
private Tuple<Settings, Settings> partitionKnownAndValidSettings(final Settings settings, final String settingsType, final Logger logger) {
final Settings existingArchivedSettings = settings.filter(k -> k.startsWith(ARCHIVED_SETTINGS_PREFIX));
final Settings settingsExcludingExistingArchivedSettings = settings.filter(k -> k.startsWith(ARCHIVED_SETTINGS_PREFIX) == false);
final Settings settingsWithUnknownOrInvalidArchived = clusterSettings.archiveUnknownOrInvalidSettings(settingsExcludingExistingArchivedSettings, e -> logUnknownSetting(settingsType, e, logger), (e, ex) -> logInvalidSetting(settingsType, e, ex, logger));
return Tuple.tuple(Settings.builder().put(settingsWithUnknownOrInvalidArchived.filter(k -> k.startsWith(ARCHIVED_SETTINGS_PREFIX) == false)).put(existingArchivedSettings).build(), settingsWithUnknownOrInvalidArchived.filter(k -> k.startsWith(ARCHIVED_SETTINGS_PREFIX)));
}
use of org.opensearch.common.collect.Tuple 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();
}
});
}
use of org.opensearch.common.collect.Tuple in project OpenSearch by opensearch-project.
the class TemplateUpgradeService method clusterChanged.
@Override
public void clusterChanged(ClusterChangedEvent event) {
ClusterState state = event.state();
if (state.nodes().isLocalNodeElectedMaster() == false) {
return;
}
if (state.blocks().hasGlobalBlock(GatewayService.STATE_NOT_RECOVERED_BLOCK)) {
// while they actually do exist
return;
}
if (upgradesInProgress.get() > 0) {
// we are already running some upgrades - skip this cluster state update
return;
}
ImmutableOpenMap<String, IndexTemplateMetadata> templates = state.getMetadata().getTemplates();
if (templates == lastTemplateMetadata) {
// if there were no changes
return;
}
lastTemplateMetadata = templates;
Optional<Tuple<Map<String, BytesReference>, Set<String>>> changes = calculateTemplateChanges(templates);
if (changes.isPresent()) {
if (upgradesInProgress.compareAndSet(0, changes.get().v1().size() + changes.get().v2().size() + 1)) {
logger.info("Starting template upgrade to version {}, {} templates will be updated and {} will be removed", Version.CURRENT, changes.get().v1().size(), changes.get().v2().size());
assert threadPool.getThreadContext().isSystemContext();
threadPool.generic().execute(() -> upgradeTemplates(changes.get().v1(), changes.get().v2()));
}
}
}
use of org.opensearch.common.collect.Tuple in project OpenSearch by opensearch-project.
the class OpenSearchExceptionTests method randomExceptions.
public static Tuple<Throwable, OpenSearchException> randomExceptions() {
Throwable actual;
OpenSearchException expected;
int type = randomIntBetween(0, 5);
switch(type) {
case 0:
actual = new ClusterBlockException(singleton(NoMasterBlockService.NO_MASTER_BLOCK_WRITES));
expected = new OpenSearchException("OpenSearch exception [type=cluster_block_exception, " + "reason=blocked by: [SERVICE_UNAVAILABLE/2/no master];]");
break;
case // Simple opensearch exception with headers (other metadata of type number are not parsed)
1:
actual = new ParsingException(3, 2, "Unknown identifier", null);
expected = new OpenSearchException("OpenSearch exception [type=parsing_exception, reason=Unknown identifier]");
break;
case 2:
actual = new SearchParseException(SHARD_TARGET, "Parse failure", new XContentLocation(12, 98));
expected = new OpenSearchException("OpenSearch exception [type=search_parse_exception, reason=Parse failure]");
break;
case 3:
actual = new IllegalArgumentException("Closed resource", new RuntimeException("Resource"));
expected = new OpenSearchException("OpenSearch exception [type=illegal_argument_exception, reason=Closed resource]", new OpenSearchException("OpenSearch exception [type=runtime_exception, reason=Resource]"));
break;
case 4:
actual = new SearchPhaseExecutionException("search", "all shards failed", new ShardSearchFailure[] { new ShardSearchFailure(new ParsingException(1, 2, "foobar", null), new SearchShardTarget("node_1", new ShardId("foo", "_na_", 1), null, OriginalIndices.NONE)) });
expected = new OpenSearchException("OpenSearch exception [type=search_phase_execution_exception, " + "reason=all shards failed]");
expected.addMetadata("opensearch.phase", "search");
break;
case 5:
actual = new OpenSearchException("Parsing failed", new ParsingException(9, 42, "Wrong state", new NullPointerException("Unexpected null value")));
OpenSearchException expectedCause = new OpenSearchException("OpenSearch exception [type=parsing_exception, " + "reason=Wrong state]", new OpenSearchException("OpenSearch exception [type=null_pointer_exception, " + "reason=Unexpected null value]"));
expected = new OpenSearchException("OpenSearch exception [type=exception, reason=Parsing failed]", expectedCause);
break;
default:
throw new UnsupportedOperationException("No randomized exceptions generated for type [" + type + "]");
}
if (actual instanceof OpenSearchException) {
OpenSearchException actualException = (OpenSearchException) actual;
if (randomBoolean()) {
int nbHeaders = randomIntBetween(1, 5);
Map<String, List<String>> randomHeaders = new HashMap<>(nbHeaders);
for (int i = 0; i < nbHeaders; i++) {
List<String> values = new ArrayList<>();
int nbValues = randomIntBetween(1, 3);
for (int j = 0; j < nbValues; j++) {
values.add(frequently() ? randomAlphaOfLength(5) : "");
}
randomHeaders.put("header_" + i, values);
}
for (Map.Entry<String, List<String>> entry : randomHeaders.entrySet()) {
actualException.addHeader(entry.getKey(), entry.getValue());
expected.addHeader(entry.getKey(), entry.getValue());
}
if (rarely()) {
// Empty or null headers are not printed out by the toXContent method
actualException.addHeader("ignored", randomBoolean() ? emptyList() : null);
}
}
if (randomBoolean()) {
int nbMetadata = randomIntBetween(1, 5);
Map<String, List<String>> randomMetadata = new HashMap<>(nbMetadata);
for (int i = 0; i < nbMetadata; i++) {
List<String> values = new ArrayList<>();
int nbValues = randomIntBetween(1, 3);
for (int j = 0; j < nbValues; j++) {
values.add(frequently() ? randomAlphaOfLength(5) : "");
}
randomMetadata.put("opensearch.metadata_" + i, values);
}
for (Map.Entry<String, List<String>> entry : randomMetadata.entrySet()) {
actualException.addMetadata(entry.getKey(), entry.getValue());
expected.addMetadata(entry.getKey(), entry.getValue());
}
if (rarely()) {
// Empty or null metadata are not printed out by the toXContent method
actualException.addMetadata("opensearch.ignored", randomBoolean() ? emptyList() : null);
}
}
if (randomBoolean()) {
int nbResources = randomIntBetween(1, 5);
for (int i = 0; i < nbResources; i++) {
String resourceType = "type_" + i;
String[] resourceIds = new String[randomIntBetween(1, 3)];
for (int j = 0; j < resourceIds.length; j++) {
resourceIds[j] = frequently() ? randomAlphaOfLength(5) : "";
}
actualException.setResources(resourceType, resourceIds);
expected.setResources(resourceType, resourceIds);
}
}
}
return new Tuple<>(actual, expected);
}
use of org.opensearch.common.collect.Tuple in project OpenSearch by opensearch-project.
the class IndexResponseTests method doFromXContentTestWithRandomFields.
private void doFromXContentTestWithRandomFields(boolean addRandomFields) throws IOException {
final Tuple<IndexResponse, IndexResponse> tuple = randomIndexResponse();
IndexResponse indexResponse = tuple.v1();
IndexResponse expectedIndexResponse = tuple.v2();
boolean humanReadable = randomBoolean();
XContentType xContentType = randomFrom(XContentType.values());
BytesReference originalBytes = toShuffledXContent(indexResponse, xContentType, ToXContent.EMPTY_PARAMS, humanReadable);
BytesReference mutated;
if (addRandomFields) {
// The ShardInfo.Failure's exception is rendered out in a "reason" object. We shouldn't add anything random there
// because exception rendering and parsing are very permissive: any extra object or field would be rendered as
// a exception custom metadata and be parsed back as a custom header, making it impossible to compare the results
// in this test.
Predicate<String> excludeFilter = path -> path.contains("reason");
mutated = insertRandomFields(xContentType, originalBytes, excludeFilter, random());
} else {
mutated = originalBytes;
}
IndexResponse parsedIndexResponse;
try (XContentParser parser = createParser(xContentType.xContent(), mutated)) {
parsedIndexResponse = IndexResponse.fromXContent(parser);
assertNull(parser.nextToken());
}
// We can't use equals() to compare the original and the parsed index response
// because the random index response can contain shard failures with exceptions,
// and those exceptions are not parsed back with the same types.
assertDocWriteResponse(expectedIndexResponse, parsedIndexResponse);
}
Aggregations