"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 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~