diff --git a/src/stratifier.c b/src/stratifier.c index d1154232..4d6ec81f 100644 --- a/src/stratifier.c +++ b/src/stratifier.c @@ -5092,15 +5092,17 @@ static worker_instance_t *get_create_worker(sdata_t *sdata, user_instance_t *use /* Load the statistics of and create all known users at startup */ static void read_userstats(ckpool_t *ckp, sdata_t *sdata, int tvsec_diff) { - char dnam[512], s[512], *username; + char dnam[512], s[512], *username, *buf; user_instance_t *user; struct dirent *dir; + struct stat fdbuf; bool new_user; int ret, len; json_t *val; FILE *fp; tv_t now; DIR *d; + int fd; snprintf(dnam, 511, "%susers", ckp->logdir); d = opendir(dnam); @@ -5130,18 +5132,29 @@ static void read_userstats(ckpool_t *ckp, sdata_t *sdata, int tvsec_diff) LOGWARNING("Failed to load user %s logfile to read", username); continue; } - memset(s, 0, 512); - ret = fread(s, 1, 511, fp); + fd = fileno(fp); + if (unlikely(fstat(fd, &fdbuf))) { + LOGERR("Failed to fstat user %s logfile", username); + fclose(fp); + continue; + } + /* We don't know how big the logfile will be so allocate + * according to file size */ + buf = ckzalloc(fdbuf.st_size + 1); + ret = fread(buf, 1, fdbuf.st_size, fp); fclose(fp); if (ret < 1) { LOGNOTICE("Failed to read user %s logfile", username); + dealloc(buf); continue; } - val = json_loads(s, 0, NULL); + val = json_loads(buf, 0, NULL); if (!val) { - LOGNOTICE("Failed to json decode user %s logfile: %s", username, s); + LOGNOTICE("Failed to json decode user %s logfile: %s", username, buf); + dealloc(buf); continue; } + dealloc(buf); copy_tv(&user->last_share, &now); copy_tv(&user->last_decay, &now); @@ -5204,21 +5217,29 @@ static void read_userstats(ckpool_t *ckp, sdata_t *sdata, int tvsec_diff) LOGWARNING("Failed to load worker %s logfile to read", workername); continue; } - memset(s, 0, 512); - ret = fread(s, 1, 511, fp); + fd = fileno(fp); + if (unlikely(fstat(fd, &fdbuf))) { + LOGERR("Failed to fstat user %s logfile", username); + fclose(fp); + continue; + } + buf = ckzalloc(fdbuf.st_size + 1); + ret = fread(buf, 1, fdbuf.st_size, fp); fclose(fp); if (ret < 1) { LOGNOTICE("Failed to read worker %s logfile", workername); + dealloc(buf); continue; } - val = json_loads(s, 0, NULL); + val = json_loads(buf, 0, NULL); if (!val) { LOGNOTICE("Failed to json decode worker %s logfile: %s", - workername, s); + workername, buf); + dealloc(buf); continue; } - copy_tv(&worker->last_share, &now); + copy_tv(&worker->last_share, &now); copy_tv(&worker->last_decay, &now); worker->dsps1 = dsps_from_key(val, "hashrate1m"); worker->dsps5 = dsps_from_key(val, "hashrate5m"); @@ -8259,10 +8280,12 @@ static void *statsupdate(void *arg) while ((user = next_user(sdata, user)) != NULL) { worker_instance_t *worker; bool idle = false; + json_t *user_array; if (!user->authorised) continue; + user_array = json_array(); worker = NULL; tv_time(&now); @@ -8298,13 +8321,12 @@ static void *statsupdate(void *arg) "shares", worker->shares, "bestshare", worker->best_diff); - /* Only log workers of authorised users */ - if (user->authorised) { - ASPRINTF(&fname, "%s/workers/%s", ckp->logdir, worker->workername); - s = json_dumps(val, JSON_NO_UTF8 | JSON_PRESERVE_ORDER | JSON_EOL); - add_log_entry(&log_entries, &fname, &s); - } - json_decref(val); + ASPRINTF(&fname, "%s/workers/%s", ckp->logdir, worker->workername); + s = json_dumps(val, JSON_NO_UTF8 | JSON_PRESERVE_ORDER | JSON_EOL); + add_log_entry(&log_entries, &fname, &s); + json_set_string(val, "workername", worker->workername); + json_array_append_new(user_array, val); + val = NULL; } /* Decay times per user */ @@ -8349,17 +8371,16 @@ static void *statsupdate(void *arg) remote_users++; } - if (user->authorised) { - ASPRINTF(&fname, "%s/users/%s", ckp->logdir, user->username); - s = json_dumps(val, JSON_NO_UTF8 | JSON_PRESERVE_ORDER | JSON_EOL); - add_log_entry(&log_entries, &fname, &s); - if (!idle) { - s = json_dumps(val, JSON_NO_UTF8 | JSON_PRESERVE_ORDER); - ASPRINTF(&sp, "User %s:%s", user->username, s); - dealloc(s); - add_msg_entry(&char_list, &sp); - } + if (!idle) { + s = json_dumps(val, JSON_NO_UTF8 | JSON_PRESERVE_ORDER); + ASPRINTF(&sp, "User %s:%s", user->username, s); + dealloc(s); + add_msg_entry(&char_list, &sp); } + json_object_set_new_nocheck(val, "worker", user_array); + ASPRINTF(&fname, "%s/users/%s", ckp->logdir, user->username); + s = json_dumps(val, JSON_NO_UTF8 | JSON_PRESERVE_ORDER | JSON_EOL); + add_log_entry(&log_entries, &fname, &s); json_decref(val); if (ckp->remote) upstream_workers(ckp, user);