Commit 21e4cd85ead88c3452e8fd4cca26ffb1a486f474

Kano 2012-06-30T02:49:01

api.c data structure rather than raw sprintf - 1st test

diff --git a/api.c b/api.c
index c88c915..7785ae8 100644
--- a/api.c
+++ b/api.c
@@ -630,6 +630,195 @@ static char *escape_string(char *str, bool isjson)
 	return buf;
 }
 
+struct api_data *api_add_data_full(struct api_data *root, char *name, enum api_data_type type, void *data, bool copy_data)
+{
+	struct api_data *api_data;
+
+	api_data = (struct api_data *)malloc(sizeof(struct api_data));
+
+	api_data->type = type;
+	api_data->name = name;
+
+	if (root == NULL) {
+		root = api_data;
+		root->prev = root;
+		root->next = root;
+	}
+	else {
+		api_data->prev = root->prev;
+		root->prev = api_data;
+		api_data->next = root;
+		api_data->prev->next = api_data;
+	}
+
+	api_data->data_was_malloc = copy_data;
+
+	if (!copy_data)
+		api_data->data = data;
+	else
+		switch(type) {
+		case API_ESCAPE:
+		case API_STRING:
+			api_data->data = (void *)malloc(strlen((char *)data) + 1);
+			strcpy((char*)(api_data->data), (char *)data);
+			break;
+		case API_INT:
+			api_data->data = (void *)malloc(sizeof(int));
+			*((int *)(api_data->data)) = *((int *)data);
+			break;
+		case API_UINT:
+			api_data->data = (void *)malloc(sizeof(unsigned int));
+			*((unsigned int *)(api_data->data)) = *((unsigned int *)data);
+			break;
+		case API_UINT64:
+			api_data->data = (void *)malloc(sizeof(uint64_t));
+			*((uint64_t *)(api_data->data)) = *((uint64_t *)data);
+			break;
+		case API_ULONG:
+			api_data->data = (void *)malloc(sizeof(unsigned long));
+			*((unsigned long *)(api_data->data)) = *((unsigned long *)data);
+			break;
+		case API_DOUBLE:
+		case API_MHS:
+		case API_MHTOTAL:
+		case API_UTILITY:
+		case API_VOLTS:
+		case API_HS:
+			api_data->data = (void *)malloc(sizeof(double));
+			*((double *)(api_data->data)) = *((double *)data);
+			break;
+		case API_BOOL:
+			api_data->data = (void *)malloc(sizeof(bool));
+			*((bool *)(api_data->data)) = *((bool *)data);
+			break;
+		case API_TIMEVAL:
+			api_data->data = (void *)malloc(sizeof(struct timeval));
+			memcpy(api_data->data, data, sizeof(struct timeval));
+			break;
+		case API_TIME:
+			api_data->data = (void *)malloc(sizeof(time_t));
+			*(time_t *)(api_data->data) = *((time_t *)data);
+			break;
+		case API_TEMP:
+			api_data->data = (void *)malloc(sizeof(float));
+			*((float *)(api_data->data)) = *((float *)data);
+			break;
+		default:
+			applog(LOG_ERR, "API: unknown1 data type %d ignored", type);
+			api_data->type = API_STRING;
+			api_data->data_was_malloc = false;
+			api_data->data = (void *)UNKNOWN;
+			break;
+		}
+
+	return root;
+}
+
+static struct api_data *print_data(struct api_data *root, char *buf, bool isjson)
+{
+	struct api_data *tmp;
+	bool first = true;
+	char *quote;
+
+	if (isjson) {
+		strcpy(buf, JSON0);
+		quote = JSON1;
+	} else {
+		strcpy(buf, COMMA);
+		quote = (char *)BLANK;
+	}
+
+	buf = strchr(buf, '\0');
+
+	while (root) {
+		if (!first)
+			*(buf++) = *COMMA;
+		else
+			first = false;
+
+		sprintf(buf, "%s%s%s%s", quote, root->name, quote, isjson ? ":" : "=");
+
+		buf = strchr(buf, '\0');
+
+		switch(root->type) {
+		case API_STRING:
+			sprintf(buf, "%s%s%s", quote, (char *)(root->data), quote);
+			break;
+		case API_ESCAPE:
+			sprintf(buf, "%s%s%s",
+				quote,
+				escape_string((char *)(root->data), isjson),
+				quote);
+			break;
+		case API_INT:
+			sprintf(buf, "%d", *((int *)(root->data)));
+			break;
+		case API_UINT:
+			sprintf(buf, "%u", *((unsigned int *)(root->data)));
+			break;
+		case API_UINT64:
+			sprintf(buf, "%"PRIu64, *((uint64_t *)(root->data)));
+			break;
+		case API_ULONG:
+		case API_TIME:
+			sprintf(buf, "%lu", *((unsigned long *)(root->data)));
+			break;
+		case API_DOUBLE:
+			sprintf(buf, "%f", *((double *)(root->data)));
+			break;
+		case API_UTILITY:
+		case API_MHS:
+			sprintf(buf, "%.2f", *((double *)(root->data)));
+			break;
+		case API_VOLTS:
+			sprintf(buf, "%.3f", *((double *)(root->data)));
+			break;
+		case API_MHTOTAL:
+			sprintf(buf, "%.4f", *((double *)(root->data)));
+			break;
+		case API_HS:
+			sprintf(buf, "%.15f", *((double *)(root->data)));
+			break;
+		case API_BOOL:
+			sprintf(buf, "%s", *((bool *)(root->data)) ? "true" : "false");
+			break;
+		case API_TIMEVAL:
+			sprintf(buf, "%ld.%06ld",
+				((struct timeval *)(root->data))->tv_sec,
+				((struct timeval *)(root->data))->tv_usec);
+			break;
+		case API_TEMP:
+			sprintf(buf, "%.2f", *((float *)(root->data)));
+			break;
+		default:
+			applog(LOG_ERR, "API: unknown2 data type %d ignored", root->type);
+			sprintf(buf, "%s%s%s", quote, UNKNOWN, quote);
+			break;
+		}
+
+		buf = strchr(buf, '\0');
+
+		if (root->data_was_malloc)
+			free(root->data);
+
+		if (root->next == root) {
+			free(root);
+			root = NULL;
+		} else {
+			tmp = root;
+			root = tmp->next;
+			root->prev = tmp->prev;
+			root->prev->next = root;
+			free(tmp);
+		}
+	}
+
+	if (isjson)
+		strcat(buf, "}");
+
+	return root;
+}
+
 #ifdef HAVE_AN_FPGA
 static int numpgas()
 {
@@ -819,15 +1008,33 @@ static char *message(int messageid, int paramid, char *param2, bool isjson)
 
 static void apiversion(__maybe_unused SOCKETTYPE c, __maybe_unused char *param, bool isjson, __maybe_unused char group)
 {
+	struct api_data *root = NULL;
+	char buf[TMPBUFSIZ];
+
+	sprintf(io_buffer, isjson
+		? "%s," JSON_VERSION
+		: "%s" _VERSION,
+		message(MSG_VERSION, 0, NULL, isjson));
+
+	root = api_add_data(root, "CGMiner", API_STRING, VERSION);
+	root = api_add_data(root, "API", API_STRING, APIVERSION);
+
+/*
 	sprintf(io_buffer, isjson
 		? "%s," JSON_VERSION "{\"CGMiner\":\"%s\",\"API\":\"%s\"}" JSON_CLOSE
 		: "%s" _VERSION ",CGMiner=%s,API=%s" SEPSTR,
 		message(MSG_VERSION, 0, NULL, isjson),
 		VERSION, APIVERSION);
+*/
+
+	root = print_data(root, buf, isjson);
+	strcat(io_buffer, buf);
+	strcat(io_buffer, isjson ? JSON_CLOSE : SEPSTR);
 }
 
 static void minerconfig(__maybe_unused SOCKETTYPE c, __maybe_unused char *param, bool isjson, __maybe_unused char group)
 {
+	struct api_data *root = NULL;
 	char buf[TMPBUFSIZ];
 	int gpucount = 0;
 	int pgacount = 0;
@@ -859,6 +1066,23 @@ static void minerconfig(__maybe_unused SOCKETTYPE c, __maybe_unused char *param,
 	cpucount = opt_n_threads > 0 ? num_processors : 0;
 #endif
 
+	sprintf(io_buffer, isjson
+		? "%s," JSON_MINECON
+		: "%s" _MINECON ",",
+		message(MSG_MINECON, 0, NULL, isjson));
+
+	root = api_add_data(root, "GPU Count", API_INT, &gpucount);
+	root = api_add_data(root, "PGA Count", API_INT, &pgacount);
+	root = api_add_data(root, "CPU Count", API_INT, &cpucount);
+	root = api_add_data(root, "Pool Count", API_INT, &total_pools);
+	root = api_add_data(root, "ADL", API_STRING, adl);
+	root = api_add_data(root, "ADL in use", API_STRING, adlinuse);
+	root = api_add_data(root, "Strategy", API_STRING, strategies[pool_strategy].s);
+	root = api_add_data(root, "Log Interval", API_INT, &opt_log_interval);
+	root = api_add_data(root, "Device Code", API_STRING, DEVICECODE);
+	root = api_add_data(root, "OS", API_STRING, OSINFO);
+
+/*
 	strcpy(io_buffer, message(MSG_MINECON, 0, NULL, isjson));
 
 	sprintf(buf, isjson
@@ -869,10 +1093,16 @@ static void minerconfig(__maybe_unused SOCKETTYPE c, __maybe_unused char *param,
 		strategies[pool_strategy].s, opt_log_interval, DEVICECODE, OSINFO);
 
 	strcat(io_buffer, buf);
+*/
+
+	root = print_data(root, buf, isjson);
+	strcat(io_buffer, buf);
+	strcat(io_buffer, isjson ? JSON_CLOSE : SEPSTR);
 }
 #ifdef HAVE_OPENCL
 static void gpustatus(int gpu, bool isjson)
 {
+	struct api_data *root = NULL;
 	char intensity[20];
 	char buf[TMPBUFSIZ];
 	char *enabled;
@@ -909,6 +1139,38 @@ static void gpustatus(int gpu, bool isjson)
 		else
 			sprintf(intensity, "%d", cgpu->intensity);
 
+		root = api_add_data(root, "GPU", API_INT, &gpu);
+		root = api_add_data(root, "Enabled", API_STRING, &enabled);
+		root = api_add_data(root, "Status", API_STRING, &status);
+		root = api_add_data(root, "Temperature", API_TEMP, &gt);
+		root = api_add_data(root, "Fan Speed", API_INT, &gf);
+		root = api_add_data(root, "Fan Percent", API_INT, &gp);
+		root = api_add_data(root, "GPU Clock", API_INT, &gc);
+		root = api_add_data(root, "Memory Clock", API_INT, &gm);
+		root = api_add_data(root, "GPU Voltage", API_VOLTS, &gv);
+		root = api_add_data(root, "GPU Activity", API_INT, &ga);
+		root = api_add_data(root, "Powertune", API_INT, &pt);
+
+		double mhs = cgpu->total_mhashes / total_secs;
+		root = api_add_data(root, "MHS av", API_MHS, &mhs);
+
+		char mhsname[27];
+		sprintf(mhsname, "MHS %ds", opt_log_interval);
+		root = api_add_data(root, mhsname, API_MHS, &(cgpu->rolling));
+
+		root = api_add_data(root, "Accepted", API_INT, &(cgpu->accepted));
+		root = api_add_data(root, "Rejected", API_INT, &(cgpu->rejected));
+		root = api_add_data(root, "Hardware Errors", API_INT, &(cgpu->hw_errors));
+		root = api_add_data(root, "Utility", API_UTILITY, &(cgpu->utility));
+		root = api_add_data(root, "Intensity", API_STRING, intensity);
+
+		unsigned long last_share_pool = cgpu->last_share_pool_time > 0 ? cgpu->last_share_pool : -1;
+		root = api_add_data(root, "Last Share Pool", API_INT, &last_share_pool);
+
+		root = api_add_data(root, "Last Share Time", API_ULONG, &(cgpu->last_share_pool_time));
+		root = api_add_data(root, "Total MH", API_MHTOTAL, &(cgpu->total_mhashes));
+
+		/*
 		sprintf(buf, isjson
 			? "{\"GPU\":%d,\"Enabled\":\"%s\",\"Status\":\"%s\",\"Temperature\":%.2f,\"Fan Speed\":%d,\"Fan Percent\":%d,\"GPU Clock\":%d,\"Memory Clock\":%d,\"GPU Voltage\":%.3f,\"GPU Activity\":%d,\"Powertune\":%d,\"MHS av\":%.2f,\"MHS %ds\":%.2f,\"Accepted\":%d,\"Rejected\":%d,\"Hardware Errors\":%d,\"Utility\":%.2f,\"Intensity\":\"%s\",\"Last Share Pool\":%d,\"Last Share Time\":%lu,\"Total MH\":%.4f}"
 			: "GPU=%d,Enabled=%s,Status=%s,Temperature=%.2f,Fan Speed=%d,Fan Percent=%d,GPU Clock=%d,Memory Clock=%d,GPU Voltage=%.3f,GPU Activity=%d,Powertune=%d,MHS av=%.2f,MHS %ds=%.2f,Accepted=%d,Rejected=%d,Hardware Errors=%d,Utility=%.2f,Intensity=%s,Last Share Pool=%d,Last Share Time=%lu,Total MH=%.4f" SEPSTR,
@@ -920,6 +1182,10 @@ static void gpustatus(int gpu, bool isjson)
 			(unsigned long)(cgpu->last_share_pool_time), cgpu->total_mhashes);
 
 		strcat(io_buffer, buf);
+		*/
+		root = print_data(root, buf, isjson);
+		strcat(io_buffer, buf);
+		strcat(io_buffer, isjson ? BLANK : SEPSTR);
 	}
 }
 #endif
diff --git a/miner.h b/miner.h
index 57fa774..1be29d6 100644
--- a/miner.h
+++ b/miner.h
@@ -791,4 +791,36 @@ extern bool successful_connect;
 extern void adl(void);
 extern void app_restart(void);
 
+enum api_data_type {
+	API_ESCAPE,
+	API_STRING,
+	API_INT,
+	API_UINT,
+	API_UINT64,
+	API_ULONG,
+	API_DOUBLE,
+	API_BOOL,
+	API_TIMEVAL,
+	API_TIME,
+	API_MHS,
+	API_MHTOTAL,
+	API_TEMP,
+	API_UTILITY,
+	API_VOLTS,
+	API_HS
+};
+
+struct api_data {
+	enum api_data_type type;
+	char *name;
+	void *data;
+	bool data_was_malloc;
+	struct api_data *prev;
+	struct api_data *next;
+};
+
+extern struct api_data *api_add_data_full(struct api_data *root, char *name, enum api_data_type type, void *data, bool copy_data);
+#define api_add_data_copy(r, n, t, d) api_add_data_full((r), (n), (t), (void *)(d), true)
+#define api_add_data(r, n, t, d) api_add_data_full((r), (n), (t), (void *)(d), false)
+
 #endif /* __MINER_H__ */