package net.floodlightcontroller.staticflowentry;

import java.io.IOException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.Comparator;
import java.util.Iterator;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;

import net.floodlightcontroller.core.FloodlightContext;
import net.floodlightcontroller.core.IFloodlightProviderService;
import net.floodlightcontroller.core.IFloodlightProviderService.Role;
import net.floodlightcontroller.core.IHAListener;
import net.floodlightcontroller.core.IOFMessageListener;
import net.floodlightcontroller.core.IOFSwitch;
import net.floodlightcontroller.core.IOFSwitchListener;
import net.floodlightcontroller.core.annotations.LogMessageCategory;
import net.floodlightcontroller.core.annotations.LogMessageDoc;
import net.floodlightcontroller.core.module.FloodlightModuleContext;
import net.floodlightcontroller.core.module.FloodlightModuleException;
import net.floodlightcontroller.core.module.IFloodlightModule;
import net.floodlightcontroller.core.module.IFloodlightService;
import net.floodlightcontroller.core.util.AppCookie;
import net.floodlightcontroller.restserver.IRestApiService;
import net.floodlightcontroller.staticflowentry.web.StaticFlowEntryWebRoutable;
import net.floodlightcontroller.staticflowentry.IStaticFlowEntryPusherService;
import net.floodlightcontroller.storage.IResultSet;
import net.floodlightcontroller.storage.IStorageSourceService;
import net.floodlightcontroller.storage.IStorageSourceListener;

import net.floodlightcontroller.storage.StorageException;
import org.openflow.protocol.OFFlowMod;
import org.openflow.protocol.OFFlowRemoved;
import org.openflow.protocol.OFMatch;
import org.openflow.protocol.OFMessage;
import org.openflow.protocol.OFType;
import org.openflow.protocol.factory.BasicFactory;
import org.openflow.util.HexString;
import org.openflow.util.U16;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

@LogMessageCategory("Static Flow Pusher")
/**
 * This module is responsible for maintaining a set of static flows on
 * switches. This is just a big 'ol dumb list of flows and something external
 * is responsible for ensuring they make sense for the network.
 */
public class StaticFlowEntryPusher 
    implements IOFSwitchListener, IFloodlightModule, IStaticFlowEntryPusherService,
        IStorageSourceListener, IOFMessageListener, IHAListener {
    protected static Logger log = LoggerFactory.getLogger(StaticFlowEntryPusher.class);
    public static final String StaticFlowName = "staticflowentry";
    
    public static final int STATIC_FLOW_APP_ID = 10;

    public static final String TABLE_NAME = "controller_staticflowtableentry";
    public static final String COLUMN_NAME = "name";
    public static final String COLUMN_SWITCH = "switch_id";
    public static final String COLUMN_ACTIVE = "active";
    public static final String COLUMN_IDLE_TIMEOUT = "idle_timeout";
    public static final String COLUMN_HARD_TIMEOUT = "hard_timeout";
    public static final String COLUMN_PRIORITY = "priority";
    public static final String COLUMN_COOKIE = "cookie";
    public static final String COLUMN_WILDCARD = "wildcards";
    public static final String COLUMN_IN_PORT = "in_port";
    public static final String COLUMN_DL_SRC = "dl_src";
    public static final String COLUMN_DL_DST = "dl_dst";
    public static final String COLUMN_DL_VLAN = "dl_vlan";
    public static final String COLUMN_DL_VLAN_PCP = "dl_vlan_pcp";
    public static final String COLUMN_DL_TYPE = "dl_type";
    public static final String COLUMN_NW_TOS = "nw_tos";
    public static final String COLUMN_NW_PROTO = "nw_proto";
    public static final String COLUMN_NW_SRC = "nw_src"; // includes CIDR-style
                                                         // netmask, e.g.
                                                         // "128.8.128.0/24"
    public static final String COLUMN_NW_DST = "nw_dst";
    public static final String COLUMN_TP_DST = "tp_dst";
    public static final String COLUMN_TP_SRC = "tp_src";
    public static final String COLUMN_ACTIONS = "actions";
    public static String ColumnNames[] = { COLUMN_NAME, COLUMN_SWITCH,
            COLUMN_ACTIVE, COLUMN_IDLE_TIMEOUT, COLUMN_HARD_TIMEOUT,
            COLUMN_PRIORITY, COLUMN_COOKIE, COLUMN_WILDCARD, COLUMN_IN_PORT,
            COLUMN_DL_SRC, COLUMN_DL_DST, COLUMN_DL_VLAN, COLUMN_DL_VLAN_PCP,
            COLUMN_DL_TYPE, COLUMN_NW_TOS, COLUMN_NW_PROTO, COLUMN_NW_SRC,
            COLUMN_NW_DST, COLUMN_TP_DST, COLUMN_TP_SRC, COLUMN_ACTIONS };
 

    protected IFloodlightProviderService floodlightProvider;
    protected IStorageSourceService storageSource;
    protected IRestApiService restApi;

    // Map<DPID, Map<Name, FlowMod>> ; FlowMod can be null to indicate non-active
    protected Map<String, Map<String, OFFlowMod>> entriesFromStorage;
    // Entry Name -> DPID of Switch it's on
    protected Map<String, String> entry2dpid;

    private BasicFactory ofMessageFactory;

    // Class to sort FlowMod's by priority, from lowest to highest
    class FlowModSorter implements Comparator<String> {
        private String dpid;
        public FlowModSorter(String dpid) {
            this.dpid = dpid;
        }
        @Override
        public int compare(String o1, String o2) {
            OFFlowMod f1 = entriesFromStorage.get(dpid).get(o1);
            OFFlowMod f2 = entriesFromStorage.get(dpid).get(o2);
            if (f1 == null || f2 == null) // sort active=false flows by key
                return o1.compareTo(o2);
            return U16.f(f1.getPriority()) - U16.f(f2.getPriority());
        }
    };

    /**
     * used for debugging and unittests
     * @return the number of static flow entries as cached from storage
     */
    public int countEntries() {
        int size = 0;
        if (entriesFromStorage == null)
            return 0;
        for (String ofswitch : entriesFromStorage.keySet())
            size += entriesFromStorage.get(ofswitch).size();
        return size;
    }

    public IFloodlightProviderService getFloodlightProvider() {
        return floodlightProvider;
    }

    public void setFloodlightProvider(IFloodlightProviderService floodlightProvider) {
        this.floodlightProvider = floodlightProvider;
    }

    public void setStorageSource(IStorageSourceService storageSource) {
        this.storageSource = storageSource;
    }

    /**
     * Reads from our entriesFromStorage for the specified switch and
     * sends the FlowMods down to the controller in <b>sorted</b> order.
     *
     * Sorted is important to maintain correctness of the switch:
     * if a packet would match both a lower and a higher priority
     * rule, then we want it to match the higher priority or nothing,
     * but never just the lower priority one.  Inserting from high to
     * low priority fixes this.
     *
     * TODO consider adding a "block all" flow mod and then removing it
     * while starting up.
     *
     * @param sw The switch to send entries to
     */
    protected void sendEntriesToSwitch(IOFSwitch sw) {
        String dpid = sw.getStringId();

        if ((entriesFromStorage != null) && (entriesFromStorage.containsKey(dpid))) {
            Map<String, OFFlowMod> entries = entriesFromStorage.get(dpid);
            List<String> sortedList = new ArrayList<String>(entries.keySet());
            // weird that Collections.sort() returns void
            Collections.sort( sortedList, new FlowModSorter(dpid));
            for (String entryName : sortedList) {
                OFFlowMod flowMod = entries.get(entryName);
                if (flowMod != null) {
                    if (log.isDebugEnabled()) {
                        log.debug("Pushing static entry {} for {}", dpid, entryName);
                    }
                    writeFlowModToSwitch(sw, flowMod);
                }
            }
        }
    }
    
    /**
     * Used only for bundle-local indexing
     * 
     * @param map
     * @return
     */

    protected Map<String, String> computeEntry2DpidMap(
                Map<String, Map<String, OFFlowMod>> map) {
        Map<String, String> ret = new HashMap<String, String>();
        for(String dpid : map.keySet()) {
            for( String entry: map.get(dpid).keySet())
                ret.put(entry, dpid);
        }
        return ret;
    }
    
    /**
     * Read entries from storageSource, and store them in a hash
     * 
     * @return
     */
    @LogMessageDoc(level="ERROR",
            message="failed to access storage: {reason}",
            explanation="Could not retrieve static flows from the system " +
            		"database",
            recommendation=LogMessageDoc.CHECK_CONTROLLER)
    private Map<String, Map<String, OFFlowMod>> readEntriesFromStorage() {
        Map<String, Map<String, OFFlowMod>> entries = new ConcurrentHashMap<String, Map<String, OFFlowMod>>();
        try {
            Map<String, Object> row;
            // null1=no predicate, null2=no ordering
            IResultSet resultSet = storageSource.executeQuery(TABLE_NAME,
                    ColumnNames, null, null);
            for (Iterator<IResultSet> it = resultSet.iterator(); it.hasNext();) {
                row = it.next().getRow();
                parseRow(row, entries);
            }
        } catch (StorageException e) {
            log.error("failed to access storage: {}", e.getMessage());
            // if the table doesn't exist, then wait to populate later via
            // setStorageSource()
        }
        return entries;
    }

    /**
     * Take a single row, turn it into a flowMod, and add it to the
     * entries{$dpid}.{$entryName}=FlowMod 
     * 
     * IF an entry is in active, mark it with FlowMod = null
     * 
     * @param row
     * @param entries
     */

    void parseRow(Map<String, Object> row,
            Map<String, Map<String, OFFlowMod>> entries) {
        String switchName = null;
        String entryName = null;

        StringBuffer matchString = new StringBuffer();
        if (ofMessageFactory == null) // lazy init
            ofMessageFactory = new BasicFactory();

        OFFlowMod flowMod = (OFFlowMod) ofMessageFactory
                .getMessage(OFType.FLOW_MOD);

        if (!row.containsKey(COLUMN_SWITCH) || !row.containsKey(COLUMN_NAME)) {
            log.debug(
                    "skipping entry with missing required 'switch' or 'name' entry: {}",
                    row);
            return;
        }
        // most error checking done with ClassCastException
        try {
            // first, snag the required entries, for debugging info
            switchName = (String) row.get(COLUMN_SWITCH);
            entryName = (String) row.get(COLUMN_NAME);
            if (!entries.containsKey(switchName))
                entries.put(switchName, new HashMap<String, OFFlowMod>());
            StaticFlowEntries.initDefaultFlowMod(flowMod, entryName);
            
            for (String key : row.keySet()) {
                if (row.get(key) == null)
                    continue;
                if ( key.equals(COLUMN_SWITCH) || key.equals(COLUMN_NAME)
                        || key.equals("id"))
                    continue; // already handled
                // explicitly ignore timeouts and wildcards
                if ( key.equals(COLUMN_HARD_TIMEOUT) || key.equals(COLUMN_IDLE_TIMEOUT) ||
                        key.equals(COLUMN_WILDCARD))
                    continue;
                if ( key.equals(COLUMN_ACTIVE)) {
                    if  (! Boolean.valueOf((String) row.get(COLUMN_ACTIVE))) {
                        log.debug("skipping inactive entry {} for switch {}",
                                entryName, switchName);
                        entries.get(switchName).put(entryName, null);  // mark this an inactive
                        return;
                    }
                } else if ( key.equals(COLUMN_ACTIONS)){
                    StaticFlowEntries.parseActionString(flowMod, (String) row.get(COLUMN_ACTIONS), log);
                } else if ( key.equals(COLUMN_COOKIE)) {
                    flowMod.setCookie(
                            StaticFlowEntries.computeEntryCookie(flowMod, 
                                    Integer.valueOf((String) row.get(COLUMN_COOKIE)), 
                                    entryName)
                        );
                } else if ( key.equals(COLUMN_PRIORITY)) {
                    flowMod.setPriority(U16.t(Integer.valueOf((String) row.get(COLUMN_PRIORITY))));
                } else { // the rest of the keys are for OFMatch().fromString()
                    if (matchString.length() > 0)
                        matchString.append(",");
                    matchString.append(key + "=" + row.get(key).toString());
                }
            }
        } catch (ClassCastException e) {
            if (entryName != null && switchName != null)
                log.debug(
                        "skipping entry {} on switch {} with bad data : "
                                + e.getMessage(), entryName, switchName);
            else
                log.debug("skipping entry with bad data: {} :: {} ",
                        e.getMessage(), e.getStackTrace());
        }

        OFMatch ofMatch = new OFMatch();
        String match = matchString.toString();
        try {
            ofMatch.fromString(match);
        } catch (IllegalArgumentException e) {
            log.debug(
                    "ignoring flow entry {} on switch {} with illegal OFMatch() key: "
                            + match, entryName, switchName);
            return;
        }
        flowMod.setMatch(ofMatch);

        entries.get(switchName).put(entryName, flowMod);
    }
    
    @Override
    public void addedSwitch(IOFSwitch sw) {
        log.debug("addedSwitch {}; processing its static entries", sw);
        sendEntriesToSwitch(sw);
    }

    @Override
    public void removedSwitch(IOFSwitch sw) {
        log.debug("removedSwitch {}", sw);
        // do NOT delete from our internal state; we're tracking the rules,
        // not the switches
    }
    
    @Override
    public void switchPortChanged(Long switchId) {
        // no-op
    }

    /**
     * This handles both rowInsert() and rowUpdate()
     */
    
    @Override
    public void rowsModified(String tableName, Set<Object> rowKeys) {
        log.debug("Modifying Table {}", tableName);

        HashMap<String, Map<String, OFFlowMod>> entriesToAdd = 
            new HashMap<String, Map<String, OFFlowMod>>();
        // build up list of what was added 
        for(Object key: rowKeys) {
            IResultSet resultSet = storageSource.getRow(tableName, key);
            for (Iterator<IResultSet> it = resultSet.iterator(); it.hasNext();) {
                Map<String, Object> row = it.next().getRow();
                parseRow(row, entriesToAdd);
            }            
        }
        // batch updates by switch and blast them out
        for (String dpid : entriesToAdd.keySet()) {
            if (!entriesFromStorage.containsKey(dpid))
                entriesFromStorage.put(dpid, new HashMap<String, OFFlowMod>());
            List<OFMessage> outQueue = new ArrayList<OFMessage>();
            for(String entry : entriesToAdd.get(dpid).keySet()) {
                OFFlowMod newFlowMod = entriesToAdd.get(dpid).get(entry);
                OFFlowMod oldFlowMod = entriesFromStorage.get(dpid).get(entry);
                if (oldFlowMod != null) {  // remove any pre-existing rule
                    oldFlowMod.setCommand(OFFlowMod.OFPFC_DELETE_STRICT);
                    outQueue.add(oldFlowMod);
                }
                if (newFlowMod != null) {
                    entriesFromStorage.get(dpid).put(entry, newFlowMod);
                    outQueue.add(newFlowMod);
                    entry2dpid.put(entry, dpid);
                } else {
                    entriesFromStorage.get(dpid).remove(entry);
                    entry2dpid.remove(entry);
                }
            }
            
            writeOFMessagesToSwitch(HexString.toLong(dpid), outQueue);
        }
    }

    @Override
    public void rowsDeleted(String tableName, Set<Object> rowKeys) {
        if (log.isDebugEnabled()) {
            log.debug("deleting from Table {}", tableName);
        }
        
        for(Object obj : rowKeys) {
            if (!(obj instanceof String)) {
                log.debug("tried to delete non-string key {}; ignoring", obj);
                continue;
            }
            deleteStaticFlowEntry((String) obj);
        }
    }
    
    @LogMessageDoc(level="ERROR",
            message="inconsistent internal state: no switch has rule {rule}",
            explanation="Inconsistent internat state discovered while " +
            		"deleting a static flow rule",
            recommendation=LogMessageDoc.REPORT_CONTROLLER_BUG)
    private boolean deleteStaticFlowEntry(String entryName) {
        String dpid = entry2dpid.get(entryName);
        if (log.isDebugEnabled()) {
            log.debug("Deleting flow {} for switch {}", entryName, dpid);
        }
        if (dpid == null) {
            log.error("inconsistent internal state: no switch has rule {}",
                    entryName);
            return false;
        }
        
        // send flow_mod delete
        OFFlowMod flowMod = entriesFromStorage.get(dpid).get(entryName);
        flowMod.setCommand(OFFlowMod.OFPFC_DELETE_STRICT);

        if (entriesFromStorage.containsKey(dpid) && 
                entriesFromStorage.get(dpid).containsKey(entryName)) {
            entriesFromStorage.get(dpid).remove(entryName);
        } else { 
            log.debug("Tried to delete non-existent entry {} for switch {}", 
                    entryName, dpid);
            return false;
        }
        
        writeFlowModToSwitch(HexString.toLong(dpid), flowMod);
        return true;
    }
    
    /**
     * Writes a list of OFMessages to a switch
     * @param dpid The datapath ID of the switch to write to
     * @param messages The list of OFMessages to write.
     */
    @LogMessageDoc(level="ERROR",
            message="Tried to write to switch {switch} but got {error}",
            explanation="An I/O error occured while trying to write a " +
            		"static flow to a switch",
            recommendation=LogMessageDoc.CHECK_SWITCH)
    private void writeOFMessagesToSwitch(long dpid, List<OFMessage> messages) {
        IOFSwitch ofswitch = floodlightProvider.getSwitches().get(dpid);
        if (ofswitch != null) {  // is the switch connected
            try {
                if (log.isDebugEnabled()) {
                    log.debug("Sending {} new entries to {}", messages.size(), dpid);
                }
                ofswitch.write(messages, null);
                ofswitch.flush();
            } catch (IOException e) {
                log.error("Tried to write to switch {} but got {}", dpid, e.getMessage());
            }
        }
    }
    
    /**
     * Writes an OFFlowMod to a switch. It checks to make sure the switch
     * exists before it sends
     * @param dpid The data  to write the flow mod to
     * @param flowMod The OFFlowMod to write
     */
    private void writeFlowModToSwitch(long dpid, OFFlowMod flowMod) {
        Map<Long,IOFSwitch> switches = floodlightProvider.getSwitches();
        IOFSwitch ofSwitch = switches.get(dpid);
        if (ofSwitch == null) {
            if (log.isDebugEnabled()) {
                log.debug("Not deleting key {} :: switch {} not connected", 
                          dpid);
            }
            return;
        }
        writeFlowModToSwitch(ofSwitch, flowMod);
    }
    
    /**
     * Writes an OFFlowMod to a switch
     * @param sw The IOFSwitch to write to
     * @param flowMod The OFFlowMod to write
     */
    @LogMessageDoc(level="ERROR",
            message="Tried to write OFFlowMod to {switch} but got {error}",
            explanation="An I/O error occured while trying to write a " +
                    "static flow to a switch",
            recommendation=LogMessageDoc.CHECK_SWITCH)
    private void writeFlowModToSwitch(IOFSwitch sw, OFFlowMod flowMod) {
        try {
            sw.write(flowMod, null);
            sw.flush();
        } catch (IOException e) {
            log.error("Tried to write OFFlowMod to {} but failed: {}", 
                    HexString.toHexString(sw.getId()), e.getMessage());
        }
    }

    @Override
    public String getName() {
        return StaticFlowName;
    }
    
    @Override
    @LogMessageDoc(level="ERROR",
        message="Got a FlowRemove message for a infinite " +
                "timeout flow: {flow} from switch {switch}",
        explanation="Flows with infinite timeouts should not expire. " +
        		"The switch has expired the flow anyway.",
        recommendation=LogMessageDoc.REPORT_SWITCH_BUG)
    public Command receive(IOFSwitch sw, OFMessage msg, FloodlightContext cntx) {
        switch (msg.getType()) {
        case FLOW_REMOVED:
            break;
        default:
            return Command.CONTINUE;
        }
        OFFlowRemoved flowRemoved = (OFFlowRemoved) msg;
        long cookie = flowRemoved.getCookie();
        /**
         * This is just to sanity check our assumption that static flows 
         * never expire.
         */
        if( AppCookie.extractApp(cookie) == STATIC_FLOW_APP_ID) {
            if (flowRemoved.getReason() != 
                    OFFlowRemoved.OFFlowRemovedReason.OFPRR_DELETE)
                log.error("Got a FlowRemove message for a infinite " +
                		  "timeout flow: {} from switch {}", msg, sw);
            return Command.STOP;    // only for us
        } else
            return Command.CONTINUE;
    }

    @Override
    public boolean isCallbackOrderingPrereq(OFType type, String name) {
        return false;  // no dependency for non-packet in
    }

    @Override
    public boolean isCallbackOrderingPostreq(OFType type, String name) {
        return false;  // no dependency for non-packet in
    }

    // IFloodlightModule
    
    @Override
    public Collection<Class<? extends IFloodlightService>> getModuleServices() {
        Collection<Class<? extends IFloodlightService>> l = 
                new ArrayList<Class<? extends IFloodlightService>>();
        l.add(IStaticFlowEntryPusherService.class);
        return l;
    }

    @Override
    public Map<Class<? extends IFloodlightService>, IFloodlightService> getServiceImpls() {
        Map<Class<? extends IFloodlightService>,
            IFloodlightService> m = 
                new HashMap<Class<? extends IFloodlightService>,
                    IFloodlightService>();
        m.put(IStaticFlowEntryPusherService.class, this);
        return m;
    }

    @Override
    public Collection<Class<? extends IFloodlightService>> getModuleDependencies() {
        Collection<Class<? extends IFloodlightService>> l = 
                new ArrayList<Class<? extends IFloodlightService>>();
        l.add(IFloodlightProviderService.class);
        l.add(IStorageSourceService.class);
        l.add(IRestApiService.class);
        return l;
    }

    @Override
    public void init(FloodlightModuleContext context)
            throws FloodlightModuleException {
        floodlightProvider =
            context.getServiceImpl(IFloodlightProviderService.class);
        storageSource =
            context.getServiceImpl(IStorageSourceService.class);
        restApi =
            context.getServiceImpl(IRestApiService.class);
    }

    @Override
    public void startUp(FloodlightModuleContext context) {        
        floodlightProvider.addOFMessageListener(OFType.FLOW_REMOVED, this);
        floodlightProvider.addOFSwitchListener(this);
        floodlightProvider.addHAListener(this);
        
        // assumes no switches connected at startup()
        storageSource.createTable(TABLE_NAME, null);
        storageSource.setTablePrimaryKeyName(TABLE_NAME, COLUMN_NAME);
        storageSource.addListener(TABLE_NAME, this);
        entriesFromStorage = readEntriesFromStorage(); 
        entry2dpid = computeEntry2DpidMap(entriesFromStorage);
        restApi.addRestletRoutable(new StaticFlowEntryWebRoutable());
    }

    // IStaticFlowEntryPusherService methods
    
    @Override
    public void addFlow(String name, OFFlowMod fm, String swDpid) {
        Map<String, Object> fmMap = StaticFlowEntries.flowModToStorageEntry(fm, swDpid, name);
        entry2dpid.put(name, swDpid);
        Map<String, OFFlowMod> switchEntries = entriesFromStorage.get(swDpid);
        if (switchEntries == null) {
            switchEntries = new HashMap<String, OFFlowMod>();
            entriesFromStorage.put(swDpid, switchEntries);
        }
        switchEntries.put(name, fm);
        storageSource.insertRowAsync(TABLE_NAME, fmMap);
    }

    @Override
    public void deleteFlow(String name) {
        storageSource.deleteRowAsync(TABLE_NAME, name);
        // TODO - What if there is a delay in storage?
    }
    
    @Override
    public void deleteAllFlows() {
        for (String entry : entry2dpid.keySet()) {
            deleteFlow(entry);
        }
    }
    
    @Override
    public void deleteFlowsForSwitch(long dpid) {
        String sDpid = HexString.toHexString(dpid);
        
        for (Entry<String, String> e : entry2dpid.entrySet()) {
            if (e.getValue().equals(sDpid))
                deleteFlow(e.getKey());
        }
    }
    
    @Override
    public Map<String, Map<String, OFFlowMod>> getFlows() {
        return entriesFromStorage;
    }
    
    @Override
    public Map<String, OFFlowMod> getFlows(String dpid) {
        return entriesFromStorage.get(dpid);
    }

    
    // IHAListener
    
    @Override
    public void roleChanged(Role oldRole, Role newRole) {
        switch(newRole) {
            case MASTER:
                if (oldRole == Role.SLAVE) {
                    log.debug("Re-reading static flows from storage due " +
                            "to HA change from SLAVE->MASTER");
                    entriesFromStorage = readEntriesFromStorage(); 
                    entry2dpid = computeEntry2DpidMap(entriesFromStorage);
                }
                break;
            case SLAVE:
                log.debug("Clearing in-memory flows due to " +
                        "HA change to SLAVE");
                entry2dpid.clear();
                entriesFromStorage.clear();
                break;
            default:
            	break;
        }
    }
    
    @Override
    public void controllerNodeIPsChanged(
            Map<String, String> curControllerNodeIPs,
            Map<String, String> addedControllerNodeIPs,
            Map<String, String> removedControllerNodeIPs) {
        // ignore
    }
     
}
