Previous | Contents | Index |
All client and application programs must be written using C, C++, or a language that can use RTR API calls. Include the RTR data types and error messages file rtr.h in your compilation so that it will be appropriately referenced by your application. For each client and server application, your compilation/link process is as follows:
This process is illustrated in Figure 4-1. In this figure, Library represents the RTR C API shareable images (OpenVMS), DLLs (Win32), and shared libraries (UNIX).
Figure 4-1 Compile Sequence
Compilers
Compilers commonly used in developing RTR applications include those in Table 4-1. For additional information, see the Reliable Transaction Router Software Product Description.
Operating System | Compiler | Compiler Version |
---|---|---|
Microsoft Windows | Microsoft Visual C++ (Microsoft Visual Studio 6.0) | Version 6.0 SP4 |
OpenVMS Alpha | Compaq C | Version 6.2-006 |
OpenVMS VAX | Compaq C | Version 6.2-003 |
Sun | Workshop Compilers | Version 4.2 |
Tru64 UNIX | Compaq C | Version 6.3-126 |
To compile and link a C RTR application, use command lines as shown below. Separate examples are shown for use of RTR with threaded or unthreaded libraries. You may need to specify library directories explictly if the RTR header files and libraries are not installed in the same directory or in system directories.
Windows
> cl /c /MT yourapp.c > link yourapp.obj /out:yourapp.exe rtrdll.lib |
Tru64 UNIX
Single-threaded:
# cc -o yourapp -lrtr yourapp.c |
Multi-threaded:
# cc -o yourapp -pthread -lrtr_r yourapp.c |
OpenVMS Alpha
Single-threaded:
$ cc yourapp.c $ link yourapp,sys$input/opt librtr/share |
Multi-threaded:
$ cc yourapp.c $ link yourapp,sys$input/opt librtr_r/share |
OpenVMS VAX
Single-threaded:
$ cc yourapp.c $ link yourapp,sys$input/opt librtr/share |
Multi-threaded:
$ cc yourapp.c $ link yourapp,sys$input/opt librtr_r/share |
Sun
Single-threaded:
$ cc -o yourapp -lrtr yourapp.c |
Multi-threaded:
$ cc -o yourapp -mt -lrtr_r yourapp.c |
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_HEADER.h
ADG_SHARED.c
ADG_CLIENT.c
ADG_SERVER.c
The client and server code are shown on the next few pages. Note the following:
/* 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), MESSAGE_DATA_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, NULL, /* 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; } |
/* 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), MESSAGE_DATA_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, NULL, /* 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; } |
The Active-X Case Study uses RTR deployed on three laptops to demonstrate the capabilities of RTR using one client and two servers. It displays a graph of the number of transactions that is continuously updated. Periodically, one of the servers goes off line, and the display and activity show RTR failing over to the other server while continuing to process transactions. The failure can be simulated or can be effected by someone disconnecting the cable from one of the laptops.
The code for the Active-X Case Study is available on the RTR website at http://www.compaq.com/rtr. The website also contains a short case study describing the demo in more detail.
Previous | Next | Contents | Index |