001package daikon.tools;
002
003import daikon.FileIO;
004import daikon.PptMap;
005import daikon.PptTopLevel;
006import daikon.ValueTuple;
007import daikon.VarInfo;
008import java.util.ArrayList;
009import java.util.Arrays;
010import java.util.LinkedHashMap;
011import java.util.List;
012import java.util.Map;
013import org.checkerframework.checker.nullness.qual.Nullable;
014import org.checkerframework.checker.nullness.qual.RequiresNonNull;
015
016/**
017 * A class that gives an example of how to use a FileIO.Processor object to read a trace file.
018 * Invoke it like:
019 *
020 * <pre>
021 *   java daikon.tools.ReadTrace file1 file2 ...
022 * </pre>
023 *
024 * A concrete example invocation:
025 *
026 * <pre>
027 *   java -cp $DAIKONDIR/daikon.jar daikon.tools.ReadTrace /scratch/$USER/tests/daikon-tests/StackAr/StackAr.dtrace.gz
028 * </pre>
029 *
030 * You probably won't run this program. Instead, you will copy parts of its source code in the
031 * process of writing your own program that reads a dtrace file.
032 */
033public class ReadTrace {
034
035  /**
036   * The entry point for ReadTrace.
037   *
038   * @param args data trace file names
039   */
040  public static void main(String[] args) {
041    CollectDataProcessor processor = new CollectDataProcessor();
042    PptMap ppts = new PptMap();
043    try {
044      FileIO.read_data_trace_files(Arrays.asList(args), ppts, processor, false);
045    } catch (Exception e) {
046      throw new Error(e);
047    }
048
049    // At this point, the processor has been called on each sample in turn.
050    // Now, we can do whatever we like with the data.
051
052    for (PptTopLevel ppt : processor.samples.keySet()) {
053      for (ValueTuple vt : processor.samples.get(ppt)) {
054        System.out.printf("%nSample for %s :%n", ppt.name());
055        for (VarInfo vi : ppt.var_infos) {
056          System.out.printf("%s = %s%n", vi.name(), vt.getValueOrNull(vi));
057        }
058      }
059    }
060  }
061
062  /**
063   * Populates the {@code samples} map with all the data read from the file. This is only reasonable
064   * for small trace files, since all the data will be retained in memory!
065   */
066  public static class CollectDataProcessor extends FileIO.Processor {
067
068    public Map<PptTopLevel, List<ValueTuple>> samples = new LinkedHashMap<>();
069
070    /** Process the sample, by adding it to the {@code samples} map. */
071    @RequiresNonNull("daikon.FileIO.data_trace_state")
072    @Override
073    public void process_sample(
074        PptMap all_ppts, PptTopLevel ppt, ValueTuple vt, @Nullable Integer nonce) {
075
076      // Add orig and derived variables to the ValueTuple
077      FileIO.compute_orig_variables(ppt, vt.vals, vt.mods, nonce);
078      FileIO.compute_derived_variables(ppt, vt.vals, vt.mods);
079
080      // Intern the sample, to save space, since we are storing them all.
081      vt = new ValueTuple(vt.vals, vt.mods);
082
083      // Add the sample to the map
084      if (!samples.containsKey(ppt)) {
085        samples.put(ppt, new ArrayList<ValueTuple>());
086      }
087      samples.get(ppt).add(vt);
088    }
089  }
090}