Skip to content
Open
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
45 changes: 28 additions & 17 deletions jdm-core/src/main/java/jdiskmark/Smart.java
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.TimeUnit;
import java.util.logging.Level;
Expand Down Expand Up @@ -356,41 +357,51 @@ public static void startHeartbeat() {
* @return a populated {@link Smart} instance, or {@code null} on error
*/
private static Smart getSmartDirect(String deviceName, String smartctlPath) {
List<List<String>> candidates = new ArrayList<>();
candidates.add(List.of("--json", "-a", "/dev/" + deviceName));
candidates.add(List.of("--json", "-a", deviceName));
if (deviceName.startsWith("pd")) {
String win32 = "\\\\.\\PhysicalDrive" + deviceName.substring(2);
candidates.add(List.of("--json", "-a", win32));
candidates.add(List.of("--json", "-a", win32, "-d", "nvme"));
candidates.add(List.of("--json", "-a", win32, "-d", "sat"));
}
Smart fallback = null;
try {
for (String devArg : new String[]{"/dev/" + deviceName, deviceName}) {
ProcessBuilder pb = new ProcessBuilder(smartctlPath, "--json", "-a", devArg);
for (List<String> args : candidates) {
List<String> cmd = new ArrayList<>();
cmd.add(smartctlPath);
cmd.addAll(args);
ProcessBuilder pb = new ProcessBuilder(cmd);
pb.redirectErrorStream(true);
Process p = pb.start();

StringBuilder sb = new StringBuilder();
try (BufferedReader reader = new BufferedReader(
new InputStreamReader(p.getInputStream(), StandardCharsets.UTF_8))) {
String line;
while ((line = reader.readLine()) != null) {
sb.append(line).append('\n');
}
while ((line = reader.readLine()) != null) sb.append(line).append('\n');
}
if (!p.waitFor(15, TimeUnit.SECONDS)) {
p.destroyForcibly();
LOGGER.warning("getSmartDirect: smartctl timed out for: " + devArg);
App.err("Smart - smartctl timed out for: " + devArg);
LOGGER.warning("getSmartDirect: smartctl timed out for: " + args);
continue;
}
String result = sb.toString().trim();
if (result.isEmpty()) {
LOGGER.warning("getSmartDirect: empty response for: " + devArg);
App.err("Smart - empty response for: " + devArg);
continue;
}
if (!result.startsWith("{")) {
LOGGER.warning("getSmartDirect: non-JSON response for " + devArg + ": " + result);
App.err("Smart - non-JSON response for: " + devArg);
if (result.isEmpty() || !result.startsWith("{")) continue;
if ((p.exitValue() & 2) != 0) {
LOGGER.info("getSmartDirect: device open failed (exit " + p.exitValue() + ") for: " + args);
if (fallback == null) fallback = fromJson(result);
continue;
}
Smart smart = fromJson(result);
logSmart(smart);
return smart;
}
if (fallback != null) {
LOGGER.warning("getSmartDirect: all candidates failed; using error response for: " + deviceName);
logSmart(fallback);
return fallback;
}
LOGGER.severe("getSmartDirect: all attempts failed for: " + deviceName);
App.err("Smart - all attempts failed for: " + deviceName);
} catch (InterruptedException ex) {
Expand All @@ -399,7 +410,7 @@ private static Smart getSmartDirect(String deviceName, String smartctlPath) {
App.err("Smart - interrupted for: " + deviceName);
} catch (IOException ex) {
LOGGER.log(Level.SEVERE, "getSmartDirect failed for: " + deviceName, ex);
App.err("Smart - failed for: " + deviceName + " " + ex.getMessage());
App.err("Smart - failed for: " + deviceName + " \u2014 " + ex.getMessage());
}
return null;
}
Expand Down
Loading
Loading