INFO ON CSL/SSL LIBRARIES v. 1.0

Important Changes Affecting Wrappers and Mediators


This info is intended for all those who are working on wrappers or mediators that use CSL/SSL v1.0. Technical details will follow. The CSL/SSL v1.0 library has been updated to fix a few bugs as well as add a few new features. If your program links with "libtmcomm.a", "libtmssl.a", or "libtmcsl.a", you need to recompile your program to make sure that it still works. If you are writing Tsimmis wrapper or mediator that is intended to be able to connect with Mobie browser, you HAVE TO modify your program to support the partial fetch protocols now. If you don't modify your program, Mobie browser will not be able to perform partial fetch with your wrapper or mediator. Partial fetch can be supported by your wrapper in two ways. The simplest way is to rely on the SSL library to handle everything. The other way (preferred) is to provide "native" partial fetch ability. If you rely on SSL to do partial fetch, your wrapper will retrieve all objects from the native source after a query as before. Then you can pass the objects to the SSL library. SSL library caches the objects in memory and performs partial fetch on the cached objects. This kind of partial fetch will be called "default partial fetch" from now on. As usuall, the SSL library and CSL library contains a set of built-in default functions to support the default partial fetch behaviors without the need to make big modifications to your program. If you plan on using the preferred "native" partial support, you wrapper will have to be "smarter". You will need to provide (partial) objects from any portion of the result object space on demand. You can use your own caching scheme or using the partial fetch ability of your "native" source. This method is harder to implement than the previous one since it requires you to rewrite the way you fetch objects from the native source. The following describes the minimal set of things that you need to do in order for SSL library to handle partial fetch for you. (i.e. you need to do the following to have the default partial fetch ability.)

  1. In your "tmFetchObj" function, you can no longer return an error message if the fetch type is not TM_FETCH_ALL. You "tmFetchObj" must also be able to be called multiple times after a query is submitted.
  2. You can not send objects directly in your "tmFetchObj" function. You must return the root (the "answer" object) of your objects in the function parameter "result" and return TM_NEED_SEND. You should do this regardless which fetch type is requested.
  3. Whenever you create an object with TM_NewObject(...), you should add the following:
    	     obj = TM_NewObject(...);
    	     TM_ObjectSetOid(obj, tmCreateRef(obj, NULL)); /* add this */
    
    You may not use your own kind of object id unless you are willing to write two more functions (see *).
  4. Note that the default scope of object referenced created by above method is between the last tmQuery() call and the next tmQuery() call. So if you plan to reuse an in-memory object across tmQuery() invokation, you must either recompute an object reference or set the SSL global variable "tmRecomputeReference" to 0. * The functional variable "tmCreateRef" is one of two new hooks added to CSL/SSL. The other hook is "tmFindObj". These hooks are for you to attach your custom object reference creation and object search methods. There are default functions for these two hooks in the SSL library. If you change one of the hook, you must change the other one since the default "tmFindObj" assumes the object reference format created by the default "tmCreateRef" function. For now, if you decide to use the default SSL partial fetch ability, you have no need to change either hooks from their respective default functions. But you must use object reference created by "tmCreateRef". Here is an example of the modified fetch function for Sybase wrapper. Changes from the previous version are marked by /* -- BEGIN CHANGE -- */ and /* -- END CHANGE -- */.
      /* **********************************************************************
       * SybaseFetch -- Fetches result from last executed query.
       * This function calls Sybase library function to extract all tuples
       * from the query.  Then OEM objects are created based on the tuples
       * extracted.  This function can be called repeatly after a query is
       * submitted.  However, it only retrieves objects from Sybase source
       * at most once after every query.
       *
       * RETURNS:
       *      TM_NO_ERROR             - no error
       *      TM_QUERY_FAILED         - query failed
       * **********************************************************************/
      TM_Error SybaseFetch(TM_ConnEnd    *conn,
    		       uint8         fetchType,
    		       TM_Data       *objRef,
    		       TM_Object     **result)
      {
          TM_Object   *root;
          TM_Error    err;
          DBPROCESS   *dbproc;
          RETCODE     retCode;
    
          if ((sDB == NULL) || (querySuccess == 0)) {
    	  return TM_FETCH_FAILED;
          }
    
      /* -- BEGIN CHANGE -- */
      /*
       * the following is now commented out since the function needs to
       * support all fetch types.
       */
      /*    if (fetchType != TM_FETCH_ALL) {
    	  return TM_NO_SUPPORT;
          } 
      */
      /* -- END CHANGE -- */
    
          answerObj.flags = 0;
          answerObj.label = "answer";
          answerObj.type  = "set";
    
      /*
       * The global variable 'needFetch' variable is used to ensure that this 
       * function retrieves at most once from Sybase source after every query
       * submission.  The variable is set to '1' in the 'tmQuery' function.
       */
          if (needFetch) {
    	  dbproc = sDB->dbproc;
    	  while ((retCode = dbresults(sDB->dbproc)) != NO_MORE_RESULTS) {
    	      if ((retCode == SUCCEED) && (DBROWS(sDB->dbproc))) {
    		  if (ExtractOEMResult(sDB->dbproc, &answerObj,
    				       tupleName, single) != TM_NO_ERROR) {
    		      return TM_FETCH_FAILED;
    		  }
    	      }
    	  }
    	  needFetch = 0;
          }
    
      /* BEGIN CHANGE */
      /*
       * If you want to use SSL library to perform partial fetch, you should
       * not send your objects in this function.  You must let the SSL to
       * send the objects for you.  Alternatively, you can copy the code
       * from "tmssl.c" to do your own version of send which must
       * understand how to fetch the correct objects and send them
       * depending on the fetch type.
       */
       /*   return TM_DefaultSendAll(conn, &answerObj); */
    
    
      /*
       * You must now return the root objects (regardless of the fetch type)
       * in the "result" parameter.  You must return TM_NEED_SEND to signal
       * SSL library to send the objects for you.  Note that this function
       * does not delete the objects before it returns since the SSL library
       * rely on the existance of these objects for partial fetch.
       *
       * This function also does not worry about the fetch type.  SSL library
       * takes care of finding the needed objects using the returned pointer
       * to the "root" object.  This function always returns the full object
       * tree.
       */
          *result = &answerObj;
          return TM_NEED_SEND;
      /* END CHANGE */
      }
    
    If you are interested in producing a "native" partial fetch wrapper, please contact Jiang (jwu@db.stanford.edu). We suspect that the above mentioned method will work ok for now since it requires minimal changes. Feel free to contact Jiang if you have any problems or encounter bugs.