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 /** Do not instantiate. */ 036 private ReadTrace() { 037 throw new Error("Do not instantiate"); 038 } 039 040 /** 041 * The entry point for ReadTrace. 042 * 043 * @param args data trace file names, read from the command line 044 */ 045 public static void main(String[] args) { 046 CollectDataProcessor processor = new CollectDataProcessor(); 047 PptMap ppts = new PptMap(); 048 try { 049 // `read_data_trace_files()` requires the list of files to be modifiable. 050 FileIO.read_data_trace_files(new ArrayList<>(Arrays.asList(args)), ppts, processor, false); 051 } catch (Exception e) { 052 throw new Error(e); 053 } 054 055 // At this point, the processor has been called on each sample in turn. 056 // Now, we can do whatever we like with the data. 057 058 for (PptTopLevel ppt : processor.samples.keySet()) { 059 for (ValueTuple vt : processor.samples.get(ppt)) { 060 System.out.printf("%nSample for %s :%n", ppt.name()); 061 for (VarInfo vi : ppt.var_infos) { 062 System.out.printf("%s = %s%n", vi.name(), vt.getValueOrNull(vi)); 063 } 064 } 065 } 066 } 067 068 /** 069 * Populates the {@code samples} map with all the data read from the file. This is only reasonable 070 * for small trace files, since all the data will be retained in memory! 071 */ 072 public static class CollectDataProcessor extends FileIO.Processor { 073 074 public Map<PptTopLevel, List<ValueTuple>> samples = new LinkedHashMap<>(); 075 076 /** Process the sample, by adding it to the {@code samples} map. */ 077 @RequiresNonNull("daikon.FileIO.data_trace_state") 078 @Override 079 public void process_sample( 080 PptMap all_ppts, PptTopLevel ppt, ValueTuple vt, @Nullable Integer nonce) { 081 082 // Add orig and derived variables to the ValueTuple 083 FileIO.compute_orig_variables(ppt, vt.vals, vt.mods, nonce); 084 FileIO.compute_derived_variables(ppt, vt.vals, vt.mods); 085 086 // Intern the sample, to save space, since we are storing them all. 087 vt = new ValueTuple(vt.vals, vt.mods); 088 089 // Add the sample to the map 090 if (!samples.containsKey(ppt)) { 091 samples.put(ppt, new ArrayList<ValueTuple>()); 092 } 093 samples.get(ppt).add(vt); 094 } 095 } 096}