diff -u -x '*.log' -x '*.pyc' -x '*.elf' -r jedi95-Phoenix-Miner-2b57b96.old/ConsoleLogger.py jedi95-Phoenix-Miner-2b57b96/ConsoleLogger.py --- jedi95-Phoenix-Miner-2b57b96.old/ConsoleLogger.py 2011-08-16 03:37:25.000000000 +0200 +++ jedi95-Phoenix-Miner-2b57b96/ConsoleLogger.py 2011-10-24 01:58:05.742230539 +0200 @@ -39,80 +39,525 @@ else: break return '%s%s %s' % (whole, decimal, prefixes[i]) - + +def formatPercent(n,m): + """Format a positive integer division as a percent.""" + if n < 0 or m < 0: + raise ValueError('can only format positive integers') + if m == 0: + return '' + if n == 0: + return '' + p = '%' + s = 1000000 * n / m + t = s % 100 + s = s / 100 + + if t == 50 and s % 2 == 1: + t = 51 + if t > 50: + t = 1 + else: + t = 0 + part = str(s + t) + while len(part) < 3: + part = "0" + part + if len(part) > 4: + return ' %s%s' % (part[:-2], p) + if len(part) < 4: + return ' %s.%s%s' % (part[-3:-2], part[-2:], p) + return ' %s.%s%s' % (part[-4:-2], part[-2:], p) + +def formatDecimal(n,m): + """Format a positive integer division as a decimal.""" + if n < 0 or m < 0: + raise ValueError('can only format positive integers') + if m == 0: + return '' + if n == 0: + return '' + s = 10000 * n / m + t = s % 100 + s = s / 100 + if t == 50 and s % 2 == 1: + t = 51 + if t > 50: + t = 1 + else: + t = 0 + part = str(s + t) + while len(part) < 3: + part = "0" + part + if len(part) > 4: + return ' %s' % part[:-2] + if len(part) < 4: + return ' %s.%s' % (part[-3:-2],part[-2:]) + return ' %s.%s' % (part[-4:-2],part[-2:]) + class ConsoleLogger(object): """This class will handle printing messages to the console.""" TIME_FORMAT = '[%d/%m/%Y %H:%M:%S]' - - UPDATE_TIME = 1.0 - - def __init__(self, miner, verbose=False): + + NETWORK_TIME = 5 # Number of seconds left for network to deliver new requested work + RESTART_CONNECTION = 300 # Number of seconds to wait before disconnect/connect phase on RPC/MMP connection to pool + SAMPLELPTIME1 = 100 + SAMPLELPTIME2 = 50 + SAMPLELPTIME3 = 25 + + MAXSAMPLE = 10 # Max + 1 number of accepted or rejected results in one getwork + + RECEIVED = 0 + ABANDONWORK = 1 + WASTEWORK = 2 + UNSOLVEWORK = 3 + ACCEPTWORK = 4 + REJECTWORK = 5 + ACCEPTED = 6 + REJECTED = 7 + MAXWORK = 8 + + THIS_PART = 0 + BLOCK_PART = 1 + SUM_PART = 2 + STR_PART = 3 + + def __init__(self, miner, verbose=False, logtotext=None): + self.first = True self.verbose = verbose + self.noShow = False + self.showPercent = False + self.showReceived = False + self.showWork = False + self.showBlocks = False + self.showLongPulls = False + self.showDevice = False + self.showCompact = False + self.showDetail = 0 # 0=None, 1=some, 2=show new block stats, 4=show queue stats + self.showLogDetail = 0 + self.showNewBlockTime = 0 + + self.updateTime = 1.0 + self.kernelPlatform = None + self.kernelDevice = None self.miner = miner self.lastUpdate = time() - 1 - self.rate = 0 - self.accepted = 0 - self.invalid = 0 + self.started = self.lastUpdate + 1 + self.lastLP = self.started + self.lastWork = None + self.logtotext = logtotext + self.oldstatus = '' self.lineLength = 0 self.connectionType = None - - def reportRate(self, rate, update=True): + + self.workOn = None + self.rate = 0 + self.blocks = 0 # How many blocks we have worked on + self.longPulls = 0 # How many long pulls have we received + + self.sumWork = [] + self.sumWork.append([]) + self.sumWork.append([]) + self.sumWork.append([]) + self.sumWork.append([]) + for i in range(0, self.MAXWORK): + self.sumWork[self.THIS_PART].append(0) # This part + self.sumWork[self.BLOCK_PART].append(0) # Block part + self.sumWork[self.SUM_PART].append(0) # Total part + self.sumWork[self.STR_PART].append('') # String percentage part + + self.newBlockTimes = [] # The different new block times + self.newBlockTime = [] # As all new block times are essentially the same, they can live in one array + self.newBlockMax = 0 # Max number of new block times + self.newBlockTop = 0 + + self.sampleAccept = [] + self.sampleReject = [] + self.sampleTotAcc = [] + self.sampleTotRej = [] + for i in range(0, self.MAXSAMPLE): + self.sampleAccept.append(0) + self.sampleTotAcc.append(0) + self.sampleReject.append(0) + self.sampleTotRej.append(0) + if self.logtotext is not None: + d = datetime.now().strftime(self.TIME_FORMAT) + msg = d + '\n' + msg = msg + d + ' ' + 'Phoenix Miner %s Started' % miner.VERSION + '\n' + msg = msg + d + ' ' + '----------------------------------' + self.logToText(msg, True) + + def setNoShow(self, arg): + """Change if we shall show anything to console or not. Log not affected.""" + self.noShow = arg + + def setShowPercent(self, arg): + """Change if we shall show procentage of accepted and rejected of received work""" + self.showPercent = arg + + def setShowReceived(self, arg): + """Change if we shall show received number of work or not in status.""" + self.showReceived = arg + + def setShowCompact(self, arg): + """Change if we shall show status in compact mode or not.""" + self.showCompact = arg + + def setShowDetail(self, arg): + """Change how detailed we are on the logs output. + 0=Don't be so detailed at all, give rough work ping pong + 1=Some details, give some internal stats + 2=Give block stats + 4=Give work queue stats + """ + self.showDetail = arg + + def setShowLogDetail(self, arg): + """Change how detailed we are on the logs output. + 0=Don't be so detailed at all, give rough work ping pong + 1=Some details, give some internal stats + 2=Give block stats + 4=Give work queue stats + """ + self.showLogDetail = arg + +# def setShowNewBlockTime(self, arg): +# """Change if we should show detailed time average +# on new blocks received or not. This information +# is shown together with the output of 'New Block' +# on both screen and if needed on log file as well. +# """ +# self.showNewBlockTime = arg + + def addNewBlockTime(self, arg): + """Add new time ranges for New Block. This will be + the number of new blocks received that should be + made an average on. + Arg is an comma separated list of numbers as a string. + """ + for a in arg.split(','): + v = int(a) + self.newBlockTimes.append(v) + self.newBlockMax += 1 + if self.newBlockTop < v: + self.newBlockTop = v # Save largest size of table + + def setShowLongPulls(self, arg): + """Change if we shall show number of long pulls in status or not.""" + self.showLongPulls = arg + + def setShowDevice(self, arg): + """Change if we shall show device number in status or not.""" + self.showDevice = arg + + def setShowBlocks(self, arg): + """Change if we shall show received number of blocks or not in status.""" + self.showBlocks = arg + + def setShowWork(self, arg): + """Change if we shall show wasted number of work or not in status.""" + self.showWork = arg + + def setUpdateFrequence(self, arg): + """Change how often in seconds we check for update status line change.""" + self.updateTime = 1.0 * arg + + def _sumthis(self, t, v = 1, th = False): + self.sumWork[self.SUM_PART][t] += v # Add to total for all blocks + self.sumWork[self.BLOCK_PART][t] += v # Add to total for this block only + if th: # Also, add to this part, ie. to the sum for this work only + if self.sumWork[self.THIS_PART][t] + v < self.MAXSAMPLE: + self.sumWork[self.THIS_PART][t] += v + else: + self.sumWork[self.THIS_PART][t] = self.MAXSAMPLE - 1 + if self.showPercent and t != self.RECEIVED: + self.sumWork[self.STR_PART][t] = formatPercent(self.sumWork[self.SUM_PART][t], self.sumWork[self.SUM_PART][self.RECEIVED]) + + def reportRate(self, rate, update=False): """Used to tell the logger the current Khash/sec.""" + isDifferentRate = (self.rate != rate) self.rate = rate - if update: + if update or isDifferentRate: self.updateStatus() - + def reportType(self, type): self.connectionType = type - + + def reportKernelInfo(self, platform, device): + self.kernelPlatform = platform + self.kernelDevice = device + def reportBlock(self, block): - self.log('Currently on block: ' + str(block)) - + msg = 'Currently on block: ' + str(block) + self.logToText(msg) + self.canLog(msg) + + def reportReceived(self, ignore=None): + self._sumthis(self.RECEIVED, 1, True) # Add to received total and to total for this block as well + if self.blocks == 0: + self.blocks += 1 # Make sure that we show current block recveived at all time + if self.showPercent: + for i in range(0, self.MAXWORK): + if i != self.RECEIVED: + self.sumWork[self.STR_PART][i] = formatPercent(self.sumWork[self.SUM_PART][i], self.sumWork[self.SUM_PART][self.RECEIVED]) + msg = 'reportReceived' + if ignore is not None: + msg = msg + ('(%d)' % ignore) +# self.reportDebug(msg) + def reportFound(self, hash, accepted): if accepted: - self.accepted += 1 - else: - self.invalid += 1 - + t1 = self.ACCEPTED + t2 = self.ACCEPTWORK + else: + t1 = self.REJECTED + t2 = self.REJECTWORK + + if self.sumWork[self.THIS_PART][t1] == 0: + self._sumthis(t2) # Only add to accepted/rejected work if this is the first report on this work + self._sumthis(t1, 1, True) # Add to accepted/rejected totals and to total for this block as well + + self.workOn = 1 + hexHash = hash[::-1] hexHash = hexHash[:8].encode('hex') + msg = None if self.verbose: - self.log('Result %s... %s' % (hexHash, - 'accepted' if accepted else 'rejected')) + msg = 'Result %s... %s' % (hexHash, + 'accepted' if accepted else '-rejected') else: - self.log('Result: %s %s' % (hexHash[8:], - 'accepted' if accepted else 'rejected')) - + msg = 'Result: %s %s' % (hexHash[8:], + 'accepted' if accepted else '-rejected') + if msg is not None: + self.logToText(msg) + self.canLog(msg) + def reportMsg(self, message): - self.log(('MSG: ' + message), True, True) - + msg = 'MSG: ' + message + self.logToText(msg) + self.log(msg, True, True) + def reportConnected(self, connected): - if connected: - self.log('Connected to server') - else: - self.log('Disconnected from server') - + msg = 'Connected to server' if connected else 'Disconnected from server' + self.logToText(msg) + self.canLog(msg) + def reportConnectionFailed(self): - self.log('Failed to connect, retrying...') - + msg = 'Failed to connect, retrying...' + self.logToText(msg) + self.canLog(msg) + def reportDebug(self, message): if self.verbose: - self.log(message) - - def updateStatus(self, force=False): - #only update if last update was more than a second ago - dt = time() - self.lastUpdate - if force or dt > self.UPDATE_TIME: - rate = self.rate if (not self.miner.idle) else 0 - type = " [" + str(self.connectionType) + "]" if self.connectionType is not None else '' - status = ( - "[" + formatNumber(rate) + "hash/sec] " - "[" + str(self.accepted) + " Accepted] " - "[" + str(self.invalid) + " Rejected]" + type) - self.say(status) - self.lastUpdate = time() - + self.canLog(message) + + def reportPush(self, ignored=None): + self.longPulls += 1 + msg = 'LP: New work pushed' + self.logToText(msg) + self.canLog(msg) + + def reportNewBlock(self, ignored=None): + # The first call here is called out of phase at the begining of the program. + # It should not be called, but the sequence of calls are easiest fixed with this + # flag, so I don't mess with the statistics. + if self.first: + #self.first = False # This is cleared in reportNewWork, as it is called as well out of phase. + return + self.reportNewWork() + msg = 'New Block' + now = time() + dt = now - self.started + if self.lastLP is not None: + self.newBlockTime.append(now - self.lastLP) + self.newBlockTime = self.newBlockTime[ -self.newBlockTop: ] + if self.blocks > 0: + if self.newBlockMax == 0: + msg = msg + ', %s' % self.formatTime(dt/self.blocks) + for i in range(0, self.newBlockMax): + b = None + b = self.newBlockTime[ -self.newBlockTimes[ i ]: ] + t = sum(b) / len(b) + msg = msg + ', %s(%d)' % (self.formatTime(t), self.newBlockTimes[ i ]) + msg = msg + ' sec on blocks, %s sec on last' % self.formatTime(now - self.lastLP) + + self.blocks += 1 + # Move all statistics for last block to totals. Different all single accept work from double accept work aso, + # as well as for rejects. + for i in range(0, self.MAXSAMPLE): + self.sampleTotAcc[ i ] += self.sampleAccept[ i ] + self.sampleTotRej[ i ] += self.sampleReject[ i ] + + # Produce statistics output + msg2 = '' + for (v, s) in ([self.sumWork[self.BLOCK_PART][self.RECEIVED], 'r'], + [self.sumWork[self.BLOCK_PART][self.ABANDONWORK], 'n'], + [self.sumWork[self.BLOCK_PART][self.WASTEWORK], 'w'], + [self.sumWork[self.BLOCK_PART][self.UNSOLVEWORK], 'u']): + if v > 0: + if msg2 != '': + msg2 = msg2 + ', ' + msg2 = msg2 + ('%s=%d' % (s, v)) + for (a, s) in ([self.sampleAccept, 'a'], [self.sampleReject, 'r']): + for i in range(1,self.MAXSAMPLE): + if a[ i ] > 0: + if msg2 != '': + msg2 = msg2 + ', ' + msg2 = msg2 + ('%s[%d]=%d' % (s, i, a[ i ])) + + msg3 = '' + for (v, s) in ([self.sumWork[self.SUM_PART][self.RECEIVED], 'r'], + [self.sumWork[self.SUM_PART][self.ABANDONWORK], 'n'], + [self.sumWork[self.SUM_PART][self.WASTEWORK], 'w'], + [self.sumWork[self.SUM_PART][self.UNSOLVEWORK], 'u']): + if v > 0: + if msg3 != '': + msg3 = msg3 + ', ' + msg3 = msg3 + ('%s=%d' % (s, v)) + for (a, s) in ([self.sampleTotAcc, 'a'], [self.sampleTotRej, 'r']): + for i in range(1,self.MAXSAMPLE): + if a[ i ] > 0: + if msg3 != '': + msg3 = msg3 + ', ' + msg3 = msg3 + ('%s[%d]=%d' % (s, i, a[ i ])) + + self.logToText(msg) + if msg2 != '': + msg2 = 'Cur: ' + msg2 + if msg3 != '': + msg3 = 'Tot: ' + msg3 + self.canLog(msg, msg2 == '' and msg3 == '') + if msg2 != '' and self.verbose: + self.logToText(msg2) + self.canLog(msg2, msg3 == '') + if msg3 != '' and self.verbose: + self.logToText(msg3) + self.canLog(msg3) + self.lastLP = now + self.sampleAccept = [] + self.sampleReject = [] + for i in range(0, self.MAXSAMPLE): + self.sampleAccept.append(0) + self.sampleReject.append(0) + for i in range(0, self.MAXWORK): + self.sumWork[self.BLOCK_PART][i] = 0 + + def reportAbandon(self, ignored=None): + t = 1 if ignored is None else ignored + self._sumthis(self.ABANDONWORK, t, True) + msg = 'Abandon work' + self.logToText(msg) + self.canLog(msg, False) + self.miner.queue.storePush() + + def reportWaste(self, ignored=None): + if self.workOn is None: + self._sumthis(self.WASTEWORK, 1, True) + msg = 'Wasted work' + self.logToText(msg) + self.canLog(msg, False) + self.workOn = 1 + + def reportNewWork(self, ignored=None): + if self.first: + self.first = False + return + if ignored is None: + if self.workOn is None: + self._sumthis(self.UNSOLVEWORK, 1, True) + msg = 'Unsolved work' + self.logToText(msg) + self.canLog(msg, False) + if self.sumWork[self.THIS_PART][self.ACCEPTED] > 0: + self.sampleAccept[ self.sumWork[self.THIS_PART][self.ACCEPTED] ] += 1 + if self.sumWork[self.THIS_PART][self.REJECTED] > 0: + self.sampleReject[ self.sumWork[self.THIS_PART][self.REJECTED] ] += 1 + + self.workOn = None + self.sumWork[self.THIS_PART][self.ABANDONWORK] = 0 + self.sumWork[self.THIS_PART][self.WASTEWORK] = 0 + self.sumWork[self.THIS_PART][self.UNSOLVEWORK] = 0 + self.sumWork[self.THIS_PART][self.RECEIVED] = 0 + self.sumWork[self.THIS_PART][self.ACCEPTED] = 0 + self.sumWork[self.THIS_PART][self.REJECTED] = 0 + + def formatTime(self, t): + #"""Format an integer of seconds as h:m:s format""" + if t < 0: + raise ValueError('can only format positive integers') + t = int(t + 0.5) + if t == 0: + return '0' + h = int(t / 3600) + t = int(t % 3600) + m = int(t / 60) + s = int(t % 60) + ms = str(m) + ss = str(s) + if h > 0: + hs = str(h) + ':' + if len(ms) == 1: + ms = '0' + ms + else: + hs = '' + if m > 0 or len(ms) == 2: + ms = ms + ':' + if len(ss) == 1: + ss = '0' + ss + else: + ms = '' + return '%s%s%s' % (hs, ms, ss) + + def updateStatus(self, force=False, log=False): + #only update if last update was more than updateTime seconds ago + now = time() + dt = now - self.lastUpdate + if force or dt > self.updateTime: + pstr = '|' if self.showCompact else '[' + lstr = '' if self.showCompact else '] ' + rate = self.rate # if (not self.miner.idle) else 0 + if self.showCompact: + pst = '|' + lst = ']' + else: + pst = '[' + lst = '' + type = pst + str(self.connectionType) + ']' if self.connectionType is not None else lst + + pstat = '[' + formatNumber(rate) + ('h/s' if self.showCompact else 'hash/sec] ') + + dstat = (pstr + 'Dev ' + str(self.kernelPlatform) + '-' + str(self.kernelDevice) + lstr) if self.showDevice else '' + + nstatus = '' + if self.showReceived: + nstatus = nstatus + pstr + str(self.sumWork[self.SUM_PART][self.RECEIVED]) + ' Rcv' + lstr + if self.showBlocks: + nstatus = nstatus + pstr + str(self.blocks) + ' Blk' + lstr + if self.showLongPulls: + nstatus = nstatus + pstr + str(self.longPulls) + ' LP' + lstr + if self.showWork: + nstatus = nstatus + ( + pstr + str(self.sumWork[self.SUM_PART][self.ABANDONWORK]) + (" AbnW%s" % self.sumWork[self.STR_PART][self.ABANDONWORK]) + lstr + + pstr + str(self.sumWork[self.SUM_PART][self.WASTEWORK]) + (" WstW%s" % self.sumWork[self.STR_PART][self.WASTEWORK]) + lstr + + pstr + str(self.sumWork[self.SUM_PART][self.UNSOLVEWORK]) + (" UsvW%s" % self.sumWork[self.STR_PART][self.UNSOLVEWORK]) + lstr + + pstr + str(self.sumWork[self.SUM_PART][self.ACCEPTWORK]) + (" ActW%s" % self.sumWork[self.STR_PART][self.ACCEPTWORK]) + lstr + + pstr + str(self.sumWork[self.SUM_PART][self.REJECTWORK]) + (" RejW%s" % self.sumWork[self.STR_PART][self.REJECTWORK]) + lstr + + "" + ) + nstatus = nstatus + ( + pstr + str(self.sumWork[self.SUM_PART][self.ACCEPTED]) + (" Act%s" % self.sumWork[self.STR_PART][self.ACCEPTED]) + lstr + + pstr + str(self.sumWork[self.SUM_PART][self.REJECTED]) + (" Rej%s" % self.sumWork[self.STR_PART][self.REJECTED]) + lstr + + "" + ) + + status = pstat + nstatus + dstat + type + if not self.noShow: + self.say(status) + if nstatus != self.oldstatus and log: + self.logToText(status) + self.oldstatus = nstatus + self.lastUpdate = now + def say(self, message, newLine=False, hideTimestamp=False): #add new line if requested if newLine: @@ -121,19 +566,19 @@ timestamp = '' else: timestamp = datetime.now().strftime(self.TIME_FORMAT) + ' ' - + message = timestamp + message - + #erase the previous line if self.lineLength > 0: - sys.stdout.write('\b \b' * self.lineLength) + sys.stdout.write('\r') sys.stdout.write(' ' * self.lineLength) - sys.stdout.write('\b \b' * self.lineLength) + sys.stdout.write('\r') #print the line sys.stdout.write(message) sys.stdout.flush() - + #cache the current line length if newLine: self.lineLength = 0 @@ -141,7 +586,20 @@ self.lineLength = len(message) def log(self, message, update=True, hideTimestamp=False): - self.say(message, True, hideTimestamp) + self.say(message, True, hideTimestamp) if update: self.updateStatus(True) - \ Ingen nyrad vid filslut + + def canLog(self, message, update=True, hideTimestamp=False): + if not self.noShow: + self.log(message, update, hideTimestamp) + + def logToText(self, message, hideTimeStamp=False): + if self.logtotext is not None: + if hideTimeStamp: + d = '' + else: + d = datetime.now().strftime(self.TIME_FORMAT) + ' ' + fileHandle = open (self.logtotext, 'a') + fileHandle.write(d + message + '\n') + fileHandle.close() diff -u -x '*.log' -x '*.pyc' -x '*.elf' -r jedi95-Phoenix-Miner-2b57b96.old/KernelInterface.py jedi95-Phoenix-Miner-2b57b96/KernelInterface.py --- jedi95-Phoenix-Miner-2b57b96.old/KernelInterface.py 2011-08-16 03:37:25.000000000 +0200 +++ jedi95-Phoenix-Miner-2b57b96/KernelInterface.py 2011-10-17 02:37:35.679622071 +0200 @@ -128,6 +128,9 @@ def setMeta(self, var, value): """Set metadata for this kernel.""" + self.debug("KernelInterface: var=%s, val=%s" % (str(var), str(value))) + if self.miner.logger.verbose: + self.miner.logger.logToText("KernelInterface: var=%s, val=%s" % (str(var), str(value))) self.miner.connection.setMeta(var, value) def fetchRange(self, size=None): @@ -140,6 +143,9 @@ else: return self.miner.queue.fetchRange(size) + def reportAbandon(self, ignored=None): + self.miner.logger.reportAbandon(ignored) + def addStaleCallback(self, callback): """Register a new function to be called, with no arguments, whenever a new block comes out that would render all previous work stale, @@ -204,6 +210,9 @@ # Check if the block has changed while this NonceRange was being # processed by the kernel. If so, don't send it to the server. if self.miner.queue.isRangeStale(nr): + msg = 'KernelInterface: NounceRage is stale, new block arrived before this solution' + self.miner.logger.logToText(msg) + self.debug(msg) return False # Check if the hash meets the full difficulty before sending. @@ -217,8 +226,9 @@ d.addCallback(callback) return True else: - self.miner.logger.reportDebug("Result didn't meet full " - "difficulty, not sending") + msg = "KernelInterface: Result didn't meet full difficulty, not sending" + self.miner.logger.logToText(msg) + self.debug(msg) return False def debug(self, msg): @@ -229,11 +239,12 @@ def log(self, msg, withTimestamp=True, withIdentifier=True): """Log some general kernel information to the console.""" - self.miner.logger.log(msg, True, not withTimestamp) + self.miner.logger.canLog(msg, True, not withTimestamp) def error(self, msg=None): """The kernel has an issue that requires user attention.""" if msg is not None: + self.miner.logger.logToText('KernelInterface: Error, ' + msg) self.miner.logger.log('Kernel error: ' + msg) def fatal(self, msg=None): @@ -241,8 +252,9 @@ operate. """ if msg is not None: + self.miner.logger.logToText('KernelInterface: FATAL, ' + msg) self.miner.logger.log('FATAL kernel error: ' + msg, False) if reactor.running: reactor.stop() os._exit(0) - \ Ingen nyrad vid filslut + diff -u -x '*.log' -x '*.pyc' -x '*.elf' -r jedi95-Phoenix-Miner-2b57b96.old/kernels/phatk2/__init__.py jedi95-Phoenix-Miner-2b57b96/kernels/phatk2/__init__.py --- jedi95-Phoenix-Miner-2b57b96.old/kernels/phatk2/__init__.py 2011-08-16 03:37:25.000000000 +0200 +++ jedi95-Phoenix-Miner-2b57b96/kernels/phatk2/__init__.py 2011-08-30 06:34:11.054297602 +0200 @@ -21,6 +21,7 @@ # THE SOFTWARE. import pyopencl as cl +#import OpenCL as cl import numpy as np import os import math diff -u -x '*.log' -x '*.pyc' -x '*.elf' -r jedi95-Phoenix-Miner-2b57b96.old/kernels/poclbm/__init__.py jedi95-Phoenix-Miner-2b57b96/kernels/poclbm/__init__.py --- jedi95-Phoenix-Miner-2b57b96.old/kernels/poclbm/__init__.py 2011-08-16 03:37:25.000000000 +0200 +++ jedi95-Phoenix-Miner-2b57b96/kernels/poclbm/__init__.py 2011-08-30 05:38:48.944303451 +0200 @@ -401,4 +401,4 @@ self.output.fill(0) cl.enqueue_write_buffer( self.commandQueue, self.output_buf, self.output) - \ Ingen nyrad vid filslut + diff -u -x '*.log' -x '*.pyc' -x '*.elf' -r jedi95-Phoenix-Miner-2b57b96.old/Miner.py jedi95-Phoenix-Miner-2b57b96/Miner.py --- jedi95-Phoenix-Miner-2b57b96.old/Miner.py 2011-08-16 03:37:25.000000000 +0200 +++ jedi95-Phoenix-Miner-2b57b96/Miner.py 2011-10-24 00:04:50.801915555 +0200 @@ -29,8 +29,8 @@ class Miner(object): # This must be manually set for Git - VER = (1, 6, 2) - REVISION = reduce(lambda x,y: x*100+y, VER) + VER = (1, 6, 2, 1) + REVISION = reduce(lambda x,y: x*100+y if x < 1000000 else x, VER) VERSION = 'v%s' % '.'.join(str(x) for x in VER) def __init__(self): @@ -45,6 +45,8 @@ self.failures = 0 self.lastMetaRate = 0.0 self.lastRateUpdate = time() + self.myPush = False + self.timeout = None # Connection callbacks... def onFailure(self): @@ -63,12 +65,16 @@ def onMsg(self, msg): self.logger.reportMsg(msg) def onWork(self, work): + self.queue.storeWork(work, self.myPush) self.logger.reportDebug('Server gave new work; passing to WorkQueue') - self.queue.storeWork(work) + self.logger.reportReceived() + self.myPush = False def onLongpoll(self, lp): - self.logger.reportType('RPC' + (' (+LP)' if lp else '')) + self.logger.reportType('RPC' + ('+LP' if lp else '')) def onPush(self, ignored): - self.logger.log('LP: New work pushed') + self.logger.reportPush() + self.queue.storePush(True) + self.myPush = True def onLog(self, message): self.logger.log(message) def onDebug(self, message): @@ -82,13 +88,15 @@ self.connection = None #log - self.logger.log("Backup server failed,") - self.logger.log("attempting to return to primary server.") + self.logger.canLog("Backup server failed,") + self.logger.canLog("attempting to return to primary server.") #reset failure count and return to primary server self.failures = 0 self.backup = False self.connection = self.options.makeConnection(self) + self.kernel.applyMeta() + self.applyMeta() self.connection.connect() else: self.failures += 1 @@ -100,13 +108,15 @@ self.connection = None #log - self.logger.log("Primary server failed too many times,") - self.logger.log("attempting to connect to backup server.") + self.logger.canLog("Primary server failed too many times,") + self.logger.canLog("attempting to connect to backup server.") #reset failure count and connect to backup server self.failures = 0 self.backup = True self.connection = self.options.makeConnection(self, True) + self.kernel.applyMeta() + self.applyMeta() self.connection.connect() else: self.failures += 1 @@ -126,10 +136,11 @@ self.logger = self.options.makeLogger(self, self) self.connection = self.options.makeConnection(self) self.kernel = self.options.makeKernel(KernelInterface(self)) + self.logger.reportKernelInfo(self.kernel.PLATFORM,self.kernel.DEVICE) self.queue = self.options.makeQueue(self) #log a message to let the user know that phoenix is starting - self.logger.log("Phoenix %s starting..." % self.VERSION) + self.logger.canLog("Phoenix %s starting..." % self.VERSION) #this will need to be changed to add new protocols if isinstance(self.connection, MMPClient): @@ -166,21 +177,49 @@ #if idle status has changed force an update if self.idle != idle: + self.idle = idle if idle: - self.idle = idle - self.logger.log("Warning: work queue empty, miner is idle") self.logger.reportRate(0, True) self.connection.setMeta('rate', 0) self.lastMetaRate = time() - self.idleFixer() + reactor.callLater(1, self.idleCheck) + self.timeout = 300/15 # If timed out more then 5 min, make a reconnect by dropping conn and reestablish it again else: - self.idle = idle self.logger.updateStatus(True) + self.timeout = None + + def idleCheck(self): + if self.idle: + self.queue.storePush() + msg = "Warning: work queue empty, miner is idle" + self.logger.logToText(msg) + self.logger.canLog(msg) + reactor.callLater(14, self.idleFixer) + #request work from the protocol every 15 seconds while idle def idleFixer(self): if self.idle: - self.connection.requestWork() + self.queue.storePush() # Work taking too long, don't count it + msg = "Warning: still idle work queue, requesting more work..." + if self.timeout is not None: + if self.timeout == 0: # We have a timeout... + msg = "Warning: still idle work queue, doing brute force disconnect/connect cycle..." + self.timeout = 300/15 + self.connection.disconnect() + self.connection = None + self.connection = self.options.makeConnection(self, self.backup) + self.kernel.applyMeta() + self.applyMeta() + self.connection.connect() + else: + self.timeout -= 1 + self.connection.requestWork() + else: + self.timeout = 300/15 # strange behaviour, just resume on track + self.connection.requestWork() + self.logger.logToText(msg) + self.logger.canLog(msg) reactor.callLater(15, self.idleFixer) def updateAverage(self): @@ -196,4 +235,4 @@ # Let's not spam the server with rate messages. if self.lastMetaRate+30 < time(): self.connection.setMeta('rate', total) - self.lastMetaRate = time() \ Ingen nyrad vid filslut + self.lastMetaRate = time() diff -u -x '*.log' -x '*.pyc' -x '*.elf' -r jedi95-Phoenix-Miner-2b57b96.old/minerutil/RPCProtocol.py jedi95-Phoenix-Miner-2b57b96/minerutil/RPCProtocol.py --- jedi95-Phoenix-Miner-2b57b96.old/minerutil/RPCProtocol.py 2011-08-16 03:37:25.000000000 +0200 +++ jedi95-Phoenix-Miner-2b57b96/minerutil/RPCProtocol.py 2011-09-28 21:34:29.334780033 +0200 @@ -127,8 +127,12 @@ (headers, result) = x except TypeError: return - self.root.handleWork(result) + # Note, these two where run the other way around, + # but we need to handle them in correct order for the + # flags to be handled correctly in other parts of the + # miner. self.root.handleHeaders(headers) + self.root.handleWork(result) finally: self._startCall() # Minor bug in the #3420 patch; you can't start new requests during @@ -410,4 +414,4 @@ if self.longPoller: self.longPoller.stop() self.longPoller = None - self.runCallback('longpoll', False) \ Ingen nyrad vid filslut + self.runCallback('longpoll', False) diff -u -x '*.log' -x '*.pyc' -x '*.elf' -r jedi95-Phoenix-Miner-2b57b96.old/phoenix.py jedi95-Phoenix-Miner-2b57b96/phoenix.py --- jedi95-Phoenix-Miner-2b57b96.old/phoenix.py 2011-08-16 03:37:25.000000000 +0200 +++ jedi95-Phoenix-Miner-2b57b96/phoenix.py 2011-10-23 21:07:41.700985053 +0200 @@ -47,21 +47,74 @@ self._parse() def _parse(self): - parser = OptionParser(usage="%prog -u URL [-k kernel] [kernel params]") - parser.add_option("-v", "--verbose", action="store_true", - dest="verbose", default=False, help="show debug messages") + parser = OptionParser(usage="%prog -u URL [phoenix options] [-k kernel] [kernel params]") + parser.add_option("-2", "--use2phase", action="store_true", + dest="use2phase", default=False, + help="Use the two phase option to minimize queue abandon. ") +# "Can be unstable for miner rigs above 800MHash/sec") + parser.add_option("-a", "--avgsamples", dest="avgsamples", + type="int", default=10, + help="how many samples to use for hashrate average") + parser.add_option("-B", "--showblock", action="store_true", + dest="showBlocks", default=False, + help="Show received number of blocks on status line") + parser.add_option("-b", "--backupurl", dest="url2", default=None, + help="the URL of the backup mining server to work for if the " + "primary is down [OPTIONAL]") + parser.add_option("-c", "--showcompact", action="store_true", + dest="showCompact", default=False, + help="Show status in compact mode") + #parser.add_option("-D", "--showdetail", dest="showDetail", + # type="int", default=0, + # help="Show how detailed we should be. " + # "NOT Implemented YET!!!") + parser.add_option("-d", "--showdevice", action="store_true", + dest="showDevice", default=False, + help="Show kernel info on status line") + parser.add_option("-f", "--frequence", dest="frequence", type="int", + default=1, help="how many seconds between screen updates") parser.add_option("-k", "--kernel", dest="kernel", default="phatk2", help="the name of the kernel to use") + #parser.add_option("-L", "--showlogdetail", dest="showLogDetail", + # type="int", default=0, + # help="show how detailed we should be in logs. " + # "NOT Implemented YET!!!") + parser.add_option("-l", "--logtotext", dest="logtotext", default=None, + help="Log to text file") + parser.add_option("-N", "--networkdelay", dest="networkDelay", + type="int", default=5, + help="How many seconds before new work to request for more. Default is 5 seconds. " + "This can be tweeked down to 1 to use -2 even for faster rigs") + parser.add_option("-n", "--noshow", action="store_true", + dest="noshow", default=False, + help="Don't show anything on screen but errors") + parser.add_option("-P", "--showlongpull", action="store_true", + dest="showLongPulls", default=False, + help="Show long pulls on status line") + parser.add_option("-p", "--showpercent", action="store_true", + dest="showPercent", default=False, + help="Show percent of accepted and rejected work of received work") + parser.add_option("-q", "--queuesize", dest="queuesize", + type="int", default=1, + help="How many work units to keep queued at all times") + parser.add_option("-r", "--showreceived", action="store_true", + dest="showReceived", default=False, + help="Show number of received work on status line") + #parser.add_option("-T", "--shownewblocktime", action="store_true", + # dest="showNewBlockTime", default=False, + # help="Show time average on new blocks received. " + # "Use -t to add the specific times") + parser.add_option("-t", "--addblocktime", dest="addblocktime", default=None, + help="Add specific time averages as a comma separated list to show for new block arriavals.") parser.add_option("-u", "--url", dest="url", default=None, help="the URL of the mining server to work for [REQUIRED]") - parser.add_option("-b", "--backupurl", dest="url2", default=None, - help="the URL of the backup mining server to work for if the " - "primary is down [OPTIONAL]") - parser.add_option("-q", "--queuesize", dest="queuesize", type="int", - default=1, help="how many work units to keep queued at all times") - parser.add_option("-a", "--avgsamples", dest="avgsamples", type="int", - default=10, - help="how many samples to use for hashrate average") + parser.add_option("-v", "--verbose", action="store_true", + dest="verbose", default=False, + help="Show debug messages") + parser.add_option("-w", "--showwork", action="store_true", + dest="showWork", default=False, + help="Show number of work abandoned, wasted, accepted and rejected on status line. " + "If -p is also used, show the above with percent against received work as well") self.parsedSettings, args = parser.parse_args() @@ -89,7 +142,34 @@ def makeLogger(self, requester, miner): if not self.logger: - self.logger = ConsoleLogger(miner, self.parsedSettings.verbose) + self.logger = ConsoleLogger(miner, self.parsedSettings.verbose, self.parsedSettings.logtotext) + if self.parsedSettings.noshow: + self.logger.setNoShow(self.parsedSettings.noshow) + self.parsedSettings.frequence = 999 # effectivly inhibit screen update frequence as it should not be used at all. + if self.parsedSettings.showCompact: + self.logger.setShowCompact(self.parsedSettings.showCompact) + # if self.parsedSettings.showDetail > 0: + # self.logger.setShowDetail(self.parsedSettings.showDetail) + # if self.parsedSettings.showLogDetail > 0: + # self.logger.setShowLogDetail(self.parsedSettings.showLogDetail) + if self.parsedSettings.showDevice: + self.logger.setShowDevice(self.parsedSettings.showDevice) + if self.parsedSettings.addblocktime: + self.logger.addNewBlockTime(self.parsedSettings.addblocktime) + # if self.parsedSettings.showNewBlockTime: + # self.logger.setShowNewBlockTime(self.parsedSettings.showNewBlockTime) + if self.parsedSettings.showBlocks: + self.logger.setShowBlocks(self.parsedSettings.showBlocks) + if self.parsedSettings.showLongPulls: + self.logger.setShowLongPulls(self.parsedSettings.showLongPulls) + if self.parsedSettings.showReceived: + self.logger.setShowReceived(self.parsedSettings.showReceived) + if self.parsedSettings.showPercent: + self.logger.setShowPercent(self.parsedSettings.showPercent) + if self.parsedSettings.showWork: + self.logger.setShowWork(self.parsedSettings.showWork) + if self.parsedSettings.frequence > 0: + self.logger.setUpdateFrequence(self.parsedSettings.frequence) return self.logger def makeConnection(self, requester, backup = False): @@ -116,6 +196,10 @@ def makeQueue(self, requester): if not self.queue: self.queue = WorkQueue(requester, self) + if requester.options.parsedSettings.use2phase: + self.queue.setUse2Phase(requester.options.parsedSettings.use2phase) + if requester.options.parsedSettings.networkDelay > 0: + self.queue.setNetworkDelay(requester.options.parsedSettings.networkDelay) return self.queue if __name__ == '__main__': @@ -123,4 +207,4 @@ miner = Miner() miner.start(options) - reactor.run() \ Ingen nyrad vid filslut + reactor.run() diff -u -x '*.log' -x '*.pyc' -x '*.elf' -r jedi95-Phoenix-Miner-2b57b96.old/QueueReader.py jedi95-Phoenix-Miner-2b57b96/QueueReader.py --- jedi95-Phoenix-Miner-2b57b96.old/QueueReader.py 2011-08-16 03:37:25.000000000 +0200 +++ jedi95-Phoenix-Miner-2b57b96/QueueReader.py 2011-09-29 01:26:17.394802186 +0200 @@ -153,11 +153,14 @@ #meas a request for more work is already in progress if not self.dataQueue.empty(): # Out with the old... + #i = 0 while not self.dataQueue.empty(): try: self.dataQueue.get(False) + #i += 1 except Empty: continue # ...in with the new. + #self.interface.reportAbandon(i if i > 0 else 1) self._requestMore() def __iter__(self): @@ -191,4 +194,4 @@ reactor.callFromThread(self._requestMore) # currentData is actually a tuple, with item 0 intended for the kernel. - return self.currentData[0] \ Ingen nyrad vid filslut + return self.currentData[0] diff -u -x '*.log' -x '*.pyc' -x '*.elf' -r jedi95-Phoenix-Miner-2b57b96.old/WorkQueue.py jedi95-Phoenix-Miner-2b57b96/WorkQueue.py --- jedi95-Phoenix-Miner-2b57b96.old/WorkQueue.py 2011-08-16 03:37:25.000000000 +0200 +++ jedi95-Phoenix-Miner-2b57b96/WorkQueue.py 2011-10-24 00:21:09.041915648 +0200 @@ -19,8 +19,9 @@ # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN # THE SOFTWARE. +from time import time from minerutil.Midstate import calculateMidstate -from twisted.internet import defer +from twisted.internet import defer, reactor, error from collections import deque """A WorkUnit is a single unit containing 2^32 nonces. A single getWork @@ -54,7 +55,10 @@ """A WorkQueue contains WorkUnits and dispatches NonceRanges when requested by the miner. WorkQueues dispatch deffereds when they runs out of nonces. """ - + + SAMPLELEN = 5 # Number of moving samples to take averange on + MINNETTIME = 5 # The minimun time we expect the network to answer us + def __init__(self, miner, options): self.miner = miner @@ -67,24 +71,75 @@ self.block = '' self.lastBlock = None self.test = False + self.lastWork = None + self.sampleWorkLen = [] + self.sampleNetworkSpeed = [] + self.mode = 0 # 0 = do samples, queue as usual, 1 = optimize queue + self.myTick = 0 # Time to wait before requesting more work, if > 0 + self.hadAbandon = False + self.lastNetworkTime = 0 + self.networkAdjustTime = self.MINNETTIME + self.minNetworkDelay = self.MINNETTIME + self.askCall = None + self.decrementAdjust = None + self.myPush = False + self.use2phase = False # if set, use 2 state machine to reduce queue abandoned work + self.alreadyRequested = 0 # Number of already requested not received work # This is set externally. Not the best practice, but it can be changed # in the future. self.staleCallbacks = [] + + def _startCall(self, interval, where): + self._stopCall() + if interval: + self.askCall = reactor.callLater(interval, where) + else: + self.askCall = None + + def _stopCall(self): + if self.askCall: + try: + self.askCall.cancel() + except (error.AlreadyCancelled, error.AlreadyCalled): + pass + except: + pass + self.askCall = None + + def setUse2Phase(self, use2phase=False): + self.use2phase = use2phase + + def setNetworkDelay(self, networkDelay=None): + if networkDelay is None: + self.networkAdjustTime = self.MINNETTIME + else: + self.networkAdjustTime = networkDelay + self.minNetworkDelay = self.networkAdjustTime + # Called by foundNonce to check if a NonceRange is stale before submitting def isRangeStale(self, nr): return (nr.unit.data[4:36] != self.block) - - def storeWork(self, wu): - + + def storeWork(self, wu, onpush=False): + now = time() #check if this work matches the previous block if self.lastBlock is not None and (wu.data[4:36] == self.lastBlock): - self.logger.reportDebug('Server gave work from the previous ' - 'block, ignoring.') - #if the queue is too short request more work + self.logger.reportAbandon() # We are abandoning this work as it didn't meet criteria. + if not onpush: + self.logger.reportNewWork() + msg = 'Server gave work from the previous block, ignoring.' + self.logger.logToText(msg) + self.logger.reportDebug(msg) + self.alreadyRequested -= 1 + if self.alreadyRequested < 0: + self.alreadyRequested = 0 + if self.logger.verbose: + self.logger.logToText('WorkQueue: storeWork, alreadyRequested = %d' % self.alreadyRequested) + #if the queue is to short, request more work if (len(self.queue)) < (self.queueSize): - self.miner.connection.requestWork() + self._getWork('storeWork') return #create a WorkUnit @@ -98,23 +153,73 @@ #check if there is a new block, if so reset queue newBlock = (wu.data[4:36] != self.block) if newBlock: + if len(self.queue) > 0: + self.storePush() + self.logger.reportAbandon(len(self.queue)) self.queue.clear() self.currentUnit = None self.lastBlock = self.block self.block = wu.data[4:36] - self.logger.reportDebug("New block (WorkQueue)") + if onpush: + self.logger.reportWaste() + msg = "New block (WorkQueue) size %d bits" % int(wu.mask) + if self.logger.verbose: + self.logger.logToText(msg) + self.logger.reportDebug(msg) + self.logger.reportNewBlock() #clear the idle flag since we just added work to queue self.miner.reportIdle(False) - + + if self.lastNetworkTime != 0: + dt = now - self.lastNetworkTime + if dt > 0: # it took some time to get it from the net + if dt > self.networkAdjustTime: # it took longer then usual, add some time + self.networkAdjustTime += 0.4 + self._decrementAdjustTimeStart() + if self.networkAdjustTime >= self.myTick and self.myTick > 0: + if self.queueSize < int(dt / self.myTick): + self.queueSize += 1 + self.logger.logToText('WorkQueue: storeWork, adding queueSize %d(%d)' % (self.queueSize, int(dt/self.myTick))) + theQueue = deque('', self.queueSize) + while len(self.queue) > 0: + theQueue.append(self.queue.popleft()) + self.queue = None + self.queue = theQueue + else: + if self.queueSize - 1 > int(dt / self.myTick): + self.queueSize -= 1 + self.logger.logToText('WorkQueue: storeWork, lessen queueSize %d(%d)' % (self.queueSize, int(dt/self.myTick))) + if len(self.queue) > self.queueSize: + self.logger.reportAbandon(len(self.queue) - self.queueSize) + theQueue = deque('', self.queueSize) + while len(self.queue) > 0: + theQueue.append(self.queue.popleft()) + self.queue = None + self.queue = theQueue + + self.alreadyRequested -= 1 + if self.alreadyRequested < 0: + self.alreadyRequested = 0 + if self.logger.verbose: + self.logger.logToText('WorkQueue: storeWork, alreadyRequested = %d' % self.alreadyRequested) #add new WorkUnit to queue if work.data and work.target and work.midstate and work.nonces: + if len(self.queue) == self.queueSize: + self.logger.reportAbandon() self.queue.append(work) - - #if the queue is too short request more work - if (len(self.queue)) < (self.queueSize): - self.miner.connection.requestWork() - + + #if the queue is to short, request more work + if onpush: + self.myPush = onpush + if self.logger.verbose: + self.logger.logToText('WorkQueue: storeWork, queueSize %d(%d)' % (len(self.queue), self.queueSize)) + if (len(self.queue)) < (self.queueSize - 1): + self.requestWork('storeWork force,') + else: + if (len(self.queue)) < (self.queueSize): + self._getWork('storeWork') + #if there is a new block notify kernels that their work is now stale if newBlock: for callback in self.staleCallbacks: @@ -127,19 +232,96 @@ df, size = self.deferredQueue.popleft() d = self.fetchRange(size) d.chainDeferred(df) - + + # decrement network expected delay, each 5 min to help finetune access + def _decrementAdjustTimeStart(self): + if self.decrementAdjust is not None: + try: + self.decrementAdjust.cancel() + except (error.AlreadyCancelled, error.AlreadyCalled): + pass + except: + pass + self.decrementAdjust = None + self.decrementAdjust = reactor.callLater(500, self._decrementAdjustTime) + + def _decrementAdjustTime(self): + if self.decrementAdjust is not None: + self.networkAdjustTime -= 1 + if self.networkAdjustTime < self.minNetworkDelay: + self.networkAdjustTime = self.minNetworkDelay + self.decrementAdjust = None + else: + self.decrementAdjust = reactor.callLater(500, self._decrementAdjustTime) + + #acknowledge a new block + def storePush(self, ignored=None): + self.hadAbandon = True + if ignored is None: + return + if ignored: + self.alreadyRequested += 1 + if self.logger.verbose: + self.logger.logToText('WorkQueue: storePush, alreadyRequested = %d' % self.alreadyRequested) + #gets the next WorkUnit from queue def getNext(self): - + msg = 'Next Work' + now = time() + if self.lastWork is not None: + dt = now - self.lastWork + if not self.hadAbandon: + if self.logger.verbose: + msg = msg + ' (no Abandon)' + self.sampleWorkLen.append(dt) + self.sampleWorkLen = self.sampleWorkLen[ -self.SAMPLELEN:] + if len(self.sampleWorkLen) >= self.SAMPLELEN: + if self.use2phase: + self.mode = 1 # now we shall adjust len + self.myTick = max(0,int((sum(self.sampleWorkLen) / len(self.sampleWorkLen)) - self.networkAdjustTime)) + self.hadAbandon = False + if self.logger.verbose: + msg = msg + ', last %s(%d) away' % (self.logger.formatTime(dt), self.networkAdjustTime) + self.lastWork = now + if not self.myPush: + self.logger.reportNewWork() + self.logger.updateStatus(True, True) + self.logger.logToText(msg) #check if the queue will fall below desired size - if (len(self.queue) - 1) < (self.queueSize): - self.miner.connection.requestWork() + if self.logger.verbose: + self.logger.logToText('WorkQueue: getNext, queueSize %d(%d)' % (len(self.queue), self.queueSize)) + if (len(self.queue)) < (self.queueSize): + self.requestWork('getNext force,') + else: + if (len(self.queue) - 1) < (self.queueSize): + self._getWork('getNext') + self.myPush = False #return next WorkUnit + self.logger.canLog('Next Work') return self.queue.popleft() - - def getRangeFromUnit(self, size): + + def _getWork(self, where=None): + if self.mode == 0 or self.myTick == 0: + self.requestWork((where + ',') if where is not None else '') + else: # we reschedule the request for work + if self.logger.verbose: + self.logger.logToText('WorkQueue: %sdefering requestWork %s sec...' % ((where + ', ') if where is not None else '', self.logger.formatTime(self.myTick))) + self._startCall(self.myTick, self.requestWork) + + def requestWork(self, ignore=None): + self.lastNetworkTime = time() + msg = 'WorkQueue: %s' % ('defered' if ignore is None else ignore) + msg = msg + ' requestWork from server, mode=%d(%d,%d)...' % (self.mode, len(self.queue), self.queueSize) + if self.logger.verbose: + self.logger.logToText(msg) + self.alreadyRequested += 1 + if self.logger.verbose: + self.logger.logToText('WorkQueue: requestWork, alreadyRequested = %d' % self.alreadyRequested) + self.miner.connection.requestWork() + self._stopCall() # Kill defered call, if nessecery + def getRangeFromUnit(self, size): #get remaining nonces noncesLeft = self.currentUnit.nonces - self.currentUnit.base @@ -163,7 +345,6 @@ return nr def fetchRange(self, size=0x10000): - #make sure size is not too large size = min(size, 0x100000000) @@ -199,8 +380,9 @@ #if the queue is empty else: - #request more work - self.miner.connection.requestWork() + #request more work if not done so already + if self.alreadyRequested == 0: + self.requestWork('fetchRange force,') #report that the miner is idle self.miner.reportIdle(True)