34b790e2381539fa6830bd2129c5089f44be4595 max Tue Feb 26 02:14:18 2019 -0800 making hgGeneGraph bottleneck penalty stricter, refs #22999 diff --git src/hg/pyLib/hgLib.py src/hg/pyLib/hgLib.py index ed6d3d0..53a375e 100644 --- src/hg/pyLib/hgLib.py +++ src/hg/pyLib/hgLib.py @@ -39,38 +39,38 @@ # debug level: a number. the higher, the more debug info is printed verboseLevel = None cgiArgs = None # like in the kent tree, we keep track of whether we have already output the content-type line contentLineDone = False jksqlTrace = False def warn(format, *args): print (format % args) def errAbort(msg): " show msg and abort. Like errAbort.c " - if not contentLineDone: printContentType() print msg exit(0) def debug(level, msg): " output debug message with a given verbosity level " if level >= verboseLevel: + printContentType() print(msg+"<br>") sys.stdout.flush() def parseConf(fname): " parse a hg.conf style file, return as dict key -> value (all strings) " conf = {} for line in open(fname): line = line.strip() if line.startswith("#"): continue elif line.startswith("include "): inclFname = line.split()[1] absFname = normpath(join(dirname(fname), inclFname)) if os.path.isfile(absFname): inclDict = parseConf(absFname) @@ -320,30 +320,32 @@ def webStartGbNoBanner(prefix, title): " output the <head> part, largely copied from web.c / webStartGbNoBanner " print (getGbHeader() % (prefix, title, getNonce(), getNonce())) def runCmd(cmd, mustRun=True): " wrapper around system() that prints error messages. cmd preferably a list, not just a string. " import subprocess ret = subprocess.call(cmd) if ret!=0 and mustRun: errAbort("Could not run command %s" % cmd) return ret def printContentType(contType="text/html", fname=None): " print the HTTP Content-type header line with an optional file name " global contentLineDone + if contentLineDone: + return contentLineDone = True print("Content-type: %s; charset=utf-8" % contType) if fname is not None: print("Content-Disposition: attachment; filename=%s" % fname) print def queryBottleneck(host, port, ip): " contact UCSC-style bottleneck server to get current delay time. From hg/lib/botDelay.c " # send ip address import socket s = socket.socket() s.connect((host, int(port))) msg = ip d = chr(len(msg))+msg s.send(d) @@ -353,44 +355,46 @@ totalLen = 0 buf = list() while True: resp = s.recv(1024) buf.append(resp) totalLen+= len(resp) if totalLen==expLen: break return int("".join(buf)) def hgBotDelay(): """ Implement bottleneck delay, get bottleneck server from hg.conf. This behaves similar to the function src/hg/lib/botDelay.c:hgBotDelay It does not use the hgsid, currently it always uses the IP address. - Using the hgsid makes little sense. It is more lenient than that C version. + Using the hgsid makes little sense. It is more lenient than the C version. """ import time if "DOCUMENT_ROOT" not in os.environ: # skip if not called from Apache return global hgConf hgConf = parseHgConf() if "bottleneck.host" not in hgConf: return ip = os.environ["REMOTE_ADDR"] delay = queryBottleneck(hgConf["bottleneck.host"], hgConf["bottleneck.port"], ip) - if delay>10000: + printContentType() + debug(1, "Bottleneck delay: %d msecs" % delay) + if delay>2000: time.sleep(delay/1000.0) - if delay>20000: + if delay>10000: errAbort("Too many queries. Your IP has been blocked. Please contact genome-www@soe.ucsc.edu to unblock your IP address.") sys.exit(0) def parseRa(text): " Parse ra-style string and return as dict name -> value " import string lines = text.split("\n") data = dict() for l in lines: if len(l)==0: continue key, val = string.split(l, " ", maxsplit=1) data[key] = val return data