Java tutorial
/* $Id$ */ /* * ProgramProbeManagerImpl.java * * Network Embedded Sensor Testbed (NESTbed) * * Copyright (C) 2006-2007 * Dependable Systems Research Group * School of Computing * Clemson University * Andrew R. Dalton and Jason O. Hallstrom * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the * * Free Software Foundation, Inc. * 51 Franklin Street, Fifth Floor * Boston, MA 02110-1301, USA. */ package edu.clemson.cs.nestbed.server.management.instrumentation; import java.rmi.RemoteException; import java.rmi.server.UnicastRemoteObject; import java.io.File; import java.io.IOException; import java.io.ObjectInputStream; import java.io.FileInputStream; import java.util.ArrayList; import java.util.List; import java.util.Map; import java.util.TreeMap; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import edu.clemson.cs.nestbed.common.management.instrumentation.ProgramProbeManager; import edu.clemson.cs.nestbed.common.management.instrumentation.ProgramWeaverManager; import edu.clemson.cs.nestbed.common.management.configuration.ProgramManager; import edu.clemson.cs.nestbed.common.model.Mote; import edu.clemson.cs.nestbed.common.model.MoteTestbedAssignment; import edu.clemson.cs.nestbed.common.model.Program; import edu.clemson.cs.nestbed.common.trace.StaticProgramData; import edu.clemson.cs.nestbed.common.trace.TraceEntry; import edu.clemson.cs.nestbed.common.trace.TraceMessage; import edu.clemson.cs.nestbed.server.management.configuration.MoteManagerImpl; import edu.clemson.cs.nestbed.server.management.configuration.ProgramManagerImpl; import edu.clemson.cs.nestbed.server.management.instrumentation.ProgramWeaverManagerImpl; import edu.clemson.cs.nesctk.NescToolkit; import edu.clemson.cs.nesctk.SourceFile; import edu.clemson.cs.nesctk.records.FunctionCalleeRecord; import edu.clemson.cs.nesctk.records.FunctionRecord; import edu.clemson.cs.nesctk.records.TraceFunctionRecord; import edu.clemson.cs.nesctk.records.TraceModuleRecord; import edu.clemson.cs.nesctk.records.WiringRecord; import edu.clemson.cs.nesctk.tools.trace.instrumentor.TraceInstrumentor; import edu.clemson.cs.nesctk.tools.trace.FunctionTraceData; import edu.clemson.cs.nesctk.tools.trace.RadioTraceData; import edu.clemson.cs.nesctk.tools.trace.TraceData; import edu.clemson.cs.nesctk.util.AstUtils; import edu.clemson.cs.nesctk.util.FileUtils; import net.tinyos.message.Message; import net.tinyos.message.MessageListener; import net.tinyos.message.MoteIF; import net.tinyos.packet.BuildSource; import net.tinyos.packet.PacketSource; import net.tinyos.packet.PhoenixSource; public class ProgramProbeManagerImpl extends UnicastRemoteObject implements ProgramProbeManager { private final static ProgramProbeManagerImpl instance; private final static Log log = LogFactory.getLog(ProgramProbeManagerImpl.class); private final static String NESTBED_NESC_ROOT; private final static TraceEntry TRACE_ENTRY = new TraceEntry(); private final static TraceMessage TRACE_MESSAGE = new TraceMessage(); static { String property; property = "nestbed.dir.lib.nesc"; String rootStr = System.getProperty(property); File root = null; if (rootStr == null) { log.fatal("Property '" + property + "' is not set"); System.exit(1); } else { root = new File(rootStr); if (!root.exists()) { log.fatal("Directory " + rootStr + " does not exist!"); System.exit(1); } } NESTBED_NESC_ROOT = root.getAbsolutePath(); log.info(property + " = " + NESTBED_NESC_ROOT); ProgramProbeManagerImpl impl = null; try { impl = new ProgramProbeManagerImpl(); } catch (Exception ex) { log.fatal("Unable to create singleton instance", ex); System.exit(1); } finally { instance = impl; } } private ProgramManager programManager = ProgramManagerImpl.getInstance(); private ProgramWeaverManager programWeaverManager = ProgramWeaverManagerImpl.getInstance(); public static ProgramProbeManagerImpl getInstance() { return instance; } private class TraceMessageListener implements MessageListener { private MoteIF moteIf; private List<TraceData> traceData = new ArrayList<TraceData>(); public TraceMessageListener(MoteIF moteIf) { this.moteIf = moteIf; } public synchronized void messageReceived(int toAddr, Message message) { if (message instanceof TraceEntry) { TraceEntry entry = (TraceEntry) message; if (entry.get_type() == 0 || entry.get_type() == 1) { traceData.add(new FunctionTraceData(entry.get_type(), entry.get_u_callTrace_moduleId(), entry.get_u_callTrace_functionId())); } else { traceData.add(new RadioTraceData(entry.get_type(), entry.get_u_radioTrace_address(), entry.get_u_radioTrace_magic())); } } else if (message instanceof TraceMessage) { moteIf.deregisterListener(TRACE_ENTRY, this); moteIf.deregisterListener(TRACE_MESSAGE, this); notifyAll(); } } public List<TraceData> getTraceData() { return traceData; } } public Map<Integer, List<TraceData>> collectData(List<MoteTestbedAssignment> interestingMotes) throws RemoteException { Map<Integer, List<TraceData>> map = new TreeMap<Integer, List<TraceData>>(); for (MoteTestbedAssignment mta : interestingMotes) { try { Mote mote = MoteManagerImpl.getInstance().getMote(mta.getMoteID()); int address = mta.getMoteAddress(); String moteSerialID = mote.getMoteSerialID(); String tosPlatform = "telosb"; // Should really look this up String commPort = "/dev/motes/" + moteSerialID; // Start PacketSource packetSource; PhoenixSource phoenixSource; MoteIF moteIf; TraceMessageListener listener; packetSource = BuildSource.makePacketSource("serial@" + commPort + ":telos"); phoenixSource = BuildSource.makePhoenix(packetSource, null); moteIf = new MoteIF(phoenixSource); listener = new TraceMessageListener(moteIf); moteIf.registerListener(TRACE_ENTRY, listener); moteIf.registerListener(TRACE_MESSAGE, listener); moteIf.send(address, new TraceMessage()); synchronized (listener) { try { listener.wait(); } catch (Exception ex) { } } phoenixSource.shutdown(); packetSource.close(); map.put(address, listener.getTraceData()); } catch (IOException ex) { log.error("Exception while collecting trace data", ex); } } return map; } public Map<String, List<String>> getModuleFunctionListMap(int programID) throws RemoteException { log.debug("getModuleFunctionListMap called"); try { Program program = programManager.getProgram(programID); File makefile = new File(program.getSourcePath(), "Makefile"); String topLevelConfiguration = programWeaverManager.findComponentFromMakefile(makefile); log.info("Top-level config: " + topLevelConfiguration); File topLevelFile = new File(program.getSourcePath(), topLevelConfiguration + ".nc").getAbsoluteFile(); File analysisDir = new File(program.getSourcePath()).getAbsoluteFile(); log.info("Top-Level file: " + topLevelFile.getAbsolutePath()); log.info("Basedir directory: " + analysisDir.getAbsolutePath()); NescToolkit toolkit = new NescToolkit(topLevelFile, analysisDir); toolkit.prependIncludePath(NESTBED_NESC_ROOT + "/ModifiedTinyOS"); toolkit.addIncludePath(NESTBED_NESC_ROOT + "/TraceRecorder"); toolkit.addIncludePath(NESTBED_NESC_ROOT + "/MemoryProfiler"); toolkit.addIncludePath(NESTBED_NESC_ROOT + "/NestbedControl"); toolkit.appendGccArgument("-I"); toolkit.appendGccArgument(NESTBED_NESC_ROOT + "/ModifiedTinyOS"); toolkit.appendGccArgument("-I"); toolkit.appendGccArgument(NESTBED_NESC_ROOT + "/TraceRecorder"); toolkit.appendGccArgument("-I"); toolkit.appendGccArgument(NESTBED_NESC_ROOT + "/MemoryProfiler"); toolkit.appendGccArgument("-I"); toolkit.appendGccArgument(NESTBED_NESC_ROOT + "/NestbedControl"); toolkit.load(); Map<String, SourceFile> sourceFiles = toolkit.getSourceFileMap(); return AstUtils.buildModuleFunctionListMap(sourceFiles); } catch (Exception ex) { throw new RemoteException("Exception:", ex); } } public void insertProbes(int programID, Map<String, List<String>> moduleIncludeMap) throws RemoteException { log.debug("insertProbes called"); try { Program program = programManager.getProgram(programID); File makefile = new File(program.getSourcePath(), "Makefile"); String topLevelConfiguration = programWeaverManager.findComponentFromMakefile(makefile); String topLevelPath = new File(program.getSourcePath(), topLevelConfiguration + ".nc") .getAbsolutePath(); backup(program.getSourcePath()); log.info("Top-level config: " + topLevelConfiguration); List<String> prependList = new ArrayList<String>(1); List<String> appendList = new ArrayList<String>(3); List<String> gccArgs = new ArrayList<String>(2); prependList.add(NESTBED_NESC_ROOT + "/ModifiedTinyOS"); appendList.add(NESTBED_NESC_ROOT + "/TraceRecorder"); appendList.add(NESTBED_NESC_ROOT + "/MemoryProfiler"); appendList.add(NESTBED_NESC_ROOT + "/NestbedControl"); gccArgs.add("-I"); gccArgs.add(NESTBED_NESC_ROOT + "/TraceRecorder"); gccArgs.add("-I"); gccArgs.add(NESTBED_NESC_ROOT + "/ModifiedTinyOS"); gccArgs.add("-I"); gccArgs.add(NESTBED_NESC_ROOT + "/MemoryProfiler"); gccArgs.add("-I"); gccArgs.add(NESTBED_NESC_ROOT + "/NestbedControl"); log.debug("Prepend list: " + prependList); log.debug("Append list: " + appendList); File topLevelFile = new File(topLevelPath).getAbsoluteFile(); File analysisDir = topLevelFile.getParentFile(); log.info("Top-Level file: " + topLevelFile.getAbsolutePath()); log.info("Basedir directory: " + analysisDir.getAbsolutePath()); TraceInstrumentor traceInstrumentor; traceInstrumentor = new TraceInstrumentor(prependList, appendList, gccArgs, topLevelFile.getAbsolutePath(), analysisDir); traceInstrumentor.setModuleIncludeMap(moduleIncludeMap); traceInstrumentor.enableTrace(); traceInstrumentor.handleCommit(); File source = new File(NESTBED_NESC_ROOT + "/TraceRecorder/TraceRecorder.h"); File dest = new File(program.getSourcePath() + "/analysis/TraceRecorder.h"); FileUtils.copyFile(source, dest); log.info("Moving source files from analysis directory down..."); moveFiles(program.getSourcePath()); traceInstrumentor.generateRadioHeader(program.getSourcePath()); } catch (Exception ex) { ex.printStackTrace(); //throw new RemoteException("Exception:", ex); } } public StaticProgramData getStaticData(Program program) throws RemoteException { log.debug("getStaticData called"); StaticProgramData data = null; try { data = readStaticData(new File(program.getSourcePath() + "/staticTraceData.dat")); } catch (Exception ex) { log.error("Exception in getStaticData", ex); throw new RemoteException("Exception in getStaticData", ex); } return data; } @SuppressWarnings("unchecked") private StaticProgramData readStaticData(File file) throws IOException, ClassNotFoundException { StaticProgramData data; ObjectInputStream in = new ObjectInputStream(new FileInputStream(file)); data = new StaticProgramData((List<TraceModuleRecord>) in.readObject(), (List<TraceFunctionRecord>) in.readObject(), (Map<FunctionRecord, List<FunctionCalleeRecord>>) in.readObject(), (List<WiringRecord>) in.readObject()); in.close(); return data; } private void moveFiles(String path) throws IOException { File dest = new File(path).getAbsoluteFile(); File src = new File(dest, "analysis"); log.info("Moving " + src.getAbsolutePath() + " to " + dest.getAbsolutePath()); FileUtils.copyDirectory(src, dest); FileUtils.deleteRecursive(src); } private void backup(String path) throws IOException { File directory = new File(path).getAbsoluteFile(); File backup = new File(directory, "nb_backup"); FileUtils.copyDirectory(directory, backup); } private ProgramProbeManagerImpl() throws RemoteException { super(); } }