def ask_wc(self, key, ts, time, ttl): ret = set() # look for matching keys for cat, (_, lock, db) in listitems(self._cat): prefix = cat + '/' if cat != 'nocat' else '' with lock: for subkey, entry in iteritems(db): if key not in prefix + subkey: continue # check for removed keys if entry.value is None: continue # check for expired keys op = entry.expired and OP_TELLOLD or OP_TELL if entry.ttl: if ts: ret.add('%r+%s@%s%s%s\n' % (entry.time, entry.ttl, prefix + subkey, op, entry.value)) else: ret.add(prefix + subkey + op + entry.value + '\n') elif ts: ret.add('%r@%s%s%s\n' % (entry.time, prefix + subkey, op, entry.value)) else: ret.add(prefix + subkey + op + entry.value + '\n') return [''.join(ret)]
def doStatus(self, maxage=0): st = multiStatus(listitems(self._adevs), maxage) if st[0] == status.OK: # check position try: self.doRead(maxage) except PositionError as e: return status.NOTREACHED, str(e) return st
def statusinfo(self): self.log.info('got SIGUSR2 - current stacktraces for each thread:') active = threading._active for tid, frame in listitems(sys._current_frames()): if tid in active: name = active[tid].getName() else: name = str(tid) self.log.info('%s: %s', name, ''.join(traceback.format_stack(frame)))
def updateAliasList(self): setups, _ = self._calculateSetups() # get includes as well seen = set() def add_includes(s): if s in seen or s not in self._setupinfo: return seen.add(s) for inc in self._setupinfo[s]['includes']: add_includes(inc) setups.add(inc) for setup in setups.copy(): add_includes(setup) # now collect alias config alias_config = {} for setup in setups: if 'alias_config' in self._setupinfo[setup]: aliasconfig = self._setupinfo[setup]['alias_config'] for aliasname, targets in aliasconfig.items(): for (target, prio) in targets.items(): alias_config.setdefault(aliasname, []).append( (target, prio)) # sort by priority for aliasname in alias_config: alias_config[aliasname].sort(key=lambda x: -x[1]) # create/update widgets layout = self.aliasGroup.layout() # only preselect previous aliases if we have the same choices for them # as in the beginning for aliasname in sorted(alias_config): preselect = self._prev_alias_config is None or \ (alias_config.get(aliasname) == self._prev_alias_config.get(aliasname)) selections = [x[0] for x in alias_config[aliasname]] if aliasname in self._aliasWidgets: self._aliasWidgets[aliasname].setSelections( selections, preselect and self._prev_aliases.get(aliasname)) else: wid = self._aliasWidgets[aliasname] = AliasWidget( self, aliasname, selections, preselect and self._prev_aliases.get(aliasname)) layout.addWidget(wid) for name, wid in listitems(self._aliasWidgets): if name not in alias_config: layout.takeAt(layout.indexOf(wid)).widget().deleteLater() del self._aliasWidgets[name] if alias_config: self.aliasGroup.show() else: self.aliasGroup.hide() self._alias_config = alias_config
def fixup_stacked_devices(logger, devdict): """ Replace <adevname> = Device(..) entries in devices dict with a proper name and move the device definition under that name. """ def add_new_dev(devname, subname, devconfig): # guess a name: newname = '%s_%s' % (devname, subname) while newname in devdict: logger.error('Device %r already exists, but is also a ' 'subdevice of %r which should be renamed', newname, devname) newname = '_' + newname # set subDevice lowlevel if not specified otherwise if 'lowlevel' not in devconfig[1]: devconfig[1]['lowlevel'] = True # 'rename' device, keeping logical connection devdict[newname] = devconfig return newname patched = True while patched: patched = False # iter over all devices for devname, dev in listitems(devdict): # iter over all key=value pairs for dict for subname, config in listitems(dev[1]): if isinstance(config, Device): # need to fixup! newname = add_new_dev(devname, subname, config) dev[1][subname] = newname patched = True elif isinstance(config, (tuple, list)) and \ any(isinstance(e, Device) for e in config): dev[1][subname] = list(config) for idx, item in enumerate(config): if isinstance(item, Device): subentryname = '%s%d' % (subname, idx + 1) newname = add_new_dev(devname, subentryname, item) dev[1][subname][idx] = newname patched = True return devdict
def devIter(devices, baseclass=None, onlydevs=True, allwaiters=False): """Filtering generator over the given devices. Iterates over the given devices. If the *baseclass* argument is specified (not ``None``), filter out (ignore) those devices which do not belong to the given baseclass. If the boolean *onlydevs* argument is false, yield ``(name, devices)`` tuples otherwise just the devices. If *allwaiters* is true, recursively include devices given by devices' ``_getWaiters`` methods. The given devices argument can either be a dictionary (_adevs, _sdevs,...) or a list of (name, device) tuples or a simple list of devices. """ if baseclass is None: # avoid import loop and still default to Device from nicos.core.device import Device baseclass = Device # convert dict to list of name:dev tuples if isinstance(devices, dict): devices = listitems(devices) else: # we iterate twice: make sure to convert generators # to a list first devices = list(devices) try: # to convert list of devices into desired format devices = [(dev.name, dev) for dev in devices if dev] except AttributeError: pass # not convertible, must be right format already... for devname, dev in devices: # handle _adevs style entries correctly if isinstance(dev, (tuple, list)): for subdev in dev: if isinstance(subdev, baseclass): if allwaiters: for subsubdev in devIter(subdev._getWaiters(), baseclass, onlydevs, allwaiters): yield subsubdev yield subdev if onlydevs else (subdev.name, subdev) else: if isinstance(dev, baseclass): if allwaiters: for subdev in devIter(dev._getWaiters(), baseclass, onlydevs, allwaiters): yield subdev yield dev if onlydevs else (devname, dev)
def _collectMetaInformation(self, update_headerinfo=None): bycategory = {} metainfo = self.dataset.metainfo for (device, key), (_, val, unit, category) in iteritems(metainfo): if category: bycategory.setdefault(category, []).append( ('%s_%s' % (device, key), (val + ' ' + unit).strip())) if update_headerinfo is None: update_headerinfo = getattr(self.sink, 'update_headerinfo', self.update_headerinfo) if update_headerinfo: # put count result in its own category: 'result' # note: status may need to be update manually as it is not # collected in the values :( # note2: as we may be called during counting, some devices # may be busy: this may irritate users :( bycategory['result'] = results = [] for devname, val in listitems(self.dataset.values): device = session.getDevice(devname) if (devname, 'value') in metainfo: # re-use the category _, _, unit, category = metainfo[(devname, 'value')] else: unit = device.unit category = 'result' bycategory.setdefault(category,[]).append( ('%s_value' % devname, (str(val) + ' ' + unit).strip())) # refresh status as well stat = device.status() # also map stat[0] to a string if stat[1]: stat = ('%s_status' % devname, ('%s: %s' % (statuses[stat[0]].lower(), stat[1].strip()))) else: stat = ('%s_status' % devname, statuses[stat[0]].lower()) bycategory[category].append(stat) # collect countresults (if already existing) if self.dataset.results: bycategory['result'] = results = [] for detname, detvalue in zip(self.dataset.detvalueinfo, self.dataset.detvaluelist): results.append((detname.name, str(detvalue))) return bycategory
def statusinfo(self): self.log.info('got SIGUSR2') if self._setup is not None: info = [] for worker in itervalues(self._workers): wname = worker.getName() if worker.is_alive(): info.append('%s: alive' % wname) else: info.append('%s: dead' % wname) self.log.info(', '.join(info)) self.log.info('current stacktraces for each thread:') active = threading._active for tid, frame in listitems(sys._current_frames()): if tid in active: name = active[tid].getName() else: name = str(tid) self.log.info('%s: %s', name, ''.join(traceback.format_stack(frame)))
def _wait_master_nt(self): # this is the same as _wait_master, but with active polling instead # of using os.wait(), which does not exist on Windows while True: sleep(0.5) if not self._children: break for setup, ch in listitems(self._children): ret = ch.poll() if ret is not None: # a process exited; restart if necessary del self._childpids[ch.pid] del self._children[setup] if setup in self._setups and not self._stoprequest: session.log.warning( '%s poller terminated with %s, ' 'restarting', setup, ret) self._start_child(setup) break else: session.log.info('%s poller terminated with %s', setup, ret) session.log.info('all pollers terminated')
def kwscount(**arguments): """Move sample and devices into place followed by a count. This takes KWS-specific circumstances such as sample time factor into account. Example: >>> kwscount(sample=1, selector='12A', resolution='2m', sample_pos='1.3m', time=3600) Keywords for standard instrument components are: * sample (sample number or name if unique, defaults to no sample change) * selector (must be present) * resolution (must be present) * sample_pos (must be present) * detector (must be present) * beamstop (defaults to out) * polarizer (defaults to out) * chopper (defaults to off) Any other keywords are interpreted as devices names and the target values. """ def sort_key(kv): try: # main components move first, in selected order return (0, DEFAULT.index(kv[0])) except ValueError: # all other devices move last, sorted by devname return (1, kv[0]) # check that all required components are present, and put defaults for # optional components if 'selector' not in arguments: raise UsageError('kwscount must have a value for the selector') if 'detector' not in arguments: raise UsageError('kwscount must have a value for the detector') if 'sample_pos' not in arguments: raise UsageError('kwscount must have a value for the sample_pos') if 'detector' not in arguments: raise UsageError('kwscount must have a value for the detector') if 'beamstop' not in arguments: arguments['beamstop'] = 'out' if 'polarizer' not in arguments: arguments['polarizer'] = 'out' if 'chopper' not in arguments: arguments['chopper'] = 'off' # leave space between kwscounts session.log.info('') # measurement time meastime = arguments.pop('time', 0) # select sample sample = arguments.pop('sample', None) # move devices waiters = [] # the order is important! devs = listitems(arguments) devs.sort(key=sort_key) # add moved devices to sampleenv _fixupSampleenv(devs) # start devices for devname, value in devs: if devname == 'chopper': # currently a no-op continue dev = session.getDevice(devname, Moveable) dev.start(value) if devname == 'selector': dev2 = session.getDevice('sel_speed') session.log.info('%-12s --> %s (%s)', devname, dev.format(value), dev2.format(dev2.target, unit=True)) else: session.log.info('%-12s --> %s', devname, dev.format(value, unit=True)) waiters.append(dev) # select and wait for sample here if sample is not None: session.experiment.sample.select(sample) # now wait for everyone else multiWait(waiters) # count session.log.info('Now counting for %d seconds...', meastime) count(t=meastime)
def _server_thread(self): self.log.info('server starting') # bind UDP broadcast socket self.log.debug('trying to bind to UDP broadcast') self._serversocket_udp = self._bind_to('', 'udp')[0] if self._serversocket_udp: self.log.info('UDP bound to broadcast') # now try to bind TCP socket, include 'MUST WORK' standalone names self.log.debug('trying to bind to %s', self.server) self._serversocket, self._boundto = self._bind_to(self.server) # one of the must have worked, otherwise continuing makes no sense if not self._serversocket and not self._serversocket_udp: self._stoprequest = True self.log.error("couldn't bind any sockets, giving up!") return if not self._boundto: self.log.warning('starting main loop only bound to UDP broadcast') else: self.log.info('TCP bound to %s:%s', self._boundto[0], self._boundto[1]) # now enter main serving loop while not self._stoprequest: # loop through connections, first to remove dead ones, # secondly to try to reconnect for addr, client in listitems(self._connected): if not client.is_active(): # dead or stopped self.log.info('client connection %s closed', addr) client.closedown() client.join() # wait for threads to end del self._connected[addr] # now check for additional incoming connections # build list of things to check selectlist = [] if self._serversocket: selectlist.append(self._serversocket) if self._serversocket_udp: selectlist.append(self._serversocket_udp) # 3 times client-side timeout res = select.select(selectlist, [], [], CYCLETIME * 3) if not res[0]: continue # nothing to read -> continue loop # lock aginst code in self.quit with self._connectionLock: if self._stoprequest: break if self._serversocket in res[0]: # TCP connection came in conn, addr = self._serversocket.accept() addr = 'tcp://%s:%d' % addr self.log.info('new connection from %s', addr) self._connected[addr] = CacheWorker(self._attached_db, conn, name=addr, loglevel=self.loglevel) elif self._serversocket_udp in res[0]: # UDP data came in data, addr = self._serversocket_udp.recvfrom(3072) nice_addr = 'udp://%s:%d' % addr self.log.info('new connection from %s', nice_addr) self._connected[nice_addr] = CacheUDPWorker( self._attached_db, self._serversocket_udp, name=nice_addr, data=data, remoteaddr=addr, loglevel=self.loglevel) if self._serversocket: closeSocket(self._serversocket) self._serversocket = None
def readSetup(infodict, modname, filepath, all_setups, logger): try: with open(filepath, 'rb') as modfile: code = modfile.read() except IOError as err: logger.exception('Could not read setup ' 'module %r: %s', filepath, err) return ns = prepareNamespace(modname, filepath, all_setups) try: exec_(code, ns) except Exception as err: logger.exception('An error occurred while processing ' 'setup %r: %s', filepath, err) return devices = fixup_stacked_devices(logger, ns.get('devices', {})) for devname in devices: if not nicosdev_re.match(devname): logger.exception('While processing setup %r: device name %r is ' 'invalid, names must be Python identifiers', filepath, devname) return info = { 'description': ns.get('description', modname), 'group': ns.get('group', 'optional'), 'sysconfig': ns.get('sysconfig', {}), 'includes': ns.get('includes', []), 'excludes': ns.get('excludes', []), 'modules': ns.get('modules', []), 'devices': devices, 'alias_config': ns.get('alias_config', {}), 'startupcode': ns.get('startupcode', ''), 'display_order': ns.get('display_order', 50), 'extended': ns.get('extended', {}), 'filenames': [filepath] + list(ns.get('_dep_files', ())), 'monitor_blocks': ns.get('monitor_blocks', {}), 'watch_conditions': ns.get('watch_conditions', []), } if info['group'] not in SETUP_GROUPS: logger.warning('Setup %s has an invalid group (valid groups ' 'are: %s)', modname, ', '.join(SETUP_GROUPS)) info['group'] = 'optional' if modname in infodict: # setup already exists; override/extend with new values oldinfo = infodict[modname] or {} oldinfo['description'] = ns.get('description', oldinfo['description']) oldinfo['group'] = ns.get('group', oldinfo['group']) oldinfo['sysconfig'].update(info['sysconfig']) oldinfo['includes'].extend(info['includes']) oldinfo['excludes'].extend(info['excludes']) oldinfo['modules'].extend(info['modules']) oldinfo['devices'].update(info['devices']) # remove devices overridden by "None" entries completely for devname, value in listitems(oldinfo['devices']): if value is None: del oldinfo['devices'][devname] oldinfo['startupcode'] += '\n' + info['startupcode'] oldinfo['alias_config'].update(info['alias_config']) oldinfo['display_order'] = ns.get('display_order', oldinfo['display_order']) oldinfo['extended'].update(info['extended']) oldinfo['filenames'].extend(info['filenames']) oldinfo['monitor_blocks'].update(info['monitor_blocks']) oldinfo['watch_conditions'].extend(info['watch_conditions']) logger.debug('%r setup partially merged with version ' 'from parent directory', modname) else: infodict[modname] = info