[PEAK] Re: Trellis: Sensor.listening and iter_listeners()

Sergey Schetinin maluke at gmail.com
Wed Nov 12 13:33:29 EST 2008


The problem is caused by initialization not being undo-logged, so when
the rule is initialized, its _process_reads sets .next_listener of
some Sensor, but the Link creation is not undo-logged. Later, it all
gets rolled back, and the schedule(self.update_connection) vanishes
from the ctrl.commit, but the .next_listener is not rolled back, so
next time the dependency is recreated was_seen is True and the
_set_listener decides there's no need to schedule update_connection,
so it never runs. Removing one "if undo" condition in final part of
the _process_reads fixes the problem. Trellis test suite never passes
for me (hangs up on "testSequentialCalls
(test_trellis.TestReactorEventLoop) ..."), so I'm not sure if this
breaks anything else.

Initialization is once again a culprit of a hard to detect bug. =)



On Wed, Nov 12, 2008 at 20:16, Sergey Schetinin <maluke at gmail.com> wrote:
> Switching to a manager instead of scheduling update_connection
> pseudo-rule fixed the issue.
>
> from peak.util.addons import AddOn
>
> class UpdateConnection(AddOn):
>    def __init__(self, sensor):
>        self.sensor = sensor
>
>    def __enter__(self):
>        pass
>
>    def update_connection(self):
>        sensor = self.sensor
>        descr = type(sensor).listening
>        listening = descr.__get__(sensor)
>        if sensor.next_listener is not None:
>            if listening is NOT_GIVEN:
>                descr.__set__(sensor, sensor.connector.connect(self))
>        elif listening is not NOT_GIVEN:
>            sensor.connector.disconnect(sensor, listening)
>            descr.__set__(sensor, NOT_GIVEN)
>
>    def __exit__(self, *args):
>        self.update_connection()
>        self.delete_from(self.sensor)
>
>
> then manage(UpdateManager(self)) or
>
> from contextlib import contextmanager
>
>    @property
>    def upd_manager(self):
>        if not self._upd_manager:
>            self._upd_manager = self.make_upd_manager()
>        return self._upd_manager
>
>    @contextmanager
>    def make_upd_manager(self):
>        yield
>        descr = type(self).listening
>        listening = descr.__get__(self)
>        if self.next_listener is not None:
>            if listening is NOT_GIVEN:
>                descr.__set__(self, self.connector.connect(self))
>        elif listening is not NOT_GIVEN:
>            self.connector.disconnect(self, listening)
>            descr.__set__(self, NOT_GIVEN)
>        if not isinstance(self, ConstantMixin):
>            self._upd_manager = None
>
> then manage(self.upd_manager).
>
>
>
>
>
> On Wed, Nov 12, 2008 at 19:24, Sergey Schetinin <maluke at gmail.com> wrote:
>> After adding `if self.update_connection not in pending:
>> on_undo(pending.remove, self.update_connection)` in relevant places,
>> the printed counts show that all of them get called, so this has to be
>> something else.
>>
>>
>> On Wed, Nov 12, 2008 at 18:25, Sergey Schetinin <maluke at gmail.com> wrote:
>>> I forgot to mention that the same debug prints were added to
>>> LazyCell.run right after scheduling of update_connection.
>>>
>>> On Wed, Nov 12, 2008 at 18:19, Sergey Schetinin <maluke at gmail.com> wrote:
>>>> I tracked this down to the fact that not all scheduled
>>>> update_connection get called.
>>>>
>>>> In attempt to find out how often does this happen I added the
>>>> following to SensorBase._set_listener (`pending` refers to a global
>>>> set())
>>>>
>>>>            print len(pending), '++'
>>>>            pending.add(self)
>>>>
>>>>  and in update_connection
>>>>
>>>>            print len(pending), '--'
>>>>            pending.remove(self)
>>>>
>>>> And the printed counts don't go back to 1 even for tests that seem to
>>>> work correctly. Am I missing something?
>>>>
>>>>
>>>>
>>>>
>>>> On Wed, Nov 12, 2008 at 16:18, Sergey Schetinin <maluke at gmail.com> wrote:
>>>>> I tracked one of the issues I was having periodically to a case when a
>>>>> sensor did not connect when it should have.
>>>>>
>>>>>>>> evt_cell
>>>>> Sensor(<bound method PyEventBinder._events of <wx._core.PyEventBinder
>>>>> object at 0x00E5DD10>>, None, discrete[None])
>>>>>>>> evt_cell.listening
>>>>> NOT_GIVEN
>>>>>>>> list(evt_cell.iter_listeners())
>>>>> [WxCell(221), WxCell(392)]
>>>>>
>>>>> This state is invalid, correct?
>>>>>
>>>>>
>>>>> --
>>>>> Best Regards,
>>>>> Sergey Schetinin
>>>>>
>>>>> http://s3bk.com/ -- S3 Backup
>>>>> http://word-to-html.com/ -- Word to HTML Converter
>>>>>
>>>>
>>>>
>>>>
>>>> --
>>>> Best Regards,
>>>> Sergey Schetinin
>>>>
>>>> http://s3bk.com/ -- S3 Backup
>>>> http://word-to-html.com/ -- Word to HTML Converter
>>>>
>>>
>>>
>>>
>>> --
>>> Best Regards,
>>> Sergey Schetinin
>>>
>>> http://s3bk.com/ -- S3 Backup
>>> http://word-to-html.com/ -- Word to HTML Converter
>>>
>>
>>
>>
>> --
>> Best Regards,
>> Sergey Schetinin
>>
>> http://s3bk.com/ -- S3 Backup
>> http://word-to-html.com/ -- Word to HTML Converter
>>
>
>
>
> --
> Best Regards,
> Sergey Schetinin
>
> http://s3bk.com/ -- S3 Backup
> http://word-to-html.com/ -- Word to HTML Converter
>



-- 
Best Regards,
Sergey Schetinin

http://s3bk.com/ -- S3 Backup
http://word-to-html.com/ -- Word to HTML Converter



More information about the PEAK mailing list