Search code examples
mainframepl-i

ONCODE=451 The STORAGE condition was raised


I recently issued an update to a HOST Reporting program. Our shop uses Enterprise PLI.

I added 2 new structures Declared as BASED. So i basically use an ALLOC statement to allocate the required storage for the structures and then pass the pointers to a Fetchable to get some details i need.

It failed with a storage error during a pilot run in production (LEMSG below). It was trying to process more than a million records there and it appears the job basically ran out of storage.

IBM0451S  ONCODE=451  The STORAGE condition was raised.                         
From entry point MXXX at compile unit offset +000001EA at entry offset 

More Details: IBM0451S

As a fix , i am issuing an update to explicitly add a FREE for the storage after the Fetchable call and i also updated the REGION PARM of my JCL to 0M.

Thought i'd check if you have seen this kind of errors before and have any additional thoughts. Thanks.

Here is how my latest updated code looks like

DECLARES
  =======================================
  DCL                                     
   01 IN_DATA  BASED(IN_PTR),       
     % INCLUDE SYSLIB(XXXXXPAA);          
  DCL                                     
   01 OUT_DATA BASED(OUT_PTR),      
     % INCLUDE SYSLIB(YYYYYPAA);          

  DCL                                     
   01 IN_PTR        PTR;                  
  DCL                                     
   01 OUT_PTR       PTR;  

 ======================================

 The below block of code runs for every record that get processed. The    
 FREE statement is what i now added. I was thinking that because i did 
 not have a FREE before , the ALLOC was basically getting new STOARGE
 everytime it executed that block of code and ran out of storage.



 ALLOC IN_DATA;                              
 ALLOC OUT_DATA;                             

 IN_DATA  = '';                              
 OUT_DATA = '';                              

 IN_DATA.CODE =  'XXX';

 CALL FABCD(IN_PTR,                                 
            OUT_PTR);                               

 IF OUT_DATA.RTRN_CD <= 04 THEN               
   DETAIL_REC.XYZ = OUT_DATA.YYY_CODE;   
 ELSE                                               
  ;                                                 


 FREE IN_DATA;    -------->> What i added now                         
 FREE OUT_DATA;   -------->> What i added now                             

=============================================   

Solution

  • Apart from the storage problem point of view, allocating and freeing storage for each and every record processes is ahuge perforance killer.

    From the snipped you show, it is not clear to be a) why you ALLOC in the first place, and b) why you think you need a fresh piece of storage for each record.

    Just allocte the structures locally, the pass a pointer to them to the function.

    DCL 01 IN_DATA,       
        % INCLUDE SYSLIB(XXXXXPAA);
    DCL 01 OUT_DATA,      
        % INCLUDE SYSLIB(YYYYYPAA);          
    
    DCL IN_PTR        PTR INIT ( ADDR( IN_DATA) );                  
    DCL OUT_PTR       PTR INIT ( ADDR( OUT_DATA ) );
    

    This will have PL/I allocate the structures only once, but still allow pointers to the storage be passe to the function routine.

    I would also remove the second performance killer: The probably unneeded initialization of the structures

    IN_DATA  = ‘‘;
    OUT_DATA = ‘‘;
    

    This does a field by field initialization. Don‘t do this unless you have good reason.