| 
						
						
						
					 | 
					 | 
					@ -1,5 +1,5 @@ | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					/*
 | 
					 | 
					 | 
					 | 
					/*
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 * Copyright 2014 Con Kolivas | 
					 | 
					 | 
					 | 
					 * Copyright 2014-2015 Con Kolivas | 
				
			
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 * | 
					 | 
					 | 
					 | 
					 * | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 * This program is free software; you can redistribute it and/or modify it | 
					 | 
					 | 
					 | 
					 * This program is free software; you can redistribute it and/or modify it | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 * under the terms of the GNU General Public License as published by the Free | 
					 | 
					 | 
					 | 
					 * under the terms of the GNU General Public License as published by the Free | 
				
			
			
		
	
	
		
		
			
				
					| 
						
							
								
							
						
						
							
								
							
						
						
					 | 
					 | 
					@ -172,6 +172,8 @@ struct user_instance { | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					
 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
						int workers; | 
					 | 
					 | 
					 | 
						int workers; | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					
 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
						double best_diff; /* Best share found by this user */ | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
						double dsps1; /* Diff shares per second, 1 minute rolling average */ | 
					 | 
					 | 
					 | 
						double dsps1; /* Diff shares per second, 1 minute rolling average */ | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
						double dsps5; /* ... 5 minute ... */ | 
					 | 
					 | 
					 | 
						double dsps5; /* ... 5 minute ... */ | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
						double dsps60;/* etc */ | 
					 | 
					 | 
					 | 
						double dsps60;/* etc */ | 
				
			
			
		
	
	
		
		
			
				
					| 
						
						
						
							
								
							
						
					 | 
					 | 
					@ -195,6 +197,7 @@ struct worker_instance { | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
						tv_t last_share; | 
					 | 
					 | 
					 | 
						tv_t last_share; | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
						time_t start_time; | 
					 | 
					 | 
					 | 
						time_t start_time; | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					
 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
						double best_diff; /* Best share found by this worker */ | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
						int mindiff; /* User chosen mindiff */ | 
					 | 
					 | 
					 | 
						int mindiff; /* User chosen mindiff */ | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					
 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
						bool idle; | 
					 | 
					 | 
					 | 
						bool idle; | 
				
			
			
		
	
	
		
		
			
				
					| 
						
							
								
							
						
						
							
								
							
						
						
					 | 
					 | 
					@ -252,8 +255,10 @@ struct stratum_instance { | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
						ckpool_t *ckp; | 
					 | 
					 | 
					 | 
						ckpool_t *ckp; | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					
 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
						time_t last_txns; /* Last time this worker requested txn hashes */ | 
					 | 
					 | 
					 | 
						time_t last_txns; /* Last time this worker requested txn hashes */ | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
						time_t disconnected_time; /* Time this instance disconnected */ | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					
 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
						int64_t suggest_diff; /* Stratum client suggested diff */ | 
					 | 
					 | 
					 | 
						int64_t suggest_diff; /* Stratum client suggested diff */ | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
						double best_diff; /* Best share found by this instance */ | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					}; | 
					 | 
					 | 
					 | 
					}; | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					
 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					struct share { | 
					 | 
					 | 
					 | 
					struct share { | 
				
			
			
		
	
	
		
		
			
				
					| 
						
							
								
							
						
						
							
								
							
						
						
					 | 
					 | 
					@ -1098,6 +1103,14 @@ static stratum_instance_t *__stratum_add_instance(ckpool_t *ckp, int64_t id, int | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
						return instance; | 
					 | 
					 | 
					 | 
						return instance; | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					} | 
					 | 
					 | 
					 | 
					} | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					
 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					/* Add a stratum instance to the dead instances list */ | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					static void kill_instance(sdata_t *sdata, stratum_instance_t *client) | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					{ | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
						if (client->user_instance) | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
							DL_DELETE(client->user_instance->instances, client); | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
						LL_PREPEND(sdata->dead_instances, client); | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					} | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					/* Only supports a full ckpool instance sessionid with an 8 byte sessionid */ | 
					 | 
					 | 
					 | 
					/* Only supports a full ckpool instance sessionid with an 8 byte sessionid */ | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					static bool disconnected_sessionid_exists(sdata_t *sdata, const char *sessionid, int64_t id) | 
					 | 
					 | 
					 | 
					static bool disconnected_sessionid_exists(sdata_t *sdata, const char *sessionid, int64_t id) | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					{ | 
					 | 
					 | 
					 | 
					{ | 
				
			
			
		
	
	
		
		
			
				
					| 
						
						
						
							
								
							
						
					 | 
					 | 
					@ -1112,7 +1125,7 @@ static bool disconnected_sessionid_exists(sdata_t *sdata, const char *sessionid, | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
						/* Number is in BE but we don't swap either of them */ | 
					 | 
					 | 
					 | 
						/* Number is in BE but we don't swap either of them */ | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
						hex2bin(&session64, sessionid, 8); | 
					 | 
					 | 
					 | 
						hex2bin(&session64, sessionid, 8); | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					
 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
						ck_rlock(&sdata->instance_lock); | 
					 | 
					 | 
					 | 
						ck_ilock(&sdata->instance_lock); | 
				
			
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
						HASH_ITER(hh, sdata->stratum_instances, instance, tmp) { | 
					 | 
					 | 
					 | 
						HASH_ITER(hh, sdata->stratum_instances, instance, tmp) { | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
							if (instance->id == id) | 
					 | 
					 | 
					 | 
							if (instance->id == id) | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
								continue; | 
					 | 
					 | 
					 | 
								continue; | 
				
			
			
		
	
	
		
		
			
				
					| 
						
						
						
							
								
							
						
					 | 
					 | 
					@ -1123,10 +1136,18 @@ static bool disconnected_sessionid_exists(sdata_t *sdata, const char *sessionid, | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
						} | 
					 | 
					 | 
					 | 
						} | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
						instance = NULL; | 
					 | 
					 | 
					 | 
						instance = NULL; | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
						HASH_FIND(hh, sdata->disconnected_instances, &session64, sizeof(uint64_t), instance); | 
					 | 
					 | 
					 | 
						HASH_FIND(hh, sdata->disconnected_instances, &session64, sizeof(uint64_t), instance); | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
						if (instance) | 
					 | 
					 | 
					 | 
						if (instance) { | 
				
			
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
							/* If we've found a matching disconnected instance, use it only
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
							 * once and discard it */ | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
							ck_ulock(&sdata->instance_lock); | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
							HASH_DEL(sdata->disconnected_instances, instance); | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
							kill_instance(sdata, instance); | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
							ck_dwilock(&sdata->instance_lock); | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
							ret = true; | 
					 | 
					 | 
					 | 
							ret = true; | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
						} | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					out_unlock: | 
					 | 
					 | 
					 | 
					out_unlock: | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
						ck_runlock(&sdata->instance_lock); | 
					 | 
					 | 
					 | 
						ck_uilock(&sdata->instance_lock); | 
				
			
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					out: | 
					 | 
					 | 
					 | 
					out: | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
						return ret; | 
					 | 
					 | 
					 | 
						return ret; | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					} | 
					 | 
					 | 
					 | 
					} | 
				
			
			
		
	
	
		
		
			
				
					| 
						
							
								
							
						
						
							
								
							
						
						
					 | 
					 | 
					@ -1209,6 +1230,7 @@ static void dec_worker(ckpool_t *ckp, user_instance_t *instance) | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					static void drop_client(sdata_t *sdata, int64_t id) | 
					 | 
					 | 
					 | 
					static void drop_client(sdata_t *sdata, int64_t id) | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					{ | 
					 | 
					 | 
					 | 
					{ | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
						stratum_instance_t *client, *tmp; | 
					 | 
					 | 
					 | 
						stratum_instance_t *client, *tmp; | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
						time_t now_t = time(NULL); | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
						bool dec = false; | 
					 | 
					 | 
					 | 
						bool dec = false; | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					
 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
						LOGINFO("Stratifier dropping client %ld", id); | 
					 | 
					 | 
					 | 
						LOGINFO("Stratifier dropping client %ld", id); | 
				
			
			
		
	
	
		
		
			
				
					| 
						
						
						
							
								
							
						
					 | 
					 | 
					@ -1227,13 +1249,11 @@ static void drop_client(sdata_t *sdata, int64_t id) | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
							HASH_DEL(sdata->stratum_instances, client); | 
					 | 
					 | 
					 | 
							HASH_DEL(sdata->stratum_instances, client); | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
							HASH_FIND(hh, sdata->disconnected_instances, &client->enonce1_64, sizeof(uint64_t), old_client); | 
					 | 
					 | 
					 | 
							HASH_FIND(hh, sdata->disconnected_instances, &client->enonce1_64, sizeof(uint64_t), old_client); | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
							/* Only keep around one copy of the old client in server mode */ | 
					 | 
					 | 
					 | 
							/* Only keep around one copy of the old client in server mode */ | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
							if (!client->ckp->proxy && !old_client && client->enonce1_64) | 
					 | 
					 | 
					 | 
							if (!client->ckp->proxy && !old_client && client->enonce1_64) { | 
				
			
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
								HASH_ADD(hh, sdata->disconnected_instances, enonce1_64, sizeof(uint64_t), client); | 
					 | 
					 | 
					 | 
								HASH_ADD(hh, sdata->disconnected_instances, enonce1_64, sizeof(uint64_t), client); | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
							else { | 
					 | 
					 | 
					 | 
								client->disconnected_time = time(NULL); | 
				
			
			
				
				
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
								if (client->user_instance) | 
					 | 
					 | 
					 | 
							} else | 
				
			
			
				
				
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
									DL_DELETE(client->user_instance->instances, client); | 
					 | 
					 | 
					 | 
								kill_instance(sdata, client); | 
				
			
			
				
				
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
								LL_PREPEND(sdata->dead_instances, client); | 
					 | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
							} | 
					 | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
	
		
		
	
		
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
						} | 
					 | 
					 | 
					 | 
						} | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
						ck_wunlock(&sdata->instance_lock); | 
					 | 
					 | 
					 | 
						ck_wunlock(&sdata->instance_lock); | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					
 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
	
		
		
			
				
					| 
						
						
						
							
								
							
						
					 | 
					 | 
					@ -1247,6 +1267,18 @@ static void drop_client(sdata_t *sdata, int64_t id) | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
						ck_wlock(&sdata->instance_lock); | 
					 | 
					 | 
					 | 
						ck_wlock(&sdata->instance_lock); | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
						if (client) | 
					 | 
					 | 
					 | 
						if (client) | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
							__dec_instance_ref(client); | 
					 | 
					 | 
					 | 
							__dec_instance_ref(client); | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
						/* Old disconnected instances will not have any valid shares so remove
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
						 * them from the disconnected instances list if they've been dead for | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
						 * more than 10 minutes */ | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
						HASH_ITER(hh, sdata->disconnected_instances, client, tmp) { | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
							if (now_t - client->disconnected_time < 600) | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
								continue; | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
							LOGINFO("Discarding aged disconnected instance %ld", client->id); | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
							HASH_DEL(sdata->disconnected_instances, client); | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
							kill_instance(sdata, client); | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
						} | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
						/* Discard any dead instances that no longer hold any reference counts,
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
						 * freeing up their memory safely */ | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
						DL_FOREACH_SAFE(sdata->dead_instances, client, tmp) { | 
					 | 
					 | 
					 | 
						DL_FOREACH_SAFE(sdata->dead_instances, client, tmp) { | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
							if (!client->ref) { | 
					 | 
					 | 
					 | 
							if (!client->ref) { | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
								LOGINFO("Stratifier discarding instance %ld", client->id); | 
					 | 
					 | 
					 | 
								LOGINFO("Stratifier discarding instance %ld", client->id); | 
				
			
			
		
	
	
		
		
			
				
					| 
						
							
								
							
						
						
							
								
							
						
						
					 | 
					 | 
					@ -2533,6 +2565,17 @@ static json_t *parse_submit(stratum_instance_t *client, json_t *json_msg, | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
							nonce2[len] = '\0'; | 
					 | 
					 | 
					 | 
							nonce2[len] = '\0'; | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
						} | 
					 | 
					 | 
					 | 
						} | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
						sdiff = submission_diff(client, wb, nonce2, ntime32, nonce, hash); | 
					 | 
					 | 
					 | 
						sdiff = submission_diff(client, wb, nonce2, ntime32, nonce, hash); | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
						if (sdiff > client->best_diff) { | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
							worker_instance_t *worker = client->worker_instance; | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
							client->best_diff = sdiff; | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
							LOGINFO("User %s worker %s client %ld new best diff %lf", user_instance->username, | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
								worker->workername, client->id, sdiff); | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
							if (sdiff > worker->best_diff) | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
								worker->best_diff = sdiff; | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
							if (sdiff > user_instance->best_diff) | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
								user_instance->best_diff = sdiff; | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
						} | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
						bswap_256(sharehash, hash); | 
					 | 
					 | 
					 | 
						bswap_256(sharehash, hash); | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
						__bin2hex(hexhash, sharehash, 32); | 
					 | 
					 | 
					 | 
						__bin2hex(hexhash, sharehash, 32); | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					
 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
	
		
		
			
				
					| 
						
							
								
							
						
						
							
								
							
						
						
					 | 
					 | 
					@ -2619,9 +2662,9 @@ out_unlock: | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
						if (ckp->logshares) { | 
					 | 
					 | 
					 | 
						if (ckp->logshares) { | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
							fp = fopen(fname, "ae"); | 
					 | 
					 | 
					 | 
							fp = fopen(fname, "ae"); | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
							if (likely(fp)) { | 
					 | 
					 | 
					 | 
							if (likely(fp)) { | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
								s = json_dumps(val, 0); | 
					 | 
					 | 
					 | 
								s = json_dumps(val, JSON_EOL); | 
				
			
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
								len = strlen(s); | 
					 | 
					 | 
					 | 
								len = strlen(s); | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
								len = fprintf(fp, "%s\n", s); | 
					 | 
					 | 
					 | 
								len = fprintf(fp, "%s", s); | 
				
			
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
								free(s); | 
					 | 
					 | 
					 | 
								free(s); | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
								fclose(fp); | 
					 | 
					 | 
					 | 
								fclose(fp); | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
								if (unlikely(len < 0)) | 
					 | 
					 | 
					 | 
								if (unlikely(len < 0)) | 
				
			
			
		
	
	
		
		
			
				
					| 
						
							
								
							
						
						
							
								
							
						
						
					 | 
					 | 
					@ -3543,11 +3586,12 @@ static void *statsupdate(void *arg) | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
									ghs = worker->dsps1440 * nonces; | 
					 | 
					 | 
					 | 
									ghs = worker->dsps1440 * nonces; | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
									suffix_string(ghs, suffix1440, 16, 0); | 
					 | 
					 | 
					 | 
									suffix_string(ghs, suffix1440, 16, 0); | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					
 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
									JSON_CPACK(val, "{ss,ss,ss,ss}", | 
					 | 
					 | 
					 | 
									JSON_CPACK(val, "{ss,ss,ss,ss,sf}", | 
				
			
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
											"hashrate1m", suffix1, | 
					 | 
					 | 
					 | 
											"hashrate1m", suffix1, | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
											"hashrate5m", suffix5, | 
					 | 
					 | 
					 | 
											"hashrate5m", suffix5, | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
											"hashrate1hr", suffix60, | 
					 | 
					 | 
					 | 
											"hashrate1hr", suffix60, | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
											"hashrate1d", suffix1440); | 
					 | 
					 | 
					 | 
											"hashrate1d", suffix1440, | 
				
			
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
											"bestshare", worker->best_diff); | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					
 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
									snprintf(fname, 511, "%s/workers/%s", ckp->logdir, worker->workername); | 
					 | 
					 | 
					 | 
									snprintf(fname, 511, "%s/workers/%s", ckp->logdir, worker->workername); | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
									fp = fopen(fname, "we"); | 
					 | 
					 | 
					 | 
									fp = fopen(fname, "we"); | 
				
			
			
		
	
	
		
		
			
				
					| 
						
						
						
							
								
							
						
					 | 
					 | 
					@ -3555,8 +3599,8 @@ static void *statsupdate(void *arg) | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
										LOGERR("Failed to fopen %s", fname); | 
					 | 
					 | 
					 | 
										LOGERR("Failed to fopen %s", fname); | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
										continue; | 
					 | 
					 | 
					 | 
										continue; | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
									} | 
					 | 
					 | 
					 | 
									} | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
									s = json_dumps(val, JSON_NO_UTF8 | JSON_PRESERVE_ORDER); | 
					 | 
					 | 
					 | 
									s = json_dumps(val, JSON_NO_UTF8 | JSON_PRESERVE_ORDER | JSON_EOL); | 
				
			
			
				
				
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
									fprintf(fp, "%s\n", s); | 
					 | 
					 | 
					 | 
									fprintf(fp, "%s", s); | 
				
			
			
				
				
			
		
	
		
		
	
		
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
									dealloc(s); | 
					 | 
					 | 
					 | 
									dealloc(s); | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
									json_decref(val); | 
					 | 
					 | 
					 | 
									json_decref(val); | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
									fclose(fp); | 
					 | 
					 | 
					 | 
									fclose(fp); | 
				
			
			
		
	
	
		
		
			
				
					| 
						
							
								
							
						
						
							
								
							
						
						
					 | 
					 | 
					@ -3587,13 +3631,14 @@ static void *statsupdate(void *arg) | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
								ghs = instance->dsps10080 * nonces; | 
					 | 
					 | 
					 | 
								ghs = instance->dsps10080 * nonces; | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
								suffix_string(ghs, suffix10080, 16, 0); | 
					 | 
					 | 
					 | 
								suffix_string(ghs, suffix10080, 16, 0); | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					
 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
								JSON_CPACK(val, "{ss,ss,ss,ss,ss,si}", | 
					 | 
					 | 
					 | 
								JSON_CPACK(val, "{ss,ss,ss,ss,ss,si,sf}", | 
				
			
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
										"hashrate1m", suffix1, | 
					 | 
					 | 
					 | 
										"hashrate1m", suffix1, | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
										"hashrate5m", suffix5, | 
					 | 
					 | 
					 | 
										"hashrate5m", suffix5, | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
										"hashrate1hr", suffix60, | 
					 | 
					 | 
					 | 
										"hashrate1hr", suffix60, | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
										"hashrate1d", suffix1440, | 
					 | 
					 | 
					 | 
										"hashrate1d", suffix1440, | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
										"hashrate7d", suffix10080, | 
					 | 
					 | 
					 | 
										"hashrate7d", suffix10080, | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
										"workers", instance->workers); | 
					 | 
					 | 
					 | 
										"workers", instance->workers, | 
				
			
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
										"bestshare", instance->best_diff); | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					
 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
								snprintf(fname, 511, "%s/users/%s", ckp->logdir, instance->username); | 
					 | 
					 | 
					 | 
								snprintf(fname, 511, "%s/users/%s", ckp->logdir, instance->username); | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
								fp = fopen(fname, "we"); | 
					 | 
					 | 
					 | 
								fp = fopen(fname, "we"); | 
				
			
			
		
	
	
		
		
			
				
					| 
						
							
								
							
						
						
						
					 | 
					 | 
					
  |