def startBitcoind(self, callback): self.btcOut, self.btcErr = None,None if self.disabled: LOGERROR('SDM was disabled, must be re-enabled before starting') return LOGINFO('Called startBitcoind') if self.isRunningBitcoind() or TheTDM.getTDMState()=='Downloading': raise self.BitcoindError, 'Looks like we have already started theSDM' if not os.path.exists(self.executable): raise self.BitcoindError, 'Could not find bitcoind' chk1 = os.path.exists(self.useTorrentFile) chk2 = self.shouldTryBootstrapTorrent() chk3 = TheTDM.getTDMState()=='ReadyToStart' if chk1 and chk2 and chk3: TheTDM.startDownload() else: self.launchBitcoindAndGuardian() #New backend code: we wont be polling the SDM state in the main thread #anymore, instead create a thread at bitcoind start to poll the SDM state #and notify the main thread once bitcoind is ready, then terminates self.pollBitcoindState(callback, async=True)
def startBitcoind(self, callback): self.btcOut, self.btcErr = None, None if self.disabled: LOGERROR('SDM was disabled, must be re-enabled before starting') return LOGINFO('Called startGroestlcoind') if self.isRunningBitcoind() or TheTDM.getTDMState() == 'Downloading': raise self.BitcoindError, 'Looks like we have already started theSDM' if not os.path.exists(self.executable): raise self.BitcoindError, 'Could not find groestlcoind' chk1 = os.path.exists(self.useTorrentFile) chk2 = self.shouldTryBootstrapTorrent() chk3 = TheTDM.getTDMState() == 'ReadyToStart' if chk1 and chk2 and chk3: TheTDM.startDownload() else: self.launchBitcoindAndGuardian() #New backend code: we wont be polling the SDM state in the main thread #anymore, instead create a thread at groestlcoind start to poll the SDM state #and notify the main thread once groestlcoind is ready, then terminates self.pollBitcoindState(callback, async=True)
def startBitcoind(self): self.btcOut, self.btcErr = None, None if self.disabled: LOGERROR('SDM was disabled, must be re-enabled before starting') return LOGINFO('Called startBitcoind') if self.isRunningBitcoind() or TheTDM.getTDMState() == 'Downloading': raise self.BitcoindError, 'Looks like we have already started theSDM' if not os.path.exists(self.executable): raise self.BitcoindError, 'Could not find bitcoind' chk1 = os.path.exists(self.useTorrentFile) chk2 = self.shouldTryBootstrapTorrent() chk3 = TheTDM.getTDMState() == 'ReadyToStart' if chk1 and chk2 and chk3: TheTDM.startDownload() else: self.launchBitcoindAndGuardian()
def startBitcoind(self): self.btcOut, self.btcErr = None,None if self.disabled: LOGERROR('SDM was disabled, must be re-enabled before starting') return LOGINFO('Called startBitcoind') if self.isRunningBitcoind() or TheTDM.getTDMState()=='Downloading': raise self.BitcoindError, 'Looks like we have already started theSDM' if not os.path.exists(self.executable): raise self.BitcoindError, 'Could not find peercoind' chk1 = os.path.exists(self.useTorrentFile) chk2 = self.shouldTryBootstrapTorrent() chk3 = TheTDM.getTDMState()=='ReadyToStart' if chk1 and chk2 and chk3: TheTDM.startDownload() else: self.launchBitcoindAndGuardian()
def shouldTryBootstrapTorrent(self): if DISABLE_TORRENTDL or TheTDM.getTDMState()=='Disabled': return False # The only torrent we have is for the primary Bitcoin network if not MAGIC_BYTES=='\xf9\xbe\xb4\xd9': return False if TheTDM.torrentSize: bootfile = os.path.join(self.satoshiHome, 'bootstrap.dat') if os.path.exists(bootfile): if os.path.getsize(bootfile) >= TheTDM.torrentSize/2: LOGWARN('Looks like a full bootstrap is already here') LOGWARN('Skipping torrent download') return False # If they don't even have a BTC_HOME_DIR, corebtc never been installed blockDir = os.path.join(self.satoshiHome, 'blocks') if not os.path.exists(self.satoshiHome) or not os.path.exists(blockDir): return True # Get the cumulative size of the blk*.dat files blockDirSize = sum([os.path.getsize(os.path.join(blockDir, a)) \ for a in os.listdir(blockDir) if a.startswith('blk')]) sizeStr = bytesToHumanSize(blockDirSize) LOGINFO('Total size of files in %s is %s' % (blockDir, sizeStr)) # If they have only a small portion of the blockchain, do it szThresh = 100*MEGABYTE if USE_TESTNET else 6*GIGABYTE if blockDirSize < szThresh: return True # So far we know they have a BTC_HOME_DIR, with more than 6GB in blocks/ # The only thing that can induce torrent now is if we have a partially- # finished bootstrap file bigger than the blocks dir. bootFiles = ['',''] bootFiles[0] = os.path.join(self.satoshiHome, 'bootstrap.dat') bootFiles[1] = os.path.join(self.satoshiHome, 'bootstrap.dat.partial') for fn in bootFiles: if os.path.exists(fn): if os.path.getsize(fn) > blockDirSize: return True # Okay, we give up -- just download [the rest] via P2P return False
def getSDMStateLogic(self): if self.disabled: return 'GroestlcoindMgmtDisabled' if self.failedFindExe: return 'GroestlcoindExeMissing' if self.failedFindHome: return 'GroestlcoindHomeMissing' if TheTDM.isRunning(): return 'TorrentSynchronizing' latestInfo = self.getTopBlockInfo() if self.groestlcoind == None and latestInfo['error'] == 'Uninitialized': return 'GroestlcoindNeverStarted' if not self.isRunningBitcoind(): # Not running at all: either never started, or process terminated if not self.btcErr == None and len(self.btcErr) > 0: errstr = self.btcErr.replace(',', ' ').replace('.', ' ').replace( '!', ' ') errPcs = set([a.lower() for a in errstr.split()]) runPcs = set( ['cannot', 'obtain', 'lock', 'already', 'running']) dbePcs = set([ 'database', 'recover', 'backup', 'except', 'wallet', 'dat' ]) if len(errPcs.intersection(runPcs)) >= (len(runPcs) - 1): return 'GroestlcoindAlreadyRunning' elif len(errPcs.intersection(dbePcs)) >= (len(dbePcs) - 1): return 'GroestlcoindDatabaseEnvError' else: return 'GroestlcoindUnknownCrash' else: return 'GroestlcoindNotAvailable' elif not self.bitcoindIsResponsive(): # Running but not responsive... must still be initializing return 'GroestlcoindInitializing' else: # If it's responsive, get the top block and check # TODO: These conditionals are based on experimental results. May # not be accurate what the specific errors mean... if latestInfo['error'] == 'ValueError': return 'GroestlcoindWrongPassword' elif latestInfo['error'] == 'JsonRpcException': return 'GroestlcoindInitializing' elif latestInfo['error'] == 'SocketError': return 'GroestlcoindNotAvailable' if 'GroestlcoindReady' in self.circBufferState: # If ready, always ready return 'GroestlcoindReady' # If we get here, groestlcoind is gave us a response. secSinceLastBlk = RightNow() - latestInfo['toptime'] blkspersec = latestInfo['blkspersec'] #print 'Blocks per 10 sec:', ('UNKNOWN' if blkspersec==-1 else blkspersec*10) if secSinceLastBlk > 4 * HOUR or blkspersec == -1: return 'GroestlcoindSynchronizing' else: if blkspersec * 20 > 2 and not 'GroestlcoindReady' in self.circBufferState: return 'GroestlcoindSynchronizing' else: return 'GroestlcoindReady'
def tryToSetupTorrentDL(self, torrentPath): if self.torrentDisabled: LOGWARN('Tried to setup torrent download mgr but we are disabled') return False if not torrentPath or not os.path.exists(torrentPath): self.useTorrentFinalAnswer = False return False bootfile = os.path.join(self.satoshiHome, 'bootstrap.dat') bootfilePart = bootfile + '.partial' bootfileOld = bootfile + '.old' # cleartorrent.flag means we should remove any pre-existing files delTorrentFlag = os.path.join(ARMORY_HOME_DIR, 'cleartorrent.flag') if os.path.exists(delTorrentFlag): LOGWARN('Flag found to delete any pre-existing torrent files') if os.path.exists(bootfile): os.remove(bootfile) if os.path.exists(bootfilePart): os.remove(bootfilePart) if os.path.exists(bootfileOld): os.remove(bootfileOld) if os.path.exists(delTorrentFlag): os.remove(delTorrentFlag) TheTDM.setupTorrent(torrentPath, bootfile) if not TheTDM.getTDMState() == 'ReadyToStart': LOGERROR('Unknown error trying to start torrent manager') self.useTorrentFinalAnswer = False return False # We will tell the TDM to write status updates to the log file, and only # every 90 seconds. After it finishes (or fails), simply launch groestlcoind # as we would've done without the torrent ##### def torrentLogToFile(dpflag=Event(), fractionDone=None, timeEst=None, downRate=None, upRate=None, activity=None, statistics=None, **kws): statStr = '' if fractionDone: statStr += ' Done: %0.1f%% ' % (fractionDone * 100) if downRate: statStr += ' / DLRate: %0.1f/sec' % (downRate / 1024.) if timeEst: statStr += ' / TLeft: %s' % secondsToHumanTime(timeEst) if statistics: statStr += ' / Seeds: %d' % (statistics.numSeeds) statStr += ' / Peers: %d' % (statistics.numPeers) if len(statStr) == 0: statStr = 'No torrent info available' LOGINFO('Torrent: %s' % statStr) ##### def torrentFinished(): bootsz = '<Unknown>' if os.path.exists(bootfile): bootsz = bytesToHumanSize(os.path.getsize(bootfile)) LOGINFO('Torrent finished; size of %s is %s', torrentPath, bootsz) LOGINFO('Remove the core btc databases before doing bootstrap') deleteBitcoindDBs() self.launchBitcoindAndGuardian() ##### def warnUserHashFail(): from PyQt4.QtGui import QMessageBox QMessageBox.warning( self, tr('Hash Failure'), tr("""The torrent download is currently encountering too many packet hash failures to allow it to progress properly. As a result, the torrent engine has been halted. You should report this incident to the Groestlcoin Armory team and turn off this feature until further notice."""), QMessageBox.Ok) ##### def torrentFailed(errMsg=''): # Not sure there's actually anything we need to do here... if errMsg == 'hashFail': warnUserHashFail() bootsz = '<Unknown>' if os.path.exists(bootfile): bootsz = bytesToHumanSize(os.path.getsize(bootfile)) LOGERROR('Torrent failed; size of %s is %s', torrentPath, bootsz) self.launchBitcoindAndGuardian() TheTDM.setSecondsBetweenUpdates(90) TheTDM.setCallback('displayFunc', torrentLogToFile) TheTDM.setCallback('finishedFunc', torrentFinished) TheTDM.setCallback('failedFunc', torrentFailed) LOGINFO('Bootstrap file is %s' % bytesToHumanSize(TheTDM.torrentSize)) self.useTorrentFinalAnswer = True self.useTorrentFile = torrentPath return True
def getSDMStateLogic(self): if self.disabled: return 'BitcoindMgmtDisabled' if self.failedFindExe: return 'BitcoindExeMissing' if self.failedFindHome: return 'BitcoindHomeMissing' if TheTDM.isRunning(): return 'TorrentSynchronizing' latestInfo = self.getTopBlockInfo() if self.bitcoind==None and latestInfo['error']=='Uninitialized': return 'BitcoindNeverStarted' if not self.isRunningBitcoind(): # Not running at all: either never started, or process terminated if not self.btcErr==None and len(self.btcErr)>0: errstr = self.btcErr.replace(',',' ').replace('.',' ').replace('!',' ') errPcs = set([a.lower() for a in errstr.split()]) runPcs = set(['cannot','obtain','lock','already','running']) dbePcs = set(['database', 'recover','backup','except','wallet','dat']) if len(errPcs.intersection(runPcs))>=(len(runPcs)-1): return 'BitcoindAlreadyRunning' elif len(errPcs.intersection(dbePcs))>=(len(dbePcs)-1): return 'BitcoindDatabaseEnvError' else: return 'BitcoindUnknownCrash' else: return 'BitcoindNotAvailable' elif not self.bitcoindIsResponsive(): # Running but not responsive... must still be initializing return 'BitcoindInitializing' else: # If it's responsive, get the top block and check # TODO: These conditionals are based on experimental results. May # not be accurate what the specific errors mean... if latestInfo['error']=='ValueError': return 'BitcoindWrongPassword' elif latestInfo['error']=='JsonRpcException': return 'BitcoindInitializing' elif latestInfo['error']=='SocketError': return 'BitcoindNotAvailable' if 'BitcoindReady' in self.circBufferState: # If ready, always ready return 'BitcoindReady' # If we get here, bitcoind is gave us a response. secSinceLastBlk = RightNow() - latestInfo['toptime'] blkspersec = latestInfo['blkspersec'] #print 'Blocks per 10 sec:', ('UNKNOWN' if blkspersec==-1 else blkspersec*10) if secSinceLastBlk > 4*HOUR or blkspersec==-1: return 'BitcoindSynchronizing' else: if blkspersec*20 > 2 and not 'BitcoindReady' in self.circBufferState: return 'BitcoindSynchronizing' else: return 'BitcoindReady'
def tryToSetupTorrentDL(self, torrentPath): if self.torrentDisabled: LOGWARN('Tried to setup torrent download mgr but we are disabled') return False if not torrentPath or not os.path.exists(torrentPath): self.useTorrentFinalAnswer = False return False bootfile = os.path.join(self.satoshiHome, 'bootstrap.dat') bootfilePart = bootfile + '.partial' bootfileOld = bootfile + '.old' # cleartorrent.flag means we should remove any pre-existing files delTorrentFlag = os.path.join(ARMORY_HOME_DIR, 'cleartorrent.flag') if os.path.exists(delTorrentFlag): LOGWARN('Flag found to delete any pre-existing torrent files') if os.path.exists(bootfile): os.remove(bootfile) if os.path.exists(bootfilePart): os.remove(bootfilePart) if os.path.exists(bootfileOld): os.remove(bootfileOld) if os.path.exists(delTorrentFlag): os.remove(delTorrentFlag) TheTDM.setupTorrent(torrentPath, bootfile) if not TheTDM.getTDMState()=='ReadyToStart': LOGERROR('Unknown error trying to start torrent manager') self.useTorrentFinalAnswer = False return False # We will tell the TDM to write status updates to the log file, and only # every 90 seconds. After it finishes (or fails), simply launch bitcoind # as we would've done without the torrent ##### def torrentLogToFile(dpflag=Event(), fractionDone=None, timeEst=None, downRate=None, upRate=None, activity=None, statistics=None, **kws): statStr = '' if fractionDone: statStr += ' Done: %0.1f%% ' % (fractionDone*100) if downRate: statStr += ' / DLRate: %0.1f/sec' % (downRate/1024.) if timeEst: statStr += ' / TLeft: %s' % secondsToHumanTime(timeEst) if statistics: statStr += ' / Seeds: %d' % (statistics.numSeeds) statStr += ' / Peers: %d' % (statistics.numPeers) if len(statStr)==0: statStr = 'No torrent info available' LOGINFO('Torrent: %s' % statStr) ##### def torrentFinished(): bootsz = '<Unknown>' if os.path.exists(bootfile): bootsz = bytesToHumanSize(os.path.getsize(bootfile)) LOGINFO('Torrent finished; size of %s is %s', torrentPath, bootsz) LOGINFO('Remove the core btc databases before doing bootstrap') deleteBitcoindDBs() self.launchBitcoindAndGuardian() ##### def warnUserHashFail(): from PyQt4.QtGui import QMessageBox QMessageBox.warning(self, tr('Hash Failure'), tr("""The torrent download is currently encountering too many packet hash failures to allow it to progress properly. As a result, the torrent engine has been halted. You should report this incident to the Armory team and turn off this feature until further notice."""), QMessageBox.Ok) ##### def torrentFailed(errMsg=''): # Not sure there's actually anything we need to do here... if errMsg == 'hashFail': warnUserHashFail() bootsz = '<Unknown>' if os.path.exists(bootfile): bootsz = bytesToHumanSize(os.path.getsize(bootfile)) LOGERROR('Torrent failed; size of %s is %s', torrentPath, bootsz) self.launchBitcoindAndGuardian() TheTDM.setSecondsBetweenUpdates(90) TheTDM.setCallback('displayFunc', torrentLogToFile) TheTDM.setCallback('finishedFunc', torrentFinished) TheTDM.setCallback('failedFunc', torrentFailed) LOGINFO('Bootstrap file is %s' % bytesToHumanSize(TheTDM.torrentSize)) self.useTorrentFinalAnswer = True self.useTorrentFile = torrentPath return True
def tryToSetupTorrentDL(self, torrentPath): if self.torrentDisabled: LOGWARN('Tried to setup torrent download mgr but we are disabled') return False if not torrentPath or not os.path.exists(torrentPath): self.useTorrentFinalAnswer = False return False bootfile = os.path.join(self.satoshiHome, 'bootstrap.dat') TheTDM.setupTorrent(torrentPath, bootfile) if not TheTDM.getTDMState()=='ReadyToStart': LOGERROR('Unknown error trying to start torrent manager') self.useTorrentFinalAnswer = False return False # We will tell the TDM to write status updates to the log file, and only # every 90 seconds. After it finishes (or fails), simply launch bitcoind # as we would've done without the torrent ##### def torrentLogToFile(dpflag=Event(), fractionDone=None, timeEst=None, downRate=None, upRate=None, activity=None, statistics=None, **kws): statStr = '' if fractionDone: statStr += ' Done: %0.1f%% ' % (fractionDone*100) if downRate: statStr += ' / DLRate: %0.1f/sec' % (downRate/1024.) if timeEst: statStr += ' / TLeft: %s' % secondsToHumanTime(timeEst) if statistics: statStr += ' / Seeds: %d' % (statistics.numSeeds) statStr += ' / Peers: %d' % (statistics.numPeers) if len(statStr)==0: statStr = 'No torrent info available' LOGINFO('Torrent: %s' % statStr) ##### def torrentFinished(): bootsz = '<Unknown>' if os.path.exists(bootfile): bootsz = bytesToHumanSize(os.path.getsize(bootfile)) LOGINFO('Torrent finished; size of %s is %s', torrentPath, bootsz) LOGINFO('Remove the core btc databases before doing bootstrap') deleteBitcoindDBs() self.launchBitcoindAndGuardian() ##### def torrentFailed(): # Not sure there's actually anything we need to do here... bootsz = '<Unknown>' if os.path.exists(bootfile): bootsz = bytesToHumanSize(os.path.getsize(bootfile)) LOGERROR('Torrent failed; size of %s is %s', torrentPath, bootsz) self.launchBitcoindAndGuardian() TheTDM.setSecondsBetweenUpdates(90) TheTDM.setCallback('displayFunc', torrentLogToFile) TheTDM.setCallback('finishedFunc', torrentFinished) TheTDM.setCallback('failedFunc', torrentFailed) LOGINFO('Bootstrap file is %s' % bytesToHumanSize(TheTDM.torrentSize)) self.useTorrentFinalAnswer = True self.useTorrentFile = torrentPath return True