From df937333df8136bfd10a0213673ef39e07b72b29 Mon Sep 17 00:00:00 2001
From: Subrata Banerjee <subrata.banerjee@bigswitch.com>
Date: Tue, 10 Jan 2012 21:32:53 -0800
Subject: [PATCH] Cleanup of event-history infra.

---
 .../core/web/CoreWebRoutable.java             |  5 +++
 .../EventHistoryAttachmentPointResource.java  | 43 ++++++++++++++++++
 .../web/EventHistoryPacketInResource.java     | 34 ++++++++++++++
 .../core/web/JacksonCustomConverter.java      | 26 ++++++++---
 ...tHistoryAttachmentPointJSONSerializer.java | 45 +++++++++++++++++++
 ...> EventHistoryBaseInfoJSONSerializer.java} | 37 ++++++++++-----
 .../serializers/OFMatchJSONSerializer.java    |  2 +-
 .../internal/DeviceManagerImpl.java           | 40 ++---------------
 .../internal/EventHistoryAttachmentPoint.java | 33 ++++++++++++++
 .../util/EventHistory.java                    | 32 ++-----------
 .../util/EventHistoryBaseInfo.java            | 22 +++++++++
 11 files changed, 235 insertions(+), 84 deletions(-)
 create mode 100644 src/main/java/net/floodlightcontroller/core/web/EventHistoryAttachmentPointResource.java
 create mode 100644 src/main/java/net/floodlightcontroller/core/web/EventHistoryPacketInResource.java
 create mode 100644 src/main/java/net/floodlightcontroller/core/web/serializers/EventHistoryAttachmentPointJSONSerializer.java
 rename src/main/java/net/floodlightcontroller/core/web/serializers/{BaseInfoJSONSerializer.java => EventHistoryBaseInfoJSONSerializer.java} (59%)
 create mode 100644 src/main/java/net/floodlightcontroller/devicemanager/internal/EventHistoryAttachmentPoint.java
 create mode 100644 src/main/java/net/floodlightcontroller/util/EventHistoryBaseInfo.java

diff --git a/src/main/java/net/floodlightcontroller/core/web/CoreWebRoutable.java b/src/main/java/net/floodlightcontroller/core/web/CoreWebRoutable.java
index 71578dfa1..51e092bc8 100644
--- a/src/main/java/net/floodlightcontroller/core/web/CoreWebRoutable.java
+++ b/src/main/java/net/floodlightcontroller/core/web/CoreWebRoutable.java
@@ -44,6 +44,11 @@ public class CoreWebRoutable implements RestletRoutable {
         router.attach("/memory/json", ControllerMemoryResource.class);
         router.attach("/staticflowentrypusher/json", StaticFlowEntryPusherResource.class);
         router.attach("/packettrace/json", PacketTraceResource.class);
+        // Get the last {count} events from the event histories
+        router.attach("/event-history/attachment-point/{count}/json",
+                EventHistoryAttachmentPointResource.class);
+        router.attach("/event-history/packet-in/{count}/json",
+                EventHistoryPacketInResource.class);
         return router;
     }
 }
diff --git a/src/main/java/net/floodlightcontroller/core/web/EventHistoryAttachmentPointResource.java b/src/main/java/net/floodlightcontroller/core/web/EventHistoryAttachmentPointResource.java
new file mode 100644
index 000000000..0ada3a35a
--- /dev/null
+++ b/src/main/java/net/floodlightcontroller/core/web/EventHistoryAttachmentPointResource.java
@@ -0,0 +1,43 @@
+/**
+ * 
+ */
+package net.floodlightcontroller.core.web;
+
+import net.floodlightcontroller.devicemanager.internal.DeviceManagerImpl;
+import net.floodlightcontroller.devicemanager.internal.EventHistoryAttachmentPoint;
+import net.floodlightcontroller.util.EventHistory;
+
+import org.restlet.resource.ServerResource;
+import org.restlet.resource.Get;
+
+/**
+ * @author subrata
+ *
+ */
+public class EventHistoryAttachmentPointResource extends ServerResource {
+    /***
+     * Event History Names:
+     *     (a) attachment-point
+     *     (b) host-network-address
+     *     (c) switch-connect
+     *     (d) switch-link
+     *     (g) packet-ins
+     *     (h) packet-outs
+     *     (i) error (for floodlight)
+     *     (l) route-computation
+     *     (n) pktin-drops
+     */
+
+    @Get("json")
+    public EventHistory<EventHistoryAttachmentPoint> handleEvHistReq() {
+
+        // Get the event history count. Last <count> events would be returned
+        String evHistCount = (String)getRequestAttributes().get("count");
+
+        DeviceManagerImpl deviceManager = 
+           (DeviceManagerImpl)getContext().getAttributes().get("deviceManager");
+
+        return new EventHistory<EventHistoryAttachmentPoint>(deviceManager.evHistDevMgrAttachPt,
+                Integer.parseInt(evHistCount));
+    }
+}
diff --git a/src/main/java/net/floodlightcontroller/core/web/EventHistoryPacketInResource.java b/src/main/java/net/floodlightcontroller/core/web/EventHistoryPacketInResource.java
new file mode 100644
index 000000000..ea0bb3ef9
--- /dev/null
+++ b/src/main/java/net/floodlightcontroller/core/web/EventHistoryPacketInResource.java
@@ -0,0 +1,34 @@
+/**
+ * 
+ */
+package net.floodlightcontroller.core.web;
+
+import net.floodlightcontroller.devicemanager.internal.DeviceManagerImpl;
+import net.floodlightcontroller.util.EventHistory;
+
+import org.openflow.protocol.OFMatch;
+import org.restlet.resource.Get;
+import org.restlet.resource.ServerResource;
+
+/**
+ * @author subrata
+ *
+ */
+public class EventHistoryPacketInResource extends ServerResource {
+
+    @Get("json")
+    public EventHistory<OFMatch> handleEvHistReq() {
+
+        EventHistory<OFMatch> ofm = null;
+        // Get the count (number of latest events requested), zero means all
+        String evHistCount = (String)getRequestAttributes().get("count");
+
+        DeviceManagerImpl deviceManager = 
+           (DeviceManagerImpl)getContext().getAttributes().get("deviceManager");
+
+        ofm =  new EventHistory<OFMatch>(deviceManager.evHistDevMgrPktIn,
+                                            Integer.parseInt(evHistCount));
+        return ofm;
+    }
+
+}
diff --git a/src/main/java/net/floodlightcontroller/core/web/JacksonCustomConverter.java b/src/main/java/net/floodlightcontroller/core/web/JacksonCustomConverter.java
index 230389c41..452d6f1de 100644
--- a/src/main/java/net/floodlightcontroller/core/web/JacksonCustomConverter.java
+++ b/src/main/java/net/floodlightcontroller/core/web/JacksonCustomConverter.java
@@ -19,6 +19,8 @@ package net.floodlightcontroller.core.web;
 
 import java.util.List;
 
+import net.floodlightcontroller.core.web.serializers.EventHistoryAttachmentPointJSONSerializer;
+import net.floodlightcontroller.core.web.serializers.EventHistoryBaseInfoJSONSerializer;
 import net.floodlightcontroller.core.web.serializers.OFFeaturesReplyJSONSerializer;
 import net.floodlightcontroller.core.web.serializers.OFMatchJSONSerializer;
 import net.floodlightcontroller.core.web.serializers.OFPhysicalPortJSONSerializer;
@@ -44,7 +46,8 @@ import org.slf4j.LoggerFactory;
  *
  */
 public class JacksonCustomConverter extends JacksonConverter {
-    protected static Logger log = LoggerFactory.getLogger(JacksonCustomConverter.class);
+    protected static Logger log = 
+                        LoggerFactory.getLogger(JacksonCustomConverter.class);
 
     protected static ObjectMapper jsonObjectMapper;
     protected static SimpleModule jsonModule;
@@ -56,19 +59,26 @@ public class JacksonCustomConverter extends JacksonConverter {
         jsonModule.addSerializer(new OFMatchJSONSerializer());
         jsonModule.addSerializer(new OFFeaturesReplyJSONSerializer());
         jsonModule.addSerializer(new OFPhysicalPortJSONSerializer());
+        jsonModule.addSerializer(new EventHistoryBaseInfoJSONSerializer());
+        jsonModule.addSerializer(
+                            new EventHistoryAttachmentPointJSONSerializer());
         jsonObjectMapper.registerModule(jsonModule);
     }
     
     @Override
-    protected <T> JacksonRepresentation<T> create(MediaType mediaType, T source) {
-        JacksonRepresentation<T> jr = new JacksonRepresentation<T>(mediaType, source);
+    protected <T> JacksonRepresentation<T> 
+                                        create(MediaType mediaType, T source) {
+        JacksonRepresentation<T> jr = 
+                                new JacksonRepresentation<T>(mediaType, source);
         jr.setObjectMapper(jsonObjectMapper);
         return jr;
     }
 
     @Override
-    protected <T> JacksonRepresentation<T> create(Representation source, Class<T> objectClass) {
-        JacksonRepresentation<T> jr = new JacksonRepresentation<T>(source, objectClass);
+    protected <T> JacksonRepresentation<T> 
+                        create(Representation source, Class<T> objectClass) {
+        JacksonRepresentation<T> jr = 
+                        new JacksonRepresentation<T>(source, objectClass);
         jr.setObjectMapper(jsonObjectMapper);
         return jr;
     }
@@ -81,7 +91,8 @@ public class JacksonCustomConverter extends JacksonConverter {
     public static void replaceConverter() {
         ConverterHelper oldConverter = null;
 
-        List<ConverterHelper> converters = Engine.getInstance().getRegisteredConverters();
+        List<ConverterHelper> converters = 
+                            Engine.getInstance().getRegisteredConverters();
         for (ConverterHelper converter : converters) {
             if (converter.getClass().equals(JacksonConverter.class)) {
                 converters.remove(converter);
@@ -93,7 +104,8 @@ public class JacksonCustomConverter extends JacksonConverter {
         converters.add(new JacksonCustomConverter());
 
         if (oldConverter == null) {
-            log.debug("Added {} to Restlet Engine", JacksonCustomConverter.class);
+            log.debug("Added {} to Restlet Engine", 
+                                                JacksonCustomConverter.class);
         } else {
             log.debug("Replaced {} with {} in Restlet Engine", 
                          oldConverter.getClass(), JacksonCustomConverter.class);
diff --git a/src/main/java/net/floodlightcontroller/core/web/serializers/EventHistoryAttachmentPointJSONSerializer.java b/src/main/java/net/floodlightcontroller/core/web/serializers/EventHistoryAttachmentPointJSONSerializer.java
new file mode 100644
index 000000000..6a8fb939d
--- /dev/null
+++ b/src/main/java/net/floodlightcontroller/core/web/serializers/EventHistoryAttachmentPointJSONSerializer.java
@@ -0,0 +1,45 @@
+package net.floodlightcontroller.core.web.serializers;
+
+import java.io.IOException;
+
+import net.floodlightcontroller.devicemanager.internal.EventHistoryAttachmentPoint;
+
+import org.codehaus.jackson.JsonGenerator;
+import org.codehaus.jackson.JsonProcessingException;
+import org.codehaus.jackson.map.JsonSerializer;
+import org.codehaus.jackson.map.SerializerProvider;
+import org.openflow.util.HexString;
+
+/**
+ * 
+ * @author subrata
+ *
+ */
+
+public class EventHistoryAttachmentPointJSONSerializer 
+                        extends JsonSerializer<EventHistoryAttachmentPoint> {
+    /**
+     * Performs the serialization of a EventHistory.BaseInfo object
+     */
+   @Override
+   public void serialize(EventHistoryAttachmentPoint attachPt, 
+                   JsonGenerator jGen,
+                   SerializerProvider serializer) 
+                   throws IOException, JsonProcessingException {
+       jGen.writeStartObject();
+       jGen.writeStringField("Switch", HexString.toHexString(attachPt.dpid));
+       jGen.writeStringField("Host",   HexString.toHexString(attachPt.mac));
+       jGen.writeNumberField("Port",   attachPt.port);
+       jGen.writeNumberField("VLAN",   attachPt.vlan);
+       jGen.writeStringField("Reason", attachPt.reason);
+       jGen.writeEndObject();
+   }
+
+   /**
+    * Tells SimpleModule that we are the serializer for OFMatch
+    */
+   @Override
+   public Class<EventHistoryAttachmentPoint> handledType() {
+       return EventHistoryAttachmentPoint.class;
+   }
+}
diff --git a/src/main/java/net/floodlightcontroller/core/web/serializers/BaseInfoJSONSerializer.java b/src/main/java/net/floodlightcontroller/core/web/serializers/EventHistoryBaseInfoJSONSerializer.java
similarity index 59%
rename from src/main/java/net/floodlightcontroller/core/web/serializers/BaseInfoJSONSerializer.java
rename to src/main/java/net/floodlightcontroller/core/web/serializers/EventHistoryBaseInfoJSONSerializer.java
index 82c4a2973..0ad8786da 100644
--- a/src/main/java/net/floodlightcontroller/core/web/serializers/BaseInfoJSONSerializer.java
+++ b/src/main/java/net/floodlightcontroller/core/web/serializers/EventHistoryBaseInfoJSONSerializer.java
@@ -17,37 +17,42 @@
 package net.floodlightcontroller.core.web.serializers;
 
 import java.io.IOException;
-import java.util.Date;
 
-import net.floodlightcontroller.util.EventHistory.BaseInfo;
+import java.sql.Timestamp;
+
+import net.floodlightcontroller.util.EventHistoryBaseInfo;
 
 import org.codehaus.jackson.JsonGenerator;
 import org.codehaus.jackson.JsonProcessingException;
 import org.codehaus.jackson.map.JsonSerializer;
 import org.codehaus.jackson.map.SerializerProvider;
 
+
 /**
  * @author subrata
  *
  */
 
-public class BaseInfoJSONSerializer extends 
-                                    JsonSerializer<BaseInfo> {
+public class EventHistoryBaseInfoJSONSerializer extends 
+                                    JsonSerializer<EventHistoryBaseInfo> {
 
  
     /**
      * Performs the serialization of a EventHistory.BaseInfo object
      */
     @Override
-    public void serialize(BaseInfo base_info, JsonGenerator jGen,
+    public void serialize(EventHistoryBaseInfo base_info, JsonGenerator jGen,
                     SerializerProvider serializer) 
                     throws IOException, JsonProcessingException {
         jGen.writeStartObject();
         jGen.writeNumberField("Idx",    base_info.getIdx());
-        jGen.writeStringField("Time",   
+        jGen.writeStringField("Time",
                             convertNanoSecondsToStr(base_info.getTime_ns()));
         jGen.writeStringField("State",  base_info.getState().name());
-        jGen.writeStringField("Action", base_info.getAction().name());
+        String acStr = base_info.getAction().name().toLowerCase();
+        // Capitalize the first letter
+        acStr = acStr.substring(0,1).toUpperCase().concat(acStr.substring(1));
+        jGen.writeStringField("Action", acStr);
         jGen.writeEndObject();
     }
 
@@ -55,13 +60,21 @@ public class BaseInfoJSONSerializer extends
      * Tells SimpleModule that we are the serializer for OFMatch
      */
     @Override
-    public Class<BaseInfo> handledType() {
-        return BaseInfo.class;
+    public Class<EventHistoryBaseInfo> handledType() {
+        return EventHistoryBaseInfo.class;
     }
-    
+
     public String convertNanoSecondsToStr(long nanoSeconds) {
-        long millisecs = nanoSeconds / 1000000;
-        String timeStr = (new Date(millisecs)).toString();
+        long millisecs    = nanoSeconds / 1000000;
+        int  remaining_ns = (int)(nanoSeconds % 1000000000);
+        Timestamp ts      = new Timestamp(millisecs);
+        ts.setNanos(remaining_ns);
+        // Show up to microseconds resolution
+        // length of "2012-01-09 14:54:45.067253" is 26
+        String timeStr = ts.toString();
+        while (timeStr.length() < 26) {
+            timeStr = timeStr.concat("0");
+        }
         return timeStr;
     }
 }
diff --git a/src/main/java/net/floodlightcontroller/core/web/serializers/OFMatchJSONSerializer.java b/src/main/java/net/floodlightcontroller/core/web/serializers/OFMatchJSONSerializer.java
index 99edc0120..e08eeb61a 100644
--- a/src/main/java/net/floodlightcontroller/core/web/serializers/OFMatchJSONSerializer.java
+++ b/src/main/java/net/floodlightcontroller/core/web/serializers/OFMatchJSONSerializer.java
@@ -48,7 +48,7 @@ public class OFMatchJSONSerializer extends JsonSerializer<OFMatch> {
         jGen.writeStartObject();
         jGen.writeStringField("dataLayerDestination", HexString.toHexString(match.getDataLayerDestination()));
         jGen.writeStringField("dataLayerSource", HexString.toHexString(match.getDataLayerSource()));
-        jGen.writeNumberField("dataLayerType", match.getDataLayerType());
+        jGen.writeStringField("dataLayerType", "0x" + Integer.toHexString(match.getDataLayerType()));
         jGen.writeNumberField("dataLayerVirtualLan", match.getDataLayerVirtualLan());
         jGen.writeNumberField("dataLayerVirtualLanPriorityCodePoint", match.getDataLayerVirtualLanPriorityCodePoint());
         jGen.writeStringField("inputSwitch", HexString.toHexString(match.getSwitchDataPathId()));
diff --git a/src/main/java/net/floodlightcontroller/devicemanager/internal/DeviceManagerImpl.java b/src/main/java/net/floodlightcontroller/devicemanager/internal/DeviceManagerImpl.java
index df1d93c4b..c42ce554d 100755
--- a/src/main/java/net/floodlightcontroller/devicemanager/internal/DeviceManagerImpl.java
+++ b/src/main/java/net/floodlightcontroller/devicemanager/internal/DeviceManagerImpl.java
@@ -624,7 +624,7 @@ public class DeviceManagerImpl implements IDeviceManager, IOFMessageListener,
         this.lock = new ReentrantReadWriteLock();
         this.updates = new LinkedList<Update>();
         this.evHistDevMgrAttachPt = 
-                new EventHistory<EvHistAttachmentPt>("Attachment-Point");
+                new EventHistory<EventHistoryAttachmentPoint>("Attachment-Point");
         this.evHistDevMgrPktIn =
                 new EventHistory<OFMatch>("Pakcet-In");
     }
@@ -1910,41 +1910,9 @@ public class DeviceManagerImpl implements IDeviceManager, IOFMessageListener,
     // Device Manager's Event History members and methods
     // **************************************************
 
-    /***
-     * Attachment-Point Event history related classes and members
-     * @author subrata
-     *
-     */
-    public class EvHistAttachmentPt {
-        public String   reason;
-        // The following fields are not stored as String to save memory
-        // They shoudl be converted to appropriate human-readable strings by 
-        // the front end (e.g. in cli in python)
-        public long     mac;
-        public short    vlan;
-        public short    port;
-        public long     dpid;
-
-        public long getMac() {
-            return mac;
-        }
-        public short getVlan() {
-            return vlan;
-        }
-        public short getPort() {
-            return port;
-        }
-        public long getDpid() {
-            return dpid;
-        }
-        public String getReason() {
-            return reason;
-        }
-    }
-
     // Attachment-point event history
-    public EventHistory<EvHistAttachmentPt> evHistDevMgrAttachPt;
-    public EvHistAttachmentPt evHAP;
+    public EventHistory<EventHistoryAttachmentPoint> evHistDevMgrAttachPt;
+    public EventHistoryAttachmentPoint evHAP;
 
     private void evHistAttachmtPt(Device d, SwitchPortTuple swPrt,
                                             EvAction action, String reason) {
@@ -1968,7 +1936,7 @@ public class DeviceManagerImpl implements IDeviceManager, IOFMessageListener,
     private void evHistAttachmtPt(long mac, long dpid, short port,
                                               EvAction action, String reason) {
         if (evHAP == null) {
-            evHAP = new EvHistAttachmentPt();
+            evHAP = new EventHistoryAttachmentPoint();
         }
         evHAP.dpid   = dpid;
         evHAP.port   = port;
diff --git a/src/main/java/net/floodlightcontroller/devicemanager/internal/EventHistoryAttachmentPoint.java b/src/main/java/net/floodlightcontroller/devicemanager/internal/EventHistoryAttachmentPoint.java
new file mode 100644
index 000000000..fb22b6049
--- /dev/null
+++ b/src/main/java/net/floodlightcontroller/devicemanager/internal/EventHistoryAttachmentPoint.java
@@ -0,0 +1,33 @@
+package net.floodlightcontroller.devicemanager.internal;
+
+/***
+ * Attachment-Point Event history related classes and members
+ * @author subrata
+ *
+ */
+public class EventHistoryAttachmentPoint {
+    public String   reason;
+    // The following fields are not stored as String to save memory
+    // They shoudl be converted to appropriate human-readable strings by 
+    // the front end (e.g. in cli in python)
+    public long     mac;
+    public short    vlan;
+    public short    port;
+    public long     dpid;
+
+    public long getMac() {
+        return mac;
+    }
+    public short getVlan() {
+        return vlan;
+    }
+    public short getPort() {
+        return port;
+    }
+    public long getDpid() {
+        return dpid;
+    }
+    public String getReason() {
+        return reason;
+    }
+}
\ No newline at end of file
diff --git a/src/main/java/net/floodlightcontroller/util/EventHistory.java b/src/main/java/net/floodlightcontroller/util/EventHistory.java
index e57e398d3..a5cad1e80 100644
--- a/src/main/java/net/floodlightcontroller/util/EventHistory.java
+++ b/src/main/java/net/floodlightcontroller/util/EventHistory.java
@@ -35,30 +35,9 @@ public class EventHistory<T> {
         return events;
     }
 
-    public class BaseInfo {
-        public int              idx;
-        public long             time_ns; // timestamp in nanoseconds
-        public EvState          state;
-        public EvAction         action;
-
-        // Getters
-        public int getIdx() {
-            return idx;
-        }
-        public long getTime_ns() {
-            return time_ns;
-        }
-        public EvState getState() {
-            return state;
-        }
-        public EvAction getAction() {
-            return action;
-        }
-    }
-
     public class Event {
-        public BaseInfo  base_info;
-        public T          info;
+        public EventHistoryBaseInfo base_info;
+        public T info;
     }
 
     public enum EvState {
@@ -84,7 +63,7 @@ public class EventHistory<T> {
 
         for (int idx = 0; idx < maxEvents; idx++) {
             Event evH     = new Event();
-            evH.base_info = new BaseInfo();
+            evH.base_info = new EventHistoryBaseInfo();
             evH.info      = null;
             evH.base_info.state = EvState.FREE;
             evH.base_info.idx   = idx;
@@ -103,10 +82,7 @@ public class EventHistory<T> {
     }
 
     // Copy constructor - copy latest k items of the event history
-    public EventHistory(Object eventHistIn, int latestK) {
-
-        EventHistory<T> eventHist = (EventHistory<T>)eventHistIn;
-
+    public EventHistory(EventHistory<T> eventHist, int latestK) {
         int curSize = (eventHist.full)?eventHist.event_history_size:
                                                     eventHist.current_index;
         int size  = (latestK < curSize)?latestK:curSize;
diff --git a/src/main/java/net/floodlightcontroller/util/EventHistoryBaseInfo.java b/src/main/java/net/floodlightcontroller/util/EventHistoryBaseInfo.java
new file mode 100644
index 000000000..c23ef79d1
--- /dev/null
+++ b/src/main/java/net/floodlightcontroller/util/EventHistoryBaseInfo.java
@@ -0,0 +1,22 @@
+package net.floodlightcontroller.util;
+
+public class EventHistoryBaseInfo {
+    public int              idx;
+    public long             time_ns; // timestamp in nanoseconds
+    public EventHistory.EvState          state;
+    public EventHistory.EvAction         action;
+
+    // Getters
+    public int getIdx() {
+        return idx;
+    }
+    public long getTime_ns() {
+        return time_ns;
+    }
+    public EventHistory.EvState getState() {
+        return state;
+    }
+    public EventHistory.EvAction getAction() {
+        return action;
+    }
+}
\ No newline at end of file
-- 
GitLab