Skip to content
Merged
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
Expand Up @@ -20,6 +20,8 @@
import static org.apache.hadoop.hdds.utils.NativeConstants.ROCKS_TOOLS_NATIVE_LIBRARY_NAME;

import java.util.Collections;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.concurrent.Callable;
import java.util.function.Supplier;
import org.apache.hadoop.crypto.OpensslCipher;
Expand All @@ -28,6 +30,7 @@
import org.apache.hadoop.hdds.utils.NativeLibraryLoader;
import org.apache.hadoop.hdds.utils.db.managed.ManagedRocksObjectUtils;
import org.apache.hadoop.io.erasurecode.ErasureCodeNative;
import org.apache.hadoop.util.NativeCodeLoader;
import org.kohsuke.MetaInfServices;
import picocli.CommandLine;

Expand All @@ -39,77 +42,45 @@
@MetaInfServices(DebugSubcommand.class)
public class CheckNative extends AbstractSubcommand implements Callable<Void>, DebugSubcommand {

private static class LibraryCheckResult {
private final boolean loaded;
private final String detail;

LibraryCheckResult(boolean loaded, String detail) {
this.loaded = loaded;
this.detail = detail;
}

public boolean isLoaded() {
return loaded;
}

public String getDetail() {
return detail;
}
}

private LibraryCheckResult getLibraryStatus(
Supplier<String> failureReasonSupplier,
Supplier<String> libraryNameSupplier) {
String failureReason = failureReasonSupplier.get();
if (failureReason != null) {
return new LibraryCheckResult(false, failureReason);
} else {
return new LibraryCheckResult(true, libraryNameSupplier.get());
}
}

@Override
public Void call() throws Exception {
boolean nativeHadoopLoaded = org.apache.hadoop.util.NativeCodeLoader.isNativeCodeLoaded();
String hadoopLibraryName = "";
String isalDetail = "";
boolean isalLoaded = false;
String opensslDetail = "";
boolean opensslLoaded = false;
Map<String, Object> results = new LinkedHashMap<>();
Copy link
Member

@peterxcli peterxcli Jun 14, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Was there a specific reason for using Object instead of String? Are you planning to return different types in future iterations?

    ...
    Map<String, String> results = new LinkedHashMap<>();
    ...

  private static String checkLibrary(boolean loaded, Supplier<String> libraryName) {
    return checkLibrary(loaded ? null : "", libraryName);
  }
  
  private static String checkLibrary(String failureReason, Supplier<String> libraryName) {
    boolean loaded = failureReason == null;
    String detail = loaded ? libraryName.get() : failureReason;
    return String.format("%-5b  %s", loaded, detail);
  }

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Was there a specific reason for using Object instead of String? Are you planning to return different types in future iterations?

I had exactly that in mind, although currently I don't plan to. I thought there is no downside as opposed to limiting the map to String values.


// Hadoop
results.put("hadoop", checkLibrary(NativeCodeLoader.isNativeCodeLoaded(), NativeCodeLoader::getLibraryName));
results.put("ISA-L", checkLibrary(ErasureCodeNative.getLoadingFailureReason(), ErasureCodeNative::getLibraryName));
results.put("OpenSSL", checkLibrary(
// OpensslCipher provides cryptic reason if Hadoop native library itself is not loaded
NativeCodeLoader.isNativeCodeLoaded() ? OpensslCipher.getLoadingFailureReason() : "",
OpensslCipher::getLibraryName
));

if (nativeHadoopLoaded) {
hadoopLibraryName = org.apache.hadoop.util.NativeCodeLoader.getLibraryName();
// Ozone
NativeLibraryLoader.getInstance().loadLibrary(
ROCKS_TOOLS_NATIVE_LIBRARY_NAME,
Collections.singletonList(ManagedRocksObjectUtils.getRocksDBLibFileName()));
results.put("rocks-tools", checkLibrary(
NativeLibraryLoader.isLibraryLoaded(ROCKS_TOOLS_NATIVE_LIBRARY_NAME),
NativeLibraryLoader::getJniLibraryFileName));

LibraryCheckResult isalStatus = getLibraryStatus(
ErasureCodeNative::getLoadingFailureReason,
ErasureCodeNative::getLibraryName
);
isalLoaded = isalStatus.isLoaded();
isalDetail = isalStatus.getDetail();
final int maxLength = results.keySet().stream()
.mapToInt(String::length)
.max()
.getAsInt();

// Check OpenSSL status
LibraryCheckResult opensslStatus = getLibraryStatus(
OpensslCipher::getLoadingFailureReason,
OpensslCipher::getLibraryName
);
opensslLoaded = opensslStatus.isLoaded();
opensslDetail = opensslStatus.getDetail();
}
out().println("Native library checking:");
out().printf("hadoop: %b %s%n", nativeHadoopLoaded,
hadoopLibraryName);
out().printf("ISA-L: %b %s%n", isalLoaded, isalDetail);
out().printf("OpenSSL: %b %s%n", opensslLoaded, opensslDetail);
results.forEach((name, result) -> out().printf("%" + maxLength + "s: %s%n", name, result));

// Attempt to load the rocks-tools lib
boolean nativeRocksToolsLoaded = NativeLibraryLoader.getInstance().loadLibrary(
ROCKS_TOOLS_NATIVE_LIBRARY_NAME,
Collections.singletonList(ManagedRocksObjectUtils.getRocksDBLibFileName()));
String rocksToolsDetail = "";
if (nativeRocksToolsLoaded) {
rocksToolsDetail = NativeLibraryLoader.getJniLibraryFileName();
}
out().printf("rocks-tools: %b %s%n", nativeRocksToolsLoaded, rocksToolsDetail);
return null;
}

private static Object checkLibrary(boolean loaded, Supplier<String> libraryName) {
return checkLibrary(loaded ? null : "", libraryName);
}

private static Object checkLibrary(String failureReason, Supplier<String> libraryName) {
boolean loaded = failureReason == null;
String detail = loaded ? libraryName.get() : failureReason;
return String.format("%-5b %s", loaded, detail);
}
}
Loading