Handle network errors properly
This commit is contained in:
parent
35ae813dc8
commit
14f953e0f8
5 changed files with 55 additions and 71 deletions
6
NEWS
6
NEWS
|
@ -1,3 +1,8 @@
|
||||||
|
Version 2.1.1 - Jan 20, 2012
|
||||||
|
|
||||||
|
- Handle network errors properly
|
||||||
|
- Make scantime retargeting more accurate
|
||||||
|
|
||||||
Version 2.1 - Jan 19, 2012
|
Version 2.1 - Jan 19, 2012
|
||||||
|
|
||||||
- Share the same work among all threads
|
- Share the same work among all threads
|
||||||
|
@ -9,6 +14,7 @@ Version 2.0 - Jan 16, 2012
|
||||||
- Change default port to 9332 for Litecoin and remove default credentials
|
- Change default port to 9332 for Litecoin and remove default credentials
|
||||||
- Add 'scrypt' as the default algorithm and remove other algorithms (ArtForz)
|
- Add 'scrypt' as the default algorithm and remove other algorithms (ArtForz)
|
||||||
- Optimize scrypt for x86 and x86-64
|
- Optimize scrypt for x86 and x86-64
|
||||||
|
- Make scantime retargeting less granular (ArtForz)
|
||||||
- Test the whole hash instead of just looking at the high 32 bits
|
- Test the whole hash instead of just looking at the high 32 bits
|
||||||
- Add configurable timeout, with a default of 180 seconds
|
- Add configurable timeout, with a default of 180 seconds
|
||||||
- Add share summary output (inlikeflynn)
|
- Add share summary output (inlikeflynn)
|
||||||
|
|
80
cpu-miner.c
80
cpu-miner.c
|
@ -101,7 +101,7 @@ int opt_scantime = 5;
|
||||||
static json_t *opt_config;
|
static json_t *opt_config;
|
||||||
static const bool opt_time = true;
|
static const bool opt_time = true;
|
||||||
static enum sha256_algos opt_algo = ALGO_SCRYPT;
|
static enum sha256_algos opt_algo = ALGO_SCRYPT;
|
||||||
int opt_n_threads;
|
static int opt_n_threads;
|
||||||
static int num_processors;
|
static int num_processors;
|
||||||
static char *rpc_url;
|
static char *rpc_url;
|
||||||
static char *rpc_userpass;
|
static char *rpc_userpass;
|
||||||
|
@ -292,7 +292,7 @@ static bool submit_upstream_work(CURL *curl, const struct work *work)
|
||||||
hexstr);
|
hexstr);
|
||||||
|
|
||||||
/* issue JSON-RPC request */
|
/* issue JSON-RPC request */
|
||||||
val = json_rpc_call(curl, rpc_url, rpc_userpass, s, false, false);
|
val = json_rpc_call(curl, rpc_url, rpc_userpass, s, false, false, NULL);
|
||||||
if (unlikely(!val)) {
|
if (unlikely(!val)) {
|
||||||
applog(LOG_ERR, "submit_upstream_work json_rpc_call failed");
|
applog(LOG_ERR, "submit_upstream_work json_rpc_call failed");
|
||||||
goto out;
|
goto out;
|
||||||
|
@ -312,7 +312,7 @@ static bool submit_upstream_work(CURL *curl, const struct work *work)
|
||||||
accepted_count,
|
accepted_count,
|
||||||
accepted_count + rejected_count,
|
accepted_count + rejected_count,
|
||||||
100. * accepted_count / (accepted_count + rejected_count),
|
100. * accepted_count / (accepted_count + rejected_count),
|
||||||
hashrate,
|
1e-3 * hashrate,
|
||||||
json_is_true(res) ? "(yay!!!)" : "(booooo)");
|
json_is_true(res) ? "(yay!!!)" : "(booooo)");
|
||||||
|
|
||||||
json_decref(val);
|
json_decref(val);
|
||||||
|
@ -333,7 +333,7 @@ static bool get_upstream_work(CURL *curl, struct work *work)
|
||||||
bool rc;
|
bool rc;
|
||||||
|
|
||||||
val = json_rpc_call(curl, rpc_url, rpc_userpass, rpc_req,
|
val = json_rpc_call(curl, rpc_url, rpc_userpass, rpc_req,
|
||||||
want_longpoll, false);
|
want_longpoll, false, NULL);
|
||||||
if (!val)
|
if (!val)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
|
@ -456,22 +456,6 @@ static void *workio_thread(void *userdata)
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void hashmeter(int thr_id, const struct timeval *diff,
|
|
||||||
unsigned long hashes_done)
|
|
||||||
{
|
|
||||||
double khashes, secs;
|
|
||||||
|
|
||||||
khashes = hashes_done / 1000.0;
|
|
||||||
secs = (double)diff->tv_sec + ((double)diff->tv_usec / 1000000.0);
|
|
||||||
|
|
||||||
thr_hashrates[thr_id] = khashes / secs;
|
|
||||||
|
|
||||||
if (!opt_quiet)
|
|
||||||
applog(LOG_INFO, "thread %d: %lu hashes, %.2f khash/s",
|
|
||||||
thr_id, hashes_done,
|
|
||||||
khashes / secs);
|
|
||||||
}
|
|
||||||
|
|
||||||
static bool get_work(struct thr_info *thr, struct work *work)
|
static bool get_work(struct thr_info *thr, struct work *work)
|
||||||
{
|
{
|
||||||
struct workio_cmd *wc;
|
struct workio_cmd *wc;
|
||||||
|
@ -535,7 +519,7 @@ static void *miner_thread(void *userdata)
|
||||||
{
|
{
|
||||||
struct thr_info *mythr = userdata;
|
struct thr_info *mythr = userdata;
|
||||||
int thr_id = mythr->id;
|
int thr_id = mythr->id;
|
||||||
uint32_t max_nonce = 0xffffff;
|
uint32_t max_nonce;
|
||||||
uint32_t next_nonce;
|
uint32_t next_nonce;
|
||||||
unsigned char *scratchbuf = NULL;
|
unsigned char *scratchbuf = NULL;
|
||||||
|
|
||||||
|
@ -553,15 +537,13 @@ static void *miner_thread(void *userdata)
|
||||||
if (opt_algo == ALGO_SCRYPT)
|
if (opt_algo == ALGO_SCRYPT)
|
||||||
{
|
{
|
||||||
scratchbuf = scrypt_buffer_alloc();
|
scratchbuf = scrypt_buffer_alloc();
|
||||||
max_nonce = 0xffff * opt_n_threads;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
while (1) {
|
while (1) {
|
||||||
struct work work __attribute__((aligned(128)));
|
struct work work __attribute__((aligned(128)));
|
||||||
unsigned long hashes_done;
|
unsigned long hashes_done;
|
||||||
struct timeval tv_start, tv_end, diff;
|
struct timeval tv_start, tv_end, diff;
|
||||||
int diffms;
|
int64_t max64;
|
||||||
uint64_t max64;
|
|
||||||
bool rc;
|
bool rc;
|
||||||
|
|
||||||
/* obtain new work from internal workio thread */
|
/* obtain new work from internal workio thread */
|
||||||
|
@ -579,20 +561,29 @@ static void *miner_thread(void *userdata)
|
||||||
}
|
}
|
||||||
if (memcmp(work.data, g_work.data, 76)) {
|
if (memcmp(work.data, g_work.data, 76)) {
|
||||||
memcpy(&work, &g_work, sizeof(struct work));
|
memcpy(&work, &g_work, sizeof(struct work));
|
||||||
next_nonce = thr_id;
|
next_nonce = 0xffffffffU / opt_n_threads * thr_id;
|
||||||
}
|
}
|
||||||
pthread_mutex_unlock(&g_work_lock);
|
pthread_mutex_unlock(&g_work_lock);
|
||||||
|
|
||||||
work_restart[thr_id].restart = 0;
|
work_restart[thr_id].restart = 0;
|
||||||
|
|
||||||
|
/* adjust max_nonce to meet target scan time */
|
||||||
|
max64 = (g_work_time + opt_scantime - time(NULL)) *
|
||||||
|
(int64_t)thr_hashrates[thr_id];
|
||||||
|
if (max64 <= 0)
|
||||||
|
max64 = 0xfffLL;
|
||||||
|
if (next_nonce + max64 > 0xfffffffeLL)
|
||||||
|
max_nonce = 0xfffffffeU;
|
||||||
|
else
|
||||||
|
max_nonce = next_nonce + max64;
|
||||||
|
|
||||||
hashes_done = 0;
|
hashes_done = 0;
|
||||||
gettimeofday(&tv_start, NULL);
|
gettimeofday(&tv_start, NULL);
|
||||||
|
|
||||||
/* scan nonces for a proof-of-work hash */
|
/* scan nonces for a proof-of-work hash */
|
||||||
switch (opt_algo) {
|
switch (opt_algo) {
|
||||||
case ALGO_SCRYPT:
|
case ALGO_SCRYPT:
|
||||||
rc = scanhash_scrypt(thr_id, work.data, scratchbuf,
|
rc = scanhash_scrypt(thr_id, work.data, scratchbuf, work.target,
|
||||||
work.target, next_nonce + max_nonce,
|
max_nonce, &next_nonce, &hashes_done);
|
||||||
&next_nonce, &hashes_done);
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
|
@ -603,19 +594,11 @@ static void *miner_thread(void *userdata)
|
||||||
/* record scanhash elapsed time */
|
/* record scanhash elapsed time */
|
||||||
gettimeofday(&tv_end, NULL);
|
gettimeofday(&tv_end, NULL);
|
||||||
timeval_subtract(&diff, &tv_end, &tv_start);
|
timeval_subtract(&diff, &tv_end, &tv_start);
|
||||||
|
thr_hashrates[thr_id] =
|
||||||
hashmeter(thr_id, &diff, hashes_done);
|
hashes_done / (diff.tv_sec + 1e-6 * diff.tv_usec);
|
||||||
|
if (!opt_quiet)
|
||||||
/* adjust max_nonce to meet target scan time */
|
applog(LOG_INFO, "thread %d: %lu hashes, %.2f khash/s",
|
||||||
diffms = diff.tv_sec * 1000 + diff.tv_usec / 1000;
|
thr_id, hashes_done, 1e-3 * thr_hashrates[thr_id]);
|
||||||
if (diffms > 0) {
|
|
||||||
max64 =
|
|
||||||
((uint64_t)hashes_done * opt_scantime * 1000) / diffms;
|
|
||||||
max64 *= opt_n_threads;
|
|
||||||
if (max64 > 0xffff0000ULL)
|
|
||||||
max64 = 0xffff0000ULL;
|
|
||||||
max_nonce = max64;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* if nonce found, submit work */
|
/* if nonce found, submit work */
|
||||||
if (rc && !submit_work(mythr, &work))
|
if (rc && !submit_work(mythr, &work))
|
||||||
|
@ -677,9 +660,10 @@ static void *longpoll_thread(void *userdata)
|
||||||
|
|
||||||
while (1) {
|
while (1) {
|
||||||
json_t *val;
|
json_t *val;
|
||||||
|
int err;
|
||||||
|
|
||||||
val = json_rpc_call(curl, lp_url, rpc_userpass, rpc_req,
|
val = json_rpc_call(curl, lp_url, rpc_userpass, rpc_req,
|
||||||
false, true);
|
false, true, &err);
|
||||||
if (likely(val)) {
|
if (likely(val)) {
|
||||||
failures = 0;
|
failures = 0;
|
||||||
applog(LOG_INFO, "LONGPOLL detected new block");
|
applog(LOG_INFO, "LONGPOLL detected new block");
|
||||||
|
@ -691,10 +675,14 @@ static void *longpoll_thread(void *userdata)
|
||||||
restart_threads();
|
restart_threads();
|
||||||
}
|
}
|
||||||
pthread_mutex_unlock(&g_work_lock);
|
pthread_mutex_unlock(&g_work_lock);
|
||||||
} else {
|
json_decref(val);
|
||||||
/* longpoll failed, keep trying */
|
} else if (err != CURLE_OPERATION_TIMEDOUT) {
|
||||||
|
pthread_mutex_lock(&g_work_lock);
|
||||||
|
g_work_time -= opt_scantime;
|
||||||
|
pthread_mutex_unlock(&g_work_lock);
|
||||||
|
restart_threads();
|
||||||
|
sleep(opt_fail_pause);
|
||||||
}
|
}
|
||||||
json_decref(val);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
out:
|
out:
|
||||||
|
|
3
miner.h
3
miner.h
|
@ -123,7 +123,7 @@ extern bool opt_debug;
|
||||||
extern bool opt_protocol;
|
extern bool opt_protocol;
|
||||||
extern const uint32_t sha256_init_state[];
|
extern const uint32_t sha256_init_state[];
|
||||||
extern json_t *json_rpc_call(CURL *curl, const char *url, const char *userpass,
|
extern json_t *json_rpc_call(CURL *curl, const char *url, const char *userpass,
|
||||||
const char *rpc_req, bool, bool);
|
const char *rpc_req, bool, bool, int *);
|
||||||
extern char *bin2hex(const unsigned char *p, size_t len);
|
extern char *bin2hex(const unsigned char *p, size_t len);
|
||||||
extern bool hex2bin(unsigned char *p, const char *hexstr, size_t len);
|
extern bool hex2bin(unsigned char *p, const char *hexstr, size_t len);
|
||||||
|
|
||||||
|
@ -141,7 +141,6 @@ extern int opt_scantime;
|
||||||
extern int opt_timeout;
|
extern int opt_timeout;
|
||||||
extern bool want_longpoll;
|
extern bool want_longpoll;
|
||||||
extern bool have_longpoll;
|
extern bool have_longpoll;
|
||||||
extern int opt_n_threads;
|
|
||||||
struct thread_q;
|
struct thread_q;
|
||||||
|
|
||||||
struct work_restart {
|
struct work_restart {
|
||||||
|
|
31
scrypt.c
31
scrypt.c
|
@ -520,7 +520,7 @@ int scanhash_scrypt(int thr_id, unsigned char *pdata, unsigned char *scratchbuf,
|
||||||
uint32_t data3[20], hash3[8];
|
uint32_t data3[20], hash3[8];
|
||||||
int throughput;
|
int throughput;
|
||||||
#endif
|
#endif
|
||||||
unsigned long c = 0;
|
unsigned long first_nonce = *next_nonce;
|
||||||
uint32_t n = *next_nonce;
|
uint32_t n = *next_nonce;
|
||||||
uint32_t Htarg = le32dec(&((const uint32_t *)ptarget)[7]);
|
uint32_t Htarg = le32dec(&((const uint32_t *)ptarget)[7]);
|
||||||
int i;
|
int i;
|
||||||
|
@ -533,24 +533,18 @@ int scanhash_scrypt(int thr_id, unsigned char *pdata, unsigned char *scratchbuf,
|
||||||
throughput = scrypt_best_throughput();
|
throughput = scrypt_best_throughput();
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
while (1) {
|
do {
|
||||||
data[19] = n;
|
data[19] = n++;
|
||||||
n += opt_n_threads;
|
|
||||||
++c;
|
|
||||||
#ifdef SCRYPT_3WAY
|
#ifdef SCRYPT_3WAY
|
||||||
if (throughput >= 2 && n <= max_nonce) {
|
if (throughput >= 2 && n <= max_nonce) {
|
||||||
data2[19] = n;
|
data2[19] = n++;
|
||||||
n += opt_n_threads;
|
|
||||||
++c;
|
|
||||||
if (throughput >= 3 && n <= max_nonce) {
|
if (throughput >= 3 && n <= max_nonce) {
|
||||||
data3[19] = n;
|
data3[19] = n++;
|
||||||
n += opt_n_threads;
|
|
||||||
++c;
|
|
||||||
scrypt_1024_1_1_256_sp_3way(data, data2, data3, hash, hash2, hash3, scratchbuf);
|
scrypt_1024_1_1_256_sp_3way(data, data2, data3, hash, hash2, hash3, scratchbuf);
|
||||||
if (hash3[7] < Htarg || hash3[7] == Htarg && test_hash(hash3, (uint32_t *)ptarget)) {
|
if (hash3[7] < Htarg || hash3[7] == Htarg && test_hash(hash3, (uint32_t *)ptarget)) {
|
||||||
be32enc(&((uint32_t *)pdata)[19], data3[19]);
|
be32enc(&((uint32_t *)pdata)[19], data3[19]);
|
||||||
*next_nonce = n;
|
*next_nonce = n;
|
||||||
*hashes_done = c;
|
*hashes_done = n - first_nonce;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
@ -559,7 +553,7 @@ int scanhash_scrypt(int thr_id, unsigned char *pdata, unsigned char *scratchbuf,
|
||||||
if (hash2[7] < Htarg || hash2[7] == Htarg && test_hash(hash2, (uint32_t *)ptarget)) {
|
if (hash2[7] < Htarg || hash2[7] == Htarg && test_hash(hash2, (uint32_t *)ptarget)) {
|
||||||
be32enc(&((uint32_t *)pdata)[19], data2[19]);
|
be32enc(&((uint32_t *)pdata)[19], data2[19]);
|
||||||
*next_nonce = n;
|
*next_nonce = n;
|
||||||
*hashes_done = c;
|
*hashes_done = n - first_nonce;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
@ -568,19 +562,16 @@ int scanhash_scrypt(int thr_id, unsigned char *pdata, unsigned char *scratchbuf,
|
||||||
#else
|
#else
|
||||||
scrypt_1024_1_1_256_sp(data, hash, scratchbuf);
|
scrypt_1024_1_1_256_sp(data, hash, scratchbuf);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (hash[7] < Htarg || hash[7] == Htarg && test_hash(hash, (uint32_t *)ptarget)) {
|
if (hash[7] < Htarg || hash[7] == Htarg && test_hash(hash, (uint32_t *)ptarget)) {
|
||||||
be32enc(&((uint32_t *)pdata)[19], data[19]);
|
be32enc(&((uint32_t *)pdata)[19], data[19]);
|
||||||
*next_nonce = n;
|
*next_nonce = n;
|
||||||
*hashes_done = c;
|
*hashes_done = n - first_nonce;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
} while (n <= max_nonce && !work_restart[thr_id].restart);
|
||||||
if ((n > max_nonce) || work_restart[thr_id].restart)
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
*next_nonce = n;
|
*next_nonce = n;
|
||||||
*hashes_done = c;
|
*hashes_done = n - first_nonce;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
6
util.c
6
util.c
|
@ -205,7 +205,7 @@ out:
|
||||||
|
|
||||||
json_t *json_rpc_call(CURL *curl, const char *url,
|
json_t *json_rpc_call(CURL *curl, const char *url,
|
||||||
const char *userpass, const char *rpc_req,
|
const char *userpass, const char *rpc_req,
|
||||||
bool longpoll_scan, bool longpoll)
|
bool longpoll_scan, bool longpoll, int *curl_err)
|
||||||
{
|
{
|
||||||
json_t *val, *err_val, *res_val;
|
json_t *val, *err_val, *res_val;
|
||||||
int rc;
|
int rc;
|
||||||
|
@ -266,11 +266,11 @@ json_t *json_rpc_call(CURL *curl, const char *url,
|
||||||
curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers);
|
curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers);
|
||||||
|
|
||||||
rc = curl_easy_perform(curl);
|
rc = curl_easy_perform(curl);
|
||||||
|
if (curl_err != NULL)
|
||||||
|
*curl_err = rc;
|
||||||
if (rc) {
|
if (rc) {
|
||||||
if (!(longpoll && rc == CURLE_OPERATION_TIMEDOUT))
|
if (!(longpoll && rc == CURLE_OPERATION_TIMEDOUT))
|
||||||
applog(LOG_ERR, "HTTP request failed: %s", curl_err_str);
|
applog(LOG_ERR, "HTTP request failed: %s", curl_err_str);
|
||||||
if (longpoll && rc != CURLE_OPERATION_TIMEDOUT)
|
|
||||||
sleep(30);
|
|
||||||
goto err_out;
|
goto err_out;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue