def final_status(self, upload, temp, final=False): end_time = time.time() start_time = self.st total_uploaded_b = 0 total_downloaded_b = 0 total_copied_b = 0 total_uploaded_t = 0 total_downloaded_t = 0 total_copied_t = 0 for item in self.up_complete: total_uploaded_t += item["timespan"] total_uploaded_b += item["size_uploaded"] for item in self.down_complete: total_downloaded_t += item["timespan"] total_downloaded_b += item["size_downloaded"] for item in self.copy_complete: total_copied_t += item["timespan"] total_copied_b += item["size_copied"] downspeed = utils.get_speed(total_downloaded_b, total_downloaded_t) copyspeed = utils.get_speed(total_copied_b, total_copied_t) upspeed = utils.get_speed(total_uploaded_b, total_uploaded_t) runspeed = utils.get_speed(total_downloaded_b, (end_time - start_time)) uprunspeed = utils.get_speed(total_uploaded_b, (end_time - start_time)) copyrunspeed = utils.get_speed(total_copied_b, (end_time - start_time)) if final or total_downloaded_t > 0: log.info("Total download time: %s", utils.convert_time(total_downloaded_t)) if upload and (final or total_uploaded_t): log.info("Total upload time: %s", utils.convert_time(total_uploaded_t)) elif temp and (final or total_copied_t): log.info("Total copy time: %s", utils.convert_time(total_copied_t)) log.info("Total run time: %s", utils.convert_time(end_time - start_time)) if final or total_downloaded_b: log.info("Download speed: %s at %s", utils.convert_size(total_downloaded_b), downspeed) if upload and (final or total_uploaded_b): log.info("Upload speed: %s at %s", utils.convert_size(total_uploaded_b), upspeed) elif temp and (final or total_copied_b): log.info("Copy speed: %s at %s", utils.convert_size(total_copied_b), copyspeed) if final or total_downloaded_b: log.info("Overall download speed: %s at %s", utils.convert_size(total_downloaded_b), runspeed) if upload and (final or total_uploaded_b): log.info("Overall upload speed: %s at %s", utils.convert_size(total_uploaded_b), uprunspeed) elif temp and (final or total_copied_b): log.info("Overall copy speed: %s at %s", utils.convert_size(total_copied_b), copyrunspeed)
def download(status, should_exit, session, results, command_args): log.debug("Starting up") while not should_exit.is_set(): item = None try: item = status.down() except EmptyException: if status.queuers_active > 0 or status.queues > 0: continue else: log.debug("Nothing more to download. Shutting down") return if item is None: continue random.seed(item["filepath"]) filename = item["filename"] size_bytes = item["filesize"] size_str = utils.convert_size(size_bytes) temp_dir = item["filedir"] temp_file = item["fullpath"] log.info("%s size %s", filename, size_str) timespan = 0 if command_args.temp: temp_dir = command_args.temp temp_file = os.path.join(temp_dir, filename) apidownloaduri = "%smyfile.ext?access_token=%s&path=%s" % (BASE_URL, command_args.token, item["filepath"]) if (not command_args.upload and not os.path.exists(item["filedir"])) or (command_args.temp and not os.path.exists(temp_dir)): cleanUpAfterError("Missing temp or destination parent directory", item, results) continue if command_args.temp: filehash = sha1("blob " + str(size_bytes) + "\0" + item["filepath"]) tmpname = filehash.hexdigest() temp_file = os.path.join(command_args.temp, tmpname) item["temppath"] = temp_file log.debug("Downloading file to %s", temp_file) retriesleft = 10 apiratecount = 1 down_failed = True while retriesleft > 0 and not should_exit.is_set(): sleeptime = random.randint(10, 70) if apiratecount > 5: apiratecount = 5 try: mode = "wb" filecomplete = False seek = 0 sizecopied = 0 try: seek = os.path.getsize(temp_file) if seek > size_bytes: seek = 0 elif seek == size_bytes: log.info("Found temp. Nothing to download") filecomplete = True elif seek > 0: sizecopied += seek log.info("continuing download") mode = "ab" except: pass if not filecomplete: req = session.get(apidownloaduri, stream=True, timeout=120, headers={'Range':"bytes=%s-" % seek}) req.raise_for_status() with open(temp_file, mode) as tmpfile: st = time.time() cr = st progress_time = st + 60 timespan = 0 chunk_size = 1024 * 1024 for chunk in req.iter_content(chunk_size=chunk_size): cr = time.time() if should_exit.is_set() or not chunk: break tmpfile.write(chunk) sizecopied += len(chunk) if command_args.progress and progress_time < cr: progress_time = cr + 60 speed = utils.get_speed(sizecopied-seek, (cr-st)) sizecopied_str = utils.convert_size(sizecopied) time_left = utils.get_remaining_time(sizecopied-seek, size_bytes-sizecopied, (cr-st)) log.info(filename) log.info("Downloaded %s of %s at %s. %s left", sizecopied_str, size_str, speed, time_left) if should_exit.is_set(): log.info("Stopping download") elif sizecopied != size_bytes: raise SizeMismatchError("Download size mismatch downloaded %s expected %s" % (sizecopied, size_bytes)) else: timespan = (cr-st) except (requests.exceptions.Timeout, requests.exceptions.ConnectionError, requests.exceptions.HTTPError, requests.exceptions.RequestException): retriesleft -= 1 if req.status_code == 429: apiratecount += 1 retriesleft += 1 log.warn("API rate limit reached. Will retry") else: log.exception("Network error %s. Will retry %s more times", req.status_code, retriesleft) if retriesleft > 0: time.sleep(10 * apiratecount) else: log.error("Error downloading %s", filename) cleanUpAfterError("Maximum retries reached", item, results) except SizeMismatchError: retriesleft -= 1 log.exception("%s File size mismatch. Will retry %s more times", filename, retriesleft) if retriesleft > 0: time.sleep(sleeptime) else: cleanUpAfterError("Error downloading %s Maximum retries reached" % filename, item, results) except IOError as e: if e.errno == errno.ENOSPC: if status.up_active > 0 or status.copy_active > 0: log.warn("Out of space. Waiting %s secs", sleeptime) time.sleep(sleeptime) else: log.critical("No space left on target or temp disk. Exiting") should_exit.set() else: retriesleft -= 1 if retriesleft > 0: log.exception("Error downloading %s. Will retry %s more times", filename, retriesleft) time.sleep(sleeptime) else: cleanUpAfterError("An unknown error occurred", item, results) except: retriesleft -= 1 if retriesleft > 0: log.exception("Error downloading %s. Will retry %s more times", filename, retriesleft) time.sleep(sleeptime) else: cleanUpAfterError("An unknown error occurred", item, results) else: if not should_exit.is_set(): down_failed = False retriesleft = 0 if timespan <= 0: timespan = 1 status.down({ "timespan": timespan, "size_downloaded": sizecopied, "temppath": temp_file }) if command_args.upload: log.info("Finished download %s in %s", filename, utils.convert_time(timespan)) log.debug("Adding to upload queue") status.queue_up(item) elif command_args.temp: log.info("Finished download %s in %s", filename, utils.convert_time(timespan)) log.debug("Adding to move queue") status.queue_copy(item) else: log.info("Finished download %s in %s", item["fullpath"], utils.convert_time(timespan)) results.writeSuccess(item["fullpath"], item["filepath"]) if command_args.progress: speed = utils.get_speed(sizecopied-seek, timespan) log.info("%s downloaded at %s", size_str, speed) else: cleanUpAfterError("Download stopped", item, results) if down_failed: status.down_fail(item) log.debug("End of thread") log.debug("Shutting down")