mirror of
https://github.com/GOSTSec/ccminer
synced 2025-01-09 06:18:07 +00:00
refactor: move pool functions in pools.cpp
ccminer.cpp begins to be too big...
This commit is contained in:
parent
9f5744d4c0
commit
576884b199
@ -19,7 +19,7 @@ ccminer_SOURCES = elist.h miner.h compat.h \
|
||||
compat/inttypes.h compat/stdbool.h compat/unistd.h \
|
||||
compat/sys/time.h compat/getopt/getopt.h \
|
||||
crc32.c hefty1.c \
|
||||
ccminer.cpp util.cpp bignum.cpp \
|
||||
ccminer.cpp pools.cpp util.cpp bignum.cpp \
|
||||
api.cpp hashlog.cpp nvml.cpp stats.cpp sysinfos.cpp cuda.cpp \
|
||||
heavy/heavy.cu \
|
||||
heavy/cuda_blake512.cu heavy/cuda_blake512.h \
|
||||
|
354
ccminer.cpp
354
ccminer.cpp
@ -23,7 +23,6 @@
|
||||
#include <signal.h>
|
||||
|
||||
#include <curl/curl.h>
|
||||
#include <jansson.h>
|
||||
#include <openssl/sha.h>
|
||||
|
||||
#ifdef WIN32
|
||||
@ -177,10 +176,10 @@ static bool opt_background = false;
|
||||
bool opt_quiet = false;
|
||||
static int opt_retries = -1;
|
||||
static int opt_fail_pause = 30;
|
||||
static int opt_time_limit = -1;
|
||||
static time_t firstwork_time = 0;
|
||||
int opt_time_limit = -1;
|
||||
time_t firstwork_time = 0;
|
||||
int opt_timeout = 60; // curl
|
||||
static int opt_scantime = 10;
|
||||
int opt_scantime = 10;
|
||||
static json_t *opt_config;
|
||||
static const bool opt_time = true;
|
||||
static enum sha_algos opt_algo = ALGO_X11;
|
||||
@ -226,9 +225,9 @@ bool conditional_pool_rotate = false;
|
||||
|
||||
// current connection
|
||||
char *rpc_user = NULL;
|
||||
static char *rpc_pass;
|
||||
char *rpc_pass;
|
||||
char *rpc_url;
|
||||
static char *short_url = NULL;
|
||||
char *short_url = NULL;
|
||||
|
||||
struct stratum_ctx stratum = { 0 };
|
||||
pthread_mutex_t stratum_sock_lock;
|
||||
@ -269,17 +268,6 @@ char *opt_api_allow = strdup("127.0.0.1"); /* 0.0.0.0 for all ips */
|
||||
int opt_api_remote = 0;
|
||||
int opt_api_listen = 4068; /* 0 to disable */
|
||||
|
||||
#ifdef HAVE_GETOPT_LONG
|
||||
#include <getopt.h>
|
||||
#else
|
||||
struct option {
|
||||
const char *name;
|
||||
int has_arg;
|
||||
int *flag;
|
||||
int val;
|
||||
};
|
||||
#endif
|
||||
|
||||
static char const usage[] = "\
|
||||
Usage: " PROGRAM_NAME " [OPTIONS]\n\
|
||||
Options:\n\
|
||||
@ -381,7 +369,7 @@ static char const short_options[] =
|
||||
#endif
|
||||
"a:Bc:i:Dhp:Px:f:m:nqr:R:s:t:T:o:u:O:Vd:N:b:l:L:";
|
||||
|
||||
static struct option const options[] = {
|
||||
struct option options[] = {
|
||||
{ "algo", 1, NULL, 'a' },
|
||||
{ "api-bind", 1, NULL, 'b' },
|
||||
{ "api-remote", 0, NULL, 1030 },
|
||||
@ -456,31 +444,18 @@ Scrypt specific options:\n\
|
||||
--no-autotune disable auto-tuning of kernel launch parameters\n\
|
||||
";
|
||||
|
||||
#define CFG_NULL 0
|
||||
#define CFG_POOL 1
|
||||
struct opt_config_array {
|
||||
int cat;
|
||||
const char *name; // json key
|
||||
const char *longname; // global opt name if different
|
||||
} cfg_array_keys[] = {
|
||||
{ CFG_POOL, "url", NULL }, /* let this key first, increment pools */
|
||||
{ CFG_POOL, "user", NULL },
|
||||
{ CFG_POOL, "pass", NULL },
|
||||
{ CFG_POOL, "userpass", NULL },
|
||||
{ CFG_POOL, "name", "pool-name" },
|
||||
{ CFG_POOL, "scantime", "pool-scantime" },
|
||||
{ CFG_POOL, "max-diff", "pool-max-diff" },
|
||||
{ CFG_POOL, "max-rate", "pool-max-rate" },
|
||||
{ CFG_POOL, "removed", "pool-removed" },
|
||||
{ CFG_POOL, "disabled", "pool-removed" }, // sample alias
|
||||
{ CFG_POOL, "time-limit", "pool-time-limit" },
|
||||
{ CFG_NULL, NULL, NULL }
|
||||
};
|
||||
|
||||
struct work _ALIGN(64) g_work;
|
||||
volatile time_t g_work_time;
|
||||
pthread_mutex_t g_work_lock;
|
||||
|
||||
// get const array size (defined in ccminer.cpp)
|
||||
int options_count()
|
||||
{
|
||||
int n = 0;
|
||||
while (options[n].name != NULL)
|
||||
n++;
|
||||
return n;
|
||||
}
|
||||
|
||||
#ifdef __linux /* Linux specific policy and affinity management */
|
||||
#include <sched.h>
|
||||
@ -1275,7 +1250,7 @@ static void *workio_thread(void *userdata)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static bool get_work(struct thr_info *thr, struct work *work)
|
||||
bool get_work(struct thr_info *thr, struct work *work)
|
||||
{
|
||||
struct workio_cmd *wc;
|
||||
struct work *work_heap;
|
||||
@ -2402,236 +2377,6 @@ pool_switched:
|
||||
goto wait_stratum_url;
|
||||
}
|
||||
|
||||
// store current credentials in pools container
|
||||
void pool_set_creds(int pooln)
|
||||
{
|
||||
struct pool_infos *p = &pools[pooln];
|
||||
|
||||
snprintf(p->url, sizeof(p->url), "%s", rpc_url);
|
||||
snprintf(p->short_url, sizeof(p->short_url), "%s", short_url);
|
||||
snprintf(p->user, sizeof(p->user), "%s", rpc_user);
|
||||
snprintf(p->pass, sizeof(p->pass), "%s", rpc_pass);
|
||||
|
||||
if (!(p->status & POOL_ST_DEFINED)) {
|
||||
p->id = pooln;
|
||||
p->status |= POOL_ST_DEFINED;
|
||||
// init pool options as "unset"
|
||||
// until cmdline is not fully parsed...
|
||||
p->max_diff = -1.;
|
||||
p->max_rate = -1.;
|
||||
p->scantime = -1;
|
||||
p->time_limit = -1;
|
||||
|
||||
p->allow_mininginfo = allow_mininginfo;
|
||||
p->allow_gbt = allow_gbt;
|
||||
p->check_dups = check_dups;
|
||||
|
||||
p->status |= POOL_ST_DEFINED;
|
||||
}
|
||||
|
||||
if (strlen(rpc_url)) {
|
||||
if (!strncasecmp(rpc_url, "stratum", 7))
|
||||
p->type = POOL_STRATUM;
|
||||
else /* if (!strncasecmp(rpc_url, "http", 4)) */
|
||||
p->type = POOL_GETWORK; // todo: or longpoll
|
||||
p->status |= POOL_ST_VALID;
|
||||
}
|
||||
}
|
||||
|
||||
// fill the unset pools options with cmdline ones
|
||||
void pool_init_defaults()
|
||||
{
|
||||
struct pool_infos *p;
|
||||
for (int i=0; i<num_pools; i++) {
|
||||
p = &pools[i];
|
||||
if (p->max_diff <= -1.) p->max_diff = opt_max_diff;
|
||||
if (p->max_rate <= -1.) p->max_rate = opt_max_rate;
|
||||
if (p->scantime == -1) p->scantime = opt_scantime;
|
||||
if (p->time_limit == -1) p->time_limit = opt_time_limit;
|
||||
}
|
||||
}
|
||||
|
||||
// attributes only set by a json pools config
|
||||
void pool_set_attr(int pooln, const char* key, char* arg)
|
||||
{
|
||||
struct pool_infos *p = &pools[pooln];
|
||||
|
||||
if (!strcasecmp(key, "name")) {
|
||||
snprintf(p->name, sizeof(p->name), "%s", arg);
|
||||
return;
|
||||
}
|
||||
if (!strcasecmp(key, "scantime")) {
|
||||
p->scantime = atoi(arg);
|
||||
return;
|
||||
}
|
||||
if (!strcasecmp(key, "max-diff")) {
|
||||
p->max_diff = atof(arg);
|
||||
return;
|
||||
}
|
||||
if (!strcasecmp(key, "max-rate")) {
|
||||
p->max_rate = atof(arg);
|
||||
return;
|
||||
}
|
||||
if (!strcasecmp(key, "time-limit")) {
|
||||
p->time_limit = atoi(arg);
|
||||
return;
|
||||
}
|
||||
if (!strcasecmp(key, "removed")) {
|
||||
int removed = atoi(arg);
|
||||
if (removed) {
|
||||
p->status |= POOL_ST_REMOVED;
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// pool switching code
|
||||
bool pool_switch(int pooln)
|
||||
{
|
||||
int prevn = cur_pooln;
|
||||
struct pool_infos *prev = &pools[cur_pooln];
|
||||
struct pool_infos* p = NULL;
|
||||
|
||||
// save prev stratum connection infos (struct)
|
||||
if (prev->type & POOL_STRATUM) {
|
||||
// may not be the right moment to free,
|
||||
// to check if required on submit...
|
||||
stratum_free_job(&stratum);
|
||||
prev->stratum = stratum;
|
||||
}
|
||||
|
||||
if (pooln < num_pools) {
|
||||
cur_pooln = pooln;
|
||||
p = &pools[cur_pooln];
|
||||
} else {
|
||||
applog(LOG_ERR, "Switch to inexistant pool %d!", pooln);
|
||||
return false;
|
||||
}
|
||||
|
||||
// save global attributes
|
||||
prev->allow_mininginfo = allow_mininginfo;
|
||||
prev->allow_gbt = allow_gbt;
|
||||
prev->check_dups = check_dups;
|
||||
|
||||
pthread_mutex_lock(&stratum_work_lock);
|
||||
|
||||
free(rpc_user); rpc_user = strdup(p->user);
|
||||
free(rpc_pass); rpc_pass = strdup(p->pass);
|
||||
free(rpc_url); rpc_url = strdup(p->url);
|
||||
|
||||
short_url = p->short_url; // just a pointer, no alloc
|
||||
|
||||
opt_scantime = p->scantime;
|
||||
opt_max_diff = p->max_diff;
|
||||
opt_max_rate = p->max_rate;
|
||||
opt_time_limit = p->time_limit;
|
||||
|
||||
want_stratum = have_stratum = (p->type & POOL_STRATUM) != 0;
|
||||
|
||||
pthread_mutex_unlock(&stratum_work_lock);
|
||||
|
||||
if (prevn != cur_pooln) {
|
||||
|
||||
pool_switch_count++;
|
||||
g_work_time = 0;
|
||||
g_work.data[0] = 0;
|
||||
pool_is_switching = true;
|
||||
stratum_need_reset = true;
|
||||
// used to get the pool uptime
|
||||
firstwork_time = time(NULL);
|
||||
restart_threads();
|
||||
|
||||
// restore flags
|
||||
allow_gbt = p->allow_gbt;
|
||||
allow_mininginfo = p->allow_mininginfo;
|
||||
check_dups = p->check_dups;
|
||||
|
||||
if (want_stratum) {
|
||||
|
||||
// temporary... until stratum code cleanup
|
||||
stratum = p->stratum;
|
||||
stratum.pooln = cur_pooln;
|
||||
|
||||
// unlock the stratum thread
|
||||
tq_push(thr_info[stratum_thr_id].q, strdup(rpc_url));
|
||||
applog(LOG_BLUE, "Switch to stratum pool %d: %s", cur_pooln,
|
||||
strlen(p->name) ? p->name : p->short_url);
|
||||
} else {
|
||||
applog(LOG_BLUE, "Switch to pool %d: %s", cur_pooln,
|
||||
strlen(p->name) ? p->name : p->short_url);
|
||||
}
|
||||
|
||||
// will unlock the longpoll thread on /LP url receive
|
||||
want_longpoll = (p->type & POOL_LONGPOLL) || !(p->type & POOL_STRATUM);
|
||||
if (want_longpoll) {
|
||||
pthread_mutex_lock(&stratum_work_lock);
|
||||
// will issue a lp_url request to unlock the longpoll thread
|
||||
have_longpoll = false;
|
||||
get_work(&thr_info[0], &g_work);
|
||||
pthread_mutex_unlock(&stratum_work_lock);
|
||||
}
|
||||
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
// search available pool
|
||||
int pool_get_first_valid(int startfrom)
|
||||
{
|
||||
int next = 0;
|
||||
struct pool_infos *p;
|
||||
for (int i=0; i<num_pools; i++) {
|
||||
int pooln = (startfrom + i) % num_pools;
|
||||
p = &pools[pooln];
|
||||
if (!(p->status & POOL_ST_VALID))
|
||||
continue;
|
||||
if (p->status & (POOL_ST_DISABLED | POOL_ST_REMOVED))
|
||||
continue;
|
||||
next = pooln;
|
||||
break;
|
||||
}
|
||||
return next;
|
||||
}
|
||||
|
||||
// switch to next available pool
|
||||
bool pool_switch_next()
|
||||
{
|
||||
if (num_pools > 1) {
|
||||
int pooln = pool_get_first_valid(cur_pooln+1);
|
||||
return pool_switch(pooln);
|
||||
} else {
|
||||
// no switch possible
|
||||
if (!opt_quiet)
|
||||
applog(LOG_DEBUG, "No other pools to try...");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// seturl from api remote
|
||||
bool pool_switch_url(char *params)
|
||||
{
|
||||
int prevn = cur_pooln, nextn;
|
||||
parse_arg('o', params);
|
||||
// cur_pooln modified by parse_arg('o'), get new pool num
|
||||
nextn = cur_pooln;
|
||||
// and to handle the "hot swap" from current one...
|
||||
cur_pooln = prevn;
|
||||
if (nextn == prevn)
|
||||
return false;
|
||||
return pool_switch(nextn);
|
||||
}
|
||||
|
||||
// debug stuff
|
||||
void pool_dump_infos()
|
||||
{
|
||||
struct pool_infos *p;
|
||||
for (int i=0; i<num_pools; i++) {
|
||||
p = &pools[i];
|
||||
applog(LOG_DEBUG, "POOL %01d: %s USER %s -s %d", i,
|
||||
p->short_url, p->user, p->scantime);
|
||||
}
|
||||
}
|
||||
|
||||
static void show_version_and_exit(void)
|
||||
{
|
||||
printf("%s v%s\n"
|
||||
@ -3130,75 +2875,6 @@ void parse_arg(int key, char *arg)
|
||||
use_colors = false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse json config
|
||||
*/
|
||||
static bool parse_pool_array(json_t *obj)
|
||||
{
|
||||
size_t idx;
|
||||
json_t *p, *val;
|
||||
|
||||
if (!json_is_array(obj))
|
||||
return false;
|
||||
|
||||
// array of objects [ {}, {} ]
|
||||
json_array_foreach(obj, idx, p)
|
||||
{
|
||||
if (!json_is_object(p))
|
||||
continue;
|
||||
|
||||
for (int i = 0; i < ARRAY_SIZE(cfg_array_keys); i++)
|
||||
{
|
||||
int opt = -1;
|
||||
char *s = NULL;
|
||||
if (cfg_array_keys[i].cat != CFG_POOL)
|
||||
continue;
|
||||
|
||||
val = json_object_get(p, cfg_array_keys[i].name);
|
||||
if (!val)
|
||||
continue;
|
||||
|
||||
for (int k = 0; k < ARRAY_SIZE(options); k++)
|
||||
{
|
||||
const char *alias = cfg_array_keys[i].longname;
|
||||
if (alias && !strcasecmp(options[k].name, alias)) {
|
||||
opt = k;
|
||||
break;
|
||||
}
|
||||
if (!alias && !strcasecmp(options[k].name, cfg_array_keys[i].name)) {
|
||||
opt = k;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (opt == -1)
|
||||
continue;
|
||||
|
||||
if (json_is_string(val)) {
|
||||
s = strdup(json_string_value(val));
|
||||
if (!s)
|
||||
continue;
|
||||
|
||||
// applog(LOG_DEBUG, "pool key %s '%s'", options[opt].name, s);
|
||||
parse_arg(options[opt].val, s);
|
||||
free(s);
|
||||
} else {
|
||||
// numeric or bool
|
||||
char buf[32] = { 0 };
|
||||
double d = 0.;
|
||||
if (json_is_true(val)) d = 1.;
|
||||
else if (json_is_integer(val))
|
||||
d = 1.0 * json_integer_value(val);
|
||||
else if (json_is_real(val))
|
||||
d = json_real_value(val);
|
||||
snprintf(buf, sizeof(buf)-1, "%f", d);
|
||||
// applog(LOG_DEBUG, "pool key %s '%f'", options[opt].name, d);
|
||||
parse_arg(options[opt].val, buf);
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void parse_config(json_t* json_obj)
|
||||
{
|
||||
int i;
|
||||
|
@ -227,8 +227,7 @@
|
||||
<TreatWChar_tAsBuiltInType>false</TreatWChar_tAsBuiltInType>
|
||||
<Optimization Condition="'$(Configuration)'=='Release'">Full</Optimization>
|
||||
</ClCompile>
|
||||
<ClCompile Include="scrypt-jane.cpp" />
|
||||
<ClCompile Include="scrypt.cpp" />
|
||||
<ClCompile Include="pools.cpp" />
|
||||
<ClCompile Include="util.cpp" />
|
||||
<ClCompile Include="bignum.cpp" />
|
||||
<ClInclude Include="bignum.hpp" />
|
||||
@ -249,6 +248,8 @@
|
||||
<ClCompile Include="neoscrypt\neoscrypt-cpu.c" />
|
||||
<ClInclude Include="neoscrypt\cuda_vectors.h" />
|
||||
<CudaCompile Include="neoscrypt\cuda_neoscrypt.cu" />
|
||||
<ClCompile Include="scrypt-jane.cpp" />
|
||||
<ClCompile Include="scrypt.cpp" />
|
||||
<ClCompile Include="skein2.cpp" />
|
||||
<ClCompile Include="sph\aes_helper.c" />
|
||||
<ClCompile Include="sph\blake.c" />
|
||||
|
@ -111,6 +111,9 @@
|
||||
<ClCompile Include="ccminer.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="pools.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="crc32.c">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
@ -653,4 +656,4 @@
|
||||
<Filter>Ressources</Filter>
|
||||
</Text>
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
</Project>
|
||||
|
17
miner.h
17
miner.h
@ -469,6 +469,18 @@ struct work_restart {
|
||||
char padding[128 - sizeof(uint32_t)];
|
||||
};
|
||||
|
||||
#ifdef HAVE_GETOPT_LONG
|
||||
#include <getopt.h>
|
||||
#else
|
||||
struct option {
|
||||
const char *name;
|
||||
int has_arg;
|
||||
int *flag;
|
||||
int val;
|
||||
};
|
||||
#endif
|
||||
extern int options_count();
|
||||
|
||||
extern bool opt_benchmark;
|
||||
extern bool opt_debug;
|
||||
extern bool opt_quiet;
|
||||
@ -680,12 +692,15 @@ extern struct pool_infos pools[MAX_POOLS];
|
||||
extern int num_pools;
|
||||
extern volatile int cur_pooln;
|
||||
|
||||
int pool_get_first_valid(int startfrom);
|
||||
void pool_init_defaults(void);
|
||||
void pool_set_creds(int pooln);
|
||||
void pool_set_attr(int pooln, const char* key, char* arg);
|
||||
bool pool_switch_url(char *params);
|
||||
bool pool_switch(int pooln);
|
||||
bool pool_switch_next(void);
|
||||
int pool_get_first_valid(int startfrom);
|
||||
bool parse_pool_array(json_t *obj);
|
||||
void pool_dump_infos(void);
|
||||
|
||||
json_t * json_rpc_call_pool(CURL *curl, struct pool_infos*,
|
||||
const char *req, bool lp_scan, bool lp, int *err);
|
||||
|
357
pools.cpp
Normal file
357
pools.cpp
Normal file
@ -0,0 +1,357 @@
|
||||
/**
|
||||
* Functions which handle multiple pools data
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "miner.h"
|
||||
#include "compat.h"
|
||||
|
||||
// to move in miner.h
|
||||
extern bool allow_gbt;
|
||||
extern bool allow_mininginfo;
|
||||
extern bool check_dups;
|
||||
|
||||
extern double opt_max_diff;
|
||||
extern double opt_max_rate;
|
||||
extern int opt_scantime;
|
||||
extern int opt_time_limit;
|
||||
|
||||
extern char* rpc_url;
|
||||
extern char* rpc_user;
|
||||
extern char* rpc_pass;
|
||||
extern char* short_url;
|
||||
|
||||
extern struct work _ALIGN(64) g_work;
|
||||
extern struct stratum_ctx stratum;
|
||||
extern pthread_mutex_t stratum_work_lock;
|
||||
extern bool get_work(struct thr_info *thr, struct work *work);
|
||||
extern bool stratum_need_reset;
|
||||
extern time_t firstwork_time;
|
||||
|
||||
extern volatile time_t g_work_time;
|
||||
extern volatile int pool_switch_count;
|
||||
extern volatile bool pool_is_switching;
|
||||
|
||||
extern struct option options[];
|
||||
|
||||
#define CFG_NULL 0
|
||||
#define CFG_POOL 1
|
||||
struct opt_config_array {
|
||||
int cat;
|
||||
const char *name; // json key
|
||||
const char *longname; // global opt name if different
|
||||
} cfg_array_keys[] = {
|
||||
{ CFG_POOL, "url", NULL }, /* let this key first, increment pools */
|
||||
{ CFG_POOL, "user", NULL },
|
||||
{ CFG_POOL, "pass", NULL },
|
||||
{ CFG_POOL, "userpass", NULL },
|
||||
{ CFG_POOL, "name", "pool-name" },
|
||||
{ CFG_POOL, "scantime", "pool-scantime" },
|
||||
{ CFG_POOL, "max-diff", "pool-max-diff" },
|
||||
{ CFG_POOL, "max-rate", "pool-max-rate" },
|
||||
{ CFG_POOL, "removed", "pool-removed" },
|
||||
{ CFG_POOL, "disabled", "pool-removed" }, // sample alias
|
||||
{ CFG_POOL, "time-limit", "pool-time-limit" },
|
||||
{ CFG_NULL, NULL, NULL }
|
||||
};
|
||||
|
||||
// store current credentials in pools container
|
||||
void pool_set_creds(int pooln)
|
||||
{
|
||||
struct pool_infos *p = &pools[pooln];
|
||||
|
||||
snprintf(p->url, sizeof(p->url), "%s", rpc_url);
|
||||
snprintf(p->short_url, sizeof(p->short_url), "%s", short_url);
|
||||
snprintf(p->user, sizeof(p->user), "%s", rpc_user);
|
||||
snprintf(p->pass, sizeof(p->pass), "%s", rpc_pass);
|
||||
|
||||
if (!(p->status & POOL_ST_DEFINED)) {
|
||||
p->id = pooln;
|
||||
p->status |= POOL_ST_DEFINED;
|
||||
// init pool options as "unset"
|
||||
// until cmdline is not fully parsed...
|
||||
p->max_diff = -1.;
|
||||
p->max_rate = -1.;
|
||||
p->scantime = -1;
|
||||
p->time_limit = -1;
|
||||
|
||||
p->allow_mininginfo = allow_mininginfo;
|
||||
p->allow_gbt = allow_gbt;
|
||||
p->check_dups = check_dups;
|
||||
|
||||
p->status |= POOL_ST_DEFINED;
|
||||
}
|
||||
|
||||
if (strlen(rpc_url)) {
|
||||
if (!strncasecmp(rpc_url, "stratum", 7))
|
||||
p->type = POOL_STRATUM;
|
||||
else /* if (!strncasecmp(rpc_url, "http", 4)) */
|
||||
p->type = POOL_GETWORK; // todo: or longpoll
|
||||
p->status |= POOL_ST_VALID;
|
||||
}
|
||||
}
|
||||
|
||||
// fill the unset pools options with cmdline ones
|
||||
void pool_init_defaults()
|
||||
{
|
||||
struct pool_infos *p;
|
||||
for (int i=0; i<num_pools; i++) {
|
||||
p = &pools[i];
|
||||
if (p->max_diff == -1.) p->max_diff = opt_max_diff;
|
||||
if (p->max_rate == -1.) p->max_rate = opt_max_rate;
|
||||
if (p->scantime == -1) p->scantime = opt_scantime;
|
||||
if (p->time_limit == -1) p->time_limit = opt_time_limit;
|
||||
}
|
||||
}
|
||||
|
||||
// attributes only set by a json pools config
|
||||
void pool_set_attr(int pooln, const char* key, char* arg)
|
||||
{
|
||||
struct pool_infos *p = &pools[pooln];
|
||||
|
||||
if (!strcasecmp(key, "name")) {
|
||||
snprintf(p->name, sizeof(p->name), "%s", arg);
|
||||
return;
|
||||
}
|
||||
if (!strcasecmp(key, "scantime")) {
|
||||
p->scantime = atoi(arg);
|
||||
return;
|
||||
}
|
||||
if (!strcasecmp(key, "max-diff")) {
|
||||
p->max_diff = atof(arg);
|
||||
return;
|
||||
}
|
||||
if (!strcasecmp(key, "max-rate")) {
|
||||
p->max_rate = atof(arg);
|
||||
return;
|
||||
}
|
||||
if (!strcasecmp(key, "time-limit")) {
|
||||
p->time_limit = atoi(arg);
|
||||
return;
|
||||
}
|
||||
if (!strcasecmp(key, "removed")) {
|
||||
int removed = atoi(arg);
|
||||
if (removed) {
|
||||
p->status |= POOL_ST_REMOVED;
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// pool switching code
|
||||
bool pool_switch(int pooln)
|
||||
{
|
||||
int prevn = cur_pooln;
|
||||
struct pool_infos *prev = &pools[cur_pooln];
|
||||
struct pool_infos* p = NULL;
|
||||
|
||||
// save prev stratum connection infos (struct)
|
||||
if (prev->type & POOL_STRATUM) {
|
||||
// may not be the right moment to free,
|
||||
// to check if required on submit...
|
||||
stratum_free_job(&stratum);
|
||||
prev->stratum = stratum;
|
||||
}
|
||||
|
||||
if (pooln < num_pools) {
|
||||
cur_pooln = pooln;
|
||||
p = &pools[cur_pooln];
|
||||
} else {
|
||||
applog(LOG_ERR, "Switch to inexistant pool %d!", pooln);
|
||||
return false;
|
||||
}
|
||||
|
||||
// save global attributes
|
||||
prev->allow_mininginfo = allow_mininginfo;
|
||||
prev->allow_gbt = allow_gbt;
|
||||
prev->check_dups = check_dups;
|
||||
|
||||
pthread_mutex_lock(&stratum_work_lock);
|
||||
|
||||
free(rpc_user); rpc_user = strdup(p->user);
|
||||
free(rpc_pass); rpc_pass = strdup(p->pass);
|
||||
free(rpc_url); rpc_url = strdup(p->url);
|
||||
|
||||
short_url = p->short_url; // just a pointer, no alloc
|
||||
|
||||
opt_scantime = p->scantime;
|
||||
opt_max_diff = p->max_diff;
|
||||
opt_max_rate = p->max_rate;
|
||||
opt_time_limit = p->time_limit;
|
||||
|
||||
want_stratum = have_stratum = (p->type & POOL_STRATUM) != 0;
|
||||
|
||||
pthread_mutex_unlock(&stratum_work_lock);
|
||||
|
||||
if (prevn != cur_pooln) {
|
||||
|
||||
pool_switch_count++;
|
||||
g_work_time = 0;
|
||||
g_work.data[0] = 0;
|
||||
pool_is_switching = true;
|
||||
stratum_need_reset = true;
|
||||
// used to get the pool uptime
|
||||
firstwork_time = time(NULL);
|
||||
restart_threads();
|
||||
|
||||
// restore flags
|
||||
allow_gbt = p->allow_gbt;
|
||||
allow_mininginfo = p->allow_mininginfo;
|
||||
check_dups = p->check_dups;
|
||||
|
||||
if (want_stratum) {
|
||||
|
||||
// temporary... until stratum code cleanup
|
||||
stratum = p->stratum;
|
||||
stratum.pooln = cur_pooln;
|
||||
|
||||
// unlock the stratum thread
|
||||
tq_push(thr_info[stratum_thr_id].q, strdup(rpc_url));
|
||||
applog(LOG_BLUE, "Switch to stratum pool %d: %s", cur_pooln,
|
||||
strlen(p->name) ? p->name : p->short_url);
|
||||
} else {
|
||||
applog(LOG_BLUE, "Switch to pool %d: %s", cur_pooln,
|
||||
strlen(p->name) ? p->name : p->short_url);
|
||||
}
|
||||
|
||||
// will unlock the longpoll thread on /LP url receive
|
||||
want_longpoll = (p->type & POOL_LONGPOLL) || !(p->type & POOL_STRATUM);
|
||||
if (want_longpoll) {
|
||||
pthread_mutex_lock(&stratum_work_lock);
|
||||
// will issue a lp_url request to unlock the longpoll thread
|
||||
have_longpoll = false;
|
||||
get_work(&thr_info[0], &g_work);
|
||||
pthread_mutex_unlock(&stratum_work_lock);
|
||||
}
|
||||
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
// search available pool
|
||||
int pool_get_first_valid(int startfrom)
|
||||
{
|
||||
int next = 0;
|
||||
struct pool_infos *p;
|
||||
for (int i=0; i<num_pools; i++) {
|
||||
int pooln = (startfrom + i) % num_pools;
|
||||
p = &pools[pooln];
|
||||
if (!(p->status & POOL_ST_VALID))
|
||||
continue;
|
||||
if (p->status & (POOL_ST_DISABLED | POOL_ST_REMOVED))
|
||||
continue;
|
||||
next = pooln;
|
||||
break;
|
||||
}
|
||||
return next;
|
||||
}
|
||||
|
||||
// switch to next available pool
|
||||
bool pool_switch_next()
|
||||
{
|
||||
if (num_pools > 1) {
|
||||
int pooln = pool_get_first_valid(cur_pooln+1);
|
||||
return pool_switch(pooln);
|
||||
} else {
|
||||
// no switch possible
|
||||
if (!opt_quiet)
|
||||
applog(LOG_DEBUG, "No other pools to try...");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// seturl from api remote (deprecated)
|
||||
bool pool_switch_url(char *params)
|
||||
{
|
||||
int prevn = cur_pooln, nextn;
|
||||
parse_arg('o', params);
|
||||
// cur_pooln modified by parse_arg('o'), get new pool num
|
||||
nextn = cur_pooln;
|
||||
// and to handle the "hot swap" from current one...
|
||||
cur_pooln = prevn;
|
||||
if (nextn == prevn)
|
||||
return false;
|
||||
return pool_switch(nextn);
|
||||
}
|
||||
|
||||
// Parse pools array in json config
|
||||
bool parse_pool_array(json_t *obj)
|
||||
{
|
||||
size_t idx;
|
||||
json_t *p, *val;
|
||||
|
||||
if (!json_is_array(obj))
|
||||
return false;
|
||||
|
||||
// array of objects [ {}, {} ]
|
||||
json_array_foreach(obj, idx, p)
|
||||
{
|
||||
if (!json_is_object(p))
|
||||
continue;
|
||||
|
||||
for (int i = 0; i < ARRAY_SIZE(cfg_array_keys); i++)
|
||||
{
|
||||
int opt = -1;
|
||||
char *s = NULL;
|
||||
if (cfg_array_keys[i].cat != CFG_POOL)
|
||||
continue;
|
||||
|
||||
val = json_object_get(p, cfg_array_keys[i].name);
|
||||
if (!val)
|
||||
continue;
|
||||
|
||||
for (int k = 0; k < options_count(); k++)
|
||||
{
|
||||
const char *alias = cfg_array_keys[i].longname;
|
||||
if (alias && !strcasecmp(options[k].name, alias)) {
|
||||
opt = k;
|
||||
break;
|
||||
}
|
||||
if (!alias && !strcasecmp(options[k].name, cfg_array_keys[i].name)) {
|
||||
opt = k;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (opt == -1)
|
||||
continue;
|
||||
|
||||
if (json_is_string(val)) {
|
||||
s = strdup(json_string_value(val));
|
||||
if (!s)
|
||||
continue;
|
||||
|
||||
// applog(LOG_DEBUG, "pool key %s '%s'", options[opt].name, s);
|
||||
parse_arg(options[opt].val, s);
|
||||
free(s);
|
||||
} else {
|
||||
// numeric or bool
|
||||
char buf[32] = { 0 };
|
||||
double d = 0.;
|
||||
if (json_is_true(val)) d = 1.;
|
||||
else if (json_is_integer(val))
|
||||
d = 1.0 * json_integer_value(val);
|
||||
else if (json_is_real(val))
|
||||
d = json_real_value(val);
|
||||
snprintf(buf, sizeof(buf)-1, "%f", d);
|
||||
// applog(LOG_DEBUG, "pool key %s '%f'", options[opt].name, d);
|
||||
parse_arg(options[opt].val, buf);
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
// debug stuff
|
||||
void pool_dump_infos()
|
||||
{
|
||||
struct pool_infos *p;
|
||||
for (int i=0; i<num_pools; i++) {
|
||||
p = &pools[i];
|
||||
applog(LOG_DEBUG, "POOL %01d: %s USER %s -s %d", i,
|
||||
p->short_url, p->user, p->scantime);
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user