blob: 2b7bd73ada6e5292e5b4f40558e6cf4e43e57b4e [file] [log] [blame]
Brian O'Connorc67f9fa2014-08-07 18:17:46 -07001package net.floodlightcontroller.debugevent;
2
3import java.lang.ref.SoftReference;
4import java.lang.reflect.Field;
5import java.text.SimpleDateFormat;
6import java.util.HashMap;
7import java.util.List;
8import java.util.Map;
Jonathan Hartc78b8f62014-08-07 22:31:09 -07009import java.util.Set;
Brian O'Connorc67f9fa2014-08-07 18:17:46 -070010
11import net.floodlightcontroller.debugevent.IDebugEventService.EventColumn;
12import net.onrc.onos.core.packet.IPv4;
13import net.onrc.onos.core.util.SwitchPort;
14
Jonathan Hartc78b8f62014-08-07 22:31:09 -070015import org.projectfloodlight.openflow.protocol.OFFlowModFlags;
16import org.projectfloodlight.openflow.util.HexString;
Brian O'Connorc67f9fa2014-08-07 18:17:46 -070017
18public class Event {
19 long timestamp;
20 long threadId;
21 String threadName;
22 Object eventData;
23 private Map<String, String> returnMap;
24
25 public Event(long timestamp, long threadId, String threadName, Object eventData) {
26 super();
27 this.timestamp = timestamp;
28 this.threadId = threadId;
29 this.threadName = threadName;
30 this.eventData = eventData;
31 }
32
33 public long getTimestamp() {
34 return timestamp;
35 }
36
37 public void setTimestamp(long timestamp) {
38 this.timestamp = timestamp;
39 }
40
41 public long getThreadId() {
42 return threadId;
43 }
44
45 public void setThreadId(long threadId) {
46 this.threadId = threadId;
47 }
48
49 public String getThreadName() {
50 return threadName;
51 }
52
53 public void setThreadName(String threadName) {
54 this.threadName = threadName;
55 }
56
57 public Object geteventData() {
58 return eventData;
59 }
60
61 public void seteventData(Object eventData) {
62 this.eventData = eventData;
63 }
64
65 /**
66 * If an old event (eg. popped from a circular buffer) is being re-used for
67 * storing a new event, it is very important to clear the cached formatted
68 * event, so that the formatting can be redone with the new event data.
69 * Otherwise it will appear as if the circular buffer is not getting updated
70 * at all as old (cached) formatted event is delivered to the user.
71 */
72 public void nullifyCachedFormattedEvent() {
73 this.returnMap = null;
74 }
75
76 @Override
77 public String toString() {
78 return "Event [timestamp=" + timestamp + ", threadId=" + threadId
79 + ", eventData=" + eventData.toString() + "]";
80 }
81
82 public Map<String, String> getFormattedEvent(Class<?> eventClass, String moduleEventName) {
83 if (eventClass == null || !eventClass.equals(eventData.getClass())) {
84 returnMap = new HashMap<String, String>();
85 returnMap.put("Error", "null event data or event-class does not match event-data");
86 return returnMap;
87 }
88 // return cached value if there is one
89 if (returnMap != null)
90 return returnMap;
91
92 returnMap = new HashMap<String, String>();
93 returnMap.put("Timestamp", new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSZ")
94 .format(timestamp));
95 returnMap.put("Thread Id", String.valueOf(threadId));
96 returnMap.put("Thread Name", String.valueOf(threadName));
97 customFormat(eventClass, eventData, returnMap);
98 return returnMap;
99 }
100
101 private void customFormat(Class<?> clazz, Object eventData,
102 Map<String, String> retMap) {
103 for (Field f : clazz.getDeclaredFields()) {
104 EventColumn ec = f.getAnnotation(EventColumn.class);
105 if (ec == null) continue;
106 f.setAccessible(true);
107 try {
108 Object obj = f.get(eventData);
109
110 switch(ec.description()) {
111 case DPID:
112 retMap.put(ec.name(), HexString.toHexString((Long) obj));
113 break;
114 case MAC:
115 retMap.put(ec.name(), HexString.toHexString((Long) obj, 6));
116 break;
117 case IPv4:
118 retMap.put(ec.name(), net.onrc.onos.core.packet.IPv4.fromIPv4Address((Integer) obj));
119 break;
120 case FLOW_MOD_FLAGS:
Jonathan Hartc78b8f62014-08-07 22:31:09 -0700121 @SuppressWarnings("unchecked")
122 Set<OFFlowModFlags> flags = (Set<OFFlowModFlags>) obj;
Brian O'Connorc67f9fa2014-08-07 18:17:46 -0700123 StringBuilder builder = new StringBuilder();
Jonathan Hartc78b8f62014-08-07 22:31:09 -0700124 if (flags.isEmpty()) {
Brian O'Connorc67f9fa2014-08-07 18:17:46 -0700125 builder.append("None");
126 }
127 else {
Jonathan Hartc78b8f62014-08-07 22:31:09 -0700128 if (flags.contains(OFFlowModFlags.SEND_FLOW_REM)) {
Brian O'Connorc67f9fa2014-08-07 18:17:46 -0700129 builder.append("SEND_FLOW_REM ");
130 }
Jonathan Hartc78b8f62014-08-07 22:31:09 -0700131 if (flags.contains(OFFlowModFlags.CHECK_OVERLAP)) {
Brian O'Connorc67f9fa2014-08-07 18:17:46 -0700132 builder.append("CHECK_OVERLAP ");
133 }
Jonathan Hartc78b8f62014-08-07 22:31:09 -0700134 if (flags.contains(OFFlowModFlags.EMERG)) {
Brian O'Connorc67f9fa2014-08-07 18:17:46 -0700135 builder.append("EMERG ");
136 }
137 }
138 retMap.put(ec.name(), builder.toString());
139 break;
140 case LIST_IPV4:
141 @SuppressWarnings("unchecked")
142 List<Integer> ipv4Addresses = (List<Integer>)obj;
143 StringBuilder ipv4AddressesStr = new StringBuilder();
144 if (ipv4Addresses.size() == 0) {
145 ipv4AddressesStr.append("--");
146 } else {
147 for (Integer ipv4Addr : ipv4Addresses) {
148 ipv4AddressesStr.append(IPv4.fromIPv4Address(ipv4Addr.intValue()));
149 ipv4AddressesStr.append(" ");
150 }
151 }
152 retMap.put(ec.name(), ipv4AddressesStr.toString());
153 break;
154 case LIST_ATTACHMENT_POINT:
155 @SuppressWarnings("unchecked")
156 List<SwitchPort> aps = (List<SwitchPort>)obj;
157 StringBuilder apsStr = new StringBuilder();
158 if (aps.size() == 0) {
159 apsStr.append("--");
160 } else {
161 for (SwitchPort ap : aps) {
Pavlin Radoslavov3d322f42014-08-18 14:58:55 -0700162 apsStr.append(HexString.toHexString(ap.getDpid().value()));
Brian O'Connorc67f9fa2014-08-07 18:17:46 -0700163 apsStr.append("/");
Pavlin Radoslavov3d322f42014-08-18 14:58:55 -0700164 apsStr.append(ap.getPortNumber().value());
Brian O'Connorc67f9fa2014-08-07 18:17:46 -0700165 apsStr.append(" ");
166 }
167 }
168 retMap.put(ec.name(), apsStr.toString());
169 break;
170 case LIST_OBJECT:
171 @SuppressWarnings("unchecked")
172 List<Object> obl = (List<Object>)obj;
173 StringBuilder sbldr = new StringBuilder();
174 if (obl.size() == 0) {
175 sbldr.append("--");
176 } else {
177 for (Object o : obl) {
178 sbldr.append(o.toString());
179 sbldr.append(" ");
180 }
181 }
182 retMap.put(ec.name(), sbldr.toString());
183 break;
184 case SREF_LIST_OBJECT:
185 @SuppressWarnings("unchecked")
186 SoftReference<List<Object>> srefListObj =
187 (SoftReference<List<Object>>)obj;
188 List<Object> ol = srefListObj.get();
189 if (ol != null) {
190 StringBuilder sb = new StringBuilder();
191 if (ol.size() == 0) {
192 sb.append("--");
193 } else {
194 for (Object o : ol) {
195 sb.append(o.toString());
196 sb.append(" ");
197 }
198 }
199 retMap.put(ec.name(), sb.toString());
200 } else {
201 retMap.put(ec.name(), "-- reference not available --");
202 }
203 break;
204 case SREF_OBJECT:
205 @SuppressWarnings("unchecked")
206 SoftReference<Object> srefObj = (SoftReference<Object>)obj;
207 if (srefObj == null) {
208 retMap.put(ec.name(), "--");
209 } else {
210 Object o = srefObj.get();
211 if (o != null) {
212 retMap.put(ec.name(), o.toString());
213 } else {
214 retMap.put(ec.name(),
215 "-- reference not available --");
216 }
217 }
218 break;
219 case STRING:
220 case OBJECT:
221 case PRIMITIVE:
222 default:
223 retMap.put(ec.name(), obj.toString());
224 }
225 } catch (ClassCastException e) {
226 retMap.put("Error", e.getMessage());
227 } catch (IllegalArgumentException e) {
228 retMap.put("Error", e.getMessage());
229 } catch (IllegalAccessException e) {
230 retMap.put("Error", e.getMessage());
231 }
232 }
233 }
234
235}