hp Reliable Transaction Router
C Application Programmer's
Reference Manual


Previous Contents Index


Appendix A
RTR C API Sample Applications

A.1 Overview

The software kit contains a short sample application that is unsupported and not part of the RTR product. Code for the sample application is in the [EXAMPLES] directory on the software kit. This sample application contains four components:

adg_client.c
adg_server.c
adg_shared.c
adg_header.h

The code is shown on the next few pages. Note the following:

A.2 Client Application


/* Client Application */ 
 
/************************************************************************** 
* Copyright Compaq Computer Corporation 1998. All rights reserved. 
* Restricted Rights: Use, duplication, or disclosure by the U.S. Government 
* is subject to restrictions as set forth in subparagraph (c) (1) (ii) of 
* DFARS 252.227-7013, or in FAR 52.227-19, or in FAR 52.227-14 Alt. III, as 
* applicable. 
* This software is proprietary to and embodies the confidential technology of 
* Compaq Computer Corporation. Possession, use, of copying of this software 
* and media is authorized only pursuant to a valid written license from Compaq, 
* Digital or an authorized sublicensor. 
******************************************************************************/ 
/***************************************************************************** 
* APPLICATION: RTR Sample Client Application 
* MODULE NAME: adg_client.c 
* AUTHOR:      Compaq Computer Corporation 
* DESCRIPTION: This client application initiates transactions and requests 
*              transaction status asynchronously. It is to be used with 
               adg_server.c, adg_header.h, and adg_shared.c. 
* DATE       : Oct 22, 1998 
******************************************************************************/ 
/* 
    adg_client.c 
 
    Goes with adg_server.c 
 
    To build on Unix: 
        cc -o adg_client adg_client.c adg_shared.c -lrtr 
*/ 
 
#include "adg_header.h" 
 
void declare_client ( rtr_channel_t *pchannel ); 
FILE *fpLog; 
 
int main ( int argc, char *argv[] ) 
{ 
    /* 
     * This program expects 3 parameters : 
     *   1: client number (1 or 2) 
     *   2: partition range 
     *   3: messages to send 
     */ 
 
    rtr_status_t        status; 
    rtr_channel_t       channel ; 
    time_t time_val = { 0 }; 
 
    message_data_t send_msg = {0}; 
    receive_msg_t receive_msg = {0}; 
    int txn_cnt; 
    rtr_timout_t receive_time_out = RTR_NO_TIMOUTMS; 
    rtr_msgsb_t msgsb; 
    char CliLog[80]; 
 
    send_msg.sequence_number = 1 ; 
    strcpy( send_msg.text , "from Client"); 
 
    get_client_parameters( argc , argv, &send_msg, &txn_cnt); 
 
    sprintf( CliLog, "CLIENT_%c_%d.LOG", send_msg.routing_key, 
             send_msg.client_number ); 
    fpLog = fopen( CliLog, "w"); 
 
    if ( fpLog == NULL ) 
    { 
        perror("adg_client: fopen failed"); 
        fprintf(stderr, " Error opening client log %s\n", CliLog ); 
        exit(EXIT_FAILURE); 
    } 
 
    printf( "\n Client log = %s\n", CliLog ); 
 
    fprintf(fpLog, " txn count = %d\n", txn_cnt ); 
    fprintf(fpLog, " client number = %d\n", send_msg.client_number ); 
    fprintf(fpLog, " routing key = %c\n\n", send_msg.routing_key); 
 
    declare_client ( &channel ); 
 
    /* Send the requested number of txns */ 
 
    for ( ; txn_cnt > 0; txn_cnt--, send_msg.sequence_number++ ) 
    { 
        status = rtr_send_to_server( 
                channel, 
                RTR_NO_FLAGS , 
                &send_msg, 
                sizeof(send_msg), 
                msgfmt ); 
 
        check_status( "rtr_send_to_server", status ); 
 
        fprintf(fpLog, "\n *************    sequence %10d *************\n", 
                send_msg.sequence_number); 
        time(&time_val); 
        fprintf(fpLog, "   send_to_server at:         %s", 
                ctime( &time_val)); 
        fflush(fpLog); 
 
        /* 
         *  Get the server's reply OR 
         *  an rtr_mt_rejected 
         */ 
 
        status = rtr_receive_message( 
                        &channel, 
                        RTR_NO_FLAGS, 
                        RTR_ANYCHAN, 
                        &receive_msg, 
                        sizeof(receive_msg), 
                        receive_time_out, 
                        &msgsb); 
 
        check_status( "rtr_receive_message", status ); 
 
        time(&time_val); 
        switch (msgsb.msgtype) 
        { 
        case rtr_mt_reply: 
            fprintf(fpLog, "   reply from server at:      %s", 
                    ctime( &time_val)); 
            fprintf(fpLog, "     sequence %10d from server %d\n", 
                    receive_msg.receive_data_msg.sequence_number, 
                    receive_msg.receive_data_msg.server_number); 
            fflush(fpLog); 
            break; 
 
        case rtr_mt_rejected: 
            fprintf(fpLog, "  txn rejected at:            %s", 
                    ctime( &time_val)); 
            fprint_tid(fpLog, &msgsb.tid ); 
            fprintf(fpLog, "     status is : %d\n", status); 
            fprintf(fpLog, "     %s\n", rtr_error_text(status)); 
            fflush(fpLog); 
 
            /* Resend same sequence_number after reject */ 
            send_msg.sequence_number--; 
            txn_cnt++; 
            break; 
 
        default: 
            fprintf(fpLog, 
                    "  unexpected msg at: %s", ctime( &time_val)); 
            fprint_tid(fpLog, &msgsb.tid ); 
            fflush(fpLog); 
            exit(EXIT_FAILURE); 
        } 
 
 
        if (msgsb.msgtype == rtr_mt_reply) 
        { 
            status = rtr_accept_tx( 
                            channel, 
                            RTR_NO_FLAGS, 
                            RTR_NO_REASON ); 
 
            check_status( "rtr_accept_tx", status ); 
 
            status = rtr_receive_message( 
                            &channel, 
                            RTR_NO_FLAGS, 
                            RTR_ANYCHAN, 
                            &receive_msg, 
                            sizeof(receive_msg), 
                            receive_time_out, 
                            &msgsb); 
 
            check_status( "rtr_receive_message", status ); 
 
            time(&time_val); 
 
            switch ( msgsb.msgtype ) 
            { 
            case rtr_mt_accepted: 
                fprintf(fpLog, "   txn accepted at :          
                        %s", ctime( &time_val)); 
                fprint_tid(fpLog, &msgsb.tid ); 
                fflush(fpLog); 
                break; 
 
            case rtr_mt_rejected: 
                fprintf(fpLog, "   txn rejected at :          
                       %s", ctime( &time_val)); 
                fprint_tid(fpLog, &msgsb.tid ); 
                fprintf(fpLog, "      status is : %d\n", 
                       receive_msg.receive_status_msg.status); 
                fprintf(fpLog, " %s\n", 
                       rtr_error_text(receive_msg.receive_status_msg.status)); 
                fflush(fpLog); 
 
                /* Resend same sequence_number after reject */ 
 
                send_msg.sequence_number--; 
                txn_cnt++; 
                break; 
 
            default: 
                fprintf(fpLog, 
                        "    unexpected status on rtr_mt_accepted message\n"); 
                fprint_tid(fpLog, &msgsb.tid ); 
                fprintf(fpLog, "      status is : %d\n", 
                        receive_msg.receive_status_msg.status); 
                fprintf(fpLog, 
                " %s\n", rtr_error_text(receive_msg.receive_status_msg.status)); 
                fflush(fpLog); 
                break; 
            } 
        } 
 
 
    } 
 
    close_channel ( channel ); 
} 
 
void 
declare_client ( rtr_channel_t *pchannel ) 
{ 
    rtr_status_t        status; 
    receive_msg_t       receive_msg; 
    rtr_timout_t receive_time_out = RTR_NO_TIMOUTMS;  /* forever */ 
    rtr_msgsb_t msgsb;  /* Structure into which receive puts msgtype */ 
 
    status = rtr_open_channel( 
                    pchannel, 
                    RTR_F_OPE_CLIENT , 
                    FACILITY_NAME, 
                    NULL,                       /* rpcnam */ 
                    RTR_NO_PEVTNUM, 
                    RTR_NO_ACCESS               /* access */ 
                    RTR_NO_NUMSEG , 
                    RTR_NO_PKEYSEG ); 
 
    check_status( "rtr_open_channel", status); 
 
    status = rtr_receive_message( 
                    pchannel, 
                    RTR_NO_FLAGS, 
                    RTR_ANYCHAN, 
                    &receive_msg, 
                    sizeof(receive_msg), 
                    receive_time_out, 
                    &msgsb); 
 
    check_status( "rtr_receive_message", status ); 
 
    if ( msgsb.msgtype != rtr_mt_opened ) 
    { 
       fprintf(fpLog, " Error opening rtr channel %s : \n", FACILITY_NAME); 
 
        fprintf(fpLog, "%s\n", 
                rtr_error_text(receive_msg.receive_status_msg.status)); 
        exit(EXIT_FAILURE); 
    } 
 
    fprintf(fpLog, " Client channel successfully opened\n"); 
    return; 
} 

A.3 Server Application


/* Server Application */ 
 
/*************************************************************************** 
* Copyright Compaq Computer Corporation 1998. All rights reserved. 
* Restricted Rights: Use, duplication, or disclosure by the U.S. Government 
* is subject to restrictions as set forth in subparagraph (c) (1) (ii) of 
* DFARS 252.227-7013, or in FAR 52.227-19, or in FAR 52.227-14 Alt. III, as 
* applicable. 
* This software is proprietary to and embodies the confidential technology of 
* Compaq Computer Corporation. Possession, use, of copying of this software 
* and media is authorized only pursuant to a valid written license from Compaq, 
* Digital or an authorized sublicensor. 
******************************************************************************/ 
/***************************************************************************** 
* APPLICATION: RTR Sample Server Application 
* MODULE NAME: adg_server.c 
* AUTHOR     : Compaq Computer Corporation 
* DESCRIPTION: This server application receives transactions and receives 
*              transaction status. It is to be used with adg_client.c, 
*              adg_header.h, and adg_shared.c. 
* DATE       : Oct 22, 1998 
******************************************************************************/ 
/* 
    adg_server.c 
      Goes with adg_client.c 
 
    To build on Unix: 
        cc -o adg_server adg_server.c adg_shared.c -lrtr 
*/ 
 
#include "adg_header.h" 
 
void declare_server (rtr_channel_t *channel, const message_data_t *outmsg); 
 
FILE *fpLog; 
 
int main( int argc, char *argv[] ) 
{ 
    /* 
     * This program expects 2 parameters : 
     *   1: server number (1 or 2) 
     *   2: partition range 
     */ 
 
    rtr_msgsb_t msgsb; 
    receive_msg_t receive_msg; 
    message_data_t reply_msg; 
    rtr_timout_t receive_time_out = RTR_NO_TIMOUTMS; 
    char SvrLog[80]; 
    time_t time_val = { 0 }; 
 
    rtr_channel_t   channel; 
 
    rtr_status_t    status      = (rtr_status_t)0; 
    rtr_bool_t replay; 
 
    strcpy( reply_msg.text , "from Server"); 
 
    get_server_parameters ( argc, argv, &reply_msg ); 
 
    sprintf( SvrLog, "SERVER_%c_%d.LOG", reply_msg.routing_key, 
             reply_msg.server_number ); 
    fpLog = fopen( SvrLog, "w"); 
 
    if ( fpLog == NULL ) 
    { 
        perror("adg_server: fopen() failed"); 
        printf( " Error opening server log %s\n", SvrLog ); 
        exit(EXIT_FAILURE); 
    } 
 
    printf( " Server log = %s\n", SvrLog ); 
 
    fprintf(fpLog, " server number = %d\n", reply_msg.server_number ); 
    fprintf(fpLog, " routing key = %c\n", reply_msg.routing_key); 
 
    declare_server(&channel, &reply_msg); 
 
    while ( RTR_TRUE ) 
    { 
        status = rtr_receive_message( 
                                     &channel, 
                                     RTR_NO_FLAGS, 
                                     RTR_ANYCHAN, 
                                     &receive_msg, 
                                     sizeof(receive_msg), 
                                     receive_time_out, 
                                     &msgsb); 
        check_status( "rtr_receive_message", status); 
 
        time(&time_val); 
 
        switch (msgsb.msgtype) 
        { 
        case rtr_mt_msg1_uncertain: 
        case rtr_mt_msg1: 
            if (msgsb.msgtype ==  rtr_mt_msg1_uncertain) 
                replay = RTR_TRUE; 
            else 
                replay = RTR_FALSE; 
 
           fprintf(fpLog, "\n *************    sequence %10d *************\n", 
                    receive_msg.receive_data_msg.sequence_number); 
 
            if ( replay == RTR_TRUE ) 
                fprintf(fpLog, "   uncertain txn started at :%s", 
                        ctime( &time_val)); 
            else 
                fprintf(fpLog, "   normal txn started at :%s", 
                        ctime( &time_val)); 
 
            fprintf(fpLog, "     sequence %10d from client %d\n", 
                    receive_msg.receive_data_msg.sequence_number, 
                    receive_msg.receive_data_msg.client_number); 
            fflush(fpLog); 
 
            reply_msg.sequence_number = 
                    receive_msg.receive_data_msg.sequence_number; 
 
            status = rtr_reply_to_client ( 
                                          channel, 
                                          RTR_NO_FLAGS, 
                                          &reply_msg, 
                                          sizeof(reply_msg), 
                                          msgfmt); 
 
            check_status( "rtr_reply_to_client", status); 
            break; 
 
        case rtr_mt_prepare: 
            fprintf(fpLog, "   txn prepared at :          %s", 
                    ctime( &time_val)); 
            fflush(fpLog); 
 
            status = rtr_accept_tx ( 
                                    channel, 
                                    RTR_NO_FLAGS, 
                                    RTR_NO_REASON); 
            check_status( "rtr_accept_tx", status); 
            break; 
 
        case rtr_mt_rejected: 
            fprintf(fpLog, "   txn rejected at :          %s", 
                    ctime( &time_val)); 
            fprint_tid(fpLog, &msgsb.tid ); 
            fprintf(fpLog, "      status is : %d\n", status); 
            fprintf(fpLog, "      %s\n", rtr_error_text(status)); 
            fflush(fpLog); 
            break; 
 
        case rtr_mt_accepted: 
            fprintf(fpLog, "   txn accepted at :          %s", 
                    ctime( &time_val)); 
            fprint_tid(fpLog, &msgsb.tid ); 
            fflush(fpLog); 
            break; 
 
        } /* End of switch */ 
    } /* While loop */ 
} 
 
void 
declare_server (rtr_channel_t *channel, const message_data_t *outmsg) 
{ 
    rtr_status_t    status; 
    rtr_uns_32_t    numseg = 1; 
    rtr_keyseg_t    p_keyseg[1]; 
    receive_msg_t  receive_msg; 
    rtr_timout_t receive_time_out = RTR_NO_TIMOUTMS;  /* forever */ 
    rtr_msgsb_t msgsb;   /* Structure into which receive puts msgtype */ 
    const char *facility = FACILITY_NAME; 
 
    p_keyseg[0].ks_type = rtr_keyseg_string; 
    p_keyseg[0].ks_length  = 1; 
    p_keyseg[0].ks_offset  =  0; 
    p_keyseg[0].ks_lo_bound = 
             /* const_cast */ (rtr_uns_8_t *)(&outmsg->routing_key); 
    p_keyseg[0].ks_hi_bound = 
             /* const_cast */ (rtr_uns_8_t *)(&outmsg->routing_key); 
 
    status = rtr_open_channel( 
                    &channel, 
                    RTR_F_OPE_SERVER,/* | RTR_F_OPE_EXPLICIT_ACCEPT | */ 
                                     /*   RTR_F_OPE_EXPLICIT_PREPARE, */ 
                    facility, 
                    NULL,            /* rpcnam */ 
                    RTR_NO_PEVTNUM, 
                    RTR_NO_ACCESS,   /* access */ 
                    numseg, 
                    p_keyseg); 
 
    check_status( "rtr_open_channel", status); 
 
    status = rtr_receive_message( 
                    &channel, 
                    RTR_NO_FLAGS, 
                    RTR_ANYCHAN, 
                    &receive_msg, 
                    sizeof(receive_msg), 
                    receive_time_out, 
                    &msgsb); 
 
    check_status( "rtr_receive_message", status); 
 
    if ( msgsb.msgtype != rtr_mt_opened ) 
    { 
        fprintf(fpLog, " Error opening rtr channel %s: \n", facility); 
 
        fprintf(fpLog, "%s\n", 
                rtr_error_text(receive_msg.receive_status_msg.status)); 
        fclose (fpLog); 
        exit(EXIT_FAILURE); 
    } 
 
    fprintf(fpLog, "  Server channel successfully opened \n"); 
    return; 
} 
 

A.4 Shared Code


/* Shared Code */ 
 
/***************************************************************************** 
* Copyright Compaq Computer Corporation 1998. All rights reserved. 
* Restricted Rights: Use, duplication, or disclosure by the U.S. Government 
* is subject to restrictions as set forth in subparagraph (c) (1) (ii) of 
* DFARS 252.227-7013, or in FAR 52.227-19, or in FAR 52.227-14 Alt. III, as 
* applicable. 
* This software is proprietary to and embodies the confidential technology of 
* Compaq Computer Corporation. Possession, use, of copying of this software 
* and media is authorized only pursuant to a valid written license from Compaq, 
* Digital or an authorized sublicensor. 
*******************************************************************************/ 
/****************************************************************************** 
* APPLICATION: RTR Sample Client Application 
* MODULE NAME: adg_shared.c 
* AUTHOR         : Compaq Computer Corporation 
* DESCRIPTION: This shared code is to be used with adg_server.c, 
*                          adg_header.h, and adg_client.c. 
* DATE           : Oct 22, 1998 
*******************************************************************************/ 
 
#include "adg_header.h" 
 
void 
check_status( char *call, rtr_status_t status ) 
{ 
    time_t time_val = { 0 }; 
    if (status != RTR_STS_OK) 
    { 
                time(&time_val); 
                fprintf(fpLog, "    Call to %s failed at %s:\n", 
                        call, ctime( &time_val)); 
                fprintf(fpLog, "\n Call status = %s\n", 
                        rtr_error_text(status)); 
                fflush(fpLog); 
                exit(status); 
        } 
} 
 
void 
get_server_parameters ( rtr_sgn_32_t argc, char *argv[], message_data_t 
*o_msg) 
{ 
    String31 buffer; 
  if (argc < 2) 
    { 
                printf (" Server number : " ); 
                gets(buffer); 
                o_msg->server_number = atoi(buffer); 
 
                printf(" routing key : " ); 
                gets (buffer); 
                o_msg->routing_key = buffer[0]; 
    } 
    else 
    { 
                sscanf( argv[1], "%1d", &(o_msg->server_number) ); 
                o_msg->routing_key = *(argv[2]); 
    } 
} /* End of get_server_parameters */ 
 
void 
get_client_parameters ( rtr_sgn_32_t argc, char *argv[], message_data_t 
*o_msg, int *txn_cnt) 
{ 
        String31        buffer; 
 
        if (argc < 3) 
        { 
                printf (" Client number : " ); 
                gets(buffer); 
                o_msg->client_number = atoi(buffer); 
 
                printf(" routing key : " ); 
                gets (buffer); 
                o_msg->routing_key = buffer[0]; 
 
                printf(" Message Count : " ); 
                gets (buffer); 
                *txn_cnt = atoi(buffer); 
        } 
        else 
        { 
                sscanf( argv[1], "%1d", &(o_msg->client_number) ); 
                sscanf(argv[2], "%s", buffer ); 
 
        } 
} /* End of get_client_parameters */ 
 
/***************************************************************************/ 
 
void fprint_tid ( FILE *fp , rtr_tid_t  *tid ) 
{ 
          fprintf ( fp , "     tid: %x,%x,%x,%x,%x,%x,%x\n", tid->tid32[0], 
tid->tid32[1], 
                tid->tid32[2], tid->tid32[3], tid->tid32[4], tid->tid32[5], 
                tid->tid32[6] ); 
} 
 
void 
close_channel ( rtr_channel_t channel ) 
{ 
    rtr_status_t status; 
 
    printf ( " Closing Channel.\n" ); 
 
    status = rtr_close_channel ( 
                   channel , 
                   RTR_NO_FLAGS); 
 
    check_status( "rtr_close_channel", status ); 
 
    return; 
 
} 

A.5 Header Code


/* Header Code */ 
 
/******************************************************************************* 
* Copyright Compaq Computer Corporation 1998. All rights reserved. 
* Restricted Rights: Use, duplication, or disclosure by the U.S. Government 
* is subject to restrictions as set forth in subparagraph (c) (1) (ii) of 
* DFARS 252.227-7013, or in FAR 52.227-19, or in FAR 52.227-14 Alt. III, as 
* applicable. 
* This software is proprietary to and embodies the confidential technology of 
* Compaq Computer Corporation. Possession, use, of copying of this software 
* and media is authorized only pursuant to a valid written license from Compaq, 
* Digital or an authorized sublicensor. 
*******************************************************************************/ 
/******************************************************************************* 
* APPLICATION: RTR Sample Application 
* MODULE NAME: adg_header.h 
* AUTHOR         : Compaq Computer Corporation 
* DESCRIPTION: This header file is to be used with adg_server.c, 
*                          adg_client.c, and adg_shared.c. 
* DATE           : Oct 22, 1998 
*******************************************************************************/ 
/* 
    Header file for adg_client.c and adg_server.c 
 
*/ 
 
#include "rtr.h" 
#include <stdio.h> 
#include <stdlib.h> 
#include <string.h> 
#include <time.h> 
#include <math.h> 
#include <signal.h> 
#include <ctype.h> 
#include <fcntl.h> 
#include <sys/stat.h> 
/* #include <sys/types.h> */ 
 
#define PERMS 0666 /* File permissions */ 
#define FACILITY_NAME "DESIGN" 
 
typedef char String31[31]; 
typedef char String200[200]; 
 
typedef  struct {    
    rtr_uns_8_t     routing_key; 
    rtr_uns_32_t    server_number; 
    rtr_uns_32_t    client_number; 
    rtr_uns_32_t    sequence_number; 
    String31        text; 
    } message_data_t; 
 
typedef union { 
    message_data_t receive_data_msg; 
    rtr_status_data_t receive_status_msg; 
    } receive_msg_t; 
 
typedef struct  { 
    rtr_uns_32_t    low; 
    rtr_uns_32_t    high; 
    rtr_uns_32_t    expected ; 
    rtr_tid_t       prior_txn; 
    rtr_uns_32_t    prior_seqno; 
    }boundaries_t; 
 
/* Function prototype section */ 
 
void 
check_status( char *call, rtr_status_t status ); 
 
void get_client_parameters ( rtr_sgn_32_t argc, 
                        char *argv[], 
                        message_data_t *o_msg, 
                        int *txn_cnt); 
void get_server_parameters ( rtr_sgn_32_t argc, 
                        char *argv[], 
                        message_data_t *o_msg); 
 
rtr_status_t send_reply ( 
                        message_data_t *o_msg, 
                        rtr_channel_t channel); 
 
void close_channel ( rtr_channel_t channel ); 
 
void fprint_tid (FILE *fpLog, rtr_tid_t  *tid ); 
 
/* External section */ 
 
extern String200            Errormsg; 
 
extern time_t               time_val; 
extern boundaries_t         txn_range[10]; 
extern char                 TxnLog[]; 
extern char                 SvrLog[]; 
extern rtr_uns_32_t         msg_cnt; 
extern int                  errno; 
extern FILE*                fpLog; 


Previous Next Contents Index