Fixed bugs in CCClient, added missing delete/desttructors for restart

This commit is contained in:
BenDroid 2017-10-17 22:31:22 +02:00
parent 5c065a8e48
commit 2b97e2f4ff
17 changed files with 194 additions and 110 deletions

View file

@ -36,10 +36,8 @@
#include "log/Log.h" #include "log/Log.h"
#include "Mem.h" #include "Mem.h"
#include "net/Network.h" #include "net/Network.h"
#include "Options.h"
#include "Platform.h" #include "Platform.h"
#include "Summary.h" #include "Summary.h"
#include "version.h"
#include "workers/Workers.h" #include "workers/Workers.h"
#include "cc/CCClient.h" #include "cc/CCClient.h"
@ -57,6 +55,7 @@ App *App::m_self = nullptr;
App::App(int argc, char **argv) : App::App(int argc, char **argv) :
m_restart(false),
m_console(nullptr), m_console(nullptr),
m_httpd(nullptr), m_httpd(nullptr),
m_network(nullptr), m_network(nullptr),
@ -99,7 +98,12 @@ App::App(int argc, char **argv) :
App::~App() App::~App()
{ {
uv_tty_reset_mode(); Log::release();
Options::release();
Mem::release();
Platform::release();
delete m_network;
# ifndef XMRIG_NO_HTTPD # ifndef XMRIG_NO_HTTPD
delete m_httpd; delete m_httpd;
@ -110,10 +114,19 @@ App::~App()
# endif # endif
delete m_console; delete m_console;
# ifndef XMRIG_NO_API
Api::release();
# endif
uv_signal_stop(&m_signal);
uv_tty_reset_mode();
m_self = nullptr;
} }
int App::exec() int App::start()
{ {
if (!m_options) { if (!m_options) {
return 0; return 0;
@ -130,7 +143,7 @@ int App::exec()
return 1; return 1;
} }
Mem::allocate(m_options->algo(), m_options->threads(), m_options->doubleHash(), m_options->hugePages()); Mem::allocate(m_options);
Summary::print(); Summary::print();
# ifndef XMRIG_NO_API # ifndef XMRIG_NO_API
@ -153,13 +166,7 @@ int App::exec()
const int r = uv_run(uv_default_loop(), UV_RUN_DEFAULT); const int r = uv_run(uv_default_loop(), UV_RUN_DEFAULT);
uv_loop_close(uv_default_loop()); uv_loop_close(uv_default_loop());
delete m_network; return m_restart ? ERESTART : r;
Options::release();
Mem::release();
Platform::release();
return r;
} }
@ -171,6 +178,11 @@ void App::onConsoleCommand(char command)
Workers::printHashrate(true); Workers::printHashrate(true);
break; break;
case 'i':
case 'I':
restart();
break;
case 'p': case 'p':
case 'P': case 'P':
LOG_INFO(m_options->colors() ? "\x1B[01;33mpaused\x1B[0m, press \x1B[01;35mr\x1B[0m to resume" : "paused, press 'r' to resume"); LOG_INFO(m_options->colors() ? "\x1B[01;33mpaused\x1B[0m, press \x1B[01;35mr\x1B[0m to resume" : "paused, press 'r' to resume");
@ -185,9 +197,10 @@ void App::onConsoleCommand(char command)
} }
break; break;
case 'q':
case 'Q':
case 3: case 3:
LOG_WARN("Ctrl+C received, exiting"); stop(false);
close();
break; break;
default: default:
@ -196,33 +209,19 @@ void App::onConsoleCommand(char command)
} }
void App::close() void App::stop(bool restart)
{ {
m_restart = restart;
m_network->stop(); m_network->stop();
Workers::stop(); Workers::stop();
uv_stop(uv_default_loop()); uv_stop(uv_default_loop());
} }
void App::reloadConfig() void App::restart()
{ {
// reload config WIP m_self->stop(true);
/*
m_self->m_options->parseConfig(m_self->m_options->configFile());
Platform::release();
Platform::init(m_self->m_options->userAgent());
Platform::setProcessPriority(m_self->m_options->priority());
m_self->m_network->stop();
Workers::stop(); // free resources here
Mem::release();
Mem::allocate(m_self->m_options->algo(), m_self->m_options->threads(), m_self->m_options->doubleHash(), m_self->m_options->hugePages());
Summary::print();
Workers::start(m_self->m_options->affinity(), m_self->m_options->priority());
*/
} }
void App::onSignal(uv_signal_t *handle, int signum) void App::onSignal(uv_signal_t *handle, int signum)
@ -245,7 +244,5 @@ void App::onSignal(uv_signal_t *handle, int signum)
break; break;
} }
uv_signal_stop(handle); m_self->stop(false);
m_self->close();
} }

View file

@ -43,21 +43,23 @@ public:
App(int argc, char **argv); App(int argc, char **argv);
~App(); ~App();
int exec(); int start();
static void reloadConfig(); static void restart();
protected: protected:
void onConsoleCommand(char command) override; void onConsoleCommand(char command) override;
private: private:
void background(); void background();
void close(); void stop(bool restart);
static void onSignal(uv_signal_t *handle, int signum); static void onSignal(uv_signal_t *handle, int signum);
static App *m_self; static App *m_self;
bool m_restart;
Console *m_console; Console *m_console;
Httpd *m_httpd; Httpd *m_httpd;
Network *m_network; Network *m_network;

View file

@ -40,6 +40,11 @@ Console::Console(IConsoleListener *listener)
uv_read_start(reinterpret_cast<uv_stream_t*>(&m_tty), Console::onAllocBuffer, Console::onRead); uv_read_start(reinterpret_cast<uv_stream_t*>(&m_tty), Console::onAllocBuffer, Console::onRead);
} }
Console::~Console()
{
uv_read_stop(reinterpret_cast<uv_stream_t*>(&m_tty));
uv_tty_reset_mode();
}
void Console::onAllocBuffer(uv_handle_t *handle, size_t suggested_size, uv_buf_t *buf) void Console::onAllocBuffer(uv_handle_t *handle, size_t suggested_size, uv_buf_t *buf)
{ {
@ -48,7 +53,6 @@ void Console::onAllocBuffer(uv_handle_t *handle, size_t suggested_size, uv_buf_t
buf->base = console->m_buf; buf->base = console->m_buf;
} }
void Console::onRead(uv_stream_t *stream, ssize_t nread, const uv_buf_t *buf) void Console::onRead(uv_stream_t *stream, ssize_t nread, const uv_buf_t *buf)
{ {
if (nread < 0) { if (nread < 0) {

View file

@ -35,6 +35,7 @@ class Console
{ {
public: public:
Console(IConsoleListener *listener); Console(IConsoleListener *listener);
~Console();
private: private:
static void onAllocBuffer(uv_handle_t *handle, size_t suggested_size, uv_buf_t *buf); static void onAllocBuffer(uv_handle_t *handle, size_t suggested_size, uv_buf_t *buf);

View file

@ -28,9 +28,8 @@
#include <stddef.h> #include <stddef.h>
#include <stdint.h> #include <stdint.h>
#include "align.h" #include "align.h"
#include "Options.h"
struct cryptonight_ctx; struct cryptonight_ctx;
@ -44,7 +43,7 @@ public:
Lock = 4 Lock = 4
}; };
static bool allocate(int algo, int threads, bool doubleHash, bool enabled); static bool allocate(const Options* options);
static cryptonight_ctx *create(int threadId); static cryptonight_ctx *create(int threadId);
static void *calloc(size_t num, size_t size); static void *calloc(size_t num, size_t size);
static void release(); static void release();

View file

@ -33,16 +33,16 @@
#include "Options.h" #include "Options.h"
bool Mem::allocate(int algo, int threads, bool doubleHash, bool enabled) bool Mem::allocate(const Options* options)
{ {
m_algo = algo; m_algo = options->algo();
m_threads = threads; m_threads = options->threads();
m_doubleHash = doubleHash; m_doubleHash = options->doubleHash();
const int ratio = (doubleHash && algo != Options::ALGO_CRYPTONIGHT_LITE) ? 2 : 1; const int ratio = (m_doubleHash && m_algo != Options::ALGO_CRYPTONIGHT_LITE) ? 2 : 1;
const size_t size = MEMORY * (threads * ratio + 1); const size_t size = MEMORY * (m_threads * ratio + 1);
if (!enabled) { if (!options->hugePages()) {
m_memory = static_cast<uint8_t*>(_mm_malloc(size, 16)); m_memory = static_cast<uint8_t*>(_mm_malloc(size, 16));
return true; return true;
} }

View file

@ -144,16 +144,16 @@ static BOOL TrySetLockPagesPrivilege() {
} }
bool Mem::allocate(int algo, int threads, bool doubleHash, bool enabled) bool Mem::allocate(const Options* options)
{ {
m_algo = algo; m_algo = options->algo();
m_threads = threads; m_threads = options->threads();
m_doubleHash = doubleHash; m_doubleHash = options->doubleHash();
const int ratio = (doubleHash && algo != Options::ALGO_CRYPTONIGHT_LITE) ? 2 : 1; const int ratio = (m_doubleHash && m_algo != Options::ALGO_CRYPTONIGHT_LITE) ? 2 : 1;
const size_t size = MEMORY * (threads * ratio + 1); const size_t size = MEMORY * (m_threads * ratio + 1);
if (!enabled) { if (!options->hugePages()) {
m_memory = static_cast<uint8_t*>(_mm_malloc(size, 16)); m_memory = static_cast<uint8_t*>(_mm_malloc(size, 16));
return true; return true;
} }

View file

@ -152,10 +152,10 @@ static void print_cc()
static void print_commands() static void print_commands()
{ {
if (Options::i()->colors()) { if (Options::i()->colors()) {
Log::i()->text("\x1B[01;32m * \x1B[01;37mCOMMANDS: \x1B[01;35mh\x1B[01;37mashrate, \x1B[01;35mp\x1B[01;37mause, \x1B[01;35mr\x1B[01;37mesume"); Log::i()->text("\x1B[01;32m * \x1B[01;37mCOMMANDS: \x1B[01;35mh\x1B[01;37mashrate, \x1B[01;35mi\x1B[01;37mnvalidate, \x1B[01;35mp\x1B[01;37mause, \x1B[01;35mr\x1B[01;37mesume, \x1B[01;35mq\x1B[01;37muit");
} }
else { else {
Log::i()->text(" * COMMANDS: 'h' hashrate, 'p' pause, 'r' resume"); Log::i()->text(" * COMMANDS: 'h' hashrate, 'i' invalidate, 'p' pause, 'r' resume, 'q' quit");
} }
} }

View file

@ -88,7 +88,7 @@ void CCClient::updateNetworkState(const NetworkState &network)
{ {
uv_mutex_lock(&m_mutex); uv_mutex_lock(&m_mutex);
m_self->m_clientStatus.setCurrentStatus(Workers::isEnabled() ? "mining" : "paused"); m_self->m_clientStatus.setCurrentStatus(Workers::isEnabled() ? ClientStatus::RUNNING : ClientStatus::PAUSED);
m_self->m_clientStatus.setCurrentPool(network.pool); m_self->m_clientStatus.setCurrentPool(network.pool);
m_self->m_clientStatus.setSharesGood(network.accepted); m_self->m_clientStatus.setSharesGood(network.accepted);
m_self->m_clientStatus.setSharesTotal(network.accepted + network.rejected); m_self->m_clientStatus.setSharesTotal(network.accepted + network.rejected);
@ -100,50 +100,55 @@ void CCClient::updateNetworkState(const NetworkState &network)
void CCClient::publishClientStatusReport() void CCClient::publishClientStatusReport()
{ {
std::string requestUrl = m_self->m_serverURL + "/client/setClientStatus?clientId=" + m_self->m_clientStatus.getClientId(); std::string requestUrl = m_self->m_serverURL
+ "/client/setClientStatus?clientId="
+ m_self->m_clientStatus.getClientId();
std::string requestBuffer = m_self->m_clientStatus.toJsonString(); std::string requestBuffer = m_self->m_clientStatus.toJsonString();
std::string responseBuffer; std::string responseBuffer;
CURLcode res = performCurl(requestUrl, requestBuffer, "POST", responseBuffer); CURLcode res = performCurl(requestUrl, requestBuffer, "POST", responseBuffer);
if (res != CURLE_OK) { if (res != CURLE_OK) {
LOG_ERR("CCClient error: %s", curl_easy_strerror(res)); LOG_ERR("[CC-Client] error: \"%s\" -> %s",
curl_easy_strerror(res), requestUrl.c_str());
} else { } else {
ControlCommand controlCommand; ControlCommand controlCommand;
if (controlCommand.parseFromJsonString(responseBuffer)) { if (controlCommand.parseFromJsonString(responseBuffer)) {
if (controlCommand.getCommand() == ControlCommand::START) { if (controlCommand.getCommand() == ControlCommand::START) {
if (!Workers::isEnabled()) { if (!Workers::isEnabled()) {
LOG_INFO("Command: START received -> Resuming"); LOG_INFO("[CC-Client] Command: START received -> resume");
Workers::setEnabled(true); Workers::setEnabled(true);
} }
} else if (controlCommand.getCommand() == ControlCommand::STOP) { } else if (controlCommand.getCommand() == ControlCommand::STOP) {
if (!Workers::isEnabled()) { if (Workers::isEnabled()) {
LOG_INFO("Command: STOP received -> Pausing"); LOG_INFO("[CC-Client] Command: STOP received -> pause");
Workers::setEnabled(true); Workers::setEnabled(false);
} }
} else if (controlCommand.getCommand() == ControlCommand::UPDATE_CONFIG) { } else if (controlCommand.getCommand() == ControlCommand::UPDATE_CONFIG) {
LOG_INFO("Command: UPDATE_CONFIG received -> Updating config");
updateConfig(); updateConfig();
} else if (controlCommand.getCommand() == ControlCommand::RELOAD) { } else if (controlCommand.getCommand() == ControlCommand::RESTART) {
LOG_INFO("Command: RELOAD received -> Reload"); App::restart();
App::reloadConfig(); } else if (controlCommand.getCommand() == ControlCommand::QUIT) {
} else { // TODO
LOG_ERR("Command: GET_CONFIG received -> NOT IMPLEMENTED YET!");
} }
} else { } else {
LOG_ERR("Unknown Command received from CC Server."); LOG_ERR("[CC-Client] unknown command received from CC Server.");
} }
} }
} }
void CCClient::updateConfig() void CCClient::updateConfig()
{ {
std::string requestUrl = m_self->m_serverURL + "/client/getConfig?clientId=" + m_self->m_clientStatus.getClientId(); std::string requestUrl = m_self->m_serverURL
+ "/client/getConfig?clientId="
+ m_self->m_clientStatus.getClientId();
std::string requestBuffer; std::string requestBuffer;
std::string responseBuffer; std::string responseBuffer;
CURLcode res = performCurl(requestUrl, requestBuffer, "GET", responseBuffer); CURLcode res = performCurl(requestUrl, requestBuffer, "GET", responseBuffer);
if (res != CURLE_OK) { if (res != CURLE_OK) {
LOG_ERR("CCClient error: %s", curl_easy_strerror(res)); LOG_ERR("[CC-Client] error: \"%s\" -> %s", curl_easy_strerror(res), requestUrl.c_str());
} else { } else {
rapidjson::Document document; rapidjson::Document document;
if (!document.Parse(responseBuffer.c_str()).HasParseError()) { if (!document.Parse(responseBuffer.c_str()).HasParseError()) {
@ -157,13 +162,13 @@ void CCClient::updateConfig()
clientConfigFile << buffer.GetString(); clientConfigFile << buffer.GetString();
clientConfigFile.close(); clientConfigFile.close();
LOG_INFO("Config update done. Reload."); LOG_INFO("[CC-Client] config updated. restart.");
App::reloadConfig(); App::restart();
} else { } else {
LOG_ERR("Not able to store client config to file %s.", m_self->m_options->configFile()); LOG_ERR("[CC-Client] not able to store client config to file %s.", m_self->m_options->configFile());
} }
} else{ } else{
LOG_ERR("Not able to store client config. The received client config is broken!"); LOG_ERR("[CC-Client] not able to store client config. received client config is broken!");
} }
} }
} }

View file

@ -63,12 +63,12 @@ void ClientStatus::setCurrentPool(const std::string& currentPool)
m_currentPool = currentPool; m_currentPool = currentPool;
} }
const std::string ClientStatus::getCurrentStatus() const ClientStatus::Status ClientStatus::getCurrentStatus() const
{ {
return m_currentStatus; return m_currentStatus;
} }
void ClientStatus::setCurrentStatus(const std::string& currentStatus) void ClientStatus::setCurrentStatus(Status currentStatus)
{ {
m_currentStatus = currentStatus; m_currentStatus = currentStatus;
} }
@ -175,7 +175,7 @@ bool ClientStatus::parseFromJson(const rapidjson::Document& document)
} }
if (clientStatus.HasMember("current_status")) { if (clientStatus.HasMember("current_status")) {
m_currentStatus = clientStatus["current_status"].GetString(); m_currentStatus = toStatus(clientStatus["current_status"].GetString());
} }
if (clientStatus.HasMember("hashrate_short")) { if (clientStatus.HasMember("hashrate_short")) {
@ -227,7 +227,7 @@ rapidjson::Value ClientStatus::toJson(rapidjson::MemoryPoolAllocator<rapidjson::
clientStatus.AddMember("client_id", rapidjson::StringRef(m_clientId.c_str()), allocator); clientStatus.AddMember("client_id", rapidjson::StringRef(m_clientId.c_str()), allocator);
clientStatus.AddMember("current_pool", rapidjson::StringRef(m_currentPool.c_str()), allocator); clientStatus.AddMember("current_pool", rapidjson::StringRef(m_currentPool.c_str()), allocator);
clientStatus.AddMember("current_status", rapidjson::StringRef(m_currentStatus.c_str()), allocator); clientStatus.AddMember("current_status", rapidjson::StringRef(toString(m_currentStatus)), allocator);
clientStatus.AddMember("hashrate_short", m_hashrateShort, allocator); clientStatus.AddMember("hashrate_short", m_hashrateShort, allocator);
clientStatus.AddMember("hashrate_medium", m_hashrateMedium, allocator); clientStatus.AddMember("hashrate_medium", m_hashrateMedium, allocator);

View file

@ -31,18 +31,41 @@
class ClientStatus class ClientStatus
{ {
public:
public:
enum Status {
RUNNING,
PAUSED,
CONFIG_UPDATED
};
public:
ClientStatus(); ClientStatus();
inline const char *toString (Status status)
{
return status_str[static_cast<int>(status)];
}
inline Status toStatus (const char *status)
{
const int n = sizeof(status_str) / sizeof(status_str[0]);
for (int i = 0; i < n; ++i)
{
if (strcmp(status_str[i], status) == 0)
return (Status) i;
}
return Status::RUNNING;
}
const std::string getClientId() const; const std::string getClientId() const;
void setClientId(const std::string& clientId); void setClientId(const std::string& clientId);
const std::string getCurrentPool() const; const std::string getCurrentPool() const;
void setCurrentPool(const std::string& currentPool); void setCurrentPool(const std::string& currentPool);
const std::string getCurrentStatus() const; Status getCurrentStatus() const;
void setCurrentStatus(const std::string& currentStatus); void setCurrentStatus(Status currentStatus);
double getHashrateShort() const; double getHashrateShort() const;
void setHashrateShort(double hashrateShort); void setHashrateShort(double hashrateShort);
@ -76,9 +99,16 @@ public:
private: private:
const char* status_str[3] = {
"RUNNING",
"PAUSED",
"CONFIG_UPDATED"
};
Status m_currentStatus;
std::string m_clientId; std::string m_clientId;
std::string m_currentPool; std::string m_currentPool;
std::string m_currentStatus;
double m_hashrateShort; double m_hashrateShort;
double m_hashrateMedium; double m_hashrateMedium;

View file

@ -34,7 +34,7 @@ ControlCommand::ControlCommand()
} }
ControlCommand::ControlCommand(ControlCommand::Command command) ControlCommand::ControlCommand(Command command)
: m_command(command) : m_command(command)
{ {
@ -59,7 +59,7 @@ bool ControlCommand::parseFromJson(const rapidjson::Document& document)
if (document.HasMember("control_command")) { if (document.HasMember("control_command")) {
rapidjson::Value::ConstObject controlCommand = document["control_command"].GetObject(); rapidjson::Value::ConstObject controlCommand = document["control_command"].GetObject();
if (controlCommand.HasMember("command")) { if (controlCommand.HasMember("command")) {
m_command = static_cast<Command>(controlCommand["command"].GetUint()); m_command = toCommand(controlCommand["command"].GetString());
result = true; result = true;
} }
else { else {
@ -76,12 +76,12 @@ rapidjson::Value ControlCommand::toJson(rapidjson::MemoryPoolAllocator<rapidjson
{ {
rapidjson::Value controlCommand(rapidjson::kObjectType); rapidjson::Value controlCommand(rapidjson::kObjectType);
controlCommand.AddMember("command", m_command, allocator); controlCommand.AddMember("command", rapidjson::StringRef(toString(m_command)), allocator);
return controlCommand; return controlCommand;
} }
void ControlCommand::setCommand(ControlCommand::Command command) void ControlCommand::setCommand(Command command)
{ {
m_command = command; m_command = command;
} }
@ -90,3 +90,10 @@ ControlCommand::Command ControlCommand::getCommand() const
{ {
return m_command; return m_command;
} }
bool ControlCommand::isOneTimeCommand() const {
return m_command == ControlCommand::UPDATE_CONFIG ||
m_command == ControlCommand::RESTART ||
m_command == ControlCommand::QUIT;
}

View file

@ -32,18 +32,34 @@
class ControlCommand class ControlCommand
{ {
public: public:
enum Command enum Command {
{
START, START,
STOP, STOP,
RELOAD,
UPDATE_CONFIG, UPDATE_CONFIG,
HALT RESTART,
QUIT
}; };
public:
ControlCommand(); ControlCommand();
explicit ControlCommand(Command command); explicit ControlCommand(Command command);
inline const char *toString (Command command)
{
return command_str[static_cast<int>(command)];
}
inline Command toCommand (const char *command)
{
const int n = sizeof(command_str) / sizeof(command_str[0]);
for (int i = 0; i < n; ++i)
{
if (strcmp(command_str[i], command) == 0)
return (Command) i;
}
return Command::START;
}
rapidjson::Value toJson(rapidjson::MemoryPoolAllocator<rapidjson::CrtAllocator>& allocator); rapidjson::Value toJson(rapidjson::MemoryPoolAllocator<rapidjson::CrtAllocator>& allocator);
bool parseFromJsonString(const std::string& json); bool parseFromJsonString(const std::string& json);
bool parseFromJson(const rapidjson::Document& document); bool parseFromJson(const rapidjson::Document& document);
@ -51,7 +67,17 @@ public:
Command getCommand() const; Command getCommand() const;
void setCommand(Command command); void setCommand(Command command);
bool isOneTimeCommand() const;
private: private:
const char* command_str[5] = {
"START",
"STOP",
"UPDATE_CONFIG",
"RESTART",
"QUIT"
};
Command m_command; Command m_command;
}; };

View file

@ -60,7 +60,7 @@ unsigned Service::handleGET(const Options* options, const std::string& url, cons
{ {
uv_mutex_lock(&m_mutex); uv_mutex_lock(&m_mutex);
unsigned resultCode = MHD_HTTP_BAD_REQUEST; unsigned resultCode = MHD_HTTP_NOT_FOUND;
LOG_INFO("GET(url='%s', clientId='%s')", url.c_str(), clientId.c_str()); LOG_INFO("GET(url='%s', clientId='%s')", url.c_str(), clientId.c_str());
@ -72,12 +72,6 @@ unsigned Service::handleGET(const Options* options, const std::string& url, cons
if (!clientId.empty()) { if (!clientId.empty()) {
if (url.rfind("/client/getConfig", 0) == 0 || url.rfind("/admin/getClientConfig", 0) == 0) { if (url.rfind("/client/getConfig", 0) == 0 || url.rfind("/admin/getClientConfig", 0) == 0) {
resultCode = getClientConfig(options, clientId, resp); resultCode = getClientConfig(options, clientId, resp);
if (url.rfind("/client/getConfig", 0) == 0) {
std::map<std::string,ControlCommand>::iterator iter = m_clientCommand.find(clientId);
if (iter != m_clientCommand.end()) {
m_clientCommand.erase(iter);
}
}
} else if (url.rfind("/admin/getClientCommand", 0) == 0) { } else if (url.rfind("/admin/getClientCommand", 0) == 0) {
resultCode = getClientCommand(clientId, resp); resultCode = getClientCommand(clientId, resp);
} }
@ -96,7 +90,7 @@ unsigned Service::handlePOST(const Options* options, const std::string& url, con
{ {
uv_mutex_lock(&m_mutex); uv_mutex_lock(&m_mutex);
unsigned resultCode = MHD_HTTP_BAD_REQUEST; unsigned resultCode = MHD_HTTP_NOT_FOUND;
LOG_INFO("POST(url='%s', clientId='%s', data='%s')", url.c_str(), clientId.c_str(), data.c_str()); LOG_INFO("POST(url='%s', clientId='%s', data='%s')", url.c_str(), clientId.c_str(), data.c_str());
@ -212,6 +206,8 @@ unsigned Service::getClientStatusList(std::string& resp)
unsigned Service::setClientStatus(const std::string& clientId, const std::string& data, std::string& resp) unsigned Service::setClientStatus(const std::string& clientId, const std::string& data, std::string& resp)
{ {
int resultCode = MHD_HTTP_BAD_REQUEST;
rapidjson::Document document; rapidjson::Document document;
if (!document.Parse(data.c_str()).HasParseError()) { if (!document.Parse(data.c_str()).HasParseError()) {
LOG_INFO("Status from client: %s", clientId.c_str()); LOG_INFO("Status from client: %s", clientId.c_str());
@ -220,12 +216,17 @@ unsigned Service::setClientStatus(const std::string& clientId, const std::string
clientStatus.parseFromJson(document); clientStatus.parseFromJson(document);
m_clientStatus[clientId] = clientStatus; m_clientStatus[clientId] = clientStatus;
resultCode = getClientCommand(clientId, resp);
if (m_clientCommand[clientId].isOneTimeCommand()) {
m_clientCommand.erase(clientId);
}
} else { } else {
LOG_ERR("Parse Error Occured: %d", document.GetParseError()); LOG_ERR("Parse Error Occured: %d", document.GetParseError());
return MHD_HTTP_BAD_REQUEST;
} }
return getClientCommand(clientId, resp); return resultCode;
} }
unsigned Service::getClientCommand(const std::string& clientId, std::string& resp) unsigned Service::getClientCommand(const std::string& clientId, std::string& resp)

View file

@ -57,7 +57,7 @@ public:
static inline Log* i() { return m_self; } static inline Log* i() { return m_self; }
static inline void add(ILogBackend *backend) { i()->m_backends.push_back(backend); } static inline void add(ILogBackend *backend) { i()->m_backends.push_back(backend); }
static inline void init() { if (!m_self) { m_self = new Log();} } static inline void init() { if (!m_self) { m_self = new Log();} }
static inline void release() { delete m_self; } static inline void release() { delete m_self; m_self = nullptr; }
void message(Level level, const char* fmt, ...); void message(Level level, const char* fmt, ...);
void text(const char* fmt, ...); void text(const char* fmt, ...);

View file

@ -55,7 +55,6 @@ Network::Network(const Options *options) :
Workers::setListener(this); Workers::setListener(this);
const std::vector<Url*> &pools = options->pools(); const std::vector<Url*> &pools = options->pools();
if (pools.size() > 1) { if (pools.size() > 1) {
m_strategy = new FailoverStrategy(pools, Platform::userAgent(), this); m_strategy = new FailoverStrategy(pools, Platform::userAgent(), this);
} }
@ -76,6 +75,13 @@ Network::Network(const Options *options) :
Network::~Network() Network::~Network()
{ {
uv_timer_stop(&m_timer);
if (m_donate) {
delete m_donate;
}
delete m_strategy;
} }

View file

@ -25,7 +25,13 @@
int main(int argc, char **argv) { int main(int argc, char **argv) {
App app(argc, argv); for (;;) {
App* app = new App(argc, argv);
int res = app->start();
delete app;
return app.exec(); if (res != ERESTART) {
break;
}
}
} }