| package net.floodlightcontroller.debugevent; |
| |
| import java.lang.ref.SoftReference; |
| import java.lang.reflect.Field; |
| import java.text.SimpleDateFormat; |
| import java.util.HashMap; |
| import java.util.List; |
| import java.util.Map; |
| import java.util.Set; |
| |
| import net.floodlightcontroller.debugevent.IDebugEventService.EventColumn; |
| import net.onrc.onos.core.packet.IPv4; |
| import net.onrc.onos.core.util.SwitchPort; |
| |
| import org.projectfloodlight.openflow.protocol.OFFlowModFlags; |
| import org.projectfloodlight.openflow.util.HexString; |
| |
| public class Event { |
| long timestamp; |
| long threadId; |
| String threadName; |
| Object eventData; |
| private Map<String, String> returnMap; |
| |
| public Event(long timestamp, long threadId, String threadName, Object eventData) { |
| super(); |
| this.timestamp = timestamp; |
| this.threadId = threadId; |
| this.threadName = threadName; |
| this.eventData = eventData; |
| } |
| |
| public long getTimestamp() { |
| return timestamp; |
| } |
| |
| public void setTimestamp(long timestamp) { |
| this.timestamp = timestamp; |
| } |
| |
| public long getThreadId() { |
| return threadId; |
| } |
| |
| public void setThreadId(long threadId) { |
| this.threadId = threadId; |
| } |
| |
| public String getThreadName() { |
| return threadName; |
| } |
| |
| public void setThreadName(String threadName) { |
| this.threadName = threadName; |
| } |
| |
| public Object geteventData() { |
| return eventData; |
| } |
| |
| public void seteventData(Object eventData) { |
| this.eventData = eventData; |
| } |
| |
| /** |
| * If an old event (eg. popped from a circular buffer) is being re-used for |
| * storing a new event, it is very important to clear the cached formatted |
| * event, so that the formatting can be redone with the new event data. |
| * Otherwise it will appear as if the circular buffer is not getting updated |
| * at all as old (cached) formatted event is delivered to the user. |
| */ |
| public void nullifyCachedFormattedEvent() { |
| this.returnMap = null; |
| } |
| |
| @Override |
| public String toString() { |
| return "Event [timestamp=" + timestamp + ", threadId=" + threadId |
| + ", eventData=" + eventData.toString() + "]"; |
| } |
| |
| public Map<String, String> getFormattedEvent(Class<?> eventClass, String moduleEventName) { |
| if (eventClass == null || !eventClass.equals(eventData.getClass())) { |
| returnMap = new HashMap<String, String>(); |
| returnMap.put("Error", "null event data or event-class does not match event-data"); |
| return returnMap; |
| } |
| // return cached value if there is one |
| if (returnMap != null) |
| return returnMap; |
| |
| returnMap = new HashMap<String, String>(); |
| returnMap.put("Timestamp", new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSZ") |
| .format(timestamp)); |
| returnMap.put("Thread Id", String.valueOf(threadId)); |
| returnMap.put("Thread Name", String.valueOf(threadName)); |
| customFormat(eventClass, eventData, returnMap); |
| return returnMap; |
| } |
| |
| private void customFormat(Class<?> clazz, Object eventData, |
| Map<String, String> retMap) { |
| for (Field f : clazz.getDeclaredFields()) { |
| EventColumn ec = f.getAnnotation(EventColumn.class); |
| if (ec == null) continue; |
| f.setAccessible(true); |
| try { |
| Object obj = f.get(eventData); |
| |
| switch(ec.description()) { |
| case DPID: |
| retMap.put(ec.name(), HexString.toHexString((Long) obj)); |
| break; |
| case MAC: |
| retMap.put(ec.name(), HexString.toHexString((Long) obj, 6)); |
| break; |
| case IPv4: |
| retMap.put(ec.name(), net.onrc.onos.core.packet.IPv4.fromIPv4Address((Integer) obj)); |
| break; |
| case FLOW_MOD_FLAGS: |
| @SuppressWarnings("unchecked") |
| Set<OFFlowModFlags> flags = (Set<OFFlowModFlags>) obj; |
| StringBuilder builder = new StringBuilder(); |
| if (flags.isEmpty()) { |
| builder.append("None"); |
| } |
| else { |
| if (flags.contains(OFFlowModFlags.SEND_FLOW_REM)) { |
| builder.append("SEND_FLOW_REM "); |
| } |
| if (flags.contains(OFFlowModFlags.CHECK_OVERLAP)) { |
| builder.append("CHECK_OVERLAP "); |
| } |
| if (flags.contains(OFFlowModFlags.EMERG)) { |
| builder.append("EMERG "); |
| } |
| } |
| retMap.put(ec.name(), builder.toString()); |
| break; |
| case LIST_IPV4: |
| @SuppressWarnings("unchecked") |
| List<Integer> ipv4Addresses = (List<Integer>)obj; |
| StringBuilder ipv4AddressesStr = new StringBuilder(); |
| if (ipv4Addresses.size() == 0) { |
| ipv4AddressesStr.append("--"); |
| } else { |
| for (Integer ipv4Addr : ipv4Addresses) { |
| ipv4AddressesStr.append(IPv4.fromIPv4Address(ipv4Addr.intValue())); |
| ipv4AddressesStr.append(" "); |
| } |
| } |
| retMap.put(ec.name(), ipv4AddressesStr.toString()); |
| break; |
| case LIST_ATTACHMENT_POINT: |
| @SuppressWarnings("unchecked") |
| List<SwitchPort> aps = (List<SwitchPort>)obj; |
| StringBuilder apsStr = new StringBuilder(); |
| if (aps.size() == 0) { |
| apsStr.append("--"); |
| } else { |
| for (SwitchPort ap : aps) { |
| apsStr.append(HexString.toHexString(ap.getDpid().value())); |
| apsStr.append("/"); |
| apsStr.append(ap.getPortNumber().value()); |
| apsStr.append(" "); |
| } |
| } |
| retMap.put(ec.name(), apsStr.toString()); |
| break; |
| case LIST_OBJECT: |
| @SuppressWarnings("unchecked") |
| List<Object> obl = (List<Object>)obj; |
| StringBuilder sbldr = new StringBuilder(); |
| if (obl.size() == 0) { |
| sbldr.append("--"); |
| } else { |
| for (Object o : obl) { |
| sbldr.append(o.toString()); |
| sbldr.append(" "); |
| } |
| } |
| retMap.put(ec.name(), sbldr.toString()); |
| break; |
| case SREF_LIST_OBJECT: |
| @SuppressWarnings("unchecked") |
| SoftReference<List<Object>> srefListObj = |
| (SoftReference<List<Object>>)obj; |
| List<Object> ol = srefListObj.get(); |
| if (ol != null) { |
| StringBuilder sb = new StringBuilder(); |
| if (ol.size() == 0) { |
| sb.append("--"); |
| } else { |
| for (Object o : ol) { |
| sb.append(o.toString()); |
| sb.append(" "); |
| } |
| } |
| retMap.put(ec.name(), sb.toString()); |
| } else { |
| retMap.put(ec.name(), "-- reference not available --"); |
| } |
| break; |
| case SREF_OBJECT: |
| @SuppressWarnings("unchecked") |
| SoftReference<Object> srefObj = (SoftReference<Object>)obj; |
| if (srefObj == null) { |
| retMap.put(ec.name(), "--"); |
| } else { |
| Object o = srefObj.get(); |
| if (o != null) { |
| retMap.put(ec.name(), o.toString()); |
| } else { |
| retMap.put(ec.name(), |
| "-- reference not available --"); |
| } |
| } |
| break; |
| case STRING: |
| case OBJECT: |
| case PRIMITIVE: |
| default: |
| retMap.put(ec.name(), obj.toString()); |
| } |
| } catch (ClassCastException e) { |
| retMap.put("Error", e.getMessage()); |
| } catch (IllegalArgumentException e) { |
| retMap.put("Error", e.getMessage()); |
| } catch (IllegalAccessException e) { |
| retMap.put("Error", e.getMessage()); |
| } |
| } |
| } |
| |
| } |