def __init__(self, uri, scenename, context, name, imageType): """ @param uri: uri of remote renderserver OR 'localhost' @type uri: string @param scenename: name of current scene @type scenename: string @param context: current render context @type context: Scene.Renderdata @param name: filename of saved .blend file @type name: string @param imageType: type of output image @type imageType: int """ self.configurer = Configurer() self.uri = uri self.scenename = scenename self.context = context self.name = name self.rpcserver = None self.blendSent = False self.imageType = imageType if uri == 'localhost': self.blendSent = True self.scn = Scene.Get(scenename) else: self.rpcserver = Server(uri) self._reset()
def __init__(self, scenename, context, name, fqueue, squeue, threadfactory, *args): """ Initialize a Listener instance. @param scenename: name of current scene @type scenename: string @param context: rendercontext of current scene @type context: Blender.Renderdata @param name: filename of saved .blend file @type name: string @param fqueue: worklist queue @type fqueue: Queue.queue @param squeue: statistics queue @type squeue: Queue.queue @param threadfactory: a classfactory to spawn worker threads @type threadfactory: NetworkRender.Renderthread @param args: additional arguments to be given to the threadfactory """ Thread.__init__(self) self.scenename = scenename self.context = context self.name = name self.factory = threadfactory self.fqueue = fqueue self.squeue = squeue self.args = args self.configurer = Configurer() debug('UDPlistener starting') self.socket = socket.socket(socket.AF_INET,socket.SOCK_DGRAM) debug('UDPlistener socket created %s' % self.socket) self.socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) debug('UDPlistener options set') #self.ip = socket.gethostbyname(socket.gethostname()) self.ip = '0.0.0.0' self.socket.bind((self.ip, self.configurer.get('ClientPort'))) debug('UDPlistener listening on %s'%self.socket)
An image is (for now) always split into 2x2 parts """ import os, Blender, NetworkRender, time from tempfile import mkstemp from Queue import Queue from Blender import Image, Draw from NetworkRender.StillRenderThread import StillRenderThread from NetworkRender.Configurer import Configurer NetworkRender.debugset() from NetworkRender import debug # Get configuration singleton and read some settings configurer = Configurer() localRendering = configurer.get('ClientLocalRendering') parts = configurer.get('StillParts') imageType = configurer.get('ImageType') # the worklist (either part- or framenumbers) frames = Queue() # statistics are communicated by the renderthreads via this queue stats = Queue() # lets start! starttime = time.time() # save the current .blend (scn, context, scenename, name) = NetworkRender.saveblend()
""" global configurer data = self.fd2.read(configurer.get('ServerBufferSize')) if len(data) <= 0: self.fd2.close() return Binary(data) def stop (self): global running; running = False; return 'stop requested' configurer = Configurer() # Instantiate and bind to localhost:<ServerPort> server = Server(('0.0.0.0', configurer.get('ServerPort')), SimpleXMLRPCRequestHandler) # Register example object instance server.register_instance(Render()) # run! server.serve_till_stopped() # bye print 'Render server terminated'
class RendererImpl(): """ Common functions for rendering frames and part of stills. """ def __init__(self, uri, scenename, context, name, imageType): """ @param uri: uri of remote renderserver OR 'localhost' @type uri: string @param scenename: name of current scene @type scenename: string @param context: current render context @type context: Scene.Renderdata @param name: filename of saved .blend file @type name: string @param imageType: type of output image @type imageType: int """ self.configurer = Configurer() self.uri = uri self.scenename = scenename self.context = context self.name = name self.rpcserver = None self.blendSent = False self.imageType = imageType if uri == 'localhost': self.blendSent = True self.scn = Scene.Get(scenename) else: self.rpcserver = Server(uri) self._reset() def _reset(self): self.busy = False self.frame = None def isLocal(self): """ returns True if these services run on 'localhost' @rtype: boolean """ return self.uri == 'localhost' def _sendBlendFile(self): """ Sent saved .blendfile if needed. Uploads saved .blend file to remote host if not already done so. """ if self.isLocal() or self.blendSent: pass else: self.rpcserver.newfile() fd = open(self.name, 'rb', self.configurer.get('ServerBufferSize')) debug('%s sending .blend: %s'%(self.uri, fd)) n = 0 buffer = True while buffer : buffer = fd.read(self.configurer.get('ServerBufferSize')) if buffer: r = self.rpcserver.put(Binary(buffer)) debug('%s put response %s' % (self.uri, r)) n = n + 1 debug('%s %d blocks put'%(self.uri, n)) fd.close() r = self.rpcserver.endfile() debug('%s endfile called, response %s'%(self.uri, r)) self.blendSent = True def _getResult(self): """ Download rendered frame or part from remote server. """ debug('%s saving frame %d'%(self.uri, self.frame)) if not self.isLocal(): debug('%s getting remote frame %d'%(self.uri, self.frame)) rname = self.rpcserver.getResult() from tempfile import mkstemp import os from os import path remotedir,remotefile = path.split(rname) if self.animation == True : localdir,localfile = path.split(self.context.getFrameFilename()) name = path.join(localdir,remotefile) fd,tname = mkstemp(suffix = remotefile) os.close(fd) debug('%s saving remote frame %d as tempfile %s' % (self.uri, self.frame, tname)) fd = open(tname,'wb',self.configurer.get('ServerBufferSize')) while True: data = str(self.rpcserver.get()) if len(data) <= 0: fd.close() break else: fd.write(str(data)) fd.close() if self.animation == True : debug('%s frame %d renaming %s to %s'%(self.uri,self.frame, tname, name)) if os.access(name, os.F_OK): os.unlink(name) # windows won't let us rename to an existing file debug("%s %s exists? %s" % (self.uri,tname, os.access(tname, os.F_OK))) os.rename(tname,name) # why all this trouble? the source file on the serverside might # be on the exact same location as the file we try to write # on the clientside if we run the server and the on the same # machine (as we might do for testing) self.result = name else : self.result = tname print 'Saved: %s (remotely rendered)'% self.result else: print 'Saved: %s (locally rendered)'% self.result pass debug('%s saving frame %d done'%(self.uri,self.frame))
class Listener(Thread): """ Implements a listener process that listens to announcements of remote renderservers and spawns a RenderThread if it detects a new one. """ def __init__(self, scenename, context, name, fqueue, squeue, threadfactory, *args): """ Initialize a Listener instance. @param scenename: name of current scene @type scenename: string @param context: rendercontext of current scene @type context: Blender.Renderdata @param name: filename of saved .blend file @type name: string @param fqueue: worklist queue @type fqueue: Queue.queue @param squeue: statistics queue @type squeue: Queue.queue @param threadfactory: a classfactory to spawn worker threads @type threadfactory: NetworkRender.Renderthread @param args: additional arguments to be given to the threadfactory """ Thread.__init__(self) self.scenename = scenename self.context = context self.name = name self.factory = threadfactory self.fqueue = fqueue self.squeue = squeue self.args = args self.configurer = Configurer() debug('UDPlistener starting') self.socket = socket.socket(socket.AF_INET,socket.SOCK_DGRAM) debug('UDPlistener socket created %s' % self.socket) self.socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) debug('UDPlistener options set') #self.ip = socket.gethostbyname(socket.gethostname()) self.ip = '0.0.0.0' self.socket.bind((self.ip, self.configurer.get('ClientPort'))) debug('UDPlistener listening on %s'%self.socket) def reusable(self, uri): nodeData = self.uriMap.get(uri) rt = nodeData['renderThread'] # Check is thread still alive and not failed if (not rt.serviceAlive()): # Thread is not alive because of remote server caught an # unhandled exception. But is this case remote server freezes. # So, a ping pocket from this server means this server is restarted # and we could reuse this thread # It would be safer to manually request stopping of thread rt.requestStop() debug('node uri %s caught a failure, but send a ping pocket again.') return True return False def registerNode(self, uri): """ Register rendering node """ nodeData = self.uriMap.get(uri) if (nodeData == None or self.reusable(uri)): debug('spawning new thread for %s' % uri) rt = self.factory(uri, self.scenename, self.context, self.name, self.fqueue, self.squeue,*self.args) self.r.append(rt) self.uriMap[uri] = {'renderThread': rt} rt.start() def run(self): """ Listen and spawn new worker threads if appropriate. Overridden from Thread. Implements a stoppable loop (stops when requestStop is called on this thread) and records with workerthreads were spawned. """ import time self.stop = False self.r = [] self.uriMap = {} # Register static list of server servers = self.configurer.get('ClientServerList').split(',') for server in servers: if (server == ''): continue serverData = server.split(':') if (len (serverData) == 1): serverData.append(str(self.configurer.get('ServerPort'))) self.registerNode('http://' + serverData[0].strip() + ':' + serverData[1].strip()) while not self.stop: debug('UDPlistener ready for request on %s,%s' % self.socket.getsockname()) try: self.socket.settimeout(5) data, addr = self.socket.recvfrom(512) debug('UDPlistener received request: %s from %s' % (data, addr)) self.registerNode(data) except (socket.timeout) : debug('UDPlistener received nothing, will try again') finally: time.sleep(self.configurer.get('ServerBCastInterval')) debug('UDPlistener stopped') def requestStop(self): """ Request this thread to stop. """ self.stop = True def getRemotethreads(self): """ @returns: a list of previously spawned workerthreads. """ return self.r
Its only possible to render an animation as a sequence of images, not directly as an .avi """ import time, Blender, NetworkRender from NetworkRender.AnimRenderThread import AnimRenderThread from Queue import Queue from NetworkRender.Configurer import Configurer from Blender import Draw NetworkRender.debugset() from NetworkRender import debug # Get configuration singleton and read some settings configurer = Configurer() localRendering = configurer.get("ClientLocalRendering") imageType = configurer.get("ImageType") # the worklist (either part- or framenumbers) frames = Queue() # statistics are communicated by the renderthreads via this queue stats = Queue() # lets start! starttime = time.time() # save the current .blend (scn, context, scenename, name) = NetworkRender.saveblend()