mirror of
https://github.com/GOSTSec/sgminer
synced 2025-01-11 07:17:58 +00:00
Implement the ability to live add, enable, disable, and switch to pools.
This commit is contained in:
parent
baddb82ad9
commit
b0a8f279f7
275
main.c
275
main.c
@ -190,9 +190,10 @@ static unsigned int new_blocks;
|
||||
static unsigned int local_work;
|
||||
static unsigned int total_lo, total_ro;
|
||||
|
||||
static struct pool *pools = NULL;
|
||||
static struct pool *currentpool;
|
||||
static int pool_no;
|
||||
#define MAX_POOLS (32)
|
||||
|
||||
static struct pool *pools[MAX_POOLS];
|
||||
static struct pool *currentpool = NULL;
|
||||
static int total_pools;
|
||||
static enum pool_strategy pool_strategy = POOL_FAILOVER;
|
||||
static int opt_rotate_period;
|
||||
@ -222,18 +223,15 @@ static void applog_and_exit(const char *fmt, ...)
|
||||
|
||||
static void add_pool(void)
|
||||
{
|
||||
int poolno;
|
||||
struct pool *pool;
|
||||
|
||||
poolno = total_pools++;
|
||||
pools = realloc(pools, sizeof(struct pool) * total_pools);
|
||||
if (!pools) {
|
||||
applog(LOG_ERR, "Failed to malloc pools in add_pool");
|
||||
pool = calloc(sizeof(struct pool), 1);
|
||||
if (!pool) {
|
||||
applog(LOG_ERR, "Failed to malloc pool in add_pool");
|
||||
exit (1);
|
||||
}
|
||||
pool = &pools[poolno];
|
||||
memset(pool, 0, sizeof(struct pool));
|
||||
pool->pool_no = poolno;
|
||||
pool->pool_no = total_pools;
|
||||
pools[total_pools++] = pool;
|
||||
if (unlikely(pthread_mutex_init(&pool->pool_lock, NULL))) {
|
||||
applog(LOG_ERR, "Failed to pthread_mutex_init in add_pool");
|
||||
exit (1);
|
||||
@ -367,7 +365,7 @@ static char *set_url(const char *arg, char **p)
|
||||
total_urls++;
|
||||
if (total_urls > total_pools)
|
||||
add_pool();
|
||||
pool = &pools[total_urls - 1];
|
||||
pool = pools[total_urls - 1];
|
||||
|
||||
opt_set_charp(arg, &pool->rpc_url);
|
||||
if (strncmp(arg, "http://", 7) &&
|
||||
@ -387,7 +385,7 @@ static char *set_user(const char *arg, char **p)
|
||||
if (total_users > total_pools)
|
||||
add_pool();
|
||||
|
||||
pool = &pools[total_users - 1];
|
||||
pool = pools[total_users - 1];
|
||||
opt_set_charp(arg, &pool->rpc_user);
|
||||
|
||||
return NULL;
|
||||
@ -403,7 +401,7 @@ static char *set_pass(const char *arg, char **p)
|
||||
if (total_passes > total_pools)
|
||||
add_pool();
|
||||
|
||||
pool = &pools[total_passes - 1];
|
||||
pool = pools[total_passes - 1];
|
||||
opt_set_charp(arg, &pool->rpc_pass);
|
||||
|
||||
return NULL;
|
||||
@ -419,7 +417,7 @@ static char *set_userpass(const char *arg, char **p)
|
||||
if (total_userpasses > total_pools)
|
||||
add_pool();
|
||||
|
||||
pool = &pools[total_userpasses - 1];
|
||||
pool = pools[total_userpasses - 1];
|
||||
opt_set_charp(arg, &pool->rpc_userpass);
|
||||
|
||||
return NULL;
|
||||
@ -788,11 +786,13 @@ static void print_status(int thr_id)
|
||||
|
||||
void log_curses(const char *f, va_list ap)
|
||||
{
|
||||
if (curses_active && !opt_loginput) {
|
||||
pthread_mutex_lock(&curses_lock);
|
||||
vw_printw(logwin, f, ap);
|
||||
wrefresh(logwin);
|
||||
pthread_mutex_unlock(&curses_lock);
|
||||
if (curses_active) {
|
||||
if (!opt_loginput) {
|
||||
pthread_mutex_lock(&curses_lock);
|
||||
vw_printw(logwin, f, ap);
|
||||
wrefresh(logwin);
|
||||
pthread_mutex_unlock(&curses_lock);
|
||||
}
|
||||
} else
|
||||
vprintf(f, ap);
|
||||
}
|
||||
@ -917,9 +917,9 @@ static inline struct pool *select_pool(void)
|
||||
rotating_pool++;
|
||||
if (rotating_pool >= total_pools)
|
||||
rotating_pool = 0;
|
||||
pool = &pools[rotating_pool];
|
||||
pool = pools[rotating_pool];
|
||||
if (!pool->idle && pool->enabled)
|
||||
return &pools[rotating_pool];
|
||||
return pools[rotating_pool];
|
||||
}
|
||||
return current_pool();
|
||||
}
|
||||
@ -1202,32 +1202,57 @@ static int real_staged(void)
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void switch_pools(void)
|
||||
/* Find the pool that currently has the highest priority */
|
||||
static struct pool *priority_pool(int choice)
|
||||
{
|
||||
struct pool *pool, *last_pool;
|
||||
int i, pools_active = 0;
|
||||
struct pool *ret = NULL;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < total_pools; i++) {
|
||||
pool = &pools[i];
|
||||
struct pool *pool = pools[i];
|
||||
|
||||
if (!pool->idle && pool->enabled)
|
||||
pools_active++;
|
||||
if (pool->prio == choice) {
|
||||
ret = pool;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!pools_active) {
|
||||
applog(LOG_ERR, "No pools active, waiting...");
|
||||
goto out;
|
||||
|
||||
if (unlikely(!ret)) {
|
||||
applog(LOG_ERR, "WTF No pool %d found!", choice);
|
||||
return pools[choice];
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void switch_pools(struct pool *selected)
|
||||
{
|
||||
struct pool *pool, *last_pool;
|
||||
int i, pool_no;
|
||||
|
||||
pthread_mutex_lock(&control_lock);
|
||||
last_pool = currentpool;
|
||||
pool_no = currentpool->pool_no;
|
||||
|
||||
/* Switch selected to pool number 0 and move the rest down */
|
||||
if (selected) {
|
||||
if (selected->prio != 0) {
|
||||
for (i = 0; i < total_pools; i++) {
|
||||
pool = pools[i];
|
||||
if (pool->prio < selected->prio)
|
||||
pool->prio++;
|
||||
}
|
||||
selected->prio = 0;
|
||||
}
|
||||
}
|
||||
|
||||
switch (pool_strategy) {
|
||||
/* Both of these set to the master pool */
|
||||
case POOL_FAILOVER:
|
||||
case POOL_LOADBALANCE:
|
||||
for (i = 0; i < total_pools; i++) {
|
||||
if (!pools[i].idle && pools[i].enabled) {
|
||||
pool_no = i;
|
||||
pool = priority_pool(i);
|
||||
if (!pool->idle && pool->enabled) {
|
||||
pool_no = pool->pool_no;
|
||||
break;
|
||||
}
|
||||
}
|
||||
@ -1235,6 +1260,10 @@ static void switch_pools(void)
|
||||
/* Both of these simply increment and cycle */
|
||||
case POOL_ROUNDROBIN:
|
||||
case POOL_ROTATE:
|
||||
if (selected) {
|
||||
pool_no = selected->pool_no;
|
||||
break;
|
||||
}
|
||||
pool_no++;
|
||||
if (pool_no >= total_pools)
|
||||
pool_no = 0;
|
||||
@ -1242,7 +1271,8 @@ static void switch_pools(void)
|
||||
default:
|
||||
break;
|
||||
}
|
||||
currentpool = &pools[pool_no];
|
||||
|
||||
currentpool = pools[pool_no];
|
||||
pool = currentpool;
|
||||
pthread_mutex_unlock(&control_lock);
|
||||
|
||||
@ -1253,7 +1283,7 @@ static void switch_pools(void)
|
||||
pthread_mutex_lock(&qd_lock);
|
||||
total_queued = 0;
|
||||
pthread_mutex_unlock(&qd_lock);
|
||||
out:
|
||||
|
||||
inc_staged(pool, 1, true);
|
||||
}
|
||||
|
||||
@ -1330,27 +1360,95 @@ static void *stage_thread(void *userdata)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static char *curses_input(const char *query);
|
||||
|
||||
static int curses_int(const char *query)
|
||||
{
|
||||
int ret;
|
||||
char *cvar;
|
||||
|
||||
cvar = curses_input(query);
|
||||
ret = atoi(cvar);
|
||||
free(cvar);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static bool input_pool(bool live);
|
||||
|
||||
static void display_pools(void)
|
||||
{
|
||||
int i, cp = current_pool()->pool_no;
|
||||
int i, active = 0;
|
||||
struct pool *pool;
|
||||
int selected;
|
||||
char input;
|
||||
|
||||
opt_loginput = true;
|
||||
updated:
|
||||
clear_logwin();
|
||||
pthread_mutex_lock(&curses_lock);
|
||||
for (i = 0; i < total_pools; i++) {
|
||||
struct pool *pool = &pools[i];
|
||||
pool = pools[i];
|
||||
|
||||
if (i == cp)
|
||||
if (pool == current_pool())
|
||||
wattron(logwin, A_BOLD);
|
||||
if (!pool->enabled)
|
||||
wattron(logwin, A_DIM);
|
||||
wprintw(logwin, "%s Pool %d: %s User:%s\n", pool->enabled? "Enabled" : "Disabled",
|
||||
pool->pool_no, pool->rpc_url, pool->rpc_user);
|
||||
wattroff(logwin, A_BOLD);
|
||||
wattroff(logwin, A_BOLD | A_DIM);
|
||||
}
|
||||
//wprintw(logwin, "[A]dd pool [S]witch pool [D]isable pool [E]nable pool");
|
||||
wprintw(logwin, "Press any key to continue\n");
|
||||
retry:
|
||||
wprintw(logwin, "\n[A]dd pool [S]witch pool [D]isable pool [E]nable pool\n");
|
||||
wprintw(logwin, "Or press any other key to continue\n");
|
||||
wrefresh(logwin);
|
||||
pthread_mutex_unlock(&curses_lock);
|
||||
i = getch();
|
||||
input = getch();
|
||||
|
||||
if (!strncasecmp(&input, "a", 1)) {
|
||||
input_pool(true);
|
||||
goto updated;
|
||||
} else if (!strncasecmp(&input, "s", 1)) {
|
||||
selected = curses_int("Select pool number");
|
||||
if (selected < 0 || selected >= total_pools) {
|
||||
wprintw(logwin, "Invalid selection");
|
||||
goto retry;
|
||||
}
|
||||
pool = pools[selected];
|
||||
pool->enabled = true;
|
||||
switch_pools(pool);
|
||||
goto updated;
|
||||
} else if (!strncasecmp(&input, "d", 1)) {
|
||||
for (i = 0; i < total_pools; i++) {
|
||||
if ((pools[i])->enabled)
|
||||
active++;
|
||||
}
|
||||
if (active <= 1) {
|
||||
wprintw(logwin, "Cannot disable last pool");
|
||||
goto retry;
|
||||
}
|
||||
selected = curses_int("Select pool number");
|
||||
if (selected < 0 || selected >= total_pools) {
|
||||
wprintw(logwin, "Invalid selection");
|
||||
goto retry;
|
||||
}
|
||||
pool = pools[selected];
|
||||
pool->enabled = false;
|
||||
if (pool == current_pool())
|
||||
switch_pools(NULL);
|
||||
goto updated;
|
||||
} else if (!strncasecmp(&input, "e", 1)) {
|
||||
selected = curses_int("Select pool number");
|
||||
if (selected < 0 || selected >= total_pools) {
|
||||
wprintw(logwin, "Invalid selection");
|
||||
goto retry;
|
||||
}
|
||||
pool = pools[selected];
|
||||
pool->enabled = true;
|
||||
if (pool->prio < current_pool()->prio)
|
||||
switch_pools(pool);
|
||||
goto updated;
|
||||
}
|
||||
|
||||
opt_loginput = false;
|
||||
clear_logwin();
|
||||
}
|
||||
@ -1552,6 +1650,7 @@ static bool pool_active(struct pool *pool)
|
||||
return false;
|
||||
}
|
||||
|
||||
applog(LOG_WARNING, "Testing pool %s", pool->rpc_url);
|
||||
val = json_rpc_call(curl, pool->rpc_url, pool->rpc_userpass, rpc_req,
|
||||
true, false, pool);
|
||||
|
||||
@ -1580,9 +1679,11 @@ static bool pool_active(struct pool *pool)
|
||||
free(work);
|
||||
}
|
||||
json_decref(val);
|
||||
} else
|
||||
} else {
|
||||
applog(LOG_DEBUG, "FAILED to retrieve work from pool %u %s",
|
||||
pool->pool_no, pool->rpc_url);
|
||||
applog(LOG_WARNING, "Pool down, URL or credentials invalid");
|
||||
}
|
||||
out:
|
||||
curl_easy_cleanup(curl);
|
||||
return ret;
|
||||
@ -1592,14 +1693,14 @@ static void pool_died(struct pool *pool)
|
||||
{
|
||||
applog(LOG_WARNING, "Pool %d %s not responding!", pool->pool_no, pool->rpc_url);
|
||||
gettimeofday(&pool->tv_idle, NULL);
|
||||
switch_pools();
|
||||
switch_pools(NULL);
|
||||
}
|
||||
|
||||
static void pool_resus(struct pool *pool)
|
||||
{
|
||||
applog(LOG_WARNING, "Pool %d %s recovered", pool->pool_no, pool->rpc_url);
|
||||
if (pool->pool_no < pool_no && pool_strategy == POOL_FAILOVER)
|
||||
switch_pools();
|
||||
if (pool->prio < current_pool()->prio && pool_strategy == POOL_FAILOVER)
|
||||
switch_pools(NULL);
|
||||
}
|
||||
|
||||
static bool queue_request(void)
|
||||
@ -2518,7 +2619,7 @@ static void *watchdog_thread(void *userdata)
|
||||
gettimeofday(&now, NULL);
|
||||
|
||||
for (i = 0; i < total_pools; i++) {
|
||||
struct pool *pool = &pools[i];
|
||||
struct pool *pool = pools[i];
|
||||
|
||||
if (!pool->enabled)
|
||||
continue;
|
||||
@ -2533,7 +2634,7 @@ static void *watchdog_thread(void *userdata)
|
||||
|
||||
if (pool_strategy == POOL_ROTATE && now.tv_sec - rotate_tv.tv_sec > 60 * opt_rotate_period) {
|
||||
gettimeofday(&rotate_tv, NULL);
|
||||
switch_pools();
|
||||
switch_pools(NULL);
|
||||
}
|
||||
|
||||
//for (i = 0; i < mining_threads; i++) {
|
||||
@ -2600,7 +2701,7 @@ static void print_summary(void)
|
||||
|
||||
if (total_pools > 1) {
|
||||
for (i = 0; i < total_pools; i++) {
|
||||
struct pool *pool = &pools[i];
|
||||
struct pool *pool = pools[i];
|
||||
|
||||
printf("Pool: %s\n", pool->rpc_url);
|
||||
printf(" Queued work requests: %d\n", pool->getwork_requested);
|
||||
@ -2647,6 +2748,7 @@ static char *curses_input(const char *query)
|
||||
{
|
||||
char *input;
|
||||
|
||||
echo();
|
||||
input = malloc(255);
|
||||
if (!input)
|
||||
quit(1, "Failed to malloc input");
|
||||
@ -2655,44 +2757,43 @@ static char *curses_input(const char *query)
|
||||
wrefresh(logwin);
|
||||
wgetnstr(logwin, input, 255);
|
||||
leaveok(logwin, true);
|
||||
noecho();
|
||||
return input;
|
||||
}
|
||||
|
||||
static bool input_pool(bool live)
|
||||
{
|
||||
char *url, *user, *pass;
|
||||
int poolno = total_pools;
|
||||
struct pool *pool;
|
||||
bool ret = false;
|
||||
|
||||
echo();
|
||||
immedok(logwin, true);
|
||||
if (total_pools == MAX_POOLS) {
|
||||
wprintw(logwin, "Reached maximum number of pools.\n");
|
||||
goto out;
|
||||
}
|
||||
wprintw(logwin, "Input server details.\n");
|
||||
|
||||
url = curses_input("URL");
|
||||
if (strncmp(url, "http://", 7) &&
|
||||
strncmp(url, "https://", 8)) {
|
||||
applog(LOG_ERR, "URL must start with http:// or https://");
|
||||
return false;
|
||||
goto out;
|
||||
}
|
||||
|
||||
user = curses_input("Username");
|
||||
if (!user)
|
||||
return false;
|
||||
goto out;
|
||||
|
||||
pass = curses_input("Password");
|
||||
if (!pass)
|
||||
return false;
|
||||
goto out;
|
||||
|
||||
wclear(logwin);
|
||||
immedok(logwin, false);
|
||||
noecho();
|
||||
|
||||
pools = realloc(pools, sizeof(struct pool) * (total_pools + 1));
|
||||
if (!pools)
|
||||
quit(1, "Failed to malloc pools in input_pool");
|
||||
pool = &pools[poolno];
|
||||
memset(pool, 0, sizeof(struct pool));
|
||||
pool->pool_no = poolno;
|
||||
pool = calloc(sizeof(struct pool), 1);
|
||||
if (!pool)
|
||||
quit(1, "Failed to realloc pools in input_pool");
|
||||
pool->pool_no = total_pools;
|
||||
pool->prio = total_pools;
|
||||
if (unlikely(pthread_mutex_init(&pool->pool_lock, NULL)))
|
||||
quit (1, "Failed to pthread_mutex_init in input_pool");
|
||||
pool->rpc_url = url;
|
||||
@ -2705,18 +2806,25 @@ static bool input_pool(bool live)
|
||||
|
||||
pool->tv_idle.tv_sec = ~0UL;
|
||||
|
||||
if (!live) {
|
||||
total_pools++;
|
||||
return true;
|
||||
}
|
||||
|
||||
/* Test the pool before we enable it if we're live running*/
|
||||
if (pool_active(pool)) {
|
||||
/* Test the pool before we enable it if we're live running, otherwise
|
||||
* it will be tested separately */
|
||||
ret = true;
|
||||
if (live && pool_active(pool))
|
||||
pool->enabled = true;
|
||||
total_pools++;
|
||||
return true;
|
||||
pools[total_pools++] = pool;
|
||||
out:
|
||||
immedok(logwin, false);
|
||||
|
||||
if (!ret) {
|
||||
free(pool);
|
||||
if (url)
|
||||
free(url);
|
||||
if (user)
|
||||
free(user);
|
||||
if (pass)
|
||||
free(pass);
|
||||
}
|
||||
return false;
|
||||
return ret;
|
||||
}
|
||||
|
||||
int main (int argc, char *argv[])
|
||||
@ -2842,7 +2950,7 @@ int main (int argc, char *argv[])
|
||||
}
|
||||
|
||||
for (i = 0; i < total_pools; i++) {
|
||||
struct pool *pool = &pools[i];
|
||||
struct pool *pool = pools[i];
|
||||
|
||||
if (!pool->rpc_userpass) {
|
||||
if (!pool->rpc_user || !pool->rpc_pass)
|
||||
@ -2861,8 +2969,8 @@ int main (int argc, char *argv[])
|
||||
quit(1, "Failed to find colon delimiter in userpass");
|
||||
}
|
||||
}
|
||||
/* Set the current pool to pool 0 */
|
||||
currentpool = pools;
|
||||
/* Set the currentpool to pool 0 */
|
||||
currentpool = pools[0];
|
||||
|
||||
#ifdef HAVE_SYSLOG_H
|
||||
if (use_syslog)
|
||||
@ -2943,13 +3051,18 @@ int main (int argc, char *argv[])
|
||||
for (i = 0; i < total_pools; i++) {
|
||||
struct pool *pool;
|
||||
|
||||
pool = &pools[i];
|
||||
pool = pools[i];
|
||||
if (pool_active(pool)) {
|
||||
if (!currentpool)
|
||||
currentpool = pool;
|
||||
applog(LOG_INFO, "Pool %d %s active", pool->pool_no, pool->rpc_url);
|
||||
pools_active++;
|
||||
pool->enabled = true;
|
||||
} else
|
||||
} else {
|
||||
if (pool == currentpool)
|
||||
currentpool = NULL;
|
||||
applog(LOG_WARNING, "Unable to get work from pool %d %s", pool->pool_no, pool->rpc_url);
|
||||
}
|
||||
}
|
||||
|
||||
if (!pools_active)
|
||||
@ -3069,8 +3182,6 @@ int main (int argc, char *argv[])
|
||||
free(gpus);
|
||||
if (opt_n_threads)
|
||||
free(cpus);
|
||||
if (pools)
|
||||
free(pools);
|
||||
|
||||
curl_global_cleanup();
|
||||
|
||||
|
1
miner.h
1
miner.h
@ -267,6 +267,7 @@ typedef struct {
|
||||
|
||||
struct pool {
|
||||
int pool_no;
|
||||
int prio;
|
||||
int accepted, rejected;
|
||||
bool submit_fail;
|
||||
bool idle;
|
||||
|
11
util.c
11
util.c
@ -285,8 +285,11 @@ json_t *json_rpc_call(CURL *curl, const char *url,
|
||||
|
||||
/* it is assumed that 'curl' is freshly [re]initialized at this pt */
|
||||
|
||||
if (probe)
|
||||
if (probe) {
|
||||
probing = ((want_longpoll && !have_longpoll) || !pool->probed);
|
||||
/* Probe for only 10 seconds */
|
||||
curl_easy_setopt(curl, CURLOPT_TIMEOUT, 10);
|
||||
}
|
||||
|
||||
if (opt_protocol)
|
||||
curl_easy_setopt(curl, CURLOPT_VERBOSE, 1);
|
||||
@ -409,10 +412,8 @@ err_out:
|
||||
databuf_free(&all_data);
|
||||
curl_slist_free_all(headers);
|
||||
curl_easy_reset(curl);
|
||||
if (!successful_connect) {
|
||||
kill_work();
|
||||
applog(LOG_ERR, "Failed to connect - wrong URL or login details?");
|
||||
}
|
||||
if (!successful_connect)
|
||||
applog(LOG_DEBUG, "Failed to connect in json_rpc_call");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user