]> Git Repo - VerusCoin.git/blob - src/metrics.cpp
Auto merge of #1870 - str4d:1749-benchmark-rescanning, r=str4d
[VerusCoin.git] / src / metrics.cpp
1 // Copyright (c) 2016 The Zcash developers
2 // Distributed under the MIT software license, see the accompanying
3 // file COPYING or http://www.opensource.org/licenses/mit-license.php.
4
5 #include "metrics.h"
6
7 #include "chainparams.h"
8 #include "main.h"
9 #include "ui_interface.h"
10 #include "util.h"
11 #include "utiltime.h"
12 #include "utilmoneystr.h"
13
14 #include <boost/thread.hpp>
15 #include <boost/thread/synchronized_value.hpp>
16 #include <string>
17 #include <sys/ioctl.h>
18 #include <unistd.h>
19
20 CCriticalSection cs_metrics;
21
22 boost::synchronized_value<int64_t> nNodeStartTime;
23 AtomicCounter transactionsValidated;
24 AtomicCounter ehSolverRuns;
25 AtomicCounter solutionTargetChecks;
26 AtomicCounter minedBlocks;
27
28 boost::synchronized_value<std::list<uint256>> trackedBlocks;
29
30 boost::synchronized_value<std::list<std::string>> messageBox;
31 boost::synchronized_value<std::string> initMessage;
32 bool loaded = false;
33
34 extern int64_t GetNetworkHashPS(int lookup, int height);
35
36 void TrackMinedBlock(uint256 hash)
37 {
38     LOCK(cs_metrics);
39     minedBlocks.increment();
40     trackedBlocks->push_back(hash);
41 }
42
43 void MarkStartTime()
44 {
45     *nNodeStartTime = GetTime();
46 }
47
48 int64_t GetUptime()
49 {
50     return GetTime() - *nNodeStartTime;
51 }
52
53 double GetLocalSolPS_INTERNAL(int64_t uptime)
54 {
55     return uptime > 0 ? (double)solutionTargetChecks.get() / uptime : 0;
56 }
57
58 double GetLocalSolPS()
59 {
60     return GetLocalSolPS_INTERNAL(GetUptime());
61 }
62
63 static bool metrics_ThreadSafeMessageBox(const std::string& message,
64                                       const std::string& caption,
65                                       unsigned int style)
66 {
67     std::string strCaption;
68     // Check for usage of predefined caption
69     switch (style) {
70     case CClientUIInterface::MSG_ERROR:
71         strCaption += _("Error");
72         break;
73     case CClientUIInterface::MSG_WARNING:
74         strCaption += _("Warning");
75         break;
76     case CClientUIInterface::MSG_INFORMATION:
77         strCaption += _("Information");
78         break;
79     default:
80         strCaption += caption; // Use supplied caption (can be empty)
81     }
82
83     boost::strict_lock_ptr<std::list<std::string>> u = messageBox.synchronize();
84     u->push_back(strCaption + ": " + message);
85     if (u->size() > 5) {
86         u->pop_back();
87     }
88 }
89
90 static void metrics_InitMessage(const std::string& message)
91 {
92     *initMessage = message;
93 }
94
95 void ConnectMetricsScreen()
96 {
97     uiInterface.ThreadSafeMessageBox.disconnect_all_slots();
98     uiInterface.ThreadSafeMessageBox.connect(metrics_ThreadSafeMessageBox);
99     uiInterface.InitMessage.disconnect_all_slots();
100     uiInterface.InitMessage.connect(metrics_InitMessage);
101 }
102
103 int printNetworkStats()
104 {
105     LOCK2(cs_main, cs_vNodes);
106
107     std::cout << "           " << _("Block height") << " | " << chainActive.Height() << std::endl;
108     std::cout << "  " << _("Network solution rate") << " | " << GetNetworkHashPS(120, -1) << " Sol/s" << std::endl;
109     std::cout << "            " << _("Connections") << " | " << vNodes.size() << std::endl;
110     std::cout << std::endl;
111
112     return 4;
113 }
114
115 int printMiningStatus(bool mining)
116 {
117     // Number of lines that are always displayed
118     int lines = 1;
119
120     if (mining) {
121         int nThreads = GetArg("-genproclimit", 1);
122         if (nThreads < 0) {
123             // In regtest threads defaults to 1
124             if (Params().DefaultMinerThreads())
125                 nThreads = Params().DefaultMinerThreads();
126             else
127                 nThreads = boost::thread::hardware_concurrency();
128         }
129         std::cout << strprintf(_("You are mining with the %s solver on %d threads."),
130                                GetArg("-equihashsolver", "default"), nThreads) << std::endl;
131         lines++;
132     } else {
133         std::cout << _("You are currently not mining.") << std::endl;
134         std::cout << _("To enable mining, add 'gen=1' to your zcash.conf and restart.") << std::endl;
135         lines += 2;
136     }
137     std::cout << std::endl;
138
139     return lines;
140 }
141
142 int printMetrics(size_t cols, bool mining)
143 {
144     // Number of lines that are always displayed
145     int lines = 3;
146
147     // Calculate uptime
148     int64_t uptime = GetUptime();
149     int days = uptime / (24 * 60 * 60);
150     int hours = (uptime - (days * 24 * 60 * 60)) / (60 * 60);
151     int minutes = (uptime - (((days * 24) + hours) * 60 * 60)) / 60;
152     int seconds = uptime - (((((days * 24) + hours) * 60) + minutes) * 60);
153
154     // Display uptime
155     std::string duration;
156     if (days > 0) {
157         duration = strprintf(_("%d days, %d hours, %d minutes, %d seconds"), days, hours, minutes, seconds);
158     } else if (hours > 0) {
159         duration = strprintf(_("%d hours, %d minutes, %d seconds"), hours, minutes, seconds);
160     } else if (minutes > 0) {
161         duration = strprintf(_("%d minutes, %d seconds"), minutes, seconds);
162     } else {
163         duration = strprintf(_("%d seconds"), seconds);
164     }
165     std::string strDuration = strprintf(_("Since starting this node %s ago:"), duration);
166     std::cout << strDuration << std::endl;
167     lines += (strDuration.size() / cols);
168
169     int validatedCount = transactionsValidated.get();
170     if (validatedCount > 1) {
171       std::cout << "- " << strprintf(_("You have validated %d transactions!"), validatedCount) << std::endl;
172     } else if (validatedCount == 1) {
173       std::cout << "- " << _("You have validated a transaction!") << std::endl;
174     } else {
175       std::cout << "- " << _("You have validated no transactions.") << std::endl;
176     }
177
178     if (mining && loaded) {
179         double solps = GetLocalSolPS_INTERNAL(uptime);
180         std::string strSolps = strprintf("%.4f Sol/s", solps);
181         std::cout << "- " << strprintf(_("You have contributed %s on average to the network solution rate."), strSolps) << std::endl;
182         std::cout << "- " << strprintf(_("You have completed %d Equihash solver runs."), ehSolverRuns.get()) << std::endl;
183         lines += 2;
184
185         int mined = 0;
186         int orphaned = 0;
187         CAmount immature {0};
188         CAmount mature {0};
189         {
190             LOCK2(cs_main, cs_metrics);
191             boost::strict_lock_ptr<std::list<uint256>> u = trackedBlocks.synchronize();
192             auto consensusParams = Params().GetConsensus();
193             auto tipHeight = chainActive.Height();
194
195             // Update orphans and calculate subsidies
196             std::list<uint256>::iterator it = u->begin();
197             while (it != u->end()) {
198                 auto hash = *it;
199                 if (mapBlockIndex.count(hash) > 0 &&
200                         chainActive.Contains(mapBlockIndex[hash])) {
201                     int height = mapBlockIndex[hash]->nHeight;
202                     CAmount subsidy = GetBlockSubsidy(height, consensusParams);
203                     if ((height > 0) && (height <= consensusParams.GetLastFoundersRewardBlockHeight())) {
204                         subsidy -= subsidy/5;
205                     }
206                     if (std::max(0, COINBASE_MATURITY - (tipHeight - height)) > 0) {
207                         immature += subsidy;
208                     } else {
209                         mature += subsidy;
210                     }
211                     it++;
212                 } else {
213                     it = u->erase(it);
214                 }
215             }
216
217             mined = minedBlocks.get();
218             orphaned = mined - u->size();
219         }
220
221         if (mined > 0) {
222             std::string units = Params().CurrencyUnits();
223             std::cout << "- " << strprintf(_("You have mined %d blocks!"), mined) << std::endl;
224             std::cout << "  "
225                       << strprintf(_("Orphaned: %d blocks, Immature: %u %s, Mature: %u %s"),
226                                      orphaned,
227                                      FormatMoney(immature), units,
228                                      FormatMoney(mature), units)
229                       << std::endl;
230             lines += 2;
231         }
232     }
233     std::cout << std::endl;
234
235     return lines;
236 }
237
238 int printMessageBox(size_t cols)
239 {
240     boost::strict_lock_ptr<std::list<std::string>> u = messageBox.synchronize();
241
242     if (u->size() == 0) {
243         return 0;
244     }
245
246     int lines = 2 + u->size();
247     std::cout << _("Messages:") << std::endl;
248     for (auto it = u->cbegin(); it != u->cend(); ++it) {
249         std::cout << *it << std::endl;
250         // Handle wrapped lines
251         lines += (it->size() / cols);
252     }
253     std::cout << std::endl;
254     return lines;
255 }
256
257 int printInitMessage()
258 {
259     if (loaded) {
260         return 0;
261     }
262
263     std::string msg = *initMessage;
264     std::cout << _("Init message:") << " " << msg << std::endl;
265     std::cout << std::endl;
266
267     if (msg == _("Done loading")) {
268         loaded = true;
269     }
270
271     return 2;
272 }
273
274 void ThreadShowMetricsScreen()
275 {
276     // Make this thread recognisable as the metrics screen thread
277     RenameThread("zcash-metrics-screen");
278
279     // Determine whether we should render a persistent UI or rolling metrics
280     bool isTTY = isatty(STDOUT_FILENO);
281     bool isScreen = GetBoolArg("-metricsui", isTTY);
282     int64_t nRefresh = GetArg("-metricsrefreshtime", isTTY ? 1 : 600);
283
284     if (isScreen) {
285         // Clear screen
286         std::cout << "\e[2J";
287
288         // Print art
289         std::cout << METRICS_ART << std::endl;
290         std::cout << std::endl;
291
292         // Thank you text
293         std::cout << _("Thank you for running a Zcash node!") << std::endl;
294         std::cout << _("You're helping to strengthen the network and contributing to a social good :)") << std::endl;
295         std::cout << std::endl;
296     }
297
298     while (true) {
299         // Number of lines that are always displayed
300         int lines = 1;
301         int cols = 80;
302
303         // Get current window size
304         if (isTTY) {
305             struct winsize w;
306             w.ws_col = 0;
307             if (ioctl(STDOUT_FILENO, TIOCGWINSZ, &w) != -1 && w.ws_col != 0) {
308                 cols = w.ws_col;
309             }
310         }
311
312         if (isScreen) {
313             // Erase below current position
314             std::cout << "\e[J";
315         }
316
317         // Miner status
318         bool mining = GetBoolArg("-gen", false);
319
320         if (loaded) {
321             lines += printNetworkStats();
322         }
323         lines += printMiningStatus(mining);
324         lines += printMetrics(cols, mining);
325         lines += printMessageBox(cols);
326         lines += printInitMessage();
327
328         if (isScreen) {
329             // Explain how to exit
330             std::cout << "[" << _("Press Ctrl+C to exit") << "] [" << _("Set 'showmetrics=0' to hide") << "]" << std::endl;
331         } else {
332             // Print delineator
333             std::cout << "----------------------------------------" << std::endl;
334         }
335
336         int64_t nWaitEnd = GetTime() + nRefresh;
337         while (GetTime() < nWaitEnd) {
338             boost::this_thread::interruption_point();
339             MilliSleep(200);
340         }
341
342         if (isScreen) {
343             // Return to the top of the updating section
344             std::cout << "\e[" << lines << "A";
345         }
346     }
347 }
This page took 0.042553 seconds and 4 git commands to generate.