forked from bartvdbraak/blender
netrender: fix some bugs with job cancellation, remove credits system, add more status report on server, cleanup server error management
This commit is contained in:
parent
da5ff2ca98
commit
903d8231d9
@ -61,12 +61,6 @@ class Balancer:
|
|||||||
|
|
||||||
# ==========================
|
# ==========================
|
||||||
|
|
||||||
|
|
||||||
class RatingCredit(RatingRule):
|
|
||||||
def rate(self, job):
|
|
||||||
# more credit is better (sort at first in list)
|
|
||||||
return -job.credits * job.priority
|
|
||||||
|
|
||||||
class RatingUsage(RatingRule):
|
class RatingUsage(RatingRule):
|
||||||
def rate(self, job):
|
def rate(self, job):
|
||||||
# less usage is better
|
# less usage is better
|
||||||
|
@ -36,8 +36,13 @@ class MRenderSlave(netrender.model.RenderSlave):
|
|||||||
def seen(self):
|
def seen(self):
|
||||||
self.last_seen = time.time()
|
self.last_seen = time.time()
|
||||||
|
|
||||||
|
def finishedFrame(self, frame_number):
|
||||||
|
self.job_frames.remove(frame_number)
|
||||||
|
if not self.job_frames:
|
||||||
|
self.job = None
|
||||||
|
|
||||||
class MRenderJob(netrender.model.RenderJob):
|
class MRenderJob(netrender.model.RenderJob):
|
||||||
def __init__(self, job_id, name, files, chunks = 1, priority = 1, credits = 100.0, blacklist = []):
|
def __init__(self, job_id, name, files, chunks = 1, priority = 1, blacklist = []):
|
||||||
super().__init__()
|
super().__init__()
|
||||||
self.id = job_id
|
self.id = job_id
|
||||||
self.name = name
|
self.name = name
|
||||||
@ -46,7 +51,6 @@ class MRenderJob(netrender.model.RenderJob):
|
|||||||
self.chunks = chunks
|
self.chunks = chunks
|
||||||
self.priority = priority
|
self.priority = priority
|
||||||
self.usage = 0.0
|
self.usage = 0.0
|
||||||
self.credits = credits
|
|
||||||
self.blacklist = blacklist
|
self.blacklist = blacklist
|
||||||
self.last_dispatched = time.time()
|
self.last_dispatched = time.time()
|
||||||
|
|
||||||
@ -80,14 +84,6 @@ class MRenderJob(netrender.model.RenderJob):
|
|||||||
def start(self):
|
def start(self):
|
||||||
self.status = JOB_QUEUED
|
self.status = JOB_QUEUED
|
||||||
|
|
||||||
def update(self):
|
|
||||||
if self.last_update == 0:
|
|
||||||
self.credits += (time.time() - self.last_dispatched) / 60
|
|
||||||
else:
|
|
||||||
self.credits += (time.time() - self.last_update) / 60
|
|
||||||
|
|
||||||
self.last_update = time.time()
|
|
||||||
|
|
||||||
def addLog(self, frames):
|
def addLog(self, frames):
|
||||||
log_name = "_".join(("%04d" % f for f in frames)) + ".log"
|
log_name = "_".join(("%04d" % f for f in frames)) + ".log"
|
||||||
log_path = self.save_path + log_name
|
log_path = self.save_path + log_name
|
||||||
@ -110,7 +106,6 @@ class MRenderJob(netrender.model.RenderJob):
|
|||||||
frames = []
|
frames = []
|
||||||
for f in self.frames:
|
for f in self.frames:
|
||||||
if f.status == QUEUED:
|
if f.status == QUEUED:
|
||||||
self.credits -= 1 # cost of one frame
|
|
||||||
self.last_dispatched = time.time()
|
self.last_dispatched = time.time()
|
||||||
frames.append(f)
|
frames.append(f)
|
||||||
if len(frames) >= self.chunks:
|
if len(frames) >= self.chunks:
|
||||||
@ -150,30 +145,24 @@ class RenderHandler(http.server.BaseHTTPRequestHandler):
|
|||||||
self.end_headers()
|
self.end_headers()
|
||||||
|
|
||||||
def do_HEAD(self):
|
def do_HEAD(self):
|
||||||
print(self.path)
|
|
||||||
|
|
||||||
if self.path == "/status":
|
if self.path == "/status":
|
||||||
job_id = self.headers.get('job-id', "")
|
job_id = self.headers.get('job-id', "")
|
||||||
job_frame = int(self.headers.get('job-frame', -1))
|
job_frame = int(self.headers.get('job-frame', -1))
|
||||||
|
|
||||||
if job_id:
|
job = self.server.getJobID(job_id)
|
||||||
print("status:", job_id, "\n")
|
|
||||||
|
|
||||||
job = self.server.getJobByID(job_id)
|
|
||||||
if job:
|
if job:
|
||||||
if job_frame != -1:
|
frame = job[job_frame]
|
||||||
frame = job[frame]
|
|
||||||
|
|
||||||
if not frame:
|
|
||||||
|
if frame:
|
||||||
|
self.send_head(http.client.OK)
|
||||||
|
else:
|
||||||
# no such frame
|
# no such frame
|
||||||
self.send_heat(http.client.NO_CONTENT)
|
self.send_head(http.client.NO_CONTENT)
|
||||||
return
|
|
||||||
else:
|
else:
|
||||||
# no such job id
|
# no such job id
|
||||||
self.send_head(http.client.NO_CONTENT)
|
self.send_head(http.client.NO_CONTENT)
|
||||||
return
|
|
||||||
|
|
||||||
self.send_head()
|
|
||||||
|
|
||||||
# =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
|
# =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
|
||||||
# -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
|
# -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
|
||||||
@ -182,19 +171,17 @@ class RenderHandler(http.server.BaseHTTPRequestHandler):
|
|||||||
# =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
|
# =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
|
||||||
|
|
||||||
def do_GET(self):
|
def do_GET(self):
|
||||||
print(self.path)
|
|
||||||
|
|
||||||
if self.path == "/version":
|
if self.path == "/version":
|
||||||
self.send_head()
|
self.send_head()
|
||||||
self.server.stats("", "New client connection")
|
self.server.stats("", "Version check")
|
||||||
self.wfile.write(VERSION)
|
self.wfile.write(VERSION)
|
||||||
# =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
|
# =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
|
||||||
elif self.path == "/render":
|
elif self.path == "/render":
|
||||||
job_id = self.headers['job-id']
|
job_id = self.headers['job-id']
|
||||||
job_frame = int(self.headers['job-frame'])
|
job_frame = int(self.headers['job-frame'])
|
||||||
print("render:", job_id, job_frame)
|
|
||||||
|
|
||||||
job = self.server.getJobByID(job_id)
|
job = self.server.getJobID(job_id)
|
||||||
|
|
||||||
if job:
|
if job:
|
||||||
frame = job[job_frame]
|
frame = job[job_frame]
|
||||||
@ -203,7 +190,7 @@ class RenderHandler(http.server.BaseHTTPRequestHandler):
|
|||||||
if frame.status in (QUEUED, DISPATCHED):
|
if frame.status in (QUEUED, DISPATCHED):
|
||||||
self.send_head(http.client.ACCEPTED)
|
self.send_head(http.client.ACCEPTED)
|
||||||
elif frame.status == DONE:
|
elif frame.status == DONE:
|
||||||
self.server.stats("", "Sending result back to client")
|
self.server.stats("", "Sending result to client")
|
||||||
f = open(job.save_path + "%04d" % job_frame + ".exr", 'rb')
|
f = open(job.save_path + "%04d" % job_frame + ".exr", 'rb')
|
||||||
|
|
||||||
self.send_head()
|
self.send_head()
|
||||||
@ -223,9 +210,8 @@ class RenderHandler(http.server.BaseHTTPRequestHandler):
|
|||||||
elif self.path == "/log":
|
elif self.path == "/log":
|
||||||
job_id = self.headers['job-id']
|
job_id = self.headers['job-id']
|
||||||
job_frame = int(self.headers['job-frame'])
|
job_frame = int(self.headers['job-frame'])
|
||||||
print("log:", job_id, job_frame)
|
|
||||||
|
|
||||||
job = self.server.getJobByID(job_id)
|
job = self.server.getJobID(job_id)
|
||||||
|
|
||||||
if job:
|
if job:
|
||||||
frame = job[job_frame]
|
frame = job[job_frame]
|
||||||
@ -234,7 +220,7 @@ class RenderHandler(http.server.BaseHTTPRequestHandler):
|
|||||||
if not frame.log_path or frame.status in (QUEUED, DISPATCHED):
|
if not frame.log_path or frame.status in (QUEUED, DISPATCHED):
|
||||||
self.send_head(http.client.PROCESSING)
|
self.send_head(http.client.PROCESSING)
|
||||||
else:
|
else:
|
||||||
self.server.stats("", "Sending log back to client")
|
self.server.stats("", "Sending log to client")
|
||||||
f = open(frame.log_path, 'rb')
|
f = open(frame.log_path, 'rb')
|
||||||
|
|
||||||
self.send_head()
|
self.send_head()
|
||||||
@ -254,9 +240,8 @@ class RenderHandler(http.server.BaseHTTPRequestHandler):
|
|||||||
job_frame = int(self.headers.get('job-frame', -1))
|
job_frame = int(self.headers.get('job-frame', -1))
|
||||||
|
|
||||||
if job_id:
|
if job_id:
|
||||||
print("status:", job_id, "\n")
|
|
||||||
|
|
||||||
job = self.server.getJobByID(job_id)
|
job = self.server.getJobID(job_id)
|
||||||
if job:
|
if job:
|
||||||
if job_frame != -1:
|
if job_frame != -1:
|
||||||
frame = job[frame]
|
frame = job[frame]
|
||||||
@ -279,21 +264,21 @@ class RenderHandler(http.server.BaseHTTPRequestHandler):
|
|||||||
for job in self.server:
|
for job in self.server:
|
||||||
message.append(job.serialize())
|
message.append(job.serialize())
|
||||||
|
|
||||||
|
|
||||||
|
self.server.stats("", "Sending status")
|
||||||
self.send_head()
|
self.send_head()
|
||||||
self.wfile.write(bytes(repr(message), encoding='utf8'))
|
self.wfile.write(bytes(repr(message), encoding='utf8'))
|
||||||
|
|
||||||
# =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
|
# =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
|
||||||
elif self.path == "/job":
|
elif self.path == "/job":
|
||||||
self.server.update()
|
self.server.balance()
|
||||||
|
|
||||||
slave_id = self.headers['slave-id']
|
slave_id = self.headers['slave-id']
|
||||||
|
|
||||||
print("slave-id", slave_id)
|
slave = self.server.getSeenSlave(slave_id)
|
||||||
|
|
||||||
slave = self.server.updateSlave(slave_id)
|
|
||||||
|
|
||||||
if slave: # only if slave id is valid
|
if slave: # only if slave id is valid
|
||||||
job, frames = self.server.getNewJob(slave_id)
|
job, frames = self.server.newDispatch(slave_id)
|
||||||
|
|
||||||
if job and frames:
|
if job and frames:
|
||||||
for f in frames:
|
for f in frames:
|
||||||
@ -310,9 +295,12 @@ class RenderHandler(http.server.BaseHTTPRequestHandler):
|
|||||||
|
|
||||||
self.wfile.write(bytes(repr(message), encoding='utf8'))
|
self.wfile.write(bytes(repr(message), encoding='utf8'))
|
||||||
|
|
||||||
self.server.stats("", "Sending job frame to render node")
|
self.server.stats("", "Sending job to slave")
|
||||||
else:
|
else:
|
||||||
# no job available, return error code
|
# no job available, return error code
|
||||||
|
slave.job = None
|
||||||
|
slave.job_frames = []
|
||||||
|
|
||||||
self.send_head(http.client.ACCEPTED)
|
self.send_head(http.client.ACCEPTED)
|
||||||
else: # invalid slave id
|
else: # invalid slave id
|
||||||
self.send_head(http.client.NO_CONTENT)
|
self.send_head(http.client.NO_CONTENT)
|
||||||
@ -320,21 +308,19 @@ class RenderHandler(http.server.BaseHTTPRequestHandler):
|
|||||||
elif self.path == "/file":
|
elif self.path == "/file":
|
||||||
slave_id = self.headers['slave-id']
|
slave_id = self.headers['slave-id']
|
||||||
|
|
||||||
slave = self.server.updateSlave(slave_id)
|
slave = self.server.getSeenSlave(slave_id)
|
||||||
|
|
||||||
if slave: # only if slave id is valid
|
if slave: # only if slave id is valid
|
||||||
job_id = self.headers['job-id']
|
job_id = self.headers['job-id']
|
||||||
job_file = self.headers['job-file']
|
job_file = self.headers['job-file']
|
||||||
print("job:", job_id, "\n")
|
|
||||||
print("file:", job_file, "\n")
|
|
||||||
|
|
||||||
job = self.server.getJobByID(job_id)
|
job = self.server.getJobID(job_id)
|
||||||
|
|
||||||
if job:
|
if job:
|
||||||
render_file = job.files_map.get(job_file, None)
|
render_file = job.files_map.get(job_file, None)
|
||||||
|
|
||||||
if render_file:
|
if render_file:
|
||||||
self.server.stats("", "Sending file to render node")
|
self.server.stats("", "Sending file to slave")
|
||||||
f = open(render_file.filepath, 'rb')
|
f = open(render_file.filepath, 'rb')
|
||||||
|
|
||||||
self.send_head()
|
self.send_head()
|
||||||
@ -350,9 +336,11 @@ class RenderHandler(http.server.BaseHTTPRequestHandler):
|
|||||||
else: # invalid slave id
|
else: # invalid slave id
|
||||||
self.send_head(http.client.NO_CONTENT)
|
self.send_head(http.client.NO_CONTENT)
|
||||||
# =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
|
# =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
|
||||||
elif self.path == "/slave":
|
elif self.path == "/slaves":
|
||||||
message = []
|
message = []
|
||||||
|
|
||||||
|
self.server.stats("", "Sending slaves status")
|
||||||
|
|
||||||
for slave in self.server.slaves:
|
for slave in self.server.slaves:
|
||||||
message.append(slave.serialize())
|
message.append(slave.serialize())
|
||||||
|
|
||||||
@ -370,12 +358,9 @@ class RenderHandler(http.server.BaseHTTPRequestHandler):
|
|||||||
# -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
|
# -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
|
||||||
# =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
|
# =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
|
||||||
def do_POST(self):
|
def do_POST(self):
|
||||||
print(self.path)
|
|
||||||
|
|
||||||
# =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
|
# =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
|
||||||
if self.path == "/job":
|
if self.path == "/job":
|
||||||
print("posting job info")
|
|
||||||
self.server.stats("", "Receiving job")
|
|
||||||
|
|
||||||
length = int(self.headers['content-length'])
|
length = int(self.headers['content-length'])
|
||||||
|
|
||||||
@ -383,8 +368,6 @@ class RenderHandler(http.server.BaseHTTPRequestHandler):
|
|||||||
|
|
||||||
job_id = self.server.nextJobID()
|
job_id = self.server.nextJobID()
|
||||||
|
|
||||||
print(job_info.files)
|
|
||||||
|
|
||||||
job = MRenderJob(job_id, job_info.name, job_info.files, chunks = job_info.chunks, priority = job_info.priority, blacklist = job_info.blacklist)
|
job = MRenderJob(job_id, job_info.name, job_info.files, chunks = job_info.chunks, priority = job_info.priority, blacklist = job_info.blacklist)
|
||||||
|
|
||||||
for frame in job_info.frames:
|
for frame in job_info.frames:
|
||||||
@ -395,16 +378,29 @@ class RenderHandler(http.server.BaseHTTPRequestHandler):
|
|||||||
headers={"job-id": job_id}
|
headers={"job-id": job_id}
|
||||||
|
|
||||||
if job.testStart():
|
if job.testStart():
|
||||||
|
self.server.stats("", "New job, missing files")
|
||||||
self.send_head(headers=headers)
|
self.send_head(headers=headers)
|
||||||
else:
|
else:
|
||||||
|
self.server.stats("", "New job, started")
|
||||||
self.send_head(http.client.ACCEPTED, headers=headers)
|
self.send_head(http.client.ACCEPTED, headers=headers)
|
||||||
# =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
|
# =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
|
||||||
elif self.path == "/cancel":
|
elif self.path == "/cancel":
|
||||||
job_id = self.headers.get('job-id', "")
|
job_id = self.headers.get('job-id', "")
|
||||||
if job_id:
|
|
||||||
print("cancel:", job_id, "\n")
|
job = self.server.getJobID(job_id)
|
||||||
self.server.removeJob(job_id)
|
|
||||||
else: # cancel all jobs
|
if job:
|
||||||
|
self.server.stats("", "Cancelling job")
|
||||||
|
self.server.removeJob(job)
|
||||||
|
self.send_head()
|
||||||
|
else:
|
||||||
|
# no such job id
|
||||||
|
self.send_head(http.client.NO_CONTENT)
|
||||||
|
|
||||||
|
# =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
|
||||||
|
elif self.path == "/clear":
|
||||||
|
# cancel all jobs
|
||||||
|
self.server.stats("", "Clearing jobs")
|
||||||
self.server.clear()
|
self.server.clear()
|
||||||
|
|
||||||
self.send_head()
|
self.send_head()
|
||||||
@ -414,15 +410,25 @@ class RenderHandler(http.server.BaseHTTPRequestHandler):
|
|||||||
job_frame = int(self.headers.get('job-frame', "-1"))
|
job_frame = int(self.headers.get('job-frame', "-1"))
|
||||||
all = bool(self.headers.get('reset-all', "False"))
|
all = bool(self.headers.get('reset-all', "False"))
|
||||||
|
|
||||||
job = self.server.getJobByID(job_id)
|
job = self.server.getJobID(job_id)
|
||||||
|
|
||||||
if job:
|
if job:
|
||||||
if job_frame != -1:
|
if job_frame != -1:
|
||||||
job[job_frame].reset(all)
|
|
||||||
else:
|
|
||||||
job.reset(all)
|
|
||||||
|
|
||||||
|
frame = job[job_frame]
|
||||||
|
if frame:
|
||||||
|
self.server.stats("", "Reset job frame")
|
||||||
|
frame.reset(all)
|
||||||
self.send_head()
|
self.send_head()
|
||||||
|
else:
|
||||||
|
# no such frame
|
||||||
|
self.send_head(http.client.NO_CONTENT)
|
||||||
|
|
||||||
|
else:
|
||||||
|
self.server.stats("", "Reset job")
|
||||||
|
job.reset(all)
|
||||||
|
self.send_head()
|
||||||
|
|
||||||
else: # job not found
|
else: # job not found
|
||||||
self.send_head(http.client.NO_CONTENT)
|
self.send_head(http.client.NO_CONTENT)
|
||||||
# =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
|
# =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
|
||||||
@ -430,6 +436,8 @@ class RenderHandler(http.server.BaseHTTPRequestHandler):
|
|||||||
length = int(self.headers['content-length'])
|
length = int(self.headers['content-length'])
|
||||||
job_frame_string = self.headers['job-frame']
|
job_frame_string = self.headers['job-frame']
|
||||||
|
|
||||||
|
self.server.stats("", "New slave connected")
|
||||||
|
|
||||||
slave_info = netrender.model.RenderSlave.materialize(eval(str(self.rfile.read(length), encoding='utf8')))
|
slave_info = netrender.model.RenderSlave.materialize(eval(str(self.rfile.read(length), encoding='utf8')))
|
||||||
|
|
||||||
slave_id = self.server.addSlave(slave_info.name, self.client_address, slave_info.stats)
|
slave_id = self.server.addSlave(slave_info.name, self.client_address, slave_info.stats)
|
||||||
@ -439,16 +447,17 @@ class RenderHandler(http.server.BaseHTTPRequestHandler):
|
|||||||
elif self.path == "/log":
|
elif self.path == "/log":
|
||||||
slave_id = self.headers['slave-id']
|
slave_id = self.headers['slave-id']
|
||||||
|
|
||||||
slave = self.server.updateSlave(slave_id)
|
slave = self.server.getSeenSlave(slave_id)
|
||||||
|
|
||||||
if slave: # only if slave id is valid
|
if slave: # only if slave id is valid
|
||||||
length = int(self.headers['content-length'])
|
length = int(self.headers['content-length'])
|
||||||
|
|
||||||
log_info = netrender.model.LogFile.materialize(eval(str(self.rfile.read(length), encoding='utf8')))
|
log_info = netrender.model.LogFile.materialize(eval(str(self.rfile.read(length), encoding='utf8')))
|
||||||
|
|
||||||
job = self.server.getJobByID(log_info.job_id)
|
job = self.server.getJobID(log_info.job_id)
|
||||||
|
|
||||||
if job:
|
if job:
|
||||||
|
self.server.stats("", "Log announcement")
|
||||||
job.addLog(log_info.frames)
|
job.addLog(log_info.frames)
|
||||||
self.send_head(http.client.OK)
|
self.send_head(http.client.OK)
|
||||||
else:
|
else:
|
||||||
@ -462,18 +471,16 @@ class RenderHandler(http.server.BaseHTTPRequestHandler):
|
|||||||
# -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
|
# -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
|
||||||
# =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
|
# =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
|
||||||
def do_PUT(self):
|
def do_PUT(self):
|
||||||
print(self.path)
|
|
||||||
|
|
||||||
# =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
|
# =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
|
||||||
if self.path == "/file":
|
if self.path == "/file":
|
||||||
print("writing blend file")
|
|
||||||
self.server.stats("", "Receiving job")
|
self.server.stats("", "Receiving job")
|
||||||
|
|
||||||
length = int(self.headers['content-length'])
|
length = int(self.headers['content-length'])
|
||||||
job_id = self.headers['job-id']
|
job_id = self.headers['job-id']
|
||||||
job_file = self.headers['job-file']
|
job_file = self.headers['job-file']
|
||||||
|
|
||||||
job = self.server.getJobByID(job_id)
|
job = self.server.getJobID(job_id)
|
||||||
|
|
||||||
if job:
|
if job:
|
||||||
|
|
||||||
@ -501,8 +508,10 @@ class RenderHandler(http.server.BaseHTTPRequestHandler):
|
|||||||
render_file.filepath = file_path # set the new path
|
render_file.filepath = file_path # set the new path
|
||||||
|
|
||||||
if job.testStart():
|
if job.testStart():
|
||||||
|
self.server.stats("", "File upload, starting job")
|
||||||
self.send_head(http.client.OK)
|
self.send_head(http.client.OK)
|
||||||
else:
|
else:
|
||||||
|
self.server.stats("", "File upload, file missings")
|
||||||
self.send_head(http.client.ACCEPTED)
|
self.send_head(http.client.ACCEPTED)
|
||||||
else: # invalid file
|
else: # invalid file
|
||||||
self.send_head(http.client.NO_CONTENT)
|
self.send_head(http.client.NO_CONTENT)
|
||||||
@ -510,17 +519,16 @@ class RenderHandler(http.server.BaseHTTPRequestHandler):
|
|||||||
self.send_head(http.client.NO_CONTENT)
|
self.send_head(http.client.NO_CONTENT)
|
||||||
# =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
|
# =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
|
||||||
elif self.path == "/render":
|
elif self.path == "/render":
|
||||||
print("writing result file")
|
|
||||||
self.server.stats("", "Receiving render result")
|
self.server.stats("", "Receiving render result")
|
||||||
|
|
||||||
slave_id = self.headers['slave-id']
|
slave_id = self.headers['slave-id']
|
||||||
|
|
||||||
slave = self.server.updateSlave(slave_id)
|
slave = self.server.getSeenSlave(slave_id)
|
||||||
|
|
||||||
if slave: # only if slave id is valid
|
if slave: # only if slave id is valid
|
||||||
job_id = self.headers['job-id']
|
job_id = self.headers['job-id']
|
||||||
|
|
||||||
job = self.server.getJobByID(job_id)
|
job = self.server.getJobID(job_id)
|
||||||
|
|
||||||
if job:
|
if job:
|
||||||
job_frame = int(self.headers['job-frame'])
|
job_frame = int(self.headers['job-frame'])
|
||||||
@ -529,6 +537,7 @@ class RenderHandler(http.server.BaseHTTPRequestHandler):
|
|||||||
|
|
||||||
frame = job[job_frame]
|
frame = job[job_frame]
|
||||||
|
|
||||||
|
if frame:
|
||||||
if job_result == DONE:
|
if job_result == DONE:
|
||||||
length = int(self.headers['content-length'])
|
length = int(self.headers['content-length'])
|
||||||
buf = self.rfile.read(length)
|
buf = self.rfile.read(length)
|
||||||
@ -541,30 +550,29 @@ class RenderHandler(http.server.BaseHTTPRequestHandler):
|
|||||||
# blacklist slave on this job on error
|
# blacklist slave on this job on error
|
||||||
job.blacklist.append(slave.id)
|
job.blacklist.append(slave.id)
|
||||||
|
|
||||||
slave.job_frames.remove(job_frame)
|
self.server.stats("", "Receiving result")
|
||||||
if not slave.job_frames:
|
|
||||||
slave.job = None
|
slave.finishedFrame(job_frame)
|
||||||
|
|
||||||
frame.status = job_result
|
frame.status = job_result
|
||||||
frame.time = job_time
|
frame.time = job_time
|
||||||
|
|
||||||
job.testFinished()
|
job.testFinished()
|
||||||
|
|
||||||
self.server.updateSlave(self.headers['slave-id'])
|
|
||||||
|
|
||||||
self.send_head()
|
self.send_head()
|
||||||
|
else: # frame not found
|
||||||
|
self.send_head(http.client.NO_CONTENT)
|
||||||
else: # job not found
|
else: # job not found
|
||||||
self.send_head(http.client.NO_CONTENT)
|
self.send_head(http.client.NO_CONTENT)
|
||||||
else: # invalid slave id
|
else: # invalid slave id
|
||||||
self.send_head(http.client.NO_CONTENT)
|
self.send_head(http.client.NO_CONTENT)
|
||||||
# =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
|
# =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
|
||||||
elif self.path == "/log":
|
elif self.path == "/log":
|
||||||
print("writing log file")
|
|
||||||
self.server.stats("", "Receiving log file")
|
self.server.stats("", "Receiving log file")
|
||||||
|
|
||||||
job_id = self.headers['job-id']
|
job_id = self.headers['job-id']
|
||||||
|
|
||||||
job = self.server.getJobByID(job_id)
|
job = self.server.getJobID(job_id)
|
||||||
|
|
||||||
if job:
|
if job:
|
||||||
job_frame = int(self.headers['job-frame'])
|
job_frame = int(self.headers['job-frame'])
|
||||||
@ -580,7 +588,7 @@ class RenderHandler(http.server.BaseHTTPRequestHandler):
|
|||||||
|
|
||||||
del buf
|
del buf
|
||||||
|
|
||||||
self.server.updateSlave(self.headers['slave-id'])
|
self.server.getSeenSlave(self.headers['slave-id'])
|
||||||
|
|
||||||
self.send_head()
|
self.send_head()
|
||||||
else: # frame not found
|
else: # frame not found
|
||||||
@ -600,10 +608,7 @@ class RenderMasterServer(http.server.HTTPServer):
|
|||||||
|
|
||||||
self.slave_timeout = 2
|
self.slave_timeout = 2
|
||||||
|
|
||||||
self.first_usage = True
|
|
||||||
|
|
||||||
self.balancer = netrender.balancing.Balancer()
|
self.balancer = netrender.balancing.Balancer()
|
||||||
#self.balancer.addRule(netrender.balancing.RatingCredit())
|
|
||||||
self.balancer.addRule(netrender.balancing.RatingUsage())
|
self.balancer.addRule(netrender.balancing.RatingUsage())
|
||||||
self.balancer.addException(netrender.balancing.ExcludeQueuedEmptyJob())
|
self.balancer.addException(netrender.balancing.ExcludeQueuedEmptyJob())
|
||||||
self.balancer.addException(netrender.balancing.ExcludeSlavesLimit(self.countJobs, self.countSlaves, limit = 0.9))
|
self.balancer.addException(netrender.balancing.ExcludeSlavesLimit(self.countJobs, self.countSlaves, limit = 0.9))
|
||||||
@ -631,7 +636,7 @@ class RenderMasterServer(http.server.HTTPServer):
|
|||||||
def getSlave(self, slave_id):
|
def getSlave(self, slave_id):
|
||||||
return self.slaves_map.get(slave_id, None)
|
return self.slaves_map.get(slave_id, None)
|
||||||
|
|
||||||
def updateSlave(self, slave_id):
|
def getSeenSlave(self, slave_id):
|
||||||
slave = self.getSlave(slave_id)
|
slave = self.getSlave(slave_id)
|
||||||
if slave:
|
if slave:
|
||||||
slave.seen()
|
slave.seen()
|
||||||
@ -655,18 +660,12 @@ class RenderMasterServer(http.server.HTTPServer):
|
|||||||
self.removeSlave(slave)
|
self.removeSlave(slave)
|
||||||
|
|
||||||
def updateUsage(self):
|
def updateUsage(self):
|
||||||
m = 1.0
|
blend = 0.5
|
||||||
|
|
||||||
if not self.first_usage:
|
|
||||||
for job in self.jobs:
|
for job in self.jobs:
|
||||||
job.usage *= 0.5
|
job.usage *= (1 - blend)
|
||||||
|
|
||||||
m = 0.5
|
|
||||||
else:
|
|
||||||
self.first_usage = False
|
|
||||||
|
|
||||||
if self.slaves:
|
if self.slaves:
|
||||||
slave_usage = m / self.countSlaves()
|
slave_usage = blend / self.countSlaves()
|
||||||
|
|
||||||
for slave in self.slaves:
|
for slave in self.slaves:
|
||||||
if slave.job:
|
if slave.job:
|
||||||
@ -679,9 +678,7 @@ class RenderMasterServer(http.server.HTTPServer):
|
|||||||
for job in removed:
|
for job in removed:
|
||||||
self.removeJob(job)
|
self.removeJob(job)
|
||||||
|
|
||||||
def update(self):
|
def balance(self):
|
||||||
for job in self.jobs:
|
|
||||||
job.update()
|
|
||||||
self.balancer.balance(self.jobs)
|
self.balancer.balance(self.jobs)
|
||||||
|
|
||||||
def countJobs(self, status = JOB_QUEUED):
|
def countJobs(self, status = JOB_QUEUED):
|
||||||
@ -695,11 +692,9 @@ class RenderMasterServer(http.server.HTTPServer):
|
|||||||
def countSlaves(self):
|
def countSlaves(self):
|
||||||
return len(self.slaves)
|
return len(self.slaves)
|
||||||
|
|
||||||
def removeJob(self, id):
|
def removeJob(self, job):
|
||||||
job = self.jobs_map.pop(id)
|
|
||||||
|
|
||||||
if job:
|
|
||||||
self.jobs.remove(job)
|
self.jobs.remove(job)
|
||||||
|
self.jobs_map.pop(job.id)
|
||||||
|
|
||||||
for slave in self.slaves:
|
for slave in self.slaves:
|
||||||
if slave.job == job:
|
if slave.job == job:
|
||||||
@ -717,14 +712,14 @@ class RenderMasterServer(http.server.HTTPServer):
|
|||||||
|
|
||||||
job.save()
|
job.save()
|
||||||
|
|
||||||
def getJobByID(self, id):
|
def getJobID(self, id):
|
||||||
return self.jobs_map.get(id, None)
|
return self.jobs_map.get(id, None)
|
||||||
|
|
||||||
def __iter__(self):
|
def __iter__(self):
|
||||||
for job in self.jobs:
|
for job in self.jobs:
|
||||||
yield job
|
yield job
|
||||||
|
|
||||||
def getNewJob(self, slave_id):
|
def newDispatch(self, slave_id):
|
||||||
if self.jobs:
|
if self.jobs:
|
||||||
for job in self.jobs:
|
for job in self.jobs:
|
||||||
if not self.balancer.applyExceptions(job) and slave_id not in job.blacklist:
|
if not self.balancer.applyExceptions(job) and slave_id not in job.blacklist:
|
||||||
|
@ -55,7 +55,6 @@ def get(handler):
|
|||||||
headerTable(
|
headerTable(
|
||||||
"name",
|
"name",
|
||||||
"priority",
|
"priority",
|
||||||
"credits",
|
|
||||||
"usage",
|
"usage",
|
||||||
"wait",
|
"wait",
|
||||||
"length",
|
"length",
|
||||||
@ -66,14 +65,13 @@ def get(handler):
|
|||||||
"exception"
|
"exception"
|
||||||
)
|
)
|
||||||
|
|
||||||
handler.server.update()
|
handler.server.balance()
|
||||||
|
|
||||||
for job in handler.server.jobs:
|
for job in handler.server.jobs:
|
||||||
results = job.framesStatus()
|
results = job.framesStatus()
|
||||||
rowTable(
|
rowTable(
|
||||||
link(job.name, "/html/job" + job.id),
|
link(job.name, "/html/job" + job.id),
|
||||||
job.priority,
|
job.priority,
|
||||||
round(job.credits, 1),
|
|
||||||
"%0.1f%%" % (job.usage * 100),
|
"%0.1f%%" % (job.usage * 100),
|
||||||
"%is" % int(time.time() - job.last_dispatched),
|
"%is" % int(time.time() - job.last_dispatched),
|
||||||
len(job),
|
len(job),
|
||||||
@ -92,7 +90,7 @@ def get(handler):
|
|||||||
|
|
||||||
output("<html><head><title>NetRender</title></head><body>")
|
output("<html><head><title>NetRender</title></head><body>")
|
||||||
|
|
||||||
job = handler.server.getJobByID(job_id)
|
job = handler.server.getJobID(job_id)
|
||||||
|
|
||||||
if job:
|
if job:
|
||||||
output("<h2>Frames</h2>")
|
output("<h2>Frames</h2>")
|
||||||
@ -119,7 +117,7 @@ def get(handler):
|
|||||||
job_id = match.groups()[0]
|
job_id = match.groups()[0]
|
||||||
frame_number = int(match.groups()[1])
|
frame_number = int(match.groups()[1])
|
||||||
|
|
||||||
job = handler.server.getJobByID(job_id)
|
job = handler.server.getJobID(job_id)
|
||||||
|
|
||||||
if job:
|
if job:
|
||||||
frame = job[frame_number]
|
frame = job[frame_number]
|
||||||
|
@ -80,7 +80,6 @@ class RenderJob:
|
|||||||
self.frames = []
|
self.frames = []
|
||||||
self.chunks = 0
|
self.chunks = 0
|
||||||
self.priority = 0
|
self.priority = 0
|
||||||
self.credits = 0
|
|
||||||
self.usage = 0.0
|
self.usage = 0.0
|
||||||
self.blacklist = []
|
self.blacklist = []
|
||||||
self.last_dispatched = 0.0
|
self.last_dispatched = 0.0
|
||||||
@ -145,7 +144,6 @@ class RenderJob:
|
|||||||
"chunks": self.chunks,
|
"chunks": self.chunks,
|
||||||
"priority": self.priority,
|
"priority": self.priority,
|
||||||
"usage": self.usage,
|
"usage": self.usage,
|
||||||
"credits": self.credits,
|
|
||||||
"blacklist": self.blacklist,
|
"blacklist": self.blacklist,
|
||||||
"last_dispatched": self.last_dispatched
|
"last_dispatched": self.last_dispatched
|
||||||
}
|
}
|
||||||
@ -163,7 +161,6 @@ class RenderJob:
|
|||||||
job.chunks = data["chunks"]
|
job.chunks = data["chunks"]
|
||||||
job.priority = data["priority"]
|
job.priority = data["priority"]
|
||||||
job.usage = data["usage"]
|
job.usage = data["usage"]
|
||||||
job.credits = data["credits"]
|
|
||||||
job.blacklist = data["blacklist"]
|
job.blacklist = data["blacklist"]
|
||||||
job.last_dispatched = data["last_dispatched"]
|
job.last_dispatched = data["last_dispatched"]
|
||||||
|
|
||||||
|
@ -205,7 +205,7 @@ class RENDER_OT_netclientslaves(bpy.types.Operator):
|
|||||||
conn = clientConnection(context.scene)
|
conn = clientConnection(context.scene)
|
||||||
|
|
||||||
if conn:
|
if conn:
|
||||||
conn.request("GET", "/slave")
|
conn.request("GET", "/slaves")
|
||||||
|
|
||||||
response = conn.getresponse()
|
response = conn.getresponse()
|
||||||
print( response.status, response.reason )
|
print( response.status, response.reason )
|
||||||
@ -289,7 +289,7 @@ class RENDER_OT_netclientcancelall(bpy.types.Operator):
|
|||||||
conn = clientConnection(context.scene)
|
conn = clientConnection(context.scene)
|
||||||
|
|
||||||
if conn:
|
if conn:
|
||||||
conn.request("POST", "/cancel")
|
conn.request("POST", "/clear")
|
||||||
|
|
||||||
response = conn.getresponse()
|
response = conn.getresponse()
|
||||||
print( response.status, response.reason )
|
print( response.status, response.reason )
|
||||||
|
@ -32,8 +32,8 @@ def slave_Info():
|
|||||||
slave.stats = sysname + " " + release + " " + machine + " " + processor
|
slave.stats = sysname + " " + release + " " + machine + " " + processor
|
||||||
return slave
|
return slave
|
||||||
|
|
||||||
def testCancel(conn, job_id):
|
def testCancel(conn, job_id, frame_number):
|
||||||
conn.request("HEAD", "/status", headers={"job-id":job_id})
|
conn.request("HEAD", "/status", headers={"job-id":job_id, "job-frame": str(frame_number)})
|
||||||
response = conn.getresponse()
|
response = conn.getresponse()
|
||||||
|
|
||||||
# cancelled if job isn't found anymore
|
# cancelled if job isn't found anymore
|
||||||
@ -152,7 +152,7 @@ def render_slave(engine, scene):
|
|||||||
stdout = bytes()
|
stdout = bytes()
|
||||||
|
|
||||||
run_t = current_t
|
run_t = current_t
|
||||||
if testCancel(conn, job.id):
|
if testCancel(conn, job.id, first_frame):
|
||||||
cancelled = True
|
cancelled = True
|
||||||
|
|
||||||
if cancelled:
|
if cancelled:
|
||||||
|
Loading…
Reference in New Issue
Block a user