Skip to content

Commit

Permalink
detect fs device partition automatically
Browse files Browse the repository at this point in the history
  • Loading branch information
mullermarian committed Apr 24, 2021
1 parent ffe910d commit 0d8bd23
Show file tree
Hide file tree
Showing 7 changed files with 118 additions and 40 deletions.
12 changes: 10 additions & 2 deletions driver/src/main/java/studio/driver/LibUsbDetectionHelper.java
Original file line number Diff line number Diff line change
Expand Up @@ -115,10 +115,18 @@ private static void registerCallback(int vendorId, int productId, DeviceHotplugE
LOGGER.info(String.format("Hotplug event callback (%04x:%04x): " + event, vendorId, productId));
switch (event) {
case LibUsb.HOTPLUG_EVENT_DEVICE_ARRIVED:
CompletableFuture.runAsync(() -> listener.onDevicePlugged(device));
CompletableFuture.runAsync(() -> listener.onDevicePlugged(device))
.exceptionally(e -> {
LOGGER.log(Level.SEVERE, "An error occurred while handling device plug event", e);
return null;
});
break;
case LibUsb.HOTPLUG_EVENT_DEVICE_LEFT:
CompletableFuture.runAsync(() -> listener.onDeviceUnplugged(device));
CompletableFuture.runAsync(() -> listener.onDeviceUnplugged(device))
.exceptionally(e -> {
LOGGER.log(Level.SEVERE, "An error occurred while handling device unplug event", e);
return null;
});
break;
}
return 0; // Do not deregister the callback
Expand Down
86 changes: 86 additions & 0 deletions driver/src/main/java/studio/driver/fs/DeviceUtils.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
/*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
*/

package studio.driver.fs;

import org.apache.commons.lang3.SystemUtils;
import studio.driver.StoryTellerException;

import java.io.BufferedReader;
import java.io.File;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.stream.Collectors;

public class DeviceUtils {

private static final Logger LOGGER = Logger.getLogger(DeviceUtils.class.getName());

public static List<String> listMountPoints() {
if (SystemUtils.IS_OS_WINDOWS) {
return Arrays.stream(File.listRoots())
.map(root -> root.toPath().toString())
.collect(Collectors.toList());
} else {
final String CMD_DF = "df -l";
final Pattern dfPattern = Pattern.compile("^(\\/[^ ]+)[^/]+(/.*)$");

List<String> mountPoints = new ArrayList<>();

Process dfProcess = null;
BufferedReader dfReader = null;
try {
dfProcess = Runtime.getRuntime().exec(CMD_DF);
dfReader = new BufferedReader(new InputStreamReader(dfProcess.getInputStream()));
String dfLine;
while ((dfLine = dfReader.readLine()) != null) {
if (dfLine.isEmpty()) {
continue;
}
final Matcher matcher = dfPattern.matcher(dfLine);
if (matcher.matches()) {
final String dev = matcher.group(1);
final String rootPath = matcher.group(2);
if (dev.startsWith("/dev/")) {
mountPoints.add(rootPath);
}
}
}
} catch (IOException e) {
throw new StoryTellerException("Failed to list mount points", e);
} finally {
if (dfProcess != null) {
try {
int exitValue = dfProcess.waitFor();
if (exitValue != 0) {
LOGGER.log(Level.SEVERE, "Abnormal command termination. Exit value: " + exitValue);
}
dfProcess.destroy();
} catch (InterruptedException e) {
LOGGER.log(Level.SEVERE, "Error while waiting for command to complete", e);
}
}
if (dfReader != null) {
try {
dfReader.close();
} catch (IOException e) {
LOGGER.log(Level.SEVERE, "Failed to close command output reader", e);
}
}
}

return mountPoints;
}
}

}
41 changes: 17 additions & 24 deletions driver/src/main/java/studio/driver/fs/FsStoryTellerAsyncDriver.java
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,6 @@ public class FsStoryTellerAsyncDriver {
private static final String CONTENT_FOLDER = ".content";
private static final String NODE_INDEX_FILENAME = "ni";

private static final String FS_MOUNTPOINT_PROP = "studio.fs.mountpoint";
private static final long FS_MOUNTPOINT_POLL_DELAY = 1000L;
private static final long FS_MOUNTPOINT_RETRY = 10;

Expand All @@ -57,32 +56,26 @@ public FsStoryTellerAsyncDriver() {
LibUsbDetectionHelper.initializeLibUsb(DeviceVersion.DEVICE_VERSION_2, new DeviceHotplugEventListener() {
@Override
public void onDevicePlugged(Device device) {
// Use configuration to determine mount point
partitionMountPoint = System.getProperty(FS_MOUNTPOINT_PROP);
if (partitionMountPoint == null || partitionMountPoint.isBlank()) {
throw new StoryTellerException("FS device partition must be defined with system property " + FS_MOUNTPOINT_PROP);
}
LOGGER.fine("Lunii FS mount point: " + partitionMountPoint);

// Wait for partition to be available
String mdFile = partitionMountPoint + File.separator + DEVICE_METADATA_FILENAME;
boolean mounted = false;
try {
for (int i = 0; i < FS_MOUNTPOINT_RETRY && !mounted; i++) {
File folder = new File(mdFile);
if (folder.exists()) {
LOGGER.info("FS device partition is mounted.");
mounted = true;
} else {
Thread.sleep(FS_MOUNTPOINT_POLL_DELAY);
}
// Wait for a partition to be mounted which contains the .md file
LOGGER.fine("Waiting for device partition...");
for (int i = 0; i < FS_MOUNTPOINT_RETRY && partitionMountPoint==null; i++) {
try {
Thread.sleep(FS_MOUNTPOINT_POLL_DELAY);
DeviceUtils.listMountPoints().forEach(path -> {
LOGGER.finest("Looking for .md file on mount point / drive: " + path);
File mdFile = new File(path, DEVICE_METADATA_FILENAME);
if (mdFile.exists()) {
partitionMountPoint = path;
LOGGER.info("FS device partition located: " + partitionMountPoint);
}
});
} catch (InterruptedException e) {
LOGGER.log(Level.SEVERE, "Failed to locate device partition", e);
}
} catch (InterruptedException e) {
LOGGER.log(Level.SEVERE, "Failed to open device partition", e);
}

if (!mounted) {
throw new StoryTellerException("FS device partition is not mounted: " + partitionMountPoint);
if (partitionMountPoint == null) {
throw new StoryTellerException("Could not locate device partition");
}

// Update device reference
Expand Down
4 changes: 2 additions & 2 deletions web-ui/src/main/resources/log4j2.xml
Original file line number Diff line number Diff line change
Expand Up @@ -32,12 +32,12 @@
<AppenderRef ref="RollingFile"/>
</Logger>

<Logger name="studio.driver" level="ALL" additivity="false">
<Logger name="studio.driver" level="TRACE" additivity="false">
<AppenderRef ref="STDOUT"/>
<AppenderRef ref="RollingFile"/>
</Logger>

<Logger name="studio.core" level="ALL" additivity="false">
<Logger name="studio.core" level="TRACE" additivity="false">
<AppenderRef ref="STDOUT"/>
<AppenderRef ref="RollingFile"/>
</Logger>
Expand Down
5 changes: 1 addition & 4 deletions web-ui/src/main/resources/studio-linux.sh
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,6 @@
STUDIO_PATH="`dirname \"$0\"`"
DOT_STUDIO=$HOME/.studio

# Configure mount point of the device
FS_MOUNTPOINT=

# Make sure the .studio subdirectories exist
if [ ! -d $DOT_STUDIO/agent ]; then mkdir -p $DOT_STUDIO/agent; fi
if [ ! -d $DOT_STUDIO/db ]; then mkdir -p $DOT_STUDIO/db; fi
Expand All @@ -15,4 +12,4 @@ if [ ! -d $DOT_STUDIO/library ]; then mkdir -p $DOT_STUDIO/library; fi
cp $STUDIO_PATH/agent/studio-agent-${project.version}-jar-with-dependencies.jar $DOT_STUDIO/agent/studio-agent.jar
cp $STUDIO_PATH/agent/studio-metadata-${project.version}-jar-with-dependencies.jar $DOT_STUDIO/agent/studio-metadata.jar

java -Dvertx.disableDnsResolver=true -Djava.util.logging.manager=org.apache.logging.log4j.jul.LogManager -Dvertx.logger-delegate-factory-class-name=io.vertx.core.logging.Log4j2LogDelegateFactory -Dfile.encoding=UTF-8 -Dstudio.fs.mountpoint=$FS_MOUNTPOINT -cp $STUDIO_PATH/${project.build.finalName}.jar:$STUDIO_PATH/lib/*:. io.vertx.core.Launcher run ${vertx.main.verticle}
java -Dvertx.disableDnsResolver=true -Djava.util.logging.manager=org.apache.logging.log4j.jul.LogManager -Dvertx.logger-delegate-factory-class-name=io.vertx.core.logging.Log4j2LogDelegateFactory -Dfile.encoding=UTF-8 -cp $STUDIO_PATH/${project.build.finalName}.jar:$STUDIO_PATH/lib/*:. io.vertx.core.Launcher run ${vertx.main.verticle}
5 changes: 1 addition & 4 deletions web-ui/src/main/resources/studio-macos.sh
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,6 @@
STUDIO_PATH="`dirname \"$0\"`"
DOT_STUDIO="$HOME/.studio"

# Configure mount point of the device
FS_MOUNTPOINT=/Volumes/LUNII

# Make sure the .studio subdirectories exist
if [ ! -d $DOT_STUDIO/agent ]; then mkdir -p $DOT_STUDIO/agent; fi
if [ ! -d $DOT_STUDIO/db ]; then mkdir -p $DOT_STUDIO/db; fi
Expand All @@ -15,4 +12,4 @@ if [ ! -d $DOT_STUDIO/library ]; then mkdir -p $DOT_STUDIO/library; fi
cp $STUDIO_PATH/agent/studio-agent-${project.version}-jar-with-dependencies.jar $DOT_STUDIO/agent/studio-agent.jar
cp $STUDIO_PATH/agent/studio-metadata-${project.version}-jar-with-dependencies.jar $DOT_STUDIO/agent/studio-metadata.jar

java -Dvertx.disableDnsResolver=true -Djava.util.logging.manager=org.apache.logging.log4j.jul.LogManager -Dvertx.logger-delegate-factory-class-name=io.vertx.core.logging.Log4j2LogDelegateFactory -Dfile.encoding=UTF-8 -Dstudio.fs.mountpoint=$FS_MOUNTPOINT -cp $STUDIO_PATH/${project.build.finalName}.jar:$STUDIO_PATH/lib/*:. io.vertx.core.Launcher run ${vertx.main.verticle}
java -Dvertx.disableDnsResolver=true -Djava.util.logging.manager=org.apache.logging.log4j.jul.LogManager -Dvertx.logger-delegate-factory-class-name=io.vertx.core.logging.Log4j2LogDelegateFactory -Dfile.encoding=UTF-8 -cp $STUDIO_PATH/${project.build.finalName}.jar:$STUDIO_PATH/lib/*:. io.vertx.core.Launcher run ${vertx.main.verticle}
5 changes: 1 addition & 4 deletions web-ui/src/main/resources/studio-windows.bat
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,6 @@
set STUDIO_PATH=%~dp0
set DOT_STUDIO=%UserProfile%\.studio

:: Configure mount point of the device
set FS_MOUNTPOINT=

:: Make sure the .studio subdirectories exist
if not exist %DOT_STUDIO%\agent\* mkdir %DOT_STUDIO%\agent
if not exist %DOT_STUDIO%\db\* mkdir %DOT_STUDIO%\db
Expand All @@ -15,4 +12,4 @@ if not exist %DOT_STUDIO%\library\* mkdir %DOT_STUDIO%\library
copy %STUDIO_PATH%\agent\studio-agent-${project.version}-jar-with-dependencies.jar %DOT_STUDIO%\agent\studio-agent.jar
copy %STUDIO_PATH%\agent\studio-metadata-${project.version}-jar-with-dependencies.jar %DOT_STUDIO%\agent\studio-metadata.jar

java -Dvertx.disableDnsResolver=true -Djava.util.logging.manager=org.apache.logging.log4j.jul.LogManager -Dvertx.logger-delegate-factory-class-name=io.vertx.core.logging.Log4j2LogDelegateFactory -Dfile.encoding=UTF-8 -Dstudio.fs.mountpoint=%FS_MOUNTPOINT% -cp %STUDIO_PATH%/${project.build.finalName}.jar;%STUDIO_PATH%/lib/*;. io.vertx.core.Launcher run ${vertx.main.verticle}
java -Dvertx.disableDnsResolver=true -Djava.util.logging.manager=org.apache.logging.log4j.jul.LogManager -Dvertx.logger-delegate-factory-class-name=io.vertx.core.logging.Log4j2LogDelegateFactory -Dfile.encoding=UTF-8 -cp %STUDIO_PATH%/${project.build.finalName}.jar;%STUDIO_PATH%/lib/*;. io.vertx.core.Launcher run ${vertx.main.verticle}

0 comments on commit 0d8bd23

Please sign in to comment.