Code Comments
Programming Forum and web based access to our favorite programming groups.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
Post Follow-up to this message"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.
Post Follow-up to this messagePete 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 do es > 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 whe n > 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 tha t, > 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 ha ve > 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/
Post Follow-up to this messageFrank (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 CI CS TS V3.1 - for z/OS) at: [url]http://publibz.boulder.ibm.com/cgi-bin/bookmgr_OS390/BOOKS/dfhp3b00/2.1.5.1.19[/ur l] -- 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 qu eue > 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 retriev ed, > 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 give n > 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 wh en > 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 cour se, > Frank's shop may put all TS Queues to the VSAM AUX Temp Storage File rathe r > 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 ch eck > my work for errors! (I apologize for snipping that portion of the origina l > 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 3 2K > 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 th at > way. > > An interesting problem! > > -- > http://arnold.trembley.home.att.net/ >
Post Follow-up to this message"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 to course, we longer does > > 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 TS-POINTER, it > > 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 that, > > This is true. > 4096 actually have TS-TRAN-BKPG-CNT MOVE > > 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... :-) wrong, the > > 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.
Post Follow-up to this message"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.
Post Follow-up to this messageHi 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: > "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/
Post Follow-up to this messageWe 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... > > > Pete Dashwood wrote: for to we longer does > > 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 TS-POINTER, it > > 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 that, > > This is true. > 4096 actually have TS-TRAN-BKPG-CNT MOVE > > That's certainly one solution that would work. > wrong, the > > 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/ >
Post Follow-up to this message> 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 ?
Post Follow-up to this message"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>
Post Follow-up to this messagePowered by vBulletin
Copyright 2000-2006 Jelsoft Enterprises Limited.