package org.overture.interpreter.messages.rtlog.nextgen; import java.io.BufferedWriter; import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.FileWriter; import java.io.IOException; import java.io.ObjectInputStream; import java.io.ObjectOutputStream; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.TreeMap; import org.overture.interpreter.messages.rtlog.IRTLogger; import org.overture.interpreter.messages.rtlog.RTBusActivateMessage; import org.overture.interpreter.messages.rtlog.RTBusCompletedMessage; import org.overture.interpreter.messages.rtlog.RTBusMessage; import org.overture.interpreter.messages.rtlog.RTBusReplyRequestMessage; import org.overture.interpreter.messages.rtlog.RTBusRequestMessage; import org.overture.interpreter.messages.rtlog.RTDeclareBUSMessage; import org.overture.interpreter.messages.rtlog.RTDeclareCPUMessage; import org.overture.interpreter.messages.rtlog.RTDeployObjectMessage; import org.overture.interpreter.messages.rtlog.RTMessage; import org.overture.interpreter.messages.rtlog.RTOperationMessage; import org.overture.interpreter.messages.rtlog.RTThreadCreateMessage; import org.overture.interpreter.messages.rtlog.RTThreadKillMessage; import org.overture.interpreter.messages.rtlog.RTThreadMessage; import org.overture.interpreter.messages.rtlog.RTThreadSwapMessage; import org.overture.interpreter.messages.rtlog.RTThreadSwapMessage.SwapType; import org.overture.interpreter.messages.rtlog.nextgen.NextGenBusMessageEvent.NextGenBusMessageEventType; import org.overture.interpreter.messages.rtlog.nextgen.NextGenOperationEvent.OperationEventType; import org.overture.interpreter.messages.rtlog.nextgen.NextGenThread.ThreadType; import org.overture.interpreter.messages.rtlog.nextgen.NextGenThreadSwapEvent.ThreadEventSwapType; import org.overture.interpreter.scheduler.CPUResource; import org.overture.interpreter.scheduler.ISchedulableThread; import org.overture.interpreter.scheduler.InitThread; import org.overture.interpreter.scheduler.MainThread; import org.overture.interpreter.scheduler.MessagePacket; import org.overture.interpreter.scheduler.MessageRequest; import org.overture.interpreter.scheduler.MessageResponse; import org.overture.interpreter.values.ObjectValue; import org.overture.interpreter.values.OperationValue; public class NextGenRTLogger implements IRTLogger { private boolean enabled = false; public static NextGenRTLogger getInstanceFromFile(String filename) throws IOException, ClassNotFoundException { final NextGenRTLogger logger = new NextGenRTLogger(); logger.readFromFile(filename); return logger; } private Map<Integer, NextGenCpu> cpuMap = new HashMap<Integer, NextGenCpu>(); private Map<Integer, NextGenBus> busMap = new HashMap<Integer, NextGenBus>(); private Map<Integer, NextGenObject> objectMap = new HashMap<Integer, NextGenObject>(); private Map<Integer, NextGenClassDefinition> classDefMap = new HashMap<Integer, NextGenClassDefinition>(); private Map<String, NextGenOperation> operationMap = new HashMap<String, NextGenOperation>(); private Map<Long, NextGenBusMessage> busMessage = new HashMap<Long, NextGenBusMessage>(); private Map<Long, NextGenThread> threadMap = new HashMap<Long, NextGenThread>(); // private ArrayList<INextGenEvent> events = new ArrayList<INextGenEvent>(); private Map<Long, ArrayList<INextGenEvent>> events = new TreeMap<Long, ArrayList<INextGenEvent>>(); private NextGenBus vBus; private File logFile = null; private long currentAbsoluteTime = -1L; private int currentRelativeTime = -1; public NextGenRTLogger() { this.addBus(0, new ArrayList<Integer>(), "vBus"); vBus = this.busMap.get(0); this.addCpu(0, false, "vCpu", "system"); // Add the implicit virtual CPU - assuming expl means explicit } public Map<Long, ArrayList<INextGenEvent>> getEvents() { return this.events; } public Map<Integer, NextGenCpu> getCpuMap() { return cpuMap; } public Map<Integer, NextGenBus> getBusMap() { return busMap; } public Map<Integer, NextGenObject> getObjectMap() { return objectMap; } public Map<Integer, NextGenClassDefinition> getClassDefMap() { return classDefMap; } public Map<String, NextGenOperation> getOperationMap() { return operationMap; } public Map<Long, NextGenBusMessage> getBusMessage() { return busMessage; } public Map<Long, NextGenThread> getThreadMap() { return threadMap; } public NextGenBus getvBus() { return vBus; } public void log(RTMessage message) { if (!enabled) { return; } // Keep track of relative time among events happening at the same wall clock time if (currentAbsoluteTime != message.getLogTime()) { currentRelativeTime = 0; } else { currentRelativeTime++; } currentAbsoluteTime = message.getLogTime(); NextGenTimeStamp logTime = new NextGenTimeStamp(currentAbsoluteTime, currentRelativeTime); /** * Declarations: CPUs and Busses */ if (message instanceof RTDeclareCPUMessage) { RTDeclareCPUMessage m = (RTDeclareCPUMessage) message; this.addCpu(m.cpuId, m.expl, m.cpuName, m.sysName); } if (message instanceof RTDeclareBUSMessage) { RTDeclareBUSMessage m = (RTDeclareBUSMessage) message; this.addBus(m.busNumber, parseCpuIds(m.cpus), m.name); } /** * Object deployments */ if (message instanceof RTDeployObjectMessage) { RTDeployObjectMessage m = (RTDeployObjectMessage) message; this.deployObject(m.object, m.cpu); } /** * Thread related: create, swap and kill */ if (message instanceof RTThreadCreateMessage) { RTThreadMessage m = (RTThreadCreateMessage) message; this.createThread(m.thread, m.cpuNumber, logTime); } if (message instanceof RTThreadSwapMessage) { RTThreadSwapMessage m = (RTThreadSwapMessage) message; this.addThreadSwap(m.thread, m.cpuNumber, m.getType(), m.overhead, m.delay, logTime); } if (message instanceof RTThreadKillMessage) { RTThreadKillMessage m = (RTThreadKillMessage) message; this.addThreadKill(m.thread, m.cpuNumber, logTime); } /** * Operation related: request, activate and completed */ if (message instanceof RTOperationMessage) { RTOperationMessage m = (RTOperationMessage) message; this.treatOperationMessage(m, logTime); } /** * Bus related: */ if (message instanceof RTBusMessage) { RTBusMessage m = (RTBusMessage) message; this.treatBusMessage(m, logTime); } } // public static void dump() // { // try // { // getInstance().persistToFile(); // } catch (IOException e) // { // //silent ignore // } // } public void persistToFile() throws IOException { if (logFile != null) { FileOutputStream fos = new FileOutputStream(logFile + ".rtbin"); ObjectOutputStream out = new ObjectOutputStream(fos); out.writeObject(cpuMap); out.writeObject(busMap); out.writeObject(objectMap); out.writeObject(classDefMap); out.writeObject(operationMap); out.writeObject(busMessage); out.writeObject(threadMap); out.writeObject(events); out.flush(); out.close(); } } public void printDataStructure(String fileName) throws IOException { FileWriter fstream = new FileWriter(fileName); BufferedWriter out = new BufferedWriter(fstream); out.newLine(); out.append("### CPUs ##########################\n"); out.newLine(); for (Integer cpuKey : this.cpuMap.keySet()) { out.append(cpuKey.toString()); out.append(" -> "); out.append(this.cpuMap.get(cpuKey).toString()); out.newLine(); } out.newLine(); out.append("### Busses ########################\n"); out.newLine(); for (Integer busKey : this.busMap.keySet()) { out.append(busKey.toString()); out.append(" -> "); out.append(this.busMap.get(busKey).toString()); out.newLine(); } out.newLine(); out.append("### Objects #######################\n"); out.newLine(); for (Integer objectKey : this.objectMap.keySet()) { out.append(objectKey.toString()); out.append(" -> "); out.append(this.objectMap.get(objectKey).toString()); out.newLine(); } out.newLine(); out.append("### Operations #####################\n"); out.newLine(); for (String opKey : this.operationMap.keySet()) { out.append(opKey.toString()); out.append(" -> "); out.append(this.operationMap.get(opKey).toString()); out.newLine(); } out.newLine(); out.append("### Bus Msgs ######################\n"); out.newLine(); for (Long busMsgKey : this.busMessage.keySet()) { out.append(busMsgKey.toString()); out.append(" -> "); out.append(this.busMessage.get(busMsgKey).toString()); out.newLine(); } // System.out.println("Printing events"); out.newLine(); out.append("### Events ######################\n"); out.newLine(); for (Map.Entry<Long, ArrayList<INextGenEvent>> entry : events.entrySet()) { for (INextGenEvent e : entry.getValue()) { out.append(Long.toString(e.getTime().getAbsoluteTime())); out.append(", "); out.append(Long.toString(e.getTime().getRelativeTime())); out.append(" -> "); out.append(e.toString()); out.newLine(); } } out.newLine(); out.append("### Threads ######################\n"); out.newLine(); for (Long threadKey : this.threadMap.keySet()) { out.append(Long.toString(threadKey)); out.append(" -> "); out.append(this.threadMap.get(threadKey).toString()); out.newLine(); } out.flush(); out.close(); } public void setLogfile(File logfile) { this.logFile = logfile; this.enabled = logfile != null; } // Writing to log public void toFile() throws IOException { if (logFile != null) { FileWriter fstream = new FileWriter(logFile + ".rttxt"); BufferedWriter out = new BufferedWriter(fstream); writeCPUdecls(out); writeBUSdecls(out); writeDeployObjs(out); writeEvents(out); out.flush(); out.close(); } } private void treatBusMessage(RTBusMessage message, NextGenTimeStamp time) { MessagePacket mp = message.message; NextGenBusMessage busMessage = null; if (message instanceof RTBusRequestMessage) { NextGenOperation operation = this.operationMap.get(getClassName(mp.operation) + mp.operation.name); busMessage = new NextGenBusMessage(mp.msgId, this.busMap.get(mp.bus.getNumber()), this.cpuMap.get(mp.from.getNumber()), this.cpuMap.get(mp.to.getNumber()), this.threadMap.get(mp.thread.getId()), operation, // this.operationMap.get(mp.operation.classdef.getName() // + // mp.operation.name), ((MessageRequest) mp).getSize(), this.objectMap.get(mp.target.objectReference)); this.busMessage.put(mp.msgId, busMessage); NextGenBusMessageEvent e = new NextGenBusMessageEvent(busMessage, NextGenBusMessageEventType.REQUEST, time); addEvent(e); } if (message instanceof RTBusActivateMessage) { busMessage = this.busMessage.get(mp.msgId); NextGenBusMessageEvent e = new NextGenBusMessageEvent(busMessage, NextGenBusMessageEventType.ACTIVATE, time); addEvent(e); } if (message instanceof RTBusCompletedMessage) { busMessage = this.busMessage.get(mp.msgId); NextGenBusMessageEvent e = new NextGenBusMessageEvent(busMessage, NextGenBusMessageEventType.COMPLETED, time); addEvent(e); } if (message instanceof RTBusReplyRequestMessage) { busMessage = this.busMessage.get(((MessageResponse) message.message).originalId); NextGenThread replyingThread = this.threadMap.get(((MessageResponse) message.message).thread.getId()); NextGenBusMessage replyBusMessage = new NextGenBusMessage(mp.msgId, this.busMap.get(mp.bus.getNumber()), this.cpuMap.get(mp.from.getNumber()), this.cpuMap.get(mp.to.getNumber()), replyingThread, busMessage.callerThread, busMessage.operation, ((MessageResponse) mp).getSize(), busMessage.object); this.busMessage.put(mp.msgId, replyBusMessage); NextGenBusMessageEvent e = new NextGenBusMessageReplyRequestEvent(busMessage, replyBusMessage, time); addEvent(e); } } private String getClassName(OperationValue operation) { if (operation.getSelf() != null) { return operation.getSelf().type.getName().getName(); } else { // return SClassDefinitionAssistantInterpreter.getName(operation.classdef); if (operation.classdef.getName() != null) { return operation.classdef.getName().getName(); } return null; } } private NextGenThread getThread(long id) { return this.threadMap.get(id); } private NextGenObject getObject(Long objref) { return this.objectMap.get(objref.intValue()); } private void treatOperationMessage(RTOperationMessage m, NextGenTimeStamp time) { String opName = m.operationVal.name.toString(); String className = getClassName(m.operationVal); boolean isAsync = m.operationVal.isAsync; boolean isStatic = m.operationVal.isStatic; NextGenOperation op = getOperation(className, opName); if (op == null) { op = new NextGenOperation(opName, getClassDefinition(className), isAsync, isStatic); } this.operationMap.put(className + opName, op); OperationEventType eventType = null; switch (m.messageType) { case Activate: eventType = OperationEventType.ACTIVATE; break; case Request: eventType = OperationEventType.REQUEST; break; case Completed: eventType = OperationEventType.COMPLETE; default: break; } NextGenObject obj = null; if (m.objref != null) { obj = getObject(m.objref); } NextGenOperationEvent opEvent = new NextGenOperationEvent(getThread(m.threadId), time, op, obj, eventType); addEvent(opEvent); } private NextGenOperation getOperation(String className, String opName) { return this.operationMap.get(className + opName); } private void addThreadKill(ISchedulableThread thread, CPUResource cpuNumber, NextGenTimeStamp time) { NextGenThread t = this.threadMap.get(thread.getId()); NextGenThreadEvent threadEvent = new NextGenThreadEvent(t, time, NextGenThreadEvent.ThreadEventType.KILL); // t.addEvent(threadEvent); addEvent(threadEvent); } private void addThreadSwap(ISchedulableThread thread, CPUResource cpuNumber, SwapType swapType, int overhead, long delay, NextGenTimeStamp time) { NextGenThread t = this.threadMap.get(thread.getId()); ThreadEventSwapType ngSwapType = null; switch (swapType) { case In: ngSwapType = ThreadEventSwapType.SWAP_IN; break; case DelayedIn: ngSwapType = ThreadEventSwapType.DELAYED_IN; break; case Out: ngSwapType = ThreadEventSwapType.SWAP_OUT; break; default: break; } NextGenThreadSwapEvent swapEvent = new NextGenThreadSwapEvent(t, time, ngSwapType, overhead, delay); addEvent(swapEvent); } private void addCpu(int id, boolean expl, String name, String systemClassName) { NextGenCpu cpu = new NextGenCpu(id, expl, name, systemClassName); this.cpuMap.put(cpu.id, cpu); vBus.cpus.add(cpu); } private void addBus(int busNumber, List<Integer> cpus, String name) { ArrayList<NextGenCpu> newCpus = new ArrayList<NextGenCpu>(); for (Integer cpuId : cpus) { newCpus.add(this.cpuMap.get(cpuId)); } NextGenBus bus = new NextGenBus(busNumber, name, newCpus); this.busMap.put(bus.id, bus); } private void deployObject(ObjectValue object, CPUResource cpuResource) { NextGenObject o = new NextGenObject(object.objectReference, getClassDefinition(object.type.getName().getName()), cpuMap.get(cpuResource.getNumber())); objectMap.put(object.objectReference, o); } private NextGenClassDefinition getClassDefinition(String name) { NextGenClassDefinition classDef = null; if (this.classDefMap.containsKey(name)) { classDef = this.classDefMap.get(name); } else { classDef = new NextGenClassDefinition(name); } return classDef; } private void createThread(ISchedulableThread thread, CPUResource cpuNumber, NextGenTimeStamp time) { long threadId = thread.getId(); // Creates thread object NextGenObject object = getObjectFromThread(thread); NextGenCpu cpu = cpuMap.get(cpuNumber.getNumber()); ThreadType tType = ThreadType.OBJECT; if (object == null && thread instanceof InitThread) { tType = ThreadType.INIT; } else if (thread instanceof MainThread) { tType = ThreadType.MAIN; } NextGenThread t = new NextGenThread(threadId, cpu, object, object == null ? false : thread.isPeriodic(), tType); // Creates thread create event NextGenThreadEvent e = new NextGenThreadEvent(t, time, NextGenThreadEvent.ThreadEventType.CREATE); // t.addEvent(e); addEvent(e); this.threadMap.put(thread.getId(), t); } private NextGenObject getObjectFromThread(ISchedulableThread thread) { ObjectValue obj = thread.getObject(); int id; NextGenClassDefinition classDef = null; NextGenCpu cpu = null; if (obj == null) { return null; } else { classDef = getClassDefinition(obj.type.getName().getName()); id = obj.objectReference; cpu = this.cpuMap.get(obj.getCPU().getNumber()); return new NextGenObject(id, classDef, cpu); } } private List<Integer> parseCpuIds(String cpus) { List<Integer> res = new ArrayList<Integer>(); cpus = cpus.replace("{", ""); cpus = cpus.replace("}", ""); String[] ids = cpus.split(","); for (String string : ids) { res.add(Integer.parseInt(string)); } return res; } private void writeEvents(BufferedWriter out) throws IOException { for (Map.Entry<Long, ArrayList<INextGenEvent>> entry : this.events.entrySet()) { for (INextGenEvent e : entry.getValue()) { out.append(e.toString()); out.newLine(); } } } private void writeDeployObjs(BufferedWriter out) throws IOException { for (NextGenObject o : this.objectMap.values()) { out.append(o.toString()); out.newLine(); } } private void writeBUSdecls(BufferedWriter out) throws IOException { for (NextGenBus bus : this.busMap.values()) { if (bus.id != 0) { out.append(bus.toString()); out.newLine(); } } } private void writeCPUdecls(BufferedWriter out) throws IOException { for (NextGenCpu cpu : this.cpuMap.values()) { if (cpu.id != 0) { out.append(cpu.toString()); out.newLine(); } } } @SuppressWarnings("unchecked") private void readFromFile(String filename) throws IOException, ClassNotFoundException { FileInputStream fis = new FileInputStream(filename); ObjectInputStream in = new ObjectInputStream(fis); this.cpuMap = (Map<Integer, NextGenCpu>) in.readObject(); this.busMap = (Map<Integer, NextGenBus>) in.readObject(); this.objectMap = (Map<Integer, NextGenObject>) in.readObject(); this.classDefMap = (Map<Integer, NextGenClassDefinition>) in.readObject(); this.operationMap = (Map<String, NextGenOperation>) in.readObject(); this.busMessage = (Map<Long, NextGenBusMessage>) in.readObject(); this.threadMap = (Map<Long, NextGenThread>) in.readObject(); this.events = (Map<Long, ArrayList<INextGenEvent>>) in.readObject(); in.close(); // printDataStructure("d:\\readFromFile_structure.txt"); } private void addEvent(INextGenEvent event) { NextGenTimeStamp eventTime = event.getTime(); if (!events.containsKey(eventTime.getAbsoluteTime())) { events.put(eventTime.getAbsoluteTime(), new ArrayList<INextGenEvent>()); } ArrayList<INextGenEvent> eventList = events.get(eventTime.getAbsoluteTime()); eventList.add(event); } @Override public void enable(boolean on) { this.enabled = on; } @Override public int getLogSize() { return this.events.size(); } @Override public void dump(boolean close) { try { persistToFile(); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } } }