www.pudn.com > query_cycle_simulator.rar > PowerLawNetworkImpl.java


/* ====================================================================
 * The Stanford P2P Sociology Project Software License, Version 1.0
 *
 * Copyright (c) 2003 The Stanford P2P Sociology Project.  All rights
 * reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 *
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in
 *    the documentation and/or other materials provided with the
 *    distribution.
 *
 * 3. The end-user documentation included with the redistribution,
 *    if any, must include the following acknowledgment:
 *       "This product includes software developed by the
 *        Stanford P2P Sociology Project(http://p2p.stanford.edu/)."
 *    Alternately, this acknowledgment may appear in the software itself,
 *    if and wherever such third-party acknowledgments normally appear.
 *
 *
 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
 * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
 * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 * SUCH DAMAGE.
 * ====================================================================
 *
 * For more
 * information on the Stanford P2P Sociology Project,
 * see .
 *
 */

package qcsim.net.impl;

import java.util.*;
import java.io.*;
import qcsim.*;
import qcsim.peer.*;
import qcsim.net.*;
import qcsim.net.util.*;

 /*
  * Title: Query Cycle Simulator
  * Description: P2P file sharing network simulator
  * Copyright: Copyright (c) 2002
  * Company:
  */

 /**
  * Implements the network functionality.
  * @author unascribed
  * @version 1.0
  */

public class PowerLawNetworkImpl implements NetworkManager, Serializable 
{
  /**
   * Debug level
   */
  private int debugLevel_;

  /**
   * The query cycle manager.
   */
  private QueryCycleManager manager_;

  /**
   * Total number of messages send during a simulated cycle.
   */
  private Vector messages_;

  /**
   * Count up the number of malicious query responses.
   */
  private Vector maliciousResponses_;

  /**
   * Count up the number of good query responses.
   */
  private Vector goodResponses_;

  public PowerLawNetworkImpl(QueryCycleManager manager)
  {
    manager_            = manager;
    messages_           = new Vector();
    maliciousResponses_ = new Vector();
    goodResponses_      = new Vector();

    messages_.addElement( new Integer(0) );
    maliciousResponses_.addElement( new Integer(0) );
    goodResponses_.addElement( new Integer(0) );
  }

  public int messages(int cycle)
  {
    if (cycle <= manager_.cycle() && cycle < messages_.size())
    {
      Integer messages = (Integer) messages_.elementAt(cycle);
      return messages.intValue();
    }
    return 0;
  }

  public int maliciousResponses(int cycle)
  {
    if (cycle <= manager_.cycle() && cycle < maliciousResponses_.size())
    {
      Integer responses = (Integer) maliciousResponses_.elementAt(cycle);
      return responses.intValue();
    }
    return 0;
  }

  public int goodResponses(int cycle)
  {
    if (cycle <= manager_.cycle() && cycle < goodResponses_.size())
    {
      Integer responses = (Integer) goodResponses_.elementAt(cycle);
      return responses.intValue();
    }
    return 0;
  }


  /**
   * Send a message to a peer.
   * @param nextHop next hop peer id.
   * @param msg message to send.
   */
  public void send(int nextHop, PeerMsg msg) 
  {
      if (nextHop >= 0) {
    Peer    peer    = manager_.peerManager().peer( nextHop );
    PeerMsg message = (PeerMsg) msg.clone();

    message.ttl( message.ttl() - 1 );
    if (message.ttl() == 0)
      return;
    peer.message( message );
      }

    if (msg instanceof PeerMsgQuery ||
        msg instanceof PeerMsgQueryResponse)
    {
      while (messages_.size() <= manager_.cycle())
        messages_.addElement(new Integer(0));

      // @@@ only add message if it is a query message
      if (msg instanceof PeerMsgQuery) {
	  int messages = ((Integer) messages_.lastElement()).intValue();
	  messages_.setElementAt(new Integer(messages+1), manager_.cycle()); 
      }

      if (msg instanceof PeerMsgQueryResponse && 
          nextHop == msg.destination())
      {
        if (manager_.peerManager().peer(msg.source()).behavior().type() >= 
            PeerBehavior.MALICIOUS_PEER 
            &&
            manager_.peerManager().peer(msg.destination()).behavior().type() <
            PeerBehavior.MALICIOUS_PEER)
        {
          while (maliciousResponses_.size() <= manager_.cycle())
            maliciousResponses_.addElement(new Integer(0));

          int r = maliciousResponses(manager_.cycle());
          maliciousResponses_.setElementAt(new Integer(r+1), manager_.cycle()); 
        }
        else if (manager_.peerManager().peer(msg.source()).behavior().type() <
                 PeerBehavior.MALICIOUS_PEER) 
        {
          while (goodResponses_.size() <= manager_.cycle())
            goodResponses_.addElement(new Integer(0));

          int r = goodResponses(manager_.cycle());
          goodResponses_.setElementAt(new Integer(r+1), manager_.cycle()); 
        }
      }
    }
  }

  /**
   * Remote procedure call to destination peer.
   * @param msg Peer message containing rpc information.
   * @return rpc return value.
   */
  public Object rpc(PeerMsg msg)
  {
    Peer    peer    = manager_.peerManager().peer( msg.destination() );
    PeerMsg message = (PeerMsg) msg.clone();

    message.ttl( message.ttl() - 1 );
    return peer.rpc( message );
  }

// =============== Add Peers to Network =========================

  /**
   * Creates power-law topology network of good peers.
   * @param nodes number of nodes in network
   * @param neighbors initial number of neighbors for each peer
   */
  public void goodPeers(int nodes, int neighbors)
  {
    // create backbone of nodes
    for (int i = 0; i < neighbors; i++)
      manager_.peerManager().newPeer(PeerBehavior.GOOD_PEER);

    // connect existing nodes as clique
    for (int i = 0; i < manager_.peerManager().peers(); i++)
    {
      Peer peer = manager_.peerManager().peer(i);
      for (int j = 0; j < manager_.peerManager().peers(); j++)
      {
        if (i == j) continue;
        peer.addNeighbor(manager_.peerManager().peer(j));
        manager_.peerManager().peer(j).addNeighbor(peer);
      }
    }

    // add N nodes to form power-law network
    for (int i = neighbors; i < nodes; i++)
    {
      Peer peer = manager_.peerManager().newPeer(PeerBehavior.GOOD_PEER);
      connectPeerDegreeBased(peer, neighbors);
    }
    System.err.println("DONE GOOD PEERS");
  }

  /**
   * Adds highly trusted peers to the network.
   * @param nodes number of peers to be connected
   * @param neighbors number of initial neighbors
   */
  public void highlyTrustedPeers(int nodes, int neighbors) 
  {
    // create ordered list of peers based on node degree
    int[] lop = new int[manager_.peerManager().peers()];
    for (int i = 0; i < manager_.peerManager().peers(); i++)
      lop[i] = i;
    
    boolean changed = true;
    while (changed) 
    {
      changed = false;
      for (int i = 0; i < manager_.peerManager().peers() - 1; i++) 
      {
        if (manager_.peerManager().peer(lop[i]).neighbors() < 
            manager_.peerManager().peer(lop[i+1]).neighbors()) 
        {
          int tmpID = lop[i+1];
          lop[i+1] = lop[i];
          lop[i] = tmpID;
          changed = true;
        }
      }
    }

    // add peers
    for (int i = 0; i < nodes; i++) 
    {
      Peer peer = manager_.peerManager().newPeer(PeerBehavior.HIGHLY_TRUSTED_PEER);

      // connect to the topmost highly connected nodes
      for (int j = 0; j < neighbors; j++) 
      {
        if (j >= lop.length)
        {
          break;
        }
        else
        {
          manager_.peerManager().peer(lop[j]).addNeighbor(peer);
          peer.addNeighbor(manager_.peerManager().peer(lop[j]));
        } 
      }
    }
    System.err.println("DONE HIGHT TRUST PEERS");
  }
    
  /**
   * Adds malicious peers to the network.
   * @param nodes number of peers to be connected
   * @param neighbors number of initial neighbors
   */
  public void maliciousPeers(int nodes, int neighbors)  
  {
    // create ordered list of peers based on node degree
    int[] lop = new int[manager_.peerManager().peers()];
    for (int i = 0; i < manager_.peerManager().peers(); i++)
      lop[i] = i;
    
    // Bubble sort based on the degree of neighbors.
    boolean changed = true;
    while (changed) 
    {
      changed = false;
      for (int i = 0; i < manager_.peerManager().peers() - 1; i++) 
      {
        if (manager_.peerManager().peer(lop[i]).neighbors() < 
            manager_.peerManager().peer(lop[i+1]).neighbors()) 
        {
          int tmpID = lop[i+1];
          lop[i+1] = lop[i];
          lop[i] = tmpID;
          changed = true;
        }
      }
    }
    
    // add peers
    for (int i = 0; i < nodes; i++) 
    {
      Peer peer = manager_.peerManager().newPeer(PeerBehavior.MALICIOUS_PEER);

      // connect to the topmost highly connected nodes
      for (int j = 0; j < neighbors; j++) 
      {
        if (j >= lop.length)
        {
          break;
        }
        else
        {
          manager_.peerManager().peer(lop[j]).addNeighbor(peer);
          peer.addNeighbor(manager_.peerManager().peer(lop[j]));
        }
      }
    }
  }


// ======================= PRIVATE ===============================

  /**
   * Adds peer to network based on node degree.
   * @param peer  peer to be added
   * @param neighbors  initial number of neighbors of peer
   */
  private void connectPeerDegreeBased(Peer peer, int neighbors) 
  {
    // sum up join probabilities of all nodes currently in the network
    double totalLinks = 0;
    for (int i = 0; i < manager_.peerManager().peers(); i++)
    {
      if (i == peer.peerID())
        continue;
      totalLinks += manager_.peerManager().peer(i).neighbors();
    }

    for (int i = 0; i < neighbors; i++) 
    {
      /* try to integrate random peer until peer which 
       * is not yet neighbor is found
       */
      for (Peer neighbor = null; neighbor == null; ) 
      {
        // get random value
        int rand = (int)(Math.random() * (totalLinks));

        int randomPeerID = 0;
        for (int sum = 0; sum < rand; randomPeerID++ ) 
        {
          if (randomPeerID == peer.peerID()) 
            continue;
          sum += manager_.peerManager().peer(randomPeerID).neighbors();
        }

        if (peer.isNeighbor(randomPeerID) == null)
        {
          neighbor = manager_.peerManager().peer(randomPeerID);
          peer.addNeighbor(neighbor);
          neighbor.addNeighbor(peer);
        }
      }
    }
  }

}