From 87533a12629ab09e40a0788501af31ccfdc3f6fd Mon Sep 17 00:00:00 2001 From: Luis Uguina Date: Mon, 20 Apr 2020 01:01:43 +1000 Subject: [PATCH] feature: improve user information on queued uploads (#210) * feature: improve user information about queued uploads --- src/com/sheepit/client/Client.java | 30 +++++++++++++++---- src/com/sheepit/client/Gui.java | 2 ++ src/com/sheepit/client/Job.java | 5 +++- .../sheepit/client/standalone/GuiSwing.java | 7 +++++ .../sheepit/client/standalone/GuiText.java | 9 ++++++ .../client/standalone/GuiTextOneLine.java | 23 +++++++++++++- .../standalone/swing/activity/Working.java | 24 ++++++++++++--- 7 files changed, 89 insertions(+), 11 deletions(-) diff --git a/src/com/sheepit/client/Client.java b/src/com/sheepit/client/Client.java index 3c38228..eef1785 100644 --- a/src/com/sheepit/client/Client.java +++ b/src/com/sheepit/client/Client.java @@ -67,6 +67,9 @@ public class Client { private int maxDownloadFileAttempts = 5; + private int uploadQueueSize; + private long uploadQueueVolume; + public Client(Gui gui_, Configuration configuration, String url_) { this.configuration = configuration; this.server = new Server(url_, this.configuration, this); @@ -80,6 +83,9 @@ public class Client { this.disableErrorSending = false; this.running = false; this.suspended = false; + + this.uploadQueueSize = 0; + this.uploadQueueVolume = 0; } public String toString() { @@ -324,6 +330,10 @@ public class Client { } if (this.renderingJob.isSynchronousUpload() == true) { // power or compute_method job, need to upload right away + this.gui.status(String.format("Uploading frame (%.2fMB)", + (this.renderingJob.getOutputImageSize() / 1024.0 / 1024.0) + )); + ret = confirmJob(this.renderingJob); if (ret != Error.Type.OK) { gui.error("Client::run problem with confirmJob (returned " + ret + ")"); @@ -331,13 +341,23 @@ public class Client { } } else { + this.gui.status(String.format("Queuing frame for upload (%.2fMB)", + (this.renderingJob.getOutputImageSize() / 1024.0 / 1024.0) + )); + this.jobsToValidate.add(this.renderingJob); + + this.uploadQueueSize++; + this.uploadQueueVolume += this.renderingJob.getOutputImageSize(); + this.gui.displayUploadQueueStats(uploadQueueSize, uploadQueueVolume); + this.renderingJob = null; } while (this.shouldWaitBeforeRender() == true) { try { Thread.sleep(4000); // wait a little bit + this.gui.status("Sending frames. Please wait"); } catch (InterruptedException e3) { } @@ -436,13 +456,17 @@ public class Client { try { job_to_send = jobsToValidate.take(); this.log.debug("will validate " + job_to_send); - //gui.status("Sending frame"); + ret = confirmJob(job_to_send); if (ret != Error.Type.OK) { this.gui.error(Error.humanString(ret)); this.log.debug("Client::senderLoop confirm failed, ret: " + ret); sendError(step); } + + this.uploadQueueSize--; + this.uploadQueueVolume -= job_to_send.getOutputImageSize(); + this.gui.displayUploadQueueStats(this.uploadQueueSize, this.uploadQueueVolume); } catch (InterruptedException e) { } @@ -750,10 +774,6 @@ public class Client { int max_try = 3; ServerCode ret = ServerCode.UNKNOWN; while (nb_try < max_try && ret != ServerCode.OK) { - this.gui.status(String.format("Uploading frame (%.2fMB)", - (new File(ajob.getOutputImagePath()).length() / 1024.0 / 1024.0) - )); - ret = this.server.HTTPSendFile(url_real, ajob.getOutputImagePath()); switch (ret) { case OK: diff --git a/src/com/sheepit/client/Gui.java b/src/com/sheepit/client/Gui.java index c82ae9b..77b9243 100644 --- a/src/com/sheepit/client/Gui.java +++ b/src/com/sheepit/client/Gui.java @@ -36,6 +36,8 @@ public interface Gui { public void displayStats(Stats stats); + public void displayUploadQueueStats(int queueSize, long queueVolume); + public void error(String err_); public void AddFrameRendered(); diff --git a/src/com/sheepit/client/Job.java b/src/com/sheepit/client/Job.java index 4923640..7728443 100644 --- a/src/com/sheepit/client/Job.java +++ b/src/com/sheepit/client/Job.java @@ -64,6 +64,7 @@ public class Job { private String rendererMD5; private String id; private String outputImagePath; + private long outputImageSize; private String path; // path inside of the archive private String rendererCommand; private String validationUrl; @@ -98,6 +99,7 @@ public class Job { synchronousUpload = synchronous_upload_; gui = gui_; outputImagePath = null; + outputImageSize = 0; script = script_; updateRenderingStatusMethod = update_method_; askForRendererKill = false; @@ -412,7 +414,8 @@ public class Job { } else { setOutputImagePath(files[0].getAbsolutePath()); - log.debug("Job::render pictureFilename: '" + getOutputImagePath() + "'"); + this.outputImageSize = new File(getOutputImagePath()).length(); + log.debug(String.format("Job::render pictureFilename: %s, size: %d'",getOutputImagePath(), this.outputImageSize)); } File scene_dir = new File(getSceneDirectory()); diff --git a/src/com/sheepit/client/standalone/GuiSwing.java b/src/com/sheepit/client/standalone/GuiSwing.java index f689795..95d7db5 100644 --- a/src/com/sheepit/client/standalone/GuiSwing.java +++ b/src/com/sheepit/client/standalone/GuiSwing.java @@ -237,6 +237,13 @@ public class GuiSwing extends JFrame implements Gui { } } + @Override + public void displayUploadQueueStats(int queueSize, long queueVolume) { + if (activityWorking != null) { + this.activityWorking.displayUploadQueueStats(queueSize, queueVolume); + } + } + @Override public Client getClient() { return client; diff --git a/src/com/sheepit/client/standalone/GuiText.java b/src/com/sheepit/client/standalone/GuiText.java index 00896c7..d9f2ce6 100644 --- a/src/com/sheepit/client/standalone/GuiText.java +++ b/src/com/sheepit/client/standalone/GuiText.java @@ -117,6 +117,15 @@ public class GuiText implements Gui { System.out.println("Credits earned: " + stats.getCreditsEarnedDuringSession()); } + @Override + public void displayUploadQueueStats(int queueSize, long queueVolume) { + // No need to check if the queue is not empty to show the volume bc this line is always shown at the end + // of the render process in text GUI (unless an error occurred, where the file is uploaded synchronously) + System.out.println(String.format("Queued uploads: %d (%.2fMB)", + queueSize, + (queueVolume / 1024.0 / 1024.0))); + } + @Override public void setRenderingProjectName(String name_) { if (name_ != null && name_.isEmpty() == false) { diff --git a/src/com/sheepit/client/standalone/GuiTextOneLine.java b/src/com/sheepit/client/standalone/GuiTextOneLine.java index 4ac551f..6a9fd13 100644 --- a/src/com/sheepit/client/standalone/GuiTextOneLine.java +++ b/src/com/sheepit/client/standalone/GuiTextOneLine.java @@ -42,6 +42,9 @@ public class GuiTextOneLine implements Gui { private String status; private String line; + private int uploadQueueSize; + private long uploadQueueVolume; + private boolean exiting = false; private Client client; @@ -54,6 +57,8 @@ public class GuiTextOneLine implements Gui { status = ""; computeMethod = ""; line = ""; + uploadQueueSize = 0; + uploadQueueVolume = 0; } @Override @@ -135,6 +140,12 @@ public class GuiTextOneLine implements Gui { updateLine(); } + @Override + public void displayUploadQueueStats(int queueSize, long queueVolume) { + this.uploadQueueSize = queueSize; + this.uploadQueueVolume = queueVolume; + } + @Override public void setRemainingTime(String time_) { status = "(remaining " + time_ + ")"; @@ -171,7 +182,17 @@ public class GuiTextOneLine implements Gui { int charToRemove = line.length(); System.out.print("\r"); - line = String.format("Frames: %d Points: %s | %s %s %s", rendered, creditsEarned != null ? creditsEarned : "unknown", project, computeMethod, status + (exiting ? " (Exiting after this frame)" : "")); + + line = String.format("Frames: %d Points: %s | Queued uploads: %d%s | %s %s %s", + rendered, + creditsEarned != null ? creditsEarned : "unknown", + this.uploadQueueSize, + (this.uploadQueueSize > 0 ? String.format(" (%.2fMB)", (this.uploadQueueVolume / 1024.0 / 1024.0)) : ""), + project, + computeMethod, + status + (exiting ? " (Exiting after all frames are uploaded)" : "") + ); + System.out.print(line); for (int i = line.length(); i <= charToRemove; i++) { System.out.print(" "); diff --git a/src/com/sheepit/client/standalone/swing/activity/Working.java b/src/com/sheepit/client/standalone/swing/activity/Working.java index f4b3b40..127554b 100644 --- a/src/com/sheepit/client/standalone/swing/activity/Working.java +++ b/src/com/sheepit/client/standalone/swing/activity/Working.java @@ -71,13 +71,14 @@ public class Working implements Activity { private JLabel waiting_projects_value; private JLabel connected_machines_value; private JLabel user_info_total_rendertime_this_session_value; + private JLabel userInfoQueuedUploadsAndSizeValue; private String currentTheme; public Working(GuiSwing parent_) { parent = parent_; statusContent = new JLabel("Init"); - renderedFrameContent = new JLabel(""); + renderedFrameContent = new JLabel("0"); remainingFrameContent = new JLabel(""); creditEarned = new JLabel(""); current_project_name_value = new JLabel(""); @@ -91,6 +92,7 @@ public class Working implements Activity { user_info_total_rendertime_this_session_value = new JLabel(""); lastRenderTime = new JLabel(""); lastRender = new JLabel(""); + userInfoQueuedUploadsAndSizeValue = new JLabel("0"); currentTheme = UIManager.getLookAndFeel().getName(); // Capture the theme on component instantiation } @@ -118,6 +120,7 @@ public class Working implements Activity { user_info_total_rendertime_this_session_value = new JLabel(user_info_total_rendertime_this_session_value.getText()); lastRenderTime = new JLabel(lastRenderTime.getText()); lastRender = new JLabel(lastRender.getText()); + userInfoQueuedUploadsAndSizeValue = new JLabel(userInfoQueuedUploadsAndSizeValue.getText()); // set the new theme as the current one currentTheme = UIManager.getLookAndFeel().getName(); @@ -154,6 +157,7 @@ public class Working implements Activity { JLabel user_info_credits_this_session = new JLabel("Points earned: ", JLabel.TRAILING); JLabel user_info_total_rendertime_this_session = new JLabel("Duration: ", JLabel.TRAILING); + JLabel user_info_pending_uploads_and_size = new JLabel("Queued uploads: ", JLabel.TRAILING); JLabel user_info_rendered_frame_this_session = new JLabel("Rendered frames: ", JLabel.TRAILING); JLabel global_static_renderable_project = new JLabel("Renderable projects: ", JLabel.TRAILING); @@ -163,6 +167,9 @@ public class Working implements Activity { session_info_panel.add(user_info_rendered_frame_this_session); session_info_panel.add(renderedFrameContent); + session_info_panel.add(user_info_pending_uploads_and_size); + session_info_panel.add(userInfoQueuedUploadsAndSizeValue); + session_info_panel.add(global_static_renderable_project); session_info_panel.add(renderable_projects_value); @@ -193,7 +200,7 @@ public class Working implements Activity { // last frame JPanel last_frame_panel = new JPanel(); last_frame_panel.setLayout(new BoxLayout(last_frame_panel, BoxLayout.Y_AXIS)); - last_frame_panel.setBorder(BorderFactory.createTitledBorder("Last rendered frame")); + last_frame_panel.setBorder(BorderFactory.createTitledBorder("Last uploaded frame")); lastRender.setIcon(new ImageIcon(new BufferedImage(200, 120, BufferedImage.TYPE_INT_ARGB))); lastRender.setAlignmentX(Component.CENTER_ALIGNMENT); lastRenderTime.setAlignmentX(Component.CENTER_ALIGNMENT); @@ -245,10 +252,10 @@ public class Working implements Activity { Spring widthLeftColumn = getBestWidth(current_project_panel, 4, 2); widthLeftColumn = Spring.max(widthLeftColumn, getBestWidth(global_stats_panel, 4, 2)); - widthLeftColumn = Spring.max(widthLeftColumn, getBestWidth(session_info_panel, 3, 2)); + widthLeftColumn = Spring.max(widthLeftColumn, getBestWidth(session_info_panel, 4, 2)); alignPanel(current_project_panel, 5, 2, widthLeftColumn); alignPanel(global_stats_panel, 4, 2, widthLeftColumn); - alignPanel(session_info_panel, 4, 2, widthLeftColumn); + alignPanel(session_info_panel, 5, 2, widthLeftColumn); } public void setStatus(String msg_) { @@ -279,9 +286,18 @@ public class Working implements Activity { renderable_projects_value.setText(df.format(stats.getRenderableProject())); waiting_projects_value.setText(df.format(stats.getWaitingProject())); connected_machines_value.setText(df.format(stats.getConnectedMachine())); + updateTime(); } + public void displayUploadQueueStats(int queueSize, long queueVolume) { + userInfoQueuedUploadsAndSizeValue.setText(String.format("%d%s%s", + queueSize, + (queueSize > 0 ? String.format(" (%.2fMB) ", (queueVolume / 1024.0 / 1024.0)) : ""), + (queueSize == this.parent.getConfiguration().getMaxUploadingJob() ? "- Queue full!" : "") + )); + } + public void updateTime() { if (this.parent.getClient().getStartTime() != 0) { user_info_total_rendertime_this_session_value.setText(Utils.humanDuration(new Date((new Date().getTime() - this.parent.getClient().getStartTime()))));