Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMartin Poirier <theeth@yahoo.com>2009-09-01 05:09:05 +0400
committerMartin Poirier <theeth@yahoo.com>2009-09-01 05:09:05 +0400
commit285d665d99da1e4ab9406f66026fcca77195d761 (patch)
tree1d214b65559102cac171d731adca42befdfa8e3a /release
parent47beb68a0fbeecf0135efd5a356b6ece03e24457 (diff)
more use of data structures for communication. begining support for more than one file per fob (external dependencies, point cache, ...)
Diffstat (limited to 'release')
-rw-r--r--release/io/netrender/client.py13
-rw-r--r--release/io/netrender/master.py117
-rw-r--r--release/io/netrender/model.py23
-rw-r--r--release/io/netrender/operators.py76
-rw-r--r--release/io/netrender/slave.py88
-rw-r--r--release/io/netrender/ui.py23
-rw-r--r--release/io/netrender/utils.py36
7 files changed, 221 insertions, 155 deletions
diff --git a/release/io/netrender/client.py b/release/io/netrender/client.py
index 90039a3273a..bc4d363c996 100644
--- a/release/io/netrender/client.py
+++ b/release/io/netrender/client.py
@@ -22,7 +22,7 @@ class NetworkRenderEngine(bpy.types.RenderEngine):
def render_master(self, scene):
server_address = (scene.network_render.server_address, scene.network_render.server_port)
- httpd = master.RenderMasterServer(server_address, master.RenderHandler)
+ httpd = master.RenderMasterServer(server_address, master.RenderHandler, scene.network_render.path)
httpd.timeout = 1
httpd.stats = self.update_stats
while not self.test_break():
@@ -32,6 +32,7 @@ class NetworkRenderEngine(bpy.types.RenderEngine):
slave.render_slave(self, scene)
def render_client(self, scene):
+ netsettings = scene.network_render
self.update_stats("", "Network render client initiation")
conn = clientConnection(scene)
@@ -41,7 +42,7 @@ class NetworkRenderEngine(bpy.types.RenderEngine):
self.update_stats("", "Network render exporting")
- job_id = scene.network_render.job_id
+ job_id = netsettings.job_id
# reading back result
@@ -51,10 +52,10 @@ class NetworkRenderEngine(bpy.types.RenderEngine):
response = conn.getresponse()
if response.status == http.client.NO_CONTENT:
- scene.network_render.job_id = clientSendJob(conn, scene)
+ netsettings.job_id = clientSendJob(conn, scene)
clientRequestResult(conn, scene, job_id)
- while response.status == http.client.PROCESSING and not self.test_break():
+ while response.status == http.client.ACCEPTED and not self.test_break():
print("waiting")
time.sleep(1)
clientRequestResult(conn, scene, job_id)
@@ -68,7 +69,7 @@ class NetworkRenderEngine(bpy.types.RenderEngine):
x= int(r.resolution_x*r.resolution_percentage*0.01)
y= int(r.resolution_y*r.resolution_percentage*0.01)
- f = open(PATH_PREFIX + "output.exr", "wb")
+ f = open(netsetting.path + "output.exr", "wb")
buf = response.read(1024)
while buf:
@@ -78,7 +79,7 @@ class NetworkRenderEngine(bpy.types.RenderEngine):
f.close()
result = self.begin_result(0, 0, x, y)
- result.load_from_file(PATH_PREFIX + "output.exr", 0, 0)
+ result.load_from_file(netsettings.path + "output.exr", 0, 0)
self.end_result(result)
conn.close()
diff --git a/release/io/netrender/master.py b/release/io/netrender/master.py
index daca3bcf653..6f97685935d 100644
--- a/release/io/netrender/master.py
+++ b/release/io/netrender/master.py
@@ -9,12 +9,22 @@ JOB_WAITING = 0 # before all data has been entered
JOB_PAUSED = 1 # paused by user
JOB_QUEUED = 2 # ready to be dispatched
+class MRenderFile:
+ def __init__(self, filepath):
+ self.filepath = filepath
+ self.found = False
+
+ def test(self):
+ self.found = os.path.exists(self.filepath)
+ return self.found
+
+
class MRenderSlave(netrender.model.RenderSlave):
- def __init__(self, name, adress, stats):
+ def __init__(self, name, address, stats):
super().__init__()
- self.id = hashlib.md5(bytes(repr(name) + repr(adress), encoding='utf8')).hexdigest()
+ self.id = hashlib.md5(bytes(repr(name) + repr(address), encoding='utf8')).hexdigest()
self.name = name
- self.adress = adress
+ self.address = address
self.stats = stats
self.last_seen = time.time()
@@ -31,11 +41,12 @@ def groupKey(job):
return (job.status, job.framesLeft() > 0, job.priority, job.credits)
class MRenderJob(netrender.model.RenderJob):
- def __init__(self, job_id, name, path, chunks = 1, priority = 1, credits = 100.0, blacklist = []):
+ def __init__(self, job_id, name, files, chunks = 1, priority = 1, credits = 100.0, blacklist = []):
super().__init__()
self.id = job_id
self.name = name
- self.path = path
+ self.files = files
+ self.render_files = [MRenderFile(path) for path in files]
self.status = JOB_WAITING
self.frames = []
self.chunks = chunks
@@ -44,6 +55,14 @@ class MRenderJob(netrender.model.RenderJob):
self.blacklist = blacklist
self.last_dispatched = time.time()
+ def testStart(self):
+ for f in self.render_files:
+ if not f.test():
+ return False
+
+ self.start()
+ return True
+
def start(self):
self.status = JOB_QUEUED
@@ -75,7 +94,7 @@ class MRenderJob(netrender.model.RenderJob):
if f.status == QUEUED:
self.update()
frames.append(f)
- if len(frames) == self.chunks:
+ if len(frames) >= self.chunks:
break
return frames
@@ -162,10 +181,10 @@ class RenderHandler(http.server.BaseHTTPRequestHandler):
if frame:
if frame.status in (QUEUED, DISPATCHED):
- self.send_head(http.client.PROCESSING)
+ self.send_head(http.client.ACCEPTED)
elif frame.status == DONE:
self.server.stats("", "Sending result back to client")
- f = open(PATH_PREFIX + job_id + "%04d" % job_frame + ".exr", 'rb')
+ f = open(self.server.path + job_id + "%04d" % job_frame + ".exr", 'rb')
self.send_head()
@@ -173,13 +192,13 @@ class RenderHandler(http.server.BaseHTTPRequestHandler):
f.close()
elif frame.status == ERROR:
- self.send_head(http.client.NO_CONTENT)
+ self.send_head(http.client.PARTIAL_CONTENT)
else:
# no such frame
- self.send_head(http.client.NOT_FOUND)
+ self.send_head(http.client.NO_CONTENT)
else:
# no such job id
- self.send_head(http.client.NOT_FOUND)
+ self.send_head(http.client.NO_CONTENT)
# =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
elif self.path == "log":
job_id = self.headers['job-id']
@@ -194,23 +213,21 @@ class RenderHandler(http.server.BaseHTTPRequestHandler):
if frame:
if frame.status in (QUEUED, DISPATCHED):
self.send_head(http.client.PROCESSING)
- elif frame.status == DONE:
+ else:
self.server.stats("", "Sending log back to client")
- f = open(PATH_PREFIX + job_id + "%04d" % job_frame + ".log", 'rb')
+ f = open(self.server.path + job_id + "%04d" % job_frame + ".log", 'rb')
self.send_head()
shutil.copyfileobj(f, self.wfile)
f.close()
- elif frame.status == ERROR:
- self.send_head(http.client.NO_CONTENT)
else:
# no such frame
- self.send_head(http.client.NOT_FOUND)
+ self.send_head(http.client.NO_CONTENT)
else:
# no such job id
- self.send_head(http.client.NOT_FOUND)
+ self.send_head(http.client.NO_CONTENT)
# =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
elif self.path == "status":
job_id = self.headers.get('job-id', "")
@@ -228,13 +245,13 @@ class RenderHandler(http.server.BaseHTTPRequestHandler):
message = frame.serialize()
else:
# no such frame
- self.send_heat(http.client.NOT_FOUND)
+ self.send_heat(http.client.NO_CONTENT)
return
else:
message = job.serialize()
else:
# no such job id
- self.send_head(http.client.NOT_FOUND)
+ self.send_head(http.client.NO_CONTENT)
return
else: # status of all jobs
message = []
@@ -262,6 +279,7 @@ class RenderHandler(http.server.BaseHTTPRequestHandler):
if job and frames:
for f in frames:
+ print("dispatch", f.number)
f.status = DISPATCHED
f.slave = slave
@@ -274,9 +292,9 @@ class RenderHandler(http.server.BaseHTTPRequestHandler):
self.server.stats("", "Sending job frame to render node")
else:
# no job available, return error code
- self.send_head(http.client.NO_CONTENT)
+ self.send_head(http.client.ACCEPTED)
else: # invalid slave id
- self.send_head(http.client.NOT_FOUND)
+ self.send_head(http.client.NO_CONTENT)
# =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
elif self.path == "file":
job_id = self.headers['job-id']
@@ -288,14 +306,14 @@ class RenderHandler(http.server.BaseHTTPRequestHandler):
self.send_head(headers={"job-id": job.id})
self.server.stats("", "Sending file to render node")
- f = open(PATH_PREFIX + job.id + ".blend", 'rb')
+ f = open(self.server.path + job.id + ".blend", 'rb')
shutil.copyfileobj(f, self.wfile)
f.close()
else:
# no such job id
- self.send_head(http.client.NOT_FOUND)
+ self.send_head(http.client.NO_CONTENT)
# =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
elif self.path == "slave":
message = []
@@ -322,33 +340,25 @@ class RenderHandler(http.server.BaseHTTPRequestHandler):
self.server.stats("", "Receiving job")
length = int(self.headers['content-length'])
- job_frame_string = self.headers['job-frame']
- job_name = self.headers.get('job-name', "")
- job_chunks = int(self.headers.get('job-chunks', "1"))
- blacklist = self.headers.get('slave-blacklist', '').split()
- job_path = str(self.rfile.read(length), encoding='utf8')
+ job_info = netrender.model.RenderJob.materialize(eval(str(self.rfile.read(length), encoding='utf8')))
- if os.path.exists(job_path):
- job_id = self.server.nextJobID()
-
- job = MRenderJob(job_id, job_name, job_path, chunks = job_chunks, blacklist = blacklist)
- self.server.addJob(job)
+ job_id = self.server.nextJobID()
+
+ print("chunks", job_info.chunks)
+
+ job = MRenderJob(job_id, job_info.name, job_info.files, chunks = job_info.chunks, priority = job_info.priority, blacklist = job_info.blacklist)
+ self.server.addJob(job)
+
+ for frame in job_info.frames:
+ frame = job.addFrame(frame.number)
- if ":" in job_frame_string:
- frame_start, frame_end = [int(x) for x in job_frame_string.split(":")]
-
- for job_frame in range(frame_start, frame_end + 1):
- frame = job.addFrame(job_frame)
- else:
- job_frame = int(job_frame_string)
- frame = job.addFrame(job_frame)
-
- job.start()
-
- self.send_head(headers={"job-id": job_id})
+ headers={"job-id": job_id}
+
+ if job.testStart():
+ self.send_head(headers=headers)
else:
- self.send_head(http.client.NOT_FOUND)
+ self.send_head(http.client.ACCEPTED, headers=headers)
# =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
elif self.path == "cancel":
job_id = self.headers.get('job-id', "")
@@ -375,7 +385,7 @@ class RenderHandler(http.server.BaseHTTPRequestHandler):
self.send_head()
else: # job not found
- self.send_head(http.client.NOT_FOUND)
+ self.send_head(http.client.NO_CONTENT)
# =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
elif self.path == "slave":
length = int(self.headers['content-length'])
@@ -412,7 +422,7 @@ class RenderHandler(http.server.BaseHTTPRequestHandler):
job_path = job_id + ".blend"
- f = open(PATH_PREFIX + job_path, "wb")
+ f = open(self.server.path + job_path, "wb")
f.write(buf)
f.close()
del buf
@@ -445,7 +455,7 @@ class RenderHandler(http.server.BaseHTTPRequestHandler):
if job_result == DONE:
length = int(self.headers['content-length'])
buf = self.rfile.read(length)
- f = open(PATH_PREFIX + job_id + "%04d" % job_frame + ".exr", 'wb')
+ f = open(self.server.path + job_id + "%04d" % job_frame + ".exr", 'wb')
f.write(buf)
f.close()
@@ -471,7 +481,7 @@ class RenderHandler(http.server.BaseHTTPRequestHandler):
print("log length:", length)
buf = self.rfile.read(length)
- f = open(PATH_PREFIX + job_id + "%04d" % job_frame + ".log", 'wb')
+ f = open(self.server.path + job_id + "%04d" % job_frame + ".log", 'wb')
f.write(buf)
f.close()
@@ -483,20 +493,21 @@ class RenderHandler(http.server.BaseHTTPRequestHandler):
class RenderMasterServer(http.server.HTTPServer):
- def __init__(self, address, handler_class):
+ def __init__(self, address, handler_class, path):
super().__init__(address, handler_class)
self.jobs = []
self.jobs_map = {}
self.slaves = []
self.slaves_map = {}
self.job_id = 0
+ self.path = path
def nextJobID(self):
self.job_id += 1
return str(self.job_id)
- def addSlave(self, name, adress, stats):
- slave = MRenderSlave(name, adress, stats)
+ def addSlave(self, name, address, stats):
+ slave = MRenderSlave(name, address, stats)
self.slaves.append(slave)
self.slaves_map[slave.id] = slave
diff --git a/release/io/netrender/model.py b/release/io/netrender/model.py
index 98866ff1dfc..8b919b1fa36 100644
--- a/release/io/netrender/model.py
+++ b/release/io/netrender/model.py
@@ -10,7 +10,7 @@ class RenderSlave:
def __init__(self):
self.id = ""
self.name = ""
- self.adress = (0,0)
+ self.address = (0,0)
self.stats = ""
self.total_done = 0
self.total_error = 0
@@ -20,7 +20,7 @@ class RenderSlave:
return {
"id": self.id,
"name": self.name,
- "adress": self.adress,
+ "address": self.address,
"stats": self.stats,
"total_done": self.total_done,
"total_error": self.total_error,
@@ -40,7 +40,7 @@ class RenderSlave:
slave = RenderSlave()
slave.id = slave_id
slave.name = data["name"]
- slave.adress = data["adress"]
+ slave.address = data["address"]
slave.stats = data["stats"]
slave.total_done = data["total_done"]
slave.total_error = data["total_error"]
@@ -54,7 +54,7 @@ class RenderJob:
def __init__(self):
self.id = ""
self.name = ""
- self.path = ""
+ self.files = []
self.frames = []
self.chunks = 0
self.priority = 0
@@ -62,6 +62,11 @@ class RenderJob:
self.blacklist = []
self.last_dispatched = 0.0
+ def addFrame(self, frame_number):
+ frame = RenderFrame(frame_number)
+ self.frames.append(frame)
+ return frame
+
def __len__(self):
return len(self.frames)
@@ -96,8 +101,9 @@ class RenderJob:
return {
"id": self.id,
"name": self.name,
- "path": self.path,
+ "files": self.files,
"frames": [f.serialize() for f in self.frames if not frames or f in frames],
+ "chunks": self.chunks,
"priority": self.priority,
"credits": self.credits,
"blacklist": self.blacklist,
@@ -112,8 +118,9 @@ class RenderJob:
job = RenderJob()
job.id = data["id"]
job.name = data["name"]
- job.path = data["path"]
+ job.files = data["files"]
job.frames = [RenderFrame.materialize(f) for f in data["frames"]]
+ job.chunks = data["chunks"]
job.priority = data["priority"]
job.credits = data["credits"]
job.blacklist = data["blacklist"]
@@ -122,8 +129,8 @@ class RenderJob:
return job
class RenderFrame:
- def __init__(self):
- self.number = 0
+ def __init__(self, number = 0):
+ self.number = number
self.time = 0
self.status = QUEUED
self.slave = None
diff --git a/release/io/netrender/operators.py b/release/io/netrender/operators.py
index 8df662b6b52..a1208aa1b46 100644
--- a/release/io/netrender/operators.py
+++ b/release/io/netrender/operators.py
@@ -48,7 +48,7 @@ class RENDER_OT_netclientstatus(bpy.types.Operator):
return True
def execute(self, context):
- netprops = context.scene.network_render
+ netsettings = context.scene.network_render
conn = clientConnection(context.scene)
if conn:
@@ -59,12 +59,12 @@ class RENDER_OT_netclientstatus(bpy.types.Operator):
jobs = (netrender.model.RenderJob.materialize(j) for j in eval(str(response.read(), encoding='utf8')))
- while(len(netprops.jobs) > 0):
- netprops.jobs.remove(0)
+ while(len(netsettings.jobs) > 0):
+ netsettings.jobs.remove(0)
for j in jobs:
- netprops.jobs.add()
- job = netprops.jobs[-1]
+ netsettings.jobs.add()
+ job = netsettings.jobs[-1]
job_results = j.framesStatus()
@@ -93,22 +93,22 @@ class RENDER_OT_netclientblacklistslave(bpy.types.Operator):
return True
def execute(self, context):
- netprops = context.scene.network_render
+ netsettings = context.scene.network_render
- if netprops.active_slave_index >= 0:
+ if netsettings.active_slave_index >= 0:
- slave = netrender.slaves[netprops.active_slave_index]
+ slave = netrender.slaves[netsettings.active_slave_index]
- netprops.slaves_blacklist.add()
+ netsettings.slaves_blacklist.add()
- netprops.slaves_blacklist[-1].id = slave.id
- netprops.slaves_blacklist[-1].name = slave.name
- netprops.slaves_blacklist[-1].adress = slave.adress
- netprops.slaves_blacklist[-1].last_seen = slave.last_seen
- netprops.slaves_blacklist[-1].stats = slave.stats
+ netsettings.slaves_blacklist[-1].id = slave.id
+ netsettings.slaves_blacklist[-1].name = slave.name
+ netsettings.slaves_blacklist[-1].address = slave.address
+ netsettings.slaves_blacklist[-1].last_seen = slave.last_seen
+ netsettings.slaves_blacklist[-1].stats = slave.stats
- netprops.slaves.remove(netprops.active_slave_index)
- netprops.active_slave_index = -1
+ netsettings.slaves.remove(netsettings.active_slave_index)
+ netsettings.active_slave_index = -1
return ('FINISHED',)
@@ -129,22 +129,22 @@ class RENDER_OT_netclientwhitelistslave(bpy.types.Operator):
return True
def execute(self, context):
- netprops = context.scene.network_render
+ netsettings = context.scene.network_render
- if netprops.active_blacklisted_slave_index >= 0:
+ if netsettings.active_blacklisted_slave_index >= 0:
- slave = netprops.slaves_blacklist[netprops.active_blacklisted_slave_index]
+ slave = netsettings.slaves_blacklist[netsettings.active_blacklisted_slave_index]
- netprops.slaves.add()
+ netsettings.slaves.add()
- netprops.slaves[-1].id = slave.id
- netprops.slaves[-1].name = slave.name
- netprops.slaves[-1].adress = slave.adress
- netprops.slaves[-1].last_seen = slave.last_seen
- netprops.slaves[-1].stats = slave.stats
+ netsettings.slaves[-1].id = slave.id
+ netsettings.slaves[-1].name = slave.name
+ netsettings.slaves[-1].address = slave.address
+ netsettings.slaves[-1].last_seen = slave.last_seen
+ netsettings.slaves[-1].stats = slave.stats
- netprops.slaves_blacklist.remove(netprops.active_blacklisted_slave_index)
- netprops.active_blacklisted_slave_index = -1
+ netsettings.slaves_blacklist.remove(netsettings.active_blacklisted_slave_index)
+ netsettings.active_blacklisted_slave_index = -1
return ('FINISHED',)
@@ -166,7 +166,7 @@ class RENDER_OT_netclientslaves(bpy.types.Operator):
return True
def execute(self, context):
- netprops = context.scene.network_render
+ netsettings = context.scene.network_render
conn = clientConnection(context.scene)
if conn:
@@ -177,21 +177,21 @@ class RENDER_OT_netclientslaves(bpy.types.Operator):
slaves = (netrender.model.RenderSlave.materialize(s) for s in eval(str(response.read(), encoding='utf8')))
- while(len(netprops.slaves) > 0):
- netprops.slaves.remove(0)
+ while(len(netsettings.slaves) > 0):
+ netsettings.slaves.remove(0)
for s in slaves:
- for slave in netprops.slaves_blacklist:
+ for slave in netsettings.slaves_blacklist:
if slave.id == s.id:
break
- netprops.slaves.add()
- slave = netprops.slaves[-1]
+ netsettings.slaves.add()
+ slave = netsettings.slaves[-1]
slave.id = s.id
slave.name = s.name
slave.stats = s.stats
- slave.adress = s.adress[0]
+ slave.address = s.address[0]
slave.last_seen = time.ctime(s.last_seen)
return ('FINISHED',)
@@ -210,15 +210,15 @@ class RENDER_OT_netclientcancel(bpy.types.Operator):
__props__ = []
def poll(self, context):
- netprops = context.scene.network_render
- return netprops.active_job_index >= 0 and len(netprops.jobs) > 0
+ netsettings = context.scene.network_render
+ return netsettings.active_job_index >= 0 and len(netsettings.jobs) > 0
def execute(self, context):
- netprops = context.scene.network_render
+ netsettings = context.scene.network_render
conn = clientConnection(context.scene)
if conn:
- job = netprops.jobs[netprops.active_job_index]
+ job = netsettings.jobs[netsettings.active_job_index]
conn.request("POST", "cancel", headers={"job-id":job.id})
diff --git a/release/io/netrender/slave.py b/release/io/netrender/slave.py
index 59c474293b3..64801743d70 100644
--- a/release/io/netrender/slave.py
+++ b/release/io/netrender/slave.py
@@ -21,18 +21,51 @@ def testCancel(conn, job_id):
response = conn.getresponse()
# cancelled if job isn't found anymore
- if response.status == http.client.NOT_FOUND:
+ if response.status == http.client.NO_CONTENT:
return True
else:
return False
+def testFile(conn, JOB_PREFIX, file_path, main_path = None):
+ if os.path.isabs(file_path):
+ # if an absolute path, make sure path exists, if it doesn't, use relative local path
+ job_full_path = file_path
+ if not os.path.exists(job_full_path):
+ p, n = os.path.split(job_full_path)
+
+ if main_path and p.startswith(main_path):
+ directory = JOB_PREFIX + p[len(main_path):]
+ job_full_path = directory + n
+ if not os.path.exists(directory):
+ os.mkdir(directory)
+ else:
+ job_full_path = JOB_PREFIX + n
+ else:
+ job_full_path = JOB_PREFIX + file_path
+
+ if not os.path.exists(job_full_path):
+ conn.request("GET", "file", headers={"job-id": job.id, "slave-id":slave_id})
+ response = conn.getresponse()
+
+ if response.status != http.client.OK:
+ return None # file for job not returned by server, need to return an error code to server
+
+ f = open(job_full_path, "wb")
+ buf = response.read(1024)
+
+ while buf:
+ f.write(buf)
+ buf = response.read(1024)
+
+ f.close()
+
+ return job_full_path
+
+
def render_slave(engine, scene):
- NODE_PREFIX = PATH_PREFIX + "node" + os.sep
+ netsettings = scene.network_render
timeout = 1
- if not os.path.exists(NODE_PREFIX):
- os.mkdir(NODE_PREFIX)
-
engine.update_stats("", "Network render node initiation")
conn = clientConnection(scene)
@@ -43,6 +76,10 @@ def render_slave(engine, scene):
slave_id = response.getheader("slave-id")
+ NODE_PREFIX = netsettings.path + "node_" + slave_id + os.sep
+ if not os.path.exists(NODE_PREFIX):
+ os.mkdir(NODE_PREFIX)
+
while not engine.test_break():
conn.request("GET", "job", headers={"slave-id":slave_id})
@@ -53,41 +90,30 @@ def render_slave(engine, scene):
job = netrender.model.RenderJob.materialize(eval(str(response.read(), encoding='utf8')))
- print("File:", job.path)
- engine.update_stats("", "Render File", job.path, "for job", job.id)
+ JOB_PREFIX = NODE_PREFIX + "job_" + job.id + os.sep
+ if not os.path.exists(JOB_PREFIX):
+ os.mkdir(JOB_PREFIX)
- if os.path.isabs(job.path):
- # if an absolute path, make sure path exists, if it doesn't, use relative local path
- job_full_path = job.path
- if not os.path.exists(job_full_path):
- job_full_path = NODE_PREFIX + job.id + ".blend"
- else:
- job_full_path = NODE_PREFIX + job.path
+ job_path = job.files[0]
+ main_path, main_file = os.path.split(job_path)
- if not os.path.exists(job_full_path):
- conn.request("GET", "file", headers={"job-id": job.id, "slave-id":slave_id})
- response = conn.getresponse()
-
- if response.status != http.client.OK:
- break # file for job not returned by server, need to return an error code to server
-
- f = open(job_full_path, "wb")
- buf = response.read(1024)
-
- while buf:
- f.write(buf)
- buf = response.read(1024)
-
- f.close()
+ job_full_path = testFile(conn, 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)
+
+ for file_path in job.files[1:]:
+ testFile(conn, JOB_PREFIX, file_path, main_path)
frame_args = []
for frame in job.frames:
+ print("frame", frame.number)
frame_args += ["-f", str(frame.number)]
start_t = time.time()
- process = subprocess.Popen([sys.argv[0], "-b", job_full_path, "-o", NODE_PREFIX + job.id, "-E", "BLENDER_RENDER", "-F", "MULTILAYER"] + frame_args, stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
+ process = subprocess.Popen([sys.argv[0], "-b", job_full_path, "-o", JOB_PREFIX + "######", "-E", "BLENDER_RENDER", "-F", "MULTILAYER"] + frame_args, stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
cancelled = False
stdout = bytes()
@@ -120,7 +146,7 @@ def render_slave(engine, scene):
for frame in job.frames:
headers["job-frame"] = str(frame.number)
# send result back to server
- f = open(NODE_PREFIX + job.id + "%04d" % frame.number + ".exr", 'rb')
+ f = open(JOB_PREFIX + "%06d" % frame.number + ".exr", 'rb')
conn.request("PUT", "render", f, headers=headers)
f.close()
response = conn.getresponse()
diff --git a/release/io/netrender/ui.py b/release/io/netrender/ui.py
index 71b013c5a63..f8179fedbda 100644
--- a/release/io/netrender/ui.py
+++ b/release/io/netrender/ui.py
@@ -48,9 +48,11 @@ class SCENE_PT_network_settings(RenderButtonsPanel):
col.itemR(scene.network_render, "mode")
col.itemR(scene.network_render, "server_address")
col.itemR(scene.network_render, "server_port")
+ col.itemR(scene.network_render, "path")
if scene.network_render.mode == "RENDER_CLIENT":
col.itemR(scene.network_render, "chunks")
+ col.itemR(scene.network_render, "priority")
col.itemR(scene.network_render, "job_name")
col.itemO("render.netclientsend", text="send job to server")
bpy.types.register(SCENE_PT_network_settings)
@@ -84,7 +86,7 @@ class SCENE_PT_network_slaves(RenderButtonsPanel):
slave = netrender.slaves[netrender.active_slave_index]
layout.itemL(text="Name: " + slave.name)
- layout.itemL(text="Adress: " + slave.adress)
+ layout.itemL(text="Address: " + slave.address)
layout.itemL(text="Seen: " + slave.last_seen)
layout.itemL(text="Stats: " + slave.stats)
@@ -119,7 +121,7 @@ class SCENE_PT_network_slaves_blacklist(RenderButtonsPanel):
slave = netrender.slaves_blacklist[netrender.active_blacklisted_slave_index]
layout.itemL(text="Name: " + slave.name)
- layout.itemL(text="Adress: " + slave.adress)
+ layout.itemL(text="Address: " + slave.address)
layout.itemL(text="Seen: " + slave.last_seen)
layout.itemL(text="Stats: " + slave.stats)
@@ -189,6 +191,12 @@ NetRenderSettings.IntProperty( attr="server_port",
min=1,
max=65535)
+NetRenderSettings.StringProperty( attr="path",
+ name="Path",
+ description="Path for temporary files",
+ maxlen = 128,
+ default = "/tmp/")
+
NetRenderSettings.StringProperty( attr="job_name",
name="Job name",
description="Name of the job",
@@ -202,6 +210,13 @@ NetRenderSettings.IntProperty( attr="chunks",
min=1,
max=65535)
+NetRenderSettings.IntProperty( attr="priority",
+ name="Priority",
+ description="Priority of the job",
+ default = 1,
+ min=1,
+ max=10)
+
NetRenderSettings.StringProperty( attr="job_id",
name="Network job id",
description="id of the last sent render job",
@@ -249,8 +264,8 @@ NetRenderSlave.StringProperty( attr="name",
maxlen = 64,
default = "")
-NetRenderSlave.StringProperty( attr="adress",
- name="Adress of the slave",
+NetRenderSlave.StringProperty( attr="address",
+ name="Address of the slave",
description="",
maxlen = 64,
default = "")
diff --git a/release/io/netrender/utils.py b/release/io/netrender/utils.py
index c158ff115fa..d64b6fcda1e 100644
--- a/release/io/netrender/utils.py
+++ b/release/io/netrender/utils.py
@@ -3,9 +3,9 @@ import sys, os
import http, http.client, http.server, urllib
import subprocess, shutil, time, hashlib
-VERSION = b"0.3"
+import netrender.model
-PATH_PREFIX = "/tmp/"
+VERSION = b"0.3"
QUEUED = 0
DISPATCHED = 1
@@ -41,40 +41,46 @@ def clientVerifyVersion(conn):
return True
def clientSendJob(conn, scene, anim = False, chunks = 5):
+ netsettings = scene.network_render
+ job = netrender.model.RenderJob()
if anim:
- job_frame = "%i:%i" % (scene.start_frame, scene.end_frame)
+ for f in range(scene.start_frame, scene.end_frame + 1):
+ job.addFrame(f)
else:
- job_frame = "%i" % (scene.current_frame, )
-
- blacklist = []
+ job.addFrame(scene.current_frame)
filename = bpy.data.filename
+ job.files.append(filename)
- name = scene.network_render.job_name
-
+ name = netsettings.job_name
if name == "[default]":
path, name = os.path.split(filename)
+ job.name = name
+
for slave in scene.network_render.slaves_blacklist:
- blacklist.append(slave.id)
-
- blacklist = " ".join(blacklist)
+ job.blacklist.append(slave.id)
- headers = {"job-frame":job_frame, "job-name":name, "job-chunks": str(chunks), "slave-blacklist": blacklist}
+ job.chunks = netsettings.chunks
+ job.priority = netsettings.priority
# try to send path first
- conn.request("POST", "job", filename, headers=headers)
+ conn.request("POST", "job", repr(job.serialize()))
response = conn.getresponse()
+ job_id = response.getheader("job-id")
+
# if not found, send whole file
if response.status == http.client.NOT_FOUND:
f = open(bpy.data.filename, "rb")
- conn.request("PUT", "file", f, headers=headers)
+ conn.request("PUT", "file", f, headers={"job-id": job_id})
f.close()
response = conn.getresponse()
- return response.getheader("job-id")
+ # server will reply with NOT_FOUD until all files are found
+
+ return job_id
def clientRequestResult(conn, scene, job_id):
conn.request("GET", "render", headers={"job-id": job_id, "job-frame":str(scene.current_frame)})