You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
120 lines
4.6 KiB
120 lines
4.6 KiB
3 years ago
|
import threading
|
||
|
import time
|
||
|
|
||
|
from . import utils
|
||
|
|
||
|
class ControlThread(threading.Thread):
|
||
|
"A class that shows information about a running SmartDL object."
|
||
|
def __init__(self, obj):
|
||
|
threading.Thread.__init__(self)
|
||
|
self.obj = obj
|
||
|
self.progress_bar = obj.progress_bar
|
||
|
self.logger = obj.logger
|
||
|
self.shared_var = obj.shared_var
|
||
|
|
||
|
self.dl_speed = 0
|
||
|
self.eta = 0
|
||
|
self.lastBytesSamples = [] # list with last 50 Bytes Samples.
|
||
|
self.last_calculated_totalBytes = 0
|
||
|
self.calcETA_queue = []
|
||
|
self.calcETA_i = 0
|
||
|
self.calcETA_val = 0
|
||
|
self.dl_time = -1.0
|
||
|
|
||
|
self.daemon = True
|
||
|
self.start()
|
||
|
|
||
|
def run(self):
|
||
|
t1 = time.time()
|
||
|
self.logger.info("Control thread has been started.")
|
||
|
|
||
|
while not self.obj.pool.done():
|
||
|
self.dl_speed = self.calcDownloadSpeed(self.shared_var.value)
|
||
|
if self.dl_speed > 0:
|
||
|
self.eta = self.calcETA((self.obj.filesize-self.shared_var.value)/self.dl_speed)
|
||
|
|
||
|
if self.progress_bar:
|
||
|
if self.obj.filesize:
|
||
|
status = r"[*] %s / %s @ %s/s %s [%3.1f%%, %s left] " % (utils.sizeof_human(self.shared_var.value), utils.sizeof_human(self.obj.filesize), utils.sizeof_human(self.dl_speed), utils.progress_bar(1.0*self.shared_var.value/self.obj.filesize), self.shared_var.value * 100.0 / self.obj.filesize, utils.time_human(self.eta, fmt_short=True))
|
||
|
else:
|
||
|
status = r"[*] %s / ??? MB @ %s/s " % (utils.sizeof_human(self.shared_var.value), utils.sizeof_human(self.dl_speed))
|
||
|
status = status + chr(8)*(len(status)+1)
|
||
|
print(status, end=' ', flush=True)
|
||
|
time.sleep(0.1)
|
||
|
|
||
|
if self.obj._killed:
|
||
|
self.logger.info("File download process has been stopped.")
|
||
|
return
|
||
|
|
||
|
if self.progress_bar:
|
||
|
if self.obj.filesize:
|
||
|
print(r"[*] %s / %s @ %s/s %s [100%%, 0s left] " % (utils.sizeof_human(self.obj.filesize), utils.sizeof_human(self.obj.filesize), utils.sizeof_human(self.dl_speed), utils.progress_bar(1.0)))
|
||
|
else:
|
||
|
print(r"[*] %s / %s @ %s/s " % (utils.sizeof_human(self.shared_var.value), utils.sizeof_human(self.shared_var.value), utils.sizeof_human(self.dl_speed)))
|
||
|
|
||
|
t2 = time.time()
|
||
|
self.dl_time = float(t2-t1)
|
||
|
|
||
|
while self.obj.post_threadpool_thread.is_alive():
|
||
|
time.sleep(0.1)
|
||
|
|
||
|
self.obj.pool.shutdown()
|
||
|
self.obj.status = "finished"
|
||
|
if not self.obj.errors:
|
||
|
self.logger.info("File downloaded within %.2f seconds." % self.dl_time)
|
||
|
|
||
|
def get_eta(self):
|
||
|
if self.eta <= 0 or self.obj.status == 'paused':
|
||
|
return 0
|
||
|
return self.eta
|
||
|
def get_speed(self):
|
||
|
if self.obj.status == 'paused':
|
||
|
return 0
|
||
|
return self.dl_speed
|
||
|
def get_dl_size(self):
|
||
|
if self.shared_var.value > self.obj.filesize:
|
||
|
return self.obj.filesize
|
||
|
return self.shared_var.value
|
||
|
def get_final_filesize(self):
|
||
|
return self.obj.filesize
|
||
|
def get_progress(self):
|
||
|
if not self.obj.filesize:
|
||
|
return 0
|
||
|
return 1.0*self.shared_var.value/self.obj.filesize
|
||
|
def get_dl_time(self):
|
||
|
return self.dl_time
|
||
|
|
||
|
def calcDownloadSpeed(self, totalBytes, sampleCount=30, sampleDuration=0.1):
|
||
|
'''
|
||
|
Function calculates the download rate.
|
||
|
@param totalBytes: The total amount of bytes.
|
||
|
@param sampleCount: How much samples should the function take into consideration.
|
||
|
@param sampleDuration: Duration of a sample in seconds.
|
||
|
'''
|
||
|
l = self.lastBytesSamples
|
||
|
newBytes = totalBytes - self.last_calculated_totalBytes
|
||
|
self.last_calculated_totalBytes = totalBytes
|
||
|
if newBytes >= 0: # newBytes may be negetive, will happen
|
||
|
# if a thread has crushed and the totalBytes counter got decreased.
|
||
|
if len(l) == sampleCount: # calc download for last 3 seconds (30 * 100ms per signal emit)
|
||
|
l.pop(0)
|
||
|
|
||
|
l.append(newBytes)
|
||
|
|
||
|
dlRate = sum(l)/len(l)/sampleDuration
|
||
|
return dlRate
|
||
|
|
||
|
def calcETA(self, eta):
|
||
|
self.calcETA_i += 1
|
||
|
l = self.calcETA_queue
|
||
|
l.append(eta)
|
||
|
|
||
|
if self.calcETA_i % 10 == 0:
|
||
|
self.calcETA_val = sum(l)/len(l)
|
||
|
if len(l) == 30:
|
||
|
l.pop(0)
|
||
|
|
||
|
if self.calcETA_i < 50:
|
||
|
return 0
|
||
|
return self.calcETA_val
|