mirror of https://gitee.com/bigwinds/arangodb
Also notify the windows service facilities if we go down unexpectedly.
This commit is contained in:
parent
f121e665d4
commit
8eb5bda729
|
@ -228,6 +228,10 @@ void ApplicationServer::beginShutdown() {
|
|||
// to run method
|
||||
}
|
||||
|
||||
void ApplicationServer::shutdownFatalError() {
|
||||
reportServerProgress(ServerState::ABORT);
|
||||
}
|
||||
|
||||
VPackBuilder ApplicationServer::options(
|
||||
std::unordered_set<std::string> const& excludes) const {
|
||||
return _options->toVPack(false, excludes);
|
||||
|
|
|
@ -44,7 +44,8 @@ enum class ServerState {
|
|||
IN_START,
|
||||
IN_WAIT,
|
||||
IN_STOP,
|
||||
STOPPED
|
||||
STOPPED,
|
||||
ABORT
|
||||
};
|
||||
|
||||
class ProgressHandler {
|
||||
|
@ -191,6 +192,9 @@ class ApplicationServer {
|
|||
// signal the server to shut down
|
||||
void beginShutdown();
|
||||
|
||||
// report that we are going down by fatal error
|
||||
void shutdownFatalError();
|
||||
|
||||
// return VPack options
|
||||
VPackBuilder options(std::unordered_set<std::string> const& excludes) const;
|
||||
|
||||
|
|
|
@ -67,6 +67,12 @@ static std::string FriendlyServiceName = "ArangoDB - the multi-model database";
|
|||
|
||||
static SERVICE_STATUS_HANDLE ServiceStatus;
|
||||
|
||||
void reportServiceAborted(void) {
|
||||
if (ArangoInstance != nullptr && ArangoInstance->_server != nullptr) {
|
||||
ArangoInstance->_server->beginShutdown();
|
||||
}
|
||||
}
|
||||
|
||||
// So we have a valid minidump area during startup:
|
||||
void WindowsServiceFeature::StartArangoService (bool WaitForRunning) {
|
||||
TRI_ERRORBUF;
|
||||
|
@ -290,6 +296,71 @@ void WindowsServiceFeature::installService() {
|
|||
CloseServiceHandle(schService);
|
||||
}
|
||||
|
||||
void WindowsServiceFeature::DeleteService (bool force) {
|
||||
CHAR path[MAX_PATH] = "";
|
||||
|
||||
if (! GetModuleFileNameA(nullptr, path, MAX_PATH)) {
|
||||
std::cerr << "FATAL: GetModuleFileNameA failed" << std::endl;
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
std::cout << "INFO: removing service '" << ServiceName << "'" << std::endl;
|
||||
|
||||
SC_HANDLE schSCManager = OpenSCManager(nullptr, SERVICES_ACTIVE_DATABASE, SC_MANAGER_ALL_ACCESS);
|
||||
|
||||
if (schSCManager == 0) {
|
||||
std::cerr << "FATAL: OpenSCManager failed with " << GetLastError() << std::endl;
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
SC_HANDLE schService = OpenServiceA(
|
||||
schSCManager, // SCManager database
|
||||
ServiceName.c_str(), // name of service
|
||||
DELETE|SERVICE_QUERY_CONFIG); // first validate whether its us, then delete.
|
||||
|
||||
char serviceConfigMemory[8192]; // msdn says: 8k is enough.
|
||||
DWORD bytesNeeded = 0;
|
||||
if (QueryServiceConfig(schService,
|
||||
(LPQUERY_SERVICE_CONFIGA)&serviceConfigMemory,
|
||||
sizeof(serviceConfigMemory),
|
||||
&bytesNeeded)) {
|
||||
QUERY_SERVICE_CONFIG *cfg = (QUERY_SERVICE_CONFIG*) &serviceConfigMemory;
|
||||
|
||||
std::string command = std::string("\"") + std::string(path) + std::string("\" --start-service");
|
||||
if (strcmp(cfg->lpBinaryPathName, command.c_str())) {
|
||||
if (! force) {
|
||||
std::cerr << "NOT removing service of other installation: " <<
|
||||
cfg->lpBinaryPathName <<
|
||||
" Our path is: " <<
|
||||
path << std::endl;
|
||||
|
||||
CloseServiceHandle(schSCManager);
|
||||
return;
|
||||
}
|
||||
else {
|
||||
std::cerr << "Removing service of other installation because of FORCE: " <<
|
||||
cfg->lpBinaryPathName <<
|
||||
"Our path is: " <<
|
||||
path << std::endl;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
CloseServiceHandle(schSCManager);
|
||||
|
||||
if (schService == 0) {
|
||||
std::cerr << "FATAL: OpenServiceA failed with " << GetLastError() << std::endl;
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
if (! DeleteService(schService)) {
|
||||
std::cerr << "FATAL: DeleteService failed with " << GetLastError() << std::endl;
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
CloseServiceHandle(schService);
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief flips the status for a service
|
||||
|
@ -357,6 +428,24 @@ void WindowsServiceFeature::shutDownBegins () {
|
|||
}
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief wrap ArangoDB server so we can properly emmit a status on shutdown
|
||||
/// starting
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
void WindowsServiceFeature::shutDownComplete () {
|
||||
// startup finished - signalize we're running.
|
||||
SetServiceStatus(SERVICE_STOPPED, NO_ERROR, 0, 0);
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief wrap ArangoDB server so we can properly emmit a status on shutdown
|
||||
/// starting
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
void WindowsServiceFeature::shutDownFailure () {
|
||||
// startup finished - signalize we're running.
|
||||
SetServiceStatus(SERVICE_STOP, ERROR_FAIL_RESTART, 0, 0);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief service control handler
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -467,15 +556,15 @@ void WindowsServiceFeature::collectOptions(std::shared_ptr<ProgramOptions> optio
|
|||
}
|
||||
|
||||
void WindowsServiceFeature::validateOptions(std::shared_ptr<ProgramOptions> options) {
|
||||
if (_startAsService) {
|
||||
}
|
||||
else if (_installService) {
|
||||
|
||||
if (_installService) {
|
||||
installService();
|
||||
exit(EXIT_SUCCESS);
|
||||
}
|
||||
else if (_unInstallService) {
|
||||
}
|
||||
|
||||
else if (_forceUninstall) {
|
||||
}
|
||||
else if (_startAsService) {
|
||||
ProgressHandler reporter{
|
||||
[this](ServerState state) {
|
||||
|
|
|
@ -36,6 +36,7 @@ class WindowsServiceFeature final : public application_features::ApplicationFeat
|
|||
|
||||
private:
|
||||
void installService();
|
||||
void DeleteService (bool force);
|
||||
void StartArangoService (bool WaitForRunning);
|
||||
void StopArangoService (bool WaitForShutdown);
|
||||
void startupProgress ();
|
||||
|
@ -43,6 +44,8 @@ class WindowsServiceFeature final : public application_features::ApplicationFeat
|
|||
void startupFinished ();
|
||||
|
||||
void shutDownBegins ();
|
||||
void shutDownComplete ();
|
||||
void shutDownFailure ();
|
||||
|
||||
public:
|
||||
bool _installService = false;
|
||||
|
|
|
@ -619,7 +619,16 @@ void ADB_WindowsEntryFunction() {
|
|||
TRI_Application_Exit_SetExit(ADB_WindowsExitFunction);
|
||||
}
|
||||
|
||||
TRI_serviceAboert_t serviceAbort = nullptr;
|
||||
|
||||
void TRI_SetWindowsServiceAbortFunction(TRI_serviceAboert_t f) {
|
||||
serviceAbort = f;
|
||||
}
|
||||
|
||||
void ADB_WindowsExitFunction(int exitCode, void* data) {
|
||||
if (serviceAbort != nullptr) {
|
||||
serviceAbort();
|
||||
}
|
||||
int res = finalizeWindows(TRI_WIN_FINAL_WSASTARTUP_FUNCTION_CALL, 0);
|
||||
|
||||
if (res != 0) {
|
||||
|
|
|
@ -108,6 +108,10 @@ int TRI_MapSystemError(DWORD);
|
|||
bool TRI_InitWindowsEventLog(void);
|
||||
void TRI_CloseWindowsEventlog(void);
|
||||
|
||||
typedef void (*TRI_serviceAboert_t)(void);
|
||||
|
||||
void TRI_SetWindowsServiceAbortFunction(TRI_serviceAboert_t);
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief logs a message to the windows event log.
|
||||
/// we rather are keen on logging something at all then on being able to work
|
||||
|
|
Loading…
Reference in New Issue