Browse Source

Merge branch 'master' into usb-dev

Con Kolivas 13 years ago
parent
commit
ab0cc58cb4
5 changed files with 198 additions and 33 deletions
  1. 67 24
      cgminer.c
  2. 3 0
      miner.h
  3. 1 1
      ocl.c
  4. 126 8
      util.c
  5. 1 0
      util.h

+ 67 - 24
cgminer.c

@@ -250,6 +250,7 @@ struct stratum_share {
 	bool block;
 	struct work *work;
 	int id;
+	time_t sshare_time;
 };
 
 static struct stratum_share *stratum_shares = NULL;
@@ -1422,10 +1423,7 @@ void clean_work(struct work *work)
 	free(work->nonce2);
 	free(work->ntime);
 	free(work->gbt_coinbase);
-	work->job_id = NULL;
-	work->nonce2 = NULL;
-	work->ntime = NULL;
-	work->gbt_coinbase = NULL;
+	free(work->sessionid);
 	memset(work, 0, sizeof(struct work));
 }
 
@@ -3209,36 +3207,69 @@ static void *submit_work_thread(void *userdata)
 	if (work->stratum) {
 		struct stratum_share *sshare = calloc(sizeof(struct stratum_share), 1);
 		uint32_t *hash32 = (uint32_t *)work->hash, nonce;
+		bool submitted = false;
 		char *noncehex;
 		char s[1024];
 
+		sshare->sshare_time = time(NULL);
 		/* This work item is freed in parse_stratum_response */
 		sshare->work = work;
+		nonce = *((uint32_t *)(work->data + 76));
+		noncehex = bin2hex((const unsigned char *)&nonce, 4);
+		memset(s, 0, 1024);
+
 		mutex_lock(&sshare_lock);
 		/* Give the stratum share a unique id */
 		sshare->id = swork_id++;
-		HASH_ADD_INT(stratum_shares, id, sshare);
 		mutex_unlock(&sshare_lock);
 
-		nonce = *((uint32_t *)(work->data + 76));
-		noncehex = bin2hex((const unsigned char *)&nonce, 4);
-		memset(s, 0, 1024);
 		sprintf(s, "{\"params\": [\"%s\", \"%s\", \"%s\", \"%s\", \"%s\"], \"id\": %d, \"method\": \"mining.submit\"}",
 			pool->rpc_user, work->job_id, work->nonce2, work->ntime, noncehex, sshare->id);
 		free(noncehex);
 
-		applog(LOG_INFO, "Submitting share %08lx to pool %d", (unsigned long)(hash32[6]), pool->pool_no);
+		applog(LOG_INFO, "Submitting share %08lx to pool %d", hash32[6], pool->pool_no);
+
+		/* Try resubmitting for up to 2 minutes if we fail to submit
+		 * once and the stratum pool supports sessionid for mining
+		 * resume. */
+		while (time(NULL) < sshare->sshare_time + 120) {
+			bool sessionid_match;
+
+			if (likely(stratum_send(pool, s, strlen(s)))) {
+				if (pool_tclear(pool, &pool->submit_fail))
+						applog(LOG_WARNING, "Pool %d communication resumed, submitting work", pool->pool_no);
+				mutex_lock(&sshare_lock);
+				HASH_ADD_INT(stratum_shares, id, sshare);
+				mutex_unlock(&sshare_lock);
+				applog(LOG_DEBUG, "Successfully submitted, adding to stratum_shares db");
+				submitted = true;
+				break;
+			}
+			if (!pool_tset(pool, &pool->submit_fail) && cnx_needed(pool)) {
+				applog(LOG_WARNING, "Pool %d stratum share submission failure", pool->pool_no);
+				total_ro++;
+				pool->remotefail_occasions++;
+			}
 
-		if (likely(stratum_send(pool, s, strlen(s)))) {
-			if (pool_tclear(pool, &pool->submit_fail))
-					applog(LOG_WARNING, "Pool %d communication resumed, submitting work", pool->pool_no);
-			applog(LOG_DEBUG, "Successfully submitted, adding to stratum_shares db");
-		} else if (!pool_tset(pool, &pool->submit_fail) && cnx_needed(pool)) {
-			applog(LOG_WARNING, "Pool %d stratum share submission failure", pool->pool_no);
-			total_ro++;
-			pool->remotefail_occasions++;
+			mutex_lock(&pool->pool_lock);
+			sessionid_match = pool->sessionid && work->sessionid && !strcmp(pool->sessionid, work->sessionid);
+			mutex_unlock(&pool->pool_lock);
+
+			if (!sessionid_match) {
+				applog(LOG_DEBUG, "No matching session id for resubmitting stratum share");
+				break;
+			}
+			/* Retry every 5 seconds */
+			sleep(5);
 		}
 
+		if (unlikely(!submitted)) {
+			applog(LOG_DEBUG, "Failed to submit stratum share, discarding");
+			free_work(work);
+			free(sshare);
+			pool->stale_shares++;
+			total_stale++;
+		}
 		goto out;
 	}
 
@@ -4662,7 +4693,7 @@ out:
 	return ret;
 }
 
-static void clear_stratum_shares(struct pool *pool)
+void clear_stratum_shares(struct pool *pool)
 {
 	struct stratum_share *sshare, *tmpshare;
 	int cleared = 0;
@@ -4741,6 +4772,16 @@ static void stratum_resumed(struct pool *pool)
 	}
 }
 
+static bool supports_resume(struct pool *pool)
+{
+	bool ret;
+
+	mutex_lock(&pool->pool_lock);
+	ret = (pool->sessionid != NULL);
+	mutex_unlock(&pool->pool_lock);
+	return ret;
+}
+
 /* One stratum thread per pool that has stratum waits on the socket checking
  * for new messages and for the integrity of the socket connection. We reset
  * the connection based on the integrity of the receive side only as the send
@@ -4770,9 +4811,9 @@ static void *stratum_thread(void *userdata)
 			clear_pool_work(pool);
 
 			wait_lpcurrent(pool);
-			if (!initiate_stratum(pool) || !auth_stratum(pool)) {
+			if (!restart_stratum(pool)) {
 				pool_died(pool);
-				while (!initiate_stratum(pool) || !auth_stratum(pool)) {
+				while (!restart_stratum(pool)) {
 					if (pool->removed)
 						goto out;
 					nmsleep(30000);
@@ -4801,16 +4842,17 @@ static void *stratum_thread(void *userdata)
 			/* If the socket to our stratum pool disconnects, all
 			 * tracked submitted shares are lost and we will leak
 			 * the memory if we don't discard their records. */
-			clear_stratum_shares(pool);
+			if (!supports_resume(pool))
+				clear_stratum_shares(pool);
 			clear_pool_work(pool);
 			if (pool == current_pool())
 				restart_threads();
 
-			if (initiate_stratum(pool) && auth_stratum(pool))
+			if (restart_stratum(pool))
 				continue;
 
 			pool_died(pool);
-			while (!initiate_stratum(pool) || !auth_stratum(pool)) {
+			while (!restart_stratum(pool)) {
 				if (pool->removed)
 					goto out;
 				nmsleep(30000);
@@ -5250,7 +5292,8 @@ static void gen_stratum_work(struct pool *pool, struct work *work)
 	/* Copy parameters required for share submission */
 	work->job_id = strdup(pool->swork.job_id);
 	work->ntime = strdup(pool->swork.ntime);
-
+	if (pool->sessionid)
+		work->sessionid = strdup(pool->sessionid);
 	mutex_unlock(&pool->pool_lock);
 
 	applog(LOG_DEBUG, "Generated stratum merkle %s", merkle_hash);

+ 3 - 0
miner.h

@@ -746,6 +746,7 @@ extern pthread_mutex_t restart_lock;
 extern pthread_cond_t restart_cond;
 
 extern void thread_reportin(struct thr_info *thr);
+extern void clear_stratum_shares(struct pool *pool);
 extern int restart_wait(unsigned int mstime);
 
 extern void kill_work(void);
@@ -971,6 +972,7 @@ struct pool {
 	size_t n1_len;
 	uint32_t nonce2;
 	int n2size;
+	char *sessionid;
 	bool has_stratum;
 	bool stratum_active;
 	bool stratum_auth;
@@ -1035,6 +1037,7 @@ struct work {
 	char		*nonce2;
 	char		*ntime;
 	double		sdiff;
+	char		*sessionid;
 
 	bool		gbt;
 	char		*gbt_coinbase;

+ 1 - 1
ocl.c

@@ -380,7 +380,7 @@ _clState *initCl(unsigned int gpu, char *name, size_t nameSize)
 	 */
 	char binaryfilename[255];
 	char filename[255];
-	char numbuf[10];
+	char numbuf[16];
 
 	if (cgpu->kernel == KL_NONE) {
 		if (opt_scrypt) {

+ 126 - 8
util.c

@@ -1247,7 +1247,7 @@ static bool parse_reconnect(struct pool *pool, json_t *val)
 
 	applog(LOG_NOTICE, "Reconnect requested from pool %d to %s", pool->pool_no, address);
 
-	if (!initiate_stratum(pool) || !auth_stratum(pool))
+	if (!restart_stratum(pool))
 		return false;
 
 	return true;
@@ -1391,15 +1391,12 @@ out:
 	return ret;
 }
 
-bool initiate_stratum(struct pool *pool)
+static bool setup_stratum_curl(struct pool *pool)
 {
-	json_t *val = NULL, *res_val, *err_val;
 	char curl_err_str[CURL_ERROR_SIZE];
-	char s[RBUFSIZE], *sret = NULL;
 	CURL *curl = NULL;
 	double byte_count;
-	json_error_t err;
-	bool ret = false;
+	char s[RBUFSIZE];
 
 	mutex_lock(&pool->stratum_lock);
 	pool->stratum_active = false;
@@ -1419,7 +1416,6 @@ bool initiate_stratum(struct pool *pool)
 	}
 
 	/* Create a http url for use with curl */
-	memset(s, 0, RBUFSIZE);
 	sprintf(s, "http://%s:%s", pool->sockaddr_url, pool->stratum_port);
 
 	curl_easy_setopt(curl, CURLOPT_FRESH_CONNECT, 1);
@@ -1439,7 +1435,7 @@ bool initiate_stratum(struct pool *pool)
 	curl_easy_setopt(curl, CURLOPT_CONNECT_ONLY, 1);
 	if (curl_easy_perform(curl)) {
 		applog(LOG_INFO, "Stratum connect failed to pool %d: %s", pool->pool_no, curl_err_str);
-		goto out;
+		return false;
 	}
 	curl_easy_getinfo(curl, CURLINFO_LASTSOCKET, (long *)&pool->sock);
 	keep_alive(curl, pool->sock);
@@ -1451,6 +1447,19 @@ bool initiate_stratum(struct pool *pool)
 	if (curl_easy_getinfo(curl, CURLINFO_SIZE_DOWNLOAD, &byte_count) == CURLE_OK)
 		pool->cgminer_pool_stats.bytes_received += byte_count;
 
+	return true;
+}
+
+bool initiate_stratum(struct pool *pool)
+{
+	json_t *val = NULL, *res_val, *err_val;
+	char s[RBUFSIZE], *sret = NULL;
+	json_error_t err;
+	bool ret = false;
+
+	if (!setup_stratum_curl(pool))
+		goto out;
+
 	sprintf(s, "{\"id\": %d, \"method\": \"mining.subscribe\", \"params\": []}", swork_id++);
 
 	if (!__stratum_send(pool, s, strlen(s))) {
@@ -1504,6 +1513,11 @@ bool initiate_stratum(struct pool *pool)
 		applog(LOG_INFO, "Failed to get n2size in initiate_stratum");
 		goto out;
 	}
+	pool->sessionid = json_array_string(res_val, 3);
+	if (pool->sessionid)
+		applog(LOG_DEBUG, "Pool %d stratum session id: %s", pool->pool_no, pool->sessionid);
+	else
+		applog(LOG_DEBUG, "Pool %d stratum session id does not exist");
 
 	ret = true;
 out:
@@ -1525,6 +1539,110 @@ out:
 	return ret;
 }
 
+static void reset_sessionid(struct pool *pool)
+{
+	mutex_lock(&pool->pool_lock);
+	free(pool->sessionid);
+	pool->sessionid = NULL;
+	mutex_unlock(&pool->pool_lock);
+}
+
+/* Placeholder for real resume function in the future */
+static bool resume_stratum(struct pool *pool)
+{
+	json_t *val = NULL, *err_val, *res_val;
+	char s[RBUFSIZE], *sret = NULL;
+	json_error_t err;
+	bool ret = false;
+
+	if (!setup_stratum_curl(pool))
+		goto out;
+
+	mutex_lock(&pool->pool_lock);
+	sprintf(s, "{\"id\": %d, \"method\": \"mining.resume\", \"params\": [\"%s\"]}", swork_id++, pool->sessionid);
+	mutex_unlock(&pool->pool_lock);
+
+	if (!__stratum_send(pool, s, strlen(s))) {
+		applog(LOG_DEBUG, "Failed to send s in resume_stratum");
+		goto out;
+	}
+
+	if (!socket_full(pool, true)) {
+		applog(LOG_DEBUG, "Timed out waiting for response in resume_stratum");
+		goto out;
+	}
+
+	sret = recv_line(pool);
+	if (!sret)
+		goto out;
+
+	val = JSON_LOADS(sret, &err);
+	free(sret);
+	if (!val) {
+		applog(LOG_INFO, "JSON decode failed(%d): %s", err.line, err.text);
+		goto out;
+	}
+
+	res_val = json_object_get(val, "result");
+	err_val = json_object_get(val, "error");
+
+	/* If there is an error, assume resume support is not there or broken */
+	if (!res_val || json_is_null(res_val) ||
+	    (err_val && !json_is_null(err_val))) {
+		char *ss;
+
+		if (err_val)
+			ss = json_dumps(err_val, JSON_INDENT(3));
+		else
+			ss = strdup("(unknown reason)");
+
+		applog(LOG_INFO, "JSON-RPC decode failed: %s", ss);
+
+		free(ss);
+
+		reset_sessionid(pool);
+		goto out;
+	}
+
+	if (json_is_true(res_val)) {
+		applog(LOG_NOTICE, "Resumed stratum connection to pool %d", pool->pool_no);
+		pool->stratum_active = true;
+		ret = true;
+	} else {
+		applog(LOG_NOTICE, "Unable to resume old stratum connection to pool %d", pool->pool_no);
+		reset_sessionid(pool);
+		clear_stratum_shares(pool);
+		json_decref(val);
+
+		return initiate_stratum(pool);
+	}
+out:
+	if (val)
+		json_decref(val);
+
+	return ret;
+}
+
+bool restart_stratum(struct pool *pool)
+{
+	bool resume;
+
+	mutex_lock(&pool->pool_lock);
+	resume = pool->sessionid != NULL;
+	mutex_unlock(&pool->pool_lock);
+
+	if (resume) {
+		if (!resume_stratum(pool))
+			return false;
+	} else {
+		if (!initiate_stratum(pool))
+			return false;
+	}
+	if (!auth_stratum(pool))
+		return false;
+	return true;
+}
+
 void suspend_stratum(struct pool *pool)
 {
 	applog(LOG_INFO, "Closing socket for stratum pool %d", pool->pool_no);

+ 1 - 0
util.h

@@ -52,6 +52,7 @@ bool parse_method(struct pool *pool, char *s);
 bool extract_sockaddr(struct pool *pool, char *url);
 bool auth_stratum(struct pool *pool);
 bool initiate_stratum(struct pool *pool);
+bool restart_stratum(struct pool *pool);
 void suspend_stratum(struct pool *pool);
 void dev_error(struct cgpu_info *dev, enum dev_reason reason);
 void *realloc_strcat(char *ptr, char *s);