| 
						
						
							
								
							
						
						
					 | 
				
				 | 
				 | 
				
					@ -479,9 +479,10 @@ static const char *hashpatt = "^[A-Fa-f0-9]*$";
					 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
					#define JSON_TRANSFER_LEN (sizeof(JSON_TRANSFER)-1) | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
					
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
					// Methods for sharelog (common function for all 3)
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
					#define METHOD_WORKINFO "workinfo" | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
					#define METHOD_SHARES "shares" | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
					#define METHOD_SHAREERRORS "shareerror" | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
					#define STR_WORKINFO "workinfo" | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
					#define STR_SHARES "shares" | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
					#define STR_SHAREERRORS "shareerror" | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
					#define STR_AGEWORKINFO "ageworkinfo" | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
					
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
					// TRANSFER
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
					#define NAME_SIZE 63 | 
				
			
			
		
	
	
		
			
				
					| 
						
							
								
							
						
						
							
								
							
						
						
					 | 
				
				 | 
				 | 
				
					@ -793,11 +794,10 @@ typedef struct sharesummary {
					 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
					#define DATA_SHARESUMMARY(_item) ((SHARESUMMARY *)(_item->data)) | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
					
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
					#define SUMMARY_NEW 'n' | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
					#define SUMMARY_AGED 'a' | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
					#define SUMMARY_CONFIRM 'y' | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
					
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
					static K_TREE *sharesummary_root; | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
					/* TODO: for 'complete' flagging i.e.
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
					   older items should be flagged if we flag a newer item */ | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
					static K_TREE *sharesummary_workinfoid_root; | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
					static K_LIST *sharesummary_list; | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
					static K_STORE *sharesummary_store; | 
				
			
			
		
	
	
		
			
				
					| 
						
							
								
							
						
						
							
								
							
						
						
					 | 
				
				 | 
				 | 
				
					@ -2468,6 +2468,87 @@ unparam:
					 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
						return workinfoid; | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
					} | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
					
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
					static double cmp_shares(K_ITEM *a, K_ITEM *b); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
					static double cmp_sharesummary_workinfoid(K_ITEM *a, K_ITEM *b); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
					static bool sharesummary_update(PGconn *conn, SHARES *s_row, SHAREERRORS *e_row, K_ITEM *ss_item, | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
									tv_t *now, char *by, char *code, char *inet); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
					
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
					static bool workinfo_age(PGconn *conn, char *workinfoidstr, char *poolinstance, | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
								 tv_t *now, char *by, char *code, char *inet) | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
					{ | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
						K_ITEM *wi_item, ss_look, *ss_item, s_look, *s_item, *tmp_item; | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
						K_TREE_CTX ss_ctx[1], s_ctx[1], tmp_ctx[1]; | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
						int64_t workinfoid; | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
						SHARESUMMARY sharesummary; | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
						SHARES shares; | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
						bool ok = false, conned = false; | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
					
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
						LOGDEBUG("%s(): complete", __func__); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
					
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
						TXT_TO_BIGINT("workinfoid", workinfoidstr, workinfoid); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
					
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
						wi_item = find_workinfo(workinfoid); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
						if (!wi_item) | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
							goto bye; | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
					
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
						if (strcmp(poolinstance, DATA_WORKINFO(wi_item)->poolinstance) != 0) | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
							goto bye; | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
					
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
						// Find the first matching sharesummary
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
						sharesummary.workinfoid = workinfoid; | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
						sharesummary.userid = -1; | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
						sharesummary.workername[0] = '\0'; | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
					
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
						ok = true; | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
						ss_look.data = (void *)(&sharesummary); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
						ss_item = find_after_in_ktree(sharesummary_workinfoid_root, &ss_look, cmp_sharesummary_workinfoid, ss_ctx); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
						while (ss_item && DATA_SHARESUMMARY(ss_item)->workinfoid == workinfoid) { | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
							if (conn == NULL) { | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
								conn = dbconnect(); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
								conned = true; | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
							} | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
					
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
							if (!sharesummary_update(conn, NULL, NULL, ss_item, now, by, code, inet)) { | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
								LOGERR("%s(): Failed to age share summary %"PRId64"/%s/%"PRId64, | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
									__func__, DATA_SHARESUMMARY(ss_item)->userid, | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
									DATA_SHARESUMMARY(ss_item)->workername, | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
									DATA_SHARESUMMARY(ss_item)->workinfoid); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
								ok = false; | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
							} | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
					
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
							// Discard the shares either way
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
							shares.workinfoid = workinfoid; | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
							shares.userid = DATA_SHARESUMMARY(ss_item)->userid; | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
							strcpy(shares.workername, DATA_SHARESUMMARY(ss_item)->workername); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
							shares.createdate.tv_sec = 0; | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
							shares.createdate.tv_usec = 0; | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
					
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
							s_look.data = (void *)(&shares); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
							s_item = find_after_in_ktree(shares_root, &s_look, cmp_shares, s_ctx); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
							K_WLOCK(shares_list); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
							while (s_item) { | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
								if (DATA_SHARES(s_item)->workinfoid != workinfoid || | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
								    DATA_SHARES(s_item)->userid != shares.userid || | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
								    strcmp(DATA_SHARES(s_item)->workername, shares.workername) != 0) | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
									break; | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
					
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
								tmp_item = next_in_ktree(s_ctx); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
								shares_root = remove_from_ktree(shares_root, s_item, cmp_shares, tmp_ctx); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
								k_unlink_item(shares_store, s_item); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
								k_add_head(shares_list, s_item); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
								s_item = tmp_item; | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
							} | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
							K_WUNLOCK(shares_list); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
							ss_item = next_in_ktree(ss_ctx); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
						} | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
					
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
						if (conned) | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
							PQfinish(conn); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
					
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
					bye: | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
						return ok; | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
					} | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
					
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
					static bool workinfo_fill(PGconn *conn) | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
					{ | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
						ExecStatusType rescode; | 
				
			
			
		
	
	
		
			
				
					| 
						
							
								
							
						
						
							
								
							
						
						
					 | 
				
				 | 
				 | 
				
					@ -2611,7 +2692,7 @@ void workinfo_reload()
					 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
					*/ | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
					} | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
					
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
					// order by workinfoid asc,userid asc,createdate asc,nonce asc,expirydate desc
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
					// order by workinfoid asc,userid asc,workername asc,createdate asc,nonce asc,expirydate desc
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
					static double cmp_shares(K_ITEM *a, K_ITEM *b) | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
					{ | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
						double c = (double)(DATA_SHARES(a)->workinfoid - | 
				
			
			
		
	
	
		
			
				
					| 
						
						
						
							
								
							
						
					 | 
				
				 | 
				 | 
				
					@ -2620,14 +2701,18 @@ static double cmp_shares(K_ITEM *a, K_ITEM *b)
					 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
							c = (double)(DATA_SHARES(a)->userid - | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
								     DATA_SHARES(b)->userid); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
							if (c == 0) { | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
								c = tvdiff(&(DATA_SHARES(a)->createdate), | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
									   &(DATA_SHARES(b)->createdate)); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
								c = strcmp(DATA_SHARES(a)->workername, | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
									   DATA_SHARES(b)->workername); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
								if (c == 0) { | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
									c = strcmp(DATA_SHARES(a)->nonce, | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
										   DATA_SHARES(b)->nonce); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
									c = tvdiff(&(DATA_SHARES(a)->createdate), | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
										   &(DATA_SHARES(b)->createdate)); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
									if (c == 0) { | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
										c = tvdiff(&(DATA_SHARES(b)->expirydate), | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
											   &(DATA_SHARES(a)->expirydate)); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
										c = strcmp(DATA_SHARES(a)->nonce, | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
											   DATA_SHARES(b)->nonce); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
										if (c == 0) { | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
											c = tvdiff(&(DATA_SHARES(b)->expirydate), | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
												   &(DATA_SHARES(a)->expirydate)); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
										} | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
									} | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
								} | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
							} | 
				
			
			
		
	
	
		
			
				
					| 
						
						
						
							
								
							
						
					 | 
				
				 | 
				 | 
				
					@ -2635,9 +2720,6 @@ static double cmp_shares(K_ITEM *a, K_ITEM *b)
					 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
						return c; | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
					} | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
					
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
					static bool sharesummary_update(PGconn *conn, SHARES *s_row, SHAREERRORS *e_row, | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
									tv_t *now, char *by, char *code, char *inet); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
					
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
					// Memory (and log file) only
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
					static bool shares_add(char *workinfoid, char *username, char *workername, char *clientid, | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
								char *enonce1, char *nonce2, char *nonce, char *diff, char *sdiff, | 
				
			
			
		
	
	
		
			
				
					| 
						
							
								
							
						
						
							
								
							
						
						
					 | 
				
				 | 
				 | 
				
					@ -2684,7 +2766,7 @@ static bool shares_add(char *workinfoid, char *username, char *workername, char
					 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
						if (!w_item) | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
							goto unitem; | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
					
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
						sharesummary_update(NULL, shares, NULL, now, by, code, inet); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
						sharesummary_update(NULL, shares, NULL, NULL, now, by, code, inet); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
					
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
						ok = true; | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
					unitem: | 
				
			
			
		
	
	
		
			
				
					| 
						
							
								
							
						
						
							
								
							
						
						
					 | 
				
				 | 
				 | 
				
					@ -2771,7 +2853,7 @@ static bool shareerrors_add(char *workinfoid, char *username, char *workername,
					 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
						if (!w_item) | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
							goto unitem; | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
					
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
						sharesummary_update(NULL, NULL, shareerrors, now, by, code, inet); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
						sharesummary_update(NULL, NULL, shareerrors, NULL, now, by, code, inet); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
					
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
						ok = true; | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
					unitem: | 
				
			
			
		
	
	
		
			
				
					| 
						
							
								
							
						
						
							
								
							
						
						
					 | 
				
				 | 
				 | 
				
					@ -2865,10 +2947,7 @@ static K_ITEM *find_sharesummary(int64_t userid, char *workername, int64_t worki
					 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
						return find_in_ktree(sharesummary_root, &look, cmp_sharesummary, ctx); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
					} | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
					
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
					// TODO: discard shares,shareerrors in caller if this returns true?
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
					// or keep them for a specific history so can check the errors?
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
					// or error checking should use the log files?
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
					static bool sharesummary_update(PGconn *conn, SHARES *s_row, SHAREERRORS *e_row, | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
					static bool sharesummary_update(PGconn *conn, SHARES *s_row, SHAREERRORS *e_row, K_ITEM *ss_item, | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
									tv_t *now, char *by, char *code, char *inet) | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
					{ | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
						ExecStatusType rescode; | 
				
			
			
		
	
	
		
			
				
					| 
						
						
						
							
								
							
						
					 | 
				
				 | 
				 | 
				
					@ -2882,115 +2961,128 @@ static bool sharesummary_update(PGconn *conn, SHARES *s_row, SHAREERRORS *e_row,
					 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
						int64_t userid, workinfoid; | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
						char *workername; | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
						tv_t *sharecreatedate; | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
						bool conned = false; | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
						bool must_update = false, conned = false; | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
					
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
						LOGDEBUG("%s(): add", __func__); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
						LOGDEBUG("%s(): update", __func__); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
					
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
						if (s_row) { | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
							if (e_row) { | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
								quithere(1, "ERR: %s() one of s_row and e_row must be NULL", | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
									    __func__); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
							} | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
							userid = s_row->userid; | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
							workername = s_row->workername; | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
							workinfoid = s_row->workinfoid; | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
							sharecreatedate = &(s_row->createdate); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
						} else { | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
							if (!e_row) { | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
								quithere(1, "ERR: %s() both s_row and e_row are NULL", | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
						if (ss_item) { | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
							if (s_row || e_row) { | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
								quithere(1, "ERR: %s() only one of s_row, e_row and ss_item allowed", | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
									    __func__); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
							} | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
							userid = e_row->userid; | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
							workername = e_row->workername; | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
							workinfoid = e_row->workinfoid; | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
							sharecreatedate = &(e_row->createdate); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
						} | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
					
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
						item = find_sharesummary(userid, workername, workinfoid); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
						if (item) { | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
							new = false; | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
							item = ss_item; | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
							row = DATA_SHARESUMMARY(item); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
						} else { | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
							new = true; | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
							K_WLOCK(sharesummary_list); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
							item = k_unlink_head(sharesummary_list); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
							K_WUNLOCK(sharesummary_list); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
							row = DATA_SHARESUMMARY(item); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
							row->userid = userid; | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
							STRNCPY(row->workername, workername); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
							row->workinfoid = workinfoid; | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
							row->diffacc = row->diffsta = row->diffdup = row->diffhi = | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
							row->diffrej = row->shareacc = row->sharesta = row->sharedup = | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
							row->sharehi = row->sharerej = 0.0; | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
							row->sharecount = row->errorcount = row->countlastupdate = 0; | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
							row->inserted = false; | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
							row->firstshare.tv_sec = sharecreatedate->tv_sec; | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
							row->firstshare.tv_usec = sharecreatedate->tv_usec; | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
							row->lastshare.tv_sec = row->firstshare.tv_sec; | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
							row->lastshare.tv_usec = row->firstshare.tv_usec; | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
							row->complete[0] = SUMMARY_NEW; | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
							must_update = true; | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
							row->complete[0] = SUMMARY_AGED; | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
							row->complete[1] = '\0'; | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
						} | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
					
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
						if (e_row) | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
							row->errorcount += 1; | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
						else { | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
							row->sharecount += 1; | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
							switch (s_row->errn) { | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
								case SE_NONE: | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
									row->diffacc += s_row->diff; | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
									row->shareacc++; | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
									break; | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
								case SE_STALE: | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
									row->diffsta += s_row->diff; | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
									row->sharesta++; | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
									break; | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
								case SE_DUPE: | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
									row->diffdup += s_row->diff; | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
									row->sharedup++; | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
									break; | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
								case SE_HIGH_DIFF: | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
									row->diffhi += s_row->diff; | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
									row->sharehi++; | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
									break; | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
								default: | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
									row->diffrej += s_row->diff; | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
									row->sharerej++; | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
									break; | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
						} else { | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
							if (s_row) { | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
								if (e_row) { | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
									quithere(1, "ERR: %s() only one of s_row, e_row (and ss_item) allowed", | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
										    __func__); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
								} | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
								userid = s_row->userid; | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
								workername = s_row->workername; | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
								workinfoid = s_row->workinfoid; | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
								sharecreatedate = &(s_row->createdate); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
							} else { | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
								if (!e_row) { | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
									quithere(1, "ERR: %s() all s_row, e_row and ss_item are NULL", | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
										    __func__); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
								} | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
								userid = e_row->userid; | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
								workername = e_row->workername; | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
								workinfoid = e_row->workinfoid; | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
								sharecreatedate = &(e_row->createdate); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
							} | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
						} | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
					
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
						if (!new) { | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
							double td; | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
							td = tvdiff(sharecreatedate, &(row->firstshare)); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
							if (td <= 0.0) { | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
								char *tmp1, *tmp2; | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
								LOGERR("%s(): %s createdate (%s) is before summary firstshare (%s)", | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
									__func__, s_row ? "shares" : "shareerrors", | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
									(tmp1 = ctv_to_buf(sharecreatedate, NULL, 0)), | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
									(tmp2 = ctv_to_buf(&(row->firstshare), NULL, 0))); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
								free(tmp2); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
								free(tmp1); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
							item = find_sharesummary(userid, workername, workinfoid); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
							if (item) { | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
								new = false; | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
								row = DATA_SHARESUMMARY(item); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
							} else { | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
								new = true; | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
								K_WLOCK(sharesummary_list); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
								item = k_unlink_head(sharesummary_list); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
								K_WUNLOCK(sharesummary_list); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
								row = DATA_SHARESUMMARY(item); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
								row->userid = userid; | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
								STRNCPY(row->workername, workername); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
								row->workinfoid = workinfoid; | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
								row->diffacc = row->diffsta = row->diffdup = row->diffhi = | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
								row->diffrej = row->shareacc = row->sharesta = row->sharedup = | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
								row->sharehi = row->sharerej = 0.0; | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
								row->sharecount = row->errorcount = row->countlastupdate = 0; | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
								row->inserted = false; | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
								row->firstshare.tv_sec = sharecreatedate->tv_sec; | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
								row->firstshare.tv_usec = sharecreatedate->tv_usec; | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
								row->lastshare.tv_sec = row->firstshare.tv_sec; | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
								row->lastshare.tv_usec = row->firstshare.tv_usec; | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
								row->complete[0] = SUMMARY_NEW; | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
								row->complete[1] = '\0'; | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
							} | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
							td = tvdiff(sharecreatedate, &(row->lastshare)); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
							if (td > 0.0) { | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
								row->lastshare.tv_sec = sharecreatedate->tv_sec; | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
								row->lastshare.tv_usec = sharecreatedate->tv_usec; | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
							} else { | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
								char *tmp1, *tmp2; | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
								LOGERR("%s(): %s createdate (%s) is before summary lastshare (%s)", | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
									__func__, s_row ? "shares" : "shareerrors", | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
									(tmp1 = ctv_to_buf(sharecreatedate, NULL, 0)), | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
									(tmp2 = ctv_to_buf(&(row->lastshare), NULL, 0))); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
								free(tmp2); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
								free(tmp1); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
					
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
							if (e_row) | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
								row->errorcount += 1; | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
							else { | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
								row->sharecount += 1; | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
								switch (s_row->errn) { | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
									case SE_NONE: | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
										row->diffacc += s_row->diff; | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
										row->shareacc++; | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
										break; | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
									case SE_STALE: | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
										row->diffsta += s_row->diff; | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
										row->sharesta++; | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
										break; | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
									case SE_DUPE: | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
										row->diffdup += s_row->diff; | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
										row->sharedup++; | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
										break; | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
									case SE_HIGH_DIFF: | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
										row->diffhi += s_row->diff; | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
										row->sharehi++; | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
										break; | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
									default: | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
										row->diffrej += s_row->diff; | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
										row->sharerej++; | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
										break; | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
								} | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
							} | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
							if (row->complete[0] != SUMMARY_NEW) { | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
								LOGDEBUG("%s(): updating sharesummary not '%c' %"PRId64"/%s/%"PRId64"/%s", | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
									__func__, SUMMARY_NEW, row->userid, row->workername, | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
									row->workinfoid, row->complete); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
					
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
							if (!new) { | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
								double td; | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
								td = tvdiff(sharecreatedate, &(row->firstshare)); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
									if (td <= 0.0) { | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
									char *tmp1, *tmp2; | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
									LOGERR("%s(): %s createdate (%s) is before summary firstshare (%s)", | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
										__func__, s_row ? "shares" : "shareerrors", | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
										(tmp1 = ctv_to_buf(sharecreatedate, NULL, 0)), | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
										(tmp2 = ctv_to_buf(&(row->firstshare), NULL, 0))); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
									free(tmp2); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
									free(tmp1); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
									row->firstshare.tv_sec = sharecreatedate->tv_sec; | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
									row->firstshare.tv_usec = sharecreatedate->tv_usec; | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
								} | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
								td = tvdiff(sharecreatedate, &(row->lastshare)); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
								if (td > 0.0) { | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
									row->lastshare.tv_sec = sharecreatedate->tv_sec; | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
									row->lastshare.tv_usec = sharecreatedate->tv_usec; | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
								} else { | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
									char *tmp1, *tmp2; | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
									LOGERR("%s(): %s createdate (%s) is before summary lastshare (%s)", | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
										__func__, s_row ? "shares" : "shareerrors", | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
										(tmp1 = ctv_to_buf(sharecreatedate, NULL, 0)), | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
										(tmp2 = ctv_to_buf(&(row->lastshare), NULL, 0))); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
									free(tmp2); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
									free(tmp1); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
								} | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
								if (row->complete[0] != SUMMARY_NEW) { | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
									LOGDEBUG("%s(): updating sharesummary not '%c' %"PRId64"/%s/%"PRId64"/%s", | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
										__func__, SUMMARY_NEW, row->userid, row->workername, | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
										row->workinfoid, row->complete); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
								} | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
							} | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
						} | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
					
 | 
				
			
			
		
	
	
		
			
				
					| 
						
							
								
							
						
						
							
								
							
						
						
					 | 
				
				 | 
				 | 
				
					@ -3040,10 +3132,18 @@ static bool sharesummary_update(PGconn *conn, SHARES *s_row, SHAREERRORS *e_row,
					 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
							row->countlastupdate = row->sharecount + row->errorcount; | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
							row->inserted = true; | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
						} else { | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
							bool stats_update = false; | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
					
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
							MODIFYUPDATE(row, now, by, code, inet); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
					
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
							if ((row->countlastupdate + SHARESUMMARY_UPDATE_EVERY) < | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
							    (row->sharecount + row->errorcount)) { | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
							    (row->sharecount + row->errorcount)) | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
								stats_update = true; | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
					
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
							if (must_update && row->countlastupdate < (row->sharecount + row->errorcount)) | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
								stats_update = true; | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
					
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
							if (stats_update) { | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
								par = 0; | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
								params[par++] = bigint_to_buf(row->userid, NULL, 0); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
								params[par++] = str_to_buf(row->workername, NULL, 0); | 
				
			
			
		
	
	
		
			
				
					| 
						
						
						
							
								
							
						
					 | 
				
				 | 
				 | 
				
					@ -3060,26 +3160,49 @@ static bool sharesummary_update(PGconn *conn, SHARES *s_row, SHAREERRORS *e_row,
					 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
								params[par++] = double_to_buf(row->sharerej, NULL, 0); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
								params[par++] = tv_to_buf(&(row->firstshare), NULL, 0); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
								params[par++] = tv_to_buf(&(row->lastshare), NULL, 0); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
								params[par++] = str_to_buf(row->complete, NULL, 0); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
								MODIFYUPDATEPARAMS(params, par, row); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
								PARCHKVAL(par, 19, params); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
								PARCHKVAL(par, 20, params); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
					
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
								upd = "update sharesummary " | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
									"set diffacc=$4,diffsta=$5,diffdup=$6,diffhi=$7,diffrej=$8," | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
									"shareacc=$9,sharesta=$10,sharedup=$11,sharehi=$12," | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
									"sharerej=$13,firstshare=$14,lastshare=$15" | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
									",modifydate=$16,modifyby=$17,modifycode=$18,modifyinet=$19 " | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
									"sharerej=$13,firstshare=$14,lastshare=$15,complete=$16" | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
									",modifydate=$17,modifyby=$18,modifycode=$19,modifyinet=$20 " | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
									"where userid=$1 and workername=$2 and workinfoid=$3"; | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
					
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
								res = PQexecParams(conn, upd, par, NULL, (const char **)params, NULL, NULL, 0); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
								rescode = PQresultStatus(res); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
								if (!PGOK(rescode)) { | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
									PGLOGERR("Insert", rescode, conn); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
									PGLOGERR("Update", rescode, conn); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
									goto unparam; | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
								} | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
								row->countlastupdate = row->sharecount + row->errorcount; | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
							} else { | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
								ok = true; | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
								goto late; | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
								if (!must_update) { | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
									ok = true; | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
									goto late; | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
								} else { | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
									par = 0; | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
									params[par++] = bigint_to_buf(row->userid, NULL, 0); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
									params[par++] = str_to_buf(row->workername, NULL, 0); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
									params[par++] = bigint_to_buf(row->workinfoid, NULL, 0); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
									params[par++] = str_to_buf(row->complete, NULL, 0); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
									MODIFYUPDATEPARAMS(params, par, row); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
									PARCHKVAL(par, 8, params); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
					
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
									upd = "update sharesummary " | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
										"set complete=$4,modifydate=$5,modifyby=$6,modifycode=$7,modifyinet=$8 " | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
										"where userid=$1 and workername=$2 and workinfoid=$3"; | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
					
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
									res = PQexecParams(conn, upd, par, NULL, (const char **)params, NULL, NULL, 0); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
									rescode = PQresultStatus(res); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
									if (!PGOK(rescode)) { | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
										PGLOGERR("MustUpdate", rescode, conn); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
										goto unparam; | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
									} | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
									row->countlastupdate = row->sharecount + row->errorcount; | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
								} | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
							} | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
						} | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
					
 | 
				
			
			
		
	
	
		
			
				
					| 
						
						
						
							
								
							
						
					 | 
				
				 | 
				 | 
				
					@ -3092,7 +3215,7 @@ late:
					 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
						if (conned) | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
							PQfinish(conn); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
					
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
						// We keep the new item anyway since it can be inserted next time
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
						// We keep the new item no matter what 'ok' is, since it will be inserted later
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
						K_WLOCK(sharesummary_list); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
						if (new) { | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
							sharesummary_root = add_to_ktree(sharesummary_root, item, cmp_sharesummary); | 
				
			
			
		
	
	
		
			
				
					| 
						
							
								
							
						
						
							
								
							
						
						
					 | 
				
				 | 
				 | 
				
					@ -4798,7 +4921,7 @@ static char *cmd_workers(char *cmd, char *id, __maybe_unused tv_t *now, __maybe_
					 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
									__maybe_unused char *code, __maybe_unused char *inet) | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
					{ | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
						K_ITEM *i_username, *i_stats, wlook, *u_item, *w_item, uslook, *us_item; | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
						K_TREE_CTX wctx[1], usctx[1]; | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
						K_TREE_CTX w_ctx[1], us_ctx[1]; | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
						WORKERS workers; | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
						USERSTATS userstats; | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
						char reply[1024] = ""; | 
				
			
			
		
	
	
		
			
				
					| 
						
							
								
							
						
						
							
								
							
						
						
					 | 
				
				 | 
				 | 
				
					@ -4830,7 +4953,7 @@ static char *cmd_workers(char *cmd, char *id, __maybe_unused tv_t *now, __maybe_
					 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
						workers.expirydate.tv_sec = 0; | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
						workers.expirydate.tv_usec = 0; | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
						wlook.data = (void *)(&workers); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
						w_item = find_after_in_ktree(workers_root, &wlook, cmp_workers, wctx); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
						w_item = find_after_in_ktree(workers_root, &wlook, cmp_workers, w_ctx); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
						APPEND_REALLOC_INIT(buf, off, len); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
						APPEND_REALLOC(buf, off, len, "ok."); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
						rows = 0; | 
				
			
			
		
	
	
		
			
				
					| 
						
						
						
							
								
							
						
					 | 
				
				 | 
				 | 
				
					@ -4854,7 +4977,7 @@ static char *cmd_workers(char *cmd, char *id, __maybe_unused tv_t *now, __maybe_
					 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
					
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
								if (stats) { | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
									K_TREE *userstats_workername_root = new_ktree(); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
									K_TREE_CTX uswctx[1]; | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
									K_TREE_CTX usw_ctx[1]; | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
									double w_hashrate5m, w_hashrate1hr; | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
									int64_t w_elapsed; | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
									tv_t w_lastshare; | 
				
			
			
		
	
	
		
			
				
					| 
						
						
						
							
								
							
						
					 | 
				
				 | 
				 | 
				
					@ -4871,7 +4994,7 @@ static char *cmd_workers(char *cmd, char *id, __maybe_unused tv_t *now, __maybe_
					 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
									userstats.poolinstance[0] = '\0'; | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
									userstats.workername[0] = '\0'; | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
									uslook.data = (void *)(&userstats); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
									us_item = find_before_in_ktree(userstats_root, &uslook, cmp_userstats, usctx); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
									us_item = find_before_in_ktree(userstats_root, &uslook, cmp_userstats, us_ctx); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
									while (us_item && DATA_USERSTATS(us_item)->userid == userstats.userid) { | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
										if (strcmp(DATA_USERSTATS(us_item)->workername, DATA_WORKERS(w_item)->workername) == 0) { | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
											// first found is the newest share
 | 
				
			
			
		
	
	
		
			
				
					| 
						
						
						
							
								
							
						
					 | 
				
				 | 
				 | 
				
					@ -4880,7 +5003,7 @@ static char *cmd_workers(char *cmd, char *id, __maybe_unused tv_t *now, __maybe_
					 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
					
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
											if (tvdiff(now, &(DATA_USERSTATS(us_item)->createdate)) < USERSTATS_PER_S) { | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
												// TODO: add together the latest per pool instance (this is the latest per worker)
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
												if (!find_in_ktree(userstats_workername_root, us_item, cmp_userstats_workername, uswctx)) { | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
												if (!find_in_ktree(userstats_workername_root, us_item, cmp_userstats_workername, usw_ctx)) { | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
													w_hashrate5m += DATA_USERSTATS(us_item)->hashrate5m; | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
													w_hashrate1hr += DATA_USERSTATS(us_item)->hashrate1hr; | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
													if (w_elapsed == -1 || w_elapsed > DATA_USERSTATS(us_item)->elapsed) | 
				
			
			
		
	
	
		
			
				
					| 
						
						
						
							
								
							
						
					 | 
				
				 | 
				 | 
				
					@ -4894,7 +5017,7 @@ static char *cmd_workers(char *cmd, char *id, __maybe_unused tv_t *now, __maybe_
					 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
												break; | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
					
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
										} | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
										us_item = prev_in_ktree(usctx); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
										us_item = prev_in_ktree(us_ctx); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
									} | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
					
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
									double_to_buf(w_hashrate5m, reply, sizeof(reply)); | 
				
			
			
		
	
	
		
			
				
					| 
						
						
						
							
								
							
						
					 | 
				
				 | 
				 | 
				
					@ -4918,7 +5041,7 @@ static char *cmd_workers(char *cmd, char *id, __maybe_unused tv_t *now, __maybe_
					 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
					
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
								rows++; | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
							} | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
							w_item = next_in_ktree(wctx); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
							w_item = next_in_ktree(w_ctx); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
						} | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
						snprintf(tmp, sizeof(tmp), "rows=%d", rows); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
						APPEND_REALLOC(buf, off, len, tmp); | 
				
			
			
		
	
	
		
			
				
					| 
						
						
						
							
								
							
						
					 | 
				
				 | 
				 | 
				
					@ -4932,7 +5055,7 @@ static char *cmd_allusers(char *cmd, char *id, __maybe_unused tv_t *now, __maybe
					 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
					{ | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
						K_TREE *userstats_workername_root = new_ktree(); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
						K_ITEM *us_item, *usw_item, *tmp_item, *u_item; | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
						K_TREE_CTX usctx[1], uswctx[1]; | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
						K_TREE_CTX us_ctx[1], usw_ctx[1]; | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
						char reply[1024] = ""; | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
						char tmp[1024]; | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
						char *buf; | 
				
			
			
		
	
	
		
			
				
					| 
						
						
						
							
								
							
						
					 | 
				
				 | 
				 | 
				
					@ -4945,9 +5068,9 @@ static char *cmd_allusers(char *cmd, char *id, __maybe_unused tv_t *now, __maybe
					 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
					
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
						// Find last records for each user/worker in ALLUSERS_LIMIT_S
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
						// TODO: include pool_instance
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
						us_item = last_in_ktree(userstats_root, usctx); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
						us_item = last_in_ktree(userstats_root, us_ctx); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
						while (us_item && tvdiff(now, &(DATA_USERSTATS(us_item)->createdate)) < ALLUSERS_LIMIT_S) { | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
							usw_item = find_in_ktree(userstats_workername_root, us_item, cmp_userstats_workername, uswctx); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
							usw_item = find_in_ktree(userstats_workername_root, us_item, cmp_userstats_workername, usw_ctx); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
							if (!usw_item) { | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
								K_WLOCK(userstats_list); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
								usw_item = k_unlink_head(userstats_list); | 
				
			
			
		
	
	
		
			
				
					| 
						
						
						
							
								
							
						
					 | 
				
				 | 
				 | 
				
					@ -4966,7 +5089,7 @@ static char *cmd_allusers(char *cmd, char *id, __maybe_unused tv_t *now, __maybe
					 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
						APPEND_REALLOC(buf, off, len, "ok."); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
						rows = 0; | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
						// Add up per user
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
						usw_item = first_in_ktree(userstats_workername_root, uswctx); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
						usw_item = first_in_ktree(userstats_workername_root, usw_ctx); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
						while (usw_item) { | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
							if (DATA_USERSTATS(usw_item)->userid != userid) { | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
								if (userid != -1) { | 
				
			
			
		
	
	
		
			
				
					| 
						
							
								
							
						
						
							
								
							
						
						
					 | 
				
				 | 
				 | 
				
					@ -4996,7 +5119,7 @@ static char *cmd_allusers(char *cmd, char *id, __maybe_unused tv_t *now, __maybe
					 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
							u_hashrate1hr += DATA_USERSTATS(usw_item)->hashrate1hr; | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
					
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
							tmp_item = usw_item; | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
							usw_item = tmp_item->next; | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
							usw_item = next_in_ktree(usw_ctx); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
					
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
							K_WLOCK(userstats_list); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
							k_add_head(userstats_list, tmp_item); | 
				
			
			
		
	
	
		
			
				
					| 
						
							
								
							
						
						
							
								
							
						
						
					 | 
				
				 | 
				 | 
				
					@ -5043,7 +5166,7 @@ static char *cmd_sharelog(char *cmd, char *id, tv_t *now, char *by, char *code,
					 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
					
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
						LOGDEBUG("%s(): cmd '%s'", __func__, cmd); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
					
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
						if (strcasecmp(cmd, METHOD_WORKINFO) == 0) { | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
						if (strcasecmp(cmd, STR_WORKINFO) == 0) { | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
							K_ITEM *i_workinfoid, *i_poolinstance, *i_transactiontree, *i_merklehash; | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
							K_ITEM *i_prevhash, *i_coinbase1, *i_coinbase2, *i_version, *i_bits; | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
							K_ITEM *i_ntime, *i_reward; | 
				
			
			
		
	
	
		
			
				
					| 
						
							
								
							
						
						
							
								
							
						
						
					 | 
				
				 | 
				 | 
				
					@ -5115,7 +5238,7 @@ static char *cmd_sharelog(char *cmd, char *id, tv_t *now, char *by, char *code,
					 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
							LOGDEBUG("%s.ok.added %"PRId64, id, workinfoid); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
							snprintf(reply, siz, "ok.%"PRId64, workinfoid); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
							return strdup(reply); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
						} else if (strcasecmp(cmd, METHOD_SHARES) == 0) { | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
						} else if (strcasecmp(cmd, STR_SHARES) == 0) { | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
							K_ITEM *i_workinfoid, *i_username, *i_workername, *i_clientid, *i_enonce1; | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
							K_ITEM *i_nonce2, *i_nonce, *i_diff, *i_sdiff, *i_secondaryuserid; | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
							bool ok; | 
				
			
			
		
	
	
		
			
				
					| 
						
							
								
							
						
						
							
								
							
						
						
					 | 
				
				 | 
				 | 
				
					@ -5179,7 +5302,7 @@ static char *cmd_sharelog(char *cmd, char *id, tv_t *now, char *by, char *code,
					 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
							LOGDEBUG("%s.ok.added %s", id, DATA_TRANSFER(i_nonce)->data); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
							snprintf(reply, siz, "ok.added %s", DATA_TRANSFER(i_nonce)->data); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
							return strdup(reply); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
						} else if (strcasecmp(cmd, METHOD_SHAREERRORS) == 0) { | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
						} else if (strcasecmp(cmd, STR_SHAREERRORS) == 0) { | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
							K_ITEM *i_workinfoid, *i_username, *i_workername, *i_clientid, *i_errn; | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
							K_ITEM *i_error, *i_secondaryuserid; | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
							bool ok; | 
				
			
			
		
	
	
		
			
				
					| 
						
							
								
							
						
						
							
								
							
						
						
					 | 
				
				 | 
				 | 
				
					@ -5226,6 +5349,34 @@ static char *cmd_sharelog(char *cmd, char *id, tv_t *now, char *by, char *code,
					 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
							} | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
							LOGDEBUG("%s.ok.added %s", id, DATA_TRANSFER(i_username)->data); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
							snprintf(reply, siz, "ok.added %s", DATA_TRANSFER(i_username)->data); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
							return strdup(reply); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
						} else if (strcasecmp(cmd, STR_AGEWORKINFO) == 0) { | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
							K_ITEM *i_workinfoid, *i_poolinstance; | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
							bool ok; | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
					
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
							i_workinfoid = require_name("workinfoid", 1, NULL, reply, siz); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
							if (!i_workinfoid) | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
								return strdup(reply); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
					
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
							i_poolinstance = require_name("poolinstance", 1, NULL, reply, siz); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
							if (!i_poolinstance) | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
								return strdup(reply); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
					
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
							ok = workinfo_age(NULL, DATA_TRANSFER(i_workinfoid)->data, | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
										DATA_TRANSFER(i_poolinstance)->data, | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
										now, by, code, inet); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
					
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
							if (!ok) { | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
								LOGERR("%s.failed.DATA", id); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
								return strdup("failed.DATA"); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
							} | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
							LOGDEBUG("%s.ok.aged %.*s", | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
								 id, BIGINT_BUFSIZ, | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
								 DATA_TRANSFER(i_workinfoid)->data); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
							snprintf(reply, siz, "ok.%.*s", | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
									     BIGINT_BUFSIZ, | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
									     DATA_TRANSFER(i_workinfoid)->data); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
							return strdup(reply); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
						} | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
					
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
						LOGERR("%s.bad.cmd %s", cmd); | 
				
			
			
		
	
	
		
			
				
					| 
						
							
								
							
						
						
							
								
							
						
						
					 | 
				
				 | 
				 | 
				
					@ -5398,7 +5549,7 @@ static char *cmd_homepage(char *cmd, char *id, __maybe_unused tv_t *now, __maybe
					 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
						char reply[1024], tmp[1024], *buf; | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
						USERSTATS userstats; | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
						int64_t u_elapsed; | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
						K_TREE_CTX ctx[1], wctx[1]; | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
						K_TREE_CTX ctx[1], w_ctx[1]; | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
						size_t len, off; | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
						bool has_uhr; | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
					
 | 
				
			
			
		
	
	
		
			
				
					| 
						
							
								
							
						
						
							
								
							
						
						
					 | 
				
				 | 
				 | 
				
					@ -5483,7 +5634,7 @@ static char *cmd_homepage(char *cmd, char *id, __maybe_unused tv_t *now, __maybe
					 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
							       DATA_USERSTATS(us_item)->userid == userstats.userid && | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
							       tvdiff(now, &(DATA_USERSTATS(us_item)->createdate)) < USERSTATS_PER_S) { | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
								// TODO: add the latest per pool instance (this is the latest per worker)
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
								if (!find_in_ktree(userstats_workername_root, us_item, cmp_userstats_workername, wctx)) { | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
								if (!find_in_ktree(userstats_workername_root, us_item, cmp_userstats_workername, w_ctx)) { | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
									u_hashrate5m += DATA_USERSTATS(us_item)->hashrate5m; | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
									u_hashrate1hr += DATA_USERSTATS(us_item)->hashrate1hr; | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
									if (u_elapsed == -1 || | 
				
			
			
		
	
	
		
			
				
					| 
						
							
								
							
						
						
							
								
							
						
						
					 | 
				
				 | 
				 | 
				
					@ -5584,24 +5735,25 @@ static struct CMDS {
					 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
						char *(*func)(char *, char *, tv_t *, char *, char *, char *); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
						char *access; | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
					} cmds[] = { | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
						{ CMD_SHUTDOWN,	"shutdown",	NULL,		ACCESS_SYSTEM }, | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
						{ CMD_PING,	"ping",		NULL,		ACCESS_SYSTEM ACCESS_POOL ACCESS_WEB }, | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
						{ CMD_SHARELOG,	"workinfo",	cmd_sharelog,	ACCESS_POOL }, | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
						{ CMD_SHARELOG,	"shares",	cmd_sharelog,	ACCESS_POOL }, | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
						{ CMD_SHARELOG,	"shareerrors",	cmd_sharelog,	ACCESS_POOL }, | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
						{ CMD_AUTH,	"authorise",	cmd_auth,	ACCESS_POOL }, | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
						{ CMD_ADDUSER,	"adduser",	cmd_adduser,	ACCESS_WEB }, | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
						{ CMD_CHKPASS,	"chkpass",	cmd_chkpass,	ACCESS_WEB }, | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
						{ CMD_POOLSTAT,	"poolstats",	cmd_poolstats,	ACCESS_POOL }, | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
						{ CMD_USERSTAT,	"userstats",	cmd_userstats,	ACCESS_POOL }, | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
						{ CMD_BLOCK,	"block",	cmd_blocks,	ACCESS_POOL }, | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
						{ CMD_NEWID,	"newid",	cmd_newid,	ACCESS_SYSTEM }, | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
						{ CMD_PAYMENTS,	"payments",	cmd_payments,	ACCESS_WEB }, | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
						{ CMD_WORKERS,	"workers",	cmd_workers,	ACCESS_WEB }, | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
						{ CMD_ALLUSERS,	"allusers",	cmd_allusers,	ACCESS_WEB }, | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
						{ CMD_HOMEPAGE,	"homepage",	cmd_homepage,	ACCESS_WEB }, | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
						{ CMD_DSP,	"dsp",		cmd_dsp,	ACCESS_SYSTEM }, | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
						{ CMD_END,	NULL,		NULL,		NULL } | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
						{ CMD_SHUTDOWN,	"shutdown",		NULL,		ACCESS_SYSTEM }, | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
						{ CMD_PING,	"ping",			NULL,		ACCESS_SYSTEM ACCESS_POOL ACCESS_WEB }, | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
						{ CMD_SHARELOG,	STR_WORKINFO,		cmd_sharelog,	ACCESS_POOL }, | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
						{ CMD_SHARELOG,	STR_SHARES,		cmd_sharelog,	ACCESS_POOL }, | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
						{ CMD_SHARELOG,	STR_SHAREERRORS,	cmd_sharelog,	ACCESS_POOL }, | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
						{ CMD_SHARELOG,	STR_AGEWORKINFO,	cmd_sharelog,	ACCESS_POOL }, | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
						{ CMD_AUTH,	"authorise",		cmd_auth,	ACCESS_POOL }, | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
						{ CMD_ADDUSER,	"adduser",		cmd_adduser,	ACCESS_WEB }, | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
						{ CMD_CHKPASS,	"chkpass",		cmd_chkpass,	ACCESS_WEB }, | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
						{ CMD_POOLSTAT,	"poolstats",		cmd_poolstats,	ACCESS_POOL }, | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
						{ CMD_USERSTAT,	"userstats",		cmd_userstats,	ACCESS_POOL }, | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
						{ CMD_BLOCK,	"block",		cmd_blocks,	ACCESS_POOL }, | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
						{ CMD_NEWID,	"newid",		cmd_newid,	ACCESS_SYSTEM }, | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
						{ CMD_PAYMENTS,	"payments",		cmd_payments,	ACCESS_WEB }, | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
						{ CMD_WORKERS,	"workers",		cmd_workers,	ACCESS_WEB }, | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
						{ CMD_ALLUSERS,	"allusers",		cmd_allusers,	ACCESS_WEB }, | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
						{ CMD_HOMEPAGE,	"homepage",		cmd_homepage,	ACCESS_WEB }, | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
						{ CMD_DSP,	"dsp",			cmd_dsp,	ACCESS_SYSTEM }, | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
						{ CMD_END,	NULL,			NULL,		NULL } | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
					}; | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
					
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				 | 
				
					static enum cmd_values breakdown(char *buf, int *which_cmds, char *cmd, char *id) | 
				
			
			
		
	
	
		
			
				
					| 
						
							
								
							
						
						
						
					 | 
				
				 | 
				 | 
				
					
 
					 |