| 
									
										
										
										
											2009-11-01 15:21:20 +00:00
										 |  |  | # ##### BEGIN GPL LICENSE BLOCK ##### | 
					
						
							|  |  |  | # | 
					
						
							|  |  |  | #  This program is free software; you can redistribute it and/or | 
					
						
							|  |  |  | #  modify it under the terms of the GNU General Public License | 
					
						
							|  |  |  | #  as published by the Free Software Foundation; either version 2 | 
					
						
							|  |  |  | #  of the License, or (at your option) any later version. | 
					
						
							| 
									
										
										
										
											2009-12-29 00:04:57 +00:00
										 |  |  | # | 
					
						
							| 
									
										
										
										
											2009-11-01 15:21:20 +00:00
										 |  |  | #  This program is distributed in the hope that it will be useful, | 
					
						
							|  |  |  | #  but WITHOUT ANY WARRANTY; without even the implied warranty of | 
					
						
							|  |  |  | #  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | 
					
						
							|  |  |  | #  GNU General Public License for more details. | 
					
						
							| 
									
										
										
										
											2009-12-29 00:04:57 +00:00
										 |  |  | # | 
					
						
							| 
									
										
										
										
											2009-11-01 15:21:20 +00:00
										 |  |  | #  You should have received a copy of the GNU General Public License | 
					
						
							|  |  |  | #  along with this program; if not, write to the Free Software Foundation, | 
					
						
							|  |  |  | #  Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA. | 
					
						
							|  |  |  | # | 
					
						
							|  |  |  | # ##### END GPL LICENSE BLOCK ##### | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-09-19 22:11:26 +00:00
										 |  |  | import time | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | from netrender.utils import * | 
					
						
							|  |  |  | import netrender.model | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | class RatingRule: | 
					
						
							| 
									
										
										
										
											2009-12-31 19:11:46 +00:00
										 |  |  |     def __init__(self): | 
					
						
							|  |  |  |         self.enabled = True | 
					
						
							|  |  |  |          | 
					
						
							| 
									
										
										
										
											2009-12-29 00:04:57 +00:00
										 |  |  |     def rate(self, job): | 
					
						
							|  |  |  |         return 0 | 
					
						
							| 
									
										
										
										
											2009-09-19 22:11:26 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | class ExclusionRule: | 
					
						
							| 
									
										
										
										
											2009-12-31 19:11:46 +00:00
										 |  |  |     def __init__(self): | 
					
						
							|  |  |  |         self.enabled = True | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-12-29 00:04:57 +00:00
										 |  |  |     def test(self, job): | 
					
						
							|  |  |  |         return False | 
					
						
							| 
									
										
										
										
											2009-09-19 22:11:26 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | class PriorityRule: | 
					
						
							| 
									
										
										
										
											2009-12-31 19:11:46 +00:00
										 |  |  |     def __init__(self): | 
					
						
							|  |  |  |         self.enabled = True | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-12-29 00:04:57 +00:00
										 |  |  |     def test(self, job): | 
					
						
							|  |  |  |         return False | 
					
						
							| 
									
										
										
										
											2009-09-19 22:11:26 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | class Balancer: | 
					
						
							| 
									
										
										
										
											2009-12-29 00:04:57 +00:00
										 |  |  |     def __init__(self): | 
					
						
							|  |  |  |         self.rules = [] | 
					
						
							|  |  |  |         self.priorities = [] | 
					
						
							|  |  |  |         self.exceptions = [] | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-12-31 19:11:46 +00:00
										 |  |  |     def ruleByID(self, rule_id): | 
					
						
							|  |  |  |         for rule in self.rules: | 
					
						
							|  |  |  |             if id(rule) == rule_id: | 
					
						
							|  |  |  |                 return rule | 
					
						
							|  |  |  |         for rule in self.priorities: | 
					
						
							|  |  |  |             if id(rule) == rule_id: | 
					
						
							|  |  |  |                 return rule | 
					
						
							|  |  |  |         for rule in self.exceptions: | 
					
						
							|  |  |  |             if id(rule) == rule_id: | 
					
						
							|  |  |  |                 return rule | 
					
						
							|  |  |  |          | 
					
						
							|  |  |  |         return None | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-12-29 00:04:57 +00:00
										 |  |  |     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): | 
					
						
							| 
									
										
										
										
											2009-12-31 19:11:46 +00:00
										 |  |  |         return sum((rule.rate(job) for rule in self.rules if rule.enabled)) | 
					
						
							| 
									
										
										
										
											2009-12-29 00:04:57 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |     def applyPriorities(self, job): | 
					
						
							|  |  |  |         for priority in self.priorities: | 
					
						
							| 
									
										
										
										
											2009-12-31 19:11:46 +00:00
										 |  |  |             if priority.enabled and priority.test(job): | 
					
						
							| 
									
										
										
										
											2009-12-29 00:04:57 +00:00
										 |  |  |                 return True # priorities are first | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         return False | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def applyExceptions(self, job): | 
					
						
							|  |  |  |         for exception in self.exceptions: | 
					
						
							| 
									
										
										
										
											2009-12-31 19:11:46 +00:00
										 |  |  |             if exception.enabled and exception.test(job): | 
					
						
							| 
									
										
										
										
											2009-12-29 00:04:57 +00:00
										 |  |  |                 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: | 
					
						
							|  |  |  |             # use inline copy to make sure the list is still accessible while sorting | 
					
						
							|  |  |  |             jobs[:] = sorted(jobs, key=self.sortKey) | 
					
						
							|  |  |  |             return jobs[0] | 
					
						
							|  |  |  |         else: | 
					
						
							|  |  |  |             return None | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-09-19 22:11:26 +00:00
										 |  |  | # ========================== | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-09-24 21:05:54 +00:00
										 |  |  | class RatingUsage(RatingRule): | 
					
						
							| 
									
										
										
										
											2009-12-29 00:04:57 +00:00
										 |  |  |     def __str__(self): | 
					
						
							| 
									
										
										
										
											2009-12-31 19:11:46 +00:00
										 |  |  |         return "Usage per job" | 
					
						
							| 
									
										
										
										
											2009-12-29 00:04:57 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |     def rate(self, job): | 
					
						
							|  |  |  |         # less usage is better | 
					
						
							|  |  |  |         return job.usage / job.priority | 
					
						
							| 
									
										
										
										
											2009-09-19 22:11:26 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-12-10 18:56:21 +00:00
										 |  |  | class RatingUsageByCategory(RatingRule): | 
					
						
							| 
									
										
										
										
											2009-12-29 00:04:57 +00:00
										 |  |  |     def __init__(self, get_jobs): | 
					
						
							| 
									
										
										
										
											2009-12-31 19:11:46 +00:00
										 |  |  |         super().__init__() | 
					
						
							| 
									
										
										
										
											2009-12-29 00:04:57 +00:00
										 |  |  |         self.getJobs = get_jobs | 
					
						
							| 
									
										
										
										
											2009-12-31 19:11:46 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |     def __str__(self): | 
					
						
							|  |  |  |         return "Usage per category" | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-12-29 00:04:57 +00:00
										 |  |  |     def rate(self, job): | 
					
						
							|  |  |  |         total_category_usage = sum([j.usage for j in self.getJobs() if j.category == job.category]) | 
					
						
							|  |  |  |         maximum_priority = max([j.priority for j in self.getJobs() if j.category == job.category]) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         # less usage is better | 
					
						
							|  |  |  |         return total_category_usage / maximum_priority | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-09-19 22:11:26 +00:00
										 |  |  | class NewJobPriority(PriorityRule): | 
					
						
							| 
									
										
										
										
											2009-12-31 19:11:46 +00:00
										 |  |  |     def __init__(self, limit = 1): | 
					
						
							|  |  |  |         super().__init__() | 
					
						
							|  |  |  |         self.limit = limit | 
					
						
							|  |  |  |      | 
					
						
							|  |  |  |     def setLimit(self, value): | 
					
						
							|  |  |  |         self.limit = int(value) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-12-29 00:04:57 +00:00
										 |  |  |     def str_limit(self): | 
					
						
							|  |  |  |         return "less than %i frame%s done" % (self.limit, "s" if self.limit > 1 else "") | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def __str__(self): | 
					
						
							|  |  |  |         return "Priority to new jobs" | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def test(self, job): | 
					
						
							|  |  |  |         return job.countFrames(status = DONE) < self.limit | 
					
						
							| 
									
										
										
										
											2009-09-21 16:01:31 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | class MinimumTimeBetweenDispatchPriority(PriorityRule): | 
					
						
							| 
									
										
										
										
											2009-12-31 19:11:46 +00:00
										 |  |  |     def __init__(self, limit = 10): | 
					
						
							|  |  |  |         super().__init__() | 
					
						
							|  |  |  |         self.limit = limit | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def setLimit(self, value): | 
					
						
							|  |  |  |         self.limit = int(value) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-12-29 00:04:57 +00:00
										 |  |  |     def str_limit(self): | 
					
						
							|  |  |  |         return "more than %i minute%s since last" % (self.limit, "s" if self.limit > 1 else "") | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def __str__(self): | 
					
						
							|  |  |  |         return "Priority to jobs that haven't been dispatched recently" | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def test(self, job): | 
					
						
							|  |  |  |         return job.countFrames(status = DISPATCHED) == 0 and (time.time() - job.last_dispatched) / 60 > self.limit | 
					
						
							| 
									
										
										
										
											2009-09-19 22:11:26 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | class ExcludeQueuedEmptyJob(ExclusionRule): | 
					
						
							| 
									
										
										
										
											2009-12-29 00:04:57 +00:00
										 |  |  |     def __str__(self): | 
					
						
							| 
									
										
										
										
											2010-01-07 18:54:47 +00:00
										 |  |  |         return "Exclude non queued or empty jobs" | 
					
						
							| 
									
										
										
										
											2009-12-29 00:04:57 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |     def test(self, job): | 
					
						
							|  |  |  |         return job.status != JOB_QUEUED or job.countFrames(status = QUEUED) == 0 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-09-21 16:01:31 +00:00
										 |  |  | class ExcludeSlavesLimit(ExclusionRule): | 
					
						
							| 
									
										
										
										
											2009-12-31 19:11:46 +00:00
										 |  |  |     def __init__(self, count_jobs, count_slaves, limit = 0.75): | 
					
						
							|  |  |  |         super().__init__() | 
					
						
							|  |  |  |         self.count_jobs = count_jobs | 
					
						
							|  |  |  |         self.count_slaves = count_slaves | 
					
						
							|  |  |  |         self.limit = limit | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def setLimit(self, value): | 
					
						
							|  |  |  |         self.limit = float(value) | 
					
						
							|  |  |  |          | 
					
						
							| 
									
										
										
										
											2009-12-29 00:04:57 +00:00
										 |  |  |     def str_limit(self): | 
					
						
							|  |  |  |         return "more than %.0f%% of all slaves" % (self.limit * 100) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def __str__(self): | 
					
						
							|  |  |  |         return "Exclude jobs that would use too many slaves" | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def test(self, job): | 
					
						
							|  |  |  |         return not ( self.count_jobs() == 1 or self.count_slaves() <= 1 or float(job.countSlaves() + 1) / self.count_slaves() <= self.limit ) |