Get a work item once per second for all getwork and GBT pools to test they're still alive and to maintain a current GBT template.
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
diff --git a/cgminer.c b/cgminer.c
index af2936f..cdc1bcd 100644
--- a/cgminer.c
+++ b/cgminer.c
@@ -1614,6 +1614,7 @@ static bool work_decode(struct pool *pool, struct work *work, json_t *val)
json_t *res_val = json_object_get(val, "result");
bool ret = false;
+ gettimeofday(&pool->tv_lastwork, NULL);
if (!res_val || json_is_null(res_val)) {
applog(LOG_ERR, "JSON Failed to decode result");
goto out;
@@ -1622,7 +1623,6 @@ static bool work_decode(struct pool *pool, struct work *work, json_t *val)
if (pool->has_gbt) {
if (unlikely(!gbt_decode(pool, res_val)))
goto out;
- gettimeofday(&pool->tv_template, NULL);
work->gbt = true;
ret = true;
goto out;
@@ -3319,8 +3319,6 @@ static struct pool *priority_pool(int choice)
return ret;
}
-static bool pool_active(struct pool *pool, bool pinging);
-
void switch_pools(struct pool *selected)
{
struct pool *pool, *last_pool;
@@ -3389,13 +3387,8 @@ void switch_pools(struct pool *selected)
if (opt_fail_only)
pool_tset(pool, &pool->lagging);
- if (pool != last_pool) {
+ if (pool != last_pool)
applog(LOG_WARNING, "Switching to %s", pool->rpc_url);
- /* Get a fresh block template since we may not have an up to
- * date one */
- if (pool->has_gbt)
- pool_active(pool, true);
- }
mutex_lock(&lp_lock);
pthread_cond_broadcast(&lp_cond);
@@ -5852,6 +5845,58 @@ static void reap_curl(struct pool *pool)
applog(LOG_DEBUG, "Reaped %d curl%s from pool %d", reaped, reaped > 1 ? "s" : "", pool->pool_no);
}
+static bool pool_getswork(struct pool *pool)
+{
+ struct timeval tv_getwork, tv_getwork_reply;
+ bool ret = false;
+ int rolltime;
+ json_t *val;
+ CURL *curl;
+
+ curl = curl_easy_init();
+ if (unlikely(!curl))
+ quit (1, "CURL initialisation failed in pool_getswork");
+
+ gettimeofday(&tv_getwork, NULL);
+ val = json_rpc_call(curl, pool->rpc_url, pool->rpc_userpass,
+ pool->rpc_req, true, false, &rolltime, pool, false);
+ gettimeofday(&tv_getwork_reply, NULL);
+
+ if (val) {
+ struct work *work = make_work();
+ bool rc = work_decode(pool, work, val);
+
+ if (rc) {
+ applog(LOG_DEBUG, "Successfully retrieved and deciphered work from pool %u %s",
+ pool->pool_no, pool->rpc_url);
+ work->pool = pool;
+ work->rolltime = rolltime;
+ memcpy(&(work->tv_getwork), &tv_getwork, sizeof(struct timeval));
+ memcpy(&(work->tv_getwork_reply), &tv_getwork_reply, sizeof(struct timeval));
+ work->getwork_mode = GETWORK_MODE_TESTPOOL;
+ calc_diff(work, 0);
+ applog(LOG_DEBUG, "Pushing pool_getswork work for pool %d", pool->pool_no);
+
+ tq_push(thr_info[stage_thr_id].q, work);
+ total_getworks++;
+ pool->getwork_requested++;
+ ret = true;
+ gettimeofday(&pool->tv_idle, NULL);
+ ret = true;
+ } else {
+ applog(LOG_DEBUG, "Successfully retrieved but FAILED to decipher work from pool %u %s",
+ pool->pool_no, pool->rpc_url);
+ free_work(work);
+ }
+ json_decref(val);
+ } else {
+ applog(LOG_DEBUG, "FAILED to retrieve pool_getswork work from pool %u %s",
+ pool->pool_no, pool->rpc_url);
+ }
+ curl_easy_cleanup(curl);
+ return ret;
+}
+
static void *watchpool_thread(void __maybe_unused *userdata)
{
int intervals = 0;
@@ -5875,13 +5920,13 @@ static void *watchpool_thread(void __maybe_unused *userdata)
if (pool->enabled == POOL_DISABLED || pool->has_stratum)
continue;
- /* Apart from longpollid comms, we retrieve a fresh
- * template if more than 30 seconds has elapsed since
- * the last one to keep the data current and as a test
- * for when the pool dies. */
- if (!pool->idle && pool->has_gbt && pool == current_pool() &&
- now.tv_sec - pool->tv_template.tv_sec > 60) {
- if (!pool_active(pool, true))
+ /* Stratum works off pushing work, but GBT and getwork
+ * off requests so even for the non current pool, get
+ * new work once per minute to ensure the pool is still
+ * alive and to maintain the current block template for
+ * GBT pools in case we switch to them. */
+ if (!pool->idle && now.tv_sec - pool->tv_lastwork.tv_sec > 60) {
+ if (!pool_getswork(pool))
pool_died(pool);
}
diff --git a/miner.h b/miner.h
index 827fa4f..698691d 100644
--- a/miner.h
+++ b/miner.h
@@ -923,7 +923,7 @@ struct pool {
unsigned char *txn_hashes;
int gbt_txns;
int coinbase_len;
- struct timeval tv_template;
+ struct timeval tv_lastwork;
};
#define GETWORK_MODE_TESTPOOL 'T'