fix initwrite behaviour

with handlers, a parameter from the cfg file which is not the
first of parameters with the same handler were not written.
fix: write_<param> method is called for all parameters in
<module>.writeDict even if there is no poll entry.

with this fix, the write_<method> is called even when a parameter
is not polled.
This commit is contained in:
l_samenv 2020-09-25 11:19:17 +02:00
parent 587b170f6a
commit f7576cf541
4 changed files with 38 additions and 35 deletions

View File

@ -346,16 +346,6 @@ class Module(HasProperties, metaclass=ModuleMeta):
def initModule(self): def initModule(self):
self.log.debug('empty %s.initModule()' % self.__class__.__name__) self.log.debug('empty %s.initModule()' % self.__class__.__name__)
def startModule(self, started_callback):
"""runs after init of all modules
started_callback to be called when thread spawned by late_init
or, if not implemented, immediately
might return a timeout value, if different from default
"""
self.log.debug('empty %s.startModule()' % self.__class__.__name__)
started_callback()
def pollOneParam(self, pname): def pollOneParam(self, pname):
"""poll parameter <pname> with proper error handling""" """poll parameter <pname> with proper error handling"""
try: try:
@ -367,23 +357,34 @@ class Module(HasProperties, metaclass=ModuleMeta):
except Exception: except Exception:
self.log.error(formatException()) self.log.error(formatException())
def writeOrPoll(self, pname): def writeInitParams(self, started_callback=None):
"""write configured value for a parameter, if any, else poll """write values for parameters with configured values
this must be called at the beginning of the poller thread
with proper error handling with proper error handling
""" """
try: for pname in list(self.writeDict):
if pname in self.writeDict: if pname in self.writeDict: # this might not be true with handlers
self.log.debug('write parameter %s', pname) try:
getattr(self, 'write_' + pname)(self.writeDict.pop(pname)) self.log.debug('initialize parameter %s', pname)
else: getattr(self, 'write_' + pname)(self.writeDict.pop(pname))
getattr(self, 'read_' + pname)() except SilentError:
except SilentError: pass
pass except SECoPError as e:
except SECoPError as e: self.log.error(str(e))
self.log.error(str(e)) except Exception:
except Exception: self.log.error(formatException())
self.log.error(formatException()) if started_callback:
started_callback()
def startModule(self, started_callback):
"""runs after init of all modules
started_callback to be called when the thread spawned by startModule
has finished its initial work
might return a timeout value, if different from default
"""
mkthread(self.writeInitParams, started_callback)
class Readable(Module): class Readable(Module):
@ -424,7 +425,7 @@ class Readable(Module):
# use basic poller for legacy code # use basic poller for legacy code
mkthread(self.__pollThread, started_callback) mkthread(self.__pollThread, started_callback)
else: else:
started_callback() super().startModule(self, started_callback)
def __pollThread(self, started_callback): def __pollThread(self, started_callback):
while True: while True:
@ -439,8 +440,7 @@ class Readable(Module):
def __pollThread_inner(self, started_callback): def __pollThread_inner(self, started_callback):
"""super simple and super stupid per-module polling thread""" """super simple and super stupid per-module polling thread"""
for pname in list(self.writeDict): self.writeInitParams()
self.writeOrPoll(pname)
i = 0 i = 0
fastpoll = self.pollParams(i) fastpoll = self.pollParams(i)
started_callback() started_callback()

View File

@ -115,7 +115,8 @@ class Parameter(Accessible):
settable=False, default=False), settable=False, default=False),
'handler': Property('[internal] overload the standard read and write functions', 'handler': Property('[internal] overload the standard read and write functions',
ValueType(), export=False, default=None, mandatory=False, settable=False), ValueType(), export=False, default=None, mandatory=False, settable=False),
'initwrite': Property('[internal] write this parameter on initialization (default None: write if given in config)', 'initwrite': Property('[internal] write this parameter on initialization'
' (default None: write if given in config)',
NoneOr(BoolType()), export=False, default=None, mandatory=False, settable=False), NoneOr(BoolType()), export=False, default=None, mandatory=False, settable=False),
} }
@ -139,11 +140,8 @@ class Parameter(Accessible):
datatype.setProperty('unit', unit) datatype.setProperty('unit', unit)
super(Parameter, self).__init__(**kwds) super(Parameter, self).__init__(**kwds)
if self.initwrite: if self.initwrite and self.readonly:
if self.readonly: raise ProgrammingError('can not have both readonly and initwrite!')
raise ProgrammingError('can not have both readonly and initwrite!')
if not self.poll:
raise ProgrammingError('only polled parameters can have initwrite!')
if self.constant is not None: if self.constant is not None:
self.properties['readonly'] = True self.properties['readonly'] = True

View File

@ -118,8 +118,10 @@ class Poller(PollerBase):
self._stopped = False self._stopped = False
self.maxwait = 3600 self.maxwait = 3600
self.name = name self.name = name
self.modules = [] # used for writeInitParams only
def add_to_poller(self, module): def add_to_poller(self, module):
self.modules.append(module)
factors = self.DEFAULT_FACTORS.copy() factors = self.DEFAULT_FACTORS.copy()
try: try:
factors[DYNAMIC] = module.fast_pollfactor factors[DYNAMIC] = module.fast_pollfactor
@ -227,11 +229,13 @@ class Poller(PollerBase):
# nothing to do (else we might call time.sleep(float('inf')) below # nothing to do (else we might call time.sleep(float('inf')) below
started_callback() started_callback()
return return
for module in self.modules:
module.writeInitParams()
# do all polls once and, at the same time, insert due info # do all polls once and, at the same time, insert due info
for _, queue in sorted(self.queues.items()): # do SLOW polls first for _, queue in sorted(self.queues.items()): # do SLOW polls first
for idx, (_, _, (_, module, pobj, pname, factor)) in enumerate(queue): for idx, (_, _, (_, module, pobj, pname, factor)) in enumerate(queue):
lastdue = time.time() lastdue = time.time()
module.writeOrPoll(pname) module.pollOneParam(pname)
due = lastdue + min(self.maxwait, module.pollinterval * factor) due = lastdue + min(self.maxwait, module.pollinterval * factor)
# in python 3 comparing tuples need some care, as not all objects # in python 3 comparing tuples need some care, as not all objects
# are comparable. Inserting a unique idx solves the problem. # are comparable. Inserting a unique idx solves the problem.

View File

@ -163,7 +163,8 @@ class Module:
def pollOneParam(self, pname): def pollOneParam(self, pname):
getattr(self, 'read_' + pname)() getattr(self, 'read_' + pname)()
writeOrPoll = pollOneParam def writeInitParams(self):
pass
def __repr__(self): def __repr__(self):
rdict = self.__dict__.copy() rdict = self.__dict__.copy()