Revision: 23357
          
http://projects.blender.org/plugins/scmsvn/viewcvs.php?view=rev&root=bf-blender&revision=23357
Author:   theeth
Date:     2009-09-20 00:11:26 +0200 (Sun, 20 Sep 2009)

Log Message:
-----------
netrender: first draft for job balancer + some minor fixes

Modified Paths:
--------------
    trunk/blender/release/io/netrender/__init__.py
    trunk/blender/release/io/netrender/client.py
    trunk/blender/release/io/netrender/master.py
    trunk/blender/release/io/netrender/model.py
    trunk/blender/release/io/netrender/operators.py
    trunk/blender/release/io/netrender/slave.py
    trunk/blender/release/io/netrender/utils.py

Added Paths:
-----------
    trunk/blender/release/io/netrender/balancing.py

Modified: trunk/blender/release/io/netrender/__init__.py
===================================================================
--- trunk/blender/release/io/netrender/__init__.py      2009-09-19 22:02:15 UTC 
(rev 23356)
+++ trunk/blender/release/io/netrender/__init__.py      2009-09-19 22:11:26 UTC 
(rev 23357)
@@ -6,6 +6,7 @@
 import slave
 import master
 import utils
+import balancing
 import ui
 
 # store temp data in bpy module

Added: trunk/blender/release/io/netrender/balancing.py
===================================================================
--- trunk/blender/release/io/netrender/balancing.py                             
(rev 0)
+++ trunk/blender/release/io/netrender/balancing.py     2009-09-19 22:11:26 UTC 
(rev 23357)
@@ -0,0 +1,75 @@
+import time
+
+from netrender.utils import *
+import netrender.model
+
+class RatingRule:
+       def rate(self, job):
+               return 0
+
+class ExclusionRule:
+       def test(self, job):
+               return False
+
+class PriorityRule:
+       def test(self, job):
+               return False
+
+class Balancer:
+       def __init__(self):
+               self.rules = []
+               self.priorities = []
+               self.exceptions = []
+       
+       def addRule(self, rule):
+               self.rules.append(rule)
+       
+       def addPriority(self, priority):
+               self.priorities.append(priority)
+               
+       def addException(self, exception):
+               self.exceptions.append(exception)
+       
+       def applyRules(self, job):
+               return sum((rule.rate(job) for rule in self.rules))
+       
+       def applyPriorities(self, job):
+               for priority in self.priorities:
+                       if priority.test(job):
+                               return True # priorities are first
+               
+               return False
+       
+       def applyExceptions(self, job):
+               for exception in self.exceptions:
+                       if exception.test(job):
+                               return True # exceptions are last
+                       
+               return False
+       
+       def sortKey(self, job):
+               return (1 if self.applyExceptions(job) else 0, # exceptions 
after
+                                               0 if self.applyPriorities(job) 
else 1, # priorities first
+                                               self.applyRules(job))
+       
+       def balance(self, jobs):
+               if jobs:
+                       jobs.sort(key=self.sortKey)
+                       return jobs[0]
+               else:
+                       return None
+       
+# ==========================
+
+
+class RatingCredit(RatingRule):
+       def rate(self, job):
+               return -job.credits # more credit is better (sort at first in 
list)
+
+class NewJobPriority(PriorityRule):
+       def test(self, job):
+               return job.countFrames(status = DISPATCHED) == 0
+
+class ExcludeQueuedEmptyJob(ExclusionRule):
+       def test(self, job):
+               return job.status != JOB_QUEUED or job.countFrames(status = 
QUEUED) == 0


Property changes on: trunk/blender/release/io/netrender/balancing.py
___________________________________________________________________
Name: svn:keywords
   + Author Date Id Revision
Name: svn:eol-style
   + native

Modified: trunk/blender/release/io/netrender/client.py
===================================================================
--- trunk/blender/release/io/netrender/client.py        2009-09-19 22:02:15 UTC 
(rev 23356)
+++ trunk/blender/release/io/netrender/client.py        2009-09-19 22:11:26 UTC 
(rev 23357)
@@ -103,7 +103,7 @@
        job.priority = netsettings.priority
        
        # try to send path first
-       conn.request("POST", "job", repr(job.serialize()))
+       conn.request("POST", "/job", repr(job.serialize()))
        response = conn.getresponse()
        
        job_id = response.getheader("job-id")
@@ -112,7 +112,7 @@
        if response.status == http.client.ACCEPTED:
                for filepath, start, end in job.files:
                        f = open(filepath, "rb")
-                       conn.request("PUT", "file", f, headers={"job-id": 
job_id, "job-file": filepath})
+                       conn.request("PUT", "/file", f, headers={"job-id": 
job_id, "job-file": filepath})
                        f.close()
                        response = conn.getresponse()
        
@@ -121,7 +121,7 @@
        return job_id
 
 def requestResult(conn, job_id, frame):
-       conn.request("GET", "render", headers={"job-id": job_id, 
"job-frame":str(frame)})
+       conn.request("GET", "/render", headers={"job-id": job_id, 
"job-frame":str(frame)})
 
 @rnaType
 class NetworkRenderEngine(bpy.types.RenderEngine):
@@ -174,7 +174,6 @@
                                requestResult(conn, job_id, scene.current_frame)
                        
                        while response.status == http.client.ACCEPTED and not 
self.test_break():
-                               print("waiting")
                                time.sleep(1)
                                requestResult(conn, job_id, scene.current_frame)
                                response = conn.getresponse()

Modified: trunk/blender/release/io/netrender/master.py
===================================================================
--- trunk/blender/release/io/netrender/master.py        2009-09-19 22:02:15 UTC 
(rev 23356)
+++ trunk/blender/release/io/netrender/master.py        2009-09-19 22:11:26 UTC 
(rev 23357)
@@ -4,11 +4,8 @@
 
 from netrender.utils import *
 import netrender.model
+import netrender.balancing
 
-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, start, end):
                self.filepath = filepath
@@ -38,10 +35,6 @@
        def seen(self):
                self.last_seen = time.time()
 
-# sorting key for jobs
-def groupKey(job):
-       return (job.status, job.framesLeft() > 0, job.priority, job.credits)
-
 class MRenderJob(netrender.model.RenderJob):
        def __init__(self, job_id, name, files, chunks = 1, priority = 1, 
credits = 100.0, blacklist = []):
                super().__init__()
@@ -95,15 +88,7 @@
                frame = MRenderFrame(frame_number)
                self.frames.append(frame)
                return frame
-       
-       def framesLeft(self):
-               total = 0
-               for j in self.frames:
-                       if j.status == QUEUED:
-                               total += 1
                
-               return total
-               
        def reset(self, all):
                for f in self.frames:
                        f.reset(all)
@@ -153,7 +138,7 @@
        def do_HEAD(self):
                print(self.path)
        
-               if self.path == "status":
+               if self.path == "/status":
                        job_id = self.headers.get('job-id', "")
                        job_frame = int(self.headers.get('job-frame', -1))
                        
@@ -185,12 +170,12 @@
        def do_GET(self):
                print(self.path)
                
-               if self.path == "version":
+               if self.path == "/version":
                        self.send_head()
                        self.server.stats("", "New client connection")
                        self.wfile.write(VERSION)
                # 
=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
-               elif self.path == "render":
+               elif self.path == "/render":
                        job_id = self.headers['job-id']
                        job_frame = int(self.headers['job-frame'])
                        print("render:", job_id, job_frame)
@@ -221,7 +206,7 @@
                                # no such job id
                                self.send_head(http.client.NO_CONTENT)
                # 
=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
-               elif self.path == "log":
+               elif self.path == "/log":
                        job_id = self.headers['job-id']
                        job_frame = int(self.headers['job-frame'])
                        print("log:", job_id, job_frame)
@@ -250,7 +235,7 @@
                                # no such job id
                                self.send_head(http.client.NO_CONTENT)
                # 
=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
-               elif self.path == "status":
+               elif self.path == "/status":
                        job_id = self.headers.get('job-id', "")
                        job_frame = int(self.headers.get('job-frame', -1))
                        
@@ -284,7 +269,7 @@
                        self.wfile.write(bytes(repr(message), encoding='utf8'))
                        
                # 
=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
-               elif self.path == "job":
+               elif self.path == "/job":
                        self.server.update()
                        
                        slave_id = self.headers['slave-id']
@@ -315,7 +300,7 @@
                        else: # invalid slave id
                                self.send_head(http.client.NO_CONTENT)
                # 
=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
-               elif self.path == "file":
+               elif self.path == "/file":
                        slave_id = self.headers['slave-id']
                        
                        slave = self.server.updateSlave(slave_id)
@@ -348,7 +333,7 @@
                        else: # invalid slave id
                                self.send_head(http.client.NO_CONTENT)
                # 
=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
-               elif self.path == "slave":
+               elif self.path == "/slave":
                        message = []
                        
                        for slave in self.server.slaves:
@@ -368,7 +353,7 @@
                print(self.path)
        
                # 
=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
-               if self.path == "job":
+               if self.path == "/job":
                        print("posting job info")
                        self.server.stats("", "Receiving job")
                        
@@ -394,7 +379,7 @@
                        else:
                                self.send_head(http.client.ACCEPTED, 
headers=headers)
                # 
=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
-               elif self.path == "cancel":
+               elif self.path == "/cancel":
                        job_id = self.headers.get('job-id', "")
                        if job_id:
                                print("cancel:", job_id, "\n")
@@ -404,7 +389,7 @@
                                
                        self.send_head()
                # 
=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
-               elif self.path == "reset":
+               elif self.path == "/reset":
                        job_id = self.headers.get('job-id', "")
                        job_frame = int(self.headers.get('job-frame', "-1"))
                        all = bool(self.headers.get('reset-all', "False"))
@@ -421,7 +406,7 @@
                        else: # job not found
                                self.send_head(http.client.NO_CONTENT)
                # 
=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
-               elif self.path == "slave":
+               elif self.path == "/slave":
                        length = int(self.headers['content-length'])
                        job_frame_string = self.headers['job-frame']
                        
@@ -431,7 +416,7 @@
                        
                        self.send_head(headers = {"slave-id": slave_id})
                # 
=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
-               elif self.path == "log":
+               elif self.path == "/log":
                        slave_id = self.headers['slave-id']
                        
                        slave = self.server.updateSlave(slave_id)
@@ -460,7 +445,7 @@
                print(self.path)
                
                # 
=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
-               if self.path == "file":
+               if self.path == "/file":
                        print("writing blend file")
                        self.server.stats("", "Receiving job")
                        
@@ -504,7 +489,7 @@
                        else: # job not found
                                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")
                        
@@ -547,7 +532,7 @@
                        else: # invalid slave id
                                self.send_head(http.client.NO_CONTENT)
                # 
=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
-               elif self.path == "log":

@@ Diff output truncated at 10240 characters. @@

_______________________________________________
Bf-blender-cvs mailing list
[email protected]
http://lists.blender.org/mailman/listinfo/bf-blender-cvs

Reply via email to