Agent Foundation Classes (AFC): FAQ






I assume each incoming message spawns a process_message, up
to MAX_THREADS threads (including other running callbacks),
but what happens when this is exceeded?


No this is not the case in fact. None of the AFC agents use threading.
If they do use threading then this is because the compiler will
choose threading libraries but this can be turned of as well.
Deciding not to use a threading model was done on purpose for a number
of reasons. First of all not all platforms support threading (PalmOS).
Second, as you already noticed an agent might run into operating system
boundaries, which are not necessarily realistic. I chose to apply an
event based mechanism, whereby ultimately the operating system is
responsible for the workload of buffering data. Each open socket
contains an incoming message queue (an outgoing queue can be configured
but is disabled for now I believe) This incoming message queue is set to
store 100 messages by default but can be adjusted in real time in case
of high traffic. If you want to change the size of the queue for all
agents by compiling in a new value then add: "set_queue_size (200);"
within the constructor of the CClientBase class. File: "c_client.cpp".

There is no ordering of messages as they come in. In that respect
each AFC agent is truly asynchronous. The Communicator or agent
shell could be easily rigged to oversee ordering of messages however.
Each message is already assigned a parser when it comes in. You can
therefor already make certain inferences about it's content and use
that to either internally route the message or apply ordering.
The Communicator can also be used to monitor traffic load. It has
access to all the sockets and can evaluate how many of the queues are
reaching maximum capability:

 (N Sockets * N Messages) / (N Sockets * 100) = Load %

There is a global timer or hearbeat that is present in all agents.
This heartbeat is as of yet not propagated to the Communicator but
can be by adding a call within the agent container "c_container.cpp".
A timer could periodically check the agent's message load. This
mechanism is already used to check connection integrity to such
infrastructure components as: MiddleAgents, Agent Name Servers and
visualization clients.

I don't know if you guys use the agents I wrote for the PRET project
but a good start to see how an agent handles high load would be to
look at the SAFBroker.

Hope this helps, let me know if you need more information.


Question: Why not use the Standard C++ Library for agent classes?


I just downloaded the RETSINA AFC developer's guide. I saw the use of
plain char pointers and a home-grown list class. Why not use the
Standard C++ Library? It would be nice to program agents in C++ instead
of Java, because I am more familiar with it. But working with char*,
lots of new & delete and non-standard container classes scares me: it's
just too much work!


There are 4 reasons why we did not choose to use the standard
C++ datastructures such as STL:

1) They are not standard and differ from compiler to compiler
   and platform to platform. 

2) The second reason that we did not choose to use STL for our 
   datastructures was that the AFC needed to be compiled on a 
   variety of platforms that may not support some or all features 
   present in STL and other C++ libraries. For example, we have a 
   version that compiles under PalmOS and we even have a MicroAFC 
   edition that could easily fit on certain micro-controllers. 
   WindowsCE, PalmOS and Linux on StrongARM have no concept of

3) There is another reason why we did not go with STL. All of the 
   datastructures present in the AFC can be streamed into an ACL 
   string. This allows agent developers to move or share entire sets 
   of datastructures between two agents. If we had used pre-existing 
   implementations present in either C++ or any of the standard 
   libraries such as STL we would not have been able to do this.
   For example, the CString class does not allow you to do:
    CString a_string="Hello World";
    a_string->to_string ();

   The output in KQML would be:
    :string (Hello World)

   or in XML:

    Hello World

4) We have an experimental version of the AFC that breaks out to:
   Java,Tcl/Tk,Guile and Python. One of the requirements we found
   while doing this was that it would require a large amount of work
   to bind the CString class to any other language since we would
   have to write shadow versions in each of the languages. Instead
   we could make direct mappings from a 'char *'

As you can see there are a lot of directions in which the development
of the AFC was pulled and which determined it's current implementation.
I hope this answers your question.

Question: How do I create a socket and a string packet? Hi How do I create a TCP/IP (or UDP) socket and write a string to the TCP/IP packet and send it out. Does AFC have the class for this? PS. Do you have any more document about AFC? I prefer examples with documentation. Answer:(more complete answer in AFC Users' Manual: Part V, page 83): There is defenately a UDP socket available through the AFC. The discovery client uses it. Here is a small snippet on how to use it: // include core AFC libraries -------------------------------------- #include "c_afc.h" // create the socket ----------------------------------------------- // the socket_handler variable is a CWnd pointer since you will want // to have events be received when something arrives on the socket // this will come into play when you use the code below to add custom // sockets to AFC agents. CDataGramSocket *m_unicast=new CDataGramSocket (sock_handler); if (m_unicast->Create ()==FALSE) { AfxMessageBox ("Error creating socket"); delete m_unicast; return; } // connect to remote system ---------------------------------------- BOOL response=m_unicast->Connect ("",23); // telnet I think if (response==FALSE) { delete m_unicast; AfxMessageBox ("Unable to connect to remote machine"); } // send data through the socket ------------------------------------ int socket_ret=m_unicast->mfc_send ("Hello World"); if (socket_ret==SOCKET_ERROR) AfxMessageBox ("Unablet to sebd data to remote machine"); // and we're done -------------------------------------------------- delete m_unicast; // ----------------------------------------------------------------- Question: How do I create a socket and a string packet? (cont'd) Is mfc_send() a function in the MFC distribution or RETSINA? I could not find this function anywhere. What could the "send" function for the UDP or TCP socket? Answer: The mfc_send method is part of the CClientSocket class and should be available to all raw TCP/IP sockets derived from it. The name is slightly deceptive since it suggests that it only works under windows. The method itself is actually a generalized socket send call that takes a string and will attempt to send it through the socket. The method assumes the socket has been created and connected. If you want to use the MFC socket calls for sending then I would suggest you use the 'Send ()' method. This method takes 3 parameters. The first one is a pointer to the actual string to be send. The second parameter indicates the length of the data and the third parameter is one that is mostly used for internal purposes and the AFC sets it to 0. In fact, under Windows the AFC method mfc_send will make a call to Send. Question: Why do I get an error when trying to send a message? Hi What could be the possibility of Segmentation Fault when one Agent trying to send a message to another agent? Message format? I add codes similar to Example One that came with the RETSINA distribution. The example is that AgentA sends a mesage to AgentB when its timer is expired. Basically, my agent receives some data from a UDP socket and convert to a string. Then, I put the string into a message and send it to another agent. Whenever it tries to send a message, I got the Window Dialog error box and the program is frozen. Please help. Answer: In order to track down what is going wrong here I would like to propose a number of steps. These steps will determine where the problem lies roughly. 1) Find out if there are any AFC DLL's lying around from previous versions. You can do this by comparing the timestamp of the DLL's found in %RETSINA%/system/dll to the AFC DLL's you find in your windows directory. Sometimes people find that they have previous DLL's in their executable directory which are loaded instead of the ones from the Windows directory. 2) In the code where you send the string, replace the point to that string and send a static string like "Hello World" instead. If your agent still crashes then it might be a problem with the AFC. I would like to rule out any problems associated with pointers being given to the Communicator. 3) Make sure that the last parameter you give to the 'send_message' method is NULL. There is a situation where we actually give more parameters than the standard ones we use for KQML. You need to use NULL as the last parameter to indicate to the Communicator that the last parameter was the content field. If neither of these steps fixes the problem then let me know and I will come over to see what the problem is.

AFC Internal Site (Restricted Access)




Copyright 2001-2009 © The Intelligent Software Agents Lab - The Robotics Institute - Carnegie Mellon University

We welcome your comments and suggestions: nospam-retsina at cs dot cmu dot edu

Internal Site (Restricted Access)