Article Number 000074263

Posted by Mike Fechner on 29-Sep-2016 01:50

knowledgebase.progress.com/.../sample-code-for-analyzing-pasoe-agent-log-for-possible-memory-leaks

"Version: 11.5, 11.6"

But the sample code uses // style comments (introduced in 11.6).... OK. But the real bummer is:

Call me a rookie, but an explicit transaction block on a NO-UNDO temp-table? I personally would rather use one method or another to scope the buffer TTObject to the internal procedures instead. 

All Replies

Posted by Roberta Miller on 29-Sep-2016 13:49

Hi Mike,

Just letting you know we saw your post and will engage the author of the article. Thanks for starting the discussion.

Regards,

Roberta

Posted by George Potemkin on 29-Sep-2016 15:10

> but an explicit transaction block on a NO-UNDO temp-table?

What is wrong with that?

Posted by Mike Fechner on 29-Sep-2016 15:28

What are you expecting to UNDO? In which way, would the code behave any different with/without those TRANSACTION blocks?
 
If something fails during the ASSIGN, the CREATE and the assignments so far are not undone.
 
So the DO TRANSCATION is just misleading any developer reading the code.
 

Posted by George Potemkin on 29-Sep-2016 15:38

> What are you expecting to UNDO?

I would expect that a transaction block commits the changes.

> In which way, would the code behave any different with/without those TRANSACTION blocks?

For example:

DEFINE TEMP-TABLE tt
  FIELD f1 AS INTEGER INITIAL 0
  FIELD f2 AS INTEGER INITIAL 0
  INDEX f1 f1
  INDEX f2 f2.

/*DO TRANSACTION:*/
  CREATE tt.
  ASSIGN tt.f1 = 1.
/*END.*/

MESSAGE CAN-FIND(FIRST tt WHERE tt.f2 EQ 0)
VIEW-AS ALERT-BOX INFO BUTTONS OK.

Posted by Mike Fechner on 29-Sep-2016 15:44

Well, not with a NO-UNDO temp-table...  Which is the substantial difference between your sample and the code in the K-Base article.
 
That’s the whole point. Mixing NO-UNDO temp-table and an explicit TRANSACTION blocks is very confusing – and makes no difference.
 
Which is why it should be changed.

Posted by George Potemkin on 29-Sep-2016 15:54

Sorry, I just forgot to specify NO-UNDO (I'm watching football in parallel ;-). But the result is the same.

We could explicitly add: ASSIGN tt.f2 = 0. but the index key will not be created until the end of transaction block. It might confuse a reader of the code.

Posted by Brian K. Maher on 30-Sep-2016 04:26

Mike,

This is my article.  Thanks for the feedback.  I'll remove 11.5 from the version info as I don't want to go back and change the comments.  As for the NO-UNDO & DO TRANSACTION block, I know it isn't really needed but I prefer to write it that way as a safety net so that when (not if) people change the code they don't accidentally introduce a scoping issue.  I've seen that happen too many times over the years.  If the bit of extra code really bothers people I will consider removing it but for now I will leave it as it is.

Brian

Posted by Tim Kuehn on 30-Sep-2016 20:55

I put locks on TTs and transactions around them to indicate my intent, and to have a consistent coding appearance across the code base.  If a developer gets confused by that, one has to wonder what else they're getting wrong.

Posted by Mike Fechner on 01-Oct-2016 04:46

The problem is, that a developer reading only that internal procedure may assume that when the ASSIGN failes, the CREATE is undone. But it won't. Code should be easy to understand.

Posted by George Potemkin on 01-Oct-2016 06:30

> a developer reading only that internal procedure may assume that when the ASSIGN failes, the CREATE is undone.

...while a developer SHOULD always assume that the CREATE is completed /only/ outside transaction block. It's especially important for UNDO temp-tables because in this case it's a programmer (not Progress) who is responsible for handling the errors (for example, the errors for the unique index keys). I saw many cases when programs had the problems just due to the lack of explicite transaction property of the blocks where temp-tables are created.

And for the same reasons mentioned by Tim Kuehn I specify the explicite locks (no-lock or exclusive-lock) for temp-tables. Though I understand it might confuse a reader.

Posted by Mike Fechner on 01-Oct-2016 06:36

But the explicit lock options on temp-table buffers are not dangerous.
 
But assuming that in case of an error the CREATE is undone on an error thrown by the ASSIGN statement will bite you on the second CREATE and error thrown by the ASSIGN statement because that will end up with a unique index conflict.
 
The explicit DO TRANSACTION shouts: Watch: This entire block will be undone in case of error. But as a matter of fact, that is nothing to get undone.

Posted by George Potemkin on 01-Oct-2016 07:24

> The explicit DO TRANSACTION shouts

I would re-word it as: programmer shouts: I guarantee there will be no errors inside the block.

PROCEDURE HandleCreated:
    DO TRANSACTION:
        CREATE TTObject.
        ASSIGN TTObject.CreateLine    = ILineNumber
               TTObject.LogDateTime   = SUBSTRING(CData, 2, 26)
               TTObject.ProcessID     = TRIM(ENTRY(2, CData, ' '))
               TTObject.ThreadID      = TRIM(ENTRY(3, CData, ' '))
               TTObject.ObjectType    = TRIM(SUBSTRING(CData, 89, (INDEX(CData, 'Handle:') - 89)))
               TTObject.Created       = TRUE
               TTObject.ObjectHandle  = INTEGER(ENTRY(1, SUBSTRING(CData, (INDEX(CData, 'Handle:') + 7), 20), ' '))
               TTObject.ObjectDetails = CData.
   END.
END PROCEDURE.

I don't need to check the logic of the program - will the ASSIGN validate the uniqueness of the temp-table indexes or not. The explicit transaction block means the author of program thought about such things.

Posted by Mike Fechner on 01-Oct-2016 07:48

Take this program:
 
DEFINE TEMP-TABLE ttTest NO-UNDO
    FIELD MyField AS CHARACTER
    INDEX MyField IS UNIQUE MyField .
 
DEFINE VARIABLE i AS INTEGER     NO-UNDO.
 
DO i = 1 TO 2:
 
    RUN test.
 
END.
 
MESSAGE "after" VIEW-AS ALERT-BOX .
 
FOR EACH ttTest:
    DISPL ttTest.
END.
 
PROCEDURE test:
 
    MESSAGE i VIEW-AS ALERT-BOX .
 
    DO TRANSACTION:
        CREATE ttTest .
        ASSIGN ttTest.MyField = "42" .
    END.
END.
 
The second iteration will violate uniqueness.
 
So within the second invocation of the test procedure you get:
 
** ttTest already exists with  "42". (132)
 
Then the message “after”.
 
And three times
 
** ttTest already exists with  "42". (132)
 
as we reach the FOR EACH – which is where the buffer scope ends.
 
Remove the DO TRANSACTION Block and the flow is 100% the same. The CREATE is never undone (because the TT is NO-UNDO). But I bet most programmers – at first sight – would expect the CREATE to get undone.
 
You can resolve this for instance by adding this inside the DO TRANSCATION block:
 
        CATCH err AS Progress.Lang.Error:
            IF AVAILABLE ttTest THEN
                DELETE ttTest .
        END CATCH .
 
 

Posted by George Potemkin on 01-Oct-2016 08:36

> Remove the DO TRANSACTION Block and the flow is 100% the same.

But TRANSACTION keyword was there only as a comment.

> You can resolve this for instance by adding this inside the DO TRANSCATION block

IMHO, the "comment" simply says where the error checks should be added if they are needed.

As with any "holy wars": people can read the different meaning looking at the same words.

Posted by Mike Fechner on 01-Oct-2016 09:41

An interesting point of view ... IMHO a dangerous assumption.

Outlook for Android herunterladen

Posted by Mike Fechner on 01-Oct-2016 09:41

And as a matter of fact, the code in the quoted k-base article didn't follow your suggestion ... As there was no error handling at all. And that was what this thread is all about

Outlook for Android herunterladen

Posted by Tim Kuehn on 01-Oct-2016 10:14

[quote user="Mike Fechner"] The problem is, that a developer reading only that internal procedure may assume that when the ASSIGN failes, the CREATE is undone. But it won't. Code should be easy to understand. [/quote]

Are we projecting something here? I personally don't assume anything about follow-on developers so I try to communicate intent as often as possible. My personal opinion on TRANSACTION blocks is that it says "this all gets grouped together".

If a failure happens with CREATE - or any other place - the result will be a business logic issue that needs to be fixed regardless of whether the entire TX was backed out or only parts of it.

And I have seen cases in a TX block where the code ran into an runtime issue where part of the work was left undone w/out triggering the UNDO behavior, so a DO TRANSACTION isn't a 100% all-or-nothing guarantee.

Posted by Brian K. Maher on 03-Oct-2016 04:42

Mike,
 
No error handling is needed because there will never be a uniqueness constraint violation.
 
Brian

This thread is closed