Java tutorial
/** *Copyright 2012, InCNTRE. This file is licensed under Apache 2.0 * **/ package edu.iu.incntre.flowscalestatcollector; import java.util.Calendar; import java.util.List; import org.openflow.protocol.OFPhysicalPort; import org.openflow.protocol.statistics.OFStatistics; import org.openflow.util.HexString; import java.util.HashMap; import java.util.concurrent.ExecutionException; import java.util.concurrent.TimeoutException; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import edu.iu.incntre.flowscale.FlowscaleController; import edu.iu.incntre.flowscale.SwitchDevice; import org.json.simple.JSONArray; import org.json.simple.JSONObject; import org.json.simple.JSONValue; import edu.iu.incntre.flowscale.exception.NoSwitchException; import edu.iu.incntre.flowscale.util.JSONConverter; import java.io.IOException; import java.sql.*; /** * The class responsible for polling all statistics from the switch and storing * them in a database * * * @author Ali Khalfan (akhalfan@indiana.edu) * * **/ public class StatCollector { private boolean isQuery; private long intervalTime; private FlowscaleController flowscaleController; protected static Logger logger = LoggerFactory.getLogger(StatCollector.class); private String datapathIdStrings; private Connection conn; private String databaseDriver; private String databaseClass; protected Thread statThread; private HashMap<Long, HashMap<Long, Long>> tempPortStatTransmittedHashMap = new HashMap<Long, HashMap<Long, Long>>(); private HashMap<Long, HashMap<Long, Long>> tempPortStatReceivedHashMap = new HashMap<Long, HashMap<Long, Long>>(); private HashMap<Long, HashMap<String, Long>> tempFlowStatHashMap = new HashMap<Long, HashMap<String, Long>>(); private String dbUsername; private String dbPassword; private Calendar calendar; public void setIsQuery(boolean isQuery) { this.isQuery = isQuery; } public void setIntervalTime(long intervalTime) { this.intervalTime = intervalTime; } public void setFlowscaleController(FlowscaleController flowscaleController) { this.flowscaleController = flowscaleController; } public void setDatapathIdStrings(String datapathIdStrings) { this.datapathIdStrings = datapathIdStrings; } public void setDatabaseDriver(String databaseDriver) { this.databaseDriver = databaseDriver; } public void setDatabaseClass(String databaseClass) { this.databaseClass = databaseClass; } public void setDbUsername(String dbUsername) { this.dbUsername = dbUsername; } public void setDbPassword(String dbPassword) { this.dbPassword = dbPassword; } public void killThread() { this.statThread = null; } public void startUp() { logger.trace("Startup of StatCollector"); try { if (isQuery) { // initiate sqlite database try { Class.forName(databaseClass); conn = DriverManager.getConnection(databaseDriver, dbUsername, dbPassword); } catch (ClassNotFoundException e2) { logger.error("{}", e2); } catch (SQLException e1) { // TODO Auto-generated catch block logger.error("{}", e1); } // end initiate database // start up thread statThread = new Thread(new Runnable() { @Override public void run() { try { logger.trace("Starting Thread .."); logger.trace("Getting flows from switch every {} seconds", intervalTime); List<OFStatistics> portStats; List<OFStatistics> flowStats; List<OFPhysicalPort> portStatus; SwitchDevice swd = null; String[] datapathIdStringElements = datapathIdStrings.split(","); try { while (statThread != null) { calendar = Calendar.getInstance(); logger.trace("getting flows from switches"); //check if conn is null if it is, reset connection if (conn == null) { conn = DriverManager.getConnection(databaseDriver, dbUsername, dbPassword); } for (String datapathIdString : datapathIdStringElements) { try { swd = flowscaleController.getSwitchDevices() .get(HexString.toLong(datapathIdString)); if (swd == null) { logger.info("switch {} does not exist, is it connected?", datapathIdString); continue; } logger.info("Getting flows from switch {} with ID {}", swd.getSwitchName(), datapathIdString); try { portStats = flowscaleController .getSwitchStatisticsFromInterface(datapathIdString, "port"); flowStats = flowscaleController .getSwitchStatisticsFromInterface(datapathIdString, "flow"); portStatus = swd.getPortStates(); if (flowStats != null && portStats != null) { String flowStatsJSON = JSONConverter.toStat(flowStats, "flow") .toJSONString(); String portStatsJSON = JSONConverter.toStat(portStats, "port") .toJSONString(); String portStatusJSON = JSONConverter.toPortStatus(portStatus) .toJSONString(); // initialize or set hashmaps HashMap<Long, Long> tempPortStatTransmitted; HashMap<Long, Long> tempPortStatReceived; HashMap<String, Long> tempFlowStat; long datapathId = HexString.toLong(datapathIdString); if (tempPortStatTransmittedHashMap.get(datapathId) == null) { tempPortStatTransmitted = new HashMap<Long, Long>(); tempPortStatTransmittedHashMap.put(datapathId, tempPortStatTransmitted); } else { tempPortStatTransmitted = tempPortStatTransmittedHashMap .get(datapathId); } if (tempPortStatReceivedHashMap.get(datapathId) == null) { tempPortStatReceived = new HashMap<Long, Long>(); tempPortStatReceivedHashMap.put(datapathId, tempPortStatReceived); } else { tempPortStatReceived = tempPortStatReceivedHashMap .get(datapathId); } if (tempFlowStatHashMap.get(datapathId) == null) { tempFlowStat = new HashMap<String, Long>(); tempFlowStatHashMap.put(datapathId, tempFlowStat); } else { tempFlowStat = tempFlowStatHashMap.get(datapathId); } storeSwitchDetails(HexString.toLong(datapathIdString), portStatsJSON, flowStatsJSON, portStatusJSON, tempPortStatTransmitted, tempPortStatReceived, tempFlowStat); } else { logger.error( "Switch {} returned a null result possibility because the switch is not connected to the controller", datapathIdString); } } catch (NoSwitchException e1) { // TODO Auto-generated catch block logger.error("Switch {} with ID {} is not connected aborting", swd.getSwitchName(), datapathIdString); } catch (IOException e1) { logger.error("IOException {}", e1); } catch (InterruptedException e1) { logger.error("Thread Interrupted {}", e1); killThread(); } catch (ExecutionException e1) { logger.error("Execution Exception {}", e1); } catch (TimeoutException e1) { logger.error("Switch Timeout Exception {}", e1); killThread(); } } catch (Exception e) { logger.error("unchecked exception here {}", e); killThread(); shutDown(); Thread.yield(); } } try { Thread.sleep(intervalTime); } catch (InterruptedException e) { logger.error("{}", e); break; } } } catch (Exception e) { logger.error("exception in while {}", e); shutDown(); } try { conn.close(); } catch (SQLException e) { // TODO Auto-generated catch block logger.error("{}", e); } } catch (Exception generalException) { logger.error("General Exception throws {} ", generalException); } } /** * insert details into database, 3 tables will be populated: flow_stats, port_stats ,and port_status * * @param datapathId * @param portStats * @param flowStats * @param portStatus * @param tempPortStatTransmitted * @param tempPortStatReceived * @param tempFlowStat */ private void storeSwitchDetails(long datapathId, String portStats, String flowStats, String portStatus, HashMap<Long, Long> tempPortStatTransmitted, HashMap<Long, Long> tempPortStatReceived, HashMap<String, Long> tempFlowStat) { Object obj = JSONValue.parse(portStats); JSONArray jsonArray = (JSONArray) obj; for (int i = 0; i < jsonArray.size(); i++) { JSONObject jsonObject = (JSONObject) jsonArray.get(i); long transmittedPackets = (Long) jsonObject.get("transmit_packets"); long receivedPackets = (Long) jsonObject.get("receive_packets"); long portId = (Long) jsonObject.get("port_id"); // logger.info("the port is {}", portId); // logger.info("{} packets transmitted and {} packets received", // receivedPackets,transmittedPackets); PreparedStatement prep = null; try { prep = null; if (conn != null) { prep = conn.prepareStatement("insert into port_stats values (?,?,?,?,?);"); } else { logger.error("no connection object instantiated aborting .. "); return; } prep.setLong(1, datapathId); prep.setLong(2, calendar.getTimeInMillis()); if (tempPortStatTransmitted.get(portId) != null) { long currentTransmittedPackets = transmittedPackets - tempPortStatTransmitted.get(portId); if (currentTransmittedPackets < 0) { prep.setLong(5, transmittedPackets); } else { prep.setLong(5, currentTransmittedPackets); } } else { prep.setLong(5, transmittedPackets); } tempPortStatTransmitted.put(portId, transmittedPackets); // take care of port received if (tempPortStatReceived.get(portId) != null) { long currentReceivedPackets = receivedPackets - tempPortStatReceived.get(portId); if (currentReceivedPackets < 0) { prep.setLong(4, receivedPackets); } else { prep.setLong(4, currentReceivedPackets); } } else { prep.setLong(4, receivedPackets); } tempPortStatReceived.put(portId, receivedPackets); prep.setLong(3, portId); prep.addBatch(); conn.setAutoCommit(false); prep.executeBatch(); conn.setAutoCommit(true); } catch (SQLRecoverableException sqlRecoverableException) { logger.error("{}", sqlRecoverableException); //exit function since there is a timeout return; } catch (SQLException e) { logger.error("{}", e); } finally { if (prep != null) { try { prep.close(); } catch (SQLException e) { // TODO Auto-generated catch block logger.error("{}", e); } } } } Object flowJSONobj = JSONValue.parse(flowStats); JSONArray flowJsonArray = (JSONArray) flowJSONobj; for (int i = 0; i < flowJsonArray.size(); i++) { JSONObject jsonObject = (JSONObject) flowJsonArray.get(i); long packets = (Long) jsonObject.get("packet_count"); String matchString = (String) jsonObject.get("match"); String action = (String) jsonObject.get("actions"); long priority = (Long) jsonObject.get("priority"); PreparedStatement prep = null; try { prep = conn.prepareStatement("insert into flow_stats values (?,?,?,?,?,?);"); String insertString = datapathId + "," + calendar.getTimeInMillis() + "," + matchString + "," + action; logger.debug("flow_stat values to insert are {}", insertString); prep.setLong(1, datapathId); prep.setLong(2, calendar.getTimeInMillis()); if (tempFlowStat.get(matchString) != null) { long packetsReceived = packets - tempFlowStat.get(matchString); if (packetsReceived < 0) { prep.setLong(5, packets); } else { prep.setLong(5, packetsReceived); } } else { prep.setLong(5, packets); } tempFlowStat.put(matchString, packets); prep.setString(3, matchString); prep.setString(4, action); prep.setShort(6, (short) priority); prep.addBatch(); conn.setAutoCommit(false); prep.executeBatch(); conn.setAutoCommit(true); } catch (SQLException e) { // TODO Auto-generated catch block logger.error("error when insert flow {} in switch {}", matchString, datapathId); logger.error("{}", e); } finally { if (prep != null) { try { prep.close(); } catch (SQLException e) { // TODO Auto-generated catch block logger.error("{}", e); } } } } Object portStatusJSONobj = JSONValue.parse(portStatus); JSONArray portStatusJsonArray = (JSONArray) portStatusJSONobj; for (int i = 0; i < portStatusJsonArray.size(); i++) { byte portStatusValue = 0; JSONObject jsonObject = (JSONObject) portStatusJsonArray.get(i); long portId = (Long) jsonObject.get("port_id"); String portAddress = (String) jsonObject.get("port_address"); try { portStatusValue = (byte) (Integer.parseInt(jsonObject.get("state").toString()) % 2); } catch (NumberFormatException nfe) { logger.error("{}", nfe); continue; } PreparedStatement prep = null; try { prep = conn.prepareStatement("insert into port_status values (?,?,?,?,?);"); prep.setLong(1, datapathId); prep.setLong(2, calendar.getTimeInMillis()); prep.setLong(3, portId); prep.setString(4, portAddress); prep.setByte(5, portStatusValue); prep.addBatch(); conn.setAutoCommit(false); prep.executeBatch(); conn.setAutoCommit(true); } catch (SQLException e) { // TODO Auto-generated catch block logger.error("{}", e); } finally { if (prep != null) { try { prep.close(); } catch (SQLException e) { // TODO Auto-generated catch block logger.error("{}", e); } } } } } }, "Switch Stat Collector"); statThread.start(); } } catch (Exception e) { logger.error("general excecption thrown {}", e); } } public void shutDown() { statThread.interrupt(); statThread = null; this.notify(); } public String getName() { // TODO Auto-generated method stub return "statCollector"; } }