Warning
This page is located in archive. Go to the latest version of this course pages. Go the latest version of this page.

Čtvrtý domácí úkol

Zadání tohoto domácího úkolu je inspirováno technologií BitTorrent, ve které si skupina uzlů navzájem posílá stahovaná data tak dlouho, až každý uzel stáhne celý soubor. Část kódu už naprogramovaná je, vaším úkolem je napsat kód třídy Homework4 dědící ze třídy MessageVisitor.

public class Homework4 extends MessageVisitor {
    public Homework4(Peer peer) {
        super(peer);
    }
 
    // zde doplnte svuj kod
}

Odevzdávejte pouze implementovanou třídu Homework4, ostatní níže uvedené třídy hodnotící systém již obsahuje.

Všechny vaše třídy se musí nacházet v package cz.cvut.k36.omo.hw.hw04.

Odevzdávanou třídu Homework4 zabalte do .zip archivu a odevzdejte do systému Brute. Celý projekt také uložte do svého gitlab repozitáře.

“Okolí” vašeho kódu tvoří níže uvedené třídy.

/**
 * Instance implementujici PeerInterface reprezentuje lokalni uzel nebo uzel
 * pripojeny pres sit.
 */
public interface PeerInterface {
    /**
     * Sdeli vzdalenemu uzlu, ze uzel sender prave obdrzel blok s indexem
     * blockIndex.
     */
    public void have(PeerInterface sender, int blockIndex);
 
    /**
     * Pozada vzdaleny uzel o blok s indexem blockIndex.
     */
    public void request(PeerInterface sender, int blockIndex);
 
    /**
     * Zasle vzdalenemu uzlu blok s indexem blockIndex.
     */
    public void piece(PeerInterface sender, int blockIndex, byte[] data);
}
 
import java.util.Map;
import java.util.Queue;
import java.util.concurrent.LinkedBlockingQueue;
 
/**
 * Instance tridy Peer reprezentuje lokalni uzel.
 */
public class Peer implements PeerInterface {
    /**
     * Fronta nezpracovanych zprav.
     */
    final Queue<Message> messageQueue = new LinkedBlockingQueue<>();
    /**
     * Mapovani z uzlu na bitovou mapu urcujici ktere bloky ma dany uzel k
     * dispozici.
     */
    final Map<PeerInterface, boolean[]> peers2BlocksMap;
    /**
     * Celkovy pocet bloku ve stahovanem souboru.
     */
    final int totalBlocksCount;
    /**
     * Pole se stazenymi bloky.
     */
    final byte[][] data;
    /**
     * Pocet stazenych bloku.
     */
    int downloadedBlocksCount = 0;
 
    public Peer(Map<PeerInterface, boolean[]> peers2BlocksMap, int totalBlocksCount) {
        this.peers2BlocksMap = peers2BlocksMap;
        this.totalBlocksCount = totalBlocksCount;
        data = new byte[totalBlocksCount][];
    }
 
    /**
     * Prijme zpravu "have" a prida ji do fronty zprav.
     */
    public void have(PeerInterface sender, int blockIndex) {
        messageQueue.add(new HaveMessage(blockIndex, sender));
    }
 
    /**
     * Prijme zpravu "request" a prida ji do fronty zprav.
     */
    public void request(PeerInterface sender, int blockIndex) {
        messageQueue.add(new RequestMessage(blockIndex, sender));
    }
 
    /**
     * Prijme zpravu "piece" a prida ji do fronty zprav.
     */
    public void piece(PeerInterface sender, int blockIndex, byte[] data) {
        messageQueue.add(new PieceMessage(blockIndex, data, sender));
    }
 
    /**
     * Vyzvedne nejstarsi zpravu z fronty zprav a zpracuje ji pomoci zadaneho
     * navstevnika. Pokud ve fronte zadna zprava neni, zasle sam sobe a zpracuje
     * zpravu "idle". Vrati true v pripade, ze tento uzel stahnul vsechny bloky,
     * false jinak.
     */
    public boolean processMessage(MessageVisitor visitor) {
        return (messageQueue.isEmpty() ? new IdleMessage(this) : messageQueue.poll()).accept(visitor);
    }
}
 
/**
 * Instance tridy MessageVisitor reprezentuji navstevniky zpracovavajici zpravy.
 */
public abstract class MessageVisitor {
    protected final Peer peer;
 
    public MessageVisitor(Peer peer) {
        this.peer = peer;
    }
 
    /*
     * Zpracuje zpravu "have": v lokalnim uzlu vyznaci, ze dany vzdaleny uzel ma
     * k dispozici blok s danym indexem.
     *
     * Vzdy vrati false.
     */
    public abstract boolean visitHaveMessage(HaveMessage message);
 
    /*
     * Zpracuje zpravu "request": pokud ma lokalni uzel pozadovany blok k
     * dispozici, obratem ho posle vzdalenemu uzlu pomoci zpravy "piece". Pokud
     * ne, pozadavek ignoruje.
     *
     * Vzdy vrati false.
     */
    public abstract boolean visitRequestMessage(RequestMessage message);
 
    /*
     * Zpracuje zpravu "piece": ulozi obdrzena data do lokalniho uzlu, zvysi
     * pocet stazenych bloku a vsem vzdalenym uzlum (vcetne toho, od ktereho
     * data obdrzel) rozesle zpravu "have".
     *
     * Vrati true, pokud lokalni uzel stahl vsechny bloky, false jinak.
     */
    public abstract boolean visitPieceMessage(PieceMessage message);
 
    /*
     * Zpracuje zpravu "idle": vybere nejvzacnejsi jeste nestazeny blok a zazada
     * o nej u nektereho z jeho vlastniku. Nejvzacnejsi blok je takovy, ktery
     * vlastni nejmene vzdalenych uzlu. Pokud je nejvzacnejsich bloku nekolik,
     * vybere jeden z nich.
     *
     * Vzdy vrati false.
     */
    public abstract boolean visitIdleMessage(IdleMessage message);
}
 
public abstract class Message {
    private final PeerInterface sender;
 
    public Message(PeerInterface sender) {
        this.sender = sender;
    }
 
    public PeerInterface getSender()
    {
        return sender;
    }
 
    public abstract boolean accept(MessageVisitor visitor);
}
 
public class HaveMessage extends Message {
    private final int blockIndex;
 
    public HaveMessage(int blockIndex, PeerInterface sender) {
        super(sender);
        this.blockIndex = blockIndex;
    }
 
    public int getBlockIndex()
    {
        return blockIndex;
    }
 
    public boolean accept(MessageVisitor visitor) {
        return visitor.visitHaveMessage(this);
    }
}
 
public class RequestMessage extends Message {
    private final int blockIndex;
 
    public RequestMessage(int blockIndex, PeerInterface sender) {
        super(sender);
        this.blockIndex = blockIndex;
    }
 
    public int getBlockIndex()
    {
        return blockIndex;
    }
 
    public boolean accept(MessageVisitor visitor) {
        return visitor.visitRequestMessage(this);
    }
}
 
public class PieceMessage extends Message {
    private final int blockIndex;
    private final byte[] data;
 
    public PieceMessage(int blockIndex, byte[] data, PeerInterface sender) {
        super(sender);
        this.blockIndex = blockIndex;
        this.data = data;
    }
 
    public int getBlockIndex()
    {
        return blockIndex;
    }
 
    public byte[] getData()
    {
        return data;
    }
 
    public boolean accept(MessageVisitor visitor) {
        return visitor.visitPieceMessage(this);
    }
}
 
public class IdleMessage extends Message {
    public IdleMessage(PeerInterface sender) {
        super(sender);
    }
 
    @Override
    public boolean accept(MessageVisitor visitor) {
        return visitor.visitIdleMessage(this);
    }
}

courses/b6b36omo/hw/042018/start.txt · Last modified: 2018/11/12 21:59 by balikm1