Browse Source

refactor: move pool functions in pools.cpp

ccminer.cpp begins to be too big...
master
Tanguy Pruvot 10 years ago
parent
commit
576884b199
  1. 2
      Makefile.am
  2. 354
      ccminer.cpp
  3. 5
      ccminer.vcxproj
  4. 5
      ccminer.vcxproj.filters
  5. 17
      miner.h
  6. 357
      pools.cpp

2
Makefile.am

@ -19,7 +19,7 @@ ccminer_SOURCES = elist.h miner.h compat.h \
compat/inttypes.h compat/stdbool.h compat/unistd.h \ compat/inttypes.h compat/stdbool.h compat/unistd.h \
compat/sys/time.h compat/getopt/getopt.h \ compat/sys/time.h compat/getopt/getopt.h \
crc32.c hefty1.c \ 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 \ api.cpp hashlog.cpp nvml.cpp stats.cpp sysinfos.cpp cuda.cpp \
heavy/heavy.cu \ heavy/heavy.cu \
heavy/cuda_blake512.cu heavy/cuda_blake512.h \ heavy/cuda_blake512.cu heavy/cuda_blake512.h \

354
ccminer.cpp

@ -23,7 +23,6 @@
#include <signal.h> #include <signal.h>
#include <curl/curl.h> #include <curl/curl.h>
#include <jansson.h>
#include <openssl/sha.h> #include <openssl/sha.h>
#ifdef WIN32 #ifdef WIN32
@ -177,10 +176,10 @@ static bool opt_background = false;
bool opt_quiet = false; bool opt_quiet = false;
static int opt_retries = -1; static int opt_retries = -1;
static int opt_fail_pause = 30; static int opt_fail_pause = 30;
static int opt_time_limit = -1; int opt_time_limit = -1;
static time_t firstwork_time = 0; time_t firstwork_time = 0;
int opt_timeout = 60; // curl int opt_timeout = 60; // curl
static int opt_scantime = 10; int opt_scantime = 10;
static json_t *opt_config; static json_t *opt_config;
static const bool opt_time = true; static const bool opt_time = true;
static enum sha_algos opt_algo = ALGO_X11; static enum sha_algos opt_algo = ALGO_X11;
@ -226,9 +225,9 @@ bool conditional_pool_rotate = false;
// current connection // current connection
char *rpc_user = NULL; char *rpc_user = NULL;
static char *rpc_pass; char *rpc_pass;
char *rpc_url; char *rpc_url;
static char *short_url = NULL; char *short_url = NULL;
struct stratum_ctx stratum = { 0 }; struct stratum_ctx stratum = { 0 };
pthread_mutex_t stratum_sock_lock; 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_remote = 0;
int opt_api_listen = 4068; /* 0 to disable */ 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[] = "\ static char const usage[] = "\
Usage: " PROGRAM_NAME " [OPTIONS]\n\ Usage: " PROGRAM_NAME " [OPTIONS]\n\
Options:\n\ Options:\n\
@ -381,7 +369,7 @@ static char const short_options[] =
#endif #endif
"a:Bc:i:Dhp:Px:f:m:nqr:R:s:t:T:o:u:O:Vd:N:b:l:L:"; "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' }, { "algo", 1, NULL, 'a' },
{ "api-bind", 1, NULL, 'b' }, { "api-bind", 1, NULL, 'b' },
{ "api-remote", 0, NULL, 1030 }, { "api-remote", 0, NULL, 1030 },
@ -456,31 +444,18 @@ Scrypt specific options:\n\
--no-autotune disable auto-tuning of kernel launch parameters\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; struct work _ALIGN(64) g_work;
volatile time_t g_work_time; volatile time_t g_work_time;
pthread_mutex_t g_work_lock; 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 */ #ifdef __linux /* Linux specific policy and affinity management */
#include <sched.h> #include <sched.h>
@ -1275,7 +1250,7 @@ static void *workio_thread(void *userdata)
return NULL; 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 workio_cmd *wc;
struct work *work_heap; struct work *work_heap;
@ -2402,236 +2377,6 @@ pool_switched:
goto wait_stratum_url; 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) static void show_version_and_exit(void)
{ {
printf("%s v%s\n" printf("%s v%s\n"
@ -3130,75 +2875,6 @@ void parse_arg(int key, char *arg)
use_colors = false; 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) void parse_config(json_t* json_obj)
{ {
int i; int i;

5
ccminer.vcxproj

@ -227,8 +227,7 @@
<TreatWChar_tAsBuiltInType>false</TreatWChar_tAsBuiltInType> <TreatWChar_tAsBuiltInType>false</TreatWChar_tAsBuiltInType>
<Optimization Condition="'$(Configuration)'=='Release'">Full</Optimization> <Optimization Condition="'$(Configuration)'=='Release'">Full</Optimization>
</ClCompile> </ClCompile>
<ClCompile Include="scrypt-jane.cpp" /> <ClCompile Include="pools.cpp" />
<ClCompile Include="scrypt.cpp" />
<ClCompile Include="util.cpp" /> <ClCompile Include="util.cpp" />
<ClCompile Include="bignum.cpp" /> <ClCompile Include="bignum.cpp" />
<ClInclude Include="bignum.hpp" /> <ClInclude Include="bignum.hpp" />
@ -249,6 +248,8 @@
<ClCompile Include="neoscrypt\neoscrypt-cpu.c" /> <ClCompile Include="neoscrypt\neoscrypt-cpu.c" />
<ClInclude Include="neoscrypt\cuda_vectors.h" /> <ClInclude Include="neoscrypt\cuda_vectors.h" />
<CudaCompile Include="neoscrypt\cuda_neoscrypt.cu" /> <CudaCompile Include="neoscrypt\cuda_neoscrypt.cu" />
<ClCompile Include="scrypt-jane.cpp" />
<ClCompile Include="scrypt.cpp" />
<ClCompile Include="skein2.cpp" /> <ClCompile Include="skein2.cpp" />
<ClCompile Include="sph\aes_helper.c" /> <ClCompile Include="sph\aes_helper.c" />
<ClCompile Include="sph\blake.c" /> <ClCompile Include="sph\blake.c" />

5
ccminer.vcxproj.filters

@ -111,6 +111,9 @@
<ClCompile Include="ccminer.cpp"> <ClCompile Include="ccminer.cpp">
<Filter>Source Files</Filter> <Filter>Source Files</Filter>
</ClCompile> </ClCompile>
<ClCompile Include="pools.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="crc32.c"> <ClCompile Include="crc32.c">
<Filter>Source Files</Filter> <Filter>Source Files</Filter>
</ClCompile> </ClCompile>
@ -653,4 +656,4 @@
<Filter>Ressources</Filter> <Filter>Ressources</Filter>
</Text> </Text>
</ItemGroup> </ItemGroup>
</Project> </Project>

17
miner.h

@ -469,6 +469,18 @@ struct work_restart {
char padding[128 - sizeof(uint32_t)]; 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_benchmark;
extern bool opt_debug; extern bool opt_debug;
extern bool opt_quiet; extern bool opt_quiet;
@ -680,12 +692,15 @@ extern struct pool_infos pools[MAX_POOLS];
extern int num_pools; extern int num_pools;
extern volatile int cur_pooln; 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_creds(int pooln);
void pool_set_attr(int pooln, const char* key, char* arg); void pool_set_attr(int pooln, const char* key, char* arg);
bool pool_switch_url(char *params); bool pool_switch_url(char *params);
bool pool_switch(int pooln); bool pool_switch(int pooln);
bool pool_switch_next(void); 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*, json_t * json_rpc_call_pool(CURL *curl, struct pool_infos*,
const char *req, bool lp_scan, bool lp, int *err); const char *req, bool lp_scan, bool lp, int *err);

357
pools.cpp

@ -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…
Cancel
Save