Handle network errors properly

This commit is contained in:
pooler 2012-01-21 00:31:51 +01:00
parent 35ae813dc8
commit 14f953e0f8
5 changed files with 55 additions and 71 deletions

6
NEWS
View file

@ -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
- 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
- Add 'scrypt' as the default algorithm and remove other algorithms (ArtForz)
- 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
- Add configurable timeout, with a default of 180 seconds
- Add share summary output (inlikeflynn)

View file

@ -101,7 +101,7 @@ int opt_scantime = 5;
static json_t *opt_config;
static const bool opt_time = true;
static enum sha256_algos opt_algo = ALGO_SCRYPT;
int opt_n_threads;
static int opt_n_threads;
static int num_processors;
static char *rpc_url;
static char *rpc_userpass;
@ -292,7 +292,7 @@ static bool submit_upstream_work(CURL *curl, const struct work *work)
hexstr);
/* 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)) {
applog(LOG_ERR, "submit_upstream_work json_rpc_call failed");
goto out;
@ -312,7 +312,7 @@ static bool submit_upstream_work(CURL *curl, const struct work *work)
accepted_count,
accepted_count + rejected_count,
100. * accepted_count / (accepted_count + rejected_count),
hashrate,
1e-3 * hashrate,
json_is_true(res) ? "(yay!!!)" : "(booooo)");
json_decref(val);
@ -333,7 +333,7 @@ static bool get_upstream_work(CURL *curl, struct work *work)
bool rc;
val = json_rpc_call(curl, rpc_url, rpc_userpass, rpc_req,
want_longpoll, false);
want_longpoll, false, NULL);
if (!val)
return false;
@ -456,22 +456,6 @@ static void *workio_thread(void *userdata)
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)
{
struct workio_cmd *wc;
@ -535,7 +519,7 @@ static void *miner_thread(void *userdata)
{
struct thr_info *mythr = userdata;
int thr_id = mythr->id;
uint32_t max_nonce = 0xffffff;
uint32_t max_nonce;
uint32_t next_nonce;
unsigned char *scratchbuf = NULL;
@ -553,15 +537,13 @@ static void *miner_thread(void *userdata)
if (opt_algo == ALGO_SCRYPT)
{
scratchbuf = scrypt_buffer_alloc();
max_nonce = 0xffff * opt_n_threads;
}
while (1) {
struct work work __attribute__((aligned(128)));
unsigned long hashes_done;
struct timeval tv_start, tv_end, diff;
int diffms;
uint64_t max64;
int64_t max64;
bool rc;
/* 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)) {
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);
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;
gettimeofday(&tv_start, NULL);
/* scan nonces for a proof-of-work hash */
switch (opt_algo) {
case ALGO_SCRYPT:
rc = scanhash_scrypt(thr_id, work.data, scratchbuf,
work.target, next_nonce + max_nonce,
&next_nonce, &hashes_done);
rc = scanhash_scrypt(thr_id, work.data, scratchbuf, work.target,
max_nonce, &next_nonce, &hashes_done);
break;
default:
@ -603,19 +594,11 @@ static void *miner_thread(void *userdata)
/* record scanhash elapsed time */
gettimeofday(&tv_end, NULL);
timeval_subtract(&diff, &tv_end, &tv_start);
hashmeter(thr_id, &diff, hashes_done);
/* adjust max_nonce to meet target scan time */
diffms = diff.tv_sec * 1000 + diff.tv_usec / 1000;
if (diffms > 0) {
max64 =
((uint64_t)hashes_done * opt_scantime * 1000) / diffms;
max64 *= opt_n_threads;
if (max64 > 0xffff0000ULL)
max64 = 0xffff0000ULL;
max_nonce = max64;
}
thr_hashrates[thr_id] =
hashes_done / (diff.tv_sec + 1e-6 * diff.tv_usec);
if (!opt_quiet)
applog(LOG_INFO, "thread %d: %lu hashes, %.2f khash/s",
thr_id, hashes_done, 1e-3 * thr_hashrates[thr_id]);
/* if nonce found, submit work */
if (rc && !submit_work(mythr, &work))
@ -677,9 +660,10 @@ static void *longpoll_thread(void *userdata)
while (1) {
json_t *val;
int err;
val = json_rpc_call(curl, lp_url, rpc_userpass, rpc_req,
false, true);
false, true, &err);
if (likely(val)) {
failures = 0;
applog(LOG_INFO, "LONGPOLL detected new block");
@ -691,10 +675,14 @@ static void *longpoll_thread(void *userdata)
restart_threads();
}
pthread_mutex_unlock(&g_work_lock);
} else {
/* longpoll failed, keep trying */
json_decref(val);
} 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:

View file

@ -123,7 +123,7 @@ extern bool opt_debug;
extern bool opt_protocol;
extern const uint32_t sha256_init_state[];
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 bool hex2bin(unsigned char *p, const char *hexstr, size_t len);
@ -141,7 +141,6 @@ extern int opt_scantime;
extern int opt_timeout;
extern bool want_longpoll;
extern bool have_longpoll;
extern int opt_n_threads;
struct thread_q;
struct work_restart {

View file

@ -520,7 +520,7 @@ int scanhash_scrypt(int thr_id, unsigned char *pdata, unsigned char *scratchbuf,
uint32_t data3[20], hash3[8];
int throughput;
#endif
unsigned long c = 0;
unsigned long first_nonce = *next_nonce;
uint32_t n = *next_nonce;
uint32_t Htarg = le32dec(&((const uint32_t *)ptarget)[7]);
int i;
@ -533,24 +533,18 @@ int scanhash_scrypt(int thr_id, unsigned char *pdata, unsigned char *scratchbuf,
throughput = scrypt_best_throughput();
#endif
while (1) {
data[19] = n;
n += opt_n_threads;
++c;
do {
data[19] = n++;
#ifdef SCRYPT_3WAY
if (throughput >= 2 && n <= max_nonce) {
data2[19] = n;
n += opt_n_threads;
++c;
data2[19] = n++;
if (throughput >= 3 && n <= max_nonce) {
data3[19] = n;
n += opt_n_threads;
++c;
data3[19] = n++;
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)) {
be32enc(&((uint32_t *)pdata)[19], data3[19]);
*next_nonce = n;
*hashes_done = c;
*hashes_done = n - first_nonce;
return true;
}
} 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)) {
be32enc(&((uint32_t *)pdata)[19], data2[19]);
*next_nonce = n;
*hashes_done = c;
*hashes_done = n - first_nonce;
return true;
}
} else {
@ -568,19 +562,16 @@ int scanhash_scrypt(int thr_id, unsigned char *pdata, unsigned char *scratchbuf,
#else
scrypt_1024_1_1_256_sp(data, hash, scratchbuf);
#endif
if (hash[7] < Htarg || hash[7] == Htarg && test_hash(hash, (uint32_t *)ptarget)) {
be32enc(&((uint32_t *)pdata)[19], data[19]);
*next_nonce = n;
*hashes_done = c;
*hashes_done = n - first_nonce;
return true;
}
if ((n > max_nonce) || work_restart[thr_id].restart)
break;
}
} while (n <= max_nonce && !work_restart[thr_id].restart);
*next_nonce = n;
*hashes_done = c;
*hashes_done = n - first_nonce;
return false;
}

6
util.c
View file

@ -205,7 +205,7 @@ out:
json_t *json_rpc_call(CURL *curl, const char *url,
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;
int rc;
@ -266,11 +266,11 @@ json_t *json_rpc_call(CURL *curl, const char *url,
curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers);
rc = curl_easy_perform(curl);
if (curl_err != NULL)
*curl_err = rc;
if (rc) {
if (!(longpoll && rc == CURLE_OPERATION_TIMEDOUT))
applog(LOG_ERR, "HTTP request failed: %s", curl_err_str);
if (longpoll && rc != CURLE_OPERATION_TIMEDOUT)
sleep(30);
goto err_out;
}