2021-11-20 14:40:07 +00:00
|
|
|
from multiprocessing import Process
|
2021-11-25 18:03:58 +00:00
|
|
|
from typing import NoReturn, Optional
|
2021-11-20 14:40:07 +00:00
|
|
|
|
2021-11-25 15:31:49 +00:00
|
|
|
from classes.vessel import Vessel
|
2021-11-25 18:03:58 +00:00
|
|
|
from classes.remotefile import RemoteFile
|
|
|
|
from classes.retry import retry
|
|
|
|
from classes.database import Database
|
|
|
|
from const import STATUS_COMPLETE, STATUS_START
|
2021-11-25 15:31:49 +00:00
|
|
|
|
2021-11-22 10:14:38 +00:00
|
|
|
import time
|
|
|
|
|
2021-11-25 16:09:40 +00:00
|
|
|
|
2021-11-20 14:40:07 +00:00
|
|
|
class VesselThread(Process):
|
2021-11-25 15:31:49 +00:00
|
|
|
"""Thread processing uploads to a single vessel
|
|
|
|
"""
|
2021-11-25 16:09:40 +00:00
|
|
|
|
2021-11-25 16:02:09 +00:00
|
|
|
def __init__(self, vessel: Vessel, state: dict) -> None:
|
2021-11-25 15:31:49 +00:00
|
|
|
"""Initialize a new VesselThread
|
|
|
|
|
|
|
|
Args:
|
|
|
|
vessel (classes.vessel.Vessel): Vessel object to handle uploads for
|
|
|
|
state (dict): Dictionary containing the current application state
|
|
|
|
"""
|
2021-11-20 14:40:07 +00:00
|
|
|
super().__init__()
|
|
|
|
self.vessel = vessel
|
2021-11-25 15:31:49 +00:00
|
|
|
self._state = state
|
2021-11-20 14:40:07 +00:00
|
|
|
|
2021-11-25 16:02:09 +00:00
|
|
|
def run(self) -> NoReturn:
|
2021-11-25 15:31:49 +00:00
|
|
|
"""Run thread and process uploads to the vessel
|
|
|
|
"""
|
2021-11-22 10:14:38 +00:00
|
|
|
print("Launched Vessel Thread for " + self.vessel.name)
|
|
|
|
while True:
|
|
|
|
try:
|
2021-11-25 16:21:04 +00:00
|
|
|
self.upload()
|
2021-11-25 16:09:40 +00:00
|
|
|
except Exception as e:
|
|
|
|
print("An exception occurred in the Vessel Thread for " +
|
|
|
|
self.vessel.name)
|
|
|
|
print(repr(e))
|
|
|
|
|
2021-11-25 18:03:58 +00:00
|
|
|
@retry()
|
2021-11-25 16:21:04 +00:00
|
|
|
def upload(self) -> None:
|
|
|
|
"""Continue uploading process
|
|
|
|
"""
|
2021-11-25 18:03:58 +00:00
|
|
|
if not (current := self.vessel.currentUpload() or self.processQueue()):
|
2021-11-25 16:21:04 +00:00
|
|
|
return
|
|
|
|
|
2021-11-25 18:03:58 +00:00
|
|
|
remotefile = RemoteFile(current, self.vessel,
|
|
|
|
self._state["config"].chunksize)
|
|
|
|
|
|
|
|
while True:
|
|
|
|
status = remotefile.getStatus()
|
|
|
|
|
|
|
|
if status == STATUS_COMPLETE:
|
|
|
|
remotefile.finalizeUpload()
|
|
|
|
db = Database()
|
|
|
|
db.logCompletion(current, self.vessel)
|
|
|
|
return
|
|
|
|
|
|
|
|
nextchunk = 0 if status == STATUS_START else status + 1
|
|
|
|
|
|
|
|
chunk = remotefile.getChunk(nextchunk)
|
|
|
|
|
|
|
|
# If the Chunk has no data, the selected range is beyond the end
|
|
|
|
# of the file, i.e. the complete file has already been uploaded
|
|
|
|
|
|
|
|
if chunk.data:
|
|
|
|
self.vessel.pushChunk(chunk)
|
|
|
|
else:
|
|
|
|
self.vessel.compileComplete(remotefile)
|
|
|
|
|
|
|
|
def processQueue(self) -> Optional[str]:
|
|
|
|
"""Return a file from the processing queue
|
2021-11-25 16:21:04 +00:00
|
|
|
"""
|
2021-11-25 16:09:40 +00:00
|
|
|
for f in self._state["files"]:
|
|
|
|
if not f.uuid in self.vessel._uploaded:
|
2021-11-25 18:03:58 +00:00
|
|
|
return f
|