oaaconnector.java
来自「SRI international 发布的OAA框架软件」· Java 代码 · 共 310 行
JAVA
310 行
/*
#=========================================================================
# Copyright 2003 SRI International. All rights reserved.
#
# The material contained in this file is confidential and proprietary to SRI
# International and may not be reproduced, published, or disclosed to others
# without authorization from SRI International.
#
# DISCLAIMER OF WARRANTIES
#
# SRI International MAKES NO REPRESENTATIONS OR WARRANTIES ABOUT THE
# SUITABILITY OF THE SOFTWARE, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT
# LIMITED TO THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
# PARTICULAR PURPOSE, OR NON-INFRINGEMENT. SRI International SHALL NOT BE
# LIABLE FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING
# OR DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES
#=========================================================================
*/
package com.sri.oaa2.tools.oaatest;
import java.util.*;
import com.sri.oaa2.com.*;
import com.sri.oaa2.lib.*;
import com.sri.oaa2.icl.*;
/** OaaConnector maintains a connection to the OAA facilitator and records all events from the
* facilitator in an event queue.
*/
class OaaConnector {
/** Make the singleton connection to facilitator. Must be called before
* singleton(). Doesn nothing if already connected.
* @throws ConnectionException if unable to connect
*/
static void connect() throws ConnectionException {
if (singleton != null) {
return;
}
singleton = new OaaConnector();
}
/** Disconnect from the facilitator and destroy singleton. Does nothing if
* not connected.
*/
static void disconnect() {
if (singleton == null) {
return;
}
singleton._disconnect();
singleton = null;
}
/** Slightly different than the usual singleton pattern in that caller must explicitly call
* connect() / disconnect() to create/destroy the singleton object. Will return null if
* not connected.
* @return the singleton OaaConnector object
*/
static OaaConnector get() {
return singleton;
}
/** Ask the StartIt agent to kill itself and any apps it is running. */
void killStartIt() {
IclList params = (IclList)IclUtils.fromString(true,"[reply(none)]");
libOaa.oaaSolve(IclTerm.fromString(true,"kill_and_exit_startit"),
params,new IclList());
}
/** The queue of events coming from the facilitator. A synchronized List of Event. This
* list can be used as a monitor. If the list is empty, caller can wait() on the list and expect to
* be notified when an event is added. */
List getEventQ() {
return eventQ;
}
void flushEventQ() {
eventQ.clear();
}
LibOaa getLibOaa() {
return libOaa;
}
private OaaConnector() throws ConnectionException {
// Connect to facilitator.
LibCom com = new LibCom(new LibComTcpProtocol(),new String[0]);
libOaa = new LibOaa(com);
libOaa.oaaRegisterCallback("app_do_event",
new OAAEventListener() {
public boolean doOAAEvent(IclTerm goal,IclList params,IclList answers) {
return appDoEvent(goal,params,answers);
}
}
);
if (!libOaa.oaaSetupCommunication(AGENT_NAME)) {
throw new ConnectionException();
}
// Register solvables.
if (!libOaa.oaaRegister("parent",AGENT_NAME,
IclTerm.fromString(true, "[tst_ev(Op,Id,Ev)]"),
new IclList())) {
throw new ConnectionException();
}
libOaa.oaaReady(true);
}
/** Should not call any methods on OaaConnector after _disconnect() */
private void _disconnect() {
// Explicitly remove triggers.
setTriggers(null,null);
libOaa.oaaDisconnect(new IclList());
}
private boolean appDoEvent(IclTerm goal,IclList params,IclList answers) {
// Don't need to compute this every time.
final IclTerm tstEvEvent = IclTerm.fromString(true,"tst_ev(Dir,_,Event)");
final IclTerm evSolvedEvent = IclTerm.fromString(true,"ev_solved(_,_,_,_,_,_)");
Event event;
Unifier unifier = Unifier.getInstance();
HashMap bindings = new HashMap();
// The ususal case, receive a tst_ev from a trigger notification.
if (unifier.unify(tstEvEvent,goal,bindings) != null) {
IclTerm dir = (IclTerm)bindings.get("Dir");
if (dir == null) {
throw new RuntimeException("Bug in unification.");
}
IclTerm iclTerm = (IclTerm)bindings.get("Event");
if (iclTerm == null) {
throw new RuntimeException("Bug in unification.");
}
String iclStr = dir.toString();
if (iclStr.equals("send")) {
event = new SendEvent(iclTerm);
}
else if (iclStr.equals("recv")) {
event = new RecvEvent(iclTerm);
}
else {
return false;
}
}
// Something of a hack, temporary bug workaround.
// Treat received ev_solved events like a tst_ev(send,...), or <fromFac>
/* else {
bindings.clear();
if (unifier.unify(evSolvedEvent,goal,bindings) != null) {
event = new SendEvent(goal);
}
else {
return false;
}
}
*/
else {
return false;
}
synchronized (eventQ) {
// Trim eventQ to at least one element less than MAX_EVENTS.
// Remove oldest elements.
while (eventQ.size() >= MAX_EVENTS) {
eventQ.remove(0);
}
// Add to eventQ.
eventQ.add(event);
// An empty queue just had an element added. There may be threads waiting on
// this queue.
if (eventQ.size() == 1) {
eventQ.notifyAll();
}
}
return true;
}
/* Add triggers on facilitator to watch for these events (sent
* or received). Will remove any previous triggers added with setTrigger().
* null or empty list for recv/sendEvents means don't watch for any
* recv/send events, respectively.
*/
public void setTriggers(IclList recvEvents,IclList sendEvents) {
if (triggers == null) {
triggers = new TriggerInfo();
triggers.type = new IclStr("comm");
triggers.condition = IclTerm.fromString(true,"event(E,P)");
triggers.recvAction = IclTerm.fromString(true,
"oaa_Solve(tst_ev(recv,Id,E),[reply(none),address("
+ libOaa.oaaPrimaryAddress() + ")])");
triggers.sendAction = IclTerm.fromString(true,
"oaa_Solve(tst_ev(send,Id,E),[reply(none),address("
+ libOaa.oaaPrimaryAddress() + ")])");
triggers.recvParams = null;
triggers.sendParams = null;
}
else {
// Only remove triggers if added in the first place.
if (triggers.recvParams != null) {
libOaa.oaaRemoveTrigger(triggers.type,triggers.condition,
triggers.recvAction,triggers.recvParams);
triggers.recvParams = null;
}
if (triggers.sendParams != null) {
libOaa.oaaRemoveTrigger(triggers.type,triggers.condition,
triggers.sendAction,triggers.sendParams);
triggers.sendParams = null;
}
}
// At this point, triggers is a valid struct with everything except
// send/recvParams filled in.
if (recvEvents != null && recvEvents.getNumChildren() > 0) {
IclGroup testBody = new IclGroup(
IclTerm.fromString(true,"memberchk(from(Id),P)"),
new IclStruct("memberchk",new IclVar("E"),recvEvents));
testBody.setStarter('(');
testBody.setEnder(')');
IclTerm eventTest = new IclStruct("test",testBody);
triggers.recvParams = (IclList)IclTerm.fromString(true,"[recurrence(whenever),address(parent),on(receive)]");
triggers.recvParams.add(eventTest);
libOaa.oaaAddTrigger(triggers.type,triggers.condition,
triggers.recvAction,triggers.recvParams);
}
else {
// Indication that no trigger added to fac.
triggers.recvParams = null;
}
if (sendEvents != null && sendEvents.getNumChildren() > 0) {
IclGroup testBody = new IclGroup(
IclTerm.fromString(true,"memberchk(address(Id),P)"),
new IclStruct("memberchk",new IclVar("E"),sendEvents));
testBody.setStarter('(');
testBody.setEnder(')');
IclTerm eventTest = new IclStruct("test",testBody);
triggers.sendParams = (IclList)IclTerm.fromString(true, "[recurrence(whenever),address(parent),on(send)]");
triggers.sendParams.add(eventTest);
libOaa.oaaAddTrigger(triggers.type,triggers.condition,
triggers.sendAction,triggers.sendParams);
}
else {
// Indication that no trigger added to fac.
triggers.sendParams = null;
}
}
/*
// Copied from Monitor agent with a few changes.
private void logAllEvents(IclTerm me) {
// Add trigger to trace any events from or to agents.
// Don't trace events coming to/from me, or from any other oaatest or monitor agent.
// Do this in two steps, one for receive and once for send, because
// constraint check is slightly different.
IclTerm recTest = IclTerm.fromString(true, "(memberchk(from(Id),P),agent_data(Id,Type,Status,Sv,Name,Info),not(memberchk(solvable(tst_ev(_,_,_),_,_),Sv)),not(memberchk(solvable(m_ev(_,_,_),_,_),Sv)))");
IclList recParams = (IclList)IclTerm.fromString(true, "[recurrence(whenever),address(parent),on(receive)]");
recParams.add(new IclStruct("test", recTest));
libOaa.oaaAddTrigger(
new IclStr("comm"),
IclTerm.fromString(true, "event(E,P)"),
IclTerm.fromString(true, "oaa_Solve(tst_ev(receive,Id,E),[reply(none),address(" + me.toString() + ")])"),
recParams);
boolean res1 = libOaa.oaaAddTrigger(
new IclStr("comm"),
IclTerm.fromString(true, "event(E,P)"),
IclTerm.fromString(true, "oaa_Solve(tst_ev(receive,Id,E),[reply(none),address(" + me.toString() + ")])"),
IclTerm.fromString()"");[recurrence(whenever),address(parent),on(receive)]
memberchk(E,[event1,event2,s)
IclTerm sendTest = IclTerm.fromString(true, "(memberchk(address(Id),P),agent_data(Id,Type,Status,Sv,Name,Info),not(memberchk(solvable(tst_ev(_,_,_),_,_),Sv)),not(memberchk(solvable(m_ev(_,_,_),_,_),Sv)))");
IclList sendParams = (IclList)IclTerm.fromString(true, "[recurrence(whenever),address(parent),on(send)]");
sendParams.add(new IclStruct("test", sendTest));
libOaa.oaaAddTrigger(
new IclStr("comm"),
IclTerm.fromString(true, "event(E,P)"),
sendParams);
}
*/
private static OaaConnector singleton = null;
private static final String AGENT_NAME = "oaatest";
/** Maximum size of eventQ, will start dropping oldest events when full. */
private static int MAX_EVENTS = 1000;
private LibOaa libOaa;
private List eventQ = Collections.synchronizedList(new LinkedList());
/** Triggers we have installed on facilitator, or null. */
private TriggerInfo triggers;
private static class TriggerInfo {
IclStr type;
IclTerm condition;
IclTerm recvAction;
IclTerm sendAction;
IclTerm recvParams;
IclTerm sendParams;
}
}
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?