Example #1
0
    def test_unsubscribe_scan(self):
        controller.subscribe(self.long_pvs[0], SubscriptionMode.Scan(period=1))

        #check that the system has registered the subscription
        apv = controller.get_apv(self.long_pvs[0])
        self.assertEqual( apv.name, self.long_pvs[0] )

        # wait for a while so that we gather some data 
        time.sleep(3)

        # request unsubscription
        unsub_req = controller.unsubscribe(self.long_pvs[0])
        self.assertTrue(unsub_req)
        unsub_req.wait()
        before = controller.get_values(self.long_pvs[0])

        # verify that the system has removed the pv
        apv = controller.get_apv(self.long_pvs[0])
        self.assertFalse(apv.subscribed)

        # wait to see if we are still receiving data 
        time.sleep(3)
        after = controller.get_values(self.long_pvs[0])

        # we shouldn't have received any data during the last sleep period
        self.assertEqual(len(before), len(after))

        # and the scan task's timer should have been cleaned up
        self.assertEqual(controller.timers.num_active_tasks, 0)
Example #2
0
    def test_get_values_throttled(self):
        # give it time to gather some data
        wait_for = 5
        ioc_freq = 10 # Hz
        max_archiving_freq = 5 # Hz

        mode = SubscriptionMode.Monitor(delta=0.01,max_freq=max_archiving_freq)
        self.test_subscribe(mode)

        time.sleep(wait_for) 

        no_values = controller.get_values('test:doesntexist')
        self.assertEqual(no_values['rows'], [])

        for pvset in (self.long_pvs, self.double_pvs):
            for pv in pvset:
                values = controller.get_values(pv)
                logger.info("Received %d values for '%s' after %d seconds at %d Hz", \
                        len(values['rows']), pv, wait_for, max_archiving_freq)

                # diferences in timestamp shouldn't exceed 1/max_archiving_freq (period) 
                max_period = 1/max_archiving_freq
                for i in range(len(values['rows'])-1):
                    ith = values['rows'][i]['timestamp']
                    ip1th = values['rows'][i+1]['timestamp'] 
                    self.assertGreaterEqual( ith-ip1th, max_period) 
Example #3
0
    def test_unsubscribe_monitor(self):
        pvname = self.long_pvs[0]
        controller.subscribe(pvname, SubscriptionMode.Monitor(delta=0.01))

        #check that the system has registered the subscription
        apv = controller.get_apv(pvname)
        self.assertEqual( apv.name, self.long_pvs[0] )

        # wait for a while so that we gather some data 
        time.sleep(2)

        # request unsubscription
        unsub_req = controller.unsubscribe(self.long_pvs[0])
        self.assertTrue(unsub_req)
        unsub_req.wait()
        # take note of the data present
        before = controller.get_values(self.long_pvs[0])['rows']

        # verify that the system has removed the pv
        apv = controller.get_apv(self.long_pvs[0])
        self.assertFalse(apv.subscribed)

        # wait to see if we are still receiving data 
        time.sleep(2)
        after = controller.get_values(self.long_pvs[0])['rows']

        # we shouldn't have received any data during the last sleep period
        self.assertEqual(len(before), len(after))
Example #4
0
    def test_get_values_by_date(self):
        self.test_subscribe()

        wait_for = 5
        start = datetime.datetime.now()
        halftime = start + datetime.timedelta(seconds=wait_for/2.0)
        halftime_ts = time.mktime( halftime.timetuple())
 
        time.sleep(wait_for) 

        # test "up to" semantics, open interval on the left
        for pvset in (self.long_pvs, self.double_pvs):
            for pv in pvset:
                all_values = controller.get_values(pv, limit=2**30)
                upto_values = controller.get_values(pv, to_date=halftime, limit=2**30) # first half
                from_values = controller.get_values(pv, from_date=halftime, limit=2**30) # second half
                ts = time.mktime( halftime.timetuple())
                for v in upto_values['rows']:
                    self.assertLessEqual(v['timestamp'], ts)
                for v in from_values['rows']:
                    self.assertGreaterEqual(v['timestamp'], ts)

                # it may happen that new values arrive between the gathering of values and the
                # counting colums operation
                self.assertLessEqual(len(all_values['rows']), all_values['meta']['total'])
                self.assertLessEqual(len(upto_values['rows']), upto_values['meta']['total'])
                self.assertLessEqual(upto_values['meta']['last_ts'], halftime_ts)
                self.assertGreaterEqual(from_values['meta']['first_ts'], halftime_ts)
                self.assertLessEqual(len(from_values['rows']), from_values['meta']['total'])


                # it's >= because there may be some overlap, due to the loss of precision in the
                # timestamp we use in the get_values call
                self.assertGreaterEqual( len(upto_values['rows'])+len(from_values['rows']), len(all_values['rows']) )
Example #5
0
    def test_subscribe_scan(self):
        for pv in self.pvs[:4]:
            self.assertEqual(len(controller.get_values(pv)['rows']), 0)

        periods = (1,1.5, 2, 2.1)
        for pv,p in zip(self.pvs[:4], periods):
            controller.subscribe(pv, SubscriptionMode.Scan(period=p))

        sleep_for = 10
        time.sleep(sleep_for)
        
        for pv,p in zip(self.pvs[:4], periods):
            res = controller.get_values(pv)['rows']
            self.assertAlmostEqual(sleep_for/p, len(res), delta=1)
Example #6
0
    def test_get_values(self):
        self.test_subscribe()

        # give it time to gather some data
        wait_for = 10
        ioc_freq = 10 # Hz
        time.sleep(wait_for) # ioc generates values at 1 Hz
        expected_num_values = wait_for * ioc_freq

        # doesn't exist AND never subscribed
        no_values = controller.get_values('test:doesntexist')
        self.assertEqual(no_values['rows'], [])
        self.assertEqual(no_values['meta']['total'], 0)

        for longpv in self.long_pvs:
            values = controller.get_values(longpv, limit=expected_num_values)
            rows = values['rows']
            logger.info("Received %d values after %d seconds at %d Hz", len(rows), wait_for, ioc_freq)
            self.assertEqual(len(rows), expected_num_values)
            # we don't really know how for from a change the PV is. We 
            # can only guarantee that we'll get expected_num_values 
            # updates during our sleep period
            first_value = int(rows[0]['value'])
            for (i,value) in enumerate(rows):
                self.assertEqual(longpv, value['pvname'])
                self.assertEqual('long', value['type'])
                self.assertEqual(first_value-i, int(value['value']))

        for doublepv in self.double_pvs:
            values = controller.get_values(doublepv, limit=expected_num_values)
            rows = values['rows']
            logger.info("Received %d values after %d seconds at %d Hz", len(rows), wait_for, ioc_freq)
            self.assertEqual(len(rows), expected_num_values)
            first_value = float(rows[0]['value'])
            print(first_value)
            for (i,value) in enumerate(rows):
                self.assertEqual(doublepv, value['pvname'])
                self.assertEqual('double', value['type'])
                self.assertEqual(first_value-i, float(value['value']))

        for fakepv in self.fake_pvs:
            values = controller.get_values(fakepv)
            # they don't exist but we subscribed to them. Expect entries with null values
            rows = values['rows']
            for row in rows:
                self.assertIsNone(row['value'])
Example #7
0
    def test_get_values_disconnected(self):
        conn_ts = datastore._get_timestamp_ms()
        futures = [ controller.subscribe(pv, SubscriptionMode.Monitor(delta=0.01)) \
                     for pv in self.existing_pvs ]
        results = [ fut.get() for fut in futures ]
        time.sleep(2)
        # when a pv gets disconnected, NaN should be stored as its value. 
        # moreover, the pv's status should reflect the disconnection at that
        # point in time
        for pv in self.existing_pvs:
            statuses = controller.get_statuses(pv)
            self.assertTrue(statuses)
            status = statuses[0]
            self.assertTrue(status['connected'])

            last_values = controller.get_values(pv)
            self.assertTrue(last_values['rows'])
            last_value = last_values['rows'][0]
            self.assertGreater(last_value['archived_at_ts'], conn_ts)
            self.assertGreater(last_value['value'], 1)


        predisconn_ts = datastore._get_timestamp_ms()
        _block_ioc(True)
        time.sleep(35)
        postdisconn_ts = datastore._get_timestamp_ms()

        for pv in self.existing_pvs:
            statuses = controller.get_statuses(pv)
            self.assertTrue(statuses)
            status = statuses[0]
            self.assertFalse(status['connected'])

            last_values = controller.get_values(pv)
            self.assertTrue(last_values['rows'])
            last_value = last_values['rows'][0]
            self.assertGreater(last_value['archived_at_ts'], predisconn_ts)
            self.assertGreater(postdisconn_ts, last_value['archived_at_ts'])
            self.assertIsNone(last_value['value'])

        _block_ioc(False)
Example #8
0
    def test_constant_value_scan(self):
        pv = self.nonchanging_pvs[0]
        controller.subscribe(pv, SubscriptionMode.Scan(period=1))

        time.sleep(4)

        values = controller.get_values(self.nonchanging_pvs[0])
        rows = values['rows']
        self.assertGreaterEqual(len(rows), 3)
        self.assertLessEqual(len(rows), 4)
        last_value = rows[-1] # ie, oldest
        for i,value in enumerate(reversed(rows[:-1])):
            self.assertAlmostEqual(value['archived_at_ts']-(i+1)*1e6, last_value['archived_at_ts'], delta=0.1*1e6)
            self.assertEqual(value['timestamp'], last_value['timestamp'])
Example #9
0
    def test_get_values_delta(self):
        # give it time to gather some data
        wait_for = 10
        ioc_freq = 10 # Hz
        delta = 2

        mode = SubscriptionMode.Monitor(delta=delta)
        self.test_subscribe(mode)

        time.sleep(wait_for) 

        no_values = controller.get_values('test:doesntexist')
        self.assertEqual(no_values['rows'], [])

        for pvset in (self.long_pvs, self.double_pvs):
            for pv in pvset:
                values = controller.get_values(pv)
                rows = values['rows']
                logger.info("Received %d values for '%s' after %d seconds", \
                        len(rows), pv, wait_for)
                for i in range(len(rows)-1):
                    ith = rows[i]['value']
                    ip1th = rows[i+1]['value'] 
                    self.assertGreaterEqual( ith-ip1th, delta) 
Example #10
0
    def get(self, pvname):
        fields = self.get_arguments("field")
        limit = int(self.get_argument("limit", default=10))
        from_ts = self.get_argument("from_ts", default=None)
        to_ts = self.get_argument("to_ts", default=None)

        nextpage = self.get_argument("nextpage", None)
        prevpage = self.get_argument("prevpage", None)

        reverse = True
        if nextpage:
            from_ts = nextpage
        if prevpage:
            from_ts = prevpage
            reverse = False

        next_url = None
        prev_url = None
        at_first_page = False

        rows = controller.get_values(pvname, fields, limit + 1, from_ts, to_ts, reverse)
        count_total = controller.get_count(pvname)
        count_remaining = controller.get_count(pvname, from_ts)

        if prevpage:  # we come from a prevpage link
            # if a prevpage has been requested while already at the first page,
            # a single row is returned, that with the prevpage's pointer value
            # in its archived_at_ts field
            at_first_page = len(rows) == 1
            if not at_first_page:
                rows.reverse()

        if rows:
            # check if we are at the end
            if len(rows) > limit or at_first_page:  # not at the end
                last = rows.pop()
                next_ts = last["archived_at_ts"]
            else:  # at the end
                next_ts = None

            current_url = self.request.full_url()
            url_parts = urlparse.urlparse(current_url)
            qargs = urlparse.parse_qsl(url_parts.query)
            qargs[:] = [qarg for qarg in qargs if (qarg[0] not in ("nextpage", "prevpage"))]

            if next_ts:
                qargs.append(("nextpage", next_ts))
                qs = urllib.urlencode(qargs)
                next_url = urlparse.urlunparse(url_parts._replace(query=qs))
                qargs.pop()  # restore, get ready for prevpage

            if not at_first_page:
                curr_hdr_st = rows[0]["archived_at_ts"]

                qargs.append(("prevpage", curr_hdr_st))
                qs = urllib.urlencode(qargs)
                prev_url = urlparse.urlunparse(url_parts._replace(query=qs))

        self.win(
            {
                "rows": rows,
                "count_total": count_total,
                "count_remaining": count_remaining,
                "nextpage": next_url,
                "prevpage": prev_url,
            }
        )