Beispiel #1
0
def startSubprocess(filename, *args, **kwds):
    adjustPYTHONPATH()
    name = path.splitext(filename)[0]
    sys.stderr.write(' [%s start... ' % name)
    if kwds.get('piped'):
        popen_kwds = dict(stdin=subprocess.PIPE,
                          stdout=subprocess.PIPE,
                          stderr=subprocess.STDOUT)
    else:
        popen_kwds = dict()
    proc = createSubprocess(
        [sys.executable,
         path.join(module_root, 'test', 'bin', filename)] + list(args),
        **popen_kwds)
    proc.nicos_name = name
    if 'wait_cb' in kwds:
        try:
            kwds['wait_cb']()
        except Exception:
            caught = sys.exc_info()
            sys.stderr.write('%s failed]' % proc.pid)
            try:
                proc.kill()
            except Exception:
                pass
            proc.wait()
            reraise(*caught)
    sys.stderr.write('%s ok]\n' % proc.pid)
    return proc
Beispiel #2
0
 def _hw_wait(self, devices):
     loops = 0
     final_exc = None
     devlist = devices[:]  # make a 'real' copy of the list
     while devlist:
         loops += 1
         for dev in devlist[:]:
             try:
                 done = dev.doStatus(0)[0]
             except Exception:
                 dev.log.exception('while waiting')
                 final_exc = filterExceptions(sys.exc_info(), final_exc)
                 # remove this device from the waiters - we might still
                 # have its subdevices in the list so that _hw_wait()
                 # should not return until everything is either OK or
                 # ERROR
                 devlist.remove(dev)
             if done == status.BUSY:
                 # we found one busy dev, normally go to next iteration
                 # until this one is done (saves going through the whole
                 # list of devices and doing unnecessary HW communication)
                 if loops % 10:
                     break
                 # every 10 loops, go through everything to get an accurate
                 # display in the action line
                 continue
             devlist.remove(dev)
         if devlist:
             session.delay(self._base_loop_delay)
     if final_exc:
         reraise(*final_exc)
Beispiel #3
0
def _basemove(dev_pos_list, waithook=None, poshook=None):
    """Core move function.

    Options:

    *waithook*: a waiting function that gets the list of started devices
    *poshook*: gets device and requested pos, returns modified position
    """
    movelist = []
    errors = []

    for dev, pos in _devposlist(dev_pos_list, Moveable):
        try:
            if poshook:
                pos = poshook(dev, pos)
            pos = dev._check_start(pos)
            if pos is not Ellipsis:
                movelist.append((dev, pos))
        except (NicosError, ValueError, TypeError):
            errors.append((dev, sys.exc_info()))

    if errors:
        for (dev, exc_info) in errors[:-1]:
            dev.log.error(exc_info=exc_info)
        reraise(*errors[-1][1])

    devs = []
    for (dev, pos) in movelist:
        dev.log.info('moving to %s', dev.format(pos, unit=True))
        dev._start_unchecked(pos)
        devs.append(dev)
    if waithook:
        waithook(devs)
Beispiel #4
0
 def _raise_taco(self, err, addmsg=None):
     """Raise a suitable NicosError for a given TACOError instance."""
     tb = sys.exc_info()[2]
     code = err.errcode
     cls = NicosError
     if code in self.taco_errorcodes:
         cls = self.taco_errorcodes[code]
     elif code < 50:
         # error numbers 0-50: RPC call errors
         cls = CommunicationError
     elif 400 <= code < 500:
         # error number 400-499: database system error messages
         cls = CommunicationError
     elif code == DevErr_RangeError:
         cls = LimitError
     elif code in (DevErr_InvalidValue, DevErr_ExecutionDenied):
         cls = InvalidValueError
     elif code in (DevErr_IOError, DevErr_InternalError,
                   DevErr_RuntimeError, DevErr_SystemError):
         cls = CommunicationError
     msg = '[TACO %d] %s' % (err.errcode, err)
     if addmsg is not None:
         msg = addmsg + ': ' + msg
     exc = cls(self, msg, tacoerr=err.errcode)
     reraise(cls, exc, tb)
Beispiel #5
0
 def _retryFailed(self, step, action, nretries, exc_info):
     self._seq_stopflag = True
     self._setROParam(
         'fixed', 'Error during sequence (step %r), needs '
         'manual fixing!' % step)
     self._setROParam('fixedby', ('admin', 20))
     reraise(*exc_info)
Beispiel #6
0
    def _retryFailed(self, step, action, nretries, exc_info):
        """Called whenever an actions retry failed.

        This may raise an Exception to end the sequence or return
        anything to ignore this.

        Default is to re-raise the given exception.
        """
        reraise(*exc_info)
Beispiel #7
0
    def _runFailed(self, step, action, exc_info):
        """Called whenever an action run failed.

        This may raise an Exception to end the sequence or return
        an integer. If that integer is > 0, the actions retry is called.

        Default is to re-raise the given exception.
        """
        reraise(*exc_info)
Beispiel #8
0
 def _inner_run(self):
     dataman = session.experiment.data
     # move all devices to starting position before starting scan
     try:
         self.prepareScan(self._startpositions[0])
         skip_first_point = False
     except StopScan:
         return
     except SkipPoint:
         skip_first_point = True
     # if the scan was already aborted, we haven't started writing
     self.beginScan()
     try:
         for i, position in enumerate(self._startpositions):
             with self.pointScope(i + 1):
                 try:
                     self.preparePoint(i + 1, position)
                     if i == 0 and skip_first_point:
                         continue
                     waitresults = self.moveDevices(self._devices,
                                                    position,
                                                    wait=True)
                     # start moving to end positions
                     if self._endpositions:
                         self.moveDevices(self._devices,
                                          self._endpositions[i],
                                          wait=False)
                 except SkipPoint:
                     continue
                 except:  # pylint: disable=bare-except
                     exc_info = sys.exc_info()
                     try:
                         self.finishPoint()
                     except Exception:
                         session.log.exception('could not finish point')
                     reraise(*exc_info)
                 try:
                     # measure...
                     # XXX(dataapi): is target= needed?
                     point = dataman.beginPoint(target=position)
                     dataman.putValues(waitresults)
                     self.readEnvironment()
                     try:
                         self.acquire(point, self._preset)
                     finally:
                         dataman.finishPoint()
                 except NicosError as err:
                     self.handleError('count', err)
                 except SkipPoint:
                     pass
                 finally:
                     self.finishPoint()
     except StopScan:
         pass
     finally:
         self.endScan()
Beispiel #9
0
    def _waitFailed(self, step, action, exc_info):
        """Called whenever a wait failed.

        This may raise an Exception to end the sequence or return
        anything to ignore this.
        If the returned value evaluates to a boolean True, the wait
        is retried once. If it still fails, the sequence is aborted.

        Default is to re-raise the given exception.
        """
        reraise(*exc_info)
Beispiel #10
0
def _multiMethod(baseclass, method, devices):
    """Calls a method on a list of devices.

    Errors raised are handled like in the following way:
    The error is logged, and the first exception with the highest serverity
    (exception in `CONTINUE_EXCEPTIONS` < `SKIP_EXCEPTIONS` < other exceptions)
    is re-raised at the end.

    Additional arguments are used when calling the method.
    The same arguments are used for *ALL* calls.
    """
    final_exc = None
    for dev in devIter(devices, baseclass):
        try:
            # method has to be provided by baseclass!
            getattr(dev, method)()
        except Exception:
            dev.log.exception('during %s()', method)
            final_exc = filterExceptions(sys.exc_info(), final_exc)
    if final_exc:
        reraise(*final_exc)
Beispiel #11
0
def acquire(point, preset, iscompletefunc=None):
    """Low-level acquisition function.

    The loop delay is configurable in the instrument object, and defaults to
    0.025 seconds.

    The result is stored in the given argument, which must be an empty list.
    This is so that a result can be returned even when a stop exception is
    propagated upwards.

    The *iscompletefunc* callback can be used to influence the stop of the
    detectors. When *iscompeletefunc* returns `True` the detectors will be
    stopped. This can be useful to implement scans with software
    synchronisation, e.g. stopping of the detector when the movement of
    the scanned axis has been finished although the preset has not yet
    been fulfilled.
    """
    if iscompletefunc is None:  # do not influence count loop using callback
        iscompletefunc = lambda: False
    # put detectors in a set and discard them when completed
    detset = set(point.detectors)
    delay = (session.instrument and session.instrument.countloopdelay or 0.025
             if session.mode != SIMULATION else 0.0)

    dataman = session.experiment.data

    session.beginActionScope('Counting')
    if session.countloop_request:
        _wait_for_continuation(delay, only_pause=True)
    for det in point.detectors:
        det.setPreset(**preset)

    for det in point.detectors:
        det.prepare()
    for det in point.detectors:
        waitForCompletion(det)

    dataman.updateMetainfo()
    point.started = currenttime()
    try:
        for det in point.detectors:
            det.start()
    except:
        session.endActionScope()
        raise
    session.delay(delay)
    try:
        quality = None
        while True:
            looptime = currenttime()
            for det in list(detset):
                if session.mode != SIMULATION:
                    quality = det.duringMeasureHook(looptime - point.started)
                if det.isCompleted():
                    det.finish()
                    quality = FINAL
                if quality:
                    try:
                        res = det.readResults(quality)
                    except Exception:
                        det.log.exception('error reading measurement data')
                        res = None
                    dataman.putResults(quality, {det.name: res})
                if quality == FINAL:
                    detset.discard(det)
            if not detset:
                # all detectors finished measuring
                break
            if session.countloop_request:
                for det in detset:
                    if not det.pause():
                        session.log.warning(
                            'detector %r could not be paused', det.name)
                if not _wait_for_continuation(delay):
                    for det in detset:
                        # next iteration of loop will see det is finished
                        det.finish()
                else:
                    for det in detset:
                        det.resume()
            if iscompletefunc():  # stop via callback function
                for det in detset:
                    det.stop()
            session.delay(delay)
    except BaseException as e:
        exc_info = sys.exc_info()
        point.finished = currenttime()
        if e.__class__.__name__ != 'ControlStop':
            session.log.warning('Exception during count, trying to save data',
                                exc=True)
        for det in detset:
            try:
                # XXX: in theory, stop() can return True or False to indicate
                # whether saving makes sense.
                #
                # However, it might be better to leave that to the data sink
                # handling the INTERRUPTED quality.
                det.stop()
                res = det.readResults(INTERRUPTED)
            except Exception:
                det.log.exception('error reading measurement data')
                res = None
            try:
                dataman.putResults(INTERRUPTED, {det.name: res})
            except Exception:
                det.log.exception('error saving measurement data')
        reraise(*exc_info)
    finally:
        point.finished = currenttime()
        session.endActionScope()
Beispiel #12
0
    def _stopFailed(self, step, action, exc_info):
        """Called whenever a stop failed with an exception.

        Default is to re-raise the exception.
        """
        reraise(*exc_info)
Beispiel #13
0
def multiWait(devices):
    """Wait for the *devices*.

    Returns a dictionary mapping devices to current values after waiting.

    This is the main waiting loop to be used when waiting for multiple devices.
    It checks the device status until all devices are OK or errored.

    Errors raised are handled like in the following way:
    The error is logged, and the first exception with the highest serverity
    (exception in `CONTINUE_EXECPTIONS` < `SKIP_EXCPTIONS` < other exceptions)
    is re-raised at the end.

    *baseclass* allows to restrict the devices waited on.
    """
    from nicos.core.device import Waitable

    def get_target_str():
        return ', '.join(
            '%s -> %s' %
            (dev,
             dev.format(dev.target)) if hasattr(dev, 'target') else str(dev)
            for dev in reversed(devlist))

    delay = 0.3
    final_exc = None
    devlist = list(devIter(devices, baseclass=Waitable, allwaiters=True))
    session.log.debug('multiWait: initial devices %s, all waiters %s', devices,
                      devlist)
    values = {}
    loops = -2  # wait 2 iterations for full loop
    eta_update = 1 if session.mode != SIMULATION else 0
    first_ts = currenttime()
    session.beginActionScope('Waiting')
    eta_str = ''
    target_str = get_target_str()
    session.action(target_str)
    try:
        while devlist:
            session.log.debug('multiWait: iteration %d, devices left %s',
                              loops, devlist)
            loops += 1
            for dev in devlist[:]:
                try:
                    done = dev.isCompleted()
                    if done:
                        dev.finish()
                except Exception:
                    final_exc = filterExceptions(sys.exc_info(), final_exc)
                    # remove this device from the waiters - we might still have
                    # its subdevices in the list so that multiWait() should not
                    # return until everything is either OK or ERROR
                    devlist.remove(dev)
                    if devlist:
                        # at least one more device left, show the exception now
                        dev.log.exception('while waiting')
                    continue
                if not done:
                    # we found one busy dev, normally go to next iteration
                    # until this one is done (saves going through the whole
                    # list of devices and doing unnecessary HW communication)
                    if loops % 10:
                        break
                    # every 10 loops, go through everything to get an accurate
                    # display in the action line
                    continue
                if dev in devices:
                    # populate the results dictionary, but only with the values
                    # of excplicitly given devices
                    values[dev] = dev.read()
                # this device is done: don't wait for it anymore
                devlist.remove(dev)
                target_str = get_target_str()
                session.action(eta_str + target_str)
            if devlist:
                if eta_update >= 1:
                    eta_update -= 1
                    now = currenttime()
                    eta = {dev.estimateTime(now - first_ts) for dev in devlist}
                    eta.discard(None)
                    # use max here as we wait for ALL movements to finish
                    eta_str = ('estimated %s left / ' %
                               formatDuration(max(eta)) if eta else '')
                    session.action(eta_str + target_str)
                session.delay(delay)
                eta_update += delay
        if final_exc:
            reraise(*final_exc)
    finally:
        session.endActionScope()
        session.log.debug('multiWait: finished')
    return values