-
Notifications
You must be signed in to change notification settings - Fork 599
HDDS-14859. Use RocksDb secondary instance for validating volumes. #9947
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
base: master
Are you sure you want to change the base?
Changes from 5 commits
9f50fba
c2ffea9
7190e4e
a2160c2
7dc2bfd
02a6986
dafaf60
13bba73
1986d60
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -25,6 +25,7 @@ | |
| import jakarta.annotation.Nullable; | ||
| import java.io.File; | ||
| import java.io.IOException; | ||
| import java.time.Duration; | ||
| import java.util.Iterator; | ||
| import java.util.List; | ||
| import java.util.concurrent.ConcurrentSkipListSet; | ||
|
|
@@ -306,20 +307,34 @@ public synchronized VolumeCheckResult check(@Nullable Boolean unused) | |
|
|
||
| @VisibleForTesting | ||
| public VolumeCheckResult checkDbHealth(File dbFile) throws InterruptedException { | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Let's add javadoc to this method to clarify that our goal is to check global files like CURRENT and MANIFEST, and that verifying the contents of all SST files/values in the DB is done by the container data scanner. |
||
| if (!getDiskCheckEnabled()) { | ||
| if (!(getDiskCheckEnabled() && getDatanodeConfig().isRocksDbDiskCheckEnabled())) { | ||
| return VolumeCheckResult.HEALTHY; | ||
| } | ||
|
|
||
| try (ManagedOptions managedOptions = new ManagedOptions(); | ||
| ManagedRocksDB ignored = ManagedRocksDB.openReadOnly(managedOptions, dbFile.toString())) { | ||
| // Do nothing. Only check if rocksdb is accessible. | ||
| LOG.debug("Successfully opened the database at \"{}\" for HDDS volume {}.", dbFile, getStorageDir()); | ||
| } catch (Exception e) { | ||
| if (Thread.currentThread().isInterrupted()) { | ||
| throw new InterruptedException("Check of database for volume " + this + " interrupted."); | ||
| // We attempt to open RocksDb twice to ignore any transient errors | ||
| // and to confirm that we actually cannot open RocksDb in readonly mode. | ||
| final int maxAttempts = getDatanodeConfig().getDiskCheckRetryAttempts(); | ||
| final Duration maxRetryGap = getDatanodeConfig().getDiskCheckRetryGap(); | ||
| for (int attempt = 0; attempt < maxAttempts; attempt++) { | ||
| try (ManagedOptions managedOptions = new ManagedOptions(); | ||
|
ptlrs marked this conversation as resolved.
Outdated
|
||
| ManagedRocksDB ignored = | ||
| ManagedRocksDB.openAsSecondary(managedOptions, dbFile.toString(), getTmpDir().getPath())) { | ||
| // Do nothing. Only check if rocksdb is accessible. | ||
| LOG.debug("Successfully opened the database at \"{}\" for HDDS volume {}.", dbFile, getStorageDir()); | ||
|
ptlrs marked this conversation as resolved.
Outdated
|
||
| break; | ||
| } catch (Exception e) { | ||
|
ptlrs marked this conversation as resolved.
Outdated
|
||
| if (Thread.currentThread().isInterrupted()) { | ||
| throw new InterruptedException("Check of database for volume " + this + " interrupted."); | ||
| } | ||
|
|
||
| if (attempt == maxAttempts - 1) { | ||
|
ptlrs marked this conversation as resolved.
Outdated
|
||
| LOG.error("Could not open Volume DB located at {}", dbFile, e); | ||
| getIoTestSlidingWindow().add(); | ||
| } else { | ||
| LOG.warn("Could not open Volume DB located at {}", dbFile, e); | ||
| Thread.sleep(maxRetryGap.toMillis()); | ||
|
ptlrs marked this conversation as resolved.
Outdated
|
||
| } | ||
| } | ||
| LOG.warn("Could not open Volume DB located at {}", dbFile, e); | ||
| getIoTestSlidingWindow().add(); | ||
| } | ||
|
|
||
| if (getIoTestSlidingWindow().isExceeded()) { | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -75,6 +75,14 @@ public static ManagedRocksDB openReadOnly( | |
| ); | ||
| } | ||
|
|
||
| public static ManagedRocksDB openAsSecondary( | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @ptlrs thanks for all the research you've done on secondary instances. It would be great to put a summary as a javadoc above this method about how they work and what we can expect vs. readonly instances. |
||
| final ManagedOptions options, | ||
| final String dbPath, | ||
| final String secondaryDbLogFilePath) | ||
| throws RocksDBException { | ||
| return new ManagedRocksDB(RocksDB.openAsSecondary(options, dbPath, secondaryDbLogFilePath)); | ||
|
ptlrs marked this conversation as resolved.
|
||
| } | ||
|
|
||
| public static ManagedRocksDB open( | ||
| final DBOptions options, final String path, | ||
| final List<ColumnFamilyDescriptor> columnFamilyDescriptors, | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
How about we rename it to "hdds.datanode.disk.check.rocksdb.io.test.enabled", so that all the disk check property will share the "hdds.datanode.disk.check" prefix?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I have moved the switch to its own PR in #10149.
I have updated it there.