';
+ $top .= '';
+ $top .= "$lh | ";
+ $top .= "$ls | ";
+ $top .= "$lw | ";
+ $top .= ' | ';
$top .= '';
$top .= 'CKPool: | ';
$top .= " $phr | ";
diff --git a/src/ckdb.c b/src/ckdb.c
index 70e1380a..6cb14b17 100644
--- a/src/ckdb.c
+++ b/src/ckdb.c
@@ -170,6 +170,14 @@ const char *hashpatt = "^[A-Fa-f0-9]*$";
* bitcoind is used to fully validate them when required */
const char *addrpatt = "^[13][A-HJ-NP-Za-km-z1-9]*$";
+/* These are included in cmd_homepage
+ * to help identify when ckpool locks up (or dies) */
+tv_t last_heartbeat;
+tv_t last_workinfo;
+tv_t last_share;
+tv_t last_auth;
+cklock_t last_lock;
+
// So the records below have the same 'name' as the klist
const char Transfer[] = "Transfer";
@@ -280,6 +288,13 @@ bool startup_complete = false;
// Tell everyone to die
bool everyone_die = false;
+/* These are included in cmd_homepage
+ * to help identify when ckpool locks up (or dies) */
+tv_t last_heartbeat;
+tv_t last_workinfo;
+tv_t last_share;
+tv_t last_auth;
+
static cklock_t fpm_lock;
static char *first_pool_message;
static sem_t socketer_sem;
@@ -3207,6 +3222,16 @@ static void *listener(void *arg)
LOGWARNING("%s(): ckdb ready, queue %d", __func__, wqcount);
+ /* Until startup_complete, the values should be ignored
+ * Setting them to 'now' means that they won't time out
+ * until after startup_complete */
+ ck_wlock(&last_lock);
+ setnow(&last_heartbeat);
+ copy_tv(&last_workinfo, &last_heartbeat);
+ copy_tv(&last_share, &last_heartbeat);
+ copy_tv(&last_auth, &last_heartbeat);
+ ck_wunlock(&last_lock);
+
startup_complete = true;
}
@@ -3219,9 +3244,9 @@ static void *listener(void *arg)
wq_item = k_unlink_head(workqueue_store);
K_WUNLOCK(workqueue_store);
- /* Don't keep a connection for more than ~10s or ~1000 items
+ /* Don't keep a connection for more than ~10s or ~10000 items
* but always have a connection open */
- if ((time(NULL) - now) > 10 || wqgot > 1000) {
+ if ((time(NULL) - now) > 10 || wqgot > 10000) {
PQfinish(conn);
conn = dbconnect();
now = time(NULL);
@@ -4056,6 +4081,8 @@ int main(int argc, char **argv)
ckp.main.ckp = &ckp;
ckp.main.processname = strdup("main");
+ cklock_init(&last_lock);
+
if (confirm_sharesummary) {
// TODO: add a system lock to stop running 2 at once?
confirm_summaries();
diff --git a/src/ckdb.h b/src/ckdb.h
index 56272881..f4d43220 100644
--- a/src/ckdb.h
+++ b/src/ckdb.h
@@ -52,7 +52,7 @@
#define DB_VLOCK "1"
#define DB_VERSION "0.9.6"
-#define CKDB_VERSION DB_VERSION"-0.903"
+#define CKDB_VERSION DB_VERSION"-0.910"
#define WHERE_FFL " - from %s %s() line %d"
#define WHERE_FFL_HERE __FILE__, __func__, __LINE__
@@ -197,6 +197,7 @@ enum data_type {
TYPE_TV,
TYPE_TVS,
TYPE_CTV,
+ TYPE_FTV,
TYPE_BLOB,
TYPE_DOUBLE
};
@@ -266,6 +267,14 @@ extern bool startup_complete;
// Tell everyone to die
extern bool everyone_die;
+/* These are included in cmd_homepage
+ * to help identify when ckpool locks up (or dies) */
+extern tv_t last_heartbeat;
+extern tv_t last_workinfo;
+extern tv_t last_share;
+extern tv_t last_auth;
+extern cklock_t last_lock;
+
#define JSON_TRANSFER "json="
#define JSON_TRANSFER_LEN (sizeof(JSON_TRANSFER)-1)
#define JSON_BEGIN '{'
@@ -1558,6 +1567,7 @@ extern char *_data_to_buf(enum data_type typ, void *data, char *buf, size_t siz,
#define int_to_buf(_data, _buf, _siz) _int_to_buf(_data, _buf, _siz, WHERE_FFL_HERE)
#define tv_to_buf(_data, _buf, _siz) _tv_to_buf(_data, _buf, _siz, WHERE_FFL_HERE)
#define ctv_to_buf(_data, _buf, _siz) _ctv_to_buf(_data, _buf, _siz, WHERE_FFL_HERE)
+#define ftv_to_buf(_data, _buf, _siz) _ftv_to_buf(_data, _buf, _siz, WHERE_FFL_HERE)
#define tvs_to_buf(_data, _buf, _siz) _tvs_to_buf(_data, _buf, _siz, WHERE_FFL_HERE)
//#define blob_to_buf(_data, _buf, _siz) _blob_to_buf(_data, _buf, _siz, WHERE_FFL_HERE)
#define double_to_buf(_data, _buf, _siz) _double_to_buf(_data, _buf, _siz, WHERE_FFL_HERE)
@@ -1568,6 +1578,8 @@ extern char *_int_to_buf(int32_t data, char *buf, size_t siz, WHERE_FFL_ARGS);
extern char *_tv_to_buf(tv_t *data, char *buf, size_t siz, WHERE_FFL_ARGS);
// Convert tv to S,uS
extern char *_ctv_to_buf(tv_t *data, char *buf, size_t siz, WHERE_FFL_ARGS);
+// Convert tv to S.uS
+extern char *_ftv_to_buf(tv_t *data, char *buf, size_t siz, WHERE_FFL_ARGS);
// Convert tv to seconds (ignore uS)
extern char *_tvs_to_buf(tv_t *data, char *buf, size_t siz, WHERE_FFL_ARGS);
/* unused yet
diff --git a/src/ckdb_cmd.c b/src/ckdb_cmd.c
index 08001bdf..f957fd8c 100644
--- a/src/ckdb_cmd.c
+++ b/src/ckdb_cmd.c
@@ -1823,6 +1823,11 @@ static char *cmd_sharelog(PGconn *conn, char *cmd, char *id,
if (workinfoid == -1) {
LOGERR("%s(%s) %s.failed.DBE", __func__, cmd, id);
return strdup("failed.DBE");
+ } else {
+ // Only flag a successful workinfo
+ ck_wlock(&last_lock);
+ setnow(&last_workinfo);
+ ck_wunlock(&last_lock);
}
LOGDEBUG("%s.ok.added %"PRId64, id, workinfoid);
wiconf:
@@ -1909,6 +1914,11 @@ wiconf:
if (!ok) {
LOGERR("%s(%s) %s.failed.DATA", __func__, cmd, id);
return strdup("failed.DATA");
+ } else {
+ // Only flag a successful share
+ ck_wlock(&last_lock);
+ setnow(&last_share);
+ ck_wunlock(&last_lock);
}
LOGDEBUG("%s.ok.added %s", id, transfer_data(i_nonce));
sconf:
@@ -2237,8 +2247,12 @@ static char *cmd_auth_do(PGconn *conn, char *cmd, char *id, char *by,
if (!ok) {
LOGDEBUG("%s() %s.failed.DBE", __func__, id);
return strdup("failed.DBE");
+ } else {
+ // Only flag a successful auth
+ ck_wlock(&last_lock);
+ setnow(&last_auth);
+ ck_wunlock(&last_lock);
}
-
snprintf(reply, siz,
"ok.authorise={\"secondaryuserid\":\"%s\","
"\"difficultydefault\":%d}",
@@ -2321,8 +2335,12 @@ static char *cmd_addrauth_do(PGconn *conn, char *cmd, char *id, char *by,
if (!ok) {
LOGDEBUG("%s() %s.failed.DBE", __func__, id);
return strdup("failed.DBE");
+ } else {
+ // Only flag a successful auth
+ ck_wlock(&last_lock);
+ setnow(&last_auth);
+ ck_wunlock(&last_lock);
}
-
snprintf(reply, siz,
"ok.addrauth={\"secondaryuserid\":\"%s\","
"\"difficultydefault\":%d}",
@@ -2367,6 +2385,10 @@ static char *cmd_heartbeat(__maybe_unused PGconn *conn, char *cmd, char *id,
if (!startup_complete)
goto pulse;
+ ck_wlock(&last_lock);
+ setnow(&last_heartbeat);
+ ck_wunlock(&last_lock);
+
K_WLOCK(heartbeatqueue_free);
if (heartbeatqueue_store->count == 0) {
K_WUNLOCK(heartbeatqueue_free);
@@ -2413,7 +2435,7 @@ pulse:
}
static char *cmd_homepage(__maybe_unused PGconn *conn, char *cmd, char *id,
- __maybe_unused tv_t *now, __maybe_unused char *by,
+ tv_t *now, __maybe_unused char *by,
__maybe_unused char *code, __maybe_unused char *inet,
__maybe_unused tv_t *notcd, K_TREE *trf_root)
{
@@ -2437,6 +2459,26 @@ static char *cmd_homepage(__maybe_unused PGconn *conn, char *cmd, char *id,
APPEND_REALLOC_INIT(buf, off, len);
APPEND_REALLOC(buf, off, len, "ok.");
+
+ // N.B. cmd_homepage isn't called until startup_complete
+ ftv_to_buf(now, reply, siz);
+ snprintf(tmp, sizeof(tmp), "now=%s%c", reply, FLDSEP);
+ APPEND_REALLOC(buf, off, len, tmp);
+ ck_wlock(&last_lock);
+ ftv_to_buf(&last_heartbeat, reply, siz);
+ snprintf(tmp, sizeof(tmp), "lasthb=%s%c", reply, FLDSEP);
+ APPEND_REALLOC(buf, off, len, tmp);
+ ftv_to_buf(&last_workinfo, reply, siz);
+ snprintf(tmp, sizeof(tmp), "lastwi=%s%c", reply, FLDSEP);
+ APPEND_REALLOC(buf, off, len, tmp);
+ ftv_to_buf(&last_share, reply, siz);
+ snprintf(tmp, sizeof(tmp), "lastsh=%s%c", reply, FLDSEP);
+ APPEND_REALLOC(buf, off, len, tmp);
+ ftv_to_buf(&last_auth, reply, siz);
+ ck_wunlock(&last_lock);
+ snprintf(tmp, sizeof(tmp), "lastau=%s%c", reply, FLDSEP);
+ APPEND_REALLOC(buf, off, len, tmp);
+
if (last_bc.tv_sec) {
tvs_to_buf(&last_bc, reply, siz);
snprintf(tmp, sizeof(tmp), "lastbc=%s%c", reply, FLDSEP);
diff --git a/src/ckdb_data.c b/src/ckdb_data.c
index 1139f8fc..d8ef8b38 100644
--- a/src/ckdb_data.c
+++ b/src/ckdb_data.c
@@ -358,6 +358,7 @@ void _txt_to_double(char *nam, char *fld, double *data, size_t siz, WHERE_FFL_AR
char *_data_to_buf(enum data_type typ, void *data, char *buf, size_t siz, WHERE_FFL_ARGS)
{
struct tm tm;
+ double d;
if (!buf) {
switch (typ) {
@@ -376,6 +377,7 @@ char *_data_to_buf(enum data_type typ, void *data, char *buf, size_t siz, WHERE_
siz = DATE_BUFSIZ;
break;
case TYPE_CTV:
+ case TYPE_FTV:
siz = CDATE_BUFSIZ;
break;
case TYPE_DOUBLE:
@@ -419,6 +421,11 @@ char *_data_to_buf(enum data_type typ, void *data, char *buf, size_t siz, WHERE_
(((tv_t *)data)->tv_sec),
(((tv_t *)data)->tv_usec));
break;
+ case TYPE_FTV:
+ d = (double)(((tv_t *)data)->tv_sec) +
+ (double)(((tv_t *)data)->tv_usec) / 1000000.0;
+ snprintf(buf, siz, "%.6f", d);
+ break;
case TYPE_TVS:
snprintf(buf, siz, "%ld", (((tv_t *)data)->tv_sec));
break;
@@ -456,6 +463,12 @@ char *_ctv_to_buf(tv_t *data, char *buf, size_t siz, WHERE_FFL_ARGS)
return _data_to_buf(TYPE_CTV, (void *)data, buf, siz, WHERE_FFL_PASS);
}
+// Convert tv to S.uS
+char *_ftv_to_buf(tv_t *data, char *buf, size_t siz, WHERE_FFL_ARGS)
+{
+ return _data_to_buf(TYPE_FTV, (void *)data, buf, siz, WHERE_FFL_PASS);
+}
+
// Convert tv to seconds (ignore uS)
char *_tvs_to_buf(tv_t *data, char *buf, size_t siz, WHERE_FFL_ARGS)
{
|