basicp2psim.protocols.peer.peer Maven / Gradle / Ivy
package basicp2psim.protocols.peer;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import org.nongnu.multigraph.debug;
import basicp2psim.protocols.peer.data.file;
import agarnet.framework.Simulation;
import agarnet.protocols.AbstractProtocol;
import agarnet.protocols.protocol;
public class peer extends AbstractProtocol
implements PeerTemplate {
/* track what's still to be sent to each neighbor */
//Map> neightxl = new HashMap> ();
/* Track what we know the neighbour must have in its DB */
Map> neighdb = new HashMap<> ();
/* DB of received, distinct messages */
Set msgdb = new HashSet<> ();
/* for connected hosts */
Simulation sim;
public peer (Simulation sim) {
this.sim = sim;
}
@Override
public void reset () {
super.reset ();
msgdb.clear ();
neighdb.clear ();
}
public boolean should_accept (I from, file msg) {
return !msgdb.contains (msg);
}
public boolean should_send (I to, file msg) {
Set db = neighdb.get (to);
return (db == null || !db.contains (msg));
}
public boolean should_store (file msg) {
return true;
}
@Override
public void insert (protocol above, protocol below) {
if (above != null)
throw new UnsupportedOperationException (
"application protocol doesn't accept messsages from above");
super.insert (null, below);
}
/**
* Receive message from peer
* @param from Peer message was sent from
* @param msg The message received
*/
public void up (I from, byte [] data) {
debug.printf ("peer %s: receive msg: %s from %s\n", this, data, from);
file f = null;
try {
f = file.deserialise (data);
} catch (Exception e) {
debug.println ("Unhandled message: " + e);
return;
}
stats_inc (stat.recvd);
register_has_msg (from, f);
if (!should_accept (from, f))
return;
if (should_store (f)) {
msgdb.add (f);
setChanged ();
debug.printf ("peer %s: storing %s (from %s), db size %d\n",
this, f, from, msgdb.size ());
}
/* We've accepted a message, now flood it on to all other peers */
for (I to : sim.connected (selfId))
if (!to.equals (from) && should_send (to, f)) {
debug.printf ("peer %s: forward %s from %s to %s\n",
this, f, from, to);
send (to, data);
}
/* Acknowledge receipt to the sender by flooding back */
send (from, data);
}
@Override
public long stat_get (int ordinal) {
if (ordinal == stat.stored.ordinal ())
return msgdb.size ();
return super.stat_get (ordinal);
}
@Override
public boolean has_stored (file msg) {
return msgdb.contains (msg);
}
protected void send (file msg) {
if (should_store (msg))
msgdb.add (msg);
for (I host : sim.connected (selfId)) {
debug.printf ("peer %s: consider sending %s to %s\n",
this, msg, host);
if (should_send (host, msg))
send (host, msg);
}
}
private void register_has_msg (I node, file msg) {
Set db = neighdb.get (node);
if (db == null) {
db = new HashSet ();
neighdb.put (node, db);
}
debug.printf ("peer %s register: %s (%s) for %s\n",
this, msg.name, msg, node);
if (!db.contains (msg))
db.add (msg);
}
protected void send (I to, file msg) {
debug.printf ("peer %s: send %s to %s\n", this, msg, to);
super.send (to, msg);
}
@Override
public void link_add (I neigh) {
super.link_add (neigh);
for (file msg : msgdb)
if (should_send (neigh, msg))
send (neigh, msg);
}
@Override
public void link_remove (I neigh) {
super.link_remove (neigh);
neighdb.remove (neigh);
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy