From 5c721df72e5e2f5c3d76ce0a51dec70a976400d8 Mon Sep 17 00:00:00 2001 From: Simon Dudley Date: Mon, 20 Nov 2023 12:04:22 +1000 Subject: [PATCH 1/6] Add RockDB Subcommand for printing usage per column family Signed-off-by: Simon Dudley --- besu/build.gradle | 1 + .../storage/RocksDbSubCommand.java | 114 ++++++++++++++++++ .../storage/RocksDbUsageHelper.java | 94 +++++++++++++++ .../storage/StorageSubCommand.java | 4 +- .../hyperledger/besu/crypto/KeyPairUtil.java | 1 + 5 files changed, 212 insertions(+), 2 deletions(-) create mode 100644 besu/src/main/java/org/hyperledger/besu/cli/subcommands/storage/RocksDbSubCommand.java create mode 100644 besu/src/main/java/org/hyperledger/besu/cli/subcommands/storage/RocksDbUsageHelper.java diff --git a/besu/build.gradle b/besu/build.gradle index 73977d81ba7..b3c6d0644e9 100644 --- a/besu/build.gradle +++ b/besu/build.gradle @@ -77,6 +77,7 @@ dependencies { implementation 'org.springframework.security:spring-security-crypto' implementation 'org.xerial.snappy:snappy-java' implementation 'tech.pegasys:jc-kzg-4844' + implementation 'org.rocksdb:rocksdbjni' runtimeOnly 'org.apache.logging.log4j:log4j-jul' runtimeOnly 'com.splunk.logging:splunk-library-javalogging' diff --git a/besu/src/main/java/org/hyperledger/besu/cli/subcommands/storage/RocksDbSubCommand.java b/besu/src/main/java/org/hyperledger/besu/cli/subcommands/storage/RocksDbSubCommand.java new file mode 100644 index 00000000000..9d08248c64b --- /dev/null +++ b/besu/src/main/java/org/hyperledger/besu/cli/subcommands/storage/RocksDbSubCommand.java @@ -0,0 +1,114 @@ +/* + * Copyright Hyperledger Besu Contributors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on + * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the + * specific language governing permissions and limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 + */ +package org.hyperledger.besu.cli.subcommands.storage; + +import static org.hyperledger.besu.controller.BesuController.DATABASE_PATH; + +import org.hyperledger.besu.cli.util.VersionProvider; + +import java.io.PrintWriter; +import java.util.ArrayList; +import java.util.List; + +import org.rocksdb.ColumnFamilyDescriptor; +import org.rocksdb.ColumnFamilyHandle; +import org.rocksdb.Options; +import org.rocksdb.RocksDB; +import org.rocksdb.RocksDBException; +import picocli.CommandLine; +import picocli.CommandLine.Command; +import picocli.CommandLine.ParentCommand; + +/** The RocksDB subcommand. */ +@Command( + name = "x-rocksdb", + description = "Print RocksDB information", + mixinStandardHelpOptions = true, + versionProvider = VersionProvider.class, + subcommands = {RocksDbSubCommand.RocksDbUsage.class}) +public class RocksDbSubCommand implements Runnable { + + @SuppressWarnings("unused") + @ParentCommand + private StorageSubCommand parentCommand; + + @SuppressWarnings("unused") + @CommandLine.Spec + private CommandLine.Model.CommandSpec spec; + + @Override + public void run() { + spec.commandLine().usage(System.out); + } + + @Command( + name = "usage", + description = "Prints disk usage", + mixinStandardHelpOptions = true, + versionProvider = VersionProvider.class) + static class RocksDbUsage implements Runnable { + + @SuppressWarnings("unused") + @CommandLine.Spec + private CommandLine.Model.CommandSpec spec; + + @SuppressWarnings("unused") + @ParentCommand + private RocksDbSubCommand parentCommand; + + @Override + public void run() { + + final PrintWriter out = spec.commandLine().getOut(); + + final String dbPath = + parentCommand + .parentCommand + .parentCommand + .dataDir() + .toString() + .concat("/") + .concat(DATABASE_PATH); + + RocksDB.loadLibrary(); + Options options = new Options(); + options.setCreateIfMissing(true); + + // Open the RocksDB database with multiple column families + List cfNames; + try { + cfNames = RocksDB.listColumnFamilies(options, dbPath); + } catch (RocksDBException e) { + throw new RuntimeException(e); + } + List cfHandles = new ArrayList<>(); + List cfDescriptors = new ArrayList<>(); + for (byte[] cfName : cfNames) { + cfDescriptors.add(new ColumnFamilyDescriptor(cfName)); + } + try (final RocksDB rocksdb = RocksDB.openReadOnly(dbPath, cfDescriptors, cfHandles)) { + for (ColumnFamilyHandle cfHandle : cfHandles) { + RocksDbUsageHelper.printUsageForColumnFamily(rocksdb, cfHandle, out); + } + } catch (RocksDBException e) { + throw new RuntimeException(e); + } finally { + for (ColumnFamilyHandle cfHandle : cfHandles) { + cfHandle.close(); + } + } + } + } +} diff --git a/besu/src/main/java/org/hyperledger/besu/cli/subcommands/storage/RocksDbUsageHelper.java b/besu/src/main/java/org/hyperledger/besu/cli/subcommands/storage/RocksDbUsageHelper.java new file mode 100644 index 00000000000..3846158330b --- /dev/null +++ b/besu/src/main/java/org/hyperledger/besu/cli/subcommands/storage/RocksDbUsageHelper.java @@ -0,0 +1,94 @@ +/* + * Copyright contributors to Hyperledger Besu. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on + * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the + * specific language governing permissions and limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +package org.hyperledger.besu.cli.subcommands.storage; + +import org.hyperledger.besu.ethereum.storage.keyvalue.KeyValueSegmentIdentifier; + +import java.io.PrintWriter; + +import org.bouncycastle.util.Arrays; +import org.rocksdb.ColumnFamilyHandle; +import org.rocksdb.ColumnFamilyMetaData; +import org.rocksdb.RocksDB; +import org.rocksdb.RocksDBException; + +public class RocksDbUsageHelper { + + static void printUsageForColumnFamily( + final RocksDB rocksdb, final ColumnFamilyHandle cfHandle, final PrintWriter out) + throws RocksDBException { + String size = rocksdb.getProperty(cfHandle, "rocksdb.estimate-live-data-size"); + boolean emptyColumnFamily = false; + if (!size.isEmpty() && !size.isBlank()) { + long sizeLong = Long.parseLong(size); + if (sizeLong == 0) emptyColumnFamily = true; + if (!emptyColumnFamily) { + out.println( + "****** Column family '" + + getNameById(cfHandle.getName()) + + "' size: " + + formatOutputSize(sizeLong) + + " ******"); + + out.println( + "Number of keys : " + rocksdb.getProperty(cfHandle, "rocksdb.estimate-num-keys")); + out.println( + "Number of live snapshots : " + rocksdb.getProperty(cfHandle, "rocksdb.num-snapshots")); + + String totolSstFilesSize = rocksdb.getProperty(cfHandle, "rocksdb.total-sst-files-size"); + if (!totolSstFilesSize.isEmpty() && !totolSstFilesSize.isBlank()) { + out.println( + "Total size of SST Files : " + formatOutputSize(Long.parseLong(totolSstFilesSize))); + } + String liveSstFilesSize = rocksdb.getProperty(cfHandle, "rocksdb.live-sst-files-size"); + if (!liveSstFilesSize.isEmpty() && !liveSstFilesSize.isBlank()) { + out.println( + "Size of live SST Filess : " + formatOutputSize(Long.parseLong(liveSstFilesSize))); + } + + ColumnFamilyMetaData columnFamilyMetaData = rocksdb.getColumnFamilyMetaData(cfHandle); + long sizeBytes = columnFamilyMetaData.size(); + out.println( + "Column family size (with getColumnFamilyMetaData) : " + formatOutputSize(sizeBytes)); + out.println(""); + } + } + } + + private static String formatOutputSize(final long size) { + if (size > (1024 * 1024 * 1024)) { + long sizeInGiB = size / (1024 * 1024 * 1024); + return sizeInGiB + " GiB"; + } else if (size > (1024 * 1024)) { + long sizeInMiB = size / (1024 * 1024); + return sizeInMiB + " MiB"; + } else if (size > 1024) { + long sizeInKiB = size / 1024; + return sizeInKiB + " KiB"; + } else { + return size + " B"; + } + } + + public static String getNameById(final byte[] id) { + for (KeyValueSegmentIdentifier segment : KeyValueSegmentIdentifier.values()) { + if (Arrays.areEqual(segment.getId(), id)) { + return segment.getName(); + } + } + return null; // id not found + } +} diff --git a/besu/src/main/java/org/hyperledger/besu/cli/subcommands/storage/StorageSubCommand.java b/besu/src/main/java/org/hyperledger/besu/cli/subcommands/storage/StorageSubCommand.java index bd40a42a431..e46ffde2739 100644 --- a/besu/src/main/java/org/hyperledger/besu/cli/subcommands/storage/StorageSubCommand.java +++ b/besu/src/main/java/org/hyperledger/besu/cli/subcommands/storage/StorageSubCommand.java @@ -45,7 +45,7 @@ description = "This command provides storage related actions.", mixinStandardHelpOptions = true, versionProvider = VersionProvider.class, - subcommands = {StorageSubCommand.RevertVariablesStorage.class}) + subcommands = {StorageSubCommand.RevertVariablesStorage.class, RocksDbSubCommand.class}) public class StorageSubCommand implements Runnable { /** The constant COMMAND_NAME. */ @@ -53,7 +53,7 @@ public class StorageSubCommand implements Runnable { @SuppressWarnings("unused") @ParentCommand - private BesuCommand parentCommand; + BesuCommand parentCommand; @SuppressWarnings("unused") @Spec diff --git a/crypto/algorithms/src/main/java/org/hyperledger/besu/crypto/KeyPairUtil.java b/crypto/algorithms/src/main/java/org/hyperledger/besu/crypto/KeyPairUtil.java index f20b1b37103..013b385c3c2 100644 --- a/crypto/algorithms/src/main/java/org/hyperledger/besu/crypto/KeyPairUtil.java +++ b/crypto/algorithms/src/main/java/org/hyperledger/besu/crypto/KeyPairUtil.java @@ -84,6 +84,7 @@ public static KeyPair loadKeyPair(final File keyFile) { final KeyPair key; if (keyFile.exists()) { + LOG.info("Attempting to load public key from {}", keyFile.getAbsolutePath()); key = load(keyFile); LOG.info( "Loaded public key {} from {}", key.getPublicKey().toString(), keyFile.getAbsolutePath()); From da8583c16b7517152efa9bc36e2d45191ee4a411 Mon Sep 17 00:00:00 2001 From: Simon Dudley Date: Mon, 20 Nov 2023 12:27:36 +1000 Subject: [PATCH 2/6] javadoc Signed-off-by: Simon Dudley --- .../besu/cli/subcommands/storage/RocksDbUsageHelper.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/besu/src/main/java/org/hyperledger/besu/cli/subcommands/storage/RocksDbUsageHelper.java b/besu/src/main/java/org/hyperledger/besu/cli/subcommands/storage/RocksDbUsageHelper.java index 3846158330b..47d1c093f25 100644 --- a/besu/src/main/java/org/hyperledger/besu/cli/subcommands/storage/RocksDbUsageHelper.java +++ b/besu/src/main/java/org/hyperledger/besu/cli/subcommands/storage/RocksDbUsageHelper.java @@ -25,6 +25,7 @@ import org.rocksdb.RocksDB; import org.rocksdb.RocksDBException; +/** RocksDB Usage subcommand helper methods for formatting and printing. */ public class RocksDbUsageHelper { static void printUsageForColumnFamily( @@ -83,7 +84,7 @@ private static String formatOutputSize(final long size) { } } - public static String getNameById(final byte[] id) { + private static String getNameById(final byte[] id) { for (KeyValueSegmentIdentifier segment : KeyValueSegmentIdentifier.values()) { if (Arrays.areEqual(segment.getId(), id)) { return segment.getName(); From c251e6e6a15508d7f92f2c64b5209649a4af1527 Mon Sep 17 00:00:00 2001 From: Gabriel Fukushima Date: Fri, 1 Dec 2023 12:24:08 +1000 Subject: [PATCH 3/6] Change format to a markdown formatted table and remove experimental prefix Signed-off-by: Gabriel Fukushima --- .../storage/RocksDbSubCommand.java | 9 +-- .../storage/RocksDbUsageHelper.java | 64 +++++++++---------- 2 files changed, 37 insertions(+), 36 deletions(-) diff --git a/besu/src/main/java/org/hyperledger/besu/cli/subcommands/storage/RocksDbSubCommand.java b/besu/src/main/java/org/hyperledger/besu/cli/subcommands/storage/RocksDbSubCommand.java index 9d08248c64b..461175a2282 100644 --- a/besu/src/main/java/org/hyperledger/besu/cli/subcommands/storage/RocksDbSubCommand.java +++ b/besu/src/main/java/org/hyperledger/besu/cli/subcommands/storage/RocksDbSubCommand.java @@ -33,7 +33,7 @@ /** The RocksDB subcommand. */ @Command( - name = "x-rocksdb", + name = "rocksdb", description = "Print RocksDB information", mixinStandardHelpOptions = true, versionProvider = VersionProvider.class, @@ -55,7 +55,7 @@ public void run() { @Command( name = "usage", - description = "Prints disk usage", + description = "Print disk usage", mixinStandardHelpOptions = true, versionProvider = VersionProvider.class) static class RocksDbUsage implements Runnable { @@ -93,11 +93,12 @@ public void run() { } catch (RocksDBException e) { throw new RuntimeException(e); } - List cfHandles = new ArrayList<>(); - List cfDescriptors = new ArrayList<>(); + final List cfHandles = new ArrayList<>(); + final List cfDescriptors = new ArrayList<>(); for (byte[] cfName : cfNames) { cfDescriptors.add(new ColumnFamilyDescriptor(cfName)); } + RocksDbUsageHelper.printTableHeader(out); try (final RocksDB rocksdb = RocksDB.openReadOnly(dbPath, cfDescriptors, cfHandles)) { for (ColumnFamilyHandle cfHandle : cfHandles) { RocksDbUsageHelper.printUsageForColumnFamily(rocksdb, cfHandle, out); diff --git a/besu/src/main/java/org/hyperledger/besu/cli/subcommands/storage/RocksDbUsageHelper.java b/besu/src/main/java/org/hyperledger/besu/cli/subcommands/storage/RocksDbUsageHelper.java index 47d1c093f25..35a1c429eca 100644 --- a/besu/src/main/java/org/hyperledger/besu/cli/subcommands/storage/RocksDbUsageHelper.java +++ b/besu/src/main/java/org/hyperledger/besu/cli/subcommands/storage/RocksDbUsageHelper.java @@ -21,7 +21,6 @@ import org.bouncycastle.util.Arrays; import org.rocksdb.ColumnFamilyHandle; -import org.rocksdb.ColumnFamilyMetaData; import org.rocksdb.RocksDB; import org.rocksdb.RocksDBException; @@ -31,40 +30,24 @@ public class RocksDbUsageHelper { static void printUsageForColumnFamily( final RocksDB rocksdb, final ColumnFamilyHandle cfHandle, final PrintWriter out) throws RocksDBException { - String size = rocksdb.getProperty(cfHandle, "rocksdb.estimate-live-data-size"); + final String size = rocksdb.getProperty(cfHandle, "rocksdb.estimate-live-data-size"); boolean emptyColumnFamily = false; if (!size.isEmpty() && !size.isBlank()) { - long sizeLong = Long.parseLong(size); - if (sizeLong == 0) emptyColumnFamily = true; + final long sizeLong = Long.parseLong(size); + if (sizeLong == 0) { + emptyColumnFamily = true; + } + String totolSstFilesSize = rocksdb.getProperty(cfHandle, "rocksdb.total-sst-files-size"); if (!emptyColumnFamily) { - out.println( - "****** Column family '" - + getNameById(cfHandle.getName()) - + "' size: " - + formatOutputSize(sizeLong) - + " ******"); - - out.println( - "Number of keys : " + rocksdb.getProperty(cfHandle, "rocksdb.estimate-num-keys")); - out.println( - "Number of live snapshots : " + rocksdb.getProperty(cfHandle, "rocksdb.num-snapshots")); - - String totolSstFilesSize = rocksdb.getProperty(cfHandle, "rocksdb.total-sst-files-size"); - if (!totolSstFilesSize.isEmpty() && !totolSstFilesSize.isBlank()) { - out.println( - "Total size of SST Files : " + formatOutputSize(Long.parseLong(totolSstFilesSize))); - } - String liveSstFilesSize = rocksdb.getProperty(cfHandle, "rocksdb.live-sst-files-size"); - if (!liveSstFilesSize.isEmpty() && !liveSstFilesSize.isBlank()) { - out.println( - "Size of live SST Filess : " + formatOutputSize(Long.parseLong(liveSstFilesSize))); - } - - ColumnFamilyMetaData columnFamilyMetaData = rocksdb.getColumnFamilyMetaData(cfHandle); - long sizeBytes = columnFamilyMetaData.size(); - out.println( - "Column family size (with getColumnFamilyMetaData) : " + formatOutputSize(sizeBytes)); - out.println(""); + printLine( + out, + getNameById(cfHandle.getName()), + rocksdb.getProperty(cfHandle, "rocksdb.estimate-num-keys"), + formatOutputSize(sizeLong), + formatOutputSize( + !totolSstFilesSize.isEmpty() && !totolSstFilesSize.isBlank() + ? Long.parseLong(rocksdb.getProperty(cfHandle, "rocksdb.total-sst-files-size")) + : 0)); } } } @@ -92,4 +75,21 @@ private static String getNameById(final byte[] id) { } return null; // id not found } + + public static void printTableHeader(final PrintWriter out) { + out.format( + "| Column Family | Keys | Column Size | SST Files Size |\n"); + out.format( + "|--------------------------------|-----------------|--------------|-----------------|\n"); + } + + public static void printLine( + final PrintWriter out, + final String cfName, + final String keys, + final String columnSize, + final String sstFilesSize) { + final String format = "| %-30s | %-15s | %-12s | %-15s |\n"; + out.format(format, cfName, keys, columnSize, sstFilesSize); + } } From 8aa786388af99ca54f0a97fbd7a00a17cd87ee8c Mon Sep 17 00:00:00 2001 From: Gabriel Fukushima Date: Fri, 1 Dec 2023 13:02:07 +1000 Subject: [PATCH 4/6] change access modified back Signed-off-by: Gabriel Fukushima --- .../besu/cli/subcommands/storage/RocksDbUsageHelper.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/besu/src/main/java/org/hyperledger/besu/cli/subcommands/storage/RocksDbUsageHelper.java b/besu/src/main/java/org/hyperledger/besu/cli/subcommands/storage/RocksDbUsageHelper.java index 35a1c429eca..a3f4ad7834d 100644 --- a/besu/src/main/java/org/hyperledger/besu/cli/subcommands/storage/RocksDbUsageHelper.java +++ b/besu/src/main/java/org/hyperledger/besu/cli/subcommands/storage/RocksDbUsageHelper.java @@ -76,14 +76,14 @@ private static String getNameById(final byte[] id) { return null; // id not found } - public static void printTableHeader(final PrintWriter out) { + static void printTableHeader(final PrintWriter out) { out.format( "| Column Family | Keys | Column Size | SST Files Size |\n"); out.format( "|--------------------------------|-----------------|--------------|-----------------|\n"); } - public static void printLine( + static void printLine( final PrintWriter out, final String cfName, final String keys, From a5271610e04933412f980699629e5c28531d8372 Mon Sep 17 00:00:00 2001 From: Gabriel Fukushima Date: Mon, 4 Dec 2023 14:52:39 +1000 Subject: [PATCH 5/6] handle possible Long.parse exception Signed-off-by: Gabriel Fukushima --- .../storage/RocksDbUsageHelper.java | 42 ++++++++++++------- 1 file changed, 26 insertions(+), 16 deletions(-) diff --git a/besu/src/main/java/org/hyperledger/besu/cli/subcommands/storage/RocksDbUsageHelper.java b/besu/src/main/java/org/hyperledger/besu/cli/subcommands/storage/RocksDbUsageHelper.java index a3f4ad7834d..4bfd9f42951 100644 --- a/besu/src/main/java/org/hyperledger/besu/cli/subcommands/storage/RocksDbUsageHelper.java +++ b/besu/src/main/java/org/hyperledger/besu/cli/subcommands/storage/RocksDbUsageHelper.java @@ -23,31 +23,41 @@ import org.rocksdb.ColumnFamilyHandle; import org.rocksdb.RocksDB; import org.rocksdb.RocksDBException; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; /** RocksDB Usage subcommand helper methods for formatting and printing. */ public class RocksDbUsageHelper { + private static final Logger LOG = LoggerFactory.getLogger(RocksDbUsageHelper.class); static void printUsageForColumnFamily( final RocksDB rocksdb, final ColumnFamilyHandle cfHandle, final PrintWriter out) - throws RocksDBException { + throws RocksDBException, NumberFormatException { final String size = rocksdb.getProperty(cfHandle, "rocksdb.estimate-live-data-size"); boolean emptyColumnFamily = false; if (!size.isEmpty() && !size.isBlank()) { - final long sizeLong = Long.parseLong(size); - if (sizeLong == 0) { - emptyColumnFamily = true; - } - String totolSstFilesSize = rocksdb.getProperty(cfHandle, "rocksdb.total-sst-files-size"); - if (!emptyColumnFamily) { - printLine( - out, - getNameById(cfHandle.getName()), - rocksdb.getProperty(cfHandle, "rocksdb.estimate-num-keys"), - formatOutputSize(sizeLong), - formatOutputSize( - !totolSstFilesSize.isEmpty() && !totolSstFilesSize.isBlank() - ? Long.parseLong(rocksdb.getProperty(cfHandle, "rocksdb.total-sst-files-size")) - : 0)); + try { + final long sizeLong = Long.parseLong(size); + final String totalSstFilesSize = + rocksdb.getProperty(cfHandle, "rocksdb.total-sst-files-size"); + final long totalSstFilesSizeLong = + !totalSstFilesSize.isEmpty() && !totalSstFilesSize.isBlank() + ? Long.parseLong(totalSstFilesSize) + : 0; + if (sizeLong == 0) { + emptyColumnFamily = true; + } + + if (!emptyColumnFamily) { + printLine( + out, + getNameById(cfHandle.getName()), + rocksdb.getProperty(cfHandle, "rocksdb.estimate-num-keys"), + formatOutputSize(sizeLong), + formatOutputSize(totalSstFilesSizeLong)); + } + } catch (NumberFormatException e) { + LOG.error("Failed to parse string into long: " + e.getMessage()); } } } From 0d3b94a33220e7e7b31571c673be324c66e9292c Mon Sep 17 00:00:00 2001 From: Gabriel Fukushima Date: Tue, 5 Dec 2023 09:52:16 +1000 Subject: [PATCH 6/6] add changelog Signed-off-by: Gabriel Fukushima --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index f0a00eda376..7b2607eed4e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -16,6 +16,7 @@ - Fix the unavailability of `address` field when returning an `Account` entity on GraphQL in case of unreachable world state [#6198](https://github.com/hyperledger/besu/pull/6198) - Update OpenJ9 Docker image to latest version [#6226](https://github.com/hyperledger/besu/pull/6226) - Add error messages on authentication failures with username and password [#6212](https://github.com/hyperledger/besu/pull/6212) +- Add `rocksdb usage` to the `storage` subcommand to allow users and dev to check columns families usage [#6185](https://github.com/hyperledger/besu/pull/6185) ### Bug fixes - Fix Docker image name clash between Besu and evmtool [#6194](https://github.com/hyperledger/besu/pull/6194)