diff --git a/backend/src/main/java/net/laprun/sustainability/power/nuprocess/BaseProcessHandler.java b/backend/src/main/java/net/laprun/sustainability/power/nuprocess/BaseProcessHandler.java new file mode 100644 index 0000000..2da7310 --- /dev/null +++ b/backend/src/main/java/net/laprun/sustainability/power/nuprocess/BaseProcessHandler.java @@ -0,0 +1,93 @@ +package net.laprun.sustainability.power.nuprocess; + +import java.io.ByteArrayInputStream; +import java.io.InputStream; +import java.nio.ByteBuffer; +import java.util.Arrays; +import java.util.concurrent.CompletableFuture; +import java.util.concurrent.Future; +import java.util.concurrent.TimeUnit; + +import com.zaxxer.nuprocess.NuAbstractProcessHandler; +import com.zaxxer.nuprocess.NuProcess; + +public class BaseProcessHandler extends NuAbstractProcessHandler { + private String errorMsg; + private NuProcess process; + private final String[] command; + private final GrowableBuffer stdOutBuffer = new GrowableBuffer(); + private final CompletableFuture output = new CompletableFuture<>(); + + public BaseProcessHandler(String... command) { + if (command == null || command.length == 0) { + throw new IllegalArgumentException("No command specified"); + } + this.command = initCommand(command); + } + + protected String[] initCommand(String... command) { + return command; + } + + public String[] command() { + return command; + } + + @Override + public void onPreStart(NuProcess nuProcess) { + this.process = nuProcess; + } + + @Override + public void onExit(int statusCode) { + if (Integer.MIN_VALUE == statusCode) { + throw new IllegalArgumentException("Unknown command " + Arrays.toString(command)); + } + if (statusCode != 0) { + throw new RuntimeException("Couldn't execute command " + Arrays.toString(command) + + ". Error code: " + statusCode + ", message: " + errorMsg); + } + } + + public void stop() { + if (process.isRunning()) { + process.destroy(false); + try { + process.waitFor(5, TimeUnit.SECONDS); + } catch (InterruptedException e) { + throw new RuntimeException(e); + } finally { + process.destroy(true); + } + } + } + + @Override + public void onStdout(ByteBuffer buffer, boolean closed) { + if (buffer.hasRemaining()) { + stdOutBuffer.put(buffer); + } + + if (closed) { + output.complete(new ByteArrayInputStream(stdOutBuffer.array())); + } + } + + @Override + public void onStderr(ByteBuffer buffer, boolean closed) { + if (!closed) { + byte[] bytes = new byte[buffer.remaining()]; + buffer.get(bytes); + errorMsg = new String(bytes); + } + super.onStderr(buffer, closed); + } + + public Future getInputStream() { + return output; + } + + public boolean isRunning() { + return process != null && process.isRunning(); + } +} diff --git a/backend/src/main/java/net/laprun/sustainability/power/sensors/macos/powermetrics/GrowableBuffer.java b/backend/src/main/java/net/laprun/sustainability/power/nuprocess/GrowableBuffer.java similarity index 88% rename from backend/src/main/java/net/laprun/sustainability/power/sensors/macos/powermetrics/GrowableBuffer.java rename to backend/src/main/java/net/laprun/sustainability/power/nuprocess/GrowableBuffer.java index 58ccedf..57acf2e 100644 --- a/backend/src/main/java/net/laprun/sustainability/power/sensors/macos/powermetrics/GrowableBuffer.java +++ b/backend/src/main/java/net/laprun/sustainability/power/nuprocess/GrowableBuffer.java @@ -1,4 +1,4 @@ -package net.laprun.sustainability.power.sensors.macos.powermetrics; +package net.laprun.sustainability.power.nuprocess; import java.nio.ByteBuffer; diff --git a/backend/src/main/java/net/laprun/sustainability/power/sensors/macos/powermetrics/PowermetricsProcessHandler.java b/backend/src/main/java/net/laprun/sustainability/power/sensors/macos/powermetrics/PowermetricsProcessHandler.java index 41e40f3..e3873fc 100644 --- a/backend/src/main/java/net/laprun/sustainability/power/sensors/macos/powermetrics/PowermetricsProcessHandler.java +++ b/backend/src/main/java/net/laprun/sustainability/power/sensors/macos/powermetrics/PowermetricsProcessHandler.java @@ -1,95 +1,20 @@ package net.laprun.sustainability.power.sensors.macos.powermetrics; -import java.io.ByteArrayInputStream; -import java.io.InputStream; -import java.nio.ByteBuffer; -import java.util.Arrays; -import java.util.concurrent.CompletableFuture; -import java.util.concurrent.Future; -import java.util.concurrent.TimeUnit; - -import com.zaxxer.nuprocess.NuAbstractProcessHandler; -import com.zaxxer.nuprocess.NuProcess; - -public class PowermetricsProcessHandler extends NuAbstractProcessHandler { - private String errorMsg; - private NuProcess process; - private final String[] command; - private final GrowableBuffer stdOutBuffer = new GrowableBuffer(); - private final CompletableFuture output = new CompletableFuture<>(); +import net.laprun.sustainability.power.nuprocess.BaseProcessHandler; +public class PowermetricsProcessHandler extends BaseProcessHandler { public PowermetricsProcessHandler(String... command) { - if (command == null || command.length == 0) { - throw new IllegalArgumentException("No powermetrics options specified"); - } + super(command); + } + + @Override + protected String[] initCommand(String... command) { final var additionalArgsCardinality = 3; final var args = new String[command.length + additionalArgsCardinality]; args[0] = "sudo"; args[1] = "powermetrics"; args[2] = "--samplers"; System.arraycopy(command, 0, args, additionalArgsCardinality, command.length); - this.command = args; - } - - public String[] command() { - return command; - } - - @Override - public void onPreStart(NuProcess nuProcess) { - this.process = nuProcess; - } - - @Override - public void onExit(int statusCode) { - if (Integer.MIN_VALUE == statusCode) { - throw new IllegalArgumentException("Unknown command " + Arrays.toString(command)); - } - if (statusCode != 0) { - throw new RuntimeException("Couldn't execute command " + Arrays.toString(command) - + ". Error code: " + statusCode + ", message: " + errorMsg); - } - } - - public void stop() { - if (process.isRunning()) { - process.destroy(false); - try { - process.waitFor(5, TimeUnit.SECONDS); - } catch (InterruptedException e) { - throw new RuntimeException(e); - } finally { - process.destroy(true); - } - } - } - - @Override - public void onStdout(ByteBuffer buffer, boolean closed) { - if (buffer.hasRemaining()) { - stdOutBuffer.put(buffer); - } - - if (closed) { - output.complete(new ByteArrayInputStream(stdOutBuffer.array())); - } - } - - @Override - public void onStderr(ByteBuffer buffer, boolean closed) { - if (!closed) { - byte[] bytes = new byte[buffer.remaining()]; - buffer.get(bytes); - errorMsg = new String(bytes); - } - super.onStderr(buffer, closed); - } - - public Future getInputStream() { - return output; - } - - public boolean isRunning() { - return process != null && process.isRunning(); + return args; } }