Browse Source

Merge branch 'config-parser' into v5_0

djm34
Noel Maersk 10 years ago
parent
commit
0886740a5f
  1. 19
      AUTHORS.md
  2. 3
      Makefile.am
  3. 18
      NEWS.md
  4. 2
      adl.c
  5. 1
      adl.h
  6. 593
      api.c
  7. 398
      api.h
  8. 2029
      config_parser.c
  9. 122
      config_parser.h
  10. 448
      doc/API.md
  11. 0
      doc/GPU.md
  12. 2187
      doc/configuration.md
  13. 161
      example.conf
  14. 59
      miner.h
  15. 1013
      sgminer.c

19
AUTHORS.md

@ -2,12 +2,19 @@ @@ -2,12 +2,19 @@
## Core
* Multiple algorithms and switching: Jan Berdajs <mrbrdo at mrbrdo dot net> 15bULC8snaKAMeFb3xBmmhbWj1xyTmBUfm
* Historical scrypt-only refactor: Noel Maersk <veox at wemakethings dot net> 12jF1VExtmmMu8D36vo4Y4CYqLK5yCtLC4
* Core: Martin Danielsen <kalroth {at} gmail _dot_ com> 1DNBcSEENBwDKrcTyTW61ezWhzsPy5imkn
* Jan Berdajs <mrbrdo at mrbrdo dot net> 15bULC8snaKAMeFb3xBmmhbWj1xyTmBUfm
* Noel Maersk <veox at wemakethings dot net> 12jF1VExtmmMu8D36vo4Y4CYqLK5yCtLC4
* troky <troky2001 at yahoo dot com> Letoqz4yEnJxjWw9B7Ysn8h9VDQTMDnT29
* ystarnaud <**FIXME**>
* lasybear <**FIXME**>
* Luke Dashjr <luke-jr+cgminer @at@ utopios .dot. org> 1QATWksNFGeUJCWBrN4g6hGM178Lovm7Wh
* Andrew Smith <kan0i {at} kano-kun [dot] net> 1Jjk2LmktEQKnv8r2cZ9MvLiZwZ9gxabKm
## Core (history)
* Core: Con Kolivas <kernel [at] kolivas {dot} org> 15qSxP1SQcUX3o4nhkfdbgyoWEFMomJ4rZ
* Core: Luke Dashjr <luke-jr+cgminer @at@ utopios .dot. org> 1QATWksNFGeUJCWBrN4g6hGM178Lovm7Wh
* API: Andrew Smith <kan0i {at} kano-kun [dot] net> 1Jjk2LmktEQKnv8r2cZ9MvLiZwZ9gxabKm
* Martin Danielsen <kalroth {at} gmail _dot_ com> 1DNBcSEENBwDKrcTyTW61ezWhzsPy5imkn
## Cross-platform support
@ -21,6 +28,8 @@ @@ -21,6 +28,8 @@
## OpenCL kernels
**FIXME**: this section is outdated.
All current kernels are based on `scrypt`, originally by Colin Percival,
updated by many others.

3
Makefile.am

@ -32,7 +32,7 @@ sgminer_CPPFLAGS += -DGIT_VERSION=\"$(GIT_VERSION)\" @@ -32,7 +32,7 @@ sgminer_CPPFLAGS += -DGIT_VERSION=\"$(GIT_VERSION)\"
endif
sgminer_SOURCES := sgminer.c
sgminer_SOURCES += api.c
sgminer_SOURCES += api.c api.h
sgminer_SOURCES += elist.h miner.h compat.h bench_block.h
sgminer_SOURCES += util.c util.h uthash.h
sgminer_SOURCES += logging.c logging.h
@ -42,6 +42,7 @@ sgminer_SOURCES += findnonce.c findnonce.h @@ -42,6 +42,7 @@ sgminer_SOURCES += findnonce.c findnonce.h
sgminer_SOURCES += adl.c adl.h adl_functions.h
sgminer_SOURCES += pool.c pool.h
sgminer_SOURCES += algorithm.c algorithm.h
sgminer_SOURCES += config_parser.c config_parser.h
sgminer_SOURCES += ocl/patch_kernel.c ocl/patch_kernel.h
sgminer_SOURCES += ocl/build_kernel.c ocl/build_kernel.h
sgminer_SOURCES += ocl/binary_kernel.c ocl/binary_kernel.h

18
NEWS.md

@ -4,11 +4,19 @@ @@ -4,11 +4,19 @@
* Added support for animecoin, darkcoin, fuguecoin, groestlcoin, inkcoin,
marucoin, myriadcoin-groestl, quarkcoin, qubitcoin, sifcoin, twecoin,
darkcoin-mod ("X11-mod"), marucoin-mod ("X13-mod"), maxcoin (by mrbrdo).
* intensity, xintensity, rawintensity, gpu-memclock, gpu-engine,
thread-concurrency, gpu-threads now also have a `pool-*` version to
configure them for each pool separately (by mrbrdo).
* Extranonce support for stratum (by bitbandi).
darkcoin-mod ("X11-mod"), marucoin-mod ("X13-mod"), maxcoin (by
_mrbrdo_).
* `intensity`, `xintensity`, `rawintensity`, `gpu-memclock`,
`gpu-engine`, `thread-concurrency`, `gpu-threads` now also have a
`pool-*` version to configure them for each pool separately
(by _mrbrdo_).
* Initial configuration system revamping (by _ystarnaud_).
* Algorithm profile configuration (by _ystarnaud_).
* Complete configuration documentation, see `doc/configuration.md` (by
_ystarnaud_).
* API documentation update, see `doc/API.md` (by _ystarnaud_).
* Extranonce support for stratum (by _bitbandi_).
## Version 4.2.1 - 22nd May 2014

2
adl.c

@ -1208,7 +1208,7 @@ int set_fanspeed(int gpu, int iFanSpeed) @@ -1208,7 +1208,7 @@ int set_fanspeed(int gpu, int iFanSpeed)
}
#ifdef HAVE_CURSES
static int set_powertune(int gpu, int iPercentage)
int set_powertune(int gpu, int iPercentage)
{
struct gpu_adl *ga;
int dummy, ret = 1;

1
adl.h

@ -15,6 +15,7 @@ float gpu_vddc(int gpu); @@ -15,6 +15,7 @@ float gpu_vddc(int gpu);
int gpu_activity(int gpu);
int gpu_fanspeed(int gpu);
int gpu_fanpercent(int gpu);
extern int set_powertune(int gpu, int iPercentage);
bool gpu_stats(int gpu, float *temp, int *engineclock, int *memclock, float *vddc,
int *activity, int *fanspeed, int *fanpercent, int *powertune);
void change_gpusettings(int gpu);

593
api.c

@ -26,77 +26,17 @@ @@ -26,77 +26,17 @@
#include <sys/types.h>
#include "compat.h"
#include "api.h"
#include "miner.h"
#include "pool.h"
#include "util.h"
#include "pool.h"
// BUFSIZ varies on Windows and Linux
#define TMPBUFSIZ 8192
#include "config_parser.h"
// Number of requests to queue - normally would be small
#define QUEUE 100
#if defined WIN32
#ifdef WIN32
static char WSAbuf[1024];
struct WSAERRORS {
int id;
char *code;
} WSAErrors[] = {
{ 0, "No error" },
{ WSAEINTR, "Interrupted system call" },
{ WSAEBADF, "Bad file number" },
{ WSAEACCES, "Permission denied" },
{ WSAEFAULT, "Bad address" },
{ WSAEINVAL, "Invalid argument" },
{ WSAEMFILE, "Too many open sockets" },
{ WSAEWOULDBLOCK, "Operation would block" },
{ WSAEINPROGRESS, "Operation now in progress" },
{ WSAEALREADY, "Operation already in progress" },
{ WSAENOTSOCK, "Socket operation on non-socket" },
{ WSAEDESTADDRREQ, "Destination address required" },
{ WSAEMSGSIZE, "Message too long" },
{ WSAEPROTOTYPE, "Protocol wrong type for socket" },
{ WSAENOPROTOOPT, "Bad protocol option" },
{ WSAEPROTONOSUPPORT, "Protocol not supported" },
{ WSAESOCKTNOSUPPORT, "Socket type not supported" },
{ WSAEOPNOTSUPP, "Operation not supported on socket" },
{ WSAEPFNOSUPPORT, "Protocol family not supported" },
{ WSAEAFNOSUPPORT, "Address family not supported" },
{ WSAEADDRINUSE, "Address already in use" },
{ WSAEADDRNOTAVAIL, "Can't assign requested address" },
{ WSAENETDOWN, "Network is down" },
{ WSAENETUNREACH, "Network is unreachable" },
{ WSAENETRESET, "Net connection reset" },
{ WSAECONNABORTED, "Software caused connection abort" },
{ WSAECONNRESET, "Connection reset by peer" },
{ WSAENOBUFS, "No buffer space available" },
{ WSAEISCONN, "Socket is already connected" },
{ WSAENOTCONN, "Socket is not connected" },
{ WSAESHUTDOWN, "Can't send after socket shutdown" },
{ WSAETOOMANYREFS, "Too many references, can't splice" },
{ WSAETIMEDOUT, "Connection timed out" },
{ WSAECONNREFUSED, "Connection refused" },
{ WSAELOOP, "Too many levels of symbolic links" },
{ WSAENAMETOOLONG, "File name too long" },
{ WSAEHOSTDOWN, "Host is down" },
{ WSAEHOSTUNREACH, "No route to host" },
{ WSAENOTEMPTY, "Directory not empty" },
{ WSAEPROCLIM, "Too many processes" },
{ WSAEUSERS, "Too many users" },
{ WSAEDQUOT, "Disc quota exceeded" },
{ WSAESTALE, "Stale NFS file handle" },
{ WSAEREMOTE, "Too many levels of remote in path" },
{ WSASYSNOTREADY, "Network system is unavailable" },
{ WSAVERNOTSUPPORTED, "Winsock version out of range" },
{ WSANOTINITIALISED, "WSAStartup not yet called" },
{ WSAEDISCON, "Graceful shutdown in progress" },
{ WSAHOST_NOT_FOUND, "Host not found" },
{ WSANO_DATA, "No host data of that type was found" },
{ -1, "Unknown error code" }
};
char *WSAErrorMsg(void) {
int i;
int id = WSAGetLastError();
@ -112,236 +52,8 @@ char *WSAErrorMsg(void) { @@ -112,236 +52,8 @@ char *WSAErrorMsg(void) {
}
#endif
static const char *UNAVAILABLE = " - API will not be available";
static const char *MUNAVAILABLE = " - API multicast listener will not be available";
static const char *BLANK = "";
static const char *COMMA = ",";
#define COMSTR ","
static const char SEPARATOR = '|';
#define SEPSTR "|"
static const char GPUSEP = ',';
#define CMDJOIN '+'
#define JOIN_CMD "CMD="
#define BETWEEN_JOIN SEPSTR
static const char *APIVERSION = "3.2";
static const char *DEAD = "Dead";
static const char *SICK = "Sick";
static const char *NOSTART = "NoStart";
static const char *INIT = "Initialising";
static const char *DISABLED = "Disabled";
static const char *ALIVE = "Alive";
static const char *REJECTING = "Rejecting";
static const char *UNKNOWN = "Unknown";
#define _DYNAMIC "D"
static const char *DYNAMIC = _DYNAMIC;
static __maybe_unused const char *NONE = "None";
static const char *YES = "Y";
static const char *NO = "N";
static const char *NULLSTR = "(null)";
static const char *TRUESTR = "true";
static const char *FALSESTR = "false";
static const char *DEVICECODE = "GPU ";
static const char *OSINFO =
#if defined(__linux__)
"Linux";
#elif defined(__APPLE__)
"Apple";
#elif defined(WIN32)
"Windows";
#elif defined(__CYGWIN__)
"Cygwin";
#elif defined(__unix__)
"Unix";
#else
"Unknown";
#endif
#define _DEVS "DEVS"
#define _POOLS "POOLS"
#define _SUMMARY "SUMMARY"
#define _STATUS "STATUS"
#define _VERSION "VERSION"
#define _MINECONFIG "CONFIG"
#define _GPU "GPU"
#define _GPUS "GPUS"
#define _NOTIFY "NOTIFY"
#define _DEVDETAILS "DEVDETAILS"
#define _BYE "BYE"
#define _RESTART "RESTART"
#define _MINESTATS "STATS"
#define _CHECK "CHECK"
#define _MINECOIN "COIN"
#define _DEBUGSET "DEBUG"
#define _SETCONFIG "SETCONFIG"
static const char ISJSON = '{';
#define JSON0 "{"
#define JSON1 "\""
#define JSON2 "\":["
#define JSON3 "]"
#define JSON4 ",\"id\":1"
// If anyone cares, id=0 for truncated output
#define JSON4_TRUNCATED ",\"id\":0"
#define JSON5 "}"
#define JSON_START JSON0
#define JSON_DEVS JSON1 _DEVS JSON2
#define JSON_POOLS JSON1 _POOLS JSON2
#define JSON_SUMMARY JSON1 _SUMMARY JSON2
#define JSON_STATUS JSON1 _STATUS JSON2
#define JSON_VERSION JSON1 _VERSION JSON2
#define JSON_MINECONFIG JSON1 _MINECONFIG JSON2
#define JSON_GPU JSON1 _GPU JSON2
#define JSON_GPUS JSON1 _GPUS JSON2
#define JSON_NOTIFY JSON1 _NOTIFY JSON2
#define JSON_DEVDETAILS JSON1 _DEVDETAILS JSON2
#define JSON_CLOSE JSON3
#define JSON_MINESTATS JSON1 _MINESTATS JSON2
#define JSON_CHECK JSON1 _CHECK JSON2
#define JSON_MINECOIN JSON1 _MINECOIN JSON2
#define JSON_DEBUGSET JSON1 _DEBUGSET JSON2
#define JSON_SETCONFIG JSON1 _SETCONFIG JSON2
#define JSON_END JSON4 JSON5
#define JSON_END_TRUNCATED JSON4_TRUNCATED JSON5
#define JSON_BETWEEN_JOIN ","
static const char *JSON_COMMAND = "command";
static const char *JSON_PARAMETER = "parameter";
#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
#define MSG_MISID 15
#define MSG_GPUDEV 17
#define MSG_NUMGPU 20
#define MSG_VERSION 22
#define MSG_INVJSON 23
#define MSG_MISCMD 24
#define MSG_MISPID 25
#define MSG_INVPID 26
#define MSG_SWITCHP 27
#define MSG_MISVAL 28
#define MSG_NOADL 29
#define MSG_NOGPUADL 30
#define MSG_INVINT 31
#define MSG_GPUINT 32
#define MSG_MINECONFIG 33
#define MSG_GPUMERR 34
#define MSG_GPUMEM 35
#define MSG_GPUEERR 36
#define MSG_GPUENG 37
#define MSG_GPUVERR 38
#define MSG_GPUVDDC 39
#define MSG_GPUFERR 40
#define MSG_GPUFAN 41
#define MSG_MISFN 42
#define MSG_BADFN 43
#define MSG_SAVED 44
#define MSG_ACCDENY 45
#define MSG_ACCOK 46
#define MSG_ENAPOOL 47
#define MSG_DISPOOL 48
#define MSG_ALRENAP 49
#define MSG_ALRDISP 50
#define MSG_MISPDP 52
#define MSG_INVPDP 53
#define MSG_TOOMANYP 54
#define MSG_ADDPOOL 55
#define MSG_NOTIFY 60
#define MSG_REMLASTP 66
#define MSG_ACTPOOL 67
#define MSG_REMPOOL 68
#define MSG_DEVDETAILS 69
#define MSG_MINESTATS 70
#define MSG_MISCHK 71
#define MSG_CHECK 72
#define MSG_POOLPRIO 73
#define MSG_DUPPID 74
#define MSG_MISBOOL 75
#define MSG_INVBOOL 76
#define MSG_FOO 77
#define MSG_MINECOIN 78
#define MSG_DEBUGSET 79
#define MSG_SETCONFIG 82
#define MSG_UNKCON 83
#define MSG_INVNUM 84
#define MSG_CONPAR 85
#define MSG_CONVAL 86
#define MSG_NOUSTA 88
#define MSG_ZERMIS 94
#define MSG_ZERINV 95
#define MSG_ZERSUM 96
#define MSG_ZERNOSUM 97
#define MSG_BYE 0x101
#define MSG_INVNEG 121
#define MSG_SETQUOTA 122
#define MSG_LOCKOK 123
#define MSG_LOCKDIS 124
enum code_severity {
SEVERITY_ERR,
SEVERITY_WARN,
SEVERITY_INFO,
SEVERITY_SUCC,
SEVERITY_FAIL
};
enum code_parameters {
PARAM_GPU,
PARAM_PID,
PARAM_GPUMAX,
PARAM_PMAX,
PARAM_POOLMAX,
// Single generic case: have the code resolve it - see below
PARAM_DMAX,
PARAM_CMD,
PARAM_POOL,
PARAM_STR,
PARAM_BOTH,
PARAM_BOOL,
PARAM_SET,
PARAM_INT,
PARAM_NONE
};
struct CODES {
const enum code_severity severity;
const int code;
const enum code_parameters params;
const char *description;
} codes[] = {
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" },
@ -424,10 +136,78 @@ struct CODES { @@ -424,10 +136,78 @@ struct CODES {
{ 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_CHPOOLPR, PARAM_BOTH, "Changed pool %d to profile '%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";
static const char *BLANK = "";
static const char *COMMA = ",";
static const char SEPARATOR = '|';
static const char GPUSEP = ',';
static const char *APIVERSION = "4.0";
static const char *DEAD = "Dead";
static const char *SICK = "Sick";
static const char *NOSTART = "NoStart";
static const char *INIT = "Initialising";
static const char *DISABLED = "Disabled";
static const char *ALIVE = "Alive";
static const char *REJECTING = "Rejecting";
static const char *UNKNOWN = "Unknown";
static const char *DYNAMIC = _DYNAMIC;
static __maybe_unused const char *NONE = "None";
static const char *YES = "Y";
static const char *NO = "N";
static const char *NULLSTR = "(null)";
static const char *TRUESTR = "true";
static const char *FALSESTR = "false";
static const char *DEVICECODE = "GPU ";
static const char *OSINFO =
#if defined(__linux__)
"Linux";
#elif defined(__APPLE__)
"Apple";
#elif defined(WIN32)
"Windows";
#elif defined(__CYGWIN__)
"Cygwin";
#elif defined(__unix__)
"Unix";
#else
"Unknown";
#endif
static const char *JSON_COMMAND = "command";
static const char *JSON_PARAMETER = "parameter";
static const char ISJSON = '{';
static const char *localaddr = "127.0.0.1";
static int my_thr_id = 0;
@ -441,50 +221,11 @@ static bool do_a_restart; @@ -441,50 +221,11 @@ static bool do_a_restart;
static time_t when = 0; // when the request occurred
struct IP4ACCESS {
in_addr_t ip;
in_addr_t mask;
char group;
};
#define GROUP(g) (toupper(g))
#define PRIVGROUP GROUP('W')
#define NOPRIVGROUP GROUP('R')
#define ISPRIVGROUP(g) (GROUP(g) == PRIVGROUP)
#define GROUPOFFSET(g) (GROUP(g) - GROUP('A'))
#define VALIDGROUP(g) (GROUP(g) >= GROUP('A') && GROUP(g) <= GROUP('Z'))
#define COMMANDS(g) (apigroups[GROUPOFFSET(g)].commands)
#define DEFINEDGROUP(g) (ISPRIVGROUP(g) || COMMANDS(g) != NULL)
struct APIGROUPS {
// This becomes a string like: "|cmd1|cmd2|cmd3|" so it's quick to search
char *commands;
} apigroups['Z' - 'A' + 1]; // only A=0 to Z=25 (R: noprivs, W: allprivs)
static struct IP4ACCESS *ipaccess = NULL;
static int ips = 0;
struct io_data {
size_t siz;
char *ptr;
char *cur;
bool sock;
bool close;
};
struct io_list {
struct io_data *io_data;
struct io_list *prev;
struct io_list *next;
};
static struct io_list *io_head = NULL;
#define SOCKBUFALLOCSIZ 65536
#define io_new(init) _io_new(init, false)
#define sock_io_new() _io_new(SOCKBUFALLOCSIZ, true)
static void io_reinit(struct io_data *io_data)
{
io_data->cur = io_data->ptr;
@ -521,7 +262,7 @@ static struct io_data *_io_new(size_t initial, bool socket_buf) @@ -521,7 +262,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;
@ -547,12 +288,12 @@ static bool io_add(struct io_data *io_data, char *buf) @@ -547,12 +288,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;
@ -902,7 +643,7 @@ struct api_data *api_add_avg(struct api_data *root, char *name, float *data, boo @@ -902,7 +643,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;
@ -1045,7 +786,7 @@ static struct api_data *print_data(struct api_data *root, char *buf, bool isjson @@ -1045,7 +786,7 @@ static struct api_data *print_data(struct api_data *root, char *buf, bool isjson
// All replies (except BYE and RESTART) start with a message
// thus for JSON, message() inserts JSON_START at the front
// and send_result() adds JSON_END at the end
static void message(struct io_data *io_data, int messageid, int paramid, char *param2, bool isjson)
void message(struct io_data *io_data, int messageid, int paramid, char *param2, bool isjson)
{
struct api_data *root = NULL;
char buf[TMPBUFSIZ];
@ -1091,6 +832,9 @@ static void message(struct io_data *io_data, int messageid, int paramid, char *p @@ -1091,6 +832,9 @@ static void message(struct io_data *io_data, int messageid, int paramid, char *p
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;
@ -1147,49 +891,6 @@ static void message(struct io_data *io_data, int messageid, int paramid, char *p @@ -1147,49 +891,6 @@ static void message(struct io_data *io_data, int messageid, int paramid, char *p
#if LOCK_TRACKING
#define LOCK_FMT_FFL " - called from %s %s():%d"
#define LOCKMSG(fmt, ...) fprintf(stderr, "APILOCK: " fmt "\n", ##__VA_ARGS__)
#define LOCKMSGMORE(fmt, ...) fprintf(stderr, " " fmt "\n", ##__VA_ARGS__)
#define LOCKMSGFFL(fmt, ...) fprintf(stderr, "APILOCK: " fmt LOCK_FMT_FFL "\n", ##__VA_ARGS__, file, func, linenum)
#define LOCKMSGFLUSH() fflush(stderr)
typedef struct lockstat {
uint64_t lock_id;
const char *file;
const char *func;
int linenum;
struct timeval tv;
} LOCKSTAT;
typedef struct lockline {
struct lockline *prev;
struct lockstat *stat;
struct lockline *next;
} LOCKLINE;
typedef struct lockinfo {
void *lock;
enum cglock_typ typ;
const char *file;
const char *func;
int linenum;
uint64_t gets;
uint64_t gots;
uint64_t tries;
uint64_t dids;
uint64_t didnts; // should be tries - dids
uint64_t unlocks;
LOCKSTAT lastgot;
LOCKLINE *lockgets;
LOCKLINE *locktries;
} LOCKINFO;
typedef struct locklist {
LOCKINFO *info;
struct locklist *next;
} LOCKLIST;
static uint64_t lock_id = 1;
static LOCKLIST *lockhead;
@ -1532,6 +1233,23 @@ void show_locks() @@ -1532,6 +1233,23 @@ void show_locks()
}
#endif
static void copyadvanceafter(char ch, char **param, char **buf)
{
#define src_p (*param)
#define dst_b (*buf)
while (*src_p && *src_p != ch) {
if (*src_p == '\\' && *(src_p+1) != '\0')
src_p++;
*(dst_b++) = *(src_p++);
}
if (*src_p)
src_p++;
*(dst_b++) = '\0';
}
static void lockstats(struct io_data *io_data, __maybe_unused SOCKETTYPE c, __maybe_unused char *param, bool isjson, __maybe_unused char group)
{
#if LOCK_TRACKING
@ -1822,6 +1540,7 @@ static void poolstatus(struct io_data *io_data, __maybe_unused SOCKETTYPE c, __m @@ -1822,6 +1540,7 @@ static void poolstatus(struct io_data *io_data, __maybe_unused SOCKETTYPE c, __m
root = api_add_string(root, "Name", get_pool_name(pool), true);
mutex_unlock(&pool->stratum_lock);
root = api_add_escape(root, "URL", pool->rpc_url, false);
root = api_add_string(root, "Profile", pool->profile, false);
root = api_add_string(root, "Algorithm", pool->algorithm.name, false);
root = api_add_string(root, "Description", pool->description, false);
root = api_add_string(root, "Status", status, false);
@ -2099,25 +1818,74 @@ static void switchpool(struct io_data *io_data, __maybe_unused SOCKETTYPE c, cha @@ -2099,25 +1818,74 @@ static void switchpool(struct io_data *io_data, __maybe_unused SOCKETTYPE c, cha
message(io_data, MSG_SWITCHP, id, NULL, isjson);
}
static void copyadvanceafter(char ch, char **param, char **buf)
static void api_pool_strategy(struct io_data *io_data, __maybe_unused SOCKETTYPE c, char *param, bool isjson, __maybe_unused char group)
{
#define src_p (*param)
#define dst_b (*buf)
char *p;
int strategy;
while (*src_p && *src_p != ch) {
if (*src_p == '\\' && *(src_p+1) != '\0')
src_p++;
if (total_pools == 0)
{
message(io_data, MSG_NOPOOL, 0, NULL, isjson);
return;
}
*(dst_b++) = *(src_p++);
if (param == NULL || *param == '\0')
{
message(io_data, MSG_MISSTRAT, 0, NULL, isjson);
return;
}
if (*src_p)
src_p++;
*(dst_b++) = '\0';
//get strategy in parameter 1
if(!(p = strtok(param, ",")))
{
message(io_data, MSG_MISSTRAT, 0, NULL, isjson);
return;
}
strategy = atoi(p);
//invalid strategy
if(strategy < 0 || strategy > TOP_STRATEGY)
{
message(io_data, MSG_INVSTRAT, strategy, NULL, isjson);
return;
}
//if set to rotate, get second param
if(strategy == POOL_ROTATE)
{
//if second param is missing then invalid
if(!(p = strtok(NULL, ",")))
{
message(io_data, MSG_MISSTRATINT, 0, NULL, isjson);
return;
}
//get interval in parameter 2
int interval;
interval = atoi(p);
//interval can only be between 0 and 9999
if(interval < 0 || interval > 9999)
{
message(io_data, MSG_INVNUM, interval, "interval", isjson);
return;
}
//set interval
opt_rotate_period = interval;
}
//set pool strategy
pool_strategy = (enum pool_strategy)strategy;
//initiate new strategy
switch_pools(NULL);
message(io_data, MSG_CHSTRAT, 0, (char *)strategies[strategy].s, isjson);
}
static bool pooldetails(char *param, char **url, char **user, char **pass,
char **name, char **desc, char **algo)
char **name, char **desc, char **profile, char **algo)
{
char *ptr, *buf;
@ -2132,23 +1900,28 @@ static bool pooldetails(char *param, char **url, char **user, char **pass, @@ -2132,23 +1900,28 @@ static bool pooldetails(char *param, char **url, char **user, char **pass,
*user = buf;
copyadvanceafter(',', &param, &buf);
if (!*param) // missing pass
if (!(*param)) // missing pass
goto exitsama;
*pass = buf;
copyadvanceafter(',', &param, &buf);
if (!*param) // missing name (allowed)
if (!(*param)) // missing name (allowed)
return true;
*name = buf;
copyadvanceafter(',', &param, &buf);
if (!*param) // missing desc
goto exitsama;
if (!(*param)) // missing desc
return true;
*desc = buf;
copyadvanceafter(',', &param, &buf);
if (!*param) // missing algo
goto exitsama;
if (!(*param)) // missing profile
return true;
*profile = buf;
copyadvanceafter(',', &param, &buf);
if (!(*param)) // missing algo
return true;
*algo = buf;
copyadvanceafter(',', &param, &buf);
@ -2163,7 +1936,7 @@ exitsama: @@ -2163,7 +1936,7 @@ exitsama:
static void addpool(struct io_data *io_data, __maybe_unused SOCKETTYPE c, char *param, bool isjson, __maybe_unused char group)
{
char *url, *user, *pass;
char *name = NULL, *desc = NULL, *algo = NULL;
char *name = NULL, *desc = NULL, *algo = NULL, *profile = NULL;
struct pool *pool;
char *ptr;
@ -2173,7 +1946,7 @@ static void addpool(struct io_data *io_data, __maybe_unused SOCKETTYPE c, char * @@ -2173,7 +1946,7 @@ static void addpool(struct io_data *io_data, __maybe_unused SOCKETTYPE c, char *
}
if (!pooldetails(param, &url, &user, &pass,
&name, &desc, &algo)) {
&name, &desc, &profile, &algo)) {
ptr = escape_string(param, isjson);
message(io_data, MSG_INVPDP, 0, ptr, isjson);
if (ptr != param)
@ -2183,13 +1956,14 @@ static void addpool(struct io_data *io_data, __maybe_unused SOCKETTYPE c, char * @@ -2183,13 +1956,14 @@ static void addpool(struct io_data *io_data, __maybe_unused SOCKETTYPE c, char *
}
/* If API client is old, it might not have provided all fields. */
if (name == NULL) name = strdup("");
if (desc == NULL) desc = strdup("");
if (algo == NULL) algo = strdup("scrypt"); // FIXME?
name = ((name == NULL)?strdup(""):name);
desc = ((desc == NULL)?strdup(""):desc);
profile = ((profile == NULL)?strdup(""):profile);
algo = ((algo == NULL)?strdup(""):algo);
pool = add_pool();
detect_stratum(pool, url);
add_pool_details(pool, true, url, user, pass, name, desc, algo);
add_pool_details(pool, true, url, user, pass, name, desc, profile, algo);
ptr = escape_string(url, isjson);
message(io_data, MSG_ADDPOOL, 0, ptr, isjson);
@ -2727,7 +2501,7 @@ static void devdetails(struct io_data *io_data, __maybe_unused SOCKETTYPE c, __m @@ -2727,7 +2501,7 @@ static void devdetails(struct io_data *io_data, __maybe_unused SOCKETTYPE c, __m
void dosave(struct io_data *io_data, __maybe_unused SOCKETTYPE c, char *param, bool isjson, __maybe_unused char group)
{
char filename[PATH_MAX];
FILE *fcfg;
// FILE *fcfg;
char *ptr;
if (param == NULL || *param == '\0') {
@ -2735,7 +2509,7 @@ void dosave(struct io_data *io_data, __maybe_unused SOCKETTYPE c, char *param, b @@ -2735,7 +2509,7 @@ void dosave(struct io_data *io_data, __maybe_unused SOCKETTYPE c, char *param, b
param = filename;
}
fcfg = fopen(param, "w");
/*fcfg = fopen(param, "w");
if (!fcfg) {
ptr = escape_string(param, isjson);
message(io_data, MSG_BADFN, 0, ptr, isjson);
@ -2743,10 +2517,10 @@ void dosave(struct io_data *io_data, __maybe_unused SOCKETTYPE c, char *param, b @@ -2743,10 +2517,10 @@ void dosave(struct io_data *io_data, __maybe_unused SOCKETTYPE c, char *param, b
free(ptr);
ptr = NULL;
return;
}
}*/
write_config(fcfg);
fclose(fcfg);
write_config(param);
//fclose(fcfg);
ptr = escape_string(param, isjson);
message(io_data, MSG_SAVED, 0, ptr, isjson);
@ -3062,6 +2836,7 @@ struct CMDS { @@ -3062,6 +2836,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 },
@ -3069,12 +2844,16 @@ struct CMDS { @@ -3069,12 +2844,16 @@ struct CMDS {
{ "gpu", gpudev, false, false },
{ "gpucount", gpucount, false, true },
{ "switchpool", switchpool, true, false },
{ "changestrategy", api_pool_strategy, true, false },
{ "addpool", addpool, true, false },
{ "poolpriority", poolpriority, true, false },
{ "poolquota", poolquota, true, false },
{ "enablepool", enablepool, true, false },
{ "disablepool", disablepool, true, false },
{ "removepool", removepool, true, false },
{ "changepoolprofile", api_pool_profile, 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 },

398
api.h

@ -0,0 +1,398 @@ @@ -0,0 +1,398 @@
#ifndef API_H
#define API_H
#include "config.h"
#include "miner.h"
// BUFSIZ varies on Windows and Linux
#define TMPBUFSIZ 8192
// Number of requests to queue - normally would be small
#define QUEUE 100
#ifdef WIN32
struct WSAERRORS {
int id;
char *code;
} WSAErrors[] = {
{ 0, "No error" },
{ WSAEINTR, "Interrupted system call" },
{ WSAEBADF, "Bad file number" },
{ WSAEACCES, "Permission denied" },
{ WSAEFAULT, "Bad address" },
{ WSAEINVAL, "Invalid argument" },
{ WSAEMFILE, "Too many open sockets" },
{ WSAEWOULDBLOCK, "Operation would block" },
{ WSAEINPROGRESS, "Operation now in progress" },
{ WSAEALREADY, "Operation already in progress" },
{ WSAENOTSOCK, "Socket operation on non-socket" },
{ WSAEDESTADDRREQ, "Destination address required" },
{ WSAEMSGSIZE, "Message too long" },
{ WSAEPROTOTYPE, "Protocol wrong type for socket" },
{ WSAENOPROTOOPT, "Bad protocol option" },
{ WSAEPROTONOSUPPORT, "Protocol not supported" },
{ WSAESOCKTNOSUPPORT, "Socket type not supported" },
{ WSAEOPNOTSUPP, "Operation not supported on socket" },
{ WSAEPFNOSUPPORT, "Protocol family not supported" },
{ WSAEAFNOSUPPORT, "Address family not supported" },
{ WSAEADDRINUSE, "Address already in use" },
{ WSAEADDRNOTAVAIL, "Can't assign requested address" },
{ WSAENETDOWN, "Network is down" },
{ WSAENETUNREACH, "Network is unreachable" },
{ WSAENETRESET, "Net connection reset" },
{ WSAECONNABORTED, "Software caused connection abort" },
{ WSAECONNRESET, "Connection reset by peer" },
{ WSAENOBUFS, "No buffer space available" },
{ WSAEISCONN, "Socket is already connected" },
{ WSAENOTCONN, "Socket is not connected" },
{ WSAESHUTDOWN, "Can't send after socket shutdown" },
{ WSAETOOMANYREFS, "Too many references, can't splice" },
{ WSAETIMEDOUT, "Connection timed out" },
{ WSAECONNREFUSED, "Connection refused" },
{ WSAELOOP, "Too many levels of symbolic links" },
{ WSAENAMETOOLONG, "File name too long" },
{ WSAEHOSTDOWN, "Host is down" },
{ WSAEHOSTUNREACH, "No route to host" },
{ WSAENOTEMPTY, "Directory not empty" },
{ WSAEPROCLIM, "Too many processes" },
{ WSAEUSERS, "Too many users" },
{ WSAEDQUOT, "Disc quota exceeded" },
{ WSAESTALE, "Stale NFS file handle" },
{ WSAEREMOTE, "Too many levels of remote in path" },
{ WSASYSNOTREADY, "Network system is unavailable" },
{ WSAVERNOTSUPPORTED, "Winsock version out of range" },
{ WSANOTINITIALISED, "WSAStartup not yet called" },
{ WSAEDISCON, "Graceful shutdown in progress" },
{ WSAHOST_NOT_FOUND, "Host not found" },
{ WSANO_DATA, "No host data of that type was found" },
{ -1, "Unknown error code" }
};
#endif
#define COMSTR ","
#define SEPSTR "|"
#define CMDJOIN '+'
#define JOIN_CMD "CMD="
#define BETWEEN_JOIN SEPSTR
#define _DYNAMIC "D"
#define _DEVS "DEVS"
#define _POOLS "POOLS"
#define _PROFILES "PROFILES"
#define _SUMMARY "SUMMARY"
#define _STATUS "STATUS"
#define _VERSION "VERSION"
#define _MINECONFIG "CONFIG"
#define _GPU "GPU"
#define _GPUS "GPUS"
#define _NOTIFY "NOTIFY"
#define _DEVDETAILS "DEVDETAILS"
#define _BYE "BYE"
#define _RESTART "RESTART"
#define _MINESTATS "STATS"
#define _CHECK "CHECK"
#define _MINECOIN "COIN"
#define _DEBUGSET "DEBUG"
#define _SETCONFIG "SETCONFIG"
#define JSON0 "{"
#define JSON1 "\""
#define JSON2 "\":["
#define JSON3 "]"
#define JSON4 ",\"id\":1"
// If anyone cares, id=0 for truncated output
#define JSON4_TRUNCATED ",\"id\":0"
#define JSON5 "}"
#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
#define JSON_MINECONFIG JSON1 _MINECONFIG JSON2
#define JSON_GPU JSON1 _GPU JSON2
#define JSON_GPUS JSON1 _GPUS JSON2
#define JSON_NOTIFY JSON1 _NOTIFY JSON2
#define JSON_DEVDETAILS JSON1 _DEVDETAILS JSON2
#define JSON_CLOSE JSON3
#define JSON_MINESTATS JSON1 _MINESTATS JSON2
#define JSON_CHECK JSON1 _CHECK JSON2
#define JSON_MINECOIN JSON1 _MINECOIN JSON2
#define JSON_DEBUGSET JSON1 _DEBUGSET JSON2
#define JSON_SETCONFIG JSON1 _SETCONFIG JSON2
#define JSON_END JSON4 JSON5
#define JSON_END_TRUNCATED JSON4_TRUNCATED JSON5
#define JSON_BETWEEN_JOIN ","
#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
#define MSG_MISID 15
#define MSG_GPUDEV 17
#define MSG_NUMGPU 20
#define MSG_VERSION 22
#define MSG_INVJSON 23
#define MSG_MISCMD 24
#define MSG_MISPID 25
#define MSG_INVPID 26
#define MSG_SWITCHP 27
#define MSG_MISVAL 28
#define MSG_NOADL 29
#define MSG_NOGPUADL 30
#define MSG_INVINT 31
#define MSG_GPUINT 32
#define MSG_MINECONFIG 33
#define MSG_GPUMERR 34
#define MSG_GPUMEM 35
#define MSG_GPUEERR 36
#define MSG_GPUENG 37
#define MSG_GPUVERR 38
#define MSG_GPUVDDC 39
#define MSG_GPUFERR 40
#define MSG_GPUFAN 41
#define MSG_MISFN 42
#define MSG_BADFN 43
#define MSG_SAVED 44
#define MSG_ACCDENY 45
#define MSG_ACCOK 46
#define MSG_ENAPOOL 47
#define MSG_DISPOOL 48
#define MSG_ALRENAP 49
#define MSG_ALRDISP 50
#define MSG_MISPDP 52
#define MSG_INVPDP 53
#define MSG_TOOMANYP 54
#define MSG_ADDPOOL 55
#define MSG_NOTIFY 60
#define MSG_REMLASTP 66
#define MSG_ACTPOOL 67
#define MSG_REMPOOL 68
#define MSG_DEVDETAILS 69
#define MSG_MINESTATS 70
#define MSG_MISCHK 71
#define MSG_CHECK 72
#define MSG_POOLPRIO 73
#define MSG_DUPPID 74
#define MSG_MISBOOL 75
#define MSG_INVBOOL 76
#define MSG_FOO 77
#define MSG_MINECOIN 78
#define MSG_DEBUGSET 79
#define MSG_SETCONFIG 82
#define MSG_UNKCON 83
#define MSG_INVNUM 84
#define MSG_CONPAR 85
#define MSG_CONVAL 86
#define MSG_NOUSTA 88
#define MSG_ZERMIS 94
#define MSG_ZERINV 95
#define MSG_ZERSUM 96
#define MSG_ZERNOSUM 97
#define MSG_BYE 0x101
#define MSG_INVNEG 121
#define MSG_SETQUOTA 122
#define MSG_LOCKOK 123
#define MSG_LOCKDIS 124
#define MSG_CHSTRAT 125
#define MSG_MISSTRAT 126
#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
#define MSG_CHPOOLPR 139
enum code_severity {
SEVERITY_ERR,
SEVERITY_WARN,
SEVERITY_INFO,
SEVERITY_SUCC,
SEVERITY_FAIL
};
enum code_parameters {
PARAM_GPU,
PARAM_PID,
PARAM_GPUMAX,
PARAM_PMAX,
PARAM_PRMAX,
PARAM_POOLMAX,
// Single generic case: have the code resolve it - see below
PARAM_DMAX,
PARAM_CMD,
PARAM_POOL,
PARAM_STR,
PARAM_BOTH,
PARAM_BOOL,
PARAM_SET,
PARAM_INT,
PARAM_NONE
};
struct CODES {
const enum code_severity severity;
const int code;
const enum code_parameters params;
const char *description;
};
extern struct CODES codes[];
struct IP4ACCESS {
in_addr_t ip;
in_addr_t mask;
char group;
};
#define GROUP(g) (toupper(g))
#define PRIVGROUP GROUP('W')
#define NOPRIVGROUP GROUP('R')
#define ISPRIVGROUP(g) (GROUP(g) == PRIVGROUP)
#define GROUPOFFSET(g) (GROUP(g) - GROUP('A'))
#define VALIDGROUP(g) (GROUP(g) >= GROUP('A') && GROUP(g) <= GROUP('Z'))
#define COMMANDS(g) (apigroups[GROUPOFFSET(g)].commands)
#define DEFINEDGROUP(g) (ISPRIVGROUP(g) || COMMANDS(g) != NULL)
struct APIGROUPS {
// This becomes a string like: "|cmd1|cmd2|cmd3|" so it's quick to search
char *commands;
} apigroups['Z' - 'A' + 1]; // only A=0 to Z=25 (R: noprivs, W: allprivs)
struct io_data {
size_t siz;
char *ptr;
char *cur;
bool sock;
bool close;
};
struct io_list {
struct io_data *io_data;
struct io_list *prev;
struct io_list *next;
};
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
#define io_new(init) _io_new(init, false)
#define sock_io_new() _io_new(SOCKBUFALLOCSIZ, true)
#if LOCK_TRACKING
#define LOCK_FMT_FFL " - called from %s %s():%d"
#define LOCKMSG(fmt, ...) fprintf(stderr, "APILOCK: " fmt "\n", ##__VA_ARGS__)
#define LOCKMSGMORE(fmt, ...) fprintf(stderr, " " fmt "\n", ##__VA_ARGS__)
#define LOCKMSGFFL(fmt, ...) fprintf(stderr, "APILOCK: " fmt LOCK_FMT_FFL "\n", ##__VA_ARGS__, file, func, linenum)
#define LOCKMSGFLUSH() fflush(stderr)
typedef struct lockstat {
uint64_t lock_id;
const char *file;
const char *func;
int linenum;
struct timeval tv;
} LOCKSTAT;
typedef struct lockline {
struct lockline *prev;
struct lockstat *stat;
struct lockline *next;
} LOCKLINE;
typedef struct lockinfo {
void *lock;
enum cglock_typ typ;
const char *file;
const char *func;
int linenum;
uint64_t gets;
uint64_t gots;
uint64_t tries;
uint64_t dids;
uint64_t didnts; // should be tries - dids
uint64_t unlocks;
LOCKSTAT lastgot;
LOCKLINE *lockgets;
LOCKLINE *locktries;
} LOCKINFO;
typedef struct locklist {
LOCKINFO *info;
struct locklist *next;
} LOCKLIST;
#endif
#endif /* API_H */

2029
config_parser.c

File diff suppressed because it is too large Load Diff

122
config_parser.h

@ -0,0 +1,122 @@ @@ -0,0 +1,122 @@
#ifndef CONFIG_PARSER_H
#define CONFIG_PARSER_H
#include "config.h"
#include "miner.h"
#include "api.h"
#include "algorithm.h"
//helper to check for empty or NULL strings
#ifndef empty_string
#define empty_string(str) ((str && str[0] != '\0')?0:1)
#endif
#ifndef safe_cmp
#define safe_cmp(val1, val2) (((val1 && strcmp(val1, val2) != 0) || empty_string(val1))?1:0)
#endif
#ifndef isnull
#define isnull(str, default_str) ((str == NULL)?default_str:str)
#endif
//helper function to get a gpu option value
#ifndef gpu_opt
#define gpu_opt(i,optname) gpus[i].optname
#endif
//profile structure
struct profile {
int profile_no;
char *name;
bool removed;
algorithm_t algorithm;
const char *devices;
const char *intensity;
const char *xintensity;
const char *rawintensity;
const char *lookup_gap;
const char *gpu_engine;
const char *gpu_memclock;
const char *gpu_threads;
const char *gpu_fan;
const char *gpu_powertune;
const char *gpu_vddc;
const char *shaders;
const char *thread_concurrency;
const char *worksize;
};
/* globals needed outside */
extern char *cnfbuf;
extern int fileconf_load;
extern const char def_conf[];
extern char *default_config;
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);
extern char *set_default_lookup_gap(const char *arg);
extern char *set_default_intensity(const char *arg);
extern char *set_default_xintensity(const char *arg);
extern char *set_default_rawintensity(const char *arg);
extern char *set_default_thread_concurrency(const char *arg);
#ifdef HAVE_ADL
extern char *set_default_gpu_engine(const char *arg);
extern char *set_default_gpu_memclock(const char *arg);
extern char *set_default_gpu_threads(const char *arg);
extern char *set_default_gpu_fan(const char *arg);
extern char *set_default_gpu_powertune(const char *arg);
extern char *set_default_gpu_vddc(const char *arg);
#endif
extern char *set_default_profile(char *arg);
extern char *set_default_shaders(const char *arg);
extern char *set_default_worksize(const char *arg);
extern char *set_profile_name(const char *arg);
extern char *set_profile_algorithm(const char *arg);
extern char *set_profile_devices(const char *arg);
extern char *set_profile_lookup_gap(const char *arg);
extern char *set_profile_intensity(const char *arg);
extern char *set_profile_xintensity(const char *arg);
extern char *set_profile_rawintensity(const char *arg);
extern char *set_profile_thread_concurrency(const char *arg);
#ifdef HAVE_ADL
extern char *set_profile_gpu_engine(const char *arg);
extern char *set_profile_gpu_memclock(const char *arg);
extern char *set_profile_gpu_threads(const char *arg);
extern char *set_profile_gpu_fan(const char *arg);
extern char *set_profile_gpu_powertune(const char *arg);
extern char *set_profile_gpu_vddc(const char *arg);
#endif
extern char *set_profile_nfactor(const char *arg);
extern char *set_profile_shaders(const char *arg);
extern char *set_profile_worksize(const char *arg);
/* config parser functions */
extern char *parse_config(json_t *val, const char *key, const char *parentkey, bool fileconf, int parent_iteration);
extern char *load_config(const char *arg, const char *parentkey, void __maybe_unused *unused);
extern char *set_default_config(const char *arg);
extern void load_default_config(void);
/* startup functions */
extern void load_default_profile();
extern void apply_defaults();
extern void apply_pool_profiles();
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);
extern void api_pool_profile(struct io_data *io_data, __maybe_unused SOCKETTYPE c, char *param, bool isjson, __maybe_unused char group);
#endif // CONFIG_PARSER_H

448
doc/API → doc/API.md

@ -1,202 +1,299 @@ @@ -1,202 +1,299 @@
This README contains details about the sgminer RPC API
It also includes some detailed information at the end,
about using miner.php
If you start sgminer with the "--api-listen" option, it will listen on a
simple TCP/IP socket for single string API requests from the same machine
running sgminer and reply with a string and then close the socket each time
If you add the "--api-network" option, it will accept API requests from any
network attached computer.
You can only access the comands that reply with data in this mode.
By default, you cannot access any privileged command that affects the miner -
you will receive an access denied status message see --api-allow below.
You can specify IP addresses/prefixes that are only allowed to access the API
with the "--api-allow" option e.g. --api-allow W:192.168.0.1,10.0.0/24
will allow 192.168.0.1 or any address matching 10.0.0.*, but nothing else
IP addresses are automatically padded with extra '.0's as needed
Without a /prefix is the same as specifying /32
0/0 means all IP addresses.
The 'W:' on the front gives that address/subnet privileged access to commands
that modify sgminer (thus all API commands)
Without it those commands return an access denied status.
See --api-groups below to define other groups like W:
Privileged access is checked in the order the IP addresses were supplied to
"--api-allow"
The first match determines the privilege level.
Using the "--api-allow" option overides the "--api-network" option if they
are both specified
With "--api-allow", 127.0.0.1 is not by default given access unless specified
If you start sgminer also with the "--api-mcast" option, it will listen for
a multicast message and reply to it with a message containing it's API port
number, but only if the IP address of the sender is allowed API access
More groups (like the privileged group W:) can be defined using the
--api-groups command
Valid groups are only the letters A-Z (except R & W are predefined) and are
not case sensitive
The R: group is the same as not privileged access
The W: group is (as stated) privileged access (thus all API commands)
To give an IP address/subnet access to a group you use the group letter
in front of the IP address instead of W: e.g. P:192.168.0/32
An IP address/subnet can only be a member of one group
# sgminer RPC API Documentation
*Work in Progress!*
This README contains details about the sgminer RPC API and also includes some detailed information
at the end, about using [miner.php](#miner-php).
---
## API Configuration
If you start sgminer with the `--api-listen` option, it will listen on a simple TCP/IP socket for single string API requests from the same machine running sgminer and reply with a string and then close the socket each time If you add the `--api-network` option, it will accept API requests from any network attached computer.
You can only access the comands that reply with data in this mode. By default, you cannot access any privileged command that affects the miner - you will receive an access denied status message see `--api-allow` below.
You can specify IP addresses/prefixes that are only allowed to access the API with the `--api-allow` option.
```
--api-allow W:192.168.0.1,10.0.0/24
```
The example above will allow 192.168.0.1 or any address matching 10.0.0.*, but nothing else. IP addresses are automatically padded with extra '.0's as needed Without a /prefix is the same as specifying /32 0/0 means all IP addresses. The `W:` on the front gives that address/subnet privileged access to commands that modify sgminer (thus all API commands). Without it those commands return an access denied status. See `--api-groups` below to define other groups like `W:`. Privileged access is checked in the order the IP addresses were supplied to `--api-allow`. The first match determines the privilege level. Using the `--api-allow` option overides the `--api-network` option if they are both specified. With `--api-allow`, 127.0.0.1 is not by default given access unless specified.
If you start sgminer also with the `--api-mcast` option, it will listen for a multicast message and reply to it with a message containing it's API port number, but only if the IP address of the sender is allowed API access.
More groups (like the privileged group `W:`) can be defined using the `--api-groups` command. Valid groups are only the letters A-Z (except R & W are predefined) and are not case sensitive. The `R:` group is the same as not privileged access. The `W:` group is (as stated) privileged access (thus all API commands). To give an IP address/subnet access to a group you use the group letter in front of the IP address instead of `W:` e.g. `P:192.168.0/32`. An IP address/subnet can only be a member of one group
A sample API group would be:
--api-groups
P:switchpool:enablepool:addpool:disablepool:removepool:poolpriority:*
This would create a group 'P' that can do all current pool commands and all
non-priviliged commands - the '*' means all non-priviledged commands
Without the '*' the group would only have access to the pool commands
```
--api-groups P:switchpool:enablepool:addpool:disablepool:removepool:poolpriority:*
```
This would create a group `P` that can do all current pool commands and all non-priviliged commands - the asterisk (\*) means all non-priviledged commands. Without the asterisk (\*), the group would only have access to the pool commands.
Defining multiple groups example:
--api-groups Q:quit:restart:*,S:save
This would define 2 groups:
Q: that can 'quit' and 'restart' as well as all non-priviledged commands
S: that can only 'save' and no other commands
```
--api-groups Q:quit:restart:*,S:save
```
This would define 2 groups: `Q:`, that can `quit` and `restart` as well as all non-priviledged commands, and `S:`, that can only `save` and no other commands.
For API configuration options, see `doc/configuration.md`.
---
## API Requests
The RPC API request can be either simple text or JSON.
If the request is JSON (starts with '{'), it will reply with a JSON formatted
If the request is JSON (starts with `{`), it will reply with a JSON formatted
response, otherwise it replies with text formatted as described further below.
The JSON request format required is '{"command":"CMD","parameter":"PARAM"}'
The JSON request format required is `{"command":"CMD","parameter":"PARAM"}`
(though of course parameter is not required for all requests)
where "CMD" is from the "Request" column below and "PARAM" would be e.g.
the ASC/GPU number if required.
An example request in both formats to set GPU 0 fan to 80%:
```
gpufan|0,80
{"command":"gpufan","parameter":"0,80"}
```
The format of each reply (unless stated otherwise) is a STATUS section
followed by an optional detail section
From API version 1.7 onwards, reply strings in JSON and Text have the
necessary escaping as required to avoid ambiguity - they didn't before 1.7
For JSON the 2 characters '"' and '\' are escaped with a '\' before them
For Text the 4 characters '|' ',' '=' and '\' are escaped the same way
For JSON the 2 characters `"` and `\` are escaped with a `\` before them
For Text the 4 characters `|` `,` `=` and `\` are escaped the same way
Only user entered information will contain characters that require being
escaped, such as Pool URL, User and Password or the Config save filename,
when they are returned in messages or as their values by the API
For API version 1.4 and later:
The STATUS section is:
For API version 1.4 and later the STATUS section is:
STATUS=X,When=NNN,Code=N,Msg=string,Description=string|
`STATUS=X,When=NNN,Code=N,Msg=string,Description=string|`
STATUS=X Where X is one of:
W - Warning
I - Informational
S - Success
E - Error
F - Fatal (code bug)
* `STATUS=X` Where X is one of:
`W` Warning
`I` Informational
`S` Success
`E` Error
`F` Fatal (code bug)
When=NNN
* `When=NNN`
Standard long time of request in seconds
Code=N
Each unique reply has a unigue Code (See api.c - #define MSG_NNNNNN)
* `Code=N`
Each unique reply has a unigue Code (See `api.c` and `api.h` - #define MSG_NNNNNN)
Msg=string
* `Msg=string`
Message matching the Code value N
Description=string
This defaults to the sgminer version but is the value of --api-description
* `Description=string`
This defaults to the sgminer version but is the value of `--api-description`
if it was specified at runtime.
With API V3.1 you can also request multiple report replies in a single command
request
e.g. to request both summary and devs, the command would be summary+devs
request: e.g. to request both `summary` and `devs`, the command would be `summary+devs`
This is only available for report commands that don't need parameters,
and is not available for commands that change anything
Any parameters supplied will be ignored
**Note:** This is only available for report commands that don't need parameters,
and is not available for commands that change anything. Any parameters supplied will be ignored.
The extra formatting of the result is to have a section for each command
e.g. CMD=summary|STATUS=....|CMD=devs|STATUS=...
With JSON, each result is within a section of the command name
e.g. {"summary":{"STATUS":[{"STATUS":"S"...}],"SUMMARY":[...],"id":1},
"devs":{"STATUS":[{"STATUS:"S"...}],"DEVS":[...],"id":1},"id":1}
The extra formatting of the result is to have a section for each command:
`CMD=summary|STATUS=....|CMD=devs|STATUS=...`
As before, if you supply bad JSON you'll just get a single 'E' STATUS section
With JSON, each result is within a section of the command name
```
{
"summary":{
"STATUS":[
{"STATUS":"S"...}
],
"SUMMARY":[...],
"id":1
},
"devs":{
"STATUS":[
{"STATUS:"S"...}
],
"DEVS":[...],
"id":1
},
"id":1
}
````
As before, if you supply bad JSON you'll just get a single `E` STATUS section
in the old format, since it doesn't switch to using the new format until it
correctly processes the JSON and can match a '+' in the command
correctly processes the JSON and can match a `+` in the command.
If you request a command multiple times, e.g. devs+devs
you'll just get it once
If you request a command multiple times, e.g. `devs+devs`, you'll just get it once.
If this results in only one command, it will still use the new layout
with just the one command
If you request a command that can't be used due to requiring parameters,
a command that isn't a report, or an invalid command, you'll get an 'E' STATUS
a command that isn't a report, or an invalid command, you'll get an `E` STATUS
for that one but it will still attempt to process all other commands supplied
Blank/missing commands are ignore e.g. +devs++
will just show 'devs' using the new layout
For API version 1.10 and later:
The list of requests - a (*) means it requires privileged access - and replies:
Request Reply Section Details
------- ------------- -------
version VERSION Miner="sgminer " sgminer version
CGMiner=sgminer version
API=API version
config CONFIG Some miner configuration information:
GPU Count=N, <- the number of GPUs
ASC Count=N, <- the number of ASCs
PGA Count=N, <- the number of PGAs
Pool Count=N, <- the number of Pools
ADL=X, <- Y or N if ADL is compiled in the code
ADL in use=X, <- Y or N if any GPU has ADL
Strategy=Name, <- the current pool strategy
Log Interval=N, <- log interval (--log N)
Device Code=GPU ICA , <- spaced list of compiled
device drivers
OS=Linux/Apple/..., <- operating System
Failover-Only=true/false, <- failover-only setting
ScanTime=N, <- --scan-time setting
Queue=N, <- --queue setting
Expiry=N| <- --expiry setting
summary SUMMARY The status summary of the miner
e.g. Elapsed=NNN,Found Blocks=N,Getworks=N,...|
pools POOLS The status of each pool e.g.
Pool=0,URL=http://pool.com:6311,Status=Alive,...|
devs DEVS Each available GPU, PGA and ASC with their details
e.g. GPU=0,Accepted=NN,MHS av=NNN,...,Intensity=D|
Last Share Time=NNN, <- standand long time in sec
(or 0 if none) of last accepted share
Last Share Pool=N, <- pool number (or -1 if none)
Last Valid Work=NNN, <- standand long time in sec
of last work returned that wasn't an HW:
Will not report PGAs if PGA mining is disabled
Will not report ASCs if ASC mining is disabled
gpu|N GPU The details of a single GPU number N in the same
format and details as for DEVS
Blank/missing commands are ignored. `+devs++` will just show `devs` using the new
layout.
pga|N PGA The details of a single PGA number N in the same
format and details as for DEVS
This is only available if PGA mining is enabled
Use 'pgacount' or 'config' first to see if there
are any
---
## API Commands
### version
Returns the version information of sgminer.
*Syntax:* `version`
*Arguments:* None
*Access*: `Non-priviledged`
*Returns:*
```
Miner="sgminer " <sgminer version>
CGMiner=<sgminer version>
API=<API version>
```
### config
Returns some miner configuration information
*Syntax:* `config`
*Arguments:* None
*Access*: `Non-priviledged`
*Returns:*
```
GPU Count=N, <- the number of GPUs
ASC Count=N, <- the number of ASCs
PGA Count=N, <- the number of PGAs
Pool Count=N, <- the number of Pools
ADL=X, <- Y or N if ADL is compiled in the code
ADL in use=X, <- Y or N if any GPU has ADL
Strategy=Name, <- the current pool strategy
Log Interval=N, <- log interval (--log N)
Device Code=GPU ICA, <- spaced list of compiled device drivers
OS=Linux/Apple/..., <- operating System
Failover-Only=true/false, <- failover-only setting
ScanTime=N, <- --scan-time setting
Queue=N, <- --queue setting
Expiry=N| <- --expiry setting
```
### summary
Returns the status summary of the miner
*Syntax:* `summary`
gpucount GPUS Count=N| <- the number of GPUs
*Arguments:* None
pgacount PGAS Count=N| <- the number of PGAs
Always returns 0 if PGA mining is disabled
*Access*: `Non-priviledged`
switchpool|N (*)
*Returns:* `Elapsed=NNN,Found Blocks=N,Getworks=N,...|`
### devs
Returns each available GPU, PGA and ASC with their details. **Note** that this will not return PGAs or ASCs if PGA or ASC mining is not enabled.
*Syntax:* `devs`
*Arguments:* None
*Access*: `Non-priviledged`
*Returns:*
```
GPU=0,Accepted=NN,MHS av=NNN,...,Intensity=D|
Last Share Time=NNN, <- standand long time in sec (or 0 if none) of last accepted share
Last Share Pool=N, <- pool number (or -1 if none)
Last Valid Work=NNN, <- standand long time in sec of last work returned that wasn't an HW
```
### gpu
Returns the details of a single GPU in the same format and details as [devs](#devs).
*Syntax:* `gpu|<N>`
*Arguments:* `number` GPU Number
*Access*: `Non-priviledged`
*Returns:*
```
GPU=0,Accepted=NN,MHS av=NNN,...,Intensity=D|
Last Share Time=NNN, <- standand long time in sec (or 0 if none) of last accepted share
Last Share Pool=N, <- pool number (or -1 if none)
Last Valid Work=NNN, <- standand long time in sec of last work returned that wasn't an HW
```
### pga
Returns the details of a single PGA in the same format and details as [devs](#devs). **Note** that this is only available if PGA mining is enabled. Use [pgacount](#pgacount) or [config](#config) first to see if there are any PGA devices.
*Syntax:* `pga|<N>`
*Arguments:* `number` PGA Number
*Access*: `Non-priviledged`
*Returns:*
```
PGA=0,Accepted=NN,MHS av=NNN,...,Intensity=D|
Last Share Time=NNN, <- standand long time in sec (or 0 if none) of last accepted share
Last Share Pool=N, <- pool number (or -1 if none)
Last Valid Work=NNN, <- standand long time in sec of last work returned that wasn't an HW
```
### gpucount
Returns the number of GPU devices.
*Syntax:* `gpucount`
*Arguments:* None
*Access*: `Non-priviledged`
*Returns:*
```
Count=N| <- number of GPUs
```
### pgacount
Returns the number of PGA devices.
*Syntax:* `pgacount`
*Arguments:* None
*Access*: `Non-priviledged`
*Returns:*
```
Count=N| <- number of PGAs
```
---
```
switchpool|N (*)
none There is no reply section just the STATUS section
stating the results of switching pool N to the
highest priority (the pool is also enabled)
@ -207,13 +304,13 @@ The list of requests - a (*) means it requires privileged access - and replies: @@ -207,13 +304,13 @@ The list of requests - a (*) means it requires privileged access - and replies:
stating the results of enabling pool N
The Msg includes the pool URL
addpool|URL,USR,PASS[,NAME,DESC,ALGO] (*)
addpool|URL,USR,PASS[,NAME,DESC,PROFILE,ALGO] (*)
none There is no reply section just the STATUS section
stating the results of attempting to add pool N
The Msg includes the pool URL
Use '\\' to get a '\' and '\,' to include a comma
inside URL, USR or PASS
Name, description and algorithm are optional
Name, description, profile and algorithm are optional
poolpriority|N,... (*)
none There is no reply section just the STATUS section
@ -235,7 +332,36 @@ The list of requests - a (*) means it requires privileged access - and replies: @@ -235,7 +332,36 @@ The list of requests - a (*) means it requires privileged access - and replies:
The Msg includes the pool URL
N.B. all details for the pool will be lost
gpuenable|N (*)
changestrategy|STRAT,INT (*)
none There is no reply section just the STATUS section
stating the results of changing multipool strategy
to STRAT. If the strategy requested is "rotate",
the interval INT must be specified as a number
between 0 and 9999 seconds. INT is not required
otherwise.
changepoolprofile|N,NAME (*)
none There is no reply section just the STATUS section
stating the results of changing the profile of
pool N to profile NAME.
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
@ -474,6 +600,7 @@ The list of requests - a (*) means it requires privileged access - and replies: @@ -474,6 +600,7 @@ The list of requests - a (*) means it requires privileged access - and replies:
A warning reply means lock stats are not compiled
into sgminer
The API writes all the lock stats to stderr
```
When you enable, disable or restart a GPU, PGA or ASC, you will also get
Thread messages in the sgminer status window
@ -524,15 +651,18 @@ miner.php - an example web page to access the API @@ -524,15 +651,18 @@ miner.php - an example web page to access the API
See the end of this API readme for details of how to tune the display
and also to use the option to display a multi-rig summary
----------
Feature Changelog for external applications using the API:
## API Version History
API V4.0 (sgminer v5.0)
API V
Modified API commands:
'version' - add 'Miner'
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
----------
@ -957,8 +1087,8 @@ Commands: @@ -957,8 +1087,8 @@ Commands:
----------------------------------------
miner.php
=========
## miner.php
miner.php is a PHP based interface to the sgminer RPC API
(referred to simply as the API below)

0
doc/GPU → doc/GPU.md

2187
doc/configuration.md

File diff suppressed because it is too large Load Diff

161
example.conf

@ -1,71 +1,94 @@ @@ -1,71 +1,94 @@
{
"pools" : [
{
"name" : "Preferred Pool",
"url" : "http://url1:8332",
"user" : "user1",
"pass" : "pass1"
},
{
"name" : "Failover Pool",
"url" : "http://url2:8344",
"user" : "user2",
"pass" : "pass2",
"state" : "enabled"
},
{
"name" : "Failover Pool",
"url" : "http://url3:8344",
"user" : "user3",
"pass" : "pass3",
"algorithm" : "adaptive-n-factor",
"state" : "disabled"
},
{
"name" : "Testing Pool",
"url" : "http://url4:8332",
"user" : "user4",
"pass" : "pass4",
"state" : "hidden"
}
],
"failover-only" : true,
"failover-switch-delay" : "60",
"no-pool-disable" : true,
"kernel-path" : "/usr/local/bin",
"kernel" : "alexkarold,ckolivas,zuikkis",
"algorithm" : "scrypt",
"intensity" : "d,9,9,9",
"xintensity" : "0,0,0",
"rawintensity" : "0,0,0",
"lookup-gap" : "2,2,2",
"thread-concurrency" : "15508,15508,15508",
"shaders" : "0,0,0",
"gpu-threads" : "2",
"gpu-engine" : "0-985,0-950,0-1000",
"gpu-memclock" : "860,825,875",
"gpu-powertune" : "20,20,20",
"gpu-vddc" : "0.000,0.000,0.000",
"gpu-fan" : "0-85,0-85,0-85",
"auto-gpu" : true,
"auto-fan" : true,
"temp-target" : "75,75,75",
"temp-overheat" : "80,85,90",
"temp-cutoff" : "95",
"temp-hysteresis" : "3",
"queue" : "1",
"scan-time" : "7",
"expiry" : "28",
"log" : "5"
"pools": [
{
"name":"Testpool X11",
"url": "stratum+tcp://url1:4440",
"user": "user",
"pass": "x",
"priority": "1",
"profile": "x11"
},
{
"name":"Testpool Scrypt",
"url": "stratum+tcp://url2:3339",
"user": "user",
"pass": "x",
"priority": "2",
"profile": "scrypt"
},
{
"name":"Testpool X11 with other profile",
"url": "stratum+tcp://url3:4440",
"user": "user",
"pass": "x",
"priority": "0",
"profile": "x11test"
},
{
"name":"Testpool Using default profile",
"url": "stratum+tcp://url4:3333",
"user": "user",
"pass": "x"
}
],
"profiles": [
{
"name": "x11",
"algorithm": "darkcoin-mod",
"intensity": "19",
"thread-concurrency": "10696,8192",
"worksize": "128",
"gpu-engine": "1100",
"gpu-threads": "2",
"gpu-fan": "75"
},
{
"name": "scrypt",
"algorithm": "ckolivas",
"lookup-gap": "2",
"intensity": "19,13",
"thread-concurrency": "19656,8192",
"worksize": "256",
"gpu-engine": "1000,1065",
"gpu-memclock": "1500",
"gpu-threads": "1,2",
"gpu-fan": "85",
"gpu-powertune": "20"
},
{
"name": "x11test",
"algorithm": "darkcoin-mod",
"device": "1",
"intensity": "19",
"thread-concurrency": "10696,8192",
"worksize": "512",
"gpu-engine": "1100",
"gpu-threads": "2",
"gpu-fan": "75"
}
],
"failover-only": true,
"default-profile": "scrypt",
"temp-cutoff": "95,95",
"temp-overheat": "90,90",
"temp-target": "80,80",
"gpu-memdiff": "0,0",
"shares": "0",
"kernel-path": "/usr/local/bin",
"api-allow": "W:127.0.0.1",
"api-listen": true,
"api-mcast-port": "4028",
"api-port": "4028",
"expiry": "1",
"failover-switch-delay": "60",
"gpu-dyninterval": "7",
"gpu-platform": "-1",
"hamsi-expand-big": "4",
"log": "5",
"no-pool-disable": true,
"no-client-reconnect": true,
"queue": "0",
"scan-time": "1",
"tcp-keepalive": "30",
"temp-hysteresis": "3"
}

59
miner.h

@ -124,6 +124,8 @@ static inline int fsync (int fd) @@ -124,6 +124,8 @@ static inline int fsync (int fd)
#include "ADL_SDK/adl_sdk.h"
#endif
#include <ccan/opt/opt.h>
#if (!defined(WIN32) && ((__GNUC__ > 4) || (__GNUC__ == 4 && __GNUC_MINOR__ >= 3))) \
|| (defined(WIN32) && ((__GNUC__ > 4) || (__GNUC__ == 4 && __GNUC_MINOR__ >= 7)))
#ifndef bswap_16
@ -251,7 +253,6 @@ enum alive { @@ -251,7 +253,6 @@ enum alive {
LIFE_INIT,
};
enum pool_strategy {
POOL_FAILOVER,
POOL_ROUNDROBIN,
@ -266,6 +267,9 @@ struct strategies { @@ -266,6 +267,9 @@ struct strategies {
const char *s;
};
extern enum pool_strategy pool_strategy;
extern struct strategies strategies[];
struct cgpu_info;
#ifdef HAVE_ADL
@ -932,7 +936,21 @@ extern bool opt_protocol; @@ -932,7 +936,21 @@ extern bool opt_protocol;
extern bool have_longpoll;
extern char *opt_kernel_path;
extern char *opt_socks_proxy;
#if defined(unix) || defined(__APPLE__)
extern char *opt_stderr_cmd;
#endif // defined(unix)
struct schedtime {
bool enable;
struct tm tm;
};
extern struct schedtime schedstart;
extern struct schedtime schedstop;
extern char *sgminer_path;
extern int opt_shares;
extern bool opt_fail_only;
extern bool opt_autofan;
extern bool opt_autoengine;
@ -1023,11 +1041,12 @@ extern void api(int thr_id); @@ -1023,11 +1041,12 @@ extern void api(int thr_id);
extern struct pool *current_pool(void);
extern int enabled_pools;
extern void get_intrange(char *arg, int *val1, int *val2);
extern char *set_devices(char *arg);
extern bool detect_stratum(struct pool *pool, char *url);
extern void print_summary(void);
extern void adjust_quota_gcd(void);
extern struct pool *add_pool(void);
extern bool add_pool_details(struct pool *pool, bool live, char *url, char *user, char *pass, char *name, char *desc, char *algo);
extern bool add_pool_details(struct pool *pool, bool live, char *url, char *user, char *pass, char *name, char *desc, char *profile, char *algo);
#define MAX_GPUDEVICES 16
#define MAX_DEVICES 4096
@ -1056,6 +1075,9 @@ extern struct cgpu_info gpus[MAX_GPUDEVICES]; @@ -1056,6 +1075,9 @@ extern struct cgpu_info gpus[MAX_GPUDEVICES];
extern double total_secs;
extern int mining_threads;
extern int total_devices;
extern bool devices_enabled[MAX_DEVICES];
extern int opt_devs_enabled;
extern bool opt_removedisabled;
extern struct cgpu_info **devices;
extern int total_pools;
extern struct pool **pools;
@ -1081,6 +1103,9 @@ extern double best_diff; @@ -1081,6 +1103,9 @@ extern double best_diff;
extern struct timeval block_timeval;
extern char *workpadding;
//config options table
extern struct opt_table opt_config_table[];
typedef struct _dev_blk_ctx {
cl_uint ctx_a; cl_uint ctx_b; cl_uint ctx_c; cl_uint ctx_d;
cl_uint ctx_e; cl_uint ctx_f; cl_uint ctx_g; cl_uint ctx_h;
@ -1192,15 +1217,22 @@ struct pool { @@ -1192,15 +1217,22 @@ struct pool {
proxytypes_t rpc_proxytype;
char *rpc_proxy;
char *profile;
algorithm_t algorithm;
const char *intensity;
const char *xintensity;
const char *rawintensity;
const char *thread_concurrency;
const char *gpu_engine;
const char *gpu_memclock;
const char *gpu_threads;
const char *gpu_fan;
const char *devices;
const char *intensity;
const char *xintensity;
const char *rawintensity;
const char *lookup_gap;
const char *gpu_engine;
const char *gpu_memclock;
const char *gpu_threads;
const char *gpu_fan;
const char *gpu_powertune;
const char *gpu_vddc;
const char *shaders;
const char *thread_concurrency;
const char *worksize;
pthread_mutex_t pool_lock;
cglock_t data_lock;
@ -1374,7 +1406,7 @@ extern void kill_work(void); @@ -1374,7 +1406,7 @@ extern void kill_work(void);
extern void switch_pools(struct pool *selected);
extern void discard_work(struct work *work);
extern void remove_pool(struct pool *pool);
extern void write_config(FILE *fcfg);
//extern void write_config(FILE *fcfg);
extern void zero_bestshare(void);
extern void zero_stats(void);
extern void default_save_file(char *filename);
@ -1398,6 +1430,11 @@ extern struct work *copy_work_noffset(struct work *base_work, int noffset); @@ -1398,6 +1430,11 @@ extern struct work *copy_work_noffset(struct work *base_work, int noffset);
#define copy_work(work_in) copy_work_noffset(work_in, 0)
extern struct cgpu_info *get_devices(int id);
extern char *set_int_0_to_9999(const char *arg, int *i);
extern char *set_int_1_to_65535(const char *arg, int *i);
extern char *set_int_0_to_10(const char *arg, int *i);
extern char *set_int_1_to_10(const char *arg, int *i);
enum api_data_type {
API_ESCAPE,
API_STRING,

1013
sgminer.c

File diff suppressed because it is too large Load Diff
Loading…
Cancel
Save