mirror of
https://github.com/usatiuk/dhfs.git
synced 2025-10-28 20:47:49 +01:00
starting/stopping
This commit is contained in:
@@ -15,11 +15,15 @@
|
|||||||
#include "DhfsWxProcess.hpp"
|
#include "DhfsWxProcess.hpp"
|
||||||
|
|
||||||
enum class DhfsInstanceState {
|
enum class DhfsInstanceState {
|
||||||
|
STARTING,
|
||||||
RUNNING,
|
RUNNING,
|
||||||
|
STOPPING,
|
||||||
STOPPED,
|
STOPPED,
|
||||||
};
|
};
|
||||||
|
|
||||||
class DhfsInstance {
|
class DhfsInstance {
|
||||||
|
friend DhfsWxProcess;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
DhfsInstance();
|
DhfsInstance();
|
||||||
|
|
||||||
@@ -31,14 +35,16 @@ public:
|
|||||||
|
|
||||||
void stop();
|
void stop();
|
||||||
|
|
||||||
virtual void OnTerminate(int pid, int status) = 0;
|
protected:
|
||||||
|
virtual void OnStateChange() = 0;
|
||||||
|
|
||||||
virtual void OnRead(std::string s) = 0;
|
virtual void OnRead(std::string s) = 0;
|
||||||
|
|
||||||
protected:
|
private:
|
||||||
std::unique_ptr<DhfsWxProcess> process = std::make_unique<DhfsWxProcess>(*this);
|
std::unique_ptr<DhfsWxProcess> process = std::make_unique<DhfsWxProcess>(*this);
|
||||||
|
|
||||||
private:
|
void OnTerminateInternal(int pid, int status);
|
||||||
|
|
||||||
DhfsInstanceState _state = DhfsInstanceState::STOPPED;
|
DhfsInstanceState _state = DhfsInstanceState::STOPPED;
|
||||||
std::thread _readThread;
|
std::thread _readThread;
|
||||||
std::thread _readThreadErr;
|
std::thread _readThreadErr;
|
||||||
|
|||||||
@@ -25,13 +25,17 @@ void DhfsInstance::start(DhfsStartOptions options) {
|
|||||||
std::lock_guard<std::mutex> lock(_mutex);
|
std::lock_guard<std::mutex> lock(_mutex);
|
||||||
switch (_state) {
|
switch (_state) {
|
||||||
case DhfsInstanceState::RUNNING:
|
case DhfsInstanceState::RUNNING:
|
||||||
|
case DhfsInstanceState::STARTING:
|
||||||
|
case DhfsInstanceState::STOPPING:
|
||||||
return;
|
return;
|
||||||
case DhfsInstanceState::STOPPED:
|
case DhfsInstanceState::STOPPED:
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
throw std::runtime_error("Unknown DhfsInstanceState");
|
throw std::runtime_error("Unknown DhfsInstanceState");
|
||||||
}
|
}
|
||||||
_state = DhfsInstanceState::RUNNING;
|
|
||||||
|
_state = DhfsInstanceState::STARTING;
|
||||||
|
OnStateChange();
|
||||||
|
|
||||||
std::vector<char*> args;
|
std::vector<char*> args;
|
||||||
auto readyOptions = options.getOptions();
|
auto readyOptions = options.getOptions();
|
||||||
@@ -46,18 +50,36 @@ void DhfsInstance::start(DhfsStartOptions options) {
|
|||||||
throw Exception("Failed to start DHFS");
|
throw Exception("Failed to start DHFS");
|
||||||
}
|
}
|
||||||
|
|
||||||
OnRead("Started! " + std::to_string(ret) + " PID: " + std::to_string(process->GetPid()) + "\n");
|
OnRead("Started! PID: " + std::to_string(process->GetPid()) + "\n");
|
||||||
|
|
||||||
_readThread = std::thread([&]() {
|
_readThread = std::thread([&]() {
|
||||||
auto stream = process->GetInputStream();
|
auto stream = process->GetInputStream();
|
||||||
|
|
||||||
|
bool searching = true;
|
||||||
|
std::string lastLine;
|
||||||
|
|
||||||
while (!stream->Eof() || stream->CanRead()) {
|
while (!stream->Eof() || stream->CanRead()) {
|
||||||
char buffer[1024];
|
char buffer[1024];
|
||||||
size_t bytesRead = stream->Read(buffer, sizeof(buffer) - 1).LastRead();
|
size_t bytesRead = stream->Read(buffer, sizeof(buffer) - 1).LastRead();
|
||||||
if (bytesRead > 0) {
|
if (bytesRead > 0) {
|
||||||
buffer[bytesRead] = '\0'; // Null-terminate the string
|
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));
|
OnRead(std::string(buffer));
|
||||||
} else if (bytesRead == 0) {
|
|
||||||
break; // EOF reached
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@@ -67,10 +89,8 @@ void DhfsInstance::start(DhfsStartOptions options) {
|
|||||||
char buffer[1024];
|
char buffer[1024];
|
||||||
size_t bytesRead = stream->Read(buffer, sizeof(buffer) - 1).LastRead();
|
size_t bytesRead = stream->Read(buffer, sizeof(buffer) - 1).LastRead();
|
||||||
if (bytesRead > 0) {
|
if (bytesRead > 0) {
|
||||||
buffer[bytesRead] = '\0'; // Null-terminate the string
|
buffer[bytesRead] = '\0';
|
||||||
OnRead(std::string(buffer));
|
OnRead(std::string(buffer));
|
||||||
} else if (bytesRead == 0) {
|
|
||||||
break; // EOF reached
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@@ -80,21 +100,30 @@ void DhfsInstance::stop() {
|
|||||||
std::lock_guard<std::mutex> lock(_mutex);
|
std::lock_guard<std::mutex> lock(_mutex);
|
||||||
switch (_state) {
|
switch (_state) {
|
||||||
case DhfsInstanceState::RUNNING:
|
case DhfsInstanceState::RUNNING:
|
||||||
|
case DhfsInstanceState::STARTING:
|
||||||
break;
|
break;
|
||||||
case DhfsInstanceState::STOPPED:
|
case DhfsInstanceState::STOPPED:
|
||||||
|
case DhfsInstanceState::STOPPING:
|
||||||
return;
|
return;
|
||||||
default:
|
default:
|
||||||
throw std::runtime_error("Unknown DhfsInstanceState");
|
throw std::runtime_error("Unknown DhfsInstanceState");
|
||||||
}
|
}
|
||||||
|
|
||||||
_state = DhfsInstanceState::STOPPED;
|
_state = DhfsInstanceState::STOPPING;
|
||||||
|
OnStateChange();
|
||||||
|
|
||||||
int err = wxProcess::Kill(process->GetPid(), wxSIGTERM, wxKILL_CHILDREN);
|
int err = wxProcess::Kill(process->GetPid(), wxSIGTERM, wxKILL_CHILDREN);
|
||||||
_readThread.join();
|
|
||||||
_readThreadErr.join();
|
|
||||||
OnRead("Stopped!\n");
|
|
||||||
if (err != wxKILL_OK) {
|
if (err != wxKILL_OK) {
|
||||||
OnRead("Failed to stop DHFS: " + std::to_string(err) + "\n");
|
OnRead("Failed to stop DHFS: " + std::to_string(err) + "\n");
|
||||||
}
|
}
|
||||||
OnTerminate(0, 0);
|
}
|
||||||
|
|
||||||
|
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();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -10,5 +10,5 @@ DhfsWxProcess::DhfsWxProcess(DhfsInstance& parent): wxProcess(wxPROCESS_REDIRECT
|
|||||||
}
|
}
|
||||||
|
|
||||||
void DhfsWxProcess::OnTerminate(int pid, int status) {
|
void DhfsWxProcess::OnTerminate(int pid, int status) {
|
||||||
_instance.stop();
|
_instance.OnTerminateInternal(pid, status);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -9,8 +9,8 @@
|
|||||||
DhfsGuiInstance::DhfsGuiInstance(LauncherAppMainFrame& parent): _parent(parent) {
|
DhfsGuiInstance::DhfsGuiInstance(LauncherAppMainFrame& parent): _parent(parent) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void DhfsGuiInstance::OnTerminate(int pid, int status) {
|
void DhfsGuiInstance::OnStateChange() {
|
||||||
wxCommandEvent* event = new wxCommandEvent(SHUTDOWN_EVENT, _parent.GetId());
|
wxCommandEvent* event = new wxCommandEvent(DHFS_STATE_CHANGE_EVENT, _parent.GetId());
|
||||||
event->SetEventObject(&_parent);
|
event->SetEventObject(&_parent);
|
||||||
_parent.GetEventHandler()->QueueEvent(event);
|
_parent.GetEventHandler()->QueueEvent(event);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -13,7 +13,7 @@ class DhfsGuiInstance : public DhfsInstance {
|
|||||||
public:
|
public:
|
||||||
DhfsGuiInstance(LauncherAppMainFrame& parent);
|
DhfsGuiInstance(LauncherAppMainFrame& parent);
|
||||||
|
|
||||||
void OnTerminate(int pid, int status) override;
|
void OnStateChange() override;
|
||||||
|
|
||||||
void OnRead(std::string s) override;
|
void OnRead(std::string s) override;
|
||||||
|
|
||||||
|
|||||||
@@ -6,7 +6,7 @@
|
|||||||
#include "Exception.h"
|
#include "Exception.h"
|
||||||
|
|
||||||
wxDEFINE_EVENT(NEW_LINE_OUTPUT_EVENT, wxCommandEvent);
|
wxDEFINE_EVENT(NEW_LINE_OUTPUT_EVENT, wxCommandEvent);
|
||||||
wxDEFINE_EVENT(SHUTDOWN_EVENT, wxCommandEvent);
|
wxDEFINE_EVENT(DHFS_STATE_CHANGE_EVENT, wxCommandEvent);
|
||||||
|
|
||||||
LauncherAppMainFrame::LauncherAppMainFrame(wxWindow* parent)
|
LauncherAppMainFrame::LauncherAppMainFrame(wxWindow* parent)
|
||||||
: MainFrame(parent) {
|
: MainFrame(parent) {
|
||||||
@@ -20,7 +20,7 @@ LauncherAppMainFrame::LauncherAppMainFrame(wxWindow* parent)
|
|||||||
m_webViewSizer->Fit(m_panel5);
|
m_webViewSizer->Fit(m_panel5);
|
||||||
|
|
||||||
Bind(NEW_LINE_OUTPUT_EVENT, &LauncherAppMainFrame::onNewLineOutput, this);
|
Bind(NEW_LINE_OUTPUT_EVENT, &LauncherAppMainFrame::onNewLineOutput, this);
|
||||||
Bind(SHUTDOWN_EVENT, &LauncherAppMainFrame::onShutdown, this);
|
Bind(DHFS_STATE_CHANGE_EVENT, &LauncherAppMainFrame::onShutdown, this);
|
||||||
wxFont font = wxFont(wxSize(16, 16),
|
wxFont font = wxFont(wxSize(16, 16),
|
||||||
wxFontFamily::wxFONTFAMILY_TELETYPE,
|
wxFontFamily::wxFONTFAMILY_TELETYPE,
|
||||||
wxFontStyle::wxFONTSTYLE_NORMAL,
|
wxFontStyle::wxFONTSTYLE_NORMAL,
|
||||||
@@ -36,12 +36,24 @@ void LauncherAppMainFrame::updateState() {
|
|||||||
m_startStopButton->SetLabel("Stop");
|
m_startStopButton->SetLabel("Stop");
|
||||||
m_statusBar1->SetStatusText("Running", 0);
|
m_statusBar1->SetStatusText("Running", 0);
|
||||||
break;
|
break;
|
||||||
|
case DhfsInstanceState::STARTING: {
|
||||||
|
m_statusText->SetLabel("Starting");
|
||||||
|
m_startStopButton->SetLabel("Stop");
|
||||||
|
m_statusBar1->SetStatusText("Starting", 0);
|
||||||
|
break;
|
||||||
|
}
|
||||||
case DhfsInstanceState::STOPPED: {
|
case DhfsInstanceState::STOPPED: {
|
||||||
m_statusText->SetLabel("Stopped");
|
m_statusText->SetLabel("Stopped");
|
||||||
m_startStopButton->SetLabel("Start");
|
m_startStopButton->SetLabel("Start");
|
||||||
m_statusBar1->SetStatusText("Stopped", 0);
|
m_statusBar1->SetStatusText("Stopped", 0);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
case DhfsInstanceState::STOPPING: {
|
||||||
|
m_statusText->SetLabel("Stopping");
|
||||||
|
m_startStopButton->SetLabel("Kill");
|
||||||
|
m_statusBar1->SetStatusText("Stopping", 0);
|
||||||
|
break;
|
||||||
|
}
|
||||||
default:
|
default:
|
||||||
throw Exception("Unhandled switch case");
|
throw Exception("Unhandled switch case");
|
||||||
}
|
}
|
||||||
@@ -50,8 +62,10 @@ void LauncherAppMainFrame::updateState() {
|
|||||||
void LauncherAppMainFrame::OnStartStopButtonClick(wxCommandEvent& event) {
|
void LauncherAppMainFrame::OnStartStopButtonClick(wxCommandEvent& event) {
|
||||||
switch (_dhfsInstance.state()) {
|
switch (_dhfsInstance.state()) {
|
||||||
case DhfsInstanceState::RUNNING:
|
case DhfsInstanceState::RUNNING:
|
||||||
|
case DhfsInstanceState::STARTING: {
|
||||||
_dhfsInstance.stop();
|
_dhfsInstance.stop();
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
case DhfsInstanceState::STOPPED: {
|
case DhfsInstanceState::STOPPED: {
|
||||||
DhfsStartOptions options;
|
DhfsStartOptions options;
|
||||||
options.java_home = wxFileConfig::Get()->Read(kJavaHomeSettingsKey);
|
options.java_home = wxFileConfig::Get()->Read(kJavaHomeSettingsKey);
|
||||||
@@ -65,6 +79,10 @@ void LauncherAppMainFrame::OnStartStopButtonClick(wxCommandEvent& event) {
|
|||||||
_dhfsInstance.start(options);
|
_dhfsInstance.start(options);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
case DhfsInstanceState::STOPPING: {
|
||||||
|
// TODO:
|
||||||
|
break;
|
||||||
|
}
|
||||||
default:
|
default:
|
||||||
throw Exception("Unhandled switch case");
|
throw Exception("Unhandled switch case");
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -19,7 +19,7 @@ static constexpr auto kMountPointSettingsKey = "DHFS/MountDir";
|
|||||||
static constexpr auto kDataDirSettingsKey = "DHFS/DataDir";
|
static constexpr auto kDataDirSettingsKey = "DHFS/DataDir";
|
||||||
|
|
||||||
wxDECLARE_EVENT(NEW_LINE_OUTPUT_EVENT, wxCommandEvent);
|
wxDECLARE_EVENT(NEW_LINE_OUTPUT_EVENT, wxCommandEvent);
|
||||||
wxDECLARE_EVENT(SHUTDOWN_EVENT, wxCommandEvent);
|
wxDECLARE_EVENT(DHFS_STATE_CHANGE_EVENT, wxCommandEvent);
|
||||||
|
|
||||||
/** Implementing MainFrame */
|
/** Implementing MainFrame */
|
||||||
class LauncherAppMainFrame : public MainFrame {
|
class LauncherAppMainFrame : public MainFrame {
|
||||||
|
|||||||
Reference in New Issue
Block a user