|  |  |  | @ -5795,7 +5795,7 @@ static char *cmd_marks(PGconn *conn, char *cmd, char *id, | 
			
		
	
		
			
				
					|  |  |  |  | 				TXT_TO_INT("height", transfer_data(i_height), | 
			
		
	
		
			
				
					|  |  |  |  | 					   height); | 
			
		
	
		
			
				
					|  |  |  |  | 				K_RLOCK(blocks_free); | 
			
		
	
		
			
				
					|  |  |  |  | 				b_item = find_prev_blocks(height+1); | 
			
		
	
		
			
				
					|  |  |  |  | 				b_item = find_prev_blocks(height+1, NULL); | 
			
		
	
		
			
				
					|  |  |  |  | 				K_RUNLOCK(blocks_free); | 
			
		
	
		
			
				
					|  |  |  |  | 				if (b_item) { | 
			
		
	
		
			
				
					|  |  |  |  | 					DATA_BLOCKS(blocks, b_item); | 
			
		
	
	
		
			
				
					|  |  |  | @ -6571,6 +6571,488 @@ static char *cmd_btcset(__maybe_unused PGconn *conn, char *cmd, char *id, | 
			
		
	
		
			
				
					|  |  |  |  | 	return strdup(buf); | 
			
		
	
		
			
				
					|  |  |  |  | } | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | /* Query CKDB for certain information
 | 
			
		
	
		
			
				
					|  |  |  |  |  * See each string compare below of 'request' for the list of queries | 
			
		
	
		
			
				
					|  |  |  |  |  * For non-error conditions, rows=0 means there were no matching results | 
			
		
	
		
			
				
					|  |  |  |  |  *  for the request, and rows=n is placed last in the reply */ | 
			
		
	
		
			
				
					|  |  |  |  | static char *cmd_query(__maybe_unused PGconn *conn, char *cmd, char *id, | 
			
		
	
		
			
				
					|  |  |  |  | 			__maybe_unused tv_t *now, __maybe_unused char *by, | 
			
		
	
		
			
				
					|  |  |  |  | 			__maybe_unused char *code, __maybe_unused char *inet, | 
			
		
	
		
			
				
					|  |  |  |  | 			__maybe_unused tv_t *cd, K_TREE *trf_root) | 
			
		
	
		
			
				
					|  |  |  |  | { | 
			
		
	
		
			
				
					|  |  |  |  | 	K_TREE_CTX ctx[1]; | 
			
		
	
		
			
				
					|  |  |  |  | 	char cd_buf[DATE_BUFSIZ]; | 
			
		
	
		
			
				
					|  |  |  |  | 	char reply[1024] = ""; | 
			
		
	
		
			
				
					|  |  |  |  | 	size_t siz = sizeof(reply); | 
			
		
	
		
			
				
					|  |  |  |  | 	char tmp[1024] = ""; | 
			
		
	
		
			
				
					|  |  |  |  | 	char msg[1024] = ""; | 
			
		
	
		
			
				
					|  |  |  |  | 	char *buf = NULL; | 
			
		
	
		
			
				
					|  |  |  |  | 	size_t len, off; | 
			
		
	
		
			
				
					|  |  |  |  | 	K_ITEM *i_request; | 
			
		
	
		
			
				
					|  |  |  |  | 	char *request; | 
			
		
	
		
			
				
					|  |  |  |  | 	bool ok = false; | 
			
		
	
		
			
				
					|  |  |  |  | 	int rows = 0; | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | 	LOGDEBUG("%s(): cmd '%s'", __func__, cmd); | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | 	i_request = require_name(trf_root, "request", 1, NULL, reply, siz); | 
			
		
	
		
			
				
					|  |  |  |  | 	if (!i_request) | 
			
		
	
		
			
				
					|  |  |  |  | 		return strdup(reply); | 
			
		
	
		
			
				
					|  |  |  |  | 	request = transfer_data(i_request); | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | 	APPEND_REALLOC_INIT(buf, off, len); | 
			
		
	
		
			
				
					|  |  |  |  | 	APPEND_REALLOC(buf, off, len, "ok."); | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | 	if (strcasecmp(request, "block") == 0) { | 
			
		
	
		
			
				
					|  |  |  |  | 		/* return DB information for the blocks with height=value
 | 
			
		
	
		
			
				
					|  |  |  |  | 		 * if expired= is present, it will also return expired records */ | 
			
		
	
		
			
				
					|  |  |  |  | 		K_ITEM *i_height, *i_expired, *b_item; | 
			
		
	
		
			
				
					|  |  |  |  | 		bool expired = false; | 
			
		
	
		
			
				
					|  |  |  |  | 		BLOCKS *blocks; | 
			
		
	
		
			
				
					|  |  |  |  | 		int32_t height; | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | 		i_height = require_name(trf_root, "height", | 
			
		
	
		
			
				
					|  |  |  |  | 					1, (char *)intpatt, | 
			
		
	
		
			
				
					|  |  |  |  | 					reply, siz); | 
			
		
	
		
			
				
					|  |  |  |  | 		if (!i_height) | 
			
		
	
		
			
				
					|  |  |  |  | 			return strdup(reply); | 
			
		
	
		
			
				
					|  |  |  |  | 		TXT_TO_INT("height", transfer_data(i_height), height); | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | 		i_expired = optional_name(trf_root, "expired", | 
			
		
	
		
			
				
					|  |  |  |  | 					  0, NULL, reply, siz); | 
			
		
	
		
			
				
					|  |  |  |  | 		if (i_expired) | 
			
		
	
		
			
				
					|  |  |  |  | 			expired = true; | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | 		int_to_buf(height, reply, sizeof(reply)); | 
			
		
	
		
			
				
					|  |  |  |  | 		snprintf(msg, sizeof(msg), "height=%s", reply); | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | 		K_RLOCK(blocks_free); | 
			
		
	
		
			
				
					|  |  |  |  | 		b_item = find_prev_blocks(height, ctx); | 
			
		
	
		
			
				
					|  |  |  |  | 		DATA_BLOCKS_NULL(blocks, b_item); | 
			
		
	
		
			
				
					|  |  |  |  | 		while (b_item && blocks->height <= height) { | 
			
		
	
		
			
				
					|  |  |  |  | 			if ((expired || CURRENT(&(blocks->expirydate))) && | 
			
		
	
		
			
				
					|  |  |  |  | 			    blocks->height == height) { | 
			
		
	
		
			
				
					|  |  |  |  | 				int_to_buf(blocks->height, reply, sizeof(reply)); | 
			
		
	
		
			
				
					|  |  |  |  | 				snprintf(tmp, sizeof(tmp), | 
			
		
	
		
			
				
					|  |  |  |  | 					 "height:%d=%s%c", | 
			
		
	
		
			
				
					|  |  |  |  | 					 rows, reply, FLDSEP); | 
			
		
	
		
			
				
					|  |  |  |  | 				APPEND_REALLOC(buf, off, len, tmp); | 
			
		
	
		
			
				
					|  |  |  |  | 				snprintf(tmp, sizeof(tmp), | 
			
		
	
		
			
				
					|  |  |  |  | 					 "blockhash:%d=%s%c", | 
			
		
	
		
			
				
					|  |  |  |  | 					 rows, blocks->blockhash, FLDSEP); | 
			
		
	
		
			
				
					|  |  |  |  | 				APPEND_REALLOC(buf, off, len, tmp); | 
			
		
	
		
			
				
					|  |  |  |  | 				snprintf(tmp, sizeof(tmp), | 
			
		
	
		
			
				
					|  |  |  |  | 					 "confirmed:%d=%s%c", | 
			
		
	
		
			
				
					|  |  |  |  | 					 rows, blocks->confirmed, FLDSEP); | 
			
		
	
		
			
				
					|  |  |  |  | 				APPEND_REALLOC(buf, off, len, tmp); | 
			
		
	
		
			
				
					|  |  |  |  | 				tv_to_buf(&(blocks->expirydate), cd_buf, | 
			
		
	
		
			
				
					|  |  |  |  | 					  sizeof(cd_buf)); | 
			
		
	
		
			
				
					|  |  |  |  | 				snprintf(tmp, sizeof(tmp), | 
			
		
	
		
			
				
					|  |  |  |  | 					 EDDB"_str:%d=%s%c", | 
			
		
	
		
			
				
					|  |  |  |  | 					 rows, cd_buf, FLDSEP); | 
			
		
	
		
			
				
					|  |  |  |  | 				APPEND_REALLOC(buf, off, len, tmp); | 
			
		
	
		
			
				
					|  |  |  |  | 				tv_to_buf(&(blocks->createdate), cd_buf, | 
			
		
	
		
			
				
					|  |  |  |  | 					  sizeof(cd_buf)); | 
			
		
	
		
			
				
					|  |  |  |  | 				snprintf(tmp, sizeof(tmp), | 
			
		
	
		
			
				
					|  |  |  |  | 					 CDDB"_str:%d=%s%c", | 
			
		
	
		
			
				
					|  |  |  |  | 					 rows, cd_buf, FLDSEP); | 
			
		
	
		
			
				
					|  |  |  |  | 				APPEND_REALLOC(buf, off, len, tmp); | 
			
		
	
		
			
				
					|  |  |  |  | 				tv_to_buf(&(blocks->blockcreatedate), cd_buf, | 
			
		
	
		
			
				
					|  |  |  |  | 					  sizeof(cd_buf)); | 
			
		
	
		
			
				
					|  |  |  |  | 				snprintf(tmp, sizeof(tmp), | 
			
		
	
		
			
				
					|  |  |  |  | 					 "block"CDDB"_str:%d=%s%c", | 
			
		
	
		
			
				
					|  |  |  |  | 					 rows, cd_buf, FLDSEP); | 
			
		
	
		
			
				
					|  |  |  |  | 				APPEND_REALLOC(buf, off, len, tmp); | 
			
		
	
		
			
				
					|  |  |  |  | 				bigint_to_buf(blocks->workinfoid, reply, sizeof(reply)); | 
			
		
	
		
			
				
					|  |  |  |  | 				snprintf(tmp, sizeof(tmp), | 
			
		
	
		
			
				
					|  |  |  |  | 					 "workinfoid:%d=%s%c", | 
			
		
	
		
			
				
					|  |  |  |  | 					 rows, reply, FLDSEP); | 
			
		
	
		
			
				
					|  |  |  |  | 				APPEND_REALLOC(buf, off, len, tmp); | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | 				rows++; | 
			
		
	
		
			
				
					|  |  |  |  | 			} | 
			
		
	
		
			
				
					|  |  |  |  | 			b_item = next_in_ktree(ctx); | 
			
		
	
		
			
				
					|  |  |  |  | 			DATA_BLOCKS_NULL(blocks, b_item); | 
			
		
	
		
			
				
					|  |  |  |  | 		} | 
			
		
	
		
			
				
					|  |  |  |  | 		K_RUNLOCK(blocks_free); | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | 		snprintf(tmp, sizeof(tmp), "flds=%s%c", | 
			
		
	
		
			
				
					|  |  |  |  | 			 "height,blockhash,confirmed,"EDDB"_str," | 
			
		
	
		
			
				
					|  |  |  |  | 			 CDDB"_str,block"CDDB"_str,workinfoid", FLDSEP); | 
			
		
	
		
			
				
					|  |  |  |  | 		APPEND_REALLOC(buf, off, len, tmp); | 
			
		
	
		
			
				
					|  |  |  |  | 		snprintf(tmp, sizeof(tmp), "arn=%s%carp=%s%c", | 
			
		
	
		
			
				
					|  |  |  |  | 			 "Blocks", FLDSEP, "", FLDSEP); | 
			
		
	
		
			
				
					|  |  |  |  | 		APPEND_REALLOC(buf, off, len, tmp); | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | 		ok = true; | 
			
		
	
		
			
				
					|  |  |  |  | 	} else if (strcasecmp(request, "workinfo") == 0) { | 
			
		
	
		
			
				
					|  |  |  |  | 		/* return DB information for the workinfo with wid=value
 | 
			
		
	
		
			
				
					|  |  |  |  | 		 * if expired= is present, it will also return expired records | 
			
		
	
		
			
				
					|  |  |  |  | 		 *  though ckdb doesn't expire workinfo records - only external | 
			
		
	
		
			
				
					|  |  |  |  | 		 *  pgsql scripts would do that to the DB, then ckdb would | 
			
		
	
		
			
				
					|  |  |  |  | 		 *  load them the next time it (re)starts */ | 
			
		
	
		
			
				
					|  |  |  |  | 		K_ITEM *i_wid, *i_expired, *wi_item, *wm_item; | 
			
		
	
		
			
				
					|  |  |  |  | 		char ndiffbin[TXT_SML+1]; | 
			
		
	
		
			
				
					|  |  |  |  | 		bool expired = false; | 
			
		
	
		
			
				
					|  |  |  |  | 		WORKINFO *workinfo; | 
			
		
	
		
			
				
					|  |  |  |  | 		WORKMARKERS *wm; | 
			
		
	
		
			
				
					|  |  |  |  | 		int64_t wid; | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | 		i_wid = require_name(trf_root, "wid", | 
			
		
	
		
			
				
					|  |  |  |  | 					1, (char *)intpatt, | 
			
		
	
		
			
				
					|  |  |  |  | 					reply, siz); | 
			
		
	
		
			
				
					|  |  |  |  | 		if (!i_wid) | 
			
		
	
		
			
				
					|  |  |  |  | 			return strdup(reply); | 
			
		
	
		
			
				
					|  |  |  |  | 		TXT_TO_BIGINT("wid", transfer_data(i_wid), wid); | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | 		i_expired = optional_name(trf_root, "expired", | 
			
		
	
		
			
				
					|  |  |  |  | 					  0, NULL, reply, siz); | 
			
		
	
		
			
				
					|  |  |  |  | 		if (i_expired) | 
			
		
	
		
			
				
					|  |  |  |  | 			expired = true; | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | 		bigint_to_buf(wid, reply, sizeof(reply)); | 
			
		
	
		
			
				
					|  |  |  |  | 		snprintf(msg, sizeof(msg), "wid=%s", reply); | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | 		/* We look for the 'next' (or last) workinfo then go backwards
 | 
			
		
	
		
			
				
					|  |  |  |  | 		 *  to ensure we find all expired records in case they | 
			
		
	
		
			
				
					|  |  |  |  | 		 *  were requested */ | 
			
		
	
		
			
				
					|  |  |  |  | 		K_RLOCK(workinfo_free); | 
			
		
	
		
			
				
					|  |  |  |  | 		wi_item = next_workinfo(wid, ctx); | 
			
		
	
		
			
				
					|  |  |  |  | 		if (!wi_item) | 
			
		
	
		
			
				
					|  |  |  |  | 			wi_item = last_in_ktree(workinfo_root, ctx); | 
			
		
	
		
			
				
					|  |  |  |  | 		DATA_WORKINFO_NULL(workinfo, wi_item); | 
			
		
	
		
			
				
					|  |  |  |  | 		while (wi_item && workinfo->workinfoid >= wid) { | 
			
		
	
		
			
				
					|  |  |  |  | 			if ((expired || CURRENT(&(workinfo->expirydate))) && | 
			
		
	
		
			
				
					|  |  |  |  | 			    workinfo->workinfoid == wid) { | 
			
		
	
		
			
				
					|  |  |  |  | 				bigint_to_buf(workinfo->workinfoid, | 
			
		
	
		
			
				
					|  |  |  |  | 					      reply, sizeof(reply)); | 
			
		
	
		
			
				
					|  |  |  |  | 				snprintf(tmp, sizeof(tmp), | 
			
		
	
		
			
				
					|  |  |  |  | 					 "workinfoid:%d=%s%c", | 
			
		
	
		
			
				
					|  |  |  |  | 					 rows, reply, FLDSEP); | 
			
		
	
		
			
				
					|  |  |  |  | 				APPEND_REALLOC(buf, off, len, tmp); | 
			
		
	
		
			
				
					|  |  |  |  | 				int_to_buf(coinbase1height(workinfo->coinbase1), | 
			
		
	
		
			
				
					|  |  |  |  | 					   reply, sizeof(reply)); | 
			
		
	
		
			
				
					|  |  |  |  | 				snprintf(tmp, sizeof(tmp), | 
			
		
	
		
			
				
					|  |  |  |  | 					 "height:%d=%s%c", | 
			
		
	
		
			
				
					|  |  |  |  | 					 rows, reply, FLDSEP); | 
			
		
	
		
			
				
					|  |  |  |  | 				APPEND_REALLOC(buf, off, len, tmp); | 
			
		
	
		
			
				
					|  |  |  |  | 				snprintf(tmp, sizeof(tmp), | 
			
		
	
		
			
				
					|  |  |  |  | 					 "prevhash:%d=%s%c", | 
			
		
	
		
			
				
					|  |  |  |  | 					 rows, workinfo->prevhash, FLDSEP); | 
			
		
	
		
			
				
					|  |  |  |  | 				APPEND_REALLOC(buf, off, len, tmp); | 
			
		
	
		
			
				
					|  |  |  |  | 				tv_to_buf(&(workinfo->expirydate), cd_buf, | 
			
		
	
		
			
				
					|  |  |  |  | 					  sizeof(cd_buf)); | 
			
		
	
		
			
				
					|  |  |  |  | 				snprintf(tmp, sizeof(tmp), | 
			
		
	
		
			
				
					|  |  |  |  | 					 EDDB"_str:%d=%s%c", | 
			
		
	
		
			
				
					|  |  |  |  | 					 rows, cd_buf, FLDSEP); | 
			
		
	
		
			
				
					|  |  |  |  | 				APPEND_REALLOC(buf, off, len, tmp); | 
			
		
	
		
			
				
					|  |  |  |  | 				tv_to_buf(&(workinfo->createdate), cd_buf, | 
			
		
	
		
			
				
					|  |  |  |  | 					  sizeof(cd_buf)); | 
			
		
	
		
			
				
					|  |  |  |  | 				snprintf(tmp, sizeof(tmp), | 
			
		
	
		
			
				
					|  |  |  |  | 					 CDDB"_str:%d=%s%c", | 
			
		
	
		
			
				
					|  |  |  |  | 					 rows, cd_buf, FLDSEP); | 
			
		
	
		
			
				
					|  |  |  |  | 				APPEND_REALLOC(buf, off, len, tmp); | 
			
		
	
		
			
				
					|  |  |  |  | 				hex2bin(ndiffbin, workinfo->bits, 4); | 
			
		
	
		
			
				
					|  |  |  |  | 				snprintf(tmp, sizeof(tmp), | 
			
		
	
		
			
				
					|  |  |  |  | 					 "ndiff:%d=%.1f%c", rows, | 
			
		
	
		
			
				
					|  |  |  |  | 					 diff_from_nbits(ndiffbin), | 
			
		
	
		
			
				
					|  |  |  |  | 					 FLDSEP); | 
			
		
	
		
			
				
					|  |  |  |  | 				APPEND_REALLOC(buf, off, len, tmp); | 
			
		
	
		
			
				
					|  |  |  |  | 				snprintf(tmp, sizeof(tmp), | 
			
		
	
		
			
				
					|  |  |  |  | 					 "ppsvalue:%d=%.15f%c", rows, | 
			
		
	
		
			
				
					|  |  |  |  | 					 workinfo_pps(wi_item, | 
			
		
	
		
			
				
					|  |  |  |  | 						      workinfo->workinfoid, | 
			
		
	
		
			
				
					|  |  |  |  | 						      true), | 
			
		
	
		
			
				
					|  |  |  |  | 					 FLDSEP); | 
			
		
	
		
			
				
					|  |  |  |  | 				APPEND_REALLOC(buf, off, len, tmp); | 
			
		
	
		
			
				
					|  |  |  |  | 				K_RLOCK(workmarkers_free); | 
			
		
	
		
			
				
					|  |  |  |  | 				wm_item = find_workmarkers(wid, false, | 
			
		
	
		
			
				
					|  |  |  |  | 							   MARKER_PROCESSED, | 
			
		
	
		
			
				
					|  |  |  |  | 							   NULL); | 
			
		
	
		
			
				
					|  |  |  |  | 				K_RUNLOCK(workmarkers_free); | 
			
		
	
		
			
				
					|  |  |  |  | 				if (!wm_item) { | 
			
		
	
		
			
				
					|  |  |  |  | 					snprintf(tmp, sizeof(tmp), | 
			
		
	
		
			
				
					|  |  |  |  | 						 "markerid:%d=%c", rows, FLDSEP); | 
			
		
	
		
			
				
					|  |  |  |  | 					APPEND_REALLOC(buf, off, len, tmp); | 
			
		
	
		
			
				
					|  |  |  |  | 					snprintf(tmp, sizeof(tmp), | 
			
		
	
		
			
				
					|  |  |  |  | 						 "shift:%d=%c", rows, FLDSEP); | 
			
		
	
		
			
				
					|  |  |  |  | 					APPEND_REALLOC(buf, off, len, tmp); | 
			
		
	
		
			
				
					|  |  |  |  | 					snprintf(tmp, sizeof(tmp), | 
			
		
	
		
			
				
					|  |  |  |  | 						 "shiftend:%d=%c", rows, FLDSEP); | 
			
		
	
		
			
				
					|  |  |  |  | 					APPEND_REALLOC(buf, off, len, tmp); | 
			
		
	
		
			
				
					|  |  |  |  | 					snprintf(tmp, sizeof(tmp), | 
			
		
	
		
			
				
					|  |  |  |  | 						 "shiftstart:%d=%c", rows, FLDSEP); | 
			
		
	
		
			
				
					|  |  |  |  | 					APPEND_REALLOC(buf, off, len, tmp); | 
			
		
	
		
			
				
					|  |  |  |  | 				} else { | 
			
		
	
		
			
				
					|  |  |  |  | 					DATA_WORKMARKERS(wm, wm_item); | 
			
		
	
		
			
				
					|  |  |  |  | 					bigint_to_buf(wm->markerid, | 
			
		
	
		
			
				
					|  |  |  |  | 						      reply, sizeof(reply)); | 
			
		
	
		
			
				
					|  |  |  |  | 					snprintf(tmp, sizeof(tmp), | 
			
		
	
		
			
				
					|  |  |  |  | 						 "markerid:%d=%s%c", | 
			
		
	
		
			
				
					|  |  |  |  | 						 rows, reply, FLDSEP); | 
			
		
	
		
			
				
					|  |  |  |  | 					APPEND_REALLOC(buf, off, len, tmp); | 
			
		
	
		
			
				
					|  |  |  |  | 					snprintf(tmp, sizeof(tmp), | 
			
		
	
		
			
				
					|  |  |  |  | 						 "shift:%d=%s%c", | 
			
		
	
		
			
				
					|  |  |  |  | 						 rows, wm->description, FLDSEP); | 
			
		
	
		
			
				
					|  |  |  |  | 					APPEND_REALLOC(buf, off, len, tmp); | 
			
		
	
		
			
				
					|  |  |  |  | 					bigint_to_buf(wm->workinfoidend, | 
			
		
	
		
			
				
					|  |  |  |  | 						      reply, sizeof(reply)); | 
			
		
	
		
			
				
					|  |  |  |  | 					snprintf(tmp, sizeof(tmp), | 
			
		
	
		
			
				
					|  |  |  |  | 						 "shiftend:%d=%s%c", | 
			
		
	
		
			
				
					|  |  |  |  | 						 rows, reply, FLDSEP); | 
			
		
	
		
			
				
					|  |  |  |  | 					APPEND_REALLOC(buf, off, len, tmp); | 
			
		
	
		
			
				
					|  |  |  |  | 					bigint_to_buf(wm->workinfoidstart, | 
			
		
	
		
			
				
					|  |  |  |  | 						      reply, sizeof(reply)); | 
			
		
	
		
			
				
					|  |  |  |  | 					snprintf(tmp, sizeof(tmp), | 
			
		
	
		
			
				
					|  |  |  |  | 						 "shiftstart:%d=%s%c", | 
			
		
	
		
			
				
					|  |  |  |  | 						 rows, reply, FLDSEP); | 
			
		
	
		
			
				
					|  |  |  |  | 					APPEND_REALLOC(buf, off, len, tmp); | 
			
		
	
		
			
				
					|  |  |  |  | 				} | 
			
		
	
		
			
				
					|  |  |  |  | 				rows++; | 
			
		
	
		
			
				
					|  |  |  |  | 			} | 
			
		
	
		
			
				
					|  |  |  |  | 			wi_item = prev_in_ktree(ctx); | 
			
		
	
		
			
				
					|  |  |  |  | 			DATA_WORKINFO_NULL(workinfo, wi_item); | 
			
		
	
		
			
				
					|  |  |  |  | 		} | 
			
		
	
		
			
				
					|  |  |  |  | 		K_RUNLOCK(workinfo_free); | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | 		snprintf(tmp, sizeof(tmp), "flds=%s%c", | 
			
		
	
		
			
				
					|  |  |  |  | 			 "workinfoid,height,prevhash,"EDDB"_str,"CDDB"_str," | 
			
		
	
		
			
				
					|  |  |  |  | 			 "ndiff,ppsvalue,markerid,shift,shiftend,shiftstart", | 
			
		
	
		
			
				
					|  |  |  |  | 			 FLDSEP); | 
			
		
	
		
			
				
					|  |  |  |  | 		APPEND_REALLOC(buf, off, len, tmp); | 
			
		
	
		
			
				
					|  |  |  |  | 		snprintf(tmp, sizeof(tmp), "arn=%s%carp=%s%c", | 
			
		
	
		
			
				
					|  |  |  |  | 			 "Workinfo", FLDSEP, "", FLDSEP); | 
			
		
	
		
			
				
					|  |  |  |  | 		APPEND_REALLOC(buf, off, len, tmp); | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | 		ok = true; | 
			
		
	
		
			
				
					|  |  |  |  | 	} else if (strcasecmp(request, "range") == 0) { | 
			
		
	
		
			
				
					|  |  |  |  | 		/* Return the workinfoid range that has block height=height
 | 
			
		
	
		
			
				
					|  |  |  |  | 		 * WARNING! This will traverse workinfo from the end back to | 
			
		
	
		
			
				
					|  |  |  |  | 		 *  the given height, and thus since workinfo is the 2nd | 
			
		
	
		
			
				
					|  |  |  |  | 		 *  largest tree, it may access swapped data if you request | 
			
		
	
		
			
				
					|  |  |  |  | 		 *  older data */ | 
			
		
	
		
			
				
					|  |  |  |  | 		K_ITEM *i_height, *wi_item; | 
			
		
	
		
			
				
					|  |  |  |  | 		WORKINFO *workinfo; | 
			
		
	
		
			
				
					|  |  |  |  | 		int32_t height, this_height; | 
			
		
	
		
			
				
					|  |  |  |  | 		int64_t idend, idstt; | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | 		i_height = require_name(trf_root, "height", | 
			
		
	
		
			
				
					|  |  |  |  | 					1, (char *)intpatt, | 
			
		
	
		
			
				
					|  |  |  |  | 					reply, siz); | 
			
		
	
		
			
				
					|  |  |  |  | 		if (!i_height) | 
			
		
	
		
			
				
					|  |  |  |  | 			return strdup(reply); | 
			
		
	
		
			
				
					|  |  |  |  | 		TXT_TO_INT("height", transfer_data(i_height), height); | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | 		int_to_buf(height, reply, sizeof(reply)); | 
			
		
	
		
			
				
					|  |  |  |  | 		snprintf(msg, sizeof(msg), "height=%s", reply); | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | 		idend = idstt = 0L; | 
			
		
	
		
			
				
					|  |  |  |  | 		/* Start from the last workinfo and continue until we get
 | 
			
		
	
		
			
				
					|  |  |  |  | 		 * below block 'height' */ | 
			
		
	
		
			
				
					|  |  |  |  | 		K_RLOCK(workinfo_free); | 
			
		
	
		
			
				
					|  |  |  |  | 		wi_item = last_in_ktree(workinfo_root, ctx); | 
			
		
	
		
			
				
					|  |  |  |  | 		DATA_WORKINFO_NULL(workinfo, wi_item); | 
			
		
	
		
			
				
					|  |  |  |  | 		while (wi_item) { | 
			
		
	
		
			
				
					|  |  |  |  | 			this_height = coinbase1height(workinfo->coinbase1); | 
			
		
	
		
			
				
					|  |  |  |  | 			if (this_height < height) | 
			
		
	
		
			
				
					|  |  |  |  | 				break; | 
			
		
	
		
			
				
					|  |  |  |  | 			if (CURRENT(&(workinfo->expirydate)) && | 
			
		
	
		
			
				
					|  |  |  |  | 			    this_height == height) { | 
			
		
	
		
			
				
					|  |  |  |  | 				if (idend == 0L) | 
			
		
	
		
			
				
					|  |  |  |  | 					idend = workinfo->workinfoid; | 
			
		
	
		
			
				
					|  |  |  |  | 				idstt = workinfo->workinfoid; | 
			
		
	
		
			
				
					|  |  |  |  | 			} | 
			
		
	
		
			
				
					|  |  |  |  | 			wi_item = prev_in_ktree(ctx); | 
			
		
	
		
			
				
					|  |  |  |  | 			DATA_WORKINFO_NULL(workinfo, wi_item); | 
			
		
	
		
			
				
					|  |  |  |  | 		} | 
			
		
	
		
			
				
					|  |  |  |  | 		K_RUNLOCK(workinfo_free); | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | 		int_to_buf(height, reply, sizeof(reply)); | 
			
		
	
		
			
				
					|  |  |  |  | 		snprintf(tmp, sizeof(tmp), "height:%d=%s%c", | 
			
		
	
		
			
				
					|  |  |  |  | 					   rows, reply, FLDSEP); | 
			
		
	
		
			
				
					|  |  |  |  | 		APPEND_REALLOC(buf, off, len, tmp); | 
			
		
	
		
			
				
					|  |  |  |  | 		bigint_to_buf(idend, reply, sizeof(reply)); | 
			
		
	
		
			
				
					|  |  |  |  | 		snprintf(tmp, sizeof(tmp), "workinfoidend:%d=%s%c", | 
			
		
	
		
			
				
					|  |  |  |  | 					   rows, reply, FLDSEP); | 
			
		
	
		
			
				
					|  |  |  |  | 		APPEND_REALLOC(buf, off, len, tmp); | 
			
		
	
		
			
				
					|  |  |  |  | 		bigint_to_buf(idstt, reply, sizeof(reply)); | 
			
		
	
		
			
				
					|  |  |  |  | 		snprintf(tmp, sizeof(tmp), "workinfoidstart:%d=%s%c", | 
			
		
	
		
			
				
					|  |  |  |  | 					   rows, reply, FLDSEP); | 
			
		
	
		
			
				
					|  |  |  |  | 		APPEND_REALLOC(buf, off, len, tmp); | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | 		rows++; | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | 		snprintf(tmp, sizeof(tmp), "flds=%s%c", | 
			
		
	
		
			
				
					|  |  |  |  | 			 "height,workinfoidend,workinfoidstart", FLDSEP); | 
			
		
	
		
			
				
					|  |  |  |  | 		APPEND_REALLOC(buf, off, len, tmp); | 
			
		
	
		
			
				
					|  |  |  |  | 		snprintf(tmp, sizeof(tmp), "arn=%s%carp=%s%c", | 
			
		
	
		
			
				
					|  |  |  |  | 			 "WorkinfoRange", FLDSEP, "", FLDSEP); | 
			
		
	
		
			
				
					|  |  |  |  | 		APPEND_REALLOC(buf, off, len, tmp); | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | 		ok = true; | 
			
		
	
		
			
				
					|  |  |  |  | 	} else if (strcasecmp(request, "diff") == 0) { | 
			
		
	
		
			
				
					|  |  |  |  | 		/* return the details of the next diff change after
 | 
			
		
	
		
			
				
					|  |  |  |  | 		 *  block height=height | 
			
		
	
		
			
				
					|  |  |  |  | 		 * WARNING! This will traverse workinfo from the end back to | 
			
		
	
		
			
				
					|  |  |  |  | 		 *  the given height, and thus since workinfo is the 2nd | 
			
		
	
		
			
				
					|  |  |  |  | 		 *  largest tree, it may access swapped data if you request | 
			
		
	
		
			
				
					|  |  |  |  | 		 *  older data */ | 
			
		
	
		
			
				
					|  |  |  |  | 		K_ITEM *i_height, *wi_item; | 
			
		
	
		
			
				
					|  |  |  |  | 		WORKINFO *workinfo = NULL; | 
			
		
	
		
			
				
					|  |  |  |  | 		int32_t height, this_height; | 
			
		
	
		
			
				
					|  |  |  |  | 		char ndiffbin[TXT_SML+1]; | 
			
		
	
		
			
				
					|  |  |  |  | 		char bits[TXT_SML+1]; | 
			
		
	
		
			
				
					|  |  |  |  | 		bool got = false; | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | 		i_height = require_name(trf_root, "height", | 
			
		
	
		
			
				
					|  |  |  |  | 					1, (char *)intpatt, | 
			
		
	
		
			
				
					|  |  |  |  | 					reply, siz); | 
			
		
	
		
			
				
					|  |  |  |  | 		if (!i_height) | 
			
		
	
		
			
				
					|  |  |  |  | 			return strdup(reply); | 
			
		
	
		
			
				
					|  |  |  |  | 		TXT_TO_INT("height", transfer_data(i_height), height); | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | 		int_to_buf(height, reply, sizeof(reply)); | 
			
		
	
		
			
				
					|  |  |  |  | 		snprintf(msg, sizeof(msg), "height=%s", reply); | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | 		snprintf(tmp, sizeof(tmp), "height0:%d=%s%c", | 
			
		
	
		
			
				
					|  |  |  |  | 					   rows, reply, FLDSEP); | 
			
		
	
		
			
				
					|  |  |  |  | 		APPEND_REALLOC(buf, off, len, tmp); | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | 		/* Start from the last workinfo and continue until we get
 | 
			
		
	
		
			
				
					|  |  |  |  | 		 * below block 'height' */ | 
			
		
	
		
			
				
					|  |  |  |  | 		K_RLOCK(workinfo_free); | 
			
		
	
		
			
				
					|  |  |  |  | 		wi_item = last_in_ktree(workinfo_root, ctx); | 
			
		
	
		
			
				
					|  |  |  |  | 		DATA_WORKINFO_NULL(workinfo, wi_item); | 
			
		
	
		
			
				
					|  |  |  |  | 		while (wi_item) { | 
			
		
	
		
			
				
					|  |  |  |  | 			if (CURRENT(&(workinfo->expirydate))) { | 
			
		
	
		
			
				
					|  |  |  |  | 				this_height = coinbase1height(workinfo->coinbase1); | 
			
		
	
		
			
				
					|  |  |  |  | 				if (this_height < height) | 
			
		
	
		
			
				
					|  |  |  |  | 					break; | 
			
		
	
		
			
				
					|  |  |  |  | 			} | 
			
		
	
		
			
				
					|  |  |  |  | 			wi_item = prev_in_ktree(ctx); | 
			
		
	
		
			
				
					|  |  |  |  | 			DATA_WORKINFO_NULL(workinfo, wi_item); | 
			
		
	
		
			
				
					|  |  |  |  | 		} | 
			
		
	
		
			
				
					|  |  |  |  | 		// If we fell off the front use the first one
 | 
			
		
	
		
			
				
					|  |  |  |  | 		if (!wi_item) | 
			
		
	
		
			
				
					|  |  |  |  | 			wi_item = first_in_ktree(workinfo_root, ctx); | 
			
		
	
		
			
				
					|  |  |  |  | 		DATA_WORKINFO_NULL(workinfo, wi_item); | 
			
		
	
		
			
				
					|  |  |  |  | 		while (wi_item) { | 
			
		
	
		
			
				
					|  |  |  |  | 			if (CURRENT(&(workinfo->expirydate))) { | 
			
		
	
		
			
				
					|  |  |  |  | 				this_height = coinbase1height(workinfo->coinbase1); | 
			
		
	
		
			
				
					|  |  |  |  | 				if (this_height >= height) | 
			
		
	
		
			
				
					|  |  |  |  | 					break; | 
			
		
	
		
			
				
					|  |  |  |  | 			} | 
			
		
	
		
			
				
					|  |  |  |  | 			wi_item = next_in_ktree(ctx); | 
			
		
	
		
			
				
					|  |  |  |  | 			DATA_WORKINFO_NULL(workinfo, wi_item); | 
			
		
	
		
			
				
					|  |  |  |  | 		} | 
			
		
	
		
			
				
					|  |  |  |  | 		if (wi_item) { | 
			
		
	
		
			
				
					|  |  |  |  | 			DATA_WORKINFO(workinfo, wi_item); | 
			
		
	
		
			
				
					|  |  |  |  | 			this_height = coinbase1height(workinfo->coinbase1); | 
			
		
	
		
			
				
					|  |  |  |  | 			if (this_height == height) { | 
			
		
	
		
			
				
					|  |  |  |  | 				// We have our starting point
 | 
			
		
	
		
			
				
					|  |  |  |  | 				STRNCPY(bits, workinfo->bits); | 
			
		
	
		
			
				
					|  |  |  |  | 				got = true; | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | 				bigint_to_buf(workinfo->workinfoid, | 
			
		
	
		
			
				
					|  |  |  |  | 					      reply, sizeof(reply)); | 
			
		
	
		
			
				
					|  |  |  |  | 				snprintf(tmp, sizeof(tmp), | 
			
		
	
		
			
				
					|  |  |  |  | 					 "workinfoid0:%d=%s%c", | 
			
		
	
		
			
				
					|  |  |  |  | 					 rows, reply, FLDSEP); | 
			
		
	
		
			
				
					|  |  |  |  | 				APPEND_REALLOC(buf, off, len, tmp); | 
			
		
	
		
			
				
					|  |  |  |  | 				hex2bin(ndiffbin, workinfo->bits, 4); | 
			
		
	
		
			
				
					|  |  |  |  | 				snprintf(tmp, sizeof(tmp), | 
			
		
	
		
			
				
					|  |  |  |  | 					 "ndiff0:%d=%.1f%c", rows, | 
			
		
	
		
			
				
					|  |  |  |  | 					 diff_from_nbits(ndiffbin), | 
			
		
	
		
			
				
					|  |  |  |  | 					 FLDSEP); | 
			
		
	
		
			
				
					|  |  |  |  | 				APPEND_REALLOC(buf, off, len, tmp); | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | 				while (wi_item) { | 
			
		
	
		
			
				
					|  |  |  |  | 					if (CURRENT(&(workinfo->expirydate))) { | 
			
		
	
		
			
				
					|  |  |  |  | 						if (strcmp(bits, workinfo->bits) != 0) | 
			
		
	
		
			
				
					|  |  |  |  | 							break; | 
			
		
	
		
			
				
					|  |  |  |  | 					} | 
			
		
	
		
			
				
					|  |  |  |  | 					wi_item = next_in_ktree(ctx); | 
			
		
	
		
			
				
					|  |  |  |  | 					DATA_WORKINFO_NULL(workinfo, wi_item); | 
			
		
	
		
			
				
					|  |  |  |  | 				} | 
			
		
	
		
			
				
					|  |  |  |  | 			} else | 
			
		
	
		
			
				
					|  |  |  |  | 				wi_item = NULL; | 
			
		
	
		
			
				
					|  |  |  |  | 		} | 
			
		
	
		
			
				
					|  |  |  |  | 		K_RUNLOCK(workinfo_free); | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | 		if (!got) { | 
			
		
	
		
			
				
					|  |  |  |  | 			snprintf(tmp, sizeof(tmp), "workinfoid0:%d=%c", | 
			
		
	
		
			
				
					|  |  |  |  | 						   rows, FLDSEP); | 
			
		
	
		
			
				
					|  |  |  |  | 			APPEND_REALLOC(buf, off, len, tmp); | 
			
		
	
		
			
				
					|  |  |  |  | 			snprintf(tmp, sizeof(tmp), "ndiff0:%d=%c", | 
			
		
	
		
			
				
					|  |  |  |  | 						   rows, FLDSEP); | 
			
		
	
		
			
				
					|  |  |  |  | 			APPEND_REALLOC(buf, off, len, tmp); | 
			
		
	
		
			
				
					|  |  |  |  | 		} | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | 		if (!wi_item) { | 
			
		
	
		
			
				
					|  |  |  |  | 			snprintf(tmp, sizeof(tmp), "height:%d=%c", | 
			
		
	
		
			
				
					|  |  |  |  | 						   rows, FLDSEP); | 
			
		
	
		
			
				
					|  |  |  |  | 			APPEND_REALLOC(buf, off, len, tmp); | 
			
		
	
		
			
				
					|  |  |  |  | 			snprintf(tmp, sizeof(tmp), "workinfoid:%d=%c", | 
			
		
	
		
			
				
					|  |  |  |  | 						   rows, FLDSEP); | 
			
		
	
		
			
				
					|  |  |  |  | 			APPEND_REALLOC(buf, off, len, tmp); | 
			
		
	
		
			
				
					|  |  |  |  | 			snprintf(tmp, sizeof(tmp), "ndiff:%d=%c", | 
			
		
	
		
			
				
					|  |  |  |  | 						   rows, FLDSEP); | 
			
		
	
		
			
				
					|  |  |  |  | 			APPEND_REALLOC(buf, off, len, tmp); | 
			
		
	
		
			
				
					|  |  |  |  | 		} else { | 
			
		
	
		
			
				
					|  |  |  |  | 			this_height = coinbase1height(workinfo->coinbase1); | 
			
		
	
		
			
				
					|  |  |  |  | 			int_to_buf(this_height, reply, sizeof(reply)); | 
			
		
	
		
			
				
					|  |  |  |  | 			snprintf(tmp, sizeof(tmp), "height:%d=%s%c", | 
			
		
	
		
			
				
					|  |  |  |  | 						   rows, reply, FLDSEP); | 
			
		
	
		
			
				
					|  |  |  |  | 			APPEND_REALLOC(buf, off, len, tmp); | 
			
		
	
		
			
				
					|  |  |  |  | 			bigint_to_buf(workinfo->workinfoid, | 
			
		
	
		
			
				
					|  |  |  |  | 				      reply, sizeof(reply)); | 
			
		
	
		
			
				
					|  |  |  |  | 			snprintf(tmp, sizeof(tmp), "workinfoid:%d=%s%c", | 
			
		
	
		
			
				
					|  |  |  |  | 						   rows, reply, FLDSEP); | 
			
		
	
		
			
				
					|  |  |  |  | 			APPEND_REALLOC(buf, off, len, tmp); | 
			
		
	
		
			
				
					|  |  |  |  | 			hex2bin(ndiffbin, workinfo->bits, 4); | 
			
		
	
		
			
				
					|  |  |  |  | 			snprintf(tmp, sizeof(tmp), "ndiff:%d=%.1f%c", | 
			
		
	
		
			
				
					|  |  |  |  | 						   rows, | 
			
		
	
		
			
				
					|  |  |  |  | 						   diff_from_nbits(ndiffbin), | 
			
		
	
		
			
				
					|  |  |  |  | 						   FLDSEP); | 
			
		
	
		
			
				
					|  |  |  |  | 			APPEND_REALLOC(buf, off, len, tmp); | 
			
		
	
		
			
				
					|  |  |  |  | 		} | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | 		rows++; | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | 		snprintf(tmp, sizeof(tmp), "flds=%s%c", | 
			
		
	
		
			
				
					|  |  |  |  | 			 "height0,workinfoid0,ndiff0,height,workinfo,ndiff", | 
			
		
	
		
			
				
					|  |  |  |  | 			 FLDSEP); | 
			
		
	
		
			
				
					|  |  |  |  | 		APPEND_REALLOC(buf, off, len, tmp); | 
			
		
	
		
			
				
					|  |  |  |  | 		snprintf(tmp, sizeof(tmp), "arn=%s%carp=%s%c", | 
			
		
	
		
			
				
					|  |  |  |  | 			 "WorkinfoRange", FLDSEP, "", FLDSEP); | 
			
		
	
		
			
				
					|  |  |  |  | 		APPEND_REALLOC(buf, off, len, tmp); | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | 		ok = true; | 
			
		
	
		
			
				
					|  |  |  |  | 	} else { | 
			
		
	
		
			
				
					|  |  |  |  | 		free(buf); | 
			
		
	
		
			
				
					|  |  |  |  | 		snprintf(reply, siz, "unknown request '%s'", request); | 
			
		
	
		
			
				
					|  |  |  |  | 		LOGERR("%s() %s.%s", __func__, id, reply); | 
			
		
	
		
			
				
					|  |  |  |  | 		return strdup(reply); | 
			
		
	
		
			
				
					|  |  |  |  | 	} | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | 	if (!ok) { | 
			
		
	
		
			
				
					|  |  |  |  | 		free(buf); | 
			
		
	
		
			
				
					|  |  |  |  | 		snprintf(reply, siz, "failed.%s%s%s", | 
			
		
	
		
			
				
					|  |  |  |  | 					request, | 
			
		
	
		
			
				
					|  |  |  |  | 					msg[0] ? " " : "", | 
			
		
	
		
			
				
					|  |  |  |  | 					msg[0] ? msg : ""); | 
			
		
	
		
			
				
					|  |  |  |  | 		LOGERR("%s() %s.%s", __func__, id, reply); | 
			
		
	
		
			
				
					|  |  |  |  | 		return strdup(reply); | 
			
		
	
		
			
				
					|  |  |  |  | 	} | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | 	snprintf(tmp, sizeof(tmp), "rows=%d", rows); | 
			
		
	
		
			
				
					|  |  |  |  | 	APPEND_REALLOC(buf, off, len, tmp); | 
			
		
	
		
			
				
					|  |  |  |  | 	LOGWARNING("%s() %s.%s%s%s", __func__, id, request, | 
			
		
	
		
			
				
					|  |  |  |  | 				     msg[0] ? " " : "", | 
			
		
	
		
			
				
					|  |  |  |  | 				     msg[0] ? msg : ""); | 
			
		
	
		
			
				
					|  |  |  |  | 	return buf; | 
			
		
	
		
			
				
					|  |  |  |  | } | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | /* The socket command format is as follows:
 | 
			
		
	
		
			
				
					|  |  |  |  |  *  Basic structure: | 
			
		
	
		
			
				
					|  |  |  |  |  *    cmd.ID.fld1=value1 FLDSEP fld2=value2 FLDSEP fld3=... | 
			
		
	
	
		
			
				
					|  |  |  | @ -6679,5 +7161,6 @@ struct CMDS ckdb_cmds[] = { | 
			
		
	
		
			
				
					|  |  |  |  | 	{ CMD_SHSTA,	"shsta",	true,	false,	cmd_shsta,	SEQ_NONE,	ACCESS_SYSTEM }, | 
			
		
	
		
			
				
					|  |  |  |  | 	{ CMD_USERINFO,	"userinfo",	false,	false,	cmd_userinfo,	SEQ_NONE,	ACCESS_WEB }, | 
			
		
	
		
			
				
					|  |  |  |  | 	{ CMD_BTCSET,	"btcset",	false,	false,	cmd_btcset,	SEQ_NONE,	ACCESS_SYSTEM }, | 
			
		
	
		
			
				
					|  |  |  |  | 	{ CMD_QUERY,	"query",	false,	false,	cmd_query,	SEQ_NONE,	ACCESS_SYSTEM }, | 
			
		
	
		
			
				
					|  |  |  |  | 	{ CMD_END,	NULL,		false,	false,	NULL,		SEQ_NONE,	0 } | 
			
		
	
		
			
				
					|  |  |  |  | }; | 
			
		
	
	
		
			
				
					|  |  |  | 
 |