Updated for new CCS version.
authorOrion Lawlor <olawlor@acm.org>
Wed, 3 Jan 2001 02:32:42 +0000 (02:32 +0000)
committerOrion Lawlor <olawlor@acm.org>
Wed, 3 Jan 2001 02:32:42 +0000 (02:32 +0000)
doc/converse/ccs.tex

index 7fd7b5f5dc5ec4d560deb73dfa6c2de77b460fab..bd3409aa1509cd62991cacc80835dd057c6194b0 100644 (file)
 \chapter{\converse{} Client-Server Interface}
 
-This note attempts at explaining the design of \converse{} client-server (CCS) 
-module. This
-module is responsible for enabling parallel servers to be written using
-\converse{}. Currently, this module is implemented on most of the parallel
-machines supported by \converse{}.
-
-The CCS module is split into two parts. One part consists of functions that can
-be used in \converse{} programs which act as servers. The other part consists of
-functions that can be used with clients that try to connect to servers written
-using CCS. The following sections describe both these parts. \kw{charmrun} is
-sometimes also referred to as {\tt server-host} in order to distinguish it from
-the individual \converse{} processes which are sometimes referred to as {\tt
-server-processes}. Together, the {\tt server-host} and the {\tt
-server-processes} constitute a server. In general, the client does not need to
-know the difference.
+This note describes the \converse{} client-server (CCS) 
+module. This module enables \converse{} programs to act as
+parallel servers, responding to requests from (non-\converse{}) programs
+across the internet.
 
+The CCS module is split into two parts-- client and server. 
+The server side is the interface used by a \converse{} program;
+the client side is used by arbitrary (non-\converse{}) programs.
+The following sections describe both these parts. 
+
+A CCS client accesses a running \converse{} program by talking to
+a {\tt server-host}, which receives the CCS requests and relays them
+to the appropriate processor.  The {\tt server-host} is \kw{charmrun}
+for net- versions, and is the first processor for all other versions.
 
-\section{CCS: Server-Side}
 
-On the network of workstations, any \converse{} program is started using
+\section{CCS: Starting a Server}
+A \converse{} program is started using
 \begin{alltt}
 charmrun pgmname +pN charmrun-opts pgm-opts
 \end{alltt}
-In addition to the original options, now \kw{charmrun} accepts one more option:
-{\tt ++server}.  Currently this option makes \kw{charmrun} print out its own
-(randomly allocated) port number, which can then be used to connect to it from
-the client. Note that this is the same port number over which the processes
-belonging to the server contact \kw{charmrun} (for \kw{CmiPrintf} etc.)
-
-In addition to the usual commands (aset, aget etc.), conv-host now accepts one
-more command {\tt getinfo} over the abovementioned port. This command is issued
-only by the client and not by any of the constituent server processes. The
-response to {\tt getinfo} command is as follows: 
-\[info \, N \, P_{0} \, P_{1} \, .. \, P_{N} \, IP_{0} \, IP_{1} \, .. \,
-IP_{N} \, Port_{0} \, Port_{1} \, .. \, Port_{N} \]
-
-Where \(N\)  is the number of SMP nodes, \(P_{i}\)  are number of processors in
-node i, \(IP_{i}\) is the IP address as an integer for node i, \(Port_{i}\) is
-the control port number of the server process on node i.
-
-If this command is received before all the server processes report to {\tt
-conv-host}, the response is delayed. Internally, the server processes execute
-{\tt CcsInit()}, which makes {\tt CcsEnabled()} return {\tt  1}. On
-architectures that do not yet support CCS functionality, all the CCS functions
-do not do anything, and all the functions that return boolean values return
-{\tt  0}.
-
-In the server-processes, a new type of handler mechanism is introduced. These
-handlers have a character string associated with it that identifies the handler
-function. These handlers are registered using a {\tt  CcsRegisterHandler()}.
-The handler index returned by {\tt  CcsRegisterhandler() } can be used for
-normal remote invocation too. ({\tt CcsRegisterHandler} internally calls
-\linebreak {\tt CmiRegisterHandlerLocal}.)
-
-Handler functions responsible for remote requests have the same syntax and
-semantics as the normal \converse{} handlers. However, in the handler function
-invoked by a remote request, {\tt CcsIsRemoteRequest() } returns {\tt  1}.
-Also, in that case, {\tt  CcsCallerId() } returns meaningful values for IP
-address and Port of the caller. No message format conversion is actually done
-by the runtime system and is the responsibility of the handler and the client.
-Once the server process gets hold of IP and port of the caller, it can use that
-anytime for replying to the client using {\tt  CcsSendReply } function.
-
-\function{void CcsInit(void);} 
-\index{CcsInit}
-\desc{Initializes some internal variables that CCS uses.}
-
-\function{int CcsRegisterHandler(char *id, CmiHandlerFn fn);}
-\index{CcsRegisterHandler}
-\desc{Register the handler function {\tt fn} with the handler identified by
-{\tt id}.  Returns the id number of the handler.}
+\kw{charmrun} also accepts the CCS options:
 
-\function{void CcsUseHandler(char *id, int hdlr);}
-\index{CcsUseHandler}
-\desc{Add the handler name specified by {\tt id} to the list of handlers,
-with the handler number specified by {\tt hdlr}.  This function is used by
-{\tt CcsRegisterHandler()}}
+{\tt ++server}: open a CCS server on any TCP port number
 
-\function{int CcsEnabled(void);}
-\index{CcsEnabled}
-\desc{Returns 1 if CCS is enabled}
+{\tt ++server-port}=$port$: open the given TCP port as a CCS server   
 
-\function{int CcsIsRemoteRequest(void);}
-\index{CcsIsRemoteRequest}
-\desc{Returns non-zero if the caller is remote.}
-
-\function{void CcsCallerId(int *pip, int *pport);}
-\index{CcsCallerId}
-\desc{Assigns the caller's IP addres to {\tt pip} and the port number to 
-{\tt pport}.}
+As the parallel job starts, it will print a line giving the 
+IP address and TCP port number of the new CCS server.
+The format is: ``ccs: Server IP = $ip$, Server port = $port$ \$'',
+where $ip$ is a decimal version of the native byte order 
+server IP address, and $port$ is the decimal port number.
 
-\function{void CcsSendReply(int ip, int port, int size, void *msg);}
-\index{CcsSendReply}
-\desc{Send a message to the CCS client with the IP address and port specified
-by {\tt ip} and {\tt port}.  {\tt size} indicates the number of bytes in the
-message, which is referenced by the pointer {\tt msg}.}
 
 \section{CCS: Client-Side}
 
-The client program calls {\tt  CcsConnect()} for contacting the server. This
-call will internally send the {\tt getinfo } command to the server-host and
-will wait for the server information to arrive. This information can be
-extracted using the calls such as {\tt  CcsNumNodes()}, {\tt CcsNumPes()}, {\tt
-CcsNodeFirst()}, and {\tt CcsNodeSize}. Requests can be made to individual
-server-processes of any node using {\tt CcsSendRequest()}, and response can be
-received using {\tt CcsRecvResponse()}. The latter is a blocking function. In
-addition to this, a {\tt CcsProbe} is available to check if the response is
-received, and {\tt CcsResponseHandler} is provided to invoke the specified
-function similar to an interrupt handler. No effort is made by the runtime to
-serialize multiple requests made to the server as well as responses received
-from the server. {\tt CcsFinalize()} could be used to terminate the
-request-response session with the server. Note that no assumption has been made
-about the persistence of the underlying connection, thus the implementation is
-free to choose whatever is appropriate. All functions return {\tt  -1 } on
-error.
-
-\function{int CcsConnect(CcsServer *svr);}
-\index{CcsConnect}
+A CCS client connects to a CCS server, asks a server PE to 
+execute a pre-registered handler, and receives the response data.
+The CCS client may be written in any language (see CCS network protocol,
+below), but a C interface (files ``ccs.c'' and ``ccs.h'') and Java
+interface (file ``CcsServer.java'') are available at 
+charm/pgms/converse/ccstest/.
 
-\function{int CcsNumNodes(CcsServer *svr);}
-\index{CcsNumNodes}
+The C routines use the skt\_abort error-reporting strategy;
+see ``sockRoutines.h'' for details.  The C client API is:
 
-\function{int CcsNumPes(CcsServer *svr);}
-\index{CcsNumPes}
+\function{void CcsConnect(CcsServer *svr, char *host, int port);}
+Connect to the given CCS server.  svr points to a pre-allocated
+CcsServer structure.
 
-\function{int CcsNodeFirst(CcsServer *svr, int node);}
-\index{CcsNodeFirst}
+\function{void CcsConnectIp(CcsServer *svr, int ip, int port);}
+As above, but a numeric IP is specified.
 
+\function{int CcsNumNodes(CcsServer *svr);}
+\function{int CcsNumPes(CcsServer *svr);}
+\function{int CcsNodeFirst(CcsServer *svr, int node);}
 \function{int CcsNodeSize(CcsServer *svr,int node);}
-\index{CcsNodeSize}
+These functions return information about the parallel machine;
+they are equivalent to the \converse{} calls CmiNumNodes,
+CmiNumPes, CmiNodeFirst, and CmiNodeSize.
+
+\function{void CcsSendRequest(CcsServer *svr, char *hdlrID, int pe, 
+                    unsigned int size, const char *msg);}
+Ask the server to execute the handler hdlrID on the given processor.
+The handler is passed the given data as a message.  The data may
+be in any desired format (including binary). 
+
+\function{int CcsRecvResponse(CcsServer *svr, 
+                    unsigned int maxsize, char *recvBuffer, int timeout);}
+Receive a response to the previous request in-place.
+Timeout gives the number of seconds to wait before returning 0;
+otherwise the number of bytes received is returned. 
+
+\function{int CcsRecvResponseMsg(CcsServer *svr, 
+                    unsigned int *retSize,char **newBuf, int timeout);}
+As above, but receive a variable-length response.  The
+returned buffer must be free()'d after use.
 
-\function{int CcsSendRequest(CcsServer *svr, char *hdlrID, int pe, uint size, void *msg);}
-\index{CcsSendRequest}
+\function{int CcsProbe(CcsServer *svr);}
+Return 1 if a response is available; otherwise 0.
 
-\function{int CcsRecvResponse(CcsServer *svr, uint maxsize, void *recvBuffer);}
-\index{CcsSendRequest}
+\function{void CcsFinalize(CcsServer *svr);}
+Closes connection and releases server.
 
-\function{int CcsProbe(CcsServer *svr);}
-\index{CcsProbe}
 
-\function{int CcsResponseHandler(CcsServer *svr, CcsHandlerFn fn);}
-\index{CcsResponseHandler}
+The Java routines throw an IOException on network errors.
+Use javadoc on CcsServer.java for the interface, which mirrors
+the C version above.
 
-\function{int CcsFinalize(CcsServer *svr);}
-\index{CcsFinalize}
 
+\section{CCS: Server-Side}
+
+Once a request arrives on a CCS server socket, the CCS server 
+runtime looks up the appropriate handler and calls it.
+If no handler is found, the runtime prints a diagnostic
+and ignores the message.
+
+CCS calls its handlers in the usual \converse{} fashion--
+the request data is passed as a newly-allocated message,
+and the actual user data begins CmiMsgHeaderSizeBytes
+into the message.  The handler is responsible for CmiFree'ing
+the passed-in message.
+
+The interface for the server side of CCS is included in 
+``converse.h''; if CCS is disabled (in conv-mach.h), all
+CCS routines become macros returning 0.
+
+The handler registration interface is:
+
+\function{void CcsUseHandler(char *id, int hdlr);}
+\function{int CcsRegisterHandler(char *id, CmiHandler fn);}
+Associate this handler ID string with this function.  
+hdlr is a \converse{} handler index; fn is a function pointer.
+The ID string cannot be more than 32 characters, including the
+terminating NULL.
+
+
+
+These calls can be used from within a CCS handler:
+
+\function{int CcsEnabled(void);}
+Return 1 if CCS routines are available (from conv-mach.h).
+This routine does not determine if a CCS server port is 
+actually open.
+
+\function{int CcsIsRemoteRequest(void);}
+Return 1 if this handler was called via CCS; 0 if it was
+called as the result of a normal \converse{} message.
+
+\function{void CcsCallerId(unsigned int *pip, unsigned int *pport);}
+Return the IP address (native byte order) and TCP port number
+of the CCS client that invoked this method.
+Can only be called from a CCS handler invoked remotely.
+
+\function{void CcsSendReply(int size, const void *reply);}
+Send the given data back to the client as a reply.
+Can only be called from a CCS handler invoked remotely.
+
+\function{CcsDelayedReply CcsDelayReply(void);}
+Allows a CCS reply to be delayed until after the handler
+has completed.  Returns a token used below.
+
+\function{void CcsSendDelayedReply(CcsDelayedReply d,int size, const void *reply);}
+Send a CCS reply for the given request.  Unlike
+CcsSendReply, can be invoked from any handler on any processor.
+
+
+\section{CCS: system handlers}
+The CCS runtime system provides several built-in CCS handlers,
+which are available in any \converse{} job:
+
+\kw{ccs\_getinfo}
+Takes an empty message, responds with information about the parallel
+job.  The response is in the form of network byte order (big-endian) 4-byte 
+integers: first the number of parallel nodes, then the number of processors
+on each node.  This handler is invoked by the client routine CcsConnect.
+
+\kw{ccs\_killport}
+Allows a client to be notified when a parallel run exits (for any reason).
+Takes one network byte order (big-endian) 4-byte integer: a TCP port
+number. The runtime writes ``die\\n'' to this port before exiting.
+There is no response data.
+
+\kw{perf\_monitor}
+Takes an empty message, responds (after a delay) with performance data.
+When CMK\_WEB\_MODE is enabled in conv-mach.h, the runtime system collects
+performance data.  Every 2 seconds, this data is collected on processor
+0 and sent to any clients that have invoked perf\_monitor on processor 0.
+The data is returned in ASCII format with the leading string "perf", 
+and for each processor the current load (in percent) and scheduler message
+queue length (in messages).  Thus a heavily loaded, two-processor system
+might reply with the string ``perf 98 148230 100 385401''.
+
+
+\section{CCS: network protocol}
+This information is provided for completeness and clients written
+in non-C, non-Java languages.  The client and server APIs above are
+the preferred way to use CCS.
+
+A CCS request arrives as a new TCP connection to the CCS server port.
+The client speaks first, sending a request header and then the request
+data.  The server then sends the response header and response data,
+and closes the connection.  Numbers are sent as network byte order
+(big-endian) 4-byte integers-- network binary integers.
+
+The request header has three fields: the number of bytes of request data,
+the (0-based) destination processor number, and the CCS handler identifier
+string.  The byte count and processor are network binary integers (4 bytes
+each), the CCS handler ID is zero-terminated ASCII text (32 bytes); for
+a total request header length of 40 bytes.  The remaining request data
+is passed directly to the CCS handler.
+
+The response header consists of a single network binary integer-- the 
+length in bytes of the response data to follow.  The header is thus 4 
+bytes long.  If there is no response data, this field has value 0.