summaryrefslogtreecommitdiffstats
path: root/executor.h
blob: d900b418aac4891d0a5de4f4f21a734e60ebd91d (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
#pragma once
#include "thdq.hpp"
#include "msgstruct.h"
#include <atomic>
#include <array>
#include <list>
#include <future>

class jpsock;
class minethd;
class telemetry;

class executor
{
public:
	static executor* inst()
	{
		if (oInst == nullptr) oInst = new executor;
		return oInst;
	};

	void ex_start() { my_thd = new std::thread(&executor::ex_main, this); }
	void ex_main();

	void get_http_report(ex_event_name ev_id, std::string& data);

	inline void push_event(ex_event&& ev) { oEventQ.push(std::move(ev)); }
	void push_timed_event(ex_event&& ev, size_t sec);

	constexpr static size_t invalid_pool_id = 0;
	constexpr static size_t dev_pool_id = 1;
	constexpr static size_t usr_pool_id = 2;

private:
	struct timed_event
	{
		ex_event event;
		size_t ticks_left;

		timed_event(ex_event&& ev, size_t ticks) : event(std::move(ev)), ticks_left(ticks) {}
	};

	// In miliseconds, has to divide a second (1000ms) into an integer number
	constexpr static size_t iTickTime = 500;

	// Dev donation time period in seconds. 100 minutes by default.
	// We will divide up this period according to the config setting
	constexpr static size_t iDevDonatePeriod = 100 * 60;

	std::list<timed_event> lTimedEvents;
	std::mutex timed_event_mutex;
	thdq<ex_event> oEventQ;

	telemetry* telem;
	std::vector<minethd*>* pvThreads;
	std::thread* my_thd;

	size_t current_pool_id;

	jpsock* usr_pool;
	jpsock* dev_pool;

	jpsock* pick_pool_by_id(size_t pool_id);

	bool is_dev_time;

	executor();
	static executor* oInst;

	void ex_clock_thd();
	void pool_connect(jpsock* pool);

	void hashrate_report(std::string& out);
	void result_report(std::string& out);
	void connection_report(std::string& out);

	void http_hashrate_report(std::string& out);
	void http_result_report(std::string& out);
	void http_connection_report(std::string& out);

	void http_report(ex_event_name ev);
	void print_report(ex_event_name ev);

	std::string* pHttpString = nullptr;
	std::promise<void> httpReady;
	std::mutex httpMutex;

	size_t iReconnectAttempts = 0;

	struct sck_error_log
	{
		std::chrono::system_clock::time_point time;
		std::string msg;

		sck_error_log(std::string&& err) : msg(std::move(err))
		{
			time = std::chrono::system_clock::now();
		}
	};
	std::vector<sck_error_log> vSocketLog;

	// Element zero is always the success element.
	// Keep in mind that this is a tally and not a log like above
	struct result_tally
	{
		std::chrono::system_clock::time_point time;
		std::string msg;
		size_t count;

		result_tally() : msg("[OK]"), count(0)
		{
			time = std::chrono::system_clock::now();
		}

		result_tally(std::string&& err) : msg(std::move(err)), count(1)
		{
			time = std::chrono::system_clock::now();
		}

		void increment()
		{
			count++;
			time = std::chrono::system_clock::now();
		}

		bool compare(std::string& err)
		{
			if(msg == err)
			{
				increment();
				return true;
			}
			else
				return false;
		}
	};
	std::vector<result_tally> vMineResults;

	//More result statistics
	std::array<size_t, 10> iTopDiff { { } }; //Initialize to zero

	std::chrono::system_clock::time_point tPoolConnTime;
	size_t iPoolHashes = 0;
	uint64_t iPoolDiff = 0;

	// Set it to 16 bit so that we can just let it grow
	// Maximum realistic growth rate - 5MB / month
	std::vector<uint16_t> iPoolCallTimes;

	//Those stats are reset if we disconnect
	inline void reset_stats()
	{
		iPoolCallTimes.clear();
		tPoolConnTime = std::chrono::system_clock::now();
		iPoolHashes = 0;
		iPoolDiff = 0;
	}

	double fHighestHps = 0.0;

	void log_socket_error(std::string&& sError);
	void log_result_error(std::string&& sError);
	void log_result_ok(uint64_t iActualDiff);

	void sched_reconnect();

	void on_sock_ready(size_t pool_id);
	void on_sock_error(size_t pool_id, std::string&& sError);
	void on_pool_have_job(size_t pool_id, pool_job& oPoolJob);
	void on_miner_result(size_t pool_id, job_result& oResult);
	void on_reconnect(size_t pool_id);
	void on_switch_pool(size_t pool_id);

	inline size_t sec_to_ticks(size_t sec) { return sec * (1000 / iTickTime); }
};

OpenPOWER on IntegriCloud