Appendix C:
Sample Application Code


The RTR book ordering sample application shows how the C++ Foundation classes can be used to simulate purchasing merchandise for a fictitious company named ABC.

The client, ABCOrderTaker, has a hardcoded book request which is represented by the ABCBook class. This book request has an ISBN number used for data routing. The server will display a dialog box containing the contents of the newly reconstituted ABCBook object.

The following sample application code comes from the Examples directory and includes:

This file contains int main and provides a sample for which the sample application takes book and magazine orders from the client application (ABCOrderTaker) and processes them in the server application (ABCOrderProcessor)..

Located in ABCOrderTaker.h and ABCOrderTaker.cpp, this client-side class supplies ability to pass an object derived from ABCOrder to a server. This class is derived from RTRClientTransactionController and derives from RTRClientMessageHandler and RTRClientEventHandler

Located in ABCOrderProcessor.h, ABCOrderProcessor.cpp, this server-side class processes the request sent to it by the client. This class is derived from RTRServerTransactionController.

Located in ABCOrder.h, ABCOrder.cpp, this is an abstract base class (for ABCBook and ABCMagazine) which requires all derived classes to implement three member functions.

ReadObject()

WriteObject()

Process()

This class is derived from RTRApplicationMessage.

Located in ABCBook.h, ABCBook.cpp, this class represents a book order. This class is able to write and read its state to the memory managed by its base class RTRData. This class derives from ABCOrder.

There are also class factory, client and server handlers, ABCMagazine, and ABCCommon classes in the Examples directory.

Sample Main Program

#include "ABCCommon.h"

#include "ABCOrderTaker.h"

#include "ABCOrderProcessor.h"

#include "ABCBook.h"

#include "ABCMagazine.h"

void GenerateOrders();

 

int main(int argc, char* argv[])

{

bool bValidInput = false;

while (false == bValidInput)

{

cout << endl;

cout << "**********************************************" << endl;

cout << endl;

cout << "1 - Start Server to process incoming orders" << endl;

cout << "2 - Start Client to generate predefined orders" << endl;

cout << "0 - Quit" << endl;

cout << endl;

cout << "**********************************************" << endl;

cout << endl << "Which Test should be run? : ";

unsigned int uiAnswer;

cin >> uiAnswer;

switch (uiAnswer)

{

case 1 : { ABCOrderProcessor OrderProcessor;

// Call ProcessIncomingOrders which will loop

//forever processing orders from clients.

OrderProcessor.ProcessIncomingOrders();

break;

}

case 2 : {

// Send some orders

GenerateOrders();

break;

}

case 0 : {

return 0;

}

} // switch

} //while

return 0;

}

 

void GenerateOrders()

{

abc_status sStatus;

// Create an Order Taker.

ABCOrderTaker OrderTaker;

 

// Create a sample book order and populate it with the

// ISBN 49, Price and Title

ABCBook Book;

Book.AddOrder( 49, 12345, "Everything to the Internet",
"Michael Capellas");

// Send this book order to the server for processing.

// note: This will be txn #1

cout << endl << "Transaction # 1" <<endl;

sStatus = OrderTaker.SendOrder(&Book);

cout << endl;

// Reset the stream. This way we will reuse the beginning of

// the buffer that the stream manages.

Book.ResetStream();

 

// Send another order to a server which handles ISBN 99

Book.AddOrder( 99, 56789, "Java How To Program",
"Deitel & Deitel");

// Send this book order to the server for processing.

// note: This will be txn #2

cout << endl << "Transaction # 2" <<endl;

sStatus = OrderTaker.SendOrder(&Book);

cout << endl;

 

ABCMagazine Magazine;

 

Magazine.AddOrder(29,"PC Week","ZIFF-DAVIS", "February 2000");

 

// Send this book order to the server for processing.

// note: This will be txn #3

cout << endl << "Transaction # 3" <<endl;

sStatus = OrderTaker.SendOrder(&Magazine);

cout << endl;

}

 

 

Client Application ABCOrderTaker

// ABCOrderTaker.cpp: implementation of the ABCOrderTaker class.

//

//////////////////////////////////////////////////////////////////////

 

#include "ABCCommon.h"

#include "ABCOrderTaker.h"

 

//////////////////////////////////////////////////////////////////////

// Construction/Destruction

//////////////////////////////////////////////////////////////////////

 

ABCOrderTaker::ABCOrderTaker() : m_bRegistered(false)

{

 

}

 

ABCOrderTaker::~ABCOrderTaker()

{

 

}

 

abc_status ABCOrderTaker::SendOrder(ABCOrder *pOrder)

{

abc_status sStatus;

// Register with RTR if we havn't already done so.

// This will make sure we are ready to start sending data.

sStatus = Register();

if (ABCSuccess != sStatus) return false;

// If we can't register with RTR then exit

// Start the Transaction

cout << "StartTransaction..." << endl;

sStatus = StartTransaction();

print_status_on_failure(sStatus);

// Send this Book Order object to a server capable

// of processing it.

cout << "SendApplicationMessage..." << endl;

sStatus = SendApplicationMessage(pOrder);

print_status_on_failure(sStatus);

 

// Let RTR know that this is the only object being sent

// and that we are done with our work.

cout << "AcceptTransaction..." << endl;

sStatus = AcceptTransaction();

print_status_on_failure(sStatus);

// Determine if the server successfully processed the request

return DetermineOutcome();

}

rtr_status_t ABCOrderTaker::Register()

{

rtr_status_t sStatus = RTR_STS_OK;

if(false == m_bRegistered)

{

// If RTR is not already started then start it now.

sStatus = StartRTR();

// Create a Facility if not already created.

sStatus = CreateFacility();

 

// Register our facility with RTR.

sStatus = RegisterFacility(ABCFacility);

print_status_on_failure(sStatus);

if(RTR_STS_OK == sStatus)

{

m_bRegistered = true;

}

 

 

 

// ABC Handlers

sStatus = RegisterHandlers(&m_rtrHandlers,&m_rtrHandlers);

print_status_on_failure(sStatus);

}

return sStatus;

}

abc_status ABCOrderTaker::DetermineOutcome()

{

RTRData *pResult = NULL;

abc_status sStatus = ABCSuccess;

 

// Simply wait for RTR to send us an accepted or rejected.

// We can dispatch everything we get and let the default

// handlers process what we don't care about.

bool bDone = false;

while (!bDone)

{

sStatus = Receive(&pResult);

print_status_on_failure(sStatus);

sStatus = pResult->Dispatch();

if (ABCOrderSucceeded == sStatus)

{

cout << "Transaction succeeded..." << endl;

bDone = true;

}

else

if (ABCOrderFailed == sStatus)

{

cout << "Transaction failed..." << endl;

bDone = true;

}

}

delete pResult;

return sStatus;

}

Server Application ABCOrderProcessor

// ABCOrderProcessor.cpp: implementation of the ABCOrderProcessor class.

//

//////////////////////////////////////////////////////////////////////

 

#include "ABCCommon.h"

#include "ABCOrderProcessor.h"

#include <stdio.h>

 

//////////////////////////////////////////////////////////////////////

// Construction/Destruction

//////////////////////////////////////////////////////////////////////

 

ABCOrderProcessor::ABCOrderProcessor()

{

 

}

 

ABCOrderProcessor::~ABCOrderProcessor()

{

 

}

 

void ABCOrderProcessor::ProcessIncomingOrders()

{

// Register with RTR. This will make sure we are ready to

// start receiving data.

Register();

// Start processing orders

abc_status sStatus = RTR_STS_OK;

RTRData *pOrder = NULL;

 

 

while (1)

{

// Receive an Order

sStatus = Receive(&pOrder);

print_status_on_failure(sStatus);

if(ABCSuccess != sStatus) break;

// if we can't get an Order then stop processing.

 

// Dispatch the Order to be processed

// note: This could be any kind of data. ie. RTRMessage RTREvent,

// RTRApplicationMessage or RTRApplicationEvent.

// The class ABCOrder(derived from RTRApplicationMessage) has

// redefined the Dispatch() method to call the Process() method

// of its derived class (ABCBook or ABCMagazine). All other

// data classes use the default implemenation of Dispatch()

// which will call the appropriate handler.

sStatus = pOrder->Dispatch();

print_status_on_failure(sStatus);

// Check to see if there were any problems processing the order.

// If so, let the handler know to reject this txn when asked to

// vote.

// note : For the ABC company, orders are processed in the

// Process() method of all ABCOrder derived classed.

CheckOrderStatus(sStatus);

 

// Delete this order that was allocated by the class factory.

// note: In this sample the class factory returns a separate

// instance of an order each time it is called.

delete pOrder;

}

return;

}

void ABCOrderProcessor::Register()

{

rtr_status_t sStatus;

 

// Create an environment that our server can run in.

CreateRTREnvironment();

 

// Register with RTR the following objects

sStatus = RegisterFacility(ABCFacility);

print_status_on_failure(sStatus);

 

// ABC Partition

sStatus = RegisterPartition(ABCPartition1);

print_status_on_failure(sStatus);

 

sStatus = RegisterPartition(ABCPartition2);

print_status_on_failure(sStatus);

 

// ABC Class Factory

sStatus = RegisterClassFactory(&m_ClassFactory);

print_status_on_failure(sStatus);

 

// ABC Server Handlers

sStatus = RegisterHandlers(&m_rtrHandlers,&m_rtrHandlers);

print_status_on_failure(sStatus);

 

return;

}

 

void ABCOrderProcessor::CreateRTREnvironment()

{

rtr_status_t sStatus;

// If RTR is not already started then start it now.

StartRTR();

// Create a Facility if not already created.

CreateFacility();

// Create a partition that processes ISBN numbers in the

// range 0 - 99

unsigned int low = 0;

unsigned int max = 99;

RTRKeySegment KeyZeroTo99( rtr_keyseg_unsigned,

sizeof(int),

0,

&low,

&max );

RTRPartitionManager PartitionManager;

sStatus = PartitionManager.CreateBackendPartition(

ABCPartition1,

ABCFacility,

KeyZeroTo99,

false,

true,

false);

print_status_on_failure(sStatus);

 

// Create a partition that processes ISBN numbers in the

// range 100 - 199

low = 100;

max = 199;

RTRKeySegment Key100To199( rtr_keyseg_unsigned,

sizeof(int),

0,

&low,

&max );

sStatus = PartitionManager.CreateBackendPartition(

ABCPartition2,

ABCFacility,

Key100To199,

false,

true,

false);

print_status_on_failure(sStatus);

}

 

 

 

void ABCOrderProcessor::CheckOrderStatus (abc_status sStatus)

{

// Check to see if there were any problems processing the order.

// If so, let the handler know to reject this transaction when

// asked to vote.

if (sStatus == ABCOrderFailed)

{

// Let the handler know that the current txn should be rejected

GetHandler()->OnABCOrderNotProcessed();

};

 

}

Data Class ABCOrder

// ABCOrder.cpp: implementation of the ABCOrder class.

//

//////////////////////////////////////////////////////////////////////

 

#include "ABCCommon.h"

#include "ABCOrder.h"

 

//////////////////////////////////////////////////////////////////////

// Construction/Destruction

//////////////////////////////////////////////////////////////////////

 

ABCOrder::ABCOrder() : m_uiPrice(0)

{

m_szTitle[0] = '\0';

m_szAuthor[0] = '\0';

}

 

ABCOrder::~ABCOrder()

{

 

}

 

rtr_status_t ABCOrder::Dispatch()

{

// Populate the derived object

ReadObject();

// Since we have overridden Dispatch() in our base class

// (RTRApplictaionMessage), the handler will not be called

// unless we do it ourselves. If we call our base class Dispatch

// method the handler methods OnInitialize() and

// OnApplictionMessage() will be called. This sample uses

// OnInitialize() to print out notification that a new

// transaction

// is starting.

RTRApplicationMessage::Dispatch();

// Process the purchase which the derived object represents

abc_status status = ProcessOrder();

return status;

}

Data Class ABCBook

// ABCBook.cpp: implementation of the ABCBook class.

//

//////////////////////////////////////////////////////////////////////

 

#include "ABCCommon.h"

#include "ABCBook.h"

 

//////////////////////////////////////////////////////////////////////

// Construction/Destruction

//////////////////////////////////////////////////////////////////////

 

ABCBook::ABCBook() : m_uiISBN(0)

{

 

}

 

ABCBook::~ABCBook()

{

 

}

 

bool ABCBook::AddOrder( unsigned int uiPrice,

unsigned int uiISBN,

char *pszName,

char *pszAuthor)

{

// Copy the Book purchase to our Book object.

m_uiISBN = uiISBN;

m_uiPrice = uiPrice;

strcpy(&m_szTitle[0],pszName);

strcpy(&m_szAuthor[0],pszAuthor);

WriteObject();

return true;

}

void ABCBook::WriteObject()

{

// Save the type of object we are. This is used by the

// class factory on the server side to determine which type

// of class to allocate.

*this << ABC_BOOK;

*this << m_uiPrice << m_uiISBN << m_szTitle << m_szAuthor;

// The 1 line call above is equivalent to the 4 lines below. We

// can use the << and >> operators because we know that the data

// which we store is not > the current RTR maximum = 65535 byes.

// WriteToStream(m_uiISBN);

// WriteToStream(m_uiPrice);

// WriteToStream(m_szTitle);

// WriteToStream(m_szAuthor);

char mystring[] = "ABCDEFGHIJKLMNOPQRSTUVWZYZ";

rtr_msgbuf_t p = &mystring[0];

rtr_msglen_t length = strlen(mystring)+1;

WriteToStream(p,length);

}

void ABCBook::ReadObject()

{

// The first data is the type of class we should be.

// Validate that everything is fine.

unsigned int uiClassType = 0;

*this >> uiClassType;

assert(uiClassType == ABC_BOOK);

// Populate this object with the data

*this >> m_uiPrice >> m_uiISBN >> m_szTitle >> m_szAuthor;

// The 1 line call above is equivilant to the 4 lines below.

// ReadFromStream(m_uiISBN);

// ReadFromStream(m_uiPrice);

// ReadFromStream(m_szTitle,GetLogicalBufferLength());

// ReadFromStream(m_szAuthor,GetLogicalBufferLength());

}

abc_status ABCBook::ProcessOrder()

{

// It is here that we would process the request for this book.

// For this sample simply print out the Book order.

cout <<"ABCBook::ProcessOrder()" << endl;

cout << " " << "ISBN = " << m_uiISBN << endl;

cout << " " << "Price = " << m_uiPrice << endl;

cout << " " << "Title = " << m_szTitle << endl;

cout << " " << "Author = " << m_szAuthor << endl;

 

return ABCOrderSucceeded;

}