3 Commits

Author SHA1 Message Date
6b89dbcc46 dump 2 2025-06-25 08:09:19 +02:00
651f1fc94b a start button 2025-06-24 17:33:43 +02:00
3bf4784c0d dump 2025-06-24 16:59:32 +02:00
60 changed files with 260 additions and 1741 deletions

View File

@@ -2,7 +2,7 @@
<configuration default="false" name="Main 2" type="QsApplicationConfigurationType" factoryName="QuarkusApplication">
<option name="MAIN_CLASS_NAME" value="com.usatiuk.dhfsfuse.Main" />
<module name="dhfs-fuse" />
<option name="VM_PARAMETERS" value="-XX:+UnlockDiagnosticVMOptions -XX:+UseParallelGC -XX:+DebugNonSafepoints --enable-preview --add-exports java.base/sun.nio.ch=ALL-UNNAMED --add-opens=java.base/java.nio=ALL-UNNAMED --add-exports java.base/jdk.internal.access=ALL-UNNAMED -ea -Xmx512M -Ddhfs.webui.root=$ProjectFileDir$/../webui/dist -Ddhfs.fuse.root=${HOME}/dhfs_test/2/fuse -Ddhfs.objects.persistence.root=${HOME}/dhfs_test/2/data -Ddhfs.objects.peerdiscovery.broadcast=false -Dquarkus.http.port=9020 -Dquarkus.http.ssl-port=9021 -Ddhfs.peerdiscovery.preset-uuid=22000000-0000-0000-0000-000000000000 -Ddhfs.peerdiscovery.static-peers=11000000-0000-0000-0000-000000000000:127.0.0.1:9010:9011" />
<option name="VM_PARAMETERS" value="-XX:+UnlockDiagnosticVMOptions -XX:+UseParallelGC -XX:+DebugNonSafepoints --enable-preview --add-exports java.base/sun.nio.ch=ALL-UNNAMED --add-opens=java.base/java.nio=ALL-UNNAMED --add-exports java.base/jdk.internal.access=ALL-UNNAMED -ea -Xmx512M -Ddhfs.webui.root=$ProjectFileDir$/../webui/dist -Ddhfs.fuse.root=${HOME}/dhfs_test/2/fuse -Ddhfs.objects.persistence.files.root=${HOME}/dhfs_test/2/data -Ddhfs.objects.persistence.stuff.root=${HOME}/dhfs_test/2/data/stuff -Ddhfs.objects.peerdiscovery.broadcast=false -Dquarkus.http.port=9020 -Dquarkus.http.ssl-port=9021 -Ddhfs.peerdiscovery.preset-uuid=22000000-0000-0000-0000-000000000000 -Ddhfs.peerdiscovery.static-peers=11000000-0000-0000-0000-000000000000:127.0.0.1:9010:9011" />
<extension name="coverage">
<pattern>
<option name="PATTERN" value="com.usatiuk.dhfs.remoteobj.*" />

View File

@@ -2,7 +2,7 @@
<configuration default="false" name="Main" type="QsApplicationConfigurationType" factoryName="QuarkusApplication" nameIsGenerated="true">
<option name="MAIN_CLASS_NAME" value="com.usatiuk.dhfsfuse.Main" />
<module name="dhfs-fuse" />
<option name="VM_PARAMETERS" value="-XX:+UnlockDiagnosticVMOptions -XX:+UseZGC -XX:+ZGenerational --enable-preview -XX:+DebugNonSafepoints --add-exports java.base/sun.nio.ch=ALL-UNNAMED --add-opens=java.base/java.nio=ALL-UNNAMED --add-exports java.base/jdk.internal.access=ALL-UNNAMED -ea -Xmx1G -Ddhfs.webui.root=$ProjectFileDir$/../webui/dist -Ddhfs.fuse.root=${HOME}/dhfs_test/1/fuse -Ddhfs.objects.persistence.root=${HOME}/dhfs_test/1/data -Ddhfs.objects.peerdiscovery.broadcast=true -Dquarkus.http.port=9010 -Dquarkus.http.ssl-port=9011 -Ddhfs.peerdiscovery.preset-uuid=11000000-0000-0000-0000-000000000000 -Ddhfs.peerdiscovery.static-peers=22000000-0000-0000-0000-000000000000:127.0.0.1:9020:9021 -Dquarkus.http.host=0.0.0.0" />
<option name="VM_PARAMETERS" value="-XX:+UnlockDiagnosticVMOptions -XX:+UseZGC -XX:+ZGenerational --enable-preview -XX:+DebugNonSafepoints --add-exports java.base/sun.nio.ch=ALL-UNNAMED --add-opens=java.base/java.nio=ALL-UNNAMED --add-exports java.base/jdk.internal.access=ALL-UNNAMED -ea -Xmx1G -Ddhfs.webui.root=$ProjectFileDir$/../webui/dist -Ddhfs.fuse.root=${HOME}/dhfs_test/1/fuse -Ddhfs.objects.persistence.files.root=${HOME}/dhfs_test/1/data -Ddhfs.objects.persistence.stuff.root=${HOME}/dhfs_test/1/data/stuff -Ddhfs.objects.peerdiscovery.broadcast=true -Dquarkus.http.port=9010 -Dquarkus.http.ssl-port=9011 -Ddhfs.peerdiscovery.preset-uuid=11000000-0000-0000-0000-000000000000 -Ddhfs.peerdiscovery.static-peers=22000000-0000-0000-0000-000000000000:127.0.0.1:9020:9021 -Dquarkus.http.host=0.0.0.0" />
<extension name="coverage">
<pattern>
<option name="PATTERN" value="com.usatiuk.dhfs.remoteobj.*" />

View File

@@ -0,0 +1,43 @@
version: "3.2"
services:
dhfs1:
build: .
privileged: true
devices:
- /dev/fuse
volumes:
- $HOME/dhfs/dhfs1:/dhfs_root
- $HOME/dhfs/dhfs1_f:/dhfs_root/fuse:rshared
- ./target/quarkus-app:/app
command: "java --add-exports java.base/sun.nio.ch=ALL-UNNAMED
-Ddhfs.objects.persistence.files.root=/dhfs_root/p
-Ddhfs.objects.root=/dhfs_root/d
-Ddhfs.fuse.root=/dhfs_root/fuse -Dquarkus.http.host=0.0.0.0
-agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=*:5005
-jar /app/quarkus-run.jar"
ports:
- 8080:8080
- 8081:8443
- 5005:5005
dhfs2:
build: .
privileged: true
devices:
- /dev/fuse
volumes:
- $HOME/dhfs/dhfs2:/dhfs_root
- $HOME/dhfs/dhfs2_f:/dhfs_root/fuse:rshared
- ./target/quarkus-app:/app
command: "java --add-exports java.base/sun.nio.ch=ALL-UNNAMED
--add-exports java.base/jdk.internal.access=ALL-UNNAMED
--add-opens=java.base/java.nio=ALL-UNNAMED
-Ddhfs.objects.persistence.files.root=/dhfs_root/p
-Ddhfs.objects.root=/dhfs_root/d
-Ddhfs.fuse.root=/dhfs_root/fuse -Dquarkus.http.host=0.0.0.0
-agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=*:5010
-jar /app/quarkus-run.jar"
ports:
- 8090:8080
- 8091:8443
- 5010:5010

View File

@@ -21,7 +21,7 @@ abstract public class TempDataProfile implements QuarkusTestProfile {
throw new RuntimeException(e);
}
var ret = new HashMap<String, String>();
ret.put("dhfs.objects.persistence.root", tempDirWithPrefix.resolve("dhfs_root_test").toString());
ret.put("dhfs.objects.persistence.files.root", tempDirWithPrefix.resolve("dhfs_root_test").toString());
ret.put("dhfs.fuse.root", tempDirWithPrefix.resolve("dhfs_fuse_root_test").toString());
getConfigOverrides(ret);
return ret;

View File

@@ -15,7 +15,7 @@ import java.util.Objects;
@ApplicationScoped
public class TestDataCleaner {
@ConfigProperty(name = "dhfs.objects.persistence.root")
@ConfigProperty(name = "dhfs.objects.persistence.files.root")
String tempDirectory;
void init(@Observes @Priority(1) StartupEvent event) throws IOException {

View File

@@ -1,4 +1,5 @@
dhfs.objects.persistence.root=${HOME}/dhfs_data/dhfs_root_test
dhfs.objects.persistence.files.root=${HOME}/dhfs_data/dhfs_root_test
dhfs.objects.root=${HOME}/dhfs_data/dhfs_root_d_test
dhfs.fuse.root=${HOME}/dhfs_data/dhfs_fuse_root_test
dhfs.objects.ref_verification=true
dhfs.objects.deletion.delay=0

View File

@@ -11,7 +11,8 @@ services:
- $HOME/dhfs/dhfs1_f:/dhfs_root/fuse:rshared
- ./target/quarkus-app:/app
command: "java --add-exports java.base/sun.nio.ch=ALL-UNNAMED
-Ddhfs.objects.persistence.root=/dhfs_root/p
-Ddhfs.objects.persistence.files.root=/dhfs_root/p
-Ddhfs.objects.root=/dhfs_root/d
-Ddhfs.fuse.root=/dhfs_root/fuse -Dquarkus.http.host=0.0.0.0
-agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=*:5005
-jar /app/quarkus-run.jar"
@@ -31,7 +32,8 @@ services:
command: "java --add-exports java.base/sun.nio.ch=ALL-UNNAMED
--add-exports java.base/jdk.internal.access=ALL-UNNAMED
--add-opens=java.base/java.nio=ALL-UNNAMED
-Ddhfs.objects.persistence.root=/dhfs_root/p
-Ddhfs.objects.persistence.files.root=/dhfs_root/p
-Ddhfs.objects.root=/dhfs_root/d
-Ddhfs.fuse.root=/dhfs_root/fuse -Dquarkus.http.host=0.0.0.0
-agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=*:5010
-jar /app/quarkus-run.jar"

View File

@@ -21,7 +21,7 @@ abstract public class TempDataProfile implements QuarkusTestProfile {
throw new RuntimeException(e);
}
var ret = new HashMap<String, String>();
ret.put("dhfs.objects.persistence.root", tempDirWithPrefix.resolve("dhfs_root_test").toString());
ret.put("dhfs.objects.persistence.files.root", tempDirWithPrefix.resolve("dhfs_root_test").toString());
ret.put("dhfs.fuse.root", tempDirWithPrefix.resolve("dhfs_fuse_root_test").toString());
getConfigOverrides(ret);
return ret;

View File

@@ -15,7 +15,7 @@ import java.util.Objects;
@ApplicationScoped
public class TestDataCleaner {
@ConfigProperty(name = "dhfs.objects.persistence.root")
@ConfigProperty(name = "dhfs.objects.persistence.files.root")
String tempDirectory;
void init(@Observes @Priority(1) StartupEvent event) throws IOException {

View File

@@ -56,8 +56,8 @@ public class DhfsFuseIT {
waitingConsumer2.waitUntil(frame -> frame.getUtf8String().contains("Listening"), 60, TimeUnit.SECONDS);
waitingConsumer1.waitUntil(frame -> frame.getUtf8String().contains("Listening"), 60, TimeUnit.SECONDS);
c1uuid = container1.execInContainer("/bin/sh", "-c", "cat /dhfs_test/data/self_uuid").getStdout();
c2uuid = container2.execInContainer("/bin/sh", "-c", "cat /dhfs_test/data/self_uuid").getStdout();
c1uuid = container1.execInContainer("/bin/sh", "-c", "cat /dhfs_test/data/stuff/self_uuid").getStdout();
c2uuid = container2.execInContainer("/bin/sh", "-c", "cat /dhfs_test/data/stuff/self_uuid").getStdout();
Assertions.assertDoesNotThrow(() -> UUID.fromString(c1uuid));
Assertions.assertDoesNotThrow(() -> UUID.fromString(c2uuid));

View File

@@ -72,9 +72,9 @@ public class DhfsFusex3IT {
waitingConsumer2.waitUntil(frame -> frame.getUtf8String().contains("Listening"), 60, TimeUnit.SECONDS);
waitingConsumer1.waitUntil(frame -> frame.getUtf8String().contains("Listening"), 60, TimeUnit.SECONDS);
c1uuid = container1.execInContainer("/bin/sh", "-c", "cat /dhfs_test/data/self_uuid").getStdout();
c2uuid = container2.execInContainer("/bin/sh", "-c", "cat /dhfs_test/data/self_uuid").getStdout();
c3uuid = container3.execInContainer("/bin/sh", "-c", "cat /dhfs_test/data/self_uuid").getStdout();
c1uuid = container1.execInContainer("/bin/sh", "-c", "cat /dhfs_test/data/stuff/self_uuid").getStdout();
c2uuid = container2.execInContainer("/bin/sh", "-c", "cat /dhfs_test/data/stuff/self_uuid").getStdout();
c3uuid = container3.execInContainer("/bin/sh", "-c", "cat /dhfs_test/data/stuff/self_uuid").getStdout();
Log.info(container1.getContainerId() + "=" + c1uuid + " = 1");
Log.info(container2.getContainerId() + "=" + c2uuid + " = 2");

View File

@@ -87,7 +87,7 @@ public class DhfsImage implements Future<String> {
"-Dquarkus.log.category.\"com.usatiuk.objects.transaction\".level=INFO",
"-Ddhfs.objects.periodic-push-op-interval=5s",
"-Ddhfs.fuse.root=/dhfs_test/fuse",
"-Ddhfs.objects.persistence.root=/dhfs_test/data",
"-Ddhfs.objects.persistence.files.root=/dhfs_test/data",
"-Ddhfs.objects.persistence.stuff.root=/dhfs_test/data/stuff",
"-jar", "/app/quarkus-run.jar")
.run("mkdir /dhfs_test && chmod 777 /dhfs_test")

View File

@@ -72,8 +72,8 @@ public class KillIT {
waitingConsumer2.waitUntil(frame -> frame.getUtf8String().contains("Listening"), 60, TimeUnit.SECONDS);
waitingConsumer1.waitUntil(frame -> frame.getUtf8String().contains("Listening"), 60, TimeUnit.SECONDS);
c1uuid = container1.execInContainer("/bin/sh", "-c", "cat /dhfs_test/data/self_uuid").getStdout();
c2uuid = container2.execInContainer("/bin/sh", "-c", "cat /dhfs_test/data/self_uuid").getStdout();
c1uuid = container1.execInContainer("/bin/sh", "-c", "cat /dhfs_test/data/stuff/self_uuid").getStdout();
c2uuid = container2.execInContainer("/bin/sh", "-c", "cat /dhfs_test/data/stuff/self_uuid").getStdout();
Assertions.assertDoesNotThrow(() -> UUID.fromString(c1uuid));
Assertions.assertDoesNotThrow(() -> UUID.fromString(c2uuid));

View File

@@ -23,7 +23,6 @@ import java.util.stream.Stream;
import static org.awaitility.Awaitility.await;
@Disabled
public class LazyFsIT {
GenericContainer<?> container1;
GenericContainer<?> container2;
@@ -83,8 +82,8 @@ public class LazyFsIT {
waitingConsumer2.waitUntil(frame -> frame.getUtf8String().contains("Listening"), 60, TimeUnit.SECONDS);
waitingConsumer1.waitUntil(frame -> frame.getUtf8String().contains("Listening"), 60, TimeUnit.SECONDS);
c1uuid = container1.execInContainer("/bin/sh", "-c", "cat /dhfs_test/data/self_uuid").getStdout();
c2uuid = container2.execInContainer("/bin/sh", "-c", "cat /dhfs_test/data/self_uuid").getStdout();
c1uuid = container1.execInContainer("/bin/sh", "-c", "cat /dhfs_test/data/stuff/self_uuid").getStdout();
c2uuid = container2.execInContainer("/bin/sh", "-c", "cat /dhfs_test/data/stuff/self_uuid").getStdout();
Assertions.assertDoesNotThrow(() -> UUID.fromString(c1uuid));
Assertions.assertDoesNotThrow(() -> UUID.fromString(c2uuid));

View File

@@ -66,8 +66,8 @@ public class ResyncIT {
@Test
void readWriteFileTest() throws IOException, InterruptedException, TimeoutException {
await().atMost(45, TimeUnit.SECONDS).until(() -> 0 == container1.execInContainer("/bin/sh", "-c", "echo tesempty > /dhfs_test/fuse/testf1").getExitCode());
c1uuid = container1.execInContainer("/bin/sh", "-c", "cat /dhfs_test/data/self_uuid").getStdout();
c2uuid = container2.execInContainer("/bin/sh", "-c", "cat /dhfs_test/data/self_uuid").getStdout();
c1uuid = container1.execInContainer("/bin/sh", "-c", "cat /dhfs_test/data/stuff/self_uuid").getStdout();
c2uuid = container2.execInContainer("/bin/sh", "-c", "cat /dhfs_test/data/stuff/self_uuid").getStdout();
Assertions.assertDoesNotThrow(() -> UUID.fromString(c1uuid));
Assertions.assertDoesNotThrow(() -> UUID.fromString(c2uuid));
@@ -106,8 +106,8 @@ public class ResyncIT {
foundWc = container2.execInContainer("/bin/sh", "-c", "find /dhfs_test/fuse -type f | wc -l");
Assertions.assertEquals(200, Integer.valueOf(foundWc.getStdout().strip()));
c1uuid = container1.execInContainer("/bin/sh", "-c", "cat /dhfs_test/data/self_uuid").getStdout();
c2uuid = container2.execInContainer("/bin/sh", "-c", "cat /dhfs_test/data/self_uuid").getStdout();
c1uuid = container1.execInContainer("/bin/sh", "-c", "cat /dhfs_test/data/stuff/self_uuid").getStdout();
c2uuid = container2.execInContainer("/bin/sh", "-c", "cat /dhfs_test/data/stuff/self_uuid").getStdout();
Assertions.assertDoesNotThrow(() -> UUID.fromString(c1uuid));
Assertions.assertDoesNotThrow(() -> UUID.fromString(c2uuid));
@@ -146,8 +146,8 @@ public class ResyncIT {
await().atMost(45, TimeUnit.SECONDS).until(() -> 0 == container1.execInContainer("/bin/sh", "-c", "mv /dhfs_test/fuse/testd1 /dhfs_test/fuse/testd2").getExitCode());
await().atMost(45, TimeUnit.SECONDS).until(() -> 0 == container1.execInContainer("/bin/sh", "-c", "echo tesempty2 > /dhfs_test/fuse/testd2/testf2").getExitCode());
c1uuid = container1.execInContainer("/bin/sh", "-c", "cat /dhfs_test/data/self_uuid").getStdout();
c2uuid = container2.execInContainer("/bin/sh", "-c", "cat /dhfs_test/data/self_uuid").getStdout();
c1uuid = container1.execInContainer("/bin/sh", "-c", "cat /dhfs_test/data/stuff/self_uuid").getStdout();
c2uuid = container2.execInContainer("/bin/sh", "-c", "cat /dhfs_test/data/stuff/self_uuid").getStdout();
Assertions.assertDoesNotThrow(() -> UUID.fromString(c1uuid));
Assertions.assertDoesNotThrow(() -> UUID.fromString(c2uuid));

View File

@@ -1,4 +1,5 @@
dhfs.objects.persistence.root=${HOME}/dhfs_data/dhfs_root_test
dhfs.objects.persistence.files.root=${HOME}/dhfs_data/dhfs_root_test
dhfs.objects.root=${HOME}/dhfs_data/dhfs_root_d_test
dhfs.fuse.root=${HOME}/dhfs_data/dhfs_fuse_root_test
dhfs.objects.ref_verification=true
dhfs.objects.deletion.delay=0

View File

@@ -58,7 +58,7 @@ public class LmdbObjectPersistentStore implements ObjectPersistentStore {
private Dbi<ByteBuffer> _db;
private boolean _ready = false;
public LmdbObjectPersistentStore(@ConfigProperty(name = "dhfs.objects.persistence.root") String root) {
public LmdbObjectPersistentStore(@ConfigProperty(name = "dhfs.objects.persistence.files.root") String root) {
_root = Path.of(root).resolve("objects");
}

View File

@@ -3,7 +3,7 @@ dhfs.objects.writeback.limit=16777216
dhfs.objects.lru.limit=67108864
dhfs.objects.lru.print-stats=false
dhfs.objects.lock_timeout_secs=15
dhfs.objects.persistence.root=${HOME}/dhfs_default/data/objs
dhfs.objects.persistence.files.root=${HOME}/dhfs_default/data/objs
dhfs.objects.persistence.snapshot-extra-checks=false
dhfs.objects.last-seen.update=60
dhfs.objects.last-seen.timeout=43200

View File

@@ -21,7 +21,7 @@ public class TempDataProfile implements QuarkusTestProfile {
throw new RuntimeException(e);
}
var ret = new HashMap<String, String>();
ret.put("dhfs.objects.persistence.root", tempDirWithPrefix.resolve("dhfs_root_test").toString());
ret.put("dhfs.objects.persistence.files.root", tempDirWithPrefix.resolve("dhfs_root_test").toString());
ret.put("dhfs.fuse.root", tempDirWithPrefix.resolve("dhfs_fuse_root_test").toString());
ret.put("dhfs.objects.persistence", "lmdb");
getConfigOverrides(ret);

View File

@@ -15,7 +15,7 @@ import java.util.Objects;
@ApplicationScoped
public class TestDataCleaner {
@ConfigProperty(name = "dhfs.objects.persistence.root")
@ConfigProperty(name = "dhfs.objects.persistence.files.root")
String tempDirectory;
void init(@Observes @Priority(1) StartupEvent event) throws IOException {

View File

@@ -0,0 +1,43 @@
version: "3.2"
services:
dhfs1:
build: .
privileged: true
devices:
- /dev/fuse
volumes:
- $HOME/dhfs/dhfs1:/dhfs_root
- $HOME/dhfs/dhfs1_f:/dhfs_root/fuse:rshared
- ./target/quarkus-app:/app
command: "java --add-exports java.base/sun.nio.ch=ALL-UNNAMED
-Ddhfs.objects.persistence.files.root=/dhfs_root/p
-Ddhfs.objects.root=/dhfs_root/d
-Ddhfs.fuse.root=/dhfs_root/fuse -Dquarkus.http.host=0.0.0.0
-agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=*:5005
-jar /app/quarkus-run.jar"
ports:
- 8080:8080
- 8081:8443
- 5005:5005
dhfs2:
build: .
privileged: true
devices:
- /dev/fuse
volumes:
- $HOME/dhfs/dhfs2:/dhfs_root
- $HOME/dhfs/dhfs2_f:/dhfs_root/fuse:rshared
- ./target/quarkus-app:/app
command: "java --add-exports java.base/sun.nio.ch=ALL-UNNAMED
--add-exports java.base/jdk.internal.access=ALL-UNNAMED
--add-opens=java.base/java.nio=ALL-UNNAMED
-Ddhfs.objects.persistence.files.root=/dhfs_root/p
-Ddhfs.objects.root=/dhfs_root/d
-Ddhfs.fuse.root=/dhfs_root/fuse -Dquarkus.http.host=0.0.0.0
-agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=*:5010
-jar /app/quarkus-run.jar"
ports:
- 8090:8080
- 8091:8443
- 5010:5010

View File

@@ -19,7 +19,7 @@ import java.nio.file.Paths;
@ApplicationScoped
public class ShutdownChecker {
private static final String dataFileName = "running";
@ConfigProperty(name = "dhfs.objects.persistence.root")
@ConfigProperty(name = "dhfs.objects.persistence.files.root")
String dataRoot;
boolean _cleanShutdown = true;
boolean _initialized = false;

View File

@@ -32,7 +32,7 @@ public class DeferredInvalidationQueueService implements PeerConnectedEventListe
ReachablePeerManager reachablePeerManager;
@Inject
InvalidationQueueService invalidationQueueService;
@ConfigProperty(name = "dhfs.objects.persistence.root")
@ConfigProperty(name = "dhfs.objects.persistence.files.root")
String dataRoot;
private DeferredInvalidationQueueData _persistentData = new DeferredInvalidationQueueData();

View File

@@ -60,7 +60,7 @@ public class PersistentPeerDataService {
@ConfigProperty(name = "dhfs.peerdiscovery.preset-uuid")
Optional<String> presetUuid;
@ConfigProperty(name = "dhfs.objects.persistence.root")
@ConfigProperty(name = "dhfs.objects.persistence.stuff.root")
String stuffRoot;
private PeerId _selfUuid;

View File

@@ -8,6 +8,7 @@ dhfs.objects.reconnect_interval=5s
dhfs.objects.write_log=false
dhfs.objects.periodic-push-op-interval=5m
dhfs.fuse.root=${HOME}/dhfs_default/fuse
dhfs.objects.persistence.stuff.root=${HOME}/dhfs_default/data/stuff
dhfs.fuse.debug=false
dhfs.fuse.enabled=true
dhfs.files.allow_recursive_delete=false

View File

@@ -21,7 +21,7 @@ abstract public class TempDataProfile implements QuarkusTestProfile {
throw new RuntimeException(e);
}
var ret = new HashMap<String, String>();
ret.put("dhfs.objects.persistence.root", tempDirWithPrefix.resolve("dhfs_root_test").toString());
ret.put("dhfs.objects.persistence.files.root", tempDirWithPrefix.resolve("dhfs_root_test").toString());
ret.put("dhfs.fuse.root", tempDirWithPrefix.resolve("dhfs_fuse_root_test").toString());
getConfigOverrides(ret);
return ret;

View File

@@ -15,7 +15,7 @@ import java.util.Objects;
@ApplicationScoped
public class TestDataCleaner {
@ConfigProperty(name = "dhfs.objects.persistence.root")
@ConfigProperty(name = "dhfs.objects.persistence.files.root")
String tempDirectory;
void init(@Observes @Priority(1) StartupEvent event) throws IOException {

View File

@@ -1,4 +1,5 @@
dhfs.objects.persistence.root=${HOME}/dhfs_data/dhfs_root_test
dhfs.objects.persistence.files.root=${HOME}/dhfs_data/dhfs_root_test
dhfs.objects.root=${HOME}/dhfs_data/dhfs_root_d_test
dhfs.fuse.root=${HOME}/dhfs_data/dhfs_fuse_root_test
dhfs.objects.ref_verification=true
dhfs.objects.deletion.delay=0

View File

@@ -1,20 +1,13 @@
cmake_minimum_required(VERSION 3.10)
project(launcher)
if (CMAKE_SYSTEM_NAME STREQUAL "Darwin")
enable_language(OBJC)
enable_language(OBJCXX)
endif ()
list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake")
set(CMAKE_CXX_STANDARD 20)
set(CMAKE_CXX_STANDARD_REQUIRED YES)
if (CMAKE_BUILD_TYPE STREQUAL "Debug")
# if (NOT DEFINED SANITIZE)
# set(SANITIZE YES)
# endif ()
# if (NOT DEFINED SANITIZE)
# set(SANITIZE YES)
# endif ()
endif ()
if (SANITIZE STREQUAL "YES")
@@ -35,8 +28,6 @@ if (NOT CMAKE_BUILD_TYPE STREQUAL "Debug")
add_link_options(-O3)
endif ()
include(wxWidgets)
add_subdirectory(utils)
add_subdirectory(libjvm_wrapper)
add_subdirectory(backend)
add_subdirectory(gui)

View File

@@ -1,14 +1,9 @@
add_library(backend
src/DhfsInstance.cpp
include_public/DhfsInstance.hpp
src/DhfsStartOptions.cpp
include_public/DhfsStartOptions.hpp
src/DhfsWxProcess.cpp
include_public/DhfsWxProcess.hpp
)
target_include_directories(backend PRIVATE include)
target_include_directories(backend PUBLIC include_public)
target_link_libraries(backend PRIVATE ${wxWidgets_LIBRARIES})
target_link_libraries(backend PUBLIC utils)
target_link_libraries(backend PUBLIC libjvm_wrapper)

View File

@@ -5,50 +5,30 @@
#ifndef DHFSINSTANCE_HPP
#define DHFSINSTANCE_HPP
#include <wx/process.h>
#include <string>
#include <vector>
#include <thread>
#include<mutex>
#include "DhfsStartOptions.hpp"
#include "DhfsWxProcess.hpp"
#include <jni.h>
enum class DhfsInstanceState {
STARTING,
RUNNING,
STOPPING,
STOPPED,
};
class DhfsInstance {
friend DhfsWxProcess;
public:
DhfsInstance();
virtual ~DhfsInstance();
~DhfsInstance();
DhfsInstanceState state();
void start(DhfsStartOptions start_options);
void start();
void stop();
protected:
virtual void OnStateChange() = 0;
virtual void OnRead(std::string s) = 0;
private:
std::unique_ptr<DhfsWxProcess> process = std::make_unique<DhfsWxProcess>(*this);
void OnTerminateInternal(int pid, int status);
DhfsInstanceState _state = DhfsInstanceState::STOPPED;
std::thread _readThread;
std::thread _readThreadErr;
std::mutex _mutex;
JavaVM* _jvm = nullptr;
JNIEnv *_env = nullptr;
};

View File

@@ -1,25 +0,0 @@
//
// Created by Stepan Usatiuk on 25.06.2025.
//
#ifndef DHFSSTARTOPTIONS_HPP
#define DHFSSTARTOPTIONS_HPP
#include <string>
#include <vector>
class DhfsStartOptions {
public:
std::string java_home;
std::string xmx;
std::string mount_path;
std::string data_path;
std::string jar_path;
std::string webui_path;
std::vector<std::string> extra_options;
std::vector<std::string> getOptions();
};
#endif //DHFSSTARTOPTIONS_HPP

View File

@@ -1,24 +0,0 @@
//
// Created by Stepan Usatiuk on 25.06.2025.
//
#ifndef DHFSWXPROCESS_HPP
#define DHFSWXPROCESS_HPP
#include <wx/process.h>
class DhfsInstance;
class DhfsWxProcess : public wxProcess {
public:
DhfsWxProcess(DhfsInstance& parent);
protected:
void OnTerminate(int pid, int status) override;
private:
DhfsInstance& _instance;
};
#endif //DHFSWXPROCESS_HPP

View File

@@ -7,26 +7,20 @@
#include <stdexcept>
#include <vector>
#include "Exception.h"
#include "LibjvmWrapper.hpp"
DhfsInstance::DhfsInstance() {
}
DhfsInstance::~DhfsInstance() {
stop();
}
DhfsInstanceState DhfsInstance::state() {
std::lock_guard<std::mutex> lock(_mutex);
return _state;
}
void DhfsInstance::start(DhfsStartOptions options) {
std::lock_guard<std::mutex> lock(_mutex);
void DhfsInstance::start() {
switch (_state) {
case DhfsInstanceState::RUNNING:
case DhfsInstanceState::STARTING:
case DhfsInstanceState::STOPPING:
return;
case DhfsInstanceState::STOPPED:
break;
@@ -34,96 +28,23 @@ void DhfsInstance::start(DhfsStartOptions options) {
throw std::runtime_error("Unknown DhfsInstanceState");
}
_state = DhfsInstanceState::STARTING;
OnStateChange();
JavaVMInitArgs args;
std::vector<JavaVMOption> options;
args.version = JNI_VERSION_21;
args.nOptions = 0;
args.options = options.data();
args.ignoreUnrecognized = false;
std::vector<char*> args;
auto readyOptions = options.getOptions();
for (const auto& option: readyOptions) {
args.push_back(const_cast<char*>(option.c_str()));
}
long ret = wxExecute(args.data(), wxEXEC_ASYNC | wxEXEC_HIDE_CONSOLE | wxEXEC_MAKE_GROUP_LEADER, process.get(),
nullptr);
if (ret == 0) {
_state = DhfsInstanceState::STOPPED;
throw Exception("Failed to start DHFS");
}
OnRead("Started! PID: " + std::to_string(process->GetPid()) + "\n");
_readThread = std::thread([&]() {
auto stream = process->GetInputStream();
bool searching = true;
std::string lastLine;
while (!stream->Eof() || stream->CanRead()) {
char buffer[1024];
size_t bytesRead = stream->Read(buffer, sizeof(buffer) - 1).LastRead();
if (bytesRead > 0) {
buffer[bytesRead] = '\0';
if (searching) {
for (size_t i = 0; i < bytesRead; i++) {
lastLine += buffer[i];
if (buffer[i] == '\n') {
if (lastLine.find("Listening on:") != std::string::npos) {
searching = false;
std::lock_guard<std::mutex> lock(_mutex);
if (_state == DhfsInstanceState::STARTING) {
_state = DhfsInstanceState::RUNNING;
OnStateChange();
}
}
lastLine = "";
}
}
}
OnRead(std::string(buffer));
}
}
});
_readThreadErr = std::thread([&]() {
auto stream = process->GetErrorStream();
while (!stream->Eof() || stream->CanRead()) {
char buffer[1024];
size_t bytesRead = stream->Read(buffer, sizeof(buffer) - 1).LastRead();
if (bytesRead > 0) {
buffer[bytesRead] = '\0';
OnRead(std::string(buffer));
}
}
});
LibjvmWrapper::instance().JNI_CreateJavaVM(&_jvm, (void**) &_env, &args);
}
void DhfsInstance::stop() {
std::lock_guard<std::mutex> lock(_mutex);
switch (_state) {
case DhfsInstanceState::RUNNING:
case DhfsInstanceState::STARTING:
break;
case DhfsInstanceState::STOPPED:
case DhfsInstanceState::STOPPING:
return;
default:
throw std::runtime_error("Unknown DhfsInstanceState");
}
_state = DhfsInstanceState::STOPPING;
OnStateChange();
int err = wxProcess::Kill(process->GetPid(), wxSIGTERM, wxKILL_CHILDREN);
if (err != wxKILL_OK) {
OnRead("Failed to stop DHFS: " + std::to_string(err) + "\n");
}
}
void DhfsInstance::OnTerminateInternal(int pid, int status) {
std::lock_guard<std::mutex> lock(_mutex);
_state = DhfsInstanceState::STOPPED;
_readThread.join();
_readThreadErr.join();
OnRead("Stopped!\n");
OnStateChange();
}

View File

@@ -1,31 +0,0 @@
//
// Created by Stepan Usatiuk on 25.06.2025.
//
#include "DhfsStartOptions.hpp"
std::vector<std::string> DhfsStartOptions::getOptions() {
std::vector<std::string> out;
out.emplace_back(java_home + "/bin/java");
out.emplace_back("--enable-preview");
out.emplace_back("-Xmx" + xmx);
out.emplace_back("-Ddhfs.objects.writeback.limit=16777216");
out.emplace_back("-Ddhfs.objects.lru.limit=67108864");
out.emplace_back("--add-exports");
out.emplace_back("java.base/sun.nio.ch=ALL-UNNAMED");
out.emplace_back("--add-exports");
out.emplace_back("java.base/jdk.internal.access=ALL-UNNAMED");
out.emplace_back("--add-opens=java.base/java.nio=ALL-UNNAMED");
out.emplace_back("-Dquarkus.http.host=0.0.0.0");
out.emplace_back("-Dquarkus.log.category.\"com.usatiuk\".level=INFO");
out.emplace_back("-Dquarkus.log.category.\"com.usatiuk.dhfs\".level=INFO");
out.emplace_back("-Ddhfs.fuse.root=" + mount_path);
out.emplace_back("-Ddhfs.objects.persistence.root=" + data_path);
out.emplace_back("-Ddhfs.webui.root=" + webui_path);
for (auto option: extra_options) {
out.emplace_back(option);
}
out.emplace_back("-jar");
out.emplace_back(jar_path);
return out;
}

View File

@@ -1,14 +0,0 @@
//
// Created by Stepan Usatiuk on 25.06.2025.
//
#include "DhfsWxProcess.hpp"
#include "DhfsInstance.hpp"
DhfsWxProcess::DhfsWxProcess(DhfsInstance& parent): wxProcess(wxPROCESS_REDIRECT), _instance(parent) {
}
void DhfsWxProcess::OnTerminate(int pid, int status) {
_instance.OnTerminateInternal(pid, status);
}

View File

@@ -1,26 +0,0 @@
# if linux
if (CMAKE_SYSTEM_NAME STREQUAL "Linux")
option(wxWidgets_IN_TREE_BUILD "Build wxWidgets in-tree" OFF)
else ()
option(wxWidgets_IN_TREE_BUILD "Build wxWidgets in-tree" ON)
endif ()
if (wxWidgets_IN_TREE_BUILD)
message(STATUS "Building wxWidgets in-tree")
include(FetchContent)
set(wxBUILD_SHARED OFF)
FetchContent_Declare(wx
GIT_REPOSITORY https://github.com/wxWidgets/wxWidgets.git
GIT_TAG v3.2.8.1
GIT_SHALLOW TRUE
GIT_PROGRESS TRUE
)
FetchContent_MakeAvailable(wx)
set(wxWidgets_LIBRARIES wx::core wx::base wx::webview wx::net)
else ()
message(STATUS "Using system wxWidgets")
find_package(wxWidgets REQUIRED COMPONENTS net core base webview)
if (wxWidgets_USE_FILE) # not defined in CONFIG mode
include(${wxWidgets_USE_FILE})
endif ()
endif ()

View File

@@ -1,28 +1,14 @@
add_executable(DhfsLauncher
find_package(wxWidgets REQUIRED COMPONENTS net core base)
if (wxWidgets_USE_FILE) # not defined in CONFIG mode
include(${wxWidgets_USE_FILE})
endif ()
add_executable(launcher
src/LauncherApp.cpp
src/GLauncherApp.cpp
src/LauncherAppMainFrame.cpp
src/DhfsGuiInstance.cpp
src/DhfsGuiInstance.hpp
src/DhfsWxServer.cpp
src/DhfsWxServer.hpp
src/DhfsWxConnection.cpp
src/DhfsWxConnection.hpp
)
if (CMAKE_SYSTEM_NAME STREQUAL "Darwin")
target_sources(DhfsLauncher PRIVATE
src/macos/utils.m
src/macos/utils.h
)
endif ()
target_link_libraries(DhfsLauncher ${wxWidgets_LIBRARIES})
target_link_libraries(DhfsLauncher backend utils)
set_target_properties(DhfsLauncher PROPERTIES
MACOSX_BUNDLE TRUE
MACOSX_BUNDLE_GUI_IDENTIFIER "com.usatiuk.dhfs.launcher"
MACOSX_BUNDLE_BUNDLE_NAME "DHFS Launcher"
)
target_link_libraries(launcher ${wxWidgets_LIBRARIES})
target_link_libraries(launcher backend)

View File

@@ -1,24 +0,0 @@
//
// Created by Stepan Usatiuk on 25.06.2025.
//
#include "DhfsGuiInstance.hpp"
#include "LauncherAppMainFrame.h"
wxDEFINE_EVENT(NEW_LINE_OUTPUT_EVENT, wxCommandEvent);
wxDEFINE_EVENT(DHFS_STATE_CHANGE_EVENT, wxCommandEvent);
DhfsGuiInstance::DhfsGuiInstance(wxEvtHandler& parent): _evtHandler(parent) {
}
void DhfsGuiInstance::OnStateChange() {
wxCommandEvent* event = new wxCommandEvent(DHFS_STATE_CHANGE_EVENT);
_evtHandler.QueueEvent(event);
}
void DhfsGuiInstance::OnRead(std::string s) {
wxCommandEvent* event = new wxCommandEvent(NEW_LINE_OUTPUT_EVENT);
event->SetString(std::move(s));
_evtHandler.QueueEvent(event);
}

View File

@@ -1,25 +0,0 @@
//
// Created by Stepan Usatiuk on 25.06.2025.
//
#ifndef DHFSGUIINSTANCE_HPP
#define DHFSGUIINSTANCE_HPP
#include "DhfsInstance.hpp"
wxDECLARE_EVENT(NEW_LINE_OUTPUT_EVENT, wxCommandEvent);
wxDECLARE_EVENT(DHFS_STATE_CHANGE_EVENT, wxCommandEvent);
class DhfsGuiInstance : public DhfsInstance {
public:
DhfsGuiInstance(wxEvtHandler& parent);
void OnStateChange() override;
void OnRead(std::string s) override;
protected:
wxEvtHandler& _evtHandler;
};
#endif //DHFSGUIINSTANCE_HPP

View File

@@ -1,21 +0,0 @@
//
// Created by Stepan Usatiuk on 29.06.2025.
//
#include "DhfsWxConnection.hpp"
#include <iostream>
#include "wx/app.h"
#include "LauncherApp.h"
DhfsWxConnection::DhfsWxConnection() : wxConnection() {
}
bool DhfsWxConnection::OnExec(const wxString& wx_uni_char_refs, const wxString& wx_uni_chars) {
std::cout << "DhfsWxConnection::OnExec called with topic: " << wx_uni_char_refs << " and item: " << wx_uni_chars <<
std::endl;
wxGetApp().Open();
return true;
}

View File

@@ -1,18 +0,0 @@
//
// Created by Stepan Usatiuk on 29.06.2025.
//
#ifndef DHFSWXCONNECTION_HPP
#define DHFSWXCONNECTION_HPP
#include "wx/ipc.h"
class DhfsWxConnection : public wxConnection {
public:
DhfsWxConnection();
bool OnExec(const wxString&, const wxString&) override;
};
#endif //DHFSWXCONNECTION_HPP

View File

@@ -1,11 +0,0 @@
//
// Created by Stepan Usatiuk on 29.06.2025.
//
#include "DhfsWxServer.hpp"
#include "DhfsWxConnection.hpp"
wxConnectionBase* DhfsWxServer::OnAcceptConnection(const wxString& topic) {
return new DhfsWxConnection();
}

View File

@@ -1,16 +0,0 @@
//
// Created by Stepan Usatiuk on 29.06.2025.
//
#ifndef DHFSWXSERVER_HPP
#define DHFSWXSERVER_HPP
#include "wx/ipc.h"
class DhfsWxServer : public wxServer {
public:
wxConnectionBase* OnAcceptConnection(const wxString& topic) override;
};
#endif //DHFSWXSERVER_HPP

View File

@@ -11,13 +11,13 @@
MainFrame::MainFrame( wxWindow* parent, wxWindowID id, const wxString& title, const wxPoint& pos, const wxSize& size, long style, const wxString& name ) : wxFrame( parent, id, title, pos, size, style, name )
{
this->SetSizeHints( wxSize( 600,400 ), wxDefaultSize );
this->SetSizeHints( wxSize( 100,50 ), wxDefaultSize );
m_statusBar1 = this->CreateStatusBar( 1, wxSTB_SIZEGRIP, wxID_ANY );
wxBoxSizer* bSizer3;
bSizer3 = new wxBoxSizer( wxVERTICAL );
m_notebook1 = new wxNotebook( this, wxID_ANY, wxDefaultPosition, wxDefaultSize, 0|wxBORDER_NONE );
m_notebook1 = new wxNotebook( this, wxID_ANY, wxDefaultPosition, wxDefaultSize, 0 );
m_panel1 = new wxPanel( m_notebook1, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxTAB_TRAVERSAL );
wxBoxSizer* bSizer2;
bSizer2 = new wxBoxSizer( wxVERTICAL );
@@ -30,9 +30,9 @@ MainFrame::MainFrame( wxWindow* parent, wxWindowID id, const wxString& title, co
gbSizer1->SetFlexibleDirection( wxBOTH );
gbSizer1->SetNonFlexibleGrowMode( wxFLEX_GROWMODE_SPECIFIED );
m_statusText = new wxStaticText( sbSizer4->GetStaticBox(), wxID_ANY, _("Running"), wxDefaultPosition, wxDefaultSize, 0 );
m_statusText->Wrap( -1 );
gbSizer1->Add( m_statusText, wxGBPosition( 0, 0 ), wxGBSpan( 1, 1 ), wxALIGN_CENTER_VERTICAL|wxALL, 5 );
m_staticText1 = new wxStaticText( sbSizer4->GetStaticBox(), wxID_ANY, _("Running"), wxDefaultPosition, wxDefaultSize, 0 );
m_staticText1->Wrap( -1 );
gbSizer1->Add( m_staticText1, wxGBPosition( 0, 0 ), wxGBSpan( 1, 1 ), wxALL, 5 );
m_startStopButton = new wxButton( sbSizer4->GetStaticBox(), wxID_ANY, _("Start"), wxDefaultPosition, wxDefaultSize, 0 );
gbSizer1->Add( m_startStopButton, wxGBPosition( 0, 1 ), wxGBSpan( 1, 1 ), wxALL, 5 );
@@ -41,105 +41,25 @@ MainFrame::MainFrame( wxWindow* parent, wxWindowID id, const wxString& title, co
sbSizer4->Add( gbSizer1, 1, wxEXPAND, 5 );
bSizer2->Add( sbSizer4, 1, wxALL|wxEXPAND, 5 );
bSizer2->Add( sbSizer4, 1, wxEXPAND, 5 );
wxStaticBoxSizer* sbSizer6;
sbSizer6 = new wxStaticBoxSizer( new wxStaticBox( m_panel1, wxID_ANY, _("Statistics") ), wxVERTICAL );
bSizer2->Add( sbSizer6, 1, wxALL|wxEXPAND, 5 );
bSizer2->Add( sbSizer6, 1, wxEXPAND, 5 );
m_panel1->SetSizer( bSizer2 );
m_panel1->Layout();
bSizer2->Fit( m_panel1 );
m_notebook1->AddPage( m_panel1, _("Info"), false );
m_notebook1->AddPage( m_panel1, _("Info"), true );
m_panel3 = new wxPanel( m_notebook1, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxTAB_TRAVERSAL );
wxGridSizer* gSizer1;
gSizer1 = new wxGridSizer( 1, 1, 0, 0 );
m_logOutputTextCtrl = new wxTextCtrl( m_panel3, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, wxTE_MULTILINE|wxTE_READONLY|wxBORDER_NONE );
gSizer1->Add( m_logOutputTextCtrl, 0, wxALL|wxEXPAND, 5 );
m_panel3->SetSizer( gSizer1 );
m_panel3->Layout();
gSizer1->Fit( m_panel3 );
m_notebook1->AddPage( m_panel3, _("Logs"), true );
m_notebook1->AddPage( m_panel3, _("Logs"), false );
m_panel2 = new wxPanel( m_notebook1, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxTAB_TRAVERSAL );
wxBoxSizer* bSizer5;
bSizer5 = new wxBoxSizer( wxVERTICAL );
wxStaticBoxSizer* sbSizer3;
sbSizer3 = new wxStaticBoxSizer( new wxStaticBox( m_panel2, wxID_ANY, _("JVM") ), wxVERTICAL );
wxGridBagSizer* gbSizer2;
gbSizer2 = new wxGridBagSizer( 0, 0 );
gbSizer2->SetFlexibleDirection( wxBOTH );
gbSizer2->SetNonFlexibleGrowMode( wxFLEX_GROWMODE_SPECIFIED );
m_button2 = new wxButton( sbSizer3->GetStaticBox(), wxID_ANY, _("Reset"), wxDefaultPosition, wxDefaultSize, 0 );
gbSizer2->Add( m_button2, wxGBPosition( 0, 3 ), wxGBSpan( 1, 1 ), wxALL, 5 );
gbSizer2->Add( 50, 0, wxGBPosition( 0, 2 ), wxGBSpan( 1, 1 ), wxEXPAND, 5 );
m_javaHomeDirPicker = new wxDirPickerCtrl( sbSizer3->GetStaticBox(), wxID_ANY, wxEmptyString, _("Select a folder"), wxDefaultPosition, wxDefaultSize, wxDIRP_DEFAULT_STYLE|wxDIRP_USE_TEXTCTRL );
gbSizer2->Add( m_javaHomeDirPicker, wxGBPosition( 0, 1 ), wxGBSpan( 1, 1 ), wxALL|wxEXPAND, 5 );
m_staticText2 = new wxStaticText( sbSizer3->GetStaticBox(), wxID_ANY, _("Java Home"), wxDefaultPosition, wxDefaultSize, 0 );
m_staticText2->Wrap( -1 );
gbSizer2->Add( m_staticText2, wxGBPosition( 0, 0 ), wxGBSpan( 1, 1 ), wxALIGN_CENTER_VERTICAL|wxALL, 5 );
gbSizer2->AddGrowableCol( 1 );
sbSizer3->Add( gbSizer2, 1, wxEXPAND, 5 );
bSizer5->Add( sbSizer3, 1, wxALL|wxEXPAND|wxFIXED_MINSIZE, 5 );
wxStaticBoxSizer* sbSizer41;
sbSizer41 = new wxStaticBoxSizer( new wxStaticBox( m_panel2, wxID_ANY, _("Paths") ), wxVERTICAL );
wxGridBagSizer* gbSizer3;
gbSizer3 = new wxGridBagSizer( 0, 0 );
gbSizer3->SetFlexibleDirection( wxBOTH );
gbSizer3->SetNonFlexibleGrowMode( wxFLEX_GROWMODE_SPECIFIED );
m_staticText6 = new wxStaticText( sbSizer41->GetStaticBox(), wxID_ANY, _("Mount path"), wxDefaultPosition, wxDefaultSize, 0 );
m_staticText6->Wrap( -1 );
gbSizer3->Add( m_staticText6, wxGBPosition( 0, 0 ), wxGBSpan( 1, 1 ), wxALIGN_CENTER_VERTICAL|wxALL, 5 );
m_staticText61 = new wxStaticText( sbSizer41->GetStaticBox(), wxID_ANY, _("Data path"), wxDefaultPosition, wxDefaultSize, 0 );
m_staticText61->Wrap( -1 );
gbSizer3->Add( m_staticText61, wxGBPosition( 1, 0 ), wxGBSpan( 1, 1 ), wxALIGN_CENTER_VERTICAL|wxALL, 5 );
m_mountPathDirPicker = new wxDirPickerCtrl( sbSizer41->GetStaticBox(), wxID_ANY, wxEmptyString, _("Select a folder"), wxDefaultPosition, wxDefaultSize, wxDIRP_USE_TEXTCTRL );
gbSizer3->Add( m_mountPathDirPicker, wxGBPosition( 0, 1 ), wxGBSpan( 1, 1 ), wxALL|wxEXPAND, 5 );
m_dataPathDirPicker = new wxDirPickerCtrl( sbSizer41->GetStaticBox(), wxID_ANY, wxEmptyString, _("Select a folder"), wxDefaultPosition, wxDefaultSize, wxDIRP_USE_TEXTCTRL );
gbSizer3->Add( m_dataPathDirPicker, wxGBPosition( 1, 1 ), wxGBSpan( 1, 1 ), wxALL|wxEXPAND, 5 );
gbSizer3->AddGrowableCol( 1 );
sbSizer41->Add( gbSizer3, 1, wxEXPAND, 5 );
bSizer5->Add( sbSizer41, 1, wxALL|wxEXPAND, 5 );
m_panel2->SetSizer( bSizer5 );
m_panel2->Layout();
bSizer5->Fit( m_panel2 );
m_notebook1->AddPage( m_panel2, _("Settings"), false );
m_panel4 = new wxPanel( m_notebook1, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxTAB_TRAVERSAL );
m_notebook1->AddPage( m_panel4, _("Advanced Settings"), false );
m_panel5 = new wxPanel( m_notebook1, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxTAB_TRAVERSAL );
m_notebook1->AddPage( m_panel5, _("Web UI"), false );
bSizer3->Add( m_notebook1, 1, wxBOTTOM|wxEXPAND|wxTOP, 5 );
bSizer3->Add( m_notebook1, 1, wxALL|wxEXPAND, 5 );
this->SetSizer( bSizer3 );
@@ -148,15 +68,7 @@ MainFrame::MainFrame( wxWindow* parent, wxWindowID id, const wxString& title, co
this->Centre( wxBOTH );
// Connect Events
this->Connect( wxEVT_ACTIVATE, wxActivateEventHandler( MainFrame::OnActivate ) );
this->Connect( wxEVT_ACTIVATE_APP, wxActivateEventHandler( MainFrame::OnActivateApp ) );
this->Connect( wxEVT_CLOSE_WINDOW, wxCloseEventHandler( MainFrame::OnClose ) );
m_notebook1->Connect( wxEVT_COMMAND_NOTEBOOK_PAGE_CHANGED, wxNotebookEventHandler( MainFrame::OnNotebookPageChanged ), NULL, this );
m_notebook1->Connect( wxEVT_COMMAND_NOTEBOOK_PAGE_CHANGING, wxNotebookEventHandler( MainFrame::OnNotebookPageChanging ), NULL, this );
m_startStopButton->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( MainFrame::OnStartStopButtonClick ), NULL, this );
m_javaHomeDirPicker->Connect( wxEVT_COMMAND_DIRPICKER_CHANGED, wxFileDirPickerEventHandler( MainFrame::OnJavaHomeChanged ), NULL, this );
m_mountPathDirPicker->Connect( wxEVT_COMMAND_DIRPICKER_CHANGED, wxFileDirPickerEventHandler( MainFrame::OnMountPathChanged ), NULL, this );
m_dataPathDirPicker->Connect( wxEVT_COMMAND_DIRPICKER_CHANGED, wxFileDirPickerEventHandler( MainFrame::OnDataPathChanged ), NULL, this );
}
MainFrame::~MainFrame()

View File

@@ -25,8 +25,6 @@
#include <wx/sizer.h>
#include <wx/statbox.h>
#include <wx/panel.h>
#include <wx/textctrl.h>
#include <wx/filepicker.h>
#include <wx/notebook.h>
#include <wx/frame.h>
@@ -43,36 +41,18 @@ class MainFrame : public wxFrame
wxStatusBar* m_statusBar1;
wxNotebook* m_notebook1;
wxPanel* m_panel1;
wxStaticText* m_statusText;
wxStaticText* m_staticText1;
wxButton* m_startStopButton;
wxPanel* m_panel3;
wxTextCtrl* m_logOutputTextCtrl;
wxPanel* m_panel2;
wxButton* m_button2;
wxDirPickerCtrl* m_javaHomeDirPicker;
wxStaticText* m_staticText2;
wxStaticText* m_staticText6;
wxStaticText* m_staticText61;
wxDirPickerCtrl* m_mountPathDirPicker;
wxDirPickerCtrl* m_dataPathDirPicker;
wxPanel* m_panel4;
wxPanel* m_panel5;
// Virtual event handlers, override them in your derived class
virtual void OnActivate( wxActivateEvent& event ) { event.Skip(); }
virtual void OnActivateApp( wxActivateEvent& event ) { event.Skip(); }
virtual void OnClose( wxCloseEvent& event ) { event.Skip(); }
virtual void OnNotebookPageChanged( wxNotebookEvent& event ) { event.Skip(); }
virtual void OnNotebookPageChanging( wxNotebookEvent& event ) { event.Skip(); }
virtual void OnStartStopButtonClick( wxCommandEvent& event ) { event.Skip(); }
virtual void OnJavaHomeChanged( wxFileDirPickerEvent& event ) { event.Skip(); }
virtual void OnMountPathChanged( wxFileDirPickerEvent& event ) { event.Skip(); }
virtual void OnDataPathChanged( wxFileDirPickerEvent& event ) { event.Skip(); }
public:
MainFrame( wxWindow* parent, wxWindowID id = wxID_ANY, const wxString& title = _("DHFS"), const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxSize( 600,400 ), long style = wxDEFAULT_FRAME_STYLE|wxTAB_TRAVERSAL, const wxString& name = wxT("DHFS") );
MainFrame( wxWindow* parent, wxWindowID id = wxID_ANY, const wxString& title = _("DHFS"), const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxSize( 500,300 ), long style = wxDEFAULT_FRAME_STYLE|wxTAB_TRAVERSAL, const wxString& name = wxT("DHFS") );
~MainFrame();

View File

@@ -2,109 +2,32 @@
// Created by Stepan Usatiuk on 11.07.2024.
//
// For compilers that don't support precompilation, include "wx/wx.h"
#include "wx/wxprec.h"
#ifndef WX_PRECOMP
# include "wx/wx.h"
#endif
#include "wx/notebook.h"
#include "LauncherApp.h"
#include <filesystem>
#include "LauncherAppMainFrame.h"
#include "wx/taskbar.h"
#include <wx/fileconf.h>
#include <wx/stdpaths.h>
#include "wx/snglinst.h"
IMPLEMENT_APP(LauncherApp)
static std::string getServerSocket() {
#ifdef __WIN32__
return "dhfs-sock-" + wxGetUserId().ToStdString();
#else
return wxStandardPaths::Get().GetUserLocalDataDir().ToStdString()
+ "/" + "dhfs-sock-" + wxGetUserId().ToStdString();
#endif
}
// This is executed upon startup, like 'main()' in non-wxWidgets programs.
bool LauncherApp::OnInit() {
m_checker = new wxSingleInstanceChecker;
if (!std::filesystem::is_directory(wxStandardPaths::Get().GetUserLocalDataDir().ToStdString())
&& !std::filesystem::create_directories(wxStandardPaths::Get().GetUserLocalDataDir().ToStdString())) {
wxLogError("Couldn't create data directory: %s", wxStandardPaths::Get().GetUserLocalDataDir());
return false;
}
if (m_checker->IsAnotherRunning()) {
// wxLogError(_("Another program instance is already running, aborting."));
delete m_checker; // OnExit() won't be called if we return false
m_checker = NULL;
auto clinet = new wxClient();
auto conn = clinet->MakeConnection("dhfs", getServerSocket(), "dhfs");
conn->Execute("wakeup");
return false;
}
if (!m_server.Create(getServerSocket())) {
wxLogError("Couldn't create server!");
return false;
}
wxFrame* frame = new LauncherAppMainFrame(NULL);
frame->Show(true);
SetTopWindow(frame);
Bind(NEW_LINE_OUTPUT_EVENT, &LauncherApp::forwardEventToTopWindow, this);
Bind(DHFS_STATE_CHANGE_EVENT, &LauncherApp::forwardEventToTopWindow, this);
// wxTaskBarIcon* tb = new wxTaskBarIcon();
// auto img = new wxImage(32, 32, false);
// img->Clear(128);
// tb->SetIcon(*(new wxBitmapBundle(*(new wxBitmap(*img)))), "e");
return true;
}
bool LauncherApp::OnExceptionInMainLoop() {
try {
std::rethrow_exception(std::current_exception());
} catch (const std::exception& e) {
wxMessageBox(e.what(), "Error", wxOK | wxICON_ERROR | wxCENTRE, GetTopWindow());
}
return true;
}
int LauncherApp::OnExit() {
delete m_checker;
return wxApp::OnExit();
}
void LauncherApp::Open() {
if (m_topWindow) {
m_topWindow->SetFocus();
m_topWindow->Raise();
if (auto frame = dynamic_cast<wxFrame*>(m_topWindow)) {
frame->RequestUserAttention();
}
} else {
wxFrame* frame = new LauncherAppMainFrame(NULL);
frame->Show(true);
SetTopWindow(frame);
}
}
void LauncherApp::OnTopFrameClose(wxCloseEvent& event) {
SetTopWindow(nullptr);
}
void LauncherApp::forwardEventToTopWindow(wxCommandEvent& event) {
if (m_topWindow) {
m_topWindow->GetEventHandler()->ProcessEvent(event);
} else {
event.Skip();
}
}
#ifdef __APPLE__
void LauncherApp::MacReopenApp() {
this->Open();
}
#endif

View File

@@ -5,38 +5,11 @@
#ifndef HELLOWORLDAPP_H
#define HELLOWORLDAPP_H
#include "DhfsGuiInstance.hpp"
#include "wx/wx.h"
#include "DhfsWxServer.hpp"
class wxSingleInstanceChecker;
// The HelloWorldApp class. This class shows a window
// containing a statusbar with the text "Hello World"
class LauncherApp : public wxApp {
public:
virtual bool OnInit() override;
virtual int OnExit() override;
virtual bool OnExceptionInMainLoop() override;
#ifdef __APPLE__
void MacReopenApp() override;
#endif
void Open();
void OnTopFrameClose(wxCloseEvent& event);
private:
wxSingleInstanceChecker* m_checker = nullptr;
DhfsWxServer m_server;
void forwardEventToTopWindow(wxCommandEvent& event);
public:
DhfsGuiInstance m_dhfsInstance{*this};
virtual bool OnInit();
};
DECLARE_APP(LauncherApp)

View File

@@ -1,181 +1,13 @@
#include "LauncherAppMainFrame.h"
#include <iostream>
#include <wx/fileconf.h>
#include <wx/stdpaths.h>
#include <filesystem>
#ifdef __APPLE__
#include "macos/utils.h"
#endif
#include "LauncherApp.h"
#include "Exception.h"
std::string getBundlePath() {
if (wxGetenv("DHFS_BUNDLE_PATH") == NULL)
return std::filesystem::path(wxStandardPaths::Get().GetExecutablePath().ToStdString())
#ifndef __APPLE__
.parent_path()
#endif
.parent_path().string();
return wxGetenv("DHFS_BUNDLE_PATH");
}
LauncherAppMainFrame::LauncherAppMainFrame(wxWindow* parent)
: MainFrame(parent) {
m_javaHomeDirPicker->SetPath(wxFileConfig::Get()->Read(kJavaHomeSettingsKey));
m_mountPathDirPicker->SetPath(wxFileConfig::Get()->Read(kMountPointSettingsKey));
m_dataPathDirPicker->SetPath(wxFileConfig::Get()->Read(kDataDirSettingsKey));
m_webViewSizer = new wxGridSizer(1, 0, 0);
m_panel5->SetSizer(m_webViewSizer);
m_panel5->Layout();
m_webViewSizer->Fit(m_panel5);
Bind(NEW_LINE_OUTPUT_EVENT, &LauncherAppMainFrame::onNewLineOutput, this);
Bind(DHFS_STATE_CHANGE_EVENT, &LauncherAppMainFrame::onDhfsInstanceStateChange, this);
wxFont font = wxFont(wxSize(16, 16),
wxFontFamily::wxFONTFAMILY_TELETYPE,
wxFontStyle::wxFONTSTYLE_NORMAL,
wxFontWeight::wxFONTWEIGHT_NORMAL);
m_logOutputTextCtrl->SetFont(font);
updateState();
#ifdef __APPLE__
SetAppAsRegular();
#endif
}
static DhfsInstance& getDhfsInstance() {
return wxGetApp().m_dhfsInstance;
}
void LauncherAppMainFrame::updateState() {
switch (getDhfsInstance().state()) {
case DhfsInstanceState::RUNNING: {
m_statusText->SetLabel("Running");
m_startStopButton->SetLabel("Stop");
m_statusBar1->SetStatusText("Running", 0);
if (m_notebook1->GetSelection() == 4) {
if (m_webView != nullptr)
m_webView->LoadURL("http://localhost:8080");
}
wxGetApp().SetExitOnFrameDelete(false);
break;
}
case DhfsInstanceState::STARTING: {
m_statusText->SetLabel("Starting");
m_startStopButton->SetLabel("Stop");
m_statusBar1->SetStatusText("Starting", 0);
wxGetApp().SetExitOnFrameDelete(false);
break;
}
case DhfsInstanceState::STOPPED: {
m_statusText->SetLabel("Stopped");
m_startStopButton->SetLabel("Start");
m_statusBar1->SetStatusText("Stopped", 0);
wxGetApp().SetExitOnFrameDelete(true);
break;
}
case DhfsInstanceState::STOPPING: {
m_statusText->SetLabel("Stopping");
m_startStopButton->SetLabel("Kill");
m_statusBar1->SetStatusText("Stopping", 0);
wxGetApp().SetExitOnFrameDelete(false);
break;
}
default:
throw Exception("Unhandled switch case");
}
}
void LauncherAppMainFrame::OnStartStopButtonClick(wxCommandEvent& event) {
switch (getDhfsInstance().state()) {
case DhfsInstanceState::RUNNING:
case DhfsInstanceState::STARTING: {
getDhfsInstance().stop();
break;
}
case DhfsInstanceState::STOPPED: {
DhfsStartOptions options;
options.java_home = wxFileConfig::Get()->Read(kJavaHomeSettingsKey);
options.xmx = "512m";
options.mount_path = wxFileConfig::Get()->Read(kMountPointSettingsKey);
options.data_path = wxFileConfig::Get()->Read(kDataDirSettingsKey);
options.jar_path = getBundlePath() + "/app/Server/quarkus-run.jar";
options.webui_path = getBundlePath() + "/app/Webui";
getDhfsInstance().start(options);
break;
}
case DhfsInstanceState::STOPPING: {
// TODO:
break;
}
default:
throw Exception("Unhandled switch case");
}
updateState();
}
void LauncherAppMainFrame::OnJavaHomeChanged(wxFileDirPickerEvent& event) {
wxFileConfig::Get()->Write(kJavaHomeSettingsKey, event.GetPath());
}
void LauncherAppMainFrame::OnMountPathChanged(wxFileDirPickerEvent& event) {
wxFileConfig::Get()->Write(kMountPointSettingsKey, event.GetPath());
}
void LauncherAppMainFrame::OnDataPathChanged(wxFileDirPickerEvent& event) {
wxFileConfig::Get()->Write(kDataDirSettingsKey, event.GetPath());
}
void LauncherAppMainFrame::onNewLineOutput(wxCommandEvent& event) {
m_logOutputTextCtrl->AppendText(event.GetString());
}
void LauncherAppMainFrame::OnNotebookPageChanged(wxBookCtrlEvent& event) {
if (event.GetSelection() == 4) prepareWebview();
else unloadWebview();
}
void LauncherAppMainFrame::OnNotebookPageChanging(wxBookCtrlEvent& event) {
}
void LauncherAppMainFrame::onDhfsInstanceStateChange(wxCommandEvent& event) {
updateState();
}
void LauncherAppMainFrame::unloadWebview() {
if (m_webView != nullptr) {
m_webViewSizer->Detach(m_webView);
m_webView->Destroy();
m_webView = nullptr;
}
}
void LauncherAppMainFrame::prepareWebview() {
m_webView = wxWebView::New(m_panel5, wxID_ANY);
m_webViewSizer->Add(m_webView, 0, wxALL | wxEXPAND);
m_webView->LoadURL("http://localhost:8080");
m_panel5->Layout();
}
void LauncherAppMainFrame::OnActivate(wxActivateEvent& event) {
MainFrame::OnActivate(event);
}
void LauncherAppMainFrame::OnActivateApp(wxActivateEvent& event) {
MainFrame::OnActivateApp(event);
}
void LauncherAppMainFrame::OnClose(wxCloseEvent& event) {
#ifdef __APPLE__
SetAppAsAccessory();
#endif
wxGetApp().OnTopFrameClose(event);
MainFrame::OnClose(event);
std::cout << "Hi!" << std::endl;
_dhfsInstance.start();
// TODO: Implement OnStartStopButtonClick
}

View File

@@ -10,45 +10,13 @@ Subclass of MainFrame, which is generated by wxFormBuilder.
//// end generated include
#include <wx/webview.h>
#include "DhfsGuiInstance.hpp"
static constexpr auto kJavaHomeSettingsKey = "DHFS/JavaHome";
static constexpr auto kMountPointSettingsKey = "DHFS/MountDir";
static constexpr auto kDataDirSettingsKey = "DHFS/DataDir";
#include "DhfsInstance.hpp"
/** Implementing MainFrame */
class LauncherAppMainFrame : public MainFrame {
protected:
// Handlers for MainFrame events.
void OnStartStopButtonClick(wxCommandEvent& event) override;
void OnJavaHomeChanged(wxFileDirPickerEvent& event) override;
void OnMountPathChanged(wxFileDirPickerEvent& event) override;
void OnDataPathChanged(wxFileDirPickerEvent& event) override;
void OnNotebookPageChanged(wxNotebookEvent& event) override;
void OnNotebookPageChanging(wxNotebookEvent& event) override;
void onNewLineOutput(wxCommandEvent& event);
void onDhfsInstanceStateChange(wxCommandEvent& event);
void updateState();
void unloadWebview();
void prepareWebview();
void OnActivate(wxActivateEvent& event) override;
void OnActivateApp(wxActivateEvent& event) override;
void OnClose(wxCloseEvent& event) override;
void OnStartStopButtonClick(wxCommandEvent& event);
public:
/** Constructor */
@@ -57,8 +25,7 @@ public:
//// end generated class members
private:
wxWebView* m_webView = nullptr;
wxGridSizer* m_webViewSizer;
DhfsInstance _dhfsInstance;
};
#endif // __LauncherAppMainFrame__

View File

@@ -47,10 +47,10 @@
<property name="hidden">0</property>
<property name="id">wxID_ANY</property>
<property name="maximum_size"></property>
<property name="minimum_size">600,400</property>
<property name="minimum_size">100,50</property>
<property name="name">MainFrame</property>
<property name="pos"></property>
<property name="size">600,400</property>
<property name="size">500,300</property>
<property name="style">wxDEFAULT_FRAME_STYLE</property>
<property name="subclass">; ; forward_declare</property>
<property name="title">DHFS</property>
@@ -60,9 +60,6 @@
<property name="window_name">DHFS</property>
<property name="window_style">wxTAB_TRAVERSAL</property>
<property name="xrc_skip_sizer">1</property>
<event name="OnActivate">OnActivate</event>
<event name="OnActivateApp">OnActivateApp</event>
<event name="OnClose">OnClose</event>
<object class="wxStatusBar" expanded="true">
<property name="bg"></property>
<property name="context_help"></property>
@@ -94,7 +91,7 @@
<property name="permission">none</property>
<object class="sizeritem" expanded="true">
<property name="border">5</property>
<property name="flag">wxBOTTOM|wxEXPAND|wxTOP</property>
<property name="flag">wxALL|wxEXPAND</property>
<property name="proportion">1</property>
<object class="wxNotebook" expanded="true">
<property name="BottomDockable">1</property>
@@ -149,14 +146,12 @@
<property name="tooltip"></property>
<property name="window_extra_style"></property>
<property name="window_name"></property>
<property name="window_style">wxBORDER_NONE</property>
<event name="OnNotebookPageChanged">OnNotebookPageChanged</event>
<event name="OnNotebookPageChanging">OnNotebookPageChanging</event>
<property name="window_style"></property>
<object class="notebookpage" expanded="true">
<property name="bitmap"></property>
<property name="label">Info</property>
<property name="select">0</property>
<object class="wxPanel" expanded="true">
<property name="select">1</property>
<object class="wxPanel" expanded="false">
<property name="BottomDockable">1</property>
<property name="LeftDockable">1</property>
<property name="RightDockable">1</property>
@@ -215,7 +210,7 @@
<property name="permission">none</property>
<object class="sizeritem" expanded="false">
<property name="border">5</property>
<property name="flag">wxALL|wxEXPAND</property>
<property name="flag">wxEXPAND</property>
<property name="proportion">1</property>
<object class="wxStaticBoxSizer" expanded="false">
<property name="id">wxID_ANY</property>
@@ -244,7 +239,7 @@
<property name="border">5</property>
<property name="colspan">1</property>
<property name="column">0</property>
<property name="flag">wxALIGN_CENTER_VERTICAL|wxALL</property>
<property name="flag">wxALL</property>
<property name="row">0</property>
<property name="rowspan">1</property>
<object class="wxStaticText" expanded="false">
@@ -285,7 +280,7 @@
<property name="minimize_button">0</property>
<property name="minimum_size"></property>
<property name="moveable">1</property>
<property name="name">m_statusText</property>
<property name="name">m_staticText1</property>
<property name="pane_border">1</property>
<property name="pane_position"></property>
<property name="pane_size"></property>
@@ -389,7 +384,7 @@
</object>
<object class="sizeritem" expanded="false">
<property name="border">5</property>
<property name="flag">wxALL|wxEXPAND</property>
<property name="flag">wxEXPAND</property>
<property name="proportion">1</property>
<object class="wxStaticBoxSizer" expanded="false">
<property name="id">wxID_ANY</property>
@@ -407,7 +402,7 @@
<object class="notebookpage" expanded="true">
<property name="bitmap"></property>
<property name="label">Logs</property>
<property name="select">1</property>
<property name="select">0</property>
<object class="wxPanel" expanded="true">
<property name="BottomDockable">1</property>
<property name="LeftDockable">1</property>
@@ -460,80 +455,6 @@
<property name="window_extra_style"></property>
<property name="window_name"></property>
<property name="window_style">wxTAB_TRAVERSAL</property>
<object class="wxGridSizer" expanded="true">
<property name="cols">1</property>
<property name="hgap">0</property>
<property name="minimum_size"></property>
<property name="name">gSizer1</property>
<property name="permission">none</property>
<property name="rows">1</property>
<property name="vgap">0</property>
<object class="sizeritem" expanded="true">
<property name="border">5</property>
<property name="flag">wxALL|wxEXPAND</property>
<property name="proportion">0</property>
<object class="wxTextCtrl" expanded="true">
<property name="BottomDockable">1</property>
<property name="LeftDockable">1</property>
<property name="RightDockable">1</property>
<property name="TopDockable">1</property>
<property name="aui_layer">0</property>
<property name="aui_name"></property>
<property name="aui_position">0</property>
<property name="aui_row">0</property>
<property name="best_size"></property>
<property name="bg"></property>
<property name="caption"></property>
<property name="caption_visible">1</property>
<property name="center_pane">0</property>
<property name="close_button">1</property>
<property name="context_help"></property>
<property name="context_menu">1</property>
<property name="default_pane">0</property>
<property name="dock">Dock</property>
<property name="dock_fixed">0</property>
<property name="docking">Left</property>
<property name="drag_accept_files">0</property>
<property name="enabled">1</property>
<property name="fg"></property>
<property name="floatable">1</property>
<property name="font"></property>
<property name="gripper">0</property>
<property name="hidden">0</property>
<property name="id">wxID_ANY</property>
<property name="max_size"></property>
<property name="maximize_button">0</property>
<property name="maximum_size"></property>
<property name="maxlength">0</property>
<property name="min_size"></property>
<property name="minimize_button">0</property>
<property name="minimum_size"></property>
<property name="moveable">1</property>
<property name="name">m_logOutputTextCtrl</property>
<property name="pane_border">1</property>
<property name="pane_position"></property>
<property name="pane_size"></property>
<property name="permission">protected</property>
<property name="pin_button">1</property>
<property name="pos"></property>
<property name="resize">Resizable</property>
<property name="show">1</property>
<property name="size"></property>
<property name="style">wxTE_MULTILINE|wxTE_READONLY</property>
<property name="subclass">; ; forward_declare</property>
<property name="toolbar_pane">0</property>
<property name="tooltip"></property>
<property name="validator_data_type"></property>
<property name="validator_style">wxFILTER_NONE</property>
<property name="validator_type">wxDefaultValidator</property>
<property name="validator_variable"></property>
<property name="value"></property>
<property name="window_extra_style"></property>
<property name="window_name"></property>
<property name="window_style">wxBORDER_NONE</property>
</object>
</object>
</object>
</object>
</object>
<object class="notebookpage" expanded="true">
@@ -592,682 +513,6 @@
<property name="window_extra_style"></property>
<property name="window_name"></property>
<property name="window_style">wxTAB_TRAVERSAL</property>
<object class="wxBoxSizer" expanded="true">
<property name="minimum_size"></property>
<property name="name">bSizer5</property>
<property name="orient">wxVERTICAL</property>
<property name="permission">none</property>
<object class="sizeritem" expanded="true">
<property name="border">5</property>
<property name="flag">wxALL|wxEXPAND|wxFIXED_MINSIZE</property>
<property name="proportion">1</property>
<object class="wxStaticBoxSizer" expanded="true">
<property name="id">wxID_ANY</property>
<property name="label">JVM</property>
<property name="minimum_size"></property>
<property name="name">sbSizer3</property>
<property name="orient">wxVERTICAL</property>
<property name="parent">1</property>
<property name="permission">none</property>
<object class="sizeritem" expanded="true">
<property name="border">5</property>
<property name="flag">wxEXPAND</property>
<property name="proportion">1</property>
<object class="wxGridBagSizer" expanded="true">
<property name="empty_cell_size"></property>
<property name="flexible_direction">wxBOTH</property>
<property name="growablecols">1</property>
<property name="growablerows"></property>
<property name="hgap">0</property>
<property name="minimum_size"></property>
<property name="name">gbSizer2</property>
<property name="non_flexible_grow_mode">wxFLEX_GROWMODE_SPECIFIED</property>
<property name="permission">none</property>
<property name="vgap">0</property>
<object class="gbsizeritem" expanded="false">
<property name="border">5</property>
<property name="colspan">1</property>
<property name="column">3</property>
<property name="flag">wxALL</property>
<property name="row">0</property>
<property name="rowspan">1</property>
<object class="wxButton" expanded="false">
<property name="BottomDockable">1</property>
<property name="LeftDockable">1</property>
<property name="RightDockable">1</property>
<property name="TopDockable">1</property>
<property name="aui_layer">0</property>
<property name="aui_name"></property>
<property name="aui_position">0</property>
<property name="aui_row">0</property>
<property name="auth_needed">0</property>
<property name="best_size"></property>
<property name="bg"></property>
<property name="bitmap"></property>
<property name="caption"></property>
<property name="caption_visible">1</property>
<property name="center_pane">0</property>
<property name="close_button">1</property>
<property name="context_help"></property>
<property name="context_menu">1</property>
<property name="current"></property>
<property name="default">0</property>
<property name="default_pane">0</property>
<property name="disabled"></property>
<property name="dock">Dock</property>
<property name="dock_fixed">0</property>
<property name="docking">Left</property>
<property name="drag_accept_files">0</property>
<property name="enabled">1</property>
<property name="fg"></property>
<property name="floatable">1</property>
<property name="focus"></property>
<property name="font"></property>
<property name="gripper">0</property>
<property name="hidden">0</property>
<property name="id">wxID_ANY</property>
<property name="label">Reset</property>
<property name="margins"></property>
<property name="markup">0</property>
<property name="max_size"></property>
<property name="maximize_button">0</property>
<property name="maximum_size"></property>
<property name="min_size"></property>
<property name="minimize_button">0</property>
<property name="minimum_size"></property>
<property name="moveable">1</property>
<property name="name">m_button2</property>
<property name="pane_border">1</property>
<property name="pane_position"></property>
<property name="pane_size"></property>
<property name="permission">protected</property>
<property name="pin_button">1</property>
<property name="pos"></property>
<property name="position"></property>
<property name="pressed"></property>
<property name="resize">Resizable</property>
<property name="show">1</property>
<property name="size"></property>
<property name="style"></property>
<property name="subclass">; ; forward_declare</property>
<property name="toolbar_pane">0</property>
<property name="tooltip"></property>
<property name="validator_data_type"></property>
<property name="validator_style">wxFILTER_NONE</property>
<property name="validator_type">wxDefaultValidator</property>
<property name="validator_variable"></property>
<property name="window_extra_style"></property>
<property name="window_name"></property>
<property name="window_style"></property>
</object>
</object>
<object class="gbsizeritem" expanded="false">
<property name="border">5</property>
<property name="colspan">1</property>
<property name="column">2</property>
<property name="flag">wxEXPAND</property>
<property name="row">0</property>
<property name="rowspan">1</property>
<object class="spacer" expanded="false">
<property name="height">0</property>
<property name="permission">protected</property>
<property name="width">50</property>
</object>
</object>
<object class="gbsizeritem" expanded="false">
<property name="border">5</property>
<property name="colspan">1</property>
<property name="column">1</property>
<property name="flag">wxALL|wxEXPAND</property>
<property name="row">0</property>
<property name="rowspan">1</property>
<object class="wxDirPickerCtrl" expanded="false">
<property name="BottomDockable">1</property>
<property name="LeftDockable">1</property>
<property name="RightDockable">1</property>
<property name="TopDockable">1</property>
<property name="aui_layer">0</property>
<property name="aui_name"></property>
<property name="aui_position">0</property>
<property name="aui_row">0</property>
<property name="best_size"></property>
<property name="bg"></property>
<property name="caption"></property>
<property name="caption_visible">1</property>
<property name="center_pane">0</property>
<property name="close_button">1</property>
<property name="context_help"></property>
<property name="context_menu">1</property>
<property name="default_pane">0</property>
<property name="dock">Dock</property>
<property name="dock_fixed">0</property>
<property name="docking">Left</property>
<property name="drag_accept_files">0</property>
<property name="enabled">1</property>
<property name="fg"></property>
<property name="floatable">1</property>
<property name="font"></property>
<property name="gripper">0</property>
<property name="hidden">0</property>
<property name="id">wxID_ANY</property>
<property name="max_size"></property>
<property name="maximize_button">0</property>
<property name="maximum_size"></property>
<property name="message">Select a folder</property>
<property name="min_size"></property>
<property name="minimize_button">0</property>
<property name="minimum_size"></property>
<property name="moveable">1</property>
<property name="name">m_javaHomeDirPicker</property>
<property name="pane_border">1</property>
<property name="pane_position"></property>
<property name="pane_size"></property>
<property name="permission">protected</property>
<property name="pin_button">1</property>
<property name="pos"></property>
<property name="resize">Resizable</property>
<property name="show">1</property>
<property name="size"></property>
<property name="style">wxDIRP_DEFAULT_STYLE|wxDIRP_USE_TEXTCTRL</property>
<property name="subclass">; ; forward_declare</property>
<property name="toolbar_pane">0</property>
<property name="tooltip"></property>
<property name="validator_data_type"></property>
<property name="validator_style">wxFILTER_NONE</property>
<property name="validator_type">wxDefaultValidator</property>
<property name="validator_variable"></property>
<property name="value"></property>
<property name="window_extra_style"></property>
<property name="window_name"></property>
<property name="window_style"></property>
<event name="OnDirChanged">OnJavaHomeChanged</event>
</object>
</object>
<object class="gbsizeritem" expanded="false">
<property name="border">5</property>
<property name="colspan">1</property>
<property name="column">0</property>
<property name="flag">wxALIGN_CENTER_VERTICAL|wxALL</property>
<property name="row">0</property>
<property name="rowspan">1</property>
<object class="wxStaticText" expanded="false">
<property name="BottomDockable">1</property>
<property name="LeftDockable">1</property>
<property name="RightDockable">1</property>
<property name="TopDockable">1</property>
<property name="aui_layer">0</property>
<property name="aui_name"></property>
<property name="aui_position">0</property>
<property name="aui_row">0</property>
<property name="best_size"></property>
<property name="bg"></property>
<property name="caption"></property>
<property name="caption_visible">1</property>
<property name="center_pane">0</property>
<property name="close_button">1</property>
<property name="context_help"></property>
<property name="context_menu">1</property>
<property name="default_pane">0</property>
<property name="dock">Dock</property>
<property name="dock_fixed">0</property>
<property name="docking">Left</property>
<property name="drag_accept_files">0</property>
<property name="enabled">1</property>
<property name="fg"></property>
<property name="floatable">1</property>
<property name="font"></property>
<property name="gripper">0</property>
<property name="hidden">0</property>
<property name="id">wxID_ANY</property>
<property name="label">Java Home</property>
<property name="markup">0</property>
<property name="max_size"></property>
<property name="maximize_button">0</property>
<property name="maximum_size"></property>
<property name="min_size"></property>
<property name="minimize_button">0</property>
<property name="minimum_size"></property>
<property name="moveable">1</property>
<property name="name">m_staticText2</property>
<property name="pane_border">1</property>
<property name="pane_position"></property>
<property name="pane_size"></property>
<property name="permission">protected</property>
<property name="pin_button">1</property>
<property name="pos"></property>
<property name="resize">Resizable</property>
<property name="show">1</property>
<property name="size"></property>
<property name="style"></property>
<property name="subclass">; ; forward_declare</property>
<property name="toolbar_pane">0</property>
<property name="tooltip"></property>
<property name="window_extra_style"></property>
<property name="window_name"></property>
<property name="window_style"></property>
<property name="wrap">-1</property>
</object>
</object>
</object>
</object>
</object>
</object>
<object class="sizeritem" expanded="true">
<property name="border">5</property>
<property name="flag">wxALL|wxEXPAND</property>
<property name="proportion">1</property>
<object class="wxStaticBoxSizer" expanded="true">
<property name="id">wxID_ANY</property>
<property name="label">Paths</property>
<property name="minimum_size"></property>
<property name="name">sbSizer41</property>
<property name="orient">wxVERTICAL</property>
<property name="parent">1</property>
<property name="permission">none</property>
<object class="sizeritem" expanded="true">
<property name="border">5</property>
<property name="flag">wxEXPAND</property>
<property name="proportion">1</property>
<object class="wxGridBagSizer" expanded="true">
<property name="empty_cell_size"></property>
<property name="flexible_direction">wxBOTH</property>
<property name="growablecols">1</property>
<property name="growablerows"></property>
<property name="hgap">0</property>
<property name="minimum_size"></property>
<property name="name">gbSizer3</property>
<property name="non_flexible_grow_mode">wxFLEX_GROWMODE_SPECIFIED</property>
<property name="permission">none</property>
<property name="vgap">0</property>
<object class="gbsizeritem" expanded="false">
<property name="border">5</property>
<property name="colspan">1</property>
<property name="column">0</property>
<property name="flag">wxALIGN_CENTER_VERTICAL|wxALL</property>
<property name="row">0</property>
<property name="rowspan">1</property>
<object class="wxStaticText" expanded="false">
<property name="BottomDockable">1</property>
<property name="LeftDockable">1</property>
<property name="RightDockable">1</property>
<property name="TopDockable">1</property>
<property name="aui_layer">0</property>
<property name="aui_name"></property>
<property name="aui_position">0</property>
<property name="aui_row">0</property>
<property name="best_size"></property>
<property name="bg"></property>
<property name="caption"></property>
<property name="caption_visible">1</property>
<property name="center_pane">0</property>
<property name="close_button">1</property>
<property name="context_help"></property>
<property name="context_menu">1</property>
<property name="default_pane">0</property>
<property name="dock">Dock</property>
<property name="dock_fixed">0</property>
<property name="docking">Left</property>
<property name="drag_accept_files">0</property>
<property name="enabled">1</property>
<property name="fg"></property>
<property name="floatable">1</property>
<property name="font"></property>
<property name="gripper">0</property>
<property name="hidden">0</property>
<property name="id">wxID_ANY</property>
<property name="label">Mount path</property>
<property name="markup">0</property>
<property name="max_size"></property>
<property name="maximize_button">0</property>
<property name="maximum_size"></property>
<property name="min_size"></property>
<property name="minimize_button">0</property>
<property name="minimum_size"></property>
<property name="moveable">1</property>
<property name="name">m_staticText6</property>
<property name="pane_border">1</property>
<property name="pane_position"></property>
<property name="pane_size"></property>
<property name="permission">protected</property>
<property name="pin_button">1</property>
<property name="pos"></property>
<property name="resize">Resizable</property>
<property name="show">1</property>
<property name="size"></property>
<property name="style"></property>
<property name="subclass">; ; forward_declare</property>
<property name="toolbar_pane">0</property>
<property name="tooltip"></property>
<property name="window_extra_style"></property>
<property name="window_name"></property>
<property name="window_style"></property>
<property name="wrap">-1</property>
</object>
</object>
<object class="gbsizeritem" expanded="true">
<property name="border">5</property>
<property name="colspan">1</property>
<property name="column">0</property>
<property name="flag">wxALIGN_CENTER_VERTICAL|wxALL</property>
<property name="row">1</property>
<property name="rowspan">1</property>
<object class="wxStaticText" expanded="true">
<property name="BottomDockable">1</property>
<property name="LeftDockable">1</property>
<property name="RightDockable">1</property>
<property name="TopDockable">1</property>
<property name="aui_layer">0</property>
<property name="aui_name"></property>
<property name="aui_position">0</property>
<property name="aui_row">0</property>
<property name="best_size"></property>
<property name="bg"></property>
<property name="caption"></property>
<property name="caption_visible">1</property>
<property name="center_pane">0</property>
<property name="close_button">1</property>
<property name="context_help"></property>
<property name="context_menu">1</property>
<property name="default_pane">0</property>
<property name="dock">Dock</property>
<property name="dock_fixed">0</property>
<property name="docking">Left</property>
<property name="drag_accept_files">0</property>
<property name="enabled">1</property>
<property name="fg"></property>
<property name="floatable">1</property>
<property name="font"></property>
<property name="gripper">0</property>
<property name="hidden">0</property>
<property name="id">wxID_ANY</property>
<property name="label">Data path</property>
<property name="markup">0</property>
<property name="max_size"></property>
<property name="maximize_button">0</property>
<property name="maximum_size"></property>
<property name="min_size"></property>
<property name="minimize_button">0</property>
<property name="minimum_size"></property>
<property name="moveable">1</property>
<property name="name">m_staticText61</property>
<property name="pane_border">1</property>
<property name="pane_position"></property>
<property name="pane_size"></property>
<property name="permission">protected</property>
<property name="pin_button">1</property>
<property name="pos"></property>
<property name="resize">Resizable</property>
<property name="show">1</property>
<property name="size"></property>
<property name="style"></property>
<property name="subclass">; ; forward_declare</property>
<property name="toolbar_pane">0</property>
<property name="tooltip"></property>
<property name="window_extra_style"></property>
<property name="window_name"></property>
<property name="window_style"></property>
<property name="wrap">-1</property>
</object>
</object>
<object class="gbsizeritem" expanded="false">
<property name="border">5</property>
<property name="colspan">1</property>
<property name="column">1</property>
<property name="flag">wxALL|wxEXPAND</property>
<property name="row">0</property>
<property name="rowspan">1</property>
<object class="wxDirPickerCtrl" expanded="false">
<property name="BottomDockable">1</property>
<property name="LeftDockable">1</property>
<property name="RightDockable">1</property>
<property name="TopDockable">1</property>
<property name="aui_layer">0</property>
<property name="aui_name"></property>
<property name="aui_position">0</property>
<property name="aui_row">0</property>
<property name="best_size"></property>
<property name="bg"></property>
<property name="caption"></property>
<property name="caption_visible">1</property>
<property name="center_pane">0</property>
<property name="close_button">1</property>
<property name="context_help"></property>
<property name="context_menu">1</property>
<property name="default_pane">0</property>
<property name="dock">Dock</property>
<property name="dock_fixed">0</property>
<property name="docking">Left</property>
<property name="drag_accept_files">0</property>
<property name="enabled">1</property>
<property name="fg"></property>
<property name="floatable">1</property>
<property name="font"></property>
<property name="gripper">0</property>
<property name="hidden">0</property>
<property name="id">wxID_ANY</property>
<property name="max_size"></property>
<property name="maximize_button">0</property>
<property name="maximum_size"></property>
<property name="message">Select a folder</property>
<property name="min_size"></property>
<property name="minimize_button">0</property>
<property name="minimum_size"></property>
<property name="moveable">1</property>
<property name="name">m_mountPathDirPicker</property>
<property name="pane_border">1</property>
<property name="pane_position"></property>
<property name="pane_size"></property>
<property name="permission">protected</property>
<property name="pin_button">1</property>
<property name="pos"></property>
<property name="resize">Resizable</property>
<property name="show">1</property>
<property name="size"></property>
<property name="style">wxDIRP_USE_TEXTCTRL</property>
<property name="subclass">; ; forward_declare</property>
<property name="toolbar_pane">0</property>
<property name="tooltip"></property>
<property name="validator_data_type"></property>
<property name="validator_style">wxFILTER_NONE</property>
<property name="validator_type">wxDefaultValidator</property>
<property name="validator_variable"></property>
<property name="value"></property>
<property name="window_extra_style"></property>
<property name="window_name"></property>
<property name="window_style"></property>
<event name="OnDirChanged">OnMountPathChanged</event>
</object>
</object>
<object class="gbsizeritem" expanded="true">
<property name="border">5</property>
<property name="colspan">1</property>
<property name="column">1</property>
<property name="flag">wxALL|wxEXPAND</property>
<property name="row">1</property>
<property name="rowspan">1</property>
<object class="wxDirPickerCtrl" expanded="true">
<property name="BottomDockable">1</property>
<property name="LeftDockable">1</property>
<property name="RightDockable">1</property>
<property name="TopDockable">1</property>
<property name="aui_layer">0</property>
<property name="aui_name"></property>
<property name="aui_position">0</property>
<property name="aui_row">0</property>
<property name="best_size"></property>
<property name="bg"></property>
<property name="caption"></property>
<property name="caption_visible">1</property>
<property name="center_pane">0</property>
<property name="close_button">1</property>
<property name="context_help"></property>
<property name="context_menu">1</property>
<property name="default_pane">0</property>
<property name="dock">Dock</property>
<property name="dock_fixed">0</property>
<property name="docking">Left</property>
<property name="drag_accept_files">0</property>
<property name="enabled">1</property>
<property name="fg"></property>
<property name="floatable">1</property>
<property name="font"></property>
<property name="gripper">0</property>
<property name="hidden">0</property>
<property name="id">wxID_ANY</property>
<property name="max_size"></property>
<property name="maximize_button">0</property>
<property name="maximum_size"></property>
<property name="message">Select a folder</property>
<property name="min_size"></property>
<property name="minimize_button">0</property>
<property name="minimum_size"></property>
<property name="moveable">1</property>
<property name="name">m_dataPathDirPicker</property>
<property name="pane_border">1</property>
<property name="pane_position"></property>
<property name="pane_size"></property>
<property name="permission">protected</property>
<property name="pin_button">1</property>
<property name="pos"></property>
<property name="resize">Resizable</property>
<property name="show">1</property>
<property name="size"></property>
<property name="style">wxDIRP_USE_TEXTCTRL</property>
<property name="subclass">; ; forward_declare</property>
<property name="toolbar_pane">0</property>
<property name="tooltip"></property>
<property name="validator_data_type"></property>
<property name="validator_style">wxFILTER_NONE</property>
<property name="validator_type">wxDefaultValidator</property>
<property name="validator_variable"></property>
<property name="value"></property>
<property name="window_extra_style"></property>
<property name="window_name"></property>
<property name="window_style"></property>
<event name="OnDirChanged">OnDataPathChanged</event>
</object>
</object>
</object>
</object>
</object>
</object>
</object>
</object>
</object>
<object class="notebookpage" expanded="true">
<property name="bitmap"></property>
<property name="label">Advanced Settings</property>
<property name="select">0</property>
<object class="wxPanel" expanded="true">
<property name="BottomDockable">1</property>
<property name="LeftDockable">1</property>
<property name="RightDockable">1</property>
<property name="TopDockable">1</property>
<property name="aui_layer">0</property>
<property name="aui_name"></property>
<property name="aui_position">0</property>
<property name="aui_row">0</property>
<property name="best_size"></property>
<property name="bg"></property>
<property name="caption"></property>
<property name="caption_visible">1</property>
<property name="center_pane">0</property>
<property name="close_button">1</property>
<property name="context_help"></property>
<property name="context_menu">1</property>
<property name="default_pane">0</property>
<property name="dock">Dock</property>
<property name="dock_fixed">0</property>
<property name="docking">Left</property>
<property name="drag_accept_files">0</property>
<property name="enabled">1</property>
<property name="fg"></property>
<property name="floatable">1</property>
<property name="font"></property>
<property name="gripper">0</property>
<property name="hidden">0</property>
<property name="id">wxID_ANY</property>
<property name="max_size"></property>
<property name="maximize_button">0</property>
<property name="maximum_size"></property>
<property name="min_size"></property>
<property name="minimize_button">0</property>
<property name="minimum_size"></property>
<property name="moveable">1</property>
<property name="name">m_panel4</property>
<property name="pane_border">1</property>
<property name="pane_position"></property>
<property name="pane_size"></property>
<property name="permission">protected</property>
<property name="pin_button">1</property>
<property name="pos"></property>
<property name="resize">Resizable</property>
<property name="show">1</property>
<property name="size"></property>
<property name="subclass">; ; forward_declare</property>
<property name="toolbar_pane">0</property>
<property name="tooltip"></property>
<property name="window_extra_style"></property>
<property name="window_name"></property>
<property name="window_style">wxTAB_TRAVERSAL</property>
</object>
</object>
<object class="notebookpage" expanded="true">
<property name="bitmap"></property>
<property name="label">Web UI</property>
<property name="select">0</property>
<object class="wxPanel" expanded="true">
<property name="BottomDockable">1</property>
<property name="LeftDockable">1</property>
<property name="RightDockable">1</property>
<property name="TopDockable">1</property>
<property name="aui_layer">0</property>
<property name="aui_name"></property>
<property name="aui_position">0</property>
<property name="aui_row">0</property>
<property name="best_size"></property>
<property name="bg"></property>
<property name="caption"></property>
<property name="caption_visible">1</property>
<property name="center_pane">0</property>
<property name="close_button">1</property>
<property name="context_help"></property>
<property name="context_menu">1</property>
<property name="default_pane">0</property>
<property name="dock">Dock</property>
<property name="dock_fixed">0</property>
<property name="docking">Left</property>
<property name="drag_accept_files">0</property>
<property name="enabled">1</property>
<property name="fg"></property>
<property name="floatable">1</property>
<property name="font"></property>
<property name="gripper">0</property>
<property name="hidden">0</property>
<property name="id">wxID_ANY</property>
<property name="max_size"></property>
<property name="maximize_button">0</property>
<property name="maximum_size"></property>
<property name="min_size"></property>
<property name="minimize_button">0</property>
<property name="minimum_size"></property>
<property name="moveable">1</property>
<property name="name">m_panel5</property>
<property name="pane_border">1</property>
<property name="pane_position"></property>
<property name="pane_size"></property>
<property name="permission">protected</property>
<property name="pin_button">1</property>
<property name="pos"></property>
<property name="resize">Resizable</property>
<property name="show">1</property>
<property name="size"></property>
<property name="subclass">; ; forward_declare</property>
<property name="toolbar_pane">0</property>
<property name="tooltip"></property>
<property name="window_extra_style"></property>
<property name="window_name"></property>
<property name="window_style">wxTAB_TRAVERSAL</property>
</object>
</object>
</object>

View File

@@ -1,20 +0,0 @@
//
// Created by Stepan Usatiuk on 29.06.2025.
//
#ifndef UTILS_H
#define UTILS_H
#ifdef __cplusplus
extern "C" {
#endif
void SetAppAsRegular(void);
void SetAppAsAccessory(void);
#ifdef __cplusplus
}
#endif
#endif //UTILS_H

View File

@@ -1,11 +0,0 @@
#import <Cocoa/Cocoa.h>
#import "utils.h"
void SetAppAsRegular(void) {
[NSApp setActivationPolicy:NSApplicationActivationPolicyRegular];
}
void SetAppAsAccessory(void) {
[NSApp setActivationPolicy:NSApplicationActivationPolicyAccessory];
}

View File

@@ -0,0 +1,10 @@
add_library(libjvm_wrapper
src/LibjvmWrapper.cpp
include_public/LibjvmWrapper.hpp
)
target_include_directories(libjvm_wrapper PRIVATE include)
target_include_directories(libjvm_wrapper PUBLIC include_public)
find_package(JNI REQUIRED)
target_include_directories(libjvm_wrapper PUBLIC ${JNI_INCLUDE_DIRS})

View File

@@ -0,0 +1,25 @@
//
// Created by Stepan Usatiuk on 24.06.2025.
//
#ifndef LIBJVMWRAPPER_HPP
#define LIBJVMWRAPPER_HPP
#include <jni.h>
class LibjvmWrapper {
public:
static LibjvmWrapper& instance();
decltype(JNI_CreateJavaVM)* JNI_CreateJavaVM;
private:
LibjvmWrapper();
~LibjvmWrapper();
void* _lib_handle;
};
#endif //LIBJVMWRAPPER_HPP

View File

@@ -0,0 +1,25 @@
//
// Created by Stepan Usatiuk on 24.06.2025.
//
#include "LibjvmWrapper.hpp"
#include <dlfcn.h>
#include <jni.h>
static constexpr auto LIBJVM_PATH =
"/Library/Java/JavaVirtualMachines/zulu-21.jdk/Contents/Home/lib/server/libjvm.dylib";
LibjvmWrapper& LibjvmWrapper::instance() {
static LibjvmWrapper instance;
return instance;
}
LibjvmWrapper::LibjvmWrapper() {
_lib_handle = dlopen(LIBJVM_PATH, RTLD_NOW | RTLD_GLOBAL);
JNI_CreateJavaVM = reinterpret_cast<decltype(JNI_CreateJavaVM)>(
dlsym(_lib_handle, "JNI_CreateJavaVM"));
}
LibjvmWrapper::~LibjvmWrapper() {
dlclose(_lib_handle);
}

View File

@@ -1,7 +0,0 @@
add_library(utils
src/Exception.cpp
include_public/Exception.h
)
target_include_directories(utils PRIVATE include)
target_include_directories(utils PUBLIC include_public)

View File

@@ -1,30 +0,0 @@
//
// Created by Stepan Usatiuk on 01.05.2023.
//
#ifndef SEMBACKUP_EXCEPTION_H
#define SEMBACKUP_EXCEPTION_H
#include <cstring>
#include <stdexcept>
#include <string>
#include <vector>
/// Custom exception class that uses execinfo to append a stacktrace to the exception message
class Exception : public std::runtime_error {
public:
Exception(const std::string& text);
Exception(const char* text);
private:
/// Static function to get the current stacktrace
static std::string getStacktrace();
};
class ErrnoException : public Exception {
public:
ErrnoException(const std::string& text) : Exception(text + " " + std::strerror(errno)) {}
ErrnoException(const char* text) : Exception(std::string(text) + " " + std::strerror(errno)) {}
};
#endif // SEMBACKUP_EXCEPTION_H

View File

@@ -1,35 +0,0 @@
//
// Created by Stepan Usatiuk on 01.05.2023.
//
#include "Exception.h"
#include <execinfo.h>
#include <sstream>
Exception::Exception(const std::string& text) : runtime_error(text + "\n" + getStacktrace()) {
}
Exception::Exception(const char* text) : runtime_error(std::string(text) + "\n" + getStacktrace()) {
}
// Based on: https://www.gnu.org/software/libc/manual/html_node/Backtraces.html
std::string Exception::getStacktrace() {
std::vector<void*> functions(50);
char** strings;
int n;
n = backtrace(functions.data(), 50);
strings = backtrace_symbols(functions.data(), n);
std::stringstream out;
if (strings != nullptr) {
out << "Stacktrace:" << std::endl;
for (int i = 0; i < n; i++)
out << strings[i] << std::endl;
}
free(strings);
return out.str();
}

View File

@@ -42,7 +42,8 @@ fi
--add-exports java.base/sun.nio.ch=ALL-UNNAMED \
--add-exports java.base/jdk.internal.access=ALL-UNNAMED \
--add-opens=java.base/java.nio=ALL-UNNAMED \
-Ddhfs.objects.persistence.root="$SCRIPT_DIR"/../data \
-Ddhfs.objects.persistence.files.root="$SCRIPT_DIR"/../data/objects \
-Ddhfs.objects.persistence.stuff.root="$SCRIPT_DIR"/../data/stuff \
-Ddhfs.fuse.root="$SCRIPT_DIR"/../fuse \
-Dquarkus.http.host=0.0.0.0 \
-Dquarkus.log.category.\"com.usatiuk\".level=INFO \