Skip to content
Snippets Groups Projects
model.py 10.6 KiB
Newer Older
  • Learn to ignore specific revisions
  • # ##### 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.
    #
    #  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.
    #
    #  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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
    #
    # ##### END GPL LICENSE BLOCK #####
    
    import sys, os
    import http, http.client, http.server, urllib
    import subprocess, shutil, time, hashlib
    
    import netrender.versioning as versioning
    from netrender.utils import *
    
    class LogFile:
        def __init__(self, job_id = 0, slave_id = 0, frames = []):
            self.job_id = job_id
            self.slave_id = slave_id
            self.frames = frames
    
        def serialize(self):
            return 	{
                                "job_id": self.job_id,
                                "slave_id": self.slave_id,
                                "frames": self.frames
                            }
    
        @staticmethod
        def materialize(data):
            if not data:
                return None
    
            logfile = LogFile()
            logfile.job_id = data["job_id"]
            logfile.slave_id = data["slave_id"]
            logfile.frames = data["frames"]
    
            return logfile
    
    class RenderSlave:
        _slave_map = {}
    
        def __init__(self):
            self.id = ""
            self.name = ""
            self.address = ("",0)
            self.stats = ""
            self.total_done = 0
            self.total_error = 0
            self.last_seen = 0.0
    
        def serialize(self):
            return 	{
                                "id": self.id,
                                "name": self.name,
                                "address": self.address,
                                "stats": self.stats,
                                "total_done": self.total_done,
                                "total_error": self.total_error,
                                "last_seen": self.last_seen
                            }
    
        @staticmethod
        def materialize(data, cache = True):
            if not data:
                return None
    
            slave_id = data["id"]
    
            if cache and slave_id in RenderSlave._slave_map:
                return RenderSlave._slave_map[slave_id]
    
            slave = RenderSlave()
            slave.id = slave_id
            slave.name = data["name"]
            slave.address = data["address"]
            slave.stats = data["stats"]
            slave.total_done = data["total_done"]
            slave.total_error = data["total_error"]
            slave.last_seen = data["last_seen"]
    
            if cache:
                RenderSlave._slave_map[slave_id] = slave
    
            return slave
    
    JOB_BLENDER = 1
    JOB_PROCESS = 2
    JOB_VCS     = 3
    
    JOB_TYPES = {
                    JOB_BLENDER: "Blender",
                    JOB_PROCESS: "Process",
                    JOB_VCS:     "Versioned",
                }
    
    class VersioningInfo:
        def __init__(self, info = None):
            self._system = None
            self.wpath = ""
            self.rpath = ""
            self.revision = ""
            
        @property
        def system(self):
            return self._system
    
        @system.setter
        def system(self, value):
            self._system = versioning.SYSTEMS[value]
    
        def update(self):
            self.system.update(self)
        
        def serialize(self):
            return {
                    "wpath": self.wpath,
                    "rpath": self.rpath,
                    "revision": self.revision,
                    "system": self.system.name
                    }
            
        @staticmethod
        def generate(system, path):
            vs = VersioningInfo()
            vs.wpath = path
            vs.system = system
    
            vs.rpath = vs.system.path(path)
            vs.revision = vs.system.revision(path)
            
            return vs
            
            
        @staticmethod
        def materialize(data):
            if not data:
                return None
            
            vs = VersioningInfo()
            vs.wpath = data["wpath"]
            vs.rpath = data["rpath"]
            vs.revision = data["revision"]
            vs.system = data["system"]
            
            return vs
            
    
    class RenderFile:
        def __init__(self, filepath = "", index = 0, start = -1, end = -1, signature=0):
            self.filepath = filepath
            self.original_path = filepath
            self.signature = signature
            self.index = index
            self.start = start
            self.end = end
    
        def serialize(self):
            return 	{
                        "filepath": self.filepath,
                        "original_path": self.original_path,
                        "index": self.index,
                        "start": self.start,
                        "end": self.end,
                        "signature": self.signature
                    }
    
        @staticmethod
        def materialize(data):
            if not data:
                return None
    
            rfile = RenderFile(data["filepath"], data["index"], data["start"], data["end"], data["signature"])
            rfile.original_path = data["original_path"]
    
            return rfile
    
    class RenderJob:
        def __init__(self, job_info = None):
            self.id = ""
            self.type = JOB_BLENDER
            self.name = ""
            self.category = "None"
            self.status = JOB_WAITING
            self.files = []
            self.chunks = 0
            self.priority = 0
            self.blacklist = []
            
            self.version_info = None
            
            self.resolution = None
    
            self.usage = 0.0
            self.last_dispatched = 0.0
            self.frames = []
    
            if job_info:
                self.type = job_info.type
                self.name = job_info.name
                self.category = job_info.category
                self.status = job_info.status
                self.files = job_info.files
                self.chunks = job_info.chunks
                self.priority = job_info.priority
                self.blacklist = job_info.blacklist
                self.version_info = job_info.version_info
    
        def hasRenderResult(self):
            return self.type in (JOB_BLENDER, JOB_VCS)
    
        def rendersWithBlender(self):
            return self.type in (JOB_BLENDER, JOB_VCS)
    
        def addFile(self, file_path, start=-1, end=-1, signed=True):
            if signed:
                signature = hashFile(file_path)
            else:
                signature = None
            self.files.append(RenderFile(file_path, len(self.files), start, end, signature))
    
        def addFrame(self, frame_number, command = ""):
            frame = RenderFrame(frame_number, command)
            self.frames.append(frame)
            return frame
    
        def __len__(self):
            return len(self.frames)
    
        def countFrames(self, status=QUEUED):
            total = 0
            for f in self.frames:
                if f.status == status:
                    total += 1
    
            return total
    
        def countSlaves(self):
            return len(set((frame.slave for frame in self.frames if frame.status == DISPATCHED)))
    
        def statusText(self):
            return JOB_STATUS_TEXT[self.status]
    
        def framesStatus(self):
            results = {
                                    QUEUED: 0,
                                    DISPATCHED: 0,
                                    DONE: 0,
                                    ERROR: 0
                                }
    
            for frame in self.frames:
                results[frame.status] += 1
    
            return results
    
        def __contains__(self, frame_number):
            for f in self.frames:
                if f.number == frame_number:
                    return True
            else:
                return False
    
        def __getitem__(self, frame_number):
            for f in self.frames:
                if f.number == frame_number:
                    return f
            else:
                return None
    
        def serialize(self, frames = None):
            min_frame = min((f.number for f in frames)) if frames else -1
            max_frame = max((f.number for f in frames)) if frames else -1
            return 	{
                                "id": self.id,
                                "type": self.type,
                                "name": self.name,
                                "category": self.category,
                                "status": self.status,
                                "files": [f.serialize() for f in self.files if f.start == -1 or not frames or (f.start <= max_frame and f.end >= min_frame)],
                                "frames": [f.serialize() for f in self.frames if not frames or f in frames],
                                "chunks": self.chunks,
                                "priority": self.priority,
                                "usage": self.usage,
                                "blacklist": self.blacklist,
                                "last_dispatched": self.last_dispatched,
                                "version_info": self.version_info.serialize() if self.version_info else None,
                                "resolution": self.resolution
                            }
    
        @staticmethod
        def materialize(data):
            if not data:
                return None
    
            job = RenderJob()
            job.id = data["id"]
            job.type = data["type"]
            job.name = data["name"]
            job.category = data["category"]
            job.status = data["status"]
            job.files = [RenderFile.materialize(f) for f in data["files"]]
            job.frames = [RenderFrame.materialize(f) for f in data["frames"]]
            job.chunks = data["chunks"]
            job.priority = data["priority"]
            job.usage = data["usage"]
            job.blacklist = data["blacklist"]
            job.last_dispatched = data["last_dispatched"]
            job.resolution = data["resolution"]
            
            version_info = data.get("version_info", None)
            if version_info:
                job.version_info = VersioningInfo.materialize(version_info)
    
            return job
    
    class RenderFrame:
        def __init__(self, number = 0, command = ""):
            self.number = number
            self.time = 0
            self.status = QUEUED
            self.slave = None
            self.command = command
    
        def statusText(self):
            return FRAME_STATUS_TEXT[self.status]
    
        def serialize(self):
            return 	{
                                "number": self.number,
                                "time": self.time,
                                "status": self.status,
                                "slave": None if not self.slave else self.slave.serialize(),
                                "command": self.command
                            }
    
        @staticmethod
        def materialize(data):
            if not data:
                return None
    
            frame = RenderFrame()
            frame.number = data["number"]
            frame.time = data["time"]
            frame.status = data["status"]
            frame.slave = RenderSlave.materialize(data["slave"])
            frame.command = data["command"]
    
            return frame