diff --git a/sql/2016-05-15-benchmarks.sql b/sql/2016-05-15-benchmarks.sql new file mode 100644 index 0000000..3c37669 --- /dev/null +++ b/sql/2016-05-15-benchmarks.sql @@ -0,0 +1,31 @@ +-- Recent additions to add after db init (.gz) +-- mysql yaamp -p < file.sql + +CREATE TABLE `benchmarks` ( + `id` int(11) NOT NULL AUTO_INCREMENT PRIMARY KEY, + `algo` varchar(16) NOT NULL, + `type` varchar(8) NOT NULL, + `khps` double NULL, + `device` varchar(80) NULL, + `vendorid` varchar(12) NULL, + `arch` varchar(8) NULL, + `power` int(5) UNSIGNED NULL, + `freq` int(8) UNSIGNED NULL, + `memf` int(8) UNSIGNED NULL, + `client` varchar(48) NULL, + `os` varchar(8) NULL, + `driver` varchar(32) NULL, + `intensity` double NULL, + `throughput` int(11) UNSIGNED NULL, + `userid` int(11) NULL, + `time` int(10) UNSIGNED NOT NULL +) ENGINE=InnoDB DEFAULT CHARSET=utf8; + +-- KEYS & Indexes + +ALTER TABLE `benchmarks` + ADD KEY `bench_userid` (`userid`), + ADD INDEX `ndx_type` (`type`), + ADD INDEX `ndx_algo` (`algo`), + ADD INDEX `ndx_time` (`time` DESC); + diff --git a/stratum/client.cpp b/stratum/client.cpp index ffe17bf..983b28b 100644 --- a/stratum/client.cpp +++ b/stratum/client.cpp @@ -52,6 +52,9 @@ bool client_subscribe(YAAMP_CLIENT *client, json_value *json_params) if(strstr(client->version, "NiceHash") || strstr(client->version, "proxy") || strstr(client->version, "/3.")) client->reconnectable = false; + + if(strstr(client->version, "ccminer")) + client->stats = true; } if(json_params->u.array.length>1) @@ -300,6 +303,38 @@ bool client_update_block(YAAMP_CLIENT *client, json_value *json_params) /////////////////////////////////////////////////////////////////////////////////////////// +bool client_ask_stats(YAAMP_CLIENT *client) +{ + int id; + if (!client->stats) return false; + if (!strstr(client->password, "stats")) return false; + + //client_call(client, "client.get_stats", "[]"); + id = client_ask(client, "client.get_version", "[\"stats\"]"); + return true; +} + +static bool client_store_stats(YAAMP_CLIENT *client, json_value *result) +{ + if (json_typeof(result) != json_object) + return false; + + json_value *val = json_get_val(result, "type"); + if (val && json_is_string(val)) { + // debuglog("received stats of type %s\n", json_string_value(val)); + if (!strcmp("gpu", json_string_value(val))) { + CommonLock(&g_db_mutex); + db_store_stats(g_db, client, result); + CommonUnlock(&g_db_mutex); + } + return true; + } + + return false; +} + +/////////////////////////////////////////////////////////////////////////////////////////// + //YAAMP_SOURCE *source_init(YAAMP_CLIENT *client) //{ // YAAMP_SOURCE *source = NULL; @@ -414,6 +449,15 @@ void *client_thread(void *p) client->id_str = json_get_string(json, "id"); const char *method = json_get_string(json, "method"); + + if (!method && client->stats && client->id_int == client->reqid) + { + json_value *result = json_get_object(json, "result"); + if (result) client_store_stats(client, result); + json_value_free(json); + continue; + } + if(!method) { json_value_free(json); @@ -440,6 +484,9 @@ void *client_thread(void *p) else if(!strcmp(method, "mining.authorize")) b = client_authorize(client, json_params); + else if(!strcmp(method, "mining.ping")) + b = client_send_result(client, "\"pong\""); + else if(!strcmp(method, "mining.submit")) b = client_submit(client, json_params); @@ -463,7 +510,7 @@ void *client_thread(void *p) else if(!strcmp(method, "getwork")) { - clientlog(client, "using getwork"); + clientlog(client, "using getwork"); // client using http:// url break; } diff --git a/stratum/client.h b/stratum/client.h index 5ef28a5..c792126 100644 --- a/stratum/client.h +++ b/stratum/client.h @@ -38,6 +38,7 @@ public: // YAAMP_SOURCE *source; char notify_id[1024]; + int64_t reqid; // ask request id int created; int last_best; @@ -91,6 +92,9 @@ public: YAAMP_CLIENT_ALGO algos_subscribed[YAAMP_MAXALGOS]; int job_history[YAAMP_JOB_MAXHISTORY]; + int64_t shares; + int stats; + int donation; }; @@ -134,11 +138,15 @@ void client_initialize_difficulty(YAAMP_CLIENT *client); ////////////////////////////////////////////////////////////////////////// int client_call(YAAMP_CLIENT *client, const char *method, const char *format, ...); +int client_ask(YAAMP_CLIENT *client, const char *method, const char *format, ...); + void client_dump_all(); int client_send_result(YAAMP_CLIENT *client, const char *format, ...); int client_send_error(YAAMP_CLIENT *client, int error, const char *string); +bool client_ask_stats(YAAMP_CLIENT *client); + bool client_submit(YAAMP_CLIENT *client, json_value *json_params); void *client_thread(void *p); diff --git a/stratum/client_core.cpp b/stratum/client_core.cpp index f2866ab..fc0f463 100644 --- a/stratum/client_core.cpp +++ b/stratum/client_core.cpp @@ -100,6 +100,25 @@ int client_call(YAAMP_CLIENT *client, const char *method, const char *format, .. return socket_send(client->sock, "{\"id\":null,\"method\":\"%s\",\"params\":%s}\n", method, buffer); } +int client_ask(YAAMP_CLIENT *client, const char *method, const char *format, ...) +{ + char buffer[YAAMP_SMALLBUFSIZE]; + va_list args; + int64_t id = client->shares; + + va_start(args, format); + vsprintf(buffer, format, args); + va_end(args); + + int ret = socket_send(client->sock, "{\"id\":%d,\"method\":\"%s\",\"params\":%s}\n", id, method, buffer); + if (ret == -1) { + debuglog("unable to ask %s\n", method); + return 0; // -errno + } + client->reqid = id; + return id; +} + void client_block_ip(YAAMP_CLIENT *client, const char *reason) { char buffer[1024]; diff --git a/stratum/client_submit.cpp b/stratum/client_submit.cpp index ca141f5..6d2cf28 100644 --- a/stratum/client_submit.cpp +++ b/stratum/client_submit.cpp @@ -463,6 +463,10 @@ bool client_submit(YAAMP_CLIENT *client, json_value *json_params) client_send_result(client, "true"); client_record_difficulty(client); client->submit_bad = 0; + client->shares++; + if ((client->shares % 50) == 0) { + if (!client_ask_stats(client)) client->stats = false; + } double share_diff = diff_to_target(hash_int); diff --git a/stratum/db.cpp b/stratum/db.cpp index c8d4ae4..3af23a0 100644 --- a/stratum/db.cpp +++ b/stratum/db.cpp @@ -450,9 +450,68 @@ void db_update_renters(YAAMP_DB *db) g_list_renter.Leave(); } +/////////////////////////////////////////////////////////////////////// +static void _json_str_safe(YAAMP_DB *db, json_value *json, const char *key, size_t maxlen, char* out) +{ + json_value *val = json_get_val(json, key); + out[0] = '\0'; + if (val && json_is_string(val)) { + strncpy(out, json_string_value(val), maxlen); + out[maxlen-1] = '\0'; + db_clean_string(db, out); + } else { + //debuglog("stats: invalid string for field '%s'\n", key); + } +} +#define json_str_safe(stats, k, out) _json_str_safe(db, stats, k, sizeof(out), out) +static int json_int_safe(json_value *json, const char *key) +{ + json_value *val = json_get_val(json, key); + return val ? (int) json_integer_value(val) : 0; +} +static double json_double_safe(json_value *json, const char *key) +{ + json_value *val = json_get_val(json, key); + return val ? (int) json_double_value(val) : 0.; +} +void db_store_stats(YAAMP_DB *db, YAAMP_CLIENT *client, json_value *stats) +{ + int t = time(NULL); + json_value *algo, *val; + char sdev[80], stype[8], svid[12], sarch[8]; + char salgo[32], sclient[48], sdriver[32], sos[8]; + double khashes, intensity, throughput; + int power, freq, memf; + json_str_safe(stats, "algo", salgo); + if (strcasecmp(g_current_algo->name, salgo) && client->submit_bad) { + // debuglog("stats: wrong algo used %s != %s", salgo, g_current_algo->name); + return; + } + json_str_safe(stats, "device", sdev); + json_str_safe(stats, "type", stype); + json_str_safe(stats, "vendorid", svid); + json_str_safe(stats, "arch", sarch); + json_str_safe(stats, "client", sclient); + json_str_safe(stats, "os", sos); + json_str_safe(stats, "driver", sdriver); + + power = json_int_safe(stats, "power"); + freq = json_int_safe(stats, "freq"); + memf = json_int_safe(stats, "memf"); + intensity = json_double_safe(stats, "intensity"); + throughput = json_double_safe(stats, "throughput"); + khashes = json_double_safe(stats, "khashes"); + + db_query(db, "INSERT INTO benchmarks(" + "time, algo, type, device, arch, vendorid, os, driver," + "client, khps, freq, memf, power, intensity, throughput, userid" + ") VALUES (%d,'%s','%s','%s','%s','%s','%s','%s', '%s',%f,%d,%d,%d,%.2f,%.0f,%d)", + t, g_current_algo->name, stype, sdev, sarch, svid, sos, sdriver, + sclient, khashes, freq, memf, power, intensity, throughput, client->userid); +} diff --git a/stratum/db.h b/stratum/db.h index c64e4be..769c270 100644 --- a/stratum/db.h +++ b/stratum/db.h @@ -29,5 +29,7 @@ void db_update_workers(YAAMP_DB *db); void db_init_user_coinid(YAAMP_DB *db, YAAMP_CLIENT *client); +void db_store_stats(YAAMP_DB *db, YAAMP_CLIENT *client, json_value *stats); + void db_update_renters(YAAMP_DB *db); diff --git a/stratum/json.cpp b/stratum/json.cpp index 3cc1425..ca70ef7 100644 --- a/stratum/json.cpp +++ b/stratum/json.cpp @@ -1001,3 +1001,27 @@ char* json_string_value(const json_value *json) return json->u.string.ptr; } + +double json_double_value(const json_value *json) +{ + double r = 0.; + if(json_is_double(json)) + r = *(json); + else if (json_is_integer(json)) + r = (double) json_integer_value(json); + + return r; +} + +json_value* json_get_val(json_value *obj, const char *key) +{ + if (obj->type != json_object) + return NULL; + + for (unsigned int i = 0; i < obj->u.object.length; i++) + if (!strcmp(obj->u.object.values[i].name, key)) + return obj->u.object.values[i].value; + + return NULL; +} + diff --git a/stratum/json.h b/stratum/json.h index d0471e4..d8e202a 100644 --- a/stratum/json.h +++ b/stratum/json.h @@ -261,6 +261,8 @@ void json_value_free (json_value *); void json_value_free_ex (json_settings * settings, json_value *); +json_value* json_get_val(json_value *obj, const char *key); + // todo char* json_dumps(json_value * value, int opt); @@ -268,11 +270,13 @@ typedef json_value json_t; #define json_typeof(json) ((json)->type) #define json_is_array(json) (json && json_typeof(json) == json_array) #define json_is_integer(json) (json && json_typeof(json) == json_integer) +#define json_is_double(json) (json && json_typeof(json) == json_double) #define json_is_string(json) (json && json_typeof(json) == json_string) #define json_is_null(json) (json && json_typeof(json) == json_null) int json_integer_value(const json_value *json); char* json_string_value(const json_value *json); +double json_double_value(const json_value *json); #ifdef __cplusplus } /* extern "C" */ diff --git a/stratum/socket.cpp b/stratum/socket.cpp index d885da7..f374ccc 100644 --- a/stratum/socket.cpp +++ b/stratum/socket.cpp @@ -79,7 +79,7 @@ json_value *socket_nextjson(YAAMP_SOCKET *s, YAAMP_CLIENT *client) return NULL; } - char *p = strchr(b, '}'); + char *p = strrchr(b, '}'); if(!p) { if(client)