Fix: allow to cancel download by user or server initiated reset (#266)

This commit is contained in:
Luis Uguina
2020-06-21 02:36:55 +10:00
committed by GitHub
parent 27d8b05b12
commit 57cae65412
2 changed files with 58 additions and 35 deletions

View File

@@ -639,26 +639,26 @@ import lombok.Data;
} }
public Error.Type work(final Job ajob) { public Error.Type work(final Job ajob) {
int ret; Error.Type downloadRet;
gui.setRenderingProjectName(ajob.getName()); gui.setRenderingProjectName(ajob.getName());
try { try {
ret = this.downloadExecutable(ajob); downloadRet = this.downloadExecutable(ajob);
if (ret != 0) { if (downloadRet != Error.Type.OK) {
gui.setRenderingProjectName(""); gui.setRenderingProjectName("");
this.log.error("Client::work problem with downloadExecutable (ret " + ret + ")"); this.log.error("Client::work problem with downloadExecutable (ret " + downloadRet + ")");
return Error.Type.DOWNLOAD_FILE; return downloadRet;
} }
ret = this.downloadSceneFile(ajob); downloadRet = this.downloadSceneFile(ajob);
if (ret != 0) { if (downloadRet != Error.Type.OK) {
gui.setRenderingProjectName(""); gui.setRenderingProjectName("");
this.log.error("Client::work problem with downloadSceneFile (ret " + ret + ")"); this.log.error("Client::work problem with downloadSceneFile (ret " + downloadRet + ")");
return Error.Type.DOWNLOAD_FILE; return downloadRet;
} }
ret = this.prepareWorkingDirectory(ajob); // decompress renderer and scene archives int ret = this.prepareWorkingDirectory(ajob); // decompress renderer and scene archives
if (ret != 0) { if (ret != 0) {
gui.setRenderingProjectName(""); gui.setRenderingProjectName("");
this.log.error("Client::work problem with this.prepareWorkingDirectory (ret " + ret + ")"); this.log.error("Client::work problem with this.prepareWorkingDirectory (ret " + ret + ")");
@@ -716,36 +716,40 @@ import lombok.Data;
return Error.Type.OK; return Error.Type.OK;
} }
protected int downloadSceneFile(Job ajob_) throws FermeExceptionNoSpaceLeftOnDevice { protected Error.Type downloadSceneFile(Job ajob_) throws FermeExceptionNoSpaceLeftOnDevice {
return this.downloadFile(ajob_, ajob_.getSceneArchivePath(), ajob_.getSceneMD5(), return this.downloadFile(ajob_, ajob_.getSceneArchivePath(), ajob_.getSceneMD5(),
String.format("%s?type=job&job=%s", this.server.getPage("download-archive"), ajob_.getId()), "project"); String.format("%s?type=job&job=%s", this.server.getPage("download-archive"), ajob_.getId()), "project");
} }
protected int downloadExecutable(Job ajob) throws FermeExceptionNoSpaceLeftOnDevice { protected Error.Type downloadExecutable(Job ajob) throws FermeExceptionNoSpaceLeftOnDevice {
return this.downloadFile(ajob, ajob.getRendererArchivePath(), ajob.getRendererMD5(), return this.downloadFile(ajob, ajob.getRendererArchivePath(), ajob.getRendererMD5(),
String.format("%s?type=binary&job=%s", this.server.getPage("download-archive"), ajob.getId()), "renderer"); String.format("%s?type=binary&job=%s", this.server.getPage("download-archive"), ajob.getId()), "renderer");
} }
private int downloadFile(Job ajob, String local_path, String md5_server, String url, String download_type) throws FermeExceptionNoSpaceLeftOnDevice { private Error.Type downloadFile(Job ajob, String local_path, String md5_server, String url, String download_type) throws FermeExceptionNoSpaceLeftOnDevice {
File local_path_file = new File(local_path); File local_path_file = new File(local_path);
String update_ui = "Downloading " + download_type; String update_ui = "Downloading " + download_type;
if (local_path_file.exists() == true) { if (local_path_file.exists() == true) {
this.gui.status("Reusing cached " + download_type); this.gui.status("Reusing cached " + download_type);
return 0; return Type.OK;
} }
this.gui.status(String.format("Downloading %s", download_type), 0, 0); this.gui.status(String.format("Downloading %s", download_type), 0, 0);
// must download the archive // must download the archive
int ret = this.server.HTTPGetFile(url, local_path, this.gui, update_ui); Error.Type ret = this.server.HTTPGetFile(url, local_path, this.gui, update_ui);
if (ret != Type.RENDERER_KILLED_BY_SERVER || ret != Type.RENDERER_KILLED_BY_USER_OVER_TIME) {
return ret;
}
// Try to check the download file even if a download error has occurred (MD5 file check will delete the file if partially downloaded) // Try to check the download file even if a download error has occurred (MD5 file check will delete the file if partially downloaded)
boolean md5_check = this.checkFile(ajob, local_path, md5_server); boolean md5_check = this.checkFile(ajob, local_path, md5_server);
int attempts = 1; int attempts = 1;
while ((ret != 0 || md5_check == false) && attempts < this.maxDownloadFileAttempts) { while ((ret != Error.Type.OK || md5_check == false) && attempts < this.maxDownloadFileAttempts) {
if (ret != 0) { if (ret != Error.Type.OK) {
this.gui.error(String.format("Unable to download %s (error %d). Retrying now", download_type, ret)); this.gui.error(String.format("Unable to download %s (error %d). Retrying now", download_type, ret));
this.log.debug("Client::downloadFile problem with Server.HTTPGetFile (return: " + ret + ") removing local file (path: " + local_path + ")"); this.log.debug("Client::downloadFile problem with Server.HTTPGetFile (return: " + ret + ") removing local file (path: " + local_path + ")");
} }
@@ -758,18 +762,19 @@ import lombok.Data;
this.log.debug("Client::downloadFile failed, let's try again (" + (attempts + 1) + "/" + this.maxDownloadFileAttempts + ") ..."); this.log.debug("Client::downloadFile failed, let's try again (" + (attempts + 1) + "/" + this.maxDownloadFileAttempts + ") ...");
ret = this.server.HTTPGetFile(url, local_path, this.gui, update_ui); ret = this.server.HTTPGetFile(url, local_path, this.gui, update_ui);
md5_check = this.checkFile(ajob, local_path, md5_server); md5_check = this.checkFile(ajob, local_path, md5_server);
attempts++; attempts++;
if ((ret != 0 || md5_check == false) && attempts >= this.maxDownloadFileAttempts) { if ((ret != Error.Type.OK || md5_check == false) && attempts >= this.maxDownloadFileAttempts) {
this.log.debug("Client::downloadFile failed after " + this.maxDownloadFileAttempts + " attempts, removing local file (path: " + local_path this.log.debug("Client::downloadFile failed after " + this.maxDownloadFileAttempts + " attempts, removing local file (path: " + local_path
+ "), stopping..."); + "), stopping...");
local_path_file.delete(); local_path_file.delete();
return -9; return Type.DOWNLOAD_FILE;
} }
} }
return 0; return Type.OK;
} }
private boolean checkFile(Job ajob, String local_path, String md5_server) { private boolean checkFile(Job ajob, String local_path, String md5_server) {

View File

@@ -137,11 +137,13 @@ public class Server extends Thread {
if (serverCode == ServerCode.KEEPMEALIVE_STOP_RENDERING) { if (serverCode == ServerCode.KEEPMEALIVE_STOP_RENDERING) {
this.log.debug("Server::stayAlive server asked to kill local render process"); this.log.debug("Server::stayAlive server asked to kill local render process");
// kill the current process, it will generate an error but it's okay // kill the current process, it will generate an error but it's okay
if (this.client != null && this.client.getRenderingJob() != null if (this.client != null && this.client.getRenderingJob() != null) {
&& this.client.getRenderingJob().getProcessRender().getProcess() != null) {
this.client.getRenderingJob().setServerBlockJob(true); this.client.getRenderingJob().setServerBlockJob(true);
this.client.getRenderingJob().setAskForRendererKill(true);
OS.getOS().kill(this.client.getRenderingJob().getProcessRender().getProcess()); if (this.client.getRenderingJob().getProcessRender().getProcess() != null) {
this.client.getRenderingJob().setAskForRendererKill(true);
OS.getOS().kill(this.client.getRenderingJob().getProcessRender().getProcess());
}
} }
} }
} }
@@ -414,19 +416,21 @@ public class Server extends Thread {
} }
} }
public int HTTPGetFile(String url_, String destination_, Gui gui_, String status_) throws FermeExceptionNoSpaceLeftOnDevice { public Error.Type HTTPGetFile(String url_, String destination_, Gui gui_, String status_) throws FermeExceptionNoSpaceLeftOnDevice {
// the destination_ parent directory must exist InputStream is = null;
OutputStream output = null;
try { try {
Response response = this.HTTPRequest(url_); Response response = this.HTTPRequest(url_);
if (response.code() != HttpURLConnection.HTTP_OK) { if (response.code() != HttpURLConnection.HTTP_OK) {
this.log.error("Server::HTTPGetFile(" + url_ + ", ...) HTTP code is not " + HttpURLConnection.HTTP_OK + " it's " + response.code()); this.log.error("Server::HTTPGetFile(" + url_ + ", ...) HTTP code is not " + HttpURLConnection.HTTP_OK + " it's " + response.code());
return -1; return Error.Type.DOWNLOAD_FILE;
} }
long start = new Date().getTime(); long start = new Date().getTime();
InputStream is = response.body().byteStream(); is = response.body().byteStream();
OutputStream output = new FileOutputStream(destination_); output = new FileOutputStream(destination_);
long size = response.body().contentLength(); long size = response.body().contentLength();
byte[] buffer = new byte[8 * 1024]; byte[] buffer = new byte[8 * 1024];
@@ -435,6 +439,13 @@ public class Server extends Thread {
long lastUpd = 0; // last GUI progress update long lastUpd = 0; // last GUI progress update
while ((len = is.read(buffer)) != -1) { while ((len = is.read(buffer)) != -1) {
if (this.client.getRenderingJob().isServerBlockJob()) {
return Error.Type.RENDERER_KILLED_BY_SERVER;
}
else if (this.client.getRenderingJob().isUserBlockJob()) {
return Error.Type.RENDERER_KILLED_BY_USER;
}
output.write(buffer, 0, len); output.write(buffer, 0, len);
written += len; written += len;
@@ -444,17 +455,13 @@ public class Server extends Thread {
} }
} }
output.flush();
output.close();
is.close();
gui_.status(status_, 100, size); gui_.status(status_, 100, size);
long end = new Date().getTime(); long end = new Date().getTime();
this.log.debug(String.format("File downloaded at %.1f kB/s, written %d B", ((float) (size / 1000)) / ((float) (end - start) / 1000), written)); this.log.debug(String.format("File downloaded at %.1f kB/s, written %d B", ((float) (size / 1000)) / ((float) (end - start) / 1000), written));
this.lastRequestTime = new Date().getTime(); this.lastRequestTime = new Date().getTime();
return 0; return Error.Type.OK;
} }
catch (Exception e) { catch (Exception e) {
if (Utils.noFreeSpaceOnDisk(new File(destination_).getParent())) { if (Utils.noFreeSpaceOnDisk(new File(destination_).getParent())) {
@@ -465,8 +472,19 @@ public class Server extends Thread {
e.printStackTrace(new PrintWriter(sw)); e.printStackTrace(new PrintWriter(sw));
this.log.error("Server::HTTPGetFile Exception " + e + " stacktrace " + sw.toString()); this.log.error("Server::HTTPGetFile Exception " + e + " stacktrace " + sw.toString());
} }
finally {
try {
output.flush();
output.close();
is.close();
}
catch (IOException e) {
this.log.debug(String.format("Server::HTTPGetFile Error trying to close the open streams (%s)", e.getMessage()));
}
}
this.log.debug(String.format("Server::HTTPGetFile(%s) did fail", url_)); this.log.debug(String.format("Server::HTTPGetFile(%s) did fail", url_));
return -2; return Error.Type.DOWNLOAD_FILE;
} }
public ServerCode HTTPSendFile(String surl, String file1, int checkpoint) { public ServerCode HTTPSendFile(String surl, String file1, int checkpoint) {