From ea1aba07d85a61e6d88e5007a93abc98f7b6c5cf Mon Sep 17 00:00:00 2001 From: ystarnaud Date: Thu, 19 Jun 2014 16:15:42 -0400 Subject: [PATCH] API Update Ability to add/remove profiles via API. --- api.c | 120 ++++++++++++++++++++- api.h | 138 +++++++++--------------- config_parser.c | 272 ++++++++++++++++++++++++++++++++++++++++++++++++ config_parser.h | 9 ++ doc/API.md | 33 +++++- 5 files changed, 477 insertions(+), 95 deletions(-) diff --git a/api.c b/api.c index 53ed542f..ed09318e 100644 --- a/api.c +++ b/api.c @@ -53,6 +53,112 @@ char *WSAErrorMsg(void) { #endif +struct CODES 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_ERR, MSG_GPUNON, PARAM_NONE, "No GPUs" }, + { SEVERITY_SUCC, MSG_POOL, PARAM_PMAX, "%d Pool(s)" }, + { SEVERITY_ERR, MSG_NOPOOL, PARAM_NONE, "No pools" }, + + { SEVERITY_SUCC, MSG_DEVS, PARAM_DMAX, "%d GPU(s)" }, + { SEVERITY_ERR, MSG_NODEVS, PARAM_NONE, "No GPUs" + }, + + { 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_ERR, MSG_MISID, PARAM_NONE, "Missing device id parameter" }, + { SEVERITY_SUCC, MSG_GPUDEV, PARAM_GPU, "GPU%d" }, + { SEVERITY_SUCC, MSG_NUMGPU, PARAM_NONE, "GPU count" }, + { SEVERITY_SUCC, MSG_VERSION, PARAM_NONE, "SGMiner versions" }, + { SEVERITY_ERR, MSG_INVJSON, PARAM_NONE, "Invalid JSON" }, + { SEVERITY_ERR, MSG_MISCMD, PARAM_CMD, "Missing JSON '%s'" }, + { SEVERITY_ERR, MSG_MISPID, PARAM_NONE, "Missing pool id parameter" }, + { SEVERITY_ERR, MSG_INVPID, PARAM_POOLMAX, "Invalid pool id %d - range is 0 - %d" }, + { SEVERITY_SUCC, MSG_SWITCHP, PARAM_POOL, "Switching to pool %d:'%s'" }, + { SEVERITY_ERR, MSG_MISVAL, PARAM_NONE, "Missing comma after GPU number" }, + { SEVERITY_ERR, MSG_NOADL, PARAM_NONE, "ADL is not available" }, + { SEVERITY_ERR, MSG_NOGPUADL,PARAM_GPU, "GPU %d does not have ADL" }, + { SEVERITY_ERR, MSG_INVINT, PARAM_STR, "Invalid intensity (%s) - must be '" _DYNAMIC "' or range " MIN_INTENSITY_STR " - " MAX_INTENSITY_STR }, + { SEVERITY_INFO, MSG_GPUINT, PARAM_BOTH, "GPU %d set new intensity to %s" }, + { SEVERITY_SUCC, MSG_MINECONFIG,PARAM_NONE, "sgminer config" }, + { SEVERITY_ERR, MSG_GPUMERR, PARAM_BOTH, "Setting GPU %d memoryclock to (%s) reported failure" }, + { SEVERITY_SUCC, MSG_GPUMEM, PARAM_BOTH, "Setting GPU %d memoryclock to (%s) reported success" }, + { SEVERITY_ERR, MSG_GPUEERR, PARAM_BOTH, "Setting GPU %d clock to (%s) reported failure" }, + { SEVERITY_SUCC, MSG_GPUENG, PARAM_BOTH, "Setting GPU %d clock to (%s) reported success" }, + { SEVERITY_ERR, MSG_GPUVERR, PARAM_BOTH, "Setting GPU %d vddc to (%s) reported failure" }, + { SEVERITY_SUCC, MSG_GPUVDDC, PARAM_BOTH, "Setting GPU %d vddc to (%s) reported success" }, + { SEVERITY_ERR, MSG_GPUFERR, PARAM_BOTH, "Setting GPU %d fan to (%s) reported failure" }, + { SEVERITY_SUCC, MSG_GPUFAN, PARAM_BOTH, "Setting GPU %d fan to (%s) reported success" }, + { SEVERITY_ERR, MSG_MISFN, PARAM_NONE, "Missing save filename parameter" }, + { SEVERITY_ERR, MSG_BADFN, PARAM_STR, "Can't open or create save file '%s'" }, + { SEVERITY_SUCC, MSG_SAVED, PARAM_STR, "Configuration saved to file '%s'" }, + { SEVERITY_ERR, MSG_ACCDENY, PARAM_STR, "Access denied to '%s' command" }, + { SEVERITY_SUCC, MSG_ACCOK, PARAM_NONE, "Privileged access OK" }, + { SEVERITY_SUCC, MSG_ENAPOOL, PARAM_POOL, "Enabling pool %d:'%s'" }, + { SEVERITY_SUCC, MSG_POOLPRIO,PARAM_NONE, "Changed pool priorities" }, + { SEVERITY_ERR, MSG_DUPPID, PARAM_PID, "Duplicate pool specified %d" }, + { SEVERITY_SUCC, MSG_DISPOOL, PARAM_POOL, "Disabling pool %d:'%s'" }, + { SEVERITY_INFO, MSG_ALRENAP, PARAM_POOL, "Pool %d:'%s' already enabled" }, + { SEVERITY_INFO, MSG_ALRDISP, PARAM_POOL, "Pool %d:'%s' already disabled" }, + { SEVERITY_ERR, MSG_MISPDP, PARAM_NONE, "Missing addpool details" }, + { SEVERITY_ERR, MSG_INVPDP, PARAM_STR, "Invalid addpool details '%s'" }, + { SEVERITY_ERR, MSG_TOOMANYP,PARAM_NONE, "Reached maximum number of pools (%d)" }, + { SEVERITY_SUCC, MSG_ADDPOOL, PARAM_STR, "Added pool '%s'" }, + { SEVERITY_ERR, MSG_REMLASTP,PARAM_POOL, "Cannot remove last pool %d:'%s'" }, + { SEVERITY_ERR, MSG_ACTPOOL, PARAM_POOL, "Cannot remove active pool %d:'%s'" }, + { SEVERITY_SUCC, MSG_REMPOOL, PARAM_BOTH, "Removed pool %d:'%s'" }, + { SEVERITY_SUCC, MSG_NOTIFY, PARAM_NONE, "Notify" }, + { SEVERITY_SUCC, MSG_DEVDETAILS,PARAM_NONE, "Device Details" }, + { SEVERITY_SUCC, MSG_MINESTATS,PARAM_NONE, "sgminer stats" }, + { SEVERITY_ERR, MSG_MISCHK, PARAM_NONE, "Missing check cmd" }, + { SEVERITY_SUCC, MSG_CHECK, PARAM_NONE, "Check command" }, + { SEVERITY_ERR, MSG_MISBOOL, PARAM_NONE, "Missing parameter: true/false" }, + { SEVERITY_ERR, MSG_INVBOOL, PARAM_NONE, "Invalid parameter should be true or false" }, + { SEVERITY_SUCC, MSG_FOO, PARAM_BOOL, "Failover-Only set to %s" }, + { SEVERITY_SUCC, MSG_MINECOIN,PARAM_NONE, "sgminer coin" }, + { SEVERITY_SUCC, MSG_DEBUGSET,PARAM_NONE, "Debug settings" }, + { SEVERITY_SUCC, MSG_SETCONFIG,PARAM_SET, "Set config '%s' to %d" }, + { SEVERITY_ERR, MSG_UNKCON, PARAM_STR, "Unknown config '%s'" }, + { SEVERITY_ERR, MSG_INVNUM, PARAM_BOTH, "Invalid number (%d) for '%s' range is 0-9999" }, + { SEVERITY_ERR, MSG_INVNEG, PARAM_BOTH, "Invalid negative number (%d) for '%s'" }, + { SEVERITY_SUCC, MSG_SETQUOTA,PARAM_SET, "Set pool '%s' to quota %d'" }, + { SEVERITY_ERR, MSG_CONPAR, PARAM_NONE, "Missing config parameters 'name,N'" }, + { SEVERITY_ERR, MSG_CONVAL, PARAM_STR, "Missing config value N for '%s,N'" }, + { SEVERITY_INFO, MSG_NOUSTA, PARAM_NONE, "No USB Statistics" }, + { SEVERITY_ERR, MSG_ZERMIS, PARAM_NONE, "Missing zero parameters" }, + { SEVERITY_ERR, MSG_ZERINV, PARAM_STR, "Invalid zero parameter '%s'" }, + { SEVERITY_SUCC, MSG_ZERSUM, PARAM_STR, "Zeroed %s stats with summary" }, + { SEVERITY_SUCC, MSG_ZERNOSUM, PARAM_STR, "Zeroed %s stats without summary" }, + { SEVERITY_SUCC, MSG_LOCKOK, PARAM_NONE, "Lock stats created" }, + { SEVERITY_WARN, MSG_LOCKDIS, PARAM_NONE, "Lock stats not enabled" }, + { SEVERITY_SUCC, MSG_CHSTRAT, PARAM_STR, "Multipool strategy changed to '%s'" }, + { SEVERITY_ERR, MSG_MISSTRAT, PARAM_NONE, "Missing multipool strategy" }, + { SEVERITY_ERR, MSG_INVSTRAT, PARAM_NONE, "Invalid multipool strategy %d" }, + { SEVERITY_ERR, MSG_MISSTRATINT, PARAM_NONE, "Missing rotate interval" }, + + { SEVERITY_SUCC, MSG_PROFILE, PARAM_PRMAX, "%d Profile(s)" }, + { SEVERITY_ERR, MSG_NOPROFILE, PARAM_NONE, "No profiles" }, + + { SEVERITY_ERR, MSG_PROFILEEXIST, PARAM_STR, "Profile '%s' already exists" }, + { SEVERITY_ERR, MSG_MISPRD, PARAM_NONE, "Missing addprofile details" }, + { SEVERITY_SUCC, MSG_ADDPROFILE, PARAM_STR, "Added profile '%s'" }, + + { SEVERITY_ERR, MSG_MISPRID, PARAM_STR, "Profile name missing" }, + { SEVERITY_ERR, MSG_PRNOEXIST, PARAM_STR, "Profile '%s' doesn't exist" }, + { SEVERITY_ERR, MSG_PRISDEFAULT, PARAM_STR, "Profile '%s' is the default profile" }, + { SEVERITY_ERR, MSG_PRINUSE, PARAM_STR, "Profile '%s' is used by a pool" }, + { SEVERITY_SUCC, MSG_REMPROFILE, PARAM_BOTH, "Removed pool %d:'%s'" }, + + { SEVERITY_SUCC, MSG_BYE, PARAM_STR, "%s" }, + { SEVERITY_FAIL, 0, (enum code_parameters)0, NULL } +}; + + static const char *UNAVAILABLE = " - API will not be available"; static const char *MUNAVAILABLE = " - API multicast listener will not be available"; @@ -154,7 +260,7 @@ static struct io_data *_io_new(size_t initial, bool socket_buf) return io_data; } -static bool io_add(struct io_data *io_data, char *buf) +bool io_add(struct io_data *io_data, char *buf) { size_t len, dif, tot; @@ -180,12 +286,12 @@ static bool io_add(struct io_data *io_data, char *buf) return true; } -static void io_close(struct io_data *io_data) +void io_close(struct io_data *io_data) { io_data->close = true; } -static void io_free() +void io_free() { struct io_list *io_list, *io_next; @@ -535,7 +641,7 @@ struct api_data *api_add_avg(struct api_data *root, char *name, float *data, boo return api_add_data_full(root, name, API_AVG, (void *)data, copy_data); } -static struct api_data *print_data(struct api_data *root, char *buf, bool isjson, bool precom) +struct api_data *print_data(struct api_data *root, char *buf, bool isjson, bool precom) { struct api_data *tmp; bool first = true; @@ -724,6 +830,9 @@ void message(struct io_data *io_data, int messageid, int paramid, char *param2, case PARAM_PMAX: sprintf(buf, codes[i].description, total_pools); break; + case PARAM_PRMAX: + sprintf(buf, codes[i].description, total_profiles); + break; case PARAM_POOLMAX: sprintf(buf, codes[i].description, paramid, total_pools - 1); break; @@ -2725,6 +2834,7 @@ struct CMDS { { "config", minerconfig, false, true }, { "devs", devstatus, false, true }, { "pools", poolstatus, false, true }, + { "profiles", api_profile_list, false, true }, { "summary", summary, false, true }, { "gpuenable", gpuenable, true, false }, { "gpudisable", gpudisable, true, false }, @@ -2739,6 +2849,8 @@ struct CMDS { { "enablepool", enablepool, true, false }, { "disablepool", disablepool, true, false }, { "removepool", removepool, true, false }, + { "addprofile", api_profile_add, true, false }, + { "removeprofile", api_profile_remove, true, false }, { "gpuintensity", gpuintensity, true, false }, { "gpumem", gpumem, true, false }, { "gpuengine", gpuengine, true, false }, diff --git a/api.h b/api.h index 8c445c68..4cfff42e 100644 --- a/api.h +++ b/api.h @@ -80,6 +80,7 @@ struct WSAERRORS { #define _DEVS "DEVS" #define _POOLS "POOLS" +#define _PROFILES "PROFILES" #define _SUMMARY "SUMMARY" #define _STATUS "STATUS" #define _VERSION "VERSION" @@ -109,6 +110,7 @@ struct WSAERRORS { #define JSON_START JSON0 #define JSON_DEVS JSON1 _DEVS JSON2 #define JSON_POOLS JSON1 _POOLS JSON2 +#define JSON_PROFILES JSON1 _POOLS JSON2 #define JSON_SUMMARY JSON1 _SUMMARY JSON2 #define JSON_STATUS JSON1 _STATUS JSON2 #define JSON_VERSION JSON1 _VERSION JSON2 @@ -223,6 +225,19 @@ struct WSAERRORS { #define MSG_INVSTRAT 127 #define MSG_MISSTRATINT 128 +#define MSG_PROFILE 129 +#define MSG_NOPROFILE 130 + +#define MSG_PROFILEEXIST 131 +#define MSG_MISPRD 132 +#define MSG_ADDPROFILE 133 + +#define MSG_MISPRID 134 +#define MSG_PRNOEXIST 135 +#define MSG_PRISDEFAULT 136 +#define MSG_PRINUSE 137 +#define MSG_REMPROFILE 138 + enum code_severity { SEVERITY_ERR, SEVERITY_WARN, @@ -236,6 +251,7 @@ enum code_parameters { PARAM_PID, PARAM_GPUMAX, PARAM_PMAX, + PARAM_PRMAX, PARAM_POOLMAX, // Single generic case: have the code resolve it - see below @@ -256,97 +272,10 @@ struct CODES { const int code; const 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_ERR, MSG_GPUNON, PARAM_NONE, "No GPUs" }, - { SEVERITY_SUCC, MSG_POOL, PARAM_PMAX, "%d Pool(s)" }, - { SEVERITY_ERR, MSG_NOPOOL, PARAM_NONE, "No pools" }, - - { SEVERITY_SUCC, MSG_DEVS, PARAM_DMAX, "%d GPU(s)" }, - { SEVERITY_ERR, MSG_NODEVS, PARAM_NONE, "No GPUs" - }, - - { 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_ERR, MSG_MISID, PARAM_NONE, "Missing device id parameter" }, - { SEVERITY_SUCC, MSG_GPUDEV, PARAM_GPU, "GPU%d" }, - { SEVERITY_SUCC, MSG_NUMGPU, PARAM_NONE, "GPU count" }, - { SEVERITY_SUCC, MSG_VERSION, PARAM_NONE, "SGMiner versions" }, - { SEVERITY_ERR, MSG_INVJSON, PARAM_NONE, "Invalid JSON" }, - { SEVERITY_ERR, MSG_MISCMD, PARAM_CMD, "Missing JSON '%s'" }, - { SEVERITY_ERR, MSG_MISPID, PARAM_NONE, "Missing pool id parameter" }, - { SEVERITY_ERR, MSG_INVPID, PARAM_POOLMAX, "Invalid pool id %d - range is 0 - %d" }, - { SEVERITY_SUCC, MSG_SWITCHP, PARAM_POOL, "Switching to pool %d:'%s'" }, - { SEVERITY_ERR, MSG_MISVAL, PARAM_NONE, "Missing comma after GPU number" }, - { SEVERITY_ERR, MSG_NOADL, PARAM_NONE, "ADL is not available" }, - { SEVERITY_ERR, MSG_NOGPUADL,PARAM_GPU, "GPU %d does not have ADL" }, - { SEVERITY_ERR, MSG_INVINT, PARAM_STR, "Invalid intensity (%s) - must be '" _DYNAMIC "' or range " MIN_INTENSITY_STR " - " MAX_INTENSITY_STR }, - { SEVERITY_INFO, MSG_GPUINT, PARAM_BOTH, "GPU %d set new intensity to %s" }, - { SEVERITY_SUCC, MSG_MINECONFIG,PARAM_NONE, "sgminer config" }, - { SEVERITY_ERR, MSG_GPUMERR, PARAM_BOTH, "Setting GPU %d memoryclock to (%s) reported failure" }, - { SEVERITY_SUCC, MSG_GPUMEM, PARAM_BOTH, "Setting GPU %d memoryclock to (%s) reported success" }, - { SEVERITY_ERR, MSG_GPUEERR, PARAM_BOTH, "Setting GPU %d clock to (%s) reported failure" }, - { SEVERITY_SUCC, MSG_GPUENG, PARAM_BOTH, "Setting GPU %d clock to (%s) reported success" }, - { SEVERITY_ERR, MSG_GPUVERR, PARAM_BOTH, "Setting GPU %d vddc to (%s) reported failure" }, - { SEVERITY_SUCC, MSG_GPUVDDC, PARAM_BOTH, "Setting GPU %d vddc to (%s) reported success" }, - { SEVERITY_ERR, MSG_GPUFERR, PARAM_BOTH, "Setting GPU %d fan to (%s) reported failure" }, - { SEVERITY_SUCC, MSG_GPUFAN, PARAM_BOTH, "Setting GPU %d fan to (%s) reported success" }, - { SEVERITY_ERR, MSG_MISFN, PARAM_NONE, "Missing save filename parameter" }, - { SEVERITY_ERR, MSG_BADFN, PARAM_STR, "Can't open or create save file '%s'" }, - { SEVERITY_SUCC, MSG_SAVED, PARAM_STR, "Configuration saved to file '%s'" }, - { SEVERITY_ERR, MSG_ACCDENY, PARAM_STR, "Access denied to '%s' command" }, - { SEVERITY_SUCC, MSG_ACCOK, PARAM_NONE, "Privileged access OK" }, - { SEVERITY_SUCC, MSG_ENAPOOL, PARAM_POOL, "Enabling pool %d:'%s'" }, - { SEVERITY_SUCC, MSG_POOLPRIO,PARAM_NONE, "Changed pool priorities" }, - { SEVERITY_ERR, MSG_DUPPID, PARAM_PID, "Duplicate pool specified %d" }, - { SEVERITY_SUCC, MSG_DISPOOL, PARAM_POOL, "Disabling pool %d:'%s'" }, - { SEVERITY_INFO, MSG_ALRENAP, PARAM_POOL, "Pool %d:'%s' already enabled" }, - { SEVERITY_INFO, MSG_ALRDISP, PARAM_POOL, "Pool %d:'%s' already disabled" }, - { SEVERITY_ERR, MSG_MISPDP, PARAM_NONE, "Missing addpool details" }, - { SEVERITY_ERR, MSG_INVPDP, PARAM_STR, "Invalid addpool details '%s'" }, - { SEVERITY_ERR, MSG_TOOMANYP,PARAM_NONE, "Reached maximum number of pools (%d)" }, - { SEVERITY_SUCC, MSG_ADDPOOL, PARAM_STR, "Added pool '%s'" }, - { SEVERITY_ERR, MSG_REMLASTP,PARAM_POOL, "Cannot remove last pool %d:'%s'" }, - { SEVERITY_ERR, MSG_ACTPOOL, PARAM_POOL, "Cannot remove active pool %d:'%s'" }, - { SEVERITY_SUCC, MSG_REMPOOL, PARAM_BOTH, "Removed pool %d:'%s'" }, - { SEVERITY_SUCC, MSG_NOTIFY, PARAM_NONE, "Notify" }, - { SEVERITY_SUCC, MSG_DEVDETAILS,PARAM_NONE, "Device Details" }, - { SEVERITY_SUCC, MSG_MINESTATS,PARAM_NONE, "sgminer stats" }, - { SEVERITY_ERR, MSG_MISCHK, PARAM_NONE, "Missing check cmd" }, - { SEVERITY_SUCC, MSG_CHECK, PARAM_NONE, "Check command" }, - { SEVERITY_ERR, MSG_MISBOOL, PARAM_NONE, "Missing parameter: true/false" }, - { SEVERITY_ERR, MSG_INVBOOL, PARAM_NONE, "Invalid parameter should be true or false" }, - { SEVERITY_SUCC, MSG_FOO, PARAM_BOOL, "Failover-Only set to %s" }, - { SEVERITY_SUCC, MSG_MINECOIN,PARAM_NONE, "sgminer coin" }, - { SEVERITY_SUCC, MSG_DEBUGSET,PARAM_NONE, "Debug settings" }, - { SEVERITY_SUCC, MSG_SETCONFIG,PARAM_SET, "Set config '%s' to %d" }, - { SEVERITY_ERR, MSG_UNKCON, PARAM_STR, "Unknown config '%s'" }, - { SEVERITY_ERR, MSG_INVNUM, PARAM_BOTH, "Invalid number (%d) for '%s' range is 0-9999" }, - { SEVERITY_ERR, MSG_INVNEG, PARAM_BOTH, "Invalid negative number (%d) for '%s'" }, - { SEVERITY_SUCC, MSG_SETQUOTA,PARAM_SET, "Set pool '%s' to quota %d'" }, - { SEVERITY_ERR, MSG_CONPAR, PARAM_NONE, "Missing config parameters 'name,N'" }, - { SEVERITY_ERR, MSG_CONVAL, PARAM_STR, "Missing config value N for '%s,N'" }, - { SEVERITY_INFO, MSG_NOUSTA, PARAM_NONE, "No USB Statistics" }, - { SEVERITY_ERR, MSG_ZERMIS, PARAM_NONE, "Missing zero parameters" }, - { SEVERITY_ERR, MSG_ZERINV, PARAM_STR, "Invalid zero parameter '%s'" }, - { SEVERITY_SUCC, MSG_ZERSUM, PARAM_STR, "Zeroed %s stats with summary" }, - { SEVERITY_SUCC, MSG_ZERNOSUM, PARAM_STR, "Zeroed %s stats without summary" }, - { SEVERITY_SUCC, MSG_LOCKOK, PARAM_NONE, "Lock stats created" }, - { SEVERITY_WARN, MSG_LOCKDIS, PARAM_NONE, "Lock stats not enabled" }, - { SEVERITY_SUCC, MSG_CHSTRAT, PARAM_STR, "Multipool strategy changed to '%s'" }, - { SEVERITY_ERR, MSG_MISSTRAT, PARAM_NONE, "Missing multipool strategy" }, - { SEVERITY_ERR, MSG_INVSTRAT, PARAM_NONE, "Invalid multipool strategy %d" }, - { SEVERITY_ERR, MSG_MISSTRATINT, PARAM_NONE, "Missing rotate interval" }, - { SEVERITY_SUCC, MSG_BYE, PARAM_STR, "%s" }, - { SEVERITY_FAIL, 0, (enum code_parameters)0, NULL } }; +extern struct CODES codes[]; + struct IP4ACCESS { in_addr_t ip; in_addr_t mask; @@ -382,6 +311,37 @@ struct io_list { }; extern void message(struct io_data *io_data, int messageid, int paramid, char *param2, bool isjson); +extern bool io_add(struct io_data *io_data, char *buf); +extern void io_close(struct io_data *io_data); +extern void io_free(); + +extern struct api_data *api_add_escape(struct api_data *root, char *name, char *data, bool copy_data); +extern struct api_data *api_add_string(struct api_data *root, char *name, char *data, bool copy_data); +extern struct api_data *api_add_const(struct api_data *root, char *name, const char *data, bool copy_data); +extern struct api_data *api_add_uint8(struct api_data *root, char *name, uint8_t *data, bool copy_data); +extern struct api_data *api_add_uint16(struct api_data *root, char *name, uint16_t *data, bool copy_data); +extern struct api_data *api_add_int(struct api_data *root, char *name, int *data, bool copy_data); +extern struct api_data *api_add_uint(struct api_data *root, char *name, unsigned int *data, bool copy_data); +extern struct api_data *api_add_uint32(struct api_data *root, char *name, uint32_t *data, bool copy_data); +extern struct api_data *api_add_hex32(struct api_data *root, char *name, uint32_t *data, bool copy_data); +extern struct api_data *api_add_uint64(struct api_data *root, char *name, uint64_t *data, bool copy_data); +extern struct api_data *api_add_double(struct api_data *root, char *name, double *data, bool copy_data); +extern struct api_data *api_add_elapsed(struct api_data *root, char *name, double *data, bool copy_data); +extern struct api_data *api_add_bool(struct api_data *root, char *name, bool *data, bool copy_data); +extern struct api_data *api_add_timeval(struct api_data *root, char *name, struct timeval *data, bool copy_data); +extern struct api_data *api_add_time(struct api_data *root, char *name, time_t *data, bool copy_data); +extern struct api_data *api_add_mhs(struct api_data *root, char *name, double *data, bool copy_data); +extern struct api_data *api_add_khs(struct api_data *root, char *name, double *data, bool copy_data); +extern struct api_data *api_add_mhtotal(struct api_data *root, char *name, double *data, bool copy_data); +extern struct api_data *api_add_temp(struct api_data *root, char *name, float *data, bool copy_data); +extern struct api_data *api_add_utility(struct api_data *root, char *name, double *data, bool copy_data); +extern struct api_data *api_add_freq(struct api_data *root, char *name, double *data, bool copy_data); +extern struct api_data *api_add_volts(struct api_data *root, char *name, float *data, bool copy_data); +extern struct api_data *api_add_hs(struct api_data *root, char *name, double *data, bool copy_data); +extern struct api_data *api_add_diff(struct api_data *root, char *name, double *data, bool copy_data); +extern struct api_data *api_add_percent(struct api_data *root, char *name, double *data, bool copy_data); +extern struct api_data *api_add_avg(struct api_data *root, char *name, float *data, bool copy_data); +extern struct api_data *print_data(struct api_data *root, char *buf, bool isjson, bool precom); #define SOCKBUFALLOCSIZ 65536 diff --git a/config_parser.c b/config_parser.c index 9d26b538..57e85bd6 100644 --- a/config_parser.c +++ b/config_parser.c @@ -90,6 +90,31 @@ static struct profile *add_profile() return profile; } +static void remove_profile(struct profile *profile) +{ + int i; + int found = 0; + + for(i = 0; i < (total_profiles - 1); i++) + { + //look for the profile + if(profiles[i]->profile_no == profile->profile_no) + found = 1; + + //once we found the profile, change the current index profile to next + if(found) + { + profiles[i] = profiles[i+1]; + profiles[i]->profile_no = i; + } + } + + //give the profile an invalid number and remove + profile->profile_no = total_profiles; + profile->removed = true; + total_profiles--; +} + //only used while loading config static struct profile *get_current_profile() { @@ -1931,3 +1956,250 @@ void write_config(const char *filename) json_dump_file(config, filename, JSON_PRESERVE_ORDER|JSON_INDENT(4)); } + +/********************************************* + * API functions + * *******************************************/ +//profile parameters +enum { + PR_ALGORITHM, + PR_NFACTOR, + PR_LOOKUPGAP, + PR_DEVICES, + PR_INTENSITY, + PR_XINTENSITY, + PR_RAWINTENSITY, + PR_GPUENGINE, + PR_GPUMEMCLOCK, + PR_GPUTHREADS, + PR_GPUFAN, + PR_GPUPOWERTUNE, + PR_GPUVDDC, + PR_SHADERS, + PR_TC, + PR_WORKSIZE +}; + +void api_profile_list(struct io_data *io_data, __maybe_unused SOCKETTYPE c, __maybe_unused char *param, bool isjson, __maybe_unused char group) +{ + struct api_data *root = NULL; + struct profile *profile; + char buf[TMPBUFSIZ]; + bool io_open = false; + bool b; + int i; + + if (total_profiles == 0) + { + message(io_data, MSG_NOPROFILE, 0, NULL, isjson); + return; + } + + message(io_data, MSG_PROFILE, 0, NULL, isjson); + + if (isjson) + io_open = io_add(io_data, COMSTR JSON_PROFILES); + + for (i = 0; i <= total_profiles; i++) + { + //last profile is the default profile + if(i == total_profiles) + profile = &default_profile; + else + profile = profiles[i]; + + //if default profile name is profile name or loop index is beyond the last profile, then it is the default profile + b = (((i == total_profiles) || (!strcasecmp(default_profile.name, profile->name)))?true:false); + + root = api_add_int(root, "PROFILE", &i, false); + root = api_add_escape(root, "Name", profile->name, true); + root = api_add_bool(root, "IsDefault", &b, false); + root = api_add_escape(root, "Algorithm", (char *)profile->algorithm.name, true); + root = api_add_int(root, "NFactor", (int *)&profile->algorithm.nfactor, false); + root = api_add_escape(root, "LookupGap", (char *)profile->lookup_gap, true); + root = api_add_escape(root, "Devices", (char *)profile->devices, true); + root = api_add_escape(root, "Intensity", (char *)profile->intensity, true); + root = api_add_escape(root, "XIntensity", (char *)profile->xintensity, true); + root = api_add_escape(root, "RawIntensity", (char *)profile->rawintensity, true); + root = api_add_escape(root, "Gpu Engine", (char *)profile->gpu_engine, true); + root = api_add_escape(root, "Gpu MemClock", (char *)profile->gpu_memclock, true); + root = api_add_escape(root, "Gpu Threads", (char *)profile->gpu_threads, true); + root = api_add_escape(root, "Gpu Fan%", (char *)profile->gpu_fan, true); + root = api_add_escape(root, "Gpu Powertune%", (char *)profile->gpu_powertune, true); + root = api_add_escape(root, "Gpu Vddc", (char *)profile->gpu_vddc, true); + root = api_add_escape(root, "Shaders", (char *)profile->shaders, true); + root = api_add_escape(root, "Thread Concurrency", (char *)profile->thread_concurrency, true); + root = api_add_escape(root, "Worksize", (char *)profile->worksize, true); + + root = print_data(root, buf, isjson, isjson && (i > 0)); + io_add(io_data, buf); + } + + if (isjson && io_open) + io_close(io_data); +} + +void api_profile_add(struct io_data *io_data, __maybe_unused SOCKETTYPE c, char *param, bool isjson, __maybe_unused char group) +{ + char *p; + char *split_str; + struct profile *profile; + int idx; + + split_str = strdup(param); + + //split all params by colon (:) because the comma (,) can be used in some of those parameters + if((p = strsep(&split_str, ":"))) + { + //get name first and see if the profile already exists + if((profile = get_profile(p))) + { + message(io_data, MSG_PROFILEEXIST, 0, p, isjson); + return; + } + + //doesnt exist, create new profile + profile = add_profile(); + + //assign name + profile->name = strdup(p); + + //get other parameters + idx = 0; + while((p = strsep(&split_str, ":")) != NULL) + { + switch(idx) + { + case PR_ALGORITHM: + set_algorithm(&profile->algorithm, p); + break; + case PR_NFACTOR: + if(!empty_string(p)) + set_algorithm_nfactor(&profile->algorithm, (const uint8_t)atoi(p)); + break; + case PR_LOOKUPGAP: + if(!empty_string(p)) + profile->lookup_gap = strdup(p); + break; + case PR_DEVICES: + if(!empty_string(p)) + profile->devices = strdup(p); + break; + case PR_INTENSITY: + if(!empty_string(p)) + profile->intensity = strdup(p); + break; + case PR_XINTENSITY: + if(!empty_string(p)) + profile->xintensity = strdup(p); + break; + case PR_RAWINTENSITY: + if(!empty_string(p)) + profile->rawintensity = strdup(p); + break; + case PR_GPUENGINE: + if(!empty_string(p)) + profile->gpu_engine = strdup(p); + break; + case PR_GPUMEMCLOCK: + if(!empty_string(p)) + profile->gpu_memclock = strdup(p); + break; + case PR_GPUTHREADS: + if(!empty_string(p)) + profile->gpu_threads = strdup(p); + break; + case PR_GPUFAN: + if(!empty_string(p)) + profile->gpu_fan = strdup(p); + break; + case PR_GPUPOWERTUNE: + if(!empty_string(p)) + profile->gpu_powertune = strdup(p); + break; + case PR_GPUVDDC: + if(!empty_string(p)) + profile->gpu_vddc = strdup(p); + break; + case PR_SHADERS: + if(!empty_string(p)) + profile->shaders = strdup(p); + break; + case PR_TC: + if(!empty_string(p)) + profile->thread_concurrency = strdup(p); + break; + case PR_WORKSIZE: + if(!empty_string(p)) + profile->worksize = strdup(p); + break; + default: + //invalid option ignore + break; + } + + idx++; + } + } + else + { + message(io_data, MSG_MISPRD, 0, NULL, isjson); + return; + } + + message(io_data, MSG_ADDPROFILE, 0, profile->name, isjson); +} + +void api_profile_remove(struct io_data *io_data, __maybe_unused SOCKETTYPE c, char *param, bool isjson, __maybe_unused char group) +{ + struct profile *profile; + struct pool *pool; + int i; + + //no profiles, nothing to remove + if (total_profiles == 0) + { + message(io_data, MSG_NOPROFILE, 0, NULL, isjson); + return; + } + + //make sure profile name is supplied + if(param == NULL || *param == '\0') + { + message(io_data, MSG_MISPRID, 0, NULL, isjson); + return; + } + + //see if the profile exists + if(!(profile = get_profile(param))) + { + message(io_data, MSG_PRNOEXIST, 0, param, isjson); + return; + } + + //next make sure it's not the default profile + if(!strcasecmp(default_profile.name, profile->name)) + { + message(io_data, MSG_PRISDEFAULT, 0, param, isjson); + return; + } + + //make sure no pools use it + for(i = 0;i < total_pools; i++) + { + pool = pools[i]; + + if(!strcasecmp(pool->profile, profile->name)) + { + message(io_data, MSG_PRINUSE, 0, param, isjson); + return; + } + } + + //all set, delete the profile + remove_profile(profile); + + message(io_data, MSG_REMPROFILE, profile->profile_no, profile->name, isjson); + + free(profile); +} diff --git a/config_parser.h b/config_parser.h index 8926546e..0c3309ed 100644 --- a/config_parser.h +++ b/config_parser.h @@ -4,6 +4,7 @@ #include "config.h" #include "miner.h" +#include "api.h" #include "algorithm.h" //helper to check for empty or NULL strings @@ -20,6 +21,7 @@ struct profile { int profile_no; char *name; + bool removed; algorithm_t algorithm; const char *devices; @@ -48,6 +50,8 @@ extern bool config_loaded; extern int json_array_index; extern struct profile default_profile; +extern struct profile **profiles; +extern int total_profiles; /* option parser functions */ extern char *set_default_devices(const char *arg); @@ -103,4 +107,9 @@ extern void apply_pool_profile(struct pool *pool); /* config writer */ extern void write_config(const char *filename); +/* API functions */ +extern void api_profile_list(struct io_data *io_data, __maybe_unused SOCKETTYPE c, __maybe_unused char *param, bool isjson, __maybe_unused char group); +extern void api_profile_add(struct io_data *io_data, __maybe_unused SOCKETTYPE c, char *param, bool isjson, __maybe_unused char group); +extern void api_profile_remove(struct io_data *io_data, __maybe_unused SOCKETTYPE c, char *param, bool isjson, __maybe_unused char group); + #endif // CONFIG_PARSER_H diff --git a/doc/API.md b/doc/API.md index e6b12806..67319795 100644 --- a/doc/API.md +++ b/doc/API.md @@ -234,7 +234,7 @@ The list of requests - a (*) means it requires privileged access - and replies: stating the results of removing pool N The Msg includes the pool URL N.B. all details for the pool will be lost - + changestrategy|STRAT,INT (*) none There is no reply section just the STATUS section stating the results of changing multipool strategy @@ -242,7 +242,23 @@ The list of requests - a (*) means it requires privileged access - and replies: the interval INT must be specified as a number between 0 and 9999 seconds. INT is not required otherwise. - gpuenable|N (*) +addprofile|NAME:ALGORITHM:NFACTOR:LOOKUPGAP:DEVICE:INTENSITY:XINTENSITY:RAWINTENSITY:GPUENGINE:GPUMEMCLOCK + :GPUTHREADS:GPUFAN:GPUPOWERTUNE:GPUVDDC:SHADERS:THREADCONCURRENCY:WORKSIZE (*) + none There is no reply section just the STATUS section + stating the results of attempting to add profile NAME + The Msg includes the profile NAME. Parameters NAME and + ALGORITHM are required. Everything else is optional. + Note that these parameters are colon (:) delimited. + +removeprofile|NAME (*) + none There is no reply section just the STATUS section + stating the results of removing profile NAME. + The Msg includes the profile NAME. The profile NAME + must exist and not be in use by any of the pools or + as default profile. + N.B. all details for the profile will be lost + +gpuenable|N (*) none There is no reply section just the STATUS section stating the results of the enable request @@ -543,6 +559,19 @@ Modified API commands: ---------- +API V4.0 (sgminer v5.0) + +Modified API command: + 'addpool' - supports profile and algorithm is correctly set to default if none is selected +Added API commands: + 'changestrategy' - change multi pool strategy on the fly from API + 'changepoolprofile' - change pool profile + 'addprofile' - add a new profile + 'removeprofile' - removes a profile + 'profiles' - list profiles + +---------- + API V3.1 (cgminer v3.12.1) Multiple report request command with '+' e.g. summary+devs