This is an automated email from the ASF dual-hosted git repository.
rpuch pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/ignite-3.git
The following commit(s) were added to refs/heads/main by this push:
new cf7cbf33851 IGNITE-26680 Avoid NullPointerException on metastorage
recovery (#6745)
cf7cbf33851 is described below
commit cf7cbf33851464dbe7af562e940cd66bcfa10fae
Author: Roman Puchkovskiy <[email protected]>
AuthorDate: Mon Oct 13 11:27:22 2025 +0400
IGNITE-26680 Avoid NullPointerException on metastorage recovery (#6745)
---
.../metastorage/impl/RecoveryRevisionsListenerImpl.java | 5 +++--
.../internal/metastorage/server/AbstractKeyValueStorage.java | 10 +++++++---
2 files changed, 10 insertions(+), 5 deletions(-)
diff --git
a/modules/metastorage/src/main/java/org/apache/ignite/internal/metastorage/impl/RecoveryRevisionsListenerImpl.java
b/modules/metastorage/src/main/java/org/apache/ignite/internal/metastorage/impl/RecoveryRevisionsListenerImpl.java
index 8147d916d72..6453ced227a 100644
---
a/modules/metastorage/src/main/java/org/apache/ignite/internal/metastorage/impl/RecoveryRevisionsListenerImpl.java
+++
b/modules/metastorage/src/main/java/org/apache/ignite/internal/metastorage/impl/RecoveryRevisionsListenerImpl.java
@@ -20,19 +20,20 @@ package org.apache.ignite.internal.metastorage.impl;
import static org.apache.ignite.internal.util.ExceptionUtils.sneakyThrow;
import java.util.concurrent.CompletableFuture;
+import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
import org.apache.ignite.internal.lang.NodeStoppingException;
import org.apache.ignite.internal.metastorage.Revisions;
import org.apache.ignite.internal.metastorage.server.RecoveryRevisionsListener;
import org.apache.ignite.internal.util.IgniteSpinBusyLock;
-/** Implementation of {@link RecoveryRevisionsListener}. */
+/** Listener that completes the Metastorage 'recovery finish' future. */
class RecoveryRevisionsListenerImpl implements RecoveryRevisionsListener {
private final IgniteSpinBusyLock busyLock;
private final CompletableFuture<Revisions> recoveryFinishFuture;
- private final ReentrantLock lock = new ReentrantLock();
+ private final Lock lock = new ReentrantLock();
/** Guarded by {@link #lock}. */
private Revisions targetRevisions;
diff --git
a/modules/metastorage/src/main/java/org/apache/ignite/internal/metastorage/server/AbstractKeyValueStorage.java
b/modules/metastorage/src/main/java/org/apache/ignite/internal/metastorage/server/AbstractKeyValueStorage.java
index 0d25ed549bf..292de6fe285 100644
---
a/modules/metastorage/src/main/java/org/apache/ignite/internal/metastorage/server/AbstractKeyValueStorage.java
+++
b/modules/metastorage/src/main/java/org/apache/ignite/internal/metastorage/server/AbstractKeyValueStorage.java
@@ -305,9 +305,13 @@ public abstract class AbstractKeyValueStorage implements
KeyValueStorage {
/** Notifies of revision update. */
protected void notifyRevisionsUpdate() {
- if (recoveryRevisionListener != null) {
- // Listener must be invoked only on recovery, after recovery
listener must be null.
- recoveryRevisionListener.onUpdate(createCurrentRevisions());
+ RecoveryRevisionsListener listener = recoveryRevisionListener;
+
+ if (listener != null) {
+ // The listener should be invoked only on recovery, after recovery
listener will be null.
+ // Currently, there is a race that allows the listener to be
invoked after recovery is complete, but this race is benign
+ // as it will simply lead to a second attempt to complete the
recovery future, which will be ignored.
+ listener.onUpdate(createCurrentRevisions());
}
}