Transcript Slide 1
What you can do with RPG? [email protected] Volvo IT Dep 4365, Uno Ekberg 1 2009 Who am I? Started with IT 1969, at Volvo since 1980 Worked with Mainframes, spefically IMS until 1988 With AS400/iSeries/System i since 1989 Software Architect at Volvo IT Problem solver, consultant, the ”fixer” on System i Volvo IT Dep 4365, Uno Ekberg 2 2009 The Volvo Group AB Volvo Business Areas Mack Trucks Renault Trucks Volvo Trucks Nissan Diesel Buses Business Units Volvo 3P Volvo Powertrain Volvo Parts Volvo Logistics Volvo Information Technology Volvo IT Dep 4365, Uno Ekberg 3 2009 Construction Equipment Volvo Penta Volvo Aero Financial Services Our company history 1967 Established as Volvo Data 1972 First large Data Centre building set up in Gothenburg 1991 Volvo Data gets responsibility for data centres in Greensboro and Ghent 1992-93 Offices established in the UK and Belgium 1993 Office established in the US 1996-97 Study on the future of IT at the Volvo Group – result is that IT resources stay at the Volvo Group 1998 Formation of Volvo Information Technology 1999 Volvo Car Corporation acquired by Ford Motor Co. 2001 Renault V.I./Mack Trucks integration 2004-08 Offices established in India, China, Korea, South Africa, Australia, Mexico, Turkey, Thailand, Russia, Japan, Canada and Singapore 2007-08 Volvo IT incorporated Fortos Management Consulting and WirelessCar Volvo IT Dep 4365, Uno Ekberg 4 2009 Volvo IT – Global Presence Offshore centres Sweden Canada United Kingdom France Russia Poland Belgium Korea Turkey China USA Mexico India Japan Thailand Malaysia Singapore Brazil South Africa Volvo IT Dep 4365, Uno Ekberg 5 2009 Australia Volvo IT customers The Volvo Group Volvo Cars Volvo IT Dep 4365, Uno Ekberg 6 2009 Agenda Dynamic use of files How can I work with unknown number of files in a program? API instead of commands Dynamicly invoke other programs Acknowledgement Volvo IT Dep 4365, Uno Ekberg 7 2009 If you need a simple file with mostly just text, like a temporary error log MyPgmCode If %error; tell someone someway about thist error Volvo IT Dep 4365, Uno Ekberg 8 2009 Create file Open Write msg Dynamic use of Work files FWorkfile O A F 61 Disk USROPN If Not %Open (Workfile) ; Crtcmd = 'CRTPF FILE(QTEMP/WORKFILE) RCDLEN(61) '; CallP(E) CmdPgm (Crtcmd : %Len(Crtcmd)); Open Workfile; Endif; Write Workfile Wrkrec_DS; Close Workfile; Good for logging, error notification etc. Volvo IT Dep 4365, Uno Ekberg 9 2009 Huge amount of Audit Jrn events The problem: How can we avoid to read thru the AuditJrn more than once? And we have a variable number of intrested apps on each LPAR We have n number of Receivers, all want just there own part Volvo IT Dep 4365, Uno Ekberg 10 2009 File IO without an F record We use this to filter out records from the System Audit Journal We have an unknown number of ”subscribers” for data, based on the user profile in the journal record. Each subscriber have there own result file. By using these techniques, we only need to run thru the System Audit Journal once for the time period. We use C Library functions _Ropen, _RWrite and _Rclose. H BndDir( 'QC2LE' ) D RIOFB Ds Based( pRIOFB ) D pKey * D pSysParm * D IoRcdRrn 10u 0 D IoNbrBytRw 10i 0 D IoBlkCnt 5i 0 D IoBlkFllBy 1a D IoBitFld 1a D IoRsv Volvo IT Dep 4365, Uno Ekberg 11 2009 20a File IO without an F record Procedure definitions **-- Open file: -----------------------------------------------------D Ropen Pr * ExtProc( '_Ropen' ) D pRFile * Value Options( *String ) D pMode * Value Options( *String ) **-- Close file: ----------------------------------------------------D Rclose Pr 10i 0 ExtProc( '_Rclose' ) D pRFile * Value **-- Write file ---------------------------------------------------D Rwrite Pr * ExtProc( '_Rwrite' ) D pRFile * Value D pBuffer * Value D BufLength 10u 0 Value Volvo IT Dep 4365, Uno Ekberg 12 2009 File IO without an F record Open the files! Read reqf01; Dou %eof; filnptr = %addr(filname1); %str(filnptr:35) = Jrnfilnm; pRFILE = *null; pRFILE = Ropen(Filname1 : 'ar' ) ; If pRfile = *null; Errmsg = 'Error on Open' + Jrnfilnm; Errorrtn(Errmsg); else; i = i + 1; WFilptr(i) = pRfile; // Get Users to include (not shown here) Endif; Read reqf01; Enddo; Volvo IT Dep 4365, Uno Ekberg 13 2009 File IO without an F record Write record // First search for the correct file in a table of User Profiles lookupappl = %lookup(UsrarrAppl(lookupres) : Wappl : 1: SizApplarr); If lookupappl > 0; Found! PRFILE = Wfilptr(lookupappl); Get the file ptr pRIOFB = Rwrite( PRFILE - Write record : %Addr( JrnOutDs ) : %Size( JrnOutDs )); If IoNbrBytRw = 0; Test result Errorrtn(WrtError); Endif; Endif; Volvo IT Dep 4365, Uno Ekberg 14 2009 File IO without an F record Close the files In the end close all the files For i = 1 by 1 to SizApplarr; pRfile = WFilptr(i); Rclose(pRfile); Endfor; Volvo IT Dep 4365, Uno Ekberg 15 2009 API instead of commands Retrieve Journal Entries Retrieve Journal Entries (QjoRetrieveJournalEntries) API Performance can be enhanced if you give a higher value in the Key 6, number of variable length Records. Carsten Flensburg used 1000, but I found in our environment that at least 3000 gave a lot better performance. If you want to get all records, make sure your selection are not fullfilled until all records are returned! If the continuation indicator is 0, it means you are done! So change search criteria before next call to the API! By using the API performance can be improved a lot. Volvo IT Dep 4365, Uno Ekberg 16 2009 QjoRetrieveJournalEntries D RcvVar D RtvJrnE Ds Pr Align Based(prcvvar) ExtProc( 'QjoRetrieveJournalEntries’) pRcvVar = %alloc(sizeAlloc); //Get enough bytes! DoU JhConInd = '0' Or ErrBytAvl > *Zero; RtvJrnE( JeRcvVar : %Size( RcvVar ) : JrnObject : 'RJNE0200' : JrnEntRtv + JrnVarR01 + JrnVarR02 + JrnVarR06 + JrnVarR07 + JrnVarR08 : ApiError ); // Process the records retrieved in a loop! If JhConInd = '1'; JvR01RcvStr = JhConRcvStr; JvR01LibStr = JhConLibStr; JvR02SeqNbr = JhConSeqNbr; Endif; Enddo; Volvo IT Dep 4365, Uno Ekberg 17 2009 API instead of Commands QUSLOBJ and QWCCVTDT Quslobj – List Object description Can be used to find all objects of a certain type, where the change date are between certain dates. %SUBST(WOBJ:1:10) = Obj; %SUBST(WOBJ:11:10) = Lib; OBJLNM = 'OBJL0400'; Quslobj ( PUsrSpc : 'OBJL0400' : Wobj : Objtype ApiError); If AeBytAvl = *Zero ; // OK do what you intended to do! Volvo IT Dep 4365, Uno Ekberg 18 2009 : API instead of Commands QUSLOBJ and QWCCVTDT Qwccvtdt – Convert Date and Time Quscdt03 is the change date from QUSLOBJ QWCCVTDT ('*DTS ' : Quscdt03 : '*YMD' : Workdate : ApiError); Wdate = %subst(Workdate:1:7) ; If WFrdate <= Wdate and WTodate >= Wdate; We have an object that matches our date criteria! Volvo IT Dep 4365, Uno Ekberg 19 2009 The problem: We need to send data from our ordinary files to a receiver that can’t handle our packed decimal, or binaries or zoned fields. We need to convert to ASCII as well! We can’t just convert the whole string, since the binaries and the packed will give unpredictable (well always wrong!) result 8 char 8 char 3 packed 4 char 5 packed 5 char+1Z more chars.... 4 char 9 char +1Z more chars.... When converting to Unicode, or from DBCS Ebcdic to DBCS Ascii it is even worse! Volvo IT Dep 4365, Uno Ekberg 20 2009 More use of API:s QUSLFLD D LstFldSpc Pr ExtPgm( 'QUSLFLD' ) LstFldSpc( PUsrSpc : 'FLDL0100' : FilNam + PxLibNam : *FIRST' : '0’ : ApiError); For Idx = 1 To UsNumLstEnt; // fill a table with Field information, each elemnt describe one field: Volvo IT Dep 4365, Uno Ekberg 21 2009 More use of API:s QUSLFLD For Idx = 1 To NumLstEnt; If F1DtaTyp = 'P'; WrkPack = 0; %SUBST(WrkpackX: 33 - F1len) = %SUBST(INSTR : F1InpBufPos : F1len); If WrkPack < 0; WrkSign = '-'; WrkPack = %abs(WrkPack); Else; WrkSign = ' '; Endif; Volvo IT Dep 4365, Uno Ekberg 22 2009 More use of API:s QUSLFLD Wrkstr = %Editc(Wrkpack:'X'); // we can now also do iCONV (not shown here!) // ResFldaddr is where we want to move the // result to. It is in the Output record, // on the next byte to be written to. ResFldAddr = %addr(Wrkstr) + (63 - F1Digits); Endif; Endfor; Volvo IT Dep 4365, Uno Ekberg 23 2009 Dynamically invoke other programs and still use prototypes D libpgm s 21a * Prototype for External call D Pgmtocall PR EXTPGM(libpgm) D Jobname_ LIKE(JobName) D JobUser_ LIKE(JobUser ) libpgm = %trimr(pgmlib) + '/' + %trimr(pgmtocall); CALLP(E) Pgmtocall ( Jobname : JobUser); Volvo IT Dep 4365, Uno Ekberg 24 2009 What’s next.... Search for your need on Internet! There are lots of free programs, and most of them come with source! So – when you have a need – search, download and modify! Volvo IT Dep 4365, Uno Ekberg 25 2009 Acknowledgement I have learned a LOT from people like Scott Klement – System iNetwork Carsten Flensburg – System iNetwork Bob Cozzi – RPG World Susan Gantner and Jon Paris – Partner400 and more.... Volvo IT Dep 4365, Uno Ekberg 26 2009 Be /FREE! Volvo IT Dep 4365, Uno Ekberg 27 2009