Class SmfRecordReader

java.lang.Object
com.blackhillsoftware.smf.SmfRecordReader
All Implemented Interfaces:
Closeable, AutoCloseable, Iterable<SmfRecord>

public class SmfRecordReader extends Object implements Iterable<SmfRecord>, Closeable
SmfRecordReader reads SMF records from a z/OS DD, a file, an InputStream or a sequence of byte arrays. Create a SmfRecordReader using: or using the Builder pattern:

SmfRecordReader implements Closeable and should normally be used in a try with resources block so that it will be closed automatically:

 
 try (SmfRecordReader reader = SmfRecordReader.fromName("//DD:INPUT"))             
 {
     for (SmfRecord record : reader)           
     {
         // process record 
     }
 }
 
 

Selecting record types and subtypes

The include(int) and include(int, int) methods allow you to select the record types and subtypes returned by the SmfRecordReader.

To select only SMF 30 subtype 5 records:

 reader.include(30, 5);
 

The include method returns the SmfRecordReader itself, so calls can be chained to select multiple types and/or subtypes. To select SMF 14 and 15 records:

 reader
     .include(14)
     .include(15);
 

If you don't include a specific record type, all records are selected.

Using Java Streams

SmfRecordReader can also be used with Java Streams. This allows you to chain operations such as filters, grouping, sorting, actions etc.

Java Streams allow you to create complex filters and queries with little code, however they have the disadvantage that it is difficult to refer back to the result of previous steps in the chain. This can be a problem when processing SMF as you often want to refer to information in the parent record or other sections. For this reason the
for (SmfRecord record : reader)
style above is probably preferred.

Java Streams Example:

 
 try (SmfRecordReader reader = 
         SmfRecordReader.fromName("//DD:INPUT")
             .include(100))
 {
     reader.stream()
         .filter(r -> r.system().equals("SYSA"))       // use criteria to filter records 
         .filter(r -> r.smfTime().isAfter(LocalTime.of(9, 00)) 
                    && r.smfTime().isBefore(LocalTime.of(17, 00)))
         .map(r -> new Smf100Record(r))                // map to SMF 100 record type
         .map(r100 -> r100.qwos())                     // get list of Qwos from each record (maybe empty)
         .flatMap(List::stream)                        // combine stream of lists into a single stream
         .forEach(s -> System.out.println(s.dump()));  // do something with each item
         //.count();                                   // or count items in stream - returns a long
         //.collect(Collectors.toList());              // or collect into List<> - returns List<Qwos>
 } 
                                  
 
  • Method Details

    • logstreamBuilder

      public static LogstreamBuilder<?> logstreamBuilder(String name)
      Build a SmfRecordReader to read from a logstream
      Parameters:
      name - the logstream name e.g. IFASMF.MYRECS
      Returns:
      a LogstreamBuilder allowing you to specify start and end times
    • streamBuilder

      public static StreamReaderBuilder<?> streamBuilder(InputStream stream)
      Build a SmfRecordReader to read from an InputStream
      Parameters:
      stream - the input stream
      Returns:
      a StreamReaderBuilder allowing you to specify the stream RECFM
    • ddnameBuilder

      public static SmfRecordReaderBuilder ddnameBuilder(String ddname)
      Build a SmfRecordReader to read from an allocated ddname
      Parameters:
      ddname - the DD name
      Returns:
      a SmfRecordReaderBuilder
    • nameBuilder

      public static SmfRecordReaderBuilder nameBuilder(String name)
      Build a SmfRecordReader to read from a named file or dataset
      Parameters:
      name - the file or dataset name - see fromName(String)
      Returns:
      a SmfRecordReaderBuilder
    • byteArraysBuilder

      public static SmfRecordReaderBuilder byteArraysBuilder(Iterable<byte[]> source)
      Build a SmfRecordReader with a sequence of byte arrays as the source
      Parameters:
      source - an Iterable source of byte arrays
      Returns:
      a SmfRecordReaderBuilder
    • fromLogstream

      public static SmfRecordReader fromLogstream(String logstreamName) throws IOException
      Create a new SmfRecordReader to read from a logstream.

      Set up a a try-with-resources block to automatically close the logstream, or call close() when finished reading.

      Parameters:
      logstreamName - The name of the logstream.
      Returns:
      a new SmfRecordReader to read from the logstream
      Throws:
      IOException - if the JZOS RecordReader throws an exception
    • fromLogstream

      public static SmfRecordReader fromLogstream(String logstreamName, String subsysOptions1) throws IOException
      Create a new SmfRecordReader to read from a logstream specifying LOGR subsystem options.

      Set up a a try-with-resources block to automatically close the logstream, or call close() when finished reading.

      Parameters:
      logstreamName - The name of the logstream.
      subsysOptions1 - LOGR subsystem options-1 (FROM, TO etc) including quotation marks if required.
      Returns:
      a new SmfRecordReader to read from the logstream
      Throws:
      IOException - if the JZOS RecordReader throws an exception
    • fromLogstream

      public static SmfRecordReader fromLogstream(String logstreamName, String subsysOptions1, String subsysOptions2) throws IOException
      Create a new SmfRecordReader to read from a logstream specifying LOGR subsystem options and IFASEXIT options.

      Set up a a try-with-resources block to automatically close the logstream, or call close() when finished reading.

      Parameters:
      logstreamName - The name of the logstream.
      subsysOptions1 - LOGR subsystem options-1 (FROM, TO etc) including quotation marks if required.
      subsysOptions2 - LOGR IFASEXIT subsystem options-2 (SID, SMEP etc) including quotation marks if required.
      Returns:
      a new SmfRecordReader to read from the logstream
      Throws:
      IOException - if the JZOS RecordReader throws an exception
    • fromDD

      public static SmfRecordReader fromDD(String dd) throws IOException
      Create a new SmfRecordReader to read from an allocated DD.

      Set up a a try-with-resources block to automatically close the dataset, or call close() when finished reading.

      Parameters:
      dd - The DDNAME for the SMF dataset. The DD must be already allocated e.g. via JCL.
      Returns:
      a new SmfRecordReader to read from the DD
      Throws:
      IOException - if the JZOS RecordReader throws an exception
    • fromName

      public static SmfRecordReader fromName(String name) throws IOException, FileNotFoundException
      Create a new SmfRecordReader to read from a named file or dataset. Names can take several forms:
      • If the name begins with "//DD:" the SmfRecordReader will open and read from the preallocated DD name.
         "//DD:INPUT"
      • If the name begins with "//LOGR:" or "//LOGSTREAM:" the SmfRecordReader will open and read from the LOGR subsystem using the IFASEXIT subsystem exit. Logstream options can be specified as supported by IFASEXIT and BPXWDYN.
         "//LOGR:IFASMF.LOGSTRM,'DURATION=(1,HOURS)'"
      • If the name begins with with "//" but not "///" the SmfRecordReader will open and read from a MVS dataset using the same syntax as the C fopen() function. Use single quotes to specify the complete dataset name, otherwise the user's prefix is added.
         "//'MVS.DATASET.NAME'"
         "//'MVS.DATASET.NAME(0)'"
      • Otherwise the SmfRecordReader will open a FileInputStream using that name (typically reading from a Windows/Linux/HFS etc. file).

      Set up a a try-with-resources block to automatically close the input source, or call close() when finished reading.

      Parameters:
      name - The name of the resource to open, in the formats documented above.
      Returns:
      a new SmfRecordReader
      Throws:
      IOException - if the JZOS RecordReader or FileInputStream throws an exception
      FileNotFoundException - if the FileInputStream cannot find the file
    • fromStream

      public static SmfRecordReader fromStream(InputStream stream)
      Create a new SmfRecordReader to read from an existing stream.

      The stream must contain complete SMF records, including the RDW

      Set up a a try-with-resources block to automatically close the stream, or call close() when finished reading.

      Usually, the format of the data in the stream (V or U) can be automatically detected. If this doesn't work (typically you will see data errors very quickly) you can fromStream(InputStream, RecordFormat) to specify the record format explicitly.

      Parameters:
      stream - the InputStream to read.
      Returns:
      a new SmfRecordReader to read from the stream
    • fromStream

      public static SmfRecordReader fromStream(InputStream stream, SmfRecordReader.RecordFormat format)
      Create a new SmfRecordReader to read from an existing stream specifying the record format.

      The stream must contain complete SMF records, including the RDW, and the BDW if RecordFormat.U is specified

      Set up a a try-with-resources block to automatically close the stream, or call close() when finished reading.

      Parameters:
      stream - the InputStream to read.
      format - the SmfRecordReader.RecordFormat of the records in the stream - U, V or AutoDetect
      Returns:
      a new SmfRecordReader to read from the stream
    • fromByteArrays

      public static SmfRecordReader fromByteArrays(Iterable<byte[]> source)
      Create a SmfRecordReader with a sequence of byte arrays as the source. Each byte array must be a single complete SMF record, including the RDW with the record length.

      If the data source implements Closeable it can be closed using SmfRecordReader.close(). Set up a a try-with-resources block to automatically close the source or call close() when finished reading if the data source needs to be closed.

      Parameters:
      source - an Iterable source of byte arrays
      Returns:
      a SmfRecordReader to read SmfRecords from the byte array source
    • close

      public void close() throws IOException
      Close the input source.
      Specified by:
      close in interface AutoCloseable
      Specified by:
      close in interface Closeable
      Throws:
      IOException - if an I/O error occurs
    • read

      public SmfRecord read() throws IOException
      Read a SMF record, returning null at end of input.
      Returns:
      a SmfRecord or null
      Throws:
      IOException - if an I/O error occurs
    • include

      public SmfRecordReader include(int smftype)
      Include all records of a particular SMF record type.

      If no include statements are used, all SMF record types are returned from the SmfRecordReader. If any include statements are used, only the types and optionally subtypes listed in include statements are returned.

      If previous include statements listed specific subtypes for this record type, this method will override that and return all subtypes for this record type.

      Parameters:
      smftype - the SMF record type to include
      Returns:
      this SmfRecordReader, allowing multiple include statements to be chained together
    • include

      public SmfRecordReader include(int smftype, int subtype)
      Include records of a particular SMF record type and subtype.

      If no include statements are used, all SMF record types are returned from the SmfRecordReader. If any include statements are used, only the types and optionally subtypes listed in include statements are returned.

      If a previous include statement specified this SMF type without a subtype, this statement has no effect - all subtypes will still be returned.

      Parameters:
      smftype - the SMF record type to include
      subtype - the subtype to include
      Returns:
      this SmfRecordReader, allowing multiple include statements to be chained together
    • iterator

      public Iterator<SmfRecord> iterator()
      Get an Iterator to read SmfRecords from the input source.
      Specified by:
      iterator in interface Iterable<SmfRecord>
      Returns:
      Iterator<SmfRecord>
    • spliterator

      public Spliterator<SmfRecord> spliterator()
      Specified by:
      spliterator in interface Iterable<SmfRecord>
    • stream

      public Stream<SmfRecord> stream()
      Get a Java Stream to read SmfRecords from the input stream or DD.
      Returns:
      Stream<SmfRecord>
      See Also: