For Programmers: Free Programming Magazines  


Home > Archive > Cobol > April 2005 > length and occurs depending on









You are viewing an archived Text-only version of the thread. To view this thread in it's original format and/or if you want to reply to this thread please [click here]

 

Author length and occurs depending on
Frank Swarbrick

2005-04-21, 8:55 pm

I have what I believe to be an interesting "problem". Take the following
variable length group, TS-PAGE-OF-TRANSACTIONS.

05 TS-PAGE-OF-TRANSACTIONS.
07 TS-TRAN-BKPG-CNT PIC S9(03) COMP SYNC.
07 TS-TRAN-TABLES.
10 TS-TRAN-DTL-LINE
OCCURS 13 TIMES
PIC X(79).
10 TS-TRAN-DESC-LINE OCCURS 11 TIMES.
15 TS-TRAN-DESC OCCURS 4 TIMES
PIC X(61).
15 TS-TRAN-BKPG-SUB OCCURS 4 TIMES
PIC S9(03) COMP.
07 TS-TRAN-BKPG-TABLE.
10 TS-TRAN-BKPG-DESC OCCURS 0 TO 44 TIMES
DEPENDING ON TS-TRAN-BKPG-CNT
PIC X(61).

The actual variable length table is TS-TRAN-BKPG-TABLE. The can be zero
through 44 occurances, depending on various things. I then write the whole
group to a CICS TS queue. In order to write the minimum size necessary I
set TS-TRAN-BKPG-CNT to the actual number of occurances od
TS-TRAN-BKPG-DESC. I then use the COBOL "LENGTH OF" operator to calculate
TS-LEN-TRAN. See the following...

* at this point TS-TRAN-BKPG-CNT will have already been set to some value
between 0 and 44 inclusive
COMPUTE TS-LEN-TRAN = LENGTH OF TS-PAGE-OF-TRANSACTIONS.
EXEC CICS
WRITEQ TS
QUEUE (TS-QUEUE)
FROM (TS-PAGE-OF-TRANSACTIONS)
LENGTH (TS-LEN-TRAN)
END-EXEC.

This all works fine because we know the value of TS-TRAN-BKPG-CNT.

However, when I want to *read* it from the TS queue (this will be a new
pseudo-conversational task, so all previous working-storage will be cleared)
I have to set TS-LEN-TRAN to the *largest* size that TS-PAGE-OF-TRANSACTIONS
could possibly be. Right now I do this as follows:

* At this point we do not yet know the value of TS-TRAN-BKPG-CNT
* We need to set it to 44 so that TS-LEN-TRAN will be set to the maximum
length that
* TS-PAGE-OF-TRANSACTIONS can possibly be
MOVE 44 TO TS-TRAN-BKPG-CNT.
COMPUTE TS-LEN-TRAN = LENGTH OF TS-PAGE-OF-TRANSACTIONS.
EXEC CICS
READQ TS
QUEUE (TS-QUEUE)
INTO (TS-PAGE-OF-TRANSACTIONS)
ITEM (WS-ITEM)
LENGTH (TS-LEN-TRAN)
END-EXEC.

I'm trying to figure out if there's anyway I can avoid hard coding the
setting of TS-TRAN-BKPG-CNT to 44. The following does *not* work:

COMPUTE TS-TRAN-BKPG-CNT =
LENGTH OF TS-TRAN-BKPG-TABLE / LENGTH OF TS-TRAN-BKPG-DESC (1).

This is because TS-TRAN-BKPG-CNT must already be *set* to 44 in order for it
to return a *result* of 44.

Any thoughts?

Thanks,
Frank


---
Frank Swarbrick
Senior Developer/Analyst - Mainframe Applications
FirstBank Data Corporation - Lakewood, CO USA
Pete Dashwood

2005-04-21, 8:55 pm


"Frank Swarbrick" <Frank.Swarbrick@efirstbank.com> wrote in message
news:3cqhijF6oi4baU1@individual.net...
> I have what I believe to be an interesting "problem". Take the following
> variable length group, TS-PAGE-OF-TRANSACTIONS.
>
> 05 TS-PAGE-OF-TRANSACTIONS.
> 07 TS-TRAN-BKPG-CNT PIC S9(03) COMP SYNC.
> 07 TS-TRAN-TABLES.
> 10 TS-TRAN-DTL-LINE
> OCCURS 13 TIMES
> PIC X(79).
> 10 TS-TRAN-DESC-LINE OCCURS 11 TIMES.
> 15 TS-TRAN-DESC OCCURS 4 TIMES
> PIC X(61).
> 15 TS-TRAN-BKPG-SUB OCCURS 4 TIMES
> PIC S9(03) COMP.
> 07 TS-TRAN-BKPG-TABLE.
> 10 TS-TRAN-BKPG-DESC OCCURS 0 TO 44 TIMES
> DEPENDING ON TS-TRAN-BKPG-CNT
> PIC X(61).
>
> The actual variable length table is TS-TRAN-BKPG-TABLE. The can be zero
> through 44 occurances, depending on various things. I then write the

whole
> group to a CICS TS queue. In order to write the minimum size necessary I
> set TS-TRAN-BKPG-CNT to the actual number of occurances od
> TS-TRAN-BKPG-DESC. I then use the COBOL "LENGTH OF" operator to calculate
> TS-LEN-TRAN. See the following...
>
> * at this point TS-TRAN-BKPG-CNT will have already been set to some value
> between 0 and 44 inclusive
> COMPUTE TS-LEN-TRAN = LENGTH OF TS-PAGE-OF-TRANSACTIONS.
> EXEC CICS
> WRITEQ TS
> QUEUE (TS-QUEUE)
> FROM (TS-PAGE-OF-TRANSACTIONS)
> LENGTH (TS-LEN-TRAN)
> END-EXEC.
>
> This all works fine because we know the value of TS-TRAN-BKPG-CNT.
>
> However, when I want to *read* it from the TS queue (this will be a new
> pseudo-conversational task, so all previous working-storage will be

cleared)
> I have to set TS-LEN-TRAN to the *largest* size that

TS-PAGE-OF-TRANSACTIONS
> could possibly be. Right now I do this as follows:
>
> * At this point we do not yet know the value of TS-TRAN-BKPG-CNT
> * We need to set it to 44 so that TS-LEN-TRAN will be set to the maximum
> length that
> * TS-PAGE-OF-TRANSACTIONS can possibly be
> MOVE 44 TO TS-TRAN-BKPG-CNT.
> COMPUTE TS-LEN-TRAN = LENGTH OF TS-PAGE-OF-TRANSACTIONS.
> EXEC CICS
> READQ TS
> QUEUE (TS-QUEUE)
> INTO (TS-PAGE-OF-TRANSACTIONS)
> ITEM (WS-ITEM)
> LENGTH (TS-LEN-TRAN)
> END-EXEC.
>
> I'm trying to figure out if there's anyway I can avoid hard coding the
> setting of TS-TRAN-BKPG-CNT to 44. The following does *not* work:
>
> COMPUTE TS-TRAN-BKPG-CNT =
> LENGTH OF TS-TRAN-BKPG-TABLE / LENGTH OF TS-TRAN-BKPG-DESC (1).
>
> This is because TS-TRAN-BKPG-CNT must already be *set* to 44 in order for

it
> to return a *result* of 44.
>
> Any thoughts?
>


It is 25 years since I wrote a CICS COBOL Program and in my day we had to
use GETMAIN to allocate the storage before writing the Queue. (Of course, we
were REAL programmers... :-)) I see from your code that this is no longer
required. :-)

I think there is a fundamental misunderstanding here, Frank. The length does
NOT need to be set when you READ.

CICS will set the length into the parameter you specify. (Well, it did when
I used it, but we didn't have INTO - 'into' implies you already have the
storage allocated and should therefore know its length...)

I would have coded:

EXEC CICS
READQ TS
QUEUE (TS-QUEUE)
SET (TS-POINTER)
ITEM (WS-ITEM)
LENGTH (TS-LEN-TRAN)
END-EXEC.

CICS would have grabbed storage for the area corresponding to TS-POINTER,
read the item on the queue indicated by ITEM, and placed the length of it
into LENGTH

It is then a trivial exercise to calculate the number of occurrences that
are required in your TS-TRAN-BKPG-CNT as:

(TS-LEN-TRAN - fixed part of record) / length of TS-TRAN-BKPG-DESC

....which is pretty close to what you suggested.

The only fly I can see in this ointment is that INTO doesn't work like that,
and actually requires the length to be in it before the read.

If that is the case, then why not simply define a buffer area of say, 4096
bytes and read into that? Then you can work out how much data you actually
received (I can't believe it doesn't put it into TS-LENGTH, but I don't have
access to the latest CICS stuff), calculate the value for TS-TRAN-BKPG-CNT
as shown, and, once you have set the number of occurrences correctly, MOVE
the record from the data buffer to your record definition.

SUMMARISING:

1. I believe that a CICS READQ will SET the length it gets. (If I am wrong,
and INTO doesn't work like that, then use a fixed length buffer and do the
job that CICS SHOULD have done...calculate the length you actually
received).

2. Once you have the actual data length of the item, you can easily
calculate (and set into the TS-TRAN-BKPG-CNT field), the the number of
occurrences of your variable data.

No hard coding.

Hope this helps,

Pete.



Arnold Trembley

2005-04-22, 3:55 am



Pete Dashwood wrote:
> "Frank Swarbrick" <Frank.Swarbrick@efirstbank.com> wrote in message
> news:3cqhijF6oi4baU1@individual.net...
> (snip)
>
> it
>
>
>
> It is 25 years since I wrote a CICS COBOL Program and in my day we had to
> use GETMAIN to allocate the storage before writing the Queue. (Of course, we
> were REAL programmers... :-)) I see from your code that this is no longer
> required. :-)
>
> I think there is a fundamental misunderstanding here, Frank. The length does
> NOT need to be set when you READ.


Mr. Dashwood, I beg to differ.

If you are doing a READQ TS with the INTO option the LENGTH field must
be initialized with the maximum length. Think about it. The temp
storage queue record might be as big as 32K bytes. If the queue
record is too big large for the INTO field, how is CICS to know when
to raise the LENGERR condition or EIBRESP value? How else is the
program supposed to know when the data is truncated?

>
> CICS will set the length into the parameter you specify. (Well, it did when
> I used it, but we didn't have INTO - 'into' implies you already have the
> storage allocated and should therefore know its length...)
>
> I would have coded:
>
> EXEC CICS
> READQ TS
> QUEUE (TS-QUEUE)
> SET (TS-POINTER)
> ITEM (WS-ITEM)
> LENGTH (TS-LEN-TRAN)
> END-EXEC.
>
> CICS would have grabbed storage for the area corresponding to TS-POINTER,
> read the item on the queue indicated by ITEM, and placed the length of it
> into LENGTH.


This is true, of course. But if you use the SET option you cannot
READQ directly into WORKING-STORAGE. You must define a pointer for a
LINKAGE SECTION item, GETMAIN it, and establish addressability to it.
You must do the GETMAIN every time the program is re-entered. And
you still have the possibility of reading a temp storage queue record
larger than your space allocation.

>
> It is then a trivial exercise to calculate the number of occurrences that
> are required in your TS-TRAN-BKPG-CNT as:
>
> (TS-LEN-TRAN - fixed part of record) / length of TS-TRAN-BKPG-DESC
>
> ...which is pretty close to what you suggested.
>
> The only fly I can see in this ointment is that INTO doesn't work like that,
> and actually requires the length to be in it before the read.


This is true.

>
> If that is the case, then why not simply define a buffer area of say, 4096
> bytes and read into that? Then you can work out how much data you actually
> received (I can't believe it doesn't put it into TS-LENGTH, but I don't have
> access to the latest CICS stuff), calculate the value for TS-TRAN-BKPG-CNT
> as shown, and, once you have set the number of occurrences correctly, MOVE
> the record from the data buffer to your record definition.


That's certainly one solution that would work.

>
> SUMMARISING:
>
> 1. I believe that a CICS READQ will SET the length it gets. (If I am wrong,
> and INTO doesn't work like that, then use a fixed length buffer and do the
> job that CICS SHOULD have done...calculate the length you actually
> received).


READQ TS always sets the LENGTH field equal to the length actually
retrieved, whether you use SET or INTO. But if you use the INTO
option, you must initialize the LENGTH field with the maximum length
of the working-storage field, and you must do it before executing the
READQ command. If you are using INTO, and the TS Queue record is
longer than the maximum length, you get a LENGERR condition.

That's just the way it works.

>
> 2. Once you have the actual data length of the item, you can easily
> calculate (and set into the TS-TRAN-BKPG-CNT field), the the number of
> occurrences of your variable data.
>
> No hard coding.


I agree that hard-coding the maximum length is a less desirable
solution, because it makes future changes a little more difficult. I
do see it done that way quite often, even for fixed-length TS queue
records when it would be quite easy to use LENGTH OF.

It ought to be possible to compute the the maximum length in a way
that simplifies future maintenance, but I can't figure out an easy way
to do it without defining a constant for the maximum number of
occurrences.

Truthfully, the programmers in my shop avoid ODO like the plague, and
given that CICS stands for "Core Is Cheap, Sucker", it's easier to use
a fixed-length queue record.

An interesting problem is how to get rid of those TS Queue MAIN
records when transactions are aborted. We had to use a CICS TASK Exit
to purge them. Typically the queue name is the Transaction ID plus
the Terminal ID. The exit program would build the key and delete any
outstanding TS queues. Of course, Frank's shop may put all TS Queues
to the VSAM AUX Temp Storage File rather than to MAIN storage, so
memory leaks might not be a problem for him. At least in the old
days, TS queues in MAIN storage were considerably faster than in AUX.

>
> Hope this helps,
>
> Pete.
>


I calculate the maximum length of the 05 area as 6485 bytes, but
please check my work for errors! (I apologize for snipping that
portion of the original post). That's small enough that it could be
passed in a COMMAREA, without using a TS Queue. Of course, I don't
know if Frank Swarbrick's program already has other data being passed
that would put the COMMAREA over the 32K limit.

Another advantage to using COMMAREA is that it doesn't leave TS Queues
in memory if the transaction abends. There's less chance of storage
creep that way.

An interesting problem!

--
http://arnold.trembley.home.att.net/

William M. Klein

2005-04-22, 3:55 am

Frank (and Arnold and Pete),
I know just enough to be dangerous in this area and I do *NOT* know if the
following CICS (on z/OS) option is available for VSE, but ...

You *might* want to look at the LENGTH translator option - described (for CICS
TS V3.1 - for z/OS) at:

http://publibz.boulder.ibm.com/cgi-...3b00/2.1.5.1.19


--
Bill Klein
wmklein <at> ix.netcom.com
"Arnold Trembley" <arnold.trembley@worldnet.att.net> wrote in message
news:22%9e.623343$w62.158596@bgtnsc05-news.ops.worldnet.att.net...
>
>
> Pete Dashwood wrote:
>
> Mr. Dashwood, I beg to differ.
>
> If you are doing a READQ TS with the INTO option the LENGTH field must be
> initialized with the maximum length. Think about it. The temp storage queue
> record might be as big as 32K bytes. If the queue record is too big large for
> the INTO field, how is CICS to know when to raise the LENGERR condition or
> EIBRESP value? How else is the program supposed to know when the data is
> truncated?
>
>
> This is true, of course. But if you use the SET option you cannot READQ
> directly into WORKING-STORAGE. You must define a pointer for a LINKAGE
> SECTION item, GETMAIN it, and establish addressability to it. You must do the
> GETMAIN every time the program is re-entered. And you still have the
> possibility of reading a temp storage queue record larger than your space
> allocation.
>
>
> This is true.
>
>
> That's certainly one solution that would work.
>
>
> READQ TS always sets the LENGTH field equal to the length actually retrieved,
> whether you use SET or INTO. But if you use the INTO option, you must
> initialize the LENGTH field with the maximum length of the working-storage
> field, and you must do it before executing the READQ command. If you are
> using INTO, and the TS Queue record is longer than the maximum length, you get
> a LENGERR condition.
>
> That's just the way it works.
>
>
> I agree that hard-coding the maximum length is a less desirable solution,
> because it makes future changes a little more difficult. I do see it done
> that way quite often, even for fixed-length TS queue records when it would be
> quite easy to use LENGTH OF.
>
> It ought to be possible to compute the the maximum length in a way that
> simplifies future maintenance, but I can't figure out an easy way to do it
> without defining a constant for the maximum number of occurrences.
>
> Truthfully, the programmers in my shop avoid ODO like the plague, and given
> that CICS stands for "Core Is Cheap, Sucker", it's easier to use a
> fixed-length queue record.
>
> An interesting problem is how to get rid of those TS Queue MAIN records when
> transactions are aborted. We had to use a CICS TASK Exit to purge them.
> Typically the queue name is the Transaction ID plus the Terminal ID. The exit
> program would build the key and delete any outstanding TS queues. Of course,
> Frank's shop may put all TS Queues to the VSAM AUX Temp Storage File rather
> than to MAIN storage, so memory leaks might not be a problem for him. At
> least in the old days, TS queues in MAIN storage were considerably faster than
> in AUX.
>
>
> I calculate the maximum length of the 05 area as 6485 bytes, but please check
> my work for errors! (I apologize for snipping that portion of the original
> post). That's small enough that it could be passed in a COMMAREA, without
> using a TS Queue. Of course, I don't know if Frank Swarbrick's program
> already has other data being passed that would put the COMMAREA over the 32K
> limit.
>
> Another advantage to using COMMAREA is that it doesn't leave TS Queues in
> memory if the transaction abends. There's less chance of storage creep that
> way.
>
> An interesting problem!
>
> --
> http://arnold.trembley.home.att.net/
> 



Pete Dashwood

2005-04-22, 8:55 am


"Arnold Trembley" <arnold.trembley@worldnet.att.net> wrote in message
news:22%9e.623343$w62.158596@bgtnsc05-news.ops.worldnet.att.net...
>
>
> Pete Dashwood wrote:
for[color=darkred]
to[color=darkred]
course, we[color=darkred]
longer[color=darkred]
does[color=darkred]
>
> Mr. Dashwood, I beg to differ.
>
> If you are doing a READQ TS with the INTO option the LENGTH field must
> be initialized with the maximum length. Think about it. The temp
> storage queue record might be as big as 32K bytes. If the queue
> record is too big large for the INTO field, how is CICS to know when
> to raise the LENGERR condition or EIBRESP value? How else is the
> program supposed to know when the data is truncated?


Well Arnold, I think this is a case of premature ejaculation on your part.
:-) Why not read the WHOLE response before grabbing a keyboard?

I mentioned that I wasn't sure how INTO might work and I covered both cases
(it requires a length or it doesn't) in my post.

The request was for 'any thoughts'... I posted mine.
>
when[color=darkred]
TS-POINTER,[color=darkred]
it[color=darkred]
>
> This is true, of course. But if you use the SET option you cannot
> READQ directly into WORKING-STORAGE. You must define a pointer for a
> LINKAGE SECTION item, GETMAIN it, and establish addressability to it.
> You must do the GETMAIN every time the program is re-entered. And
> you still have the possibility of reading a temp storage queue record
> larger than your space allocation.
>


I realise that and suggested using a buffer big ennough to accommodate it.
So what exactly is your issue?
that[color=darkred]
that,[color=darkred]
>
> This is true.
>
4096[color=darkred]
actually[color=darkred]
have[color=darkred]
TS-TRAN-BKPG-CNT[color=darkred]
MOVE[color=darkred]
>
> That's certainly one solution that would work.
>

Ah, we agree that these were NOT bad 'thoughts' then... :-)

However, I didn't do a precise calculation on the record length and I see
from your post below (I always read everything before ejaculating :-)) that
you reckon the size to be 6485, so my quick estimate of 4096 is certainly
insufficient... I hereby extend my buffer to 8192 and declare the problem
solved... :-)
[color=darkred]
wrong,[color=darkred]
the[color=darkred]
>
> READQ TS always sets the LENGTH field equal to the length actually
> retrieved, whether you use SET or INTO. But if you use the INTO
> option, you must initialize the LENGTH field with the maximum length
> of the working-storage field, and you must do it before executing the
> READQ command. If you are using INTO, and the TS Queue record is
> longer than the maximum length, you get a LENGERR condition.
>
> That's just the way it works.


OK. Fair enough. I believe 8192 is longer than the max length of the record
whose definition was posted. So that should work without problem. (Man! I'm
so glad I don't do this stuff for a living any more... :-))
>
>
> I agree that hard-coding the maximum length is a less desirable
> solution, because it makes future changes a little more difficult. I
> do see it done that way quite often, even for fixed-length TS queue
> records when it would be quite easy to use LENGTH OF.
>
> It ought to be possible to compute the the maximum length in a way
> that simplifies future maintenance, but I can't figure out an easy way
> to do it without defining a constant for the maximum number of
> occurrences.


It is described above.

>
> Truthfully, the programmers in my shop avoid ODO like the plague, and
> given that CICS stands for "Core Is Cheap, Sucker", it's easier to use
> a fixed-length queue record.
>


On this, you will hear no dissent from me. I am also on record as stating my
position that ODO is anathema. The overheads it incurs are simply not worth
the storage savings in these days of cheap storage. It is a remnant (like
many things in COBOL) of a bygone era when priorities were different from
the realities we face today.

> An interesting problem is how to get rid of those TS Queue MAIN
> records when transactions are aborted. We had to use a CICS TASK Exit
> to purge them. Typically the queue name is the Transaction ID plus
> the Terminal ID. The exit program would build the key and delete any
> outstanding TS queues. Of course, Frank's shop may put all TS Queues
> to the VSAM AUX Temp Storage File rather than to MAIN storage, so
> memory leaks might not be a problem for him. At least in the old
> days, TS queues in MAIN storage were considerably faster than in AUX.
>

Ah, for the Oldene Dayse when a programmer was worth 10 such as we see
now... :-)
>
> I calculate the maximum length of the 05 area as 6485 bytes, but
> please check my work for errors! (I apologize for snipping that
> portion of the original post). That's small enough that it could be
> passed in a COMMAREA, without using a TS Queue. Of course, I don't
> know if Frank Swarbrick's program already has other data being passed
> that would put the COMMAREA over the 32K limit.
>


Do you not think, Arnold, that if the COMMAREA was viable, Frank, (who is
demonstrably no slouch when it comes to programming) would be using it...?
:-) It seems to me fair to assume from what was posted, that a TS queue is
to be utilised...

> Another advantage to using COMMAREA is that it doesn't leave TS Queues
> in memory if the transaction abends. There's less chance of storage
> creep that way.


Undoubtedly. However, there are other considerations for using the COMMAREA
that are way beyond the scope of this particular post. And smart system
design should have a task doing garbage collecting if storage is a
consideration. I definitely like the idea of the terminal ID being part of
the storage queue ID, and your description of using TASK EXIT to clear the
garbage would certainly get my vote.
>
> An interesting problem!


I thought it was pretty mundane, actually, but all problems are
'interesting' until you have a solution... :-)

Pete.



Pete Dashwood

2005-04-22, 8:55 am


"William M. Klein" <wmklein@nospam.netcom.com> wrote in message
news:5E%9e.653112$za2.100755@news.easynews.com...
> Frank (and Arnold and Pete),
> I know just enough to be dangerous in this area and I do *NOT* know if

the
> following CICS (on z/OS) option is available for VSE, but ...
>
> You *might* want to look at the LENGTH translator option - described (for

CICS
> TS V3.1 - for z/OS) at:
>
>

http://publibz.boulder.ibm.com/cgi-...3b00/2.1.5.1.19
>
>


Thanks Bill. Even though I have no intention whatsoever of EVER coding CICS
(or even COBOL) on a mainframe again, I respect your judgement enough to go
and have a look.

It seems to me (and maybe I missed something here?) that LENGTH will default
if you don't set it. There is no difference therefore between allowing the
default, or moving a fixed maximum (which was part of my recommended
solution) to the field before using a READQ with INTO.

There are two things going on here:

1. The LENGTH parameter to the CICS Command level interface.
2. The length of the WS item which contains an ODO.

I am impressed to see that CICS has moved on since I last used it, but has
retained enough of value to keep it recognisable.

I still think IMS/DC is/was a better TP monitor, and I still think CICS
macro level was better for programmers (I mean REAL programmers...:-)) than
this new fangled command nonsense that removes all need for Assembler
understanding... Harrumph! :-))

Harrumph again!

Pete.



Frank Swarbrick

2005-04-22, 3:55 pm

Hi Arnold. Thanks for responding to Pete. I started to reply, but you
stated things much more clearly than I!

As for using the COMMAREA, it's not possible in this case. What our program
really does is reads through a customer's transactions for a certain period
(up to an entire month), builds a "page" of transactions (44 transactions
per page) and writes each page to the TS queue. So there's not just one
ITEM in the TS queue. For one particular customer if I look at their March
transactions it takes 734 pages. That's over 32000 transactions! Yikes.
If only for this customer alone this is the reason I like the variable
length table. Because, while each transaction has a tran description and
there are four transactions per tran-detail-line (don't expect to understand
this without knowing more about what we're doing here), not every
transaction has a bkpg description. So, for this one customer, assuming
none of their 32000 transactions has a bkpg description, I'm saving
1,970,056 bytes of TS queue storage (734 * 3801 = 2,789,934) vs (734 * 6485
= 4,759,990).

Currently I am actually doing this without using ODO. Instead I have a
simply OCCURS 44 times for the TS-TRAN-BKPG-DESC table and I calculate for
the WRITEQ as
COMPUTE TS-LEN-TRAN = LENGTH OF TS-TRAN-TABLES + (TS-HOLD-TRAN-BKPG-SUB *
LENGTH OF TS-TRAN-BKPG-DESC)
and I calculate the length for the READQ simply as
MOVE LENGTH OF TS-PAGE-OF-TRANSACTIONS.

This works fine, but I am now doing some changes to add *another* table to
the end of it, again one where not every transaction in the fixed length
part has a corresponding one in the new table. So I am trying to have to
ODO's. It seems to work (so far, but I've only tested one situation so
far), but I still have to hard code the 44 when using the following
calculation (on the READQ):
MOVE 44 TO TS-TRAN-BKPG-CNT
TS-TRAN-OTHER-CNT
MOVE LENGTH OF TS-PAGE-OF-TRANSACTIONS TO TS-LEN-TRAN.

(Yes, I actually use a "variable" name set to a value of 44, but anyway...)

Hope this explains why I'm going through all this trouble. Well, plus is a
fun intellectual exercise!

Oh, and BTW, we *do* delete the TS queue record after the user has exited
the function. If we didn't we'd run out of room rather quickly! (I believe
we do use MAIN storage instead of AUX, unless we run out of MAIN. But I
could be wrong...)

Frank


---
Frank Swarbrick
Senior Developer/Analyst - Mainframe Applications
FirstBank Data Corporation - Lakewood, CO USA



Pete Dashwood wrote:[color=darkred]
> "Frank Swarbrick" <Frank.Swarbrick@efirstbank.com> wrote in message
> news:3cqhijF6oi4baU1@individual.net...
> (snip)
>
> it
>
>
>
> It is 25 years since I wrote a CICS COBOL Program and in my day we had to
> use GETMAIN to allocate the storage before writing the Queue. (Of course,

we
> were REAL programmers... :-)) I see from your code that this is no longer
> required. :-)
>
> I think there is a fundamental misunderstanding here, Frank. The length

does
> NOT need to be set when you READ.


Mr. Dashwood, I beg to differ.

If you are doing a READQ TS with the INTO option the LENGTH field must
be initialized with the maximum length. Think about it. The temp
storage queue record might be as big as 32K bytes. If the queue
record is too big large for the INTO field, how is CICS to know when
to raise the LENGERR condition or EIBRESP value? How else is the
program supposed to know when the data is truncated?

>
> CICS will set the length into the parameter you specify. (Well, it did

when
> I used it, but we didn't have INTO - 'into' implies you already have the
> storage allocated and should therefore know its length...)
>
> I would have coded:
>
> EXEC CICS
> READQ TS
> QUEUE (TS-QUEUE)
> SET (TS-POINTER)
> ITEM (WS-ITEM)
> LENGTH (TS-LEN-TRAN)
> END-EXEC.
>
> CICS would have grabbed storage for the area corresponding to TS-POINTER,
> read the item on the queue indicated by ITEM, and placed the length of it
> into LENGTH.


This is true, of course. But if you use the SET option you cannot
READQ directly into WORKING-STORAGE. You must define a pointer for a
LINKAGE SECTION item, GETMAIN it, and establish addressability to it.
You must do the GETMAIN every time the program is re-entered. And
you still have the possibility of reading a temp storage queue record
larger than your space allocation.

>
> It is then a trivial exercise to calculate the number of occurrences that
> are required in your TS-TRAN-BKPG-CNT as:
>
> (TS-LEN-TRAN - fixed part of record) / length of TS-TRAN-BKPG-DESC
>
> ...which is pretty close to what you suggested.
>
> The only fly I can see in this ointment is that INTO doesn't work like

that,
> and actually requires the length to be in it before the read.


This is true.

>
> If that is the case, then why not simply define a buffer area of say,

4096
> bytes and read into that? Then you can work out how much data you

actually
> received (I can't believe it doesn't put it into TS-LENGTH, but I don't

have
> access to the latest CICS stuff), calculate the value for

TS-TRAN-BKPG-CNT
> as shown, and, once you have set the number of occurrences correctly,

MOVE
> the record from the data buffer to your record definition.


That's certainly one solution that would work.

>
> SUMMARISING:
>
> 1. I believe that a CICS READQ will SET the length it gets. (If I am

wrong,
> and INTO doesn't work like that, then use a fixed length buffer and do

the
> job that CICS SHOULD have done...calculate the length you actually
> received).


READQ TS always sets the LENGTH field equal to the length actually
retrieved, whether you use SET or INTO. But if you use the INTO
option, you must initialize the LENGTH field with the maximum length
of the working-storage field, and you must do it before executing the
READQ command. If you are using INTO, and the TS Queue record is
longer than the maximum length, you get a LENGERR condition.

That's just the way it works.

>
> 2. Once you have the actual data length of the item, you can easily
> calculate (and set into the TS-TRAN-BKPG-CNT field), the the number of
> occurrences of your variable data.
>
> No hard coding.


I agree that hard-coding the maximum length is a less desirable
solution, because it makes future changes a little more difficult. I
do see it done that way quite often, even for fixed-length TS queue
records when it would be quite easy to use LENGTH OF.

It ought to be possible to compute the the maximum length in a way
that simplifies future maintenance, but I can't figure out an easy way
to do it without defining a constant for the maximum number of
occurrences.

Truthfully, the programmers in my shop avoid ODO like the plague, and
given that CICS stands for "Core Is Cheap, Sucker", it's easier to use
a fixed-length queue record.

An interesting problem is how to get rid of those TS Queue MAIN
records when transactions are aborted. We had to use a CICS TASK Exit
to purge them. Typically the queue name is the Transaction ID plus
the Terminal ID. The exit program would build the key and delete any
outstanding TS queues. Of course, Frank's shop may put all TS Queues
to the VSAM AUX Temp Storage File rather than to MAIN storage, so
memory leaks might not be a problem for him. At least in the old
days, TS queues in MAIN storage were considerably faster than in AUX.

>
> Hope this helps,
>
> Pete.
>


I calculate the maximum length of the 05 area as 6485 bytes, but
please check my work for errors! (I apologize for snipping that
portion of the original post). That's small enough that it could be
passed in a COMMAREA, without using a TS Queue. Of course, I don't
know if Frank Swarbrick's program already has other data being passed
that would put the COMMAREA over the 32K limit.

Another advantage to using COMMAREA is that it doesn't leave TS Queues
in memory if the transaction abends. There's less chance of storage
creep that way.

An interesting problem!

--
http://arnold.trembley.home.att.net/



Frank Swarbrick

2005-04-22, 3:55 pm

We do use the LENGTH CICS option, but that would not help in this case. All
(as far as I know) that the LENGTH option does is uses an implied
LENGTH(LENGTH OF data-area). Since the "LENGTH OF" still depends on the
value of the ODO variable it (the ODO variable) must still be set to it's
largest value in order for the LENGTH OF operation to return the maximum
size of the entire group.

Thanks,
Frank

---
Frank Swarbrick
Senior Developer/Analyst - Mainframe Applications
FirstBank Data Corporation - Lakewood, CO USA

Frank (and Arnold and Pete),
I know just enough to be dangerous in this area and I do *NOT* know if the

following CICS (on z/OS) option is available for VSE, but ...

You *might* want to look at the LENGTH translator option - described (for
CICS
TS V3.1 - for z/OS) at:


http://publibz.boulder.ibm.com/cgi-...hp3b00/2.1.5.1.
19


--
Bill Klein
wmklein <at> ix.netcom.com
"Arnold Trembley" <arnold.trembley@worldnet.att.net> wrote in message
news:22%9e.623343$w62.158596@bgtnsc05-news.ops.worldnet.att.net...[color=darkred]
>
>
> Pete Dashwood wrote:
for[color=darkred]
to[color=darkred]
we[color=darkred]
longer[color=darkred]
does[color=darkred]
>
> Mr. Dashwood, I beg to differ.
>
> If you are doing a READQ TS with the INTO option the LENGTH field must be


> initialized with the maximum length. Think about it. The temp storage

queue
> record might be as big as 32K bytes. If the queue record is too big large

for
> the INTO field, how is CICS to know when to raise the LENGERR condition or


> EIBRESP value? How else is the program supposed to know when the data is


> truncated?
>
when[color=darkred]
TS-POINTER,[color=darkred]
it[color=darkred]
>
> This is true, of course. But if you use the SET option you cannot READQ
> directly into WORKING-STORAGE. You must define a pointer for a LINKAGE
> SECTION item, GETMAIN it, and establish addressability to it. You must do

the
> GETMAIN every time the program is re-entered. And you still have the
> possibility of reading a temp storage queue record larger than your space


> allocation.
>
that[color=darkred]
that,[color=darkred]
>
> This is true.
>
4096[color=darkred]
actually[color=darkred]
have[color=darkred]
TS-TRAN-BKPG-CNT[color=darkred]
MOVE[color=darkred]
>
> That's certainly one solution that would work.
>
wrong,[color=darkred]
the[color=darkred]
>
> READQ TS always sets the LENGTH field equal to the length actually

retrieved,
> whether you use SET or INTO. But if you use the INTO option, you must
> initialize the LENGTH field with the maximum length of the working-storage


> field, and you must do it before executing the READQ command. If you are


> using INTO, and the TS Queue record is longer than the maximum length, you

get
> a LENGERR condition.
>
> That's just the way it works.
>
>
> I agree that hard-coding the maximum length is a less desirable solution,


> because it makes future changes a little more difficult. I do see it done


> that way quite often, even for fixed-length TS queue records when it would

be
> quite easy to use LENGTH OF.
>
> It ought to be possible to compute the the maximum length in a way that
> simplifies future maintenance, but I can't figure out an easy way to do it


> without defining a constant for the maximum number of occurrences.
>
> Truthfully, the programmers in my shop avoid ODO like the plague, and

given
> that CICS stands for "Core Is Cheap, Sucker", it's easier to use a
> fixed-length queue record.
>
> An interesting problem is how to get rid of those TS Queue MAIN records

when
> transactions are aborted. We had to use a CICS TASK Exit to purge them.
> Typically the queue name is the Transaction ID plus the Terminal ID. The

exit
> program would build the key and delete any outstanding TS queues. Of

course,
> Frank's shop may put all TS Queues to the VSAM AUX Temp Storage File

rather
> than to MAIN storage, so memory leaks might not be a problem for him. At


> least in the old days, TS queues in MAIN storage were considerably faster

than
> in AUX.
>
>
> I calculate the maximum length of the 05 area as 6485 bytes, but please

check
> my work for errors! (I apologize for snipping that portion of the

original
> post). That's small enough that it could be passed in a COMMAREA, without


> using a TS Queue. Of course, I don't know if Frank Swarbrick's program
> already has other data being passed that would put the COMMAREA over the

32K
> limit.
>
> Another advantage to using COMMAREA is that it doesn't leave TS Queues in


> memory if the transaction abends. There's less chance of storage creep

that
> way.
>
> An interesting problem!
>
> --
> http://arnold.trembley.home.att.net/
>





Richard

2005-04-22, 8:55 pm

> It seems to me (and maybe I missed something here?) that LENGTH will
default
> if you don't set it.


How does it tell the difference ?

It is set to zero or -1 before your program runs ?

Pete Dashwood

2005-04-23, 3:55 am


"Frank Swarbrick" <Frank.Swarbrick@efirstbank.com> wrote in message
news:3csk8tF6o7phlU1@individual.net...
> Hi Arnold. Thanks for responding to Pete. I started to reply, but you
> stated things much more clearly than I!
>
> As for using the COMMAREA, it's not possible in this case. What our

program
> really does is reads through a customer's transactions for a certain

period
> (up to an entire month), builds a "page" of transactions (44 transactions
> per page) and writes each page to the TS queue. So there's not just one
> ITEM in the TS queue. For one particular customer if I look at their

March
> transactions it takes 734 pages. That's over 32000 transactions! Yikes.
> If only for this customer alone this is the reason I like the variable
> length table. Because, while each transaction has a tran description and
> there are four transactions per tran-detail-line (don't expect to

understand
> this without knowing more about what we're doing here), not every
> transaction has a bkpg description. So, for this one customer, assuming
> none of their 32000 transactions has a bkpg description, I'm saving
> 1,970,056 bytes of TS queue storage (734 * 3801 = 2,789,934) vs (734 *

6485
> = 4,759,990).
>

See comment on NODEs below...

> Currently I am actually doing this without using ODO. Instead I have a
> simply OCCURS 44 times for the TS-TRAN-BKPG-DESC table and I calculate for
> the WRITEQ as
> COMPUTE TS-LEN-TRAN = LENGTH OF TS-TRAN-TABLES + (TS-HOLD-TRAN-BKPG-SUB

*
> LENGTH OF TS-TRAN-BKPG-DESC)
> and I calculate the length for the READQ simply as
> MOVE LENGTH OF TS-PAGE-OF-TRANSACTIONS.
>
> This works fine, but I am now doing some changes to add *another* table to
> the end of it, again one where not every transaction in the fixed length
> part has a corresponding one in the new table. So I am trying to have to
> ODO's. It seems to work (so far, but I've only tested one situation so
> far), but I still have to hard code the 44 when using the following
> calculation (on the READQ):
> MOVE 44 TO TS-TRAN-BKPG-CNT
> TS-TRAN-OTHER-CNT
> MOVE LENGTH OF TS-PAGE-OF-TRANSACTIONS TO TS-LEN-TRAN.
>
> (Yes, I actually use a "variable" name set to a value of 44, but

anyway...)
>
> Hope this explains why I'm going through all this trouble. Well, plus is

a
> fun intellectual exercise!
>
> Oh, and BTW, we *do* delete the TS queue record after the user has exited
> the function. If we didn't we'd run out of room rather quickly! (I

believe
> we do use MAIN storage instead of AUX, unless we run out of MAIN. But I
> could be wrong...)
>
> Frank
>


The use of OCCURS and ODO is simply redundant in modern data procesing. The
removal of repeating groups is fundamental to RDB normalization. Whether you
implement the data structure into an RDB or not, the process of
normalization is 'good' for data. Variable length data should be stored in
collections. Where you put the collection (memory or disk) can be determined
by an attribute of the collection.

This is an application where the use of an OO Collection would be ideal, and
simple. There is a class called NODE that is a collection capable of
maintaining itself (it is ideal for building tree views, as nodes can have
nodes attached) and a single level node would solve this problem elegantly.
(You could also organise a collection of nodes where each node was a
'page'...)Any number of 'lines' can be added to each node, and paging them
back is trivial. The class supports trees or simple flat structures.

IF OO was in use, someone would have written (or should have...) a Class
that would implement nodes into the TS Queue. (That would be a one time
solution of this problem and would work in all future cases, eliminating ODO
altogether...)

Looking at this I can see why the COBOL approach is losing ground. Compared
to modern alternatives it is just clumsy and unwieldy.

I understand that people have to solve things within the constraints of the
environment in which they work.

I wouldn't mind a dollar for every time I wished the environment I was
working in was better...

But then, if wishese were horses, beggars would ride...:-)

Pete.
<snip>



William M. Klein

2005-04-23, 3:55 am

I knew the answer for VSE (where Frank is), but I just checked about CICS and
z/OS

From:
http://publibz.boulder.ibm.com/cgi-...KS/igy3pg20/6.1

"COBOL class definitions and methods cannot contain EXEC CICS statements,
cannot be run in a CICS environment, and cannot be compiled using the CICS
compiler option."

.... but other than that, how was the play Mrs. Lincoln? <G>

--
Bill Klein
wmklein <at> ix.netcom.com
"Pete Dashwood" <dashwood@enternet.co.nz> wrote in message
news:3ctno6F6mb06qU1@individual.net...
>
> "Frank Swarbrick" <Frank.Swarbrick@efirstbank.com> wrote in message
> news:3csk8tF6o7phlU1@individual.net...
> program
> period
> March
> understand
> 6485
> See comment on NODEs below...
>
> *
> anyway...)
> a
> believe
>
> The use of OCCURS and ODO is simply redundant in modern data procesing. The
> removal of repeating groups is fundamental to RDB normalization. Whether you
> implement the data structure into an RDB or not, the process of
> normalization is 'good' for data. Variable length data should be stored in
> collections. Where you put the collection (memory or disk) can be determined
> by an attribute of the collection.
>
> This is an application where the use of an OO Collection would be ideal, and
> simple. There is a class called NODE that is a collection capable of
> maintaining itself (it is ideal for building tree views, as nodes can have
> nodes attached) and a single level node would solve this problem elegantly.
> (You could also organise a collection of nodes where each node was a
> 'page'...)Any number of 'lines' can be added to each node, and paging them
> back is trivial. The class supports trees or simple flat structures.
>
> IF OO was in use, someone would have written (or should have...) a Class
> that would implement nodes into the TS Queue. (That would be a one time
> solution of this problem and would work in all future cases, eliminating ODO
> altogether...)
>
> Looking at this I can see why the COBOL approach is losing ground. Compared
> to modern alternatives it is just clumsy and unwieldy.
>
> I understand that people have to solve things within the constraints of the
> environment in which they work.
>
> I wouldn't mind a dollar for every time I wished the environment I was
> working in was better...
>
> But then, if wishese were horses, beggars would ride...:-)
>
> Pete.
> <snip>
>
>
>



Arnold Trembley

2005-04-23, 3:55 am



Pete Dashwood wrote:
> (snip)
> Well Arnold, I think this is a case of premature ejaculation on your part.
> :-) Why not read the WHOLE response before grabbing a keyboard?


Please accept my apologies. This has never happened to me before. :-)

>
> I mentioned that I wasn't sure how INTO might work and I covered both cases
> (it requires a length or it doesn't) in my post.
>
> The request was for 'any thoughts'... I posted mine.


I don't think we actually disagree all that much on the solutions,
although I still make my living coding CICS COBOL, and enjoy it very much.

With kindest regards,

--
http://arnold.trembley.home.att.net/

Arnold Trembley

2005-04-23, 3:55 am



Frank Swarbrick wrote:

> Hi Arnold. Thanks for responding to Pete. I started to reply, but you
> stated things much more clearly than I!
>
> As for using the COMMAREA, it's not possible in this case. What our program
> really does is reads through a customer's transactions for a certain period
> (up to an entire month), builds a "page" of transactions (44 transactions
> per page) and writes each page to the TS queue. So there's not just one
> ITEM in the TS queue. For one particular customer if I look at their March
> transactions it takes 734 pages. That's over 32000 transactions! Yikes.
> If only for this customer alone this is the reason I like the variable
> length table. Because, while each transaction has a tran description and
> there are four transactions per tran-detail-line (don't expect to understand
> this without knowing more about what we're doing here), not every
> transaction has a bkpg description. So, for this one customer, assuming
> none of their 32000 transactions has a bkpg description, I'm saving
> 1,970,056 bytes of TS queue storage (734 * 3801 = 2,789,934) vs (734 * 6485
> = 4,759,990).


Even in these days when you can have a CICS region using 200 megabytes
of "above the line" storage, saving nearly 2 megabytes for a single
transaction might have some value!

> (snip)
> Hope this explains why I'm going through all this trouble. Well, plus is a
> fun intellectual exercise!
>
> Oh, and BTW, we *do* delete the TS queue record after the user has exited
> the function. If we didn't we'd run out of room rather quickly! (I believe
> we do use MAIN storage instead of AUX, unless we run out of MAIN. But I
> could be wrong...)


IIRC, the problem we had was with CICS screens that were automagically
updated every two minutes. Sometimes the transaction was aborted, and
the program was prevented from running its normal clean-up routine.
That's when the CICS task abend exit would take control. We pointed
it to a user-written program that built the TS Queue name, searched
for queues, and purged them. It's quite common for CICS programs to
use TS queues for large amounts of presentation data, and it's also
quite common to use the transaction ID and terminal ID as the queue name.

And with regard to MAIN versus AUX, I believe the CICS system
programmer can set a DFHSIT parameter to make TS Queues default to
MAIN storage. But regardless of the default, you can add a MAIN or
AUX keyword to your WRITEQ TS command and explicitly control the
allocation from within your program.

With kindest regards,

--
http://arnold.trembley.home.att.net/

Arnold Trembley

2005-04-23, 8:55 am



Pete Dashwood wrote:

> (snip)
> I am impressed to see that CICS has moved on since I last used it, but has
> retained enough of value to keep it recognisable.
>
> I still think IMS/DC is/was a better TP monitor, and I still think CICS
> macro level was better for programmers (I mean REAL programmers...:-)) than
> this new fangled command nonsense that removes all need for Assembler
> understanding... Harrumph! :-))
>
> Harrumph again!
>
> Pete.


I've never had the opportunity to work with IMS/DC, so I don't know
how it compares to CICS. But I don't miss macro-level CICS. Perhaps
DocDwarf has more recent experience with it. The last time I worked
on a macro-level CICS program would have been in 1992. I seem to
recall that macro-level was a little more difficult to work with. I
think you lost all the contents of working-storage (except for
constants) with every invocation of your program. At least with
Command-level CICS, your working-storage is preserved when your
program is re-entered.

Back in 1985 IBM was telling customers that they planned to drop
support for macro-level CICS, and only keep command-level CICS. This
became a bit of a problem for Y2K, because the only supported CICS
releases no longer allowed macro-level code.

With kindest regards,

--
http://arnold.trembley.home.att.net/

Pete Dashwood

2005-04-23, 8:55 am


"Arnold Trembley" <arnold.trembley@worldnet.att.net> wrote in message
news:zClae.629692$w62.485119@bgtnsc05-news.ops.worldnet.att.net...
>
>
> Pete Dashwood wrote:
part.[color=darkred]
>
> Please accept my apologies. This has never happened to me before. :-)
>


Yeah... yeah... that's what we ALL say... :-)

I'm pleased to see that you and Frank have sorted it, and along the way I
gained some insight into 'modern' CICS.

Cheers,

Pete.



Pete Dashwood

2005-04-23, 8:55 am


"William M. Klein" <wmklein@nospam.netcom.com> wrote in message
news:jelae.759498$za2.118900@news.easynews.com...
> I knew the answer for VSE (where Frank is), but I just checked about CICS

and
> z/OS
>



> From:
> http://publibz.boulder.ibm.com/cgi-...KS/igy3pg20/6.1
>
> "COBOL class definitions and methods cannot contain EXEC CICS statements,
> cannot be run in a CICS environment, and cannot be compiled using the

CICS
> compiler option."
>
> ... but other than that, how was the play Mrs. Lincoln? <G>
>


:-)
Good point, Bill. I take it from this that OO cannot be used with CICS?

In which case, as they say in Texas, "Your alligator mouth just closed down
mah hummin' bird ass..." :-)

I promise not to post any more on subjects for which I am demonstrably
unqualified.

Cheers,

Pete.


<snip>



docdwarf@panix.com

2005-04-24, 3:55 am

In article <OYlae.629784$w62.576229@bgtnsc05-news.ops.worldnet.att.net>,
Arnold Trembley <arnold.trembley@worldnet.att.net> wrote:

[snip]

>But I don't miss macro-level CICS. Perhaps
>DocDwarf has more recent experience with it.


I do my best to keep emoticons out of my writings... but at the moment I
long for one which expresses the way a bad actor in a Grade-C movie lies
on a bed, eyes tightly closed, head whipping back-and-forth, saying 'No...
no... NO!' in order to indicate a bad dream.

DD

docdwarf@panix.com

2005-04-24, 3:55 am

In article <3cuiulF6oblupU1@individual.net>,
Pete Dashwood <dashwood@enternet.co.nz> wrote:
>
>"William M. Klein" <wmklein@nospam.netcom.com> wrote in message news:jelae.759498$za2.118900@news.easynews.com...


[snip]

>
>:-)
>Good point, Bill. I take it from this that OO cannot be used with CICS?


I am an applications jockey, not a systems coder... but I'd guess that OO
cannot be used with CICS, no. As I was taught lo, those many years ago...
CICS is essentially a patch (some would say a 'hack') on the System370
operating system, circa 1971, and getting OO principles that deeply into
the machine has not been, I believe, one of IBM's greatest concerns.

DD
Arnold Trembley

2005-04-24, 8:55 am



Pete Dashwood wrote:
> "Frank Swarbrick" <Frank.Swarbrick@efirstbank.com> wrote in message
> news:3cqhijF6oi4baU1@individual.net...
> (snip)
>
> it
>
>
>
> It is 25 years since I wrote a CICS COBOL Program and in my day we had to
> use GETMAIN to allocate the storage before writing the Queue. (Of course, we
> were REAL programmers... :-)) I see from your code that this is no longer
> required. :-)
>
> I think there is a fundamental misunderstanding here, Frank. The length does
> NOT need to be set when you READ.


Mr. Dashwood, I beg to differ.

If you are doing a READQ TS with the INTO option the LENGTH field must
be initialized with the maximum length. Think about it. The temp
storage queue record might be as big as 32K bytes. If the queue
record is too big large for the INTO field, how is CICS to know when
to raise the LENGERR condition or EIBRESP value? How else is the
program supposed to know when the data is truncated?

>
> CICS will set the length into the parameter you specify. (Well, it did when
> I used it, but we didn't have INTO - 'into' implies you already have the
> storage allocated and should therefore know its length...)
>
> I would have coded:
>
> EXEC CICS
> READQ TS
> QUEUE (TS-QUEUE)
> SET (TS-POINTER)
> ITEM (WS-ITEM)
> LENGTH (TS-LEN-TRAN)
> END-EXEC.
>
> CICS would have grabbed storage for the area corresponding to TS-POINTER,
> read the item on the queue indicated by ITEM, and placed the length of it
> into LENGTH.


This is true, of course. But if you use the SET option you cannot
READQ directly into WORKING-STORAGE. You must define a pointer for a
LINKAGE SECTION item, GETMAIN it, and establish addressability to it.
You must do the GETMAIN every time the program is re-entered. And
you still have the possibility of reading a temp storage queue record
larger than your space allocation.

>
> It is then a trivial exercise to calculate the number of occurrences that
> are required in your TS-TRAN-BKPG-CNT as:
>
> (TS-LEN-TRAN - fixed part of record) / length of TS-TRAN-BKPG-DESC
>
> ...which is pretty close to what you suggested.
>
> The only fly I can see in this ointment is that INTO doesn't work like that,
> and actually requires the length to be in it before the read.


This is true.

>
> If that is the case, then why not simply define a buffer area of say, 4096
> bytes and read into that? Then you can work out how much data you actually
> received (I can't believe it doesn't put it into TS-LENGTH, but I don't have
> access to the latest CICS stuff), calculate the value for TS-TRAN-BKPG-CNT
> as shown, and, once you have set the number of occurrences correctly, MOVE
> the record from the data buffer to your record definition.


That's certainly one solution that would work.

>
> SUMMARISING:
>
> 1. I believe that a CICS READQ will SET the length it gets. (If I am wrong,
> and INTO doesn't work like that, then use a fixed length buffer and do the
> job that CICS SHOULD have done...calculate the length you actually
> received).


READQ TS always sets the LENGTH field equal to the length actually
retrieved, whether you use SET or INTO. But if you use the INTO
option, you must initialize the LENGTH field with the maximum length
of the working-storage field, and you must do it before executing the
READQ command. If you are using INTO, and the TS Queue record is
longer than the maximum length, you get a LENGERR condition.

That's just the way it works.

>
> 2. Once you have the actual data length of the item, you can easily
> calculate (and set into the TS-TRAN-BKPG-CNT field), the the number of
> occurrences of your variable data.
>
> No hard coding.


I agree that hard-coding the maximum length is a less desirable
solution, because it makes future changes a little more difficult. I
do see it done that way quite often, even for fixed-length TS queue
records when it would be quite easy to use LENGTH OF.

It ought to be possible to compute the the maximum length in a way
that simplifies future maintenance, but I can't figure out an easy way
to do it without defining a constant for the maximum number of
occurrences.

Truthfully, the programmers in my shop avoid ODO like the plague, and
given that CICS stands for "Core Is Cheap, Sucker", it's easier to use
a fixed-length queue record.

An interesting problem is how to get rid of those TS Queue MAIN
records when transactions are aborted. We had to use a CICS TASK Exit
to purge them. Typically the queue name is the Transaction ID plus
the Terminal ID. The exit program would build the key and delete any
outstanding TS queues. Of course, Frank's shop may put all TS Queues
to the VSAM AUX Temp Storage File rather than to MAIN storage, so
memory leaks might not be a problem for him. At least in the old
days, TS queues in MAIN storage were considerably faster than in AUX.

>
> Hope this helps,
>
> Pete.
>


I calculate the maximum length of the 05 area as 6485 bytes, but
please check my work for errors! (I apologize for snipping that
portion of the original post). That's small enough that it could be
passed in a COMMAREA, without using a TS Queue. Of course, I don't
know if Frank Swarbrick's program already has other data being passed
that would put the COMMAREA over the 32K limit.

Another advantage to using COMMAREA is that it doesn't leave TS Queues
in memory if the transaction abends. There's less chance of storage
creep that way.

An interesting problem!

--
http://arnold.trembley.home.att.net/

William M. Klein

2005-04-24, 8:55 am

Frank (and Arnold and Pete),
I know just enough to be dangerous in this area and I do *NOT* know if the
following CICS (on z/OS) option is available for VSE, but ...

You *might* want to look at the LENGTH translator option - described (for CICS
TS V3.1 - for z/OS) at:

http://publibz.boulder.ibm.com/cgi-...3b00/2.1.5.1.19


--
Bill Klein
wmklein <at> ix.netcom.com
"Arnold Trembley" <arnold.trembley@worldnet.att.net> wrote in message
news:22%9e.623343$w62.158596@bgtnsc05-news.ops.worldnet.att.net...
>
>
> Pete Dashwood wrote:
>
> Mr. Dashwood, I beg to differ.
>
> If you are doing a READQ TS with the INTO option the LENGTH field must be
> initialized with the maximum length. Think about it. The temp storage queue
> record might be as big as 32K bytes. If the queue record is too big large for
> the INTO field, how is CICS to know when to raise the LENGERR condition or
> EIBRESP value? How else is the program supposed to know when the data is
> truncated?
>
>
> This is true, of course. But if you use the SET option you cannot READQ
> directly into WORKING-STORAGE. You must define a pointer for a LINKAGE
> SECTION item, GETMAIN it, and establish addressability to it. You must do the
> GETMAIN every time the program is re-entered. And you still have the
> possibility of reading a temp storage queue record larger than your space
> allocation.
>
>
> This is true.
>
>
> That's certainly one solution that would work.
>
>
> READQ TS always sets the LENGTH field equal to the length actually retrieved,
> whether you use SET or INTO. But if you use the INTO option, you must
> initialize the LENGTH field with the maximum length of the working-storage
> field, and you must do it before executing the READQ command. If you are
> using INTO, and the TS Queue record is longer than the maximum length, you get
> a LENGERR condition.
>
> That's just the way it works.
>
>
> I agree that hard-coding the maximum length is a less desirable solution,
> because it makes future changes a little more difficult. I do see it done
> that way quite often, even for fixed-length TS queue records when it would be
> quite easy to use LENGTH OF.
>
> It ought to be possible to compute the the maximum length in a way that
> simplifies future maintenance, but I can't figure out an easy way to do it
> without defining a constant for the maximum number of occurrences.
>
> Truthfully, the programmers in my shop avoid ODO like the plague, and given
> that CICS stands for "Core Is Cheap, Sucker", it's easier to use a
> fixed-length queue record.
>
> An interesting problem is how to get rid of those TS Queue MAIN records when
> transactions are aborted. We had to use a CICS TASK Exit to purge them.
> Typically the queue name is the Transaction ID plus the Terminal ID. The exit
> program would build the key and delete any outstanding TS queues. Of course,
> Frank's shop may put all TS Queues to the VSAM AUX Temp Storage File rather
> than to MAIN storage, so memory leaks might not be a problem for him. At
> least in the old days, TS queues in MAIN storage were considerably faster than
> in AUX.
>
>
> I calculate the maximum length of the 05 area as 6485 bytes, but please check
> my work for errors! (I apologize for snipping that portion of the original
> post). That's small enough that it could be passed in a COMMAREA, without
> using a TS Queue. Of course, I don't know if Frank Swarbrick's program
> already has other data being passed that would put the COMMAREA over the 32K
> limit.
>
> Another advantage to using COMMAREA is that it doesn't leave TS Queues in
> memory if the transaction abends. There's less chance of storage creep that
> way.
>
> An interesting problem!
>
> --
> http://arnold.trembley.home.att.net/
> 



Pete Dashwood

2005-04-24, 8:55 am


"Arnold Trembley" <arnold.trembley@worldnet.att.net> wrote in message
news:22%9e.623343$w62.158596@bgtnsc05-news.ops.worldnet.att.net...
>
>
> Pete Dashwood wrote:
for[color=darkred]
to[color=darkred]
course, we[color=darkred]
longer[color=darkred]
does[color=darkred]
>
> Mr. Dashwood, I beg to differ.
>
> If you are doing a READQ TS with the INTO option the LENGTH field must
> be initialized with the maximum length. Think about it. The temp
> storage queue record might be as big as 32K bytes. If the queue
> record is too big large for the INTO field, how is CICS to know when
> to raise the LENGERR condition or EIBRESP value? How else is the
> program supposed to know when the data is truncated?


Well Arnold, I think this is a case of premature ejaculation on your part.
:-) Why not read the WHOLE response before grabbing a keyboard?

I mentioned that I wasn't sure how INTO might work and I covered both cases
(it requires a length or it doesn't) in my post.

The request was for 'any thoughts'... I posted mine.
>
when[color=darkred]
TS-POINTER,[color=darkred]
it[color=darkred]
>
> This is true, of course. But if you use the SET option you cannot
> READQ directly into WORKING-STORAGE. You must define a pointer for a
> LINKAGE SECTION item, GETMAIN it, and establish addressability to it.
> You must do the GETMAIN every time the program is re-entered. And
> you still have the possibility of reading a temp storage queue record
> larger than your space allocation.
>


I realise that and suggested using a buffer big ennough to accommodate it.
So what exactly is your issue?
that[color=darkred]
that,[color=darkred]
>
> This is true.
>
4096[color=darkred]
actually[color=darkred]
have[color=darkred]
TS-TRAN-BKPG-CNT[color=darkred]
MOVE[color=darkred]
>
> That's certainly one solution that would work.
>

Ah, we agree that these were NOT bad 'thoughts' then... :-)

However, I didn't do a precise calculation on the record length and I see
from your post below (I always read everything before ejaculating :-)) that
you reckon the size to be 6485, so my quick estimate of 4096 is certainly
insufficient... I hereby extend my buffer to 8192 and declare the problem
solved... :-)
[color=darkred]
wrong,[color=darkred]
the[color=darkred]
>
> READQ TS always sets the LENGTH field equal to the length actually
> retrieved, whether you use SET or INTO. But if you use the INTO
> option, you must initialize the LENGTH field with the maximum length
> of the working-storage field, and you must do it before executing the
> READQ command. If you are using INTO, and the TS Queue record is
> longer than the maximum length, you get a LENGERR condition.
>
> That's just the way it works.


OK. Fair enough. I believe 8192 is longer than the max length of the record
whose definition was posted. So that should work without problem. (Man! I'm
so glad I don't do this stuff for a living any more... :-))
>
>
> I agree that hard-coding the maximum length is a less desirable
> solution, because it makes future changes a little more difficult. I
> do see it done that way quite often, even for fixed-length TS queue
> records when it would be quite easy to use LENGTH OF.
>
> It ought to be possible to compute the the maximum length in a way
> that simplifies future maintenance, but I can't figure out an easy way
> to do it without defining a constant for the maximum number of
> occurrences.


It is described above.

>
> Truthfully, the programmers in my shop avoid ODO like the plague, and
> given that CICS stands for "Core Is Cheap, Sucker", it's easier to use
> a fixed-length queue record.
>


On this, you will hear no dissent from me. I am also on record as stating my
position that ODO is anathema. The overheads it incurs are simply not worth
the storage savings in these days of cheap storage. It is a remnant (like
many things in COBOL) of a bygone era when priorities were different from
the realities we face today.

> An interesting problem is how to get rid of those TS Queue MAIN
> records when transactions are aborted. We had to use a CICS TASK Exit
> to purge them. Typically the queue name is the Transaction ID plus
> the Terminal ID. The exit program would build the key and delete any
> outstanding TS queues. Of course, Frank's shop may put all TS Queues
> to the VSAM AUX Temp Storage File rather than to MAIN storage, so
> memory leaks might not be a problem for him. At least in the old
> days, TS queues in MAIN storage were considerably faster than in AUX.
>

Ah, for the Oldene Dayse when a programmer was worth 10 such as we see
now... :-)
>
> I calculate the maximum length of the 05 area as 6485 bytes, but
> please check my work for errors! (I apologize for snipping that
> portion of the original post). That's small enough that it could be
> passed in a COMMAREA, without using a TS Queue. Of course, I don't
> know if Frank Swarbrick's program already has other data being passed
> that would put the COMMAREA over the 32K limit.
>


Do you not think, Arnold, that if the COMMAREA was viable, Frank, (who is
demonstrably no slouch when it comes to programming) would be using it...?
:-) It seems to me fair to assume from what was posted, that a TS queue is
to be utilised...

> Another advantage to using COMMAREA is that it doesn't leave TS Queues
> in memory if the transaction abends. There's less chance of storage
> creep that way.


Undoubtedly. However, there are other considerations for using the COMMAREA
that are way beyond the scope of this particular post. And smart system
design should have a task doing garbage collecting if storage is a
consideration. I definitely like the idea of the terminal ID being part of
the storage queue ID, and your description of using TASK EXIT to clear the
garbage would certainly get my vote.
>
> An interesting problem!


I thought it was pretty mundane, actually, but all problems are
'interesting' until you have a solution... :-)

Pete.



Frank Swarbrick

2005-04-24, 8:55 pm

We do use the LENGTH CICS option, but that would not help in this case. All
(as far as I know) that the LENGTH option does is uses an implied
LENGTH(LENGTH OF data-area). Since the "LENGTH OF" still depends on the
value of the ODO variable it (the ODO variable) must still be set to it's
largest value in order for the LENGTH OF operation to return the maximum
size of the entire group.

Thanks,
Frank

---
Frank Swarbrick
Senior Developer/Analyst - Mainframe Applications
FirstBank Data Corporation - Lakewood, CO USA

Frank (and Arnold and Pete),
I know just enough to be dangerous in this area and I do *NOT* know if the

following CICS (on z/OS) option is available for VSE, but ...

You *might* want to look at the LENGTH translator option - described (for
CICS
TS V3.1 - for z/OS) at:


http://publibz.boulder.ibm.com/cgi-...hp3b00/2.1.5.1.
19


--
Bill Klein
wmklein <at> ix.netcom.com
"Arnold Trembley" <arnold.trembley@worldnet.att.net> wrote in message
news:22%9e.623343$w62.158596@bgtnsc05-news.ops.worldnet.att.net...[color=darkred]
>
>
> Pete Dashwood wrote:
for[color=darkred]
to[color=darkred]
we[color=darkred]
longer[color=darkred]
does[color=darkred]
>
> Mr. Dashwood, I beg to differ.
>
> If you are doing a READQ TS with the INTO option the LENGTH field must be


> initialized with the maximum length. Think about it. The temp storage

queue
> record might be as big as 32K bytes. If the queue record is too big large

for
> the INTO field, how is CICS to know when to raise the LENGERR condition or


> EIBRESP value? How else is the program supposed to know when the data is


> truncated?
>
when[color=darkred]
TS-POINTER,[color=darkred]
it[color=darkred]
>
> This is true, of course. But if you use the SET option you cannot READQ
> directly into WORKING-STORAGE. You must define a pointer for a LINKAGE
> SECTION item, GETMAIN it, and establish addressability to it. You must do

the
> GETMAIN every time the program is re-entered. And you still have the
> possibility of reading a temp storage queue record larger than your space


> allocation.
>
that[color=darkred]
that,[color=darkred]
>
> This is true.
>
4096[color=darkred]
actually[color=darkred]
have[color=darkred]
TS-TRAN-BKPG-CNT[color=darkred]
MOVE[color=darkred]
>
> That's certainly one solution that would work.
>
wrong,[color=darkred]
the[color=darkred]
>
> READQ TS always sets the LENGTH field equal to the length actually

retrieved,
> whether you use SET or INTO. But if you use the INTO option, you must
> initialize the LENGTH field with the maximum length of the working-storage


> field, and you must do it before executing the READQ command. If you are


> using INTO, and the TS Queue record is longer than the maximum length, you

get
> a LENGERR condition.
>
> That's just the way it works.
>
>
> I agree that hard-coding the maximum length is a less desirable solution,


> because it makes future changes a little more difficult. I do see it done


> that way quite often, even for fixed-length TS queue records when it would

be
> quite easy to use LENGTH OF.
>
> It ought to be possible to compute the the maximum length in a way that
> simplifies future maintenance, but I can't figure out an easy way to do it


> without defining a constant for the maximum number of occurrences.
>
> Truthfully, the programmers in my shop avoid ODO like the plague, and

given
> that CICS stands for "Core Is Cheap, Sucker", it's easier to use a
> fixed-length queue record.
>
> An interesting problem is how to get rid of those TS Queue MAIN records

when
> transactions are aborted. We had to use a CICS TASK Exit to purge them.
> Typically the queue name is the Transaction ID plus the Terminal ID. The

exit
> program would build the key and delete any outstanding TS queues. Of

course,
> Frank's shop may put all TS Queues to the VSAM AUX Temp Storage File

rather
> than to MAIN storage, so memory leaks might not be a problem for him. At


> least in the old days, TS queues in MAIN storage were considerably faster

than
> in AUX.
>
>
> I calculate the maximum length of the 05 area as 6485 bytes, but please

check
> my work for errors! (I apologize for snipping that portion of the

original
> post). That's small enough that it could be passed in a COMMAREA, without


> using a TS Queue. Of course, I don't know if Frank Swarbrick's program
> already has other data being passed that would put the COMMAREA over the

32K
> limit.
>
> Another advantage to using COMMAREA is that it doesn't leave TS Queues in


> memory if the transaction abends. There's less chance of storage creep

that
> way.
>
> An interesting problem!
>
> --
> http://arnold.trembley.home.att.net/
>





Frank Swarbrick

2005-04-24, 8:55 pm

Hi Arnold. Thanks for responding to Pete. I started to reply, but you
stated things much more clearly than I!

As for using the COMMAREA, it's not possible in this case. What our program
really does is reads through a customer's transactions for a certain period
(up to an entire month), builds a "page" of transactions (44 transactions
per page) and writes each page to the TS queue. So there's not just one
ITEM in the TS queue. For one particular customer if I look at their March
transactions it takes 734 pages. That's over 32000 transactions! Yikes.
If only for this customer alone this is the reason I like the variable
length table. Because, while each transaction has a tran description and
there are four transactions per tran-detail-line (don't expect to understand
this without knowing more about what we're doing here), not every
transaction has a bkpg description. So, for this one customer, assuming
none of their 32000 transactions has a bkpg description, I'm saving
1,970,056 bytes of TS queue storage (734 * 3801 = 2,789,934) vs (734 * 6485
= 4,759,990).

Currently I am actually doing this without using ODO. Instead I have a
simply OCCURS 44 times for the TS-TRAN-BKPG-DESC table and I calculate for
the WRITEQ as
COMPUTE TS-LEN-TRAN = LENGTH OF TS-TRAN-TABLES + (TS-HOLD-TRAN-BKPG-SUB *
LENGTH OF TS-TRAN-BKPG-DESC)
and I calculate the length for the READQ simply as
MOVE LENGTH OF TS-PAGE-OF-TRANSACTIONS.

This works fine, but I am now doing some changes to add *another* table to
the end of it, again one where not every transaction in the fixed length
part has a corresponding one in the new table. So I am trying to have to
ODO's. It seems to work (so far, but I've only tested one situation so
far), but I still have to hard code the 44 when using the following
calculation (on the READQ):
MOVE 44 TO TS-TRAN-BKPG-CNT
TS-TRAN-OTHER-CNT
MOVE LENGTH OF TS-PAGE-OF-TRANSACTIONS TO TS-LEN-TRAN.

(Yes, I actually use a "variable" name set to a value of 44, but anyway...)

Hope this explains why I'm going through all this trouble. Well, plus is a
fun intellectual exercise!

Oh, and BTW, we *do* delete the TS queue record after the user has exited
the function. If we didn't we'd run out of room rather quickly! (I believe
we do use MAIN storage instead of AUX, unless we run out of MAIN. But I
could be wrong...)

Frank


---
Frank Swarbrick
Senior Developer/Analyst - Mainframe Applications
FirstBank Data Corporation - Lakewood, CO USA



Pete Dashwood wrote:[color=darkred]
> "Frank Swarbrick" <Frank.Swarbrick@efirstbank.com> wrote in message
> news:3cqhijF6oi4baU1@individual.net...
> (snip)
>
> it
>
>
>
> It is 25 years since I wrote a CICS COBOL Program and in my day we had to
> use GETMAIN to allocate the storage before writing the Queue. (Of course,

we
> were REAL programmers... :-)) I see from your code that this is no longer
> required. :-)
>
> I think there is a fundamental misunderstanding here, Frank. The length

does
> NOT need to be set when you READ.


Mr. Dashwood, I beg to differ.

If you are doing a READQ TS with the INTO option the LENGTH field must
be initialized with the maximum length. Think about it. The temp
storage queue record might be as big as 32K bytes. If the queue
record is too big large for the INTO field, how is CICS to know when
to raise the LENGERR condition or EIBRESP value? How else is the
program supposed to know when the data is truncated?

>
> CICS will set the length into the parameter you specify. (Well, it did

when
> I used it, but we didn't have INTO - 'into' implies you already have the
> storage allocated and should therefore know its length...)
>
> I would have coded:
>
> EXEC CICS
> READQ TS
> QUEUE (TS-QUEUE)
> SET (TS-POINTER)
> ITEM (WS-ITEM)
> LENGTH (TS-LEN-TRAN)
> END-EXEC.
>
> CICS would have grabbed storage for the area corresponding to TS-POINTER,
> read the item on the queue indicated by ITEM, and placed the length of it
> into LENGTH.


This is true, of course. But if you use the SET option you cannot
READQ directly into WORKING-STORAGE. You must define a pointer for a
LINKAGE SECTION item, GETMAIN it, and establish addressability to it.
You must do the GETMAIN every time the program is re-entered. And
you still have the possibility of reading a temp storage queue record
larger than your space allocation.

>
> It is then a trivial exercise to calculate the number of occurrences that
> are required in your TS-TRAN-BKPG-CNT as:
>
> (TS-LEN-TRAN - fixed part of record) / length of TS-TRAN-BKPG-DESC
>
> ...which is pretty close to what you suggested.
>
> The only fly I can see in this ointment is that INTO doesn't work like

that,
> and actually requires the length to be in it before the read.


This is true.

>
> If that is the case, then why not simply define a buffer area of say,

4096
> bytes and read into that? Then you can work out how much data you

actually
> received (I can't believe it doesn't put it into TS-LENGTH, but I don't

have
> access to the latest CICS stuff), calculate the value for

TS-TRAN-BKPG-CNT
> as shown, and, once you have set the number of occurrences correctly,

MOVE
> the record from the data buffer to your record definition.


That's certainly one solution that would work.

>
> SUMMARISING:
>
> 1. I believe that a CICS READQ will SET the length it gets. (If I am

wrong,
> and INTO doesn't work like that, then use a fixed length buffer and do

the
> job that CICS SHOULD have done...calculate the length you actually
> received).


READQ TS always sets the LENGTH field equal to the length actually
retrieved, whether you use SET or INTO. But if you use the INTO
option, you must initialize the LENGTH field with the maximum length
of the working-storage field, and you must do it before executing the
READQ command. If you are using INTO, and the TS Queue record is
longer than the maximum length, you get a LENGERR condition.

That's just the way it works.

>
> 2. Once you have the actual data length of the item, you can easily
> calculate (and set into the TS-TRAN-BKPG-CNT field), the the number of
> occurrences of your variable data.
>
> No hard coding.


I agree that hard-coding the maximum length is a less desirable
solution, because it makes future changes a little more difficult. I
do see it done that way quite often, even for fixed-length TS queue
records when it would be quite easy to use LENGTH OF.

It ought to be possible to compute the the maximum length in a way
that simplifies future maintenance, but I can't figure out an easy way
to do it without defining a constant for the maximum number of
occurrences.

Truthfully, the programmers in my shop avoid ODO like the plague, and
given that CICS stands for "Core Is Cheap, Sucker", it's easier to use
a fixed-length queue record.

An interesting problem is how to get rid of those TS Queue MAIN
records when transactions are aborted. We had to use a CICS TASK Exit
to purge them. Typically the queue name is the Transaction ID plus
the Terminal ID. The exit program would build the key and delete any
outstanding TS queues. Of course, Frank's shop may put all TS Queues
to the VSAM AUX Temp Storage File rather than to MAIN storage, so
memory leaks might not be a problem for him. At least in the old
days, TS queues in MAIN storage were considerably faster than in AUX.

>
> Hope this helps,
>
> Pete.
>


I calculate the maximum length of the 05 area as 6485 bytes, but
please check my work for errors! (I apologize for snipping that
portion of the original post). That's small enough that it could be
passed in a COMMAREA, without using a TS Queue. Of course, I don't
know if Frank Swarbrick's program already has other data being passed
that would put the COMMAREA over the 32K limit.

Another advantage to using COMMAREA is that it doesn't leave TS Queues
in memory if the transaction abends. There's less chance of storage
creep that way.

An interesting problem!

--
http://arnold.trembley.home.att.net/



Richard

2005-04-24, 8:55 pm

> It seems to me (and maybe I missed something here?) that LENGTH will
default
> if you don't set it.


How does it tell the difference ?

It is set to zero or -1 before your program runs ?

Pete Dashwood

2005-04-27, 3:55 am


"William M. Klein" <wmklein@nospam.netcom.com> wrote in message
news:jelae.759498$za2.118900@news.easynews.com...
> I knew the answer for VSE (where Frank is), but I just checked about CICS

and
> z/OS
>



> From:
> http://publibz.boulder.ibm.com/cgi-...KS/igy3pg20/6.1
>
> "COBOL class definitions and methods cannot contain EXEC CICS statements,
> cannot be run in a CICS environment, and cannot be compiled using the

CICS
> compiler option."
>
> ... but other than that, how was the play Mrs. Lincoln? <G>
>


:-)
Good point, Bill. I take it from this that OO cannot be used with CICS?

In which case, as they say in Texas, "Your alligator mouth just closed down
mah hummin' bird ass..." :-)

I promise not to post any more on subjects for which I am demonstrably
unqualified.

Cheers,

Pete.


<snip>



Pete Dashwood

2005-04-27, 3:55 am


"Arnold Trembley" <arnold.trembley@worldnet.att.net> wrote in message
news:22%9e.623343$w62.158596@bgtnsc05-news.ops.worldnet.att.net...
>
>
> Pete Dashwood wrote:
for[color=darkred]
to[color=darkred]
course, we[color=darkred]
longer[color=darkred]
does[color=darkred]
>
> Mr. Dashwood, I beg to differ.
>
> If you are doing a READQ TS with the INTO option the LENGTH field must
> be initialized with the maximum length. Think about it. The temp
> storage queue record might be as big as 32K bytes. If the queue
> record is too big large for the INTO field, how is CICS to know when
> to raise the LENGERR condition or EIBRESP value? How else is the
> program supposed to know when the data is truncated?


Well Arnold, I think this is a case of premature ejaculation on your part.
:-) Why not read the WHOLE response before grabbing a keyboard?

I mentioned that I wasn't sure how INTO might work and I covered both cases
(it requires a length or it doesn't) in my post.

The request was for 'any thoughts'... I posted mine.
>
when[color=darkred]
TS-POINTER,[color=darkred]
it[color=darkred]
>
> This is true, of course. But if you use the SET option you cannot
> READQ directly into WORKING-STORAGE. You must define a pointer for a
> LINKAGE SECTION item, GETMAIN it, and establish addressability to it.
> You must do the GETMAIN every time the program is re-entered. And
> you still have the possibility of reading a temp storage queue record
> larger than your space allocation.
>


I realise that and suggested using a buffer big ennough to accommodate it.
So what exactly is your issue?
that[color=darkred]
that,[color=darkred]
>
> This is true.
>
4096[color=darkred]
actually[color=darkred]
have[color=darkred]
TS-TRAN-BKPG-CNT[color=darkred]
MOVE[color=darkred]
>
> That's certainly one solution that would work.
>

Ah, we agree that these were NOT bad 'thoughts' then... :-)

However, I didn't do a precise calculation on the record length and I see
from your post below (I always read everything before ejaculating :-)) that
you reckon the size to be 6485, so my quick estimate of 4096 is certainly
insufficient... I hereby extend my buffer to 8192 and declare the problem
solved... :-)
[color=darkred]
wrong,[color=darkred]
the[color=darkred]
>
> READQ TS always sets the LENGTH field equal to the length actually
> retrieved, whether you use SET or INTO. But if you use the INTO
> option, you must initialize the LENGTH field with the maximum length
> of the working-storage field, and you must do it before executing the
> READQ command. If you are using INTO, and the TS Queue record is
> longer than the maximum length, you get a LENGERR condition.
>
> That's just the way it works.


OK. Fair enough. I believe 8192 is longer than the max length of the record
whose definition was posted. So that should work without problem. (Man! I'm
so glad I don't do this stuff for a living any more... :-))
>
>
> I agree that hard-coding the maximum length is a less desirable
> solution, because it makes future changes a little more difficult. I
> do see it done that way quite often, even for fixed-length TS queue
> records when it would be quite easy to use LENGTH OF.
>
> It ought to be possible to compute the the maximum length in a way
> that simplifies future maintenance, but I can't figure out an easy way
> to do it without defining a constant for the maximum number of
> occurrences.


It is described above.

>
> Truthfully, the programmers in my shop avoid ODO like the plague, and
> given that CICS stands for "Core Is Cheap, Sucker", it's easier to use
> a fixed-length queue record.
>


On this, you will hear no dissent from me. I am also on record as stating my
position that ODO is anathema. The overheads it incurs are simply not worth
the storage savings in these days of cheap storage. It is a remnant (like
many things in COBOL) of a bygone era when priorities were different from
the realities we face today.

> An interesting problem is how to get rid of those TS Queue MAIN
> records when transactions are aborted. We had to use a CICS TASK Exit
> to purge them. Typically the queue name is the Transaction ID plus
> the Terminal ID. The exit program would build the key and delete any
> outstanding TS queues. Of course, Frank's shop may put all TS Queues
> to the VSAM AUX Temp Storage File rather than to MAIN storage, so
> memory leaks might not be a problem for him. At least in the old
> days, TS queues in MAIN storage were considerably faster than in AUX.
>

Ah, for the Oldene Dayse when a programmer was worth 10 such as we see
now... :-)
>
> I calculate the maximum length of the 05 area as 6485 bytes, but
> please check my work for errors! (I apologize for snipping that
> portion of the original post). That's small enough that it could be
> passed in a COMMAREA, without using a TS Queue. Of course, I don't
> know if Frank Swarbrick's program already has other data being passed
> that would put the COMMAREA over the 32K limit.
>


Do you not think, Arnold, that if the COMMAREA was viable, Frank, (who is
demonstrably no slouch when it comes to programming) would be using it...?
:-) It seems to me fair to assume from what was posted, that a TS queue is
to be utilised...

> Another advantage to using COMMAREA is that it doesn't leave TS Queues
> in memory if the transaction abends. There's less chance of storage
> creep that way.


Undoubtedly. However, there are other considerations for using the COMMAREA
that are way beyond the scope of this particular post. And smart system
design should have a task doing garbage collecting if storage is a
consideration. I definitely like the idea of the terminal ID being part of
the storage queue ID, and your description of using TASK EXIT to clear the
garbage would certainly get my vote.
>
> An interesting problem!


I thought it was pretty mundane, actually, but all problems are
'interesting' until you have a solution... :-)

Pete.



docdwarf@panix.com

2005-04-27, 3:55 am

In article <OYlae.629784$w62.576229@bgtnsc05-news.ops.worldnet.att.net>,
Arnold Trembley <arnold.trembley@worldnet.att.net> wrote:

[snip]

>But I don't miss macro-level CICS. Perhaps
>DocDwarf has more recent experience with it.


I do my best to keep emoticons out of my writings... but at the moment I
long for one which expresses the way a bad actor in a Grade-C movie lies
on a bed, eyes tightly closed, head whipping back-and-forth, saying 'No...
no... NO!' in order to indicate a bad dream.

DD

Frank Swarbrick

2005-04-27, 3:55 am

Hi Arnold. Thanks for responding to Pete. I started to reply, but you
stated things much more clearly than I!

As for using the COMMAREA, it's not possible in this case. What our program
really does is reads through a customer's transactions for a certain period
(up to an entire month), builds a "page" of transactions (44 transactions
per page) and writes each page to the TS queue. So there's not just one
ITEM in the TS queue. For one particular customer if I look at their March
transactions it takes 734 pages. That's over 32000 transactions! Yikes.
If only for this customer alone this is the reason I like the variable
length table. Because, while each transaction has a tran description and
there are four transactions per tran-detail-line (don't expect to understand
this without knowing more about what we're doing here), not every
transaction has a bkpg description. So, for this one customer, assuming
none of their 32000 transactions has a bkpg description, I'm saving
1,970,056 bytes of TS queue storage (734 * 3801 = 2,789,934) vs (734 * 6485
= 4,759,990).

Currently I am actually doing this without using ODO. Instead I have a
simply OCCURS 44 times for the TS-TRAN-BKPG-DESC table and I calculate for
the WRITEQ as
COMPUTE TS-LEN-TRAN = LENGTH OF TS-TRAN-TABLES + (TS-HOLD-TRAN-BKPG-SUB *
LENGTH OF TS-TRAN-BKPG-DESC)
and I calculate the length for the READQ simply as
MOVE LENGTH OF TS-PAGE-OF-TRANSACTIONS.

This works fine, but I am now doing some changes to add *another* table to
the end of it, again one where not every transaction in the fixed length
part has a corresponding one in the new table. So I am trying to have to
ODO's. It seems to work (so far, but I've only tested one situation so
far), but I still have to hard code the 44 when using the following
calculation (on the READQ):
MOVE 44 TO TS-TRAN-BKPG-CNT
TS-TRAN-OTHER-CNT
MOVE LENGTH OF TS-PAGE-OF-TRANSACTIONS TO TS-LEN-TRAN.

(Yes, I actually use a "variable" name set to a value of 44, but anyway...)

Hope this explains why I'm going through all this trouble. Well, plus is a
fun intellectual exercise!

Oh, and BTW, we *do* delete the TS queue record after the user has exited
the function. If we didn't we'd run out of room rather quickly! (I believe
we do use MAIN storage instead of AUX, unless we run out of MAIN. But I
could be wrong...)

Frank


---
Frank Swarbrick
Senior Developer/Analyst - Mainframe Applications
FirstBank Data Corporation - Lakewood, CO USA



Pete Dashwood wrote:[color=darkred]
> "Frank Swarbrick" <Frank.Swarbrick@efirstbank.com> wrote in message
> news:3cqhijF6oi4baU1@individual.net...
> (snip)
>
> it
>
>
>
> It is 25 years since I wrote a CICS COBOL Program and in my day we had to
> use GETMAIN to allocate the storage before writing the Queue. (Of course,

we
> were REAL programmers... :-)) I see from your code that this is no longer
> required. :-)
>
> I think there is a fundamental misunderstanding here, Frank. The length

does
> NOT need to be set when you READ.


Mr. Dashwood, I beg to differ.

If you are doing a READQ TS with the INTO option the LENGTH field must
be initialized with the maximum length. Think about it. The temp
storage queue record might be as big as 32K bytes. If the queue
record is too big large for the INTO field, how is CICS to know when
to raise the LENGERR condition or EIBRESP value? How else is the
program supposed to know when the data is truncated?

>
> CICS will set the length into the parameter you specify. (Well, it did

when
> I used it, but we didn't have INTO - 'into' implies you already have the
> storage allocated and should therefore know its length...)
>
> I would have coded:
>
> EXEC CICS
> READQ TS
> QUEUE (TS-QUEUE)
> SET (TS-POINTER)
> ITEM (WS-ITEM)
> LENGTH (TS-LEN-TRAN)
> END-EXEC.
>
> CICS would have grabbed storage for the area corresponding to TS-POINTER,
> read the item on the queue indicated by ITEM, and placed the length of it
> into LENGTH.


This is true, of course. But if you use the SET option you cannot
READQ directly into WORKING-STORAGE. You must define a pointer for a
LINKAGE SECTION item, GETMAIN it, and establish addressability to it.
You must do the GETMAIN every time the program is re-entered. And
you still have the possibility of reading a temp storage queue record
larger than your space allocation.

>
> It is then a trivial exercise to calculate the number of occurrences that
> are required in your TS-TRAN-BKPG-CNT as:
>
> (TS-LEN-TRAN - fixed part of record) / length of TS-TRAN-BKPG-DESC
>
> ...which is pretty close to what you suggested.
>
> The only fly I can see in this ointment is that INTO doesn't work like

that,
> and actually requires the length to be in it before the read.


This is true.

>
> If that is the case, then why not simply define a buffer area of say,

4096
> bytes and read into that? Then you can work out how much data you

actually
> received (I can't believe it doesn't put it into TS-LENGTH, but I don't

have
> access to the latest CICS stuff), calculate the value for

TS-TRAN-BKPG-CNT
> as shown, and, once you have set the number of occurrences correctly,

MOVE
> the record from the data buffer to your record definition.


That's certainly one solution that would work.

>
> SUMMARISING:
>
> 1. I believe that a CICS READQ will SET the length it gets. (If I am

wrong,
> and INTO doesn't work like that, then use a fixed length buffer and do

the
> job that CICS SHOULD have done...calculate the length you actually
> received).


READQ TS always sets the LENGTH field equal to the length actually
retrieved, whether you use SET or INTO. But if you use the INTO
option, you must initialize the LENGTH field with the maximum length