📄 oaa.pl
字号:
% We'll always have exactly one oaa_solvables fact. Note that application
% code should NOT include a declaration or clause for oaa_solvables/1.
oaa_solvables([]).
%*****************************************************************************
% Initialization and connection functions
%*****************************************************************************
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% name: oaa_SetupCommunication
% purpose: Establishes default communications connections for a client agent
% inputs:
% remarks:
% - If oaa_listen argument is given, opens a listener socket, so the client
% can handle requests by direct connection.
% - Attempts to connect to facilitator at address indicated by oaa_connect
% or default_facilitator parameter in command line, environment
% variable, or setup file (see com_Connect, in com_tcp.pl).
% - com_Connect (which see) provides some retry options.
% - FAILS if connection to the facilitator cannot be established, and
% prints a simple error message.
% - After performing local initializations, and calling this procedure,
% the default client agent should also call oaa_MainLoop(true).
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
oaa_SetupCommunication(InitialAgentName) :-
( oaa_ResolveVariables([
[cmd('-oaa_listen',RequestedAddress)],
[env('OAA_LISTEN', RequestedAddress)],
[setup(_, oaa_listen, RequestedAddress)]
]) ->
% Open the server connection:
( com:com_ListenAt(client_listener,
[resolve_vars(false)], RequestedAddress, ServerAddress) ->
%oaa:icl_fac_id(MyId),
%com_AddInfo(fac_listener, [oaa_id(MyId)]),
format('Listening at ~p~n~n', [ServerAddress])
| otherwise ->
format('Unable to open a listener connection; continuing without it~n~n', [])
)
| otherwise ->
true
),
( oaa_Connect(parent, _Address, InitialAgentName, []) ->
true
| otherwise ->
format('Unable to connect to facilitator~n', []),
( com:com_connection_info(client_listener, _, _, _, connected) ->
format('Closing listener at ~p~n~n', [ServerAddress]),
oaa_Disconnect(client_listener, _)
| otherwise -> true),
fail
).
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% name: oaa_Connect(+ConnectionId, ?Address, +InitialAgentName, +Params).
% purpose: Connect and handshake with the agent listening on Address,
% or, if Address is a var, allow com_Connect to find
% the address.
oaa_Connect(ConnectionId, Address, InitialAgentName, Params) :-
com:com_Connect(ConnectionId, Params, Address, ActualCInfo),
format('Connected to ~p.~n',[ActualCInfo]),
oaa_handshake(ConnectionId, InitialAgentName, Params).
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% name: oaa_Disconnect
% purpose: Disconnect the given comm link.
% inputs:
% - ConnectionId: A symbolic connection Id associated with an open
% comm link
% - Params: Not currently used; reserved for future enhancements
% Params argument of com_Disconnect
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
oaa_Disconnect(ConnectionID, _Params) :-
com:com_Disconnect(ConnectionID).
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% name: oaa_Register
% purpose: Once a comm link is established, either as a client to a Facilitator
% or as a server for other agents, oaa_Register will setup and registration
% information for this agent.
% inputs:
% - ConnectionId: the symbolic connection Id (client or server connection)
% - AgentName: the name of the agent
% - Solvables: solvable list
% - Params:
% unique_name(T_F) [false]: if 'true', instructs the facilitator
% that this agent should only be registered if no other agents
% are registered with the same name.
%
% Exceptions:
% agent_name_in_use: returned if unique_name(true) is in Params, and
% another agent with AgentName is already registered.
%
% The following information is stored about the current connection,
% accessible through com_GetInfo(ConnectionId, Info):
%
% oaa_name(Name) : the name of the current agent
% oaa_address(A) : the address for the agent
% connection(C) : system-level communications handle
% (e.g., socket number)
%
% if connecting as client, these are also available:
% other_address(A) : the Facilitator's address
% other_name(Name) : the Facilitator's name
% other_language(L) : the Facilitator's language
% other_dialect(D) : the Facilitator's dialect (quintus, sicstus)
% other_version(V) : the Facilitator's agent library version
%
% In addition, the following predicates are written to parent Facilitator,
% or locally if the ConnectionId is a server connection:
%
% agent_host(Address, Name, Host)
%
% Solvables are also written using oaa_Declare()
%
% It is possible for an agent to create both server and client connections.
% If this agent is a facilitator, it's classified as an agent of class "node"
% (as opposed to a pure client "leaf" or pure server "root").
% If this agent is a non facilitator (leaf), then its server socket
% enables it to accept requests by direct connection. (However, it
% still is required to be a client of some facilitator.)
%
% examples:
% % connecting to a Facilitator
% MySolvables = [do(something)],
% com_Connect(parent, [], ConnectionRequest, ActualConnection),
% oaa_Register(parent, my_agent_name, MySolvables, []).
%
% % connecting as a Facilitator
% MySolvables = [],
% com_ListenAt(fac_listener, ConnectionInfo),
% oaa_Register(fac_listener, root, MySolvables).
%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% For connecting to a Facilitator
oaa_Register(ConnectionId, InitialAgentName, Solvables, Params) :-
% Am I a facilitator or client?
oaa_type(Type),
% Four backwards compatibility, we check to see if handshaking
% has already occurred. In pre-3.2 (internal version number),
% handshaking was always performed by oaa_Register.
( com:com_GetInfo(ConnectionId, other_name(_)) ->
true
| otherwise ->
oaa_handshake(ConnectionId, InitialAgentName, Params)
),
oaa_Address(parent, _, MyAddress),
% get host info
( environ('HOST', MyHost) ->
true
| otherwise -> true ),
% Do I have a listener Port?
( Type == facilitator ->
oaa_PrimaryAddress(MyListenAddress)
| otherwise ->
( com:com_GetInfo(client_listener, oaa_address(MyListenAddress)) ->
true
| otherwise -> true )
),
% The actual AgentName isn't necessarily the same as InitialAgentName;
% InitialAgentName may have been overridden by command line arguments
oaa_Name(AgentName),
( ground(MyHost) ->
oaa_AddData(agent_host(MyAddress, AgentName, MyHost),
[address(parent)])
| true),
( ground(MyListenAddress) ->
oaa_AddData(agent_listener(MyAddress, MyListenAddress),
[address(parent)])
| true),
% Declare solvables (and post to parent facilitator):
% Note: OK if Solvables = [].
oaa_Declare(Solvables, [], [], [if_exists(overwrite)], _),
% check any builtin command-line args actions
oaa_command_actions.
% For Facilitator serving client agents
% Note: no need to check for oaa_name cmdline argument; facilitator code
% already does that.
oaa_Register(ConnectionId, AgentName, Solvables, _Params) :-
% succeeds only if exists an open connection for ConnectionId
% as created by com_ListenAt()
com:com_connection_info(ConnectionId, _Protocol, server, _Info, connected),
oaa_Address(fac_listener, _, MyAddress),
com:com_AddInfo(ConnectionId,
[oaa_name(AgentName)]),
% The fac. records its own agent_data in the same way as its clients'.
% Note that we can't call oaa_add_data_local until after the solvables
% have been declared, and we can't declare solvables until we're
% open - so we have to bootstrap this assertion.
% IMPORTANT: by special convention, the type for the facilitator
% is unbound.
oaa_assertz(
agent_data(MyAddress, _Type, open, [], AgentName, []),
MyAddress, _, true),
% Note: OK if Solvables = [].
oaa_Declare(Solvables, [], [], [if_exists(overwrite)], _),
% write host
( environ('HOST', MyHost) ->
oaa_add_data_local(agent_host(MyAddress, AgentName, MyHost),[])
| true),
% check any builtin command-line args actions
oaa_command_actions.
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
% name: oaa_ResolveVariables(+VariableList)
% purpose: Tries to instantiate the arguments by looking in the command
% line arguments, environment variables, and setup files
% inputs:
% - VarList: A list of lists: the first sublist that completely resolves
% provides the value for oaa_ResolveVariables.
% remarks:
% sublists may contain elements in the following format:
% env(EnvVar, Val) : looks for "EnvVar" in environment vars
% env_int(EnvVar, Val) : Returns value for EnvVar as an integer
% cmd(CmdVar, Val) : looks for "CmdVar <Val>" on command line
% setup(File,SVar, Val) : reads SVar from setup file File
% example:
% resolves host and port by searching first commandline, then environment
% variables, finally reads setup file.
%
% oaa_ResolveVariables([
% [cmd('-oaa_host',Host), cmd('-oaa_port', Port)],
% [env('OAA_HOST', Host), env_int('OAA_PORT', Port)],
% [setup('setup.pl',oaa_host, Host),
% setup('setup.pl',oaa_port, Port)]
% ])
%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
oaa_ResolveVariables([VarList|_]) :-
oaa_resolve_variables(VarList), !.
oaa_ResolveVariables([_VarList|Rest]) :-
oaa_ResolveVariables(Rest).
oaa_resolve_variables([]).
oaa_resolve_variables([env_int(EnvVar, Val)|Rest]) :- !,
environ(EnvVar, EnvAtom),
name(EnvAtom, EnvChars),
number_chars(Val, EnvChars),
oaa_resolve_variables(Rest).
oaa_resolve_variables([env(EnvVar, Val)|Rest]) :- !,
environ(EnvVar, ValAtom),
oaa_parse_cmd_value(ValAtom, Val),
oaa_resolve_variables(Rest).
oaa_resolve_variables([cmd(CmdVar, Val)|Rest]) :- !,
% get command line arguments
unix(argv(ListOfArgs)),
append(_, [CmdVar, ValAtom|_], ListOfArgs),
oaa_parse_cmd_value(ValAtom, Val),
oaa_resolve_variables(Rest).
%% 0-argument command (conceptually equivalent to "-command true")
oaa_resolve_variables([cmd(CmdVar)|Rest]) :- !,
% get command line arguments
unix(argv(ListOfArgs)),
memberchk(CmdVar, ListOfArgs),
oaa_resolve_variables(Rest).
oaa_resolve_variables([setup(File, SVar, Val)|Rest]) :- !,
% read setup file to load all values
oaa_read_setup_file(File),
Pred =.. [SVar, Val],
on_exception(_, Pred, fail),
oaa_resolve_variables(Rest).
oaa_parse_cmd_value(Value, Value) :-
number(Value),
!.
% This clause is for structures with arguments.
% We restrict it by checking for '(', because we do NOT want
% strings such as /tmp/filename to be parsed here.
% We'll also parse single-quoted atoms here.
oaa_parse_cmd_value(ValAtom, Value) :-
name(ValAtom, ValChars),
( memberchk(0'(, ValChars) ;
nth0(0, ValChars, 0'') ),
concat_atom([ValAtom, '.'], StoppedAtom),
name(StoppedAtom, Chars),
on_exception(_,
oaa_read_from_chars(Chars, Value),
fail),
!.
%'
oaa_parse_cmd_value(ValAtom, Value) :-
name(ValAtom, Chars),
on_exception(_, number_chars(Value, Chars), fail),
!.
oaa_parse_cmd_value(ValAtom, ValAtom).
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% name: oaa_read_setup_file
% purpose: Finds and loads setup file
% remarks:
% Always succeeds.
% The search path for the setup file is as follows:
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -