⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 liboaa.java

📁 SRI international 发布的OAA框架软件
💻 JAVA
📖 第 1 页 / 共 5 页
字号:
/*
 * @(#)LibOaa.java  08/1999
 *
 * The contents of this file are subject to the OAA Community Research
 * License Version 2.0 (the "License"); you may not use this file except
 * in compliance with the License. You may obtain a copy of the License
 * at http://www.ai.sri.com/~oaa/.  Software distributed under the License
 * is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, either
 * express or implied. See the License for the specific language governing
 * rights and limitations under the License.  Portions of the software are
 * Copyright (c) SRI International, 1999.  All rights reserved.
 * "OAA" is a registered trademark, and "Open Agent Architecture" is a
 * trademark, of SRI International, a California nonprofit public benefit
 * corporation.
*
*/

package com.sri.oaa2.lib;

import java.io.*;
import java.util.*;
import java.lang.String;
import java.net.*;
import com.sri.oaa2.com.*;
import com.sri.oaa2.icl.*;

import edu.emory.mathcs.backport.java.util.concurrent.ArrayBlockingQueue;
import edu.emory.mathcs.backport.java.util.concurrent.CountDownLatch;
import edu.emory.mathcs.backport.java.util.concurrent.locks.ReentrantLock;

import org.apache.log4j.Logger;
import org.apache.log4j.LogManager;
import org.apache.log4j.xml.DOMConfigurator;


//DEBUG
//import com.sri.oaa2.guiutils.CChronometer;

/**
 * This class provides all the facilities to make an application become
 * an agent in an Open Agent Architecture community.
 *
 * <h3>Usage</h3>
 * <h4>Creating the OAA library</h4>
 * <p>
 * To create an agent, create a new instance of the OAA library, passing some
 * communication protocol object to use as the transport layer:
 *
 * <pre>
 * LibOaa myOaa = new LibOaa(new LibCom(new LibComTcpProtocol()));
 * </pre>
 *
 * Then, register any callbacks for agent events.  Usually, you must
 * at least define the callback <code>app_do_event</code> type to handle incoming
 * <code>oaaSolve()</code> requests.
 * In this example, we link the callback to a function <code>myOAADoEvent</code>,
 * which we must later define to handle all capabilities our agent registers with the
 * Facilitator.
 * (see <code>oaaRegister()</code> below).
 *
 * <pre>
 *   myOaa.oaaRegisterCallback("app_do_event",
 *     new OAAEventListener() {
 *     public boolean doOAAEvent(IclTerm goal, IclList params, IclList answers) {
 *       return myOAADoEvent(goal, params, answers);
 *     }
 *     });
 * </pre>
 *
 * <h4>Connecting the agent to the facilitator</h4>
 * Early on in an agent's lifecycle, it must connect to a Facilitator agent who will
 * manage it's communication with other agents. The agent must call the
 * method <code>oaaSetupCommunication</code>.
 * The name of the agent is supplied as the only argument to this method as follows:
 * <pre>
 *     // First, connects to the facilitator
 *     if (!myOaa.oaaSetupCommunication("myAgent")) {
 *     printError("Could not setup");
 *     return;
 *     }
 * </pre>
 * There are three ways to specify the facilitator address, listed here in
 * order of preference:
 * <ul>
 *     <l1>
 * 1. Specify the default facilitator in the "setup.pl" file. This file
 * is located in the home directory on unix and the root c:\ drive on windows.
 * The default facilitator is specified using the "default_facilitator" struct.
 * For example, the following entry specifies that the faciitator is located
 * on "myhost.ai.sri.com" listening on port 4020:
 * <pre><code>
 * %%%% SETUP FILE FOR OAA %%%%%%%
 * default_facilitator(tcp('myhost.ai.sri.com',4020)).
 * </code></pre>
 *     </li>
 *     <li>
 * 2. The "oaa_connect" command line parameter may be used. For example,
 * <code>" -oaa_connect "tcp('myhost.ai.sri.com',4020)"</code>
 *     </li>
 *     <li>
 * 3. The "OAA_CONNECT" System property may be set to the facilitator address.
 * The syntax is the same as the "-oaa_connect" command line parameter.
 *     </li>
 * </ul>
 * "setup.pl" is always checked first, followed by the command line and then
 * the system property.
 * <p>
 *
 * <h4>Enabling direct_connect</h4>
 * <p>
 * When a client agent sends a request to the facilitator, the facilitator forwards
 * the request to one or more agents, receives the responses and then forwards
 * the responses back to the calling agent. This means any data passed in
 * the communications must be passed through the facilitator. A better solution
 * is to pass the data directly from the calling agent to an agent which can
 * solve the request.
 * </p>
 * <p>
 * To allow this optimization it is possible to specify the parameter
 * "direct_connect(true)" when calling oaaSolve. In order for direct_connect
 * to be possible, the following conditions must hold:
 * <ul>
 *     <li>
 * 1. There must be only one agent which can solve the request. direct_connect
 * does not currently support mulitple solves from multiple agents.
 *     </li>
 *     <li>
 * 2. The agent which has registered the solvable must be enabled for direct_connect.
 * As described below, the "oaa_listen" command line variable is specified
 * to enable an agent for direct_connect.
 *     </li>
 * </ul>
 * </p>
 * <p>
 * If these conditions hold and the "direct_connect(true)" parameter is
 * specified, oaaSolve will attempt to make a direct connection to the
 * appropriate agent in order to solve the request. Once a connection has been
 * made it is cached for later use. The connection is terminated when the
 * call to <code>oaaDisconnect(IclList)</code> is made.
 * </p>
 * <p>
 * Note that "oaaSetupCommunication" sets up an agent listener for direct_connect.
 * It checks the command line variable "oaa_listen" to retrieve the address
 * to listen for direct connections. For example, if the command line
 * <code>' -oaa_listen "tcp('localhost',4012)" '</code> is supplied, the
 * OAA library will open a listen socket on port 4012 used to accept direct
 * connections. If the "oaa_listen" command line parameter is not found,
 * then the System property "OAA_LISTEN" is checked.
 * </p>
 * <p>
 * Also supported is a binary protocol for efficient data transfer. In the
 * current release, this requires another server port for a direct_connect
 * enabled agent. The binary server port defaults to the direct_connect
 * port with ten added to it. So, in the above example the agent will listen
 * on ports 4012 and 4022. The need for a second listen port is temporary and may be
 * removed in a future release of OAA. To set the second listen port manually,
 * the command line variable "oaa_listen_binary" or system property
 * "OAA_LISTEN_BINARY" may be used.
 * </p>
 * <p>
 * In addition to the <code>direct_connect</code> parameter, an <code>address</code>
 * parameter may also be specified when calling oaaSolve. Specifying the
 * <code>direct_connect</code> and <code>address</code> parameters provides
 * the fastest performance OAA can give. The <code>address</code> parameter
 * can be retrieved by invoking the <code>agent_host</code> solvable with
 * the agent's name. For example, the following code retrieves the agent
 * address for an agent by name, and then uses the address and direct_connect
 * parameter to achieve maximum performance:
 * <pre><code>
 *   public String getAgentAddress(LibOaa myOaa, String agentName) throws Exception {
 *       IclList res = new IclList();
 *
 *       myOaa.oaaSolve(IclTerm.fromString(true,
 *               "agent_host(Addr,'" + agentName + "',Host)"), new IclList(), res);
 *
 *       if (res.size() == 0) {
 *           throw new Exception("Unable to retrieve agent address using agent_host");
 *       }
 *       String agentAddr = res.getTerm(0).getTerm(0).toString();
 *       return agentAddr;
 *   }
 *
 *   private IclList solveParams = null;
 *   public IclList callOaaMaximumPerformance(LibOaa myOaa, IclTerm goal) throws Exception {
 *       if (solveParams == null) {
 *           // Retrieves the name of the agent. Note: in order to use
 *           // this method the name of the agent must be known.
 *           String agentAddress = getAgentAddress(myOaa, "myServerAgent");
 *           solveParams = new IclList();
 *           solveParams.add(new IclStruct("direct_connect", new IclStr("true")));
 *           solveParams.add(new IclStruct("address", IclTerm.fromString(true,agentAddress)));
 *       }
 *
 *       IclList res = new IclList();
 *
 *       myOaa.oaaSolve(goal, solveParams, res);
 *
 *       if (res.size() == 0) {
 *           throw new Exception("No answers found");
 *       }
 *
 *       return res;
 *   }
 * </code></pre>
 * Note that in the above example code the agent address is retrieved only once
 * since this is an expensive operation. If the method <code>callOaaMaximumPerformance</code>
 * is called repeatedly it will perform better than regular direct_connect
 * without the address.
 * </p>
 * <p>
 * Finally, a method for detecting whether or not direct_connect was successful
 * is possible specifying the <code>"get_direct_connect_used"</code> out parameter
 * in <code>oaaSolve</code>. For example, if oaaSolve is called and one of the
 * parameters is <code>"get_direct_connect_used(_)"</code>, when the solve call returns
 * this parameter is replaced with <code>"get_direct_connect_used(true)"</code>
 * if direct_connect was successfull and <code>"get_direct_connect_used(false)"</code>
 * if direct_connect was not used or was not successfull.
 * </p>
 *
 * <h4>Registering the agent</h4>
 * Once a low-level communication connection has been established, an agent registers its
 * name and published services across this connection.  In this example, the agent named
 * "fax_db" publishes that it can provide the service of finding a fax number given a
 * person name.  The default connection name for <code>comConnect()</code> and <code>
 * oaaRegister()</code> should be "parent", which represents the Facilitator agent.
 * <pre>
 *     // Then, once the connection is established, performs handshaking with the facilitator
 *     if (!myOaa.oaaRegister("parent", "fax_db", IclTerm.fromString("[fax_num(Person,Num)]"))) {
 *     printError("Could not register");
 *     return;
 *     }
 *  </pre>
 *  When the agent has finished all initializations and is ready to receive requests from
 *  the agent community, it must let the Facilitator know that it is ready.
 *
 *  <pre>
 *     myOaa.oaaReady(true);
 *  </pre>
 *
 *  That's it!  Incoming requests will arrive in the function <code>
 *  myOAADoEvent(goal, params, answers);</code> where the agent will parse the
 *  goal, try to solve the request, and return 0 (failure), 1 (success), or
 *  more solutions in the answers list.  To accomplish the goal, the agent may need
 *  to make use of communication requests to other members in the agent community
 *  using the <code>oaaSolve()</code> or other library functions.
 *
 * <h4>Disconnecting the agent</h4>
 * The agent can disconnect all connections by invoking the
 * <code>oaaDisconnect</code> method.
 *
 * <p>
 * <hr>
 * <H2>Event communication patterns for OAA primitives</H2>
 * <p>
 * Asynchronous communication events between client agents and a facilitator
 * are at the heart of the agent library and facilitator implementations.
 * Here we describe the communication message activity for the OAA
 * primitives defined in an OAA library.
 * <p>
 * <pre>
 *  <li>Handshaking between Client and Facilitator at startup time:
 *
 * <b><i>  oaaRegister(ConnectionId, AgentName, Solvables, Params) </b></i>
 *      client->Fac:  ev_connect(AgentInfoList)
 *      client<-Fac:  ev_connected(FacInfoList)
 * <p>
 *  <li>Notification to facilitator that client is ready to participate:
 * <b><i>  oaaReady(ShouldPrint)              </b></i>
 *      client->Fac:  ev_ready(SymbolicName)
 * <p>
 *  <li>Registration of client solvables and data declaractions with Facilitator:
 * <b><i>  oaaDeclare(Solvs,CPerms,CParams,Params,-Declared),    </b></i>
 * <b><i>  oaaUndeclare(Solvs,Params,-Undeclared),      </b></i>
 * <b><i>  oaaRedeclare(Solvs,Params,-Redeclared),      </b></i>
 * <b><i>  oaaDeclareData(Solvs,CPerms,CParams,Params,-Declared)  </b></i>
 *      client->Fac:  ev_post_declare(Mode,Solvs,P)  Mode = add,remove,replace
 *      if client agent is a NODE facilitator
 *        node->parent:    ev_register_solvables(Mode,Solvs,MyName,P)
 *      client<-Fac:  ev_reply_declared(Mode, Solvs, P, Declared)
 * <p>
 *  <li>Delegation of simple or compound goals across agent community:
 * <b><i>  oaaSolve(G,P)                      </b></i>
 *      client->Fac:  ev_solve(GoalId, G,P)
 *      If no clients can solve G
 *        Fac->Parent:    ev_post_solve_from_fac(Id, G, P)
 *        Fac<-Parent:    ev_reply_solved_by_fac(Id, S, G, P,Sols)
 *      else
 *        Fac->client:    ev_solve(GoalId, G, P)
 *        Fac<-client:    ev_solved(Id, Requestees, Solvers, G, P, Solutions)
 *        client<-Fac:   ev_solved(GoalId, Responders, S, G, P, Sols)
 * <p>
 *  <li>Delegation/manipulation of data across agent community:
 * <b><i>  oaaAddData(D,P),      </b></i>
 * <b><i>  oaaRemoveData(D,P),  </b></i>
 * <b><i>  oaaReplaceData(D,P)  </b></i>
 *      client->Fac:  ev_update_data(GoalId,Mode,D,P)  Mode = add,remove,replace
 *      Fac->client:    ev_update_data(GoalId, Mode, D, P),
 *      Fac<-client:    ev_data_updated(GoalId, Mode, D, P, Sols)
 *      client<-Fac:  ev_data_updated(GoalId, Mode, D, P, Responders, Sols)
 * <p>
 *  <li>Installation/removal of triggers delegated across agent community:
 * <b><i>  oaaAddTrigger(D,P), oaaRemoveTrigger(D,P)    </b></i>
 *      client->Fac:  ev_update_trigger(GoalId,Mode,T,C,A,P)  Mode = add,remove
 *      Fac->client:    ev_update_trigger(GId, Mode,T,C,A,P),
 *      Fac<-client:    ev_trigger_updated(Id,Mode,T,C,A,P,Requestees,Updaters)
 *      client<-Fac:  ev_trigger_updated(Id,Mode,T,C,A,P,Requestees,Updaters)
 * </pre>
 * <p>
 * @author    Didier Guzzoni
 * @author    Adam Cheyer
 * @author    David Martin
 * @author    Ruth Lang * @version  %I%, %G%
 */
public class LibOaa extends Thread {

  /**
   * Property name for the OAA library log4j configuration file.
   */
  public static final String OAA_LOG_CONFIG_FILE = "oaa.log.config.file";

  /**
   * Default property value for the OAA library log4j configuration file.
   */
  public static final String
    OAA_LOG_CONFIG_FILE_DEFAULT = "/com/sri/oaa2/oaa_log_config.xml";

 // setup logging in this static initializer
 static {
   System.out.println("Initializing OAA library");
   // Is OAA already initialized?
   Enumeration allLoggers = LogManager.getLoggerRepository().getCurrentLoggers();
   boolean initLog4J = true;
   if (allLoggers != null) {
     while (allLoggers.hasMoreElements() && initLog4J) {
         Logger logger = (Logger) allLoggers.nextElement();

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -