diff --git a/release/scripts/io/netrender/client.py b/release/scripts/io/netrender/client.py index a203d137174..91955e6cbc8 100644 --- a/release/scripts/io/netrender/client.py +++ b/release/scripts/io/netrender/client.py @@ -215,6 +215,8 @@ class NetworkRenderEngine(bpy.types.RenderEngine): self.update_stats("", "Network render exporting") + new_job = False + job_id = netsettings.job_id # reading back result @@ -225,6 +227,7 @@ class NetworkRenderEngine(bpy.types.RenderEngine): response = conn.getresponse() if response.status == http.client.NO_CONTENT: + new_job = True netsettings.job_id = clientSendJob(conn, scene) requestResult(conn, job_id, scene.current_frame) @@ -233,6 +236,13 @@ class NetworkRenderEngine(bpy.types.RenderEngine): requestResult(conn, job_id, scene.current_frame) response = conn.getresponse() + # cancel new jobs (animate on network) on break + if self.test_break() and new_job: + conn.request("POST", cancelURL(job_id)) + response = conn.getresponse() + print( response.status, response.reason ) + netsettings.job_id = 0 + if response.status != http.client.OK: conn.close() return diff --git a/release/scripts/io/netrender/master.py b/release/scripts/io/netrender/master.py index bf439dd0b9b..83980c95da7 100644 --- a/release/scripts/io/netrender/master.py +++ b/release/scripts/io/netrender/master.py @@ -611,6 +611,9 @@ class RenderHandler(http.server.BaseHTTPRequestHandler): # =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- elif self.path == "/render": self.server.stats("", "Receiving render result") + + # need some message content here or the slave doesn't like it + self.wfile.write(bytes("foo", encoding='utf8')) slave_id = self.headers['slave-id'] diff --git a/release/scripts/io/netrender/master_html.py b/release/scripts/io/netrender/master_html.py index 7bd54672755..d4458ff4669 100644 --- a/release/scripts/io/netrender/master_html.py +++ b/release/scripts/io/netrender/master_html.py @@ -34,6 +34,8 @@ def get(handler): output("") output(title) output("") + output("") + def link(text, url): return "%s" % (url, text) @@ -67,6 +69,13 @@ def get(handler): shutil.copyfileobj(f, handler.wfile) f.close() + elif handler.path == "/html/netrender.css": + f = open(os.path.join(src_folder, "netrender.css"), 'rb') + + handler.send_head(content = "text/css") + shutil.copyfileobj(f, handler.wfile) + + f.close() elif handler.path == "/html" or handler.path == "/": handler.send_head(content = "text/html") head("NetRender") @@ -90,7 +99,7 @@ def get(handler): startTable() headerTable( " ", - " ", + "id", "name", "category", "chunks", @@ -111,16 +120,17 @@ def get(handler): for job in handler.server.jobs: results = job.framesStatus() rowTable( - """""" % job.id, + """""" % job.id + """""" % job.id, + job.id, link(job.name, "/html/job" + job.id), job.category if job.category else "None", str(job.chunks) + """""" % (job.id, job.chunks + 1) + """""" % (job.id, job.chunks - 1, "disabled=True" if job.chunks == 1 else ""), str(job.priority) + - """""" % (job.id, job.priority + 1) + - """""" % (job.id, job.priority - 1, "disabled=True" if job.priority == 1 else ""), + """""" % (job.id, job.priority + 1) + + """""" % (job.id, job.priority - 1, "disabled=True" if job.priority == 1 else ""), "%0.1f%%" % (job.usage * 100), "%is" % int(time.time() - job.last_dispatched), job.statusText(), diff --git a/release/scripts/io/netrender/netrender.css b/release/scripts/io/netrender/netrender.css new file mode 100644 index 00000000000..ac47b36861a --- /dev/null +++ b/release/scripts/io/netrender/netrender.css @@ -0,0 +1,51 @@ +body { + background-color:#eee; + font-size:12px; + font-family: "Lucida Sans","Lucida Sans Unicode","Lucida Grande",Lucida,sans-serif; + +} +a { + /*text-decoration:none;*/ + color:#666; +} +a:hover { + color:#000; +} +h2 { + background-color:#ddd; + font-size:120% + padding:5px; +} + +table { + text-align:center; + border:0; + background-color:#ddd; + padding: 0px; + margin: 0px; +} +thead{ + font-size:90%; + color:#555; + background-color:#ccc; +} +td { + border:0; + padding:2px; + padding-left:10px; + padding-right:10px; + margin-left:20px + background-color:#ddd; +} +td:hover { + background-color:#ccc; +} +tr { + border:0; +} +button { + color: #111; + width: auto; + height: auto; +} + diff --git a/release/scripts/io/netrender/slave.py b/release/scripts/io/netrender/slave.py index 9d7fa4fb6b8..10f73dbe258 100644 --- a/release/scripts/io/netrender/slave.py +++ b/release/scripts/io/netrender/slave.py @@ -54,10 +54,9 @@ def slave_Info(): def testCancel(conn, job_id, frame_number): conn.request("HEAD", "/status", headers={"job-id":job_id, "job-frame": str(frame_number)}) - response = conn.getresponse() - + # cancelled if job isn't found anymore - if response.status == http.client.NO_CONTENT: + if conn.getresponse().status == http.client.NO_CONTENT: return True else: return False @@ -125,7 +124,7 @@ def render_slave(engine, netsettings): job_full_path = testFile(conn, job.id, slave_id, 0, JOB_PREFIX, job_path) print("Fullpath", job_full_path) print("File:", main_file, "and %i other files" % (len(job.files) - 1,)) - engine.update_stats("", "Render File", main_file, "for job", job.id) + engine.update_stats("", "Render File "+ main_file+ " for job "+ job.id) for rfile in job.files[1:]: print("\t", rfile.filepath) @@ -202,10 +201,12 @@ def render_slave(engine, netsettings): if stdout: # (only need to update on one frame, they are linked conn.request("PUT", logURL(job.id, first_frame), stdout, headers=headers) - response = conn.getresponse() + if conn.getresponse().status == http.client.NO_CONTENT: + continue headers = {"job-id":job.id, "slave-id":slave_id, "job-time":str(avg_t)} + if status == 0: # non zero status is error headers["job-result"] = str(DONE) for frame in job.frames: @@ -216,17 +217,20 @@ def render_slave(engine, netsettings): f = open(JOB_PREFIX + "%06d" % frame.number + ".exr", 'rb') conn.request("PUT", "/render", f, headers=headers) f.close() - response = conn.getresponse() + if conn.getresponse().status == http.client.NO_CONTENT: + continue elif job.type == netrender.model.JOB_PROCESS: conn.request("PUT", "/render", headers=headers) - response = conn.getresponse() + if conn.getresponse().status == http.client.NO_CONTENT: + continue else: headers["job-result"] = str(ERROR) for frame in job.frames: headers["job-frame"] = str(frame.number) # send error result back to server conn.request("PUT", "/render", headers=headers) - response = conn.getresponse() + if conn.getresponse().status == http.client.NO_CONTENT: + continue else: if timeout < MAX_TIMEOUT: timeout += INCREMENT_TIMEOUT @@ -240,4 +244,4 @@ def render_slave(engine, netsettings): conn.close() if __name__ == "__main__": - pass \ No newline at end of file + pass