HP3000-L Archives

October 1996, Week 1

HP3000-L@RAVEN.UTC.EDU

Options: Use Monospaced Font
Show Text Part by Default
Show All Mail Headers

Message: [<< First] [< Prev] [Next >] [Last >>]
Topic: [<< First] [< Prev] [Next >] [Last >>]
Author: [<< First] [< Prev] [Next >] [Last >>]

Print Reply
Subject:
From:
Jeff Vance <[log in to unmask]>
Reply To:
Jeff Vance <[log in to unmask]>
Date:
Thu, 3 Oct 1996 22:52:30 -0700
Content-Type:
text/plain
Parts/Attachments:
text/plain (384 lines)
Finally my reply to Stan's posting of a month ago.  It's kind of long, but
I have some important questions here that I hope some of you will
answer...

On Sep 5,  7:20pm, Stan Sieler wrote:
> Subject: Re: Design for System CI vars (long)
   Jeff Vance wrote:
> > A variable created by the CI or HPCIPUTVAR intrinsic that is accessible
>
> Possibly not via HPCIPUTVAR?

Shouldn't there be a programmatic equivalence to the CI functionality?  Or,
is using the [HPCI]COMMAND intrinsic sufficient, and if so then I assume
that HPCIPUTVAR, PUTJCW and SETJCW will have the same scope as today,
namely JOB/SESSION.

>
> > A variable created in the context of a UDC or command file (i.e, a script)
> > > via
> > a SETVAR command or setvar() function.  This
> > variable is accessible only within the script that created it.
Specifically,
> > it is not inherited by "children" scripts, nor is it accessible to
processes
>
Stan writes:
> *NO*  Inheritance is of extreme importance!
>
> For example, if I have a local variable called CIERROR, I expect, and *need*
> to have all child scripts that don't have their own CIERROR to use mine!
> Without this, you've given us a minimally useful feature.

This would occur if you had CIERROR defined as a JOB/SESSION var (as today).
If you execute a script that define its own CIERROR then throughout that
script all references to CIERROR would refer to the local one.  If you
execute a script without its own CIERROR then all references refer to the
JOB/SESSION one.  I know that Stans knows this and his comment is
directed towards process variables and not "scrip local" vars, but I
wanted to make that point.

Regarding process vars since several folks here have mentioned a need.
They are a bit tough assuming you want inheritance, i.e. all children
and grandchildren etc. processes inherit the variables of their parent.
Not coming from an OO background I may misuse terms, but here's my take:

Assume process A creates B and C, and that B creates D, and E and C creates F.
Process A creates a "process-local" var named VA1, which can be inherited
Here's some important questions.  1) Can VA1 be changed by any descendants of
process A? 2) If yes, does A see the change? 3) If 2) is no, is the change only
visible to the process that changed it, or to it and all descendants of it?

Eg. process A sets VA1 to 1, process B "inherits" VA1, process B sets VA1
to 2.  Who sees 2 when they reference VA1?  Process B is a good bet!
What does process A see and what do processes C and D see when they reference
VA1?  Who can delete VA1? Only process A?

If "inheritance" is make a local copy of the parent's vars then implementation
seems fairly straightforward. OTOH, if "inheritance" is really just making
a pointer to the parents vars available to the children then I think it will
be tougher to implement.

For the local copy case above I can have a known process object contain
all process local vars and I can populate this object with the parent's vars
when the child is created.  In this scenerio the parent does *not* see
changes made by its children.  This is the unix export model.

For the var pointer case ("pass by reference") each process needs an
array of pointers (how big?). The actual array is copied by value from
parent to child.  The order within the array is significant.  Why an array?
Suppose process A is the root process and sets VA1 to 1. A creates
processes B and C.  Proocess B gets a ptr to the area holding VA1.
B creates variable VB1, which is not accessible to process A (or C), thus B
creates an area to hold VB1.  B creates child process D.  D needs the ptr to
process A and process B's vars, thus D needs an array of ptrs.  The order is
important since, if process D is referencing a var, we need to look at D's
vars before B 's and before A's.

Another consideration: POSIX allows a parent process to die and its children
get adopted to a system process.  If process A dies then processes B, C, D,
and E cannot access any of the vars created by A (in the pass-by reference =
pointer model - no problem in the "make a copy model").  We could just delete
A's ptr from the var ptr array in each descendant of A.  This means we need
to know the pin associated with each cell(ptr) in this array.  Note: MPE/iX
does not support this feature of POSIX (yet).

Bottom line: we can implement either way of doing process local vars;
however, the "pass-by-reference" method is more difficult to implement and
possibly more difficult to use/explain.  Is there adequate justfication
for doing this method, or will the simplier make-a-copy way work?

ALSO, we need to define how fork/exec and POSIX vars work with all of
these new scoping rules.  Unfortunately POSIX vars are separate from CI
vars. Today a POSIX process gets a *copy* of the CI's vars and thus
cannot change any CI variables.

I forgot to mention that process local vars were not part of my original
proposal.  If you had system level vars, and some kind of script local vars
(so that your scripts have an independent environment, as far as vars are
concerned, to execute in) do you still need process local vars??
There has to be real value to you, not just a desire to make the CI a
"purer" programming language.


>
> The programming language precedence for historic scope (as opposed to
> the proposed static scope) is rich, with LISP being one of the early
> users.
>
> I can see, however, the need/desire to create 2 kinds of local variables:
>
>    1) strictly local ... not inherited
>       ...these variables simply cannot be altered or seen by any
>          child scripts/processes/UDCs.
>          This avoids accidental/deliberate interfering/tampering with
>          a parent script by trying to change its variables.

Agreed.  This was my thinking when trying to define "script-local" vars.  I
also see the value with process local vars.  The ptr to this area could
be the 1st entry in the array defined above with the rule that the 1st
entry of this array is not copied to children processes.

>
>    2) inherited local ... like CIVAR, *and others*.
>       ...these variables are automatically inherited, unless a child
>          script/UDC defines their own local variable.  Question: if script
>          A has an inherited local FOO, and calls B (which has a strict local
>          FOO), which then calls C which then accesses "FOO"...which FOO
>          does it get: none, or A's?  I don't particularly care, but would
>          suspect it get's A's.  (You search back the history stack, looking
>          for variables that match "FOO" and don't have "strictly local" bit
>          turned on)

Clarifications/assumptions: B is a script.  B calls script C.  Good
question since A, B, and C are scripts in this case and not processes
as in my example above.  Since they are all scripts they are *all* executing
on the CI's stack -- no new processes are created.  So are script local vars
really process local vars or define some new and different scope?

If script vars are really process vars then they belong to the CI process.
Since all scripts are executed in the same process thay all share the same
process vars.  Thus script B would be rescoping FOO or would get an error.
C would see the same FOO as A and B.  Note: the downside of this is
that (maybe) the script vars would not go away when the script exited.

OTOH, if script vars are not process local vars but a different scoping
all together then we need to define the rules.  If we also have process local
vars then we could apply that model to scripts.  Or we can try to make it
simplier...

Possible scoping (so far):
most global:   system vars
               [account vars?]
               job/session vars
               process local vars
most local:    script vars

Jeff wrote:
> > Script parameters are treated like script local variables except they
cannot
> > be deleted.  This allows a script to change the value of a parameter.
 (Note
> > parameters are always pass-by-value.)
Stan wrote:
>
>    Given my two kinds of locals, I'd assume that script params are
>    "strictly local", not inheritable.

Agreed.

Jeff wrote:
> > Need for local CI Variables:
> > ----------------------------
> >
> > There are 2 major reasons to have local variables: 1) a script using local
> > variables will not overwrite a variable of the same name in the job/session
> > scope,

Stan wrote:
> And, my "strictly local" adds the reason:
>    "and subscripts won't change/see a private variable in a script",
> and "inheritable" adds the reason:
>    "and subscripts will, by default, access the desired variable belonging
>    to the parent script"
>
> > 2) the local variable cannot be changed by other processes in the
> > same job/session.
>
>    Hmmm....it would be *real* useful for processes to be able to access
>    all inheritable local variables "above" them...like CIERROR!
>
Jeff wrote:
> > Example for 1: A well written command file saves the value of the
> > predefined
> > HPMSGFENCE variable, sets HPMSGFENCE to 2 and then restores the value prior
> > to
> > exiting.  Unfortunately if the script exits prematurely (due to a code path
> > that was not anticipated or because <break> was hit) HPMSGFENCE
> > remains set to 2 and the user won't see any CI error messages.
Stan wrote:
> It may be desirable to add another feature, one which isn't quite as robust
> as inheritable variables, but could still be useful:
>
>     PARM SAVE variablename          (or something)
>
> which would save the value of the variable and be guaranteed to restore
> it at script/UDC exit time (even if the script/UDC aborted or called RETURN).

Yes.  This is in my opinion one of the real benefits of some kind of
script local variable.  A script author doesn't need to worry about
cleaning up local vars.  (I know that there are TEMP files and file equations
that need to be accounted for still...)

>
> Thus, we could solve the HPMSGFENCE by doing:
>
>    PARM SAVE HPMSGFENCE
>    ...
>    SETVAR HPMSGFENCE ...
>    ...
>
> and rely on the automatic restoration of the value ... without introducing
> the concept of local & inheritable variables!

True.

>
> Note well: inheritable is a *must* without a "PARM SAVE" concept...how else
> can you guarantee that a local attempt to turn off messages will actually
> persist throughout multiple sub-scripts?  (short of changing the global
> value, which by definition is what we are trying to avoid)
>
> In short, inheritable is far more important than strictly local for
> local variables.
>
Jeff wrote:
> > monitoring.  OpC runs all of its scripts from a common job.  Each script
> > routinely sets and checks the CIERROR predefined variable.  When multiple
> > scripts are executing simultaneously they cannot determine if the command
> > they just executed was successful, since another script from another
> > process
> > may have just set CIERROR to 0 or to some error.
>
Stan wrote:
> The above is an excellent argument for inheritable local variables!

I see it as a better example for strictly local vars since each script
wants its own private copy of CIERROR. They are not communicating CIERROR
to the parent job.  Each script needs it own environment to execute in --
a common CIERROR makes it very error prone.

>
> BTW, "simultaneously"?  Do you mean:  session S1 has two processes
> running at the same time, each of which is executing scripts/UDCs?

Yes.

> If the
> top-level script/UDC of each process did:
>
>    LOCALVAR CIERROR                  /* inheritable */
>    ...
>    stuff...including scripts/UDCs, PROCESSES????
>    ...
>    if CIERORR <> ...
>    ...
>
> then only the inheritable local works ... and it works quite well.

Agreed, but in the OpC example we have this:

JOB:
create process A to do task 1
create process B to do task 2
...
create process N to do task z
eoj

Process A:
  setvar CIERROR 0
  run pgm1
  if CIERROR <> 0 then ...

Process B:
  setvar CIERROR 0
  run pgm2
  if CIERROR <> 0 then ...

You can see how processes A and B can stomp on the job/session scoped CIERROR.
Each process (or each script) needs it's own CIERROR to use.

> > 4) Some predefined variables should be "masked" (or hidden, or replaceable)
by
> > a local variable of the same name.  In this case the CI will reference the
> > local variable as if it were today's job/sesion variable.  E.g., local
> > HPPATH, HPMSGFENCE, CIERROR, HPCIERR should work.
>
> and inheritable!!!
>
> > 6a) Predefined "active function" variables (this means the variable's value
> > is a procedure to call to get the real value, e.g., HPACCOUNT, HPJOBNUM,
> > HPCPUNAME, etc.) only need to live in the system table -- no entries for
> > these variables need to be in each job/session table.
>
> Hmmm...when do we get the ability to associate a system/session/local
variable
> with an XL:procedurename ?

Not yet....
And thinking more about this "internal" objective that definitely make things
more complicated... I would like to come up with a design that meets the main
customer needs and then see if we can fit this in for almost free.  If not
then I'll drop this objective.  In other words, it is not a high priority
of mine to try to reduce the redundancy that exists today with many of our
predefined HP vars.  Eg. the HPCONSOLE var lives in every job and session's
var table when it really only needs to be in the (single) system var table.
Doing this can get a little tricky and I don't wnat this to bias the basic
design.

>
> E.g.:
>
>    :setvar check_light "XL.PROG.TEST:get_check_light:set_check_light"
"integer"
>
> then,
>    :calc check_light
> would do:
>     try
>        i := get_check_light (simplified standard CI header)
>     return
>        i
>
> and:
>     setvar check_light 9
> would do:
>    try
>       set_check_light (simplified standard CI header, 9);
>
> This would provide incredible power and flexibility to the CI.  Indeed,
> if the "simplified standard CI header" included the name of the script/UDC,
> and the current nesting level, I could probably implement my own
> strictly local *and* inheritable local variables *and* system wide variables
> just from this one construct!

Can you convince the folks who voted system level variables as their 4th or
5th SIC ballot item?

> > * HPSYSNAME may need special consideration.  This variable is thought of as
> > a system variable, but since it is really job/session in scope it can be
> > changed by anyone.  This has annoyed many system managers.  We can keep the
>
> You're clearly defining the need for attributes for variables ... and the
> controlled ability to change the attributes:
>
>    ALTVARSEC "HPSYSNAME"; (W:SM)
>    ALTVARSEC "HPSYSNAME"; (W:ANY)
>
> or something.

... like ALTSEC,variable hpsysname; access=(...) ??
For HPSYSNAME is particular, I'm leaning towards leaving it as it is and
creating a new read-only var that contains the derived system name.

> > A.  We need a way to create, modify, read, delete system and local
Stan writes:
> and lock ... potentially.  Preferably read lock (shared) *and* write
> lock (exclusive)...with the lock expiring upon session/job termination.

I've thought of this and if locking is desired then I agree with your
comment.  Is user controllable var locking needed?  Of course internally
we will lock the var table of interest shared for read access and exclusive
for write access.  You may want external locking if you need to update 2
or more vars sort of "atomically".

I'm stopping here (got to take out the trash -- which is 1.25 miles
from my terminal!)  I will continue my reply to Stan and you Fri (if the ISDN
gods are willing) ...

to be continued...
Jeff Vance, CSY
...snip...

--

ATOM RSS1 RSS2