tibco ftl r programming tutorial · 2018-11-28 · tibco ftl r programming tutorial. 4 lesson 2:...

102
TIBCO FTL R Programming Tutorial Software Release 6.0 November 2018

Upload: others

Post on 11-Apr-2020

5 views

Category:

Documents


0 download

TRANSCRIPT

Page 1: TIBCO FTL R Programming Tutorial · 2018-11-28 · TIBCO FTL R Programming Tutorial. 4 Lesson 2: Understanding the Code In this lesson, we’ll examine the code used in lesson 1

TIBCO FTL R©

Programming TutorialSoftware Release 6.0November 2018

Page 2: TIBCO FTL R Programming Tutorial · 2018-11-28 · TIBCO FTL R Programming Tutorial. 4 Lesson 2: Understanding the Code In this lesson, we’ll examine the code used in lesson 1

1

Contents

Introduction i

1 Getting Started with FTL Programming 11.1 Set Up the Environment . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11.2 Start the Local FTL Server . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11.3 Build the Samples . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 21.4 Run the Samples . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2

2 Understanding the Code 42.1 ftlbasicpub.c . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 42.2 ftlbasicsub.c . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6

3 Error Handling 93.1 Servers and Services . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 93.2 Running Without the Realm Service . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 93.3 Adding Error Handling . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 103.4 Understanding the Error Handling Code and Output . . . . . . . . . . . . . . . . . . . . . . 123.5 Restart the FTL Server . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 143.6 Working With Exceptions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 15

4 Messages and Fields 174.1 FTL Field Types . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 174.2 FTL API Functions to Set Field Values in a Message . . . . . . . . . . . . . . . . . . . . . 174.3 FTL API Functions to Get Field Values from a Message . . . . . . . . . . . . . . . . . . . . 184.4 Working with Messages . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 19

5 Introduction to Content Matchers 215.1 Matcher Specification . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 215.2 ftlbasicpub.c . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 215.3 ftlbasicsub.c . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 225.4 Build and Run the Samples . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 235.5 Some Variations . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 24

6 Exploring the Realm 276.1 The Realm Service Web Interface . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 276.2 The Realm Service Web API . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 32

7 Defining an Application 347.1 The Process . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 347.2 Defining an Application Using the Realm Service Web Interface . . . . . . . . . . . . . . . 34

TIBCO FTL R© Programming Tutorial

Page 3: TIBCO FTL R Programming Tutorial · 2018-11-28 · TIBCO FTL R Programming Tutorial. 4 Lesson 2: Understanding the Code In this lesson, we’ll examine the code used in lesson 1

2

7.3 Defining an Application Using the Realm Service Web API . . . . . . . . . . . . . . . . . . 41

8 Using Applications and Endpoints 458.1 The Client Programs . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 458.2 The Code . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 468.3 Build and Run the Sample Applications . . . . . . . . . . . . . . . . . . . . . . . . . . . . 558.4 Order Matters . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 578.5 Clients . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 588.6 Identifying Clients . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 63

9 Properties 649.1 The Properties API . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 649.2 Property Names . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 659.3 Using Properties . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 679.4 Build and Run the Samples . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 709.5 Identifying Clients Revisited . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 70

10 Client Metrics 7310.1 Client-Realm Server Communication . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 7310.2 Run the Samples . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 7510.3 Examine the Metrics . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 75

11 Field References 8511.1 Introduction . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 8511.2 Field Reference API . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 8511.3 Modify the Samples . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 8711.4 Build and Run the Samples . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 90

12 Trace Logging 9212.1 Tune the Log Level . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9212.2 Trace Log Destinations . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9312.3 FTL API Trace Logging Functions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9312.4 Modify the Samples . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9412.5 Build and Run the Samples . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 96

TIBCO FTL R© Programming Tutorial

Page 4: TIBCO FTL R Programming Tutorial · 2018-11-28 · TIBCO FTL R Programming Tutorial. 4 Lesson 2: Understanding the Code In this lesson, we’ll examine the code used in lesson 1

i

Introduction

Welcome to FTL Programming!

This tutorial will step you through using FTL to develop messaging applications through a series oflessons, with each addressing specific FTL functionality. The focus is on writing messaging applicationsusing the C language, on 64-bit Linux or 64-bit OSX.

Each lesson is designed to take from 60 to 90 minutes to complete. It is recommended that you completethe lessons in sequence, as each lesson builds upon the previous lessons.

Throughout the tutorial, the term client program is used to refer to an application program using FTL formessaging. While the samples presented in this tutorial focus almost entirely on messaging capabilities,your own applications will contain business-specific code to generate or make use of the information beingsent or received using FTL messaging.

Typographic Conventions

At various points throughout this tutorial, important concepts are pointed out. Each concept is called outusing the format shown below:

Concept 1. This is an example of an important concept or point.

Output from commands appear in a monospaced font, enclosed in a box such as:

An example of program output

Commands to be entered appear in a similar manner, but in boldface:

command arg1 arg2

For very long commands, a backslash (\) at the end of a line indicates the command is continued on thefollowing lines:

command "a long argument string" arg2 \arg3 arg4

Enter the entire command on a single line, without the backslash.

Listings (both code and output) are shown with line numbers on the left side for reference:

1 Line 12

3 Line 3

Whenever overly-specific information appears in the output from a command, it is replaced with fillcharacters. This includes dates and times, version numbers, host names, IP addresses, and other items. Inscreenshots, this information is blurred.

TIBCO FTL R© Programming Tutorial

Page 5: TIBCO FTL R Programming Tutorial · 2018-11-28 · TIBCO FTL R Programming Tutorial. 4 Lesson 2: Understanding the Code In this lesson, we’ll examine the code used in lesson 1

ii

Prerequisites

In order to successfully complete this tutorial, you should:

• Be using 64-bit Linux or 64-bit OSX.

• Have available a C compiler appropriate to the platform.

• Have available the curl command-line utility. curl is an open-source utility found in most Linuxdistributions, and available as a binary or source download for most other platforms as well.

• Have installed the appropriate version of FTL.

• Have read through the TIBCO FTL R© Concepts guide.

TIBCO FTL R© Programming Tutorial

Page 6: TIBCO FTL R Programming Tutorial · 2018-11-28 · TIBCO FTL R Programming Tutorial. 4 Lesson 2: Understanding the Code In this lesson, we’ll examine the code used in lesson 1

1

Lesson 1: Getting Started with FTL Programming

In this lesson, you will build and run two basic FTL client programs: a publisher and a subscriber.

By the end of this lesson, you will have:

• Set up the FTL development environment

• Started a local FTL server

• Built the FTL client programs from the supplied source files

• Run the FTL client programs with the publisher sending messages to the subscriber

1.1 Set Up the Environment

1. Locate the directory containing the FTL installation. Under Linux it is typically installed in/opt/tibco/ftl/VER, where VER corresponds to the FTL version. Under OSX it may be installedelsewhere, possibly in your home directory.

Open a command window and create an environment variable which points to the FTL installationdirectory:

export TIBFTL_DIR=INSTALL-DIR

Replace INSTALL-DIR in the above command with the actual location of your FTL installation.

2. Download the tutorial code and scripts (available as a single archive file). Unpack it into a localdirectory.

3. In the open command window, create an environment variable which points to the directorycontaining the unpacked tutorial files:

export TIBFTL_TUTDIR=TUTORIAL-DIR

Replace TUTORIAL-DIR with the path to the directory into which you unpacked the tutorial files.

4. Add the environment variables TIBFTL_DIR and TIBFTL_TUTDIR to your shell startup script.Under the bash shell this is typically .bash_profile or .profile. Other shells may usedifferent startup scripts.

This step is important, as each lesson assumes that these environment variables are set. Dependingon your shell, you may have to log out and back in to ensure the shell startup script is executed.

1.2 Start the Local FTL Server

Before we can run any of the samples, the FTL server must be running.

TIBCO FTL R© Programming Tutorial

Page 7: TIBCO FTL R Programming Tutorial · 2018-11-28 · TIBCO FTL R Programming Tutorial. 4 Lesson 2: Understanding the Code In this lesson, we’ll examine the code used in lesson 1

2

The FTL server uses the directory ˜/ftls-data to store data. Before starting the FTL server for the firsttime, we need to make sure that directory is empty to ensure a clean start-up. Open a command windowand enter:

rm -rf ˜/ftls-data

Next, navigate to the $TIBFTL_TUTDIR/scripts directory and start the FTL server:

./start_ftl

As the FTL server starts, you see the following output confirming the FTL server has started and is running:

Creating homedir/ftls-data as the FTL server directory.Starting FTL server.Done.

Listing 1.1: Output from running start_ftl

Note that your actual home directory replaces homedir in Listing 1.1.

1.3 Build the Samples

To build the samples, open a new command window. Navigate to the$TIBFTL_TUTDIR/code/lesson-01 directory, and build the samples for this lesson using the makecommand:

make

1.4 Run the Samples

In the open command window, navigate to the $TIBFTL_TUTDIR/code/lesson-01 directory. Start thesubscriber application for this lesson using the command:

./ftlbasicsub

Open another command window and navigate to the same directory as above. Start the publisherapplication using:

./ftlbasicpub

Once the publisher starts sending message, you’ll see the following output from the publisher:

sending ’hello world’ messages

Listing 1.2: Output from running ftlbasicpub

TIBCO FTL R© Programming Tutorial

Page 8: TIBCO FTL R Programming Tutorial · 2018-11-28 · TIBCO FTL R Programming Tutorial. 4 Lesson 2: Understanding the Code In this lesson, we’ll examine the code used in lesson 1

3

In the subscriber command window, you should start to see output indicating messages are being received;each time a message is received, you will see two lines of output from the subscriber:

waiting for message(s)received message

{string:type="hello", string:contents="hello world", long:seq=1}received message

{string:type="hello", string:contents="hello world", long:seq=2}received message

{string:type="hello", string:contents="hello world", long:seq=3}received message

{string:type="hello", string:contents="hello world", long:seq=4}received message

{string:type="hello", string:contents="hello world", long:seq=5}

Listing 1.3: Output from running ftlbasicsub

Congratulations! You have successfully run your first FTL publisher and subscriber! The publisher exitsafter sending five messages, while the subscriber continues to run and wait for messages to arrive. You canrun the publisher multiple times and see the output at the subscriber, or terminate the subscriber in itscommand window by typing ctrl + C .

TIBCO FTL R© Programming Tutorial

Page 9: TIBCO FTL R Programming Tutorial · 2018-11-28 · TIBCO FTL R Programming Tutorial. 4 Lesson 2: Understanding the Code In this lesson, we’ll examine the code used in lesson 1

4

Lesson 2: Understanding the Code

In this lesson, we’ll examine the code used in lesson 1. The goal of this lesson is to understand the purposeof each section of code in both the publisher and subscriber applications.

2.1 ftlbasicpub.c

First, let’s walk through the publisher.

1 #include <stdio.h>2 #include <unistd.h>3 #include "tib/ftl.h"

Every TIBCO FTL client program must include "tib/ftl.h", as shown in line 3 above. This C headerfile provides the FTL API definitions needed for any FTL client program.

All FTL header files reside in the include directory within the FTL installation directory. The includedirectory itself contains subdirectories, of which tib is one. An FTL client program only needs to includethe tib/ftl.h header file, which will include other FTL header files as needed.

The makefile included with the samples will set the include path appropriately to find these files at compiletime. If you are using a different compilation method or an IDE, be sure to set this path to find thenecessary include files at compile time. For most C compilers, specifying -I$TIBFTL_DIR/include onthe command line will work.

5 int main(int argc, char** argv)6 {7 tibEx ex = NULL;8 tibRealm realm = NULL;9 tibPublisher pub = NULL;

10 tibMessage msg = NULL;11 tibProperties props = NULL;12 long seq;

Lines 7 though 11 declare five variables which contain important fundamental FTL objects. Each of thesetypes is defined in tib/ftl.h.

A variable of type tibEx (line 7) holds an exception object. Exceptions are the mechanism FTL uses tocapture and return information about any error which occurred during an FTL API call, and a tibExvariable is a required parameter for almost every FTL API call. Note that these are not exceptions in theC++ or Java sense; they are not thrown or caught, and do not change the execution flow of a program. FTLexceptions can be thought of as extended return values whose contents reflect any errors encountered aspart of that specific FTL API call.

A variable of type tibRealm (line 8) encapsulates information about the application’s connection to arealm service.

A variable of type tibPublisher (line 9) encapsulates information about a message publisher.

A variable of type tibMessage (line 10) encapsulates a message.

TIBCO FTL R© Programming Tutorial

Page 10: TIBCO FTL R Programming Tutorial · 2018-11-28 · TIBCO FTL R Programming Tutorial. 4 Lesson 2: Understanding the Code In this lesson, we’ll examine the code used in lesson 1

5

A variable of type tibProperties (line 11) specifies properties to be applied to an object at the time ofits creation. Properties are discussed in lesson 9.

14 ex = tibEx_Create();15 tib_Open(ex, TIB_COMPATIBILITY_VERSION);16 props = tibProperties_Create(ex);17 tibProperties_SetLong(ex, props, TIB_REALM_PROPERTY_LONG_CONNECT_RETRIES, 5);18 realm = tibRealm_Connect(ex, "http://localhost:8080", NULL, props);19 tibProperties_Destroy(ex, props);

Line 14 creates the tibEx exception object which will be passed as a parameter to subsequent FTL APIcalls; it is important that it is created before making any other FTL API calls.

The call to tib_Open() in line 15 initializes the FTL environment for the process. Every applicationwhich uses the FTL API must include a call to tib_Open(). The value TIB_COMPATIBILITY_VERSIONis defined in tib/ftl.h, and must be provided as the second argument.

Lines 16 and 17 create the properties object and sets a specific property value.

In line 18, the call to tibRealm_Connect() establishes a connection to the specified realm service. Thefirst argument is the exception object, and the second argument is the realm service URL. The thirdargument is not used in this sample so NULL is passed, indicating the default value is to be used. The fourthargument is the properties object created in line 16. Finally the properties object is destroyed in line 19, asit is no longer needed.

It is important to note that, in order to keep the sample programs short and concise, error checking andhandling is largely ignored for now. For actual production applications you would absolutely need to checkfor error conditions and handle them appropriately. Error handling will be covered in lesson 3.

This brings up an important concept about the naming conventions used for FTL API functions:

Concept 1. All function names are of the form tibOBJ_ACTION, where OBJ is the FTL object on whichthe function operates, and ACTION is the action the function is performing. Both OBJ and ACTION are inCamelCase. There are a few functions, such as tib_Open() and tib_Close(), which operate not on anobject, but on the FTL environment itself; these functions omit OBJ.

21 pub = tibPublisher_Create(ex, realm, NULL, NULL);

Line 21 creates a publisher object (tibPublisher). The realm object is required, and we are using thevalue returned from the tibRealm_Connect() call in line 18. The remaining arguments are not used inthis sample, so NULL is passed to indicate they are not present.

23 msg = tibMessage_Create(ex, realm, NULL);24 tibMessage_SetString(ex, msg, "type", "hello");25 tibMessage_SetString(ex, msg, "contents", "hello world");

Line 23 creates a message object (tibMessage). Note that the tibRealm object is passed as an argument,rather than a tibPublisher object. Messages are not associated with a specific publisher, allowing amessage to be used with multiple publishers.

Lines 24 and 25 add and set fields within the created message. Each field in a message has a name and typeassociated with it. Line 24 creates a string field with the name "type" and sets its value to "hello". Line25 creates a string field with the name "contents" and sets its value to "hello world".

27 printf("sending ’hello world’ messages\n");28 fflush(stdout);

It’s always reassuring when a program prints some information about what it is doing, so lines 27 and 28

TIBCO FTL R© Programming Tutorial

Page 11: TIBCO FTL R Programming Tutorial · 2018-11-28 · TIBCO FTL R Programming Tutorial. 4 Lesson 2: Understanding the Code In this lesson, we’ll examine the code used in lesson 1

6

let the user know the message was created and is going to be sent.

29 for (seq = 1; seq <= 5; ++seq)30 {31 tibMessage_SetLong(ex, msg, "seq", seq);32 tibPublisher_Send(ex, pub, msg);33 sleep(1);34 }

The program builds and sends five messages. Each is identical except for the "seq" field, which containsthe message sequence number and is set in line 31. Line 32 sends the message, using the publisher createdearlier.

After each message is sent, the program sleeps for one second. By slowing the program down we will beable to see each message as it is received by the subscriber. Note that deliberately slowing down your clientprogram is not a recommended practice in production systems.

36 tibMessage_Destroy(ex, msg);37 tibPublisher_Close(ex, pub);

Client programs must destroy objects when they are no longer needed. Note that we created objects in aparticular order: first the realm object, then the publisher and message objects because each depends on therealm object. Destroy objects in the reverse order, dependent objects first.

Line 36 destroys the message created in line 23.

Likewise, line 37 closes the publisher created in line 21, since we will no longer be publishing anymessages.

39 tibRealm_Close(ex, realm);40 tib_Close(ex);41 tibEx_Destroy(ex);

Continuing with cleanup, line 39 closes the realm object created in line 18.

In line 40, the FTL environment is closed. Every call to tib_Open() (line 15) must have a correspondingcall to tib_Close().

Finally, line 41 destroys the exception object created in line 14.

2.2 ftlbasicsub.c

1 #include <stdio.h>2 #include "tib/ftl.h"

In the same manner as ftlbasicpub.c, the subscriber application must include "tib/ftl.h".

4 void onMessages(tibEx ex, tibEventQueue msgQueue, tibint32_t msgNum, tibMessage *msgs,5 void **closures)6 {7 tibint32_t i;8 char buffer[1024];

Line 4 defines the onMessages() function. onMessages() is a callback function which is invoked whena message is received by the client program. The function must have a void return type and takes fivearguments:

TIBCO FTL R© Programming Tutorial

Page 12: TIBCO FTL R Programming Tutorial · 2018-11-28 · TIBCO FTL R Programming Tutorial. 4 Lesson 2: Understanding the Code In this lesson, we’ll examine the code used in lesson 1

7

• An exception object

• An event queue object indicating the event queue from which the callback was dispatched

• A tibint32_t (a predefined FTL type) containing the number of messages delivered in thiscallback invocation

• An array of message objects

• An array of void pointers

Message delivery is asynchronous and is accomplished via an event queue running on a separate thread.

10 for (i = 0; i < msgNum; i++)11 {12 printf("received message\n");13 (void)tibMessage_ToString(ex, msgs[i], buffer, sizeof(buffer));14 printf(" %s\n", buffer);15 fflush(stdout);16 }17 }

Note that the signature of the callback function indicates it receives an array of messages, not just a singlemessage. If messages arrive in rapid succession, a single invocation of the callback must be able to processmore than one message before returning. Message callbacks generally iterate through the entire array ofmessages, processing each individual message. The number of messages in the msgs array is contained inthe msgNum argument. Lines 10 through 16 process each message in the array as indicated by the messagecount passed to the callback function.

The tibMessage_ToString() function converts a message to a human-readable string, which can beprinted in the same way as any other null-terminated string.

19 int main(int argc, char** argv)20 {21 tibEx ex = NULL;22 tibRealm realm = NULL;23 tibEventQueue queue = NULL;24 tibSubscriber sub = NULL;25 tibProperties props = NULL;

Lines 21 and 22 declare a tibEx object and a tibRealm object. An event queue tibEventQueue objectand a subscriber tibSubscriber object are declared in lines 23 and 24, and a properties object in line 25.

27 ex = tibEx_Create();28 tib_Open(ex, TIB_COMPATIBILITY_VERSION);29 props = tibProperties_Create(ex);30 tibProperties_SetLong(ex, props, TIB_REALM_PROPERTY_LONG_CONNECT_RETRIES, 5);31 realm = tibRealm_Connect(ex, "http://localhost:8080", NULL, props);32 tibProperties_Destroy(ex, props);

Every FTL client program needs to create an exception object, initialize the FTL environment, andestablish a connection to the realm service.

34 sub = tibSubscriber_Create(ex, realm, NULL, NULL, NULL);35 queue = tibEventQueue_Create(ex, realm, NULL);36 tibEventQueue_AddSubscriber(ex, queue, sub, onMessages, NULL);

In line 34 a subscriber object is created to express interest in receiving messages. In line 35 an event queueobject is created to distribute received messages.

Simply creating a subscriber and event queue is not sufficient to receive messages: a subscriber must beassociated with an event queue to effect delivery of received messages. Line 36 associates the subscriber

TIBCO FTL R© Programming Tutorial

Page 13: TIBCO FTL R Programming Tutorial · 2018-11-28 · TIBCO FTL R Programming Tutorial. 4 Lesson 2: Understanding the Code In this lesson, we’ll examine the code used in lesson 1

8

and event queue objects. When adding a subscriber to an event queue, the call must include the eventqueue, the subscriber, and a reference to the callback function to be invoked when a message is to bedelivered. The callback function in this case is onMessages(), which we looked at earlier in this lesson.

38 printf("waiting for message(s)\n");39 fflush(stdout);40 do41 {42 tibEventQueue_Dispatch(ex, queue, TIB_TIMEOUT_WAIT_FOREVER);43 } while (tibEx_GetErrorCode(ex) == TIB_OK);

Message delivery is asynchronous and is done through an event queue (and its associated thread) so theloop in lines 40 through 43 repeatedly calls tibEventQueue_Dispatch() to dispatch any receivedmessages. The arguments include the event queue to dispatch and the amount of time to wait beforereturning if the event queue is empty.

tibEventQueue_Dispatch() returns when one of three conditions is met:

• The specified wait time has elapsed and there were no messages to dispatch

• All messages in the event queue have been dispatched

• An exception occurs

In this case the wait time is specified as TIB_TIMEOUT_WAIT_FOREVER, which meanstibEventQueue_Dispatch() will not return until at least one message is received and dispatched.

Line 43 specifies the conditions under which the do statement will continue to loop; in this case, as long asthere is no exception in the dispatch call.

45 tibEventQueue_RemoveSubscriber(ex, queue, sub, NULL);46 tibEventQueue_Destroy(ex, queue, NULL);47 tibSubscriber_Close(ex, sub);

Cleaning up in reverse order, the subscriber is removed from the event queue, the event queue is destroyed,and the subscriber is cleaned up by closing it.

49 tibRealm_Close(ex, realm);50 tib_Close(ex);51 tibEx_Destroy(ex);

Continuing with cleanup, the realm object is closed, the FTL environment is closed, and the exceptionobject is destroyed.

TIBCO FTL R© Programming Tutorial

Page 14: TIBCO FTL R Programming Tutorial · 2018-11-28 · TIBCO FTL R Programming Tutorial. 4 Lesson 2: Understanding the Code In this lesson, we’ll examine the code used in lesson 1

9

Lesson 3: Error Handling

In this lesson, we will introduce basic error handling into the sample client programs. But before we begin,there are some terminology items that need to be addressed.

3.1 Servers and Services

In lesson 1 we started a local FTL server. In lesson 2 we mentioned connecting to a realm service. Whytwo different things, and what is the difference between them?

The FTL server is a process that provides and manages a number of services. Each of these servicesprovide a portion of the functionality available in FTL. One of those services is the Realm Service; othersinclude persistence, bridging, and eFTL. Services may or may not be implemented as a separate process,but if the FTL server is stopped, all services managed by the FTL server are also stopped.

Throughout these lessons, the start_ftl script starts the FTL server to listen onhttp://localhost:8080. This is the same URL used to access the realm service managed by the FTLserver.

3.2 Running Without the Realm Service

To create a specific and repeatable error condition, we’ll try to run our sample programs without a runningrealm service. The first step is to stop the FTL server (if it is running).

Open a command window and navigate to the $TIBFTL_TUTDIR/scripts directory. Stop the FTLserver:

./stop_ftl

The resulting output is shown in Listing 3.1:

Stopping FTL server.Done.

Listing 3.1: Output from running stop_ftl

We’ll want to continue to manipulate the FTL server, so in another command window, navigate to the$TIBFTL_TUTDIR/code/lesson-01 directory (where you built the ftlbasicpub and ftlbasicsub

sample programs), and start the subscriber:

./ftlbasicsub

Open a third command window and navigate to the same directory as above. Start the publisher:

TIBCO FTL R© Programming Tutorial

Page 15: TIBCO FTL R Programming Tutorial · 2018-11-28 · TIBCO FTL R Programming Tutorial. 4 Lesson 2: Understanding the Code In this lesson, we’ll examine the code used in lesson 1

10

./ftlbasicpub

The output from the publisher should appear as:

sending ’hello world’ messages

Listing 3.2: Output from running ftlbasicpub

In the subscriber command window, you should see:

waiting for message(s)

Listing 3.3: Output from running ftlbasicsub

Compare the output from these two commands with their output from lesson 1. The publisher output is thesame, but the subscriber output is quite different. The "received message" and message output linesare missing. Looking back at the source code for ftlbasicsub.c in lesson 2, it is apparent thatonMessages() function is not being called.

3.3 Adding Error Handling

FTL API calls require an exception object as the first argument. The sample program code creates andpasses the exception object to FTL API functions, but does not check the exception object for errorsfollowing the calls. We need to add error handling to the code, in which we will check the exceptionobjects and take appropriate action.

$TIBFTL_TUTDIR/code/lesson-03 contains modified ftlbasicpub.c and ftlbasicsub.c files, aswell as a new file, common.h:

1 #if !defined(COMMON_H_INCLUDED)2 #define COMMON_H_INCLUDED3

4 #include <stdio.h>5 #include <stdlib.h>6 #include "tib/ftl.h"7

8 #define CHECK(ex) \9 { \

10 if(tibEx_GetErrorCode(ex) != TIB_OK) \11 { \12 char exStr[1024]; \13 fprintf(stderr, "%s: %d\n", __FILE__, __LINE__); \14 tibEx_ToString(ex, exStr, sizeof(exStr)); \15 fprintf(stderr, "%s\n", exStr); \16 tib_Close(ex); \17 exit(-1); \18 } \19 }20

21 #endif

The modifications to ftlbasicpub.c are:

TIBCO FTL R© Programming Tutorial

Page 16: TIBCO FTL R Programming Tutorial · 2018-11-28 · TIBCO FTL R Programming Tutorial. 4 Lesson 2: Understanding the Code In this lesson, we’ll examine the code used in lesson 1

11

• Include the file common.h:

1 #include <stdio.h>2 #include <unistd.h>3 #include "tib/ftl.h"4 #include "common.h"

• Check for errors after creating the publisher:

22 pub = tibPublisher_Create(ex, realm, NULL, NULL);23 CHECK(ex);

• Check for errors after sending a message:

33 tibMessage_SetLong(ex, msg, "seq", seq);34 tibPublisher_Send(ex, pub, msg);35 CHECK(ex);36 sleep(1);

• Check for errors after closing the FTL environment:

42 tibRealm_Close(ex, realm);43 tib_Close(ex);44 CHECK(ex);

The changes made to ftlbasicsub.c are:

• Include the file common.h:

1 #include <stdio.h>2 #include "tib/ftl.h"3 #include "common.h"

• Check for errors after adding the subscriber to the event queue:

35 sub = tibSubscriber_Create(ex, realm, NULL, NULL, NULL);36 queue = tibEventQueue_Create(ex, realm, NULL);37 tibEventQueue_AddSubscriber(ex, queue, sub, onMessages, NULL);38 CHECK(ex);

• Check for errors after closing the FTL environment:

51 tibRealm_Close(ex, realm);52 tib_Close(ex);53 CHECK(ex);54 tibEx_Destroy(ex);

In a command window, navigate to $TIBFTL_TUTDIR/code/lesson-03, and build the samples:

make

Run the publisher again:

./ftlbasicpub

Now the output is:

TIBCO FTL R© Programming Tutorial

Page 17: TIBCO FTL R Programming Tutorial · 2018-11-28 · TIBCO FTL R Programming Tutorial. 4 Lesson 2: Understanding the Code In this lesson, we’ll examine the code used in lesson 1

12

ftlbasicpub.c: 23TIBCO Exception:

Error Code = Not foundDescription = unable to perform WTCP curl for url ’http://localhost:8080’Thread Name = ftlbasicpubStack Trace:

_tibCurl_PerformWtcp, 760_get_redirector_response, 1023_tibRealm_CreateBootFromServer, 1460_tibRealm_Connect, 2388tibRealm_Connect, 2721

Listing 3.4: Output from ftlbasicpub

We now we have more information as to why the output from the subscriber is different.

The Description contains the URL http://localhost:8080, which is the URL of the realm serviceto which the publisher was attempting to connect; further, the Error Code contains Not found. Fromthis we can determine that the publisher was unable to connect to the realm service, because it is notrunning; recall that we explicitly stopped the FTL server earlier in this lesson. As a result, the publisher’scall to tibRealm_Connect() failed. Since the publisher was unable to connect to the realm service, itcould not send any messages. And since no messages were sent by the publisher, the subscriber neverreceived any.

Before we address that problem, let’s run the subscriber to see how the problem manifests itself:

./ftlbasicsub

Now the output is:

ftlbasicsub.c: 38TIBCO Exception:

Error Code = Not foundDescription = unable to perform WTCP curl for url ’http://localhost:8080’Thread Name = ftlbasicsubStack Trace:

_tibCurl_PerformWtcp, 760_get_redirector_response, 1023_tibRealm_CreateBootFromServer, 1460_tibRealm_Connect, 2388tibRealm_Connect, 2721

Listing 3.5: Output from ftlbasicsub

The core problem, that the realm service is not running, is now apparent no matter which application is run.

3.4 Understanding the Error Handling Code and Output

So, what exactly is the CHECK() macro doing?

TIBCO FTL R© Programming Tutorial

Page 18: TIBCO FTL R Programming Tutorial · 2018-11-28 · TIBCO FTL R Programming Tutorial. 4 Lesson 2: Understanding the Code In this lesson, we’ll examine the code used in lesson 1

13

8 #define CHECK(ex) \9 { \

10 if(tibEx_GetErrorCode(ex) != TIB_OK) \11 { \12 char exStr[1024]; \13 fprintf(stderr, "%s: %d\n", __FILE__, __LINE__); \14 tibEx_ToString(ex, exStr, sizeof(exStr)); \15 fprintf(stderr, "%s\n", exStr); \16 tib_Close(ex); \17 exit(-1); \18 } \19 }

Listing 3.6: The CHECK() macro

Line 10 uses the FTL API function tibEx_GetErrorCode() to return the error code associated with theexception (tibEx object) passed as the argument. If no exception has occurred, the value TIB_OK isreturned, nothing more need be done by the CHECK() macro, and the invoking application continues.

However, if tibEx_GetErrorCode() returns a value other than TIB_OK, then an FTL exception hasoccurred. CHECK() prints the filename and line number at which the exception was checked, and uses thetibEx_ToString() FTL API function to format the exception information into a human-readable formwith the output going to the standard error (stderr) stream. It then closes the FTL environment and callsthe C exit() function. The assumption for our sample code is that once an FTL exception is encountered,nothing more can be done, so the program exits.

The output from tibEx_ToString() follows a standard format which includes:

• A description of the error code

• A more detailed description of the exception

• The name of the thread on which the exception occurred

• A stack trace

The first function listed in the stack trace is the internal FTL function in which the exception actuallyoccurred, and the last function is (generally) the FTL API call made by the client program.

The line numbers in the stack trace will depend on the specific version of FTL being used, so don’t beconcerned if the line numbers in your environment do not exactly match those in this lesson.

In the subscriber’s exception output (Listing 3.5), the exception was checked at line 38 offtlbasicsub.c, and the FTL API function which was called was tibRealm_Connect(). However,looking back at ftlbasicsub.c:

32 realm = tibRealm_Connect(ex, "http://localhost:8080", NULL, props);33 tibProperties_Destroy(ex, props);34

35 sub = tibSubscriber_Create(ex, realm, NULL, NULL, NULL);36 queue = tibEventQueue_Create(ex, realm, NULL);37 tibEventQueue_AddSubscriber(ex, queue, sub, onMessages, NULL);38 CHECK(ex);

Listing 3.7: ftlbasicsub.c

The call to tibRealm_Connect() is on line 32. Lines 35 through 37 also have FTL API calls, with thecall to tibEventQueue_AddSubscriber() in line 37 immediately before the CHECK() call. Why

TIBCO FTL R© Programming Tutorial

Page 19: TIBCO FTL R Programming Tutorial · 2018-11-28 · TIBCO FTL R Programming Tutorial. 4 Lesson 2: Understanding the Code In this lesson, we’ll examine the code used in lesson 1

14

didn’t the exception report an error in tibEventQueue_AddSubscriber()?

This illustrates an important feature of FTL API calls. Since an exception (tibEx) object is passed toevery call, the first thing an FTL API function does is check the exception object.

Concept 2. An FTL API function first examines the exception object passed to it. If the exception objectindicates that an exception has been detected, the function immediately returns, leaving the exceptionobject unchanged.

This approach has several benefits:

Preservation of informationIf an exception has occurred, continued processing may not be possible or desirable. In addition, ifprocessing were to continue and another exception occurred, the original exception informationcould be lost, obscuring what the initial (and most likely, actual) problem is.

Protection against compounding errorsIf an exception occurs in a call to a function which returns an object, it is possible that the object ispossibly only partially constructed or initialized. If that object is passed to another function (such asthe tibEventQueue object in lines 36 and 37 of ftlbasicsub.c), severe runtime errors (such assegfaults) could result.

Coding economyCHECK() calls (or their equivalent) are not needed after every FTL API call. Instead, exceptions canbe checked following a block of code or related group of operations.

3.5 Restart the FTL Server

Let’s return to a normal state of operations and restart the FTL server so we can observe the behavior of thesample programs with error checking. Go back to the command window in which you stopped the FTLserver and restart it:

./start_ftl

Using homedir/ftls-data as the realm server directory.Starting FTL server.Done.

Listing 3.8: Output from start_ftl

In the subscriber command window, restart the subscriber:

./ftlbasicsub

In the publisher command window, restart the publisher:

./ftlbasicpub

Once the publisher begins sending messages, you should see some familiar output in the subscribercommand window:

TIBCO FTL R© Programming Tutorial

Page 20: TIBCO FTL R Programming Tutorial · 2018-11-28 · TIBCO FTL R Programming Tutorial. 4 Lesson 2: Understanding the Code In this lesson, we’ll examine the code used in lesson 1

15

waiting for message(s)received message

{string:type="hello", string:contents="hello world", long:seq=1}received message

{string:type="hello", string:contents="hello world", long:seq=2}received message

{string:type="hello", string:contents="hello world", long:seq=3}received message

{string:type="hello", string:contents="hello world", long:seq=4}received message

{string:type="hello", string:contents="hello world", long:seq=5}

Listing 3.9: Output from ftlbasicsub

Because the realm service is now running, each client program is running as expected.

3.6 Working With Exceptions

For many situations, using the CHECK() macro (or its equivalent) with its built-in error checking, errormessage output, and subsequent client program termination is completely appropriate. However, this maynot be appropriate behavior in all circumstances. Many applications should not just exit on an FTL error,but require some cleanup operations to be performed before terminating.

For more control of detecting and handling exceptions, let’s take a look at the FTL API functions dealingwith exceptions in more detail.

3.6.1 FTL API Functions to Create and Destroy Exceptions

tibEx tibEx_Create(void);void tibEx_Destroy(tibEx e);

We’ve already seen the functions to create and destroy an exception object.

3.6.2 FTL API Functions to Retrieve Exception Information

tibErrorCode tibEx_GetErrorCode(tibEx e);const char* tibEx_GetSummaryString(tibEx e);int tibEx_ToString(tibEx e, char* buffer, int buflen);

A client program can directly access the FTL error code associated with a specific exception object byusing the tibEx_GetErrorCode() function. This is how a client program determines if an exception hasoccurred. If the call returns TIB_OK, no exception has occurred.

tibEx_ToString() was used in the CHECK() macro to format the full exception information, includingthe FTL stack backtrace. tibEx_GetSummaryString() returns only a short error code description (inour case, "Not found").

3.6.3 FTL API Functions to Clear Exceptions

void tibEx_Clear(tibEx e);

TIBCO FTL R© Programming Tutorial

Page 21: TIBCO FTL R Programming Tutorial · 2018-11-28 · TIBCO FTL R Programming Tutorial. 4 Lesson 2: Understanding the Code In this lesson, we’ll examine the code used in lesson 1

16

There may be some situations in which the code should continue to execute even though an exception hasoccurred. tibEx_Clear() can be used to clear an exception so that subsequent FTL API calls have achance to continue normally. Before using tibEx_Clear() in a client application you should be confidentthat your application, and FTL, should be able to continue regardless of any previously detected error.

TIBCO FTL R© Programming Tutorial

Page 22: TIBCO FTL R Programming Tutorial · 2018-11-28 · TIBCO FTL R Programming Tutorial. 4 Lesson 2: Understanding the Code In this lesson, we’ll examine the code used in lesson 1

17

Lesson 4: Messages and Fields

The fundamental unit of any messaging system is the message. In FTL, messages consist of one or morefields. So to use FTL effectively, it is vital to understand how to work with messages and the fields withinthem.

4.1 FTL Field Types

FTL supports five simple field types:

Type DescriptionOpaque An uninterpreted array of bytes. Suitable for binary data.Long A signed 64-bit integer value in the range [−263, 263 − 1]. When sending a long field

value, FTL encodes the value to use as few bytes as possible. So separate types for 8-,16-, and 32-bit values are not needed, and there is no performance penalty for sendingnumeric data in fields which are larger than necessary.

Double An IEEE 754 double-precision 64-bit binary floating-point value.String A UTF-8 encoded, null-terminated character string of arbitrary length.Date/Time A value representing seconds and nanoseconds since the epoch (midnight entering January

1, 1970 UTC).

FTL also supports two structured field types:

Type DescriptionMessage A complete message can be a field of another message. There is no limit to how deeply

messages may be nested.Inbox An inbox is an object that represents a specific subscriber object. The use of inboxes is an

advanced topic that is beyond the scope of this lesson.

Additionally, FTL supports fields containing arrays of longs, doubles, strings, messages, and date/timevalues.

4.2 FTL API Functions to Set Field Values in a Message

We saw in lesson 2 how FTL API calls can be used to set the value of a string field when populating ourfirst messages. We now cover the full set of FTL API calls to set field values.

TIBCO FTL R© Programming Tutorial

Page 23: TIBCO FTL R Programming Tutorial · 2018-11-28 · TIBCO FTL R Programming Tutorial. 4 Lesson 2: Understanding the Code In this lesson, we’ll examine the code used in lesson 1

18

void tibMessage_SetString(tibEx e, tibMessage message, const char* name, const char* value);void tibMessage_SetOpaque(tibEx e, tibMessage message, const char* name, const void* value,

tibint32_t size);void tibMessage_SetLong(tibEx e, tibMessage message, const char* name, tibint64_t value);void tibMessage_SetDouble(tibEx e, tibMessage message, const char* name, tibdouble_t value);void tibMessage_SetInbox(tibEx e, tibMessage message, const char* name, tibInbox inbox);void tibMessage_SetDateTime(tibEx e, tibMessage message, const char* name,

const tibDateTime* dateTime);void tibMessage_SetMessage(tibEx e, tibMessage message, const char* name, tibMessage value);

Each function is named using the standard FTL API naming convention. Each takes an exception (tibEx)object as the first argument, the message (tibMessage) object on which to operate as the secondargument, and the field name as the third argument.

The final argument (or two, depending on the function) specifies the data value to be set for that field.

void tibMessage_SetArray(tibEx e, tibMessage message, tibFieldType arrayType, const char* name,const void* const values, tibint32_t arraySize);

To set an array value, a single FTL API function is used, irrespective of the type of the array values. Insteadof a separate function for each field type, the field type is indicated via the arrayType argument, and mustbe one of the values listed in Table 4.1.

TIB_FIELD_TYPE_LONG_ARRAY An array of LongsTIB_FIELD_TYPE_DOUBLE_ARRAY An array of DoublesTIB_FIELD_TYPE_STRING_ARRAY An array of StringsTIB_FIELD_TYPE_MESSAGE_ARRAY An array of Message objectsTIB_FIELD_TYPE_DATETIME_ARRAY An array of Date/Time objects

Table 4.1: Array field types

The values argument must be an array of objects of the appropriate type, with the arraySize argumentindicating the number of elements in the array.

The definitions for all field types (including those listed in Table 4.1) can be found in the file$TIBFTL_DIR/include/ftl/msg.h provided as part of the FTL distribution.

4.3 FTL API Functions to Get Field Values from a Message

For each tibMessage_SetXXX() function there is a corresponding FTL API function to get a field valuefrom a message.

const char* tibMessage_GetString(tibEx e, tibMessage message, const char* name);const void* tibMessage_GetOpaque(tibEx e, tibMessage message, const char* name,

tibint32_t* size);tibint64_t tibMessage_GetLong(tibEx e, tibMessage message, const char* name);tibdouble_t tibMessage_GetDouble(tibEx e, tibMessage message, const char* name);tibInbox tibMessage_GetInbox(tibEx e, tibMessage message, const char* name);tibDateTime* tibMessage_GetDateTime(tibEx e, tibMessage message, const char* name);tibMessage tibMessage_GetMessage(tibEx e, tibMessage message, const char* name);

Each function takes an exception (tibEx) object as its first argument, the message (tibMessage) objecton which to operate as the second argument, and the field name as the third argument.tibMessage_GetOpaque() takes a fourth argument, a pointer to a tibint32_t, which is set to thelength of the data.

TIBCO FTL R© Programming Tutorial

Page 24: TIBCO FTL R Programming Tutorial · 2018-11-28 · TIBCO FTL R Programming Tutorial. 4 Lesson 2: Understanding the Code In this lesson, we’ll examine the code used in lesson 1

19

tibMessage_GetLong() and tibMessage_GetDouble() return the scalar field value.

tibMessage_GetString(), tibMessage_GetOpaque(), tibMessage_GetInbox(),tibMessage_GetDateTime(), and tibMessage_GetMessage() return pointers to the specific fieldvalues within the message. These pointers must not be modified by the application.

void* tibMessage_GetArray(tibEx e, tibMessage message, tibFieldType arrayType, const char* name,tibint32_t* arraySize);

To get the value of an array field, the tibMessage_GetArray() function is used, irrespective of the arrayvalue type.

4.4 Working with Messages

Beyond the FTL API functions dealing with message fields, there are a number of additional FTL APIfunctions which are useful when working with messages.

4.4.1 FTL API Functions to Create and Destroy Messages

tibMessage tibMessage_Create(tibEx e, tibRealm realm, const char* formatName);void tibMessage_Destroy(tibEx e, tibMessage message);

For review, we’ve listed the message creation and destruction functions above; ftlbasicpub.c callstibMessage_Create() to create a tibMessage object, and later calls tibMessage_Destroy() todestroy it.

Concept 3. If a client program creates a message using the tibMessage_Create() FTL API function,the client program is responsible for destroying the message. If the message is not explicitly destroyed viatibMessage_Destroy(), the memory associated with the message will not be freed.

There is one exception to this which is covered in lesson 9.

Note that the onMessages() function in ftlbasicsub.c does not call tibMessage_Destroy(). Themessage was created by the message dispatching code within the FTL library, not by ftlbasicsub.c, sothe FTL library is responsible for managing the message object.

Concept 4. If a message is created by the FTL library and passed to a client program message callbackfunction, the FTL library is responsible for destroying the message. It is destroyed upon return from themessage callback function. The client program should not destroy the message.

4.4.2 FTL API Functions to Clear Fields

void tibMessage_ClearField(tibEx e, tibMessage message, const char* name);void tibMessage_ClearAllFields(tibEx e, tibMessage message);

There are occasions when it is necessary or desirable to clear the current field value in a message,especially when reusing a message you have created. tibMessage_ClearField() allows you to clearthe current field value for a single field, while tibMessage_ClearAllFields() does the same for allfields in a message.

TIBCO FTL R© Programming Tutorial

Page 25: TIBCO FTL R Programming Tutorial · 2018-11-28 · TIBCO FTL R Programming Tutorial. 4 Lesson 2: Understanding the Code In this lesson, we’ll examine the code used in lesson 1

20

4.4.3 FTL API Functions to Get Field Information

tibbool_t tibMessage_IsFieldSet(tibEx e, tibMessage message, const char* name);

When processing a message, you may not know which fields are present. Calling one of thetibMessage_GetXXX() functions for a field name which does not exist in the message will result in anexception. Your code could check for the exception in each case, but this is an inefficient way to determineif a field exists.

If you don’t know if a field is present in a message, use tibMessage_IsFieldSet(). It returnstibtrue if the field exists and tibfalse if it does not.

tibFieldType tibMessage_GetFieldType(tibEx e, tibMessage message, const char* name);const char* tibFieldType_GetAsString(tibEx e, tibFieldType fieldType);

For situations in which the type of a field is not known, tibMessage_GetFieldType() can be used toretrieve the type (assuming, of course, that you have first verified that the field exists). It returns atibFieldType value indicating the field type: the scalar field types are listed in Table 4.2, while the arrayfield types were listed in Table 4.1, page 18.

TIB_FIELD_TYPE_OPAQUE An Opaque fieldTIB_FIELD_TYPE_LONG A Long fieldTIB_FIELD_TYPE_DOUBLE A Double fieldTIB_FIELD_TYPE_STRING A String fieldTIB_FIELD_TYPE_MESSAGE A Message fieldTIB_FIELD_TYPE_INBOX An Inbox fieldTIB_FIELD_TYPE_DATETIME A Date/Time field

Table 4.2: Scalar field types

tibFieldType_GetAsAString() translates a field type (tibFieldType) into a printable string.

4.4.4 FTL API Message Utility Functions

tibint32_t tibMessage_ToString(tibEx e, tibMessage message, char* buffer, tibint32_t size);

tibMessage_ToString() is a convenience function that formats a tibMessage into a human-readablestring.

TIBCO FTL R© Programming Tutorial

Page 26: TIBCO FTL R Programming Tutorial · 2018-11-28 · TIBCO FTL R Programming Tutorial. 4 Lesson 2: Understanding the Code In this lesson, we’ll examine the code used in lesson 1

21

Lesson 5: Introduction to Content Matchers

Content matchers (or simply matchers) provide a mechanism to specify which messages a subscribingclient program is interested in receiving. Message interest is based on the message content, specifically thepresence or value of one or more fields in a message. Matching determines which messages are deliveredto the subscriber.

In this lesson you will learn about matchers, modify the ftlsamplepub.c and ftlsamplesub.c clientprograms to use them, and then experiment with the updated programs.

The updated files can be found in $TIBFTL_TUTDIR/code/lesson-05.

5.1 Matcher Specification

Matchers use JSON expressions to specify the fields and values of interest. While the details of JSON areavailable elsewhere, we will briefly describe the format of a matcher string.

A matcher string consists of one or more conditions, separated by commas and enclosed in curly braces({}). A condition consists of a quoted string containing the field name, followed by a colon, followed bythe field value.

A field value is one of the following:

• A string contained in double quotes

• A long integer value

• A boolean constant (true or false) indicating the presence or absence of the field

Some simple examples of matcher strings are:

{"tag":"hello"}{"tag":true}{"tag":"hello","content":true}

The first example matches a message if its "tag" field contains the value "hello". If the "tag" field isnot present in the message, the condition is implicitly false. The second example matches a message if the"tag" field is present in the message, regardless of its value.

If a matcher contains more than one condition, each condition must be true for the message to match. In thethird example there are two conditions: the "tag" field must contain the value "hello", and the"content" field must be present. Both conditions must be true for the message to be delivered to thesubscriber.

5.2 ftlbasicpub.c

We’ll take the sample code from lesson 3 and add matcher support with only a few minor changes.

TIBCO FTL R© Programming Tutorial

Page 27: TIBCO FTL R Programming Tutorial · 2018-11-28 · TIBCO FTL R Programming Tutorial. 4 Lesson 2: Understanding the Code In this lesson, we’ll examine the code used in lesson 1

22

14 const char *fieldname = NULL;15

16 if (argc > 1)17 {18 fieldname = argv[1];19 }

ftlbasicpub.c now accepts an optional command-line argument. This argument is used as the name ofa field to include in the published messages. Lines 16 through 19 check if the argument is present, and if itis, stores the string in fieldname for later use.

33 if (fieldname != NULL)34 {35 tibMessage_SetString(ex, msg, fieldname, fieldname);36 }

If fieldname is not NULL, then the optional field name argument was specified on the command line. Line35 adds that field to the message. For simplicity, the field value is the same as the field name.

Note that fieldname was initialized to NULL in line 14 above. So if the command line argument was notspecified, fieldname is still NULL, indicating not to add the field to the published message.

5.3 ftlbasicsub.c

The changes made to ftlbasicsub.c from lesson 3 in support of matchers are a little more extensive.

27 const char *fieldname = NULL;28 tibContentMatcher cm = NULL;29 char matcher[256];30

31 if (argc > 1)32 {33 fieldname = argv[1];34 sprintf(matcher, "{\"%s\":true}", fieldname);35 }

Like ftlbasicpub.c, ftlbasicsub.c accepts an optional command line argument. This time theargument is used as the name of a field to match. Lines 31 through 35 check for the presence of theargument, and if it exists, line 34 creates a JSON matcher string using the field name.

Assuming abc was specified on the command line, the resulting matcher string will look like this:

{"abc":true}

This matcher string will match a message only if the "abc" field is present in the message.

43 if (fieldname != NULL)44 {45 cm = tibContentMatcher_Create(ex, realm, matcher);46 }47 sub = tibSubscriber_Create(ex, realm, NULL, cm, NULL);

If a matcher field name was specified on the command line, line 45 uses the matcher string to create amatcher object, which is passed to tibSubscriber_Create() in line 47. The resulting subscriber willonly receive messages which match the content matcher.

TIBCO FTL R© Programming Tutorial

Page 28: TIBCO FTL R Programming Tutorial · 2018-11-28 · TIBCO FTL R Programming Tutorial. 4 Lesson 2: Understanding the Code In this lesson, we’ll examine the code used in lesson 1

23

60 if (cm != NULL)61 {62 tibContentMatcher_Destroy(ex, cm);63 }

Lines 60 through 63 destroy the matcher object, as it is no longer needed.

5.4 Build and Run the Samples

In a command window, navigate to $TIBFTL_TUTDIR/code/lesson-05 and build the samples:

make

Once built, run the subscriber with no arguments:

./ftlbasicsub

In another command window, navigate to $TIBFTL_TUTDIR/code/lesson-05 and run the publisherwith no arguments:

./ftlbasicpub

The output should appear as:

sending ’hello world’ messages

Listing 5.1: Output from ftlbasicpub

Back in the subscriber command window, you should see:

waiting for message(s)received message

{string:type="hello", string:contents="hello world", long:seq=1}received message

{string:type="hello", string:contents="hello world", long:seq=2}received message

{string:type="hello", string:contents="hello world", long:seq=3}received message

{string:type="hello", string:contents="hello world", long:seq=4}received message

{string:type="hello", string:contents="hello world", long:seq=5}

Listing 5.2: Output from ftlbasicpub run with no arguments

Both programs give the same output as seen in lesson 3. Simply adding the code to use matchers has notchanged either program’s behavior if no argument is given.

Now, let’s try running them with an argument. In the subscriber command window, stop the subscriberwith ctrl + C . Restart it with a command-line argument:

./ftlbasicsub abc

TIBCO FTL R© Programming Tutorial

Page 29: TIBCO FTL R Programming Tutorial · 2018-11-28 · TIBCO FTL R Programming Tutorial. 4 Lesson 2: Understanding the Code In this lesson, we’ll examine the code used in lesson 1

24

In the publisher command window, run the publisher with the same command-line argument:

./ftlbasicpub abc

The output from the publisher is the same, but the output from the subscriber now shows that the messagesinclude the "abc" field:

waiting for message(s)received message

{string:type="hello", string:contents="hello world", string:abc="abc", long:seq=1}received message

{string:type="hello", string:contents="hello world", string:abc="abc", long:seq=2}received message

{string:type="hello", string:contents="hello world", string:abc="abc", long:seq=3}received message

{string:type="hello", string:contents="hello world", string:abc="abc", long:seq=4}received message

{string:type="hello", string:contents="hello world", string:abc="abc", long:seq=5}

Listing 5.3: Output from ftlbasicsub abc

This output is similar to the previous run, but notice that each received message now has a string fieldcalled "abc" with the value "abc".

Leave the subscriber running. In the publisher command window, run the publisher with no command-lineargument:

./ftlbasicpub

Back in the subscriber command window, you should see no additional output beyond what was alreadyseen in Listing 5.3.

The subscriber that was started with the abc command line argument is still running. When started, itcreated a matcher requiring that the "abc" field be present in a message for that message to be delivered tothe subscriber. However, the publisher was started without the command line argument, so it is sendingmessages without the "abc" field. The incoming messages did not match the subscriber’s matcher,preventing the messages from being delivered to the subscriber. The matcher is doing what it is supposedto.

Stop the subscriber with ctrl + C .

5.5 Some Variations

Next, let’s experiment with some variations. In the subscriber command window, restart the subscriberwith:

./ftlbasicsub abc

Open a new command window, navigate to $TIBFTL_TUTDIR/code/lesson-05, and start a secondsubscriber:

./ftlbasicsub abc

TIBCO FTL R© Programming Tutorial

Page 30: TIBCO FTL R Programming Tutorial · 2018-11-28 · TIBCO FTL R Programming Tutorial. 4 Lesson 2: Understanding the Code In this lesson, we’ll examine the code used in lesson 1

25

We are starting two separate instances of the subscriber, both matching the field "abc".

In the publisher command window, start the publisher with:

./ftlbasicpub abc

If you look in both subscriber command windows, you should see the same output:

waiting for message(s)received message

{string:type="hello", string:contents="hello world", string:abc="abc", long:seq=1}received message

{string:type="hello", string:contents="hello world", string:abc="abc", long:seq=2}received message

{string:type="hello", string:contents="hello world", string:abc="abc", long:seq=3}received message

{string:type="hello", string:contents="hello world", string:abc="abc", long:seq=4}received message

{string:type="hello", string:contents="hello world", string:abc="abc", long:seq=5}

Listing 5.4: Output from ftlbasicsub abc

Both subscribers match and receive the messages sent by the publisher.

Next, stop both subscribers with ctrl + C . In one subscriber command window, start the subscriber with:

./ftlbasicsub abc

In the publisher command window, start the publisher with:

./ftlbasicpub abc

In another command window, navigate to $TIBFTL_TUTDIR/code/lesson-05. Start a second publisherby typing:

./ftlbasicpub abc

This time, the output in the subscriber command window is:

TIBCO FTL R© Programming Tutorial

Page 31: TIBCO FTL R Programming Tutorial · 2018-11-28 · TIBCO FTL R Programming Tutorial. 4 Lesson 2: Understanding the Code In this lesson, we’ll examine the code used in lesson 1

26

waiting for message(s)received message

{string:type="hello", string:contents="hello world", string:abc="abc", long:seq=1}received message

{string:type="hello", string:contents="hello world", string:abc="abc", long:seq=1}received message

{string:type="hello", string:contents="hello world", string:abc="abc", long:seq=2}received message

{string:type="hello", string:contents="hello world", string:abc="abc", long:seq=2}received message

{string:type="hello", string:contents="hello world", string:abc="abc", long:seq=3}received message

{string:type="hello", string:contents="hello world", string:abc="abc", long:seq=3}received message

{string:type="hello", string:contents="hello world", string:abc="abc", long:seq=4}received message

{string:type="hello", string:contents="hello world", string:abc="abc", long:seq=4}received message

{string:type="hello", string:contents="hello world", string:abc="abc", long:seq=5}received message

{string:type="hello", string:contents="hello world", string:abc="abc", long:seq=5}

Listing 5.5: Output from ftlbasicsub abc

The subscriber has received messages from two separate instances of the publisher.

Concept 5. In FTL, a publisher can publish to multiple subscribers at the same time, and a subscriber canreceive from multiple publishers at the same time, subject to any matching criteria in the subscribers.

Depending on how quickly the two publishers are started, the exact ordering of the output may be slightlydifferent than seen in Listing 5.5, but should still show 10 messages: two with "seq" 1, two with "seq" 2,and so forth.

TIBCO FTL R© Programming Tutorial

Page 32: TIBCO FTL R Programming Tutorial · 2018-11-28 · TIBCO FTL R Programming Tutorial. 4 Lesson 2: Understanding the Code In this lesson, we’ll examine the code used in lesson 1

27

Lesson 6: Exploring the Realm

In this lesson we take a step back from FTL API programming and explore the realm definitions madeavailable by the realm service. We’ll look at the definitions through both the realm service web interfaceand the realm service web API.

In order to get the most from this lesson, make sure you have read the TIBCO FTL R© Concepts guide beforeproceeding.

Note

Throughout the remaining lessons, it is assumed that the FTL server and sample programs arerunning on the same computer. This allows the FTL server to be addressed vialocalhost:8080.

If you want to run the FTL server on a different computer, a few changes must be made.

• Start the FTL server (on the desired computer) using the start_ftl script in$TIBFTL_TUTDIR/scripts, and specify the actual address and port. For example, ifthe computer on which the FTL server is to run has the address 192.168.10.1, and port9000 is to be used, the command would be:

./start_ftl 192.168.10.1:9000

Likewise, when stopping the FTL server using the stop_ftl script, use:

./stop_ftl 192.168.10.1:9000

• When accessing the realm service web interface, rather than navigating tohttp://localhost:8080, use (assuming the values above)http://192.168.10.1:9000.

• Change the URL in any curl command lines to reference the correct address and port.

• Add the -r ip:port option to any sample program command lines. Substitute thecorrect address and port for ip:port.

6.1 The Realm Service Web Interface

Assuming the FTL server is still running, open a web browser and navigate to the URLhttp://localhost:8080. The resulting screen is shown in Figure 6.1.

TIBCO FTL R© Programming Tutorial

Page 33: TIBCO FTL R Programming Tutorial · 2018-11-28 · TIBCO FTL R Programming Tutorial. 4 Lesson 2: Understanding the Code In this lesson, we’ll examine the code used in lesson 1

28

Figure 6.1: Realm service login page

Full documentation on the realm service web interface can be found in the TIBCO FTL R© Administrationguide.

The first page shown is the login page. Normally you would enter the user ID and password assigned byyour administrator. For the sake of simplicity, in this tutorial we are running the FTL server withoutsecurity, in insecure mode. Insecure mode allows only a single user ID, “anyone”, with no password.

Click the “SIGN IN” button to display the next page:

TIBCO FTL R© Programming Tutorial

Page 34: TIBCO FTL R Programming Tutorial · 2018-11-28 · TIBCO FTL R Programming Tutorial. 4 Lesson 2: Understanding the Code In this lesson, we’ll examine the code used in lesson 1

29

Figure 6.2: Applications grid

Figure 6.2 shows the Applications grid, which displays all applications defined in the FTL system. Foreach application, the endpoints associated with it are shown, along with the transports associated with eachendpoint.

Along the left side of the page appear a series of links, each with an icon and description, which navigate tospecific pages in the realm service web interface. For example, the link denoted by the icon, andlabeled “Applications”, takes you to the Applications grid.

What is shown in Figure 6.2 is the initial, default configuration provided when starting a new FTL server.A single application is defined, “default”, along with its corresponding endpoints and transports.

The samples we’ve developed in previous lessons have implicitly used the “default” application. If youlook back at ftlbasicpub.c from lesson 5 ($TIBFTL_TUTDIR/code/lesson-05/ftlbasicpub.c),you see the line:

24 realm = tibRealm_Connect(ex, "http://localhost:8080", NULL, props);

The third argument to tibRealm_Connect() is a character string containing the application name. Byspecifying NULL, we are telling FTL to use the default application, which is conveniently named “default”— and is exactly the “default” application shown in Figure 6.2.

So, let’s take a look at the “default” application in more detail by clicking on the “default” applicationname. You should see a screen similar to Figure 6.3.

TIBCO FTL R© Programming Tutorial

Page 35: TIBCO FTL R Programming Tutorial · 2018-11-28 · TIBCO FTL R Programming Tutorial. 4 Lesson 2: Understanding the Code In this lesson, we’ll examine the code used in lesson 1

30

Figure 6.3: “default” Application details panel

This panel shows the detailed application information, including the application name (“default”) andapplication description. We can ignore the “Manage All Formats”, “Preload Formats”, and “InstanceMatching Order” items for now.

In the upper-right corner of the application display, a (close) control is shown. Clicking on this controlcloses the currently shown details panel, and is a common interaction used throughout the realm serviceweb interface. Close the Application details panel by clicking on the close control, which will take youback to the Applications grid:

TIBCO FTL R© Programming Tutorial

Page 36: TIBCO FTL R Programming Tutorial · 2018-11-28 · TIBCO FTL R Programming Tutorial. 4 Lesson 2: Understanding the Code In this lesson, we’ll examine the code used in lesson 1

31

Figure 6.4: Applications grid

The “default” application defines a single endpoint named “default”. The samples we’ve developed thus farhave implicitly used not only the “default” application, but also the “default” endpoint.

In $TIBFTL_TUTDIR/code/lesson-05/ftlbasicpub.c we had the line:

27 pub = tibPublisher_Create(ex, realm, NULL, NULL);

The third argument to tibPublisher_Create() is a string containing the endpoint name (within thatapplication) on which to publish. By specifying NULL, we are telling FTL to use the default endpointwithin the application, named “default”.

Similarly, in $TIBFTL_TUTDIR/code/lesson-05/ftlbasicsub.c we had the line:

1 sub = tibSubscriber_Create(ex, realm, NULL, cm, NULL);

The third argument to tibSubscriber_Create() is a string containing the endpoint name (within thatapplication) to subscribe to. By specifying NULL, we are telling FTL to use the default endpoint within theapplication, named “default”.

So let’s take a deeper look at the “default” endpoint. Click the “default” endpoint, which will open theEndpoint details panel:

TIBCO FTL R© Programming Tutorial

Page 37: TIBCO FTL R Programming Tutorial · 2018-11-28 · TIBCO FTL R Programming Tutorial. 4 Lesson 2: Understanding the Code In this lesson, we’ll examine the code used in lesson 1

32

Figure 6.5: “default” Endpoint details panel

Publishers and subscribers using the “default” endpoint of the “default” application communicate via astore. The store does not persist messages (note the “Store” name: “ftl.nonpersistent.store”) but insteadforwards published messages to all subscribers. This is called server-based messaging, and essentiallyemploys a message broker. Server-based messaging is simpler to manage and administrate thanpeer-to-peer messaging, which is why it is the default. A comparison of server-based and peer-to-peermessaging, as well as the benefits of each, will be presented in a later lesson.

It is important to note that the default application and endpoint really are named “default”. This is not areserved, hidden, or otherwise special name, but is the object reference used by the FTL server when noexplicit application or endpoint is specified. These “default” configuration settings are available whenstarting from an empty realm configuration and will remain part of the realm configuration unless they areexplicitly deleted.

6.2 The Realm Service Web API

The realm service web API can also be used to view, add, and modify definitions for FTL objects. For oursamples, we’ll use the open-source curl utility to access the realm service web API.

Consult the TIBCO FTL R© Administration guide for details on the realm service web API.

JSON is used to represent FTL configuration information, both as input to add and modify objects, and asoutput to return the results of a realm service web API operation.

Assuming the FTL server is still running, open a command window and type:

curl -X GET http://localhost:8080/api/v1/realm/applications/default

The resulting output is shown in Listing 6.1.

TIBCO FTL R© Programming Tutorial

Page 38: TIBCO FTL R Programming Tutorial · 2018-11-28 · TIBCO FTL R Programming Tutorial. 4 Lesson 2: Understanding the Code In this lesson, we’ll examine the code used in lesson 1

33

1 {2 "last_modified": "XXXX-XX-XXTXX:XX:XX.XXXXXXXXX-XX:XX",3 "last_modified_millis": XXXXXXXXXXXXX,4 "last_modified_by": "ftl",5 "name": "default",6 "id": XXX,7 "description": "",8 "manage_all_formats": false,9 "preload_format_names": [],

10 "endpoints": [11 {12 "name": "default",13 "id": XXX,14 "store": "ftl.nonpersistent.store",15 "cluster": "ftl.default.cluster",16 "description": "",17 "transports": [],18 "dynamic_durable": {19 "template": "ftl.pubsub.template"20 },21 "subscribers": []22 }23 ],24 "instances": []25 }

Listing 6.1: “default” application realm service web API output

This corresponds to the application definition from Figure 6.3, and you should be able to correlate itemsvisible via the realm service web interface with items in the JSON output.

A few things to note:

• Line 5 defines the name of the application, "default".

• Lines 10 through 23 list the endpoints. The value of the "endpoints" key is an array of objects. Inthis case the array contains a single endpoint object, “default”.

• Lines 11 through 22 define the “default” endpoint.

– Line 12 is the endpoint name, "default".

– Line 14 is the store used, "ftl.nonpersistent.store".

– Line 17 lists the transports associated with the endpoint. Since an endpoint can have more thanone transport, the value of the "transports" key is an array of objects. Since a store is used,no transport is present.

The JSON output also contains other information which we will discuss in later lessons.

TIBCO FTL R© Programming Tutorial

Page 39: TIBCO FTL R Programming Tutorial · 2018-11-28 · TIBCO FTL R Programming Tutorial. 4 Lesson 2: Understanding the Code In this lesson, we’ll examine the code used in lesson 1

34

Lesson 7: Defining an Application

In this lesson, we will define two new applications in the FTL server, with an endpoint for each application.For the sake of simplicity, the first new application will be named “App1” with endpoint “endpoint-1”. Thesecond new application will be named “App2” with with endpoint “endpoint-2”.

We will make use of these new applications in subsequent lessons.

7.1 The Process

There are four steps involved in any change to the realm definition.

1. Lock the realm definition workspace. Locking the workspace creates a copy of the realm definitionthat you can modify, while the realm service’s client processes continue to operate using the currentrealm definition. Locking the workspace prevents others from modifying the workspace until you arefinished.

2. Make the changes. Modify the realm definition, including the application and endpoint definitionswithin it.

3. Resolve any problems. The realm service validates the realm definition each time you modify it. Forexample, if detects references to undefined objects. If it detects any issues, you must correct them.

4. Deploy the changes. Deploying the modified workspace promotes it to become the actual realmdefinition, governing the operation of the processes that are clients of the realm service. The realmservice pushes the new information to any running clients. It also unlocks the workspace after asuccessful deployment.

7.2 Defining an Application Using the Realm Service Web Interface

Assuming the FTL server is still running, open a web browser and navigate to the URLhttp://localhost:8080. If the FTL server login page is displayed, login as you did in Section 6.1,page 27. Bring up the Applications grid by clicking on the link on the left side of the screen.

TIBCO FTL R© Programming Tutorial

Page 40: TIBCO FTL R Programming Tutorial · 2018-11-28 · TIBCO FTL R Programming Tutorial. 4 Lesson 2: Understanding the Code In this lesson, we’ll examine the code used in lesson 1

35

Figure 7.1: Applications grid

Before any changes can be made to the realm definition, the realm workspace lock must be taken. Thisprevents more than one user from changing the realm definition at the same time.

Along the top of the screen are two controls, shown below:

Figure 7.2: Edit and Deploy controls

Next to “Edit Mode” is a switch (shown in the “Off” position) which locks the realm workspace and allowsthe realm configuration to be edited. To the right is the “Deploy” control which allows you to deploy thenew realm configuration when you have finished making changes. Note that the “Deploy” control iscurrently disabled and not active.

Lock the realm workspace by clicking on the “Edit Mode” switch, resulting in the screen shown in Figure7.3.

TIBCO FTL R© Programming Tutorial

Page 41: TIBCO FTL R Programming Tutorial · 2018-11-28 · TIBCO FTL R Programming Tutorial. 4 Lesson 2: Understanding the Code In this lesson, we’ll examine the code used in lesson 1

36

Figure 7.3: Applications grid (realm workspace is locked)

The workspace is now locked, allowing changes to be made to the realm workspace. In addition, the top ofthe screen has changed and now appears as:

Figure 7.4: Edit and Deploy controls (realm workspace is locked)

Note that the “Edit Mode” switch is now “On”, and the “Deploy” control is now enabled.

Now that the realm workspace is locked, we can create the new application. Click the icon next to“Applications” to create a new, blank application row:

TIBCO FTL R© Programming Tutorial

Page 42: TIBCO FTL R Programming Tutorial · 2018-11-28 · TIBCO FTL R Programming Tutorial. 4 Lesson 2: Understanding the Code In this lesson, we’ll examine the code used in lesson 1

37

Figure 7.5: Ready to add an application

Place the cursor in the text field in the newly added row, beneath the “Application” column header, and typethe new application name: “App1”. Then press Tab .

Figure 7.6: Application created

Place the cursor in the text field beneath the “Endpoint” column header, and type the new endpoint name:“endpoint-1”. Press Tab ; the screen should appear as:

TIBCO FTL R© Programming Tutorial

Page 43: TIBCO FTL R Programming Tutorial · 2018-11-28 · TIBCO FTL R Programming Tutorial. 4 Lesson 2: Understanding the Code In this lesson, we’ll examine the code used in lesson 1

38

Figure 7.7: Endpoint added

Leave the values under “Store”, “Durable Template”, and “Transport” at their default values.

At this point. we have created the new application “App1”, including its endpoint “endpoint-1”. The nextstep is to deploy the new realm configuration to any running clients, as well as making it available to anynew clients which will start in the future.

Click the “Deploy” control at the top of the screen, which will start the deployment process:

Figure 7.8: Deploy the changed realm configuration

TIBCO FTL R© Programming Tutorial

Page 44: TIBCO FTL R Programming Tutorial · 2018-11-28 · TIBCO FTL R Programming Tutorial. 4 Lesson 2: Understanding the Code In this lesson, we’ll examine the code used in lesson 1

39

When deploying a new realm definition, you are given the opportunity to name the deployment and providea description. The name is required and a default value based on the current date and time is provided. Thedescription is optional but can be helpful when tracking changes made to the realm definition.

Click the “Deploy” button. At this point the deployment process begins, and the status of the deploymentwill be displayed as well as a final deployment status:

Figure 7.9: Deployment status

When changes are made to the realm definition and then deployed, each client (including any realmservices) is notified of the changes. The client then sends a response to the FTL server, indicating if thenew realm definition was accepted, rejected, or accepted but requires the client to be restarted. TheDeployment status page reflects the number of clients responding with each type of response, as well as thenumber of clients from whom no response was received.

As a result of the deployment, the realm workspace lock is released and the realm configuration is nolonger editable (until the “Edit” switch is used to start a new editing session).

Once the deployment has completed, clicking on the “Done” button will open the Deployment Historypage, shown in Figure 7.10.

TIBCO FTL R© Programming Tutorial

Page 45: TIBCO FTL R Programming Tutorial · 2018-11-28 · TIBCO FTL R Programming Tutorial. 4 Lesson 2: Understanding the Code In this lesson, we’ll examine the code used in lesson 1

40

Figure 7.10: Deployment History page

The Deployment History page shows the current and all previous deployments, including the name,description, deployment and creation dates, and the ID of the user who created and deployed the realmdefinition.

At this point, the changes have been made to the realm definition and deployed to all clients. To verify thatthe new application has been added to the realm definition, click the “Applications” link (denoted by the

icon) on the left side of the screen:

TIBCO FTL R© Programming Tutorial

Page 46: TIBCO FTL R Programming Tutorial · 2018-11-28 · TIBCO FTL R Programming Tutorial. 4 Lesson 2: Understanding the Code In this lesson, we’ll examine the code used in lesson 1

41

Figure 7.11: Applications grid showing new application

7.3 Defining an Application Using the Realm Service Web API

Now let’s add the second application, “App2”, this time using the realm service web API and curl. Open acommand window and navigate to $TIBFTL_TUTDIR/code/lesson-07. Although curl does notrequire you to be in a specific working directory, files containing the JSON input are provided in the lessondirectory, and having this directory as your working directory will simplify accessing these files from thecommand line. These files will be used as input to curl rather than having to type the entire JSONexpression on the command line.

The first step is to lock the realm workspace so we can modify the realm definition. Type:

curl -X POST http://localhost:8080/api/v1/realm/workspace

This form of the realm service web API command highlights the fact that we’re locking the realmworkspace rather than the FTL server. It is effectively the same as clicking the “lock realm to edit” icon inthe FTL server UI.

The resulting output is:

1 {2 "user": "anyone",3 "autosave": false4 }

Listing 7.1: Output from locking the realm via the realm service web API

The output is JSON showing that the realm is currently locked by user "anyone" and that there were noerrors.

TIBCO FTL R© Programming Tutorial

Page 47: TIBCO FTL R Programming Tutorial · 2018-11-28 · TIBCO FTL R Programming Tutorial. 4 Lesson 2: Understanding the Code In this lesson, we’ll examine the code used in lesson 1

42

Next, create the application. In the open command window, type:

curl -H "Content-Type: application/json" -d @create-application.json -X POST \http://localhost:8080/api/v1/realm/applications

The contents of create-application.json are shown in Listing 7.2:

1 {2 "name": "App2",3 "endpoints": [4 {5 "name": "endpoint-2",6 "store": "ftl.nonpersistent.store",7 "cluster": "ftl.default.cluster",8 "dynamic_durable": {9 "template": "ftl.pubsub.template"

10 }11 }12 ]13 }

Listing 7.2: create-application.json

The response from the FTL server should look like:

1 {2 "last_modified": "XXXX-XX-XXTXX:XX:XX.XXXXXXXXX-XX:XX",3 "last_modified_millis": XXXXXXXXXXXXX,4 "last_modified_by": "anyone",5 "name": "App2",6 "description": "",7 "manage_all_formats": false,8 "preload_format_names": [],9 "endpoints": [

10 {11 "name": "endpoint-2",12 "store": "ftl.nonpersistent.store",13 "cluster": "ftl.default.cluster",14 "description": "",15 "transports": [],16 "dynamic_durable": {17 "template": "ftl.pubsub.template"18 },19 "subscribers": []20 }21 ],22 "instances": []23 }

Listing 7.3: Output from creating the application

Notice that the resulting application definition includes keys and values which we did not specify increate-application.json. These default keys and values were added by the FTL server.

Before actually deploying the new definition, it is advisable to validate our workspace. In the opencommand window, type:

curl -X GET http://localhost:8080/api/v1/realm/workspace/validation

If there are no errors, the resulting output will be:

TIBCO FTL R© Programming Tutorial

Page 48: TIBCO FTL R Programming Tutorial · 2018-11-28 · TIBCO FTL R Programming Tutorial. 4 Lesson 2: Understanding the Code In this lesson, we’ll examine the code used in lesson 1

43

1 {2 "results": []3 }

Listing 7.4: Workspace validation output

No errors are shown, so we can go ahead and deploy our changes. If there were validation errors, the"results" array would include an entry for each error providing a descriptive message, an error level,and a partial URL to access the specific realm object with the error.

In the open command window, type:

curl -H "Content-Type: application/json" -d @deploy.json -X POST \http://localhost:8080/api/v1/realm/deployments

The contents of deploy.json are:

1 {2 "name": "mywebapideployment"3 }

Listing 7.5: deploy.json

The realm server response will be similar to:

1 {2 "name": "mywebapideployment",3 "description": "",4 "realm_revision": XXXX,5 "created_by": "anyone",6 "created_millis": XXXXXXXXXXXXX,7 "created_on": "XXX, XX XXX XXXX XX:XX:XX XXX",8 "last_deployed_by": "anyone",9 "last_deployed_millis": XXXXXXXXXXXXX,

10 "last_deployed_on": "XXX, XX XXX XXXX XX:XX:XX XXX",11 "automation": 3,12 "automation_label": "Force",13 "deployment_status": "Starting",14 "deployment_status_label": "Starting - notifying clients and servers",15 "deployment_time_millis": 016 }

Listing 7.6: Output from deployment

You’ve successfully created a new application using the realm service web API!

It should be noted that the new application definition is functionally equivalent to the “default” definition.

As a final step, let’s retrieve the definition for the application and transport we added using the realmservice web API. In the open command window, type:

curl -X GET http://localhost:8080/api/v1/realm/applications/App2

This requests the application definition for “App2”. The response from the FTL server should appearsimilar to:

TIBCO FTL R© Programming Tutorial

Page 49: TIBCO FTL R Programming Tutorial · 2018-11-28 · TIBCO FTL R Programming Tutorial. 4 Lesson 2: Understanding the Code In this lesson, we’ll examine the code used in lesson 1

44

1 {2 "last_modified": "XXXX-XX-XXTXX:XX:XX.XXXXXXXX-XX:XX",3 "last_modified_millis": XXXXXXXXXXXXX,4 "last_modified_by": "anyone",5 "name": "App2",6 "id": XXXX,7 "description": "",8 "manage_all_formats": false,9 "preload_format_names": [],

10 "endpoints": [11 {12 "name": "endpoint-2",13 "id": XXXX,14 "store": "ftl.nonpersistent.store",15 "cluster": "ftl.default.cluster",16 "description": "",17 "transports": [],18 "dynamic_durable": {19 "template": "ftl.pubsub.template"20 },21 "subscribers": []22 }23 ],24 "instances": []25 }

Listing 7.7: Application “App2” definition from the realm service web API

TIBCO FTL R© Programming Tutorial

Page 50: TIBCO FTL R Programming Tutorial · 2018-11-28 · TIBCO FTL R Programming Tutorial. 4 Lesson 2: Understanding the Code In this lesson, we’ll examine the code used in lesson 1

45

Lesson 8: Using Applications and Endpoints

In this lesson we’ll begin building a more general-purpose FTL publisher and subscriber. Ideally, whenyou’re finished, you’ll have a set of good reference samples for use as a starting point for your own FTLclient programs.

But first, let’s look at what the new client programs do.

8.1 The Client Programs

For our samples, the publisher and subscriber implement an application-level protocol consisting of twotypes of messages: control and data. Each message contains a subset of seven fields, listed in Table 8.1.

Each set of data messages is a stream. We use beginning of stream (BOS) and end of stream (EOS) toindicate where the stream starts and ends.

Sequence numbers denote where a message belongs in a stream.

8.1.1 Publisher Operation

The publisher begins by sending a control message. Included in this message are four fields: "tag"(containing "control"), "count", "contents", and "bos". "count" contains the number of datamessages the subscriber should expect to receive. This message marks the beginning of the stream ofmessages being published.

Next, the publisher sends zero or more data messages. Each message contains four fields: "tag"(containing "data"), "contents", "seq", and "even". "seq" contains the data message sequencenumber, counting from 1. "even" is set to 1 if "seq" is even, and 0 if it is odd.

When all data messages have been sent, the publisher sends a final control message. This message containsfour fields: "tag" (containing "control"), "count", "contents", and "eos". "count" contains thenumber of data messages the publisher sent. This message marks the end of the stream of messages beingpublished.

Field Type Description"tag" String Indicates the message type ("control" or "data")."count" Long Contains the number of data messages to expect."contents" String Payload field containing some text."seq" Long Data message sequence number."bos" Long Message is the beginning of stream (BOS) if present."eos" Long Message is the end of stream (EOS) if present."even" Long Contains 1 if the "seq" field is even, and 0 if odd.

Table 8.1: Message fields

TIBCO FTL R© Programming Tutorial

Page 51: TIBCO FTL R Programming Tutorial · 2018-11-28 · TIBCO FTL R Programming Tutorial. 4 Lesson 2: Understanding the Code In this lesson, we’ll examine the code used in lesson 1

46

8.1.2 Subscriber Operation

The subscriber will expect messages in the order listed above: a control message indicating BOS, zero ormore data messages, followed by a control message indicating EOS. Any deviation from this order shouldbe detected by the subscriber and cause a message to be printed.

8.2 The Code

The code files for this lesson can be found in the $TIBFTL_TUTDIR/code/lesson-08 directory. Fourfiles are involved: Makefile, common.h, ftlpub.c, and ftlsub.c. Instead of listing the entire contentsof each file, we will summarize the interesting parts of each.

8.2.1 common.h

21 #define FIELD_NAME_TAG "tag"22 #define FIELD_NAME_COUNT "count"23 #define FIELD_NAME_CONTENTS "contents"24 #define FIELD_NAME_SEQ "seq"25 #define FIELD_NAME_BOS "bos"26 #define FIELD_NAME_EOS "eos"27 #define FIELD_NAME_EVEN "even"28

29 #define FIELD_TAG_CONTROL "control"30 #define FIELD_TAG_DATA "data"

Listing 8.1: common.h

Most of common.h is unchanged, but we’ve added definitions for the message fields.

8.2.2 ftlpub.c

9 #define DEFAULT_REALM_SERVICE "http://localhost:8080"10 #define DEFAULT_APPLICATION NULL11 #define DEFAULT_ENDPOINT NULL12 #define DEFAULT_MSG_COUNT 2013

14 const char * RealmService = DEFAULT_REALM_SERVICE;15 const char * Application = DEFAULT_APPLICATION;16 const char * Endpoint = DEFAULT_ENDPOINT;17 tibint64_t MsgCount = DEFAULT_MSG_COUNT;

Listing 8.2: ftlpub.c Part 1

To make the applications more generally useful, we will be moving away from hard-coding values directlyin the code, and instead allow values to be specified on the command line. A variable is provided for eachsuch value, and reasonable default values established via #define statements. This approach allows us tochange the values for different invocations of a program without having to modify the source code andrebuild the program.

Listing 8.2 shows the variables (and default values) for the FTL server URL, application name, endpointname, and number of messages to send.

TIBCO FTL R© Programming Tutorial

Page 52: TIBCO FTL R Programming Tutorial · 2018-11-28 · TIBCO FTL R Programming Tutorial. 4 Lesson 2: Understanding the Code In this lesson, we’ll examine the code used in lesson 1

47

19 const char * Options = "a:c:e:hr:";20

21 void print_usage(void)22 {23 fprintf(stderr,24 "Usage: ftlpub [options]\n"25 " -a APPLICATION set application name\n"26 " -c COUNT send COUNT data messages\n"27 " -e ENDPOINT set endpoint name\n"28 " -h print this help\n"29 " -r URL use realm service URL\n"30 );31 exit(1);32 }

Listing 8.3: ftlpub.c Part 2

The standard getopt() function is used to process command-line arguments. The application (-a),endpoint (-e), message count (-c), and FTL server (-r) can be specified on the command line.

63 int main(int argc, char** argv)64 {65 tibEx ex = NULL;66 tibRealm realm = NULL;67 tibPublisher pub = NULL;68 tibMessage msg = NULL;69 tibProperties props = NULL;70 tibint64_t idx;71

72 parse_arguments(argc, argv);73

74 ex = tibEx_Create();75 tib_Open(ex, TIB_COMPATIBILITY_VERSION);76 props = tibProperties_Create(ex);77 tibProperties_SetLong(ex, props, TIB_REALM_PROPERTY_LONG_CONNECT_RETRIES, 5);78 realm = tibRealm_Connect(ex, RealmService, Application, props);79 tibProperties_Destroy(ex, props);80

81 pub = tibPublisher_Create(ex, realm, Endpoint, NULL);82 CHECK(ex);

Listing 8.4: ftlpub.c Part 3

The beginning of main() hasn’t changed much. We start by parsing any arguments given on the commandline.

The remainder of Listing 8.4 is similar to what we have seen before. However, now we’re using a variablefor the FTL server rather than a string constant. Instead of passing NULL, variables are used for theapplication and endpoint names.

TIBCO FTL R© Programming Tutorial

Page 53: TIBCO FTL R Programming Tutorial · 2018-11-28 · TIBCO FTL R Programming Tutorial. 4 Lesson 2: Understanding the Code In this lesson, we’ll examine the code used in lesson 1

48

87 printf("using Realm Service=%s\n\tApplication=%s\n\tEndpoint=%s\n",88 RealmService,89 (Application != NULL ? Application : "default"),90 (Endpoint != NULL ? Endpoint : "default"));91 printf("sending initial message\n");92 fflush(stdout);93 tibMessage_SetString(ex, msg, FIELD_NAME_TAG, FIELD_TAG_CONTROL);94 tibMessage_SetString(ex, msg, FIELD_NAME_CONTENTS, "Initial message");95 tibMessage_SetLong(ex, msg, FIELD_NAME_COUNT, MsgCount);96 tibMessage_SetLong(ex, msg, FIELD_NAME_BOS, 1);97 tibPublisher_Send(ex, pub, msg);98 CHECK(ex);

Listing 8.5: ftlpub.c Part 4

In order to confirm the command-line options specified, the program prints the values used for the FTLserver URL, application, and endpoint. Next it builds the initial control message, which contains four fieldsas described in Section 8.1. The initial control message is sent and the exception object is checked.

100 tibMessage_SetString(ex, msg, FIELD_NAME_TAG, FIELD_TAG_DATA);101 tibMessage_ClearField(ex, msg, FIELD_NAME_COUNT);102 tibMessage_ClearField(ex, msg, FIELD_NAME_BOS);103 tibMessage_SetString(ex, msg, FIELD_NAME_CONTENTS, "Data message");

Listing 8.6: ftlpub.c Part 5

The next step is to set the fields required for the data messages. The "tag" field is set to the required valueusing the symbols defined for the purpose rather than hard-coded strings.

Notice that we didn’t have to create a new message; we are using the message that was originally created tosend the initial control message. This brings up an important concept:

Concept 6. A message object can be reused multiple times.

The "contents" field is set to a new value. You may recall that this field was set while building the initialcontrol message. This highlights another important concept about FTL messages:

Concept 7. Setting a field value overwrites any existing value within the message.

Because data messages do not contain the "count" or "bos" fields, those fields are explicitly cleared.Another important concept:

Concept 8. Clearing an existing field in a message sets its value to empty. When sending a message, FTLdoes not send empty fields.

Even though the "count" and "bos" fields exist in the message (since we explicitly set them earlier),clearing them marks those fields as empty, effectively removing them from the message.

TIBCO FTL R© Programming Tutorial

Page 54: TIBCO FTL R Programming Tutorial · 2018-11-28 · TIBCO FTL R Programming Tutorial. 4 Lesson 2: Understanding the Code In this lesson, we’ll examine the code used in lesson 1

49

108 for (idx = 1; idx <= MsgCount; ++idx)109 {110 tibMessage_SetLong(ex, msg, FIELD_NAME_SEQ, idx);111 if ((idx % 2) == 0)112 {113 tibMessage_SetLong(ex, msg, FIELD_NAME_EVEN, 1);114 }115 else116 {117 tibMessage_SetLong(ex, msg, FIELD_NAME_EVEN, 0);118 }119 tibPublisher_Send(ex, pub, msg);120 CHECK(ex);121 sleep(1);122 }

Listing 8.7: ftlpub.c Part 6

Listing 8.7 contains the code to build and send the data messages. First, the "seq" field is set to themessage number. Next the program sets the "even" field; to 1 if the message number is even, and to 0 if itis odd. This is not too useful now, but will be in upcoming lessons. Then the message is sent and theexception checked.

Notice that the loop code modifies only the "seq" and "even" fields of the message. The "tag" and"contents" fields remain the same in every data message.

Concept 9. When a message object is reused, fields that were previously set remain set to those values.

And one more important concept:

Concept 10. When reusing a message object, clear any fields which are no longer relevant.

Which is why the "count" and "bos" fields are cleared in Listing 8.6.

Note the sleep(1) call in line 121. This is purely for convenience, so that the publisher will run slowenough for us to easily see what it is doing. It is not recommended that your client programs do this — inalmost every case, you want things to run as fast as possible and send messages as soon as they are ready tobe sent.

124 printf("sending final message\n");125 fflush(stdout);126 tibMessage_ClearAllFields(ex, msg);127 tibMessage_SetString(ex, msg, FIELD_NAME_TAG, FIELD_TAG_CONTROL);128 tibMessage_SetString(ex, msg, FIELD_NAME_CONTENTS, "Final message");129 tibMessage_SetLong(ex, msg, FIELD_NAME_COUNT, MsgCount);130 tibMessage_SetLong(ex, msg, FIELD_NAME_EOS, 1);131 tibPublisher_Send(ex, pub, msg);132 CHECK(ex);

Listing 8.8: ftlpub.c Part 7

Next we build and send the final control message. Rather than clearing each individual field (usingtibMessage_ClearField()), we use tibMessage_ClearAllFields() to clear all fields in themessage.

TIBCO FTL R© Programming Tutorial

Page 55: TIBCO FTL R Programming Tutorial · 2018-11-28 · TIBCO FTL R Programming Tutorial. 4 Lesson 2: Understanding the Code In this lesson, we’ll examine the code used in lesson 1

50

134 tibMessage_Destroy(ex, msg);135 tibPublisher_Close(ex, pub);136

137 tibRealm_Close(ex, realm);138 tib_Close(ex);139 CHECK(ex);140 tibEx_Destroy(ex);

Listing 8.9: ftlpub.c Part 8

Finally, any FTL objects we created are destroyed, in the reverse order of their creation.

8.2.3 ftlsub.c

9 #define DEFAULT_REALM_SERVICE "http://localhost:8080"10 #define DEFAULT_APPLICATION NULL11 #define DEFAULT_ENDPOINT NULL12

13 const char * RealmService = DEFAULT_REALM_SERVICE;14 const char * Application = DEFAULT_APPLICATION;15 const char * Endpoint = DEFAULT_ENDPOINT;16 const char * Matcher = NULL;17 tibbool_t Verbose = tibfalse;

Listing 8.10: ftlsub.c Part 1

In a manner similar to that in the publisher, our latest version moves away from hard-coded values,

We declare variables for the FTL server, application name, endpoint name, and matcher string, eachinitialized to their default values. We also declare a Verbose variable to allow us to control the amount ofoutput at runtime.

19 tibbool_t Done = tibfalse;20 tibint64_t DataMsgsReceived = 0;21 tibint64_t ControlMsgsReceived = 0;22 tibint64_t ExpectedMsgCount = 0;

Listing 8.11: ftlsub.c Part 2

In Listing 8.11 we define variables to support our previously defined application-level protocol. Done isused to indicate when all messages have been received; counters are defined to keep track of the number ofdata and control messages received; and ExpectedMsgCount stores the number of data messages weexpect to receive (from the initial control message).

TIBCO FTL R© Programming Tutorial

Page 56: TIBCO FTL R Programming Tutorial · 2018-11-28 · TIBCO FTL R Programming Tutorial. 4 Lesson 2: Understanding the Code In this lesson, we’ll examine the code used in lesson 1

51

72 void onMessages(tibEx ex, tibEventQueue msgQueue, tibint32_t msgNum, tibMessage *msgs,73 void **closures)74 {75 tibint32_t i;76 char buffer[1024];77 static tibbool_t init_received = tibfalse;78 const char * type = NULL;79

80 for (i = 0; i < msgNum; i++)81 {82 if (Verbose)83 {84 printf("received message\n");85 (void)tibMessage_ToString(ex, msgs[i], buffer, sizeof(buffer));86 printf(" %s\n", buffer);87 fflush(stdout);88 }89 if (!tibMessage_IsFieldSet(ex, msgs[i], FIELD_NAME_TAG))90 {91 printf("%s field is not present in received message\n", FIELD_NAME_TAG);92 fflush(stdout);93 continue;94 }95 type = tibMessage_GetString(ex, msgs[i], FIELD_NAME_TAG);

Listing 8.12: ftlsub.c Part 3

The onMessages() function is a little more sophisticated than the one in ftlbasicsub.c used for thefirst six lessons, although the basic structure is the same. init_received is used to keep track of whetherthe first control message has been received (refer back to Section 8.1 for a description of the protocol).

The Verbose variable controls whether or not the full message is printed.

Before fetching the value of a field, it is good practice to ensure that the field exists. We do this beforeretrieving the value of the "tag" field from the message.

TIBCO FTL R© Programming Tutorial

Page 57: TIBCO FTL R Programming Tutorial · 2018-11-28 · TIBCO FTL R Programming Tutorial. 4 Lesson 2: Understanding the Code In this lesson, we’ll examine the code used in lesson 1

52

96 if (strcmp(type, FIELD_TAG_CONTROL) == 0)97 {98 ControlMsgsReceived++;99 if (init_received)

100 {101 /* Looking for eos */102 if (tibMessage_IsFieldSet(ex, msgs[i], FIELD_NAME_EOS))103 {104 printf("received EOS indicator\n");105 fflush(stdout);106 Done = tibtrue;107 }108 else109 {110 printf("received unexpected control message\n");111 fflush(stdout);112 }113 }114 else115 {116 /* looking for bos */117 if (tibMessage_IsFieldSet(ex, msgs[i], FIELD_NAME_BOS))118 {119 init_received = tibtrue;120 printf("received BOS indicator\n");121 fflush(stdout);122 ExpectedMsgCount = tibMessage_GetLong(ex, msgs[i], FIELD_NAME_COUNT);123 }124 else125 {126 printf("received unexpected control message\n");127 fflush(stdout);128 }129 }130 }

Listing 8.13: ftlsub.c Part 4

Control messages are handled in Listing 8.13. First the counter keeping track of the number of controlmessages received is updated. Next we check to see if the initialization control message (BOS) has alreadybeen received.

If so, the only control message we expect to see is the EOS message, so we check to see if the "eos" fieldis present. If it is present, print a message indicating so and set the Done flag to tibtrue. Otherwise printa message indicating we received an unexpected control message.

If init_received is not tibtrue, indicating we have not yet received the BOS control message, thencheck for the presence of the "bos" field. If the field is present, set the init_received flag to indicate aBOS has been received, print a message indicating so, and fetch the "count" field, which indicates howmany data messages are expected.

If a BOS has not been received, and the message does not contain the "bos" field, then we have receivedan unexpected control message; print a message indicating this has occurred.

TIBCO FTL R© Programming Tutorial

Page 58: TIBCO FTL R Programming Tutorial · 2018-11-28 · TIBCO FTL R Programming Tutorial. 4 Lesson 2: Understanding the Code In this lesson, we’ll examine the code used in lesson 1

53

131 else if (strcmp(type, FIELD_TAG_DATA) == 0)132 {133 DataMsgsReceived++;134 if (init_received)135 {136 if (Verbose)137 {138 if (tibMessage_IsFieldSet(ex, msgs[i], FIELD_NAME_SEQ))139 {140 tibint64_t seq = tibMessage_GetLong(ex, msgs[i], FIELD_NAME_SEQ);141 printf("received data seq %" PRId64"\n", seq);142 }143 else144 {145 printf("%s field not present in received message\n", FIELD_NAME_SEQ);146 }147 fflush(stdout);148 }149 }150 else151 {152 printf("received unexpected data message\n");153 fflush(stdout);154 }155 }

Listing 8.14: ftlsub.c Part 5

Listing 8.14 handles the receipt of data messages. First the counter keeping track of the number of datamessages received is updated. Based on how the protocol is designed, once we’ve received a BOS messagewe expect a series of data messages.

For a data message we extract and print the sequence number field, but only if the field exists and verboseoutput is enabled.

If a BOS message has not been previously received, then we have received an unexpected data message;print a message indicating this.

156 else157 {158 printf("received unexpected message\n");159 fflush(stdout);160 }

Listing 8.15: ftlsub.c Part 6

Listing 8.15 handles the situation in which the "tag" field contained an invalid value.

TIBCO FTL R© Programming Tutorial

Page 59: TIBCO FTL R Programming Tutorial · 2018-11-28 · TIBCO FTL R Programming Tutorial. 4 Lesson 2: Understanding the Code In this lesson, we’ll examine the code used in lesson 1

54

164 int main(int argc, char** argv)165 {166 tibEx ex = NULL;167 tibRealm realm = NULL;168 tibEventQueue queue = NULL;169 tibSubscriber sub = NULL;170 tibProperties props = NULL;171 tibContentMatcher cm = NULL;172

173 parse_arguments(argc, argv);174

175 ex = tibEx_Create();176 tib_Open(ex, TIB_COMPATIBILITY_VERSION);177 props = tibProperties_Create(ex);178 tibProperties_SetLong(ex, props, TIB_REALM_PROPERTY_LONG_CONNECT_RETRIES, 5);179 realm = tibRealm_Connect(ex, RealmService, Application, props);180 tibProperties_Destroy(ex, props);181

182 if (Matcher != NULL)183 {184 cm = tibContentMatcher_Create(ex, realm, Matcher);185 CHECK(ex);186 }187 sub = tibSubscriber_Create(ex, realm, Endpoint, cm, NULL);188 if (cm != NULL)189 {190 tibContentMatcher_Destroy(ex, cm);191 }192 queue = tibEventQueue_Create(ex, realm, NULL);193 tibEventQueue_AddSubscriber(ex, queue, sub, onMessages, NULL);194 CHECK(ex);

Listing 8.16: ftlsub.c Part 7

main() accesses and parses the command line arguments as well as declaring some of the basic FTLobjects needed in the same manner as earlier sample code.

An FTL exception object is created, but now the call to tibRealm_Connect() passes a variable for theFTL server instead of a string constant, as well as passing a variable for the application name instead ofNULL (forcing the use of the default application).

The calls to create a matcher, subscriber, and event queue should look familiar, except that a variable ispassed to tibSubscriber_Create() for the endpoint name instead of NULL.

Notice that the matcher, if created, is destroyed immediately after the call to tibSubscriber_Create().It is good practice to destroy objects when they are no longer needed.

TIBCO FTL R© Programming Tutorial

Page 60: TIBCO FTL R Programming Tutorial · 2018-11-28 · TIBCO FTL R Programming Tutorial. 4 Lesson 2: Understanding the Code In this lesson, we’ll examine the code used in lesson 1

55

192 printf("using Realm Service=%s\n\tApplication=%s\n\tEndpoint=%s\n\tMatcher=%s\n",193 RealmService,194 (Application != NULL ? Application : "default"),195 (Endpoint != NULL ? Endpoint : "default"),196 (Matcher != NULL ? Matcher: "none"));197 printf("waiting for message(s)\n");198 fflush(stdout);199 do200 {201 tibEventQueue_Dispatch(ex, queue, TIB_TIMEOUT_WAIT_FOREVER);202 } while (!Done && tibEx_GetErrorCode(ex) == TIB_OK);203

204 printf("Received %" PRId64 " control, and %" PRId64 " of %" PRId64 " data messages.\n",205 ControlMsgsReceived, DataMsgsReceived, ExpectedMsgCount);206 fflush(stdout);207 tibEventQueue_RemoveSubscriber(ex, queue, sub, NULL);208 tibEventQueue_Destroy(ex, queue, NULL);209 tibSubscriber_Close(ex, sub);210

211 tibRealm_Close(ex, realm);212 tib_Close(ex);213 CHECK(ex);214 tibEx_Destroy(ex);

Listing 8.17: ftlsub.c Part 8

As in ftlpub.c, the command-line option values being used are printed. You’ll also recognize thedispatch loop as it has not changed from our earlier samples. After all messages have been received fromthe publisher, the number of control and data messages received are printed. Finally, the usual cleanupactions are performed.

8.3 Build and Run the Sample Applications

To build and run the sample applications, make sure the FTL server is running and open a commandwindow. Assuming you have set the TIBFTL_DIR environment variable, navigate to$TIBFTL_TUTDIR/code/lesson-08, build the samples, and start the subscriber:

make./ftlsub

In another command window, navigate to $TIBFTL_TUTDIR/code/lesson-08 and start the publisher:

./ftlpub

You should see the following output from the publisher:

using Realm Service=http://localhost:8080Application=defaultEndpoint=default

sending initial messagesending 20 data messagessending final message

Listing 8.18: ftlpub output

As expected, ftlpub sent the inital control message (BOS), sent 20 data messages (the default number),and send the final control message (EOS).

TIBCO FTL R© Programming Tutorial

Page 61: TIBCO FTL R Programming Tutorial · 2018-11-28 · TIBCO FTL R Programming Tutorial. 4 Lesson 2: Understanding the Code In this lesson, we’ll examine the code used in lesson 1

56

The output in the subscriber command window should appear as:

using Realm Service=http://localhost:8080Application=defaultEndpoint=defaultMatcher=none

waiting for message(s)received BOS indicatorreceived EOS indicatorReceived 2 control, and 20 of 20 data messages.

Listing 8.19: ftlsub output

Both programs appear to be operating correctly.

Now try running the subscriber with the -v option. In the subscriber command window, restart thesubscriber:

./ftlsub -v

In the publisher command window, restart the publisher but only send five messages:

./ftlpub -c 5

The output from ftlpub is the same as the first time, but the output from ftlsub includes moreinformation:

using Realm Service=http://localhost:8080Application=defaultEndpoint=defaultMatcher=none

waiting for message(s)received message

{string:tag="control", string:contents="Initial message", long:count=5, long:bos=1}received BOS indicatorreceived message

{string:tag="data", string:contents="Data message", long:seq=1, long:even=0}received data seq 1received message

{string:tag="data", string:contents="Data message", long:seq=2, long:even=1}received data seq 2received message

{string:tag="data", string:contents="Data message", long:seq=3, long:even=0}received data seq 3received message

{string:tag="data", string:contents="Data message", long:seq=4, long:even=1}received data seq 4received message

{string:tag="data", string:contents="Data message", long:seq=5, long:even=0}received data seq 5received message

{string:tag="control", string:contents="Final message", long:count=5, long:eos=1}received EOS indicatorReceived 2 control, and 5 of 5 data messages.

Listing 8.20: ftlsub -v output

As a final test, let’s run the applications with different application and endpoint names. Specifically, we’lluse the “App1” application and “endpoint-1” endpoint we created in lesson 7 for both ftlpub and ftlsub.

TIBCO FTL R© Programming Tutorial

Page 62: TIBCO FTL R Programming Tutorial · 2018-11-28 · TIBCO FTL R Programming Tutorial. 4 Lesson 2: Understanding the Code In this lesson, we’ll examine the code used in lesson 1

57

In the subscriber command window, start the subscriber with the options needed to set the application andendpoint:

./ftlsub -a App1 -e endpoint-1

In the publisher command window, start the publisher with the same options:

./ftlpub -a App1 -e endpoint-1

The resulting output from the publisher reflects the changed application and endpoint names:

using Realm Service=http://localhost:8080Application=App1Endpoint=endpoint-1

sending initial messagesending 20 data messagessending final message

Listing 8.21: ftlpub -a App1 -e endpoint-1 output

As does the subscriber output:

using Realm Service=http://localhost:8080Application=App1Endpoint=endpoint-1Matcher=none

waiting for message(s)received BOS indicatorreceived EOS indicatorReceived 2 control, and 20 of 20 data messages.

Listing 8.22: ftlsub -a App1 -e endpoint-1 output

8.4 Order Matters

Up to this point, we’ve always run the subscriber application first, and the publisher application second.This time we’ll run the publisher first.

In the publisher command window start the publisher:

./ftlpub

The resulting output is:

using Realm Service=http://localhost:8080Application=defaultEndpoint=default

sending initial messagesending 20 data messagessending final message

Listing 8.23: ftlpub output

TIBCO FTL R© Programming Tutorial

Page 63: TIBCO FTL R Programming Tutorial · 2018-11-28 · TIBCO FTL R Programming Tutorial. 4 Lesson 2: Understanding the Code In this lesson, we’ll examine the code used in lesson 1

58

The publisher reports that it sent all messages successfully, but we haven’t run the subscriber yet. Let’sstart the subscriber and see what it receives. In the subscriber command window:

./ftlsub

The resulting output is familiar up to a point:

using Realm Service=http://localhost:8080Application=defaultEndpoint=defaultMatcher=none

waiting for message(s)

Listing 8.24: ftlsub output

It seems as if the subscriber is waiting for messages but not receiving any. After all, the messages it wasexpecting to receive have already been sent by the publisher. This is an important idea in FTL messagingsystems:

Concept 11. At the application level, publishers and subscribers are completely independent (looselycoupled). Publishers are unaware of the presence (or absence, or even the number) of subscribers.

So a publisher will send messages regardless of whether or not subscribers exist; more precisely, a send cansucceed whether or not subscribers exist. Obviously, subscribers are indirectly aware of the presence orabsence of publishers by virtue of messages being received (or not received). Subscribers can subscribe toendpoints even when no publisher is sending on the corresponding endpoint.

It is important to note that this independence is at the application level. No claims are made regardingindependence at the transport level.

The independence of publishers and subscribers does not mean that the model of publisher/subscriberawareness is invalid. There may be situations in which the approach of publishers only sending messages ifsubscribers are available to consume them is a valid problem approach. However, special application logicis required to synchronize publishers and subscribers if this type of behavior is required.

Make sure you stop the subscriber via ctrl + C before continuing to the next section.

8.5 Clients

To get this part of the lesson started, start the subscriber using application “App1” and the proper endpoint:

./ftlsub -a App1 -e endpoint-1

Restart the publisher using application “App1” and the proper endpoint; but for this part of the lesson weneed the publisher to run for a much longer period of time, so tell it to send 1000 messages:

./ftlpub -c 1000 -a App1 -e endpoint-1

Open a web browser and navigate to the URL http://localhost:8080. If the FTL server login page isdisplayed, login as you did in Section 6.1, page 27. Bring up the Applications grid by clicking on thelink on the left side of the screen.

TIBCO FTL R© Programming Tutorial

Page 64: TIBCO FTL R Programming Tutorial · 2018-11-28 · TIBCO FTL R Programming Tutorial. 4 Lesson 2: Understanding the Code In this lesson, we’ll examine the code used in lesson 1

59

Figure 8.1: Applications grid

Note the changes in the top line of the display:

Figure 8.2: Status Detail

In previous lessons, the number above “Clients” was 0. Now we have started two client programs, ftlsuband ftlpub. The information in this display indicates the actual number of active client programs.

Clicking anywhere in this area of the screen will display the Status Dashboard. The dashboard slides downto reveal a status table which gives more specific counts on running client programs and services as shownin Figure 8.3.

TIBCO FTL R© Programming Tutorial

Page 65: TIBCO FTL R Programming Tutorial · 2018-11-28 · TIBCO FTL R Programming Tutorial. 4 Lesson 2: Understanding the Code In this lesson, we’ll examine the code used in lesson 1

60

Figure 8.3: Status Dashboard

The dashboard shows there are currently two clients running. All categories to the right of “Clients” areconsidered FTL Services and are included in the count of services shown at the top of the screen.

Each category can be clicked on to display information about the known FTL programs in that category.Click “Clients” in the dashboard to display client information, as shown in Figure 8.4.

It is important to note that the Status Dashboard and the more detailed status displays are not a separatepage: they appear over any page in the user interface without affecting the page underneath. Status can beshown at any time and at any place in the realm service web interface without impacting the informationdisplayed underneath.

TIBCO FTL R© Programming Tutorial

Page 66: TIBCO FTL R Programming Tutorial · 2018-11-28 · TIBCO FTL R Programming Tutorial. 4 Lesson 2: Understanding the Code In this lesson, we’ll examine the code used in lesson 1

61

Figure 8.4: Client Status Display

A row of summary information is displayed for each client. The information shown for each clientincludes:

• “Status”, representing the current status of the client (Running, Timed Out, etc.).

• “Client Label”, which will be discussed in lesson 9.

• “ID”, a unique ID assigned to each client by the realm service.

• “Host”, the machine on which the client is running.

• “Application”, the application name used by the client.

• “Instance”, the application instance used by the client. Instances are discussed in a later lesson.

• “Core Server”, the realm service to which the client application initially connected.

At the right end of each row are three icons which allow control of the client program:

Change the client’s logging level

Change the client’s monitoring mode

Disable the client

Clicking anywhere in the first client row will show additional information about that specific client:

TIBCO FTL R© Programming Tutorial

Page 67: TIBCO FTL R Programming Tutorial · 2018-11-28 · TIBCO FTL R Programming Tutorial. 4 Lesson 2: Understanding the Code In this lesson, we’ll examine the code used in lesson 1

62

Figure 8.5: Client Detail

Details about the client are displayed in a scrolling area. Each section is initially hidden but can be revealedby clicking the icon to the left of the section title. On the right side of the client information is a seriesof shortcuts to specific client details, organized into functional groups: Figure 8.5 shows “ClientInformation”, “Application”, “Endpoint”, “Queues”, “Recent Advisories”, “Recent Logs”, and “Transport”.You can scroll through the various sections, or use the shortcuts to jump directly to a specific section.

Click the icon to the left of “Client Information” section to display additional details related to thisclient:

TIBCO FTL R© Programming Tutorial

Page 68: TIBCO FTL R Programming Tutorial · 2018-11-28 · TIBCO FTL R Programming Tutorial. 4 Lesson 2: Understanding the Code In this lesson, we’ll examine the code used in lesson 1

63

Figure 8.6: Client Detail Continued

In later lessons, we will cover the various metrics displayed, along with monitoring in general.

8.6 Identifying Clients

Looking back at Figure 8.5, page 62, which client program is being displayed? We were running both apublisher and a subscriber, but which one is this? Referring back to Figure 8.4, page 61, which of the twoclients is the publisher and which is the subscriber?

Unfortunately, there is no readily apparent way to determine which client is the publisher and which is thesubscriber.

The recommended way to identify clients is through the use of properties, which is covered in the nextlesson.

TIBCO FTL R© Programming Tutorial

Page 69: TIBCO FTL R Programming Tutorial · 2018-11-28 · TIBCO FTL R Programming Tutorial. 4 Lesson 2: Understanding the Code In this lesson, we’ll examine the code used in lesson 1

64

Lesson 9: Properties

A properties object (tibProperties) represents a set of configuration name/value pairs. Properties areused when creating or initializing objects, allowing additional control over an object’s configuration.

Properties can be used with realms, publishers, subscribers, event queues, and various other objects.

9.1 The Properties API

Each property consists of a character string name and a value.

Six types are supported for a property value:

• Boolean

• 32-bit signed integer

• 64-bit signed integer

• Double precision floating-point

• String

• Message (tibMessage).

9.1.1 FTL API Functions to Create and Destroy Properties

tibProperties tibProperties_Create(tibEx e);void tibProperties_Destroy(tibEx e, tibProperties properties);

As with other FTL objects, a properties object must be created before use and should be destroyed when itis no longer needed. tibProperties_Create() is used to create a properties object, andtibProperties_Destroy() destroys a properties object.

9.1.2 FTL API Functions to Set Property Values

void tibProperties_SetBoolean(tibEx e, tibProperties properties, const char* name,tibbool_t value);

void tibProperties_SetInt(tibEx e, tibProperties properties, const char* name, tibint32_t value);void tibProperties_SetLong(tibEx e, tibProperties properties, const char* name,

tibint64_t value);void tibProperties_SetString(tibEx e, tibProperties properties, const char* name,

const char* value);void tibProperties_SetMessage(tibEx e, tibProperties properties, const char* name,

const tibMessage value);void tibProperties_SetDouble(tibEx e, tibProperties properties, const char* name,

tibdouble_t value);

Six functions are provided to set property values, one for each supported value type. Each takes anexception (tibEx) object as the first argument, the properties (tibProperties) object on which to

TIBCO FTL R© Programming Tutorial

Page 70: TIBCO FTL R Programming Tutorial · 2018-11-28 · TIBCO FTL R Programming Tutorial. 4 Lesson 2: Understanding the Code In this lesson, we’ll examine the code used in lesson 1

65

operate as the second argument, and a string containing the property name as the third argument. The finalargument is the value to be set for the property.

9.1.3 FTL API Functions to Get Property Values

tibbool_t tibProperties_GetBoolean(tibEx e, tibProperties properties, const char* name);tibint32_t tibProperties_GetInt(tibEx e, tibProperties properties, const char* name);tibint64_t tibProperties_GetLong(tibEx e, tibProperties properties, const char* name);const char* tibProperties_GetString(tibEx e, tibProperties properties, const char* name);const tibMessage tibProperties_GetMessage(tibEx e, tibProperties properties, const char* name);tibdouble_t tibProperties_GetDouble(tibEx e, tibProperties properties, const char* name);

Corresponding to each FTL API function to set a property value is a function to get a property value. Eachtakes an exception (tibEx) object as the first argument, the properties (tibProperties) object on whichto operate as the second argument, and a string containing the property name to fetch as the third argument.Each returns the value as the proper type.

9.1.4 FTL API Property Utility Functions

tibbool_t tibProperties_Exists(tibEx e, tibProperties properties, const char* name);tibbool_t tibProperties_Remove(tibEx e, tibProperties properties, const char* name);tibProperties tibProperties_Copy(tibEx e, tibProperties properties);

tibProperties_Exists() allows the existence of a specific name within a properties object to betested, and tibProperties_Remove() removes an individual name from a properties object. Each takesan exception (tibEx) object as the first argument, the properties (tibProperties) object on which tooperate as the second argument, and a string containing the property name to test for or remove as the thirdargument.

tibProperties_Copy() can be used to duplicate a properties object, returning a new tibProperties

object which contains the same name/value pairs as the original object.

9.2 Property Names

Valid property names are defined in several header files provided with the FTL distribution, located in$TIBFTL_DIR/include/ftl. Realm property names are defined in realm.h, publisher property namesin pub.h, subscriber property names in sub.h, and event queue property names in queue.h.

All property name symbols are of the form TIB_obj_PROPERTY_type_name. obj denotes the FTLobject to which the property applies, and is one of REALM, PUBLISHER, SUBSCRIBER, or EVENTQUEUE.type denotes the data type of the property value, and is one of BOOL, INT, LONG, STRING, DOUBLE, orBOOLEAN. name denotes the property name.

Note that this naming convention applies only to the property name symbols defined in the header files. Theproperty names themselves do not follow the same conventions. Property names may change, but theproperty name symbols will not. For compatibility with future versions of FTL only the symbol namesshould be used.

While there are dozens of properties, for now we will discuss only a few of them.

TIBCO FTL R© Programming Tutorial

Page 71: TIBCO FTL R Programming Tutorial · 2018-11-28 · TIBCO FTL R Programming Tutorial. 4 Lesson 2: Understanding the Code In this lesson, we’ll examine the code used in lesson 1

66

9.2.1 Realm Connect Maximum Retries

The realm connect maximum retries property (TIB_REALM_PROPERTY_LONG_CONNECT_RETRIES) is along realm property which determines how many attempts are made to connect to a realm service. Itdefaults to zero, which indicates to retry forever.

We made use of this property in the sample programs: without it, if the FTL server is not running, the callto tibRealm_Connect() would never return to indicate an error.

9.2.2 Realm Connect Interval

The realm connect interval property (TIB_REALM_PROPERTY_DOUBLE_CONNECT_INTERVAL) is a doublerealm property which determines how long to wait between connect attempts to a realm service. It defaultsto 1.0 seconds.

9.2.3 Publisher Release Ownership of Messages Property

The publisher release ownership of messages property(TIB_PUBLISHER_PROPERTY_BOOL_RELEASE_MSGS_TO_SEND) is a boolean publisher property whichcontrols ownership of message objects sent through a publisher. It defaults to tibfalse, in which case theclient program retains ownership of messages.

If set to tibtrue, the FTL library takes ownership of messages sent through this publisher whentibPublisher_Send() is called. From that point forward, the client program must no longer referencethe tibMessage object, including calling tibMessage_Destroy(). The FTL library could destroy themessage object at any time.

Lesson 4 presented the concept that a client program is responsible for destroying a message it creates, andit was noted that lesson 9 would cover the single exception. This is the exception: if the FTL library isgiven ownership of the message by virtue of theTIB_PUBLISHER_PROPERTY_BOOL_RELEASE_MSGS_TO_SEND property, the client program must notdestroy the message.

Recall from lesson 8, ftlpub.c reuses the message object it created. This approach worked because thedefault value for the publisher release property is tibfalse, and the code did not explicitly set theproperty, meaning the client program retained ownership of the message object after thetibPublisher_Send() call. An important concept noted at the time (Concept 6, page 48) was that amessage could be reused.

At this point we need to slightly amend that concept:

Concept 6. (Revised) A message object can be reused multiple times as long as the client program retainsownership of the message object.

9.2.4 Client Label Property

The client label property (TIB_REALM_PROPERTY_STRING_CLIENT_LABEL) is a string realm propertywhich sets the client label for a client program. Its primary purpose is to help distinguish one clientprogram from another (or one instance of a given client program from another) in monitoring, including theFTL server monitoring displays, essentially allowing you to name the role a client program plays.

Monitoring is covered in depth in a future lesson.

TIBCO FTL R© Programming Tutorial

Page 72: TIBCO FTL R Programming Tutorial · 2018-11-28 · TIBCO FTL R Programming Tutorial. 4 Lesson 2: Understanding the Code In this lesson, we’ll examine the code used in lesson 1

67

It is highly recommended that this property be set for all client programs. Set it using a convention thathelps you distinguish clients in the ways that are imporant to your enterprise — whether by role, byprogram name, by unique identity, or any combination of identifying information.

9.3 Using Properties

The modified versions of ftlpub.c and ftlsub.c, which include support for FTL properties, can befound in $TIBFTL_TUTDIR/code/lesson-09. Rather than look at the entire programs in detail, we’llfocus on the modifications made to support FTL properties.

9.3.1 ftlpub.c

9 #define DEFAULT_REALM_SERVICE "http://localhost:8080"10 #define DEFAULT_APPLICATION NULL11 #define DEFAULT_ENDPOINT NULL12 #define DEFAULT_CLIENTLABEL "tibpub"13 #define DEFAULT_MSG_COUNT 2014

15 const char * RealmService = DEFAULT_REALM_SERVICE;16 const char * Application = DEFAULT_APPLICATION;17 const char * Endpoint = DEFAULT_ENDPOINT;18 const char * ClientLabel = DEFAULT_CLIENTLABEL;19 tibint64_t MsgCount = DEFAULT_MSG_COUNT;

Listing 9.1: ftlpub.c Part 1

We’ve added a default value for the client label property, and a variable for the client label, with the intentof allowing it to be set from the command line.

21 const char * Options = "a:c:e:hl:r:";22

23 void print_usage(void)24 {25 fprintf(stderr,26 "Usage: ftlpub [options]\n"27 " -a APPLICATION set application name\n"28 " -c COUNT send COUNT data messages\n"29 " -e ENDPOINT set endpoint name\n"30 " -h print this help\n"31 " -l CLIENTLABEL set the client label\n"32 " -r URL use realm service URL\n"33 );34 exit(1);35 }

Listing 9.2: ftlpub.c Part 2

One new command-line argument is added: -l sets the client label. parse_arguments() has also beenextended to handle the new argument, and we’ve added it to the usage message as well.

TIBCO FTL R© Programming Tutorial

Page 73: TIBCO FTL R Programming Tutorial · 2018-11-28 · TIBCO FTL R Programming Tutorial. 4 Lesson 2: Understanding the Code In this lesson, we’ll examine the code used in lesson 1

68

69 int main(int argc, char** argv)70 {71 tibEx ex = NULL;72 tibRealm realm = NULL;73 tibPublisher pub = NULL;74 tibMessage msg = NULL;75 tibProperties props = NULL;76 tibint64_t idx;

Listing 9.3: ftlpub.c Part 3

main() now defines a tibProperties variable for creating the properties object.

83 props = tibProperties_Create(ex);84 tibProperties_SetString(ex, props, TIB_REALM_PROPERTY_STRING_CLIENT_LABEL, ClientLabel);85 realm = tibRealm_Connect(ex, RealmService, Application, props);86 CHECK(ex);87 tibProperties_Destroy(ex, props);

Listing 9.4: ftlpub.c Part 4

We’ve added code to create the properties and set the string propertyTIB_REALM_PROPERTY_STRING_CLIENT_LABEL. The properties object is passed as the last argument totibRealm_Connect(); previously a NULL had been specified here. Finally, the properties object isdestroyed when no longer needed.

95 printf("using Realm Service=%s\n\tApplication=%s\n\tEndpoint=%s\n\tClientLabel=%s\n",96 RealmService,97 (Application != NULL ? Application : "default"),98 (Endpoint != NULL ? Endpoint : "default"),99 ClientLabel);

Listing 9.5: ftlpub.c Part 5

We’ll also expand the output message to include the client label, so we can see that information at run time.

9.3.2 ftlsub.c

The changes made to ftlsub.c parallel those made to ftlpub.c.

9 #define DEFAULT_REALM_SERVICE "http://localhost:8080"10 #define DEFAULT_APPLICATION NULL11 #define DEFAULT_ENDPOINT NULL12 #define DEFAULT_CLIENTLABEL "tibsub"13

14 const char * RealmService = DEFAULT_REALM_SERVICE;15 const char * Application = DEFAULT_APPLICATION;16 const char * Endpoint = DEFAULT_ENDPOINT;17 const char * Matcher = NULL;18 tibbool_t Verbose = tibfalse;19 const char * ClientLabel = DEFAULT_CLIENTLABEL;

Listing 9.6: ftlsub.c Part 1

TIBCO FTL R© Programming Tutorial

Page 74: TIBCO FTL R Programming Tutorial · 2018-11-28 · TIBCO FTL R Programming Tutorial. 4 Lesson 2: Understanding the Code In this lesson, we’ll examine the code used in lesson 1

69

We add a default value and variable for the client label property.

26 const char * Options = "a:e:hl:m:r:v";27

28 void print_usage(void)29 {30 fprintf(stderr,31 "Usage: ftlsub [options]\n"32 " -a APPLICATION set application name\n"33 " -e ENDPOINT set endpoint name\n"34 " -h print this help\n"35 " -l CLIENTLABEL set the client label\n"36 " -m CONTENT use matcher\n"37 " -r URL use realm service URL\n"38 " -v verbose output\n"39 );40 exit(1);41 }

Listing 9.7: ftlsub.c Part 2

We have made the same changes to the command-line parsing code to handle the client label options.

170 int main(int argc, char** argv)171 {172 tibEx ex = NULL;173 tibRealm realm = NULL;174 tibEventQueue queue = NULL;175 tibSubscriber sub = NULL;176 tibContentMatcher cm = NULL;177 tibProperties props = NULL;

Listing 9.8: ftlsub.c Part 3

We define a new tibProperties variable for creating the properties object.

184 props = tibProperties_Create(ex);185 tibProperties_SetString(ex, props, TIB_REALM_PROPERTY_STRING_CLIENT_LABEL, ClientLabel);186 realm = tibRealm_Connect(ex, RealmService, Application, props);187 CHECK(ex);188 tibProperties_Destroy(ex, props);

Listing 9.9: ftlsub.c Part 4

The same changes are made (as in ftlpub.c) to create the properties object, set its value, pass it to thetibRealm_Connect() call, then destroy it when no longer needed.

204 printf("using Realm Service=%s\n\tApplication=%s\n\tEndpoint=%s\n\tMatcher=%s\n\tClientLabel=%s\n",

205 RealmService,206 (Application != NULL ? Application : "default"),207 (Endpoint != NULL ? Endpoint : "default"),208 (Matcher != NULL ? Matcher : "none"),209 ClientLabel);

Listing 9.10: ftlsub.c Part 5

TIBCO FTL R© Programming Tutorial

Page 75: TIBCO FTL R Programming Tutorial · 2018-11-28 · TIBCO FTL R Programming Tutorial. 4 Lesson 2: Understanding the Code In this lesson, we’ll examine the code used in lesson 1

70

Finally, we add the client label to the program output so we can see the client label used.

9.4 Build and Run the Samples

To build and run the samples, make sure the Realm Server is running, and open a command window.Navigate to $TIBFTL_TUTDIR/code/lesson-09, rebuild the samples, and run the subscriber:

make./ftlsub

In another command window, navigate to $TIBFTL_TUTDIR/code/lesson-09 and run the publisher:

./ftlpub

The output from ftlpub should be familiar, with the addition of the new client label information:

using Realm Service=http://localhost:8080Application=defaultEndpoint=defaultClientLabel=tibpub

sending initial messagesending 20 data messagessending final message

Listing 9.11: ftlpub output

The output from ftlsub should also include the new client label information:

using Realm Service=http://localhost:8080Application=defaultEndpoint=defaultMatcher=noneClientLabel=tibsub

waiting for message(s)received BOS indicatorreceived EOS indicatorReceived 2 control, and 20 of 20 data messages.

Listing 9.12: ftlsub output

The output from both is as expected. The default application, endpoint, and client label values are being setand used.

9.5 Identifying Clients Revisited

In lesson 8 (Section 8.6, page 63), we looked at the Client Details in the realm service web interface, notingthat at that point there was no way to distinguish the publisher client from the subscriber client. The use ofthe client label property (TIB_REALM_PROPERTY_STRING_CLIENT_LABEL) provides a solution to thisproblem.

In the subscriber command window, start the subscriber with client label “subscriber”:

TIBCO FTL R© Programming Tutorial

Page 76: TIBCO FTL R Programming Tutorial · 2018-11-28 · TIBCO FTL R Programming Tutorial. 4 Lesson 2: Understanding the Code In this lesson, we’ll examine the code used in lesson 1

71

./ftlsub -l subscriber

In the publisher command window, start the publisher with the client label “publisher”, and have it send100 messages:

./ftlpub -c 100 -l publisher

Now it’s time to see what the monitoring information looks like now that we’ve added client label support.Open a web browser and navigate to the URL http://localhost:8080. If the FTL server login page isdisplayed, login as you did in Section 6.1, page 27. Bring up the Applications grid by clicking on thelink on the left side of the screen.

Figure 9.1: Applications grid

Click anywhere in the status area at the top of the page to show the Status Dashboard:

TIBCO FTL R© Programming Tutorial

Page 77: TIBCO FTL R Programming Tutorial · 2018-11-28 · TIBCO FTL R Programming Tutorial. 4 Lesson 2: Understanding the Code In this lesson, we’ll examine the code used in lesson 1

72

Figure 9.2: Status Dashboard

Click “Clients” to display client information:

Figure 9.3: Client Status Display

We are now able to easily identify each client by the value under “Client Label”.

TIBCO FTL R© Programming Tutorial

Page 78: TIBCO FTL R Programming Tutorial · 2018-11-28 · TIBCO FTL R Programming Tutorial. 4 Lesson 2: Understanding the Code In this lesson, we’ll examine the code used in lesson 1

73

Lesson 10: Client Metrics

The realm service web interface makes available metrics as reported by each client program. In this lessonwe’ll look at some of the metrics available.

Before looking at the metrics, a basic understanding of the communication between a client and the FTLserver is needed.

10.1 Client-Realm Server Communication

The connection between a client program and the realm service is established by thetibRealm_Connect() call. Once connected, basic identifying information is exchanged, and the realmservice sends the realm definition to the client program. Next the client program sends a HELLO messageto the realm service, containing additional identifying information. At this point the client programinformation appears in the realm service’s list of clients (see Figure 9.3, page 72 for an example).

While the client program is running, the realm service periodically sends heartbeat messages to the clientprogram. In a similar manner, the client program periodically sends heartbeat messages to the realmservice. Any metrics gathered since the last heartbeat message sent to the realm service are included.

A client program’s call to tibRealm_Close() sends a GOODBYE message to the realm service, whichcauses the realm service to remove that client from its list of clients. The connection to the realm service isthen closed.

A client program that abnormally terminates (such as via ctrl + C or a fatal error) does not send aGOODBYE message. Instead it is subject to timeouts based on the absence of heartbeat messages beforebeing removed from the realm service’s list of clients.

The frequency at which heartbeat messages are sent by either side is determined by the realm properties,which are part of the realm definition. Let’s take a look at these properties.

Ensure the FTL server is still running, open a web browser, and navigate to the URLhttp://localhost:8080. If the realm service login page is displayed, login as you did in Section 6.1,page 27. Bring up the Applications grid by clicking on the link on the left side of the screen.

TIBCO FTL R© Programming Tutorial

Page 79: TIBCO FTL R Programming Tutorial · 2018-11-28 · TIBCO FTL R Programming Tutorial. 4 Lesson 2: Understanding the Code In this lesson, we’ll examine the code used in lesson 1

74

Figure 10.1: Applications grid

Along the left side of the screen, the link denoted by the icon and labeled “Realm Properties” displaysthe Realm Properties page. Click it, resulting in a display similar to Figure 10.2.

Figure 10.2: Realm Properties page

We’re interested in the information in the “Intervals” box. Under “Client→ Realm Server”, “Heartbeat”controls how often the client program sends a heartbeat message to the FTL server, while “Timeout”

TIBCO FTL R© Programming Tutorial

Page 80: TIBCO FTL R Programming Tutorial · 2018-11-28 · TIBCO FTL R Programming Tutorial. 4 Lesson 2: Understanding the Code In this lesson, we’ll examine the code used in lesson 1

75

determines how much time can pass without the FTL server receiving a heartbeat message from a clientbefore the FTL server removes that client from its list of clients.

Under “Realm Server→ Client”, “Hearbeat” controls how often the FTL server sends a heartbeat messageto all client programs, while “Timeout” determines how much time can pass without the client receiving aheartbeat message from the FTL server before the client attempts to reconnect to the FTL server.

Under “Client Statistics Sampling”, “Client Sampling Interval” controls how often the client programgathers its metrics into a timestamped sample. If “Client Sampling Interval” is smaller than the “Client→Realm Server” heartbeat interval, each heartbeat message sent to the FTL server may contain more thanone sample.

10.2 Run the Samples

In order to look at the client metrics, let’s run the sample client programs from lesson 9. Open a commandwindow, navigate to the $TIBFTL_TUTDIR/code/lesson-09 directory, and start the subscriber. We’llspecify that application “App1” and endpoint “endpoint-1” be used:

./ftlsub -a App1 -e endpoint-1

In another command window, navigate to the same directory and start the publisher. Specify the sameapplication and endpoint names. We’ll also instruct the publisher to send 10000 messages; this will give ussufficient time to look at the metrics.

./ftlpub -a App1 -e endpoint-1 -c 10000

10.3 Examine the Metrics

In the open web browser (which should still be on the Realm Properties page as shown in Figure 10.2), thestatus area should show two active clients. Click anywhere in the status area to expose the StatusDashboard:

TIBCO FTL R© Programming Tutorial

Page 81: TIBCO FTL R Programming Tutorial · 2018-11-28 · TIBCO FTL R Programming Tutorial. 4 Lesson 2: Understanding the Code In this lesson, we’ll examine the code used in lesson 1

76

Figure 10.3: Status Dashboard

Click the “Clients” count:

Figure 10.4: Client Status Display

Click anywhere in the row for the subscriber, with the “Client Label” “tibsub”:

TIBCO FTL R© Programming Tutorial

Page 82: TIBCO FTL R Programming Tutorial · 2018-11-28 · TIBCO FTL R Programming Tutorial. 4 Lesson 2: Understanding the Code In this lesson, we’ll examine the code used in lesson 1

77

Figure 10.5: Subscriber Details

Metrics are divided into categories. In Figure 10.5, seven categories are shown, each corresponding to oneof the links on the right side: “Client Information”, “Application”, “Endpoint”, “Queues”, “RecentAdvisories”, “Recent Logs”, and “Transport”.

Note that some of these categories will not appear until a heartbeat message containing the client metrics isreceived by the realm service. Since the default client heartbeat interval (as shown in Figure 10.2) is 60seconds, it may take that long before the categories are displayed on your screen.

Expand the “Application” section (by clicking the icon to the left of it) to display the applicationmetrics:

TIBCO FTL R© Programming Tutorial

Page 83: TIBCO FTL R Programming Tutorial · 2018-11-28 · TIBCO FTL R Programming Tutorial. 4 Lesson 2: Understanding the Code In this lesson, we’ll examine the code used in lesson 1

78

Figure 10.6: Subscriber Application metrics

Each metrics category contains one or more rows of metric data. Each row is identified by the context itbelongs to; the context name appears under the “Name” column. A context defines a particular instance ofthe category, and its name is established when the corresponding object is instantiated.

Application metrics pertain to the client application as a whole. Thus it makes sense that there is a singlecontext in the “Application” category. The corresponding context name is exactly the application namepassed to tibRealm_Connect(). As an example, refer back to line 75 of Listing 8.4, page 47.

The metrics provided for applications are:

Dynamic Formats The number of named dynamic formats used by the client program.

Process Peak RSS (KB) The peak resident set size of the client program (in KB).

Process RSS (KB) The current resident set size of the client program (in KB).

Process VM (KB) The current amount of virtual memory used by the client program (in KB).

System CPU Time (µsec) The amount of system-level CPU time used by the client program (inµseconds).

User CPU Time (µsec) The amount of user-level CPU time used by the client program (in µseconds).

Name The application name used by the client in the tibRealm_Connect() call.

To continue, expaned the “Endpoint” section.

TIBCO FTL R© Programming Tutorial

Page 84: TIBCO FTL R Programming Tutorial · 2018-11-28 · TIBCO FTL R Programming Tutorial. 4 Lesson 2: Understanding the Code In this lesson, we’ll examine the code used in lesson 1

79

Figure 10.7: Subscriber Endpoint metrics

Each row in the “Endpoint” category corresponds to an endpoint instantiated by a call totib_PublisherCreate() or tib_SubscriberCreate(), and the corresponding name is the endpointname specified in the call. Refer back to line 77 of Listing 8.4, page 47 (for tib_PublisherCreate()),and line 183 of Listing 8.8, page 49 (for tib_SubscriberCreate()) for examples.

The metrics provided for endpoints include:

Msgs Recvd Inbound data messages received through the endpoint.

Msgs Sent Outbound data messages sent through the endpoint.

Store Mismatch Msgs The number of message flows that result from a store mismatch. This deals withpersistence and is discussed in a later lesson.

Name The endpoint name.

Next, expand the “Queues” section.

TIBCO FTL R© Programming Tutorial

Page 85: TIBCO FTL R Programming Tutorial · 2018-11-28 · TIBCO FTL R Programming Tutorial. 4 Lesson 2: Understanding the Code In this lesson, we’ll examine the code used in lesson 1

80

Figure 10.8: Subscriber Queue metrics

Each row corresponds to an event queue instantiated by a call to tibEventQueue_Create(). Unlikeother objects, event queues are named via properties; if no properties are passed totibEventQueue_Create(), the FTL library assigns a name.

Three metrics are provided for event queues:

Queue Backlog The maximum number of messages in the event queue during the Client SamplingInterval. Recall from Section 10.1, the Client Sampling Interval is a realm propertywhich controls how often the client program gathers its metrics into a timestampedsamples. After the metrics are gathered, the Queue Backlog is reset; thus the metricreflects the highest value over the interval.

Queue Discards Number of inbound messages discarded by the event queue.

Name The event queue name.

To continue, expand the “Transport” section:

TIBCO FTL R© Programming Tutorial

Page 86: TIBCO FTL R Programming Tutorial · 2018-11-28 · TIBCO FTL R Programming Tutorial. 4 Lesson 2: Understanding the Code In this lesson, we’ll examine the code used in lesson 1

81

Figure 10.9: Subscriber Transport metrics

Each row in the “Transports” category corresponds to a transport associated with an endpoint used by theclient program.

Four metrics are provided for transports:

Bytes Recvd Inbound data bytes received on the transport.Bytes Sent Outbound data bytes sent on the transport.Data Lost Number of inbound data loss events on the transport. This does not reflect the

number of bytes or messages lost, only the number of discrete loss events.Format Unavailable The number of messages with an unrecognized format received on the transport.

It is important to note that messages sent or received are endpoint metrics, while bytes sent or received aretransport metrics. In addition, even though this is a subscriber, the transport shows non-zero bytes sent.This reflects the data exchange which is part of the initial setup traffic between the publisher and subscriber.

Note the number of messages and bytes received. In Figure 10.9, 127 messages and 48631 bytes werereceived. The numbers on your screen will likely be different.

Now, let’s look at the publisher metrics. Close the client statistics panel by clicking the icon in theupper right corner:

TIBCO FTL R© Programming Tutorial

Page 87: TIBCO FTL R Programming Tutorial · 2018-11-28 · TIBCO FTL R Programming Tutorial. 4 Lesson 2: Understanding the Code In this lesson, we’ll examine the code used in lesson 1

82

Figure 10.10: Client status display

Click anywhere in the row for the publisher, with the “Client Label” “tibpub”:

Figure 10.11: Publisher Details

Expand the “Application” section:

TIBCO FTL R© Programming Tutorial

Page 88: TIBCO FTL R Programming Tutorial · 2018-11-28 · TIBCO FTL R Programming Tutorial. 4 Lesson 2: Understanding the Code In this lesson, we’ll examine the code used in lesson 1

83

Figure 10.12: Publisher Application Details

Expand the “Endpoint” section:

Figure 10.13: Publisher Endpoint Details

And finally expand the “Transport” section:

TIBCO FTL R© Programming Tutorial

Page 89: TIBCO FTL R Programming Tutorial · 2018-11-28 · TIBCO FTL R Programming Tutorial. 4 Lesson 2: Understanding the Code In this lesson, we’ll examine the code used in lesson 1

84

Figure 10.14: Publisher Transport Details

Regardless of the role of the client program, the metrics available are essentially the same. The endpointand transport metrics provided are again the same as those provided for the subscriber client program.

TIBCO FTL R© Programming Tutorial

Page 90: TIBCO FTL R Programming Tutorial · 2018-11-28 · TIBCO FTL R Programming Tutorial. 4 Lesson 2: Understanding the Code In this lesson, we’ll examine the code used in lesson 1

85

Lesson 11: Field References

A field reference is an alternative way to refer to a field within a message. In this lesson you will learnabout field references and how to use them, then modify the sample code to use field references.

11.1 Introduction

In previous lessons, setting or getting a field value required specifying the field’s name in the form of acharacter string. A field reference encapsulates field information into a tibFieldRef object, which isdefined as a pointer to an opaque object. This field reference, once created, can be used to directly specify afield for setting or getting its value, without the lookup cost of referencing it by its field name.

11.2 Field Reference API

In lesson 4 we discussed the FTL API functions used to work with fields and messages. The samefunctionality is available when working with field references.

11.2.1 FTL API Functions to Create and Destroy Field References

tibFieldRef tibFieldRef_Create(tibEx e, const char* fieldName);void tibFieldRef_Destroy(tibEx e, tibFieldRef f);

A field reference is created by a call to tibFieldRef_Create(), which returns a tibFieldRef object.

A field reference is valid until it is destroyed. Field references should be destroyed when no longer needed,using tibFieldRef_Destroy().

11.2.2 FTL API Functions to Set Field Values by References

void tibMessage_SetStringByRef(tibEx e, tibMessage message, tibFieldRef fieldRef,const char *value);

void tibMessage_SetOpaqueByRef(tibEx e, tibMessage message, tibFieldRef fieldRef,const void *value, tibint32_t size);

void tibMessage_SetLongByRef(tibEx e, tibMessage message, tibFieldRef fieldRef,tibint64_t value);

void tibMessage_SetDoubleByRef(tibEx e, tibMessage message, tibFieldRef fieldRef,tibdouble_t value);

void tibMessage_SetInboxByRef(tibEx e, tibMessage message, tibFieldRef fieldRef, tibInbox inbox);void tibMessage_SetDateTimeByRef(tibEx e, tibMessage message, tibFieldRef fieldRef,

const tibDateTime *dateTime);void tibMessage_SetMessageByRef(tibEx e, tibMessage message, tibFieldRef fieldRef,

tibMessage value);void tibMessage_SetArrayByRef(tibEx e, tibMessage message, tibFieldType arrayType,

tibFieldRef fieldRef, const void* const values,tibint32_t arraySize);

TIBCO FTL R© Programming Tutorial

Page 91: TIBCO FTL R Programming Tutorial · 2018-11-28 · TIBCO FTL R Programming Tutorial. 4 Lesson 2: Understanding the Code In this lesson, we’ll examine the code used in lesson 1

86

Each function is analogous to the FTL API functions for setting message fields by name as discussed inSection 4.2.

11.2.3 FTL API Functions to Get Field Values by References

const char* tibMessage_GetStringByRef(tibEx e, tibMessage message, tibFieldRef fieldRef);tibint64_t tibMessage_GetLongByRef(tibEx e, tibMessage message, tibFieldRef fieldRef);tibdouble_t tibMessage_GetDoubleByRef(tibEx e, tibMessage message, tibFieldRef fieldRef);const void* tibMessage_GetOpaqueByRef(tibEx e, tibMessage message, tibFieldRef fieldRef,

tibint32_t *size);tibInbox tibMessage_GetInboxByRef(tibEx e, tibMessage message, tibFieldRef fieldRef);tibDateTime* tibMessage_GetDateTimeByRef(tibEx e, tibMessage message, tibFieldRef fieldRef);tibMessage tibMessage_GetMessageByRef(tibEx e, tibMessage message, tibFieldRef fieldRef);void* tibMessage_GetArrayByRef(tibEx e, tibMessage message, tibFieldType arrayType,

tibFieldRef fieldRef, tibint32_t *arraySize);

Each function is analogous to the FTL API functions for getting messages fields by name as discussed inSection 4.3.

11.2.4 FTL API Field Reference Utility Functions

The field reference utility functions are analogous to those discussed in Section 4.4:

void tibMessage_ClearFieldByRef(tibEx e, tibMessage message, tibFieldRef fieldRef);tibbool_t tibMessage_IsFieldSetByRef(tibEx e, tibMessage message, tibFieldRef fieldRef);tibFieldType tibMessage_GetFieldTypeByRef(tibEx e, tibMessage message, tibFieldRef fieldRef);const char* tibFieldRef_GetFieldName(tibEx e, tibFieldRef f);

11.2.5 Iterators

Iterators allow a program to step through the fields in a message without knowing beforehand which fieldsmight exist in a message. This can be useful in a general-purpose client program that does not know whichformats might be used for a received message.

A message iterator is encapsulated in a tibMessageIterator, which is a pointer to an opaque structure.

tibMessageIterator tibMessageIterator_Create(tibEx e, tibMessage message);void tibMessageIterator_Destroy(tibEx e, tibMessageIterator messageIterator);

An interator is created using tibMessageIterator_Create(). The resulting tibMessageIterator

is specific to the tibMessage passed to the function and is valid as long as the message is valid.

An iterator is destroyed using tibMessageIterator_Destroy().

tibbool_t tibMessageIterator_HasNext(tibEx e, tibMessageIterator messageIterator);tibFieldRef tibMessageIterator_GetNext(tibEx e, tibMessageIterator messageIterator);

tibMessageIterator_HasNext() determines if an iterator has a next field, returning tibtrue if itdoes, and tibfalse otherwise.

tibMessageIterator_GetNext() advances the iterator to the next field in the message and returns areference to that field. If there is no next field, it returns NULL and sets the exception object to indicate an

TIBCO FTL R© Programming Tutorial

Page 92: TIBCO FTL R Programming Tutorial · 2018-11-28 · TIBCO FTL R Programming Tutorial. 4 Lesson 2: Understanding the Code In this lesson, we’ll examine the code used in lesson 1

87

error. When an iterator is created, it implicitly points before the first field in the message so that the firstcall to tibMessageIterator_GetNext() returns the first field in the message.

void tibMessageIterator_Reset(tibEx e, tibMessageIterator messageIterator);

tibMessageIterator_Reset() resets the iterator to point before the first field in the message, as if theiterator had just been created.

11.3 Modify the Samples

To modify the samples to make use of field refererences, we add two new files and modify two existingfiles.

11.3.1 fields.h

1 #if !defined(FIELDS_H_INCLUDED)2 #define FIELDS_H_INCLUDED3

4 #include "tib/ftl.h"5

6 extern tibFieldRef refTag;7 extern tibFieldRef refCount;8 extern tibFieldRef refContents;9 extern tibFieldRef refSeq;

10 extern tibFieldRef refBOS;11 extern tibFieldRef refEOS;12 extern tibFieldRef refEven;13

14 void create_field_references(tibEx ex);15 void destroy_field_references(tibEx ex);16

17 #endif

fields.h is a new file which defines seven variable declarations and two functions. The variables aredeclared extern as they are actually defined in fields.c.

create_field_references() is used to create the field references at the start of the program, anddestroy_field_references() destroys them when no longer needed.

TIBCO FTL R© Programming Tutorial

Page 93: TIBCO FTL R Programming Tutorial · 2018-11-28 · TIBCO FTL R Programming Tutorial. 4 Lesson 2: Understanding the Code In this lesson, we’ll examine the code used in lesson 1

88

11.3.2 fields.c

1 #include "fields.h"2 #include "common.h"3

4 tibFieldRef refTag = NULL;5 tibFieldRef refCount = NULL;6 tibFieldRef refContents = NULL;7 tibFieldRef refSeq = NULL;8 tibFieldRef refBOS = NULL;9 tibFieldRef refEOS = NULL;

10 tibFieldRef refEven = NULL;11

12 void create_field_references(tibEx ex)13 {14 if (tibEx_GetErrorCode(ex) != TIB_OK)15 {16 return;17 }18 refTag = tibFieldRef_Create(ex, FIELD_NAME_TAG);19 refCount = tibFieldRef_Create(ex, FIELD_NAME_COUNT);20 refContents = tibFieldRef_Create(ex, FIELD_NAME_CONTENTS);21 refSeq = tibFieldRef_Create(ex, FIELD_NAME_SEQ);22 refBOS = tibFieldRef_Create(ex, FIELD_NAME_BOS);23 refEOS = tibFieldRef_Create(ex, FIELD_NAME_EOS);24 refEven = tibFieldRef_Create(ex, FIELD_NAME_EVEN);25 }26

27 void destroy_field_references(tibEx ex)28 {29 if (refTag != NULL)30 {31 tibFieldRef_Destroy(ex, refTag);32 refTag = NULL;33 }34 if (refCount != NULL)35 {36 tibFieldRef_Destroy(ex, refCount);37 refCount = NULL;38 }39 if (refContents != NULL)40 {41 tibFieldRef_Destroy(ex, refContents);42 refContents = NULL;43 }44 if (refSeq != NULL)45 {46 tibFieldRef_Destroy(ex, refSeq);47 refSeq = NULL;48 }49 if (refBOS != NULL)50 {51 tibFieldRef_Destroy(ex, refBOS);52 refBOS = NULL;53 }54 if (refEOS != NULL)55 {56 tibFieldRef_Destroy(ex, refEOS);57 refEOS = NULL;58 }59 if (refEven != NULL)60 {61 tibFieldRef_Destroy(ex, refEven);62 refEven = NULL;63 }64 }

fields.c is also a new file, and implements the variables and functions declared in fields.h.

TIBCO FTL R© Programming Tutorial

Page 94: TIBCO FTL R Programming Tutorial · 2018-11-28 · TIBCO FTL R Programming Tutorial. 4 Lesson 2: Understanding the Code In this lesson, we’ll examine the code used in lesson 1

89

fields.h and fields.c were created to centralize the creation and destruction of field references,allowing the same code to be used in both the publisher and subscriber.

11.3.3 ftlsub.c

The modifications to ftlsub.c are extensive but fairly straightforward.

6 #include "tib/ftl.h"7 #include "common.h"8 #include "fields.h"

Since we’re using the definitions in fields.h, that file needs to be included.

96 if (!tibMessage_IsFieldSetByRef(ex, msgs[i], refTag))97 {98 printf("%s field is not present in received message\n", FIELD_NAME_TAG);99 fflush(stdout);

100 continue;101 }102 type = tibMessage_GetStringByRef(ex, msgs[i], refTag);

Most of the remaining changes consist of replacing calls to tibMessage_XXX() with the correspondingfield reference call.

109 if (tibMessage_IsFieldSetByRef(ex, msgs[i], refEOS))

124 if (tibMessage_IsFieldSetByRef(ex, msgs[i], refBOS))125 {126 init_received = tibtrue;127 printf("received BOS indicator\n");128 fflush(stdout);129 ExpectedMsgCount = tibMessage_GetLongByRef(ex, msgs[i], refCount);130 }

145 if (tibMessage_IsFieldSetByRef(ex, msgs[i], refSeq))146 {147 tibint64_t seq = tibMessage_GetLongByRef(ex, msgs[i], refSeq);

189 tibProperties_Destroy(ex, props);190

191 create_field_references(ex);

The call to create_field_references() is made after the realm is opened but before any fieldreferences might be used.

224 tibSubscriber_Close(ex, sub);225 destroy_field_references(ex);226

227 tibRealm_Close(ex, realm);

Finally, the call to destroy_field_references() is made late in the cleanup process, just before therealm is closed.

TIBCO FTL R© Programming Tutorial

Page 95: TIBCO FTL R Programming Tutorial · 2018-11-28 · TIBCO FTL R Programming Tutorial. 4 Lesson 2: Understanding the Code In this lesson, we’ll examine the code used in lesson 1

90

11.3.4 ftlpub.c

The changes to ftlpub.c closely parallel those made to ftlsub.c.

6 #include "tib/ftl.h"7 #include "common.h"8 #include "fields.h"

90 create_field_references(ex);91 pub = tibPublisher_Create(ex, realm, Endpoint, NULL);92 CHECK(ex);

102 printf("sending initial message\n");103 fflush(stdout);104 tibMessage_SetStringByRef(ex, msg, refTag, FIELD_TAG_CONTROL);105 tibMessage_SetStringByRef(ex, msg, refContents, "Initial message");106 tibMessage_SetLongByRef(ex, msg, refCount, MsgCount);107 tibMessage_SetLongByRef(ex, msg, refBOS, 1);108 tibPublisher_Send(ex, pub, msg);109 CHECK(ex);110

111 tibMessage_SetStringByRef(ex, msg, refTag, FIELD_TAG_DATA);112 tibMessage_ClearFieldByRef(ex, msg, refCount);113 tibMessage_ClearFieldByRef(ex, msg, refBOS);114 tibMessage_SetStringByRef(ex, msg, refContents, "Data message");

121 tibMessage_SetLongByRef(ex, msg, refSeq, idx);122 if ((idx % 2) == 0)123 {124 tibMessage_SetLongByRef(ex, msg, refEven, 1);125 }126 else127 {128 tibMessage_SetLongByRef(ex, msg, refEven, 0);129 }

137 tibMessage_ClearAllFields(ex, msg);138 tibMessage_SetStringByRef(ex, msg, refTag, FIELD_TAG_CONTROL);139 tibMessage_SetStringByRef(ex, msg, refContents, "Final message");140 tibMessage_SetLongByRef(ex, msg, refCount, MsgCount);141 tibMessage_SetLongByRef(ex, msg, refEOS, 1);142 tibPublisher_Send(ex, pub, msg);

145 tibMessage_Destroy(ex, msg);146 tibPublisher_Close(ex, pub);147 destroy_field_references(ex);

11.4 Build and Run the Samples

With the exception of a slight increase in efficiency, the use of field references has no effect on how thesample client programs operate. To verify this, let’s build and run the samples. Open a command window,navigate to the $TIBFTL_TUTDIR/code/lesson-11 directory, and build the samples:

make

TIBCO FTL R© Programming Tutorial

Page 96: TIBCO FTL R Programming Tutorial · 2018-11-28 · TIBCO FTL R Programming Tutorial. 4 Lesson 2: Understanding the Code In this lesson, we’ll examine the code used in lesson 1

91

Start the subscriber in the same manner used in lesson 10:

./ftlsub -a App1 -e endpoint-1

In another command window, navigate to the $TIBFTL_TUTDIR/code/lesson-11 directory and startthe publisher:

./ftlpub -a App1 -e endpoint-1

With the exception of the number of messages sent, the output from ftlpub is unchanged:

using Realm Service=http://localhost:8080Application=App1Endpoint=endpoint-1ClientLabel=tibpub

sending initial messagesending 20 data messagessending final message

Listing 11.1: ftlpub output

The output from ftlsub is also unchanged:

using Realm Service=http://localhost:8080Application=App1Endpoint=endpoint-1Matcher=noneClientLabel=tibsub

waiting for message(s)received BOS indicatorreceived EOS indicatorReceived 2 control, and 20 of 20 data messages.

Listing 11.2: ftlsub output

TIBCO FTL R© Programming Tutorial

Page 97: TIBCO FTL R Programming Tutorial · 2018-11-28 · TIBCO FTL R Programming Tutorial. 4 Lesson 2: Understanding the Code In this lesson, we’ll examine the code used in lesson 1

92

Lesson 12: Trace Logging

The FTL API library communicates information about both normal and unusual occurrences via tracelogging. Client programs can control the level of detail and quantity, as well as the destination, of logmessages.

The TIBCO FTL R© Development guide is the definitive reference for trace logging.

12.1 Tune the Log Level

The log level is expressed as a string containing one or more specifications of the form

element:level

Each specification is separated from the next by a semicolon.

12.1.1 The element Component

element indicates the category of log message. The categories supported are:

Category Descriptionapplication Tune logging related to the client application program, such as the program’s use of

FTL API calls, message formats, and content matchers.IO Tune logging related to data I/O, such as message data entering or leaving the program,

and message packetization.RS Tune logging related to the realm server. In realm server client processes, this cate-

gory includes client communication with the realm server. In realm server processes,this category includes operations within the realm server, such as communication withclients, with affiliated realm servers, and with group servers.

transports Tune logging related to transports, including peer connections, subscriber interest, mes-sage send operations, and protocols.

store Tune logging related to persistence stores and durables, such as store and durable op-erations, quorum formation, and leader election.

all Tune logging for all elements, embracing all categories listed above.

12.1.2 The level Component

The level component value denotes the severity of the log messages. The supported levels are defined inftl.h:

TIBCO FTL R© Programming Tutorial

Page 98: TIBCO FTL R Programming Tutorial · 2018-11-28 · TIBCO FTL R Programming Tutorial. 4 Lesson 2: Understanding the Code In this lesson, we’ll examine the code used in lesson 1

93

Level Symbol Descriptionoff TIB_LOG_LEVEL_OFF Disable all trace logging.severe TIB_LOG_LEVEL_SEVERE Output trace entries only for severe events.warn TIB_LOG_LEVEL_WARN Output trace entries for warning and severe events.info TIB_LOG_LEVEL_INFO Output trace entries for information, warning, and severe

events. This is the default level.verbose TIB_LOG_LEVEL_VERBOSE Output trace entries for verbose, information, warning, and

severe events.debug TIB_LOG_LEVEL_DEBUG Output trace entries for debug, verbose, information, warn-

ing, and severe events.

12.1.3 Log Level Examples

The default log level is all:info, specifying the info level for all categories.

Specifications are processed in order, with later ones superseding earlier (or default) specifications. Forexample,

all:info;RS:warn

sets the info level for all categories, then overrides the RS category level, setting it to warn. Note that thisis functionally equivalent to

RS:warn

Since the default is all:info, this overrides the default for category RS.

12.2 Trace Log Destinations

By default, all trace log statements are written to stderr.

Trace log statements can also be written to a set of rotating log files. The filename prefix, maximum sizeper file, and maximum number of files are controlled by an FTL API call, discussed below.

Finally a client program can register a callback which is invoked whenever a trace log statement would bewritten. The client program can determine how to format the output as well as the destination of the tracelog statement. This mechanism will not be discussed in this lesson: consult the TIBCO FTL R© Developmentguide for details.

12.3 FTL API Trace Logging Functions

The FTL API provides two trace logging functions.

void tib_SetLogLevel(tibEx e, const char *level);

tib_SetLogLevel() sets the trace log level for the client program. The level argument is a string ofthe form described in Section 12.1.

void tib_SetLogFiles(tibEx e, const char *filePrefix, tibint64_t maxFileSize,tibint32_t maxFiles, tibProperties properties);

TIBCO FTL R© Programming Tutorial

Page 99: TIBCO FTL R Programming Tutorial · 2018-11-28 · TIBCO FTL R Programming Tutorial. 4 Lesson 2: Understanding the Code In this lesson, we’ll examine the code used in lesson 1

94

tib_SetLogFiles() allows the client program to specify that trace log statements be written to a seriesof rotating log files.

The log file name created consists of filePrefix, followed by a dot character, followed by the suffix 0

(zero), as in filePrefix.0. The log file with the .0 suffix will always be the current log file.

When the size of the current log file exceeds the maximum size (maxFileSize), the log files are rotatedby incrementing the suffix: filePrefix.1 is renamed to filePrefix.2, filePrefix.0 isrenamed to filePrefix.1, and a new filePrefix.0 is created. If the maximum number of files(maxFiles) is reached, the oldest one is removed.

Note that maxFileSize must be at least 100K (102400), maxFiles must be between 1 and 1000inclusive, and properties must be NULL. The function will throw an exception if an invalid value isspecified.

12.4 Modify the Samples

We will modify the samples to allow a trace logging specification string on the command line, as well asallowing the option of rotating log files.

12.4.1 ftlpub.c

Most of the changes to ftlpub.c involve handling the new command-line arguments:

• -p is the log file prefix

• -s is the maximum log file size

• -x is the maximum log file count

• -t for the trace log level

21 const char * LogfilePrefix = NULL;22 tibint64_t LogfileMaxSize = 100*1024;23 tibint32_t LogfileMaxCount = 10;24 const char * TraceLevel = NULL;

26 const char * Options = "a:c:e:hl:p:r:s:t:x:";

37 " -p PREFIX set the log file prefix\n"38 " -r URL use realm service URL\n"39 " -s SIZE maximum logfile size in bytes\n"40 " -t LEVEL set trace level\n"41 " -x COUNT maximum logfile count\n"

TIBCO FTL R© Programming Tutorial

Page 100: TIBCO FTL R Programming Tutorial · 2018-11-28 · TIBCO FTL R Programming Tutorial. 4 Lesson 2: Understanding the Code In this lesson, we’ll examine the code used in lesson 1

95

66 case ’p’:67 LogfilePrefix = strdup(optarg);68 break;69 case ’r’:70 RealmService = strdup(optarg);71 break;72 case ’s’:73 LogfileMaxSize = (tibint64_t) atoi(optarg);74 break;75 case ’t’:76 TraceLevel = strdup(optarg);77 break;78 case ’x’:79 LogfileMaxCount = (tibint32_t) atoi(optarg);80 break;

103 if (TraceLevel != NULL)104 {105 tib_SetLogLevel(ex, TraceLevel);106 }107 if (LogfilePrefix != NULL)108 {109 tib_SetLogFiles(ex, LogfilePrefix, LogfileMaxSize, LogfileMaxCount, NULL);110 }111 CHECK(ex);

Lines 103 through 106 set the trace log level if specified on the command line. Lines 107 through 110establish the rotating log files, if the log file prefix was included in the command line arguments.

12.4.2 ftlsub.c

The changes to ftlsub.c exactly mirror the changes in ftlpub.c.

21 const char * LogfilePrefix = NULL;22 tibint64_t LogfileMaxSize = 100*1024;23 tibint32_t LogfileMaxCount = 10;24 const char * TraceLevel = NULL;

31 const char * Options = "a:e:hl:m:p:r:s:t:vx:";

42 " -p PREFIX set the log file prefix\n"43 " -r URL use realm service URL\n"44 " -s SIZE maximum logfile size in bytes\n"45 " -t LEVEL set trace level\n"46 " -v verbose output\n"47 " -x COUNT maximum logfile count\n"

TIBCO FTL R© Programming Tutorial

Page 101: TIBCO FTL R Programming Tutorial · 2018-11-28 · TIBCO FTL R Programming Tutorial. 4 Lesson 2: Understanding the Code In this lesson, we’ll examine the code used in lesson 1

96

72 case ’p’:73 LogfilePrefix = strdup(optarg);74 break;75 case ’r’:76 RealmService = strdup(optarg);77 break;78 case ’s’:79 LogfileMaxSize = (tibint64_t) atoi(optarg);80 break;81 case ’t’:82 TraceLevel = strdup(optarg);83 break;84 case ’v’:85 Verbose = tibtrue;86 break;87 case ’x’:88 LogfileMaxCount = (tibint32_t) atoi(optarg);89 break;

204 if (TraceLevel != NULL)205 {206 tib_SetLogLevel(ex, TraceLevel);207 }208 if (LogfilePrefix != NULL)209 {210 tib_SetLogFiles(ex, LogfilePrefix, LogfileMaxSize, LogfileMaxCount, NULL);211 }212 CHECK(ex);

12.5 Build and Run the Samples

In a command window, navigate to $TIBFTL_TUTDIR/code/lesson-12 and build the samples:

make

Once built, start the subscriber with the log level application:debug:

./ftlsub -t application:debug

In another command window, navigate to $TIBFTL_TUTDIR/code/lesson-12 and start the publisher:

./ftlpub

The output from ftlsub begins (note that your output will be different):

TIBCO FTL R© Programming Tutorial

Page 102: TIBCO FTL R Programming Tutorial · 2018-11-28 · TIBCO FTL R Programming Tutorial. 4 Lesson 2: Understanding the Code In this lesson, we’ll examine the code used in lesson 1

97

XXXX-XX-XX XX:XX:XX.XXX debu api: App ’default’ Connecting to realmserver at primary_url ’http://localhost:8080’, alt_url ’none’XXXX-XX-XX XX:XX:XX.XXX debu mon: Initialized monitoring matching via realm properties to Monitoring matching mode offXXXX-XX-XX XX:XX:XX.XXX debu mon: Initialized monitoring matching via realm properties to Monitoring matching mode offXXXX-XX-XX XX:XX:XX.XXX debu api: App ’default’ Connected to realmserver at ’http://localhost:8080’ and was assigned Client [id

:16038]XXXX-XX-XX XX:XX:XX.XXX verb api: Client [id:16038] creating subscriber on endpoint ’(null)’XXXX-XX-XX XX:XX:XX.XXX verb api: Client [id:16038] created event queue ’queue_7fbe2ec07000’XXXX-XX-XX XX:XX:XX.XXX verb api: Client [id:16038] added subscriber on endpoint ’default’ with matcher ’{}’ to queue ’

queue_7fbe2ec07000’using Realm Service=http://localhost:8080

Application=defaultEndpoint=defaultMatcher=noneClientLabel=tibsub

waiting for message(s)XXXX-XX-XX XX:XX:XX.XXX verb api: Client [id:16038] received msg from persistent server with [PubId=807008, StreamId=10, SeqNo=1]XXXX-XX-XX XX:XX:XX.XXX verb api: Client [id:16038] before invoking msg callback for subscriber on endpoint ’default’ with

matcher ’{}’ from queue ’queue_7fbe2ec07000’XXXX-XX-XX XX:XX:XX.XXX verb msg: Client [id:16038] invoking msg callback for subscriber on endpoint ’default’ with msg ’{[(

header) compact=false, mutable=true, dispatchOwns=true, modified=false] [(recv:props) INBOX_LIN:0x00000000b232eab0 INBOX_CID:16038 INBOX_RID:{66E16D44-CCDC-4E02-934A-EB6E8BA8B254} PUB_ID:0x00000000000c5060 PUB_STREAM_ID:0x000000000000000aPUB_SEQ_NO:0x0000000000000001 PUB_BATCH_START:0x0000000000000001 PUB_BATCH_END:0x0000000000000001 PUB_BATCH_ID:0x0000000000000001 QUORUM_NUM:0x000000000000000a QUORUM_VER:0x0000000000012d8d TYPE:0x000000000000000a STORE_ID:0xce6e65d43398280d ACK_BATCH_START:0x0000000000000001 DISPATCH_SEQ_NO:0x0000000000000001 DURABLE_ID:0x0000000000000000VSTORE_ID:0xc16fa7b72e40ff96 ] [(format) id={35862E81-6D3C-490B-9397-D0AA7DD5A6AC}, name="", fieldcount=4, realm="_default_realm", version=0] [(formatField) index=0, name="tag", size=unbounded, type=string] [(formatField) index=1, name="contents", size=unbounded, type=string] [(formatField) index=2, name="count", size=8, type=long] [(formatField) index=3,name="bos", size=8, type=long] string:tag="control", string:contents="Initial message", long:count=20, long:bos=1}’

received BOS indicatorXXXX-XX-XX XX:XX:XX.XXX verb msg: Client [id:16038] destroying msg ’{[(header) compact=false, mutable=true, dispatchOwns=true,

modified=false] [(recv:props) INBOX_LIN:0x00000000b232eab0 INBOX_CID:16038 INBOX_RID:{66E16D44-CCDC-4E02-934A-EB6E8BA8B254}PUB_ID:0x00000000000c5060 PUB_STREAM_ID:0x000000000000000a PUB_SEQ_NO:0x0000000000000001 PUB_BATCH_START:0x0000000000000001PUB_BATCH_END:0x0000000000000001 PUB_BATCH_ID:0x0000000000000001 QUORUM_NUM:0x000000000000000a QUORUM_VER:0x0000000000012d8dTYPE:0x000000000000000a STORE_ID:0xce6e65d43398280d ACK_BATCH_START:0x0000000000000001 DISPATCH_SEQ_NO:0x0000000000000001

DURABLE_ID:0x0000000000000000 VSTORE_ID:0xc16fa7b72e40ff96 ] [(format) id={35862E81-6D3C-490B-9397-D0AA7DD5A6AC}, name="",fieldcount=4, realm="_default_realm", version=0] [(formatField) index=0, name="tag", size=unbounded, type=string] [(formatField) index=1, name="contents", size=unbounded, type=string] [(formatField) index=2, name="count", size=8, type=long][(formatField) index=3, name="bos", size=8, type=long] string:tag="control", string:contents="Initial message", long:count

=20, long:bos=1}’ after invoking msg callback for subscriber on endpoint ’default’

Listing 12.1: Beginning of ftlsub output

It is clear that the specified log level (-t application:debug) has caused ftlsub to generate muchmore output: specifically the trace log messages.

Concept 12. The content and format of trace log statements are not part of any published interface, andare subject to change from release to release. Do not rely on the content or format of trace log statements.

We are setting the log level debug only to force the additional trace log statements, in order to demonstratethe effect of changing the log level. You should only use set the log level to verbose or debug ondirection of Tibco support personnel, as the additional logging can affect the performance of the clientprogram.

TIBCO FTL R© Programming Tutorial