EPICS Controls Argonne National Laboratory

Experimental Physics and
Industrial Control System

2002  2003  2004  <20052006  2007  2008  2009  2010  2011  2012  2013  2014  2015  2016  2017  2018  2019  2020  2021  2022  2023  2024  Index 2002  2003  2004  <20052006  2007  2008  2009  2010  2011  2012  2013  2014  2015  2016  2017  2018  2019  2020  2021  2022  2023  2024 
<== Date ==> <== Thread ==>

Subject: Re: [Fwd: Re: Link arrays / syntax]
From: Marty Kraimer <[email protected]>
To: [email protected]
Cc: Benjamin Franksen <[email protected]>
Date: Tue, 18 Oct 2005 08:22:30 -0500
Sorry I waited so long to respond but my mind was distraced with other matters.

Before starting on benjamin's message in details I do like "asyn" instead of "wait". But perhaps callback is even better with callback=true meaning that link support will call a callback when the link completes. Either asyn or callback is better than wait.

For now I will still use wait.

Now for Benjamin's message.

I am concerned about how complex it will be to implement something like what Benjamin is proposing.

The original proposal uses "block" to mean no further record processing until this link and all previous links complete. Bemjamin's proposal uses "after" to mean the this link (or something more generic) should not be processed until a list of other links (or something more generic) completes.

The proposal to have just

process - boolean, i.e. should request be made to process record
wait - boolean, i.e. link is not complete until linked record completes processing block - boolean, i.e. dont do any more record processing until link completes

Could be implemented easily as follows:

When link support returns it specifies 1) If wait is true, i.e. it will call a callback when the link completes and 2) If block is true. If wait is true Record support incremements a counter indicating how many callbacks are outstanding. If block is true, record support will not do any more record processing until all outstanding callbacks complete.

This is simple and efficient. Is it intuitive for the Application Developer?
With regards to the example of the array of processLink, I say yes.
The application developer has control of the order. If the definition is:

processLink = [3] {
       {pvname = "incA"; wait=true},
       {pvname = "incB"; wait=true,block=true},
       {pvname = "getSample"; wait=true;}
}

The link for getSample will not be requested until both incA and incB complete. I think this is intuitive.
There is a problem for separate link fields rather than an array of links.
Now the order in which the fields appear in the record matter. The order can never be changed or databases will break.

Adding plugin's via support for structs, which I fully support, adds additional compexity.
Now what should record support do?

If the struct support also returns a wait and block status then I see no problem. The application developer still decides. The only restriction is the the order of links in the struct
and the link,struct definitions in the record can not be changed.

I still maintain that it is intutive for the developer.

A struct support, just like link support, always returns a wait and block state.

Maintaining after lists sounds complex to implement. Is it more intuitive for the database developer? Not clear to me.

Marty


Benjamin Franksen wrote:

On Thursday 29 September 2005 17:40, Marty Kraimer wrote:
Ralph Lange wrote:
menu(LinkWait) {
choice(linkWaitNo,"no")
choice(linkWaitYes,"yes")
choice(linkWaitGroup,"group")
}

struct(ProcessLink) {
field(pvname,string) { link}
field(wait,menu(LinkWait))
field(delay,double64)
}

so that the example is:

void collectSample=processLink=[3] {
{pvname="incA”; wait=group},
{pvname="incB”; wait=group,delay=1.0},
{pvname="getSample”; wait=yes,delay=5.0}
}
}

Let us ignore the proposal to add timeouts or delays, for the moment.

I share Ralph's sentiment about loss of symmetry, but his proposal has a drawback: It can't express adjacent but separate parallel groups. Suppose we want to have processLink[0] and processLink[1] to be processed in paralel, wait for both of them to complete, then process processLink[2] and processLink[3] in paralel, too, then wait for them to complete, and finally complete processing. This is not possible with Ralph's 'group' approach, because 'wait=group' always groups /all/ adjacent links with this property.

Speaking generally, I think the whole problem stems from a too low-level, that is, implementation-oriented view of how links get processed. See, for instance, Kay's remark that "'parallel' is meant as a 'execute in fork'"; see also the (implicit) assumption that the links get (somehow, more or less, that is, "modulo parallel flags") processed in the order they appear in the processLink array. All this makes it a bit hard to reason about the semantics of the link specification.

So, let us for the moment forget that the process links are given in a certain order and instead view them as an un-ordered set of independent entities. We would then need to specify for each of them

(a) whether it should 'complete' immediately or only after the record it references has completed its processing, and

(b) which other links must have completed processing, before this link can start processing.

As regards (a), this is easily done with a boolean flag. I propose to name it 'async' with a default value of 'false'.

With regard to (b), this could be an (unordered) list of other /links/. To specify the identity of a link, we could use it's index in the array. The property could be named 'after', with a default value of {} (empty set).

Thus my (first) proposal:

void collectSample={
   processLink = [3] {
       {pvname = "incA"; async=true},
       {pvname = "incB"; async=true},
       {pvname = "getSample"; async=true; after={0,1}}
   }
}

There is still one problem with this: we cannot yet specify when the record /containing/ the links should complete it's own processing. I can imagine a number of ad-hoc solutions, like adding a special field, maybe grouped to gether with the process links into a struct, whatever.

However, let us again take a step back and review the problem from a high-level perspective.

First, note that firing one of the process links on the one hand, and completion of the record's processing on the other hand, are both merely two special steps (actions) to be performed at certain times as part of general record processing. The fact that they are so tightly coupled is, I think, a legacy of the way dbPut completion was hacked into V3. I can't see any reason why this must remain so.

Second, the new record processing semantics already subdivides record processing into a number of steps.

Third, remember Kay's idea for plugging additional functionality into record processing at certain predefined 'slots'.

There is a pattern here, I think. It suggests the following generalization of the above proposal. Note that these are quite raw ideas.

Each step of processing gets associated with a record field. This field specifies its trigger condition in a declarative way in the form of a list of dependent entities owned by the record. The meaning is that all these entities must have completed their own processing, before this one can start its processing. These 'entities' can be:

o input, output, or process links
o subentities like an embedded struct with it's own support
o maybe additional components, plugged-in at record creation time,
  or even online
o a certain number of fixed points, one of them record process finish

All these things have the common attribute 'after' (or whatever it is called). All predefined link types, processing steps, and all subentities of fixed type (struct+support) have a default value for this property declared in the dbd file. For instance, the default for the "record finish field" is 'after={processLink}', meaning "record processing has finished after all process links have". (This is with the understanding that naming an array means "all its elements"; we could also define some sort of scoping, i.e. inside an array of links, it would be sufficient to give the index to identify another one of those links. Inside a struct, the tag would suffice, etc.)

Processing steps that are specific to a certain record type can be reflected as fields that also have this property. Additionally, the DB designer (maybe also the record type designer) can give any such fields other values, thereby overriding the redefined behavior in a controlled way. Individual proocess links, for instance, could be fired at any time during record processing, not only at the end (although this would be the default).

Any comments?

Ben


Replies:
Re: Link arrays / syntax Ralph Lange
Re: [Fwd: Re: Link arrays / syntax] Benjamin Franksen
References:
[Fwd: Re: Link arrays / syntax] Marty Kraimer
Re: [Fwd: Re: Link arrays / syntax] Benjamin Franksen

Navigate by Date:
Prev: Re: ICALEPCS and EPICS iocCore V4 Benjamin Franksen
Next: FW: Ice GPL based Licensing Jeff Hill
Index: 2002  2003  2004  <20052006  2007  2008  2009  2010  2011  2012  2013  2014  2015  2016  2017  2018  2019  2020  2021  2022  2023  2024 
Navigate by Thread:
Prev: Re: [Fwd: Re: Link arrays / syntax] Benjamin Franksen
Next: Re: Link arrays / syntax Ralph Lange
Index: 2002  2003  2004  <20052006  2007  2008  2009  2010  2011  2012  2013  2014  2015  2016  2017  2018  2019  2020  2021  2022  2023  2024 
ANJ, 02 Feb 2012 Valid HTML 4.01! · Home · News · About · Base · Modules · Extensions · Distributions · Download ·
· Search · EPICS V4 · IRMIS · Talk · Bugs · Documents · Links · Licensing ·