2016-09-03 09:39:45 -07:00
|
|
|
// Copyright (c) 2016 The Zcash developers
|
|
|
|
// Distributed under the MIT software license, see the accompanying
|
|
|
|
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
|
|
|
|
|
|
|
#include "metrics.h"
|
|
|
|
|
|
|
|
#include "chainparams.h"
|
2016-09-03 10:51:54 -07:00
|
|
|
#include "ui_interface.h"
|
2016-09-03 09:39:45 -07:00
|
|
|
#include "util.h"
|
|
|
|
#include "utiltime.h"
|
|
|
|
|
|
|
|
#include <boost/thread.hpp>
|
2016-09-03 10:51:54 -07:00
|
|
|
#include <boost/thread/synchronized_value.hpp>
|
|
|
|
#include <string>
|
2016-09-03 20:40:28 -07:00
|
|
|
#include <sys/ioctl.h>
|
2016-10-23 19:23:56 -07:00
|
|
|
#include <unistd.h>
|
2016-09-03 09:39:45 -07:00
|
|
|
|
|
|
|
AtomicCounter transactionsValidated;
|
|
|
|
AtomicCounter ehSolverRuns;
|
2016-09-04 15:54:15 -07:00
|
|
|
AtomicCounter solutionTargetChecks;
|
2016-09-03 09:39:45 -07:00
|
|
|
AtomicCounter minedBlocks;
|
|
|
|
|
2016-09-03 10:51:54 -07:00
|
|
|
boost::synchronized_value<std::list<std::string>> messageBox;
|
|
|
|
boost::synchronized_value<std::string> initMessage;
|
|
|
|
bool loaded = false;
|
|
|
|
|
|
|
|
static bool metrics_ThreadSafeMessageBox(const std::string& message,
|
|
|
|
const std::string& caption,
|
|
|
|
unsigned int style)
|
|
|
|
{
|
|
|
|
std::string strCaption;
|
|
|
|
// Check for usage of predefined caption
|
|
|
|
switch (style) {
|
|
|
|
case CClientUIInterface::MSG_ERROR:
|
|
|
|
strCaption += _("Error");
|
|
|
|
break;
|
|
|
|
case CClientUIInterface::MSG_WARNING:
|
|
|
|
strCaption += _("Warning");
|
|
|
|
break;
|
|
|
|
case CClientUIInterface::MSG_INFORMATION:
|
|
|
|
strCaption += _("Information");
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
strCaption += caption; // Use supplied caption (can be empty)
|
|
|
|
}
|
|
|
|
|
|
|
|
boost::strict_lock_ptr<std::list<std::string>> u = messageBox.synchronize();
|
|
|
|
u->push_back(strCaption + ": " + message);
|
|
|
|
if (u->size() > 5) {
|
|
|
|
u->pop_back();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static void metrics_InitMessage(const std::string& message)
|
|
|
|
{
|
|
|
|
*initMessage = message;
|
|
|
|
}
|
|
|
|
|
|
|
|
void ConnectMetricsScreen()
|
|
|
|
{
|
|
|
|
uiInterface.ThreadSafeMessageBox.disconnect_all_slots();
|
|
|
|
uiInterface.ThreadSafeMessageBox.connect(metrics_ThreadSafeMessageBox);
|
|
|
|
uiInterface.InitMessage.disconnect_all_slots();
|
|
|
|
uiInterface.InitMessage.connect(metrics_InitMessage);
|
|
|
|
}
|
|
|
|
|
2016-09-03 20:18:44 -07:00
|
|
|
void printMiningStatus(bool mining)
|
|
|
|
{
|
|
|
|
if (mining) {
|
|
|
|
int nThreads = GetArg("-genproclimit", 1);
|
|
|
|
if (nThreads < 0) {
|
|
|
|
// In regtest threads defaults to 1
|
|
|
|
if (Params().DefaultMinerThreads())
|
|
|
|
nThreads = Params().DefaultMinerThreads();
|
|
|
|
else
|
|
|
|
nThreads = boost::thread::hardware_concurrency();
|
|
|
|
}
|
2016-09-03 20:31:50 -07:00
|
|
|
std::cout << strprintf(_("You are running %d mining threads."), nThreads) << std::endl;
|
2016-09-03 20:18:44 -07:00
|
|
|
} else {
|
2016-09-03 20:31:50 -07:00
|
|
|
std::cout << _("You are currently not mining.") << std::endl;
|
|
|
|
std::cout << _("To enable mining, add 'gen=1' to your zcash.conf and restart.") << std::endl;
|
2016-09-03 20:18:44 -07:00
|
|
|
}
|
|
|
|
std::cout << std::endl;
|
|
|
|
}
|
|
|
|
|
2016-09-03 20:40:28 -07:00
|
|
|
int printMetrics(size_t cols, int64_t nStart, bool mining)
|
2016-09-03 20:18:44 -07:00
|
|
|
{
|
|
|
|
// Number of lines that are always displayed
|
|
|
|
int lines = 3;
|
|
|
|
|
|
|
|
// Calculate uptime
|
|
|
|
int64_t uptime = GetTime() - nStart;
|
|
|
|
int days = uptime / (24 * 60 * 60);
|
|
|
|
int hours = (uptime - (days * 24 * 60 * 60)) / (60 * 60);
|
|
|
|
int minutes = (uptime - (((days * 24) + hours) * 60 * 60)) / 60;
|
|
|
|
int seconds = uptime - (((((days * 24) + hours) * 60) + minutes) * 60);
|
2016-10-28 10:14:13 -07:00
|
|
|
int validatedCount = 0;
|
2016-09-03 20:18:44 -07:00
|
|
|
|
|
|
|
// Display uptime
|
2016-09-03 20:31:50 -07:00
|
|
|
std::string duration;
|
2016-09-03 20:18:44 -07:00
|
|
|
if (days > 0) {
|
2016-09-03 20:31:50 -07:00
|
|
|
duration = strprintf(_("%d days, %d hours, %d minutes, %d seconds"), days, hours, minutes, seconds);
|
|
|
|
} else if (hours > 0) {
|
|
|
|
duration = strprintf(_("%d hours, %d minutes, %d seconds"), hours, minutes, seconds);
|
|
|
|
} else if (minutes > 0) {
|
|
|
|
duration = strprintf(_("%d minutes, %d seconds"), minutes, seconds);
|
|
|
|
} else {
|
|
|
|
duration = strprintf(_("%d seconds"), seconds);
|
2016-09-03 20:18:44 -07:00
|
|
|
}
|
2016-09-03 20:40:28 -07:00
|
|
|
std::string strDuration = strprintf(_("Since starting this node %s ago:"), duration);
|
|
|
|
std::cout << strDuration << std::endl;
|
|
|
|
lines += (strDuration.size() / cols);
|
2016-09-03 20:18:44 -07:00
|
|
|
|
2016-10-28 10:14:13 -07:00
|
|
|
validatedCount = transactionsValidated.get();
|
|
|
|
if (validatedCount > 1) {
|
|
|
|
std::cout << "- " << strprintf(_("You have validated %d transactions!"), validatedCount) << std::endl;
|
|
|
|
} else if (validatedCount == 1) {
|
|
|
|
std::cout << "- " << strprintf(_("You have validated %d transaction."), validatedCount) << std::endl;
|
|
|
|
} else {
|
|
|
|
std::cout << "- " << strprintf(_("You have validated %d transactions."), validatedCount) << std::endl;
|
|
|
|
}
|
2016-09-03 20:18:44 -07:00
|
|
|
|
|
|
|
if (mining) {
|
2016-10-05 16:45:00 -07:00
|
|
|
double solps = uptime > 0 ? (double)solutionTargetChecks.get() / uptime : 0;
|
|
|
|
std::string strSolps = strprintf("%.4f Sol/s", solps);
|
|
|
|
std::cout << "- " << strprintf(_("You have contributed %s on average to the network solution rate."), strSolps) << std::endl;
|
2016-09-03 20:31:50 -07:00
|
|
|
std::cout << "- " << strprintf(_("You have completed %d Equihash solver runs."), ehSolverRuns.get()) << std::endl;
|
2016-09-04 15:54:15 -07:00
|
|
|
lines += 2;
|
2016-09-03 20:18:44 -07:00
|
|
|
|
|
|
|
int mined = minedBlocks.get();
|
|
|
|
if (mined > 0) {
|
2016-09-03 20:31:50 -07:00
|
|
|
std::cout << "- " << strprintf(_("You have mined %d blocks!"), mined) << std::endl;
|
2016-09-03 20:18:44 -07:00
|
|
|
lines++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
std::cout << std::endl;
|
|
|
|
|
|
|
|
return lines;
|
|
|
|
}
|
|
|
|
|
2016-09-03 20:40:28 -07:00
|
|
|
int printMessageBox(size_t cols)
|
2016-09-03 10:51:54 -07:00
|
|
|
{
|
|
|
|
boost::strict_lock_ptr<std::list<std::string>> u = messageBox.synchronize();
|
|
|
|
|
|
|
|
if (u->size() == 0) {
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2016-09-03 20:40:28 -07:00
|
|
|
int lines = 2 + u->size();
|
2016-09-03 20:31:50 -07:00
|
|
|
std::cout << _("Messages:") << std::endl;
|
2016-09-03 10:51:54 -07:00
|
|
|
for (auto it = u->cbegin(); it != u->cend(); ++it) {
|
|
|
|
std::cout << *it << std::endl;
|
2016-09-03 20:40:28 -07:00
|
|
|
// Handle wrapped lines
|
|
|
|
lines += (it->size() / cols);
|
2016-09-03 10:51:54 -07:00
|
|
|
}
|
2016-09-03 20:18:44 -07:00
|
|
|
std::cout << std::endl;
|
2016-09-03 20:40:28 -07:00
|
|
|
return lines;
|
2016-09-03 10:51:54 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
int printInitMessage()
|
|
|
|
{
|
|
|
|
if (loaded) {
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
std::string msg = *initMessage;
|
2016-09-03 20:31:50 -07:00
|
|
|
std::cout << _("Init message:") << " " << msg << std::endl;
|
2016-09-03 20:18:44 -07:00
|
|
|
std::cout << std::endl;
|
2016-09-03 10:51:54 -07:00
|
|
|
|
2016-09-03 20:31:50 -07:00
|
|
|
if (msg == _("Done loading")) {
|
2016-09-03 10:51:54 -07:00
|
|
|
loaded = true;
|
|
|
|
}
|
|
|
|
|
|
|
|
return 2;
|
|
|
|
}
|
|
|
|
|
2016-09-03 09:39:45 -07:00
|
|
|
void ThreadShowMetricsScreen()
|
|
|
|
{
|
|
|
|
// Make this thread recognisable as the metrics screen thread
|
|
|
|
RenameThread("zcash-metrics-screen");
|
|
|
|
|
|
|
|
// Clear screen
|
|
|
|
std::cout << "\e[2J";
|
|
|
|
|
|
|
|
// Print art
|
|
|
|
std::cout << METRICS_ART << std::endl;
|
|
|
|
std::cout << std::endl;
|
|
|
|
|
|
|
|
// Thank you text
|
2016-09-03 20:31:50 -07:00
|
|
|
std::cout << _("Thank you for running a Zcash node!") << std::endl;
|
|
|
|
std::cout << _("You're helping to strengthen the network and contributing to a social good :)") << std::endl;
|
2016-09-03 09:39:45 -07:00
|
|
|
std::cout << std::endl;
|
|
|
|
|
|
|
|
// Miner status
|
|
|
|
bool mining = GetBoolArg("-gen", false);
|
2016-09-03 20:18:44 -07:00
|
|
|
printMiningStatus(mining);
|
2016-09-03 09:39:45 -07:00
|
|
|
|
|
|
|
// Count uptime
|
|
|
|
int64_t nStart = GetTime();
|
|
|
|
|
|
|
|
while (true) {
|
2016-09-03 10:51:54 -07:00
|
|
|
// Number of lines that are always displayed
|
2016-09-03 20:18:44 -07:00
|
|
|
int lines = 1;
|
2016-10-23 08:54:50 -07:00
|
|
|
int cols = 80;
|
2016-09-03 09:39:45 -07:00
|
|
|
|
2016-09-03 20:40:28 -07:00
|
|
|
// Get current window size
|
2016-10-23 08:54:50 -07:00
|
|
|
if (isatty(STDOUT_FILENO)) {
|
2016-10-23 19:23:56 -07:00
|
|
|
struct winsize w;
|
|
|
|
w.ws_col = 0;
|
|
|
|
if (ioctl(STDOUT_FILENO, TIOCGWINSZ, &w) != -1 && w.ws_col != 0) {
|
|
|
|
cols = w.ws_col;
|
|
|
|
}
|
2016-10-23 08:54:50 -07:00
|
|
|
}
|
2016-09-03 20:40:28 -07:00
|
|
|
|
2016-09-03 09:39:45 -07:00
|
|
|
// Erase below current position
|
|
|
|
std::cout << "\e[J";
|
|
|
|
|
2016-10-23 08:54:50 -07:00
|
|
|
lines += printMetrics(cols, nStart, mining);
|
|
|
|
lines += printMessageBox(cols);
|
2016-09-03 10:51:54 -07:00
|
|
|
lines += printInitMessage();
|
|
|
|
|
2016-09-03 09:39:45 -07:00
|
|
|
// Explain how to exit
|
2016-09-03 20:31:50 -07:00
|
|
|
std::cout << "[" << _("Press Ctrl+C to exit") << "] [" << _("Set 'showmetrics=0' to hide") << "]" << std::endl;;
|
2016-09-03 09:39:45 -07:00
|
|
|
|
|
|
|
boost::this_thread::interruption_point();
|
|
|
|
MilliSleep(1000);
|
|
|
|
|
|
|
|
// Return to the top of the updating section
|
|
|
|
std::cout << "\e[" << lines << "A";
|
|
|
|
}
|
|
|
|
}
|