<<<<<<<<<<<<<<<<<

lymb_process(prog_tools)Programming Toolslymb_process(prog_tools)

NAME

lymb_process - an encapsulation of a remote LYMB process

DESCRIPTION

The lymb_process object provides a simple mechanism by which another lymb process, either on the same machine or on a different machine on the network, can be created and/or manipulated. It allows users to forward messages to objects on the remote process and retrieve the results of those messages. Unlike the network object, which simply allows users to send strings to be parsed by a remote lymb parser, thereby providing one-way communication, the lymb_process object provides full two-way communication with message passing, argument passing, and argument return.

Output from the remote process is piped back to the stderr (standard error file descriptor) of the local process. This allows the user to see the results of the remote operations, whether they be error messages, output from objects in "debugon!" mode, or output from messages like "print!".

By default, lymb_process operates in synchronous mode. This means that when a message is sent to a remote object, the local process waits until the method invoked on the remote process is completed. This can be overriden by setting the async instance variable. When set to non-zero, no waiting is done, except for query messages, since it must wait to retrieve the arguments returned as a result of the message. (Asynchronous mode is somewhat obsolete. It was added as a means of killing slave processes without hanging the master process. The "close!" message now provides a clean mechanism for doing this.)

There are essentially two ways in which multiple lymb processes can cooperate in a distributed manner. There is the "single master / multi slave" relationship, and the "single server / multi client" relationship.

Master/Slave paradigm

Typically, use of the lymb_process object requires minimal setup. The user simply creates an instance (e.g. with "new:"), sets the name of the host on which the process is to run, and sends a "create!" message to the object. After that, communication with remote objects is simple: Whereas the LYMB statement "<obj> <message_list>;" sends a list of messages to the object named <obj> on the local process, the LYMB statemment "<lymb_process_instance> redirect# <obj> <message_list>;" sends a list of messages to the object

named <obj> on the remote process.

The lymb_process object creates the remote process by using rsh(1) to start up LYMB on a remote machine. Thus, your .rhosts file must be set up to allow rsh commands to be executed on the remote machine. Also, your .cshrc must do whatever is necessary to ensure that your environment is in a state in which it can run LYMB. This means that if important environment variables are defined in your .login file, which is not read during rsh, you will need to rectify this.

When a remote LYMB process is created, it creates a remote instance of the lymb_process object running in "slave mode". In this mode, it establishes socket connections to the master (local) process and does nothing but wait to process requests from the local lymb_process object. The user need not be concerned about this mechanism. However, it *is* possible to use this mechanism to put an existing interactive LYMB session into slave mode on behalf of another master. To do this, the client lymb_process instance is created and initialized. Then it can be asked for its control port number and its stdout port number. On the slave side, this information can be used, along with the hostname of the client process, as arguments to the "slave_mode:" message, which will connect to the client and wait for requests. Then, the client- side lymb_process object can be sent an "accept!" message which then completes the connection.

Although this mechanism is still available to the user, the preferred method of achieving the same result is to take advantage of the Client/Server mechanism by putting the interactive session in "server mode" rather than "slave mode".

Client/Server paradigm

Sometimes it is desireable not to have a "slave" process to act as a workhorse for some master, but rather to have a "server" process resident on a machine such that multiple clients can connect to and disconnect from the server process, sharing its objects and resources. This can be achieved by putting a lymb_process object in "server mode". Once this is done, the lymp_process server creates two ports which client processes can use to connect to the server. The server process remains interactive, and asynchronously (via the io_select object) accepts connection requests from clients. After a

client connects to a server, it can communicate with it in the same way that a master communicates with a slave. Additionally, a client process can "grab" or "lock" the server, so that other clients' requests are blocked until the server is released. A server-mode process can also register itself with the portmapper on that machine, so that clients can connect simply by specifying the hostname. In virtually all situations, a lymb_process object in "client_mode" behaves just like one in "master_mode", and in what follows, "client_mode" will be used to mean either, unless an explicit distinction is made.

SUPERCLASS

object

INSTANCE VARIABLES

lymb_command the command to be used to invoke lymb from the remote shell. The dafault value is "lymb", but it can be changed to point to an absolute path name if necessary.

async boolean instance variable that indicates whether the lymb_process object is in asynchronous mode. If it is, it will not wait for non-query messages to complete on the remote side before returning control on the client side. However, *further* messages cannot be sent until previous ones complete. In older versions, this was used for killing the remote processes. In synchronous mode, sending "redirect# `parser' exit!;" to the lymb_process object will cause problems since it waits forever for an acknowedgement from the now-deceased slave process. Now, the "close!" message can be used to kill the remote process.

hostname the name of the host that the remote process is to run on when it is created with "create!". If not set, or set to the empty string, the remote process will be created on the local machine *without* using rsh, to improve startup performance.

redirect_string contains a string used to redirect stdout and stderr of the remote process to /dev/null so that the startup banner and initial prompt don't get piped back to the client. If this value is not set, the lymb_process object will figure out the appropriate redirection systax based on what shell was used to invoke the local lymb process.

pmap_key contains a string used to identify a particular application-specific lymb server when more than one may be running on a particular machine. The string may contain LETTERS ONLY, and is case insensitive. Only the first six letters in the string are significant. For a server, must be set before the "pmap_register!" message is sent. For a client, must be set before the "connect_to_server:" message is sent.

auto_wait_mode boolean variable. If set in a client, requests made to a locked server will block until they can be processed, rather than immediately returning an error message.

peer_death_actions delegated actions object containing actions for a client-mode process to perform upon death of its peer (either a slave-mode or server-mode process). When the io_select object detects the peer death, it tells the client to close its end of the connection and then execute its peer_death_actions.

MESSAGES

lymb_command[=?] standard string set/get methods

async{=,?,_on!,_off} standard boolean methods

hostname[=?] standard string set/get methods

redirect_string[=?] standard string set/get methods

pmap_key[=?] standard string set/get methods

peer_death_actions[=+?] Messages to manipulate the actions object associated with the death of a slave or server process. These messages get translated to the "tick_actions[=+?]" messages that the actions object understands.

control_portnum? returns the port number of the control socket of an initialized lymb_process (Meaningful mostly for server_mode processes.)

stdout_portnum? returns the port number of the stdout socket of an initialized lymb_process (Meaningful mostly for server_mode processes.)

create! creates a slave process on the host specified by the "hostname" instance variable. The local process acts as master for that slave. If "hostname" is not set, the slave process is created on te local machine without using rsh.

server_mode! Puts the lymb_process instance in server mode, in which it accepts incoming connection requests from clients (via "connect_to_server:"). Sets the port numbers for the control_portnum and stdout_portnum which clients can use to connect to the server.

pmap_register! Registers a server_mode lymb_process object with the port mapper on the machine on which it is running. Only one lymb process may be registered with the port mapper of a machine at any given time.

pmap_unregister! Unregisters the server process from the port mapper.

connect_to_server:(hostname,[cport,oport]) Requests a connection to a server_mode lymb_process object running on "hostname". The local process becomes a client of this server. The second and third arguments are optional. If specified, they indicate the control and stdout port numbers used by the server process. If unspecified, it will ask the port mapper on the remote machine for the port numbers of a lymb_process server registered on that machine.

lock!(grab!) When sent to a lymb_process object in client mode, it locks the corresponding server (or slave) until an "unlock!" or "ungrab!" message is received. While the server is locked, the client has full control of the server. If other clients request its services, those clients return immediately with an error message, unless auto_wait_mode is set for the client, in which case it will block until the server is released. This allows a client to perform a series of server requests as an atomic unit. Although this message may be used to lock a slave mode process, doing so would probably be useless, since slave mode processes are usually dedicated to

the master that created them anyway. However, it is possible to create a slave process, and on that process create an instance of lymb_process running in server mode. In this situation the "master" can lock out other "clients", and vice versa. If a lock attempt is made while the server is currently locked by someone else, the attempt will fail and an error message will be reported.

test_and_set_lock? Similar to the "lock!" message in that it is a non- blocking attempt to lock, but different in that it returns zero on the argument stack if the attempt failed and one if the attempt succeeded. No error message is produced.

wait_and_lock! Blocks until server is unblocked by whatever other client is locking it. When it returns, the issuing client has a lock on the server. If multiple clients are waiting on a locked server when the lock is released, the lock will be granted to one of them in a deterministic (though not necessarily fair) manner.

num_clients_waiting? Asks the server how many of its other clients are currently blocked and waiting for a chance to lock.

unlock!(ungrab!) Releases a server process after a "lock!" or "grab!" message.

status? Returns the status of a client's connection with a server (or slave). They reflect the status codes reported by the network object which created the underlying network connection. "0" means no connection is established, or a connection was closed. "1" is an intermediate state corresponding to an established socket that is not yet connected (this value is unused by lymb_process), and "2" means there is a valid open connection to a server/slave. A value of "-1" means that an error in communication has occurred, most likely due to the death of a slave or server process. This is usually a transient state. If a server or slave process dies, the client will close its connection (thus returning status to "0") as soon as control returns to the io_select object's event processing loop, where the broken connection is detected. Before closing, however, the client-mode instance will execute its "peer_death_actions".

server_lock_status? Returns the lock status of the server that serves the client to whom this message is sent. The return value is one of three integers: "0" means unlocked, "1" means locked by this client, "2" means locked by some other client.

initialize! establishes control and stdout sockets in preparation for an "accept!" (Mainly internal -- user doesn't need this)

accept! waits for a connection from the server process (Mainly internal -- user doesn't need this)

close! closes the connection to the remote (slave or server) process. The remote process exits automatically if it's a slave process, but continues to execute if it's a server process. (This message need not be sent because if the local (client) process terminates for whatever reason, the remote slave process detects this automatically and exits immediately.

slave_mode:<hostname,control_portnum,stdout_portnum> puts process in server mode and waits for requests (Mainly internal -- user doesn't need this)

read! used internally. Processes an incoming request while in server mode.

redirect#<object> causes subsequent messages to be forwarded to <object> on the remote process. Since <object> is an ordinary message argument, it is subject to name evaluation and should therefore be quoted.

local_host? returns the name of the local host.

free! sends itself a "close!" message and frees the object.

print! forwards "print!" to the remote object (after a redirect# message) and modifies the incoming output stream from the remote process so that the text seen by the user indicates the script code needed to create that remote object. For example, if "myproc" is a lymb_process object, and on the remote process is a scalar object named sc1, then upon executing the statement:

myproc redirect# "sc1" print!;

Something similar to the following would be printed:

myproc redirect# "scalar" new: `sc1' /* @ 101cf008 created: 54 modified: 54 */ value= 0.000000 upper= 0.000000 lower= 0.000000 mod= 0.000000 upperoff! loweroff! ;

EXAMPLE

lymb_process new:proc1 hostname="cheetah" create!;

proc1 redirect# "scalar" new: sc1 = 5;

scalar new:sc2 = [proc1 redirect# "sc1" value?];

NOTES

The lymb process maintains a stack of object pointers. This stack is ten levels deep, which means that brackets ("[]") can be nested only 9 levels deep. For example, if x and y are remote objects, the following statement:

proc1 redirect# `x' = [proc1 redirect# `y' value?];

uses two levels of that stack to maintain the pointers for x and y. It would be a rare script that needed more than three levels. Ten should be more than enough.

SEE ALSO

proxy, netclient_filter, netserver_filter, network


Please send comments and suggestions to
consult@rpi.edu