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):
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):
"""poll parameter <pname> with proper error handling"""
try:
@ -367,23 +357,34 @@ class Module(HasProperties, metaclass=ModuleMeta):
except Exception:
self.log.error(formatException())
def writeOrPoll(self, pname):
"""write configured value for a parameter, if any, else poll
def writeInitParams(self, started_callback=None):
"""write values for parameters with configured values
this must be called at the beginning of the poller thread
with proper error handling
"""
try:
if pname in self.writeDict:
self.log.debug('write parameter %s', pname)
getattr(self, 'write_' + pname)(self.writeDict.pop(pname))
else:
getattr(self, 'read_' + pname)()
except SilentError:
pass
except SECoPError as e:
self.log.error(str(e))
except Exception:
self.log.error(formatException())
for pname in list(self.writeDict):
if pname in self.writeDict: # this might not be true with handlers
try:
self.log.debug('initialize parameter %s', pname)
getattr(self, 'write_' + pname)(self.writeDict.pop(pname))
except SilentError:
pass
except SECoPError as e:
self.log.error(str(e))
except Exception:
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):
@ -424,7 +425,7 @@ class Readable(Module):
# use basic poller for legacy code
mkthread(self.__pollThread, started_callback)
else:
started_callback()
super().startModule(self, started_callback)
def __pollThread(self, started_callback):
while True:
@ -439,8 +440,7 @@ class Readable(Module):
def __pollThread_inner(self, started_callback):
"""super simple and super stupid per-module polling thread"""
for pname in list(self.writeDict):
self.writeOrPoll(pname)
self.writeInitParams()
i = 0
fastpoll = self.pollParams(i)
started_callback()

View File

@ -115,7 +115,8 @@ class Parameter(Accessible):
settable=False, default=False),
'handler': Property('[internal] overload the standard read and write functions',
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),
}
@ -139,11 +140,8 @@ class Parameter(Accessible):
datatype.setProperty('unit', unit)
super(Parameter, self).__init__(**kwds)
if self.initwrite:
if self.readonly:
raise ProgrammingError('can not have both readonly and initwrite!')
if not self.poll:
raise ProgrammingError('only polled parameters can have initwrite!')
if self.initwrite and self.readonly:
raise ProgrammingError('can not have both readonly and initwrite!')
if self.constant is not None:
self.properties['readonly'] = True

View File

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

View File

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