test_nxw_readers.py 4.63 KB
Newer Older
Wout De Nolf's avatar
Wout De Nolf committed
1
2
3
4
# -*- coding: utf-8 -*-
#
# This file is part of the bliss project
#
Benoit Formet's avatar
Benoit Formet committed
5
# Copyright (c) 2015-2020 Beamline Control Unit, ESRF
Wout De Nolf's avatar
Wout De Nolf committed
6
7
8
9
10
# Distributed under the GNU LGPLv3. See LICENSE for more info.

import gevent
import pytest
from bliss.common import scans
11
from bliss.common.tango import DevState
Wout De Nolf's avatar
Wout De Nolf committed
12
13
from nexus_writer_service.utils import scan_utils
from nexus_writer_service.io import nexus
14
15
from tests.nexus_writer.helpers import nxw_test_data
from tests.nexus_writer.helpers import nxw_test_utils
Wout De Nolf's avatar
Wout De Nolf committed
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43


def test_nxw_readers(nexus_writer_config):
    _test_nxw_readers(mode="r", enable_file_locking=False, **nexus_writer_config)


def test_nxw_readers_lock(nexus_writer_config):
    _test_nxw_readers(mode="r", enable_file_locking=True, **nexus_writer_config)


def test_nxw_readers_append(nexus_writer_config):
    _test_nxw_readers(mode="a", enable_file_locking=False, **nexus_writer_config)


def test_nxw_readers_appendlock(nexus_writer_config):
    _test_nxw_readers(mode="a", enable_file_locking=True, **nexus_writer_config)


@nxw_test_utils.writer_stdout_on_exception
def _test_nxw_readers(
    mode="r",
    enable_file_locking=False,
    session=None,
    tmpdir=None,
    writer=None,
    config=True,
    **kwargs
):
44
    session.scan_saving.dataset.all.definition = "none"
45
46
47
48
    detector = "diode3"
    detectorobj = session.env_dict[detector]

    # make sure the file exists
49
    filename = scan_utils.session_filename(scan_saving=session.scan_saving)
50
    scans.sct(0.1, detectorobj, save=True)
51
52

    # start readers
Wout De Nolf's avatar
Wout De Nolf committed
53
    startevent = gevent.event.Event()
Wout De Nolf's avatar
Wout De Nolf committed
54
    readerkwargs = {"mode": mode, "enable_file_locking": enable_file_locking}
Wout De Nolf's avatar
Wout De Nolf committed
55
56
57
58
59
    readers = [
        gevent.spawn(reader, filename, startevent, hold=i == 0, **readerkwargs)
        for i in range(4)
    ]
    startevent.wait()
60
61

    # start scan
Wout De Nolf's avatar
Wout De Nolf committed
62
63
    try:
        if mode == "a" and not enable_file_locking:
64
            # Readers will not crash the writer (not sure why) but corrupt the file
Wout De Nolf's avatar
Wout De Nolf committed
65
            scan_shape = (100,)
66
            scan = scans.loopscan(scan_shape[0], .1, detectorobj, run=False)
Wout De Nolf's avatar
Wout De Nolf committed
67
            nxw_test_utils.run_scan(scan)
68
69
            # We can only detect the corruption after closing the readers
            nxw_test_utils.wait_scan_finished([scan], writer=writer)
Wout De Nolf's avatar
Wout De Nolf committed
70
71
72
            gevent.killall(readers)
            gevent.joinall(readers)
            readers = []
73
            assert writer.proxy.scan_state(scan.node.name) == DevState.OFF
Wout De Nolf's avatar
Wout De Nolf committed
74
            with pytest.raises(AssertionError):
75
                nxw_test_utils.assert_scan_data_not_corrupt([scan])
Wout De Nolf's avatar
Wout De Nolf committed
76
        elif enable_file_locking:
77
78
            # Readers will crash the writer but not corrupt the file
            scan = scans.timescan(.1, detectorobj, run=False)
Wout De Nolf's avatar
Wout De Nolf committed
79
80
81
82
83
84
            with gevent.Timeout(10):
                with pytest.raises(RuntimeError):
                    nxw_test_utils.run_scan(scan)
            gevent.killall(readers)
            gevent.joinall(readers)
            readers = []
85
            assert writer.proxy.scan_state(scan.node.name) == DevState.FAULT
86
            nxw_test_utils.assert_scan_data_not_corrupt([scan])
Wout De Nolf's avatar
Wout De Nolf committed
87
88
89
        else:
            # Neither scan nor file are disturbed by these readers
            scan_shape = (100,)
90
            scan = scans.loopscan(scan_shape[0], .1, detectorobj, run=False)
Wout De Nolf's avatar
Wout De Nolf committed
91
92
93
94
            nxw_test_utils.run_scan(scan)
            gevent.killall(readers)
            gevent.joinall(readers)
            readers = []
95
            nxw_test_utils.wait_scan_finished([scan], writer=writer)
96
            nxw_test_utils.assert_scan_data_not_corrupt([scan])
Wout De Nolf's avatar
Wout De Nolf committed
97
            nxw_test_data.assert_scan_data(
98
99
100
101
102
                scan,
                scan_shape=scan_shape,
                positioners=[["elapsed_time", "epoch"]],
                detectors=[detector],
                **kwargs
Wout De Nolf's avatar
Wout De Nolf committed
103
104
105
106
107
108
109
110
111
112
113
114
115
116
            )
    finally:
        if readers:
            gevent.killall(readers)
            gevent.joinall(readers)


def reader(filename, startevent, hold=False, **kwargs):
    """This reader opens in different modes but only performs reading operations.
    """
    while True:
        gevent.sleep(0.1)
        try:
            with nexus.File(filename, **kwargs) as f:
117
118
                if hold:
                    startevent.set()
Wout De Nolf's avatar
Wout De Nolf committed
119
120
121
122
123
124
                while True:
                    gevent.sleep(0.1)
                    try:
                        for entry in f:
                            list(f[entry]["instrument"].keys())
                            list(f[entry]["measurement"].keys())
125
                    except BaseException:
Wout De Nolf's avatar
Wout De Nolf committed
126
127
128
129
130
131
                        pass
                    finally:
                        if not hold:
                            break
        except (KeyboardInterrupt, gevent.GreenletExit):
            break
132
        except BaseException:
Wout De Nolf's avatar
Wout De Nolf committed
133
            pass