Secondo esempio: "Let us share our files!"

Si vuole realizzare un agente (o peer) per permette di condividere un certo insieme di file (ad esempio, quelli contenuti nel direttorio in cui l'agente è eseguito) con altri agenti. SI desidera che ogni peer possa agire sia come risponditore/fornitore di richieste di file che arrivano da altri peer, sia come esso stesso richiedente di file ad altri peer presenti in rete in un dato momento.

Il diagramma di sequenza di interzione potrebbe essere, ad esempio, quello riportato in Figura 5 (tale interazione è ispirata al protocollo Contract Net come descritto in [2]). Per un esempio di trasferimento di file attraverso la rete mediante la tecnologia RMI si faccia riferimento all'esempio rmi-transferfile disponibile in [1].

Figure: Diagramma di sequenza dell'esempio del file sharing.
Image Peer

class PeerRisponditore extends JAMWhileBehaviour {
  MyListOfFile myList;
  public PeerRisponditore(JAMAgent myAgent) {
    super(myAgent);
    myList = myAgent.getMyListOfFile();
    [ ... ]
  }
  [ ... ]
  public void action() {
    Message msg = myAgent.receive(MessageType.QUERY_IF);
    if (!msg.getContent().equals("File disponibile?")) {
      // INVIO NOT UNDERSTOOD
      Message4You not_understood = new Message4You(MessageType.AGREE);
      not_understood.setSender(myAgent.getMyID());
      not_understood.setReceiver(msg.getSender());
      not_understood.setContent("Richiesta non capita");
      not_understood.setExtraArgument(msg);
      myAgent.send(not_understood);
    } else if (!myList.isMember((String)msg.getExtraArgument())) {
      // INVIO REFUSE PERCHE' NON DISPONIBILE
      Message4You refuse = new Message4You(MessageType.REFUSE);
      refuse.setSender(myAgent.getMyID());
      refuse.setReceiver(msg.getSender());
      refuse.setContent("File non disponibile");
      refuse.setExtraArgument(msg.getExtraArgument());
      myAgent.send(refuse);
    } else {
      // INVIO INFORM DISPONIBILITA' E INFO SU VELOCITA' MIA CONNESSIONE
      Message4You inform = new Message4You(MessageType.INFORM);
      inform.setSender(myAgent.getMyID());
      inform.setReceiver(msg.getSender());
      inform.setContent("File disponibile");
      Object[] infoFile = new Object[] { msg.getExtraArgument(), myAgent.mySpeed() };
      inform.setExtraArgument(infoFile);
      myAgent.send(inform);
    }
  }
}

class PeerFornitore extends JAMWhileBehaviour {
  MyListOfFile myList;
  public PeerFornitore(JAMAgent myAgent) {
    super(myAgent);
    myList = myAgent.getMyListOfFile();
    [ ... ]
  }
  [ ... ]
  public void action() {
    Message msg = myAgent.receive(MessageType.REQUEST);
    if (!msg.getContent().equals("Invia file")) {
      // INVIO NOT UNDERSTOOD
      Message4You not_understood = new Message4You(MessageType.AGREE);
      not_understood.setSender(myAgent.getMyID());
      not_understood.setReceiver(msg.getSender());
      not_understood.setContent("Richiesta non capita");
      not_understood.setExtraArgument(msg);
      myAgent.send(not_understood);
    } else if (!myList.isMember((String)msg.getExtraArgument())) {
      // INVIO FAILURE PERCHE' NON PIU' DISPONIBILE (MEGLIO RICONTROLLARE!)
      Message4You failure = new Message4You(MessageType.FAILURE);
      failure.setSender(myAgent.getMyID());
      failure.setReceiver(msg.getSender());
      failure.setContent("File non disponibile");
      failure.setExtraArgument(msg.getExtraArgument());
      myAgent.send(failure);
    } else {
      // INVIO INFORM CON FILE
      Message4You inform = new Message4You(MessageType.INFORM);
      inform.setSender(myAgent.getMyID());
      inform.setReceiver(msg.getSender());
      inform.setContent("File");
      Object[] file = new Object[] { msg.getExtraArgument(), 
                                         myList.getFile( (String) msg.getExtraArgument() };
      inform.setExtraArgument(file);
      myAgent.send(inform);
    }
  }
}
Mentre il seguente comportamento di occupa di rispondere ai clienti che inviano le richieste.
class PeerRicercatore extends JAMSimpleBehaviour {
  public void action() {
    // EFFETTUA LA QUERY_IF PER UN CERTO FILE A TUTTI I PEER FORNITORI
    // ATTENDE UN CERTO TEMPO
    // PRELEVA LE PRIME N INFORM CON RISPOSTA AFFERMATIVA
    // SCEGLIE QUELLA CON LA CONNESSIONE CON VELOCITA' MIGLIORE
    // INVIA LA REQUEST DEL FILE AL PEER SELEZIONATO
    // ATTENDE LA RISPOSTA
    // SE RICEVE FAILURE ALLORA SELEZIONA UN ALTRO PEER E RIPETE LA REQUEST
    // SE RICEVE INFORM ALLORA MEMORIZZA IL NUOVO FILE SUL DIRETTORIO
  }
}

La seguente classe si occupa di gestire la lista dei file presenti nel direttorio corrente in un dato momento e di fornire i metodi per il caricamento o il salvataggio di un file.

class MyListOfFile {
  private java.util.List<String> myListOfFiles;
  public void loadMyListOfFile() {
    [ ... ]
  }
  public boolean isMember(String nomeFile) {
    [ ... ]
  }
  public MioFile getFile(String nomeFile) {
    [ ... ]
    byte[] data;
    InputStream in = new FileInputStream(nomeFile);
    System.out.println("Loading file " + nomeFile);
    int bytesAvailable = in.available();
    if (bytesAvailable > 0) {
      data = new byte[bytesAvailable];
      in.read(data);
    }  
    [ ... ]
  }
  public void saveFile(String nomeFile, byte[] data) {
    [ ... ]
    OutputStream out = new FileOutputStream(nomeFile);
    out.write(data);
    [ ... ]
  }
}

class MioFile {
  [ ... ]
}
La definizione dell'agente si riduce a creare i vari comportamenti e il timer.
class PeerAgent extends JAMAgent {
  public PeerAgent ( ... ) {
    [ ... ]
    loadMyListOfFile();
    addBehaviour(new PeerRisponditore(this));
    addBehaviour(new PeerFornitore(this));
    addBehaviour(new PeerRicercatore(this));
    [ ... ]
  }
  [ ... ]
}
L'agente lo si potrà creare in un main qualsiasi nel seguente modo (alcuni dettagli sono per ora omessi):
class TestPeer {
  public static void main(String[] args) {
    [ ... ]
    JAMAgent peer = new PeerAgent( ... );
    peer.init();
    peer.start();
    [ ... ]
  }
}

baldoni 2005-01-13