2

I have a Sender that reads from a file and sends each line to a Receiver agent.

Typically, I want my Receiver agent to send a confirmation for every line received line and the Sender Agent is blocked (or waits) until that confirmation is received.

Here is a snap-code of the Sender agent

private volatile boolean recieved = false;
// Codes and 

            while ((line = bufferedReader.readLine()) != null) {
                // SENDING LINES ...
                String Agentname="Sender";
                ACLMessage aclMessage= new ACLMessage(ACLMessage.CONFIRM);
                aclMessage.addReceiver(new AID(Agentname,AID.ISLOCALNAME));
                aclMessage.setContent(line);
                send(aclMessage);
                if (isRecieved() == false ) { block(); return; }
                System.out.println("Value after "+isRecieved());
            } 

for recieving the ACLMessages:

                    if (msg == null) {
                        block();
                        return;
                    }
                    else {

                        switch (msg.getPerformative()) {
// Other cases
                        case ACLMessage.INFORM:
                            System.out.println("Confirmation");
                            setRecieved(true);
                            break;

                        default:
                            break;
                        }

The Receiver agent when it receives the message it sends a confirmation

                case ACLMessage.CONFIRM:

                    // Process the results
                    String result = doNormalize (msg.getContent());
                    if (result!=null) {
                        //send the results to the writer
                        ACLMessage aclMessage= new ACLMessage(ACLMessage.CONFIRM);
                        aclMessage.addReceiver(new AID("Writer",AID.ISLOCALNAME));
                        aclMessage.setContent(result);
                        send(aclMessage);

// Sends a confirmation to using the method sendConfirmation
                        sendConfirmation(msg);
                    }
                    break;

                default:
                     break;
                    }
    // Code ..
    // ..
   // ..
   // ..

    public void sendConfirmation(ACLMessage aclMessage) {
    ACLMessage message = aclMessage.createReply();
    message.setPerformative(ACLMessage.INFORM);
    send(message);
}

So the sender uses a flag value that helps determine whether a confirmation is received or not. For this, it uses the isRecieved() method, if it is false, Ideally the agent should be blocked and wait for the confirmation message.

The problem is when I run the code it, the Sender is blocked when recieved() == false is true, but it doesn't resume the while loop when it receives the confirmation. Am I doing this wrong ?

U. User
  • 533
  • 4
  • 22
  • Does everything run on one thread ? Can you give the send code ? – Sami Tahri Jul 08 '18 at 21:07
  • Yes everything on one thread. The send code is the default send method provided by Jade. – U. User Jul 08 '18 at 21:09
  • If everything run on one thread, why do you need blocking mechanism as no other thread is going to "wake" them ? – Sami Tahri Jul 08 '18 at 21:16
  • The block() puts the Behaviour on hold until the next message is received. This is why we use: if (msg == null) { block(); return; } when receiving ACLMessages. – U. User Jul 08 '18 at 21:24
  • is sender's behaviour that has loop a OneShotBehaviour or CycleBehaviour? – nikelyn Jul 09 '18 at 09:34
  • The switch-case statement of both the Reciever and Sender agents is inside a CyclicBehaviour. The problem is that when I use the block(); return; statement in the Sender agent, it leaves the while loop and **does** receive the confirmation message, but the agent then stops after that. Normally, it should resume executing the while loop. I hope I was clear. – U. User Jul 09 '18 at 09:55
  • I meant the behaviour with "while" statement.Agent should resume execution of the behaviour but not exactly the while loop. – nikelyn Jul 09 '18 at 10:25
  • The Behaviour with the while loop is a OneShotBehaviour. So are you saying that it is not possible? Do you have any other approaches to this? – U. User Jul 09 '18 at 10:45
  • added answer with the code. – nikelyn Jul 09 '18 at 11:34
  • I have found the answer. Thank you for your time! – U. User Jul 09 '18 at 14:11

2 Answers2

2

To block an agents behaviour there various methods :

  • receive() - nonblocking receive, returns first message in queue or null if queue is empty
  • receive(MessageTemplate pattern) - behaves like the the previous one, but you can also specify pattern for message, like for example specific sender AID, conversation ID, also combinations.
  • blockingReceive() - blocking receive, blocks agent until message appears in queue
  • blockingReceive(MessageTemplate pattern) - blocking receive, with pattern

So adding the blockingReceive() or blockingReceive(MessageTemplate pattern) blocks the agents Behaviour until a certain message is received. Which will look something like this:

            while ((line = bufferedReader.readLine()) != null) {
                // SENDING EVENT LINES ...
                String Agentname="Reciever";
                ACLMessage aclMessage= new ACLMessage(ACLMessage.CONFIRM);
                aclMessage.addReceiver(new AID(Agentname,AID.ISLOCALNAME));
                aclMessage.setContent(line);
                send(aclMessage);
                // Block an Agent until a confirmation is received..
                ACLMessage aclMessage2 = blockingReceive(mt);
            }
U. User
  • 533
  • 4
  • 22
0

I would do the behaviour with a switch statement, something like this:

public class ReadBehaviour extends Behaviour {
   private boolean isDone = false;
   private int step = 0;
   private BufferedReader bufferedReader;

   @Override
   public void action() {
       switch (step){
           case 0:
               // TODO initialize your bufferedReader
               step++;
               break;
           case 1:
               try {
                   String line = bufferedReader.readLine();
                   if(line == null){
                       isDone = true;
                   } else {
                       ACLMessage aclMessage= new ACLMessage(ACLMessage.CONFIRM);
                       aclMessage.addReceiver(new AID("Sender", AID.ISLOCALNAME));
                       aclMessage.setContent(line);
                       myAgent.send(aclMessage);
                       step++;
                   }
               } catch (IOException e) {
                   isDone = true;
               }
               break;
           case 2:
               if(isRecieved()){
                   step--;
               } else {
                   block();
               }
       }
   }

   @Override
   public boolean done() {
       return isDone;
   }
}
nikelyn
  • 418
  • 3
  • 12