Article Number 000074263 - Forum - Knowledge Base - Progress Community

Article Number 000074263

 Forum

Article Number 000074263

  • 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. 

    Architect of the SmartComponent Library and WinKit

    Consultingwerk Ltd.

  • 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

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

    What is wrong with that?

  • 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.
     

    Architect of the SmartComponent Library and WinKit

    Consultingwerk Ltd.

  • > 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.
    
  • 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.

    Architect of the SmartComponent Library and WinKit

    Consultingwerk Ltd.

  • 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.

  • 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

  • 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.

  • 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.

    Architect of the SmartComponent Library and WinKit

    Consultingwerk Ltd.

  • > 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.

  • 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.

    Architect of the SmartComponent Library and WinKit

    Consultingwerk Ltd.

  • > 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.

  • 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 .
     
     

    Architect of the SmartComponent Library and WinKit

    Consultingwerk Ltd.

  • > 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.