// // Copyright (C) 2012 United States Government as represented by the // Administrator of the National Aeronautics and Space Administration // (NASA). All Rights Reserved. // // This software is distributed under the NASA Open Source Agreement // (NOSA), version 1.3. The NOSA has been approved by the Open Source // Initiative. See the file NOSA-1.3-JPF at the top of the distribution // directory tree for the complete NOSA document. // // THE SUBJECT SOFTWARE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY OF ANY // KIND, EITHER EXPRESSED, IMPLIED, OR STATUTORY, INCLUDING, BUT NOT // LIMITED TO, ANY WARRANTY THAT THE SUBJECT SOFTWARE WILL CONFORM TO // SPECIFICATIONS, ANY IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR // A PARTICULAR PURPOSE, OR FREEDOM FROM INFRINGEMENT, ANY WARRANTY THAT // THE SUBJECT SOFTWARE WILL BE ERROR FREE, OR ANY WARRANTY THAT // DOCUMENTATION, IF PROVIDED, WILL CONFORM TO THE SUBJECT SOFTWARE. // package gov.nasa.jpf.vm; import java.io.File; import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.IOException; import gov.nasa.jpf.Config; import gov.nasa.jpf.JPFConfigException; import gov.nasa.jpf.JPFException; /** * a JenkinsStateSet that stores program state information in a readable * and diffable format. * * Storing states as readable text is enabled by setting vm.storage.class to this class * * Note: this automatically sets/overrides the serializer to Debug<serializer-class> */ public class DebugJenkinsStateSet extends JenkinsStateSet { static final String LOGFILE = "state"; File outputDir; File outputFile; public DebugJenkinsStateSet (Config conf){ String serializerCls = conf.getString("vm.serializer.class"); if (serializerCls != null){ int idx = serializerCls.lastIndexOf('.') + 1; String cname = serializerCls.substring(idx); if (!cname.startsWith("Debug")){ if (idx > 0){ serializerCls = serializerCls.substring(0,idx) + "Debug" + cname; } else { serializerCls = "Debug" + cname; } } serializer = conf.getInstance(null, serializerCls, DebugStateSerializer.class); if (serializer == null){ throw new JPFConfigException("Debug StateSet cannot instantiate serializer: " + serializerCls); } } String path = conf.getString("vm.serializer.output", "tmp"); outputDir = new File(path); if (!outputDir.isDirectory()){ if (!outputDir.mkdirs()){ throw new JPFConfigException("Debug StateSet cannot create output dir: " + outputDir.getAbsolutePath()); } } outputFile = new File( outputDir, LOGFILE); } @Override public void attach(VM vm){ // we use our own serializer vm.setSerializer( serializer); // <2do> this is a bit hack'ish - why does the VM keep the serializer anyways, // if it is only used here super.attach(vm); } @Override public int addCurrent () { int maxId = lastStateId; FileOutputStream fos = null; try { fos = new FileOutputStream( outputFile); } catch (FileNotFoundException fnfx){ throw new JPFException("cannot create Debug state set output file: " + outputFile.getAbsolutePath()); } ((DebugStateSerializer)serializer).setOutputStream(fos); int stateId = super.addCurrent(); try { fos.flush(); fos.close(); } catch (IOException iox){ throw new JPFException("cannot write Debug state set output file: " + outputFile.getAbsolutePath()); } // if this is a new state, store it under its id, otherwise throw it away if (stateId > maxId){ String fname = "state." + stateId; outputFile.renameTo( new File(outputDir, fname)); } else { if (outputFile.isFile()){ outputFile.delete(); } } return stateId; } }