MainframeSupports
tip uge 41/2012:

MVS stiller et system til rådighed kaldet SMF. SMF er i bund og grund magen til MVS loggen, men bare langt mindre tilgængelig. Næsten alle de produkter, der kører under MVS skriver SMF-records. Disse records kan indeholde alle mulige oplysninger typisk om produktets performance, men det kan også være om adgang til produktet. Records med samme layout tildeler man en SMF-record type. De mest anvendte SMF-record typer og deres layout kan du finde på firmaet Pacsys hjemmeside.

En af grundene til SMF-records utilgængelighed er, at de bliver skrevet som spanned records. De kan altså være op til 32756 bytes lange. Dette format er intet problem for produkter som DFSORT og især SAS. Det er mest systemprogrammører, der arbejder med indholdet af SMF-records, og mange af dem bruger SAS med det ene formål at kunne læse SMF-records. Problemet med DFSORT er, at dette produkt kun kan arbejde med informationer i faste positioner, og mange typer SMF-records er bygget op på en måde, så den samme information findes i forskellige positioner inden for samme type. Heldigvis kan både COBOL og PLI læse spanned records, og derudover håndtere, at samme information skifter plads fra record til record.

Den første del af alle SMF-records uanset type indeholder de samme informationer. Her står blandt andet record typen, datoen, tiden, MVS-systemet og subsystemet. Kig på Pacsys linket for den præcise position og indhold. I resten af SMF-recorden er formatet frit. For at give dig et godt udgangspunkt for at læse SMF-records har jeg skruet et PLI-program sammen, som kan læse SMF type 101 records. Denne type records skrives af DB2 i tæt på uendelige mængder. Type 101 records er netop kendetegnet ved, at mange af felterne flytter position fra record til record. For at kunne finde rundt skal du bruge diverse offsets, og programmet viser brugen af et par af disse offsets:

smf101: PROC(parm) OPTIONS(MAIN) ORDER;

DCL parm            CHAR(100) VAR;
DCL sysprint        FILE PRINT;
DCL accFile         FILE RECORD SEQUENTIAL;
DCL accFile_data    CHAR(114);
DCL smfFile         FILE RECORD SEQUENTIAL;
DCL smfFile_data    CHAR(32767) VAR;
DCL smfFile_eof     CHAR(1);
DCL maxRecords      FIXED BIN(31);
DCL smfDateChar     CHAR(4);
DCL smfTime         FIXED BIN(31);
DCL smfTimeChar     CHAR(4) BASED(addr(smfTime));
DCL timeFrst        FIXED BIN(31);
DCL timeLast        FIXED BIN(31);
DCL ifcid           FIXED BIN(15);
DCL ifcidPic        PIC'999';
DCL ifcidChar       CHAR(2) BASED(addr(ifcid));
DCL ssid            CHAR(4);
DCL corrname        CHAR(12);
DCL planname        CHAR(8);
DCL recordNo        FIXED BIN(31);
DCL productOfsChar  CHAR(2);
DCL productOfs      FIXED BIN(15) BASED(addr(productOfsChar));
DCL corrdataOfsChar CHAR(2);
DCL corrdataOfs     FIXED BIN(15) BASED(addr(corrdataOfsChar));
DCL putCount        FIXED BIN(31);

ON ENDFILE(smfFile) smfFile_eof = 'Y';

maxRecords = 100;
timeFrst = 10 * 360000;
timeLast = 14 * 360000;
recordNo = 0;
putCount = 0;
smfFile_eof = 'N';
OPEN FILE(smfFile);
READ FILE(smfFile) INTO(smfFile_data);
DO WHILE(smfFile_eof = 'N' & recordNo < maxRecords);
  recordNo = recordNo + 1;
  smfTimeChar = substr(smfFile_data, 3, 4);
  IF smfTime >= timeFrst & smfTime < timeLast
   & substr(smfFile_data, 2, 1) = '65'X
  THEN DO;
    smfDateChar = substr(smfFile_data, 7, 4);
    productOfsChar = substr(smfFile_data, 27, 2);
    productOfs = productOfs - 3;
    ifcidChar = substr(smfFile_data, productOfs + 4, 2);
    ssid = substr(smfFile_data, productOfs + 12, 4);
    corrdataOfsChar = substr(smfFile_data, productOfs, 2);
    corrdataOfs = productOfs + corrdataOfs;
    corrname = substr(smfFile_data, corrdataOfs + 12, 12);
    planname = substr(smfFile_data, corrdataOfs + 32, 8);
    ifcidPic = ifcid;
    CALL writeRec;
  END;
  READ FILE(smfFile) INTO(smfFile_data);
END;
CLOSE FILE(smfFile);
PUT SKIP LIST('Records read . : ' !! recordNo);
PUT SKIP LIST('Records written: ' !! putCount);

writeRec: PROC;

  IF putcount = 0
  THEN DO;
    accFile_data = 'IFC DATE SSID PLAN CORRELATION';
    WRITE FILE(accFile) FROM(accFile_data);
  END;
  accFile_data = ifcidPic !! ' ' !! smfDateChar !! ' ' !! ssid !! ' '
               !! planname !! ' ' !! corrname
               ;
  WRITE FILE(accFile) FROM(accFile_data);
  putcount = putcount + 1;

END writeRec;

END smf101;

I loop'et, der gennemlæser filen med SMF-records (smfFile), er der en IF, som sørger for, at programmet kun behandler records af type 101 ('65'X) og er skrevet mellem kl. 10.00 og kl. 14.00. Inde i denne IF finder jeg offset til en såkaldt product section, hvor blandt andet den interne DB2-record type står (ifcid). I product section står et andet offset, som peger hen på en correlation section, hvor oplysninger om forbindelsen til DB2, såsom DB2 plan navnet og correlation navnet står.

Filer med SMF records kan være vildt store og gemmes af mange installationer på tape. PLI I/O går ikke specielt hurtigt i forhold til eksempelvis DFSORT, så det kan være en god ide at starte med at filtrere SMF-records med DFSORT, før du sender dem igennem PLI. Eksempelvis kan den IF, der udvælger records til behandling i ovenstående program sagtens kodes i DFSORT, da både SMF-record typen og tiden står i faste positioner. Ja, så er det vist bare at ønske god fornøjelse.

Forrige danske tip        Last tip in english        Tip oversigten