/** * @copyright 2013 Computer Science Department, Recursive InterNetworking Architecture (RINA) laboratory, Boston University. * All rights reserved. Permission to use, copy, modify, and distribute this software and its documentation * for any purpose and without fee is hereby granted, provided that the above copyright notice appear in all * copies and that both the copyright notice and this permission notice appear in supporting documentation. * The RINA laboratory of the Computer Science Department at Boston University makes no * representations about the suitability of this software for any purpose. */ package rina.rib.impl; import java.util.LinkedHashMap; import java.util.LinkedList; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import rina.rib.api.RIBAPI; import rina.object.internal.*; /** * The OIB/RIB Daemon is a key element for the DIF or DAF. For DAFs * (Distributed Application Facilities), this is the Object Information Base (OIB) * Daemon, for DIFs (Distributed IPC Facilities), this is the Resource Information * Base (RIB) Daemon. The members of a DIF/DAF need to share information * relevant to their collaboration. Different aspects of the DAF/DIF will want * different information that will need to be updated with different frequency or * upon the occurrence of some event. The OIB/RIB Daemon provides this service * and optimizes the operation by combining requests where possible. * * @author Yuefeng Wang. Computer Science Department, Boston University * @version 1.0 * */ public class RIBImpl implements RIBAPI { private Log log = LogFactory.getLog(RIBImpl.class); private LinkedHashMap<String, Object> attributeList = null; /** * the members of the DAF/DIF from/to which attributes are exchanged. * ApName + ApInstance is the key */ private LinkedList<String> memberList = null; private LinkedHashMap<Integer,Member> addrToMember = null; private LinkedList<Member> memberEntryList = null; //contains the details private LinkedHashMap<Integer, String > addrToName = null; //ApName + ApInstance is the key private LinkedHashMap<String, Integer > nameToAddr = null; //the following is used to calculate the direct neighbor for new IPC member based on their underlying DIF private LinkedHashMap<String, LinkedList<Integer>> underlyingDIFsMembers = null; //an ipc may have multiple underlying DIF, so here the key is LinkedList<String> private LinkedHashMap<Integer,LinkedList<String>> addrToUnderlyingDIFName = null; private LinkedHashMap<Integer, Neighbor> addrInfo = null; // private int addrRange = 10000; public RIBImpl() { this.attributeList = new LinkedHashMap<String, Object>(); this.memberList = new LinkedList<String>(); this.memberEntryList = new LinkedList<Member>(); this.addrToMember = new LinkedHashMap<Integer,Member>(); this.addrToName = new LinkedHashMap<Integer, String>(); this.nameToAddr = new LinkedHashMap<String,Integer>(); this.underlyingDIFsMembers = new LinkedHashMap<String, LinkedList<Integer>>(); this.addrToUnderlyingDIFName = new LinkedHashMap<Integer,LinkedList<String > >(); this.addrInfo = new LinkedHashMap<Integer, Neighbor>(); } public synchronized LinkedHashMap<String, Object> getAttributeList() { return attributeList; } public synchronized void setAttributeList(LinkedHashMap<String, Object> attributeList) { this.attributeList = attributeList; } public synchronized LinkedList<String> getMemberList() { return memberList; } public synchronized void setMemberList(LinkedList<String> memberList) { this.memberList = memberList; } public synchronized Object getAttribute(String attribute) { return this.attributeList.get(attribute); } public synchronized void removeAttribute(String attribute) { this.attributeList.remove(attribute); } public synchronized void addAttribute(String attributeName, Object attribute) { this.attributeList.put(attributeName, attribute); } public synchronized int addMember(String ipcName, String ipcInstance, LinkedList<String> underlyingDIFs) { int rinaAddr = -1; rinaAddr = this.generateRINAAddr(); this.addMember(rinaAddr, ipcName, ipcInstance, underlyingDIFs); return rinaAddr; } public synchronized void addMember(int rinaAddr, String ipcName, String ipcInstance, LinkedList<String> underlyingDIFs) { String name = ipcName + ipcInstance; if(this.nameToAddr.containsKey(name)) { this.log.debug("The IPC process(" + ipcName + "/" + ipcInstance + ")was a member before with address" + rinaAddr); this.removeMember(name);// remove the old existing info, FIXME needs to update everyone }else { this.log.debug("The IPC process(" + ipcName + "/" + ipcInstance + ")is a new member with address " + rinaAddr); } this.addrToName.put(rinaAddr, name); this.nameToAddr.put(name, rinaAddr); this.addrInfo.put(rinaAddr, new Neighbor(ipcName, ipcInstance,rinaAddr)); this.memberList.add(name); Member newMember = new Member(ipcName, ipcInstance,rinaAddr, underlyingDIFs); this.memberEntryList.add(newMember); this.addrToMember.put(rinaAddr, newMember); this.addUnderlyingDIFsInfo(rinaAddr, underlyingDIFs); } /** * Check if DIF contains the member * @param rinaAddr * @param ipcName * @param ipcInstance */ public synchronized boolean containMember(String ipcName, String ipcInstance) { String name = ipcName + ipcInstance; return this.memberList.contains(name); } public synchronized boolean containMember(String ipcName, String ipcInstance, int addr) { String name = ipcName + ipcInstance; if( this.memberList.contains(name) && this.nameToAddr.get(name) == addr ) { return true; }else { return false; } } // private int generateRINAAddr() // { // int rinaAddr = -1; // // rinaAddr = (int)( Math.random()* this.addrRange); // // while(this.addrToName.containsKey(rinaAddr)) // { // rinaAddr = (int)( Math.random()* this.addrRange); // } // // // this.log.debug("RINA Address generated is " + rinaAddr); // // this.addrToName.put(rinaAddr, null); // // return rinaAddr; // } //just for testinging purpose, delete later, and replace with the above one // static int rinaAddr = 1; // private synchronized int generateRINAAddr() // { // rinaAddr = rinaAddr + 1; // // this.log.debug("RINA Address generated is " + rinaAddr); // // this.addrToName.put(rinaAddr, null); // // return rinaAddr; // } //static int counter = 1; int counter = 1; private synchronized int generateRINAAddr() { String addressPolicy = this.getAttribute("addressPolicy").toString(); this.log.debug("addressPolicy is " + addressPolicy); int rinaAddr = -1; //POCICY HOLDER if(addressPolicy.equals("RANDOM")) { rinaAddr = (int)( Math.random()* this.addrRange); while(this.addrToName.containsKey(rinaAddr)) { rinaAddr = (int)( Math.random()* this.addrRange); } } else if(addressPolicy.equals("DEFAULT")) { int localRINAAddr = (Integer)this.getAttribute("rinaAddr"); rinaAddr = localRINAAddr * 10 + counter; counter++; this.log.debug("888888888888888888888888888888888888This IPC process's Addr is " + localRINAAddr); }else if (addressPolicy.equals("myNewAddressPolicy")) { //Implement your own policy here } this.log.debug("88888888888888888888888888888888888RINA Address generated is " + rinaAddr); this.addrToName.put(rinaAddr, null); return rinaAddr; } /** * Here name = ipcName + ipcInstance */ public synchronized void removeMember(String name) { if(this.memberList.contains(name)) { int rinaAddr = this.nameToAddr.get(name); this.memberList.remove(name); Member oldMemberEntry = this.addrToMember.get(rinaAddr); this.memberEntryList.remove(oldMemberEntry); this.addrToName.remove(rinaAddr); this.nameToAddr.remove(name); /////////////////////////////////////////////////////////////////////////////////////////////////// //the following is to clean the part used for tell new member's direct neigbor // see the def above for details LinkedList<String> allUnderlyingDIFs = this.addrToUnderlyingDIFName.get(rinaAddr); this.addrToUnderlyingDIFName.remove(rinaAddr); for(int i = 0 ;i < allUnderlyingDIFs.size(); i++) { String underlyingDIFName = allUnderlyingDIFs.get(i); this.underlyingDIFsMembers.get(underlyingDIFName).remove((Integer)rinaAddr); // System.out.println("tttttttttttttttttttthis.underlyingDIFsMembers.get(underlyingDIFName) is " + this.underlyingDIFsMembers.get(underlyingDIFName) ); } ////////////////////////////////////////////////////////////////////////////////////////////// this.addrInfo.remove(rinaAddr); }else { this.log.error(name + " does not exist in the DIF "); } } /** * This is used to add the underlying DIF info for a IPC with address rinaAddr * @param rinaAddr * @param underlyingDIFName */ private synchronized void addUnderlyingDIFInfo(int rinaAddr, String underlyingDIFName) { this.log.debug("addUnderlyingDIFInfo(rinaAddr/underlyingDIFName): " + rinaAddr + "/" + underlyingDIFName ); if(! this.addrToUnderlyingDIFName.containsKey(rinaAddr)) { this.addrToUnderlyingDIFName.put(rinaAddr, new LinkedList<String>()); } this.addrToUnderlyingDIFName.get(rinaAddr).add(underlyingDIFName); if(!this.underlyingDIFsMembers.containsKey(underlyingDIFName)) { this.underlyingDIFsMembers.put(underlyingDIFName, new LinkedList<Integer>()); } this.underlyingDIFsMembers.get(underlyingDIFName).add(rinaAddr); } public synchronized LinkedList<Neighbor> getIPCListOfUnderlyingDIFName(String underlyingDIFName) { LinkedList <Integer> addrList = this.underlyingDIFsMembers.get(underlyingDIFName); System.out.println("aaaaaaaaaaaaddrList is " + addrList); LinkedList<Neighbor> neighbors = new LinkedList<Neighbor>(); for(int i= 0; i<addrList.size();i++) { neighbors.add(this.addrInfo.get( addrList.get(i) ) ); } return neighbors; } public synchronized void addUnderlyingDIFsInfo(int rinaAddr,LinkedList<String> underlyingDIFs) { for(int i = 0;i < underlyingDIFs.size(); i++) { this.addUnderlyingDIFInfo(rinaAddr, underlyingDIFs.get(i)); } } /** * @return the memberEntryList */ public synchronized LinkedList<Member> getMemberEntryList() { return memberEntryList; } /** * @param memberEntryList the memberEntryList to set */ public synchronized void setMemberEntryList(LinkedList<Member> memberEntryList) { this.memberEntryList = memberEntryList; } }