diff --git a/pool/page_shifts.php b/pool/page_shifts.php
index b83d3ec6..7627c0a3 100644
--- a/pool/page_shifts.php
+++ b/pool/page_shifts.php
@@ -14,10 +14,13 @@ function doshifts($data, $user)
$pg .= "
Shares | ";
$pg .= "Avg Share | ";
$pg .= "\n";
- if ($ans['STATUS'] != 'ok')
+
+ if (($ans['STATUS'] != 'ok') || !isset($ans['prefix_all']))
$pg = 'Shifts
'.$pg;
else
{
+ $pre = $ans['prefix_all'];
+
$count = $ans['rows'];
$pg = 'Last '.($count+1).' Shifts
'.$pg;
for ($i = 0; $i < $count; $i++)
@@ -49,11 +52,11 @@ function doshifts($data, $user)
$nd = $ans['end:'.$i];
$elapsed = $nd - $start;
$pg .= ''.howmanyhrs($elapsed).' | ';
- $diffacc = $ans['diffacc:'.$i];
+ $diffacc = $ans[$pre.'diffacc:'.$i];
$pg .= ''.difffmt($diffacc).' | ';
$hr = $diffacc * pow(2,32) / $elapsed;
$pg .= ''.dsprate($hr).' | ';
- $shareacc = $ans['shareacc:'.$i];
+ $shareacc = $ans[$pre.'shareacc:'.$i];
$pg .= ''.difffmt($shareacc).' | ';
if ($shareacc > 0)
$avgsh = $diffacc / $shareacc;
diff --git a/pool/page_usperf.php b/pool/page_usperf.php
index ed903428..5edd947c 100644
--- a/pool/page_usperf.php
+++ b/pool/page_usperf.php
@@ -4,8 +4,8 @@ function uspg()
{
$g = "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=0;
-for(var i=0;iths){ymin=ths}if(ths>ymax)ymax=ths;d['nx:'+i]=sn(i,d['shift:'+i]);if(xmin==-1||xmin>s){xmin=s}if(xmaxths){ymin=ths}if(ths>ymax)ymax=ths;d['nx:'+i]=sn(i,d['shift:'+i]);if(xmin==-1||xmin>s){xmin=s}if(xmax trg
@@ -839,6 +845,16 @@ extern K_STORE *workers_store;
#define IDLENOTIFICATIONTIME_DEF 0
#define IDLENOTIFICATIONTIME_DEF_STR STRINT(IDLENOTIFICATIONTIME_DEF)
+#define WORKERS_SEL_SEP ','
+#define WORKERS_SEL_SEP_STR ","
+/* There are 2 special select workernames
+ * A DB workername can't accidentally match them
+ * when including the WORKSEPx at the front of the workername,
+ * since these 2 don't start with WORKSEP1 or WORKSEP2 */
+#define WORKERS_ALL "all"
+// Empty has a value rather than "", so that "" means nothing selected
+#define WORKERS_EMPTY "noname"
+
// PAYMENTADDRESSES
typedef struct paymentaddresses {
int64_t paymentaddressid;
diff --git a/src/ckdb_cmd.c b/src/ckdb_cmd.c
index c171f4f3..1da701e3 100644
--- a/src/ckdb_cmd.c
+++ b/src/ckdb_cmd.c
@@ -4679,13 +4679,96 @@ static char *cmd_mpayouts(__maybe_unused PGconn *conn, char *cmd, char *id,
return buf;
}
+/* Find the offset, in list, of the workername
+ * -1 means NULL list, empty list or not found */
+static int worker_offset(char **list, char *workername)
+{
+ char *c1, *c2;
+ int i;
+
+ if (!list || !(*list))
+ return -1;
+
+ /* Find the start of the workername including the SEP */
+ c1 = strchr(workername, WORKSEP1);
+ c2 = strchr(workername, WORKSEP2);
+ if (c1 || c2) {
+ if (!c1 || (c1 && c2 && (c2 < c1)))
+ c1 = c2;
+ }
+ // No workername after the username
+ if (!c1)
+ c1 = WORKERS_EMPTY;
+ for (i = 0; list[i]; i++) {
+ if (strcmp(c1, list[i]) == 0)
+ return i;
+ }
+ return -1;
+}
+
+/* Some arbitrarily large limit, increase it if needed
+ (doesn't need to be very large) */
+#define SELECT_LIMIT 63
+
+/* select is a string of workernames separated by WORKERS_SEL_SEP
+ * Return an array of strings of select broken up
+ * The array is terminated by NULL
+ * and will have 0 elements if select is NULL/empty
+ * The count of the first occurrence of WORKERS_ALL is returned in *all_count,
+ * or -1 if WORKERS_ALL isn't found */
+static char **select_list(char *select, int *all_count)
+{
+ size_t len, offset, siz;
+ char **list = NULL;
+ int count;
+ char *end;
+
+ *all_count = -1;
+
+ siz = sizeof(char *) * (SELECT_LIMIT + 1);
+ list = malloc(siz);
+ if (!list)
+ quithere(1, "malloc (%d) OOM", (int)siz);
+ list[0] = NULL;
+
+ if (select == NULL || *select == '\0')
+ return list;
+
+ len = strlen(select);
+ count = 0;
+ offset = 0;
+ while (offset < len) {
+ if (select[offset] == WORKERS_SEL_SEP)
+ offset++;
+ else {
+ list[count] = select + offset;
+ list[count+1] = NULL;
+ end = strchr(list[count], WORKERS_SEL_SEP);
+ if (end != NULL) {
+ offset = 1 + end - select;
+ *end = '\0';
+ }
+
+ if (*all_count == -1 &&
+ strcasecmp(list[count], WORKERS_ALL) == 0) {
+ *all_count = count;
+ }
+
+ if (end == NULL || ++count > SELECT_LIMIT)
+ break;
+ }
+ }
+ return list;
+}
+
static char *cmd_shifts(__maybe_unused PGconn *conn, char *cmd, char *id,
__maybe_unused tv_t *now, __maybe_unused char *by,
__maybe_unused char *code, __maybe_unused char *inet,
__maybe_unused tv_t *notcd,
__maybe_unused K_TREE *trf_root)
{
- K_ITEM *i_username, *u_item, *m_item, ms_look, *wm_item, *ms_item, *wi_item;
+ K_ITEM *i_username, *i_select;
+ K_ITEM *u_item, *m_item, ms_look, *wm_item, *ms_item, *wi_item;
K_TREE_CTX wm_ctx[1], ms_ctx[1];
WORKMARKERS *wm;
WORKINFO *wi;
@@ -4695,10 +4778,13 @@ static char *cmd_shifts(__maybe_unused PGconn *conn, char *cmd, char *id,
char reply[1024] = "";
char tmp[1024];
size_t siz = sizeof(reply);
+ char *select = NULL;
+ char **selects = NULL;
+ bool used[SELECT_LIMIT];
char *buf;
size_t len, off;
tv_t marker_end = { 0L, 0L };
- int rows;
+ int rows, want, i, where_all;
LOGDEBUG("%s(): cmd '%s'", __func__, cmd);
@@ -4713,6 +4799,21 @@ static char *cmd_shifts(__maybe_unused PGconn *conn, char *cmd, char *id,
return strdup("bad");
DATA_USERS(users, u_item);
+ i_select = optional_name(trf_root, "select", 1, NULL, reply, siz);
+ if (i_select)
+ select = strdup(transfer_data(i_select));
+
+ selects = select_list(select, &where_all);
+ // Nothing selected = all
+ if (*selects == NULL) {
+ where_all = 0;
+ selects[0] = WORKERS_ALL;
+ selects[1] = NULL;
+ }
+
+ if (where_all >= 0)
+ used[where_all] = true;
+
APPEND_REALLOC_INIT(buf, off, len);
APPEND_REALLOC(buf, off, len, "ok.");
INIT_MARKERSUMMARY(&ms_look);
@@ -4756,6 +4857,30 @@ static char *cmd_shifts(__maybe_unused PGconn *conn, char *cmd, char *id,
ms_add.shareacc += ms->shareacc;
ms_add.sharerej += ms->sharerej;
+ want = worker_offset(selects, ms->workername);
+ if (want >= 0) {
+ used[want] = true;
+ double_to_buf(ms->diffacc, reply, sizeof(reply));
+ snprintf(tmp, sizeof(tmp), "%d_diffacc:%d=%s%c",
+ want, rows, reply, FLDSEP);
+ APPEND_REALLOC(buf, off, len, tmp);
+
+ double_to_buf(ms->diffrej, reply, sizeof(reply));
+ snprintf(tmp, sizeof(tmp), "%d_diffrej:%d=%s%c",
+ want, rows, reply, FLDSEP);
+ APPEND_REALLOC(buf, off, len, tmp);
+
+ double_to_buf(ms->shareacc, reply, sizeof(reply));
+ snprintf(tmp, sizeof(tmp), "%d_shareacc:%d=%s%c",
+ want, rows, reply, FLDSEP);
+ APPEND_REALLOC(buf, off, len, tmp);
+
+ double_to_buf(ms->sharerej, reply, sizeof(reply));
+ snprintf(tmp, sizeof(tmp), "%d_sharerej:%d=%s%c",
+ want, rows, reply, FLDSEP);
+ APPEND_REALLOC(buf, off, len, tmp);
+ }
+
ms_item = next_in_ktree(ms_ctx);
DATA_MARKERSUMMARY_NULL(ms, ms_item);
}
@@ -4775,7 +4900,9 @@ static char *cmd_shifts(__maybe_unused PGconn *conn, char *cmd, char *id,
wm->description,
wm->workinfoidend);
snprintf(reply, siz, "data error 1");
- return strdup(reply);
+ free(buf);
+ free(selects);
+ return(strdup(reply));
}
DATA_WORKINFO(wi, wi_item);
copy_tv(&marker_end, &(wi->createdate));
@@ -4794,13 +4921,15 @@ static char *cmd_shifts(__maybe_unused PGconn *conn, char *cmd, char *id,
__func__, wm->markerid, wm->description,
wm->workinfoidstart);
snprintf(reply, siz, "data error 2");
- return strdup(reply);
+ free(buf);
+ free(selects);
+ return(strdup(reply));
}
DATA_WORKINFO(wi, wi_item);
bigint_to_buf(wm->markerid, reply, sizeof(reply));
snprintf(tmp, sizeof(tmp), "markerid:%d=%s%c",
- rows, reply, FLDSEP);
+ rows, reply, FLDSEP);
APPEND_REALLOC(buf, off, len, tmp);
str_to_buf(wm->description, reply, sizeof(reply));
@@ -4824,27 +4953,33 @@ static char *cmd_shifts(__maybe_unused PGconn *conn, char *cmd, char *id,
rows, reply, FLDSEP);
APPEND_REALLOC(buf, off, len, tmp);
- double_to_buf(ms_add.diffacc, reply, sizeof(reply));
- snprintf(tmp, sizeof(tmp), "diffacc:%d=%s%c",
- rows, reply, FLDSEP);
- APPEND_REALLOC(buf, off, len, tmp);
+ if (where_all >= 0) {
+ double_to_buf(ms_add.diffacc, reply, sizeof(reply));
+ snprintf(tmp, sizeof(tmp), "%d_diffacc:%d=%s%c",
+ where_all, rows,
+ reply, FLDSEP);
+ APPEND_REALLOC(buf, off, len, tmp);
- double_to_buf(ms_add.diffrej, reply, sizeof(reply));
- snprintf(tmp, sizeof(tmp), "diffrej:%d=%s%c",
- rows, reply, FLDSEP);
- APPEND_REALLOC(buf, off, len, tmp);
+ double_to_buf(ms_add.diffrej, reply, sizeof(reply));
+ snprintf(tmp, sizeof(tmp), "%d_diffrej:%d=%s%c",
+ where_all, rows,
+ reply, FLDSEP);
+ APPEND_REALLOC(buf, off, len, tmp);
- double_to_buf(ms_add.shareacc, reply, sizeof(reply));
- snprintf(tmp, sizeof(tmp), "shareacc:%d=%s%c",
- rows, reply, FLDSEP);
- APPEND_REALLOC(buf, off, len, tmp);
+ double_to_buf(ms_add.shareacc, reply, sizeof(reply));
+ snprintf(tmp, sizeof(tmp), "%d_shareacc:%d=%s%c",
+ where_all, rows,
+ reply, FLDSEP);
+ APPEND_REALLOC(buf, off, len, tmp);
- double_to_buf(ms_add.sharerej, reply, sizeof(reply));
- snprintf(tmp, sizeof(tmp), "sharerej:%d=%s%c",
- rows, reply, FLDSEP);
- APPEND_REALLOC(buf, off, len, tmp);
+ double_to_buf(ms_add.sharerej, reply, sizeof(reply));
+ snprintf(tmp, sizeof(tmp), "%d_sharerej:%d=%s%c",
+ where_all, rows,
+ reply, FLDSEP);
+ APPEND_REALLOC(buf, off, len, tmp);
- rows++;
+ rows++;
+ }
// Setup for next shift
copy_tv(&marker_end, &(wi->createdate));
@@ -4856,17 +4991,55 @@ static char *cmd_shifts(__maybe_unused PGconn *conn, char *cmd, char *id,
}
K_RUNLOCK(workmarkers_free);
+ for (i = 0; selects[i]; i++) {
+ if (used[i]) {
+ snprintf(tmp, sizeof(tmp),
+ "%d_worker=%s%c",
+ i, selects[i], FLDSEP);
+ APPEND_REALLOC(buf, off, len, tmp);
+ snprintf(tmp, sizeof(tmp),
+ "%d_flds=%s%c", i,
+ "diffacc,diffrej,shareacc,sharerej", FLDSEP);
+ APPEND_REALLOC(buf, off, len, tmp);
+ }
+ }
+
+ // Missing if all isn't selected
+ if (where_all >= 0) {
+ snprintf(tmp, sizeof(tmp), "prefix_all=%d_%c",
+ where_all, FLDSEP);
+ APPEND_REALLOC(buf, off, len, tmp);
+ }
+
+ /* rows is an upper limit of rows in each worker
+ * 'all' starts at 0 and finishes at rows-1
+ * other workers start >= 0 and finish <= rows-1 */
snprintf(tmp, sizeof(tmp), "rows=%d%cflds=%s%c",
- rows, FLDSEP,
- "markerid,shift,start,end,diffacc,diffrej,shareacc,sharerej",
- FLDSEP);
+ rows, FLDSEP,
+ "markerid,shift,start,end", FLDSEP);
APPEND_REALLOC(buf, off, len, tmp);
- snprintf(tmp, sizeof(tmp), "arn=%s%carp=%s", "Shifts", FLDSEP, "");
+ snprintf(tmp, sizeof(tmp), "arn=%s", "Shifts");
APPEND_REALLOC(buf, off, len, tmp);
+ for (i = 0; selects[i]; i++) {
+ if (used[i]) {
+ snprintf(tmp, sizeof(tmp), ",Worker_%d", i);
+ APPEND_REALLOC(buf, off, len, tmp);
+ }
+ }
+
+ snprintf(tmp, sizeof(tmp), "%carp=", FLDSEP);
+ APPEND_REALLOC(buf, off, len, tmp);
+ for (i = 0; selects[i]; i++) {
+ if (used[i]) {
+ snprintf(tmp, sizeof(tmp), ",%d_", i);
+ APPEND_REALLOC(buf, off, len, tmp);
+ }
+ }
LOGDEBUG("%s.ok.%s", id, transfer_data(i_username));
- return buf;
+ free(selects);
+ return(buf);
}
static char *cmd_dsp(__maybe_unused PGconn *conn, __maybe_unused char *cmd,