Browse Source

Merge branch 'master' into userstats

master
Con Kolivas 10 years ago
parent
commit
26d9bd9e08
  1. 4
      pool/page.php
  2. 24
      pool/page_pplns.php
  3. 5
      pool/prime.php
  4. 19
      sql/ckdb.sql
  5. 41
      sql/v0.9.4-v0.9.5.sql
  6. 56
      src/ckdb.c
  7. 118
      src/ckdb.h
  8. 310
      src/ckdb_cmd.c
  9. 73
      src/ckdb_data.c
  10. 151
      src/ckdb_dbio.c

4
pool/page.php

@ -110,8 +110,8 @@ span.err {color:red; font-weight:bold; font-size:120%;}
span.alert {color:red; font-weight:bold; font-size:250%;}
input.tiny {width: 0px; height: 0px; margin: 0px; padding: 0px; outline: none; border: 0px;}
#n42 {margin:0; position: relative; color:#fff; background:#07e;}
#n42 a {color:#fff; text-decoration:none; margin: 4px;}
#n42 td {min-width: 100px; float: left; vertical-align: top; padding: 2px;}
#n42 a {color:#fff; text-decoration:none; padding: 6px; display:block;}
#n42 td {min-width: 100px; float: left; vertical-align: top; padding: 0px 2px;}
#n42 td.navboxr {float: right;}
#n42 td.nav {position: relative;}
#n42 div.sub {left: 0px; z-index: 42; position: absolute; visibility: hidden;}

24
pool/page_pplns.php

@ -14,7 +14,7 @@ function stnum($num)
return $b4.$fmt.$af;
}
#
# ... Of course ... check the output and add the txin
# ... Of course ... check the output and add the txin ... etc.
function calctx($ans, $count, $miner_sat, $diffacc_total)
{
$pg = '<br><table cellpadding=0 cellspacing=0 border=0>';
@ -159,6 +159,7 @@ Block: <input type=text name=blk size=10 value='$blkuse'>
$ans['miner_sat'] = $miner_sat;
$data = array( 'Block' => 'block',
'Block Status' => 'block_status',
'Block Hash' => 'block_hash',
'Block Reward (Satoshis)' => 'block_reward',
'Miner Reward (Satoshis)' => 'miner_sat',
@ -178,10 +179,29 @@ Block: <input type=text name=blk size=10 value='$blkuse'>
'Network Difficulty' => 'block_ndiff',
'PPLNS Factor' => 'diff_times',
'PPLNS Added' => 'diff_add',
'Share Count' => 'share_count');
'Accepted Share Count' => 'acc_share_count',
'Total Share Count' => 'total_share_count',
'ShareSummary Count' => 'ss_count',
'WorkMarkers Count' => 'wm_count',
'MarkerSummary Count' => 'ms_count');
$pg = '<br><a href=https://blockchain.info/block-height/';
$pg .= $ans['block'].'>Blockchain '.$ans['block']."</a><br>\n";
if (strlen($ans['block_extra']) > 0)
{
$pg .= '<br><span class=err>';
$msg = $ans['block_status'].' - '.$ans['block_extra'];
$pg .= str_replace(' ', '&nbsp;', $msg)."</span><br>\n";
}
if (strlen($ans['share_status']) > 0)
{
$pg .= '<br><span class=err>';
$msg = $ans['share_status']." - Can't be paid out yet";
$pg .= str_replace(' ', '&nbsp;', $msg)."</span><br>\n";
}
$pg .= "<br><table callpadding=0 cellspacing=0 border=0>\n";
$pg .= '<tr class=title>';
$pg .= '<td class=dl>Name</td>';

5
pool/prime.php

@ -69,8 +69,9 @@ function check()
'API' => 'api'
),
'Help' => array(
'Help' => 'help',
'Payouts' => 'payout'
'Payouts' => 'payout',
'Workers ' => 'workers',
'Blocks' => 'blocks'
)
);
tryLogInOut();

19
sql/ckdb.sql

@ -251,6 +251,21 @@ CREATE TABLE sharesummary ( -- per workinfo for each user+worker
);
CREATE TABLE marks ( -- workinfoids to make workmarkers
poolinstance character varying(256) NOT NULL,
workinfoid bigint NOT NULL,
description character varying(256) DEFAULT ''::character varying NOT NULL,
marktype char NOT NULL, -- 'b'lock 'p'plns-begin 's'hift-begin 'e'=shift-end
status char NOT NULL,
createdate timestamp with time zone NOT NULL,
createby character varying(64) DEFAULT ''::character varying NOT NULL,
createcode character varying(128) DEFAULT ''::character varying NOT NULL,
createinet character varying(128) DEFAULT ''::character varying NOT NULL,
expirydate timestamp with time zone DEFAULT '6666-06-06 06:06:06+00',
PRIMARY KEY (poolinstance, workinfoid, expirydate)
);
CREATE TABLE workmarkers ( -- range of workinfo for share accounting
markerid bigint NOT NULL,
poolinstance character varying(256) NOT NULL,
@ -263,7 +278,7 @@ CREATE TABLE workmarkers ( -- range of workinfo for share accounting
createcode character varying(128) DEFAULT ''::character varying NOT NULL,
createinet character varying(128) DEFAULT ''::character varying NOT NULL,
expirydate timestamp with time zone DEFAULT '6666-06-06 06:06:06+00',
PRIMARY KEY (markerid)
PRIMARY KEY (markerid, expirydate)
);
@ -417,4 +432,4 @@ CREATE TABLE version (
PRIMARY KEY (vlock)
);
insert into version (vlock,version) values (1,'0.9.4');
insert into version (vlock,version) values (1,'0.9.5');

41
sql/v0.9.4-v0.9.5.sql

@ -0,0 +1,41 @@
SET SESSION AUTHORIZATION 'postgres';
BEGIN transaction;
DO $$
DECLARE ver TEXT;
BEGIN
UPDATE version set version='0.9.5' where vlock=1 and version='0.9.4';
IF found THEN
RETURN;
END IF;
SELECT version into ver from version
WHERE vlock=1;
RAISE EXCEPTION 'Wrong DB version - expect "0.9.4" - found "%"', ver;
END $$;
CREATE TABLE marks ( -- workinfoids to make workmarkers
poolinstance character varying(256) NOT NULL,
workinfoid bigint NOT NULL,
description character varying(256) DEFAULT ''::character varying NOT NULL,
marktype char NOT NULL, -- 'b'lock(end) 'p'plns-begin 's'hift-begin 'e'=shift-end
status char NOT NULL,
createdate timestamp with time zone NOT NULL,
createby character varying(64) DEFAULT ''::character varying NOT NULL,
createcode character varying(128) DEFAULT ''::character varying NOT NULL,
createinet character varying(128) DEFAULT ''::character varying NOT NULL,
expirydate timestamp with time zone DEFAULT '6666-06-06 06:06:06+00',
PRIMARY KEY (poolinstance, workinfoid, expirydate)
);
ALTER TABLE workmarkers DROP CONSTRAINT workmarkers_pkey;
ALTER TABLE workmarkers ADD CONSTRAINT workmarkers_pkey
PRIMARY KEY (markerid, expirydate);
END transaction;

56
src/ckdb.c

@ -174,8 +174,12 @@ const char *mailpatt = "^[A-Za-z0-9_-][A-Za-z0-9_\\.-]*@[A-Za-z0-9][A-Za-z0-9\\.
const char *idpatt = "^[_A-Za-z][_A-Za-z0-9]*$";
const char *intpatt = "^[0-9][0-9]*$";
const char *hashpatt = "^[A-Fa-f0-9]*$";
// TODO: bitcoind will check it properly
const char *addrpatt = "^[A-Za-z0-9]*$";
/* BTC addresses start with '1' (one) or '3' (three),
* exclude: capital 'I' (eye), capital 'O' (oh),
* lowercase 'l' (elle) and '0' (zero)
* and with a simple test must be ADDR_MIN_LEN to ADDR_MAX_LEN (ckdb.h)
* bitcoind is used to fully validate them when required */
const char *addrpatt = "^[13][A-HJ-NP-Za-km-z1-9]*$";
// So the records below have the same 'name' as the klist
const char Transfer[] = "Transfer";
@ -268,6 +272,8 @@ static tv_t reload_timestamp;
* workinfo and sharesummary */
int64_t dbload_workinfoid_start = -1;
int64_t dbload_workinfoid_finish = MAXID;
// Only restrict sharesummary, not workinfo
bool dbload_only_sharesummary = false;
// DB users,workers,auth load is complete
bool db_auths_complete = false;
@ -449,6 +455,11 @@ K_TREE *workmarkers_workinfoid_root;
K_LIST *workmarkers_free;
K_STORE *workmarkers_store;
// MARKS
K_TREE *marks_root;
K_LIST *marks_free;
K_STORE *marks_store;
static char logname[512];
static char *dbcode;
@ -728,6 +739,8 @@ static bool getdata3()
}
if (!(ok = workinfo_fill(conn)) || everyone_die)
goto sukamudai;
if (!(ok = marks_fill(conn)) || everyone_die)
goto sukamudai;
if (!(ok = workmarkers_fill(conn)) || everyone_die)
goto sukamudai;
if (!(ok = markersummary_fill(conn)) || everyone_die)
@ -1030,6 +1043,11 @@ static void alloc_storage()
workmarkers_root = new_ktree();
workmarkers_workinfoid_root = new_ktree();
workmarkers_free->dsp_func = dsp_workmarkers;
marks_free = k_new_list("Marks", sizeof(MARKS),
ALLOC_MARKS, LIMIT_MARKS, true);
marks_store = k_new_store(workmarkers_free);
marks_root = new_ktree();
}
static void free_workinfo_data(K_ITEM *item)
@ -1048,6 +1066,11 @@ static void free_sharesummary_data(K_ITEM *item)
SHARESUMMARY *sharesummary;
DATA_SHARESUMMARY(sharesummary, item);
if (sharesummary->workername) {
LIST_MEM_SUB(sharesummary_free, sharesummary->workername);
free(sharesummary->workername);
sharesummary->workername = NULL;
}
SET_CREATEBY(sharesummary_free, sharesummary->createby, EMPTY);
SET_CREATECODE(sharesummary_free, sharesummary->createcode, EMPTY);
SET_CREATEINET(sharesummary_free, sharesummary->createinet, EMPTY);
@ -1131,6 +1154,8 @@ static void dealloc_storage()
{
FREE_LISTS(logqueue);
FREE_ALL(marks);
FREE_TREE(workmarkers_workinfoid);
FREE_TREE(workmarkers);
FREE_STORE_DATA(workmarkers);
@ -1212,6 +1237,8 @@ static bool setup_data()
if (dbload_workinfoid_start != -1) {
LOGWARNING("WARNING: dbload starting at workinfoid %"PRId64,
dbload_workinfoid_start);
if (dbload_only_sharesummary)
LOGWARNING("NOTICE: dbload only restricting sharesummary");
}
if (!getdata3() || everyone_die)
@ -1586,7 +1613,7 @@ static void summarise_blocks()
// Add up the sharesummaries, abort if any SUMMARY_NEW
looksharesummary.workinfoid = wi_finish;
looksharesummary.userid = MAXID;
looksharesummary.workername[0] = '\0';
looksharesummary.workername = EMPTY;
INIT_SHARESUMMARY(&ss_look);
ss_look.data = (void *)(&looksharesummary);
@ -1652,7 +1679,7 @@ static void summarise_blocks()
if (WMREADY(workmarkers->status)) {
lookmarkersummary.markerid = workmarkers->markerid;
lookmarkersummary.userid = MAXID;
lookmarkersummary.workername[0] = '\0';
lookmarkersummary.workername = EMPTY;
INIT_MARKERSUMMARY(&ms_look);
ms_look.data = (void *)(&lookmarkersummary);
ms_item = find_before_in_ktree(markersummary_root, &ms_look,
@ -2048,6 +2075,7 @@ static void *socketer(__maybe_unused void *arg)
char *last_newid = NULL, *reply_newid = NULL;
char *last_setatts = NULL, *reply_setatts = NULL;
char *last_setopts = NULL, *reply_setopts = NULL;
char *last_userstatus = NULL, *reply_userstatus = NULL;
char *last_web = NULL, *reply_web = NULL;
char *reply_last, duptype[CMD_SIZ+1];
enum cmd_values cmdnum;
@ -2151,6 +2179,9 @@ static void *socketer(__maybe_unused void *arg)
} else if (last_setopts && strcmp(last_setopts, buf) == 0) {
reply_last = reply_setopts;
dup = true;
} else if (last_userstatus && strcmp(last_userstatus, buf) == 0) {
reply_last = reply_userstatus;
dup = true;
} else if (last_web && strcmp(last_web, buf) == 0) {
reply_last = reply_web;
dup = true;
@ -2251,6 +2282,7 @@ static void *socketer(__maybe_unused void *arg)
case CMD_BLOCKLIST:
case CMD_NEWID:
case CMD_STATS:
case CMD_USERSTATUS:
ans = ckdb_cmds[which_cmds].func(NULL, cmd, id, &now,
by_default,
(char *)__func__,
@ -2293,6 +2325,9 @@ static void *socketer(__maybe_unused void *arg)
case CMD_SETOPTS:
STORELASTREPLY(setopts);
break;
case CMD_USERSTATUS:
STORELASTREPLY(userstatus);
break;
// The rest
default:
free(rep);
@ -2499,6 +2534,7 @@ static bool reload_line(PGconn *conn, char *filename, uint64_t count, char *buf)
case CMD_DSP:
case CMD_STATS:
case CMD_PPLNS:
case CMD_USERSTATUS:
LOGERR("%s() Message line %"PRIu64" '%s' - invalid - ignored",
__func__, count, cmd);
break;
@ -2854,7 +2890,7 @@ static void compare_summaries(K_TREE *leftsum, char *leftname,
looksharesummary.workinfoid = confirm_first_workinfoid;
looksharesummary.userid = -1;
looksharesummary.workername[0] = '\0';
looksharesummary.workername = EMPTY;
INIT_SHARESUMMARY(&look);
look.data = (void *)(&looksharesummary);
@ -3535,7 +3571,15 @@ int main(int argc, char **argv)
case 'w':
// Don't use this :)
{
int64_t start = atoll(optarg);
char *ptr = optarg;
int64_t start;
if (*ptr == 's') {
dbload_only_sharesummary = true;
ptr++;
}
start = atoll(ptr);
if (start < 0) {
quit(1, "Invalid workinfoid start"
" %"PRId64" - must be >= 0",

118
src/ckdb.h

@ -51,8 +51,8 @@
*/
#define DB_VLOCK "1"
#define DB_VERSION "0.9.4"
#define CKDB_VERSION DB_VERSION"-0.631"
#define DB_VERSION "0.9.5"
#define CKDB_VERSION DB_VERSION"-0.652"
#define WHERE_FFL " - from %s %s() line %d"
#define WHERE_FFL_HERE __FILE__, __func__, __LINE__
@ -80,6 +80,14 @@ extern const char *intpatt;
extern const char *hashpatt;
extern const char *addrpatt;
/* If a trimmed username is like an address but this many or more characters,
* disallow it */
#define ADDR_USER_CHECK 16
// BTC address size
#define ADDR_MIN_LEN 26
#define ADDR_MAX_LEN 34
typedef struct loadstatus {
tv_t oldest_sharesummary_firstshare_n;
tv_t newest_sharesummary_firstshare_a;
@ -232,6 +240,8 @@ extern int64_t confirm_last_workinfoid;
* workinfo and sharesummary */
extern int64_t dbload_workinfoid_start;
extern int64_t dbload_workinfoid_finish;
// Only restrict sharesummary, not workinfo
extern bool dbload_only_sharesummary;
// DB users,workers,auth load is complete
extern bool db_auths_complete;
@ -295,6 +305,7 @@ enum cmd_values {
CMD_DSP,
CMD_STATS,
CMD_PPLNS,
CMD_USERSTATUS,
CMD_END
};
@ -338,15 +349,26 @@ enum cmd_values {
// The size strdup will allocate multiples of
#define MEMBASE 4
#define LIST_MEM_ADD(_list, _fld) do { \
size_t __siz; \
__siz = strlen(_fld) + 1; \
if (__siz % MEMBASE) \
__siz += MEMBASE - (__siz % MEMBASE); \
_list->ram += (int)__siz; \
} while (0)
#define LIST_MEM_SUB(_list, _fld) do { \
size_t __siz; \
__siz = strlen(_fld) + 1; \
if (__siz % MEMBASE) \
__siz += MEMBASE - (__siz % MEMBASE); \
_list->ram -= (int)__siz; \
} while (0)
#define SET_POINTER(_list, _fld, _val, _def) do { \
size_t _siz; \
if ((_fld) && ((_fld) != EMPTY) && ((_fld) != (_def))) { \
if (_list) { \
_siz = strlen(_fld) + 1; \
if (_siz % MEMBASE) \
_siz += MEMBASE - (_siz % MEMBASE); \
_list->ram -= (int)_siz; \
} \
if (_list) \
LIST_MEM_SUB(_list, _fld); \
free(_fld); \
} \
if (!(_val) || !(*(_val))) \
@ -355,12 +377,8 @@ enum cmd_values {
if (((_val) == (_def)) || (strcmp(_val, _def) == 0)) \
(_fld) = (_def); \
else { \
if (_list) { \
_siz = strlen(_val) + 1; \
if (_siz % MEMBASE) \
_siz += MEMBASE - (_siz % MEMBASE); \
_list->ram += (int)_siz; \
} \
if (_list) \
LIST_MEM_ADD(_list, _val); \
_fld = strdup(_val); \
if (!(_fld)) \
quithere(1, "malloc OOM"); \
@ -603,9 +621,10 @@ typedef struct transfer {
char *mvalue;
} TRANSFER;
#define ALLOC_TRANSFER 64
// Suggest malloc use MMAP - 1913 = largest under 2MB
#define ALLOC_TRANSFER 1913
#define LIMIT_TRANSFER 0
#define CULL_TRANSFER 1024
#define CULL_TRANSFER 16
#define INIT_TRANSFER(_item) INIT_GENERIC(_item, transfer)
#define DATA_TRANSFER(_var, _item) DATA_GENERIC(_var, _item, transfer, true)
@ -632,7 +651,7 @@ typedef struct users {
int64_t userid;
char username[TXT_BIG+1];
char usertrim[TXT_BIG+1]; // Non DB field
// TODO: Anything in 'status' disables the account
// Anything in 'status' fails mining authentication
char status[TXT_BIG+1];
char emailaddress[TXT_BIG+1];
tv_t joineddate;
@ -926,7 +945,7 @@ extern K_STORE *shareerrors_store;
// SHARESUMMARY
typedef struct sharesummary {
int64_t userid;
char workername[TXT_BIG+1];
char *workername;
int64_t workinfoid;
double diffacc;
double diffsta;
@ -1323,6 +1342,58 @@ extern K_STORE *workmarkers_store;
#define MARKER_COMPLETE 'x'
#define WMREADY(_status) (tolower(_status[0]) == MARKER_COMPLETE)
// MARKS
// TODO: implement
typedef struct marks {
char *poolinstance;
int64_t workinfoid;
char *description;
char marktype[TXT_FLAG+1];
char status[TXT_FLAG+1];
HISTORYDATECONTROLFIELDS;
} MARKS;
/* Marks:
* marktype is one of:
* b - block end
* p - pplns begin
* s - shift begin (not yet used)
* e - shift end (not yet used)
* description should one one of
* b - Block NNN stt
* p - Payout NNN fin (where NNN is the block number of the payout)
* s/e - to be decided
*
* WorkMarkers are from a begin workinfoid to an end workinfoid
* the "-1" and "+1" below mean adding to or subtracting from
* the workinfoid number
*
* Until we start using shifts:
* WorkMarkers can be created up to ending in the largest 'p' "-1"
* WorkMarkers will always be the smallest of:
* Block NNN-1 "+1" to Block NNN
* Block NNN "+1" to Payout MMM "-1"
* Payout MMM to Block NNN
* Payout MMM-1 to Payout MMM "-1"
* Thus to generate the WorkMarkers from the Marks:
* Find the last 'p' with no matching workinfoidbegin
* Then determine each previous WorkMarker based on each previous
* mark, using the above rules and stop when we find one that already exists
*/
#define ALLOC_MARKS 1000
#define LIMIT_MARKS 0
#define INIT_MARKS(_item) INIT_GENERIC(_item, marks)
#define DATA_MARKS(_var, _item) DATA_GENERIC(_var, _item, marks, true)
#define DATA_MARKS_NULL(_var, _item) DATA_GENERIC(_var, _item, marks, false)
extern K_TREE *marks_root;
extern K_LIST *marks_free;
extern K_STORE *marks_store;
#define MARK_READY 'x'
#define MREADY(_status) (tolower(_status[0]) == MARK_READY)
extern void logmsg(int loglevel, const char *fmt, ...);
extern void setnow(tv_t *now);
extern void tick();
@ -1334,6 +1405,7 @@ extern PGconn *dbconnect();
extern char *safe_text(char *txt);
extern void username_trim(USERS *users);
extern bool like_address(char *username);
extern void _txt_to_data(enum data_type typ, char *nam, char *fld, void *data, size_t siz, WHERE_FFL_ARGS);
@ -1487,6 +1559,7 @@ extern cmp_t cmp_workmarkers(K_ITEM *a, K_ITEM *b);
extern cmp_t cmp_workmarkers_workinfoid(K_ITEM *a, K_ITEM *b);
extern K_ITEM *find_workmarkers(int64_t workinfoid);
extern K_ITEM *find_workmarkerid(int64_t markerid);
extern cmp_t cmp_marks(K_ITEM *a, K_ITEM *b);
// ***
// *** PostgreSQL functions ckdb_dbio.c
@ -1534,9 +1607,9 @@ extern char *pqerrmsg(PGconn *conn);
extern int64_t nextid(PGconn *conn, char *idname, int64_t increment,
tv_t *cd, char *by, char *code, char *inet);
extern bool users_pass_email(PGconn *conn, K_ITEM *u_item, char *oldhash,
char *newhash, char *email, char *by, char *code,
char *inet, tv_t *cd, K_TREE *trf_root);
extern bool users_update(PGconn *conn, K_ITEM *u_item, char *oldhash,
char *newhash, char *email, char *by, char *code,
char *inet, tv_t *cd, K_TREE *trf_root, char *status);
extern K_ITEM *users_add(PGconn *conn, char *username, char *emailaddress,
char *passwordhash, char *by, char *code, char *inet,
tv_t *cd, K_TREE *trf_root);
@ -1630,6 +1703,7 @@ extern bool userstats_add(char *poolinstance, char *elapsed, char *username,
extern bool userstats_fill(PGconn *conn);
extern bool markersummary_fill(PGconn *conn);
extern bool workmarkers_fill(PGconn *conn);
extern bool marks_fill(PGconn *conn);
extern bool check_db_version(PGconn *conn);
// ***

310
src/ckdb_cmd.c

@ -15,7 +15,7 @@ static char *cmd_adduser(PGconn *conn, char *cmd, char *id, tv_t *now, char *by,
{
char reply[1024] = "";
size_t siz = sizeof(reply);
K_ITEM *i_username, *i_emailaddress, *i_passwordhash, *u_item;
K_ITEM *i_username, *i_emailaddress, *i_passwordhash, *u_item = NULL;
LOGDEBUG("%s(): cmd '%s'", __func__, cmd);
@ -23,18 +23,30 @@ static char *cmd_adduser(PGconn *conn, char *cmd, char *id, tv_t *now, char *by,
if (!i_username)
return strdup(reply);
i_emailaddress = require_name(trf_root, "emailaddress", 7, (char *)mailpatt, reply, siz);
if (!i_emailaddress)
return strdup(reply);
/* If a username added from the web site looks like an address
* then disallow it - a false positive is not an issue
* Allowing it will create a security issue - someone could create
* an account with someone else's, as yet unused, payout address
* and redirect the payout to another payout address.
* ... and the person who owns the payout address can't check that
* in advance, they'll just find out with their first payout not
* arriving at their payout address */
if (!like_address(transfer_data(i_username))) {
i_emailaddress = require_name(trf_root, "emailaddress", 7,
(char *)mailpatt, reply, siz);
if (!i_emailaddress)
return strdup(reply);
i_passwordhash = require_name(trf_root, "passwordhash", 64, (char *)hashpatt, reply, siz);
if (!i_passwordhash)
return strdup(reply);
i_passwordhash = require_name(trf_root, "passwordhash", 64,
(char *)hashpatt, reply, siz);
if (!i_passwordhash)
return strdup(reply);
u_item = users_add(conn, transfer_data(i_username),
transfer_data(i_emailaddress),
transfer_data(i_passwordhash),
by, code, inet, now, trf_root);
u_item = users_add(conn, transfer_data(i_username),
transfer_data(i_emailaddress),
transfer_data(i_passwordhash),
by, code, inet, now, trf_root);
}
if (!u_item) {
LOGERR("%s() %s.failed.DBE", __func__, id);
@ -85,12 +97,13 @@ static char *cmd_newpass(__maybe_unused PGconn *conn, char *cmd, char *id,
K_RUNLOCK(users_free);
if (u_item) {
ok = users_pass_email(NULL, u_item,
oldhash,
transfer_data(i_newhash),
NULL,
by, code, inet, now,
trf_root);
ok = users_update(NULL, u_item,
oldhash,
transfer_data(i_newhash),
NULL,
by, code, inet, now,
trf_root,
NULL);
} else
ok = false;
}
@ -223,7 +236,8 @@ static char *cmd_userset(PGconn *conn, char *cmd, char *id,
email = NULL;
}
i_address = optional_name(trf_root, "address",
27, (char *)addrpatt,
ADDR_MIN_LEN,
(char *)addrpatt,
reply, siz);
if (i_address)
address = transfer_data(i_address);
@ -248,10 +262,12 @@ static char *cmd_userset(PGconn *conn, char *cmd, char *id,
}
if (email && *email) {
ok = users_pass_email(conn, u_item, NULL,
NULL, email,
by, code, inet,
now, trf_root);
ok = users_update(conn, u_item,
NULL, NULL,
email,
by, code, inet, now,
trf_root,
NULL);
if (!ok) {
reason = "email error";
goto struckout;
@ -2909,6 +2925,9 @@ static K_TREE *upd_add_mu(K_TREE *mu_root, K_STORE *mu_store, int64_t userid, in
(also summarising diffacc per user)
then keep stepping back until we complete the current begin_workinfoid
(also summarising diffacc per user)
While we are still below diff_want
find each workmarker and add on the full set of worksummary
diffacc shares (also summarising diffacc per user)
This will give us the total number of diff1 shares (diffacc_total)
to use for the payment calculations
The value of diff_want defaults to the block's network difficulty
@ -2922,21 +2941,26 @@ static K_TREE *upd_add_mu(K_TREE *mu_root, K_STORE *mu_store, int64_t userid, in
diffacc_user * 2^32 / pplns_elapsed
PPLNS fraction of the payout would be:
diffacc_user / diffacc_total
N.B. 'begin' means the oldest back in time and 'end' means the newest
'end' should usually be the info of the found block with the pplns
data going back in time to 'begin'
*/
/* TODO: redesign to include workmarkers
* ... before next payout that extends into a markersummary ... */
static char *cmd_pplns(__maybe_unused PGconn *conn, char *cmd, char *id,
__maybe_unused tv_t *now, __maybe_unused char *by,
__maybe_unused char *code, __maybe_unused char *inet,
__maybe_unused tv_t *notcd, K_TREE *trf_root)
{
char reply[1024], tmp[1024], *buf;
char reply[1024], tmp[1024], *buf, *block_extra, *share_status = EMPTY;
size_t siz = sizeof(reply);
K_ITEM *i_height, *i_difftimes, *i_diffadd, *i_allowaged;
K_ITEM b_look, ss_look, *b_item, *w_item, *ss_item;
K_ITEM wm_look, *wm_item, ms_look, *ms_item;
K_ITEM *mu_item, *wb_item, *u_item;
SHARESUMMARY looksharesummary, *sharesummary;
WORKMARKERS lookworkmarkers, *workmarkers;
MARKERSUMMARY lookmarkersummary, *markersummary;
MININGPAYOUTS *miningpayouts;
WORKINFO *workinfo;
TRANSFER *transfer;
@ -2945,13 +2969,14 @@ static char *cmd_pplns(__maybe_unused PGconn *conn, char *cmd, char *id,
K_STORE *mu_store;
USERS *users;
int32_t height;
int64_t workinfoid, end_workinfoid;
int64_t workinfoid, end_workinfoid = 0;
int64_t begin_workinfoid;
int64_t share_count;
int64_t total_share_count, acc_share_count;
int64_t ss_count, wm_count, ms_count;
char tv_buf[DATE_BUFSIZ];
tv_t cd, begin_tv, block_tv, end_tv;
K_TREE_CTX ctx[1];
double ndiff, total, elapsed;
K_TREE_CTX ctx[1], wm_ctx[1], ms_ctx[1];
double ndiff, total_diff, elapsed;
double diff_times = 1.0;
double diff_add = 0.0;
double diff_want;
@ -2982,6 +3007,7 @@ static char *cmd_pplns(__maybe_unused PGconn *conn, char *cmd, char *id,
allow_aged = true;
}
block_tv.tv_sec = block_tv.tv_usec = 0L;
cd.tv_sec = cd.tv_usec = 0L;
lookblocks.height = height + 1;
lookblocks.blockhash[0] = '\0';
@ -2996,20 +3022,39 @@ static char *cmd_pplns(__maybe_unused PGconn *conn, char *cmd, char *id,
}
DATA_BLOCKS_NULL(blocks, b_item);
while (b_item && blocks->height == height) {
if (blocks->confirmed[0] == BLOCKS_CONFIRM)
if (blocks->confirmed[0] == BLOCKS_NEW) {
copy_tv(&block_tv, &(blocks->createdate));
copy_tv(&end_tv, &(blocks->createdate));
}
// Allow any state, but report it
if (CURRENT(&(blocks->expirydate)))
break;
b_item = prev_in_ktree(ctx);
DATA_BLOCKS_NULL(blocks, b_item);
}
K_RUNLOCK(blocks_free);
if (!b_item || blocks->height != height) {
snprintf(reply, siz, "ERR.unconfirmed block %d", height);
snprintf(reply, siz, "ERR.no CURRENT block %d", height);
return strdup(reply);
}
if (block_tv.tv_sec == 0) {
snprintf(reply, siz, "ERR.block %d missing '%s' record",
height,
blocks_confirmed(BLOCKS_NEW_STR));
return strdup(reply);
}
switch (blocks->confirmed[0]) {
case BLOCKS_NEW:
block_extra = "Can't be paid out yet";
break;
case BLOCKS_ORPHAN:
block_extra = "Can't be paid out";
break;
default:
block_extra = EMPTY;
break;
}
workinfoid = blocks->workinfoid;
copy_tv(&block_tv, &(blocks->createdate));
copy_tv(&end_tv, &(blocks->createdate));
w_item = find_workinfo(workinfoid);
if (!w_item) {
snprintf(reply, siz, "ERR.missing workinfo %"PRId64, workinfoid);
@ -3028,34 +3073,30 @@ static char *cmd_pplns(__maybe_unused PGconn *conn, char *cmd, char *id,
}
begin_workinfoid = 0;
share_count = 0;
total = 0;
total_share_count = acc_share_count = 0;
total_diff = 0;
ss_count = wm_count = ms_count = 0;
mu_store = k_new_store(miningpayouts_free);
mu_root = new_ktree();
looksharesummary.workinfoid = workinfoid;
looksharesummary.userid = MAXID;
looksharesummary.workername[0] = '\0';
looksharesummary.workername = EMPTY;
INIT_SHARESUMMARY(&ss_look);
ss_look.data = (void *)(&looksharesummary);
K_RLOCK(sharesummary_free);
K_RLOCK(workmarkers_free);
K_RLOCK(markersummary_free);
ss_item = find_before_in_ktree(sharesummary_workinfoid_root, &ss_look,
cmp_sharesummary_workinfoid, ctx);
if (!ss_item) {
K_RUNLOCK(sharesummary_free);
snprintf(reply, siz,
"ERR.no shares found with or before "
"workinfo %"PRId64,
workinfoid);
return strdup(reply);
}
DATA_SHARESUMMARY(sharesummary, ss_item);
mu_store = k_new_store(miningpayouts_free);
mu_root = new_ktree();
end_workinfoid = sharesummary->workinfoid;
DATA_SHARESUMMARY_NULL(sharesummary, ss_item);
if (ss_item)
end_workinfoid = sharesummary->workinfoid;
/* add up all sharesummaries until >= diff_want
* also record the latest lastshare - that will be the end pplns time
* which will be >= block_tv */
while (ss_item && total < diff_want) {
while (total_diff < diff_want && ss_item) {
switch (sharesummary->complete[0]) {
case SUMMARY_CONFIRM:
break;
@ -3063,15 +3104,12 @@ static char *cmd_pplns(__maybe_unused PGconn *conn, char *cmd, char *id,
if (allow_aged)
break;
default:
K_RUNLOCK(sharesummary_free);
snprintf(reply, siz,
"ERR.sharesummary1 not ready in "
"workinfo %"PRId64,
sharesummary->workinfoid);
goto shazbot;
share_status = "Not ready1";
}
share_count++;
total += (int64_t)(sharesummary->diffacc);
ss_count++;
total_share_count += sharesummary->sharecount;
acc_share_count += sharesummary->shareacc;
total_diff += (int64_t)(sharesummary->diffacc);
begin_workinfoid = sharesummary->workinfoid;
if (tv_newer(&end_tv, &(sharesummary->lastshare)))
copy_tv(&end_tv, &(sharesummary->lastshare));
@ -3091,24 +3129,71 @@ static char *cmd_pplns(__maybe_unused PGconn *conn, char *cmd, char *id,
if (allow_aged)
break;
default:
K_RUNLOCK(sharesummary_free);
snprintf(reply, siz,
"ERR.sharesummary2 not ready in "
"workinfo %"PRId64,
sharesummary->workinfoid);
goto shazbot;
if (share_status == EMPTY)
share_status = "Not ready2";
else
share_status = "Not ready1+2";
}
share_count++;
total += (int64_t)(sharesummary->diffacc);
ss_count++;
total_share_count += sharesummary->sharecount;
acc_share_count += sharesummary->shareacc;
total_diff += (int64_t)(sharesummary->diffacc);
mu_root = upd_add_mu(mu_root, mu_store,
sharesummary->userid,
(int64_t)(sharesummary->diffacc));
ss_item = prev_in_ktree(ctx);
DATA_SHARESUMMARY_NULL(sharesummary, ss_item);
}
/* If we haven't met or exceeded the required N,
* move on to the markersummaries */
if (total_diff < diff_want) {
lookworkmarkers.expirydate.tv_sec = default_expiry.tv_sec;
lookworkmarkers.expirydate.tv_usec = default_expiry.tv_usec;
lookworkmarkers.workinfoidend = begin_workinfoid;
INIT_WORKMARKERS(&wm_look);
wm_look.data = (void *)(&lookworkmarkers);
wm_item = find_before_in_ktree(workmarkers_workinfoid_root, &wm_look,
cmp_workmarkers_workinfoid, wm_ctx);
DATA_WORKMARKERS_NULL(workmarkers, wm_item);
while (total_diff < diff_want && wm_item && CURRENT(&(workmarkers->expirydate))) {
if (WMREADY(workmarkers->status)) {
wm_count++;
lookmarkersummary.markerid = workmarkers->markerid;
lookmarkersummary.userid = MAXID;
lookmarkersummary.workername = EMPTY;
INIT_MARKERSUMMARY(&ms_look);
ms_look.data = (void *)(&lookmarkersummary);
ms_item = find_before_in_ktree(markersummary_root, &ms_look,
cmp_markersummary, ms_ctx);
DATA_MARKERSUMMARY_NULL(markersummary, ms_item);
// add the whole markerid
while (ms_item && markersummary->markerid == workmarkers->markerid) {
if (end_workinfoid == 0)
end_workinfoid = workmarkers->workinfoidend;
ms_count++;
total_share_count += markersummary->sharecount;
acc_share_count += markersummary->shareacc;
total_diff += (int64_t)(markersummary->diffacc);
begin_workinfoid = workmarkers->workinfoidstart;
if (tv_newer(&end_tv, &(markersummary->lastshare)))
copy_tv(&end_tv, &(markersummary->lastshare));
mu_root = upd_add_mu(mu_root, mu_store,
markersummary->userid,
(int64_t)(markersummary->diffacc));
ms_item = prev_in_ktree(ms_ctx);
DATA_MARKERSUMMARY_NULL(markersummary, ms_item);
}
}
wm_item = prev_in_ktree(wm_ctx);
DATA_WORKMARKERS_NULL(workmarkers, wm_item);
}
}
K_RUNLOCK(markersummary_free);
K_RUNLOCK(workmarkers_free);
K_RUNLOCK(sharesummary_free);
if (total == 0.0) {
if (total_diff == 0.0) {
snprintf(reply, siz,
"ERR.total share diff 0 before workinfo %"PRId64,
workinfoid);
@ -3140,6 +3225,13 @@ static char *cmd_pplns(__maybe_unused PGconn *conn, char *cmd, char *id,
APPEND_REALLOC(buf, off, len, tmp);
snprintf(tmp, sizeof(tmp), "block_reward=%"PRId64"%c", blocks->reward, FLDSEP);
APPEND_REALLOC(buf, off, len, tmp);
snprintf(tmp, sizeof(tmp), "block_status=%s%c",
blocks_confirmed(blocks->confirmed), FLDSEP);
APPEND_REALLOC(buf, off, len, tmp);
snprintf(tmp, sizeof(tmp), "block_extra=%s%c", block_extra, FLDSEP);
APPEND_REALLOC(buf, off, len, tmp);
snprintf(tmp, sizeof(tmp), "share_status=%s%c", share_status, FLDSEP);
APPEND_REALLOC(buf, off, len, tmp);
snprintf(tmp, sizeof(tmp), "workername=%s%c", blocks->workername, FLDSEP);
APPEND_REALLOC(buf, off, len, tmp);
snprintf(tmp, sizeof(tmp), "nonce=%s%c", blocks->nonce, FLDSEP);
@ -3150,7 +3242,7 @@ static char *cmd_pplns(__maybe_unused PGconn *conn, char *cmd, char *id,
APPEND_REALLOC(buf, off, len, tmp);
snprintf(tmp, sizeof(tmp), "end_workinfoid=%"PRId64"%c", end_workinfoid, FLDSEP);
APPEND_REALLOC(buf, off, len, tmp);
snprintf(tmp, sizeof(tmp), "diffacc_total=%.0f%c", total, FLDSEP);
snprintf(tmp, sizeof(tmp), "diffacc_total=%.0f%c", total_diff, FLDSEP);
APPEND_REALLOC(buf, off, len, tmp);
snprintf(tmp, sizeof(tmp), "pplns_elapsed=%f%c", elapsed, FLDSEP);
APPEND_REALLOC(buf, off, len, tmp);
@ -3233,7 +3325,17 @@ static char *cmd_pplns(__maybe_unused PGconn *conn, char *cmd, char *id,
APPEND_REALLOC(buf, off, len, tmp);
snprintf(tmp, sizeof(tmp), "diff_want=%f%c", diff_want, FLDSEP);
APPEND_REALLOC(buf, off, len, tmp);
snprintf(tmp, sizeof(tmp), "share_count=%"PRId64, share_count);
snprintf(tmp, sizeof(tmp), "acc_share_count=%"PRId64"%c",
acc_share_count, FLDSEP);
APPEND_REALLOC(buf, off, len, tmp);
snprintf(tmp, sizeof(tmp), "total_share_count=%"PRId64"%c",
total_share_count, FLDSEP);
APPEND_REALLOC(buf, off, len, tmp);
snprintf(tmp, sizeof(tmp), "ss_count=%"PRId64"%c", ss_count, FLDSEP);
APPEND_REALLOC(buf, off, len, tmp);
snprintf(tmp, sizeof(tmp), "wm_count=%"PRId64"%c", wm_count, FLDSEP);
APPEND_REALLOC(buf, off, len, tmp);
snprintf(tmp, sizeof(tmp), "ms_count=%"PRId64, ms_count);
APPEND_REALLOC(buf, off, len, tmp);
mu_root = free_ktree(mu_root, NULL);
@ -3379,6 +3481,69 @@ static char *cmd_stats(__maybe_unused PGconn *conn, char *cmd, char *id,
return buf;
}
// TODO: add to heartbeat to disable the miner if active and status != ""
static char *cmd_userstatus(PGconn *conn, char *cmd, char *id, tv_t *now, char *by,
char *code, char *inet, __maybe_unused tv_t *cd,
K_TREE *trf_root)
{
char reply[1024] = "";
size_t siz = sizeof(reply);
K_ITEM *i_username, *i_userid, *i_status, *u_item;
int64_t userid;
char *status;
USERS *users;
bool ok;
LOGDEBUG("%s(): cmd '%s'", __func__, cmd);
i_username = optional_name(trf_root, "username", 3, (char *)userpatt, reply, siz);
i_userid = optional_name(trf_root, "userid", 1, (char *)intpatt, reply, siz);
// Either username or userid
if (!i_username && !i_userid) {
snprintf(reply, siz, "failed.invalid/missing userinfo");
LOGERR("%s.%s", id, reply);
return strdup(reply);
}
// A zero length status re-enables it
i_status = require_name(trf_root, "status", 0, NULL, reply, siz);
if (!i_status)
return strdup(reply);
status = transfer_data(i_status);
K_RLOCK(users_free);
if (i_username)
u_item = find_users(transfer_data(i_username));
else {
TXT_TO_BIGINT("userid", transfer_data(i_userid), userid);
u_item = find_userid(userid);
}
K_RUNLOCK(users_free);
if (!u_item)
ok = false;
else {
ok = users_update(conn, u_item,
NULL, NULL,
NULL,
by, code, inet, now,
trf_root,
status);
}
if (!ok) {
LOGERR("%s() %s.failed.DBE", __func__, id);
return strdup("failed.DBE");
}
DATA_USERS(users, u_item);
snprintf(reply, siz, "ok.updated %"PRId64" %s status %s",
users->userid,
users->username,
status[0] ? "disabled" : "enabled");
LOGWARNING("%s.%s", id, reply);
return strdup(reply);
}
// TODO: limit access by having seperate sockets for each
#define ACCESS_POOL "p"
#define ACCESS_SYSTEM "s"
@ -3479,7 +3644,8 @@ struct CMDS ckdb_cmds[] = {
{ CMD_GETOPTS, "getopts", false, false, cmd_getopts, ACCESS_WEB },
{ CMD_SETOPTS, "setopts", false, false, cmd_setopts, ACCESS_WEB },
{ CMD_DSP, "dsp", false, false, cmd_dsp, ACCESS_SYSTEM },
{ CMD_STATS, "stats", true, false, cmd_stats, ACCESS_SYSTEM },
{ CMD_PPLNS, "pplns", false, false, cmd_pplns, ACCESS_SYSTEM },
{ CMD_STATS, "stats", true, false, cmd_stats, ACCESS_SYSTEM ACCESS_WEB },
{ CMD_PPLNS, "pplns", false, false, cmd_pplns, ACCESS_SYSTEM ACCESS_WEB },
{ CMD_USERSTATUS,"userstatus", false, false, cmd_userstatus, ACCESS_SYSTEM ACCESS_WEB },
{ CMD_END, NULL, false, false, NULL, NULL }
};

73
src/ckdb_data.c

@ -67,6 +67,55 @@ void username_trim(USERS *users)
}
}
/* Is the trimmed username like an address?
* False positive is OK (i.e. 'like')
* Before checking, it is trimmed to avoid web display confusion
* Length check is done before trimming - this may give a false
* positive on any username with lots of trim characters ... which is OK */
bool like_address(char *username)
{
char *tmp, *front, *trail;
size_t len;
regex_t re;
int ret;
len = strlen(username);
if (len < ADDR_USER_CHECK)
return false;
tmp = strdup(username);
front = tmp;
while (*front && TRIM_IGNORE(*front))
front++;
trail = front + strlen(front) - 1;
while (trail >= front) {
if (TRIM_IGNORE(*trail))
*(trail--) = '\0';
else
break;
}
if (regcomp(&re, addrpatt, REG_NOSUB) != 0) {
LOGEMERG("%s(): failed to compile addrpatt '%s'",
__func__, addrpatt);
free(tmp);
// This will disable adding any new usernames ...
return true;
}
ret = regexec(&re, front, (size_t)0, NULL, 0);
regfree(&re);
if (ret == 0) {
free(tmp);
return true;
}
free(tmp);
return false;
}
void _txt_to_data(enum data_type typ, char *nam, char *fld, void *data, size_t siz, WHERE_FFL_ARGS)
{
char *tmp;
@ -661,7 +710,7 @@ void workerstatus_ready()
// The last one
looksharesummary.userid = workerstatus->userid;
STRNCPY(looksharesummary.workername, workerstatus->workername);
looksharesummary.workername = workerstatus->workername;
looksharesummary.workinfoid = MAXID;
ss_look.data = (void *)(&looksharesummary);
K_RLOCK(sharesummary_free);
@ -1327,7 +1376,7 @@ bool workinfo_age(PGconn *conn, int64_t workinfoid, char *poolinstance,
// Find the first matching sharesummary
looksharesummary.workinfoid = workinfoid;
looksharesummary.userid = -1;
looksharesummary.workername[0] = '\0';
looksharesummary.workername = EMPTY;
ok = true;
ss_tot = ss_already = ss_failed = shares_tot = shares_dumped = 0;
@ -1558,7 +1607,7 @@ K_ITEM *find_sharesummary(int64_t userid, char *workername, int64_t workinfoid)
K_ITEM look;
sharesummary.userid = userid;
STRNCPY(sharesummary.workername, workername);
sharesummary.workername = workername;
sharesummary.workinfoid = workinfoid;
INIT_SHARESUMMARY(&look);
@ -1594,7 +1643,7 @@ void auto_age_older(PGconn *conn, int64_t workinfoid, char *poolinstance,
// Find the oldest 'unaged' sharesummary < workinfoid and >= prev_found
looksharesummary.workinfoid = prev_found;
looksharesummary.userid = -1;
looksharesummary.workername[0] = '\0';
looksharesummary.workername = EMPTY;
INIT_SHARESUMMARY(&look);
look.data = (void *)(&looksharesummary);
@ -1907,8 +1956,7 @@ void set_block_share_counters()
if (sharesummary->workinfoid <= pool.workinfoid) {
// Skip back to the next worker
looksharesummary.userid = sharesummary->userid;
STRNCPY(looksharesummary.workername,
sharesummary->workername);
looksharesummary.workername = sharesummary->workername;
looksharesummary.workinfoid = -1;
ss_look.data = (void *)(&looksharesummary);
ss_item = find_before_in_ktree(sharesummary_root, &ss_look,
@ -2386,3 +2434,16 @@ K_ITEM *find_workmarkerid(int64_t markerid)
return wm_item;
}
// order by expirydate asc,workinfoid asc
// TODO: add poolinstance
cmp_t cmp_marks(K_ITEM *a, K_ITEM *b)
{
MARKS *ma, *mb;
DATA_MARKS(ma, a);
DATA_MARKS(mb, b);
cmp_t c = CMP_TV(ma->expirydate, mb->expirydate);
if (c == 0)
c = CMP_BIGINT(ma->workinfoid, mb->workinfoid);
return c;
}

151
src/ckdb_dbio.c

@ -304,9 +304,10 @@ cleanup:
return lastid;
}
bool users_pass_email(PGconn *conn, K_ITEM *u_item, char *oldhash,
char *newhash, char *email, char *by, char *code,
char *inet, tv_t *cd, K_TREE *trf_root)
// status was added to the end so type checking intercepts new mistakes
bool users_update(PGconn *conn, K_ITEM *u_item, char *oldhash,
char *newhash, char *email, char *by, char *code,
char *inet, tv_t *cd, K_TREE *trf_root, char *status)
{
ExecStatusType rescode;
bool conned = false;
@ -315,7 +316,7 @@ bool users_pass_email(PGconn *conn, K_ITEM *u_item, char *oldhash,
USERS *row, *users;
char *upd, *ins;
bool ok = false;
char *params[5 + HISTORYDATECOUNT];
char *params[6 + HISTORYDATECOUNT];
bool hash;
int n, par = 0;
@ -337,14 +338,18 @@ bool users_pass_email(PGconn *conn, K_ITEM *u_item, char *oldhash,
DATA_USERS(row, item);
memcpy(row, users, sizeof(*row));
// Update one, leave the other
// Update each one supplied
if (hash) {
// New salt each password change
make_salt(row);
password_hash(row->username, newhash, row->salt,
row->passwordhash, sizeof(row->passwordhash));
} else
}
if (email)
STRNCPY(row->emailaddress, email);
if (status)
STRNCPY(row->status, status);
HISTORYDATEINIT(row, cd, by, code, inet);
HISTORYDATETRANSFER(trf_root, row);
@ -384,21 +389,22 @@ bool users_pass_email(PGconn *conn, K_ITEM *u_item, char *oldhash,
par = 0;
params[par++] = bigint_to_buf(row->userid, NULL, 0);
params[par++] = tv_to_buf(cd, NULL, 0);
// Copy them both in - one will be new and one will be old
// Copy them all in - at least one will be new
params[par++] = str_to_buf(row->status, NULL, 0);
params[par++] = str_to_buf(row->emailaddress, NULL, 0);
params[par++] = str_to_buf(row->passwordhash, NULL, 0);
// New salt for each password change (or recopy old)
params[par++] = str_to_buf(row->salt, NULL, 0);
HISTORYDATEPARAMS(params, par, row);
PARCHKVAL(par, 5 + HISTORYDATECOUNT, params); // 10 as per ins
PARCHKVAL(par, 6 + HISTORYDATECOUNT, params); // 11 as per ins
ins = "insert into users "
"(userid,username,status,emailaddress,joineddate,"
"passwordhash,secondaryuserid,salt"
HISTORYDATECONTROL ") select "
"userid,username,status,$3,joineddate,"
"$4,secondaryuserid,$5,"
"$6,$7,$8,$9,$10 from users where "
"userid,username,$3,$4,joineddate,"
"$5,secondaryuserid,$6,"
"$7,$8,$9,$10,$11 from users where "
"userid=$1 and expirydate=$2";
res = PQexecParams(conn, ins, par, NULL, (const char **)params, NULL, NULL, 0, CKPQ_WRITE);
@ -2268,7 +2274,10 @@ bool workinfo_fill(PGconn *conn)
" workinfoid in (select workinfoid from blocks) )";
par = 0;
params[par++] = tv_to_buf((tv_t *)(&default_expiry), NULL, 0);
params[par++] = bigint_to_buf(dbload_workinfoid_start, NULL, 0);
if (dbload_only_sharesummary)
params[par++] = bigint_to_buf(-1, NULL, 0);
else
params[par++] = bigint_to_buf(dbload_workinfoid_start, NULL, 0);
params[par++] = bigint_to_buf(dbload_workinfoid_finish, NULL, 0);
PARCHK(par, params);
res = PQexecParams(conn, sel, par, NULL, (const char **)params, NULL, NULL, 0, CKPQ_READ);
@ -2713,7 +2722,8 @@ bool _sharesummary_update(PGconn *conn, SHARES *s_row, SHAREERRORS *e_row, K_ITE
K_WUNLOCK(sharesummary_free);
DATA_SHARESUMMARY(row, item);
row->userid = userid;
STRNCPY(row->workername, workername);
row->workername = strdup(workername);
LIST_MEM_ADD(sharesummary_free, row->workername);
row->workinfoid = workinfoid;
zero_sharesummary(row, sharecreatedate, diff);
row->inserted = false;
@ -2942,15 +2952,15 @@ late:
PQfinish(conn);
// We keep the new item no matter what 'ok' is, since it will be inserted later
K_WLOCK(sharesummary_free);
if (new) {
K_WLOCK(sharesummary_free);
sharesummary_root = add_to_ktree(sharesummary_root, item, cmp_sharesummary);
sharesummary_workinfoid_root = add_to_ktree(sharesummary_workinfoid_root,
item,
cmp_sharesummary_workinfoid);
k_add_head(sharesummary_store, item);
K_WUNLOCK(sharesummary_free);
}
K_WUNLOCK(sharesummary_free);
return ok;
}
@ -3004,6 +3014,7 @@ bool sharesummary_fill(PGconn *conn)
for (i = 0; i < n; i++) {
item = k_unlink_head(sharesummary_free);
DATA_SHARESUMMARY(row, item);
row->workername = NULL;
if (everyone_die) {
ok = false;
@ -3020,7 +3031,8 @@ bool sharesummary_fill(PGconn *conn)
PQ_GET_FLD(res, i, "workername", field, ok);
if (!ok)
break;
TXT_TO_STR("workername", field, row->workername);
row->workername = strdup(field);
LIST_MEM_ADD(sharesummary_free, row->workername);
PQ_GET_FLD(res, i, "workinfoid", field, ok);
if (!ok)
@ -3147,8 +3159,15 @@ bool sharesummary_fill(PGconn *conn)
tick();
}
if (!ok)
if (!ok) {
DATA_SHARESUMMARY(row, item);
if (row->workername) {
LIST_MEM_SUB(sharesummary_free, row->workername);
free(row->workername);
row->workername = NULL;
}
k_add_head(sharesummary_free, item);
}
PQclear(res);
@ -4055,6 +4074,10 @@ bool auths_add(PGconn *conn, char *poolinstance, char *username,
}
DATA_USERS(*users, u_item);
// Any status content means disallow mining
if ((*users)->status[0])
goto unitem;
STRNCPY(row->poolinstance, poolinstance);
row->userid = (*users)->userid;
// since update=false, a dup will be ok and do nothing when igndup=true
@ -5088,6 +5111,100 @@ bool workmarkers_fill(PGconn *conn)
return ok;
}
bool marks_fill(PGconn *conn)
{
ExecStatusType rescode;
PGresult *res;
K_ITEM *item;
int n, i;
MARKS *row;
char *field;
char *sel;
int fields = 5;
bool ok;
LOGDEBUG("%s(): select", __func__);
// TODO: limit how far back
sel = "select "
"poolinstance,workinfoid,description,marktype,status"
HISTORYDATECONTROL
" from marks";
res = PQexec(conn, sel, CKPQ_READ);
rescode = PQresultStatus(res);
if (!PGOK(rescode)) {
PGLOGERR("Select", rescode, conn);
PQclear(res);
return false;
}
n = PQnfields(res);
if (n != (fields + HISTORYDATECOUNT)) {
LOGERR("%s(): Invalid field count - should be %d, but is %d",
__func__, fields + HISTORYDATECOUNT, n);
PQclear(res);
return false;
}
n = PQntuples(res);
LOGDEBUG("%s(): tree build count %d", __func__, n);
ok = true;
for (i = 0; i < n; i++) {
item = k_unlink_head(marks_free);
DATA_MARKS(row, item);
if (everyone_die) {
ok = false;
break;
}
PQ_GET_FLD(res, i, "poolinstance", field, ok);
if (!ok)
break;
TXT_TO_PTR("poolinstance", field, row->poolinstance);
PQ_GET_FLD(res, i, "workinfoid", field, ok);
if (!ok)
break;
TXT_TO_BIGINT("workinfoid", field, row->workinfoid);
PQ_GET_FLD(res, i, "description", field, ok);
if (!ok)
break;
TXT_TO_PTR("description", field, row->description);
PQ_GET_FLD(res, i, "marktype", field, ok);
if (!ok)
break;
TXT_TO_STR("marktype", field, row->marktype);
PQ_GET_FLD(res, i, "status", field, ok);
if (!ok)
break;
TXT_TO_STR("status", field, row->status);
HISTORYDATEFLDS(res, i, row, ok);
if (!ok)
break;
marks_root = add_to_ktree(marks_root, item, cmp_marks);
k_add_head(marks_store, item);
tick();
}
if (!ok)
k_add_head(marks_free, item);
PQclear(res);
if (ok) {
LOGDEBUG("%s(): built", __func__);
LOGWARNING("%s(): loaded %d marks records", __func__, n);
}
return ok;
}
bool check_db_version(PGconn *conn)
{
ExecStatusType rescode;

Loading…
Cancel
Save