I have a "new" Rexx pgm I'm working on that replaces members in a PDSE via
EXECIO.
(Here's what I'm using:)
"ALLOC DSNAME('"||ddlpdsname||"("||ddlpdsmember||")') F(DDLPDS) SHR"
"EXECIO 0 DISKW DDLPDS (OPEN FINIS " /* empty existing member */
"EXECIO * DISKW DDLPDS (OPEN FINIS " /* dump stack into member */
"FREE F(DDLPDS)"
The member statistics are all blank when I view the members in 3.4.
Question: Is there an easy way I could have my Rexx pgm populate those
statistics?
I will need to be able to run this process in foreground or in batch. (I'm
thinking I'll use IKJEFT01 to execute it in batch.)
Mucho thanks in advance!
Stg
----------------------------------------------------------------------
For TSO-REXX subscribe / signoff / archive access instructions,
send email to LIST...@VM.MARIST.EDU with the message: INFO TSO-REXX
You want to investigate the ISPF LM* routines. In particular, you'll need
LMPUT and LMMREP (or LMMADD).
You'll also need to run ISPF in batch by using IKJEFT01 (or IKJEFT1A) and
invoking ISPSTART for your exec.
Hope this helps. And please come back if you need help on the LM* routines
- they can be a bit of a nightmare for a novice.
Ken
Steve Grimes
<Steve_...@AISMAIL.WUSTL.EDU> To:
TSO-...@VM.MARIST.EDU
Sent by: TSO REXX Discussion List cc:
<TSO-...@VM.MARIST.EDU> Subject: PDSE Member Statistics
Thursday December 9, 2004 06:25 AM
Please respond to TSO REXX
Discussion List
Further to Ken's comments here's some working code to help you get started.
Its worth noting that if you need to create many members in the same PDS(E)
using LM* routines is faster. You LMINIT and LMOPEN the PDS once, write lots
of members, and then LMCLOSE and LMFREE. With EXECIO however, you allocate
and open each member one at a time, followed by close and free for each
member. This is quite an overhead.
/* Rexx */
arg dsn mbr
address ispexec
"lminit dataid(did) dataset("dsn") enq(shrw)"
if rc \= 0 then exit setmsg(rc,,
"Failed to lminit dataset "dsn" rc="rc)
"lmopen dataid("did") option(output)"
if rc \= 0 then exit setmsg(rc,,
"Failed to lmopen dataset "dsn" rc="rc)
queue "Some text for the member"
queue "Some more text for the member"
queue "etc"
status = create_mbr_from_q(did,mbr)
select
when status = 0 then say left(mbr,8) "replaced"
when status = 8 then say left(mbr,8) "added"
otherwise
say "Member create failed rc="status
end
"lmclose dataid("did")"
"lmfree dataid("did")"
exit 0
create_mbr_from_q: procedure
arg did,mbr
if queued() = 0 then return 30
zlinorc = queued()
zlcnorc = queued()
zlmnorc = 0
address ispexec
do queued()
parse pull lin
l = length(lin)
"lmput dataid("did") mode(invar) dataloc(lin) datalen("l")"
if rc \= 0 then return rc
end
zlvers = 1
zlmod = 0
zlc4date = translate('1234/56/78',date("S"),"12345678")
zlm4date = zlc4date
zlmtime = time()
zluser = userid()
"lmmrep dataid("did") member("mbr") stats(yes)"
return rc
setmsg: procedure expose zerrsm zerrlm
arg zispfrc
"vput zispfrc"
do q = 2 to arg()
say " "arg(q)
end
say "Zerrsm = "zerrsm
say "Zerrlm = "zerrlm
return zispfrc
I use this create_mbr_from_q procedure in a lot of my programs.
You will need JCL something like the following to run this:
//JULIANJ JOB (2),'ISPF',CLASS=A,MSGCLASS=X,
// NOTIFY=&SYSUID,LINES=9999
//*
//STEPA EXEC PGM=IKJEFT01,REGION=4M
//SYSPROC DD DISP=SHR,DSN=CAP.UJULIAN.EXEC
//ISPPLIB DD DSN=ISP.SISPPENU,DISP=SHR
//ISPMLIB DD DSN=ISP.SISPMENU,DISP=SHR
//ISPSLIB DD DSN=ISP.SISPSENU,DISP=SHR
//ISPTLIB DD DSN=ISP.SISPTENU,DISP=SHR
//SYSTSPRT DD SYSOUT=*
//ISPPROF DD UNIT=SYSDA,
// DSORG=PO,RECFM=FB,LRECL=80,BLKSIZE=3120,
// SPACE=(TRK,(5,0,5))
//ISPLOG DD UNIT=SYSDA,
// DSORG=PO,RECFM=FB,LRECL=80,BLKSIZE=3120,
// SPACE=(TRK,(5,0))
//SYSTSIN DD *
ISPSTART CMD(%GENDEMO A.JCL SQUIGLE)
/*
//
Learn as much as you can from the above code you will want to vary this to
your needs anyway.
HTH
Julian
***** Matchcode International awarded the "Best International Product" by Direct Marketing Business at the IDMF 2003 *****
*******************************************************************
This e-mail is confidential and intended solely for the use of the individual to whom it was addressed. If you are not the intended recipient, you are hereby notified that any dissemination, distribution or copying of this message is strictly prohibited. Please delete any copies you may have, on any computer. Any views expressed in this message are those of the individual sender and do not necessarily represent the views of Capscan Ltd and/or its subsidiaries. Please be aware that Internet communications are not secure.
Capscan Limited
Head Office: Capscan Limited Grand Union House 20 Kentish Town Road London NW1 9BB
Registered in England no. 1183941
*******************************************************************
My suggestion - take it for what it is worth - is to obtain the member statistics before you replace
the member and update afterwards as needed.
As others have pointed out, you need to use ISPF's LM utilities to do this. Take a look in the
manual for LMMStats; this can obtain and replace each of the fields you normally see displayed in
3.4.
An example (with all of the error checking removed for brevity):
/*
Process the input file and update the member statistics
*/
'LMInit DataID(DS2Edit) Dataset('''DS2Reset''')'
'LMOpen DataID('DS2Edit')'
'LMMList DataID('DS2Edit') Member(NextMem) Stats(Yes)'
intSCode = RC
Do While intSCode = 0
ModMem = Strip(NextMem)
'LMMStats DataID('DS2Edit') Member('ModMem')',
'Version(99) Modlevel(0) User(CPY2OPC)',
'ModDate4('ModDate') ModTime('ModTime')'
'LMMList DataID('DS2Edit') Member(NextMem) Stats(Yes)'
intSCode = RC
End
'LMMList DataID('DS2Edit') Option(Free)'
'LMClose DataID('DS2Edit')'
'LMFree DataID('DS2Edit')'
Larry Kahm
Heliotropic Systems, Inc.
"Steve Grimes" <Steve_...@AISMAIL.WUSTL.EDU> wrote in message
news:OF00508974.9662A27E-ON86256F...@wustl.edu...
> I have a "new" Rexx pgm I'm working on that replaces members in a
> PDSE via EXECIO. (Here's what I'm using:)
> "ALLOC DSNAME('"||ddlpdsname||"("||ddlpdsmember||")') F(DDLPDS) SHR"
> "EXECIO 0 DISKW DDLPDS (OPEN FINIS " /* empty existing member */
> "EXECIO * DISKW DDLPDS (OPEN FINIS " /* dump stack into member */
> "FREE F(DDLPDS)"
Other people have produced ispf LM* service advice. Do you realise
though that what you've been trying to do is dangerous? You've only
held a SHR enqueue on the PDS, but have written data into it? If
anyone else is doing the same thing at the same time the pds will most
likely end up corrupted.
ISPF via edit, and via the LM* services, will allow you to update a pds
with a SHR enqueue on the whole pds, but control access to the
directory itself exclusively, thus allowing more than one user to
update members "at once" - that's how it can tell you that a member is
in use when you try to edit a member that someone else is updating. If
the pds concerned could ever be updated via ispf then your code must
use the same methods.
--
Jeremy C B Nicoll - my opinions are my own.
There are several ways to generate member stats, all of which involve the
use of ISPF services. The "proper" way to do it is to replace the EXECIO
statements with the following:
LMINIT
LMOPEN
get first member name
do until all members processed
do until all records written for current member
LMPUT
end
LMMREP STATS(YES) <---replace the member
get next member name
end
LMFREE
Hope that helps!
Dave Salt
Soft-Center Solutions Inc.
http://www.soft-center.com
1-877-SoftCen
Bringing you SimpList(tm) - The easiest, most powerful way to surf a
mainframe!
>From: Steve Grimes <Steve_...@AISMAIL.WUSTL.EDU>
>Reply-To: TSO REXX Discussion List <TSO-...@VM.MARIST.EDU>
>To: TSO-...@VM.MARIST.EDU
>Subject: PDSE Member Statistics
Variations on the following error have plagued me for years. I can get
around it with judicious use of DO groups but I'd like to understand exactly
what syntax rule I'm breaking.
The following code is a simplified version of something I'm working on:
xcmd = 'P'
My_Txns_Open = '0'
do while (xcmd Ź= ' ')
if left(xcmd,1,1) = 'P' then
do
xcmd = ' '
if ŹMy_Txns_Open then
do
x = 4
if x > 0 then
signal My_Txns_Exit
end
My_Txns_Exit:
end
end
When I run it, I get the following (end of the trace):
12 *-* if x > 0
>V> "4"
>L> "0"
>O> "1"
*-* then
13 *-* signal My_Txns_Exit
15 *-* My_Txns_Exit:
16 *-* end
16 +++ end
IRX0010I Error running GEM, line 16: Unexpected or unmatched END
Can anyone tell me what I've done wrong?
Thanks,
George
:>Variations on the following error have plagued me for years. I can get
:>around it with judicious use of DO groups but I'd like to understand exactly
:>what syntax rule I'm breaking.
From the TSP/E REXX Reference:
To change the flow of control, a label name is derived from labelname or taken
from the result of evaluating the expression after VALUE.
All active pending DO, IF, SELECT, and INTERPRET instructions in the current
routine are then ended (that is, they cannot be resumed). Control then passes
to the first label in the program that matches the given name, as though the
search had started from the top of the program.
--
Binyamin Dissen <bdi...@dissensoftware.com>
http://www.dissensoftware.com
Director, Dissen Software, Bar & Grill - Israel
Should you use the mailblocks package and expect a response from me,
you should preauthorize the dissensoftware.com domain.
I very rarely bother responding to challenge/response systems,
especially those from irresponsible companies.
I mean, of course, that I never use SIGNAL as a goto. Using it as SIGNAL
(to trap errors for example) is a different thing entirely.
---
Bob Bridges, robert...@discoverfinancial.com, 224 405-0811
rhb...@attglobal.net, 847 520-1684 xt 243
/* Gentlemen, when the enemy is committed to a mistake we must not
interrupt him too soon. -Admiral Horatio Nelson */
Binyamin Dissen <bdi...@DISSENSOFTWARE.COM>
2004-12-09 11:13
To: TSO-...@VM.MARIST.EDU
cc:
Subject: Re: PDSE Member Statistics
From the TSP/E REXX Reference:
To change the flow of control, a label name is derived from labelname or
taken
from the result of evaluating the expression after VALUE.
All active pending DO, IF, SELECT, and INTERPRET instructions in the
current
routine are then ended (that is, they cannot be resumed). Control then
passes
to the first label in the program that matches the given name, as though
the
search had started from the top of the program.
"Mosley, George" <George...@ICBC.COM>
2004-12-09 10:54
To: TSO-...@VM.MARIST.EDU
cc:
Subject: Re: PDSE Member Statistics
Variations on the following error have plagued me for years. I can get
around it with judicious use of DO groups but I'd like to understand
exactly
what syntax rule I'm breaking.
The following code is a simplified version of something I'm working on:
xcmd = 'P'
My_Txns_Open = '0'
do while (xcmd<>' ')
if left(xcmd,1,1)='P' then do
xcmd = ' '
if ŹMy_Txns_Open then do
x = 4
if x > 0 then signal My_Txns_Exit
end
My_Txns_Exit:
end
end
When I run it, I get the following (end of the trace):
12 *-* if x > 0
>V> "4"
>L> "0"
>O> "1"
*-* then
13 *-* signal My_Txns_Exit
15 *-* My_Txns_Exit:
16 *-* end
16 +++ end
IRX0010I Error running GEM, line 16: Unexpected or unmatched END
----------------------------------------------------------------------
(Apologies for not changing the SUBJECT when I posted this).
George
Normally this is true. However, note that the requestor stated
specifically that the program replaces members in a PDSE. So the
caveat may not apply in this particular case.
- seb
I'm definately converting to use the LM* stuff. (But I never would have
gotten there with the examples given.)
I do have one subsequent question.
Julian wrote: "You LMINIT and LMOPEN the PDS once, write lots of members,
and then LMCLOSE and LMFREE."
I'm inclined to isolate all of this stuff in a routine that has LMINIT,
LMOPEN, write one member, LMCLOSE and LMFREE. This means I'd be doing it
over and over again for each member (say 40-50 members max, 25-200 lines
each.)
It's because the program is doing a lot of work inbetween each member and I
wasn't to keen on keeping the PDS/e tied up, and possibily crashing before
I get back to it.
Are my concerns unjustified -- would folks "strongly" lean toward Julian's
suggestion, even if it meant 15 minutes of elapsed execution time between
the INIT/OPEN and the CLOSE/FREE?
Thanks.
I never would have gotten there *** WITHOUT *** the examples given.
The examples were priceless!!!
Thanks again.
> You wrote:
>
> Wow -- great information -- thank you!
Glad to help.
> I'm definately converting to use the LM* stuff. (But I never would have
> gotten there with the examples given.)
>
> I do have one subsequent question.
>
> Julian wrote: "You LMINIT and LMOPEN the PDS once, write lots
> of members,
> and then LMCLOSE and LMFREE."
>
> I'm inclined to isolate all of this stuff in a routine that has LMINIT,
> LMOPEN, write one member, LMCLOSE and LMFREE. This means I'd be doing it
> over and over again for each member (say 40-50 members max, 25-200 lines
> each.)
Not recommended, performance can really suffer. I amended the routine I
posted before, to loop round and create 2000 members. I added the loop to
LMINIT/LMOPEN/LMCLOSE/LMFREE for every member.
STEPNAME PROCSTEP RC EXCP CONN TCB SRB CLOCK SERV
STEPA 00 97557 11021 1.15 .05 2.3 245K
Then I created another version with the loop just around the member create
and LMMREP.
STEPNAME PROCSTEP RC EXCP CONN TCB SRB CLOCK SERV
STEPA 00 49010 3766 .37 .01 .9 80544
As you can see this version is much faster with much less overhead.
>
> It's because the program is doing a lot of work inbetween each
> member and I
> wasn't to keen on keeping the PDS/e tied up, and possibily crashing before
> I get back to it.
This should not be an issue. The output PDS is allocated for shared writing.
It is not tied up at all.
> Are my concerns unjustified -- would folks "strongly" lean toward Julian's
> suggestion, even if it meant 15 minutes of elapsed execution time between
> the INIT/OPEN and the CLOSE/FREE?
I would say concerns unjustified. I've had jobs like this run for hours (in
exceptional cases) without any problems.
>
> Thanks.
>
> Stg
Thank You - I enjoy helping.
Julian
***** Matchcode International awarded the "Best International Product" by Direct Marketing Business at the IDMF 2003 *****
*******************************************************************
This e-mail is confidential and intended solely for the use of the individual to whom it was addressed. If you are not the intended recipient, you are hereby notified that any dissemination, distribution or copying of this message is strictly prohibited. Please delete any copies you may have, on any computer. Any views expressed in this message are those of the individual sender and do not necessarily represent the views of Capscan Ltd and/or its subsidiaries. Please be aware that Internet communications are not secure.
Capscan Limited
Head Office: Capscan Limited Grand Union House 20 Kentish Town Road London NW1 9BB
Registered in England no. 1183941
*******************************************************************
----------------------------------------------------------------------
> The following code is a simplified version of something I'm working
> on:
I reformatted that slightly to see if I could better understand what
you intended to do (because I prefer a different style of indenting)
> xcmd = 'P'
> My_Txns_Open = '0'
> do while (xcmd Ź= ' ')
> if left(xcmd,1,1) = 'P' then do
> xcmd = ' '
> if ŹMy_Txns_Open then do
> x = 4
> if x > 0 then signal My_Txns_Exit
> end
> My_Txns_Exit:
> end
> end
When you signal My_Txns_Exit you presumably just wanted to jump to
the end statements at the end of the nested condition, and then fall
through to the end at the end of the do while. In this example, which
I dare say is a poor one, that's where rexx will go anyway if the
signal wasn't there.
The problem is that rexx intends signal to be used only in
extraordinary situations, eg as part of error/exception handling, not
as if it were a goto statement. When a signal is followed the
structure of do loops etc is thrown away, so rexx no longer knows it
was in a if/then/end clause within a do/while/end. Thus it sees the
end immediately after the label as a problem.
In your example the code would actually work if you left the signal and
label out! But I guess that's not what you intended. It works because
you changed xcmd from "P" to " " and so the do/while condition is no
longer true next time control gets to the top of the loop. That's
pretty much the usual way to cope - you set a flag inside the loop that
says no more looping is required, and test it. Or, you use leave to
tell rexx that you want to abandon that loop:
xcmd = 'P'
My_Txns_Open = '0'
do while (xcmd Ź= ' ')
if left(xcmd,1,1) = 'P' then do
xcmd = ' '
if ŹMy_Txns_Open then do
x = 4
if x > 0 then leave
end
end
end
In this case trace will show you that the next statement executed after
the leave is whatever is after the do/while/end loop.
The only place I use signal in any of my code is in erro handling, when
I've written a program with a labelled satement, normally "byebye:" at
which there is code to close all open files, free any other resources
etc - generally that will clean-up whatever was going on. When I test
return-codes after invoking things there's often something like:
if rc > 8 then do
finalmsg = "what went wrong..."
signal byebye
end
That works because the destruction of the structure of the place from
which the signal happens doesn't matter when you're just about to
terminate the program.
One thing I discovered was that the version of Regina Rexx I have on my
computer at home treats this differently. With:
xcmd = 'P'
My_Txns_Open = '0'
do while (xcmd \= ' ')
if left(xcmd,1,1) = 'P' then do
xcmd = ' '
if \My_Txns_Open then do
x = 4
if x > 0 then signal My_Txns_Exit
end
My_Txns_Exit:
say "one"
end
say "two"
end
say "and finally"
when I run it, I get "one" as output (fair enough) but no error when
the following "end" is encountered - that just seems to stop the exec.
However this might be a vagary of the fairly old version of Regina that
I'm using.
--
Jeremy C B Nicoll - my opinions are my own.
----------------------------------------------------------------------
if ŹMy_Txns_Open then do
x = 4
if x > 0 then leave
is a little odd. If you set x to 4, there's no point in immediately testing
it's value. If you use x later in the rexx, then change "if x > 0 then
leave" to just "leave". If you're only using x to determine when to leave
the loop, then replace both lines with "leave".
Tina
-----Original Message-----
From: TSO REXX Discussion List [mailto:TSO-...@VM.MARIST.EDU] On Behalf Of
Jeremy C B Nicoll
Sent: Friday, December 10, 2004 1:55 PM
To: TSO-...@VM.MARIST.EDU
Subject: Re: PDSE Member Statistics
Why are you padding the LEFT(XCMS,1,1) with a character "1" ?
And also, why are you setting X to four and then testing to
see if four is greater than zero ? ___________________Gerard S.
Thanks for your comments. The code I included was stripped down to a trivial
level in order to be concise. The actual code, while logically equivalent in
terms of the use of SIGNAL, was considerably more complex. That complexity,
including the nesting involved, made LEAVE and ITERATE inappropriate choices
as well.
My mistake was using SIGNAL as a GOTO (which I'll never do again, I
promise!) and not understanding that its use caused all active DO groups to
complete.
I've re-structured my code and it's working fine now.
Thanks, again.
George
-----Original Message-----
From: Hilton, Tina [mailto:thi...@RANDOMHOUSE.COM]
Sent: Friday, December 10, 2004 11:27 AM
To: TSO-...@VM.MARIST.EDU
Subject: Re: PDSE Member Statistics
To add to Jeremy's insightful comments and suggestions, this bit of code
if ŹMy_Txns_Open then do
x = 4
if x > 0 then leave
is a little odd. If you set x to 4, there's no point in immediately testing
it's value. If you use x later in the rexx, then change "if x > 0 then
leave" to just "leave". If you're only using x to determine when to leave
the loop, then replace both lines with "leave".
Tina
-----Original Message-----
From: TSO REXX Discussion List [mailto:TSO-...@VM.MARIST.EDU] On Behalf Of
Jeremy C B Nicoll
Sent: Friday, December 10, 2004 1:55 PM
To: TSO-...@VM.MARIST.EDU
Subject: Re: PDSE Member Statistics
In article <E478EF9AB22CD3119B44...@ex01mb299.icbc.net>,
"Mosley, George" <George...@ICBC.COM> wrote:
> The following code is a simplified version of something I'm working
> on:
I reformatted that slightly to see if I could better understand what you
intended to do (because I prefer a different style of indenting)
> xcmd = 'P'
> My_Txns_Open = '0'
> do while (xcmd Ź= ' ')
> if left(xcmd,1,1) = 'P' then do
> xcmd = ' '
> if ŹMy_Txns_Open then do
> x = 4
> if x > 0 then signal My_Txns_Exit
> end
> My_Txns_Exit:
> end
> end
When you signal My_Txns_Exit you presumably just wanted to jump to the
end statements at the end of the nested condition, and then fall through to
the end at the end of the do while. In this example, which I dare say is a
poor one, that's where rexx will go anyway if the signal wasn't there.
The problem is that rexx intends signal to be used only in extraordinary
situations, eg as part of error/exception handling, not as if it were a goto
statement. When a signal is followed the structure of do loops etc is
thrown away, so rexx no longer knows it was in a if/then/end clause within
a do/while/end. Thus it sees the end immediately after the label as a
problem.
In your example the code would actually work if you left the signal and
label out! But I guess that's not what you intended. It works because you
changed xcmd from "P" to " " and so the do/while condition is no longer true
next time control gets to the top of the loop. That's pretty much the usual
way to cope - you set a flag inside the loop that says no more looping is
required, and test it. Or, you use leave to tell rexx that you want to
abandon that loop:
xcmd = 'P'
My_Txns_Open = '0'
do while (xcmd Ź= ' ')
if left(xcmd,1,1) = 'P' then do
xcmd = ' '
if ŹMy_Txns_Open then do
x = 4
if x > 0 then leave
end
end
end
In this case trace will show you that the next statement executed after the
leave is whatever is after the do/while/end loop.
The only place I use signal in any of my code is in erro handling, when I've
written a program with a labelled satement, normally "byebye:" at which
there is code to close all open files, free any other resources etc -
generally that will clean-up whatever was going on. When I test
return-codes after invoking things there's often something like:
if rc > 8 then do
finalmsg = "what went wrong..."
signal byebye
end
That works because the destruction of the structure of the place from which
the signal happens doesn't matter when you're just about to terminate the
program.
One thing I discovered was that the version of Regina Rexx I have on my
computer at home treats this differently. With:
xcmd = 'P'
My_Txns_Open = '0'
do while (xcmd \= ' ')
if left(xcmd,1,1) = 'P' then do
xcmd = ' '
if \My_Txns_Open then do
x = 4
if x > 0 then signal My_Txns_Exit
end
My_Txns_Exit: