From b7944bd27a7c9e06fde447846a52fea099be3352 Mon Sep 17 00:00:00 2001 From: kanoi Date: Sat, 12 Dec 2015 22:17:35 +1100 Subject: [PATCH 01/26] ckdb - marks action=pps to recalc the ram pps values for a shift --- src/ckdb.h | 2 +- src/ckdb_cmd.c | 35 ++++++++++++++++++++++++++++++++++- 2 files changed, 35 insertions(+), 2 deletions(-) diff --git a/src/ckdb.h b/src/ckdb.h index 2e2f1601..f6b9396c 100644 --- a/src/ckdb.h +++ b/src/ckdb.h @@ -55,7 +55,7 @@ #define DB_VLOCK "1" #define DB_VERSION "1.0.4" -#define CKDB_VERSION DB_VERSION"-1.610" +#define CKDB_VERSION DB_VERSION"-1.611" #define WHERE_FFL " - from %s %s() line %d" #define WHERE_FFL_HERE __FILE__, __func__, __LINE__ diff --git a/src/ckdb_cmd.c b/src/ckdb_cmd.c index bab3f32a..a23ad1d1 100644 --- a/src/ckdb_cmd.c +++ b/src/ckdb_cmd.c @@ -5796,7 +5796,7 @@ static char *cmd_marks(PGconn *conn, char *cmd, char *id, char description[TXT_BIG+1] = { '\0' }; char extra[TXT_BIG+1] = { '\0' }; char status[TXT_FLAG+1] = { MARK_READY, '\0' }; - bool ok; + bool ok = false, pps; LOGDEBUG("%s(): cmd '%s'", __func__, cmd); @@ -6237,6 +6237,39 @@ static char *cmd_marks(PGconn *conn, char *cmd, char *id, old ? "On" : "Off", markersummary_auto ? "On" : "Off"); ok = true; + } else if (strcasecmp(action, "pps") == 0) { + /* Recalculate a shift's rewards/rewarded + * Require markerid */ + i_markerid = require_name(trf_root, "markerid", 1, + (char *)intpatt, reply, siz); + if (!i_markerid) + return strdup(reply); + TXT_TO_BIGINT("markerid", transfer_data(i_markerid), markerid); + + K_RLOCK(workmarkers_free); + wm_item = find_workmarkerid(markerid, false, MARKER_PROCESSED); + K_RUNLOCK(workmarkers_free); + if (!wm_item) { + snprintf(reply, siz, "no markerid %"PRId64, markerid); + return strdup(reply); + } + DATA_WORKMARKERS(workmarkers, wm_item); + pps = shift_rewards(wm_item); + if (pps) { + snprintf(msg, sizeof(msg), + "shift '%s' markerid %"PRId64" rewards %d " + "rewarded %.3e pps %.3e", + workmarkers->description, + workmarkers->markerid, workmarkers->rewards, + workmarkers->rewarded, workmarkers->pps_value); + } else { + snprintf(msg, sizeof(msg), + "shift '%s' markerid %"PRId64" no rewards yet" + " pps %.3e", + workmarkers->description, + workmarkers->markerid, workmarkers->pps_value); + } + ok = true; } else { snprintf(reply, siz, "unknown action '%s'", action); LOGERR("%s.%s", id, reply); From c7ae4765382e1b5df7a36765a7c2ef7f3ae7c85d Mon Sep 17 00:00:00 2001 From: kanoi Date: Sat, 12 Dec 2015 22:45:54 +1100 Subject: [PATCH 02/26] ckdb - fix some more locking anomalies --- src/ckdb.c | 11 +++++------ src/ckdb.h | 2 +- src/ckdb_cmd.c | 4 ++-- src/klist.h | 2 +- 4 files changed, 9 insertions(+), 10 deletions(-) diff --git a/src/ckdb.c b/src/ckdb.c index 696c56f3..e0bfaa91 100644 --- a/src/ckdb.c +++ b/src/ckdb.c @@ -1746,7 +1746,7 @@ static void trans_process(SEQSET *seqset, tv_t *now, K_STORE *store) seqtrans->seq = seq; seqtrans->seqnum = u; memcpy(&(seqtrans->entry), seqentry, sizeof(SEQENTRY)); - k_add_head(store, st_item); + k_add_head_nolock(store, st_item); } u++; seqentry++; @@ -1772,7 +1772,7 @@ static void trans_process(SEQSET *seqset, tv_t *now, K_STORE *store) seqtrans->seq = seq; seqtrans->seqnum = u; memcpy(&(seqtrans->entry), seqentry, sizeof(SEQENTRY)); - k_add_head(store, st_item); + k_add_head_nolock(store, st_item); } u++; seqentry++; @@ -2143,7 +2143,7 @@ gotseqset: sizeof(SEQENTRY)); if (!lost) lost = k_new_store(seqtrans_free); - k_add_tail(lost, st_item); + k_add_tail_nolock(lost, st_item); seqdata->lost++; seqset->lost++; if (ENTRYISTRANS(u_entry)) { @@ -2173,7 +2173,7 @@ gotseqset: seqdata->reload_lost = k_new_store(seqtrans_free); seqdata_reload_lost = true; } - k_add_tail(seqdata->reload_lost, stl_item); + k_add_tail_nolock(seqdata->reload_lost, stl_item); } } else { // (u-size) wasn't missing @@ -2254,8 +2254,7 @@ gotseqset: } if (st_item) { // recovered a lost entry - k_unlink_item(seqtrans_free, st_item); - // N.B. lock inside lock + k_unlink_item_nolock(seqdata->reload_lost, st_item); K_WLOCK(seqtrans_free); k_add_head(seqtrans_free, st_item); K_WUNLOCK(seqtrans_free); diff --git a/src/ckdb.h b/src/ckdb.h index f6b9396c..b626e048 100644 --- a/src/ckdb.h +++ b/src/ckdb.h @@ -55,7 +55,7 @@ #define DB_VLOCK "1" #define DB_VERSION "1.0.4" -#define CKDB_VERSION DB_VERSION"-1.611" +#define CKDB_VERSION DB_VERSION"-1.612" #define WHERE_FFL " - from %s %s() line %d" #define WHERE_FFL_HERE __FILE__, __func__, __LINE__ diff --git a/src/ckdb_cmd.c b/src/ckdb_cmd.c index a23ad1d1..c9d9f660 100644 --- a/src/ckdb_cmd.c +++ b/src/ckdb_cmd.c @@ -3636,9 +3636,9 @@ static char *cmd_setatts(PGconn *conn, char *cmd, char *id, } } if (!ua_item) { - K_RLOCK(useratts_free); + K_WLOCK(useratts_free); ua_item = k_unlink_head(useratts_free); - K_RUNLOCK(useratts_free); + K_WUNLOCK(useratts_free); DATA_USERATTS(useratts, ua_item); bzero(useratts, sizeof(*useratts)); useratts->userid = users->userid; diff --git a/src/klist.h b/src/klist.h index 9e5888a7..d872f034 100644 --- a/src/klist.h +++ b/src/klist.h @@ -586,7 +586,7 @@ extern void _k_insert_after(K_LIST *list, K_ITEM *item, K_ITEM *after, LOCK_MAYB //#define k_insert_after_nolock(_list, _item, _after) _k_insert_after(_list, _item, _after, false, KLIST_FFL_HERE) extern void _k_unlink_item(K_LIST *list, K_ITEM *item, LOCK_MAYBE bool chklock, KLIST_FFL_ARGS); #define k_unlink_item(_list, _item) _k_unlink_item(_list, _item, true, KLIST_FFL_HERE) -//#define k_unlink_item_nolock(_list, _item) _k_unlink_item(_list, _item, false, KLIST_FFL_HERE) +#define k_unlink_item_nolock(_list, _item) _k_unlink_item(_list, _item, false, KLIST_FFL_HERE) extern void _k_list_transfer_to_head(K_LIST *from, K_LIST *to, LOCK_MAYBE bool chklock, KLIST_FFL_ARGS); #define k_list_transfer_to_head(_from, _to) _k_list_transfer_to_head(_from, _to, true, KLIST_FFL_HERE) //#define k_list_transfer_to_head_nolock(_from, _to) _k_list_transfer_to_head(_from, _to, false, KLIST_FFL_HERE) From cc9c70373ee54a1faa981a6676d28c59245ddff9 Mon Sep 17 00:00:00 2001 From: Con Kolivas Date: Mon, 14 Dec 2015 10:05:00 +1100 Subject: [PATCH 03/26] Send diff first when when sending the first stratum template after subscribing --- src/stratifier.c | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/src/stratifier.c b/src/stratifier.c index 25f654ab..bda12d4c 100644 --- a/src/stratifier.c +++ b/src/stratifier.c @@ -3534,6 +3534,13 @@ static void suggest_diff(stratum_instance_t *client, const char *method, const j stratum_send_diff(sdata, client); } +/* Send diff first when sending the first stratum template after subscribing */ +static void init_client(sdata_t *sdata, const stratum_instance_t *client, const int64_t client_id) +{ + stratum_send_diff(sdata, client); + stratum_send_update(sdata, client_id, true); +} + /* Enter with client holding ref count */ static void parse_method(sdata_t *sdata, stratum_instance_t *client, const int64_t client_id, json_t *id_val, json_t *method_val, json_t *params_val) @@ -3572,7 +3579,7 @@ static void parse_method(sdata_t *sdata, stratum_instance_t *client, const int64 json_object_set_new_nocheck(val, "error", json_null()); stratum_add_send(sdata, val, client_id); if (likely(client->subscribed)) - update_client(sdata, client, client_id); + init_client(sdata, client, client_id); return; } From 5a3183cf04bc2b5ebb575fb2aab8308f10c85c3f Mon Sep 17 00:00:00 2001 From: Con Kolivas Date: Mon, 14 Dec 2015 10:21:08 +1100 Subject: [PATCH 04/26] Fix timeout in read_socket_line inappropriately running out --- src/ckpool.c | 1 + 1 file changed, 1 insertion(+) diff --git a/src/ckpool.c b/src/ckpool.c index 4b5e95f8..6e2f92d1 100644 --- a/src/ckpool.c +++ b/src/ckpool.c @@ -539,6 +539,7 @@ rewait: } tv_time(&now); diff = tvdiff(&now, &start); + copy_tv(&start, &now); *timeout -= diff; while (42) { char readbuf[PAGESIZE] = {}; From 977d43e7a2a6bc3739d634a3de7247668e2db93e Mon Sep 17 00:00:00 2001 From: kanoi Date: Mon, 14 Dec 2015 12:41:36 +1100 Subject: [PATCH 05/26] php - include full worker invalid details (hidden by default) --- pool/page_allwork.php | 2 +- pool/page_workers.php | 39 ++++++++++++++++++++++++++++++++++++--- 2 files changed, 37 insertions(+), 4 deletions(-) diff --git a/pool/page_allwork.php b/pool/page_allwork.php index e289e8ac..bb1fb3a6 100644 --- a/pool/page_allwork.php +++ b/pool/page_allwork.php @@ -6,7 +6,7 @@ function doallwork($data, $user) { $pg = '

All Workers

'; - $pg .= "\n"; + $pg .= worktable(); $totshare = 0; $totdiff = 0; diff --git a/pool/page_workers.php b/pool/page_workers.php index 78173010..b7b50c27 100644 --- a/pool/page_workers.php +++ b/pool/page_workers.php @@ -1,5 +1,16 @@ \n"; + $pg .= "function wkdet(n,i){var t=document.getElementById(n);if(i&&t){var b,cs,j,c,a;b=i.checked;cs=t.getElementsByTagName('td');for(j=0;c=cs[j];j++) +{a=c.getAttribute('data-hid');if(a){if(b){c.className=a}else{c.className='hid'}}}}}"; + $pg .= "\n"; + $pg .= "Show Details for Invalids:
"; + $pg .= "
\n"; + return $pg; +} +# function worktitle($data, $user) { addSort(); @@ -13,8 +24,12 @@ function worktitle($data, $user) $pg .= ""; $pg .= ''; $pg .= ""; - $pg .= ''; - $pg .= ""; + $pg .= ""; + $pg .= ""; + $pg .= ""; + $pg .= ""; + $pg .= ''; + $pg .= ""; $pg .= "\n"; return $pg; } @@ -66,6 +81,14 @@ function workuser($data, $user, &$offset, &$totshare, &$totdiff, 'w_shareacc' => $ans['w_shareacc:'.$i], 'w_diffacc' => $ans['w_diffacc:'.$i], 'w_diffinv' => $ans['w_diffinv:'.$i], + 'w_diffsta' => $ans['w_diffsta:'.$i], + 'w_diffdup' => $ans['w_diffdup:'.$i], + 'w_diffhi' => $ans['w_diffhi:'.$i], + 'w_diffrej' => $ans['w_diffrej:'.$i], + 'w_sharesta' => $ans['w_sharesta:'.$i], + 'w_sharedup' => $ans['w_sharedup:'.$i], + 'w_sharehi' => $ans['w_sharehi:'.$i], + 'w_sharerej' => $ans['w_sharerej:'.$i], 'w_lastdiff' => $ans['w_lastdiff:'.$i], 'w_active_diffacc' => $ans['w_active_diffacc:'.$i], 'w_active_start' => $ans['w_active_start:'.$i], @@ -143,6 +166,15 @@ function workuser($data, $user, &$offset, &$totshare, &$totdiff, $pg .= ""; + foreach(array('sta','dup','hi','rej') as $fld) + { + $shr = number_format($all[$i]['w_share'.$fld]); + $dif = $all[$i]['w_diff'.$fld]; + $ddif = number_format($dif); + $sdif = number_format($dif,0,'',''); + $pg .= ""; + } + if ($blockacc <= 0) $blkpct = ' '; else @@ -198,6 +230,7 @@ function worktotal($offset, $totshare, $totdiff, $totshrate, $totinvalid, $blkpct = ' '; else $blkpct = number_format(100.0 * $totdiff / $blockacc, 3) . '%'; + $pg .= ""; $pg .= ""; $pg .= "\n"; return $pg; @@ -207,7 +240,7 @@ function doworker($data, $user) { $title = ''; - $pg = "
<$r id=srtshrate data-sf=r5>:Share Rate«Elapsed<$r id=srtinv data-sf=r7>:InvalidBlock %<$r id=srtrate data-sf=r9>:Hash Rate<$r id=srtstale data-sf=r8>:Stale<$r id=srtdup data-sf=r9>:Duplicate<$r id=srthi data-sf=r10>:High<$r id=srtreject data-sf=r11>:RejectBlock %<$r id=srtrate data-sf=r13>:Hash Rate
$rej%$ddif/$shr $blkpct$totrate
\n"; + $pg = worktable(); $totshare = 0; $totdiff = 0; From 853bed8281458135daad303c14a6c40ef4db3cdc Mon Sep 17 00:00:00 2001 From: Con Kolivas Date: Mon, 14 Dec 2015 12:59:49 +1100 Subject: [PATCH 06/26] Serialise all json_rpc_calls and responses --- src/ckpool.c | 3 +++ src/ckpool.h | 2 ++ src/generator.c | 2 ++ 3 files changed, 7 insertions(+) diff --git a/src/ckpool.c b/src/ckpool.c index 6e2f92d1..e74aa0ca 100644 --- a/src/ckpool.c +++ b/src/ckpool.c @@ -745,6 +745,8 @@ json_t *json_rpc_call(connsock_t *cs, const char *rpc_req) double elapsed; int len, ret; + /* Serialise all calls in case we use cs from multiple threads */ + cksem_wait(&cs->sem); if (unlikely(cs->fd < 0)) { LOGWARNING("FD %d invalid in %s", cs->fd, __func__); goto out; @@ -839,6 +841,7 @@ out_empty: out: free(http_req); dealloc(cs->buf); + cksem_post(&cs->sem); return val; } diff --git a/src/ckpool.h b/src/ckpool.h index 573ddc8f..6d0e7348 100644 --- a/src/ckpool.h +++ b/src/ckpool.h @@ -79,6 +79,8 @@ struct connsock { char *buf; int bufofs; int buflen; + /* Semaphore used to serialise request/responses */ + sem_t sem; }; typedef struct connsock connsock_t; diff --git a/src/generator.c b/src/generator.c index 27df2509..2e59816c 100644 --- a/src/generator.c +++ b/src/generator.c @@ -1698,6 +1698,8 @@ static int server_mode(ckpool_t *ckp, proc_instance_t *pi) si->auth = ckp->btcdauth[i]; si->pass = ckp->btcdpass[i]; si->notify = ckp->btcdnotify[i]; + cksem_init(&si->cs.sem); + cksem_post(&si->cs.sem); } ret = gen_loop(pi); From 3059afdf33bbfa4a9d2082c0acd2d66f317b8679 Mon Sep 17 00:00:00 2001 From: kanoi Date: Mon, 14 Dec 2015 14:15:16 +1100 Subject: [PATCH 07/26] ckdb - allow setting a history limit on markersummary with -M --- src/ckdb.c | 9 ++++++++- src/ckdb.h | 5 ++++- src/ckdb_dbio.c | 16 +++++++++++++--- 3 files changed, 25 insertions(+), 5 deletions(-) diff --git a/src/ckdb.c b/src/ckdb.c index e0bfaa91..299c177e 100644 --- a/src/ckdb.c +++ b/src/ckdb.c @@ -483,6 +483,9 @@ K_STORE *markersummary_store; K_TREE *markersummary_pool_root; K_STORE *markersummary_pool_store; +// The markerid load start for markersummary +char *mark_start = NULL; + // WORKMARKERS K_TREE *workmarkers_root; K_TREE *workmarkers_workinfoid_root; @@ -5639,6 +5642,7 @@ static struct option long_options[] = { { "loglevel", required_argument, 0, 'l' }, // marker = enable mark/workmarker/markersummary auto generation { "marker", no_argument, 0, 'm' }, + { "markstart", required_argument, 0, 'M' }, { "name", required_argument, 0, 'n' }, { "dbpass", required_argument, 0, 'p' }, { "btc-pass", required_argument, 0, 'P' }, @@ -5683,7 +5687,7 @@ int main(int argc, char **argv) memset(&ckp, 0, sizeof(ckp)); ckp.loglevel = LOG_NOTICE; - while ((c = getopt_long(argc, argv, "c:d:ghkl:mn:p:P:r:R:s:S:t:u:U:vw:yY:", long_options, &i)) != -1) { + while ((c = getopt_long(argc, argv, "c:d:ghkl:mM:n:p:P:r:R:s:S:t:u:U:vw:yY:", long_options, &i)) != -1) { switch(c) { case 'c': ckp.config = strdup(optarg); @@ -5742,6 +5746,9 @@ int main(int argc, char **argv) case 'm': markersummary_auto = true; break; + case 'M': + mark_start = strdup(optarg); + break; case 'n': ckp.name = strdup(optarg); break; diff --git a/src/ckdb.h b/src/ckdb.h index b626e048..16e33eb7 100644 --- a/src/ckdb.h +++ b/src/ckdb.h @@ -55,7 +55,7 @@ #define DB_VLOCK "1" #define DB_VERSION "1.0.4" -#define CKDB_VERSION DB_VERSION"-1.612" +#define CKDB_VERSION DB_VERSION"-1.620" #define WHERE_FFL " - from %s %s() line %d" #define WHERE_FFL_HERE __FILE__, __func__, __LINE__ @@ -1958,6 +1958,9 @@ extern K_STORE *markersummary_store; extern K_TREE *markersummary_pool_root; extern K_STORE *markersummary_pool_store; +// The markerid load start for markersummary +extern char *mark_start; + // WORKMARKERS typedef struct workmarkers { int64_t markerid; diff --git a/src/ckdb_dbio.c b/src/ckdb_dbio.c index 2aa6d8cf..5c481963 100644 --- a/src/ckdb_dbio.c +++ b/src/ckdb_dbio.c @@ -6766,9 +6766,10 @@ bool markersummary_fill(PGconn *conn) K_ITEM *item, *p_item; int n, t, i, p_n; MARKERSUMMARY *row, *p_row; + char *params[1]; char *field; char *sel; - int fields = 20; + int fields = 20, par = 0; bool ok = false; LOGDEBUG("%s(): select", __func__); @@ -6783,7 +6784,16 @@ bool markersummary_fill(PGconn *conn) "sharecount,errorcount,firstshare,lastshare,firstshareacc," "lastshareacc,lastdiffacc" MODIFYDATECONTROL - " from markersummary"; + " from markersummary where markerid>=$1"; + par = 0; + if (mark_start) + params[par++] = mark_start; + else + params[par++] = "0"; + PARCHK(par, params); + + LOGWARNING("%s(): loading from markerid>=%s", __func__, params[0]); + res = PQexec(conn, "Begin", CKPQ_READ); rescode = PQresultStatus(res); PQclear(res); @@ -6792,7 +6802,7 @@ bool markersummary_fill(PGconn *conn) return false; } - res = PQexec(conn, sel, CKPQ_READ); + res = PQexecParams(conn, sel, par, NULL, (const char **)params, NULL, NULL, 0, CKPQ_READ); rescode = PQresultStatus(res); PQclear(res); if (!PGOK(rescode)) { From 4aa73e29f88216f9d06eddfc3a5142a69984ca58 Mon Sep 17 00:00:00 2001 From: Con Kolivas Date: Mon, 14 Dec 2015 14:28:29 +1100 Subject: [PATCH 08/26] Use the cs->fd handle directy in case it gets invalidated while we're waiting for a socket line --- src/ckpool.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/ckpool.c b/src/ckpool.c index e74aa0ca..1f591a1f 100644 --- a/src/ckpool.c +++ b/src/ckpool.c @@ -500,13 +500,13 @@ void empty_buffer(connsock_t *cs) * of the buffer for use on the next receive. */ int read_socket_line(connsock_t *cs, float *timeout) { - int fd = cs->fd, ret = -1; char *eom = NULL; tv_t start, now; size_t buflen; + int ret = -1; float diff; - if (unlikely(fd < 0)) + if (unlikely(cs->fd < 0)) goto out; if (unlikely(!cs->buf)) @@ -527,7 +527,7 @@ rewait: ret = 0; goto out; } - ret = wait_read_select(fd, eom ? 0 : *timeout); + ret = wait_read_select(cs->fd, eom ? 0 : *timeout); if (ret < 1) { if (!ret) { if (eom) @@ -546,7 +546,7 @@ rewait: int backoff = 1; char *newbuf; - ret = recv(fd, readbuf, PAGESIZE - 4, MSG_DONTWAIT); + ret = recv(cs->fd, readbuf, PAGESIZE - 4, MSG_DONTWAIT); if (ret < 1) { /* No more to read or closed socket after valid message */ if (eom) From 516a708aadddff75c24082c7bec27f2a4a83b7a1 Mon Sep 17 00:00:00 2001 From: Con Kolivas Date: Mon, 14 Dec 2015 15:14:56 +1100 Subject: [PATCH 09/26] Fix bitcoind failover not working and keep connections open for faster switching in case of failure --- src/ckpool.c | 4 ++-- src/generator.c | 40 ++++++++++++++++------------------------ 2 files changed, 18 insertions(+), 26 deletions(-) diff --git a/src/ckpool.c b/src/ckpool.c index 1f591a1f..70269b46 100644 --- a/src/ckpool.c +++ b/src/ckpool.c @@ -831,10 +831,10 @@ json_t *json_rpc_call(connsock_t *cs, const char *rpc_req) out_empty: empty_socket(cs->fd); empty_buffer(cs); - if (!val) { + if (!val && cs->fd > 0) { /* Assume that a failed request means the socket will be closed * and reopen it */ - LOGWARNING("Reopening socket to %s:%s", cs->url, cs->port); + LOGWARNING("Attempting to reopen socket to %s:%s", cs->url, cs->port); Close(cs->fd); cs->fd = connect_socket(cs->url, cs->port); } diff --git a/src/generator.c b/src/generator.c index 2e59816c..5dc76b22 100644 --- a/src/generator.c +++ b/src/generator.c @@ -188,8 +188,10 @@ out: if (!ret) { /* Close and invalidate the file handle */ Close(cs->fd); - } else + } else { + LOGNOTICE("Server alive: %s:%s", cs->url, cs->port); keep_sockalive(cs->fd); + } return ret; } @@ -244,9 +246,8 @@ static void kill_server(server_instance_t *si) static int gen_loop(proc_instance_t *pi) { + server_instance_t *si = NULL, *old_si; int sockd = -1, ret = 0, selret; - server_instance_t *si = NULL; - bool reconnecting = false; unixsock_t *us = &pi->us; ckpool_t *ckp = pi->ckp; gdata_t *gdata = ckp->data; @@ -258,20 +259,17 @@ static int gen_loop(proc_instance_t *pi) reconnect: Close(sockd); - if (si) { - kill_server(si); - reconnecting = true; - } + old_si = si; si = live_server(ckp); if (!si) goto out; gbt = si->data; cs = &si->cs; - if (reconnecting) { + if (!old_si) + LOGWARNING("Connected to bitoind: %s:%s", cs->url, cs->port); + else if (si != old_si) LOGWARNING("Failed over to bitcoind: %s:%s", cs->url, cs->port); - reconnecting = false; - } retry: Close(sockd); @@ -1698,6 +1696,7 @@ static int server_mode(ckpool_t *ckp, proc_instance_t *pi) si->auth = ckp->btcdauth[i]; si->pass = ckp->btcdpass[i]; si->notify = ckp->btcdnotify[i]; + si->id = i; cksem_init(&si->cs.sem); cksem_post(&si->cs.sem); } @@ -1770,12 +1769,13 @@ static int proxy_mode(ckpool_t *ckp, proc_instance_t *pi) return ret; } -/* Tell the watchdog what the current server instance is and decide if we - * should check to see if the higher priority servers are alive and fallback */ +/* Tell the watchdog what the current server instance is, check which servers + * are alive, maintaining a connection with them and reconnect if a higher + * priority one is available. */ static void server_watchdog(ckpool_t *ckp, server_instance_t *cursi) { + server_instance_t *best = NULL; static time_t last_t = 0; - bool alive = false; time_t now_t; int i; @@ -1786,22 +1786,14 @@ static void server_watchdog(ckpool_t *ckp, server_instance_t *cursi) last_t = now_t; - /* Is this the highest priority server already? */ - if (!cursi->id) - return; - for (i = 0; i < ckp->btcds; i++) { server_instance_t *si = ckp->servers[i]; /* Have we reached the current server? */ - if (si == cursi) - return; - - alive = server_alive(ckp, si, true); - if (alive) - break; + if (server_alive(ckp, si, true) && !best) + best = si; } - if (alive) + if (best && (!cursi || cursi->id > best->id)) send_proc(ckp->generator, "reconnect"); } From 2365e4f14c466e4b831faf7c76371e104afecc30 Mon Sep 17 00:00:00 2001 From: kanoi Date: Mon, 14 Dec 2015 15:27:51 +1100 Subject: [PATCH 10/26] php - workers: abbreviate the headers for invalids to reduce the table width --- pool/page_workers.php | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/pool/page_workers.php b/pool/page_workers.php index b7b50c27..0f9c197b 100644 --- a/pool/page_workers.php +++ b/pool/page_workers.php @@ -25,9 +25,9 @@ function worktitle($data, $user) $pg .= ''; $pg .= ""; $pg .= ""; - $pg .= ""; - $pg .= ""; - $pg .= ""; + $pg .= ""; + $pg .= ""; + $pg .= ""; $pg .= ''; $pg .= ""; $pg .= "\n"; From c1f812effcd1d722727c563391bfe5c84c11e998 Mon Sep 17 00:00:00 2001 From: Con Kolivas Date: Mon, 14 Dec 2015 16:10:46 +1100 Subject: [PATCH 11/26] Fix extremely unlikely race on fd being accessed before it is set to -1 on closing --- src/libckpool.c | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/src/libckpool.c b/src/libckpool.c index 0c1b891e..4c315dfb 100644 --- a/src/libckpool.c +++ b/src/libckpool.c @@ -620,13 +620,17 @@ void block_socket(int fd) void _close(int *fd, const char *file, const char *func, const int line) { + int sockd; + if (*fd < 0) return; - LOGDEBUG("Closing file handle %d", *fd); - if (unlikely(close(*fd))) - LOGWARNING("Close of fd %d failed with errno %d:%s from %s %s:%d", - *fd, errno, strerror(errno), file, func, line); + sockd = *fd; + LOGDEBUG("Closing file handle %d", sockd); *fd = -1; + if (unlikely(close(sockd))) { + LOGWARNING("Close of fd %d failed with errno %d:%s from %s %s:%d", + sockd, errno, strerror(errno), file, func, line); + } } int bind_socket(char *url, char *port) From 8c474c1784ba9686790033034e1c87c0dbdd90d9 Mon Sep 17 00:00:00 2001 From: Con Kolivas Date: Mon, 14 Dec 2015 17:34:48 +1100 Subject: [PATCH 12/26] Support low diffs like those on testnet --- src/libckpool.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/libckpool.c b/src/libckpool.c index 4c315dfb..8e08253a 100644 --- a/src/libckpool.c +++ b/src/libckpool.c @@ -1982,6 +1982,8 @@ double diff_from_nbits(char *nbits) pow = nbits[0]; powdiff = (8 * (0x1d - 3)) - (8 * (pow - 3)); + if (powdiff < 8) + powdiff = 8; diff32 = be32toh(*((uint32_t *)nbits)) & 0x00FFFFFF; numerator = 0xFFFFULL << powdiff; return numerator / (double)diff32; From 3fc984d7fefb96b7fb2a7db79b31f733b2809220 Mon Sep 17 00:00:00 2001 From: Con Kolivas Date: Mon, 14 Dec 2015 17:58:38 +1100 Subject: [PATCH 13/26] Demote message --- src/stratifier.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/stratifier.c b/src/stratifier.c index bda12d4c..cabc654c 100644 --- a/src/stratifier.c +++ b/src/stratifier.c @@ -3513,7 +3513,7 @@ static void suggest_diff(stratum_instance_t *client, const char *method, const j int64_t sdiff; if (unlikely(!client_active(client))) { - LOGWARNING("Attempted to suggest diff on unauthorised client %"PRId64, client->id); + LOGNOTICE("Attempted to suggest diff on unauthorised client %"PRId64, client->id); return; } if (arr_val && json_is_integer(arr_val)) From 87da400f2515d20f11f305164f125f3cbf2b6c0a Mon Sep 17 00:00:00 2001 From: kanoi Date: Mon, 14 Dec 2015 18:13:56 +1100 Subject: [PATCH 14/26] php - add an optional function passed to the graphic script to allow custom effects --- pool/inc.php | 2 +- pool/page_luck.php | 2 +- pool/page_psperf.php | 2 +- pool/page_usperf.php | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/pool/inc.php b/pool/inc.php index cf29fbef..13f71101 100644 --- a/pool/inc.php +++ b/pool/inc.php @@ -29,7 +29,7 @@ function gfl(c){c['ctx'].fill()} function gst(c){c['ctx'].stroke()} function gfi(c){gle(c);gst(c)} function gbd(c){gbe(c,0,0);gln(c,1,0);gln(c,1,1);gln(c,0,1);gle(c);gfl(c);gst(c)} -function ggr(c,xs,ys,yt,xn,x0,x1,y0,y1,ar,nx,vx,vy,av,w,cols){gtso(c,xs,ys);gss(c,'black');glw(c,1.5);gbe(c,0,1);gln(c,0,0);gln(c,1,0);gst(c);glw(c,0.2);var hi=c['ctx'].measureText('M').width, wi=c['ctx'].measureText('0').width;for(var i=0;i<11;i++){var y=i/10.0;gbe(c,-0.01,y);gln(c,1,y);gst(c);var t=''+(((y1-y0)*i/10+y0).toFixed(2));gfz(c,0,y,-wi,0,t,'black','end')}gfz(c,gx0(c),0.55,wi,0,yt,'#0080ff','left');var m=Math.round(0.5+xn/20.0);for(var i=0;i=x0;i-=hrs){var xo=(i-x0)/(x1-x0);if(c['hrs'][c['hr']]<=48){n=dfmt(c,i)}else{n=dfmtm(c,i)}if(xo<=1 && c['tkey'] && ((l%hlv)==0)){gbe(c,xo,0);gln(c,xo,-0.02);gst(c);gfz(c,xo,0,0,-hi*tpos,n,'brown','center')}if(xo<=1 && c['tlines']){gbe(c,xo,0);gln(c,xo,1);gst(c)}l++}}glw(c,1);if(c['smooth']){for(var j=1;j0 && c['lin'+j]){gss(c,'red');var y=(av[j-1]-y0)/(y1-y0);gbe(c,0,y);gln(c,1,y);gst(c);var t=''+av[j-1].toFixed(2)+'av';gfz(c,1,y,1,0,t,cols[j-1],'left')}}if(c['tkey']){var i,dsp;i=c['hrs'][c['hr']];if(i < 24){dsp=''+i+'h'}else{dsp=''+(i/24)+'d'}gfz(c,1,0,c['xo']-c['pxe'],hi,dsp,'red','end');i=c['hln'][c['hl']];gfz(c,1,0,c['xo']-c['pxe'],hi*3,''+i,'red','end')}} +function ggr(c,xs,ys,yt,xn,x0,x1,y0,y1,ar,nx,vx,vy,av,w,cols,ex){gtso(c,xs,ys);if(ex){ex(0,c,xn,x0,x1,y0,y1,ar)}gss(c,'black');glw(c,1.5);gbe(c,0,1);gln(c,0,0);gln(c,1,0);gst(c);glw(c,0.2);var hi=c['ctx'].measureText('M').width, wi=c['ctx'].measureText('0').width;for(var i=0;i<11;i++){var y=i/10.0;gbe(c,-0.01,y);gln(c,1,y);gst(c);var t=''+(((y1-y0)*i/10+y0).toFixed(2));gfz(c,0,y,-wi,0,t,'black','end')}gfz(c,gx0(c),0.55,wi,0,yt,'#0080ff','left');var m=Math.round(0.5+xn/20.0);for(var i=0;i=x0;i-=hrs){var xo=(i-x0)/(x1-x0);if(c['hrs'][c['hr']]<=48){n=dfmt(c,i)}else{n=dfmtm(c,i)}if(xo<=1 && c['tkey'] && ((l%hlv)==0)){gbe(c,xo,0);gln(c,xo,-0.02);gst(c);gfz(c,xo,0,0,-hi*tpos,n,'brown','center')}if(xo<=1 && c['tlines']){gbe(c,xo,0);gln(c,xo,1);gst(c)}l++}}glw(c,1);if(c['smooth']){for(var j=1;j0 && c['lin'+j]){gss(c,'red');var y=(av[j-1]-y0)/(y1-y0);gbe(c,0,y);gln(c,1,y);gst(c);var t=''+av[j-1].toFixed(2)+'av';gfz(c,1,y,1,0,t,cols[j-1],'left')}}if(c['tkey']){var i,dsp;i=c['hrs'][c['hr']];if(i < 24){dsp=''+i+'h'}else{dsp=''+(i/24)+'d'}gfz(c,1,0,c['xo']-c['pxe'],hi,dsp,'red','end');i=c['hln'][c['hl']];gfz(c,1,0,c['xo']-c['pxe'],hi*3,''+i,'red','end')}if(ex){ex(9,c,xn,x0,x1,y0,y1,ar)}} function sn(i,shi){if(shi.indexOf(' Shift ')<0){return ''+(i%10)}else{return shi.replace(/.* ([a-z])[a-z]*$/,'$1')}} function gc2(c){var div=document.getElementById('can0');while (div.firstChild){div.removeChild(div.firstChild)}c['can']=document.createElement('canvas');c['can'].id='can';c['xo']=0.0;c['yo']=0.0;c['ctx']=c['can'].getContext('2d');c['ctx'].canvas.width=c['xm']+1;c['ctx'].canvas.height=c['ym']+1;div.appendChild(c['can']);c['pxe']=Math.max(Math.round(c['xm']/250),1)} function gc(c){c['wx']=window.innerWidth;c['wy']=window.innerHeight;c['xm']=Math.max(Math.round(c['wx']*0.9+0.5),400);c['ym']=Math.max(Math.round(c['wy']*0.8+0.5),400);if(c['ym']>c['xm']){c['ym']=c['xm']}gc2(c)} diff --git a/pool/page_luck.php b/pool/page_luck.php index 434a3e4e..19a932fd 100644 --- a/pool/page_luck.php +++ b/pool/page_luck.php @@ -13,7 +13,7 @@ for(var j=1;j500){ymax=500} ghg(c,xmax-xmin); -ggr(c,0.90,0.90,'Luck%',rows,xmin,xmax,ymin,ymax,d,'seq:','vx:','luck:',tlk,w,cols)} +ggr(c,0.90,0.90,'Luck%',rows,xmin,xmax,ymin,ymax,d,'seq:','vx:','luck:',tlk,w,cols,null)} c={}; function dodrw(data,cbx){if(hasCan()){gdrw(c,sep(data),cbx)}} function gact(t){if(t.checked){scnv(t.id,1)}else{scnv(t.id,0)}godrw(0)}"; diff --git a/pool/page_psperf.php b/pool/page_psperf.php index 62672cc3..c9c60bfa 100644 --- a/pool/page_psperf.php +++ b/pool/page_psperf.php @@ -15,7 +15,7 @@ for(var j=1;j Date: Mon, 14 Dec 2015 22:07:22 +1100 Subject: [PATCH 15/26] Don't block on dead servers if possible when calling server_alive from the gen_loop --- src/ckpool.h | 1 + src/generator.c | 25 +++++++++++++++++++------ 2 files changed, 20 insertions(+), 6 deletions(-) diff --git a/src/ckpool.h b/src/ckpool.h index 6d0e7348..61108868 100644 --- a/src/ckpool.h +++ b/src/ckpool.h @@ -111,6 +111,7 @@ struct server_instance { char *auth; char *pass; bool notify; + bool alive; connsock_t cs; void *data; // Private data diff --git a/src/generator.c b/src/generator.c index 5dc76b22..88bf20b2 100644 --- a/src/generator.c +++ b/src/generator.c @@ -147,6 +147,7 @@ static bool server_alive(ckpool_t *ckp, server_instance_t *si, bool pinging) /* Has this server already been reconnected? */ if (cs->fd > 0) return true; + si->alive = false; if (!extract_sockaddr(si->url, &cs->url, &cs->port)) { LOGWARNING("Failed to extract address from %s", si->url); return ret; @@ -189,6 +190,7 @@ out: /* Close and invalidate the file handle */ Close(cs->fd); } else { + si->alive = true; LOGNOTICE("Server alive: %s:%s", cs->url, cs->port); keep_sockalive(cs->fd); } @@ -207,19 +209,30 @@ retry: if (!ping_main(ckp)) goto out; + /* First find a server that is already flagged alive if possible + * without blocking on server_alive() */ for (i = 0; i < ckp->btcds; i++) { server_instance_t *si = ckp->servers[i]; - if (server_alive(ckp, si, false)) { + if (si->alive) { alive = si; - break; + goto living; } } - if (!alive) { - LOGWARNING("CRITICAL: No bitcoinds active!"); - sleep(5); - goto retry; + + /* No servers flagged alive, try to connect to them blocking */ + for (i = 0; i < ckp->btcds; i++) { + server_instance_t *si = ckp->servers[i]; + + if (server_alive(ckp, si, false)) { + alive = si; + goto living; + } } + LOGWARNING("CRITICAL: No bitcoinds active!"); + sleep(5); + goto retry; +living: cs = &alive->cs; LOGINFO("Connected to live server %s:%s", cs->url, cs->port); out: From 6ff89b31a25014b18d06f25920ccd1a355903e1f Mon Sep 17 00:00:00 2001 From: Con Kolivas Date: Mon, 14 Dec 2015 22:08:48 +1100 Subject: [PATCH 16/26] Check server fd is still valid as well as having its alive flag set --- src/generator.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/generator.c b/src/generator.c index 88bf20b2..2853baf7 100644 --- a/src/generator.c +++ b/src/generator.c @@ -213,8 +213,9 @@ retry: * without blocking on server_alive() */ for (i = 0; i < ckp->btcds; i++) { server_instance_t *si = ckp->servers[i]; + cs = &si->cs; - if (si->alive) { + if (si->alive && cs->fd > 0) { alive = si; goto living; } From b622a6ec8d9329b7736491dc7641c7f55933df07 Mon Sep 17 00:00:00 2001 From: Con Kolivas Date: Mon, 14 Dec 2015 23:22:16 +1100 Subject: [PATCH 17/26] Check for errors in wait_read_select, closing the socket if they occur, and add a variant for non-unix sockets that checks for hangups as well --- src/ckpool.c | 2 +- src/generator.c | 4 ++-- src/libckpool.c | 38 +++++++++++++++++++++++++++----------- src/libckpool.h | 5 ++++- 4 files changed, 34 insertions(+), 15 deletions(-) diff --git a/src/ckpool.c b/src/ckpool.c index 70269b46..aff75444 100644 --- a/src/ckpool.c +++ b/src/ckpool.c @@ -527,7 +527,7 @@ rewait: ret = 0; goto out; } - ret = wait_read_select(cs->fd, eom ? 0 : *timeout); + ret = wait_recv_select(cs->fd, eom ? 0 : *timeout); if (ret < 1) { if (!ret) { if (eom) diff --git a/src/generator.c b/src/generator.c index 2853baf7..da28e55f 100644 --- a/src/generator.c +++ b/src/generator.c @@ -290,7 +290,7 @@ retry: ckmsgq_add(gdata->srvchk, si); do { - selret = wait_read_select(us->sockd, 5); + selret = wait_recv_select(us->sockd, 5); if (!selret && !ping_main(ckp)) { LOGEMERG("Generator failed to ping main process, exiting"); ret = 1; @@ -1632,7 +1632,7 @@ retry: ckmsgq_add(gdata->srvchk, proxi->si); do { - selret = wait_read_select(us->sockd, 5); + selret = wait_recv_select(us->sockd, 5); if (!selret && !ping_main(ckp)) { LOGEMERG("Generator failed to ping main process, exiting"); ret = 1; diff --git a/src/libckpool.c b/src/libckpool.c index 8e08253a..3ba15232 100644 --- a/src/libckpool.c +++ b/src/libckpool.c @@ -758,17 +758,15 @@ out: void empty_socket(int fd) { + char buf[PAGESIZE]; int ret; if (fd < 1) return; do { - char buf[PAGESIZE]; - - ret = wait_read_select(fd, 0); + ret = recv(fd, buf, PAGESIZE - 1, MSG_DONTWAIT); if (ret > 0) { - ret = recv(fd, buf, PAGESIZE - 1, 0); buf[ret] = 0; LOGDEBUG("Discarding: %s", buf); } @@ -907,21 +905,39 @@ int wait_close(int sockd, int timeout) return sfd.revents & (POLLHUP | POLLRDHUP | POLLERR); } -/* Emulate a select read wait for high fds that select doesn't support */ -int wait_read_select(int sockd, float timeout) +/* Emulate a select read wait for high fds that select doesn't support. + * wait_read_select is for unix sockets and _wait_recv_select for regular + * sockets. */ +int _wait_read_select(int *sockd, float timeout) { struct pollfd sfd; int ret = -1; - if (unlikely(sockd < 0)) + if (unlikely(*sockd < 0)) goto out; - sfd.fd = sockd; + sfd.fd = *sockd; sfd.events = POLLIN | POLLRDHUP; - sfd.revents = 0; timeout *= 1000; ret = poll(&sfd, 1, timeout); - if (ret && !(sfd.revents & POLLIN)) - ret = -1; + if (ret > 0 && sfd.revents & (POLLERR)) + _Close(sockd); +out: + return ret; +} + +int _wait_recv_select(int *sockd, float timeout) +{ + struct pollfd sfd; + int ret = -1; + + if (unlikely(*sockd < 0)) + goto out; + sfd.fd = *sockd; + sfd.events = POLLIN | POLLRDHUP; + timeout *= 1000; + ret = poll(&sfd, 1, timeout); + if (ret > 0 && sfd.revents & (POLLHUP | POLLRDHUP | POLLERR)) + _Close(sockd); out: return ret; } diff --git a/src/libckpool.h b/src/libckpool.h index 9d8ba341..222ce26f 100644 --- a/src/libckpool.h +++ b/src/libckpool.h @@ -496,7 +496,10 @@ int _open_unix_server(const char *server_path, const char *file, const char *fun int _open_unix_client(const char *server_path, const char *file, const char *func, const int line); #define open_unix_client(server_path) _open_unix_client(server_path, __FILE__, __func__, __LINE__) int wait_close(int sockd, int timeout); -int wait_read_select(int sockd, float timeout); +int _wait_read_select(int *sockd, float timeout); +#define wait_read_select(SOCKD, TIMEOUT) _wait_read_select(&(SOCKD), TIMEOUT) +int _wait_recv_select(int *sockd, float timeout); +#define wait_recv_select(SOCKD, TIMEOUT) _wait_recv_select(&(SOCKD), TIMEOUT) int read_length(int sockd, void *buf, int len); char *_recv_unix_msg(int sockd, int timeout1, int timeout2, const char *file, const char *func, const int line); #define RECV_UNIX_TIMEOUT1 30 From 26b2123891faab761ddf97c65923e7d357fd67aa Mon Sep 17 00:00:00 2001 From: kanoi Date: Mon, 14 Dec 2015 23:46:37 +1100 Subject: [PATCH 18/26] php - show a light red highlight under the last 5Nd payout on the shift graph --- pool/page_usperf.php | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/pool/page_usperf.php b/pool/page_usperf.php index bc6acb2b..18961794 100644 --- a/pool/page_usperf.php +++ b/pool/page_usperf.php @@ -1,8 +1,9 @@ =0&&fi>=0){var xs,xf;xs=(st-x0)/(x1-x0);xf=(fi-x0)/(x1-x0);gfs(c,'$fs');gbe(c,xs,0);gln(c,xs,1);gln(c,xf,1);gln(c,xf,0);gle(c);gfl(c)}}} +function gdrw(c,d,cbx){gc(c);ghrs(c);gopt(c,cbx); gfs(c,'white');gss(c,'#0000c0');glw(c,2);gbd(c); var rows=d['rows'],ymin=-1,ymax=0,xmin=-1,xmax=0,tda=[]; var w=d['arp'].split(',');var cols=d['cols'].split(','); @@ -15,7 +16,7 @@ for(var j=1;j $txt) From 7ce2afae83283d71cda9d443ecfc3b51d91e0956 Mon Sep 17 00:00:00 2001 From: Con Kolivas Date: Tue, 15 Dec 2015 08:32:50 +1100 Subject: [PATCH 19/26] Try to reopen any closed sockets in json_rpc_call --- src/ckpool.c | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/src/ckpool.c b/src/ckpool.c index aff75444..6f4a71fd 100644 --- a/src/ckpool.c +++ b/src/ckpool.c @@ -831,14 +831,19 @@ json_t *json_rpc_call(connsock_t *cs, const char *rpc_req) out_empty: empty_socket(cs->fd); empty_buffer(cs); - if (!val && cs->fd > 0) { + if (!val) { /* Assume that a failed request means the socket will be closed * and reopen it */ - LOGWARNING("Attempting to reopen socket to %s:%s", cs->url, cs->port); Close(cs->fd); - cs->fd = connect_socket(cs->url, cs->port); } out: + if (cs->fd < 0) { + /* Attempt to reopen a socket that has been closed due to a + * failed requet or if the socket was closed while trying to + * read/write to it. */ + LOGWARNING("Attempting to reopen socket to %s:%s", cs->url, cs->port); + cs->fd = connect_socket(cs->url, cs->port); + } free(http_req); dealloc(cs->buf); cksem_post(&cs->sem); From b5ea946ef40ec159ce809164758f7eacc9bf0502 Mon Sep 17 00:00:00 2001 From: Con Kolivas Date: Tue, 15 Dec 2015 08:42:57 +1100 Subject: [PATCH 20/26] Output generator started message as soon as we have the first live server --- src/generator.c | 13 ++++--------- 1 file changed, 4 insertions(+), 9 deletions(-) diff --git a/src/generator.c b/src/generator.c index da28e55f..ed278df3 100644 --- a/src/generator.c +++ b/src/generator.c @@ -277,6 +277,10 @@ reconnect: si = live_server(ckp); if (!si) goto out; + if (unlikely(!started)) { + started = true; + LOGWARNING("%s generator ready", ckp->name); + } gbt = si->data; cs = &si->cs; @@ -342,10 +346,6 @@ retry: cs->url, cs->port); send_unix_msg(sockd, "failed"); } else { - if (unlikely(!started)) { - started = true; - LOGWARNING("%s generator ready", ckp->name); - } send_unix_msg(sockd, hash); } } else if (cmdmatch(buf, "getlast")) { @@ -362,11 +362,6 @@ retry: send_unix_msg(sockd, "failed"); goto reconnect; } else { - if (unlikely(!started)) { - started = true; - LOGWARNING("%s generator ready", ckp->name); - } - send_unix_msg(sockd, hash); LOGDEBUG("Hash: %s", hash); } From 61b25e4ac4e6e47231265a36396170730e1138be Mon Sep 17 00:00:00 2001 From: Con Kolivas Date: Tue, 15 Dec 2015 09:13:17 +1100 Subject: [PATCH 21/26] Add information about whether the attempt to reopen a socket was successful or not --- src/ckpool.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/ckpool.c b/src/ckpool.c index 6f4a71fd..3a09a4f7 100644 --- a/src/ckpool.c +++ b/src/ckpool.c @@ -839,10 +839,11 @@ out_empty: out: if (cs->fd < 0) { /* Attempt to reopen a socket that has been closed due to a - * failed requet or if the socket was closed while trying to + * failed request or if the socket was closed while trying to * read/write to it. */ - LOGWARNING("Attempting to reopen socket to %s:%s", cs->url, cs->port); cs->fd = connect_socket(cs->url, cs->port); + LOGWARNING("Attempt to reopen socket to %s:%s %ssuccessful", + cs->url, cs->port, cs->fd > 0 ? "" : "un"); } free(http_req); dealloc(cs->buf); From fba82db0f908a12a937958c7567bc5b08c8d784e Mon Sep 17 00:00:00 2001 From: Con Kolivas Date: Tue, 15 Dec 2015 09:24:52 +1100 Subject: [PATCH 22/26] Typo --- src/generator.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/generator.c b/src/generator.c index ed278df3..5807e9a9 100644 --- a/src/generator.c +++ b/src/generator.c @@ -285,7 +285,7 @@ reconnect: gbt = si->data; cs = &si->cs; if (!old_si) - LOGWARNING("Connected to bitoind: %s:%s", cs->url, cs->port); + LOGWARNING("Connected to bitcoind: %s:%s", cs->url, cs->port); else if (si != old_si) LOGWARNING("Failed over to bitcoind: %s:%s", cs->url, cs->port); From c645a6fc698ce9231af9fda8796b0d5f6c4ab3e8 Mon Sep 17 00:00:00 2001 From: Con Kolivas Date: Tue, 15 Dec 2015 10:53:32 +1100 Subject: [PATCH 23/26] Make the server watchdog a standalone thread that doesn't need messaging --- src/generator.c | 68 ++++++++++++++++++++++++------------------------- 1 file changed, 34 insertions(+), 34 deletions(-) diff --git a/src/generator.c b/src/generator.c index 5807e9a9..9419a6bd 100644 --- a/src/generator.c +++ b/src/generator.c @@ -130,7 +130,8 @@ struct proxy_instance { struct generator_data { mutex_t lock; /* Lock protecting linked lists */ proxy_instance_t *proxy_list; /* Linked list of all active proxies */ - int proxy_notify_id; // Globally increasing notify id + int proxy_notify_id; /* Globally increasing notify id */ + server_instance_t *si; /* Current server instance */ ckmsgq_t *srvchk; // Server check message queue }; @@ -264,7 +265,6 @@ static int gen_loop(proc_instance_t *pi) int sockd = -1, ret = 0, selret; unixsock_t *us = &pi->us; ckpool_t *ckp = pi->ckp; - gdata_t *gdata = ckp->data; bool started = false; char *buf = NULL; connsock_t *cs; @@ -291,7 +291,6 @@ reconnect: retry: Close(sockd); - ckmsgq_add(gdata->srvchk, si); do { selret = wait_recv_select(us->sockd, 5); @@ -1692,8 +1691,38 @@ out: return ret; } +/* Check which servers are alive, maintaining a connection with them and + * reconnect if a higher priority one is available. */ +static void *server_watchdog(void *arg) +{ + ckpool_t *ckp = (ckpool_t *)arg; + gdata_t *gdata = ckp->data; + + while (42) { + server_instance_t *best = NULL; + ts_t timer_t; + int i; + + cksleep_prepare_r(&timer_t); + for (i = 0; i < ckp->btcds; i++) { + server_instance_t *si = ckp->servers[i]; + + /* Have we reached the current server? */ + if (server_alive(ckp, si, true) && !best) + best = si; + } + if (best && best != gdata->si) { + gdata->si = best; + send_proc(ckp->generator, "reconnect"); + } + cksleep_ms_r(&timer_t, 5000); + } + return NULL; +} + static int server_mode(ckpool_t *ckp, proc_instance_t *pi) { + pthread_t pth_watchdog; server_instance_t *si; int i, ret; @@ -1710,6 +1739,7 @@ static int server_mode(ckpool_t *ckp, proc_instance_t *pi) cksem_post(&si->cs.sem); } + create_pthread(&pth_watchdog, server_watchdog, ckp); ret = gen_loop(pi); for (i = 0; i < ckp->btcds; i++) { @@ -1778,34 +1808,6 @@ static int proxy_mode(ckpool_t *ckp, proc_instance_t *pi) return ret; } -/* Tell the watchdog what the current server instance is, check which servers - * are alive, maintaining a connection with them and reconnect if a higher - * priority one is available. */ -static void server_watchdog(ckpool_t *ckp, server_instance_t *cursi) -{ - server_instance_t *best = NULL; - static time_t last_t = 0; - time_t now_t; - int i; - - /* Rate limit to checking only once every 5 seconds */ - now_t = time(NULL); - if (now_t <= last_t + 5) - return; - - last_t = now_t; - - for (i = 0; i < ckp->btcds; i++) { - server_instance_t *si = ckp->servers[i]; - - /* Have we reached the current server? */ - if (server_alive(ckp, si, true) && !best) - best = si; - } - if (best && (!cursi || cursi->id > best->id)) - send_proc(ckp->generator, "reconnect"); -} - static void proxy_watchdog(ckpool_t *ckp, server_instance_t *cursi) { gdata_t *gdata = ckp->data; @@ -1865,10 +1867,8 @@ int generator(proc_instance_t *pi) if (ckp->proxy) { gdata->srvchk = create_ckmsgq(ckp, "prxchk", &proxy_watchdog); ret = proxy_mode(ckp, pi); - } else { - gdata->srvchk = create_ckmsgq(ckp, "srvchk", &server_watchdog); + } else ret = server_mode(ckp, pi); - } dealloc(ckp->data); return process_exit(ckp, pi, ret); From 432d1ce4d5932360ab1011e53fdcf761b24ffb4b Mon Sep 17 00:00:00 2001 From: Con Kolivas Date: Tue, 15 Dec 2015 12:04:33 +1100 Subject: [PATCH 24/26] Don't treat POLLRDHUP as fatal unless we can't receive data after it, and return errors from wait_select functions when they close the socket --- src/ckpool.c | 10 ++++++++-- src/libckpool.c | 10 ++++++++-- 2 files changed, 16 insertions(+), 4 deletions(-) diff --git a/src/ckpool.c b/src/ckpool.c index 3a09a4f7..9ed16c86 100644 --- a/src/ckpool.c +++ b/src/ckpool.c @@ -504,6 +504,7 @@ int read_socket_line(connsock_t *cs, float *timeout) tv_t start, now; size_t buflen; int ret = -1; + bool polled; float diff; if (unlikely(cs->fd < 0)) @@ -528,6 +529,7 @@ rewait: goto out; } ret = wait_recv_select(cs->fd, eom ? 0 : *timeout); + polled = true; if (ret < 1) { if (!ret) { if (eom) @@ -551,12 +553,16 @@ rewait: /* No more to read or closed socket after valid message */ if (eom) break; - /* Have we used up all the timeout yet? */ - if (*timeout >= 0 && (errno == EAGAIN || errno == EWOULDBLOCK || !ret)) + /* Have we used up all the timeout yet? If polled is + * set that means poll has said there should be + * something to read and if we get nothing it means the + * socket is closed. */ + if (!polled && *timeout >= 0 && (errno == EAGAIN || errno == EWOULDBLOCK || !ret)) goto rewait; LOGERR("Failed to recv in read_socket_line"); goto out; } + polled = false; buflen = cs->bufofs + ret + 1; while (42) { newbuf = realloc(cs->buf, buflen); diff --git a/src/libckpool.c b/src/libckpool.c index 3ba15232..50a12089 100644 --- a/src/libckpool.c +++ b/src/libckpool.c @@ -919,8 +919,10 @@ int _wait_read_select(int *sockd, float timeout) sfd.events = POLLIN | POLLRDHUP; timeout *= 1000; ret = poll(&sfd, 1, timeout); - if (ret > 0 && sfd.revents & (POLLERR)) + if (ret > 0 && sfd.revents & (POLLERR)) { + ret = -1; _Close(sockd); + } out: return ret; } @@ -936,8 +938,12 @@ int _wait_recv_select(int *sockd, float timeout) sfd.events = POLLIN | POLLRDHUP; timeout *= 1000; ret = poll(&sfd, 1, timeout); - if (ret > 0 && sfd.revents & (POLLHUP | POLLRDHUP | POLLERR)) + /* If POLLRDHUP occurs, we may still have data to read so let recv() + * after this determine if the socket can still be used. */ + if (ret > 0 && sfd.revents & (POLLHUP | POLLERR)) { + ret = -1; _Close(sockd); + } out: return ret; } From edd79bd8fa970333f407e1f07d0d0695954084fe Mon Sep 17 00:00:00 2001 From: Con Kolivas Date: Tue, 15 Dec 2015 12:17:58 +1100 Subject: [PATCH 25/26] Elaborate which bitcoind has failed responses --- src/bitcoin.c | 12 ++++++------ src/generator.c | 2 +- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/src/bitcoin.c b/src/bitcoin.c index 88e37817..48052684 100644 --- a/src/bitcoin.c +++ b/src/bitcoin.c @@ -54,7 +54,7 @@ bool validate_address(connsock_t *cs, const char *address) snprintf(rpc_req, 128, "{\"method\": \"validateaddress\", \"params\": [\"%s\"]}\n", address); val = json_rpc_call(cs, rpc_req); if (!val) { - LOGERR("Failed to get valid json response to validate_address"); + LOGERR("%s:%s Failed to get valid json response to validate_address", cs->url, cs->port); return ret; } res_val = json_object_get(val, "result"); @@ -194,7 +194,7 @@ bool gen_gbtbase(connsock_t *cs, gbtbase_t *gbt) val = json_rpc_call(cs, gbt_req); if (!val) { - LOGWARNING("Failed to get valid json response to getblocktemplate"); + LOGWARNING("%s:%s Failed to get valid json response to getblocktemplate", cs->url, cs->port); return ret; } res_val = json_object_get(val, "result"); @@ -299,7 +299,7 @@ int get_blockcount(connsock_t *cs) val = json_rpc_call(cs, blockcount_req); if (!val) { - LOGWARNING("Failed to get valid json response to getblockcount"); + LOGWARNING("%s:%s Failed to get valid json response to getblockcount", cs->url, cs->port); return ret; } res_val = json_object_get(val, "result"); @@ -325,7 +325,7 @@ bool get_blockhash(connsock_t *cs, int height, char *hash) sprintf(rpc_req, "{\"method\": \"getblockhash\", \"params\": [%d]}\n", height); val = json_rpc_call(cs, rpc_req); if (!val) { - LOGWARNING("Failed to get valid json response to getblockhash"); + LOGWARNING("%s:%s Failed to get valid json response to getblockhash", cs->url, cs->port); return ret; } res_val = json_object_get(val, "result"); @@ -356,7 +356,7 @@ bool get_bestblockhash(connsock_t *cs, char *hash) val = json_rpc_call(cs, bestblockhash_req); if (!val) { - LOGWARNING("Failed to get valid json response to getbestblockhash"); + LOGWARNING("%s:%s Failed to get valid json response to getbestblockhash", cs->url, cs->port); return ret; } res_val = json_object_get(val, "result"); @@ -391,7 +391,7 @@ retry: val = json_rpc_call(cs, rpc_req); dealloc(rpc_req); if (!val) { - LOGWARNING("Failed to get valid json response to submitblock"); + LOGWARNING("%s:%s Failed to get valid json response to submitblock", cs->url, cs->port); if (++retries < 5) goto retry; return ret; diff --git a/src/generator.c b/src/generator.c index 9419a6bd..7d1dc1a0 100644 --- a/src/generator.c +++ b/src/generator.c @@ -302,7 +302,7 @@ retry: } while (selret < 1); if (unlikely(cs->fd < 0)) { - LOGWARNING("Bitcoind socket invalidated, will attempt failover"); + LOGWARNING("%s:%s Bitcoind socket invalidated, will attempt failover", cs->url, cs->port); goto reconnect; } From c7794a3d80dbc52972cc1281fe5a52acc8afa406 Mon Sep 17 00:00:00 2001 From: Con Kolivas Date: Tue, 15 Dec 2015 12:27:42 +1100 Subject: [PATCH 26/26] Retry getbase after a failure up to 5 times or indefinitely if a block change has been identified --- src/stratifier.c | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/src/stratifier.c b/src/stratifier.c index cabc654c..37a0cda7 100644 --- a/src/stratifier.c +++ b/src/stratifier.c @@ -908,10 +908,10 @@ static void broadcast_ping(sdata_t *sdata); static void *do_update(void *arg) { struct update_req *ur = (struct update_req *)arg; + int prio = ur->prio, retries = 0; ckpool_t *ckp = ur->ckp; sdata_t *sdata = ckp->data; bool new_block = false; - int prio = ur->prio; bool ret = false; workbase_t *wb; time_t now_t; @@ -921,15 +921,20 @@ static void *do_update(void *arg) pthread_detach(pthread_self()); rename_proc("updater"); +retry: buf = send_recv_generator(ckp, "getbase", prio); if (unlikely(!buf)) { LOGNOTICE("Get base in update_base delayed due to higher priority request"); goto out; } if (unlikely(cmdmatch(buf, "failed"))) { - LOGWARNING("Generator returned failure in update_base"); - goto out; + if (retries++ < 5 || prio == GEN_PRIORITY) { + LOGWARNING("Generator returned failure in update_base, retry #%d", retries); + goto retry; + } } + if (unlikely(retries)) + LOGWARNING("Generator succeeded in update_base after retrying"); wb = ckzalloc(sizeof(workbase_t)); wb->ckp = ckp;
«Elapsed<$r id=srtinv data-sf=r7>:Invalid<$r id=srtstale data-sf=r8>:Stale<$r id=srtdup data-sf=r9>:Duplicate<$r id=srthi data-sf=r10>:High<$r id=srtreject data-sf=r11>:Reject<$r id=srtdup data-sf=r9>:Dup<$r id=srthi data-sf=r10>:Hi<$r id=srtreject data-sf=r11>:RejBlock %<$r id=srtrate data-sf=r13>:Hash Rate