def __init__(self, name, session, managerlocation=None, otherdatabinder=None, otherdbdatakeeper=None, tcpport=None, launcher=None, panel=None): self.name = name self.panel = panel self.initializeLogger() self.managerclient = None if session is None or isinstance(session, leginondata.SessionData): self.session = session else: raise TypeError('session must be of proper type') self.launcher = launcher if otherdatabinder is None: name = DataBinder.__name__ databinderlogger = gui.wx.Logging.getNodeChildLogger(name, self) self.databinder = DataBinder(self, databinderlogger, tcpport=tcpport) else: self.databinder = otherdatabinder if otherdbdatakeeper is None: self.dbdatakeeper = sinedon.getConnection('leginondata') else: self.dbdatakeeper = otherdbdatakeeper self.confirmationevents = {} self.eventswaiting = {} self.ewlock = threading.Lock() #self.addEventInput(event.Event, self.logEventReceived) self.addEventInput(event.KillEvent, self.die) self.addEventInput(event.ConfirmationEvent, self.handleConfirmedEvent) self.addEventInput(event.SetManagerEvent, self.handleSetManager) self.addEventInput(event.ApplicationLaunchedEvent, self.handleApplicationEvent) self.managerlocation = managerlocation if managerlocation is not None: try: self.setManager(self.managerlocation) except: self.logger.exception('exception in setManager') raise correctorclient.CorrectorClient.__init__(self) self.initializeSettings()
class Node(correctorclient.CorrectorClient): '''Atomic operating unit for performing tasks, creating data and events.''' panelclass = None eventinputs = [ event.Event, event.KillEvent, event.ApplicationLaunchedEvent, event.ConfirmationEvent ] eventoutputs = [ event.PublishEvent, event.NodeAvailableEvent, event.NodeUnavailableEvent, event.NodeInitializedEvent, event.NodeUninitializedEvent ] objectserviceclass = remotecall.NodeObjectService def __init__(self, name, session, managerlocation=None, otherdatabinder=None, otherdbdatakeeper=None, tcpport=None, launcher=None, panel=None): self.name = name self.panel = panel self.initializeLogger() self.managerclient = None if session is None or isinstance(session, leginondata.SessionData): self.session = session else: raise TypeError('session must be of proper type') self.launcher = launcher if otherdatabinder is None: name = DataBinder.__name__ databinderlogger = gui.wx.Logging.getNodeChildLogger(name, self) self.databinder = DataBinder(self, databinderlogger, tcpport=tcpport) else: self.databinder = otherdatabinder if otherdbdatakeeper is None: self.dbdatakeeper = sinedon.getConnection('leginondata') else: self.dbdatakeeper = otherdbdatakeeper self.confirmationevents = {} self.eventswaiting = {} self.ewlock = threading.Lock() #self.addEventInput(event.Event, self.logEventReceived) self.addEventInput(event.KillEvent, self.die) self.addEventInput(event.ConfirmationEvent, self.handleConfirmedEvent) self.addEventInput(event.SetManagerEvent, self.handleSetManager) self.addEventInput(event.ApplicationLaunchedEvent, self.handleApplicationEvent) self.managerlocation = managerlocation if managerlocation is not None: try: self.setManager(self.managerlocation) except: self.logger.exception('exception in setManager') raise correctorclient.CorrectorClient.__init__(self) self.initializeSettings() def testprint(self, msg): if testing: print msg # settings def initializeSettings(self, user=None): if not hasattr(self, 'settingsclass'): return # load the requested user settings if user is None: user = self.session['user'] qsession = leginondata.SessionData(initializer={'user': user}) qdata = self.settingsclass(initializer={ 'session': qsession, 'name': self.name }) settings = self.research(qdata, results=1) # if that failed, try to load default settings from DB if not settings: qdata = self.settingsclass(initializer={ 'isdefault': True, 'name': self.name }) settings = self.research(qdata, results=1) # if that failed, use hard coded defaults if not settings: self.settings = copy.deepcopy(self.defaultsettings) else: # get query result into usable form settings = settings[0] self.settings = settings.toDict(dereference=True) del self.settings['session'] del self.settings['name'] # check if None in any fields for key, value in self.settings.items(): if value is None: if key in self.defaultsettings: self.settings[key] = copy.deepcopy( self.defaultsettings[key]) def loadSettingsByID(self, id): if not hasattr(self, 'settingsclass'): return # load the requested row by id settings = self.settingsclass.direct_query(id) # if that failed, try to load default settings from DB if not settings: self.logger.error('no settings with id: %s' % (id, )) return # get query result into usable form self.settings = settings.toDict(dereference=True) del self.settings['session'] del self.settings['name'] # check if None in any fields for key, value in self.settings.items(): if value is None: if key in self.defaultsettings: self.settings[key] = copy.deepcopy( self.defaultsettings[key]) # set to GUI def setSettings(self, d, isdefault=False): self.settings = d sd = self.settingsclass.fromDict(d) sd['session'] = self.session sd['name'] = self.name if self.session['user']['username'] == 'administrator': sd['isdefault'] = True else: sd['isdefault'] = isdefault self.publish(sd, database=True, dbforce=True) self._checkSettings(sd) def _checkSettings(self, settings): if hasattr(self, 'checkSettings'): messages = self.checkSettings(settings) else: messages = [] for message in messages: level = message[0] text = message[1] func = getattr(self.logger, level) func(text) def getSettings(self): return self.settings def initializeLogger(self): if hasattr(self, 'logger'): return self.logger = gui.wx.Logging.getNodeLogger(self) clientname = datatransport.Client.__name__ self.clientlogger = gui.wx.Logging.getNodeChildLogger(clientname, self) def logToDB(self, record): '''insertes a logger record into the DB''' record_data = leginondata.LoggerRecordData(session=self.session) for atr in ('name', 'levelno', 'levelname', 'pathname', 'filename', 'module', 'lineno', 'created', 'thread', 'process', 'message', 'exc_info'): record_data[atr] = getattr(record, atr) self.publish(record_data, database=True, dbforce=True) # main, start/stop methods def start(self): self.onInitialized() self.outputEvent(event.NodeInitializedEvent()) def onInitialized(self): if self.panel is None: return evt = gui.wx.Node.NodeInitializedEvent(self) self.panel.GetEventHandler().AddPendingEvent(evt) evt.event.wait() def setImage(self, image, typename=None): if image is not None: image = numpy.asarray(image, numpy.float32) evt = gui.wx.Events.SetImageEvent(image, typename) self.panel.GetEventHandler().AddPendingEvent(evt) def setTargets(self, targets, typename, block=False): evt = gui.wx.Events.SetTargetsEvent(targets, typename) if block: evt.event = threading.Event() self.panel.GetEventHandler().AddPendingEvent(evt) if block: evt.event.wait() def exit(self): '''Cleans up the node before it dies.''' try: self.objectservice._exit() except (AttributeError, TypeError): pass try: self.outputEvent(event.NodeUninitializedEvent(), wait=True, timeout=3.0) self.outputEvent(event.NodeUnavailableEvent()) except (ConfirmationTimeout, datatransport.TransportError): pass self.delEventInput() if self.launcher is not None: self.launcher.onDestroyNode(self) if self.databinder is self.launcher.databinder: return self.databinder.exit() def die(self, ievent=None): '''Tell the node to finish and call exit.''' self.exit() if ievent is not None: self.confirmEvent(ievent) # location method def location(self): location = {} location['hostname'] = socket.gethostname().lower() if self.launcher is not None: location['launcher'] = self.launcher.name else: location['launcher'] = None location['data binder'] = self.databinder.location() return location # event input/output/blocking methods def eventToClient(self, ievent, client, wait=False, timeout=None): ''' base method for sending events to a client ievent - event instance client - client instance wait - True/False, sould confirmation be sent back timeout - how long (seconds) to wait for confirmation before raising a ConfirmationTimeout ''' if wait: ## prepare to wait (but don't wait yet) wait_id = ievent.dmid ievent['confirm'] = wait_id self.ewlock.acquire() self.eventswaiting[wait_id] = threading.Event() eventwait = self.eventswaiting[wait_id] self.ewlock.release() ### send event and cross your fingers try: client.send(ievent) #self.logEvent(ievent, status='%s eventToClient' % (self.name,)) except datatransport.TransportError: # make sure we don't wait for an event that failed if wait: eventwait.set() raise except Exception, e: self.logger.exception('Error sending event to client: %s' % e) raise confirmationevent = None if wait: ### this wait should be released ### by handleConfirmedEvent() eventwait.wait(timeout) notimeout = eventwait.isSet() self.ewlock.acquire() try: confirmationevent = self.confirmationevents[wait_id] del self.confirmationevents[wait_id] del self.eventswaiting[wait_id] except KeyError: self.logger.warning('This could be bad to except KeyError') self.ewlock.release() if not notimeout: raise ConfirmationTimeout(str(ievent)) if confirmationevent['status'] == 'no binding': raise ConfirmationNoBinding( '%s from %s not bound to any node' % (ievent.__class__.__name__, ievent['node'])) return confirmationevent
class Node(correctorclient.CorrectorClient): '''Atomic operating unit for performing tasks, creating data and events.''' panelclass = None eventinputs = [event.Event, event.KillEvent, event.ApplicationLaunchedEvent, event.ConfirmationEvent] eventoutputs = [event.PublishEvent, event.NodeAvailableEvent, event.NodeUnavailableEvent, event.NodeInitializedEvent, event.NodeUninitializedEvent] objectserviceclass = remotecall.NodeObjectService def __init__(self, name, session, managerlocation=None, otherdatabinder=None, otherdbdatakeeper=None, tcpport=None, launcher=None, panel=None): self.name = name self.panel = panel self.initializeLogger() self.managerclient = None if session is None or isinstance(session, leginondata.SessionData): self.session = session else: raise TypeError('session must be of proper type') self.launcher = launcher if otherdatabinder is None: name = DataBinder.__name__ databinderlogger = gui.wx.Logging.getNodeChildLogger(name, self) self.databinder = DataBinder(self, databinderlogger, tcpport=tcpport) else: self.databinder = otherdatabinder if otherdbdatakeeper is None: self.dbdatakeeper = sinedon.getConnection('leginondata') else: self.dbdatakeeper = otherdbdatakeeper self.confirmationevents = {} self.eventswaiting = {} self.ewlock = threading.Lock() #self.addEventInput(event.Event, self.logEventReceived) self.addEventInput(event.KillEvent, self.die) self.addEventInput(event.ConfirmationEvent, self.handleConfirmedEvent) self.addEventInput(event.SetManagerEvent, self.handleSetManager) self.addEventInput(event.ApplicationLaunchedEvent, self.handleApplicationEvent) self.managerlocation = managerlocation if managerlocation is not None: try: self.setManager(self.managerlocation) except: self.logger.exception('exception in setManager') raise correctorclient.CorrectorClient.__init__(self) self.initializeSettings() def testprint(self,msg): if testing: print msg # settings def initializeSettings(self, user=None): if not hasattr(self, 'settingsclass'): return settings = self.reseachDBSettings(self.settingsclass, self.name, user) # if that failed, use hard coded defaults if not settings: self.settings = copy.deepcopy(self.defaultsettings) else: # get query result into usable form settings = settings[0] self.settings = settings.toDict(dereference=True) del self.settings['session'] del self.settings['name'] # check if None in any fields for key,value in self.settings.items(): if value is None: if key in self.defaultsettings: self.settings[key] = copy.deepcopy(self.defaultsettings[key]) def reseachDBSettings(self, settingsclass, inst_alias, user=None): # load the requested user settings if user is None: user = self.session['user'] qsession = leginondata.SessionData(initializer={'user': user}) qdata = settingsclass(initializer={'session': qsession, 'name': inst_alias}) settings = self.research(qdata, results=1) # if that failed, try to load default settings from DB if not settings: qdata = settingsclass(initializer={'isdefault': True, 'name': self.name}) settings = self.research(qdata, results=1) return settings def loadSettingsByID(self, id): if not hasattr(self, 'settingsclass'): return # load the requested row by id settings = self.settingsclass.direct_query(id) # if that failed, try to load default settings from DB if not settings: self.logger.error('no settings with id: %s' % (id,)) return # get query result into usable form self.settings = settings.toDict(dereference=True) del self.settings['session'] del self.settings['name'] # check if None in any fields for key,value in self.settings.items(): if value is None: if key in self.defaultsettings: self.settings[key] = copy.deepcopy(self.defaultsettings[key]) # set to GUI def setSettings(self, d, isdefault=False): self.settings = d sd = self.settingsclass.fromDict(d) sd['session'] = self.session sd['name'] = self.name if self.session['user']['username'] == 'administrator': sd['isdefault'] = True else: sd['isdefault'] = isdefault self.publish(sd, database=True, dbforce=True) self._checkSettings(sd) def _checkSettings(self, settings): if hasattr(self, 'checkSettings'): messages = self.checkSettings(settings) else: messages = [] for message in messages: level = message[0] text = message[1] func = getattr(self.logger, level) func(text) def getSettings(self): return self.settings def initializeLogger(self): if hasattr(self, 'logger'): return self.logger = gui.wx.Logging.getNodeLogger(self) clientname = datatransport.Client.__name__ self.clientlogger = gui.wx.Logging.getNodeChildLogger(clientname, self) def logToDB(self, record): '''insertes a logger record into the DB''' record_data = leginondata.LoggerRecordData(session=self.session) for atr in ('name','levelno','levelname','pathname','filename','module','lineno','created','thread','process','message','exc_info'): record_data[atr] = getattr(record,atr) self.publish(record_data, database=True, dbforce=True) # main, start/stop methods def start(self): self.onInitialized() self.outputEvent(event.NodeInitializedEvent()) def onInitialized(self): if self.panel is None: return evt = gui.wx.Node.NodeInitializedEvent(self) self.panel.GetEventHandler().AddPendingEvent(evt) evt.event.wait() def setImage(self, image, typename=None): if image is not None: image = numpy.asarray(image, numpy.float32) evt = gui.wx.Events.SetImageEvent(image, typename) self.panel.GetEventHandler().AddPendingEvent(evt) def setTargets(self, targets, typename, block=False): evt = gui.wx.Events.SetTargetsEvent(targets, typename) if block: evt.event = threading.Event() self.panel.GetEventHandler().AddPendingEvent(evt) if block: evt.event.wait() def exit(self): '''Cleans up the node before it dies.''' try: self.objectservice._exit() except (AttributeError, TypeError): pass try: self.outputEvent(event.NodeUninitializedEvent(), wait=True, timeout=3.0) self.outputEvent(event.NodeUnavailableEvent()) except (ConfirmationTimeout, datatransport.TransportError): pass self.delEventInput() if self.launcher is not None: self.launcher.onDestroyNode(self) if self.databinder is self.launcher.databinder: return self.databinder.exit() def die(self, ievent=None): '''Tell the node to finish and call exit.''' self.exit() if ievent is not None: self.confirmEvent(ievent) # location method def location(self): location = {} location['hostname'] = socket.gethostname().lower() if self.launcher is not None: location['launcher'] = self.launcher.name else: location['launcher'] = None location['data binder'] = self.databinder.location() return location # event input/output/blocking methods def eventToClient(self, ievent, client, wait=False, timeout=None): ''' base method for sending events to a client ievent - event instance client - client instance wait - True/False, sould confirmation be sent back timeout - how long (seconds) to wait for confirmation before raising a ConfirmationTimeout ''' if wait: ## prepare to wait (but don't wait yet) wait_id = ievent.dmid ievent['confirm'] = wait_id self.ewlock.acquire() self.eventswaiting[wait_id] = threading.Event() eventwait = self.eventswaiting[wait_id] self.ewlock.release() ### send event and cross your fingers try: client.send(ievent) #self.logEvent(ievent, status='%s eventToClient' % (self.name,)) except datatransport.TransportError: # make sure we don't wait for an event that failed if wait: eventwait.set() raise except Exception, e: self.logger.exception('Error sending event to client: %s' % e) raise confirmationevent = None if wait: ### this wait should be released ### by handleConfirmedEvent() eventwait.wait(timeout) notimeout = eventwait.isSet() self.ewlock.acquire() try: confirmationevent = self.confirmationevents[wait_id] del self.confirmationevents[wait_id] del self.eventswaiting[wait_id] except KeyError: self.logger.warning('This could be bad to except KeyError') self.ewlock.release() if not notimeout: raise ConfirmationTimeout(str(ievent)) if confirmationevent['status'] == 'no binding': raise ConfirmationNoBinding('%s from %s not bound to any node' % (ievent.__class__.__name__, ievent['node'])) return confirmationevent