diff --git a/sql/luck.sh b/sql/luck.sh new file mode 100755 index 00000000..b4b2f609 --- /dev/null +++ b/sql/luck.sh @@ -0,0 +1,318 @@ +#!/bin/bash +# +tmp="/tmp/`basename $0`-$$" +tmp0="$tmp.0.sql" +tmp1="$tmp.1.sql" +tmp2="$tmp.2.sql" +tmp3="$tmp.3.sql" +tmp4="$tmp.4.sql" +msdd="1,000,000,000" +msd="`echo "$msdd" | tr -d ,`" +# +usAge() +{ + echo "usAge: `basename $0` [-s sdiffX] [w] 0|[b startblock]|[s shift] endblock|z" + echo " run as root or change dosql1()" + echo + echo " -s sdiffX = all shares must have minsdiff <= sdiffX - if not then abort" + echo " any commas are removed with \"tr -d ,\"" + echo " shares with sdiff below sdiffX are ignored. Default $msdd" + echo " w = worker stats - without w = user stats" + echo " 0 = from the first hi share" + echo " b startblock = start after the workinfoid of startblock (instead of 0)" + echo " i.e. this only includes data AFTER 'startblock'" + echo " 'startblock' is the lowest block >= 'startblock'" + echo " s shift = start from the shift with the starting 5 char code 'shift'" + echo " if there ever is a duplicate, it will use the lowest one" + echo " endblock = finish at the workinfoid of endblock (instead of z)" + echo " this includes all of 'endblock'" + echo " 'endblock' is the highest block <= 'endblock'" + echo " z = to the last high share" + echo + echo " Basically would be '0 z' for all available share history or" + echo " e.g. 'b NNN MMM' for a block range after NNN up to (including) MMM or" + echo " e.g. 'b NNN z' starting after block NNN up to now" + echo " Put a 'w' in front, to get worker instead of user summarisation" + echo + echo " The share history determines the limits used" + echo " i.e. markersummaries before the first share, or after the last share," + echo " are not included since that would invalidate the results" + echo " Missing shares within the share data would invalidate the results" + exit 1 +} +# +dosql1() +{ + su - postgres << EOF +echo "$sql" | psql ckdb +EOF +} +# +procsql() +{ + got="" + fin="" + prev="" + while true ; do + read line + if [ "$?" != "0" ] ; then + break + fi + if [ "$got" ] ; then + if [ -z "$fin" ] ; then + echo "$line" + if [ "${line:0:1}" = "(" ] ;then + fin="y" + fi + fi + else + if [ "${line:0:5}" = "-----" ] ; then + got="y" + echo "$prev" + echo "$line" + else + prev="$line" + fi + fi + done +} +# +dosql() +{ + dosql1 2>&1 | procsql +} +# +# reduce a large, 9 or more digit, comma number with 2 decimal places to nnG +toG() +{ + sed -e "s/,\([0-9][0-9]\)[0-9],[0-9][0-9][0-9],[0-9][0-9][0-9]\.[0-9][0-9]*/.\1G/g" -e "s/\(\.[0-9][0-9]G\) *|/\1 |/g" -e "s/ *$//" +} +# +dedup() +{ + cut -d '|' -f 1-5,7-10,12 +} +# +dedupw() +{ + cut -d '|' -f 1-4,6-9,11 +} +# +p1="$((0x1d))" +p1v="`echo "$p1 3 - 8 * p" | dc`" +# +# calculate the diff ratio for each diffacc, given bits +diff1() +{ + read line + read line + while true ; do + read line + if [ "$?" != "0" ] ; then + break + fi + if [ "${line:0:1}" = "(" ] ; then + break + fi + bits="`echo "$line" | cut -d '|' -f2 | tr -d ' '`" + diffacc="`echo "$line" | cut -d '|' -f3 | tr -d ' '`" + po="$((0x${bits:0:2}))" + bi="$((0x${bits:2:6}))" + pd="`echo "$p1v $po 3 - 8 * - p" | dc`" + if [ "$pd" -lt "8" ] ; then + pd="8" + fi + per="`echo "8 k $diffacc 2 $pd ^ 65535 * $bi / / p" | dc`" + echo "$line | ${per}" + done +} +# +diffvals() +{ + grep "^$uorw *|" "$tmp4" | cut -d '|' -f4 | tr "\n" "+" | sed -e "s/+/ +/g" +} +# +getdiff() +{ + echo "4 k 0 `diffvals` p" | dc +} +# +# blocks are appended 3rd since if blocks exist, then at least 1 share must +proc() +{ + read line + read line + while true ; do + read line + if [ "$?" != "0" ] ; then + break + fi + if [ "${line:0:1}" = "(" ] ; then + echo "$line" + break + fi + uorw="`echo "$line" | cut -d'|' -f1 | tr -d ' '`" + diffs="`getdiff` BDR" + if [ "${diffs:0:1}" = "." ] ; then + diffs=" 0$diffs" + elif [ "${diffs:1:1}" = "." ] ; then + diffs=" $diffs" + elif [ "${diffs:2:1}" = "." ] ; then + diffs=" $diffs" + fi + stats="`grep "^$uorw *|" "$tmp2"`" + bstats="`grep "^$uorw *|" "$tmp3"`" + if [ "$stats" ] ; then + s=" | " + else + s="" + fi + if [ "$bstats" ] ; then + b=" | " + else + b="" + fi + echo "$line | $diffs$s$stats$b$bstats" + done +} +# +procblk() +{ + while true ; do + read line + if [ "$?" != "0" ] ; then + break + fi + if [ "${line:0:1}" = "(" ] ; then + echo "$line" + break + fi + uorw="`echo "$line" | cut -d'|' -f1 | tr -d ' '`" + bstats="`grep "^$uorw *|" "$tmp3"`" + echo "$line | $bstats" + done +} +# +if [ "$1" = "-s" ] ; then + shift + msd="`echo "$1" | tr -d ,`" + shift +fi +# +if [ -z "$1" ] ; then + usAge +fi +# +if [ "$1" = "-?" -o "$1" = "-h" -o "$1" = "-help" -o "$1" = "--help" ] ; then + usAge +fi +# +work="" +if [ "$1" = "w" ] ; then + work="w" + shift +fi +# +valsh="sdiff>=$msd" +# Orphans included, Rejects not - since they can be below diff, or invalid, or too late or ... +valblk="expirydate>'5555-05-05' and confirmed!='R'" +# +# START +if [ "$1" = "0" ] ; then + shift + selwm1="ms.markerid>=(select min(markerid) from workmarkers where workinfoidstart>=(select min(workinfoid) from shares))" + selsh1="" + selblk1="and b.workinfoid>=(select min(workinfoid) from shares)" +else + if [ "$1" = "s" ] ; then + shift + selwm1="ms.markerid>=(select min(markerid) from workmarkers where description like 'Shift fin: $1 %')" + selsh1="and workinfoid>=(select min(workinfoidstart) from workmarkers where description like 'Shift fin: $1 %')" + selblk1="$selsh1" + shift + else + if [ "$1" = "b" ] ; then + shift + selwm1="ms.markerid>=(select min(markerid) from workmarkers where workinfoidstart>(select min(workinfoid) from blocks where height>=$1))" + selsh1="and s.workinfoid>=(select min(workinfoid) from blocks where height>=$1)" + selblk1="and b.height>$1" + shift + else + echo "ERR: Unknown first option '$1'" + usAge + fi + fi +fi +# +# END +if [ "$1" = "z" ] ; then + selwm2="" + selsh2="" + selblk2="" +else + if [ -z "$1" ] ; then + echo "ERR: missing ending block|z" + usAge + else + selwm2="and wm.markerid<=(select max(markerid) from workmarkers where workinfoidend<=(select max(workinfoid) from blocks where height<=$1))" + selsh2="and s.workinfoid<=(select max(workinfoid) from blocks where height<=$1)" + selblk2="and b.height<=$1" + fi +fi +# +# check all shares have minsdiff > $msd +sql="select count(*) from shares s where s.minsdiff>$msd $selsh1 $selsh2 ;" +# +dosql > "$tmp0" +count="`head -n 3 "$tmp0" | tail -n 1`" +if [ "$count" != "0" ] ; then + count + echo "ERROR: there were '$count' shares with minsdiff>$msd - that must be '0'" + usAge +fi +# +# summarise markersummary into tmp1 for any user or worker with 'msd' diffacc or more +if [ -z "$work" ] ; then + sql="select ms.userid,substring(max(ms.workername) from '(^[^\._]*)'),to_char(sum(ms.diffacc),'999G999G999G999G999.99'),to_char(sum(ms.sharecount),'999G999G999G999G999') from markersummary ms where $selwm1 $selwm2 group by ms.userid having sum(ms.diffacc)>$msd order by sum(ms.diffacc) desc;" +else + sql="select ms.workername,to_char(sum(ms.diffacc),'999G999G999G999G999.99'),to_char(sum(ms.sharecount),'999G999G999G999G999.99') from markersummary ms where $selwm1 $selwm2 group by ms.workername having sum(ms.diffacc)>$msd order by sum(ms.diffacc) desc;" +fi +# +dosql > "$tmp1" +# +# summarise the shares into tmp2 +if [ -z "$work" ] ; then + sql="select s.userid,count(*),to_char(min(s.sdiff),'999G999G999G999G999.99'),to_char(max(s.sdiff),'999G999G999G999G999.99'),to_char(avg(s.sdiff),'999G999G999G999G999.99') from shares s where $valsh $selsh1 $selsh2 group by s.userid;" +else + sql="select s.workername,count(*),to_char(min(s.sdiff),'999G999G999G999G999.99'),to_char(max(s.sdiff),'999G999G999G999G999.99'),to_char(avg(s.sdiff),'999G999G999G999G999.99') from shares s where $valsh $selsh1 $selsh2 group by s.workername;" +fi +# +dosql > "$tmp2" +# +# summarise the blocks into tmp3 +if [ -z "$work" ] ; then + sql="select b.userid,count(*)||' B' from blocks b where $valblk $selblk1 $selblk2 group by b.userid;" +else + sql="select b.workername,count(*)||' B' from blocks b where $valblk $selblk1 $selblk2 group by b.workername;" +fi +# +dosql > "$tmp3" +# +# summarise diff% into tmp4 (all ids will have a value) +if [ -z "$work" ] ; then + sql0="select ms.userid,wi.bits,sum(ms.diffacc)" + sqlz="group by ms.userid,wi.bits;" +else + sql0="select ms.workername,wi.bits,sum(ms.diffacc)" + sqlz="group by ms.userid,ms.workername,wi.bits;" +fi +# +valwm="wm.status='p' and wm.expirydate>'5555-05-05'" +sql="$sql0 from markersummary ms join workmarkers wm on ms.markerid=wm.markerid join workinfo wi on wm.workinfoidend=wi.workinfoid where $valwm and $selwm1 $selwm2 $sqlz" +# +dosql | diff1 > "$tmp4" +# +# join (append) to each tmp1 row, the matching row/data in tmp4, tmp2 and tmp3 +cat "$tmp1" | proc | toG | dedup$work +# +shred -uz "$tmp0" "$tmp1" "$tmp2" "$tmp3" "$tmp4" &> /dev/null