Browse Source

API v0.2 Added GPU commands and improved messages

Kano 14 years ago
parent
commit
d234b857ff
4 changed files with 253 additions and 41 deletions
  1. 1 1
      api-example.php
  2. 245 36
      api.c
  3. 4 4
      main.c
  4. 3 0
      miner.h

+ 1 - 1
api-example.php

@@ -69,7 +69,7 @@ function request($cmd)
 			$items = explode(',', $obj);
 			$item = $items[0];
 			$id = explode('=', $items[0], 2);
-			if (count($id) == 1)
+			if (count($id) == 1 or !ctype_digit($id[1]))
 				$name = $id[0];
 			else
 				$name = $id[0].$id[1];

+ 245 - 36
api.c

@@ -16,13 +16,6 @@
 #include <stdbool.h>
 #include <stdint.h>
 #include <unistd.h>
-#include <sys/time.h>
-#include <time.h>
-#include <math.h>
-#include <stdarg.h>
-#include <assert.h>
-
-#include <sys/stat.h>
 #include <sys/types.h>
 
 #include "compat.h"
@@ -30,8 +23,6 @@
 
 #if defined(unix)
 	#include <errno.h>
-//	#include <fcntl.h>
-//	#include <sys/wait.h>
 #endif
 
 #include <sys/socket.h>
@@ -43,25 +34,145 @@
 // Current code assumes it can socket send this size also
 #define MYBUFSIZ	16384
 
-// Socket is on 127.0.0.1
-#define QUEUE	10
+// Number of requets to queue - normally would be small
+#define QUEUE	30
 
 static char *buffer = NULL;
+static char error_buffer[BUFSIZ];
 
 static const char *UNAVAILABLE = " - API will not be available";
 
 static const char *BLANK = "";
+static const char SEPARATOR = '|';
+static const char *SEPARATORSTR = "|";
+
+#define MSG_INVGPU 1
+#define MSG_ALRENA 2
+#define MSG_ALRDIS 3
+#define MSG_GPUMRE 4
+#define MSG_GPUREN 5
+#define MSG_GPUNON 6
+#define MSG_POOL 7
+#define MSG_NOPOOL 8
+#define MSG_DEVS 9
+#define MSG_NODEVS 10
+#define MSG_SUMM 11
+#define MSG_GPUDIS 12
+#define MSG_GPUREI 13
+#define MSG_INVCMD 14
+
+enum code_severity {
+	SEVERITY_ERR,
+	SEVERITY_WARN,
+	SEVERITY_INFO,
+	SEVERITY_SUCC,
+	SEVERITY_FAIL
+};
 
-static const char *APIVERSION = "0.1";
+enum code_parameters {
+	PARAM_GPU,
+	PARAM_NONE,
+	PARAM_GPUMAX,
+	PARAM_PMAX,
+	PARAM_GCMAX,
+};
+
+struct CODES {
+	enum code_severity severity;
+	int code;
+	enum code_parameters params;
+	const char *description;
+} codes[] = {
+ { SEVERITY_ERR,   MSG_INVGPU,	PARAM_GPUMAX,	"Invalid GPU id %d - range is 0 - %d" },
+ { SEVERITY_INFO,  MSG_ALRENA,	PARAM_GPU,	"GPU %d already enabled" },
+ { SEVERITY_INFO,  MSG_ALRDIS,	PARAM_GPU,	"GPU %d already disabled" },
+ { SEVERITY_WARN,  MSG_GPUMRE,	PARAM_GPU,	"GPU %d must be restarted first" },
+ { SEVERITY_INFO,  MSG_GPUREN,	PARAM_GPU,	"GPU %d sent enable message" },
+ { SEVERITY_WARN,  MSG_GPUNON,	PARAM_NONE,	"No GPUs" },
+ { SEVERITY_SUCC,  MSG_POOL,	PARAM_PMAX,	"%d Pool" },
+ { SEVERITY_WARN,  MSG_NOPOOL,	PARAM_NONE,	"No pools" },
+ { SEVERITY_SUCC,  MSG_DEVS,	PARAM_GCMAX,	"%d GPU - %d CPU" },
+ { SEVERITY_WARN,  MSG_NODEVS,	PARAM_NONE,	"No GPUs/CPUs" },
+ { SEVERITY_SUCC,  MSG_SUMM,	PARAM_NONE,	"Summary" },
+ { SEVERITY_INFO,  MSG_GPUDIS,	PARAM_GPU,	"GPU %d set disable flag" },
+ { SEVERITY_INFO,  MSG_GPUREI,	PARAM_GPU,	"GPU %d restart attempted" },
+ { SEVERITY_ERR,   MSG_INVCMD,	PARAM_NONE,	"Invalid command" },
+ { SEVERITY_FAIL }
+};
+
+static const char *APIVERSION = "0.2";
 static const char *DEAD = "DEAD";
 static const char *SICK = "SICK";
+static const char *NOSTART = "NOSTART";
 static const char *DISABLED = "DISABLED";
 static const char *ALIVE = "ALIVE";
+static const char *DYNAMIC = "D";
 
 static const char *YES = "Y";
 static const char *NO = "N";
 
 static int bye = 0;
+static bool ping = true;
+
+static char *message(int messageid, int gpuid)
+{
+	char severity;
+	char *ptr;
+	int i;
+
+	for (i = 0; codes[i].severity != SEVERITY_FAIL; i++) {
+		if (codes[i].code == messageid) {
+			switch (codes[i].severity) {
+			case SEVERITY_WARN:
+				severity = 'W';
+				break;
+			case SEVERITY_INFO:
+				severity = 'I';
+				break;
+			case SEVERITY_SUCC:
+				severity = 'S';
+				break;
+			case SEVERITY_ERR:
+			default:
+				severity = 'E';
+				break;
+			}
+
+			sprintf(error_buffer, "STATUS=%c,CODE=%d,MSG=",
+					severity, messageid);
+
+			ptr = error_buffer + strlen(error_buffer);
+
+			switch(codes[i].params) {
+			case PARAM_GPU:
+				sprintf(ptr, codes[i].description, gpuid);
+				break;
+			case PARAM_GPUMAX:
+				sprintf(ptr, codes[i].description,
+						gpuid, gpu_threads - 1);
+				break;
+			case PARAM_PMAX:
+				sprintf(ptr, codes[i].description, total_pools);
+				break;
+			case PARAM_GCMAX:
+				sprintf(ptr, codes[i].description,
+						gpu_threads,
+						(mining_threads - gpu_threads));
+				break;
+			case PARAM_NONE:
+			default:
+				strcpy(ptr, codes[i].description);
+			}
+
+			strcat(error_buffer, SEPARATORSTR);
+
+			return error_buffer;
+		}
+	}
+
+	sprintf(error_buffer, "STATUS=F,CODE=-1,MSG=%d%c", messageid, SEPARATOR);
+	return error_buffer;
+}
 
 char *apiversion(char *params)
 {
@@ -70,8 +181,9 @@ char *apiversion(char *params)
 
 void gpustatus(int thr_id)
 {
+	char intensity[10];
 	char buf[BUFSIZ];
-	char status_buf[BUFSIZ];
+	char *enabled;
 	char *status;
 	float gt;
 	int gf, gp;
@@ -92,22 +204,30 @@ void gpustatus(int thr_id)
 #endif
 		gt = gf = gp = 0;
 
+		if (gpu_devices[gpu])
+			enabled = (char *)YES;
+		else
+			enabled = (char *)NO;
+
 		if (cgpu->status == LIFE_DEAD)
 			status = (char *)DEAD;
 		else if (cgpu->status == LIFE_SICK)
 			status = (char *)SICK;
-		else if (!gpu_devices[gpu])
-			status = (char *)DISABLED;
-		else {
-			sprintf(status_buf, "%.1f", cgpu->rolling);
-			status = status_buf;
-		}
+		else if (cgpu->status == LIFE_NOSTART)
+			status = (char *)NOSTART;
+		else
+			status = (char *)ALIVE;
 
-		sprintf(buf, "GPU=%d,GT=%.2f,FR=%d,FP=%d,STA=%s,MHS=%.2f,A=%d,R=%d,HW=%d,U=%.2f,I=%d|",
-			gpu, gt, gf, gp, status,
+		if (cgpu->dynamic)
+			strcpy(intensity, DYNAMIC);
+		else
+			sprintf(intensity, "%d", gpus->intensity);
+
+		sprintf(buf, "GPU=%d,GT=%.2f,FR=%d,FP=%d,EN=%s,STA=%s,MHS=%.2f,A=%d,R=%d,HW=%d,U=%.2f,I=%s%c",
+			gpu, gt, gf, gp, enabled, status,
 			cgpu->total_mhashes / total_secs,
 			cgpu->accepted, cgpu->rejected, cgpu->hw_errors,
-			cgpu->utility, gpus->intensity);
+			cgpu->utility, intensity, SEPARATOR);
 
 		strcat(buffer, buf);
 	}
@@ -123,11 +243,11 @@ void cpustatus(int thr_id)
 
 		cgpu->utility = cgpu->accepted / ( total_secs ? total_secs : 1 ) * 60;
 
-		sprintf(buf, "CPU=%d,STA=%.2f,MHS=%.2f,A=%d,R=%d,U=%.2f|",
+		sprintf(buf, "CPU=%d,STA=%.2f,MHS=%.2f,A=%d,R=%d,U=%.2f%c",
 			cpu, cgpu->rolling,
 			cgpu->total_mhashes / total_secs,
 			cgpu->accepted, cgpu->rejected,
-			cgpu->utility);
+			cgpu->utility, SEPARATOR);
 
 		strcat(buffer, buf);
 	}
@@ -137,7 +257,10 @@ char *devstatus(char *params)
 {
 	int i;
 
-	*buffer = '\0';
+	if (gpu_threads == 0 && mining_threads == 0)
+		return message(MSG_NODEVS, 0);
+
+	strcpy(buffer, message(MSG_DEVS, 0));
 
 	for (i = 0; i < gpu_threads; i++)
 		gpustatus(i);
@@ -154,7 +277,10 @@ char *poolstatus(char *params)
 	char *status, *lp;
 	int i;
 
-	*buffer = '\0';
+	if (total_pools == 0)
+		return message(MSG_NOPOOL, 0);
+
+	strcpy(buffer, message(MSG_POOL, 0));
 
 	for (i = 0; i < total_pools; i++) {
 		struct pool *pool = pools[i];
@@ -174,14 +300,14 @@ char *poolstatus(char *params)
 		else
 			lp = (char *)NO;
 
-		sprintf(buf, "POOL=%d,URL=%s,STA=%s,PRI=%d,LP=%s,Q=%d,A=%d,R=%d,DW=%d,ST=%d,GF=%d,RF=%d|",
+		sprintf(buf, "POOL=%d,URL=%s,STA=%s,PRI=%d,LP=%s,Q=%d,A=%d,R=%d,DW=%d,ST=%d,GF=%d,RF=%d%c",
 			i, pool->rpc_url, status, pool->prio, lp,
 			pool->getwork_requested,
 			pool->accepted, pool->rejected,
 			pool->discarded_work,
 			pool->stale_shares,
 			pool->getfail_occasions,
-			pool->remotefail_occasions);
+			pool->remotefail_occasions, SEPARATOR);
 
 		strcat(buffer, buf);
 	}
@@ -196,15 +322,85 @@ char *summary(char *params)
 	utility = total_accepted / ( total_secs ? total_secs : 1 ) * 60;
 	mhs = total_mhashes_done / total_secs;
 
-	sprintf(buffer, "SUMMARY,EL=%.0lf,ALGO=%s,MHS=%.2lf,SOL=%d,Q=%d,A=%d,R=%d,HW=%d,U=%.2lf,DW=%d,ST=%d,GF=%d,LW=%d,RO=%d,BC=%d",
+	sprintf(buffer, "%sSUMMARY=all,EL=%.0lf,ALGO=%s,MHS=%.2lf,SOL=%d,Q=%d,A=%d,R=%d,HW=%d,U=%.2lf,DW=%d,ST=%d,GF=%d,LW=%d,RO=%d,BC=%d%c",
+		message(MSG_SUMM, 0),
 		total_secs, algo_names[opt_algo], mhs, found_blocks,
 		total_getworks, total_accepted, total_rejected,
 		hw_errors, utility, total_discarded, total_stale,
-		total_go, local_work, total_ro, new_blocks);
+		total_go, local_work, total_ro, new_blocks, SEPARATOR);
 
 	return buffer;
 }
 
+char *gpuenable(char *params)
+{
+	struct thr_info *thr;
+	int gpu;
+	int id;
+	int i;
+
+	if (gpu_threads == 0)
+		return message(MSG_GPUNON, 0);
+
+	id = atoi(params);
+	if (id < 0 || id >= gpu_threads)
+		return message(MSG_INVGPU, id);
+
+	if (gpu_devices[id])
+		return message(MSG_ALRENA, id);
+
+	for (i = 0; i < gpu_threads; i++) {
+		gpu = thr_info[i].cgpu->cpu_gpu;
+		if (gpu == id) {
+			thr = &thr_info[i];
+			if (thr->cgpu->status != LIFE_WELL)
+				return message(MSG_GPUMRE, id);
+
+			gpu_devices[id] = true;
+			tq_push(thr->q, &ping);
+
+			return message(MSG_GPUREN, id);
+		}
+	}
+
+	return message(-2, 0);
+}
+
+char *gpudisable(char *params)
+{
+	int id;
+
+	if (gpu_threads == 0)
+		return message(MSG_GPUNON, 0);
+
+	id = atoi(params);
+	if (id < 0 || id >= gpu_threads)
+		return message(MSG_INVGPU, id);
+
+	if (!gpu_devices[id])
+		return message(MSG_ALRDIS, id);
+
+	gpu_devices[id] = false;
+
+	return message(MSG_GPUDIS, id);
+}
+
+char *gpurestart(char *params)
+{
+	int id;
+
+	if (gpu_threads == 0)
+		return message(MSG_GPUNON, 0);
+
+	id = atoi(params);
+	if (id < 0 || id >= gpu_threads)
+		return message(MSG_INVGPU, id);
+
+	reinit_device(&gpus[id]);
+
+	return message(MSG_GPUREI, id);
+}
+
 char *doquit(char *params)
 {
 	bye = 1;
@@ -220,11 +416,13 @@ struct CMDS {
 	{ "dev",	devstatus },
 	{ "pool",	poolstatus },
 	{ "summary",	summary },
+	{ "gpuenable",	gpuenable },
+	{ "gpudisable",	gpudisable },
+	{ "gpurestart",	gpurestart },
 	{ "quit",	doquit },
+	{ NULL,		NULL }
 };
 
-#define CMDMAX 5
-
 void send_result(int c, char *result)
 {
 	int n;
@@ -251,6 +449,7 @@ void api(void)
 	long long counter;
 	char *result;
 	char *params;
+	int did;
 	int i;
 
 	sock = socket(AF_INET, SOCK_STREAM, 0);
@@ -279,7 +478,7 @@ void api(void)
 			if ((time(NULL) - bindstart) > 61)
 				break;
 			else {
-				applog(LOG_ERR, "API bind to port %d failed - trying again in 15sec", port);
+				applog(LOG_WARNING, "API bind to port %d failed - trying again in 15sec", port);
 				sleep(15);
 			}
 		}
@@ -300,6 +499,13 @@ void api(void)
 
 	buffer = malloc(MYBUFSIZ+1);
 
+	sleep(opt_log_interval);
+
+	if (opt_api_listen)
+		applog(LOG_WARNING, "API running in UNRESTRICTED access mode");
+	else
+		applog(LOG_WARNING, "API running in restricted access mode");
+
 	counter = 0;
 	while (bye == 0) {
 		counter++;
@@ -318,19 +524,22 @@ void api(void)
 		if (opt_api_listen || strcmp(tmpaddr, addr) == 0) {
 			n = read(c, &buf[0], BUFSIZ-1);
 			if (n >= 0) {
+				did = false;
 				buf[n] = '\0';
-				params = strchr(buf, '|');
+				params = strchr(buf, SEPARATOR);
 				if (params != NULL)
 					*(params++) = '\0';
 
-				for (i = 0; i < CMDMAX; i++) {
+				for (i = 0; cmds[i].name != NULL; i++) {
 					if (strcmp(buf, cmds[i].name) == 0) {
 						result = (cmds[i].func)(params);
 						send_result(c, result);
-						close(c);
+						did = true;
 						break;
 					}
 				}
+				if (!did)
+					send_result(c, message(MSG_INVCMD, 0));
 			}
 		}
 		close(c);

+ 4 - 4
main.c

@@ -186,7 +186,7 @@ static bool opt_loginput = false;
 static int opt_retries = -1;
 static int opt_fail_pause = 5;
 static int fail_pause = 5;
-static int opt_log_interval = 5;
+int opt_log_interval = 5;
 bool opt_log_output = false;
 static int opt_queue = 1;
 int opt_vectors;
@@ -223,7 +223,7 @@ bool opt_autofan;
 bool opt_autoengine;
 bool opt_noadl;
 int opt_api_port = 4028;
-bool opt_api_listen;
+bool opt_api_listen = false;
 
 char *opt_kernel_path;
 char *cgminer_path;
@@ -3476,7 +3476,7 @@ retry:
 }
 
 #ifdef HAVE_OPENCL
-static void reinit_device(struct cgpu_info *cgpu);
+void reinit_device(struct cgpu_info *cgpu);
 
 static void manage_gpu(void)
 {
@@ -5102,7 +5102,7 @@ static void *reinit_gpu(void *userdata)
 }
 #endif
 
-static void reinit_device(struct cgpu_info *cgpu)
+void reinit_device(struct cgpu_info *cgpu)
 {
 	if (cgpu->is_gpu)
 		tq_push(thr_info[gpur_thr_id].q, cgpu);

+ 3 - 0
miner.h

@@ -411,6 +411,8 @@ struct work_restart {
 
 extern void kill_work(void);
 
+extern void reinit_device(struct cgpu_info *cgpu);
+
 extern void api(void);
 
 
@@ -439,6 +441,7 @@ extern int total_accepted, total_rejected;
 extern int total_getworks, total_stale, total_discarded;
 extern unsigned int local_work;
 extern unsigned int total_go, total_ro;
+extern int opt_log_interval;
 
 #ifdef HAVE_OPENCL
 typedef struct {