Skip to content

File FreezeLeaderDeletion.java

File List > behaviour > SKD > FreezeLeaderDeletion.java

Go to the documentation of this file

package skydata.behaviour.SKD;

import java.io.IOException;
import java.io.Serializable;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

import com.google.common.collect.Sets;

import jade.core.behaviours.CyclicBehaviour;
import jade.core.behaviours.WakerBehaviour;
import jade.lang.acl.ACLMessage;
import jade.lang.acl.MessageTemplate;
import jade.lang.acl.UnreadableException;
import skydata.internal.agents.SKAgent;
import skydata.internal.agents.SKD;
import skydata.internal.message.RSBroadcast;
import skydata.internal.message.SKAID;
import skydata.internal.message.SKLMessage;

public class FreezeLeaderDeletion extends FreezeLocal {

    static int rgLocal = 1;

    public FreezeLeaderDeletion(SKAgent agent) {
        super(agent);

    }

    static private class DataDeletion implements Serializable {
        @SuppressWarnings("unused")
        boolean elected;
        boolean ask_elect;
        boolean ack_received = false;
        boolean elected_received = false;
        SKAID coordinator;
        WakerBehaviour timeout, timeout2, deletion;
    }

    private void broadcastSuperior(Data data) {
        SKLMessage msg = new SKLMessage("ELECT", "FREEZING_DELETION");
        for (SKAID a : data.listFreezing) {
            if (a.compareTo(agent.getSKAID()) > 0) {
                msg.addReceiver(a);
            }
        }
        agent.skSendReliable(msg);
    }

    private void startElection(Data data, DataDeletion d) {
        d.ask_elect = true;
        d.elected = false;
        d.ack_received = d.elected_received = false;
        broadcastSuperior(data);
        d.timeout.reset();
        agent.addBehaviour(d.timeout);
    }

    private void startDeletion(Data data, DataDeletion d) {
        SKD agent = (SKD) this.agent;
        int rg = Integer.parseInt((String) agent.args.get("rg"));
        Set<SKAID> diffSet = Sets.difference(data.listFreezing, data.listCrashed);
        Set<SKAID> newSet = new HashSet<>(diffSet);
        newSet.remove(agent.getSKAID());
        SKAID[] listSKAID = newSet.toArray(new SKAID[0]);
        List<SKAID> arraySKAID = Arrays.asList(listSKAID);
        Collections.shuffle(arraySKAID);
        Set<SKAID> toDelete = new HashSet<>();
        toDelete.addAll(arraySKAID.subList(0, Math.max(0, Math.min(agent.getFamilySize() - rg, arraySKAID.size()))));
        SKLMessage msg = new SKLMessage("FREEZING_DELETION", "DELETE");
        msg.setContent((Serializable) toDelete);
        agent.broadcast(new RSBroadcast(), msg, data.listFreezing);
        unfreeze(data);
    }

    @SuppressWarnings("unused")
    @Override
    protected void afterFreeze(Data data) {
        agent.print("Freeze ended !");
        SKD agent = (SKD) this.agent;
        int rg = Integer.parseInt((String) agent.args.get("rg"));
        DataDeletion d = new DataDeletion();
        agent.createStorageObject("DELETION_FREEZED", d);

        // Wait delta ms and start the deletion
        d.deletion = new WakerBehaviour(agent, deltaLocal) {
            @Override
            public void onWake() {
                if (data.isFreezing == Data.Stat.ENDED) {
                    startDeletion(data, d);
                }
            }
        };

        // Wait delta ms and verify if a leader is elected
        d.timeout2 = new WakerBehaviour(agent, deltaLocal) {
            @Override
            public void onWake() {
                if (data.isFreezing == Data.Stat.ENDED) {
                    if (!d.elected_received) {
                        startElection(data, d);
                    }
                }
            }
        };

        // Wait delta ms and start an election
        d.timeout = new WakerBehaviour(agent, deltaLocal) {
            @Override
            public void onWake() {
                if (data.isFreezing == Data.Stat.ENDED) {
                    if (!d.ack_received) {
                        d.elected = true;
                        SKLMessage msg = new SKLMessage("FREEZING_DELETION", "ELECTED");
                        msg.setContent(agent.getSKAID());
                        agent.broadcast(new RSBroadcast(), msg, data.listFreezing);
                        agent.print("Je suis le leader");
                        d.deletion.reset();
                        agent.addBehaviour(d.deletion);
                    } else {
                        d.timeout2.reset();
                        agent.addBehaviour(d.timeout2);
                    }

                }
            }
        };

        MessageTemplate mtElect = MessageTemplate.and(
                MessageTemplate.MatchProtocol("FREEZING_DELETION"),
                MessageTemplate.and(
                        MessageTemplate.MatchPerformative(ACLMessage.INFORM),
                        MessageTemplate.MatchOntology("ELECT")));
        agent.addBehaviour(new CyclicBehaviour(agent) {
            @Override
            public void action() {
                if (data.isFreezing == Data.Stat.ENDED) {
                    ACLMessage msg = agent.receive(mtElect);
                    if (msg == null) {
                        block();
                        return;
                    }
                    if (d.ask_elect == false) {
                        d.ask_elect = true;
                        broadcastSuperior(data);
                    }
                    ACLMessage answer = msg.createReply();
                    answer.setOntology("ACK");
                    agent.send(answer);
                }
            }
        });

        MessageTemplate mtElected = MessageTemplate.and(
                MessageTemplate.MatchProtocol("FREEZING_DELETION"),
                MessageTemplate.and(
                        MessageTemplate.MatchPerformative(ACLMessage.INFORM),
                        MessageTemplate.MatchOntology("ELECTED")));
        agent.addBehaviour(new CyclicBehaviour(agent) {
            @Override
            public void action() {
                if (data.isFreezing == Data.Stat.ENDED) {
                    SKLMessage msg = agent.skReceive(mtElected);
                    if (msg == null) {
                        block();
                        return;
                    }
                    d.ask_elect = false;
                    d.elected_received = true;
                    d.coordinator = (SKAID) msg.getContent();
                    agent.print("Le leader est : " + d.coordinator.toString());
                }
            }
        });

        MessageTemplate mtAck = MessageTemplate.and(
                MessageTemplate.MatchProtocol("FREEZING_DELETION"),
                MessageTemplate.and(
                        MessageTemplate.MatchPerformative(ACLMessage.INFORM),
                        MessageTemplate.MatchOntology("ACK")));
        agent.addBehaviour(new CyclicBehaviour(agent) {
            @Override
            public void action() {
                if (data.isFreezing == Data.Stat.ENDED) {
                    ACLMessage msg = agent.receive(mtAck);
                    if (msg == null) {
                        block();
                        return;
                    }
                    d.ack_received = true;
                }
            }
        });

        MessageTemplate mtDelete = MessageTemplate.and(
                MessageTemplate.MatchProtocol("FREEZING_DELETION"),
                MessageTemplate.and(
                        MessageTemplate.MatchPerformative(ACLMessage.INFORM),
                        MessageTemplate.MatchOntology("DELETE")));
        agent.addBehaviour(new CyclicBehaviour(agent) {
            @Override
            public void action() {
                if (data.isFreezing == Data.Stat.ENDED) {
                    SKLMessage msg = agent.skReceive(mtDelete);
                    if (msg == null) {
                        block();
                        return;
                    }
                    @SuppressWarnings("unchecked")
                    Set<SKAID> toDelete = (Set<SKAID>) msg.getContent();
                    if (toDelete.contains(agent.getSKAID())) {
                        agent.delete();
                    }
                    unfreeze(data);

                }
            }
        });

        startElection(data, d);
    }

}