// Carnegie Mellon University
//   Information Networking Institute and
//   School of Computer Science
//
// Master Thesis: A Monitoring Tool for Overlay Network
// By: TungFai Chan and Annie Cheng
//
// File: VRTUpdateManager.java
// Path: eventbase/routing
// Description: Used by network componet to cache old copy of VRT table.
//              When network component recieved the triggered update of
//              VRT table entry from each host, VRTUpdateManager can help
//              updating the old cache entries and dump new VRT table to the DB

package eventbase.routing;

import java.util.*;
import eventbase.*;

public class VRTUpdateManager {

  private int curSize;
  private Vector tables;

  public VRTUpdateManager() {
    tables = new Vector();
  }

  private VRTUpdateTable findTable (int srcID) {
    VRTUpdateTable tbl;
    for (Enumeration e = tables.elements(); e.hasMoreElements();) {
      tbl = (VRTUpdateTable) e.nextElement();
      if (tbl.getSource() == srcID)
        return tbl;
    }
    // table not found, create new table
    tbl = new VRTUpdateTable(srcID);
    tables.add(tbl);
    return tbl;
  }

  public synchronized void updateVRTEntry (int srcID, int destHostID, int nextHop, int delay, int dead) {
      System.out.println ("UpdateVRTEntry " + srcID + " " + destHostID + " " + nextHop + " " + delay + " " + dead);
    VRTUpdateTable tbl = findTable(srcID);
    if (tbl == null)
      System.err.println("VRTUpdateManager:ERROR: VRT table not found");
    tbl.updateEntry(destHostID, nextHop, delay, dead);
  }
  
  public synchronized void addChildEntries (int srcID, int destID, int numChild, String[] childStrList, int[] childIDList) {
      //      System.out.println ("addChildEntries " + srcID + " " + destID + " " + numChild);
      VRTUpdateTable tbl = findTable(srcID);
      if (tbl == null) 
	  System.err.println("ERROR: VRTUpdateManager: VRT tablenot found");
      tbl.addChildEntries(destID, numChild, childStrList, childIDList);
  }

  public synchronized void print() {
    System.out.println (" =================== VRTUpdateManager ===============");
    System.out.println();
    VRTUpdateTable tbl;
    for (Enumeration e = tables.elements(); e.hasMoreElements();) {
      tbl = (VRTUpdateTable) e.nextElement();
      tbl.print();
    }
    System.out.println (" ===================================================");
    System.out.println();
  }

  public synchronized void dumpToDB(EventBaseAgent dbAgent, int srcID, double time) {
    VRTUpdateTable tbl = findTable(srcID);
    if (tbl == null || tbl.size() == 0)
      System.err.println("VRTUpdateManager:ERROR: VRT table not found");
    //    System.out.println("$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$");
    //System.out.println("$$$$$$$ dumpToDB (source) " + srcID + " (time) " + time );
    tbl.dumpToDB(dbAgent, time);
  }

}

class VRTUpdateTable {

  int srcID;
  private Vector table;

  VRTUpdateTable(int srcid) {
    this.srcID = srcid;
    table = new Vector();
  }

  int getSource() {
    return srcID;
  }

  int size() {
    return table.size();
  }

  void dumpToDB(EventBaseAgent dbAgent, double time) {
    VirtualRoutingTableEntry entry;
    for (Enumeration e = table.elements(); e.hasMoreElements();) {
      entry = (VirtualRoutingTableEntry) e.nextElement();
      //      entry.print();
      dbAgent.insertVRTEntry(srcID, time, entry.getDestID(), entry.getNextHopID(),
                             entry.getCost(), entry.getDeadFlg(), entry.getNumChild(),
			     entry.getChildIDList());
    }

  }

  void updateEntry(int destID, int nextHop, int delay, int dead) {
    VirtualRoutingTableEntry entry = findEntry (destID);
    if (entry == null) { // insert
      entry = new VirtualRoutingTableEntry(-1, destID, nextHop, delay, dead, -1);
      table.add(entry);
    } else { // update
      entry.update(destID, nextHop, delay, dead);
    }
  }

  void addChildEntries (int destID, int numChild, String[] childStrList, int[] childIDList) {
      //    System.out.println("table: addChildEntries " + destID + " " + numChild);
    VirtualRoutingTableEntry entry = findEntry (destID);
    if (entry == null) { // insert
      System.err.println("ERROR: VRTUpdateManager: addChildEntries: entry not found");
    } else { // update
      entry.setNumChildren(numChild);
      for (int i = 0; i < entry.getNumChild(); i++)
	  entry.addChild(childStrList[i], childIDList[i]);
    }
  }

  VirtualRoutingTableEntry findEntry (int destID) {
    VirtualRoutingTableEntry entry;
    for (Enumeration e = table.elements(); e.hasMoreElements();) {
      entry = (VirtualRoutingTableEntry) e.nextElement();
      if (entry.getDestID() == destID)
        return entry;
    }
    // entry not found
    return null;
  }

  public void print() {
    VirtualRoutingTableEntry entry;
    System.out.println ("Source ID: " + srcID);
    for (Enumeration e = table.elements(); e.hasMoreElements();) {
      entry = (VirtualRoutingTableEntry) e.nextElement();
      entry.print();
    }
  }
}
