Functionality of the Server Support Library - libtmssl.a v1.0

Created: 5/22/1995

"libtmssl.a" contains a set of functions to make generation of Tsimmis translators and mediators easier. The format and structure "libtmssl.a" is similiar to the original ssl library. "libtmssl.a" is a client to "libtmcomm.a".

"libtmssl.a" provides a default server and a set of "hooks" allowing user to attach translator specific functions to the default server.

Figure 1 shows the interaction between the default server defined in "libtmssl.a" and the functions in "libtmcomm.a". The default server receives requests via "TM_RecvData()". It process the request by calling the hooks that point to user defined functions. The result is send back using "TM_SendObject()" and "TM_SendData()". Then the default server loops back to listen for next request.

                                       |                         ^
                =======================|=========================|=======
                ||                     |                         |      |
                ||  "libtmcomm.a"      |                TM_SendObject() |
                ||                TM_RecvData()         TM_SendData()   |
                ||                     |                         |      |
                ||                     |                         |      |
                ||           ++========|=========================|======+
                ||           ||        V                         |      |
                ||           ||  listen for request <---\        |      |
                ||           ||        |                |        |      |
                ||           ||        V                |        |      | 
                ||============.   decode request        |        |      |
  hooks     <---- tmInit      .        |                |        |      |
  point     <---- tmQuery     .        V                |        |      |
  to user   <---- tmConvert   .    call hook        send result -/      |
  defined   <---- tmFetchObj <---- functions            |               |
  functions <---- tmFetchRef  .                         |               |
            <---- tmShutdown  .                         |               |
            <---- tmCreateRef .                         |               |
            <---- tmFindObj   .                         |               |
                ||    |       .                         |               |
                ||    \-----------> get result ---------/ "libtmssl.a"  |
                ||            .                                         |
                +=======================================================+

        Figure 1, Interaction Between "libtmssl.a" and "libtmcomm.a"

The user defined functions have full access to all the functions and
data types defined in "libtmcomm.a".  These user functions can send
results back to the requester directly if they choose to do so.
However, the return result must follow the partial fetch protocol (see
FETCH.PROTOCOL).

When using the default server in "libtmssl.a", it is very easy to
write a new translator.  The user need only to provide the functions
for the hooks and call default server loop.  A typical main.c for a
translator looks like this:

    void main (int argc, char **argv) {
    
        /* assign my functions to hooks in tmssl */
        tmQuery    = MyQuery;
        tmConvert  = MyConvert;
        tmFetchObj = MyFetchObj;
        tmFetchRef = MyFetchRef;
        tmInit     = MyInit;
        tmShutdown = MyShutdown;

        /* call default server loop */
        TM_DefaultServer(argc, argv);
    }

  
*************
* INTERFACE *
*************

* NORMAL INTERFACE *

"libssl.a" contains the following function variables.  These function
variables are "hooks" allowing user to plug in translator/mediator
specific code to the default server.

        TM_InitHandler       tmInit;
        TM_ShutdownHandler   tmShutdown;

        TM_QueryHandler      tmQuery;
        TM_ConvertHandler    tmConvert;
        
        TM_FetchHandler      tmFetchObj;
        TM_FetchHandler      tmFetchRef;

	TM_FindObjectHandler tmFindObj;
	TM_CreateRefHandler  tmCreateRef;

In addition, this flag variable can be set (see 'tmCreateRef'):

	int tmRecomputeReference	(default value is 1)

--

tmInit

  tmInit points to a user function of following type:

         TM_Error (*) (TM_Data *option);

  This function performs Tsimmis server specific initialization
  routines.  For example, if the Tsimmis server is a translator, this
  user routine may open a connection with the native source.  'option'
  contains generic server options.  The exact content and format have
  yet to be determined.

  This function should return:
  
         TM_NO_ERROR     - init successful, no error
         TM_INIT_FAILED  - init failed
         TM_INIT_TWICE   - init called twice

--

tmShutdown

  tmShutdown points to a user function of following type:

         TM_Error (*) (TM_Data *option)

  This function performs Tsimmis server specific shutdown routines.
  'option' contains generic shutdown options.  The format and content
  have yet to be determined.

  This function should return:

         TM_NO_ERROR     - no error
       
--

tmConvert

  tmConvert points to a user function of following type:
         
        TM_Error (*) (TM_Data *query, char **result)

  This function converts a Tsimmis client query in OEM_QL into a
  native source query.  Tsimmis client query is given in 'query' which
  is a TM_Data.  This TM_Data normally encodes the client query in a
  string.  The resulting native source query should be a string
  returned in the parameter 'result'.

  This function should return:

        TM_NO_ERROR      - no error
        TM_CONVERT_FAILED - unable to convert query to native query
--

tmQuery

  tmQuery points to a user function of following type:

        TM_Error (*) (char *query)

  This function executes a native query in string format in the native
  source. The function can return:

        TM_NO_ERROR      - no error
	TM_QUERY_FAILED	      - general query error
        TM_QUERY_SYNTAXERROR  - query failed at the source due to syntax error
	TM_QUERY_UNSUPPORTED  - query is not supported at source

--

  tmCreateRef

  tmCreateRef points to a user function of following type:

        TM_Data *(*) (TM_Object *object, void *userData)

  This function creates a object reference given a pointer to an object.
  The parameter 'userData' can be used to send any additional data used
  by the user that is needed to create the reference.  An object reference
  is used during partial fetch to quickly locate an object with the
  reference.  Object reference is always treated local to the process.
  It is not meant to be persistant and process independent.

  There is a default function in the SSL library that provides object
  reference creation.  You can use the default function or use your
  own function.   Note that if you use your own object reference, you
  must write your own function for 'tmFindObj' (see below) as well.

  A global variable 'tmRecomputeReference' controls the scope of the
  object reference created by the default function within a process.
  If 'tmRecomputeReference' is set to 1 (the default setting), the
  object reference computed by the default function of SSL library
  is only valid after the last call to 'tmQuery' and before the next
  call 'tmQuery'.  This method helps to detect stale references that
  are passed to the server asking for objects that may no longer exist
  after a new query is submitted.  The drawback is that you will need
  to recompute object references for all your objects after every
  'tmQuery' even the object already has a reference from being part
  of a result from a previous query.

  This function should return:

        (TM_Data *)     - pointer to a TM_Data that encodes a reference
        NULL            - object pointer is NULL

--

  tmFindObj

  tmFindObj points to a user function of the following type:

        TM_Object *(*) (TM_Object *root, TM_Data *reference, void *userData)

  This function treats the given TM_Data as an object reference.  It
  returns the object pointed to by the reference.  'userData' can be
  used by the user to pass in any additional information that may
  be helpful in locating the object.  By convension, 'root' object
  should be returned if 'reference' is NULL or contains a NULL reference.

  There is a default function in the SSL library that provides the
  ability to location object given a reference.  However, this default
  function only understands object references generated by the default
  object reference creation function provided in the SSL library (see
  above).

  This function should return:
        'root'          - 'reference' is NULL or 'reference' contains NULL
        (TM_Object *)   - pointer to object referenced
        NULL            - 'reference' is invalid
        
--

tmFetchObj
tmFetchRef

  tmFetchObj and tmFetchRef are user functions of following type:
        
        TM_Error (*) (TM_ConnEnd    *conn,
                      uint8         fetchType,
                      TM_Data       *objRef,
                      TM_Object     **result)

  tmFetchObj and tmFetchRef retrieves OEM objects or object references
  that are result of the latest query.

  'conn' points to the TM_ConnEnd from which the fetch request
  originates.  This function can send the result directly through
  'conn' to the requestor following the appropriate partial fetch
  protocol.

  'objRef' points to a TM_Data that encodes a "object reference" that
  is implementation specific.  The fetch function can use this "object
  reference" to locate the "root" object of the result.

  'fetchType' can be:
  
        TM_FETCH_ALL      - fetch all objects/references
        TM_FETCH_ONE      - fetch only the root object/reference
        TM_FETCH_CHILDREN - fetch the root plus first level children

  'result' is where the root of the return object should placed.  The
  result is always an TM_Object with zero or more child TM_Object.

  Returning object in 'result' is optional.  The user may decide to
  directly send resulting objects to the requestor by calling
  "libtmcomm.a" functions.  If the user does this, there is no need to
  return anything in 'result'.  When finished, the user can simply
  return TM_NO_ERROR.

  If the user does not send results directly to the requestor, it must
  return the "root" result object in 'result'.  The default server
  will then send the result to the requestor for the user.  In this
  mode, the user sets the 'result' and return TM_NEED_SEND to signal
  the default server that the returned object needs to be send to the
  requestor.

  The fetch function normally work like this if it does not send
  objects directly to the requestor:

      1. Locate the object referenced by "object reference" encoded in
      'refObj'.  If there is no support for "object reference", just
      pick a default object (usually the root object of the entire
      result).  This object is the result object and should be placed
      in 'result'.

      2. Depending on the 'fetchType' flag, attach zero or more child
      objects of the result object to the result object.
      
  In case of tmFetchObj, if 'fetchType' is TM_FETCH_ONE, there is no
  need to attach any child object.  If 'fetchType' is TM_FETCH_ALL,
  all child objects of the result object must be attached.  If
  'fetchType' is TM_FETCH_CHLIDREN, only the first level children of
  the result object are required to be attached.

  In case of tmFetchRef, instead of returning objects that are result
  of some previous query, the result object contains "object
  reference".  The corresponding child objects contains "object
  reference"s of the child objects to the object referenced by
  'objRef'.  Support for tmFetchRef is optional.  If there is no good
  notion of "object reference", there is no need to support
  tmFetchRef.  Then when calling fetch function, pass in NULL as
  'objRef'.

  This function should return:

       TM_NO_ERROR              - no error
       TM_FETCH_FAILED          - unable to fetch result
       TM_INVALID_REFERENCE     - reference invalid
       TM_NULL_RESULT           - result is NULL
       TM_NEED_SEND             - let default server sends the result
       TM_NO_SUPPORT            - fetch option is not supported

* POWER USER INTERFACE *

A simple "libtmssl.a" client does not need to call any functions in
"libtmssl.a" directly.  The client simply setup the 6 hooks mentioned
above and let the default server handles everything.  However, to
provide maximum flexibility, a user may decide to bypass the default
server and write his own server.  In that case, the functions provided
in "libtmssl.a" may be called directly by the user.

To access the default server and functions defined in "libtmssl.a",
include the header file

                   tmssl.h

Inclusion of "tmssl.h" automatically includes "tmconnend.h" and
"tmtypes.h".

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

tmssl.h functions:

        TM_DefaultServer        - starts default server

        TM_SendResult           - send a result using partial fetch protocol
        TM_SendCode             - send a partial fetch protocol code
        
        TM_DefaultSendOne       - send one object using partial fetch protocol
        TM_DefaultSendChildren  - send one object and its 1st level children
        TM_DefaultSendAll       - send one object and all its children

        TM_DefaultFetchRef      - default tmFetchRef function
        TM_DefaultFetchObj      - default tmFetchObj function
        TM_DefaultFetchOne      - default function to fetch one object
        TM_DefaultFetchAll      - default function to fetch all objects
        TM_DefaultFetchChildren - default function to fetch children objects

        TM_CreateObjectReference - create a default "object reference"
        TM_FindObject            - find an object given default "object ref."

        TM_DefaultInit          - default tmInit function
        TM_DefaultShutdown      - default tmShutdown function
        TM_DefaultQuery         - default tmQuery function
        TM_DefaultConvert       - defualt tmConvert function

        TM_ListenForConnection  - default function that listens for connection
                                  on a TCP port

## More detailed explaination ##

       * consult tmssl.c for now *
--

void TM_DefaultServer(int argc, char **argv)

  Starts the default server in "libtmssl.a".  'argc' and 'argv' should
  contain command line options.  The following options are understood
  by the default server:

     -p port_number     - starts server using port_number
     -n                 - do not fork any child process, useful for debugging
     -v                 - verbose mode

  The default server listens on a TCP port for connection.  When a
  connection is requested from a client, the server forks off a new
  process to process request by the client.  (Forking may be disabled
  using "-n" command line option.)  The port on which the server
  listens for connection is determined by the following priority
  rules:

    1. Check for command line optione "-p port_number".  If a port
       number is given, use that port number.
       
    2. If no command line option, check environment variable
       "TSIMMIS_PORT".  If the environment variable is present, use
       the port number stored in the environment variable as the
       listening port.

    3. If no command line option and no environment variable, use the
       compiled default port number 6666.

  RETURNS:
        
        
--

TM_Error TM_SendResult(TM_ConnEnd *conn, TM_Error error)

  Sends a TM_Error code to the remote end using partial fetch protocol.
  'conn' is a valid TM_ConnEnd.  'error' is the error code to be send.
  This function executes synchronously.
  
  RETURNS:
        TM_NO_ERROR     - no error
        TM_ERR_SEND     - unable to send message

--

TM_Error TM_SendCode(TM_ConnEnd *conn, uint32 code, uint32 option)

  Sends a partial fetch protocol  pair to the remote end.
  This function executes synchronously.
  
  RETURNS:
        TM_NO_ERROR     - no error
        TM_ERR_SEND     - unable to send message

--
 
TM_Error TM_DefaultSendOne(TM_ConnEnd *conn, TM_Object *object)

  Sends one TM_Object to the remote end using partial fetch protocol.
  'conn' is a valid TM_ConnEnd.  'object' points to the object to be
  send.  This function executes synchronously.
  
  RETURNS:
        TM_NO_ERROR     - no error
        TM_ERR_SEND     - a network error has occured
        
--

TM_Error TM_DefaultSendChildren(TM_ConnEnd *conn, TM_Object *object)

  Sends one TM_Object and all its first level child objects to the
  remote end using partial fetch protocol.  'conn' is a valid
  TM_ConnEnd.  'object' points to the root object to be send.  This
  function executes synchronously.  
  
  RETURNS:
        TM_NO_ERROR     - no error
        TM_ERR_SEND     - a network error has occured

--

TM_Error TM_DefaultSendAll(TM_ConnEnd *conn, TM_Object *object)

  Sends one TM_Object and all its child objects to the remote end
  using partial fetch protocol.   'conn' is a valid TM_ConnEnd.
  'object' points to the root object to be send.  This function
  executes synchronously.
  
  RETURNS:
        TM_NO_ERROR     - no error
        TM_ERR_SEND     - a network error has occured
        
--

TM_Error TM_DefaultFetchRef(TM_ConnEnd      *conn,
                            uint8           fetchType,
                            TM_Data         *objRefData,
                            TM_Object       **result)

  Sends TM_NO_SUPPORT to the remote end.  This function does not do
  anything interesting.  It can be used as a dummy function for the
  'tmFetchRef' hook when the user does not want to support object
  references.
  
  RETURNS:
        TM_NO_ERROR     - no error
        TM_ERR_SEND   - a network error has occured

--

TM_Error TM_DefaultFetchObj(TM_ConnEnd      *conn,
                            uint8           fetchType,
                            TM_Data         *objRefData,
                            TM_Object       **result)

  Default function for 'tmFetchObj' hook.  Sends objects stored in
  "libtmssl.a" object cache to the remote end.  'conn' is a valid
  TM_ConnEnd.  'fetchType' determines how to fetch the objects.
  'objRefData' points to a TM_Data containing an "object reference"
  produced by TM_CreateObjectReference().  'result' is not used.  This
  function executes synchronously.

  RETURNS:
        TM_NO_ERROR     - no error
        TM_ERR_SEND     - a network error has occured
        
--

TM_Error TM_DefaultFetchOne(TM_ConnEnd  *conn,  TM_Data  *objRefData)

  Sends one object referenced by "object reference" contained in
  'objRefData' to the remote end.  This function executes
  synchronously.
  
  RETURNS:
        TM_NO_ERROR     - no error
        TM_ERR_SEND     - a network error has occured
        
--

TM_Error TM_DefaultFetchAll(TM_ConnEnd  *conn,  TM_Data  *objRefData)

  Sends one object and all its child objects referenced by "object
  reference" contained in 'objRefData' to the remote end.  This
  function executes synchronously.  
  
  RETURNS:
        TM_NO_ERROR     - no error
        TM_ERR_SEND     - a network error has occured
        
--

TM_Error TM_DefaultFetchChildren(TM_ConnEnd  *conn,  TM_Data  *objRefData)

  Sends one object and all its first level child objects referenced by
  "object reference" contained in 'objRefData' to the remote end.
  This function executes synchronously.  
  
  RETURNS:
        TM_NO_ERROR     - no error
        TM_ERR_SEND     - a network error has occured

--

TM_Data *TM_CreateObjectReference(TM_Data *parentRef, uint32 index)

  Creates an object reference based on an existing object reference
  and an integer.  If the given 'parentRef' is NULL, this routine
  returns an object reference that is appropriate for a root object.
  For example, if you want to create an object reference using this
  function for a TM_Object "Oa" whose parent is another TM_Object
  "Op".  Then, 'parentRef' should be the object reference of "Op".
  'index' is the intiger indicating which child of "Op" "Oa" is.  This
  number can be obtain as the return value from a call to
  TM_ObjectAppendChild(Op, Oa). 
  
  RETURNS:
             - a pointer to TM_Data that encodes object ref.
        NULL            - unable to assign object reference

--

TM_Object *TM_FindObject(TM_Object *startObj, TM_Data *objRef)

  Finds object with given object reference pointed by 'objRef'.  The
  search starts with 'startObj' as the root object.  'objRef' must
  point to an object reference created by TM_CreateObjectReference().

  RETURNS:
           - pointer to found object
        NULL            - object with reference not found

--

TM_Error TM_DefaultInit(TM_Data *option)

  Default function for 'tmInit' hook.  Does nothing.

  RETURN:
        TM_INIT_FAILED          - don't know how to perform init

--

TM_Error TM_DefaultShutdown(TM_Data *option)

  Default function for 'tmShutdown" hook.  Does nothing

  RETURN:
        TM_NO_ERROR             - no error

--

TM_Error TM_DefaultQuery(char *query)

  Default function for 'tmQuery' hook.  Does nothing

  RETURN:
        TM_QUERY_FAILED         - don't know how to handle the query

--

TM_Error TM_DefaultConvert(TM_Data *original, char **result)

  Default function for 'tmConvert' hook.  This function just extracts
  the string from the 'orginal' and return the string in 'result'.
  This function can be used if the input query is in native form
  already.
  
  RETURNS:
        TM_NO_ERROR             - no error
        TM_CONVERT_FAILED       - unable to convert

--

int TM_ListenForConnection(int portNumber, int dynamic)

  Creates a TCP stream socket for listening incoming connections.
  This procedure attempts to use portNumber given for listening.  If
  that port is in use and dynamic flag is 1, it dynamically searches
  for an open port to bind.  If dynamic flag is 0 and portNumber if in
  use, it will exit with -1.

  Upon receiving a connection request, this function normally forks
  another process.  The new process will return with an integer
  greater than 0.  This integer is the new socket that is connected
  with the remote end.  The original process will continue listen for
  more connections until an interrupt from the user.

  If the global variable 'tmFork' is 0, this function does not fork
  any new process.  Upon receiving a connection request, it will
  return with a new socket that is connected with the remote end.
  Setting 'tmFork' to 0 is very useful during debugging.
 
  RETURNS:
        = 0             - finished listening
        > 0             - a client is connected via returned socket number
        < 0             - a network related error occured
        
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~