/*!---------------------------------------------------------------------
  @file           ven03.c
  @author         JoergM
  @brief          communication / USER

\if EMIT_LICENCE
\endif
\if EMIT_LICENCE


    ========== licence begin  GPL
    Copyright (c) 2003-2005 SAP AG

    This program is free software; you can redistribute it and/or
    modify it under the terms of the GNU General Public License
    as published by the Free Software Foundation; either version 2
    of the License, or (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program; if not, write to the Free Software
    Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
    ========== licence end


\endif
---------------------------------------------------------------------*/




/*===========================================================================*
 *  INCLUDES                                                                 *
 *===========================================================================*/

#include <ctype.h>

#include "gsp01.h"
#include "gsp09.h"
#include "geo003.h"
#include "geo007_1.h"
#include "geo007_2.h"
#include "geo03.h"
#include "heo03.h"
#include "geo40.h"
#include "geo401.h"
#include "heo46.h"
#include "geo001.h"
#include "geo57.h"
#include "gen003.h"
#include "gen23.h"
#include "gen33.h"
#include "gen41.h"
#include "gen42.h"
#include "gen43.h"
#ifdef  DEBUG_RTE
#include "gen46.h"
#endif
#include "heo07.h"
#include "RunTime/System/RTESys_MicroTime.h"
#include "heo420.h"

/*===========================================================================*
 *  DEFINES                                                                  *
 *===========================================================================*/

#define MOD__ "ven03.c:"

#if defined (STATIC_CONNECTIONS)
#define VALID_REF_INL(ref)      (((ref) > 0) && ((ref) <= MAXCONNECTIONS))
#define CONNECTION_AT_INL(ref)  (&sql03_connection [ref])
#define CONNECTION_ARRAY        sql03_connection
#define MAXCONNECTIONS_INL      MAXCONNECTIONS
#else
#define VALID_REF_INL(ref)          \
    (((ref) > 0) && ((ref) <= sql03_connect_pool.connectionCount))
#define CONNECTION_AT_INL(ref)  (&sql03_connect_pool.connection [ref])
#define CONNECTION_ARRAY        sql03_connect_pool.connection
#define MAXCONNECTIONS_INL      (sql03_connect_pool.connectionCount)
#endif

#define SQL_PACKET_ALIGNMENT 8
#define CHECK_PID_EN03 1

/*===========================================================================*
 *  MACROS                                                                   *
 *===========================================================================*/

#define  ALIGN_BUFFER(_val,_alignment)                                               \
           ((((_val) - 1) / (_alignment) + 1 ) * (_alignment))

/*===========================================================================*
 *  LOCAL CLASSES, STRUCTURES, TYPES, UNIONS ...                             *
 *===========================================================================*/

typedef struct ten03_connect_pool {
    tsp00_Bool          initialized;
    int                 connectionCount;
    connection_info    *connection;
    tsp00_Bool          isMultiThreaded;
    teo07_MutexFunction *createMutex;
    teo07_MutexFunction *destroyMutex;
    teo07_MutexFunction *lockMutex;
    teo07_MutexFunction *unlockMutex;
    teo07_Mutex          mutex;
} ten03_connect_pool;


/*===========================================================================*
 *  GLOBAL VARIABLES                                                         *
 *===========================================================================*/

/* exported functions */
global  void    sql03_split_dbname ( char                   *serverdb,
                                     char                   *servernode );
global void sql03_init_multi_threaded ( teo07_MutexFunction *createMutex,
                                        teo07_MutexFunction *destroyMutex,
                                        teo07_MutexFunction *lockMutex,
                                        teo07_MutexFunction *unlockMutex);

static void           sql03_init ( void );
static void           sql03_finish ( void );

void                (*sql01_init_com)()   = sql03_init;
void                (*sql01_finish_com)() = sql03_finish;

/*===========================================================================*
 *  LOCAL VARIABLES                                                          *
 *===========================================================================*/

static  SIGNALFUNCTYPE                  (*sql03_oldsighup)()      = SIG_ERR;
static  SIGNALFUNCTYPE                  (*sql03_fetched_sigint)() = SIG_DFL;
static  SIGNALFUNCTYPE                  (*sql03_oldsigpipe)()     = SIG_ERR;
static  SIGNALFUNCTYPE                  (*sql03_oldsigalrm)()     = SIG_ERR;
static  SIGNALFUNCTYPE                  (*sql03_oldsigterm)()     = SIG_ERR;
static  unsigned                        sql03_oldalarm;
static  time_t                          sql03_oldclock;
static  pid_t                           sql03_pid;
#if defined (STATIC_CONNECTIONS)
static  connection_info                 sql03_connection [ MAXCONNECTIONS ];
#endif
static  connection_info                *sql03_cip;
static  tsp00_Int4                        sql03_receiving;
static  char                            sql03_nodeseparatorlist [] =
    NODESEPARATORLIST;

static ten03_connect_pool sql03_connect_pool = {
            FALSE,      /* initialized          */
            0,          /* connectionCount      */
            NULL,       /* connection           */
            FALSE       /* isMultiThreaded      */
        };

static            tsp00_Bool fNI_Installed        = FALSE;


/*===========================================================================*
 *  STATIC/INLINE FUNCTIONS (PROTOTYPES)                                     *
 *===========================================================================*/

/*------------------------------*/

static  int            sql03_connect (char              *servernode,
                                      tsp00_DbNamec     serverdb,
                                      int               service,
                                      int               packet_cnt,
                                      tsp00_Int4        *reference,
                                      tsp00_Int4        *max_reply_packet_size,
                                      tsp00_Int4        *sql_packet_size,
                                      void              **sql_packet_list,
                                      char              *dbroot,
                                      char              *serverpgm,
                                      connection_VMT    *vmt,
                                      tsp00_ErrTextc     pErrText );

static  int            sql03_release ( tsp00_Int4         reference,
                                       tsp00_ErrTextc   errtext );

static  int            sql03_request ( tsp00_Int4    reference,
                                       void       *packet,
                                       tsp00_Int4    length,
                                       tsp00_ErrTextc      errtext );

static  int            sql03_replyavailable ( tsp00_Int4         reference,
        tsp00_ErrTextc   errtext );

static  int            sql03_receive ( tsp00_Int4     reference,
                                       void       **packetp,
                                       tsp00_Int4    *lengthp,
                                       tsp00_ErrTextc errtext );

static  int            sql03_cancel ( tsp00_Int4      reference,
                                      tsp00_ErrTextc errtext );

static  int            sql03_dump ( tsp00_ErrTextc errtext );

static  int            sql03_get_protocol ( char            *Node,
        connection_info *cip,
        tsp00_ErrTextc   ErrTExtC);

static  tsp00_Int4       sql03_find_free_index ( void );
static  char          *sql03_statename ( connection_info *cip);
static  void           sql03_set_signals ( void );
static  void           sql03_reset_signals ( void );
static  void           sql03_set_alarm ( unsigned interval);
static  void           sql03_reset_alarm ( void );
static  SIGNALFUNCTYPE sql03_catch_signal ( int sig );
static  void           sql03_init_connections ( ten03_connect_pool* connectPool,
        int firstIndex,
        int count);
static  void           sql03_finish_connections ( void );
static  int            sql03_init_connect_pool (ten03_connect_pool* connectPool);
static  tsp00_Int4       sql03_alloc_connect ( void );
static  int            sql03_free_connect (int ref, char** msg);

static void en03InitConnParam (char                      *Node,
                               teo003_ConnectParamRecord *pConnParam,
                               connection_info           *cip );


static int en03GetAndCheckConnectionInfo( tsp00_Int4          reference,
        tsp00_Int4          CheckPid,
        connection_info  ** ConnectionInfo,
        char              * CallingFktName,
        tsp00_ErrTextc      pErrText );
/* PTS 1109405 */
static  tsp01_CommErr_Enum en03_aPing( char *         pszServerNode,
                                       tsp00_Versionc szServerVersion,
                                       tsp00_ErrTextc errText );

extern int sqlIsRunTimeComponent();

/*===========================================================================*
 *  PUBLIC FUNCTIONS (CODE)                                                  *
 *===========================================================================*/

externC tsp01_CommErr_Enum  SqlPingConnect ( char*                  szServerNode,    /* '\0' terminated node or saprouterstring */
                                             char*                  szServerDB,      /* '\0' terminated dbname                  */
                                             tsp00_Int4*            reference,      /* connection reference                    */
                                             tsp00_ErrTextc         pErrText )       /* '\0' terminated error string            */
  {
  #undef  MF__
  #define MF__ MOD__"SqlPingConnect"
  tsp01_CommErr_Enum        commError;
  int                       packetSize;
  void*                     packetList;
  tsp00_Int4                max_reply_packet_size;

  DBGIN;

  if ( !sql03_connect_pool.initialized )
      sql03_init();

  if (strlen (szServerDB) >= sizeof (SQL_DBNAMEC))
  {
      eo46BuildErrorStringRC ( pErrText, ERRMSG_COM_SERVERDB_NAME_TOO_LONG, 0 );
      DBGOUT;
      return commErrNotOk_esp01;
  }

  commError = (tsp01_CommErr_Enum)sql03_connect ( szServerNode,
                                                  szServerDB,
                                                  (int) srvPing_esp01,
                                                  1,
                                                  reference,
                                                  &max_reply_packet_size,
                                                  &packetSize,
                                                  &packetList,
                                                  NULL,
                                                  NULL,
                                                  NULL,
                                                  pErrText );


  DBGOUT
  return (commError) ;
  }


/*------------------------------*/


externC tsp01_CommErr_Enum SqlDBPing ( tsp00_Int4                         reference,
                                       tsp00_Uint4*                       sendBufferSize,
                                       tsp00_Uint1*                       hops,
                                       tsp00_DbNamec   VAR_ARRAY_REF      szServer,
                                       tsp00_Versionc  VAR_ARRAY_REF      szServerVersion,
                                       tsp00_ErrTextc                     pErrText )
{
    tsp01_CommErr_Enum              commState;
    char*                           server;
    char*                           serverVersion;
    connection_info*                cip;
    tsp00_Uint4                     sendLen;

    /* --- get the pointer to the internal communication structure */
    commState = (tsp01_CommErr_Enum)en03GetAndCheckConnectionInfo( reference, CHECK_PID_EN03, &cip, "SqlDBPing", pErrText );

    if ( commState != commErrOk_esp01 )
        return commErrNotOk_esp01;

    if ( *sendBufferSize > cip->ci_max_request_size ) 
        *sendBufferSize = cip->ci_max_request_size;

    *sendBufferSize = ALIGN_BUFFER( *sendBufferSize, SQL_PACKET_ALIGNMENT );

    sendLen =  eo420FillPingPacket ( (char*)cip->ci_packetData[0],
                                     *sendBufferSize, *hops, "PingClient", 0, "!!! SEND DATA !!!" );

    if ( 0 != sendLen )
    {
        commState = (tsp01_CommErr_Enum)sql03_request ( reference, cip->ci_packetData[0], sendLen, pErrText );

        if ( commState == commErrOk_esp01 )
        {
            char*              pResPacket;
            tsp00_Int4         resDataLen;

            commState = (tsp01_CommErr_Enum)sql03_receive ( reference, (void**)&pResPacket, &resDataLen, pErrText );

            if ( commState == commErrOk_esp01 )
            {
                if ( eo420ExtractPingPacket( pResPacket, resDataLen, hops, &server, &serverVersion ) )
                {
                    if ( server )
                    {
                        szServer[sizeof(tsp00_DbNamec)-1];
                        strncpy ( szServer, server, sizeof(tsp00_DbNamec));
                    }
                    if ( serverVersion )
                    {
                        szServerVersion[sizeof(tsp00_Versionc)-1];
                        strncpy ( szServerVersion, serverVersion, sizeof(tsp00_Versionc));
                    }
                }
                else
                {
                    MSGD (( ERR_PROTOCOL_ERROR, "PING REPLY" ));
                    eo46BuildErrorStringRC ( pErrText, ERRMSG_PROTOCOL_ERROR, 0 );
                    commState = commErrNotOk_esp01;
                }
            }
        }
    }
    else
    {
        MSGD (( ERR_PROTOCOL_ERROR, "PING REPLY" ));
        eo46BuildErrorStringRC ( pErrText, ERRMSG_PROTOCOL_ERROR, 0 );
        commState = commErrNotOk_esp01;
    }

    return commState;
}

/*------------------------------*/

externC void SqlPingRelease (tsp00_Int4 reference)
  {
  #undef  MF__
  #define MF__ MOD__"SqlPingRelease"
  tsp00_ErrTextc  pErrText;

  sql03_release ( reference, pErrText );

  return;
  }



/*===============================================================================*/
/* This function is used for calls from C / C++ functions only                   */
/*===============================================================================*/

/* PTS 1105295 */

externC tsp01_CommErr_Enum
SqlAPing ( char                  *pszServerNode,     /* '\0' terminated node or saprouterstring */
           tsp00_Versionc         szServerVersion,   /* '\0' terminated version from answering server */
           tsp00_ErrTextc         pErrText)          /* '\0' terminated error string   */
{
  #undef  MF__
  #define MF__ MOD__"SqlAPing"

    tsp01_CommErr_Enum        commError;

    if ( pszServerNode == NULL || *pszServerNode == '\0' )
    {
        commError = commErrNotOk_esp01;
        strcpy ( pErrText, "missing hostname" );
    }
    else
    {
        if ( eo40NiIsSaprouterSring ( pszServerNode ) )
        {
            if ( !fNI_Installed )
            {
                fNI_Installed = eo03NiInit(pErrText) != 0;
            }

            if ( !fNI_Installed )
            {
                commError = commErrNotOk_esp01;
            }
            else {
                commError = eo03NiXserverPing( pszServerNode, szServerVersion, pErrText );
            }
        }
        else
        {
            /* PTS 1109405 */
            commError = en42pingRequest(pszServerNode, szServerVersion, pErrText);
        }
    }

    DBGOUT;
    return ( commError );
}

/*
 * ===========================================================================
 */

externC tsp01_CommErr_Enum
SqlAConnect ( char                  *szServerNode,      /* '\0' terminated node or saprouterstring */
              tsp00_DbNamec          szServerDB,        /* '\0' terminated dbname                  */
              tsp01_Service_Enum     service,
              tsp00_Int4             packet_cnt,
              tsp00_Int4             *reference,
              tsp00_Int4             *sql_packet_size,
              void                  **sql_packet_list,  /* tsp00_Array<tsp1_packet_ptr, ...> */
              tsp00_ErrTextc         szErrText )        /* '\0' terminated error string   */
{
  #undef  MF__
  #define MF__ MOD__"SqlAConnect"
    tsp01_CommErr_Enum        commError;
    tsp00_Int4                max_reply_packet_size;

    DBGIN;

    DBG3 (( MF__, "pszServerNode '%s'", szServerNode ));
    DBG3 (( MF__, "pszServerDB   '%s'", szServerDB ));

    commError = (tsp01_CommErr_Enum) sql03_connect ( szServerNode,
                szServerDB,
                (int) service,
                (int) packet_cnt,
                reference,
                &max_reply_packet_size,
                sql_packet_size,
                sql_packet_list,
                NULL, NULL, NULL, szErrText);

    DBGOUT
    return (commError);
}

externC tsp01_CommErr_Enum
SqlDBConnect ( char                  *szServerNode,      /* '\0' terminated node or saprouterstring */
               tsp00_DbNamec          szServerDB,        /* '\0' terminated dbname                  */
               tsp01_Service_Enum     service,
               tsp00_Int4             packet_cnt,
               tsp00_Int4             *reference,
               tsp00_Int4             *max_reply_packet_size,
               tsp00_Int4             *sql_packet_size,
               void                   **sql_packet_list,  /* tsp00_Array<tsp1_packet_ptr, ...> */
               tsp00_ErrTextc         szErrText )        /* '\0' terminated error string   */
{
  #undef  MF__
  #define MF__ MOD__"SqlDBConnect"
    tsp01_CommErr_Enum        commError;

    DBGIN;

    DBG3 (( MF__, "pszServerNode '%s'", szServerNode ));
    DBG3 (( MF__, "pszServerDB   '%s'", szServerDB ));

    commError = (tsp01_CommErr_Enum) sql03_connect ( szServerNode,
                szServerDB,
                (int) service,
                (int) packet_cnt,
                reference,
                max_reply_packet_size,
                sql_packet_size,
                sql_packet_list,
                NULL, NULL, NULL, szErrText);

    DBGOUT
    return (commError);
}


/*
 * ===========================================================================
 */

/*ARGSUSED*/ /* pid not used */

    #undef MF__
    #define MF__ MOD__"sqlaconnect"
void sqlaconnect ( tsp00_TaskId           pid,
                   tsp00_NodeId           servernode,       /* tsp00_Array<char, mxsp_c64> */
                   tsp00_DbName           serverdb,         /* tsp00_Array<char, mxsp_c18> */
                   tsp01_Service_Enum     service,
                   tsp00_Int4             packet_cnt,
                   tsp00_Int4           * reference,
                   tsp00_Int4           * sql_packet_size,
                   void                ** sql_packet_list,  /* tsp00_Array<tsp1_packet_ptr, ...> */
                   tsp00_ErrText          errtext,          /* tsp00_Array<char, mxsp_c40> */
                   tsp01_CommErr        * returncode)       /* tsp00_Enum<tsp1_comm_error_Enum, ...> */

{
    tsp00_NodeIdc     szServerNode;
    tsp00_DbNamec     szServerDB;
    tsp00_ErrTextc    pErrText;
    tsp00_Int4        max_reply_packet_size;

    eo46PtoC ( szServerNode, servernode,  sizeof(tsp00_NodeId) );
    eo46PtoC ( szServerDB,   serverdb,    sizeof(tsp00_DbName) );

    DBG3 (( MF__,"node '%.10s' db '%.8s' srv %d pktcnt %d \n",
            szServerNode , szServerDB , (int) service , (int) packet_cnt ))

    *returncode = (tsp1_comm_error) sql03_connect ( szServerNode,
                  szServerDB,
                  (int) service,
                  (int) packet_cnt,
                  reference,
                  &max_reply_packet_size,
                  sql_packet_size,
                  sql_packet_list,
                  NULL,
                  NULL,
                  NULL,
                  pErrText);

    if ( *returncode != commErrOk_esp01 )
        eo46CtoP ( errtext, pErrText, sizeof(tsp00_ErrText) );

    DBG3 (( MF__,"rc %d ref %d pktsiz %d \n",
            (int) *returncode , (int) *reference , (int) *sql_packet_size ))
}

/*
 * ===========================================================================
 */

    #undef MF__
    #define MF__ MOD__"sqlarelease"
void sqlarelease (tsp00_Int4 reference)
{
    tsp00_ErrTextc   pErrText;
    int rc;

    DBGIN;
    DBG3 (( MF__,"ref %d \n", reference ))

    rc = sql03_release ( reference , pErrText );

    DBG3 (( MF__,"rc %d\n", rc ))
}

/*
 * ===========================================================================
 */

    #undef MF__
    #define MF__ MOD__"sqlarequest"
void sqlarequest (  tsp00_Int4        reference,
                    void            * sql_packet_addr,
                    tsp00_Int4        sql_packet_length,
                    tsp00_ErrText     errtext,
                    tsp01_CommErr   * returncode)
{
    tsp00_ErrTextc    pErrText;

    DBG1 (( MF__,"ref %d lgt %d \n", reference , sql_packet_length ))

    *returncode = (tsp1_comm_error) sql03_request ( reference , sql_packet_addr,
                  sql_packet_length , pErrText );

    if ( *returncode != commErrOk_esp01 )
        eo46CtoP ( errtext, pErrText, sizeof(tsp00_ErrText) );

    DBG1 (( MF__,"rc %d \n", (int) *returncode ))
}

/*
 * ===========================================================================
 */

    #undef MF__
    #define MF__ MOD__"sqlareplyavailable"
void sqlareplyavailable (  tsp00_Int4         reference,
                           tsp00_ErrText      errtext,
                           tsp01_CommErr    * returncode)
{
    tsp00_ErrTextc    pErrText;

    DBG1 (( MF__,"ref %d \n", reference ))

    *returncode = (tsp1_comm_error) sql03_replyavailable ( reference , pErrText);

    if ( *returncode != commErrOk_esp01 )
        eo46CtoP ( errtext, pErrText, sizeof(tsp00_ErrText) );

    DBG1 (( MF__,"rc %d \n", (int) *returncode ))
}

/*
 * ===========================================================================
 */

    #undef MF__
    #define MF__ MOD__"sqlareceive"
void sqlareceive ( tsp00_Int4        reference,
                   void            ** res_packet_ptr,
                   tsp00_Int4       * res_packet_length,
                   tsp00_ErrText      errtext,
                   tsp01_CommErr    * returncode)
{
    tsp00_ErrTextc    pErrText;

    DBG1 (( MF__,"ref %d \n", reference ))

    *returncode = (tsp1_comm_error) sql03_receive ( reference , res_packet_ptr,
                  res_packet_length , pErrText);

    if ( *returncode != commErrOk_esp01 )
        eo46CtoP ( errtext, pErrText, sizeof(tsp00_ErrText) );

    DBG1 (( MF__,"rc %d lgt %d \n", (int) *returncode , (int) *res_packet_length ))
}

/*
 * ===========================================================================
 */

    #undef MF__
    #define MF__ MOD__"sqlacancel"
void sqlacancel ( tsp00_Int4              reference)
{
    tsp00_ErrTextc    pErrText;

    int rc;

    DBG3 (( MF__,"ref %d \n", reference ))

    rc = sql03_cancel ( reference , pErrText );

    DBG3 (( MF__,"rc %d\n", rc ))
}

/*
 * ===========================================================================
 */

    #undef MF__
    #define MF__ MOD__"sqladump"
void    sqladump ( )
{
    tsp00_ErrTextc pErrText;

    DBGIN;

    (void) sql03_dump ( pErrText );

    DBGOUT;
}

/*
 * ===========================================================================
 */

/*ARGSUSED*/ /* pid not used */

    #undef MF__
    #define MF__ MOD__"sql03_xconnect"
void    sql03_xconnect (
    char            *servernode,
    tsp00_DbNamec    serverdb,
    char            *dbroot,
    char            *serverpgm,
    tsp00_Int4        *reference,
    tsp00_Int4        *sql_packet_size,
    void           **sql_packet_list,
    connection_VMT  *vmt,
    tsp00_ErrText      errtext,
    tsp1_comm_error     *returncode)
{
    tsp00_ErrTextc    pErrText;
    tsp00_Int4        max_reply_packet_size;

    DBG3 (( MF__,"node '%.10s' db '%.8s' srv %d \n",
            servernode , serverdb , (int) srvControl_esp01 ));

    *returncode = (tsp1_comm_error) sql03_connect ( servernode,
                  serverdb,
                  srvControl_esp01,
                  1,
                  reference,
                  &max_reply_packet_size,
                  sql_packet_size,
                  sql_packet_list,
                  dbroot,
                  serverpgm,
                  vmt,
                  pErrText);

    if ( *returncode != commErrOk_esp01 )
        eo46CtoP ( errtext, pErrText, sizeof(tsp00_ErrText) );

    DBG3 (( MF__,"rc %d ref %d pktsiz %d \n",
            (int) *returncode , (int) *reference , (int) *sql_packet_size ))
}

/*
 * ===========================================================================
 */

    #undef MF__
    #define MF__ MOD__"sql03_init"
static  void    sql03_init ()
{
    int                 idx;
    connection_info     *cip;

    DBGIN;

    /*
     *  Set sql03_cip to the connection data of the currently active connection.
     *  This information is used by sql03_dump and sql03_catch_signal.
     */
    sql03_cip = 0;
    sql03_init_connect_pool (&sql03_connect_pool);
#if defined (STATIC_CONNECTIONS)
    for ( idx = 0 ; idx < MAXCONNECTIONS ; idx ++ )
    {
        cip = sql03_connection + idx;
        if ( cip->ci_state )
        {
            MSGCD (( -11600,ERR_TYPE,"COMMUNIC",
                     "ABEND: sql03_init: already initialized before \n" ));
            sqlabort ();
        }
        memset ( cip , 0 , sizeof(connection_info) );
    }
#endif
    DBGOUT;
}

/*
 * ===========================================================================
 */

    #undef MF__
    #define MF__ MOD__"sql03_finish"
static  void    sql03_finish ()
{
    int              idx;
    connection_info *cip;
    tsp00_ErrTextc   pErrText;


    DBGIN;

    for ( idx = 0 ; idx < MAXCONNECTIONS_INL ; idx ++ )
    {
        cip = CONNECTION_AT_INL (idx);
        if ( cip->ci_state != CON_UNUSED_EO003 )
        {
            (void) sql03_release ( (tsp00_Int4) (idx + 1) , pErrText );
        }
        memset ( cip , 0 , sizeof(connection_info) );
    }

    /*
     *  Set sql03_cip to the connection data of the currently active connection.
     *  This information is used by sql03_dump and sql03_catch_signal.
     */
    sql03_cip = 0;

    DBGOUT;
}

/*===========================================================================*
 *  LOCAL/PRIVATE/PROTECTED FUNCTIONS (CODE)                                 *
 *===========================================================================*/

static void en03InitConnParam (char                      *Node,
                               teo003_ConnectParamRecord *pConnParam,
                               connection_info           *cip )
{
#undef  MF__
#define MF__ MOD__"en03InitConnParam"

    pConnParam->ulPacketCnt      = cip->ci_packet_cnt;
    pConnParam->ulPacketSize     = cip->ci_max_request_size;

    pConnParam->ulClientRef      = cip->ci_my_ref;
    pConnParam->ulServiceType    = cip->ci_service;
    pConnParam->pszServerDB      = cip->ci_peer_dbname;

    pConnParam->pszServerPgm     = cip->ci_serverpgm;
    pConnParam->pszServerNode    = Node;
    pConnParam->pszClientNode    = NULL;     /* comm. xserver/kernel only */
    pConnParam->ulMaxDataLen     = cip->ci_max_data_size;
    pConnParam->ulMinReplySize   = (teo00_Longuint)undef_ceo00;
    pConnParam->pidClientPID     = cip->ci_my_pid;

    pConnParam->pszServerDBRoot  = cip->ci_dbroot;

    pConnParam->ulServerRef      = (teo00_Longuint)undef_ceo00;
    pConnParam->fAcknowledge     = FALSE;
}

/*
 * ===========================================================================
 */
static int en03GetAndCheckConnectionInfo(tsp00_Int4     reference,
        tsp00_Int4                      CheckPid,
        connection_info               **ConnectionInfo,
        char                           *CallingFktName,
        tsp00_ErrTextc                  pErrText )
{
#undef  MF__
#define MF__ MOD__"en03GetAndCheckConnectionInfo"

    if (!VALID_REF_INL (reference))
    {
        en42FillErrText(pErrText, "%s:%s:%d", CallingFktName, ERRMSG_COM_ILL_REFERENCE, reference);
        MSGD (( -11607, ERR_TYPE, "COMMUNIC","%s: %s: %d",
                CallingFktName, ERRMSG_COM_ILL_REFERENCE , reference ))
        return ( commErrNotOk_esp01 );
    }

    *ConnectionInfo = CONNECTION_AT_INL (reference - 1);

    /*
     *  Check the connection information.
     */
    if ( (*ConnectionInfo)->ci_my_ref != reference )
    {
        en42FillErrText( pErrText,
                         "%s:%s:%d/%d", 
                         CallingFktName,
                         ERRMSG_COM_CORRUPTED_INTERNAL_DATA,
                         (*ConnectionInfo)->ci_my_ref,
                         reference );
        MSGALL (( -11607, ERR_TYPE, "COMMUNIC","%s: %s! my %d ref %d",
                  CallingFktName, ERRMSG_COM_CORRUPTED_INTERNAL_DATA,
                  (*ConnectionInfo)->ci_my_ref , reference ))
        return ( commErrNotOk_esp01 );
    }

    /*
     *  The application MUST NOT use a connection in a new process.
     *
     * PTS 1109225 MaO
     * The PID check is decrepitly in particular for Linux with Linuxthread
     *
     */
#if !defined(LINUX) || defined(HAS_NPTL)
    if ( CheckPid == CHECK_PID_EN03 && (*ConnectionInfo)->ci_my_pid != getpid() )
    {
        en42FillErrText( pErrText,
                         "%s:%s:%d/%d", 
                         CallingFktName,
                         ERRMSG_COM_APPLIC_FORKED,
                         (*ConnectionInfo)->ci_my_pid,
                         (int)getpid() );
        MSGALL (( -11607, ERR_TYPE, "COMMUNIC","%s: %s!",
                  CallingFktName, ERRMSG_COM_APPLIC_FORKED))
        return ( commErrNotOk_esp01 );
    }
#endif /* !LINUX || HAS_NPTL */
    return(commErrOk_esp01);
}

/*
 * ===========================================================================
 */

    #undef MF__
    #define MF__ MOD__"sql03_connect"
static  int     sql03_connect (char            * servernode,
                               tsp00_DbNamec     anyCaseServerdb, /* PTS 1125565 */
                               int               service,
                               int               packet_cnt,
                               tsp00_Int4        * reference,
							   tsp00_Int4        * max_reply_packet_size,
                               tsp00_Int4        * sql_packet_size,
                               void           ** sql_packet_list,
                               char            * dbroot,
                               char            * serverpgm,
                               connection_VMT  * vmt,
                               tsp00_ErrTextc    pErrText)
{
    int               rc;
    int               retry;
    tsp00_Int4          ref;
    pid_t             pid;
    time_t            date;
    connection_info * cip;
    tsp00_DbNamec     serverdb;
    int               iChar;
    DBGIN;

    memset(&serverdb[0], 0, sizeof(tsp00_DbNamec));
    for ( iChar = 0; (0 != anyCaseServerdb[iChar])
                  && (iChar < sizeof(tsp00_DbName)); iChar++ )
    {
        serverdb[iChar] = toupper(anyCaseServerdb[iChar]);
    }

    date = time ( (time_t*)0 );
    *reference  = MAXCONNECTIONS + 5 + date % 100 ; /* some illegal value */
    *sql_packet_size = 0;

    pid = getpid ();
    if ( sql03_pid != pid )
    {
        /*
         * PTS 1109761 BV
         * Don't check PID for Linux with Linuxthread because threads have different pids.
         */
#if !defined(LINUX) || defined(HAS_NPTL)
        if ( sql03_pid ) /* The first time this is zero. */
        {
            DBG1 (( MF__,"application forked \n" ))
            /*
             *  Clear all connections for re-use.
             *  The connetions will be cleared, not released
             *  (sql03_release notices a change of the pid).
             *  This way, the parent process can proceed in using
             *  its connections, while the child frees its
             *  connection data to allow MAXCONNECTIONS new connections.
             */
            sql03_finish ();
        }
#endif
        sql03_pid = pid ; /* from now on that's the pid for reference. */
    }

    if ( (packet_cnt < 1) || (packet_cnt > MAX_SQL_PACKETS) )
    {
        strcpy(pErrText,"illegal packet count");
        MSGALL (( -11987, ERR_TYPE, "COMMUNIC","ERROR: sqlaconnect: illegal packet count: %d \n",
                  packet_cnt ))
        return ( commErrPacketLimit_esp01 );
    }

    /*
     *  Select a reference number.
     */
    ref = sql03_alloc_connect (); /* PTS 1113728 fixed wrong limitation to maximum of 8 connections */
    if (!VALID_REF_INL (ref))
    {
        strcpy(pErrText ,ERRMSG_COM_TO_MANY_SESSIONS );
        MSGD (( -11601, ERR_TYPE, "COMMUNIC","sql03_connect: %s (%d allowed) \n",
                ERRMSG_COM_TO_MANY_SESSIONS , MAXCONNECTIONS_INL ))
        return ( commErrNotOk_esp01 );
    }
    cip = CONNECTION_AT_INL (ref - 1);
    DBG1 (( MF__,"reference %d \n", ref ))

    /*
     *  Set sql03_cip to the connection data of the currently active connection.
     *  This information is used by sql03_dump and sql03_catch_signal.
     */
    sql03_cip = cip;

    memset ( cip , 0 , sizeof(*cip) );
    cip->ci_connect_time   = date;
    cip->ci_use_count ++;
    cip->ci_state          = CON_CONNECTING_EO003;
    cip->ci_service        = service;
    cip->ci_protocol       = PROT_UNDEF_EO003;
    cip->ci_packet_cnt     = packet_cnt;
    cip->ci_my_pid         = pid;
    cip->ci_my_ref         = ref;
    cip->ci_dbroot         = dbroot;
    cip->ci_serverpgm      = serverpgm;
    cip->ci_vmt            = vmt;

    /*
     *  convert pascal names to null terminated strings
     */
    DBG1 (( MF__,"servernode '%s' \n", servernode ))
    DBG1 (( MF__,"serverdb   '%s' \n", serverdb ))

    strcpy(cip->ci_peer_dbname , serverdb   );
    /*
     *  If no node name is given, split database name into node/dbname parts.
     */
    if ( servernode && *servernode == '\0' )
    {
        sql03_split_dbname (cip->ci_peer_dbname , cip->ci_peer_node );
    }

    /*
     *  Determine the protocol to use with the database kernel.
     */
    sql03_get_protocol (servernode, cip, pErrText );

    /*
     *  Set signal catching routines for the time of the connect establishment.
     */
    sql03_set_signals ();

    /*
     *  Try to connect for at least fifteen seconds.
     */
    for ( retry  = 0          ,  rc  = commErrTasklimit_esp01;
            retry <= RETRYCOUNT && rc == commErrTasklimit_esp01;
            retry ++  )
    {
        DBG1 (( MF__,"%s" , retry ? "tasklimit, retrying ...\n" : "trying ...\n" ))

        /*
         *  Call the connect function for the requested protocol.
         */
        switch ( cip->ci_protocol )
        {
        case PROT_SHM_EO003 :
        case PROT_BIGSHM_EO003 :
            sql03_set_alarm ( LOCL_CON_TMO );
            rc = sql33_connect ( cip , pErrText , CONNECTION_ARRAY, MAXCONNECTIONS_INL );
            sql03_reset_alarm ();
            break;

#if SOCKETS
        case PROT_SOCKET_EO003 :
            sql03_set_alarm ( 0 );
            rc = sql23_connect ( cip , pErrText );
            sql03_reset_alarm ();
            break;
#endif
        case PROT_NI_EO003 :
            {
                teo003_ConnectParamRecord   ConnParam;
                en03InitConnParam  ( servernode, &ConnParam, cip );
                rc = eo03NiConnect ( &ConnParam, &cip->NI, pErrText );
                strcpy( cip->ci_peer_node, cip->NI.szServerNode ) ;  /* now we know the destination node   */
                /* it is part of the saprouter string */
                if ( rc == commErrOk_esp01 )
                {
                    int idx;
                    for ( idx = 0 ; idx < cip->ci_packet_cnt ; idx ++ )
                    {
                        cip->ci_packet[idx] = (void *)ConnParam.pCommPacketList[idx];
                    }
                    cip->ci_max_data_size = ConnParam.ulMaxDataLen;
                    cip->ci_min_reply_size= ConnParam.ulMinReplySize;
                }
            }
            break;
        case PROT_LOCAL_CONTROL_EO003:
        default :
            if (vmt != NULL) {
                sql03_set_alarm (SOCK_CON_TMO);
                rc = vmt->connect (cip, pErrText);
                sql03_reset_alarm ();
            }
            else
            {
                rc = commErrNotOk_esp01;
                strcpy(pErrText, ERRMSG_UNSUPPORTED_PROTOCOL );
                MSGD (( -11602, ERR_TYPE, "COMMUNIC","sqlaconnect: %s %d \n",
                        ERRMSG_UNSUPPORTED_PROTOCOL, cip->ci_protocol ));
            }
        }
        if ( rc == commErrTasklimit_esp01 )
            (void) sleep ( RETRYTIME );
    }

    /*
     *  Reset signal catching routines to their old values.
     *  (Some signals remain altered).
     */
    sql03_reset_signals ();

    /*
     *  Set connection state.
     */
    if ( rc == commErrOk_esp01 )
    {
        int idx;
        cip->ci_state = CON_CONNECTED_EO003;
        for ( idx = 0 ; idx < cip->ci_packet_cnt ; idx ++ )
        {
            cip->ci_packetData [idx] = ((char*) cip->ci_packet[idx])
                + RTE_HEADER_SIZE_EO003;
            sql_packet_list [idx] = cip->ci_packetData [idx];
        }
        cip->ci_max_request_size = cip->ci_max_data_size - cip->ci_min_reply_size;
        *sql_packet_size       = cip->ci_max_request_size;
        *max_reply_packet_size = cip->ci_max_data_size;
        *reference = ref;
        DBG1 (( MF__,"pack1 0x%08lx pack2 0x%08lx siz %d \n",
                (long) sql_packet_list[0] , (long) sql_packet_list[1],
                *sql_packet_size ))
    }
    else
    {
        if ( rc == commErrTasklimit_esp01 )
        {
            strcpy(pErrText, "task limit");
            MSGD (( -11987, ERR_TYPE, "COMMUNIC","sqlaconnect: task limit \n" ))
        }
        cip->ci_connect_time   = 0;
        cip->ci_state          = CON_UNUSED_EO003;
        cip->ci_protocol       = PROT_UNDEF_EO003;
    }

    DBG1 (( MF__,"returning %d ref %d \n", rc , *reference ))
    return ( rc );
}
/*
 * ===========================================================================
 */

    #undef MF__
    #define MF__ MOD__"sql03_release"
static  int     sql03_release (
    tsp00_Int4                        reference,
    tsp00_ErrTextc                  pErrText )
{
    int             rc;
    int             pid_changed = 0;
    connection_info     *cip = NULL;


    DBGIN;

    rc =  en03GetAndCheckConnectionInfo( reference, !CHECK_PID_EN03, &cip, "sql03_release", pErrText );
    if ( rc != commErrOk_esp01 )
        return(rc);

    /*
     *  If the application forked, silently clear the connection.
     *  It might still be in use by the parent process.
     *
     *  PTS 1109761 BV
     *  Don't check PID for Linux with Linuxthread because threads have different pids.
     */
#if !defined(LINUX) || defined(HAS_NPTL)
    pid_changed = ( cip->ci_my_pid != getpid() );
#endif

    /*
     *  Set sql03_cip to the connection data of the currently active connection.
     *  This information is used by sql03_dump and sql03_catch_signal.
     */
    sql03_cip = cip;

    switch ( cip->ci_protocol )
    {
        char            *errm;

    case PROT_SHM_EO003 :
    case PROT_BIGSHM_EO003 :
        if ( pid_changed )
            rc = sql33_clear ( cip , pErrText, CONNECTION_ARRAY, MAXCONNECTIONS_INL );
        else
            rc = sql33_release ( cip , pErrText, CONNECTION_ARRAY, MAXCONNECTIONS_INL );
        break;

#if SOCKETS
    case PROT_SOCKET_EO003 :
        if ( pid_changed )
            rc = sql23_clear ( cip , pErrText );
        else
            rc = sql23_release ( cip , pErrText );
        break;
#endif
    case PROT_NI_EO003 :
        rc = eo03NiRelease( &cip->NI, pErrText );
        break;

    default :
        if (cip->ci_vmt != NULL)
        {
            if ( pid_changed )
                rc = cip->ci_vmt->clear ( cip , pErrText );
            else
                rc = cip->ci_vmt->release ( cip , pErrText );
        }
        else
        {
            rc = commErrNotOk_esp01;
            en42FillErrText(pErrText,ERRMSG_UNSUPPORTED_PROTOCOL);
            MSGCD (( -11605,ERR_TYPE,"COMMUNIC",
                     "sqlarelease: unsupported protocol %d \n", cip->ci_protocol ));
        }
    }

    cip->ci_state = CON_UNUSED_EO003;

    DBG1 (( MF__,"returning %d \n", rc ))
    return ( rc );
}

/*
 * ===========================================================================
 */

/*
 * ===========================================================================
 */

    #undef MF__
    #define MF__ MOD__"sql03_request"
static  int     sql03_request (tsp00_Int4         reference,
                               void             * packet,
                               tsp00_Int4         length,
                               tsp00_ErrTextc     pErrText )
{
    int              rc;
    int              idx;
    rte_header      *header;
    connection_info *cip;
    tsp00_Int4         aligned_length;

    DBGIN;

    rc =  en03GetAndCheckConnectionInfo( reference, CHECK_PID_EN03, &cip, "sql03_request", pErrText );
    if ( rc != commErrOk_esp01 )
        return(rc);

    /*
     *  A request is only allowed after a successful connection
     *  establishment or after a successful receive.
     *  A canceled request has to wait for a cancel confirmation
     *  from the kernel. This is done through a normal receive.
     */
    if ( (cip->ci_state != CON_CONNECTED_EO003) && (cip->ci_state != CON_RECEIVED_EO003 ) )
    {
        en42FillErrText( pErrText,
                         "%s:%s",
                         ERRMSG_COM_WRONG_CONN_STATE, 
                         sql03_statename(cip));
        MSGD (( -11608, ERR_TYPE, "COMMUNIC","sql03_request: %s, state is '%s' \n",
                ERRMSG_COM_WRONG_CONN_STATE , sql03_statename(cip) ))
        return ( commErrNotOk_esp01 );
    }

    /*
     *  The packet length must be within the valid range
     *  and 8-byte aligned.
     */
    if ( (length < 0) || (length > cip->ci_max_request_size))
    {
        en42FillErrText( pErrText,
                         "%s:%d",
                         ERRMSG_COM_WRONG_PACKET_LEN, 
                         (int)length );
        MSGD (( -11609, ERR_TYPE, "COMMUNIC","sql03_request: %s: %d max %ld \n",
                ERRMSG_COM_WRONG_PACKET_LEN , length , cip->ci_max_request_size ))
        return ( commErrNotOk_esp01 );
    }

    if (length & 7)
    {
        if ( cip->ci_service != 4 )
        {
            en42FillErrText( pErrText,
                             "Wrong service %d for length %d",
                             cip->ci_service,
                             length );
            MSGD (( -11609, ERR_TYPE, "COMMUNIC","sql03_request: %s: %d max %ld \n",
                    ERRMSG_COM_WRONG_PACKET_LEN , length , cip->ci_max_request_size ))
            return ( commErrNotOk_esp01 );
        }
        else
        {
            /* packets from the hserver are not necessarily aligned */
            aligned_length = length + 8 - (length & 7);
        }
    }
    else
    {
        aligned_length = length;
    }

    /*
     *  Check the packet pointer.
     */
    header = NULL;
    for ( idx = 0 ; idx < cip->ci_packet_cnt ; idx ++ )
    {
        if ( cip->ci_packetData [idx] == packet )
        {
            header = cip->ci_packet [idx];
            break;
        }
    }
    if ( header == NULL )
    {
        en42FillErrText( pErrText, "Packet pointer points to NULL");
        MSGD (( -11604, ERR_TYPE, "COMMUNIC","sqlarequest: %s: 0x%08lx \n",
                ERRMSG_COM_WRONG_PACKET_ADDR, (long) packet ))
        for ( idx = 0 ; idx < cip->ci_packet_cnt ; idx ++ )
        {
            MSGD (( -11604, ERR_TYPE, "COMMUNIC","             allowed pointer      0x%08lx \n",
                    (long) cip->ci_packetData [idx] ))
        }
        return ( commErrNotOk_esp01 );
    }
    cip->ci_request = header;
    cip->ci_requestData = packet;
    cip->ci_request_lgt = length;
    cip->ci_current_packet = idx;

    /*
     *  Determine the pointer to a following reply.
     */
    cip->ci_reply = (rte_header*)((char *)cip->ci_requestData + aligned_length);
    cip->ci_replyData = (char *)cip->ci_requestData + aligned_length
        + RTE_HEADER_SIZE_EO003;
    cip->ci_reply_size = cip->ci_max_data_size - aligned_length;

    /*
     *  Set sql03_cip to the connection data of the currently active connection.
     *  This information is used by sql03_dump and sql03_catch_signal.
     */
    sql03_cip = cip;

    /*
     *  Setup the RTE header.
     */
    header->rh_act_send_len     = aligned_length + RTE_HEADER_SIZE_EO003;
    header->rh_max_send_len     = aligned_length + RTE_HEADER_SIZE_EO003;
    header->rh_protocol_id      = RSQL_RTE_PROT_LOCAL_EO003;
    header->rh_mess_class       = RSQL_USER_DATA_REQUEST_EO003;
    header->rh_rte_flags        = RSQL_NORMAL_EO003;
    header->rh_residual_packets = 0;
    header->rh_sender_ref       = cip->ci_my_ref;
    header->rh_receiver_ref     = cip->ci_peer_ref;
    header->rh_rte_return_code  = 0;
    header->rh_new_swap_type    = sql42_new_swap_type();
    header->rh_filler1          = 0;

#ifdef TOKERNEL
    DBG1 (( MF__,"dumping packet to DUMPFILE \n" ))
    sql46_dump ( "\nTOKERNEL------>", 16 );
    sql46_dump ( (char*) packet , (int) length );
    sql46_dump ( "<---------------", 18 - ((int)length + 13)%16 );
    sql46_dump ( "--TOKERNEL\n", 11 );
#endif
#ifdef  DEBUG_RTE
    sql46_dump_packet ( header );
#endif

    switch ( cip->ci_protocol )
    {
        char            *errm;

    case PROT_SHM_EO003 :
    case PROT_BIGSHM_EO003 :
        rc = sql33_request ( cip , pErrText );
        break;

#if SOCKETS
    case PROT_SOCKET_EO003 :
        rc = sql23_request ( cip , pErrText );
        break;
#endif

    case PROT_NI_EO003 :
        rc = eo03NiRequest  ( &cip->NI, cip->ci_current_packet,
                              aligned_length, pErrText );
        break;

    default :
        if (cip->ci_vmt != NULL)
        {
            rc = cip->ci_vmt->request (cip, pErrText);
        }
        else
        {
            rc = commErrNotOk_esp01;
            en42FillErrText( pErrText, ERRMSG_UNSUPPORTED_PROTOCOL);
            MSGCD (( -11610,ERR_TYPE,"COMMUNIC",
                     "sql03_request: unsupported protocol %d \n", cip->ci_protocol ));
        }
    }

    if ( rc == commErrOk_esp01 )
        cip->ci_state = CON_REQUESTED_EO003;

    DBG1 (( MF__,"returning %d\n", rc ))
    return ( rc );
}

/*
 * ===========================================================================
 */

    #undef MF__
    #define MF__ MOD__"sql03_replyavailable"
static  int     sql03_replyavailable (
    tsp00_Int4                        reference,
    tsp00_ErrTextc                  pErrText )
{
    int              rc;
    rte_header      *header;
    connection_info *cip;


    DBG1 (( MF__,"ref %d \n", reference ))

    rc =  en03GetAndCheckConnectionInfo( reference, CHECK_PID_EN03, &cip, "sql03_replyavailable", pErrText );
    if ( rc != commErrOk_esp01 )
        return(rc);

    /*
     *  A receive is only allowed after a successful request.
     */
    if ( cip->ci_state != CON_REQUESTED_EO003 )
    {
        en42FillErrText(pErrText,ERRMSG_COM_WRONG_CONN_STATE);
        MSGD (( -11608, ERR_TYPE, "COMMUNIC","sql03_replyavailable: %s, state is '%s' \n",
                ERRMSG_COM_WRONG_CONN_STATE , sql03_statename(cip) ))
        return ( commErrNotOk_esp01 );
    }

    /*
     *  Set sql03_cip to the connection data of the currently active connection.
     *  This information is used by sql03_dump and sql03_catch_signal.
     */
    sql03_cip = cip;

    switch ( cip->ci_protocol )
    {
        char            *errm;

    case PROT_SHM_EO003 :
    case PROT_BIGSHM_EO003 :
        rc = sql33_replyavailable ( cip , pErrText );
        break;

    case PROT_SOCKET_EO003 :
        rc = sql23_replyavailable ( cip , pErrText );
        break;

    case PROT_NI_EO003 :
        rc = eo03NiSqlReplyAvailable ( &cip->NI, pErrText );
        break;

    default :
        if (cip->ci_vmt != NULL)
        {
            rc = cip->ci_vmt->replyavailable (cip, pErrText);
        }
        else
        {
            rc = commErrNotOk_esp01;
            en42FillErrText(pErrText,ERRMSG_UNSUPPORTED_PROTOCOL);
            MSGCD (( -11610,ERR_TYPE,"COMMUNIC",
                     "sql03_replyavailable: unsupported protocol %d \n", cip->ci_protocol ));
        }
    }

    DBG1 (( MF__,"returning %d \n", rc ))
    return ( rc );
}

/*
 * ===========================================================================
 */

    #undef MF__
    #define MF__ MOD__"sql03_receive"
static  int     sql03_receive (
    tsp00_Int4                        reference,
    void                            **packetp,
    tsp00_Int4                        *lengthp,
    tsp00_ErrTextc                  pErrText )
{
    int             rc;
    rte_header          *header;
    connection_info     *cip;


    DBG1 (( MF__,"ref %d \n", reference ))
    *packetp = 0;
    *lengthp = 0;

    rc =  en03GetAndCheckConnectionInfo( reference, CHECK_PID_EN03, &cip, "sql03_receive", pErrText );
    if ( rc != commErrOk_esp01 )
        return(rc);

    /*
     *  A receive is only allowed after a successful request.
     */
    if ( cip->ci_state != CON_REQUESTED_EO003 )
    {
        en42FillErrText( pErrText,
                         "%s:%s",
                         ERRMSG_COM_WRONG_CONN_STATE,
                         sql03_statename(cip) );
        MSGD (( -11608, ERR_TYPE, "COMMUNIC","sql03_receive: %s, state is '%s' \n",
                ERRMSG_COM_WRONG_CONN_STATE , sql03_statename(cip) ))
        return ( commErrNotOk_esp01 );
    }

    /*
     *  Set sql03_cip to the connection data of the currently active connection.
     *  This information is used by sql03_dump and sql03_catch_signal.
     */
    sql03_cip = cip;

    /*
     *  Set sql03_receiving to indicate that we are waiting for a reply.
     *  This information is used by sql03_catch_signal.
     */
    sql03_receiving = reference;

    switch ( cip->ci_protocol )
    {
    case PROT_SHM_EO003 :
    case PROT_BIGSHM_EO003 :
        rc = sql33_receive ( cip , pErrText );
        break;

#if SOCKETS
    case PROT_SOCKET_EO003 :
        rc = sql23_receive ( cip , pErrText );
        break;
#endif
    case PROT_NI_EO003 :
        {
            tsp00_Longuint            ulCmdDataLen;
            teo003_CommPacketRecord  *pResPacket;
            rc = eo03NiReceive ( &cip->NI, &pResPacket,
                                 &ulCmdDataLen,  pErrText );
            if ( rc == commErrOk_esp01 )
            {
                *lengthp = ulCmdDataLen;
                *packetp = pResPacket->pDataPart;
                DBG1 (( MF__,"NI: pResPacket 0x%08lx lgt %d \n",
                        (long) *packetp , *lengthp ))
            }
        }
        break;

    default :
        if (cip->ci_vmt != NULL)
        {
            rc = cip->ci_vmt->receive (cip, pErrText);
        }
        else
        {
            rc = commErrNotOk_esp01;
            en42FillErrText(pErrText,ERRMSG_UNSUPPORTED_PROTOCOL);
            MSGCD (( -11610,ERR_TYPE,"COMMUNIC",
                     "sql03_receive: unsupported protocol %d \n", cip->ci_protocol ));
        }
    }

    /*
     *  Clear sql03_receiving to indicate that we don't wait for a reply.
     *  This information is used by sql03_catch_signal.
     */
    sql03_receiving = 0;

    if ( rc == commErrOk_esp01 )
    {
        if ( cip->ci_protocol != PROT_NI_EO003 )
        {
            /* in case of NI communication the output parameter are set correctly */
            header = cip->ci_reply;
            *packetp = cip->ci_replyData;
            *lengthp = header->rh_max_send_len - RTE_HEADER_SIZE_EO003;
            DBG1 (( MF__,"pack 0x%08lx lgt %d \n", (long) *packetp , *lengthp ))

            /*
             *  If the packet itself was ok,
             *  deliver the returncode from the kernel's RTE.
             */
            if ( *lengthp > 0 )
                rc = header->rh_rte_return_code;
            else
                rc = commErrNotOk_esp01 ; /* connection broken */
        }

        cip->ci_state = CON_RECEIVED_EO003;

#ifdef  FROMKERNEL
        DBG1 (( MF__,"dumping packet to DUMPFILE \n" ))
        sql46_dump ( "\nFROMKERNEL---->", 16 );
        sql46_dump ( (char*) (*packetp) , (int) *lengthp );
        sql46_dump ( "<---------------", 18 - ((int)*lengthp + 13)%16 );
        sql46_dump ( "FROMKERNEL\n", 11 );
#endif
#ifdef  DEBUG_RTE
        header = cip->ci_reply;
        sql46_dump_packet ( header );
#endif
#ifdef  TRACE_RETCOD
        DBG1 (( MF__,"sp1r_returncode %d \n",
                ((tsp1_packet*)(header+1))->integer.C_2.sp1_segm.
                integer.C_4.sp1r_returncode ))
#endif
    }
    else
    {
        if ( rc == commErrReleased_esp01 ) rc = commErrNotOk_esp01 ; /* connection broken */
    }

    DBG1 (( MF__,"returning %d\n", rc ))
    return ( rc );
}

/*
 * ===========================================================================
 */

    #undef MF__
    #define MF__ MOD__"sql03_cancel"
static  int     sql03_cancel ( tsp00_Int4        reference,
                               tsp00_ErrTextc  pErrText )
{
    int             rc;
    connection_info *cip;

    DBGIN;

    rc =  en03GetAndCheckConnectionInfo( reference, CHECK_PID_EN03, &cip, "sql03_cancel", pErrText );
    if ( rc != commErrOk_esp01 )
        return(rc);

    /*
     *  A cancel is only allowed after a successful request.
     */
    if ( cip->ci_state != CON_REQUESTED_EO003 )
    {
        en42FillErrText(pErrText,ERRMSG_COM_WRONG_CONN_STATE);
        MSGD (( -11608, ERR_TYPE, "COMMUNIC","sql03_cancel: %s, state is '%s' \n",
                ERRMSG_COM_WRONG_CONN_STATE , sql03_statename(cip) ))
        return ( commErrNotOk_esp01 );
    }

    /*
     *  Set sql03_cip to the connection data of the currently active connection.
     *  This information is used by sql03_dump and sql03_catch_signal.
     */
    sql03_cip = cip;

    switch ( cip->ci_protocol )
    {
        char    *errm;

    case PROT_SHM_EO003 :
    case PROT_BIGSHM_EO003 :
        sql03_set_alarm ( LOCL_PKT_TMO );
        rc = sql33_cancel ( cip , pErrText );
        break;

#if SOCKETS
    case PROT_SOCKET_EO003 :
        sql03_set_alarm ( SOCK_PKT_TMO );
        rc = sql23_cancel ( cip , pErrText );
        break;
#endif
    case PROT_NI_EO003 :
        rc = (int )eo03NiSqlCancelDump( &cip->NI, 
                                        NULL /* PTS */,
                                        SQL_RTE_CANCEL_EO003,
                                        pErrText );
        break;

    default :
        if (cip->ci_vmt != NULL)
        {
            sql03_set_alarm ( SOCK_PKT_TMO );
            rc = cip->ci_vmt->cancel (cip, pErrText);
        }
        else
        {
            rc = commErrNotOk_esp01;
            en42FillErrText(pErrText,ERRMSG_UNSUPPORTED_PROTOCOL);
            MSGCD (( -11610,ERR_TYPE,"COMMUNIC",
                     "sql03_cancel: unsupported protocol %d \n", cip->ci_protocol ));
        }
    }
    sql03_reset_alarm ();

    DBG1 (( MF__,"returning %d \n", rc ))
    return ( rc );
}

/*
 * ===========================================================================
 */

    #undef MF__
    #define MF__ MOD__"sql03_dump"
static  int     sql03_dump ( tsp00_ErrTextc pErrText )
{
    int             rc;
    connection_info     *cip;


    DBGIN;

    /*
     *  Use the connection, which was active most recently.
     *  That connection set sql03_cip to its connection data.
     */
    cip = sql03_cip;

    if ( ! cip || cip->ci_state == CON_UNUSED_EO003 )
    {
        en42FillErrText(pErrText,ERRMSG_COM_WRONG_CONN_STATE);
        MSGD (( -11608, ERR_TYPE, "COMMUNIC", "sql03_dump: %s \n", ERRMSG_COM_WRONG_CONN_STATE ))
        return ( commErrNotOk_esp01 );
    }

    switch ( cip->ci_protocol )
    {
        char    *errm;

    case PROT_SHM_EO003 :
    case PROT_BIGSHM_EO003 :
        sql03_set_alarm ( LOCL_PKT_TMO );
        rc = sql33_dump ( cip , pErrText );
        break;

#if SOCKETS
    case PROT_SOCKET_EO003 :
        sql03_set_alarm ( SOCK_PKT_TMO );
        rc = sql23_dump ( cip , pErrText );
        break;
#endif

    case PROT_NI_EO003 :
        sql03_set_alarm ( SOCK_PKT_TMO );
        rc = eo03NiSqlCancelDump( &cip->NI,
                                  NULL /* PTS */,
                                  SQL_RTE_DUMP_EO003, 
                                  pErrText );
        break;

    default :
        if (cip->ci_vmt != NULL)
        {
            sql03_set_alarm ( SOCK_PKT_TMO );
            rc = cip->ci_vmt->dump (cip, pErrText);
        }
        else
        {
            rc = commErrNotOk_esp01;
            en42FillErrText(pErrText,ERRMSG_UNSUPPORTED_PROTOCOL);
            MSGCD (( -11610,ERR_TYPE,"COMMUNIC",
                     "sql03_dump: unsupported protocol %d \n", cip->ci_protocol ));
        }
    }
    sql03_reset_alarm ();

    DBG1 (( MF__,"returning %d \n", rc ))
    return ( rc );
}

/*
 * ===========================================================================
 */

    #undef MF__
    #define MF__ MOD__"sql03_find_free_index"
static  tsp00_Int4    sql03_find_free_index ()
{
    int                             idx;

    DBGIN;

    for ( idx = 0 ; idx < MAXCONNECTIONS_INL ; idx ++ )
    {
        if ( CONNECTION_AT_INL (idx)->ci_state == CON_UNUSED_EO003 )
        {
            /* reference goes from 1 to MAXCONNECTIONS */
            idx ++;
            DBG1 (( MF__,"returning %d\n", idx ))
            return ( (tsp00_Int4) idx );
        }
    }

    DBG1 (( MF__,"returning UNDEF\n" ));
    return ( UNDEF );
}

/*
 * ===========================================================================
 */

    #undef MF__
    #define MF__ MOD__"sql03_split_dbname"
global  void    sql03_split_dbname (
    char            *serverdb,
    char            *servernode )
{
    int                     c , lgt;
    char                    *p , *q;


    DBG1 (( MF__,"serverdb '%.19s' \n" , serverdb ))

    for ( p = NULL , lgt = 0;
            (c = sql03_nodeseparatorlist[lgt]) != '\0' ; lgt ++ )
    {
        p = (char *)strchr ( (char *)serverdb , c );
        if ( p != NULL ) break;
    }

    if ( p == NULL )
    {
        DBG1 (( MF__,"no nodeseparator found \n" ))
    }
    else
    {
        DBG1 (( MF__,"nodeseparator '%c' \n" , *p ))
        lgt = p - serverdb;
        strncpy ( servernode , serverdb , lgt );
        servernode[lgt] = '\0';

        for ( q = serverdb , p ++ ; *p ; p ++ )
        {
            *(q ++) = *p;
        }
        *q = '\0';
    }

    DBG1 (( MF__,"servernode '%s' \n" , servernode ))
    DBG1 (( MF__,"serverdb   '%s' \n" , serverdb ))
}

/*
 * ===========================================================================
 */

    #undef MF__
    #define MF__ MOD__"sql03_get_protocol"
static  int    sql03_get_protocol ( char                   *Node,  /* or parouter string */
                                    connection_info        *cip,
                                    tsp00_ErrTextc          pErrText)
{
    int             rc;
    int             lnod;
    int             lnam;
    FILE               *fp;
    char               *ptr;
    VF_FILENAMEC        file;
    VF_FILENAMEC        dbname;
    SQL_NODEIDC     local_hostname;
    SQL_NODEIDC     local_nodename;
    char                line [ 256 ];
    int               IsSaprouterString = FALSE;

    DBGIN;
    lnod = strlen ( (const char *)Node );
    lnam = strlen ( (const char *)cip->ci_peer_dbname );

    /*
     *  My node name
     */
    if ( lnod )
    {
        memset ( local_hostname , 0 , sizeof(local_hostname) );
        memset ( local_nodename , 0 , sizeof(local_nodename) );

        /*
         *  Get the server's official node name.
         */

        IsSaprouterString = eo40NiIsSaprouterSring ( Node );

        if (!IsSaprouterString )
        {
            if ( sql43_is_inet_addr(Node) == TRUE )
        strncpy ( cip->ci_peer_node , Node, sizeof(cip->ci_peer_node) );
            else
            {
                rc = sql43_get_official_node_name ( Node,
                                                    (char *)local_nodename,
                                                    sizeof(local_nodename) );
                if ( ! rc )
                {
          strncpy ( cip->ci_peer_node , local_nodename ,
                           sizeof(cip->ci_peer_node) );
                }
                else
          strncpy ( cip->ci_peer_node, Node, sizeof(cip->ci_peer_node) );

                lnod = strlen ( (const char *)cip->ci_peer_node );
            }
        }

        DBG1 (( MF__,"peer node '%s' \n", cip->ci_peer_node ))
        memset ( local_nodename , 0 , sizeof(local_nodename) );

        /*
         *  Get my host name.
         */
        (void) sql43_get_my_host_name ( (char *)local_hostname ,sizeof(local_hostname) );
        DBG1 (( MF__,"local host '%s' \n", local_hostname ))

        /*
         *  Get my official node name.
         */
        (void) sql43_get_official_node_name ( (char *)local_hostname,
                                              (char *)local_nodename,
                                              sizeof(local_nodename) );

        DBG1 (( MF__,"local node '%s' \n", local_nodename ))
    }

    if ( IsSaprouterString ) {
        if ( !fNI_Installed ) {
            if ( !(fNI_Installed = eo03NiInit(pErrText) != 0) ) {
                return( commErrNotOk_esp01 ) ;
            }
        }
        cip->ci_protocol = PROT_NI_EO003 ;
        DBG1 (( MF__,"NI connection \n" ))
    }
    else
        if ( lnod
            && ( strcmp ( (const char *)cip->ci_peer_node , (const char *)local_nodename )
            ||
            ( (ptr = getenv ( "DBSOCKETS" )) && *ptr && !strchr("0Nn",*ptr) )
            )
            ) {
        cip->ci_protocol = PROT_SOCKET_EO003 ;
        DBG1 (( MF__,"remote connection \n" ))
        DBG1 (( MF__, "node '%s' db '%s'\n", cip->ci_peer_node , cip->ci_peer_dbname ))
    }
    else {
        cip->ci_protocol = PROT_BIGSHM_EO003 ;
        DBG1 (( MF__,"local connection \n" ))
    }


    if ((cip->ci_service == srvControl_esp01)
            && (cip->ci_protocol == PROT_BIGSHM_EO003)) {
        cip->ci_protocol = PROT_LOCAL_CONTROL_EO003;
    }
#ifdef  DEBUG_RTE
    switch ( cip->ci_protocol )
    {
    case PROT_SOCKET_EO003 :
        DBG1 (( MF__,"remote C connect \n" ))
        break;

    case PROT_SHM_EO003 :
        DBG1 (( MF__,"local small C connect \n" ))
        break;

    case PROT_BIGSHM_EO003 :
        DBG1 (( MF__,"local C connect \n" ))
        break;

    case PROT_NI_EO003 :
        DBG1 (( MF__,"NI connect \n" ))
        break;

    default :
        MSGD (( -11626, ERR_TYPE, "COMMUNIC", "illegal protocol type %d \n",
                cip->ci_protocol ))
    }
#endif  /*DEBUG_RTE*/
    return(commErrOk_esp01);
}

/*==========================================================================*/

static  char    *sql03_statename (
    connection_info     *cip )
{
    if ( ! cip ) return ( "no connection" );
    switch ( cip->ci_state )
    {
    case CON_UNUSED_EO003 :     return ( "unused" );
    case CON_CONNECTING_EO003 : return ( "connecting" );
    case CON_CONNECTED_EO003 :  return ( "established" );
    case CON_REQUESTED_EO003 :  return ( "requested" );
    case CON_RECEIVED_EO003 :       return ( "received" );
    case CON_TIMEDOUT_EO003 :       return ( "timed out" );
    case CON_CANCELLED_EO003 :      return ( "aborted" );
    }
    return ( "illegal" );
}

/*==========================================================================*/

static  void    sql03_set_signals ( )
{
    SIGNALFUNCTYPE      (*old_fetched_signal_func)();

    if (sql03_connect_pool.isMultiThreaded) {
        DBG1 (( MF__,"multi threaded, signals not touched \n" ));
        return;
    }
    DBG1 (( MF__,"setting signals \n" ));

    old_fetched_signal_func = sql03_oldsigpipe;
    sql03_oldsigpipe = signal ( SIGPIPE , SIG_IGN );
    DBG1 (( MF__,"old SIGPIPE 0x%08lx \n",
            (long) sql03_oldsigpipe ));
    if ( sql03_oldsigpipe == SIG_IGN )
    {
        /*
         *  Signal handler has already been set by a previous connect.
         *  Restore the original signal handler address.
         */
        sql03_oldsigpipe = old_fetched_signal_func;
    }
    else  /* PTS 1106233 */
        /* if SIGPIPE not handled by user, ignore it */
        if ( sql03_oldsigpipe != SIG_DFL )
        {
            DBG1 (( MF__,"leaving SIGPIPE unchanged \n" ))
            (void) signal ( SIGPIPE , sql03_oldsigpipe );
        }

  if ( !sqlIsRunTimeComponent() )
  {
    old_fetched_signal_func = sql03_fetched_sigint;
    sql03_fetched_sigint = signal ( SIGINT  , sql03_catch_signal );
    DBG1 (( MF__,"old SIGINT  0x%08lx \n",
            (long) sql03_fetched_sigint ))
    if ( sql03_fetched_sigint == (SIGNALFUNCTYPE(*)()) sql03_catch_signal )
    {
        /*
         *  Signal handler has already been set by a previous connect.
         *  Restore the original signal handler address.
         */
        sql03_fetched_sigint = old_fetched_signal_func;
    }

    old_fetched_signal_func = sql03_oldsighup;
    sql03_oldsighup = signal ( SIGHUP  , sql03_catch_signal );
    DBG1 (( MF__,"old SIGHUP  0x%lx \n",
            (long) sql03_oldsighup ));
    if ( sql03_fetched_sigint == (SIGNALFUNCTYPE(*)()) sql03_catch_signal )
    {
        /*
         *  Signal handler has already been set by a previous connect.
         *  Restore the original signal handler address.
         */
        sql03_oldsighup = old_fetched_signal_func;
    }

    old_fetched_signal_func = sql03_oldsigterm;
    sql03_oldsigterm = signal ( SIGTERM  , sql03_catch_signal );
    DBG1 (( MF__,"old SIGTERM  0x%lx \n",
            (long) sql03_oldsigterm ));
    if ( sql03_oldsigterm == (SIGNALFUNCTYPE(*)()) sql03_catch_signal )
    {
        /*
         *  Signal handler has already been set by a previous connect.
         *  Restore the original signal handler address.
         */
        sql03_oldsigterm = old_fetched_signal_func;
    }
  }
}

/*==========================================================================*/

    #undef MF__
    #define MF__ MOD__"sql03_reset_signals"
static  void    sql03_reset_signals ( )
{
    if (sql03_connect_pool.isMultiThreaded) {
        DBG1 (( MF__,"multi threaded, signals not touched \n" ))
        return;
    }
    DBG1 (( MF__,"resetting signals \n" ))

    /* PTS 1106233 */
    if ( sql03_oldsigpipe  != SIG_ERR )
    {
        (void) signal ( SIGPIPE  , sql03_oldsigpipe  );
        sql03_oldsigpipe = SIG_ERR;
    }
  if ( !sqlIsRunTimeComponent() )
  {
    if ( sql03_oldsighup  != SIG_ERR )
    {
        (void) signal ( SIGHUP  , sql03_oldsighup  );
        sql03_oldsighup = SIG_ERR;
    }
    if ( sql03_oldsigterm != SIG_ERR )
    {
        (void) signal ( SIGTERM , sql03_oldsigterm );
        sql03_oldsigterm = SIG_ERR;
    }
  }
}

/*==========================================================================*/


    #undef MF__
    #define MF__ MOD__"sql03_set_alarm"
static  void    sql03_set_alarm (
    unsigned                interval )
{
    connection_info     *cip;

    if (sql03_connect_pool.isMultiThreaded) {
        DBG1 (( MF__,"multi threaded, alarm not set \n" ))
        return;
    }
    DBG1 (( MF__,"setting alarm %u \n", interval ))

    sql03_oldsigalrm = signal ( SIGALRM , sql03_catch_signal );
    sql03_oldalarm   = alarm  ( interval );

    if ( sql03_oldalarm != 0 ) sql03_oldclock = time ( (time_t*)0 );

    DBG1 (( MF__,"oldalarm %u \n", sql03_oldalarm ))

}

/*==========================================================================*/

    #undef MF__
    #define MF__ MOD__"sql03_reset_alarm"
static  void    sql03_reset_alarm ( )
{
    long            interval;


    if (sql03_connect_pool.isMultiThreaded)
    {
        DBG1 (( MF__,"multi threaded, alarm not reset \n" ))
        return;
    }
    DBG1 (( MF__,"resetting alarm \n" ))

    if ( sql03_oldalarm != 0 )
    {
        interval = sql03_oldalarm - (time( (time_t*)0 ) - sql03_oldclock);
        if ( interval <= 0 ) interval = 1;
    }
    else
    {
        interval = 0;
    }
    (void) alarm ( (unsigned) interval );
    (void) signal ( SIGALRM , sql03_oldsigalrm );
    DBG1 (( MF__,"alarm %u \n" , (unsigned) interval ))
}

/*==========================================================================*/

    #undef MF__
    #define MF__ MOD__"sql03_catch_signal"
static  SIGNALFUNCTYPE  sql03_catch_signal (
    int                     sig )
{
    int              do_exit;
    connection_info *cip;


    (void) signal ( sig , SIG_IGN );
    MSGD (( -11987, INFO_TYPE, "COMMUNIC",
            "sql03_catch_signal: caught signal %d \n", sig ));

    /*
     *  Use the connection, which is currently active.
     *  That connection set sql03_cip to its connection data.
     */
    cip = sql03_cip;
    if ( cip && (cip->ci_state == CON_UNUSED_EO003) ) cip = 0;

    switch ( sig )
    {
    case SIGALRM:
        if ( cip ) cip->ci_state = CON_TIMEDOUT_EO003;
        break;

    case SIGINT:
        /*
         *  Normally, when an interrupt signal comes, terminate.
         */
        do_exit = TRUE;

        /*
         *  If waiting for kernel reply, cancel the SQL-command
         *  and don't exit.
         */
        if ( sql03_receiving && cip )
        {
            tsp00_ErrTextc  pErrText;
            (void) sql03_cancel ( cip->ci_my_ref , pErrText );
            do_exit = FALSE;
        }

        /*
         *  If the user supplied an interrupt handler,
         *  call it now and don't exit.
         */
        if ( sql03_fetched_sigint != SIG_DFL &&
                sql03_fetched_sigint != SIG_IGN &&
                sql03_fetched_sigint != (SIGNALFUNCTYPE(*)())sql03_catch_signal  )
        {
            sql03_fetched_sigint ( sig );
            do_exit = FALSE;
        }

        if ( do_exit ) exit ( 5 );
        break;

    case SIGHUP:
        if ( cip && ((cip->ci_protocol == PROT_SHM_EO003) ||
                     (cip->ci_protocol == PROT_BIGSHM_EO003)) )
        {
            sql33_cleanup ( cip );
        }

        if ( sql03_oldsighup != SIG_DFL &&
                sql03_oldsighup != SIG_IGN &&
                sql03_oldsighup != (SIGNALFUNCTYPE(*)()) sql03_catch_signal  )
        {
            sql03_oldsighup(sig);
        }
        break;

    case SIGTERM:
        if ( cip && ((cip->ci_protocol == PROT_SHM_EO003) ||
                     (cip->ci_protocol == PROT_BIGSHM_EO003)) )
        {
            sql33_cleanup ( cip );
        }

        if ( sql03_oldsigterm != SIG_DFL &&
                sql03_oldsigterm != SIG_IGN &&
                sql03_oldsigterm != (SIGNALFUNCTYPE(*)()) sql03_catch_signal  )
        {
            sql03_oldsigterm(sig);
        }
        break;

    default:
        if ( cip && ((cip->ci_protocol == PROT_SHM_EO003) ||
                     (cip->ci_protocol == PROT_BIGSHM_EO003)) )
        {
            sql33_cleanup ( cip );
        }
        break;
    }

    DBG1 (( MF__,"reestablishing signal %d \n" , sig ))
    (void) signal ( sig , sql03_catch_signal );
}

/*--------------------------------------------------*/

void sql03_init_multi_threaded (
    teo07_MutexFunction *createMutex,
    teo07_MutexFunction *destroyMutex,
    teo07_MutexFunction *lockMutex,
    teo07_MutexFunction *unlockMutex)
{
    sql03_connect_pool.isMultiThreaded = TRUE;
    sql03_connect_pool.createMutex     = createMutex;
    sql03_connect_pool.destroyMutex    = destroyMutex;
    sql03_connect_pool.lockMutex       = lockMutex;
    sql03_connect_pool.unlockMutex     = unlockMutex;
    createMutex (&sql03_connect_pool.mutex);
}

/*--------------------------------------------------*/

static void sql03_init_connections (
    ten03_connect_pool* connectPool,
    int firstIndex,
    int count)
{
    int i;

    memset (connectPool->connection + firstIndex, '\0',
          count * sizeof (connection_info));
    connectPool->connectionCount = firstIndex + count;
}

/*--------------------------------------------------*/

static void sql03_finish_connections (void)
{
    if (sql03_connect_pool.isMultiThreaded) {
        sql03_connect_pool.destroyMutex (&sql03_connect_pool.mutex);
        sql03_connect_pool.createMutex  = NULL;
        sql03_connect_pool.destroyMutex = NULL;
        sql03_connect_pool.lockMutex    = NULL;
        sql03_connect_pool.unlockMutex  = NULL;
        sql03_connect_pool.isMultiThreaded = FALSE;
    }
    FREE_MEM_EO57( sql03_connect_pool.connection );
    sql03_connect_pool.connection = NULL;
    sql03_connect_pool.connectionCount = 0;
    sql03_connect_pool.initialized = FALSE;
}

/*--------------------------------------------------*/

static int sql03_init_connect_pool (ten03_connect_pool* connectPool)
{
    static const int firstChunk = 8;
    int bytesToAllocate = firstChunk * sizeof (connection_info);

    if (connectPool->connection != NULL) {
        MSGCD (( -11600,ERR_TYPE,"COMMUNIC",
                 "ABEND: sql03_init: already initialized before \n" ))
        sqlabort ();
    }
    if ( ALLOC_MEM_EO57( (void **)&(connectPool->connection), bytesToAllocate)
            != NO_ERROR_EO001 )
    {
        MSGCD (( -11600,ERR_TYPE,"COMMUNIC",
                 "ABEND: sql03_init: out of memory\n" ))
        sqlabort ();
    }
    sql03_init_connections (connectPool, 0, firstChunk);
    connectPool->initialized = TRUE;
    return TRUE;
}

/*--------------------------------------------------*/

static tsp00_Bool sql03_realloc_pool (ten03_connect_pool* connectPool)
{
    connection_info *oldMemory;
    connection_info *newMemory;
    int              oldMax = connectPool->connectionCount;
    int              newMax = oldMax * 2;

    if ( ALLOC_MEM_EO57( (void **)&newMemory, newMax * sizeof (connection_info))
            != NO_ERROR_EO001 )
    {
        return FALSE;
    }
    memcpy( newMemory, connectPool->connection, oldMax * sizeof(connection_info) );
    oldMemory = connectPool->connection;
    connectPool->connection = newMemory;

    FREE_MEM_EO57( oldMemory );

    sql03_init_connections (connectPool, oldMax, newMax - oldMax);

    return TRUE;
}

/*--------------------------------------------------*/

static tsp00_Int4 sql03_alloc_connect (void)
{
    tsp00_Int4    result;
    tsp00_Bool     allocOK;

    if (!sql03_connect_pool.initialized) {
        sql03_init_connect_pool (&sql03_connect_pool);
    }
    if (sql03_connect_pool.isMultiThreaded) {
        sql03_connect_pool.lockMutex (&sql03_connect_pool.mutex);
    }
    result = sql03_find_free_index ();
    if (result == UNDEF) {
        allocOK = sql03_realloc_pool (&sql03_connect_pool);
        if (allocOK) {
            result = sql03_find_free_index ();
        }
    }
    if (sql03_connect_pool.isMultiThreaded) {
        sql03_connect_pool.unlockMutex (&sql03_connect_pool.mutex);
    }
    return result;
}

/*--------------------------------------------------*/

static int sql03_free_connect (int ref, char** msg)
{
    int result;
    tsp00_ErrTextc errtext;

    if (sql03_connect_pool.isMultiThreaded) {
        sql03_connect_pool.lockMutex (&sql03_connect_pool.mutex);
    }
    result = sql03_release (ref, errtext);
    if (sql03_connect_pool.isMultiThreaded) {
        sql03_connect_pool.unlockMutex (&sql03_connect_pool.mutex);
    }
    return result;
}

/*===========================================================================*
 *  END OF CODE                                                              *
 *===========================================================================*/
