Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: 17219: WARN EXCEPTION "virtual-map: cache-cleaner StandardFuture: Future has already been cancelled" #17475

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright (C) 2021-2024 Hedera Hashgraph, LLC
* Copyright (C) 2021-2025 Hedera Hashgraph, LLC
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
Expand All @@ -16,6 +16,8 @@

package com.swirlds.virtualmap.internal.cache;

import static com.swirlds.logging.legacy.LogMarker.EXCEPTION;

import com.swirlds.common.threading.futures.StandardFuture;
import java.util.NoSuchElementException;
import java.util.Objects;
Expand All @@ -27,6 +29,8 @@
import java.util.function.Consumer;
import java.util.stream.Stream;
import java.util.stream.StreamSupport;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;

/**
* An array-backed concurrent data structure optimized for use by the {@link VirtualNodeCache}.
Expand Down Expand Up @@ -58,6 +62,9 @@
* the element type
*/
final class ConcurrentArray<T> {

private static final Logger logger = LogManager.getLogger(ConcurrentArray.class);

/**
* The default number of elements to store in each array
*/
Expand Down Expand Up @@ -338,6 +345,7 @@
}

final StandardFuture<Void> result = new StandardFuture<>();
final AtomicBoolean exceptionThrown = new AtomicBoolean(false);
final AtomicInteger count = new AtomicInteger(1);
int nextIndex = 0;
int numberOfElements = elementCount.get();
Expand All @@ -354,7 +362,11 @@
result.complete(null);
}
} catch (Exception e) {
result.cancelWithError(e);
logger.error(EXCEPTION.getMarker(), "Exception in parallelTraverse", e);

Check warning on line 365 in platform-sdk/swirlds-virtualmap/src/main/java/com/swirlds/virtualmap/internal/cache/ConcurrentArray.java

View check run for this annotation

Codecov / codecov/patch

platform-sdk/swirlds-virtualmap/src/main/java/com/swirlds/virtualmap/internal/cache/ConcurrentArray.java#L365

Added line #L365 was not covered by tests
// Don't cancel the result future more than once
if (exceptionThrown.compareAndSet(false, true)) {
result.cancelWithError(e);

Check warning on line 368 in platform-sdk/swirlds-virtualmap/src/main/java/com/swirlds/virtualmap/internal/cache/ConcurrentArray.java

View check run for this annotation

Codecov / codecov/patch

platform-sdk/swirlds-virtualmap/src/main/java/com/swirlds/virtualmap/internal/cache/ConcurrentArray.java#L368

Added line #L368 was not covered by tests
}
}
});
nextIndex += size;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@

import static com.swirlds.common.threading.manager.AdHocThreadManager.getStaticThreadManager;
import static com.swirlds.logging.legacy.LogMarker.EXCEPTION;
import static com.swirlds.logging.legacy.LogMarker.VIRTUAL_MERKLE_STATS;
import static com.swirlds.virtualmap.internal.cache.VirtualNodeCache.CLASS_ID;
import static java.util.Objects.requireNonNull;

Expand Down Expand Up @@ -493,18 +494,16 @@ public boolean release() {

// Fire off the cleaning threads to go and clear out data in the indexes that doesn't need
// to be there anymore.
getCleaningPool(virtualMapConfig).execute(() -> {
purge(dirtyLeaves, keyToDirtyLeafIndex, virtualMapConfig);
purge(dirtyLeafPaths, pathToDirtyLeafIndex, virtualMapConfig);
purge(dirtyHashes, pathToDirtyHashIndex, virtualMapConfig);

dirtyLeaves = null;
dirtyLeafPaths = null;
dirtyHashes = null;
});
purge(dirtyLeaves, keyToDirtyLeafIndex, virtualMapConfig);
purge(dirtyLeafPaths, pathToDirtyLeafIndex, virtualMapConfig);
purge(dirtyHashes, pathToDirtyHashIndex, virtualMapConfig);

dirtyLeaves = null;
dirtyLeafPaths = null;
dirtyHashes = null;

if (logger.isTraceEnabled()) {
logger.trace("Released {}", fastCopyVersion);
logger.trace(VIRTUAL_MERKLE_STATS.getMarker(), "Released {}", fastCopyVersion);
}

return true;
Expand Down Expand Up @@ -553,6 +552,7 @@ public void merge() {

if (logger.isTraceEnabled()) {
logger.trace(
VIRTUAL_MERKLE_STATS.getMarker(),
"Merged version {}, {} dirty leaves, {} dirty internals",
fastCopyVersion,
dirtyLeaves.size(),
Expand Down Expand Up @@ -1434,11 +1434,11 @@ private Mutation<K, VirtualLeafRecord<K, V>> mutate(
* @param <V>
* The value type referenced by the mutation list
*/
private static <K, V> void purge(
private static <K, V> StandardFuture<Void> purge(
final ConcurrentArray<Mutation<K, V>> array,
final Map<K, Mutation<K, V>> index,
@NonNull final VirtualMapConfig virtualMapConfig) {
array.parallelTraverse(getCleaningPool(virtualMapConfig), element -> {
return array.parallelTraverse(getCleaningPool(virtualMapConfig), element -> {
if (element.isFiltered()) {
return;
}
Expand Down