Hello !
I tried to insert (out) a tuple into a remote agent tuple space, but I didn't do it.
I have read in a forum message that "the only thread that can do operations on a lime tuple space is a thread that is running inside a reaction".
I implemented this using two agents (a mobile and a monitor) both of them sharing a tuple space called "ITS".
There is a ubiquitous reaction that is running in the monitor agent and fires when the mobile agent inserts a tuple like (<formal>,"test") into ITS.
Let me make sure that I follow what you are saying:
In the reaction of agent A you issue an out operation for agent B, where B is a mobile agent. The problem is that agent B is not getting the tuple that you outputted, but when B looks into its tuple space, the tuple is not there.
One of two things is happening:
1. If A and B are on different hosts, then you should be getting IllegalReactionOperationException. This is NOT a legal operation inside an exception. Why? Because inside a reaction, all operations must be localized to the host's tuple space. If you are trying to output a tuple to a remote host's tuple space, then you are not localizing the operations on the tuple space, and are violating the rules.
2. If A and B are on the same host, then possibly either A or B's tuple spaces are not shared.
A third possibility is that there is a problem in Lime. Let's hope that the problem is one of the first two:-)
To help clairfy what is going on, please answer the following:
1. how are you *certain* that B cannot find the tuple which was outputted by A?
2. Are you certain that the reaction is firing?
3. Are A and B on the same host and are their tuple spaces shared?
4. Are you certain that the MobileAgentID that youa re using is the correct ID of agent B?
5. Are you getting an exception during the execution, and if so, what is the exception? Run without jit to find out the line numbers for the errors, if possible.
That's all I can think of right now.
-Amy
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
Let me see if I can help out a little. All the information that Liang gave is correct, but let me try to spell it out in a different way.
In your agent, you will create and install a reaction and create a queue (using the Queue from the Lime.gp package if you want). Inside the reactsTo of the reaction, the code will add an element to your queue, something simple like the tuple which triggered the reaction. Periodically the thread of the agent will check the queue to see if there are any elements on it. When there is an element on it, the agent will do the remote out operation.
This works best if your agent thread is not actually doing any work besides responding to reactions and can wait on the queue. The Queue object distributed with Lime allows the agent to wait until there is a data element in the queue (in other words, the agent will be blocked until there is work to do).
Because of the restriction that remote operations are not allowed in reactions, this is the best that you can do.
A different option is to create a separate agent whose only functionality is to react and do the remote out operation. This would free your original agent from the need to periodically check the queue for any work that needs to be done.
I hope this is clear.
Amy
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
It appears to be rejecting the initiator's transaction if the transaction is an agent disengagement and at least one of the agent's tuple spaces is not shared.
Why do all of the initiating agent's tuple spaces need to be shared in order for it to disengage?
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
I think that there is a problem because i try to output a tuple to a remote host's tuple space, which is not local operation.But how i could finally do this out operation?
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
As I mentioned before, remote operations are not allowed inside a reaction.
The best course of action for you to take is most likely to have the reaction "queue" a message to the agent. The agent then reads this message queue periodically, and when it sees the message from the reaction, the agent performs the remote out. This is a basic mechanism for decoupling the reaction from the remote operation.
-Amy
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
I don't think she means an object "reaction queue" but rather she means "make the reaction do an operation that queues an object."
By this she means have the reaction queue an object into a queue that the agent's thread is waiting on. When the object is enqueued, the agent's thread is automatically notified. When the agent's thread is notified, it obtains the queued object and uses it to determine what to do.
The object can be a "DoRemoteOutOperation" object that contains the the tuple to be outputed and the location it should be outputted to.
The Lime distribution comes with gp.util.Queue, which can be used as the queue.
Here's an example:
public class MyAgent extends StationaryAgent implements ReactionListener {
gp.util.Queue myQueue = new gp.util.Queue();
.
.
.
public void reactsTo(ReactionEvent re) {
ITuple react = re.getEventTuple();
AgentLocation al = new AgentLocation(re.getSourceAgent());
myQueue.add(new DoRemoteOutOperation(al, react));
}
.
.
.
public void run() {
while (!done)
{
myQueue.waitOnEmpty();
You mean that i could use this:
public void run() {
while (!done)
{
myQueue.waitOnEmpty();
DoRemoteOutOperation droo = (DoRemoteOutOperation)myQueue.remove();
.
// do operation ...
.
}
}
}
in order to read the contents of queue from the remote agent?
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
There is a reaction thread comming from the underlying Lime system that calls the public void reactsTo(ReactionEvent re) method within your agent. When this occurs, suppose you want to out a tuple into another agent's tuple space located on another host. To do this, you cannot simply have the body of reactsTo(ReactionEvent re) out a tuple into the remote agent's tuple space. Instead, you must notify the agent's thread to perform this operation. By "agent's thread" I mean "the thread that executes the code within the run() method of your agent." This is usually done by passing a message using a queue. Does this make sense?
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
Hello !
I tried to insert (out) a tuple into a remote agent tuple space, but I didn't do it.
I have read in a forum message that "the only thread that can do operations on a lime tuple space is a thread that is running inside a reaction".
I implemented this using two agents (a mobile and a monitor) both of them sharing a tuple space called "ITS".
There is a ubiquitous reaction that is running in the monitor agent and fires when the mobile agent inserts a tuple like (<formal>,"test") into ITS.
The reaction listener has a statement :
ITuple mytuple=new Tuple().addActual("Test tuple");
lts.out(MobileAgentID,mytuple);
This doesn't work ("Test tuple" never comes to mobile agent).
Could you help me?
Thank you very much.
Hello,
Let me make sure that I follow what you are saying:
In the reaction of agent A you issue an out operation for agent B, where B is a mobile agent. The problem is that agent B is not getting the tuple that you outputted, but when B looks into its tuple space, the tuple is not there.
One of two things is happening:
1. If A and B are on different hosts, then you should be getting IllegalReactionOperationException. This is NOT a legal operation inside an exception. Why? Because inside a reaction, all operations must be localized to the host's tuple space. If you are trying to output a tuple to a remote host's tuple space, then you are not localizing the operations on the tuple space, and are violating the rules.
2. If A and B are on the same host, then possibly either A or B's tuple spaces are not shared.
A third possibility is that there is a problem in Lime. Let's hope that the problem is one of the first two:-)
To help clairfy what is going on, please answer the following:
1. how are you *certain* that B cannot find the tuple which was outputted by A?
2. Are you certain that the reaction is firing?
3. Are A and B on the same host and are their tuple spaces shared?
4. Are you certain that the MobileAgentID that youa re using is the correct ID of agent B?
5. Are you getting an exception during the execution, and if so, what is the exception? Run without jit to find out the line numbers for the errors, if possible.
That's all I can think of right now.
-Amy
Sorry but i didn't understand.How i could finally output a tuple into a remote agent?
Hello,
Let me see if I can help out a little. All the information that Liang gave is correct, but let me try to spell it out in a different way.
In your agent, you will create and install a reaction and create a queue (using the Queue from the Lime.gp package if you want). Inside the reactsTo of the reaction, the code will add an element to your queue, something simple like the tuple which triggered the reaction. Periodically the thread of the agent will check the queue to see if there are any elements on it. When there is an element on it, the agent will do the remote out operation.
This works best if your agent thread is not actually doing any work besides responding to reactions and can wait on the queue. The Queue object distributed with Lime allows the agent to wait until there is a data element in the queue (in other words, the agent will be blocked until there is work to do).
Because of the restriction that remote operations are not allowed in reactions, this is the best that you can do.
A different option is to create a separate agent whose only functionality is to react and do the remote out operation. This would free your original agent from the need to periodically check the queue for any work that needs to be done.
I hope this is clear.
Amy
Lines 1617 - 1618 of TransactionMgr has the following:
|| (desc.transType == AGENT_BYE &&
!allTSUniform(currentInitiatedTrans.lts, true)
It appears to be rejecting the initiator's transaction if the transaction is an agent disengagement and at least one of the agent's tuple spaces is not shared.
Why do all of the initiating agent's tuple spaces need to be shared in order for it to disengage?
I think that there is a problem because i try to output a tuple to a remote host's tuple space, which is not local operation.But how i could finally do this out operation?
As I mentioned before, remote operations are not allowed inside a reaction.
The best course of action for you to take is most likely to have the reaction "queue" a message to the agent. The agent then reads this message queue periodically, and when it sees the message from the reaction, the agent performs the remote out. This is a basic mechanism for decoupling the reaction from the remote operation.
-Amy
Thank you very much!
But what do you mean "reaction queue"?How could
implement this ?
I don't think she means an object "reaction queue" but rather she means "make the reaction do an operation that queues an object."
By this she means have the reaction queue an object into a queue that the agent's thread is waiting on. When the object is enqueued, the agent's thread is automatically notified. When the agent's thread is notified, it obtains the queued object and uses it to determine what to do.
The object can be a "DoRemoteOutOperation" object that contains the the tuple to be outputed and the location it should be outputted to.
The Lime distribution comes with gp.util.Queue, which can be used as the queue.
Here's an example:
public class MyAgent extends StationaryAgent implements ReactionListener {
gp.util.Queue myQueue = new gp.util.Queue();
.
.
.
public void reactsTo(ReactionEvent re) {
ITuple react = re.getEventTuple();
AgentLocation al = new AgentLocation(re.getSourceAgent());
myQueue.add(new DoRemoteOutOperation(al, react));
}
.
.
.
public void run() {
while (!done)
{
myQueue.waitOnEmpty();
DoRemoteOutOperation droo = (DoRemoteOutOperation)myQueue.remove();
.
.
.
// do operation ...
.
.
.
}
}
}
You mean that i could use this:
public void run() {
while (!done)
{
myQueue.waitOnEmpty();
DoRemoteOutOperation droo = (DoRemoteOutOperation)myQueue.remove();
.
// do operation ...
.
}
}
}
in order to read the contents of queue from the remote agent?
No you use that within an agent to make its thread perform an operation. This operation may or may not affect a remote agent.
There is a reaction thread comming from the underlying Lime system that calls the public void reactsTo(ReactionEvent re) method within your agent. When this occurs, suppose you want to out a tuple into another agent's tuple space located on another host. To do this, you cannot simply have the body of reactsTo(ReactionEvent re) out a tuple into the remote agent's tuple space. Instead, you must notify the agent's thread to perform this operation. By "agent's thread" I mean "the thread that executes the code within the run() method of your agent." This is usually done by passing a message using a queue. Does this make sense?