Browse Source

Merge branch 'master' into multiproxy

Conflicts:
	src/stratifier.c
master
Con Kolivas 10 years ago
parent
commit
224d638adc
  1. 64
      html/can.js
  2. 71
      pool/page.php
  3. 62
      pool/page_usperf.php
  4. 172
      src/stratifier.c

64
html/can.js

@ -1,64 +0,0 @@
function hasCan(){var c0=document.getElementById('can0');c=document.getElementById('can');return !!(c0&&c&&c.getContext&&c.getContext('2d'));}
function sep(d){ans={};var ar=d.split("\t");var l=ar.length;for(var i=0;i<l;i++){var e=ar[i].indexOf('=');ans[ar[i].substr(0,e)]=ar[i].substr(e+1)};return ans}
function dfmt(e){var d=new Date(e*1000);var DD=d.getUTCDate();var HH=d.getUTCHours();var MM=d.getUTCMinutes();var ans=''+DD+'/';if(HH<10){ans+='0'}ans+=''+HH+':';if(MM<10){ans+='0'}ans+=''+MM;return ans}
function gch(z,zm){if(z<0.5){return 0.5}if(z>(zm-0.5)){return(zm-0.5)}return z}
function gchx(c,x){return gch(x*c['xm']+c['xo'],c['ctx'].canvas.width)}
function gchy(c,y){return gch((1-y)*c['ym']+c['yo'],c['ctx'].canvas.height)}
function gx0(c){return -c['xo']/c['xm']};
function gy0(c){return -c['yo']/c['ym']};
function gto(c,xo,yo){c['xo']+=xo;c['yo']+=yo}
function gts(c,xs,ys){c['xm']*=xs;c['ym']*=ys}
function gtso(c,xs,ys){gto(c,c['xm']*(1.0-xs)/2.0,c['ym']*(1.0-ys)/2.0);gts(c,xs,ys)}
function gfs(c,bg){c['ctx'].fillStyle=bg}
function gss(c,fg){c['ctx'].strokeStyle=fg}
function glw(c,pct){c['ctx'].lineWidth=pct*c['ym']/100.0}
function glwr(c,rat){c['ctx'].lineWidth*=rat}
function gfz(c,x,y,ox,oy,t,co,a){gfs(c,co);c['ctx'].textAlign=a;c['ctx'].fillText(t,gchx(c,x)+ox,gchy(c,y)-oy)}
function gbe(c,x,y){c['ctx'].beginPath();c['ctx'].moveTo(gchx(c,x),gchy(c,y))}
function gln(c,x,y){c['ctx'].lineTo(gchx(c,x),gchy(c,y))}
function gct(c,x1,y1,x2,y2,x3,y3){c['ctx'].bezierCurveTo(gchx(c,x1),gchy(c,y1),gchx(c,x2),gchy(c,y2),gchx(c,x3),gchy(c,y3))}
function glm(c,x,y){c['ctx'].moveTo(gchx(c,x),gchy(c,y))}
function gle(c){c['ctx'].closePath()}
function gfl(c){c['ctx'].fill()}
function gst(c){c['ctx'].stroke()}
function gfi(c){gle(c);gst(c)}
function gbd(c){gbe(c,0,0);gln(c,1,0);gln(c,1,1);gln(c,0,1);gle(c);gfl(c);gst(c)}
function ggr(c,xs,ys,yt,xn,x0,x1,y0,y1,ar,nx,vx,vy,av){
gtso(c,xs,ys);
gss(c,'black');glw(c,0.2);
gbe(c,0,1);gln(c,0,0);gln(c,1,0);gst(c);
glw(c,0.01);
var hi=c['ctx'].measureText('M').width, wi=c['ctx'].measureText('1').width;
for(var i=0;i<11;i++){var y=i/10.0;gbe(c,-0.01,y);gln(c,1,y);gst(c);var t=''+(((y1-y0)*i/10+y0).toFixed(2));gfz(c,0,y,-wi,0,t,'black','end')}
gfz(c,gx0(c),0.55,wi,0,yt,'#0080ff','left');
var m=Math.round(0.5+xn/20.0);
var f=1;
for(var i=0;i<xn;i++){var n=ar[nx+i];var x=ar[vx+i];var xo=(x-x0)/(x1-x0);if(c['skey']&&(i<(xn-1))&&(i%m)==0){gbe(c,xo,0);gln(c,xo,-0.01);gst(c);gfz(c,xo,0,0,-hi*1.5,n,'#00a050','center')}if(c['slines']){gbe(c,xo,0);gln(c,xo,1);gst(c)}}
var xhr=x1-(x1%3600);
gss(c,'brown');
var tpos=2.7;if(c['over']){tpos=1.5}
for(var i=xhr;i>=x0;i-=(6*3600)){var n=dfmt(i);var xo=(i-x0)/(x1-x0);if(c['tkey']){gbe(c,xo,0);gln(c,xo,-0.02);gst(c);gfz(c,xo,0,0,-hi*tpos,n,'brown','center')}if(c['tlines']){gbe(c,xo,0);gln(c,xo,1);gst(c)}}
glw(c,0.1);
gss(c,'black');
if(c['smooth']){var xa=0,ya=0,xb=0,yb=0;
for(var i=0;i<xn;i++){var x=ar[vx+i];var y=ar[vy+i];var xo=(x-x0)/(x1-x0);var yo=(y-y0)/(y1-y0);if(f==1){gbe(c,xo,yo);f=0;xb=xo;yb=yo}else{gct(c,(xa+xb)/2,(ya+yb)/2,xb,yb,(xb+xo)/2,(yb+yo)/2)}xa=xb;ya=yb;xb=xo;yb=yo}gct(c,(xa+xb)/2,(ya+yb)/2,xo,yo,xo,yo);gst(c);}
else{for(var i=0;i<xn;i++){var x=ar[vx+i];var y=ar[vy+i];var xo=(x-x0)/(x1-x0);var yo=(y-y0)/(y1-y0);if(f==1){gbe(c,xo,yo);f=0}else{gln(c,xo,yo)}}gst(c);}
glw(c,0.2);
gss(c,'red');
var y=(av-y0)/(y1-y0);
gbe(c,0,y);gln(c,1,y);gst(c);
var t=''+av.toFixed(2);gfz(c,1,y,1,0,t,'red','left')
}
function sn(i,shi){if(shi.indexOf(' Shift ')<0){return ''+(i%10)}else{return shi.replace(/.* ([a-z])[a-z]*$/,'$1')}}
function gc(c){var div=document.getElementById('can0');while(div.firstChild){div.removeChild(div.firstChild)}c['can']=document.createElement('canvas');c['can'].id='can';c['wx']=window.innerWidth;c['wy']=window.innerHeight;c['xm']=Math.round(c['wx']*0.9+0.5);c['ym']=Math.round(c['wy']*0.8+0.5);if(c['ym']>c['xm']){c['ym']=c['xm']}c['xo']=0.0;c['yo']=0.0;c['ctx']=c['can'].getContext('2d');c['ctx'].canvas.width=c['xm']+1;c['ctx'].canvas.height=c['ym']+1;div.appendChild(c['can']);div=document.getElementById('smooth');c['smooth']=(div&&div.checked);div=document.getElementById('over');c['over']=(div&&div.checked);div=document.getElementById('skey');c['skey']=(div&&div.checked);div=document.getElementById('slines');c['slines']=(div&&div.checked);div=document.getElementById('tkey');c['tkey']=(div&&div.checked);div=document.getElementById('tlines');c['tlines']=(div&&div.checked);div=document.getElementById('zerob');c['zerob']=(div&&div.checked)}
function gdrw(d){var c={};gc(c);
gfs(c,'white');gss(c,'#0000c0');glw(c,0.5);gbd(c);
var rows=d['rows'],ymin=-1,ymax=0,xmin=-1,xmax=0;
var tda=0;
for(var i=0;i<rows;i++){var s=parseFloat(d['start:'+i]);var e=parseFloat(d['end:'+i]);var da=parseFloat(d['diffacc:'+i]);tda+=da;var ths=(da/(e-s))*Math.pow(2,32)/Math.pow(10,12);d['ths:'+i]=ths;if(ymin==-1||ymin>ths){ymin=ths}if(ths>ymax)ymax=ths;d['nx:'+i]=sn(i,d['shift:'+i]);if(xmin==-1||xmin>s){xmin=s}if(xmax<e){xmax=e}d['vx:'+i]=(s+e)/2.0};
var tav=(tda/(xmax-xmin))*Math.pow(2,32)/Math.pow(10,12);
var p5=(ymax-ymin)*0.05;ymax+=p5;ymin-=p5;if(ymin<0){ymin=0}
if(c['zerob']){ymin=0}
ggr(c,0.9,0.9,'THs',rows,xmin,xmax,ymin,ymax,d,'nx:','vx:','ths:',tav);
}
function dodrw(data){if(hasCan()){gdrw(sep(data))}}

71
pool/page.php

@ -34,12 +34,79 @@ function addScript($script)
if ($script != null and trim($script) != '') if ($script != null and trim($script) != '')
{ {
if ($page_scripts == '') if ($page_scripts == '')
$page_scripts = "<script type='text/javascript'><!--\n"; $page_scripts = "<script type='text/javascript'>\n";
$page_scripts .= trim($script); $page_scripts .= trim($script);
} }
} }
# #
function addGBase()
{
$g = "function hasCan(){var c0=document.getElementById('can0');c=document.getElementById('can');return !!(c0&&c&&c.getContext&&c.getContext('2d'));}
function sep(d){ans={};var ar=d.split('\\t');var l=ar.length;for(var i=0;i<l;i++){var e=ar[i].indexOf('=');ans[ar[i].substr(0,e)]=ar[i].substr(e+1)};return ans}
function dfmt(c,e){var d=new Date(e*1000);var DD,HH,MM;if(c['utc']){DD=d.getUTCDate();HH=d.getUTCHours();MM=d.getUTCMinutes()}else{DD=d.getDate();HH=d.getHours();MM=d.getMinutes()}var ans=''+DD+'/';if(HH<10){ans+='0'}ans+=''+HH+':';if(MM<10){ans+='0'}ans+=''+MM;return ans}
function gcn(n){var ans='',d=document.cookie;if(d){var c0=d.indexOf(n+'='),cs=d.indexOf(' '+n+'=');if(c0==0||cs>0){if(cs>0){c0=cs+1}var c=d.substr(c0).split(';',1);var e=c[0].indexOf('=');if(e>0){ans=c[0].substr(e+1)}}}return ans}
function scnv(n,v){var d = new Date();d.setTime(d.getTime()+(864*Math.pow(10,8)));document.cookie=n+'='+v+'; expires='+d.toUTCString()+'; path=/'}
function ccb(c,n){var e=document.getElementById(n);c[n]=(e&&e.checked)}
function gch(z,zm){if(z<0.5){return 0.5}if(z>(zm-0.5)){return(zm-0.5)}return z}
function gchx(c,x){return gch(x*c['xm']+c['xo'],c['ctx'].canvas.width)}
function gchy(c,y){return gch((1-y)*c['ym']+c['yo'],c['ctx'].canvas.height)}
function gx0(c){return -c['xo']/c['xm']};
function gy0(c){return -c['yo']/c['ym']};
function gto(c,xo,yo){c['xo']+=xo;c['yo']+=yo}
function gts(c,xs,ys){c['xm']*=xs;c['ym']*=ys}
function gtso(c,xs,ys){gto(c,c['xm']*(1.0-xs)/2.0,c['ym']*(1.0-ys)/2.0);gts(c,xs,ys)}
function gfs(c,bg){c['ctx'].fillStyle=bg}
function gss(c,fg){c['ctx'].strokeStyle=fg}
function glw(c,w){c['ctx'].lineWidth=w}
function gfz(c,x,y,ox,oy,t,co,a){gfs(c,co);c['ctx'].textAlign=a;c['ctx'].fillText(t,gchx(c,x)+ox,gchy(c,y)-oy)}
function gbe(c,x,y){c['ctx'].beginPath();c['ctx'].moveTo(gchx(c,x),gchy(c,y))}
function gln(c,x,y){c['ctx'].lineTo(gchx(c,x),gchy(c,y))}
function gct(c,x1,y1,x2,y2,x3,y3){c['ctx'].bezierCurveTo(gchx(c,x1),gchy(c,y1),gchx(c,x2),gchy(c,y2),gchx(c,x3),gchy(c,y3))}
function glm(c,x,y){c['ctx'].moveTo(gchx(c,x),gchy(c,y))}
function gle(c){c['ctx'].closePath()}
function gfl(c){c['ctx'].fill()}
function gst(c){c['ctx'].stroke()}
function gfi(c){gle(c);gst(c)}
function gbd(c){gbe(c,0,0);gln(c,1,0);gln(c,1,1);gln(c,0,1);gle(c);gfl(c);gst(c)}
function ggr(c,xs,ys,yt,xn,x0,x1,y0,y1,ar,nx,vx,vy,av){
gtso(c,xs,ys);
gss(c,'black');glw(c,1.5);
gbe(c,0,1);gln(c,0,0);gln(c,1,0);gst(c);
glw(c,0.2);
var hi=c['ctx'].measureText('M').width, wi=c['ctx'].measureText('1').width;
for(var i=0;i<11;i++){var y=i/10.0;gbe(c,-0.01,y);gln(c,1,y);gst(c);var t=''+(((y1-y0)*i/10+y0).toFixed(2));gfz(c,0,y,-wi,0,t,'black','end')}
gfz(c,gx0(c),0.55,wi,0,yt,'#0080ff','left');
var m=Math.round(0.5+xn/20.0);
var f=1;
for(var i=0;i<xn;i++){var n=ar[nx+i];var x=ar[vx+i];var xo=(x-x0)/(x1-x0);if(c['skey']&&(i<(xn-1))&&(i%m)==0){gbe(c,xo,0);gln(c,xo,-0.01);gst(c);gfz(c,xo,0,0,-hi*1.5,n,'#00a050','center')}if(c['slines']){gbe(c,xo,0);gln(c,xo,1);gst(c)}}
var xhr=x1-(x1%3600);
gss(c,'brown');
if(c['tkey']||c['tlines']){var hlv=c['hln'][c['hl']];hrs=c['hrs'][c['hr']]*3600/hlv;
var l=0;tpos=2.7;if(c['over']){tpos=1.5}
for(var i=xhr;i>=x0;i-=hrs){var n=dfmt(c,i);var xo=(i-x0)/(x1-x0);if(c['tkey']&&((l%hlv)==0)){gbe(c,xo,0);gln(c,xo,-0.02);gst(c);gfz(c,xo,0,0,-hi*tpos,n,'brown','center')}if(c['tlines']){gbe(c,xo,0);gln(c,xo,1);gst(c)}l++}}
glw(c,1);
gss(c,'#0000c0');
if(c['smooth']){var xa=0,ya=0,xb=0,yb=0;
for(var i=0;i<xn;i++){var x=ar[vx+i];var y=ar[vy+i];var xo=(x-x0)/(x1-x0);var yo=(y-y0)/(y1-y0);if(f==1){gbe(c,xo,yo);f=0;xb=xo;yb=yo}else{gct(c,(xa+xb)/2,(ya+yb)/2,xb,yb,(xb+xo)/2,(yb+yo)/2)}xa=xb;ya=yb;xb=xo;yb=yo}gct(c,(xa+xb)/2,(ya+yb)/2,xo,yo,xo,yo);gst(c);}
else{for(var i=0;i<xn;i++){var x=ar[vx+i];var y=ar[vy+i];var xo=(x-x0)/(x1-x0);var yo=(y-y0)/(y1-y0);if(f==1){gbe(c,xo,yo);f=0}else{gln(c,xo,yo)}}gst(c);}
glw(c,1);
gss(c,'red');
var y=(av-y0)/(y1-y0);
gbe(c,0,y);gln(c,1,y);gst(c);
var t=''+av.toFixed(2)+'av';gfz(c,1,y,1,0,t,'red','left')
if(c['tkey']){var col,hrl=c['hrs'].length;for(var i=0;i<hrl;i++){if(c['hr']==i){col='red'}else{col='black'}gfz(c,1,0,c['xo']-c['pxe'],hi*(i+1)*2,''+c['hrs'][i],col,'end')}for(var i=0;i<c['hln'].length;i++){if(c['hl']==i){col='red'}else{col='black'}gfz(c,1,0,c['xo']-c['pxe'],hi*(i+2+hrl)*2,''+c['hrs'][i],col,'end')}}
}
function sn(i,shi){if(shi.indexOf(' Shift ')<0){return ''+(i%10)}else{return shi.replace(/.* ([a-z])[a-z]*$/,'$1')}}
function gc(c){var div=document.getElementById('can0');while(div.firstChild){div.removeChild(div.firstChild)}c['can']=document.createElement('canvas');c['can'].id='can';c['wx']=window.innerWidth;c['wy']=window.innerHeight;c['xm']=Math.round(c['wx']*0.9+0.5);c['ym']=Math.round(c['wy']*0.8+0.5);if(c['ym']>c['xm']){c['ym']=c['xm']}c['xo']=0.0;c['yo']=0.0;c['ctx']=c['can'].getContext('2d');c['ctx'].canvas.width=c['xm']+1;c['ctx'].canvas.height=c['ym']+1;div.appendChild(c['can']);c['pxe']=Math.max(Math.round(c['xm']/250),1)}
function opts(t,i){var e=document.getElementById(i);if(t.checked){e.style.visibility='visible'}else{e.style.visibility='hidden'}}
function ghrs(c){c['hrs']=[1,2,3,4,6,8,12,24];c['hln']=[1,2,3,4,6]}
function gopt(c,cbx){for(var i=0;i<cbx.length;i++){ccb(c,cbx[i])}c['hr']=4;c['hl']=0}
function doinit(cbx,xon){for(var i=0;i<cbx.length;i++){var e=document.getElementById(cbx[i]);if(e){var n=gcn(cbx[i]);if(n==''){if(xon[cbx[i]]){e.checked=true}else{e.checked=false}}else{if(n=='1'){e.checked=true}else{e.checked=false}}}}}
";
addScript($g);
}
#
function makeLink($page, $rest = '') function makeLink($page, $rest = '')
{ {
if ($page != '') if ($page != '')
@ -555,7 +622,7 @@ function gopage($info, $data, $pagefun, $page, $menu, $name, $user, $ispage = tr
$pg = str_replace($dbg_marker, cvtdbg(), $pg); $pg = str_replace($dbg_marker, cvtdbg(), $pg);
if ($page_scripts != '') if ($page_scripts != '')
$page_scripts .= "//-->\n</script>"; $page_scripts .= "</script>";
$head = str_replace($script_marker, $page_scripts, $head); $head = str_replace($script_marker, $page_scripts, $head);

62
pool/page_usperf.php

@ -1,5 +1,21 @@
<?php <?php
# #
function uspg()
{
$g = "function gdrw(c,d,cbx){gc(c);ghrs(c);gopt(c,cbx);
gfs(c,'white');gss(c,'#0000c0');glw(c,2);gbd(c);
var rows=d['rows'],ymin=-1,ymax=0,xmin=-1,xmax=0,tda=0;
for(var i=0;i<rows;i++){var s=parseFloat(d['start:'+i]);var e=parseFloat(d['end:'+i]);var da=parseFloat(d['diffacc:'+i]);tda+=da;var ths=(da/(e-s))*Math.pow(2,32)/Math.pow(10,12);d['ths:'+i]=ths;if(ymin==-1||ymin>ths){ymin=ths}if(ths>ymax)ymax=ths;d['nx:'+i]=sn(i,d['shift:'+i]);if(xmin==-1||xmin>s){xmin=s}if(xmax<e){xmax=e}d['vx:'+i]=(s+e)/2.0};
var tav=(tda/(xmax-xmin))*Math.pow(2,32)/Math.pow(10,12);
var p5=(ymax-ymin)*0.05;ymax+=p5;ymin-=p5;if(ymin<0){ymin=0}
if(c['zerob']){ymin=0}
ggr(c,0.9,0.9,'TH/s',rows,xmin,xmax,ymin,ymax,d,'nx:','vx:','ths:',tav)}
c={};
function dodrw(data,cbx){if(hasCan()){gdrw(c,sep(data),cbx)}}
function gact(t){if(t.checked){scnv(t.id,1)}else{scnv(t.id,0)}godrw(0)}";
return $g;
}
#
function dousperf($data, $user) function dousperf($data, $user)
{ {
$ans = getShiftData($user); $ans = getShiftData($user);
@ -10,27 +26,41 @@ function dousperf($data, $user)
else else
$vlines = true; $vlines = true;
$pg = '<h1>User Shift Performance</h1><br>'; $pg = '<h1>User Shift Reward Performance</h1><br>';
if ($ans['STATUS'] == 'ok' and $ans['DATA'] != '') if ($ans['STATUS'] == 'ok' and $ans['DATA'] != '')
{ {
$pg .= "<div><input type=checkbox id=skey onclick='godrw()' checked>shift key&nbsp;"; addGBase();
$pg .= "&nbsp;<input type=checkbox id=slines onclick='godrw()'"; $cbx = array('skey' => 'shift key', 'slines' => 'shift lines',
if ($vlines) 'tkey' => 'time key', 'tlines' => 'time lines',
$pg .= ' checked'; 'over' => 'key overlap', 'smooth' => 'smooth',
$pg .= ">shift lines&nbsp;"; 'zerob' => 'zero based', 'utc' => 'utc');
$pg .= "&nbsp;<input type=checkbox id=tkey onclick='godrw()'>time key&nbsp;"; $xon = array('skey' => 1, 'utc' => 1);
$pg .= "&nbsp;<input type=checkbox id=tlines onclick='godrw()'>time lines&nbsp;"; if ($vlines === true)
$pg .= "&nbsp;<input type=checkbox id=over onclick='godrw()'>key overlap&nbsp;"; $xon['slines'] = 1;
$pg .= "&nbsp;<input type=checkbox id=smooth onclick='godrw()'>smooth&nbsp;";
$pg .= "&nbsp;<input type=checkbox id=zerob onclick='godrw()'>zero based</div>"; $pg .= '<div>';
$pg .= "<div id=can0><canvas id=can width=1 height=1>"; foreach ($cbx as $nam => $txt)
$pg .= "A graph will show here if your browser supports html5/canvas"; $pg .= "&nbsp;<input type=checkbox id=$nam onclick='gact(this)'>$txt&nbsp;";
$pg .= '</div>';
$pg .= '<div id=can0><canvas id=can width=1 height=1>';
$pg .= 'A graph will show here if your browser supports html5/canvas';
$pg .= "</canvas></div>\n"; $pg .= "</canvas></div>\n";
$data = str_replace(array("\\","'"), array("\\\\","\\'"), $ans['DATA']); $data = str_replace(array("\\","'"), array("\\\\","\\'"), $ans['DATA']);
$pg .= "<script src='/can.js'></script>\n"; $pg .= "<script type='text/javascript'>\n";
$pg .= "<script type='text/javascript'>function godrw(){dodrw('$data')};godrw();</script>\n"; $pg .= uspg();
$pg .= "\nfunction godrw(f){var cbx=[";
$comma = '';
foreach ($cbx as $nam => $txt)
{
$pg .= "$comma'$nam'";
$comma = ',';
}
$pg .= '];if(f){var xon={};';
foreach ($xon as $nam => $val)
$pg .= "xon['$nam']=1;";
$pg .= "doinit(cbx,xon)}dodrw('$data',cbx)};godrw(1);</script>\n";
} }
return $pg; return $pg;
} }
# #

172
src/stratifier.c

@ -232,6 +232,7 @@ struct stratum_instance {
uchar enonce1bin[16]; uchar enonce1bin[16];
char enonce1var[12]; char enonce1var[12];
uint64_t enonce1_64; uint64_t enonce1_64;
int session_id;
int64_t diff; /* Current diff */ int64_t diff; /* Current diff */
int64_t old_diff; /* Previous diff */ int64_t old_diff; /* Previous diff */
@ -335,6 +336,16 @@ struct proxy_base {
bool dead; bool dead;
}; };
typedef struct session session_t;
struct session {
UT_hash_handle hh;
int session_id;
uint64_t enonce1_64;
int64_t client_id;
time_t added;
};
struct stratifier_data { struct stratifier_data {
ckpool_t *ckp; ckpool_t *ckp;
@ -363,6 +374,7 @@ struct stratifier_data {
int64_t workbase_id; int64_t workbase_id;
int64_t blockchange_id; int64_t blockchange_id;
int session_id;
char lasthash[68]; char lasthash[68];
char lastswaphash[68]; char lastswaphash[68];
@ -375,14 +387,12 @@ struct stratifier_data {
int64_t user_instance_id; int64_t user_instance_id;
/* Stratum_instances hashlist is stored by id, whereas disconnected_instances
* is sorted by enonce1_64. */
stratum_instance_t *stratum_instances; stratum_instance_t *stratum_instances;
stratum_instance_t *disconnected_instances;
stratum_instance_t *recycled_instances; stratum_instance_t *recycled_instances;
int stratum_generated; int stratum_generated;
int disconnected_generated; int disconnected_generated;
session_t *disconnected_sessions;
user_instance_t *user_instances; user_instance_t *user_instances;
@ -991,13 +1001,6 @@ static void __kill_instance(sdata_t *sdata, stratum_instance_t *client)
DL_APPEND(sdata->recycled_instances, client); DL_APPEND(sdata->recycled_instances, client);
} }
static void __del_disconnected(sdata_t *sdata, stratum_instance_t *client)
{
HASH_DEL(sdata->disconnected_instances, client);
sdata->stats.disconnected--;
__kill_instance(sdata, client);
}
/* Called with instance_lock held. Note stats.users is protected by /* Called with instance_lock held. Note stats.users is protected by
* instance lock to avoid recursive locking. */ * instance lock to avoid recursive locking. */
static void __inc_worker(sdata_t *sdata, user_instance_t *instance) static void __inc_worker(sdata_t *sdata, user_instance_t *instance)
@ -1014,6 +1017,35 @@ static void __dec_worker(sdata_t *sdata, user_instance_t *instance)
sdata->stats.users--; sdata->stats.users--;
} }
static void __disconnect_session(sdata_t *sdata, const stratum_instance_t *client)
{
time_t now_t = time(NULL);
session_t *session, *tmp;
/* Opportunity to age old sessions */
HASH_ITER(hh, sdata->disconnected_sessions, session, tmp) {
if (now_t - session->added > 600) {
HASH_DEL(sdata->disconnected_sessions, session);
dealloc(session);
sdata->stats.disconnected--;
}
}
if (!client->enonce1_64 || !client->user_instance || !client->authorised)
return;
HASH_FIND_INT(sdata->disconnected_sessions, &client->session_id, session);
if (session)
return;
session = ckalloc(sizeof(session_t));
session->enonce1_64 = client->enonce1_64;
session->session_id = client->session_id;
session->client_id = client->id;
session->added = now_t;
HASH_ADD_INT(sdata->disconnected_sessions, session_id, session);
sdata->stats.disconnected++;
sdata->disconnected_generated++;
}
/* Removes a client instance we know is on the stratum_instances list and from /* Removes a client instance we know is on the stratum_instances list and from
* the user client list if it's been placed on it */ * the user client list if it's been placed on it */
static void __del_client(sdata_t *sdata, stratum_instance_t *client, user_instance_t *user) static void __del_client(sdata_t *sdata, stratum_instance_t *client, user_instance_t *user)
@ -1023,6 +1055,7 @@ static void __del_client(sdata_t *sdata, stratum_instance_t *client, user_instan
DL_DELETE(user->clients, client); DL_DELETE(user->clients, client);
__dec_worker(sdata, user); __dec_worker(sdata, user);
} }
} }
static void connector_drop_client(ckpool_t *ckp, const int64_t id) static void connector_drop_client(ckpool_t *ckp, const int64_t id)
@ -1037,8 +1070,8 @@ static void connector_drop_client(ckpool_t *ckp, const int64_t id)
static void drop_allclients(ckpool_t *ckp) static void drop_allclients(ckpool_t *ckp)
{ {
stratum_instance_t *client, *tmp; stratum_instance_t *client, *tmp;
int disconnects = 0, kills = 0;
sdata_t *sdata = ckp->data; sdata_t *sdata = ckp->data;
int kills = 0;
ck_wlock(&sdata->instance_lock); ck_wlock(&sdata->instance_lock);
HASH_ITER(hh, sdata->stratum_instances, client, tmp) { HASH_ITER(hh, sdata->stratum_instances, client, tmp) {
@ -1052,15 +1085,9 @@ static void drop_allclients(ckpool_t *ckp)
kills++; kills++;
connector_drop_client(ckp, client_id); connector_drop_client(ckp, client_id);
} }
HASH_ITER(hh, sdata->disconnected_instances, client, tmp) {
disconnects++;
__del_disconnected(sdata, client);
}
sdata->stats.users = sdata->stats.workers = 0; sdata->stats.users = sdata->stats.workers = 0;
ck_wunlock(&sdata->instance_lock); ck_wunlock(&sdata->instance_lock);
if (disconnects)
LOGNOTICE("Disconnected %d instances", disconnects);
if (kills) if (kills)
LOGNOTICE("Dropped %d instances", kills); LOGNOTICE("Dropped %d instances", kills);
} }
@ -1759,40 +1786,11 @@ static stratum_instance_t *ref_instance_by_id(sdata_t *sdata, const int64_t id)
return client; return client;
} }
/* Has this client_id already been used and is now in one of the dropped lists */
static bool __dropped_instance(sdata_t *sdata, const int64_t id)
{
stratum_instance_t *client, *tmp;
bool ret = false;
HASH_ITER(hh, sdata->disconnected_instances, client, tmp) {
if (unlikely(client->id == id)) {
ret = true;
goto out;
}
}
out:
return ret;
}
/* Ret = 1 is disconnected, 2 is killed, 3 is workerless killed */
static void __drop_client(sdata_t *sdata, stratum_instance_t *client, user_instance_t *user, static void __drop_client(sdata_t *sdata, stratum_instance_t *client, user_instance_t *user,
bool lazily, char **msg) bool lazily, char **msg)
{ {
stratum_instance_t *old_client = NULL;
__del_client(sdata, client, user); __del_client(sdata, client, user);
HASH_FIND(hh, sdata->disconnected_instances, &client->enonce1_64, sizeof(uint64_t), old_client);
/* Only keep around one copy of the old client in server mode */
if (!client->ckp->proxy && !old_client && client->enonce1_64 && client->authorised) {
ASPRINTF(msg, "Client %"PRId64" %s %suser %s worker %s disconnected %s",
client->id, client->address, user->throttled ? "throttled " : "",
user->username, client->workername, lazily ? "lazily" : "");
HASH_ADD(hh, sdata->disconnected_instances, enonce1_64, sizeof(uint64_t), client);
sdata->stats.disconnected++;
sdata->disconnected_generated++;
client->disconnected_time = time(NULL);
} else {
if (client->workername) { if (client->workername) {
if (user) { if (user) {
ASPRINTF(msg, "Client %"PRId64" %s %suser %s worker %s dropped %s", ASPRINTF(msg, "Client %"PRId64" %s %suser %s worker %s dropped %s",
@ -1808,7 +1806,6 @@ static void __drop_client(sdata_t *sdata, stratum_instance_t *client, user_insta
client->id, client->address, lazily ? "lazily" : ""); client->id, client->address, lazily ? "lazily" : "");
} }
__kill_instance(sdata, client); __kill_instance(sdata, client);
}
} }
/* Decrease the reference count of instance. */ /* Decrease the reference count of instance. */
@ -1868,6 +1865,7 @@ static stratum_instance_t *__stratum_add_instance(ckpool_t *ckp, const int64_t i
client = __recruit_stratum_instance(sdata); client = __recruit_stratum_instance(sdata);
client->start_time = time(NULL); client->start_time = time(NULL);
client->id = id; client->id = id;
client->session_id = ++sdata->session_id;
strcpy(client->address, address); strcpy(client->address, address);
client->server = server; client->server = server;
client->diff = client->old_diff = ckp->startdiff; client->diff = client->old_diff = ckp->startdiff;
@ -1880,44 +1878,35 @@ static stratum_instance_t *__stratum_add_instance(ckpool_t *ckp, const int64_t i
return client; return client;
} }
static uint64_t disconnected_sessionid_exists(sdata_t *sdata, const char *sessionid, const int64_t id) static uint64_t disconnected_sessionid_exists(sdata_t *sdata, const char *sessionid,
int *session_id, const int64_t id)
{ {
stratum_instance_t *client, *tmp; session_t *session;
uint64_t enonce1_64 = 0, ret = 0;
int64_t old_id = 0; int64_t old_id = 0;
uint64_t ret = 0;
int slen; int slen;
if (!sessionid) if (!sessionid)
goto out; goto out;
slen = strlen(sessionid) / 2; slen = strlen(sessionid) / 2;
if (slen < 1 || slen > 8) if (slen < 1 || slen > 4)
goto out; goto out;
if (!validhex(sessionid)) if (!validhex(sessionid))
goto out; goto out;
/* Number is in BE but we don't swap either of them */ sscanf(sessionid, "%x", session_id);
hex2bin(&enonce1_64, sessionid, slen); LOGDEBUG("Testing for sessionid %s %x", sessionid, *session_id);
ck_wlock(&sdata->instance_lock); ck_wlock(&sdata->instance_lock);
HASH_ITER(hh, sdata->stratum_instances, client, tmp) { HASH_FIND_INT(sdata->disconnected_sessions, session_id, session);
if (client->id == id) if (!session)
continue;
if (client->enonce1_64 == enonce1_64) {
/* Only allow one connected instance per enonce1 */
goto out_unlock; goto out_unlock;
} HASH_DEL(sdata->disconnected_sessions, session);
} sdata->stats.disconnected--;
client = NULL; ret = session->enonce1_64;
HASH_FIND(hh, sdata->disconnected_instances, &enonce1_64, sizeof(uint64_t), client); old_id = session->client_id;
if (client) { dealloc(session);
/* Delete the entry once we are going to use it since there
* will be a new instance with the enonce1_64 */
old_id = client->id;
__del_disconnected(sdata, client);
ret = enonce1_64;
}
out_unlock: out_unlock:
ck_wunlock(&sdata->instance_lock); ck_wunlock(&sdata->instance_lock);
out: out:
@ -2030,11 +2019,9 @@ static void stratum_add_send(sdata_t *sdata, json_t *val, const int64_t client_i
static void drop_client(ckpool_t *ckp, sdata_t *sdata, const int64_t id) static void drop_client(ckpool_t *ckp, sdata_t *sdata, const int64_t id)
{ {
stratum_instance_t *client, *tmp;
char_entry_t *entries = NULL; char_entry_t *entries = NULL;
user_instance_t *user = NULL; user_instance_t *user = NULL;
time_t now_t = time(NULL); stratum_instance_t *client;
int aged = 0;
char *msg; char *msg;
LOGINFO("Stratifier asked to drop client %"PRId64, id); LOGINFO("Stratifier asked to drop client %"PRId64, id);
@ -2042,6 +2029,7 @@ static void drop_client(ckpool_t *ckp, sdata_t *sdata, const int64_t id)
ck_wlock(&sdata->instance_lock); ck_wlock(&sdata->instance_lock);
client = __instance_by_id(sdata, id); client = __instance_by_id(sdata, id);
if (client && !client->dropped) { if (client && !client->dropped) {
__disconnect_session(sdata, client);
user = client->user_instance; user = client->user_instance;
/* If the client is still holding a reference, don't drop them /* If the client is still holding a reference, don't drop them
* now but wait till the reference is dropped */ * now but wait till the reference is dropped */
@ -2051,21 +2039,9 @@ static void drop_client(ckpool_t *ckp, sdata_t *sdata, const int64_t id)
} else } else
client->dropped = true; client->dropped = true;
} }
/* Old disconnected instances will not have any valid shares so remove
* them from the disconnected instances list if they've been dead for
* more than 10 minutes */
HASH_ITER(hh, sdata->disconnected_instances, client, tmp) {
if (now_t - client->disconnected_time < 600)
continue;
aged++;
__del_disconnected(sdata, client);
}
ck_wunlock(&sdata->instance_lock); ck_wunlock(&sdata->instance_lock);
notice_msg_entries(&entries); notice_msg_entries(&entries);
if (aged)
LOGINFO("Aged %d disconnected instances to dead", aged);
reap_proxies(ckp, sdata); reap_proxies(ckp, sdata);
} }
@ -2283,7 +2259,8 @@ static char *stratifier_stats(ckpool_t *ckp, sdata_t *sdata)
objects = sdata->stats.disconnected; objects = sdata->stats.disconnected;
generated = sdata->disconnected_generated; generated = sdata->disconnected_generated;
memsize = sizeof(stratum_instance_t) * sdata->stats.disconnected; memsize = SAFE_HASH_OVERHEAD(sdata->disconnected_sessions);
memsize += sizeof(session_t) * sdata->stats.disconnected;
JSON_CPACK(subval, "{si,si,si}", "count", objects, "memory", memsize, "generated", generated); JSON_CPACK(subval, "{si,si,si}", "count", objects, "memory", memsize, "generated", generated);
json_set_object(val, "disconnected", subval); json_set_object(val, "disconnected", subval);
ck_runlock(&sdata->instance_lock); ck_runlock(&sdata->instance_lock);
@ -2805,6 +2782,7 @@ static json_t *parse_subscribe(stratum_instance_t *client, const int64_t client_
ckpool_t *ckp = client->ckp; ckpool_t *ckp = client->ckp;
sdata_t *sdata, *ckp_sdata = ckp->data; sdata_t *sdata, *ckp_sdata = ckp->data;
bool old_match = false; bool old_match = false;
char sessionid[12];
int arr_size; int arr_size;
json_t *ret; json_t *ret;
int n2len; int n2len;
@ -2843,7 +2821,7 @@ static json_t *parse_subscribe(stratum_instance_t *client, const int64_t client_
buf = json_string_value(json_array_get(params_val, 1)); buf = json_string_value(json_array_get(params_val, 1));
LOGDEBUG("Found old session id %s", buf); LOGDEBUG("Found old session id %s", buf);
/* Add matching here */ /* Add matching here */
if ((client->enonce1_64 = disconnected_sessionid_exists(sdata, buf, client_id))) { if ((client->enonce1_64 = disconnected_sessionid_exists(sdata, buf, &client->session_id, client_id))) {
sprintf(client->enonce1, "%016lx", client->enonce1_64); sprintf(client->enonce1, "%016lx", client->enonce1_64);
old_match = true; old_match = true;
@ -2871,21 +2849,10 @@ static json_t *parse_subscribe(stratum_instance_t *client, const int64_t client_
/* Workbases will exist if sdata->current_workbase is not NULL */ /* Workbases will exist if sdata->current_workbase is not NULL */
ck_rlock(&sdata->workbase_lock); ck_rlock(&sdata->workbase_lock);
n2len = sdata->workbases->enonce2varlen; n2len = sdata->workbases->enonce2varlen;
ck_runlock(&sdata->workbase_lock); sprintf(sessionid, "%08x", client->session_id);
JSON_CPACK(ret, "[[[s,s]],s,i]", "mining.notify", sessionid, client->enonce1,
/* Send a random sessionid in proxy mode so clients don't think we have
* resumed if enonce1 ends up matching on reconnect. */
if (ckp->proxy) {
unsigned int now = time(NULL);
char nowx[12];
sprintf(nowx, "%x", now);
JSON_CPACK(ret, "[[[s,s]],s,i]", "mining.notify", nowx, client->enonce1,
n2len);
} else {
JSON_CPACK(ret, "[[[s,s]],s,i]", "mining.notify", client->enonce1, client->enonce1,
n2len); n2len);
} ck_runlock(&sdata->workbase_lock);
client->subscribed = true; client->subscribed = true;
@ -4427,11 +4394,8 @@ static void srecv_process(ckpool_t *ckp, char *buf)
client = __instance_by_id(sdata, msg->client_id); client = __instance_by_id(sdata, msg->client_id);
/* If client_id instance doesn't exist yet, create one */ /* If client_id instance doesn't exist yet, create one */
if (unlikely(!client)) { if (unlikely(!client)) {
if (likely(!__dropped_instance(sdata, msg->client_id))) {
noid = true; noid = true;
client = __stratum_add_instance(ckp, msg->client_id, address, server); client = __stratum_add_instance(ckp, msg->client_id, address, server);
} else
dropped = true;
} else if (unlikely(client->dropped)) } else if (unlikely(client->dropped))
dropped = true; dropped = true;
if (likely(!dropped)) if (likely(!dropped))

Loading…
Cancel
Save